diff --git a/Changelog b/Changelog index 5a32cf0d5..d77bba51f 100644 --- a/Changelog +++ b/Changelog @@ -1,65 +1,30 @@ Entries are sorted chronologically from oldest to youngest within each release, releases are sorted from youngest to oldest. -version 5.0.1: -- avcodec/exr: Avoid signed overflow in displayWindow -- avcodec/diracdec: avoid signed integer overflow in global mv -- avcodec/takdsp: Fix integer overflow in decorrelate_sf() -- avcodec/apedec: fix a integer overflow in long_filter_high_3800() -- avdevice/dshow: fix regression -- avfilter/vf_subtitles: pass storage size to libass -- avcodec/vp9_superframe_split_bsf: Don't read inexistent data -- avcodec/vp9_superframe_split_bsf: Discard invalid zero-sized frames -- avcodec/vp9_superframe_bsf: Check for existence of data before reading it -- avcodec/vp9_raw_reorder_bsf: Check for existence of data before reading it -- avformat/imf: fix packet pts, dts and muxing -- avformat/imf: open resources only when first needed -- avformat/imf: cosmetics -- avformat/imf_cpl: do not use filesize when reading XML file -- avformat/imfdec: Use proper logcontext -- avformat/imfdec: do not use filesize when reading XML file -- doc/utils: add missing 22.2 layout entry -- avcodec/av1: only set the private context pix_fmt field if get_pixel_format() succeeds -- avformat/aqtitledec: Skip unrepresentable durations -- avformat/cafdec: Do not store empty keys in read_info_chunk() -- avformat/mxfdec: Do not clear array in mxf_read_strong_ref_array() before writing -- avformat/mxfdec: Check for avio_read() failure in mxf_read_strong_ref_array() -- avformat/mxfdec: Check count in mxf_read_strong_ref_array() -- avformat/hls: Check target_duration -- avcodec/pixlet: Avoid signed integer overflow in scaling in filterfn() -- avformat/matroskadec: Check pre_ns -- avcodec/sonic: Use unsigned for predictor_k to avoid undefined behavior -- avcodec/libuavs3d: Check ff_set_dimensions() for failure -- avcodec/speexdec: Align some comments -- avcodec/speexdec: Use correct doxygen comments -- avcodec/mjpegbdec: Set buf_size -- avformat/matroskadec: Use rounded down duration in get_cue_desc() check -- avcodec/argo: Check packet size -- avcodec/g729_parser: Check channels -- avformat/avidec: Check height -- avformat/rmdec: Better duplicate tags check -- avformat/mov: Disallow empty sidx -- avformat/argo_cvg:: Fix order of operations in error check in argo_cvg_write_trailer() -- avformat/argo_asf: Fix order of operations in error check in argo_asf_write_trailer() -- avcodec/movtextdec: add () to CMP() macro to avoid unexpected behavior -- avformat/matroskadec: Check duration -- avformat/mov: Corner case encryption error cleanup in mov_read_senc() -- avcodec/jpeglsdec: Fix if( code style -- avcodec/jpeglsdec: Check get_ur_golomb_jpegls() for error -- avcodec/motion_est: fix indention of ff_get_best_fcode() -- avcodec/motion_est: Fix xy indexing on range violation in ff_get_best_fcode() -- avformat/hls: Use unsigned for iv computation -- avcodec/jpeglsdec: Increase range for N in ls_get_code_runterm() by using unsigned -- avformat/matroskadec: Check desc_bytes -- avformat/utils: Fix invalid NULL pointer operation in ff_parse_key_value() -- avformat/matroskadec: Fix infinite loop with bz decompression -- avformat/utils: keep chapter monotonicity on chapter updates -- avformat/mov: Check size before subtraction -- avcodec/cfhd: Avoid signed integer overflow in coeff -- avcodec/libdav1d: free the Dav1dData packet on dav1d_send_data() failure -- avcodec/h264_parser: don't alter decoder private data -- configure: link to libatomic when it's present -- fate/ffmpeg: add missing samples dependency to fate-shortest +version 5.1: +- add ipfs/ipns protocol support +- dialogue enhance audio filter +- dropped obsolete XvMC hwaccel +- pcm-bluray encoder +- DFPWM audio encoder/decoder and raw muxer/demuxer +- SITI filter +- Vizrt Binary Image encoder/decoder +- avsynctest source filter +- feedback video filter +- pixelize video filter +- colormap video filter +- colorchart video source filter +- multiply video filter +- PGS subtitle frame merge bitstream filter +- blurdetect filter +- tiltshelf audio filter +- QOI image format support +- ffprobe -o option +- virtualbass audio filter +- VDPAU AV1 hwaccel +- PHM image format support +- remap_opencl filter +- added chromakey_cuda filter version 5.0: diff --git a/MAINTAINERS b/MAINTAINERS index c065e9449..274fc8920 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -161,6 +161,7 @@ Codecs: cscd.c Reimar Doeffinger cuviddec.c Timo Rothenpieler dca* foo86 + dfpwm* Jack Bruienne dirac* Rostislav Pehlivanov dnxhd* Baptiste Coudurier dolby_e* foo86 @@ -193,6 +194,7 @@ Codecs: libcodec2.c Tomas Härdin libdirac* David Conrad libdavs2.c Huiwen Ren + libjxl*.c, libjxl.h Leo Izen libgsm.c Michel Bardiaux libkvazaar.c Arttu Ylä-Outinen libopenh264enc.c Martin Storsjo, Linjie Fu @@ -266,7 +268,6 @@ Codecs: xan.c Mike Melanson xbm* Paul B Mahol xface Stefano Sabatini - xvmc.c Ivan Kalvachev xwd* Paul B Mahol Hardware acceleration: @@ -354,6 +355,7 @@ Filters: vf_il.c Paul B Mahol vf_(t)interlace Thomas Mundt (CC ) vf_lenscorrection.c Daniel Oberhoff + vf_libplacebo.c Niklas Haas vf_mergeplanes.c Paul B Mahol vf_mestimate.c Davinder Singh vf_minterpolate.c Davinder Singh @@ -416,6 +418,7 @@ Muxers/Demuxers: dashdec.c Steven Liu dashenc.c Karthick Jeyapal daud.c Reimar Doeffinger + dfpwmdec.c Jack Bruienne dss.c Oleksij Rempel dtsdec.c foo86 dtshddec.c Paul B Mahol @@ -436,6 +439,7 @@ Muxers/Demuxers: ipmovie.c Mike Melanson ircam* Paul B Mahol iss.c Stefan Gehrer + jpegxl_probe.* Leo Izen jvdec.c Peter Ross kvag.c Zane van Iperen libmodplug.c Clément Bœsch @@ -515,6 +519,7 @@ Protocols: bluray.c Petri Hintukainen ftp.c Lukasz Marek http.c Ronald S. Bultje + libsrt.c Zhao Zhili libssh.c Lukasz Marek libzmq.c Andriy Gelman mms*.c Ronald S. Bultje @@ -541,6 +546,7 @@ Operating systems / CPU architectures Alpha Falk Hueffner MIPS Manojkumar Bhosale, Shiyou Yin +LoongArch Shiyou Yin Mac OS X / PowerPC Romain Dolbeau, Guillaume Poirier Amiga / PowerPC Colin Ward Linux / PowerPC Lauri Kasanen @@ -615,10 +621,12 @@ Haihao Xiang (haihao) 1F0C 31E8 B4FE F7A4 4DC1 DC99 E0F5 76D4 76FC 437F 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 +Leo Izen (thebombzen) B6FD 3CFC 7ACF 83FC 9137 6945 5A71 C331 FD2F A19A Loren Merritt ABD9 08F4 C920 3F65 D8BE 35D7 1540 DAA7 060F 56DE Lynne FE50 139C 6805 72CA FD52 1F8D A2FE A5F0 3F03 4464 Michael Niedermayer 9FF2 128B 147E F673 0BAD F133 611E C787 040B 0FAB Nicolas George 24CE 01CE 9ACC 5CEB 74D8 8D9D B063 D997 36E5 4C93 +Niklas Haas (haasn) 1DDB 8076 B14D 5B48 32FC 99D9 EB52 DA9C 02BA 6FB4 Nikolay Aleksandrov 8978 1D8C FB71 588E 4B27 EAA8 C4F0 B5FC E011 13B1 Panagiotis Issaris 6571 13A3 33D9 3726 F728 AA98 F643 B12E ECF3 E029 Peter Ross A907 E02F A6E5 0CD2 34CD 20D2 6760 79C5 AC40 DD6B diff --git a/Makefile b/Makefile index 2d622ecd9..61f79e27a 100644 --- a/Makefile +++ b/Makefile @@ -19,6 +19,8 @@ vpath %/fate_config.sh.template $(SRC_PATH) TESTTOOLS = audiogen videogen rotozoom tiny_psnr tiny_ssim base64 audiomatch HOSTPROGS := $(TESTTOOLS:%=tests/%) doc/print_options +ALLFFLIBS = avcodec avdevice avfilter avformat avutil postproc swscale swresample + # $(FFLIBS-yes) needs to be in linking order FFLIBS-$(CONFIG_AVDEVICE) += avdevice FFLIBS-$(CONFIG_AVFILTER) += avfilter @@ -76,13 +78,14 @@ tools/target_dem_%_fuzzer$(EXESUF): $(FF_DEP_LIBS) CONFIGURABLE_COMPONENTS = \ $(wildcard $(FFLIBS:%=$(SRC_PATH)/lib%/all*.c)) \ $(SRC_PATH)/libavcodec/bitstream_filters.c \ + $(SRC_PATH)/libavcodec/hwaccels.h \ $(SRC_PATH)/libavcodec/parsers.c \ $(SRC_PATH)/libavformat/protocols.c \ -config.h: ffbuild/.config +config_components.h: ffbuild/.config ffbuild/.config: $(CONFIGURABLE_COMPONENTS) @-tput bold 2>/dev/null - @-printf '\nWARNING: $(?) newer than config.h, rerun configure\n\n' + @-printf '\nWARNING: $(?) newer than config_components.h, rerun configure\n\n' @-tput sgr0 2>/dev/null SUBDIR_VARS := CLEANFILES FFLIBS HOSTPROGS TESTPROGS TOOLS \ @@ -113,12 +116,13 @@ include $(SRC_PATH)/fftools/Makefile include $(SRC_PATH)/doc/Makefile include $(SRC_PATH)/doc/examples/Makefile -libavcodec/avcodec.o libavformat/utils.o libavdevice/avdevice.o libavfilter/avfilter.o libavutil/utils.o libpostproc/postprocess.o libswresample/swresample.o libswscale/utils.o : libavutil/ffversion.h +$(ALLFFLIBS:%=lib%/version.o): libavutil/ffversion.h $(PROGS): %$(PROGSSUF)$(EXESUF): %$(PROGSSUF)_g$(EXESUF) ifeq ($(STRIPTYPE),direct) $(STRIP) -o $@ $< else + $(RM) $@ $(CP) $< $@ $(STRIP) $@ endif @@ -159,7 +163,7 @@ clean:: $(RM) -rf coverage.info coverage.info.in lcov distclean:: clean - $(RM) .version avversion.h config.asm config.h mapfile \ + $(RM) .version config.asm config.h config_components.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 \ diff --git a/RELEASE b/RELEASE index 6b244dcd6..a75b92f1e 100644 --- a/RELEASE +++ b/RELEASE @@ -1 +1 @@ -5.0.1 +5.1 diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 1df4ace77..afc063161 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -1,10 +1,13 @@ - ┌────────────────────────────────────────┐ - │ RELEASE NOTES for FFmpeg 5.0 "Lorentz" │ - └────────────────────────────────────────┘ + ┌────────────────────────────────────────────┐ + │ RELEASE NOTES for FFmpeg 5.1 "Riemann" LTS │ + └────────────────────────────────────────────┘ - The FFmpeg Project proudly presents FFmpeg 5.0 "Lorentz", about 9 - months after the release of FFmpeg 4.4. + The FFmpeg Project proudly presents FFmpeg 5.1 "Riemann" LTS, about 6 + months after the release of FFmpeg 5.0, our first Long Term Support + release. While several past FFmpeg releases have enjoyed long term + support, this is the first release where such an intention is made + clear at release. A complete Changelog is available at the root of the project, and the complete Git history on https://git.ffmpeg.org/gitweb/ffmpeg.git diff --git a/VERSION b/VERSION index 6b244dcd6..a75b92f1e 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -5.0.1 +5.1 diff --git a/compat/cuda/cuda_runtime.h b/compat/cuda/cuda_runtime.h index 30cd085e4..5837c1ad3 100644 --- a/compat/cuda/cuda_runtime.h +++ b/compat/cuda/cuda_runtime.h @@ -181,7 +181,9 @@ static inline __device__ double trunc(double a) { return __builtin_trunc(a); } static inline __device__ float fabsf(float a) { return __builtin_fabsf(a); } static inline __device__ float fabs(float a) { return __builtin_fabsf(a); } static inline __device__ double fabs(double a) { return __builtin_fabs(a); } +static inline __device__ float sqrtf(float a) { return __builtin_sqrtf(a); } +static inline __device__ float __saturatef(float a) { return __nvvm_saturate_f(a); } static inline __device__ float __sinf(float a) { return __nvvm_sin_approx_f(a); } static inline __device__ float __cosf(float a) { return __nvvm_cos_approx_f(a); } static inline __device__ float __expf(float a) { return __nvvm_ex2_approx_f(a * (float)__builtin_log2(__builtin_exp(1))); } diff --git a/compat/w32dlfcn.h b/compat/w32dlfcn.h index 52a94efaf..fb1aa1b72 100644 --- a/compat/w32dlfcn.h +++ b/compat/w32dlfcn.h @@ -20,11 +20,40 @@ #define COMPAT_W32DLFCN_H #ifdef _WIN32 +#include + #include + #include "config.h" -#if (_WIN32_WINNT < 0x0602) || HAVE_WINRT +#include "libavutil/macros.h" #include "libavutil/wchar_filename.h" -#endif + +static inline wchar_t *get_module_filename(HMODULE module) +{ + wchar_t *path = NULL, *new_path; + DWORD path_size = 0, path_len; + + do { + path_size = path_size ? FFMIN(2 * path_size, INT16_MAX + 1) : MAX_PATH; + new_path = av_realloc_array(path, path_size, sizeof *path); + if (!new_path) { + av_free(path); + return NULL; + } + path = new_path; + // Returns path_size in case of insufficient buffer. + // Whether the error is set or not and whether the output + // is null-terminated or not depends on the version of Windows. + path_len = GetModuleFileNameW(module, path, path_size); + } while (path_len && path_size <= INT16_MAX && path_size <= path_len); + + if (!path_len) { + av_free(path); + return NULL; + } + return path; +} + /** * Safe function used to open dynamic libs. This attempts to improve program security * by removing the current directory from the dll search path. Only dll's found in the @@ -34,29 +63,53 @@ */ static inline HMODULE win32_dlopen(const char *name) { + wchar_t *name_w; + HMODULE module = NULL; + if (utf8towchar(name, &name_w)) + name_w = NULL; #if _WIN32_WINNT < 0x0602 - // Need to check if KB2533623 is available + // On Win7 and earlier we check if KB2533623 is available if (!GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "SetDefaultDllDirectories")) { - HMODULE module = NULL; - wchar_t *path = NULL, *name_w = NULL; - DWORD pathlen; - if (utf8towchar(name, &name_w)) + wchar_t *path = NULL, *new_path; + DWORD pathlen, pathsize, namelen; + if (!name_w) goto exit; - path = (wchar_t *)av_calloc(MAX_PATH, sizeof(wchar_t)); + namelen = wcslen(name_w); // Try local directory first - pathlen = GetModuleFileNameW(NULL, path, MAX_PATH); - pathlen = wcsrchr(path, '\\') - path; - if (pathlen == 0 || pathlen + wcslen(name_w) + 2 > MAX_PATH) + path = get_module_filename(NULL); + if (!path) goto exit; - path[pathlen] = '\\'; + new_path = wcsrchr(path, '\\'); + if (!new_path) + goto exit; + pathlen = new_path - path; + pathsize = pathlen + namelen + 2; + new_path = av_realloc_array(path, pathsize, sizeof *path); + if (!new_path) + goto exit; + path = new_path; wcscpy(path + pathlen + 1, name_w); module = LoadLibraryExW(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); if (module == NULL) { // Next try System32 directory - pathlen = GetSystemDirectoryW(path, MAX_PATH); - if (pathlen == 0 || pathlen + wcslen(name_w) + 2 > MAX_PATH) + pathlen = GetSystemDirectoryW(path, pathsize); + if (!pathlen) goto exit; - path[pathlen] = '\\'; + // Buffer is not enough in two cases: + // 1. system directory + \ + module name + // 2. system directory even without the module name. + if (pathlen + namelen + 2 > pathsize) { + pathsize = pathlen + namelen + 2; + new_path = av_realloc_array(path, pathsize, sizeof *path); + if (!new_path) + goto exit; + path = new_path; + // Query again to handle the case #2. + pathlen = GetSystemDirectoryW(path, pathsize); + if (!pathlen) + goto exit; + } + path[pathlen] = L'\\'; wcscpy(path + pathlen + 1, name_w); module = LoadLibraryExW(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); } @@ -73,16 +126,19 @@ exit: # define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800 #endif #if HAVE_WINRT - wchar_t *name_w = NULL; - int ret; - if (utf8towchar(name, &name_w)) + if (!name_w) return NULL; - ret = LoadPackagedLibrary(name_w, 0); - av_free(name_w); - return ret; + module = LoadPackagedLibrary(name_w, 0); #else - return LoadLibraryExA(name, NULL, LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32); +#define LOAD_FLAGS (LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32) + /* filename may be be in CP_ACP */ + if (!name_w) + return LoadLibraryExA(name, NULL, LOAD_FLAGS); + module = LoadLibraryExW(name_w, NULL, LOAD_FLAGS); +#undef LOAD_FLAGS #endif + av_free(name_w); + return module; } #define dlopen(name, flags) win32_dlopen(name) #define dlclose FreeLibrary diff --git a/configure b/configure index 7a62f0c24..9d6457d81 100755 --- a/configure +++ b/configure @@ -140,7 +140,6 @@ Component options: --disable-dwt disable DWT code --disable-error-resilience disable error resilience code --disable-lsp disable LSP code - --disable-lzo disable LZO decoder code --disable-mdct disable MDCT code --disable-rdft disable RDFT code --disable-fft disable FFT code @@ -216,6 +215,7 @@ External library support: --disable-iconv disable iconv [autodetect] --enable-jni enable JNI support [no] --enable-ladspa enable LADSPA audio filtering [no] + --enable-lcms2 enable ICC profile support via LittleCMS 2 [no] --enable-libaom enable AV1 video encoding/decoding via libaom [no] --enable-libaribb24 enable ARIB text and caption decoding via libaribb24 [no] --enable-libass enable libass subtitles rendering, @@ -241,6 +241,7 @@ External library support: --enable-libiec61883 enable iec61883 via libiec61883 [no] --enable-libilbc enable iLBC de/encoding via libilbc [no] --enable-libjack enable JACK audio sound server [no] + --enable-libjxl enable JPEG XL de/encoding via libjxl [no] --enable-libklvanc enable Kernel Labs VANC processing [no] --enable-libkvazaar enable HEVC encoding via libkvazaar [no] --enable-liblensfun enable lensfun lens correction [no] @@ -255,6 +256,7 @@ External library support: --enable-libopenvino enable OpenVINO as a DNN module backend for DNN based filters like dnn_processing [no] --enable-libopus enable Opus de/encoding via libopus [no] + --enable-libplacebo enable libplacebo library [no] --enable-libpulse enable Pulseaudio input via libpulse [no] --enable-librabbitmq enable RabbitMQ library [no] --enable-librav1e enable AV1 encoding via rav1e [no] @@ -443,6 +445,7 @@ Optimization options (experts only): --disable-fma4 disable FMA4 optimizations --disable-avx2 disable AVX2 optimizations --disable-avx512 disable AVX-512 optimizations + --disable-avx512icl disable AVX-512ICL optimizations --disable-aesni disable AESNI optimizations --disable-armv5te disable armv5te optimizations --disable-armv6 disable armv6 optimizations @@ -1812,6 +1815,7 @@ EXTERNAL_LIBRARY_LIST=" gnutls jni ladspa + lcms2 libaom libass libbluray @@ -1832,6 +1836,7 @@ EXTERNAL_LIBRARY_LIST=" libiec61883 libilbc libjack + libjxl libklvanc libkvazaar libmodplug @@ -1899,7 +1904,6 @@ HWACCEL_AUTODETECT_LIBRARY_LIST=" videotoolbox vulkan v4l2_m2m - xvmc " # catchall list of things that require external libs to link @@ -1975,7 +1979,6 @@ SUBSYSTEM_LIST=" fast_unaligned fft lsp - lzo mdct pixelutils network @@ -2098,6 +2101,7 @@ ARCH_EXT_LIST_X86_SIMD=" avx avx2 avx512 + avx512icl fma3 fma4 mmx @@ -2267,6 +2271,8 @@ SYSTEM_FUNCS=" CommandLineToArgvW fcntl getaddrinfo + getauxval + getenv gethrtime getopt GetModuleHandle @@ -2432,6 +2438,7 @@ CONFIG_EXTRA=" cbs_jpeg cbs_mpeg2 cbs_vp9 + deflate_wrapper dirac_parse dnn dovi_rpu @@ -2460,6 +2467,7 @@ CONFIG_EXTRA=" idctdsp iirfilter mdct15 + inflate_wrapper intrax8 iso_media ividsp @@ -2478,6 +2486,7 @@ CONFIG_EXTRA=" mpegaudioheader mpeg4audio mpegvideo + mpegvideodec mpegvideoenc mss34dsp pixblockdsp @@ -2665,6 +2674,7 @@ fma3_deps="avx" fma4_deps="avx" avx2_deps="avx" avx512_deps="avx2" +avx512icl_deps="avx512" mmx_external_deps="x86asm" mmx_inline_deps="inline_asm x86" @@ -2707,6 +2717,7 @@ cbs_jpeg_select="cbs" cbs_mpeg2_select="cbs" cbs_vp9_select="cbs" dct_select="rdft" +deflate_wrapper_deps="zlib" dirac_parse_select="golomb" dovi_rpu_select="golomb" dnn_suggest="libtensorflow libopenvino" @@ -2719,6 +2730,7 @@ faanidct_select="idctdsp" h264dsp_select="startcode" hevcparse_select="atsc_a53 golomb" frame_thread_encoder_deps="encoders threads" +inflate_wrapper_deps="zlib" intrax8_select="blockdsp idctdsp" iso_media_select="mpeg4audio" mdct_select="fft" @@ -2727,7 +2739,8 @@ me_cmp_select="fdctdsp idctdsp pixblockdsp" mpeg_er_select="error_resilience" mpegaudio_select="mpegaudiodsp mpegaudioheader" mpegaudiodsp_select="dct" -mpegvideo_select="blockdsp h264chroma hpeldsp idctdsp me_cmp mpeg_er videodsp" +mpegvideo_select="blockdsp h264chroma hpeldsp idctdsp videodsp" +mpegvideodec_select="mpegvideo mpeg_er" mpegvideoenc_select="aandcttables me_cmp mpegvideo pixblockdsp qpeldsp" vc1dsp_select="h264chroma qpeldsp startcode" rdft_select="fft" @@ -2752,9 +2765,8 @@ amrwb_decoder_select="lsp" amv_decoder_select="sp5x_decoder exif" amv_encoder_select="jpegtables mpegvideoenc" ape_decoder_select="bswapdsp llauddsp" -apng_decoder_deps="zlib" -apng_encoder_deps="zlib" -apng_encoder_select="llvidencdsp" +apng_decoder_select="inflate_wrapper" +apng_encoder_select="deflate_wrapper llvidencdsp" aptx_decoder_select="audio_frame_queue" aptx_encoder_select="audio_frame_queue" aptx_hd_decoder_select="audio_frame_queue" @@ -2778,7 +2790,7 @@ clearvideo_decoder_select="idctdsp" cllc_decoder_select="bswapdsp" comfortnoise_encoder_select="lpc" cook_decoder_select="audiodsp mdct sinewin" -cscd_decoder_select="lzo" +cri_decoder_select="mjpeg_decoder" cscd_decoder_suggest="zlib" dca_decoder_select="mdct" dca_encoder_select="mdct" @@ -2805,9 +2817,9 @@ ffvhuff_encoder_select="huffyuv_encoder" fic_decoder_select="golomb" flac_decoder_select="flacdsp" flac_encoder_select="bswapdsp flacdsp lpc" -flashsv2_decoder_deps="zlib" -flashsv2_encoder_deps="zlib" -flashsv_decoder_deps="zlib" +flashsv2_decoder_select="inflate_wrapper" +flashsv2_encoder_select="deflate_wrapper" +flashsv_decoder_select="inflate_wrapper" flashsv_encoder_deps="zlib" flv_decoder_select="h263_decoder" flv_encoder_select="h263_encoder" @@ -2816,9 +2828,9 @@ fraps_decoder_select="bswapdsp huffman" g2m_decoder_deps="zlib" g2m_decoder_select="blockdsp idctdsp jpegtables" g729_decoder_select="audiodsp" -h261_decoder_select="mpegvideo" +h261_decoder_select="mpegvideodec" h261_encoder_select="mpegvideoenc" -h263_decoder_select="h263_parser h263dsp mpegvideo qpeldsp" +h263_decoder_select="h263_parser h263dsp mpegvideodec qpeldsp" h263_encoder_select="h263dsp mpegvideoenc" h263i_decoder_select="h263_decoder" h263p_decoder_select="h263_decoder" @@ -2840,12 +2852,12 @@ indeo3_decoder_select="hpeldsp" indeo4_decoder_select="ividsp" indeo5_decoder_select="ividsp" interplay_video_decoder_select="hpeldsp" -ipu_decoder_select="mpegvideo" +ipu_decoder_select="mpegvideodec" jpegls_decoder_select="mjpeg_decoder" jv_decoder_select="blockdsp" lagarith_decoder_select="llviddsp" ljpeg_encoder_select="idctdsp jpegtables" -lscr_decoder_deps="zlib" +lscr_decoder_select="inflate_wrapper" magicyuv_decoder_select="llviddsp" magicyuv_encoder_select="llvidencdsp" mdec_decoder_select="blockdsp bswapdsp idctdsp mpegvideo" @@ -2870,38 +2882,36 @@ mp3on4_decoder_select="mpegaudio mpeg4audio" mp3on4float_decoder_select="mpegaudio mpeg4audio" mpc7_decoder_select="bswapdsp mpegaudiodsp" mpc8_decoder_select="mpegaudiodsp" -mpegvideo_decoder_select="mpegvideo" -mpeg1video_decoder_select="mpegvideo" +mpegvideo_decoder_select="mpegvideodec" +mpeg1video_decoder_select="mpegvideodec" mpeg1video_encoder_select="mpegvideoenc h263dsp" -mpeg2video_decoder_select="mpegvideo" +mpeg2video_decoder_select="mpegvideodec" mpeg2video_encoder_select="mpegvideoenc h263dsp" mpeg4_decoder_select="h263_decoder mpeg4video_parser" mpeg4_encoder_select="h263_encoder" msa1_decoder_select="mss34dsp" -mscc_decoder_deps="zlib" +mscc_decoder_select="inflate_wrapper" msmpeg4v1_decoder_select="h263_decoder" msmpeg4v2_decoder_select="h263_decoder" msmpeg4v2_encoder_select="h263_encoder" msmpeg4v3_decoder_select="h263_decoder" msmpeg4v3_encoder_select="h263_encoder" -mss2_decoder_select="mpegvideo qpeldsp vc1_decoder" +mss2_decoder_select="mpegvideodec qpeldsp vc1_decoder" mts2_decoder_select="jpegtables mss34dsp" mv30_decoder_select="aandcttables blockdsp" -mvha_decoder_deps="zlib" -mvha_decoder_select="llviddsp" -mwsc_decoder_deps="zlib" +mvha_decoder_select="inflate_wrapper llviddsp" +mwsc_decoder_select="inflate_wrapper" mxpeg_decoder_select="mjpeg_decoder" nellymoser_decoder_select="mdct sinewin" nellymoser_encoder_select="audio_frame_queue mdct sinewin" notchlc_decoder_select="lzf" -nuv_decoder_select="idctdsp lzo" +nuv_decoder_select="idctdsp" on2avc_decoder_select="mdct" opus_decoder_deps="swresample" opus_decoder_select="mdct15" opus_encoder_select="audio_frame_queue mdct15" -png_decoder_deps="zlib" -png_encoder_deps="zlib" -png_encoder_select="llvidencdsp" +png_decoder_select="inflate_wrapper" +png_encoder_select="deflate_wrapper llvidencdsp" prores_decoder_select="blockdsp idctdsp" prores_encoder_select="fdctdsp" qcelp_decoder_select="lsp" @@ -2909,7 +2919,7 @@ qdm2_decoder_select="mdct rdft mpegaudiodsp" ra_144_decoder_select="audiodsp" ra_144_encoder_select="audio_frame_queue lpc audiodsp" ralf_decoder_select="golomb" -rasc_decoder_deps="zlib" +rasc_decoder_select="inflate_wrapper" rawvideo_decoder_select="bswapdsp" rscc_decoder_deps="zlib" rtjpeg_decoder_select="me_cmp" @@ -2917,8 +2927,8 @@ rv10_decoder_select="h263_decoder" rv10_encoder_select="h263_encoder" 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" +rv30_decoder_select="golomb h264pred h264qpel mpegvideodec rv34dsp" +rv40_decoder_select="golomb h264pred h264qpel mpegvideodec rv34dsp" screenpresso_decoder_deps="zlib" shorten_decoder_select="bswapdsp" sipr_decoder_select="lsp" @@ -2931,7 +2941,7 @@ sonic_ls_encoder_select="golomb rangecoder" sp5x_decoder_select="mjpeg_decoder" speedhq_decoder_select="mpegvideo" speedhq_encoder_select="mpegvideoenc" -srgc_decoder_deps="zlib" +srgc_decoder_select="inflate_wrapper" svq1_decoder_select="hpeldsp" svq1_encoder_select="hpeldsp me_cmp mpegvideoenc" svq3_decoder_select="golomb h264dsp h264parse h264pred hpeldsp tpeldsp videodsp" @@ -2948,13 +2958,15 @@ truehd_decoder_select="mlp_parser" truehd_encoder_select="lpc audio_frame_queue" truemotion2_decoder_select="bswapdsp" truespeech_decoder_select="bswapdsp" -tscc_decoder_deps="zlib" +tscc_decoder_select="inflate_wrapper" twinvq_decoder_select="mdct lsp sinewin" txd_decoder_select="texturedsp" utvideo_decoder_select="bswapdsp llviddsp" utvideo_encoder_select="bswapdsp huffman llvidencdsp" vble_decoder_select="llviddsp" -vc1_decoder_select="blockdsp h263_decoder h264qpel intrax8 mpegvideo vc1dsp" +vbn_decoder_select="texturedsp" +vbn_encoder_select="texturedspenc" +vc1_decoder_select="blockdsp h263_decoder h264qpel intrax8 mpegvideodec vc1dsp" vc1image_decoder_select="vc1_decoder" vorbis_decoder_select="mdct" vorbis_encoder_select="audio_frame_queue mdct" @@ -2967,7 +2979,7 @@ vp6f_decoder_select="vp6_decoder" vp7_decoder_select="h264pred videodsp vp8dsp" vp8_decoder_select="h264pred videodsp vp8dsp" vp9_decoder_select="videodsp vp9_parser vp9_superframe_split_bsf" -wcmv_decoder_deps="zlib" +wcmv_decoder_select="inflate_wrapper" webp_decoder_select="vp8_decoder exif" wmalossless_decoder_select="llauddsp" wmapro_decoder_select="mdct sinewin wma_freqs" @@ -2985,11 +2997,11 @@ wmv3image_decoder_select="wmv3_decoder" xma1_decoder_select="wmapro_decoder" xma2_decoder_select="wmapro_decoder" ylc_decoder_select="bswapdsp" -zerocodec_decoder_deps="zlib" -zlib_decoder_deps="zlib" -zlib_encoder_deps="zlib" -zmbv_decoder_deps="zlib" -zmbv_encoder_deps="zlib" +zerocodec_decoder_select="inflate_wrapper" +zlib_decoder_select="inflate_wrapper" +zlib_encoder_select="deflate_wrapper" +zmbv_decoder_select="inflate_wrapper" +zmbv_encoder_select="deflate_wrapper" # hardware accelerators crystalhd_deps="libcrystalhd_libcrystalhd_if_h" @@ -3003,7 +3015,6 @@ vaapi_x11_deps="xlib_x11" videotoolbox_hwaccel_deps="videotoolbox pthreads" videotoolbox_hwaccel_extralibs="-framework QuartzCore" vulkan_deps_any="libdl LoadLibrary" -xvmc_deps="X11_extensions_XvMClib_h" av1_d3d11va_hwaccel_deps="d3d11va DXVA_PicParams_AV1" av1_d3d11va_hwaccel_select="av1_decoder" @@ -3015,6 +3026,8 @@ av1_nvdec_hwaccel_deps="nvdec CUVIDAV1PICPARAMS" av1_nvdec_hwaccel_select="av1_decoder" av1_vaapi_hwaccel_deps="vaapi VADecPictureParameterBufferAV1_bit_depth_idx" av1_vaapi_hwaccel_select="av1_decoder" +av1_vdpau_hwaccel_deps="vdpau VdpPictureInfoAV1" +av1_vdpau_hwaccel_select="av1_decoder" h263_vaapi_hwaccel_deps="vaapi" h263_vaapi_hwaccel_select="h263_decoder" h263_videotoolbox_hwaccel_deps="videotoolbox" @@ -3051,16 +3064,12 @@ 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" -mpeg_xvmc_hwaccel_select="mpeg2video_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" mpeg1_videotoolbox_hwaccel_select="mpeg1video_decoder" -mpeg1_xvmc_hwaccel_deps="xvmc" -mpeg1_xvmc_hwaccel_select="mpeg1video_decoder" mpeg2_d3d11va_hwaccel_deps="d3d11va" mpeg2_d3d11va_hwaccel_select="mpeg2video_decoder" mpeg2_d3d11va2_hwaccel_deps="d3d11va" @@ -3075,8 +3084,6 @@ mpeg2_vdpau_hwaccel_deps="vdpau" mpeg2_vdpau_hwaccel_select="mpeg2video_decoder" mpeg2_videotoolbox_hwaccel_deps="videotoolbox" mpeg2_videotoolbox_hwaccel_select="mpeg2video_decoder" -mpeg2_xvmc_hwaccel_deps="xvmc" -mpeg2_xvmc_hwaccel_select="mpeg2video_decoder" mpeg4_nvdec_hwaccel_deps="nvdec" mpeg4_nvdec_hwaccel_select="mpeg4_decoder" mpeg4_vaapi_hwaccel_deps="vaapi" @@ -3126,7 +3133,6 @@ wmv3_vdpau_hwaccel_select="vc1_vdpau_hwaccel" # hardware-accelerated codecs mediafoundation_deps="mftransform_h MFCreateAlignedMemoryBuffer" -mediafoundation_extralibs="-lmfplat -lmfuuid -lole32 -lstrmiids" omx_deps="libdl pthreads" omx_rpi_select="omx" qsv_deps="libmfx" @@ -3136,6 +3142,8 @@ qsvvpp_select="qsv" vaapi_encode_deps="vaapi" v4l2_m2m_deps="linux_videodev2_h sem_timedwait" +chromakey_cuda_filter_deps="ffnvcodec" +chromakey_cuda_filter_deps_any="cuda_nvcc cuda_llvm" hwupload_cuda_filter_deps="ffnvcodec" scale_npp_filter_deps="ffnvcodec libnpp" scale2ref_npp_filter_deps="ffnvcodec libnpp" @@ -3250,7 +3258,7 @@ h264_parser_select="atsc_a53 golomb h264dsp h264parse" hevc_parser_select="hevcparse" mpegaudio_parser_select="mpegaudioheader" mpegvideo_parser_select="mpegvideo" -mpeg4video_parser_select="h263dsp mpegvideo qpeldsp" +mpeg4video_parser_select="h263dsp mpegvideodec qpeldsp" vc1_parser_select="vc1dsp" # bitstream_filters @@ -3292,7 +3300,6 @@ mp2_at_decoder_select="mpegaudioheader" mp3_at_decoder_select="mpegaudioheader" pcm_alaw_at_decoder_deps="audiotoolbox" pcm_mulaw_at_decoder_deps="audiotoolbox" -qdmc_decoder_select="fft" qdmc_at_decoder_deps="audiotoolbox" qdm2_at_decoder_deps="audiotoolbox" aac_at_encoder_deps="audiotoolbox" @@ -3322,6 +3329,7 @@ libcodec2_encoder_deps="libcodec2" libdav1d_decoder_deps="libdav1d" libdav1d_decoder_select="atsc_a53" libdavs2_decoder_deps="libdavs2" +libdavs2_decoder_select="avs2_parser" libfdk_aac_decoder_deps="libfdk_aac" libfdk_aac_encoder_deps="libfdk_aac" libfdk_aac_encoder_select="audio_frame_queue" @@ -3332,6 +3340,8 @@ libgsm_ms_decoder_deps="libgsm" libgsm_ms_encoder_deps="libgsm" libilbc_decoder_deps="libilbc" libilbc_encoder_deps="libilbc" +libjxl_decoder_deps="libjxl libjxl_threads" +libjxl_encoder_deps="libjxl libjxl_threads" libkvazaar_encoder_deps="libkvazaar" libmodplug_demuxer_deps="libmodplug" libmp3lame_encoder_deps="libmp3lame" @@ -3399,6 +3409,7 @@ asf_stream_muxer_select="asf_muxer" av1_demuxer_select="av1_frame_merge_bsf av1_parser" avi_demuxer_select="riffdec exif" avi_muxer_select="riffenc" +avif_muxer_select="mov_muxer" caf_demuxer_select="iso_media" caf_muxer_select="iso_media" dash_muxer_select="mp4_muxer" @@ -3429,13 +3440,13 @@ ivf_muxer_select="av1_metadata_bsf vp9_superframe_bsf" latm_muxer_select="aac_adtstoasc_bsf mpeg4audio" matroska_audio_muxer_select="matroska_muxer" matroska_demuxer_select="riffdec" -matroska_demuxer_suggest="bzlib lzo zlib" -matroska_muxer_select="mpeg4audio riffenc vp9_superframe_bsf aac_adtstoasc_bsf" +matroska_demuxer_suggest="bzlib zlib" +matroska_muxer_select="mpeg4audio riffenc aac_adtstoasc_bsf pgs_frame_merge_bsf vp9_superframe_bsf" mlp_demuxer_select="mlp_parser" mmf_muxer_select="riffenc" mov_demuxer_select="iso_media riffdec" mov_demuxer_suggest="zlib" -mov_muxer_select="iso_media riffenc rtpenc_chain vp9_superframe_bsf aac_adtstoasc_bsf" +mov_muxer_select="iso_media riffenc rtpenc_chain vp9_superframe_bsf aac_adtstoasc_bsf ac3_parser" mp3_demuxer_select="mpegaudio_parser" mp3_muxer_select="mpegaudioheader" mp4_muxer_select="mov_muxer" @@ -3582,6 +3593,8 @@ udp_protocol_select="network" udplite_protocol_select="network" unix_protocol_deps="sys_un_h" unix_protocol_select="network" +ipfs_protocol_select="https_protocol" +ipns_protocol_select="https_protocol" # external library protocols libamqp_protocol_deps="librabbitmq" @@ -3602,19 +3615,16 @@ libzmq_protocol_deps="libzmq" libzmq_protocol_select="network" # filters -afir_filter_deps="avcodec" -afir_filter_select="rdft" ametadata_filter_deps="avformat" amovie_filter_deps="avcodec avformat" aresample_filter_deps="swresample" asr_filter_deps="pocketsphinx" ass_filter_deps="libass" -atempo_filter_deps="avcodec" -atempo_filter_select="rdft" avgblur_opencl_filter_deps="opencl" avgblur_vulkan_filter_deps="vulkan spirv_compiler" azmq_filter_deps="libzmq" blackframe_filter_deps="gpl" +blend_vulkan_filter_deps="vulkan spirv_compiler" bm3d_filter_deps="avcodec" bm3d_filter_select="dct" boxblur_filter_deps="gpl" @@ -3646,10 +3656,6 @@ drawtext_filter_suggest="libfontconfig libfribidi" elbg_filter_deps="avcodec" eq_filter_deps="gpl" erosion_opencl_filter_deps="opencl" -fftfilt_filter_deps="avcodec" -fftfilt_filter_select="rdft" -fftdnoiz_filter_deps="avcodec" -fftdnoiz_filter_select="fft" find_rect_filter_deps="avcodec avformat gpl" firequalizer_filter_deps="avcodec" firequalizer_filter_select="rdft" @@ -3665,6 +3671,8 @@ gblur_vulkan_filter_deps="vulkan spirv_compiler" hflip_vulkan_filter_deps="vulkan spirv_compiler" histeq_filter_deps="gpl" hqdn3d_filter_deps="gpl" +iccdetect_filter_deps="lcms2" +iccgen_filter_deps="lcms2" interlace_filter_deps="gpl" kerndeint_filter_deps="gpl" ladspa_filter_deps="ladspa libdl" @@ -3687,6 +3695,7 @@ openclsrc_filter_deps="opencl" overlay_opencl_filter_deps="opencl" overlay_qsv_filter_deps="libmfx" overlay_qsv_filter_select="qsvvpp" +overlay_vaapi_filter_deps="vaapi VAProcPipelineCaps_blend_flags" overlay_vulkan_filter_deps="vulkan spirv_compiler" owdenoise_filter_deps="gpl" pad_opencl_filter_deps="opencl" @@ -3699,6 +3708,7 @@ prewitt_opencl_filter_deps="opencl" procamp_vaapi_filter_deps="vaapi" program_opencl_filter_deps="opencl" pullup_filter_deps="gpl" +remap_opencl_filter_deps="opencl" removelogo_filter_deps="avcodec avformat swscale" repeatfields_filter_deps="gpl" roberts_opencl_filter_deps="opencl" @@ -3715,8 +3725,6 @@ showcqt_filter_suggest="libfontconfig libfreetype" showspatial_filter_deps="avcodec" showspatial_filter_select="fft" signature_filter_deps="gpl avcodec avformat" -sinc_filter_deps="avcodec" -sinc_filter_select="rdft" smartblur_filter_deps="gpl swscale" sobel_opencl_filter_deps="opencl" sofalizer_filter_deps="libmysofa" @@ -3728,10 +3736,6 @@ stereo3d_filter_deps="gpl" subtitles_filter_deps="avformat avcodec libass" super2xsai_filter_deps="gpl" pixfmts_super2xsai_test_deps="super2xsai_filter" -superequalizer_filter_deps="avcodec" -superequalizer_filter_select="rdft" -surround_filter_deps="avcodec" -surround_filter_select="rdft" tinterlace_filter_deps="gpl" tinterlace_merge_test_deps="tinterlace_filter" tinterlace_pad_test_deps="tinterlace_filter" @@ -3747,7 +3751,7 @@ vaguedenoiser_filter_deps="gpl" vflip_vulkan_filter_deps="vulkan spirv_compiler" vidstabdetect_filter_deps="libvidstab" vidstabtransform_filter_deps="libvidstab" -libvmaf_filter_deps="libvmaf pthreads" +libvmaf_filter_deps="libvmaf" zmq_filter_deps="libzmq" zoompan_filter_deps="swscale" zscale_filter_deps="libzimg const_nan" @@ -4000,14 +4004,14 @@ OUTDEV_LIST=$(find_things_extern muxer AVOutputFormat libavdevice/alldevices.c o 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) -DECODER_LIST=$(find_things_extern decoder AVCodec libavcodec/allcodecs.c) +ENCODER_LIST=$(find_things_extern encoder FFCodec libavcodec/allcodecs.c) +DECODER_LIST=$(find_things_extern decoder FFCodec libavcodec/allcodecs.c) CODEC_LIST=" $ENCODER_LIST $DECODER_LIST " PARSER_LIST=$(find_things_extern parser AVCodecParser libavcodec/parsers.c) -BSF_LIST=$(find_things_extern bsf AVBitStreamFilter libavcodec/bitstream_filters.c) +BSF_LIST=$(find_things_extern bsf FFBitStreamFilter libavcodec/bitstream_filters.c) HWACCEL_LIST=$(find_things_extern hwaccel AVHWAccel libavcodec/hwaccels.h) PROTOCOL_LIST=$(find_things_extern protocol URLProtocol libavformat/protocols.c) @@ -4420,11 +4424,7 @@ cc_default="${cross_prefix}${cc_default}" cxx_default="${cross_prefix}${cxx_default}" nm_default="${cross_prefix}${nm_default}" pkg_config_default="${cross_prefix}${pkg_config_default}" -if ${cross_prefix}${ranlib_default} 2>&1 | grep -q "\-D "; then - ranlib_default="${cross_prefix}${ranlib_default} -D" -else - ranlib_default="${cross_prefix}${ranlib_default}" -fi +ranlib_default="${cross_prefix}${ranlib_default}" strip_default="${cross_prefix}${strip_default}" windres_default="${cross_prefix}${windres_default}" @@ -4457,6 +4457,10 @@ set_default arch cc cxx doxygen pkg_config ranlib strip sysinclude \ enabled cross_compile || host_cc_default=$cc set_default host_cc +if ${ranlib} 2>&1 | grep -q "\-D "; then + ranlib="${ranlib} -D" +fi + pkg_config_fail_message="" if ! $pkg_config --version >/dev/null 2>&1; then warn "$pkg_config not found, library detection may fail." @@ -6146,10 +6150,11 @@ EOF elf*) enabled debug && append X86ASMFLAGS $x86asm_debug ;; esac - enabled avx512 && check_x86asm avx512_external "vmovdqa32 [eax]{k1}{z}, zmm0" - enabled avx2 && check_x86asm avx2_external "vextracti128 xmm0, ymm0, 0" - enabled xop && check_x86asm xop_external "vpmacsdd xmm0, xmm1, xmm2, xmm3" - enabled fma4 && check_x86asm fma4_external "vfmaddps ymm0, ymm1, ymm2, ymm3" + enabled avx512 && check_x86asm avx512_external "vmovdqa32 [eax]{k1}{z}, zmm0" + enabled avx512icl && check_x86asm avx512icl_external "vpdpwssds zmm31{k1}{z}, zmm29, zmm28" + enabled avx2 && check_x86asm avx2_external "vextracti128 xmm0, ymm0, 0" + enabled xop && check_x86asm xop_external "vpmacsdd xmm0, xmm1, xmm2, xmm3" + enabled fma4 && check_x86asm fma4_external "vfmaddps ymm0, ymm1, ymm2, ymm3" check_x86asm cpunop "CPU amdnop" fi @@ -6260,6 +6265,7 @@ check_func_headers lzo/lzo1x.h lzo1x_999_compress check_func_headers mach/mach_time.h mach_absolute_time check_func_headers stdlib.h getenv check_func_headers sys/stat.h lstat +check_func_headers sys/auxv.h getauxval check_func_headers windows.h GetModuleHandle check_func_headers windows.h GetProcessAffinityMask @@ -6315,7 +6321,6 @@ check_headers unistd.h check_headers valgrind/valgrind.h check_func_headers VideoToolbox/VTCompressionSession.h VTCompressionSessionPrepareToEncodeFrames -framework VideoToolbox check_headers windows.h -check_headers X11/extensions/XvMClib.h check_headers asm/types.h # it seems there are versions of clang in some distros that try to use the @@ -6393,6 +6398,7 @@ check_func_headers mfapi.h MFCreateAlignedMemoryBuffer -lmfplat check_type "vdpau/vdpau.h" "VdpPictureInfoHEVC" check_type "vdpau/vdpau.h" "VdpPictureInfoVP9" +check_type "vdpau/vdpau.h" "VdpPictureInfoAV1" if [ -z "$nvccflags" ]; then nvccflags=$nvccflags_default @@ -6504,7 +6510,9 @@ for func in $COMPLEX_FUNCS; do done # these are off by default, so fail if requested and not available -enabled avisynth && require_headers "avisynth/avisynth_c.h" +enabled avisynth && { require_headers "avisynth/avisynth_c.h avisynth/avs/version.h" && + { test_cpp_condition avisynth/avs/version.h "AVS_MAJOR_VER >= 3 && AVS_MINOR_VER >= 7 && AVS_BUGFIX_VER >= 1 || AVS_MAJOR_VER >= 3 && AVS_MINOR_VER > 7 || AVS_MAJOR_VER > 3" || + die "ERROR: AviSynth+ header version must be >= 3.7.1"; } } enabled cuda_nvcc && { check_nvcc cuda_nvcc || die "ERROR: failed checking for nvcc."; } enabled chromaprint && require chromaprint chromaprint.h chromaprint_get_version -lchromaprint enabled decklink && { require_headers DeckLinkAPI.h && @@ -6514,6 +6522,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_headers jni.h && enabled pthreads || die "ERROR: jni not found"; } enabled ladspa && require_headers "ladspa.h dlfcn.h" +enabled lcms2 && require_pkg_config lcms2 "lcms2 >= 2.13" lcms2.h cmsCreateContext enabled libaom && require_pkg_config libaom "aom >= 1.0.0" aom/aom_codec.h aom_codec_version enabled libaribb24 && { check_pkg_config libaribb24 "aribb24 > 1.0.3" "aribb24/aribb24.h" arib_instance_new || { enabled gpl && require_pkg_config libaribb24 aribb24 "aribb24/aribb24.h" arib_instance_new; } || @@ -6553,6 +6562,8 @@ 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 libjxl && require_pkg_config libjxl "libjxl >= 0.7.0" jxl/decode.h JxlDecoderVersion && + require_pkg_config libjxl_threads "libjxl_threads >= 0.7.0" jxl/thread_parallel_runner.h JxlThreadParallelRunner enabled libklvanc && require libklvanc libklvanc/vanc.h klvanc_context_create -lklvanc enabled libkvazaar && require_pkg_config libkvazaar "kvazaar >= 0.8.1" kvazaar.h kvz_api_get enabled liblensfun && require_pkg_config liblensfun lensfun lensfun.h lf_db_new @@ -6562,8 +6573,11 @@ enabled liblensfun && require_pkg_config liblensfun lensfun lensfun.h lf_ # Media SDK or Intel Media Server Studio, these don't come with # pkg-config support. Instead, users should make sure that the build # can find the libraries and headers through other means. -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 libmfx && { check_pkg_config libmfx "libmfx >= 1.28" "mfx/mfxvideo.h" MFXInit || + { require libmfx "mfx/mfxvideo.h mfx/mfxdefs.h" MFXInit "-llibmfx $advapi32_extralibs" && + { test_cpp_condition mfx/mfxdefs.h "MFX_VERSION >= 1028" || die "ERROR: libmfx version must be >= 1.28"; } && + warn "using libmfx without pkg-config"; } } + if enabled libmfx; then check_cc MFX_CODEC_VP9 "mfx/mfxvp9.h mfx/mfxstructures.h" "MFX_CODEC_VP9" fi @@ -6598,7 +6612,7 @@ enabled libplacebo && require_pkg_config libplacebo "libplacebo >= 4.192. enabled libpulse && require_pkg_config libpulse libpulse pulse/pulseaudio.h pa_context_new enabled librabbitmq && require_pkg_config librabbitmq "librabbitmq >= 0.7.1" amqp.h amqp_new_connection enabled librav1e && require_pkg_config librav1e "rav1e >= 0.4.0" rav1e.h rav1e_context_new -enabled librist && require_pkg_config librist "librist >= 0.2" librist/librist.h rist_receiver_create +enabled librist && require_pkg_config librist "librist >= 0.2.7" librist/librist.h rist_receiver_create 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 -lstdc++ && append librubberband_extralibs "-lstdc++" @@ -6611,7 +6625,7 @@ 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 enabled libsrt && require_pkg_config libsrt "srt >= 1.3.0" srt/srt.h srt_socket -enabled libsvtav1 && require_pkg_config libsvtav1 "SvtAv1Enc >= 0.8.4" EbSvtAv1Enc.h svt_av1_enc_init_handle +enabled libsvtav1 && require_pkg_config libsvtav1 "SvtAv1Enc >= 0.9.0" EbSvtAv1Enc.h svt_av1_enc_init_handle enabled libtensorflow && require libtensorflow tensorflow/c/c_api.h TF_Version -ltensorflow enabled libtesseract && require_pkg_config libtesseract tesseract tesseract/capi.h TessBaseAPICreate enabled libtheora && require libtheora theora/theoraenc.h th_info_init -ltheoraenc -ltheoradec -logg @@ -6622,7 +6636,7 @@ enabled libtwolame && require libtwolame twolame.h twolame_init -ltwolame enabled libuavs3d && require_pkg_config libuavs3d "uavs3d >= 1.1.41" uavs3d.h uavs3d_decode 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 >= 1.5.2" libvmaf.h compute_vmaf +enabled libvmaf && require_pkg_config libvmaf "libvmaf >= 2.0.0" libvmaf.h vmaf_init 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 @@ -6652,10 +6666,10 @@ enabled libvpx && { 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 $pthreads_extralibs $libm_extralibs" && - warn "using libx264 without pkg-config"; } } && - require_cpp_condition libx264 x264.h "X264_BUILD >= 118" && +enabled libx264 && check_pkg_config libx264 x264 "stdint.h x264.h" x264_encoder_encode && + require_cpp_condition libx264 x264.h "X264_BUILD >= 118" && { + [ "$toolchain" != "msvc" ] || + require_cpp_condition libx264 x264.h "X264_BUILD >= 158"; } && check_cpp_condition libx262 x264.h "X264_MPEG2" enabled libx265 && require_pkg_config libx265 x265 x265.h x265_api_get && require_cpp_condition libx265 x265.h "X265_BUILD >= 70" @@ -6739,12 +6753,12 @@ fi if enabled sdl2; then SDL2_CONFIG="${cross_prefix}sdl2-config" - test_pkg_config sdl2 "sdl2 >= 2.0.1 sdl2 < 2.1.0" SDL_events.h SDL_PollEvent + test_pkg_config sdl2 "sdl2 >= 2.0.1 sdl2 < 3.0.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) test_cpp_condition SDL.h "(SDL_MAJOR_VERSION<<16 | SDL_MINOR_VERSION<<8 | SDL_PATCHLEVEL) >= 0x020001" $sdl2_cflags && - test_cpp_condition SDL.h "(SDL_MAJOR_VERSION<<16 | SDL_MINOR_VERSION<<8 | SDL_PATCHLEVEL) < 0x020100" $sdl2_cflags && + test_cpp_condition SDL.h "(SDL_MAJOR_VERSION<<16 | SDL_MINOR_VERSION<<8 | SDL_PATCHLEVEL) < 0x030000" $sdl2_cflags && check_func_headers SDL_events.h SDL_PollEvent $sdl2_extralibs $sdl2_cflags && enable sdl2 fi @@ -6872,6 +6886,9 @@ test_cpp <> $TMPH -echo "endif # FFMPEG_CONFIG_MAK" >> ffbuild/config.mak # Do not overwrite an unchanged config.h to avoid superfluous rebuilds. cp_if_changed $TMPH config.h touch ffbuild/.config +# Copy config.asm before printing ALL_COMPONENTS; that's not needed in assembly. enabled x86asm && cp_if_changed $TMPASM config.asm +# Reopen a new TMPH for config_components.h. +cat > $TMPH <> $TMPH +echo "endif # FFMPEG_CONFIG_MAK" >> ffbuild/config.mak + +cp_if_changed $TMPH config_components.h + cat > $TMPH </version_major.h as new installed headers, which only + contain the major version number (and corresponding API deprecation + defines). + +2022-03-15 - cdba98bb80 - swr 4.5.100 - swresample.h + Add swr_alloc_set_opts2() and swr_build_matrix2(). + Deprecate swr_alloc_set_opts() and swr_build_matrix(). + +2022-03-15 - cdba98bb80 - lavfi 8.28.100 - avfilter.h buffersink.h buffersrc.h + Update AVFilterLink for the new channel layout API: add ch_layout, + deprecate channel_layout. + + Update the buffersink filter sink for the new channel layout API: + add av_buffersink_get_ch_layout() and the ch_layouts option, + deprecate av_buffersink_get_channel_layout() and the channel_layouts option. + + Update AVBufferSrcParameters for the new channel layout API: + add ch_layout, deprecate channel_layout. + +2022-03-15 - cdba98bb80 - lavf 59.19.100 - avformat.h + Add AV_DISPOSITION_NON_DIEGETIC. + +2022-03-15 - cdba98bb80 - lavc 59.24.100 - avcodec.h codec_par.h + Update AVCodecParameters for the new channel layout API: add ch_layout, + deprecate channels/channel_layout. + + Update AVCodecContext for the new channel layout API: add ch_layout, + deprecate channels/channel_layout. + + Update AVCodec for the new channel layout API: add ch_layouts, + deprecate channel_layouts. + +2022-03-15 - cdba98bb80 - lavu 57.24.100 - channel_layout.h frame.h opt.h + Add new channel layout API based on the AVChannelLayout struct. + Add support for Ambisonic audio. + Deprecate previous channel layout API based on uint64 bitmasks. + + Add AV_OPT_TYPE_CHLAYOUT option type, deprecate AV_OPT_TYPE_CHANNEL_LAYOUT. + Update AVFrame for the new channel layout API: add ch_layout, deprecate + channels/channel_layout. + +2022-03-10 - f629ea2e18 - lavu 57.23.100 - cpu.h + Add AV_CPU_FLAG_AVX512ICL. + +2022-02-07 - a10f1aec1f - lavu 57.21.100 - fifo.h + Deprecate AVFifoBuffer and the API around it, namely av_fifo_alloc(), + av_fifo_alloc_array(), av_fifo_free(), av_fifo_freep(), av_fifo_reset(), + av_fifo_size(), av_fifo_space(), av_fifo_generic_peek_at(), + av_fifo_generic_peek(), av_fifo_generic_read(), av_fifo_generic_write(), + av_fifo_realloc2(), av_fifo_grow(), av_fifo_drain() and av_fifo_peek2(). + Users should switch to the AVFifo-API. + +2022-02-07 - 7329b22c05 - lavu 57.20.100 - fifo.h + Add a new FIFO API, which allows setting a FIFO element size. + This API operates on these elements rather than on bytes. + Add av_fifo_alloc2(), av_fifo_elem_size(), av_fifo_can_read(), + av_fifo_can_write(), av_fifo_grow2(), av_fifo_drain2(), av_fifo_write(), + av_fifo_write_from_cb(), av_fifo_read(), av_fifo_read_to_cb(), + av_fifo_peek(), av_fifo_peek_to_cb(), av_fifo_drain2(), av_fifo_reset2(), + av_fifo_freep2(), av_fifo_auto_grow_limit(). + +2022-01-26 - af94ab7c7c0 - lavu 57.19.100 - tx.h + Add AV_TX_FLOAT_RDFT, AV_TX_DOUBLE_RDFT and AV_TX_INT32_RDFT. + +-------- 8< --------- FFmpeg 5.0 was cut here -------- 8< --------- + 2022-01-04 - 78dc21b123e - lavu 57.16.100 - frame.h Add AV_FRAME_DATA_DOVI_METADATA. @@ -1603,7 +1689,7 @@ API changes, most recent first: 2014-04-15 - ef818d8 - lavf 55.37.101 - avformat.h Add av_format_inject_global_side_data() -2014-04-12 - 4f698be - lavu 52.76.100 - log.h +2014-04-12 - 4f698be8f - lavu 52.76.100 - log.h Add av_log_get_flags() 2014-04-11 - 6db42a2b - lavd 55.12.100 - avdevice.h diff --git a/doc/Doxyfile b/doc/Doxyfile index 620bc3178..ba0002d5f 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 = 5.0.1 +PROJECT_NUMBER = 5.1 # 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 diff --git a/doc/Makefile b/doc/Makefile index 58ca3fabd..25774c7ba 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -27,6 +27,9 @@ HTMLPAGES = $(AVPROGS-yes:%=doc/%.html) $(AVPROGS-yes:%=doc/%-all.html) $(COMP doc/mailing-list-faq.html \ doc/nut.html \ doc/platform.html \ + $(SRC_PATH)/doc/bootstrap.min.css \ + $(SRC_PATH)/doc/style.min.css \ + $(SRC_PATH)/doc/default.css \ TXTPAGES = doc/fate.txt \ diff --git a/doc/bitstream_filters.texi b/doc/bitstream_filters.texi index 6051dc28d..50c95f035 100644 --- a/doc/bitstream_filters.texi +++ b/doc/bitstream_filters.texi @@ -132,6 +132,36 @@ 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 dv_error_marker + +Blocks in DV which are marked as damaged are replaced by blocks of the specified color. + +@table @option +@item color +The color to replace damaged blocks by +@item sta +A 16 bit mask which specifies which of the 16 possible error status values are +to be replaced by colored blocks. 0xFFFE is the default which replaces all non 0 +error status values. +@table @samp +@item ok +No error, no concealment +@item err +Error, No concealment +@item res +Reserved +@item notok +Error or concealment +@item notres +Not reserved +@item Aa, Ba, Ca, Ab, Bb, Cb, A, B, C, a, b, erri, erru +The specific error status code +@end table +see page 44-46 or section 5.5 of +@url{http://web.archive.org/web/20060927044735/http://www.smpte.org/smpte_store/standards/pdf/s314m.pdf} + +@end table + @section eac3_core Extract the core from a E-AC-3 stream, dropping extra channels. @@ -217,12 +247,16 @@ Modify metadata embedded in an H.264 stream. Insert or remove AUD NAL units in all access units of the stream. @table @samp +@item pass @item insert @item remove @end table +Default is pass. + @item sample_aspect_ratio Set the sample aspect ratio of the stream in the VUI parameters. +See H.264 table E-1. @item overscan_appropriate_flag Set whether the stream is suitable for display using overscan @@ -281,6 +315,37 @@ insert the string ``hello'' associated with the given UUID. @item delete_filler Deletes both filler NAL units and filler SEI messages. +@item display_orientation +Insert, extract or remove Display orientation SEI messages. +See H.264 section D.1.27 and D.2.27 for syntax and semantics. + +@table @samp +@item pass +@item insert +@item remove +@item extract +@end table + +Default is pass. + +Insert mode works in conjunction with @code{rotate} and @code{flip} options. +Any pre-existing Display orientation messages will be removed in insert or remove mode. +Extract mode attaches the display matrix to the packet as side data. + +@item rotate +Set rotation in display orientation SEI (anticlockwise angle in degrees). +Range is -360 to +360. Default is NaN. + +@item flip +Set flip in display orientation SEI. + +@table @samp +@item horizontal +@item vertical +@end table + +Default is unset. + @item level Set the level in the SPS. Refer to H.264 section A.3 and tables A-1 to A-5. @@ -630,6 +695,14 @@ for NTSC frame rate using the @option{frame_rate} option. ffmpeg -f lavfi -i sine=r=48000:d=1 -c pcm_s16le -bsf pcm_rechunk=r=30000/1001 -f framecrc - @end example +@section pgs_frame_merge + +Merge a sequence of PGS Subtitle segments ending with an "end of display set" +segment into a single packet. + +This is required by some containers that support PGS subtitles +(muxer @code{matroska}). + @section prores_metadata Modify color property metadata embedded in prores stream. @@ -736,6 +809,10 @@ It accepts the following parameters: @item pts @item dts Set expressions for PTS, DTS or both. +@item duration +Set expression for duration. +@item time_base +Set output time base. @end table The expressions are evaluated through the eval API and can contain the following @@ -759,6 +836,9 @@ The demux timestamp in input. @item PTS The presentation timestamp in input. +@item DURATION +The duration in input. + @item STARTDTS The DTS of the first packet. @@ -771,15 +851,33 @@ The previous input DTS. @item PREV_INPTS The previous input PTS. +@item PREV_INDURATION +The previous input duration. + @item PREV_OUTDTS The previous output DTS. @item PREV_OUTPTS The previous output PTS. +@item PREV_OUTDURATION +The previous output duration. + +@item NEXT_DTS +The next input DTS. + +@item NEXT_PTS +The next input PTS. + +@item NEXT_DURATION +The next input duration. + @item TB The timebase of stream packet belongs. +@item TB_OUT +The output timebase. + @item SR The sample rate of stream packet belongs. diff --git a/doc/decoders.texi b/doc/decoders.texi index 49ab735dc..e2fcbf5dc 100644 --- a/doc/decoders.texi +++ b/doc/decoders.texi @@ -126,6 +126,63 @@ Set amount of frame threads to use during decoding. The default value is 0 (auto @end table +@section QSV Decoders + +The family of Intel QuickSync Video decoders (VC1, MPEG-2, H.264, HEVC, +JPEG/MJPEG, VP8, VP9, AV1). + +@subsection Common Options + +The following options are supported by all qsv decoders. + +@table @option + +@item @var{async_depth} +Internal parallelization depth, the higher the value the higher the latency. + +@item @var{gpu_copy} +A GPU-accelerated copy between video and system memory +@table @samp +@item default +@item on +@item off +@end table + +@end table + +@subsection HEVC Options +Extra options for hevc_qsv. + +@table @option + +@item @var{load_plugin} +A user plugin to load in an internal session +@table @samp +@item none +@item hevc_sw +@item hevc_hw +@end table + +@item @var{load_plugins} +A :-separate list of hexadecimal plugin UIDs to load in an internal session + +@end table + +@section v210 + +Uncompressed 4:2:2 10-bit decoder. + +@subsection Options + +@table @option + +@item custom_stride +Set the line size of the v210 data in bytes. The default value is 0 +(autodetect). You can use the special -1 value for a strideless v210 as seen in +BOXX files. + +@end table + @c man end VIDEO DECODERS @chapter Audio Decoders diff --git a/doc/demuxers.texi b/doc/demuxers.texi index 26ae768d7..2b6dd86c2 100644 --- a/doc/demuxers.texi +++ b/doc/demuxers.texi @@ -274,6 +274,17 @@ 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. +@subsection Options + +This demuxer accepts the following option: + +@table @option + +@item cenc_decryption_key +16-byte key, in hex, to decrypt files encrypted using ISO Common Encryption (CENC/AES-128 CTR; ISO/IEC 23001-7). + +@end table + @section imf Interoperable Master Format demuxer. @@ -362,6 +373,9 @@ It accepts the following options: @item live_start_index segment index to start live streams at (negative values are from the end). +@item prefer_x_start +prefer to use #EXT-X-START if it's in playlist instead of live_start_index. + @item allowed_extensions ',' separated list of file extensions that hls is allowed to access. @@ -775,6 +789,10 @@ disabled). Default value is -1. @item merge_pmt_versions Re-use existing streams when a PMT's version is updated and elementary streams move to different PIDs. Default value is 0. + +@item max_packet_size +Set maximum size, in bytes, of packet emitted by the demuxer. Payloads above this size +are split across multiple packets. Range is 1 to INT_MAX/2. Default is 204800 bytes. @end table @section mpjpeg diff --git a/doc/encoders.texi b/doc/encoders.texi index e3b61de5a..02a91ffe9 100644 --- a/doc/encoders.texi +++ b/doc/encoders.texi @@ -1271,6 +1271,55 @@ follows. A64 / Commodore 64 multicolor charset encoder. @code{a64_multi5} is extended with 5th color (colram). +@section Cinepak + +Cinepak aka CVID encoder. +Compatible with Windows 3.1 and vintage MacOS. + +@subsection Options + +@table @option +@item g @var{integer} +Keyframe interval. +A keyframe is inserted at least every @code{-g} frames, sometimes sooner. + +@item q:v @var{integer} +Quality factor. Lower is better. Higher gives lower bitrate. +The following table lists bitrates when encoding akiyo_cif.y4m for various values of @code{-q:v} with @code{-g 100}: + +@table @option +@item @code{-q:v 1} 1918 kb/s +@item @code{-q:v 2} 1735 kb/s +@item @code{-q:v 4} 1500 kb/s +@item @code{-q:v 10} 1041 kb/s +@item @code{-q:v 20} 826 kb/s +@item @code{-q:v 40} 553 kb/s +@item @code{-q:v 100} 394 kb/s +@item @code{-q:v 200} 312 kb/s +@item @code{-q:v 400} 266 kb/s +@item @code{-q:v 1000} 237 kb/s +@end table + +@item max_extra_cb_iterations @var{integer} +Max extra codebook recalculation passes, more is better and slower. + +@item skip_empty_cb @var{boolean} +Avoid wasting bytes, ignore vintage MacOS decoder. + +@item max_strips @var{integer} +@itemx min_strips @var{integer} +The minimum and maximum number of strips to use. +Wider range sometimes improves quality. +More strips is generally better quality but costs more bits. +Fewer strips tend to yield more keyframes. +Vintage compatible is 1..3. + +@item strip_number_adaptivity @var{integer} +How much number of strips is allowed to change between frames. +Higher is better but slower. + +@end table + @section GIF GIF image/animation encoder. @@ -1775,28 +1824,15 @@ This is the default. @item high @end table -@item rc -Set the rate control mode to use. - -Possible modes: -@table @option -@item cqp -Constant quantizer: use fixed values of qindex (dependent on the frame type) -throughout the stream. This mode is the default. - -@item vbr -Variable bitrate: use a target bitrate for the whole stream. - -@item cvbr -Constrained variable bitrate: use a target bitrate for each GOP. -@end table - @item qmax Set the maximum quantizer to use when using a bitrate mode. @item qmin Set the minimum quantizer to use when using a bitrate mode. +@item crf +Constant rate factor value used in crf rate control mode (0-63). + @item qp Set the quantizer used in cqp rate control mode (0-63). @@ -1807,8 +1843,8 @@ Enable scene change detection. Set number of frames to look ahead (0-120). @item preset -Set the quality-speed tradeoff, in the range 0 to 8. Higher values are -faster but lower quality. Defaults to 8 (highest speed). +Set the quality-speed tradeoff, in the range 0 to 13. Higher values are +faster but lower quality. @item tile_rows Set log2 of the number of rows of tiles to use (0-6). @@ -1816,6 +1852,45 @@ Set log2 of the number of rows of tiles to use (0-6). @item tile_columns Set log2 of the number of columns of tiles to use (0-4). +@item svtav1-params +Set SVT-AV1 options using a list of @var{key}=@var{value} pairs separated +by ":". See the SVT-AV1 encoder user guide for a list of accepted parameters. + +@end table + +@section libjxl + +libjxl JPEG XL encoder wrapper. + +Requires the presence of the libjxl headers and library during +configuration. You need to explicitly configure the build with +@code{--enable-libjxl}. + +@subsection Options + +The libjxl wrapper supports the following options: + +@table @option + +@item distance +Set the target Butteraugli distance. This is a quality setting: lower +distance yields higher quality, with distance=1.0 roughly comparable to +libjpeg Quality 90 for photographic content. Setting distance=0.0 yields +true lossless encoding. Valid values range between 0.0 and 15.0, and sane +values rarely exceed 5.0. Setting distance=0.1 usually attains +transparency for most input. The default is 1.0. + +@item effort +Set the encoding effort used. Higher effort values produce more consistent +quality and usually produces a better quality/bpp curve, at the cost of +more CPU time required. Valid values range from 1 to 9, and the default is 7. + +@item modular +Force the encoder to use Modular mode instead of choosing automatically. The +default is to use VarDCT for lossy encoding and Modular for lossless. VarDCT +is generally superior to Modular for lossy encoding but does not support +lossless encoding. + @end table @section libkvazaar @@ -2005,8 +2080,11 @@ kilobits/s. @item keyint_min (@emph{kf-min-dist}) @item qmin (@emph{min-q}) +Minimum (Best Quality) Quantizer. @item qmax (@emph{max-q}) +Maximum (Worst Quality) Quantizer. +Can be changed per-frame. @item bufsize (@emph{buf-sz}, @emph{buf-optimal-sz}) Set ratecontrol buffer size (in bits). Note @command{vpxenc}'s options are @@ -2270,11 +2348,10 @@ and compression tools used, and varies the combination of these tools. This maps to the @var{method} option in libwebp. The valid range is 0 to 6. Default is 4. -@item -qscale @var{float} -For lossy encoding, this controls image quality, 0 to 100. For lossless -encoding, this controls the effort and time spent at compressing more. The -default value is 75. Note that for usage via libavcodec, this option is called -@var{global_quality} and must be multiplied by @var{FF_QP2LAMBDA}. +@item -quality @var{float} +For lossy encoding, this controls image quality. For lossless encoding, this +controls the effort and time spent in compression. +Range is 0 to 100. Default is 75. @item -preset @var{type} Configuration preset. This does some automatic settings based on the general @@ -3123,12 +3200,13 @@ Setting a higher @option{bits_per_mb} limit will improve the speed. For the fastest encoding speed set the @option{qscale} parameter (4 is the recommended value) and do not set a size constraint. -@section QSV encoders +@section QSV Encoders -The family of Intel QuickSync Video encoders (MPEG-2, H.264, HEVC, JPEG/MJPEG and VP9) +The family of Intel QuickSync Video encoders (MPEG-2, H.264, HEVC, JPEG/MJPEG +and VP9) +@subsection Ratecontrol Method The ratecontrol method is selected as follows: - @itemize @bullet @item When @option{global_quality} is specified, a quality-based mode is used. @@ -3176,6 +3254,7 @@ Note that depending on your system, a different mode than the one you specified may be selected by the encoder. Set the verbosity level to @var{verbose} or higher to see the actual settings used by the QSV runtime. +@subsection Global Options -> MSDK Options Additional libavcodec global options are mapped to MSDK options as follows: @itemize @@ -3212,6 +3291,389 @@ encoder use CAVLC instead of CABAC. @end itemize +@subsection Common Options +Following options are used by all qsv encoders. + +@table @option +@item @var{async_depth} +Specifies how many asynchronous operations an application performs +before the application explicitly synchronizes the result. If zero, +the value is not specified. + +@item @var{avbr_accuracy} +Accuracy of the AVBR ratecontrol (unit of tenth of percent). + +@item @var{avbr_convergence} +Convergence of the AVBR ratecontrol (unit of 100 frames) + +The parameters @var{avbr_accuracy} and @var{avbr_convergence} are for the +average variable bitrate control (AVBR) algorithm. +The algorithm focuses on overall encoding quality while meeting the specified +bitrate, @var{target_bitrate}, within the accuracy range @var{avbr_accuracy}, +after a @var{avbr_Convergence} period. This method does not follow HRD and the +instant bitrate is not capped or padded. + +@item @var{preset} +This option itemizes a range of choices from veryfast (best speed) to veryslow +(best quality). +@table @samp +@item veryfast +@item faster +@item fast +@item medium +@item slow +@item slower +@item veryslow +@end table + +@item @var{forced_idr} +Forcing I frames as IDR frames. + +@item @var{low_power} +For encoders set this flag to ON to reduce power consumption and GPU usage. +@end table + +@subsection Runtime Options +Following options can be used durning qsv encoding. + +@table @option +@item @var{qsv_config_qp} +Supported in h264_qsv and hevc_qsv. +This option can be set in per-frame metadata. QP parameter can be dynamically +changed when encoding in CQP mode. +@end table + +@subsection H264 options +These options are used by h264_qsv + +@table @option +@item @var{extbrc} +Extended bitrate control. + +@item @var{recovery_point_sei} +Set this flag to insert the recovery point SEI message at the beginning of every +intra refresh cycle. + +@item @var{rdo} +Enable rate distortion optimization. + +@item @var{max_frame_size} +Maximum encoded frame size in bytes. + +@item @var{max_frame_size_i} +Maximum encoded frame size for I frames in bytes. If this value is set as larger +than zero, then for I frames the value set by max_frame_size is ignored. + +@item @var{max_frame_size_p} +Maximum encoded frame size for P frames in bytes. If this value is set as larger +than zero, then for P frames the value set by max_frame_size is ignored. + +@item @var{max_slice_size} +Maximum encoded slice size in bytes. + +@item @var{bitrate_limit} +Toggle bitrate limitations. +Modifies bitrate to be in the range imposed by the QSV encoder. Setting this +flag off may lead to violation of HRD conformance. Mind that specifying bitrate +below the QSV encoder range might significantly affect quality. If on this +option takes effect in non CQP modes: if bitrate is not in the range imposed +by the QSV encoder, it will be changed to be in the range. + +@item @var{mbbrc} +Setting this flag enables macroblock level bitrate control that generally +improves subjective visual quality. Enabling this flag may have negative impact +on performance and objective visual quality metric. + +@item @var{low_delay_brc} +Setting this flag turns on or off LowDelayBRC feautre in qsv plugin, which provides +more accurate bitrate control to minimize the variance of bitstream size frame +by frame. Value: -1-default 0-off 1-on + +@item @var{adaptive_i} +This flag controls insertion of I frames by the QSV encoder. Turn ON this flag +to allow changing of frame type from P and B to I. + +@item @var{adaptive_b} +This flag controls changing of frame type from B to P. + +@item @var{p_strategy} +Enable P-pyramid: 0-default 1-simple 2-pyramid(bf need to be set to 0). + +@item @var{b_strategy} +This option controls usage of B frames as reference. + +@item @var{dblk_idc} +This option disable deblocking. It has value in range 0~2. + +@item @var{cavlc} +If set, CAVLC is used; if unset, CABAC is used for encoding. + +@item @var{vcm} +Video conferencing mode, please see ratecontrol method. + +@item @var{idr_interval} +Distance (in I-frames) between IDR frames. + +@item @var{pic_timing_sei} +Insert picture timing SEI with pic_struct_syntax element. + +@item @var{single_sei_nal_unit} +Put all the SEI messages into one NALU. + +@item @var{max_dec_frame_buffering} +Maximum number of frames buffered in the DPB. + +@item @var{look_ahead} +Use VBR algorithm with look ahead. + +@item @var{look_ahead_depth} +Depth of look ahead in number frames. + +@item @var{look_ahead_downsampling} +Downscaling factor for the frames saved for the lookahead analysis. +@table @samp +@item unknown +@item auto +@item off +@item 2x +@item 4x +@end table + +@item @var{int_ref_type} +Specifies intra refresh type. The major goal of intra refresh is improvement of +error resilience without significant impact on encoded bitstream size caused by +I frames. The SDK encoder achieves this by encoding part of each frame in +refresh cycle using intra MBs. @var{none} means no refresh. @var{vertical} means +vertical refresh, by column of MBs. To enable intra refresh, B frame should be +set to 0. + +@item @var{int_ref_cycle_size} +Specifies number of pictures within refresh cycle starting from 2. 0 and 1 are +invalid values. + +@item @var{int_ref_qp_delta} +Specifies QP difference for inserted intra MBs. This is signed value in +[-51, 51] range if target encoding bit-depth for luma samples is 8 and this +range is [-63, 63] for 10 bit-depth or [-75, 75] for 12 bit-depth respectively. + +@item @var{int_ref_cycle_dist} +Distance between the beginnings of the intra-refresh cycles in frames. + +@item @var{profile} +@table @samp +@item unknown +@item baseline +@item main +@item high +@end table + +@item @var{a53cc} +Use A53 Closed Captions (if available). + +@item @var{aud} +Insert the Access Unit Delimiter NAL. + +@item @var{mfmode} +Multi-Frame Mode. +@table @samp +@item off +@item auto +@end table + +@item @var{repeat_pps} +Repeat pps for every frame. + +@item @var{max_qp_i} +Maximum video quantizer scale for I frame. + +@item @var{min_qp_i} +Minimum video quantizer scale for I frame. + +@item @var{max_qp_p} +Maximum video quantizer scale for P frame. + +@item @var{min_qp_p} +Minimum video quantizer scale for P frame. + +@item @var{max_qp_b} +Maximum video quantizer scale for B frame. + +@item @var{min_qp_b} +Minimum video quantizer scale for B frame. +@end table + +@subsection HEVC Options +These options are used by hevc_qsv + +@table @option +@item @var{extbrc} +Extended bitrate control. + +@item @var{recovery_point_sei} +Set this flag to insert the recovery point SEI message at the beginning of every +intra refresh cycle. + +@item @var{rdo} +Enable rate distortion optimization. + +@item @var{max_frame_size} +Maximum encoded frame size in bytes. + +@item @var{max_frame_size_i} +Maximum encoded frame size for I frames in bytes. If this value is set as larger +than zero, then for I frames the value set by max_frame_size is ignored. + +@item @var{max_frame_size_p} +Maximum encoded frame size for P frames in bytes. If this value is set as larger +than zero, then for P frames the value set by max_frame_size is ignored. + +@item @var{max_slice_size} +Maximum encoded slice size in bytes. + +@item @var{mbbrc} +Setting this flag enables macroblock level bitrate control that generally +improves subjective visual quality. Enabling this flag may have negative impact +on performance and objective visual quality metric. + +@item @var{low_delay_brc} +Setting this flag turns on or off LowDelayBRC feautre in qsv plugin, which provides +more accurate bitrate control to minimize the variance of bitstream size frame +by frame. Value: -1-default 0-off 1-on + +@item @var{p_strategy} +Enable P-pyramid: 0-default 1-simple 2-pyramid(bf need to be set to 0). + +@item @var{b_strategy} +This option controls usage of B frames as reference. + +@item @var{dblk_idc} +This option disable deblocking. It has value in range 0~2. + +@item @var{idr_interval} +Distance (in I-frames) between IDR frames. +@table @samp +@item begin_only +Output an IDR-frame only at the beginning of the stream. +@end table + +@item @var{load_plugin} +A user plugin to load in an internal session. +@table @samp +@item none +@item hevc_sw +@item hevc_hw +@end table + +@item @var{load_plugins} +A :-separate list of hexadecimal plugin UIDs to load in +an internal session. + +@item @var{look_ahead_depth} +Depth of look ahead in number frames, available when extbrc option is enabled. + +@item @var{profile} +Set the encoding profile (scc requires libmfx >= 1.32). + +@table @samp +@item unknown +@item main +@item main10 +@item mainsp +@item rext +@item scc +@end table + +@item @var{gpb} +1: GPB (generalized P/B frame) + +0: regular P frame. + +@item @var{tile_cols} +Number of columns for tiled encoding. + +@item @var{tile_rows} +Number of rows for tiled encoding. + +@item @var{aud} +Insert the Access Unit Delimiter NAL. + +@item @var{pic_timing_sei} +Insert picture timing SEI with pic_struct_syntax element. + +@item @var{transform_skip} +Turn this option ON to enable transformskip. It is supported on platform equal +or newer than ICL. + +@item @var{int_ref_type} +Specifies intra refresh type. The major goal of intra refresh is improvement of +error resilience without significant impact on encoded bitstream size caused by +I frames. The SDK encoder achieves this by encoding part of each frame in +refresh cycle using intra MBs. @var{none} means no refresh. @var{vertical} means +vertical refresh, by column of MBs. To enable intra refresh, B frame should be +set to 0. + +@item @var{int_ref_cycle_size} +Specifies number of pictures within refresh cycle starting from 2. 0 and 1 are +invalid values. + +@item @var{int_ref_qp_delta} +Specifies QP difference for inserted intra MBs. This is signed value in +[-51, 51] range if target encoding bit-depth for luma samples is 8 and this +range is [-63, 63] for 10 bit-depth or [-75, 75] for 12 bit-depth respectively. + +@item @var{int_ref_cycle_dist} +Distance between the beginnings of the intra-refresh cycles in frames. + +@item @var{max_qp_i} +Maximum video quantizer scale for I frame. + +@item @var{min_qp_i} +Minimum video quantizer scale for I frame. + +@item @var{max_qp_p} +Maximum video quantizer scale for P frame. + +@item @var{min_qp_p} +Minimum video quantizer scale for P frame. + +@item @var{max_qp_b} +Maximum video quantizer scale for B frame. + +@item @var{min_qp_b} +Minimum video quantizer scale for B frame. +@end table + +@subsection MPEG2 Options +These options are used by mpeg2_qsv +@table @option +@item @var{profile} +@table @samp +@item unknown +@item simple +@item main +@item high +@end table +@end table + +@subsection VP9 Options +These options are used by vp9_qsv +@table @option +@item @var{profile} +@table @samp +@item unknown +@item profile0 +@item profile1 +@item profile2 +@item profile3 +@end table + +@item @var{tile_cols} +Number of columns for tiled encoding (requires libmfx >= 1.29). + +@item @var{tile_rows} +Number of rows for tiled encoding (requires libmfx >= 1.29). +@end table + @section snow @subsection Options @@ -3292,6 +3754,17 @@ will refer only to P- or I-frames. When set to greater values multiple layers of B-frames will be present, frames in each layer only referring to frames in higher layers. +@item async_depth +Maximum processing parallelism. Increase this to improve single channel +performance. This option doesn't work if driver doesn't implement vaSyncBuffer +function. Please make sure there are enough hw_frames allocated if a large +number of async_depth is used. + +@item max_frame_size +Set the allowed max size in bytes for each frame. If the frame size exceeds +the limitation, encoder will adjust the QP value to control the frame size. +Invalid in CQP rate control mode. + @item rc_mode Set the rate control mode to use. A given driver may only support a subset of modes. @@ -3435,6 +3908,22 @@ required to produce a stream usable with all decoders. @end table +@section vbn + +Vizrt Binary Image encoder. + +This format is used by the broadcast vendor Vizrt for quick texture streaming. +Advanced features of the format such as LZW compression of texture data or +generation of mipmaps are not supported. + +@subsection Options + +@table @option +@item format @var{string} +Sets the texture compression used by the VBN file. Can be @var{dxt1}, +@var{dxt5} or @var{raw}. Default is @var{dxt5}. +@end table + @section vc2 SMPTE VC-2 (previously BBC Dirac Pro). This codec was primarily aimed at diff --git a/doc/examples/decode_audio.c b/doc/examples/decode_audio.c index 6c2a8ed55..49ad22cba 100644 --- a/doc/examples/decode_audio.c +++ b/doc/examples/decode_audio.c @@ -97,7 +97,7 @@ static void decode(AVCodecContext *dec_ctx, AVPacket *pkt, AVFrame *frame, exit(1); } for (i = 0; i < frame->nb_samples; i++) - for (ch = 0; ch < dec_ctx->channels; ch++) + for (ch = 0; ch < dec_ctx->ch_layout.nb_channels; ch++) fwrite(frame->data[ch] + data_size*i, 1, data_size, outfile); } } @@ -215,7 +215,7 @@ int main(int argc, char **argv) sfmt = av_get_packed_sample_fmt(sfmt); } - n_channels = c->channels; + n_channels = c->ch_layout.nb_channels; if ((ret = get_format_from_sample_fmt(&fmt, sfmt)) < 0) goto end; diff --git a/doc/examples/decode_video.c b/doc/examples/decode_video.c index 18ee90a6c..7238e3810 100644 --- a/doc/examples/decode_video.c +++ b/doc/examples/decode_video.c @@ -92,6 +92,7 @@ int main(int argc, char **argv) uint8_t *data; size_t data_size; int ret; + int eof; AVPacket *pkt; if (argc <= 2) { @@ -150,15 +151,16 @@ int main(int argc, char **argv) exit(1); } - while (!feof(f)) { + do { /* read raw data from the input file */ data_size = fread(inbuf, 1, INBUF_SIZE, f); - if (!data_size) + if (ferror(f)) break; + eof = !data_size; /* use the parser to split the data into frames */ data = inbuf; - while (data_size > 0) { + while (data_size > 0 || eof) { ret = av_parser_parse2(parser, c, &pkt->data, &pkt->size, data, data_size, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0); if (ret < 0) { @@ -170,8 +172,10 @@ int main(int argc, char **argv) if (pkt->size) decode(c, frame, pkt, outfilename); + else if (eof) + break; } - } + } while (!eof); /* flush the decoder */ decode(c, frame, NULL, outfilename); diff --git a/doc/examples/demuxing_decoding.c b/doc/examples/demuxing_decoding.c index 8520d5b66..999a78db0 100644 --- a/doc/examples/demuxing_decoding.c +++ b/doc/examples/demuxing_decoding.c @@ -345,7 +345,7 @@ int main (int argc, char **argv) if (audio_stream) { enum AVSampleFormat sfmt = audio_dec_ctx->sample_fmt; - int n_channels = audio_dec_ctx->channels; + int n_channels = audio_dec_ctx->ch_layout.nb_channels; const char *fmt; if (av_sample_fmt_is_planar(sfmt)) { diff --git a/doc/examples/encode_audio.c b/doc/examples/encode_audio.c index ab3586be7..9a1792b72 100644 --- a/doc/examples/encode_audio.c +++ b/doc/examples/encode_audio.c @@ -70,26 +70,25 @@ static int select_sample_rate(const AVCodec *codec) } /* select layout with the highest channel count */ -static int select_channel_layout(const AVCodec *codec) +static int select_channel_layout(const AVCodec *codec, AVChannelLayout *dst) { - const uint64_t *p; - uint64_t best_ch_layout = 0; + const AVChannelLayout *p, *best_ch_layout; int best_nb_channels = 0; - if (!codec->channel_layouts) - return AV_CH_LAYOUT_STEREO; + if (!codec->ch_layouts) + return av_channel_layout_copy(dst, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO); - p = codec->channel_layouts; - while (*p) { - int nb_channels = av_get_channel_layout_nb_channels(*p); + p = codec->ch_layouts; + while (p->nb_channels) { + int nb_channels = p->nb_channels; if (nb_channels > best_nb_channels) { - best_ch_layout = *p; + best_ch_layout = p; best_nb_channels = nb_channels; } p++; } - return best_ch_layout; + return av_channel_layout_copy(dst, best_ch_layout); } static void encode(AVCodecContext *ctx, AVFrame *frame, AVPacket *pkt, @@ -164,8 +163,9 @@ int main(int argc, char **argv) /* select other audio parameters supported by the encoder */ c->sample_rate = select_sample_rate(codec); - c->channel_layout = select_channel_layout(codec); - c->channels = av_get_channel_layout_nb_channels(c->channel_layout); + ret = select_channel_layout(codec, &c->ch_layout); + if (ret < 0) + exit(1); /* open it */ if (avcodec_open2(c, codec, NULL) < 0) { @@ -195,7 +195,9 @@ int main(int argc, char **argv) frame->nb_samples = c->frame_size; frame->format = c->sample_fmt; - frame->channel_layout = c->channel_layout; + ret = av_channel_layout_copy(&frame->ch_layout, &c->ch_layout); + if (ret < 0) + exit(1); /* allocate the data buffers */ ret = av_frame_get_buffer(frame, 0); @@ -218,7 +220,7 @@ int main(int argc, char **argv) for (j = 0; j < c->frame_size; j++) { samples[2*j] = (int)(sin(t) * 10000); - for (k = 1; k < c->channels; k++) + for (k = 1; k < c->ch_layout.nb_channels; k++) samples[2*j + k] = samples[2*j]; t += tincr; } diff --git a/doc/examples/filter_audio.c b/doc/examples/filter_audio.c index 1611e3d95..f53e52562 100644 --- a/doc/examples/filter_audio.c +++ b/doc/examples/filter_audio.c @@ -55,7 +55,7 @@ #define INPUT_SAMPLERATE 48000 #define INPUT_FORMAT AV_SAMPLE_FMT_FLTP -#define INPUT_CHANNEL_LAYOUT AV_CH_LAYOUT_5POINT0 +#define INPUT_CHANNEL_LAYOUT (AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT0 #define VOLUME_VAL 0.90 @@ -100,7 +100,7 @@ static int init_filter_graph(AVFilterGraph **graph, AVFilterContext **src, } /* Set the filter options through the AVOptions API. */ - av_get_channel_layout_string(ch_layout, sizeof(ch_layout), 0, INPUT_CHANNEL_LAYOUT); + av_channel_layout_describe(&INPUT_CHANNEL_LAYOUT, ch_layout, sizeof(ch_layout)); av_opt_set (abuffer_ctx, "channel_layout", ch_layout, AV_OPT_SEARCH_CHILDREN); av_opt_set (abuffer_ctx, "sample_fmt", av_get_sample_fmt_name(INPUT_FORMAT), AV_OPT_SEARCH_CHILDREN); av_opt_set_q (abuffer_ctx, "time_base", (AVRational){ 1, INPUT_SAMPLERATE }, AV_OPT_SEARCH_CHILDREN); @@ -154,9 +154,8 @@ static int init_filter_graph(AVFilterGraph **graph, AVFilterContext **src, /* A third way of passing the options is in a string of the form * key1=value1:key2=value2.... */ snprintf(options_str, sizeof(options_str), - "sample_fmts=%s:sample_rates=%d:channel_layouts=0x%"PRIx64, - av_get_sample_fmt_name(AV_SAMPLE_FMT_S16), 44100, - (uint64_t)AV_CH_LAYOUT_STEREO); + "sample_fmts=%s:sample_rates=%d:channel_layouts=stereo", + av_get_sample_fmt_name(AV_SAMPLE_FMT_S16), 44100); err = avfilter_init_str(aformat_ctx, options_str); if (err < 0) { av_log(NULL, AV_LOG_ERROR, "Could not initialize the aformat filter.\n"); @@ -215,7 +214,7 @@ static int init_filter_graph(AVFilterGraph **graph, AVFilterContext **src, static int process_output(struct AVMD5 *md5, AVFrame *frame) { int planar = av_sample_fmt_is_planar(frame->format); - int channels = av_get_channel_layout_nb_channels(frame->channel_layout); + int channels = frame->ch_layout.nb_channels; int planes = planar ? channels : 1; int bps = av_get_bytes_per_sample(frame->format); int plane_size = bps * frame->nb_samples * (planar ? 1 : channels); @@ -248,7 +247,7 @@ static int get_input(AVFrame *frame, int frame_num) /* Set up the frame properties and allocate the buffer for the data. */ frame->sample_rate = INPUT_SAMPLERATE; frame->format = INPUT_FORMAT; - frame->channel_layout = INPUT_CHANNEL_LAYOUT; + av_channel_layout_copy(&frame->ch_layout, &INPUT_CHANNEL_LAYOUT); frame->nb_samples = FRAME_SIZE; frame->pts = frame_num * FRAME_SIZE; diff --git a/doc/examples/filtering_audio.c b/doc/examples/filtering_audio.c index 7d0eb19bb..51fc47be2 100644 --- a/doc/examples/filtering_audio.c +++ b/doc/examples/filtering_audio.c @@ -94,7 +94,6 @@ static int init_filters(const char *filters_descr) AVFilterInOut *outputs = avfilter_inout_alloc(); AVFilterInOut *inputs = avfilter_inout_alloc(); static const enum AVSampleFormat out_sample_fmts[] = { AV_SAMPLE_FMT_S16, -1 }; - static const int64_t out_channel_layouts[] = { AV_CH_LAYOUT_MONO, -1 }; static const int out_sample_rates[] = { 8000, -1 }; const AVFilterLink *outlink; AVRational time_base = fmt_ctx->streams[audio_stream_index]->time_base; @@ -106,12 +105,13 @@ static int init_filters(const char *filters_descr) } /* buffer audio source: the decoded frames from the decoder will be inserted here. */ - if (!dec_ctx->channel_layout) - dec_ctx->channel_layout = av_get_default_channel_layout(dec_ctx->channels); - snprintf(args, sizeof(args), - "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=0x%"PRIx64, + if (dec_ctx->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) + av_channel_layout_default(&dec_ctx->ch_layout, dec_ctx->ch_layout.nb_channels); + ret = snprintf(args, sizeof(args), + "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=", time_base.num, time_base.den, dec_ctx->sample_rate, - av_get_sample_fmt_name(dec_ctx->sample_fmt), dec_ctx->channel_layout); + av_get_sample_fmt_name(dec_ctx->sample_fmt)); + av_channel_layout_describe(&dec_ctx->ch_layout, args + ret, sizeof(args) - ret); ret = avfilter_graph_create_filter(&buffersrc_ctx, abuffersrc, "in", args, NULL, filter_graph); if (ret < 0) { @@ -134,7 +134,7 @@ static int init_filters(const char *filters_descr) goto end; } - ret = av_opt_set_int_list(buffersink_ctx, "channel_layouts", out_channel_layouts, -1, + ret = av_opt_set(buffersink_ctx, "ch_layouts", "mono", AV_OPT_SEARCH_CHILDREN); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Cannot set output channel layout\n"); @@ -185,7 +185,7 @@ static int init_filters(const char *filters_descr) /* Print summary of the sink buffer * Note: args buffer is reused to store channel layout string */ outlink = buffersink_ctx->inputs[0]; - av_get_channel_layout_string(args, sizeof(args), -1, outlink->channel_layout); + av_channel_layout_describe(&outlink->ch_layout, args, sizeof(args)); av_log(NULL, AV_LOG_INFO, "Output: srate:%dHz fmt:%s chlayout:%s\n", (int)outlink->sample_rate, (char *)av_x_if_null(av_get_sample_fmt_name(outlink->format), "?"), @@ -200,7 +200,7 @@ end: static void print_frame(const AVFrame *frame) { - const int n = frame->nb_samples * av_get_channel_layout_nb_channels(frame->channel_layout); + const int n = frame->nb_samples * frame->ch_layout.nb_channels; const uint16_t *p = (uint16_t*)frame->data[0]; const uint16_t *p_end = p + n; diff --git a/doc/examples/muxing.c b/doc/examples/muxing.c index 8a11e5284..3acb77832 100644 --- a/doc/examples/muxing.c +++ b/doc/examples/muxing.c @@ -170,16 +170,7 @@ static void add_stream(OutputStream *ost, AVFormatContext *oc, c->sample_rate = 44100; } } - c->channels = av_get_channel_layout_nb_channels(c->channel_layout); - c->channel_layout = AV_CH_LAYOUT_STEREO; - if ((*codec)->channel_layouts) { - c->channel_layout = (*codec)->channel_layouts[0]; - for (i = 0; (*codec)->channel_layouts[i]; i++) { - if ((*codec)->channel_layouts[i] == AV_CH_LAYOUT_STEREO) - c->channel_layout = AV_CH_LAYOUT_STEREO; - } - } - c->channels = av_get_channel_layout_nb_channels(c->channel_layout); + av_channel_layout_copy(&c->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO); ost->st->time_base = (AVRational){ 1, c->sample_rate }; break; @@ -224,7 +215,7 @@ static void add_stream(OutputStream *ost, AVFormatContext *oc, /* audio output */ static AVFrame *alloc_audio_frame(enum AVSampleFormat sample_fmt, - uint64_t channel_layout, + const AVChannelLayout *channel_layout, int sample_rate, int nb_samples) { AVFrame *frame = av_frame_alloc(); @@ -236,7 +227,7 @@ static AVFrame *alloc_audio_frame(enum AVSampleFormat sample_fmt, } frame->format = sample_fmt; - frame->channel_layout = channel_layout; + av_channel_layout_copy(&frame->ch_layout, channel_layout); frame->sample_rate = sample_rate; frame->nb_samples = nb_samples; @@ -281,9 +272,9 @@ static void open_audio(AVFormatContext *oc, const AVCodec *codec, else nb_samples = c->frame_size; - ost->frame = alloc_audio_frame(c->sample_fmt, c->channel_layout, + ost->frame = alloc_audio_frame(c->sample_fmt, &c->ch_layout, c->sample_rate, nb_samples); - ost->tmp_frame = alloc_audio_frame(AV_SAMPLE_FMT_S16, c->channel_layout, + ost->tmp_frame = alloc_audio_frame(AV_SAMPLE_FMT_S16, &c->ch_layout, c->sample_rate, nb_samples); /* copy the stream parameters to the muxer */ @@ -301,10 +292,10 @@ static void open_audio(AVFormatContext *oc, const AVCodec *codec, } /* set options */ - av_opt_set_int (ost->swr_ctx, "in_channel_count", c->channels, 0); + av_opt_set_chlayout (ost->swr_ctx, "in_chlayout", &c->ch_layout, 0); av_opt_set_int (ost->swr_ctx, "in_sample_rate", c->sample_rate, 0); av_opt_set_sample_fmt(ost->swr_ctx, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0); - av_opt_set_int (ost->swr_ctx, "out_channel_count", c->channels, 0); + av_opt_set_chlayout (ost->swr_ctx, "out_chlayout", &c->ch_layout, 0); av_opt_set_int (ost->swr_ctx, "out_sample_rate", c->sample_rate, 0); av_opt_set_sample_fmt(ost->swr_ctx, "out_sample_fmt", c->sample_fmt, 0); @@ -330,7 +321,7 @@ static AVFrame *get_audio_frame(OutputStream *ost) for (j = 0; j nb_samples; j++) { v = (int)(sin(ost->t) * 10000); - for (i = 0; i < ost->enc->channels; i++) + for (i = 0; i < ost->enc->ch_layout.nb_channels; i++) *q++ = v; ost->t += ost->tincr; ost->tincr += ost->tincr2; @@ -638,10 +629,6 @@ int main(int argc, char **argv) } } - /* Write the trailer, if any. The trailer must be written before you - * close the CodecContexts open when you wrote the header; otherwise - * av_write_trailer() may try to use memory that was freed on - * av_codec_close(). */ av_write_trailer(oc); /* Close each codec. */ diff --git a/doc/examples/resampling_audio.c b/doc/examples/resampling_audio.c index f35e7e177..9f1521a5a 100644 --- a/doc/examples/resampling_audio.c +++ b/doc/examples/resampling_audio.c @@ -80,7 +80,7 @@ static void fill_samples(double *dst, int nb_samples, int nb_channels, int sampl int main(int argc, char **argv) { - int64_t src_ch_layout = AV_CH_LAYOUT_STEREO, dst_ch_layout = AV_CH_LAYOUT_SURROUND; + AVChannelLayout src_ch_layout = AV_CHANNEL_LAYOUT_STEREO, dst_ch_layout = AV_CHANNEL_LAYOUT_SURROUND; int src_rate = 48000, dst_rate = 44100; uint8_t **src_data = NULL, **dst_data = NULL; int src_nb_channels = 0, dst_nb_channels = 0; @@ -92,6 +92,7 @@ int main(int argc, char **argv) int dst_bufsize; const char *fmt; struct SwrContext *swr_ctx; + char buf[64]; double t; int ret; @@ -120,11 +121,11 @@ int main(int argc, char **argv) } /* set options */ - av_opt_set_int(swr_ctx, "in_channel_layout", src_ch_layout, 0); + av_opt_set_chlayout(swr_ctx, "in_chlayout", &src_ch_layout, 0); av_opt_set_int(swr_ctx, "in_sample_rate", src_rate, 0); av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt", src_sample_fmt, 0); - av_opt_set_int(swr_ctx, "out_channel_layout", dst_ch_layout, 0); + av_opt_set_chlayout(swr_ctx, "out_chlayout", &dst_ch_layout, 0); av_opt_set_int(swr_ctx, "out_sample_rate", dst_rate, 0); av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt", dst_sample_fmt, 0); @@ -136,7 +137,7 @@ int main(int argc, char **argv) /* allocate source and destination samples buffers */ - src_nb_channels = av_get_channel_layout_nb_channels(src_ch_layout); + src_nb_channels = src_ch_layout.nb_channels; ret = av_samples_alloc_array_and_samples(&src_data, &src_linesize, src_nb_channels, src_nb_samples, src_sample_fmt, 0); if (ret < 0) { @@ -151,7 +152,7 @@ int main(int argc, char **argv) av_rescale_rnd(src_nb_samples, dst_rate, src_rate, AV_ROUND_UP); /* buffer is going to be directly written to a rawaudio file, no alignment */ - dst_nb_channels = av_get_channel_layout_nb_channels(dst_ch_layout); + dst_nb_channels = dst_ch_layout.nb_channels; ret = av_samples_alloc_array_and_samples(&dst_data, &dst_linesize, dst_nb_channels, dst_nb_samples, dst_sample_fmt, 0); if (ret < 0) { @@ -194,9 +195,10 @@ int main(int argc, char **argv) if ((ret = get_format_from_sample_fmt(&fmt, dst_sample_fmt)) < 0) goto end; + av_channel_layout_describe(&dst_ch_layout, buf, sizeof(buf)); fprintf(stderr, "Resampling succeeded. Play the output file with the command:\n" - "ffplay -f %s -channel_layout %"PRId64" -channels %d -ar %d %s\n", - fmt, dst_ch_layout, dst_nb_channels, dst_rate, dst_filename); + "ffplay -f %s -channel_layout %s -channels %d -ar %d %s\n", + fmt, buf, dst_nb_channels, dst_rate, dst_filename); end: fclose(dst_file); diff --git a/doc/examples/transcode_aac.c b/doc/examples/transcode_aac.c index 1cf6317e2..2d4f9a59d 100644 --- a/doc/examples/transcode_aac.c +++ b/doc/examples/transcode_aac.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2018 Andreas Unterweger + * Copyright (c) 2013-2022 Andreas Unterweger * * This file is part of FFmpeg. * @@ -62,6 +62,7 @@ static int open_input_file(const char *filename, { AVCodecContext *avctx; const AVCodec *input_codec; + const AVStream *stream; int error; /* Open the input file to read from it. */ @@ -89,8 +90,10 @@ static int open_input_file(const char *filename, return AVERROR_EXIT; } + stream = (*input_format_context)->streams[0]; + /* Find a decoder for the audio stream. */ - if (!(input_codec = avcodec_find_decoder((*input_format_context)->streams[0]->codecpar->codec_id))) { + if (!(input_codec = avcodec_find_decoder(stream->codecpar->codec_id))) { fprintf(stderr, "Could not find input codec\n"); avformat_close_input(input_format_context); return AVERROR_EXIT; @@ -105,7 +108,7 @@ static int open_input_file(const char *filename, } /* Initialize the stream parameters with demuxer information. */ - error = avcodec_parameters_to_context(avctx, (*input_format_context)->streams[0]->codecpar); + error = avcodec_parameters_to_context(avctx, stream->codecpar); if (error < 0) { avformat_close_input(input_format_context); avcodec_free_context(&avctx); @@ -121,6 +124,9 @@ static int open_input_file(const char *filename, return error; } + /* Set the packet timebase for the decoder. */ + avctx->pkt_timebase = stream->time_base; + /* Save the decoder context for easier access later. */ *input_codec_context = avctx; @@ -200,15 +206,11 @@ static int open_output_file(const char *filename, /* 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); + av_channel_layout_default(&avctx->ch_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. */ - avctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; - /* Set the sample rate for the container. */ stream->time_base.den = input_codec_context->sample_rate; stream->time_base.num = 1; @@ -290,21 +292,18 @@ static int init_resampler(AVCodecContext *input_codec_context, /* * Create a resampler context for the conversion. * 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). */ - *resample_context = swr_alloc_set_opts(NULL, - av_get_default_channel_layout(output_codec_context->channels), + error = swr_alloc_set_opts2(resample_context, + &output_codec_context->ch_layout, output_codec_context->sample_fmt, output_codec_context->sample_rate, - av_get_default_channel_layout(input_codec_context->channels), + &input_codec_context->ch_layout, input_codec_context->sample_fmt, input_codec_context->sample_rate, 0, NULL); - if (!*resample_context) { + if (error < 0) { fprintf(stderr, "Could not allocate resample context\n"); - return AVERROR(ENOMEM); + return error; } /* * Perform a sanity check so that the number of converted samples is @@ -332,7 +331,7 @@ static int init_fifo(AVAudioFifo **fifo, AVCodecContext *output_codec_context) { /* 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))) { + output_codec_context->ch_layout.nb_channels, 1))) { fprintf(stderr, "Could not allocate FIFO\n"); return AVERROR(ENOMEM); } @@ -381,6 +380,8 @@ static int decode_audio_frame(AVFrame *frame, if (error < 0) return error; + *data_present = 0; + *finished = 0; /* 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 at the end of the file, flush the decoder below. */ @@ -450,7 +451,7 @@ static int init_converted_samples(uint8_t ***converted_input_samples, * Each pointer will later point to the audio samples of the corresponding * channels (although it may be NULL for interleaved formats). */ - if (!(*converted_input_samples = calloc(output_codec_context->channels, + if (!(*converted_input_samples = calloc(output_codec_context->ch_layout.nb_channels, sizeof(**converted_input_samples)))) { fprintf(stderr, "Could not allocate converted input sample pointers\n"); return AVERROR(ENOMEM); @@ -459,7 +460,7 @@ static int init_converted_samples(uint8_t ***converted_input_samples, /* 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, + output_codec_context->ch_layout.nb_channels, frame_size, output_codec_context->sample_fmt, 0)) < 0) { fprintf(stderr, @@ -559,7 +560,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 = 0; + int data_present; int ret = AVERROR_EXIT; /* Initialize temporary storage for one input frame. */ @@ -633,7 +634,7 @@ static int init_output_frame(AVFrame **frame, * Default channel layouts based on the number of channels * are assumed for simplicity. */ (*frame)->nb_samples = frame_size; - (*frame)->channel_layout = output_codec_context->channel_layout; + av_channel_layout_copy(&(*frame)->ch_layout, &output_codec_context->ch_layout); (*frame)->format = output_codec_context->sample_fmt; (*frame)->sample_rate = output_codec_context->sample_rate; @@ -680,17 +681,16 @@ static int encode_audio_frame(AVFrame *frame, pts += frame->nb_samples; } + *data_present = 0; /* Send the audio frame stored in the temporary packet to the encoder. * The output audio stream encoder is used to do this. */ 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", - av_err2str(error)); - goto cleanup; + /* Check for errors, but proceed with fetching encoded samples if the + * encoder signals that it has nothing more to encode. */ + if (error < 0 && error != AVERROR_EOF) { + fprintf(stderr, "Could not send packet for encoding (error '%s')\n", + av_err2str(error)); + goto cleanup; } /* Receive one encoded frame from the encoder. */ @@ -861,7 +861,6 @@ 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; diff --git a/doc/examples/transcoding.c b/doc/examples/transcoding.c index badfba62c..013f89fc7 100644 --- a/doc/examples/transcoding.c +++ b/doc/examples/transcoding.c @@ -175,8 +175,9 @@ static int open_output_file(const char *filename) enc_ctx->time_base = av_inv_q(dec_ctx->framerate); } else { enc_ctx->sample_rate = dec_ctx->sample_rate; - enc_ctx->channel_layout = dec_ctx->channel_layout; - enc_ctx->channels = av_get_channel_layout_nb_channels(enc_ctx->channel_layout); + ret = av_channel_layout_copy(&enc_ctx->ch_layout, &dec_ctx->ch_layout); + if (ret < 0) + return ret; /* take first format from list of supported formats */ enc_ctx->sample_fmt = encoder->sample_fmts[0]; enc_ctx->time_base = (AVRational){1, enc_ctx->sample_rate}; @@ -289,6 +290,7 @@ static int init_filter(FilteringContext* fctx, AVCodecContext *dec_ctx, goto end; } } else if (dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) { + char buf[64]; buffersrc = avfilter_get_by_name("abuffer"); buffersink = avfilter_get_by_name("abuffersink"); if (!buffersrc || !buffersink) { @@ -297,14 +299,14 @@ static int init_filter(FilteringContext* fctx, AVCodecContext *dec_ctx, goto end; } - if (!dec_ctx->channel_layout) - dec_ctx->channel_layout = - av_get_default_channel_layout(dec_ctx->channels); + if (dec_ctx->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) + av_channel_layout_default(&dec_ctx->ch_layout, dec_ctx->ch_layout.nb_channels); + av_channel_layout_describe(&dec_ctx->ch_layout, buf, sizeof(buf)); snprintf(args, sizeof(args), - "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=0x%"PRIx64, + "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=%s", dec_ctx->time_base.num, dec_ctx->time_base.den, dec_ctx->sample_rate, av_get_sample_fmt_name(dec_ctx->sample_fmt), - dec_ctx->channel_layout); + buf); ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in", args, NULL, filter_graph); if (ret < 0) { @@ -327,9 +329,9 @@ static int init_filter(FilteringContext* fctx, AVCodecContext *dec_ctx, goto end; } - ret = av_opt_set_bin(buffersink_ctx, "channel_layouts", - (uint8_t*)&enc_ctx->channel_layout, - sizeof(enc_ctx->channel_layout), AV_OPT_SEARCH_CHILDREN); + av_channel_layout_describe(&enc_ctx->ch_layout, buf, sizeof(buf)); + ret = av_opt_set(buffersink_ctx, "ch_layouts", + buf, AV_OPT_SEARCH_CHILDREN); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Cannot set output channel layout\n"); goto end; diff --git a/doc/fate.texi b/doc/fate.texi index c3550785a..845085601 100644 --- a/doc/fate.texi +++ b/doc/fate.texi @@ -79,6 +79,21 @@ Do not put a '~' character in the samples path to indicate a home directory. Because of shell nuances, this will cause FATE to fail. @end float +To get the complete list of tests, run the command: +@example +make fate-list +@end example + +You can specify a subset of tests to run by specifying the +corresponding elements from the list with the @code{fate-} prefix, +e.g. as in: +@example +make fate-ffprobe_compact fate-ffprobe_xml +@end example + +This makes it easier to run a few tests in case of failure without +running the complete test suite. + To use a custom wrapper to run the test, pass @option{--target-exec} to @command{configure} or set the @var{TARGET_EXEC} Make variable. diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index 164419cad..767df69b7 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -518,6 +518,21 @@ see @ref{time duration syntax,,the Time duration section in the ffmpeg-utils(1) Like the @code{-ss} option but relative to the "end of file". That is negative values are earlier in the file, 0 is at EOF. +@item -isync @var{input_index} (@emph{input}) +Assign an input as a sync source. + +This will take the difference between the start times of the target and reference inputs and +offset the timestamps of the target file by that difference. The source timestamps of the two +inputs should derive from the same clock source for expected results. If @code{copyts} is set +then @code{start_at_zero} must also be set. If either of the inputs has no starting timestamp +then no sync adjustment is made. + +Acceptable values are those that refer to a valid ffmpeg input index. If the sync reference is +the target index itself or @var{-1}, then no adjustment is made to target timestamps. A sync +reference may not itself be synced to any other input. + +Default value is @var{-1}. + @item -itsoffset @var{offset} (@emph{input}) Set the input time offset. @@ -624,21 +639,21 @@ The parameters set for each target are as follows. @var{pal}: -f vcd -muxrate 1411200 -muxpreload 0.44 -packetsize 2324 -s 352x288 -r 25 --codec:v mpeg1video -g 15 -b:v 1150k -maxrate:v 1150v -minrate:v 1150k -bufsize:v 327680 +-codec:v mpeg1video -g 15 -b:v 1150k -maxrate:v 1150k -minrate:v 1150k -bufsize:v 327680 -ar 44100 -ac 2 -codec:a mp2 -b:a 224k @var{ntsc}: -f vcd -muxrate 1411200 -muxpreload 0.44 -packetsize 2324 -s 352x240 -r 30000/1001 --codec:v mpeg1video -g 18 -b:v 1150k -maxrate:v 1150v -minrate:v 1150k -bufsize:v 327680 +-codec:v mpeg1video -g 18 -b:v 1150k -maxrate:v 1150k -minrate:v 1150k -bufsize:v 327680 -ar 44100 -ac 2 -codec:a mp2 -b:a 224k @var{film}: -f vcd -muxrate 1411200 -muxpreload 0.44 -packetsize 2324 -s 352x240 -r 24000/1001 --codec:v mpeg1video -g 18 -b:v 1150k -maxrate:v 1150v -minrate:v 1150k -bufsize:v 327680 +-codec:v mpeg1video -g 18 -b:v 1150k -maxrate:v 1150k -minrate:v 1150k -bufsize:v 327680 -ar 44100 -ac 2 -codec:a mp2 -b:a 224k @end example @@ -1618,12 +1633,14 @@ it may cause packet loss. It is useful for when flow speed of output packets is important, such as live streaming. @item -re (@emph{input}) Read input at native frame rate. This is equivalent to setting @code{-readrate 1}. -@item -vsync @var{parameter} -Video sync method. +@item -vsync @var{parameter} (@emph{global}) +@itemx -fps_mode[:@var{stream_specifier}] @var{parameter} (@emph{output,per-stream}) +Set video sync method / framerate mode. vsync is applied to all output video streams +but can be overridden for a stream by setting fps_mode. vsync is deprecated and will be +removed in the future. -For compatibility reasons some of the values can be specified as numbers (shown -in parentheses in the following table). This is deprecated and will stop working -in the future. +For compatibility reasons some of the values for vsync can be specified as numbers (shown +in parentheses in the following table). @table @option @item passthrough (0) @@ -1747,7 +1764,7 @@ 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. +Finish encoding when the shortest output stream ends. @item -dts_delta_threshold Timestamp discontinuity delta threshold. @item -dts_error_threshold @var{seconds} @@ -1887,7 +1904,7 @@ This option sets the maximum number of queued packets when reading from the file or device. With low latency / high rate live streams, packets may be discarded if they are not read in a timely manner; setting this value can force ffmpeg to use a separate input thread and read packets as soon as they -arrive. By default ffmpeg only do this if multiple inputs are specified. +arrive. By default ffmpeg only does this if multiple inputs are specified. @item -sdp_file @var{file} (@emph{global}) Print sdp information for an output stream to @var{file}. diff --git a/doc/ffplay.texi b/doc/ffplay.texi index e187b5852..5dd860b84 100644 --- a/doc/ffplay.texi +++ b/doc/ffplay.texi @@ -34,10 +34,6 @@ various FFmpeg APIs. Force displayed width. @item -y @var{height} Force displayed height. -@item -s @var{size} -Set frame size (WxH or abbreviation), needed for videos which do -not contain a header with the frame size like raw YUV. This option -has been deprecated in favor of private options, try -video_size. @item -fs Start in fullscreen mode. @item -an @@ -126,10 +122,6 @@ Read @var{input_url}. @section Advanced options @table @option -@item -pix_fmt @var{format} -Set pixel format. -This option has been deprecated in favor of private options, try -pixel_format. - @item -stats Print several playback statistics, in particular show the stream duration, the codec parameters, the current position in the stream and @@ -222,8 +214,6 @@ Pause. Toggle mute. @item 9, 0 -Decrease and increase volume respectively. - @item /, * Decrease and increase volume respectively. diff --git a/doc/ffprobe.texi b/doc/ffprobe.texi index 59a397a22..4dc9f577b 100644 --- a/doc/ffprobe.texi +++ b/doc/ffprobe.texi @@ -12,7 +12,7 @@ @chapter Synopsis -ffprobe [@var{options}] [@file{input_url}] +ffprobe [@var{options}] @file{input_url} @chapter Description @c man begin DESCRIPTION @@ -28,6 +28,9 @@ If a url is specified in input, ffprobe will try to open and probe the url content. If the url cannot be opened or recognized as a multimedia file, a positive exit code is returned. +If no output is specified as output with @option{o} ffprobe will write +to stdout. + ffprobe may be employed both as a standalone application or in combination with a textual filter, which may perform more sophisticated processing, e.g. statistical processing or plotting. @@ -348,6 +351,10 @@ on the specific build. @item -i @var{input_url} Read @var{input_url}. +@item -o @var{output_url} +Write output to @var{output_url}. If not specified, the output is sent +to stdout. + @end table @c man end diff --git a/doc/filters.texi b/doc/filters.texi index 05d4b1a56..40f21fb34 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -557,6 +557,22 @@ Set input gain level. Allowed range is from 0 to 1. Default value is 1. @item gains Set output gain for each band. Default value is 1 for all bands. + +@item precision +Set which precision to use when processing samples. + +@table @option +@item auto +Auto pick internal sample format depending on other filters. + +@item float +Always use single-floating point precision sample format. + +@item double +Always use double-floating point precision sample format. +@end table + +Default value is @code{auto}. @end table @subsection Examples @@ -913,6 +929,16 @@ Cut frequencies above detection threshold. Boost frequencies bellow detection threshold. @end table Default mode is @samp{cut}. + +@item tftype +Set the type of target filter, can be one of the following: + +@table @samp +@item bell +@item lowshelf +@item highshelf +@end table +Default type is @samp{bell}. @end table @subsection Commands @@ -1282,89 +1308,150 @@ Denoise audio samples with FFT. A description of the accepted parameters follows. @table @option -@item nr +@item noise_reduction, nr Set the noise reduction in dB, allowed range is 0.01 to 97. Default value is 12 dB. -@item nf +@item noise_floor, nf Set the noise floor in dB, allowed range is -80 to -20. Default value is -50 dB. -@item nt +@item noise_type, nt Set the noise type. It accepts the following values: @table @option -@item w +@item white, w Select white noise. -@item v +@item vinyl, v Select vinyl noise. -@item s +@item shellac, s Select shellac noise. -@item c +@item custom, c Select custom noise, defined in @code{bn} option. Default value is white noise. @end table -@item bn -Set custom band noise for every one of 15 bands. +@item band_noise, bn +Set custom band noise profile for every one of 15 bands. Bands are separated by ' ' or '|'. -@item rf +@item residual_floor, rf Set the residual floor in dB, allowed range is -80 to -20. Default value is -38 dB. -@item tn -Enable noise tracking. By default is disabled. +@item track_noise, tn +Enable noise floor tracking. By default is disabled. With this enabled, noise floor is automatically adjusted. -@item tr +@item track_residual, tr Enable residual tracking. By default is disabled. -@item om +@item output_mode, om Set the output mode. It accepts the following values: @table @option -@item i +@item input, i Pass input unchanged. -@item o +@item output, o Pass noise filtered out. -@item n +@item noise, n Pass only noise. -Default value is @var{o}. +Default value is @var{output}. @end table + +@item adaptivity, ad +Set the adaptivity factor, used how fast to adapt gains adjustments per +each frequency bin. Value @var{0} enables instant adaptation, while higher values +react much slower. +Allowed range is from @var{0} to @var{1}. Default value is @var{0.5}. + +@item floor_offset, fo +Set the noise floor offset factor. This option is used to adjust offset applied to measured +noise floor. It is only effective when noise floor tracking is enabled. +Allowed range is from @var{-2.0} to @var{2.0}. Default value is @var{1.0}. + +@item noise_link, nl +Set the noise link used for multichannel audio. + +It accepts the following values: +@table @option +@item none +Use unchanged channel's noise floor. + +@item min +Use measured min noise floor of all channels. + +@item max +Use measured max noise floor of all channels. + +@item average +Use measured average noise floor of all channels. + +Default value is @var{min}. +@end table + +@item band_multiplier, bm +Set the band multiplier factor, used how much to spread bands across frequency bins. +Allowed range is from @var{0.2} to @var{5}. Default value is @var{1.25}. + +@item sample_noise, sn +Toggle capturing and measurement of noise profile from input audio. + +It accepts the following values: +@table @option +@item start, begin +Start sample noise capture. + +@item stop, end +Stop sample noise capture and measure new noise band profile. + +Default value is @code{none}. +@end table + +@item gain_smooth, gs +Set gain smooth spatial radius, used to smooth gains applied to each frequency bin. +Useful to reduce random music noise artefacts. +Higher values increases smoothing of gains. +Allowed range is from @code{0} to @code{50}. +Default value is @code{0}. @end table @subsection Commands -This filter supports the following commands: -@table @option -@item sample_noise, sn -Start or stop measuring noise profile. -Syntax for the command is : "start" or "stop" string. -After measuring noise profile is stopped it will be -automatically applied in filtering. +This filter supports the some above mentioned options as @ref{commands}. -@item noise_reduction, nr -Change noise reduction. Argument is single float number. -Syntax for the command is : "@var{noise_reduction}" +@subsection Examples -@item noise_floor, nf -Change noise floor. Argument is single float number. -Syntax for the command is : "@var{noise_floor}" +@itemize +@item +Reduce white noise by 10dB, and use previously measured noise floor of -40dB: +@example +afftdn=nr=10:nf=-40 +@end example -@item output_mode, om -Change output mode operation. -Syntax for the command is : "i", "o" or "n" string. -@end table +@item +Reduce white noise by 10dB, also set initial noise floor to -80dB and enable automatic +tracking of noise floor so noise floor will gradually change during processing: +@example +afftdn=nr=10:nf=-80:tn=1 +@end example + +@item +Reduce noise by 20dB, using noise floor of -40dB and using commands to take noise profile +of first 0.4 seconds of input audio: +@example +asendcmd=0.0 afftdn sn start,asendcmd=0.4 afftdn sn stop,afftdn=nr=20:nf=-40 +@end example +@end itemize @section afftfilt Apply arbitrary expressions to samples in frequency domain. @@ -1568,6 +1655,22 @@ Allowed range is from @var{1} to @var{32}. Default is @var{1}. Set IR stream which will be used for convolution, starting from @var{0}, should always be lower than supplied value by @code{nbirs} option. Default is @var{0}. This option can be changed at runtime via @ref{commands}. + +@item precision +Set which precision to use when processing samples. + +@table @option +@item auto +Auto pick internal sample format depending on other filters. + +@item float +Always use single-floating point precision sample format. + +@item double +Always use double-floating point precision sample format. +@end table + +Default value is auto. @end table @subsection Examples @@ -1924,6 +2027,11 @@ in release time while 1 produces higher release times. @item level Auto level output signal. Default is enabled. This normalizes audio back to 0dB if enabled. + +@item latency +Compensate the delay introduced by using the lookahead buffer set with attack +parameter. Also flush the valid audio data in the lookahead buffer when the +stream hits EOF. @end table Depending on picked setting it is recommended to upsample input 2x or 4x times @@ -1979,9 +2087,11 @@ Set transform type of IIR filter. @table @option @item di @item dii +@item tdi @item tdii @item latt @item svf +@item zdf @end table @item precision, r @@ -2266,7 +2376,7 @@ The filter accepts the following options: @table @option @item strength, s -Set denoising strength. Allowed range is from 0.00001 to 10. Default value is 0.00001. +Set denoising strength. Allowed range is from 0.00001 to 10000. Default value is 0.00001. @item patch, p Set patch radius duration. Allowed range is from 1 to 100 milliseconds. @@ -2294,7 +2404,7 @@ Default value is @var{o}. @end table @item smooth, m -Set smooth factor. Default value is @var{11}. Allowed range is from @var{1} to @var{15}. +Set smooth factor. Default value is @var{11}. Allowed range is from @var{1} to @var{1000}. @end table @subsection Commands @@ -2508,7 +2618,7 @@ Output only difference samples, useful to hear introduced distortions. By default is disabled. @item adaptive -Set strenght of adaptive distortion applied. Default value is 0.5. +Set strength of adaptive distortion applied. Default value is 0.5. Allowed range is from 0 to 1. @item iterations @@ -3053,15 +3163,18 @@ The filter accepts the following options: @table @option @item dry Set dry gain, how much of original signal is kept. Allowed range is from 0 to 1. -Default value is 0.7. +Default value is 1.0. @item wet Set wet gain, how much of filtered signal is kept. Allowed range is from 0 to 1. -Default value is 0.7. +Default value is 1.0. + +@item boost +Set max boost factor. Allowed range is from 1 to 12. Default value is 2. @item decay Set delay line decay gain value. Allowed range is from 0 to 1. -Default value is 0.7. +Default value is 0.0. @item feedback Set delay line feedback gain value. Allowed range is from 0 to 1. @@ -3078,6 +3191,9 @@ Default value is 0.5. @item delay Set delay. Allowed range is from 1 to 100. Default value is 20. + +@item channels +Set the channels to process. Default value is all available. @end table @subsection Commands @@ -3408,9 +3524,11 @@ Set transform type of IIR filter. @table @option @item di @item dii +@item tdi @item tdii @item latt @item svf +@item zdf @end table @item precision, r @@ -3427,6 +3545,13 @@ Always use float 32-bit. @item f64 Always use float 64-bit. @end table + +@item block_size, b +Set block size used for reverse IIR processing. If this value is set to high enough +value (higher than impulse response length truncated when reaches near zero values) filtering +will become linear phase otherwise if not big enough it will just produce nasty artifacts. + +Note that filter delay will be exactly this many samples when set to non-zero value. @end table @subsection Commands @@ -3496,9 +3621,11 @@ Set transform type of IIR filter. @table @option @item di @item dii +@item tdi @item tdii @item latt @item svf +@item zdf @end table @item precision, r @@ -3515,6 +3642,13 @@ Always use float 32-bit. @item f64 Always use float 64-bit. @end table + +@item block_size, b +Set block size used for reverse IIR processing. If this value is set to high enough +value (higher than impulse response length truncated when reaches near zero values) filtering +will become linear phase otherwise if not big enough it will just produce nasty artifacts. + +Note that filter delay will be exactly this many samples when set to non-zero value. @end table @subsection Commands @@ -3594,9 +3728,11 @@ Set transform type of IIR filter. @table @option @item di @item dii +@item tdi @item tdii @item latt @item svf +@item zdf @end table @item precision, r @@ -3613,6 +3749,13 @@ Always use float 32-bit. @item f64 Always use float 64-bit. @end table + +@item block_size, b +Set block size used for reverse IIR processing. If this value is set to high enough +value (higher than impulse response length truncated when reaches near zero values) filtering +will become linear phase otherwise if not big enough it will just produce nasty artifacts. + +Note that filter delay will be exactly this many samples when set to non-zero value. @end table @subsection Commands @@ -3677,9 +3820,11 @@ Set transform type of IIR filter. @table @option @item di @item dii +@item tdi @item tdii @item latt @item svf +@item zdf @end table @item precision, r @@ -3696,6 +3841,13 @@ Always use float 32-bit. @item f64 Always use float 64-bit. @end table + +@item block_size, b +Set block size used for reverse IIR processing. If this value is set to high enough +value (higher than impulse response length truncated when reaches near zero values) filtering +will become linear phase otherwise if not big enough it will just produce nasty artifacts. + +Note that filter delay will be exactly this many samples when set to non-zero value. @end table @section bs2b @@ -4066,6 +4218,10 @@ Set temperature in degrees Celsius. This is the temperature of the environment. Default is 20. @end table +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section crossfeed Apply headphone crossfeed filter. @@ -4097,6 +4253,13 @@ Set input gain. Default is 0.9. @item level_out Set output gain. Default is 1. + +@item block_size +Set block size used for reverse IIR processing. If this value is set to high enough +value (higher than impulse response length truncated when reaches near zero values) filtering +will become linear phase otherwise if not big enough it will just produce nasty artifacts. + +Note that filter delay will be exactly this many samples when set to non-zero value. @end table @subsection Commands @@ -4178,6 +4341,34 @@ Default value is @var{o}. @end table +@section dialoguenhance +Enhance dialogue in stereo audio. + +This filter accepts stereo input and produce surround (3.0) channels output. +The newly produced front center channel have enhanced speech dialogue originally +available in both stereo channels. +This filter outputs front left and front right channels same as available in stereo input. + +The filter accepts the following options: + +@table @option +@item original +Set the original center factor to keep in front center channel output. +Allowed range is from 0 to 1. Default value is 1. + +@item enhance +Set the dialogue enhance factor to put in front center channel output. +Allowed range is from 0 to 3. Default value is 1. + +@item voice +Set the voice detection factor. +Allowed range is from 2 to 32. Default value is 2. +@end table + +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section drmeter Measure audio dynamic range. @@ -4357,6 +4548,16 @@ If input frame volume is above this value frame will be normalized. Otherwise frame may not be normalized at all. The default value is set to 0, which means all input frames will be normalized. This option is mostly useful if digital noise is not wanted to be amplified. + +@item channels, h +Specify which channels to filter, by default all available channels are filtered. + +@item overlap, o +Specify overlap for frames. If set to 0 (default) no frame overlapping is done. +Using >0 and <1 values will make less conservative gain adjustments, like +when framelen option is set to smaller value, if framelen option value is +compensated for non-zero overlap then gain adjustments will be smoother across time +compared to zero overlap case. @end table @subsection Commands @@ -4428,9 +4629,11 @@ Set transform type of IIR filter. @table @option @item di @item dii +@item tdi @item tdii @item latt @item svf +@item zdf @end table @item precision, r @@ -4447,6 +4650,13 @@ Always use float 32-bit. @item f64 Always use float 64-bit. @end table + +@item block_size, b +Set block size used for reverse IIR processing. If this value is set to high enough +value (higher than impulse response length truncated when reaches near zero values) filtering +will become linear phase otherwise if not big enough it will just produce nasty artifacts. + +Note that filter delay will be exactly this many samples when set to non-zero value. @end table @subsection Examples @@ -4930,9 +5140,11 @@ Set transform type of IIR filter. @table @option @item di @item dii +@item tdi @item tdii @item latt @item svf +@item zdf @end table @item precision, r @@ -4949,6 +5161,13 @@ Always use float 32-bit. @item f64 Always use float 64-bit. @end table + +@item block_size, b +Set block size used for reverse IIR processing. If this value is set to high enough +value (higher than impulse response length truncated when reaches near zero values) filtering +will become linear phase otherwise if not big enough it will just produce nasty artifacts. + +Note that filter delay will be exactly this many samples when set to non-zero value. @end table @subsection Commands @@ -5183,7 +5402,7 @@ Range is -70.0 - -5.0. Default value is -24.0. @item LRA, lra Set loudness range target. -Range is 1.0 - 20.0. Default value is 7.0. +Range is 1.0 - 50.0. Default value is 7.0. @item TP, tp Set maximum true peak. @@ -5281,9 +5500,11 @@ Set transform type of IIR filter. @table @option @item di @item dii +@item tdi @item tdii @item latt @item svf +@item zdf @end table @item precision, r @@ -5300,6 +5521,13 @@ Always use float 32-bit. @item f64 Always use float 64-bit. @end table + +@item block_size, b +Set block size used for reverse IIR processing. If this value is set to high enough +value (higher than impulse response length truncated when reaches near zero values) filtering +will become linear phase otherwise if not big enough it will just produce nasty artifacts. + +Note that filter delay will be exactly this many samples when set to non-zero value. @end table @subsection Examples @@ -5391,6 +5619,10 @@ lv2=p=http\\\\://www.openavproductions.com/artyfx#bitta:c=crush=0.3 @end example @end itemize +@subsection Commands + +This filter supports all options that are exported by plugin as commands. + @section mcompand Multiband Compress or expand the audio's dynamic range. @@ -6404,15 +6636,23 @@ Set LFE output volume. By default, this is @var{1}. @item allx Set spread usage of stereo image across X axis for all channels. +Allowed range is from @var{-1} to @var{15}. +By default this value is negative @var{-1}, and thus unused. @item ally Set spread usage of stereo image across Y axis for all channels. +Allowed range is from @var{-1} to @var{15}. +By default this value is negative @var{-1}, and thus unused. @item fcx, flx, frx, blx, brx, slx, srx, bcx Set spread usage of stereo image across X axis for each channel. +Allowed range is from @var{0.06} to @var{15}. +By default this value is @var{0.5}. @item fcy, fly, fry, bly, bry, sly, sry, bcy Set spread usage of stereo image across Y axis for each channel. +Allowed range is from @var{0.06} to @var{15}. +By default this value is @var{0.5}. @item win_size Set window size. Allowed range is from @var{1024} to @var{65536}. Default size is @var{4096}. @@ -6450,6 +6690,97 @@ Set window overlap. If set to 1, the recommended overlap for selected window function will be picked. Default is @code{0.5}. @end table +@section tiltshelf + +Boost or cut the lower frequencies and cut or boost higher frequencies +of the audio using a two-pole shelving filter with a response similar to +that of a standard hi-fi's tone-controls. +This is also known as shelving equalisation (EQ). + +The filter accepts the following options: + +@table @option +@item gain, g +Give the gain at 0 Hz. Its useful range is about -20 +(for a large cut) to +20 (for a large boost). +Beware of clipping when using a positive gain. + +@item frequency, f +Set the filter's central frequency and so can be used +to extend or reduce the frequency range to be boosted or cut. +The default value is @code{3000} Hz. + +@item width_type, t +Set method to specify band-width of filter. +@table @option +@item h +Hz +@item q +Q-Factor +@item o +octave +@item s +slope +@item k +kHz +@end table + +@item width, w +Determine how steep is the filter's shelf transition. + +@item poles, p +Set number of poles. Default is 2. + +@item mix, m +How much to use filtered signal in output. Default is 1. +Range is between 0 and 1. + +@item channels, c +Specify which channels to filter, by default all available are filtered. + +@item normalize, n +Normalize biquad coefficients, by default is disabled. +Enabling it will normalize magnitude response at DC to 0dB. + +@item transform, a +Set transform type of IIR filter. +@table @option +@item di +@item dii +@item tdi +@item tdii +@item latt +@item svf +@item zdf +@end table + +@item precision, r +Set precison of filtering. +@table @option +@item auto +Pick automatic sample format depending on surround filters. +@item s16 +Always use signed 16-bit. +@item s32 +Always use signed 32-bit. +@item f32 +Always use float 32-bit. +@item f64 +Always use float 64-bit. +@end table + +@item block_size, b +Set block size used for reverse IIR processing. If this value is set to high enough +value (higher than impulse response length truncated when reaches near zero values) filtering +will become linear phase otherwise if not big enough it will just produce nasty artifacts. + +Note that filter delay will be exactly this many samples when set to non-zero value. +@end table + +@subsection Commands + +This filter supports some options as @ref{commands}. + @section treble, highshelf Boost or cut treble (upper) frequencies of the audio using a two-pole @@ -6506,9 +6837,11 @@ Set transform type of IIR filter. @table @option @item di @item dii +@item tdi @item tdii @item latt @item svf +@item zdf @end table @item precision, r @@ -6525,6 +6858,13 @@ Always use float 32-bit. @item f64 Always use float 64-bit. @end table + +@item block_size, b +Set block size used for reverse IIR processing. If this value is set to high enough +value (higher than impulse response length truncated when reaches near zero values) filtering +will become linear phase otherwise if not big enough it will just produce nasty artifacts. + +Note that filter delay will be exactly this many samples when set to non-zero value. @end table @subsection Commands @@ -6587,6 +6927,26 @@ Depth of modulation as a percentage. Range is 0.0 - 1.0. Default value is 0.5. @end table +@section virtualbass + +Apply audio Virtual Bass filter. + +This filter accepts stereo input and produce stereo with LFE (2.1) channels output. +The newly produced LFE channel have enhanced virtual bass originally obtained from both stereo channels. +This filter outputs front left and front right channels unchanged as available in stereo input. + +The filter accepts the following options: + +@table @option +@item cutoff +Set the virtual bass cutoff frequency. Default value is 250 Hz. +Allowed range is from 100 to 500 Hz. + +@item strength +Set the virtual bass strength. Allowed range is from 0.5 to 3. +Default value is 3. +@end table + @section volume Adjust the input audio volume. @@ -6743,8 +7103,9 @@ volume='if(lt(t,10),1,max(1-(t-10)/5,0))':eval=frame Detect the volume of the input video. -The filter has no parameters. The input is not modified. Statistics about -the volume will be printed in the log when the input stream end is reached. +The filter has no parameters. It supports only 16-bit signed integer samples, +so the input will be converted when needed. Statistics about the volume will +be printed in the log when the input stream end is reached. In particular it will show the mean volume (root mean square), maximum volume (on a per-sample basis), and the beginning of a histogram of the @@ -7881,6 +8242,87 @@ tblend=all_mode=grainextract @subsection Commands This filter supports same @ref{commands} as options. +@anchor{blockdetect} +@section blockdetect + +Determines blockiness of frames without altering the input frames. + +Based on Remco Muijs and Ihor Kirenko: "A no-reference blocking artifact measure for adaptive video processing." 2005 13th European signal processing conference. + +The filter accepts the following options: + +@table @option +@item period_min +@item period_max +Set minimum and maximum values for determining pixel grids (periods). +Default values are [3,24]. + +@item planes +Set planes to filter. Default is first only. +@end table + +@subsection Examples + +@itemize +@item +Determine blockiness for the first plane and search for periods within [8,32]: +@example +blockdetect=period_min=8:period_max=32:planes=1 +@end example +@end itemize + +@anchor{blurdetect} +@section blurdetect + +Determines blurriness of frames without altering the input frames. + +Based on Marziliano, Pina, et al. "A no-reference perceptual blur metric." +Allows for a block-based abbreviation. + +The filter accepts the following options: + +@table @option +@item low +@item high +Set low and high threshold values used by the Canny thresholding +algorithm. + +The high threshold selects the "strong" edge pixels, which are then +connected through 8-connectivity with the "weak" edge pixels selected +by the low threshold. + +@var{low} and @var{high} threshold values must be chosen in the range +[0,1], and @var{low} should be lesser or equal to @var{high}. + +Default value for @var{low} is @code{20/255}, and default value for @var{high} +is @code{50/255}. + +@item radius +Define the radius to search around an edge pixel for local maxima. + +@item block_pct +Determine blurriness only for the most significant blocks, given in percentage. + +@item block_width +Determine blurriness for blocks of width @var{block_width}. If set to any value smaller 1, no blocks are used and the whole image is processed as one no matter of @var{block_height}. + +@item block_height +Determine blurriness for blocks of height @var{block_height}. If set to any value smaller 1, no blocks are used and the whole image is processed as one no matter of @var{block_width}. + +@item planes +Set planes to filter. Default is first only. +@end table + +@subsection Examples + +@itemize +@item +Determine blur for 80% of most significant 32x32 blocks: +@example +blurdetect=block_width=32:block_height=32:block_pct=80 +@end example +@end itemize + @section bm3d Denoise frames using Block-Matching 3D algorithm. @@ -8157,6 +8599,7 @@ The command accepts the same syntax of the corresponding option. If the specified expression is not valid, it is kept at its current value. +@anchor{chromakey} @section chromakey YUV colorspace color/chroma keying. @@ -8209,6 +8652,48 @@ ffmpeg -f lavfi -i color=c=black:s=1280x720 -i video.mp4 -shortest -filter_compl @end example @end itemize +@section chromakey_cuda +CUDA accelerated YUV colorspace color/chroma keying. + +This filter works like normal chromakey filter but operates on CUDA frames. +for more details and parameters see @ref{chromakey}. + +@subsection Examples + +@itemize +@item +Make all the green pixels in the input video transparent and use it as an overlay for another video: + +@example +./ffmpeg \ + -hwaccel cuda -hwaccel_output_format cuda -i input_green.mp4 \ + -hwaccel cuda -hwaccel_output_format cuda -i base_video.mp4 \ + -init_hw_device cuda \ + -filter_complex \ + " \ + [0:v]chromakey_cuda=0x25302D:0.1:0.12:1[overlay_video]; \ + [1:v]scale_cuda=format=yuv420p[base]; \ + [base][overlay_video]overlay_cuda" \ + -an -sn -c:v h264_nvenc -cq 20 output.mp4 +@end example + +@item +Process two software sources, explicitly uploading the frames: + +@example +./ffmpeg -init_hw_device cuda=cuda -filter_hw_device cuda \ + -f lavfi -i color=size=800x600:color=white,format=yuv420p \ + -f lavfi -i yuvtestsrc=size=200x200,format=yuv420p \ + -filter_complex \ + " \ + [0]hwupload[under]; \ + [1]hwupload,chromakey_cuda=green:0.1:0.12[over]; \ + [under][over]overlay_cuda" \ + -c:v hevc_nvenc -cq 18 -preset slow output.mp4 +@end example + +@end itemize + @section chromanr Reduce chrominance noise. @@ -8350,6 +8835,9 @@ Show white point on CIE diagram, by default disabled. @item gamma Set input gamma. Used only with XYZ input color space. + +@item fill +Fill with CIE colors. By default is enabled. @end table @section codecview @@ -8832,6 +9320,41 @@ colorlevels=romin=0.5:gomin=0.5:bomin=0.5 This filter supports the all above options as @ref{commands}. +@section colormap +Apply custom color maps to video stream. + +This filter needs three input video streams. +First stream is video stream that is going to be filtered out. +Second and third video stream specify color patches for source +color to target color mapping. + +The filter accepts the following options: + +@table @option +@item patch_size +Set the source and target video stream patch size in pixels. + +@item nb_patches +Set the max number of used patches from source and target video stream. +Default value is number of patches available in additional video streams. +Max allowed number of patches is @code{64}. + +@item type +Set the adjustments used for target colors. Can be @code{relative} or @code{absolute}. +Defaults is @code{absolute}. + +@item kernel +Set the kernel used to measure color differences between mapped colors. + +The accepted values are: +@table @samp +@item euclidean +@item weuclidean +@end table + +Default is @code{euclidean}. +@end table + @section colormatrix Convert color matrix. @@ -11227,8 +11750,10 @@ text data in detection bboxes of side data. So please do not use this parameter if you are not sure about the text source. @item reload -If set to 1, the @var{textfile} will be reloaded before each frame. -Be sure to update it atomically, or it may be read partially, or even fail. +The @var{textfile} will be reloaded at specified frame interval. +Be sure to update @var{textfile} atomically, or it may be read partially, +or even fail. +Range is 0 to INT_MAX. Default is 0. @item x @item y @@ -11378,10 +11903,14 @@ It can be used to add padding with zeros from the left. @item gmtime The time at which the filter is running, expressed in UTC. It can accept an argument: a strftime() format string. +The format string is extended to support the variable @var{%[1-6]N} +which prints fractions of the second with optionally specified number of digits. @item localtime The time at which the filter is running, expressed in the local time zone. It can accept an argument: a strftime() format string. +The format string is extended to support the variable @var{%[1-6]N} +which prints fractions of the second with optionally specified number of digits. @item metadata Frame metadata. Takes one or two arguments. @@ -11890,8 +12419,8 @@ Specify the search radius for best edge matching. Default value is 2. Allowed range is from 0 to 15. @item ecost -Specify the edge cost for edge matching. Default value is 0.03125. -Allowed range is from 0 to 1. +Specify the edge cost for edge matching. Default value is 1.0. +Allowed range is from 0 to 9. @item mcost Specify the middle cost for edge matching. Default value is 0.5. @@ -12066,6 +12595,44 @@ fade=t=in:st=5.5:d=0.5 @end itemize +@section feedback +Apply feedback video filter. + +This filter pass cropped input frames to 2nd output. +From there it can be filtered with other video filters. +After filter receives frame from 2nd input, that frame +is combined on top of original frame from 1st input and passed +to 1st output. + +The typical usage is filter only part of frame. + +The filter accepts the following options: +@table @option +@item x +@item y +Set the top left crop position. + +@item w +@item h +Set the crop size. +@end table + +@subsection Examples + +@itemize +@item +Blur only top left rectangular part of video frame size 100x100 with gblur filter. +@example +[in][blurin]feedback=x=0:y=0:w=100:h=100[out][blurout];[blurout]gblur=8[blurin] +@end example + +@item +Draw black box on top left part of video frame of size 100x100 with drawbox filter. +@example +[in][blurin]feedback=x=0:y=0:w=100:h=100[out][blurout];[blurout]drawbox=x=0:y=0:w=100:h=100:t=100[blurin] +@end example +@end itemize + @section fftdnoiz Denoise frames using 3D FFT (frequency domain filtering). @@ -12082,13 +12649,14 @@ Set amount of denoising. By default all detected noise is reduced. Default value is 1. Allowed range is from 0 to 1. @item block -Set size of block, Default is 4, can be 3, 4, 5 or 6. -Actual size of block in pixels is 2 to power of @var{block}, so by default -block size in pixels is 2^4 which is 16. +Set size of block in pixels, Default is 32, can be 8 to 256. @item overlap Set block overlap. Default is 0.5. Allowed range is from 0.2 to 0.8. +@item method +Set denoising method. Default is @code{wiener}, can also be @code{hard}. + @item prev Set number of previous frames to use for denoising. By default is set to 0. @@ -12227,7 +12795,9 @@ case of @code{b} it will use only bottom field. If line starts with @code{#} or @code{;} that line is skipped. @item mode -Can be item @code{absolute} or @code{relative}. Default is @code{absolute}. +Can be item @code{absolute} or @code{relative} or @code{pattern}. Default is @code{absolute}. +The @code{pattern} mode is same as @code{relative} mode, except at last entry of file if there +are more frames to process than @code{hint} file is seek back to start. @end table Example of first several lines of @code{hint} file for @code{relative} mode: @@ -13379,12 +13949,21 @@ Display number of frames taken from filter. @item frame_count_out Display number of frames given out from filter. +@item frame_count_delta +Display delta number of frames between above two values. + @item pts Display current filtered frame pts. +@item pts_delta +Display pts delta between current and previous frame. + @item time Display current filtered frame time. +@item time_delta +Display time delta between current and previous frame. + @item timebase Display time base for filter link. @@ -13405,6 +13984,9 @@ Display number of samples taken from filter. @item sample_count_out Display number of samples given out from filter. + +@item sample_count_delta +Display delta number of samples between above two values. @end table @item rate, r @@ -13529,6 +14111,10 @@ The Hald CLUT input can be a simple picture or a complete video stream. The filter accepts the following options: @table @option +@item clut +Set which CLUT video frames will be processed from second input stream, +can be @var{first} or @var{all}. Default is @var{all}. + @item shortest Force termination when the shortest input terminates. Default is @code{0}. @item repeatlast @@ -14175,6 +14761,41 @@ By default value is 0. The @code{hysteresis} filter also supports the @ref{framesync} options. +@section iccdetect + +Detect the colorspace from an embedded ICC profile (if present), and update +the frame's tags accordingly. + +This filter accepts the following options: + +@table @option +@item force +If true, the frame's existing colorspace tags will always be overridden by +values detected from an ICC profile. Otherwise, they will only be assigned if +they contain @code{unknown}. Enabled by default. +@end table + +@section iccgen + +Generate ICC profiles and attach them to frames. + +This filter accepts the following options: + +@table @option +@item color_primaries +@item color_trc +Configure the colorspace that the ICC profile will be generated for. The +default value of @code{auto} infers the value from the input frame's metadata, +defaulting to BT.709/sRGB as appropriate. + +See the @ref{setparams} filter for a list of possible values, but note that +@code{unknown} are not valid values for this filter. + +@item force +If true, an ICC profile will be generated even if it would overwrite an +already existing ICC profile. Disabled by default. +@end table + @section identity Obtain the identity score between two input videos. @@ -14550,6 +15171,13 @@ filter choosing the best match with the given options, and the filter will output the chosen camera and lens models (logged with level "info"). You must provide the make, camera model, and lens model as they are required. +To obtain a list of available makes and models, leave out one or both of @code{make} and +@code{model} options. The filter will send the full list to the log with level @code{INFO}. +The first column is the make and the second column is the model. +To obtain a list of available lenses, set any values for make and model and leave out the +@code{lens_model} option. The filter will send the full list of lenses in the log with level +@code{INFO}. The ffmpeg tool will exit after the list is printed. + The filter accepts the following options: @table @option @@ -14564,6 +15192,10 @@ required. The model of the lens (for example, "Canon EF-S 18-55mm f/3.5-5.6 IS STM"). This option is required. +@item db_path +The full path to the lens database folder. If not set, the filter will attempt to +load the database from the install path when the library was built. Default is unset. + @item mode The type of correction to apply. The following values are valid options: @@ -14664,70 +15296,566 @@ ffmpeg -i input.mov -vf lensfun=make=Canon:model="Canon EOS 100D":lens_model="Ca @end itemize +@section libplacebo + +Flexible GPU-accelerated processing filter based on libplacebo +(@url{https://code.videolan.org/videolan/libplacebo}). Note that this filter +currently only accepts Vulkan input frames. + +@subsection Options + +The options for this filter are divided into the following sections: + +@subsubsection Output mode +These options control the overall output mode. By default, libplacebo will try +to preserve the source colorimetry and size as best as it can, but it will +apply any embedded film grain, dolby vision metadata or anamorphic SAR present +in source frames. +@table @option +@item w +@item h +Set the output video dimension expression. Default value is the input dimension. + +Allows for the same expressions as the @ref{scale} filter. + +@item format +Set the output format override. If unset (the default), frames will be output +in the same format as the respective input frames. Otherwise, format conversion +will be performed. + +@item force_original_aspect_ratio +@item force_divisible_by +Work the same as the identical @ref{scale} filter options. + +@item normalize_sar +If enabled (the default), output frames will always have a pixel aspect ratio +of 1:1. If disabled, any aspect ratio mismatches, including those from e.g. +anamorphic video sources, are forwarded to the output pixel aspect ratio. + +@item pad_crop_ratio +Specifies a ratio (between @code{0.0} and @code{1.0}) between padding and +cropping when the input aspect ratio does not match the output aspect ratio and +@option{normalize_sar} is in effect. The default of @code{0.0} always pads the +content with black borders, while a value of @code{1.0} always crops off parts +of the content. Intermediate values are possible, leading to a mix of the two +approaches. + +@item colorspace +@item color_primaries +@item color_trc +@item range +Configure the colorspace that output frames will be delivered in. The default +value of @code{auto} outputs frames in the same format as the input frames, +leading to no change. For any other value, conversion will be performed. + +See the @ref{setparams} filter for a list of possible values. + +@item apply_filmgrain +Apply film grain (e.g. AV1 or H.274) if present in source frames, and strip +it from the output. Enabled by default. + +@item apply_dolbyvision +Apply Dolby Vision RPU metadata if present in source frames, and strip it from +the output. Enabled by default. Note that Dolby Vision will always output +BT.2020+PQ, overriding the usual input frame metadata. These will also be +picked as the values of @code{auto} for the respective frame output options. +@end table + +@subsubsection Scaling +The options in this section control how libplacebo performs upscaling and (if +necessary) downscaling. Note that libplacebo will always internally operate on +4:4:4 content, so any sub-sampled chroma formats such as @code{yuv420p} will +necessarily be upsampled and downsampled as part of the rendering process. That +means scaling might be in effect even if the source and destination resolution +are the same. +@table @option +@item upscaler +@item downscaler +Configure the filter kernel used for upscaling and downscaling. The respective +defaults are @code{spline36} and @code{mitchell}. For a full list of possible +values, pass @code{help} to these options. The most important values are: +@table @samp + +@item none +Forces the use of built-in GPU texture sampling (typically bilinear). Extremely +fast but poor quality, especially when downscaling. + +@item bilinear +Bilinear interpolation. Can generally be done for free on GPUs, except when +doing so would lead to aliasing. Fast and low quality. + +@item nearest +Nearest-neighbour interpolation. Sharp but highly aliasing. + +@item oversample +Algorithm that looks visually similar to nearest-neighbour interpolation but +tries to preserve pixel aspect ratio. Good for pixel art, since it results in +minimal distortion of the artistic appearance. + +@item lanczos +Standard sinc-sinc interpolation kernel. + +@item spline36 +Cubic spline approximation of lanczos. No difference in performance, but has +very slightly less ringing. + +@item ewa_lanczos +Elliptically weighted average version of lanczos, based on a jinc-sinc kernel. +This is also popularly referred to as just "Jinc scaling". Slow but very high +quality. + +@item gaussian +Gaussian kernel. Has certain ideal mathematical properties, but subjectively +very blurry. + +@item mitchell +Cubic BC spline with parameters recommended by Mitchell and Netravali. Very +little ringing. +@end table + +@item lut_entries +Configures the size of scaler LUTs, ranging from @code{1} to @code{256}. The +default of @code{0} will pick libplacebo's internal default, typically +@code{64}. + +@item antiringing +Enables anti-ringing (for non-EWA filters). The value (between @code{0.0} and +@code{1.0}) configures the strength of the anti-ringing algorithm. May increase +aliasing if set too high. Disabled by default. + +@item sigmoid +Enable sigmoidal compression during upscaling. Reduces ringing slightly. +Enabled by default. +@end table + +@subsubsection Debanding +Libplacebo comes with a built-in debanding filter that is good at counteracting +many common sources of banding and blocking. Turning this on is highly +recommended whenever quality is desired. +@table @option +@item deband +Enable (fast) debanding algorithm. Disabled by default. + +@item deband_iterations +Number of deband iterations of the debanding algorithm. Each iteration is +performed with progressively increased radius (and diminished threshold). +Recommended values are in the range @code{1} to @code{4}. Defaults to @code{1}. + +@item deband_threshold +Debanding filter strength. Higher numbers lead to more aggressive debanding. +Defaults to @code{4.0}. + +@item deband_radius +Debanding filter radius. A higher radius is better for slow gradients, while +a lower radius is better for steep gradients. Defaults to @code{16.0}. + +@item deband_grain +Amount of extra output grain to add. Helps hide imperfections. Defaults to +@code{6.0}. +@end table + +@subsubsection Color adjustment +A collection of subjective color controls. Not very rigorous, so the exact +effect will vary somewhat depending on the input primaries and colorspace. +@table @option +@item brightness +Brightness boost, between @code{-1.0} and @code{1.0}. Defaults to @code{0.0}. + +@item contrast +Contrast gain, between @code{0.0} and @code{16.0}. Defaults to @code{1.0}. + +@item saturation +Saturation gain, between @code{0.0} and @code{16.0}. Defaults to @code{1.0}. + +@item hue +Hue shift in radians, between @code{-3.14} and @code{3.14}. Defaults to +@code{0.0}. This will rotate the UV subvector, defaulting to BT.709 +coefficients for RGB inputs. + +@item gamma +Gamma adjustment, between @code{0.0} and @code{16.0}. Defaults to @code{1.0}. + +@item cones +Cone model to use for color blindness simulation. Accepts any combination of +@code{l}, @code{m} and @code{s}. Here are some examples: +@table @samp +@item m +Deuteranomaly / deuteranopia (affecting 3%-4% of the population) +@item l +Protanomaly / protanopia (affecting 1%-2% of the population) +@item l+m +Monochromacy (very rare) +@item l+m+s +Achromatopsy (complete loss of daytime vision, extremely rare) +@end table + +@item cone-strength +Gain factor for the cones specified by @code{cones}, between @code{0.0} and +@code{10.0}. A value of @code{1.0} results in no change to color vision. A +value of @code{0.0} (the default) simulates complete loss of those cones. Values +above @code{1.0} result in exaggerating the differences between cones, which +may help compensate for reduced color vision. +@end table + +@subsubsection Peak detection +To help deal with sources that only have static HDR10 metadata (or no tagging +whatsoever), libplacebo uses its own internal frame analysis compute shader to +analyze source frames and adapt the tone mapping function in realtime. If this +is too slow, or if exactly reproducible frame-perfect results are needed, it's +recommended to turn this feature off. +@table @option +@item peak_detect +Enable HDR peak detection. Ignores static MaxCLL/MaxFALL values in favor of +dynamic detection from the input. Note that the detected values do not get +written back to the output frames, they merely guide the internal tone mapping +process. Enabled by default. + +@item smoothing_period +Peak detection smoothing period, between @code{0.0} and @code{1000.0}. Higher +values result in peak detection becoming less responsive to changes in the +input. Defaults to @code{100.0}. + +@item minimum_peak +Lower bound on the detected peak (relative to SDR white), between @code{0.0} +and @code{100.0}. Defaults to @code{1.0}. + +@item scene_threshold_low +@item scene_threshold_high +Lower and upper thresholds for scene change detection. Expressed in a +logarithmic scale between @code{0.0} and @code{100.0}. Default to @code{5.5} +and @code{10.0}, respectively. Setting either to a negative value disables +this functionality. + +@item overshoot +Peak smoothing overshoot margin, between @code{0.0} and @code{1.0}. Provides a +safety margin to prevent clipping as a result of peak smoothing. Defaults to +@code{0.05}, corresponding to a margin of 5%. +@end table + +@subsubsection Tone mapping +The options in this section control how libplacebo performs tone-mapping and +gamut-mapping when dealing with mismatches between wide-gamut or HDR content. +In general, libplacebo relies on accurate source tagging and mastering display +gamut information to produce the best results. +@table @option +@item intent +Rendering intent to use when adapting between different primary color gamuts +(after tone-mapping). +@table @samp +@item perceptual +Perceptual gamut mapping. Currently equivalent to relative colorimetric. +@item relative +Relative colorimetric. This is the default. +@item absolute +Absolute colorimetric. +@item saturation +Saturation mapping. Forcibly stretches the source gamut to the target gamut. +@end table + +@item gamut_mode +How to handle out-of-gamut colors that can occur as a result of colorimetric +gamut mapping. +@table @samp +@item clip +Do nothing, simply clip out-of-range colors to the RGB volume. This is the +default. +@item warn +Highlight out-of-gamut pixels (by coloring them pink). +@item darken +Linearly reduces content brightness to preserves saturated details, followed by +clipping the remaining out-of-gamut colors. As the name implies, this makes +everything darker, but provides a good balance between preserving details and +colors. +@item desaturate +Hard-desaturates out-of-gamut colors towards white, while preserving the +luminance. Has a tendency to shift colors. +@end table + +@item tonemapping +Tone-mapping algorithm to use. Available values are: +@table @samp +@item auto +Automatic selection based on internal heuristics. This is the default. +@item clip +Performs no tone-mapping, just clips out-of-range colors. Retains perfect color +accuracy for in-range colors but completely destroys out-of-range information. +Does not perform any black point adaptation. Not configurable. +@item bt.2390 +EETF from the ITU-R Report BT.2390, a hermite spline roll-off with linear +segment. The knee point offset is configurable. Note that this parameter +defaults to @code{1.0}, rather than the value of @code{0.5} from the ITU-R +spec. +@item bt.2446a +EETF from ITU-R Report BT.2446, method A. Designed for well-mastered HDR +sources. Can be used for both forward and inverse tone mapping. Not +configurable. +@item spline +Simple spline consisting of two polynomials, joined by a single pivot point. +The parameter gives the pivot point (in PQ space), defaulting to @code{0.30}. +Can be used for both forward and inverse tone mapping. +@item reinhard +Simple non-linear, global tone mapping algorithm. The parameter specifies the +local contrast coefficient at the display peak. Essentially, a parameter of +@code{0.5} implies that the reference white will be about half as bright as +when clipping. Defaults to @code{0.5}, which results in the simplest +formulation of this function. +@item mobius +Generalization of the reinhard tone mapping algorithm to support an additional +linear slope near black. The tone mapping parameter indicates the trade-off +between the linear section and the non-linear section. Essentially, for a given +parameter @var{x}, every color value below @var{x} will be mapped linearly, +while higher values get non-linearly tone-mapped. Values near @code{1.0} make +this curve behave like @code{clip}, while values near @code{0.0} make this +curve behave like @code{reinhard}. The default value is @code{0.3}, which +provides a good balance between colorimetric accuracy and preserving +out-of-gamut details. +@item hable +Piece-wise, filmic tone-mapping algorithm developed by John Hable for use in +Uncharted 2, inspired by a similar tone-mapping algorithm used by Kodak. +Popularized by its use in video games with HDR rendering. Preserves both dark +and bright details very well, but comes with the drawback of changing the +average brightness quite significantly. This is sort of similar to +@code{reinhard} with parameter @code{0.24}. +@item gamma +Fits a gamma (power) function to transfer between the source and target color +spaces, effectively resulting in a perceptual hard-knee joining two roughly +linear sections. This preserves details at all scales fairly accurately, but +can result in an image with a muted or dull appearance. The parameter is used +as the cutoff point, defaulting to @code{0.5}. +@item linear +Linearly stretches the input range to the output range, in PQ space. This will +preserve all details accurately, but results in a significantly different +average brightness. Can be used for inverse tone-mapping in addition to regular +tone-mapping. The parameter can be used as an additional linear gain +coefficient (defaulting to @code{1.0}). +@end table + +@item tonemapping_param +For tunable tone mapping functions, this parameter can be used to fine-tune the +curve behavior. Refer to the documentation of @code{tonemapping}. The default +value of @code{0.0} is replaced by the curve's preferred default setting. + +@item tonemapping_mode +This option determines how the tone mapping function specified by +@code{tonemapping} is applied to the colors in a scene. Possible values are: +@table @samp +@item auto +Automatic selection based on internal heuristics. This is the default. +@item rgb +Apply the function per-channel in the RGB colorspace. +Per-channel tone-mapping in RGB. Guarantees no clipping and heavily desaturates +the output, but distorts the colors quite significantly. Very similar to the +"Hollywood" look and feel. +@item max +Tone-mapping is performed on the brightest component found in the signal. Good +at preserving details in highlights, but has a tendency to crush blacks. +@item hybrid +Tone-map per-channel for highlights and linearly (luma-based) for +midtones/shadows, based on a fixed gamma @code{2.4} coefficient curve. +@item luma +Tone-map linearly on the luma component (CIE Y), and adjust (desaturate) the +chromaticities to compensate using a simple constant factor. This is +essentially the mode used in ITU-R BT.2446 method A. +@end table + +@item inverse_tonemapping +If enabled, this filter will also attempt stretching SDR signals to fill HDR +output color volumes. Disabled by default. + +@item tonemapping_crosstalk +Extra tone-mapping crosstalk factor, between @code{0.0} and @code{0.3}. This +can help reduce issues tone-mapping certain bright spectral colors. Defaults to +@code{0.04}. + +@item tonemapping_lut_size +Size of the tone-mapping LUT, between @code{2} and @code{1024}. Defaults to +@code{256}. Note that this figure is squared when combined with +@code{peak_detect}. +@end table + +@subsubsection Dithering +By default, libplacebo will dither whenever necessary, which includes rendering +to any integer format below 16-bit precision. It's recommended to always leave +this on, since not doing so may result in visible banding in the output, even +if the @code{debanding} filter is enabled. If maximum performance is needed, +use @code{ordered_fixed} instead of disabling dithering. +@table @option +@item dithering +Dithering method to use. Accepts the following values: +@table @samp +@item none +Disables dithering completely. May result in visible banding. +@item blue +Dither with pseudo-blue noise. This is the default. +@item ordered +Tunable ordered dither pattern. +@item ordered_fixed +Faster ordered dither with a fixed size of @code{6}. Texture-less. +@item white +Dither with white noise. Texture-less. +@end table + +@item dither_lut_size +Dither LUT size, as log base2 between @code{1} and @code{8}. Defaults to +@code{6}, corresponding to a LUT size of @code{64x64}. + +@item dither_temporal +Enables temporal dithering. Disabled by default. +@end table + +@subsubsection Custom shaders +libplacebo supports a number of custom shaders based on the mpv .hook GLSL +syntax. A collection of such shaders can be found here: +@url{https://github.com/mpv-player/mpv/wiki/User-Scripts#user-shaders} + +A full description of the mpv shader format is beyond the scope of this +section, but a summary can be found here: +@url{https://mpv.io/manual/master/#options-glsl-shader} +@table @option +@item custom_shader_path +Specifies a path to a custom shader file to load at runtime. + +@item custom_shader_bin +Specifies a complete custom shader as a raw string. +@end table + +@subsubsection Debugging / performance +All of the options in this section default off. They may be of assistance when +attempting to squeeze the maximum performance at the cost of quality. +@table @option +@item skip_aa +Disable anti-aliasing when downscaling. + +@item polar_cutoff +Truncate polar (EWA) scaler kernels below this absolute magnitude, between +@code{0.0} and @code{1.0}. + +@item disable_linear +Disable linear light scaling. + +@item disable_builtin +Disable built-in GPU sampling (forces LUT). + +@item force_icc_lut +Force the use of a full ICC 3DLUT for gamut mapping. + +@item disable_fbos +Forcibly disable FBOs, resulting in loss of almost all functionality, but +offering the maximum possible speed. +@end table + +@subsection Commands +This filter supports almost all of the above options as @ref{commands}. + +@subsection Examples +@itemize +@item +Complete example for how to initialize the Vulkan device, upload frames to the +GPU, perform filter conversion to yuv420p, and download frames back to the CPU +for output. Note that in specific cases you can get around the need to perform +format conversion by specifying the correct @code{format} filter option +corresponding to the input frames. +@example +ffmpeg -i $INPUT -init_hw_device vulkan -vf hwupload,libplacebo=format=yuv420p,hwdownload,format=yuv420p $OUTPUT +@end example + +@item +Tone-map input to standard gamut BT.709 output: +@example +libplacebo=colorspace=bt709:color_primaries=bt709:color_trc=bt709:range=tv +@end example + +@item +Rescale input to fit into standard 1080p, with high quality scaling: +@example +libplacebo=w=1920:h=1080:force_original_aspect_ratio=decrease:normalize_sar=true:upscaler=ewa_lanczos:downscaler=ewa_lanczos +@end example + +@item +Convert input to standard sRGB JPEG: +@example +libplacebo=format=yuv420p:colorspace=bt470bg:color_primaries=bt709:color_trc=iec61966-2-1:range=pc +@end example + +@item +Use higher quality debanding settings: +@example +libplacebo=deband=true:deband_iterations=3:deband_radius=8:deband_threshold=6 +@end example + +@item +Run this filter on the CPU, on systems with Mesa installed (and with the most +expensive options disabled): +@example +ffmpeg ... -init_hw_device vulkan:llvmpipe ... -vf libplacebo=upscaler=none:downscaler=none:peak_detect=false +@end example + +@item +Suppress CPU-based AV1/H.274 film grain application in the decoder, in favor of +doing it with this filter. Note that this is only a gain if the frames are +either already on the GPU, or if you're using libplacebo for other purposes, +since otherwise the VRAM roundtrip will more than offset any expected speedup. +@example +ffmpeg -export_side_data +film_grain ... -vf libplacebo=apply_filmgrain=true +@end example +@end itemize + @section libvmaf -Obtain the VMAF (Video Multi-Method Assessment Fusion) -score between two input videos. +Calulate the VMAF (Video Multi-Method Assessment Fusion) score for a +reference/distorted pair of input videos. -The first input is the encoded video, and the second input is the reference video. +The first input is the distorted video, and the second input is the reference video. 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}. The filter has following options: @table @option +@item model +A `|` delimited list of vmaf models. Each model can be configured with a number of parameters. +Default value: @code{"version=vmaf_v0.6.1"} + @item model_path -Set the model path which is to be used for SVM. -Default value: @code{"/usr/local/share/model/vmaf_v0.6.1.pkl"} - -@item log_path -Set the file path to be used to store logs. - -@item log_fmt -Set the format of the log file (csv, json or xml). +Deprecated, use model='path=...'. @item enable_transform -This option can enable/disable the @code{score_transform} applied to the final predicted VMAF score, -if you have specified score_transform option in the input parameter file passed to @code{run_vmaf_training.py} -Default value: @code{false} +Deprecated, use model='enable_transform=true'. @item phone_model -Invokes the phone model which will generate VMAF scores higher than in the -regular model, which is more suitable for laptop, TV, etc. viewing conditions. -Default value: @code{false} - -@item psnr -Enables computing psnr along with vmaf. -Default value: @code{false} - -@item ssim -Enables computing ssim along with vmaf. -Default value: @code{false} - -@item ms_ssim -Enables computing ms_ssim along with vmaf. -Default value: @code{false} - -@item pool -Set the pool method to be used for computing vmaf. -Options are @code{min}, @code{harmonic_mean} or @code{mean} (default). - -@item n_threads -Set number of threads to be used when computing vmaf. -Default value: @code{0}, which makes use of all available logical processors. - -@item n_subsample -Set interval for frame subsampling used when computing vmaf. -Default value: @code{1} +Deprecated, use model='enable_transform=true'. @item enable_conf_interval -Enables confidence interval. -Default value: @code{false} +Deprecated, use model='enable_conf_interval=true'. + +@item feature +A `|` delimited list of features. Each feature can be configured with a number of parameters. + +@item psnr +Deprecated, use feature='name=psnr'. + +@item ssim +Deprecated, use feature='name=ssim'. + +@item ms_ssim +Deprecated, use feature='name=ms_ssim'. + +@item log_path +Set the file path to be used to store log files. + +@item log_fmt +Set the format of the log file (xml, json, csv, or sub). + +@item n_threads +Set number of threads to be used when initializing libvmaf. +Default value: @code{0}, no threads. + +@item n_subsample +Set frame subsampling interval to be used. @end table This filter also supports the @ref{framesync} options. @@ -14735,23 +15863,31 @@ This filter also supports the @ref{framesync} options. @subsection Examples @itemize @item -On the below examples the input file @file{main.mpg} being processed is -compared with the reference file @file{ref.mpg}. +In the examples below, a distorted video @file{distorted.mpg} is +compared with a reference file @file{reference.mpg}. +@item +Basic usage: @example -ffmpeg -i main.mpg -i ref.mpg -lavfi libvmaf -f null - +ffmpeg -i distorted.mpg -i reference.mpg -lavfi libvmaf=log_path=output.xml -f null - @end example @item -Example with options: +Example with multiple models: @example -ffmpeg -i main.mpg -i ref.mpg -lavfi libvmaf="psnr=1:log_fmt=json" -f null - +ffmpeg -i distorted.mpg -i reference.mpg -lavfi libvmaf='model=version=vmaf_v0.6.1\\:name=vmaf|version=vmaf_v0.6.1neg\\:name=vmaf_neg' -f null - +@end example + +@item +Example with multiple addtional features: +@example +ffmpeg -i distorted.mpg -i reference.mpg -lavfi libvmaf='feature=name=psnr|name=ciede' -f null - @end example @item Example with options and different containers: @example -ffmpeg -i main.mpg -i ref.mkv -lavfi "[0:v]settb=AVTB,setpts=PTS-STARTPTS[main];[1:v]settb=AVTB,setpts=PTS-STARTPTS[ref];[main][ref]libvmaf=psnr=1:log_fmt=json" -f null - +ffmpeg -i distorted.mpg -i reference.mkv -lavfi "[0:v]settb=AVTB,setpts=PTS-STARTPTS[main];[1:v]settb=AVTB,setpts=PTS-STARTPTS[ref];[main][ref]libvmaf=log_fmt=json:log_path=output.json" -f null - @end example @end itemize @@ -15043,7 +16179,7 @@ expression @end table -All expressions default to "val". +All expressions default to "clipval". @subsection Commands @@ -15439,6 +16575,18 @@ plane, 'Cc' describes the mapping for the output stream third plane and @item format Set output pixel format. Default is @code{yuva444p}. + +@item map0s +@item map1s +@item map2s +@item map3s +Set input to output stream mapping for output Nth plane. Default is @code{0}. + +@item map0p +@item map1p +@item map2p +@item map3p +Set input to output plane mapping for output Nth plane. Default is @code{0}. @end table @subsection Examples @@ -15643,6 +16791,9 @@ Specify scale, if it is set it will be multiplied with sum of each weight multiplied with pixel values to give final destination pixel value. By default @var{scale} is auto scaled to sum of weights. +@item planes +Set which planes to filter. Default is all. Allowed range is from 0 to 15. + @item duration Specify how end of stream is determined. @table @samp @@ -15663,6 +16814,7 @@ This filter supports the following commands: @table @option @item weights @item scale +@item planes Syntax is same as option with same name. @end table @@ -15793,6 +16945,29 @@ with the reference file @file{ref.mpg}. ffmpeg -i main.mpg -i ref.mpg -lavfi msad -f null - @end example +@section multiply +Multiply first video stream pixels values with second video stream pixels values. + +The filter accepts the following options: + +@table @option +@item scale +Set the scale applied to second video stream. By default is @code{1}. +Allowed range is from @code{0} to @code{9}. + +@item offset +Set the offset applied to second video stream. By default is @code{0.5}. +Allowed range is from @code{-1} to @code{1}. + +@item planes +Specify planes from input video stream that will be processed. +By default all planes are processed. +@end table + +@subsection Commands + +This filter supports same @ref{commands} as options. + @section negate Negate (invert) the input video. @@ -17165,6 +18340,35 @@ format=monow, pixdesctest can be used to test the monowhite pixel format descriptor definition. +@section pixelize +Apply pixelization to video stream. + +The filter accepts the following options: +@table @option +@item width, w +@item height, h +Set block dimensions that will be used for pixelization. +Default value is @code{16}. + +@item mode, m +Set the mode of pixelization used. + +Possible values are: +@table @samp +@item avg +@item min +@item max +@end table +Default value is @code{avg}. + +@item planes, p +Set what planes to filter. Default is to filter all planes. +@end table + +@subsection Commands + +This filter supports all options as @ref{commands}. + @section pixscope Display sample values of color channels. Mainly useful for checking color @@ -19875,6 +21079,29 @@ ffmpeg -i input1.mkv -i input2.mkv -filter_complex "[0:v][1:v] signature=nb_inpu @end itemize +@anchor{siti} +@section siti + +Calculate Spatial Info (SI) and Temporal Info (TI) scores for a video, as defined +in ITU-T P.910: Subjective video quality assessment methods for multimedia +applications. Available PDF at @url{https://www.itu.int/rec/T-REC-P.910-199909-S/en }. + +It accepts the following option: + +@table @option +@item print_summary +If set to 1, Summary statistics will be printed to the console. Default 0. +@end table + +@subsection Examples +@itemize +@item +To calculate SI/TI metrics and print summary: +@example +ffmpeg -i input.mp4 -vf siti=print_summary=1 -f null - +@end example +@end itemize + @anchor{smartblur} @section smartblur @@ -20734,9 +21961,8 @@ The filter accepts the following options: @table @option @item layout -Set the grid size (i.e. the number of lines and columns). For the syntax of -this option, check the -@ref{video size syntax,,"Video size" section in the ffmpeg-utils manual,ffmpeg-utils}. +Set the grid size in the form @code{COLUMNSxROWS}. Range is upto UINT_MAX cells. +Default is @code{6x5}. @item nb_frames Set the maximum number of frames to render in the given area. It must be less @@ -20744,12 +21970,12 @@ than or equal to @var{w}x@var{h}. The default value is @code{0}, meaning all the area will be used. @item margin -Set the outer border margin in pixels. +Set the outer border margin in pixels. Range is 0 to 1024. Default is @code{0}. @item padding Set the inner border thickness (i.e. the number of pixels between frames). For more advanced padding options (such as having different values for the edges), -refer to the pad video filter. +refer to the pad video filter. Range is 0 to 1024. Default is @code{0}. @item color Specify the color of the unused area. For the syntax of this option, check the @@ -20758,12 +21984,12 @@ 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}. +The value must be between @code{0} and @var{nb_frames - 1}. Default is @code{0}. @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}. +The value must be between @code{0} and @var{nb_frames - 1}. Default is @code{0}. @end table @subsection Examples @@ -21090,6 +22316,9 @@ unset weights. Specify scale, if it is set it will be multiplied with sum of each weight multiplied with pixel values to give final destination pixel value. By default @var{scale} is auto scaled to sum of weights. + +@item planes +Set which planes to filter. Default is all. Allowed range is from 0 to 15. @end table @subsection Examples @@ -21120,6 +22349,7 @@ This filter supports the following commands: @table @option @item weights @item scale +@item planes Syntax is same as option with same name. @end table @@ -21526,6 +22756,23 @@ sharpen it, a value of zero will disable the effect. Default value is 0.0. +@item alpha_msize_x, ax +Set the alpha matrix horizontal size. It must be an odd integer +between 3 and 23. The default value is 5. + +@item alpha_msize_y, ay +Set the alpha matrix vertical size. It must be an odd integer +between 3 and 23. The default value is 5. + +@item alpha_amount, aa +Set the alpha effect strength. It must be a floating point number, reasonable +values lay between -1.5 and 1.5. + +Negative values will blur the input video, while positive values will +sharpen it, a value of zero will disable the effect. + +Default value is 0.0. + @end table All parameters are optional and default to the equivalent of the @@ -23061,6 +24308,8 @@ Set one of available transition effects: @item squeezeh @item squeezev @item zoomin +@item fadefast +@item fadeslow @end table Default transition effect is fade. @@ -23177,8 +24426,26 @@ the output video frame will be filled. Similarly, videos can overlap each other if their position doesn't leave enough space for the full frame of adjoining videos. -For 2 inputs, a default layout of @code{0_0|w0_0} is set. In all other cases, -a layout must be set by the user. +For 2 inputs, a default layout of @code{0_0|w0_0} (equivalent to +@code{grid=2x1}) is set. In all other cases, a layout or a grid must be set by +the user. Either @code{grid} or @code{layout} can be specified at a time. +Specifying both will result in an error. + +@item grid +Specify a fixed size grid of inputs. +This option is used to create a fixed size grid of the input streams. Set the +grid size in the form @code{COLUMNSxROWS}. There must be @code{ROWS * COLUMNS} +input streams and they will be arranged as a grid with @code{ROWS} rows and +@code{COLUMNS} columns. When using this option, each input stream within a row +must have the same height and all the rows must have the same width. + +If @code{grid} is set, then @code{inputs} option is ignored and is implicitly +set to @code{ROWS * COLUMNS}. + +For 2 inputs, a default grid of @code{2x1} (equivalent to +@code{layout=0_0|w0_0}) is set. In all other cases, a layout or a grid must be +set by the user. Either @code{grid} or @code{layout} can be specified at a time. +Specifying both will result in an error. @item shortest If set to 1, force the output to terminate when the shortest input @@ -24479,6 +25746,30 @@ __kernel void blend_images(__write_only image2d_t dst, @end itemize +@section remap_opencl + +Remap pixels using 2nd: Xmap and 3rd: Ymap input video stream. + +Destination pixel at position (X, Y) will be picked from source (x, y) position +where x = Xmap(X, Y) and y = Ymap(X, Y). If mapping values are out of range, zero +value for pixel will be used for destination pixel. + +Xmap and Ymap input video streams must be of same dimensions. Output video stream +will have Xmap/Ymap video stream dimensions. +Xmap and Ymap input video streams are 32bit float pixel format, single channel. + +@table @option +@item interp +Specify interpolation used for remapping of pixels. +Allowed values are @code{near} and @code{linear}. +Default value is @code{linear}. + +@item fill +Specify the color of the unmapped pixels. For the syntax of this option, +check the @ref{color syntax,,"Color" section in the ffmpeg-utils +manual,ffmpeg-utils}. Default color is @code{black}. +@end table + @section roberts_opencl Apply the Roberts cross operator (@url{https://en.wikipedia.org/wiki/Roberts_cross}) to input video stream. @@ -24798,6 +26089,57 @@ To enable compilation of these filters you need to configure FFmpeg with To use vaapi filters, you need to setup the vaapi device correctly. For more information, please read @url{https://trac.ffmpeg.org/wiki/Hardware/VAAPI} +@section overlay_vaapi + +Overlay one video on the top of another. + +It takes two inputs and has one output. The first input is the "main" video on which the second input is overlaid. +This filter requires same memory layout for all the inputs. So, format conversion may be needed. + +The filter accepts the following options: + +@table @option + +@item x +Set the x coordinate of the overlaid video on the main video. +Default value is @code{0}. + +@item y +Set the y coordinate of the overlaid video on the main video. +Default value is @code{0}. + +@item w +Set the width of the overlaid video on the main video. +Default value is the width of input overlay video. + +@item h +Set the height of the overlaid video on the main video. +Default value is the height of input overlay video. + +@item alpha +Set blocking detection thresholds. Allowed range is 0.0 to 1.0, it +requires an input video with alpha channel. +Default value is @code{0.0}. + +@end table + +@subsection Examples + +@itemize +@item +Overlay an image LOGO at the top-left corner of the INPUT video. Both inputs for this filter are yuv420p format. +@example +-i INPUT -i LOGO -filter_complex "[0:v]hwupload[a], [1:v]format=yuv420p, hwupload[b], [a][b]overlay_vaapi" OUTPUT +@end example +@item +Overlay an image LOGO at the offset (200, 100) from the top-left corner of the INPUT video. +The inputs have same memory layout for color channels, the overlay has additional alpha plane, like INPUT is yuv420p, and the LOGO is yuva420p. +@example +-i INPUT -i LOGO -filter_complex "[0:v]hwupload[a], [1:v]format=yuva420p, hwupload[b], [a][b]overlay_vaapi=x=200:y=100:w=400:h=300:alpha=1.0, hwdownload, format=nv12" OUTPUT +@end example + +@end itemize + @section tonemap_vaapi Perform HDR(High Dynamic Range) to SDR(Standard Dynamic Range) conversion with tone-mapping. @@ -25128,6 +26470,9 @@ supposed to be generated forever. @item speed Set speed of gradients rotation. + +@item type, t +Set type of gradients, can be @code{linear} or @code{radial} or @code{circular} or @code{spiral}. @end table @@ -25427,6 +26772,7 @@ ffplay -f lavfi life=s=300x200:mold=10:r=60:ratio=0.1:death_color=#C83232:life_c @anchor{allrgb} @anchor{allyuv} @anchor{color} +@anchor{colorchart} @anchor{colorspectrum} @anchor{haldclutsrc} @anchor{nullsrc} @@ -25438,7 +26784,7 @@ ffplay -f lavfi life=s=300x200:mold=10:r=60:ratio=0.1:death_color=#C83232:life_c @anchor{testsrc} @anchor{testsrc2} @anchor{yuvtestsrc} -@section allrgb, allyuv, color, colorspectrum, haldclutsrc, nullsrc, pal75bars, pal100bars, rgbtestsrc, smptebars, smptehdbars, testsrc, testsrc2, yuvtestsrc +@section allrgb, allyuv, color, colorchart, colorspectrum, haldclutsrc, nullsrc, pal75bars, pal100bars, rgbtestsrc, smptebars, smptehdbars, testsrc, testsrc2, yuvtestsrc The @code{allrgb} source returns frames of size 4096x4096 of all rgb colors. @@ -25446,6 +26792,8 @@ The @code{allyuv} source returns frames of size 4096x4096 of all yuv colors. The @code{color} source provides an uniformly colored input. +The @code{colorchart} source provides a colors checker chart. + The @code{colorspectrum} source provides a color spectrum input. The @code{haldclutsrc} source provides an identity Hald CLUT. See also @@ -25549,6 +26897,22 @@ Set the type of the color spectrum, only available in the @item white @item all @end table + +@item patch_size +Set patch size of single color patch, only available in the +@code{colorchart} source. Default is @code{64x64}. + +@item preset +Set colorchecker colors preset, only available in the +@code{colorchart} source. + +Available values are: +@table @samp +@item reference +@item skintones +@end table + +Default value is @code{reference}. @end table @subsection Examples @@ -25738,6 +27102,9 @@ Default value is @code{1024x256}. Specify list of colors separated by space or by '|' which will be used to draw channels. Unrecognized or missing colors will be replaced by white color. + +@item mode, m +Set output mode. Can be @code{bars} or @code{trace}. Default is @code{bars}. @end table @section adrawgraph @@ -25825,6 +27192,18 @@ replace old rows with new ones. scroll from top to bottom. @end table Default is @code{replace}. + +@item hmode +Set histogram mode. + +It accepts the following values: +@table @samp +@item abs +Use absolute values of samples. +@item sign +Use untouched values of samples. +@end table +Default is @code{abs}. @end table @section aphasemeter @@ -26534,6 +27913,10 @@ A processing speed faster than what is possible without these filters cannot be achieved. @end table +@subsection Commands + +Both filters supports the all above options as @ref{commands}. + @section segment, asegment Split single input stream into multiple streams. @@ -26882,6 +28265,12 @@ The end time in seconds of the current command interval. @item TI The interpolated time of the current command interval, TI = (T - TS) / (TE - TS). + +@item W +The video frame width. + +@item H +The video frame height. @end table @end table @@ -27464,6 +28853,9 @@ Specify size of video. For the syntax of this option, check the @ref{video size syntax,,"Video size" section in the ffmpeg-utils manual,ffmpeg-utils}. Default is @code{1024x512}. +@item rate, r +Set video rate. Default is @code{25}. + @item mode Set display mode. This set how each frequency bin will be represented. @@ -27580,6 +28972,9 @@ It accepts the following values: @item delay @end table Default is @code{magnitude}. + +@item channels +Set channels to use when processing audio. By default all are processed. @end table @section showspatial @@ -27829,6 +29224,9 @@ Allowed range is from 10 to 200. @item limit Set upper limit of input audio samples volume in dBFS. Default is 0 dBFS. Allowed range is from -100 to 100. + +@item opacity +Set opacity strength when using pixel format output with alpha component. @end table The usage is very similar to the showwaves filter; see the examples in that @@ -28010,6 +29408,9 @@ Allowed range is from 10 to 200. @item limit Set upper limit of input audio samples volume in dBFS. Default is 0 dBFS. Allowed range is from -100 to 100. + +@item opacity +Set opacity strength when using pixel format output with alpha component. @end table @subsection Examples @@ -28504,6 +29905,43 @@ Below is a description of the currently available multimedia sources. This is the same as @ref{movie} source, except it selects an audio stream by default. +@section avsynctest +Generate an Audio/Video Sync Test. + +Generated stream periodically shows flash video frame and emits beep in audio. +Useful to inspect A/V sync issues. + +It accepts the following options: + +@table @option +@item size, s +Set output video size. Default value is @code{hd720}. + +@item framerate, fr +Set output video frame rate. Default value is @code{30}. + +@item samplerate, sr +Set output audio sample rate. Default value is @code{44100}. + +@item amplitude, a +Set output audio beep amplitude. Default value is @code{0.7}. + +@item period, p +Set output audio beep period in seconds. Default value is @code{3}. + +@item delay, dl +Set output video flash delay in number of frames. Default value is @code{0}. + +@item cycle, c +Enable cycling of video delays, by default is disabled. + +@item duration, d +Set stream output duration. By default duration is unlimited. + +@item fg, bg, ag +Set foreground/background/additional color. +@end table + @anchor{movie} @section movie diff --git a/doc/general_contents.texi b/doc/general_contents.texi index df1692c8d..b1d3e3aa0 100644 --- a/doc/general_contents.texi +++ b/doc/general_contents.texi @@ -171,6 +171,13 @@ Go to @url{https://github.com/TimothyGu/libilbc} and follow the instructions for installing the library. Then pass @code{--enable-libilbc} to configure to enable it. +@section libjxl + +JPEG XL is an image format intended to fully replace legacy JPEG for an extended +period of life. See @url{https://jpegxl.info/} for more information, and see +@url{https://github.com/libjxl/libjxl} for the library source. You can pass +@code{--enable-libjxl} to configure in order enable the libjxl wrapper. + @section libvpx FFmpeg can make use of the libvpx library for VP8/VP9 decoding and encoding. @@ -578,6 +585,7 @@ library: @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 DFPWM @tab X @tab X @item raw Dirac @tab X @tab X @item raw DNxHD @tab X @tab X @item raw DTS @tab X @tab X @@ -767,6 +775,8 @@ following image formats are supported: @tab PGM with U and V components in YUV 4:2:0 @item PGX @tab @tab X @tab PGX file decoder +@item PHM @tab X @tab X + @tab Portable HalfFloatMap image @item PIC @tab @tab X @tab Pictor/PC Paint @item PNG @tab X @tab X @@ -777,6 +787,8 @@ following image formats are supported: @tab Photoshop @item PTX @tab @tab X @tab V.Flash PTX format +@item QOI @tab X @tab X + @tab Quite OK Image format @item SGI @tab X @tab X @tab SGI RGB image format @item Sun Rasterfile @tab X @tab X @@ -785,6 +797,8 @@ following image formats are supported: @tab YUV, JPEG and some extension is not supported yet. @item Truevision Targa @tab X @tab X @tab Targa (.TGA) image format +@item VBN @tab X @tab X + @tab Vizrt Binary Image format @item WebP @tab E @tab X @tab WebP image format, encoding supported through external library libwebp @item XBM @tab X @tab X @@ -1194,6 +1208,7 @@ following image formats are supported: @item CRI HCA @tab @tab X @item Delphine Software International CIN audio @tab @tab X @tab Codec used in Delphine Software International games. +@item DFPWM @tab X @tab X @item Digital Speech Standard - Standard Play mode (DSS SP) @tab @tab X @item Discworld II BMV Audio @tab @tab X @item COOK @tab @tab X diff --git a/doc/indevs.texi b/doc/indevs.texi index 9d8020311..8a198c4b4 100644 --- a/doc/indevs.texi +++ b/doc/indevs.texi @@ -1289,11 +1289,11 @@ Specify the samplerate in Hz, by default 48kHz is used. Specify the channels in use, by default 2 (stereo) is set. @item frame_size -Specify the number of bytes per frame, by default it is set to 1024. +This option does nothing and is deprecated. @item fragment_size -Specify the minimal buffering fragment in PulseAudio, it will affect the -audio latency. By default it is unset. +Specify the size in bytes of the minimal buffering fragment in PulseAudio, it +will affect the audio latency. By default it is set to 50 ms amount of data. @item wallclock Set the initial PTS using the current time. Default is 1. diff --git a/doc/muxers.texi b/doc/muxers.texi index 1ea98a69a..b2f4326aa 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -1060,6 +1060,8 @@ and remove the @code{#EXT-X-ENDLIST} from the old segment list. @item round_durations Round the duration info in the playlist file segment info to integer values, instead of using floating point. +If there are no other features requiring higher HLS versions be used, +then this will allow ffmpeg to output a HLS version 2 m3u8. @item discont_start Add the @code{#EXT-X-DISCONTINUITY} tag to the playlist, before the @@ -1567,6 +1569,15 @@ A safe size for most use cases should be about 50kB per hour of video. Note that cues are only written if the output is seekable and this option will have no effect if it is not. + +@item cues_to_front +If set, the muxer will write the index at the beginning of the file +by shifting the main data if necessary. This can be combined with +reserve_index_space in which case the data is only shifted if +the initially reserved space turns out to be insufficient. + +This option is ignored if the output is unseekable. + @item default_mode This option controls how the FlagDefault of the output tracks will be set. It influences which tracks players should play by default. The default mode @@ -1722,6 +1733,14 @@ B-frames. Additionally, eases conformance with the DASH-IF interoperability guidelines. This option is implicitly set when writing ismv (Smooth Streaming) files. + +@item -write_btrt @var{bool} +Force or disable writing bitrate box inside stsd box of a track. +The box contains decoding buffer size (in bytes), maximum bitrate and +average bitrate for the track. The box will be skipped if none of these values +can be computed. +Default is @code{-1} or @code{auto}, which will write the box only in MP4 mode. + @item -write_prft Write producer time reference box (PRFT) with a specified time source for the NTP field in the PRFT box. Set value as @samp{wallclock} to specify timesource @@ -1733,10 +1752,18 @@ where PTS values are set as as wallclock time at the source. For example, an encoding use case with decklink capture source where @option{video_pts} and @option{audio_pts} are set to @samp{abs_wallclock}. +@item -empty_hdlr_name @var{bool} +Enable to skip writing the name inside a @code{hdlr} box. +Default is @code{false}. + @item -movie_timescale @var{scale} Set the timescale written in the movie header box (@code{mvhd}). Range is 1 to INT_MAX. Default is 1000. +@item -video_track_timescale @var{scale} +Set the timescale used for video tracks. Range is 0 to INT_MAX. +If set to @code{0}, the timescale is automatically set based on +the native stream time base. Default is 0. @end table @subsection Example diff --git a/doc/protocols.texi b/doc/protocols.texi index d207df0b5..0df38d790 100644 --- a/doc/protocols.texi +++ b/doc/protocols.texi @@ -614,6 +614,38 @@ Establish a TLS (HTTPS) connection to Icecast. icecast://[@var{username}[:@var{password}]@@]@var{server}:@var{port}/@var{mountpoint} @end example +@section ipfs + +InterPlanetary File System (IPFS) protocol support. One can access files stored +on the IPFS network through so-called gateways. These are http(s) endpoints. +This protocol wraps the IPFS native protocols (ipfs:// and ipns://) to be sent +to such a gateway. Users can (and should) host their own node which means this +protocol will use one's local gateway to access files on the IPFS network. + +If a user doesn't have a node of their own then the public gateway @code{https://dweb.link} +is used by default. + +This protocol accepts the following options: + +@table @option + +@item gateway +Defines the gateway to use. When not set, the protocol will first try +locating the local gateway by looking at @code{$IPFS_GATEWAY}, @code{$IPFS_PATH} +and @code{$HOME/.ipfs/}, in that order. If that fails @code{https://dweb.link} will be used. + +@end table + +One can use this protocol in 2 ways. Using IPFS: +@example +ffplay ipfs://QmbGtJg23skhvFmu9mJiePVByhfzu5rwo74MEkVDYAmF5T +@end example + +Or the IPNS protocol (IPNS is mutable IPFS): +@example +ffplay ipns://QmbGtJg23skhvFmu9mJiePVByhfzu5rwo74MEkVDYAmF5T +@end example + @section mmst MMS (Microsoft Media Server) protocol over TCP. @@ -745,6 +777,14 @@ Set internal RIST buffer size in milliseconds for retransmission of data. Default value is 0 which means the librist default (1 sec). Maximum value is 30 seconds. +@item fifo_size +Size of the librist receiver output fifo in number of packets. This must be a +power of 2. +Defaults to 8192 (vs the librist default of 1024). + +@item overrun_nonfatal=@var{1|0} +Survive in case of librist fifo buffer overrun. Default value is 0. + @item pkt_size Set maximum packet size for sending data. 1316 by default. @@ -2025,5 +2065,4 @@ decoding errors. @end table - @c man end PROTOCOLS diff --git a/doc/utils.texi b/doc/utils.texi index b1c25c192..232a0608b 100644 --- a/doc/utils.texi +++ b/doc/utils.texi @@ -723,20 +723,28 @@ DL+DR FL+FR+FC+LFE+BL+BR+FLC+FRC+BC+SL+SR+TC+TFL+TFC+TFR+TBL+TBC+TBR+LFE2+TSL+TSR+BFC+BFL+BFR @end table -A custom channel layout can be specified as a sequence of terms, separated by -'+' or '|'. Each term can be: +A custom channel layout can be specified as a sequence of terms, separated by '+'. +Each term can be: @itemize +@item +the name of a single channel (e.g. @samp{FL}, @samp{FR}, @samp{FC}, @samp{LFE}, etc.), +each optionally containing a custom name after a '@@', (e.g. @samp{FL@@Left}, +@samp{FR@@Right}, @samp{FC@@Center}, @samp{LFE@@Low_Frequency}, etc.) +@end itemize + +A standard channel layout can be specified by the following: +@itemize +@item +the name of a single channel (e.g. @samp{FL}, @samp{FR}, @samp{FC}, @samp{LFE}, etc.) + @item the name of a standard channel layout (e.g. @samp{mono}, @samp{stereo}, @samp{4.0}, @samp{quad}, @samp{5.0}, etc.) -@item -the name of a single channel (e.g. @samp{FL}, @samp{FR}, @samp{FC}, @samp{LFE}, etc.) - @item a number of channels, in decimal, followed by 'c', yielding the default channel layout for that number of channels (see the function -@code{av_get_default_channel_layout}). Note that not all channel counts have a +@code{av_channel_layout_default}). Note that not all channel counts have a default layout. @item @@ -753,7 +761,7 @@ Before libavutil version 53 the trailing character "c" to specify a number of channels was optional, but now it is required, while a channel layout mask can also be specified as a decimal number (if and only if not followed by "c" or "C"). -See also the function @code{av_get_channel_layout} defined in +See also the function @code{av_channel_layout_from_string} defined in @file{libavutil/channel_layout.h}. @c man end SYNTAX diff --git a/ffbuild/common.mak b/ffbuild/common.mak index 42f7b2364..f52473453 100644 --- a/ffbuild/common.mak +++ b/ffbuild/common.mak @@ -29,7 +29,8 @@ $(foreach VAR,$(SILENT),$(eval override $(VAR) = @$($(VAR)))) $(eval INSTALL = @$(call ECHO,INSTALL,$$(^:$(SRC_DIR)/%=%)); $(INSTALL)) endif -ALLFFLIBS = avcodec avdevice avfilter avformat avutil postproc swscale swresample +# Prepend to a recursively expanded variable without making it simply expanded. +PREPEND = $(eval $(1) = $(patsubst %,$$(%), $(2)) $(value $(1))) # NASM requires -I path terminated with / IFLAGS := -I. -I$(SRC_LINK)/ @@ -39,7 +40,9 @@ CCFLAGS = $(CPPFLAGS) $(CFLAGS) OBJCFLAGS += $(EOBJCFLAGS) OBJCCFLAGS = $(CPPFLAGS) $(CFLAGS) $(OBJCFLAGS) ASFLAGS := $(CPPFLAGS) $(ASFLAGS) -CXXFLAGS := $(CPPFLAGS) $(CFLAGS) $(CXXFLAGS) +# Use PREPEND here so that later (target-dependent) additions to CPPFLAGS +# end up in CXXFLAGS. +$(call PREPEND,CXXFLAGS, CPPFLAGS CFLAGS) X86ASMFLAGS += $(IFLAGS:%=%/) -I$( $$@ +$(SUBDIR)lib$(NAME).version: $(SUBDIR)version.h $(SUBDIR)version_major.h | $(SUBDIR) + $$(M) $$(SRC_PATH)/ffbuild/libversion.sh $(NAME) $$^ > $$@ $(SUBDIR)lib$(FULLNAME).pc: $(SUBDIR)version.h ffbuild/config.sh | $(SUBDIR) $$(M) $$(SRC_PATH)/ffbuild/pkgconfig_generate.sh $(NAME) "$(DESC)" diff --git a/ffbuild/libversion.sh b/ffbuild/libversion.sh index 990ce9f64..a94ab5805 100755 --- a/ffbuild/libversion.sh +++ b/ffbuild/libversion.sh @@ -5,8 +5,12 @@ toupper(){ name=lib$1 ucname=$(toupper ${name}) file=$2 +file2=$3 eval $(awk "/#define ${ucname}_VERSION_M/ { print \$2 \"=\" \$3 }" "$file") +if [ -f "$file2" ]; then + eval $(awk "/#define ${ucname}_VERSION_M/ { print \$2 \"=\" \$3 }" "$file2") +fi eval ${ucname}_VERSION=\$${ucname}_VERSION_MAJOR.\$${ucname}_VERSION_MINOR.\$${ucname}_VERSION_MICRO eval echo "${name}_VERSION=\$${ucname}_VERSION" eval echo "${name}_VERSION_MAJOR=\$${ucname}_VERSION_MAJOR" diff --git a/fftools/Makefile b/fftools/Makefile index da420786e..81ad6c4f4 100644 --- a/fftools/Makefile +++ b/fftools/Makefile @@ -9,10 +9,14 @@ AVBASENAMES = ffmpeg ffplay ffprobe ALLAVPROGS = $(AVBASENAMES:%=%$(PROGSSUF)$(EXESUF)) ALLAVPROGS_G = $(AVBASENAMES:%=%$(PROGSSUF)_g$(EXESUF)) -OBJS-ffmpeg += fftools/ffmpeg_opt.o fftools/ffmpeg_filter.o fftools/ffmpeg_hw.o +OBJS-ffmpeg += \ + fftools/ffmpeg_filter.o \ + fftools/ffmpeg_hw.o \ + fftools/ffmpeg_mux.o \ + fftools/ffmpeg_opt.o \ define DOFFTOOL -OBJS-$(1) += fftools/cmdutils.o fftools/$(1).o $(OBJS-$(1)-yes) +OBJS-$(1) += fftools/cmdutils.o fftools/opt_common.o fftools/$(1).o $(OBJS-$(1)-yes) $(1)$(PROGSSUF)_g$(EXESUF): $$(OBJS-$(1)) $$(OBJS-$(1)): | fftools $$(OBJS-$(1)): CFLAGS += $(CFLAGS-$(1)) diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c index 4b50e15ee..18e768b38 100644 --- a/fftools/cmdutils.c +++ b/fftools/cmdutils.c @@ -32,54 +32,35 @@ #include "config.h" #include "compat/va_copy.h" #include "libavformat/avformat.h" -#include "libavfilter/avfilter.h" -#include "libavdevice/avdevice.h" #include "libswscale/swscale.h" +#include "libswscale/version.h" #include "libswresample/swresample.h" -#include "libpostproc/postprocess.h" -#include "libavutil/attributes.h" #include "libavutil/avassert.h" #include "libavutil/avstring.h" -#include "libavutil/bprint.h" #include "libavutil/channel_layout.h" #include "libavutil/display.h" +#include "libavutil/getenv_utf8.h" #include "libavutil/mathematics.h" #include "libavutil/imgutils.h" #include "libavutil/libm.h" #include "libavutil/parseutils.h" -#include "libavutil/pixdesc.h" #include "libavutil/eval.h" #include "libavutil/dict.h" #include "libavutil/opt.h" -#include "libavutil/cpu.h" -#include "libavutil/ffversion.h" -#include "libavutil/version.h" -#include "libavcodec/bsf.h" #include "cmdutils.h" -#if HAVE_SYS_RESOURCE_H -#include -#include -#endif +#include "fopen_utf8.h" +#include "opt_common.h" #ifdef _WIN32 #include +#include "compat/w32dlfcn.h" #endif -static int init_report(const char *env); - AVDictionary *sws_dict; AVDictionary *swr_opts; AVDictionary *format_opts, *codec_opts; -static FILE *report_file; -static int report_file_level = AV_LOG_DEBUG; int hide_banner = 0; -enum show_muxdemuxers { - SHOW_DEFAULT, - SHOW_DEMUXERS, - SHOW_MUXERS, -}; - void uninit_opts(void) { av_dict_free(&swr_opts); @@ -93,22 +74,6 @@ void log_callback_help(void *ptr, int level, const char *fmt, va_list vl) vfprintf(stdout, fmt, vl); } -static void log_callback_report(void *ptr, int level, const char *fmt, va_list vl) -{ - va_list vl2; - char line[1024]; - static int print_prefix = 1; - - va_copy(vl2, vl); - av_log_default_callback(ptr, level, fmt, vl); - av_log_format_line(ptr, level, fmt, vl2, line, sizeof(line), &print_prefix); - va_end(vl2); - if (report_file_level >= level) { - fputs(line, report_file); - fflush(report_file); - } -} - void init_dynload(void) { #if HAVE_SETDLLDIRECTORY && defined(_WIN32) @@ -341,6 +306,12 @@ static int write_option(void *optctx, const OptionDef *po, const char *opt, int parse_option(void *optctx, const char *opt, const char *arg, const OptionDef *options) { + static const OptionDef opt_avoptions = { + .name = "AVOption passthrough", + .flags = HAS_ARG, + .u.func_arg = opt_default, + }; + const OptionDef *po; int ret; @@ -354,7 +325,7 @@ int parse_option(void *optctx, const char *opt, const char *arg, arg = "1"; if (!po->name) - po = find_option(options, "default"); + po = &opt_avoptions; if (!po->name) { av_log(NULL, AV_LOG_ERROR, "Unrecognized option '%s'\n", opt); return AVERROR(EINVAL); @@ -461,7 +432,7 @@ int locate_option(int argc, char **argv, const OptionDef *options, return 0; } -static void dump_argument(const char *a) +static void dump_argument(FILE *report_file, const char *a) { const unsigned char *p; @@ -497,7 +468,7 @@ static void check_options(const OptionDef *po) void parse_loglevel(int argc, char **argv, const OptionDef *options) { int idx = locate_option(argc, argv, options, "loglevel"); - const char *env; + char *env; check_options(options); @@ -506,18 +477,21 @@ void parse_loglevel(int argc, char **argv, const OptionDef *options) if (idx && argv[idx + 1]) opt_loglevel(NULL, "loglevel", argv[idx + 1]); idx = locate_option(argc, argv, options, "report"); - if ((env = getenv("FFREPORT")) || idx) { - init_report(env); + env = getenv_utf8("FFREPORT"); + if (env || idx) { + FILE *report_file = NULL; + init_report(env, &report_file); if (report_file) { int i; fprintf(report_file, "Command line:\n"); for (i = 0; i < argc; i++) { - dump_argument(argv[i]); + dump_argument(report_file, argv[i]); fputc(i < argc - 1 ? ' ' : '\n', report_file); } fflush(report_file); } } + freeenv_utf8(env); idx = locate_option(argc, argv, options, "hide_banner"); if (idx) hide_banner = 1; @@ -571,20 +545,12 @@ int opt_default(void *optctx, const char *opt, const char *arg) #if CONFIG_SWSCALE if (!consumed && (o = opt_find(&sc, opt, NULL, 0, AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) { - struct SwsContext *sws = sws_alloc_context(); - int ret = av_opt_set(sws, opt, arg, 0); - sws_freeContext(sws); if (!strcmp(opt, "srcw") || !strcmp(opt, "srch") || !strcmp(opt, "dstw") || !strcmp(opt, "dsth") || !strcmp(opt, "src_format") || !strcmp(opt, "dst_format")) { av_log(NULL, AV_LOG_ERROR, "Directly using swscale dimensions/format options is not supported, please use the -s or -pix_fmt options\n"); return AVERROR(EINVAL); } - if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "Error setting option %s.\n", opt); - return ret; - } - av_dict_set(&sws_dict, opt, arg, FLAGS); consumed = 1; @@ -598,13 +564,6 @@ int opt_default(void *optctx, const char *opt, const char *arg) #if CONFIG_SWRESAMPLE if (!consumed && (o=opt_find(&swr_class, opt, NULL, 0, AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ))) { - struct SwrContext *swr = swr_alloc(); - int ret = av_opt_set(swr, opt, arg, 0); - swr_free(&swr); - if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "Error setting option %s.\n", opt); - return ret; - } av_dict_set(&swr_opts, opt, arg, FLAGS); consumed = 1; } @@ -831,259 +790,6 @@ do { \ return 0; } -int opt_cpuflags(void *optctx, const char *opt, const char *arg) -{ - int ret; - unsigned flags = av_get_cpu_flags(); - - if ((ret = av_parse_cpu_caps(&flags, arg)) < 0) - return ret; - - av_force_cpu_flags(flags); - return 0; -} - -int opt_cpucount(void *optctx, const char *opt, const char *arg) -{ - int ret; - int count; - - static const AVOption opts[] = { - {"count", NULL, 0, AV_OPT_TYPE_INT, { .i64 = -1}, -1, INT_MAX}, - {NULL}, - }; - static const AVClass class = { - .class_name = "cpucount", - .item_name = av_default_item_name, - .option = opts, - .version = LIBAVUTIL_VERSION_INT, - }; - const AVClass *pclass = &class; - - ret = av_opt_eval_int(&pclass, opts, arg, &count); - - if (!ret) { - av_cpu_force_count(count); - } - - return ret; -} - -int opt_loglevel(void *optctx, const char *opt, const char *arg) -{ - const struct { const char *name; int level; } log_levels[] = { - { "quiet" , AV_LOG_QUIET }, - { "panic" , AV_LOG_PANIC }, - { "fatal" , AV_LOG_FATAL }, - { "error" , AV_LOG_ERROR }, - { "warning", AV_LOG_WARNING }, - { "info" , AV_LOG_INFO }, - { "verbose", AV_LOG_VERBOSE }, - { "debug" , AV_LOG_DEBUG }, - { "trace" , AV_LOG_TRACE }, - }; - const char *token; - char *tail; - 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 (av_strstart(token, "repeat", &arg)) { - if (cmd == '-') { - flags |= AV_LOG_SKIP_REPEATED; - } else { - flags &= ~AV_LOG_SKIP_REPEATED; - } - } else if (av_strstart(token, "level", &arg)) { - if (cmd == '-') { - flags &= ~AV_LOG_PRINT_LEVEL; - } else { - flags |= AV_LOG_PRINT_LEVEL; - } - } 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)) { - level = log_levels[i].level; - goto end; - } - } - - level = strtol(arg, &tail, 10); - if (*tail) { - av_log(NULL, AV_LOG_FATAL, "Invalid loglevel \"%s\". " - "Possible levels are numbers or:\n", arg); - for (i = 0; i < FF_ARRAY_ELEMS(log_levels); i++) - 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; -} - -static void expand_filename_template(AVBPrint *bp, const char *template, - struct tm *tm) -{ - int c; - - while ((c = *(template++))) { - if (c == '%') { - if (!(c = *(template++))) - break; - switch (c) { - case 'p': - av_bprintf(bp, "%s", program_name); - break; - case 't': - av_bprintf(bp, "%04d%02d%02d-%02d%02d%02d", - tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, - tm->tm_hour, tm->tm_min, tm->tm_sec); - break; - case '%': - av_bprint_chars(bp, c, 1); - break; - } - } else { - av_bprint_chars(bp, c, 1); - } - } -} - -static int init_report(const char *env) -{ - char *filename_template = NULL; - char *key, *val; - int ret, count = 0; - int prog_loglevel, envlevel = 0; - time_t now; - struct tm *tm; - AVBPrint filename; - - if (report_file) /* already opened */ - return 0; - time(&now); - tm = localtime(&now); - - while (env && *env) { - if ((ret = av_opt_get_key_value(&env, "=", ":", 0, &key, &val)) < 0) { - if (count) - av_log(NULL, AV_LOG_ERROR, - "Failed to parse FFREPORT environment variable: %s\n", - av_err2str(ret)); - break; - } - if (*env) - env++; - count++; - if (!strcmp(key, "file")) { - av_free(filename_template); - filename_template = val; - val = NULL; - } else if (!strcmp(key, "level")) { - char *tail; - report_file_level = strtol(val, &tail, 10); - if (*tail) { - av_log(NULL, AV_LOG_FATAL, "Invalid report file level\n"); - exit_program(1); - } - envlevel = 1; - } else { - av_log(NULL, AV_LOG_ERROR, "Unknown key '%s' in FFREPORT\n", key); - } - av_free(val); - av_free(key); - } - - av_bprint_init(&filename, 0, AV_BPRINT_SIZE_AUTOMATIC); - expand_filename_template(&filename, - av_x_if_null(filename_template, "%p-%t.log"), tm); - av_free(filename_template); - if (!av_bprint_is_complete(&filename)) { - av_log(NULL, AV_LOG_ERROR, "Out of memory building report file name\n"); - return AVERROR(ENOMEM); - } - - prog_loglevel = av_log_get_level(); - if (!envlevel) - report_file_level = FFMAX(report_file_level, prog_loglevel); - - report_file = fopen(filename.str, "w"); - if (!report_file) { - int ret = AVERROR(errno); - av_log(NULL, AV_LOG_ERROR, "Failed to open report \"%s\": %s\n", - filename.str, strerror(errno)); - return ret; - } - av_log_set_callback(log_callback_report); - av_log(NULL, AV_LOG_INFO, - "%s started on %04d-%02d-%02d at %02d:%02d:%02d\n" - "Report written to \"%s\"\n" - "Log level: %d\n", - program_name, - tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, - tm->tm_hour, tm->tm_min, tm->tm_sec, - filename.str, report_file_level); - av_bprint_finalize(&filename, NULL); - return 0; -} - -int opt_report(void *optctx, const char *opt, const char *arg) -{ - return init_report(NULL); -} - -int opt_max_alloc(void *optctx, const char *opt, const char *arg) -{ - char *tail; - size_t max; - - max = strtol(arg, &tail, 10); - if (*tail) { - av_log(NULL, AV_LOG_FATAL, "Invalid max_alloc \"%s\".\n", arg); - exit_program(1); - } - av_max_alloc(max); - return 0; -} - -int opt_timelimit(void *optctx, const char *opt, const char *arg) -{ -#if HAVE_SETRLIMIT - int lim = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX); - struct rlimit rl = { lim, lim + 1 }; - if (setrlimit(RLIMIT_CPU, &rl)) - perror("setrlimit"); -#else - av_log(NULL, AV_LOG_WARNING, "-%s not implemented on this OS\n", opt); -#endif - return 0; -} - void print_error(const char *filename, int err) { char errbuf[128]; @@ -1094,960 +800,6 @@ void print_error(const char *filename, int err) av_log(NULL, AV_LOG_ERROR, "%s: %s\n", filename, errbuf_ptr); } -static int warned_cfg = 0; - -#define INDENT 1 -#define SHOW_VERSION 2 -#define SHOW_CONFIG 4 -#define SHOW_COPYRIGHT 8 - -#define PRINT_LIB_INFO(libname, LIBNAME, flags, level) \ - if (CONFIG_##LIBNAME) { \ - const char *indent = flags & INDENT? " " : ""; \ - if (flags & SHOW_VERSION) { \ - unsigned int version = libname##_version(); \ - av_log(NULL, level, \ - "%slib%-11s %2d.%3d.%3d / %2d.%3d.%3d\n", \ - indent, #libname, \ - LIB##LIBNAME##_VERSION_MAJOR, \ - LIB##LIBNAME##_VERSION_MINOR, \ - LIB##LIBNAME##_VERSION_MICRO, \ - AV_VERSION_MAJOR(version), AV_VERSION_MINOR(version),\ - AV_VERSION_MICRO(version)); \ - } \ - if (flags & SHOW_CONFIG) { \ - const char *cfg = libname##_configuration(); \ - if (strcmp(FFMPEG_CONFIGURATION, cfg)) { \ - if (!warned_cfg) { \ - av_log(NULL, level, \ - "%sWARNING: library configuration mismatch\n", \ - indent); \ - warned_cfg = 1; \ - } \ - av_log(NULL, level, "%s%-11s configuration: %s\n", \ - indent, #libname, cfg); \ - } \ - } \ - } \ - -static void print_all_libs_info(int flags, int level) -{ - PRINT_LIB_INFO(avutil, AVUTIL, flags, level); - PRINT_LIB_INFO(avcodec, AVCODEC, flags, level); - PRINT_LIB_INFO(avformat, AVFORMAT, flags, level); - PRINT_LIB_INFO(avdevice, AVDEVICE, flags, level); - PRINT_LIB_INFO(avfilter, AVFILTER, flags, level); - PRINT_LIB_INFO(swscale, SWSCALE, flags, level); - PRINT_LIB_INFO(swresample, SWRESAMPLE, flags, level); - PRINT_LIB_INFO(postproc, POSTPROC, flags, level); -} - -static void print_program_info(int flags, int level) -{ - const char *indent = flags & INDENT? " " : ""; - - av_log(NULL, level, "%s version " FFMPEG_VERSION, program_name); - if (flags & SHOW_COPYRIGHT) - av_log(NULL, level, " Copyright (c) %d-%d the FFmpeg developers", - program_birth_year, CONFIG_THIS_YEAR); - av_log(NULL, level, "\n"); - av_log(NULL, level, "%sbuilt with %s\n", indent, CC_IDENT); - - av_log(NULL, level, "%sconfiguration: " FFMPEG_CONFIGURATION "\n", indent); -} - -static void print_buildconf(int flags, int level) -{ - const char *indent = flags & INDENT ? " " : ""; - char str[] = { FFMPEG_CONFIGURATION }; - char *conflist, *remove_tilde, *splitconf; - - // Change all the ' --' strings to '~--' so that - // they can be identified as tokens. - while ((conflist = strstr(str, " --")) != NULL) { - conflist[0] = '~'; - } - - // Compensate for the weirdness this would cause - // when passing 'pkg-config --static'. - while ((remove_tilde = strstr(str, "pkg-config~")) != NULL) { - remove_tilde[sizeof("pkg-config~") - 2] = ' '; - } - - splitconf = strtok(str, "~"); - av_log(NULL, level, "\n%sconfiguration:\n", indent); - while (splitconf != NULL) { - av_log(NULL, level, "%s%s%s\n", indent, indent, splitconf); - splitconf = strtok(NULL, "~"); - } -} - -void show_banner(int argc, char **argv, const OptionDef *options) -{ - int idx = locate_option(argc, argv, options, "version"); - if (hide_banner || idx) - return; - - print_program_info (INDENT|SHOW_COPYRIGHT, AV_LOG_INFO); - print_all_libs_info(INDENT|SHOW_CONFIG, AV_LOG_INFO); - print_all_libs_info(INDENT|SHOW_VERSION, AV_LOG_INFO); -} - -int show_version(void *optctx, const char *opt, const char *arg) -{ - av_log_set_callback(log_callback_help); - print_program_info (SHOW_COPYRIGHT, AV_LOG_INFO); - print_all_libs_info(SHOW_VERSION, AV_LOG_INFO); - - return 0; -} - -int show_buildconf(void *optctx, const char *opt, const char *arg) -{ - av_log_set_callback(log_callback_help); - print_buildconf (INDENT|0, AV_LOG_INFO); - - return 0; -} - -int show_license(void *optctx, const char *opt, const char *arg) -{ -#if CONFIG_NONFREE - printf( - "This version of %s has nonfree parts compiled in.\n" - "Therefore it is not legally redistributable.\n", - program_name ); -#elif CONFIG_GPLV3 - printf( - "%s is free software; you can redistribute it and/or modify\n" - "it under the terms of the GNU General Public License as published by\n" - "the Free Software Foundation; either version 3 of the License, or\n" - "(at your option) any later version.\n" - "\n" - "%s is distributed in the hope that it will be useful,\n" - "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" - "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" - "GNU General Public License for more details.\n" - "\n" - "You should have received a copy of the GNU General Public License\n" - "along with %s. If not, see .\n", - program_name, program_name, program_name ); -#elif CONFIG_GPL - printf( - "%s is free software; you can redistribute it and/or modify\n" - "it under the terms of the GNU General Public License as published by\n" - "the Free Software Foundation; either version 2 of the License, or\n" - "(at your option) any later version.\n" - "\n" - "%s is distributed in the hope that it will be useful,\n" - "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" - "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" - "GNU General Public License for more details.\n" - "\n" - "You should have received a copy of the GNU General Public License\n" - "along with %s; if not, write to the Free Software\n" - "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n", - program_name, program_name, program_name ); -#elif CONFIG_LGPLV3 - printf( - "%s is free software; you can redistribute it and/or modify\n" - "it under the terms of the GNU Lesser General Public License as published by\n" - "the Free Software Foundation; either version 3 of the License, or\n" - "(at your option) any later version.\n" - "\n" - "%s is distributed in the hope that it will be useful,\n" - "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" - "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" - "GNU Lesser General Public License for more details.\n" - "\n" - "You should have received a copy of the GNU Lesser General Public License\n" - "along with %s. If not, see .\n", - program_name, program_name, program_name ); -#else - printf( - "%s is free software; you can redistribute it and/or\n" - "modify it under the terms of the GNU Lesser General Public\n" - "License as published by the Free Software Foundation; either\n" - "version 2.1 of the License, or (at your option) any later version.\n" - "\n" - "%s is distributed in the hope that it will be useful,\n" - "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" - "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" - "Lesser General Public License for more details.\n" - "\n" - "You should have received a copy of the GNU Lesser General Public\n" - "License along with %s; if not, write to the Free Software\n" - "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n", - program_name, program_name, program_name ); -#endif - - 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) -{ - void *ifmt_opaque = NULL; - const AVInputFormat *ifmt = NULL; - void *ofmt_opaque = NULL; - const AVOutputFormat *ofmt = NULL; - const char *last_name; - int is_dev; - - printf("%s\n" - " D. = Demuxing supported\n" - " .E = Muxing supported\n" - " --\n", device_only ? "Devices:" : "File formats:"); - last_name = "000"; - for (;;) { - int decode = 0; - int encode = 0; - const char *name = NULL; - const char *long_name = NULL; - - if (muxdemuxers !=SHOW_DEMUXERS) { - ofmt_opaque = NULL; - while ((ofmt = av_muxer_iterate(&ofmt_opaque))) { - 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) { - ifmt_opaque = NULL; - while ((ifmt = av_demuxer_iterate(&ifmt_opaque))) { - 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; - - printf(" %c%c %-15s %s\n", - decode ? 'D' : ' ', - encode ? 'E' : ' ', - name, - long_name ? long_name:" "); - } - return 0; -} - -int show_formats(void *optctx, const char *opt, const char *arg) -{ - return show_formats_devices(optctx, opt, arg, 0, SHOW_DEFAULT); -} - -int show_muxers(void *optctx, const char *opt, const char *arg) -{ - return show_formats_devices(optctx, opt, arg, 0, SHOW_MUXERS); -} - -int show_demuxers(void *optctx, const char *opt, const char *arg) -{ - return show_formats_devices(optctx, opt, arg, 0, SHOW_DEMUXERS); -} - -int show_devices(void *optctx, const char *opt, const char *arg) -{ - return show_formats_devices(optctx, opt, arg, 1, SHOW_DEFAULT); -} - -#define PRINT_CODEC_SUPPORTED(codec, field, type, list_name, term, get_name) \ - if (codec->field) { \ - const type *p = codec->field; \ - \ - printf(" Supported " list_name ":"); \ - while (*p != term) { \ - get_name(*p); \ - printf(" %s", name); \ - p++; \ - } \ - printf("\n"); \ - } \ - -static void print_codec(const AVCodec *c) -{ - int encoder = av_codec_is_encoder(c); - - printf("%s %s [%s]:\n", encoder ? "Encoder" : "Decoder", c->name, - c->long_name ? c->long_name : ""); - - printf(" General capabilities: "); - if (c->capabilities & AV_CODEC_CAP_DRAW_HORIZ_BAND) - printf("horizband "); - if (c->capabilities & AV_CODEC_CAP_DR1) - printf("dr1 "); - if (c->capabilities & AV_CODEC_CAP_DELAY) - printf("delay "); - if (c->capabilities & AV_CODEC_CAP_SMALL_LAST_FRAME) - printf("small "); - if (c->capabilities & AV_CODEC_CAP_SUBFRAMES) - printf("subframes "); - if (c->capabilities & AV_CODEC_CAP_EXPERIMENTAL) - printf("exp "); - if (c->capabilities & AV_CODEC_CAP_CHANNEL_CONF) - printf("chconf "); - if (c->capabilities & AV_CODEC_CAP_PARAM_CHANGE) - printf("paramchange "); - if (c->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE) - printf("variable "); - if (c->capabilities & (AV_CODEC_CAP_FRAME_THREADS | - AV_CODEC_CAP_SLICE_THREADS | - AV_CODEC_CAP_OTHER_THREADS)) - printf("threads "); - if (c->capabilities & AV_CODEC_CAP_AVOID_PROBING) - printf("avoidprobe "); - if (c->capabilities & AV_CODEC_CAP_HARDWARE) - printf("hardware "); - if (c->capabilities & AV_CODEC_CAP_HYBRID) - printf("hybrid "); - if (!c->capabilities) - printf("none"); - printf("\n"); - - if (c->type == AVMEDIA_TYPE_VIDEO || - c->type == AVMEDIA_TYPE_AUDIO) { - printf(" Threading capabilities: "); - switch (c->capabilities & (AV_CODEC_CAP_FRAME_THREADS | - AV_CODEC_CAP_SLICE_THREADS | - AV_CODEC_CAP_OTHER_THREADS)) { - case AV_CODEC_CAP_FRAME_THREADS | - AV_CODEC_CAP_SLICE_THREADS: printf("frame and slice"); break; - case AV_CODEC_CAP_FRAME_THREADS: printf("frame"); break; - case AV_CODEC_CAP_SLICE_THREADS: printf("slice"); break; - case AV_CODEC_CAP_OTHER_THREADS: printf("other"); break; - default: printf("none"); break; - } - printf("\n"); - } - - if (avcodec_get_hw_config(c, 0)) { - printf(" Supported hardware devices: "); - for (int i = 0;; i++) { - const AVCodecHWConfig *config = avcodec_get_hw_config(c, i); - if (!config) - break; - printf("%s ", av_hwdevice_get_type_name(config->device_type)); - } - printf("\n"); - } - - if (c->supported_framerates) { - const AVRational *fps = c->supported_framerates; - - printf(" Supported framerates:"); - while (fps->num) { - printf(" %d/%d", fps->num, fps->den); - fps++; - } - printf("\n"); - } - PRINT_CODEC_SUPPORTED(c, pix_fmts, enum AVPixelFormat, "pixel formats", - AV_PIX_FMT_NONE, GET_PIX_FMT_NAME); - PRINT_CODEC_SUPPORTED(c, supported_samplerates, int, "sample rates", 0, - GET_SAMPLE_RATE_NAME); - PRINT_CODEC_SUPPORTED(c, sample_fmts, enum AVSampleFormat, "sample formats", - AV_SAMPLE_FMT_NONE, GET_SAMPLE_FMT_NAME); - PRINT_CODEC_SUPPORTED(c, channel_layouts, uint64_t, "channel layouts", - 0, GET_CH_LAYOUT_DESC); - - if (c->priv_class) { - show_help_children(c->priv_class, - AV_OPT_FLAG_ENCODING_PARAM | - AV_OPT_FLAG_DECODING_PARAM); - } -} - -static char get_media_type_char(enum AVMediaType type) -{ - switch (type) { - case AVMEDIA_TYPE_VIDEO: return 'V'; - case AVMEDIA_TYPE_AUDIO: return 'A'; - case AVMEDIA_TYPE_DATA: return 'D'; - case AVMEDIA_TYPE_SUBTITLE: return 'S'; - case AVMEDIA_TYPE_ATTACHMENT:return 'T'; - default: return '?'; - } -} - -static const AVCodec *next_codec_for_id(enum AVCodecID id, void **iter, - int encoder) -{ - const AVCodec *c; - while ((c = av_codec_iterate(iter))) { - if (c->id == id && - (encoder ? av_codec_is_encoder(c) : av_codec_is_decoder(c))) - return c; - } - return NULL; -} - -static int compare_codec_desc(const void *a, const void *b) -{ - const AVCodecDescriptor * const *da = a; - const AVCodecDescriptor * const *db = b; - - return (*da)->type != (*db)->type ? FFDIFFSIGN((*da)->type, (*db)->type) : - strcmp((*da)->name, (*db)->name); -} - -static unsigned get_codecs_sorted(const AVCodecDescriptor ***rcodecs) -{ - const AVCodecDescriptor *desc = NULL; - const AVCodecDescriptor **codecs; - unsigned nb_codecs = 0, i = 0; - - while ((desc = avcodec_descriptor_next(desc))) - nb_codecs++; - if (!(codecs = av_calloc(nb_codecs, sizeof(*codecs)))) { - av_log(NULL, AV_LOG_ERROR, "Out of memory\n"); - exit_program(1); - } - desc = NULL; - while ((desc = avcodec_descriptor_next(desc))) - codecs[i++] = desc; - av_assert0(i == nb_codecs); - qsort(codecs, nb_codecs, sizeof(*codecs), compare_codec_desc); - *rcodecs = codecs; - return nb_codecs; -} - -static void print_codecs_for_id(enum AVCodecID id, int encoder) -{ - void *iter = NULL; - const AVCodec *codec; - - printf(" (%s: ", encoder ? "encoders" : "decoders"); - - while ((codec = next_codec_for_id(id, &iter, encoder))) - printf("%s ", codec->name); - - printf(")"); -} - -int show_codecs(void *optctx, const char *opt, const char *arg) -{ - const AVCodecDescriptor **codecs; - unsigned i, nb_codecs = get_codecs_sorted(&codecs); - - printf("Codecs:\n" - " D..... = Decoding supported\n" - " .E.... = Encoding supported\n" - " ..V... = Video codec\n" - " ..A... = Audio codec\n" - " ..S... = Subtitle codec\n" - " ...I.. = Intra frame-only codec\n" - " ....L. = Lossy compression\n" - " .....S = Lossless compression\n" - " -------\n"); - for (i = 0; i < nb_codecs; i++) { - const AVCodecDescriptor *desc = codecs[i]; - const AVCodec *codec; - void *iter = NULL; - - if (strstr(desc->name, "_deprecated")) - continue; - - printf(" "); - printf(avcodec_find_decoder(desc->id) ? "D" : "."); - printf(avcodec_find_encoder(desc->id) ? "E" : "."); - - printf("%c", get_media_type_char(desc->type)); - printf((desc->props & AV_CODEC_PROP_INTRA_ONLY) ? "I" : "."); - printf((desc->props & AV_CODEC_PROP_LOSSY) ? "L" : "."); - printf((desc->props & AV_CODEC_PROP_LOSSLESS) ? "S" : "."); - - printf(" %-20s %s", desc->name, desc->long_name ? desc->long_name : ""); - - /* print decoders/encoders when there's more than one or their - * names are different from codec name */ - while ((codec = next_codec_for_id(desc->id, &iter, 0))) { - if (strcmp(codec->name, desc->name)) { - print_codecs_for_id(desc->id, 0); - break; - } - } - iter = NULL; - while ((codec = next_codec_for_id(desc->id, &iter, 1))) { - if (strcmp(codec->name, desc->name)) { - print_codecs_for_id(desc->id, 1); - break; - } - } - - printf("\n"); - } - av_free(codecs); - return 0; -} - -static void print_codecs(int encoder) -{ - const AVCodecDescriptor **codecs; - unsigned i, nb_codecs = get_codecs_sorted(&codecs); - - printf("%s:\n" - " V..... = Video\n" - " A..... = Audio\n" - " S..... = Subtitle\n" - " .F.... = Frame-level multithreading\n" - " ..S... = Slice-level multithreading\n" - " ...X.. = Codec is experimental\n" - " ....B. = Supports draw_horiz_band\n" - " .....D = Supports direct rendering method 1\n" - " ------\n", - encoder ? "Encoders" : "Decoders"); - for (i = 0; i < nb_codecs; i++) { - const AVCodecDescriptor *desc = codecs[i]; - const AVCodec *codec; - void *iter = NULL; - - while ((codec = next_codec_for_id(desc->id, &iter, encoder))) { - printf(" %c", get_media_type_char(desc->type)); - printf((codec->capabilities & AV_CODEC_CAP_FRAME_THREADS) ? "F" : "."); - printf((codec->capabilities & AV_CODEC_CAP_SLICE_THREADS) ? "S" : "."); - printf((codec->capabilities & AV_CODEC_CAP_EXPERIMENTAL) ? "X" : "."); - printf((codec->capabilities & AV_CODEC_CAP_DRAW_HORIZ_BAND)?"B" : "."); - printf((codec->capabilities & AV_CODEC_CAP_DR1) ? "D" : "."); - - printf(" %-20s %s", codec->name, codec->long_name ? codec->long_name : ""); - if (strcmp(codec->name, desc->name)) - printf(" (codec %s)", desc->name); - - printf("\n"); - } - } - av_free(codecs); -} - -int show_decoders(void *optctx, const char *opt, const char *arg) -{ - print_codecs(0); - return 0; -} - -int show_encoders(void *optctx, const char *opt, const char *arg) -{ - print_codecs(1); - return 0; -} - -int show_bsfs(void *optctx, const char *opt, const char *arg) -{ - const AVBitStreamFilter *bsf = NULL; - void *opaque = NULL; - - printf("Bitstream filters:\n"); - while ((bsf = av_bsf_iterate(&opaque))) - printf("%s\n", bsf->name); - printf("\n"); - return 0; -} - -int show_protocols(void *optctx, const char *opt, const char *arg) -{ - void *opaque = NULL; - const char *name; - - printf("Supported file protocols:\n" - "Input:\n"); - while ((name = avio_enum_protocols(&opaque, 0))) - printf(" %s\n", name); - printf("Output:\n"); - while ((name = avio_enum_protocols(&opaque, 1))) - printf(" %s\n", name); - return 0; -} - -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; - - printf("Filters:\n" - " T.. = Timeline support\n" - " .S. = Slice threading\n" - " ..C = Command support\n" - " A = Audio input/output\n" - " V = Video input/output\n" - " N = Dynamic number and/or type of input/output\n" - " | = Source or sink filter\n"); - while ((filter = av_filter_iterate(&opaque))) { - descr_cur = descr; - for (i = 0; i < 2; i++) { - unsigned nb_pads; - if (i) { - *(descr_cur++) = '-'; - *(descr_cur++) = '>'; - } - pad = i ? filter->outputs : filter->inputs; - nb_pads = avfilter_filter_pad_count(filter, i); - for (j = 0; j < nb_pads; j++) { - if (descr_cur >= descr + sizeof(descr) - 4) - break; - *(descr_cur++) = get_media_type_char(avfilter_pad_get_type(pad, j)); - } - if (!j) - *(descr_cur++) = ((!i && (filter->flags & AVFILTER_FLAG_DYNAMIC_INPUTS)) || - ( i && (filter->flags & AVFILTER_FLAG_DYNAMIC_OUTPUTS))) ? 'N' : '|'; - } - *descr_cur = 0; - printf(" %c%c%c %-17s %-10s %s\n", - filter->flags & AVFILTER_FLAG_SUPPORT_TIMELINE ? 'T' : '.', - filter->flags & AVFILTER_FLAG_SLICE_THREADS ? 'S' : '.', - filter->process_command ? 'C' : '.', - filter->name, descr, filter->description); - } -#else - printf("No filters available: libavfilter disabled\n"); -#endif - return 0; -} - -int show_colors(void *optctx, const char *opt, const char *arg) -{ - const char *name; - const uint8_t *rgb; - int i; - - printf("%-32s #RRGGBB\n", "name"); - - for (i = 0; name = av_get_known_color_name(i, &rgb); i++) - printf("%-32s #%02x%02x%02x\n", name, rgb[0], rgb[1], rgb[2]); - - return 0; -} - -int show_pix_fmts(void *optctx, const char *opt, const char *arg) -{ - const AVPixFmtDescriptor *pix_desc = NULL; - - printf("Pixel formats:\n" - "I.... = Supported Input format for conversion\n" - ".O... = Supported Output format for conversion\n" - "..H.. = Hardware accelerated format\n" - "...P. = Paletted format\n" - "....B = Bitstream format\n" - "FLAGS NAME NB_COMPONENTS BITS_PER_PIXEL BIT_DEPTHS\n" - "-----\n"); - -#if !CONFIG_SWSCALE -# define sws_isSupportedInput(x) 0 -# define sws_isSupportedOutput(x) 0 -#endif - - while ((pix_desc = av_pix_fmt_desc_next(pix_desc))) { - enum AVPixelFormat av_unused pix_fmt = av_pix_fmt_desc_get_id(pix_desc); - printf("%c%c%c%c%c %-16s %d %3d %d", - sws_isSupportedInput (pix_fmt) ? 'I' : '.', - sws_isSupportedOutput(pix_fmt) ? 'O' : '.', - pix_desc->flags & AV_PIX_FMT_FLAG_HWACCEL ? 'H' : '.', - pix_desc->flags & AV_PIX_FMT_FLAG_PAL ? 'P' : '.', - pix_desc->flags & AV_PIX_FMT_FLAG_BITSTREAM ? 'B' : '.', - pix_desc->name, - pix_desc->nb_components, - av_get_bits_per_pixel(pix_desc), - pix_desc->comp[0].depth); - - for (unsigned i = 1; i < pix_desc->nb_components; i++) - printf("-%d", pix_desc->comp[i].depth); - printf("\n"); - } - return 0; -} - -int show_layouts(void *optctx, const char *opt, const char *arg) -{ - int i = 0; - uint64_t layout, j; - const char *name, *descr; - - printf("Individual channels:\n" - "NAME DESCRIPTION\n"); - for (i = 0; i < 63; i++) { - name = av_get_channel_name((uint64_t)1 << i); - if (!name) - continue; - descr = av_get_channel_description((uint64_t)1 << i); - printf("%-14s %s\n", name, descr); - } - printf("\nStandard channel layouts:\n" - "NAME DECOMPOSITION\n"); - for (i = 0; !av_get_standard_channel_layout(i, &layout, &name); i++) { - if (name) { - printf("%-14s ", name); - for (j = 1; j; j <<= 1) - if ((layout & j)) - printf("%s%s", (layout & (j - 1)) ? "+" : "", av_get_channel_name(j)); - printf("\n"); - } - } - return 0; -} - -int show_sample_fmts(void *optctx, const char *opt, const char *arg) -{ - int i; - char fmt_str[128]; - for (i = -1; i < AV_SAMPLE_FMT_NB; i++) - printf("%s\n", av_get_sample_fmt_string(fmt_str, sizeof(fmt_str), i)); - return 0; -} - -int show_dispositions(void *optctx, const char *opt, const char *arg) -{ - for (int i = 0; i < 32; i++) { - const char *str = av_disposition_to_string(1U << i); - if (str) - printf("%s\n", str); - } - return 0; -} - -static void show_help_codec(const char *name, int encoder) -{ - const AVCodecDescriptor *desc; - const AVCodec *codec; - - if (!name) { - av_log(NULL, AV_LOG_ERROR, "No codec name specified.\n"); - return; - } - - codec = encoder ? avcodec_find_encoder_by_name(name) : - avcodec_find_decoder_by_name(name); - - if (codec) - print_codec(codec); - else if ((desc = avcodec_descriptor_get_by_name(name))) { - void *iter = NULL; - int printed = 0; - - while ((codec = next_codec_for_id(desc->id, &iter, encoder))) { - printed = 1; - print_codec(codec); - } - - if (!printed) { - av_log(NULL, AV_LOG_ERROR, "Codec '%s' is known to FFmpeg, " - "but no %s for it are available. FFmpeg might need to be " - "recompiled with additional external libraries.\n", - name, encoder ? "encoders" : "decoders"); - } - } else { - av_log(NULL, AV_LOG_ERROR, "Codec '%s' is not recognized by FFmpeg.\n", - name); - } -} - -static void show_help_demuxer(const char *name) -{ - const AVInputFormat *fmt = av_find_input_format(name); - - if (!fmt) { - av_log(NULL, AV_LOG_ERROR, "Unknown format '%s'.\n", name); - return; - } - - printf("Demuxer %s [%s]:\n", fmt->name, fmt->long_name); - - if (fmt->extensions) - printf(" Common extensions: %s.\n", fmt->extensions); - - if (fmt->priv_class) - show_help_children(fmt->priv_class, AV_OPT_FLAG_DECODING_PARAM); -} - -static void show_help_protocol(const char *name) -{ - const AVClass *proto_class; - - if (!name) { - av_log(NULL, AV_LOG_ERROR, "No protocol name specified.\n"); - return; - } - - proto_class = avio_protocol_get_class(name); - if (!proto_class) { - av_log(NULL, AV_LOG_ERROR, "Unknown protocol '%s'.\n", name); - return; - } - - show_help_children(proto_class, AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_ENCODING_PARAM); -} - -static void show_help_muxer(const char *name) -{ - const AVCodecDescriptor *desc; - const AVOutputFormat *fmt = av_guess_format(name, NULL, NULL); - - if (!fmt) { - av_log(NULL, AV_LOG_ERROR, "Unknown format '%s'.\n", name); - return; - } - - printf("Muxer %s [%s]:\n", fmt->name, fmt->long_name); - - if (fmt->extensions) - printf(" Common extensions: %s.\n", fmt->extensions); - if (fmt->mime_type) - printf(" Mime type: %s.\n", fmt->mime_type); - if (fmt->video_codec != AV_CODEC_ID_NONE && - (desc = avcodec_descriptor_get(fmt->video_codec))) { - printf(" Default video codec: %s.\n", desc->name); - } - if (fmt->audio_codec != AV_CODEC_ID_NONE && - (desc = avcodec_descriptor_get(fmt->audio_codec))) { - printf(" Default audio codec: %s.\n", desc->name); - } - if (fmt->subtitle_codec != AV_CODEC_ID_NONE && - (desc = avcodec_descriptor_get(fmt->subtitle_codec))) { - printf(" Default subtitle codec: %s.\n", desc->name); - } - - if (fmt->priv_class) - show_help_children(fmt->priv_class, AV_OPT_FLAG_ENCODING_PARAM); -} - -#if CONFIG_AVFILTER -static void show_help_filter(const char *name) -{ -#if CONFIG_AVFILTER - const AVFilter *f = avfilter_get_by_name(name); - int i, count; - - if (!name) { - av_log(NULL, AV_LOG_ERROR, "No filter name specified.\n"); - return; - } else if (!f) { - av_log(NULL, AV_LOG_ERROR, "Unknown filter '%s'.\n", name); - return; - } - - printf("Filter %s\n", f->name); - if (f->description) - printf(" %s\n", f->description); - - if (f->flags & AVFILTER_FLAG_SLICE_THREADS) - printf(" slice threading supported\n"); - - printf(" Inputs:\n"); - count = avfilter_filter_pad_count(f, 0); - for (i = 0; i < count; i++) { - printf(" #%d: %s (%s)\n", i, avfilter_pad_get_name(f->inputs, i), - media_type_string(avfilter_pad_get_type(f->inputs, i))); - } - if (f->flags & AVFILTER_FLAG_DYNAMIC_INPUTS) - printf(" dynamic (depending on the options)\n"); - else if (!count) - printf(" none (source filter)\n"); - - printf(" Outputs:\n"); - count = avfilter_filter_pad_count(f, 1); - for (i = 0; i < count; i++) { - printf(" #%d: %s (%s)\n", i, avfilter_pad_get_name(f->outputs, i), - media_type_string(avfilter_pad_get_type(f->outputs, i))); - } - if (f->flags & AVFILTER_FLAG_DYNAMIC_OUTPUTS) - printf(" dynamic (depending on the options)\n"); - else if (!count) - printf(" none (sink filter)\n"); - - if (f->priv_class) - show_help_children(f->priv_class, AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM | - AV_OPT_FLAG_AUDIO_PARAM); - if (f->flags & AVFILTER_FLAG_SUPPORT_TIMELINE) - printf("This filter has support for timeline through the 'enable' option.\n"); -#else - av_log(NULL, AV_LOG_ERROR, "Build without libavfilter; " - "can not to satisfy request\n"); -#endif -} -#endif - -static void show_help_bsf(const char *name) -{ - const AVBitStreamFilter *bsf = av_bsf_get_by_name(name); - - if (!name) { - av_log(NULL, AV_LOG_ERROR, "No bitstream filter name specified.\n"); - return; - } else if (!bsf) { - av_log(NULL, AV_LOG_ERROR, "Unknown bit stream filter '%s'.\n", name); - return; - } - - 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); -} - -int show_help(void *optctx, const char *opt, const char *arg) -{ - char *topic, *par; - av_log_set_callback(log_callback_help); - - topic = av_strdup(arg ? arg : ""); - if (!topic) - return AVERROR(ENOMEM); - par = strchr(topic, '='); - if (par) - *par++ = 0; - - if (!*topic) { - show_help_default(topic, par); - } else if (!strcmp(topic, "decoder")) { - show_help_codec(par, 0); - } else if (!strcmp(topic, "encoder")) { - show_help_codec(par, 1); - } else if (!strcmp(topic, "demuxer")) { - show_help_demuxer(par); - } else if (!strcmp(topic, "muxer")) { - show_help_muxer(par); - } else if (!strcmp(topic, "protocol")) { - show_help_protocol(par); -#if CONFIG_AVFILTER - } 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); - } - - av_freep(&topic); - return 0; -} - int read_yesno(void) { int c = getchar(); @@ -2065,28 +817,45 @@ FILE *get_preset_file(char *filename, size_t filename_size, { FILE *f = NULL; int i; - const char *base[3] = { getenv("FFMPEG_DATADIR"), - getenv("HOME"), +#if HAVE_GETMODULEHANDLE && defined(_WIN32) + char *datadir = NULL; +#endif + char *env_home = getenv_utf8("HOME"); + char *env_ffmpeg_datadir = getenv_utf8("FFMPEG_DATADIR"); + const char *base[3] = { env_ffmpeg_datadir, + env_home, /* index=1(HOME) is special: search in a .ffmpeg subfolder */ FFMPEG_DATADIR, }; if (is_path) { av_strlcpy(filename, preset_name, filename_size); - f = fopen(filename, "r"); + f = fopen_utf8(filename, "r"); } else { #if HAVE_GETMODULEHANDLE && defined(_WIN32) - char datadir[MAX_PATH], *ls; + wchar_t *datadir_w = get_module_filename(NULL); base[2] = NULL; - if (GetModuleFileNameA(GetModuleHandleA(NULL), datadir, sizeof(datadir) - 1)) + if (wchartoutf8(datadir_w, &datadir)) + datadir = NULL; + av_free(datadir_w); + + if (datadir) { - for (ls = datadir; ls < datadir + strlen(datadir); ls++) + char *ls; + for (ls = datadir; *ls; ls++) if (*ls == '\\') *ls = '/'; if (ls = strrchr(datadir, '/')) { - *ls = 0; - strncat(datadir, "/ffpresets", sizeof(datadir) - 1 - strlen(datadir)); - base[2] = datadir; + ptrdiff_t datadir_len = ls - datadir; + size_t desired_size = datadir_len + strlen("/ffpresets") + 1; + char *new_datadir = av_realloc_array( + datadir, desired_size, sizeof *datadir); + if (new_datadir) { + datadir = new_datadir; + datadir[datadir_len] = 0; + strncat(datadir, "/ffpresets", desired_size - 1 - datadir_len); + base[2] = datadir; + } } } #endif @@ -2095,17 +864,22 @@ FILE *get_preset_file(char *filename, size_t filename_size, continue; snprintf(filename, filename_size, "%s%s/%s.ffpreset", base[i], i != 1 ? "" : "/.ffmpeg", preset_name); - f = fopen(filename, "r"); + f = fopen_utf8(filename, "r"); if (!f && codec_name) { snprintf(filename, filename_size, "%s%s/%s-%s.ffpreset", base[i], i != 1 ? "" : "/.ffmpeg", codec_name, preset_name); - f = fopen(filename, "r"); + f = fopen_utf8(filename, "r"); } } } +#if HAVE_GETMODULEHANDLE && defined(_WIN32) + av_free(datadir); +#endif + freeenv_utf8(env_ffmpeg_datadir); + freeenv_utf8(env_home); return f; } @@ -2242,164 +1016,3 @@ double get_rotation(int32_t *displaymatrix) return theta; } - -#if CONFIG_AVDEVICE -static void print_device_list(const AVDeviceInfoList *device_list) -{ - // print devices - for (int i = 0; i < device_list->nb_devices; i++) { - const AVDeviceInfo *device = device_list->devices[i]; - printf("%c %s [%s] (", device_list->default_device == i ? '*' : ' ', - device->device_name, device->device_description); - if (device->nb_media_types > 0) { - for (int j = 0; j < device->nb_media_types; ++j) { - const char* media_type = av_get_media_type_string(device->media_types[j]); - if (j > 0) - printf(", "); - printf("%s", media_type ? media_type : "unknown"); - } - } else { - printf("none"); - } - printf(")\n"); - } -} -static int print_device_sources(const AVInputFormat *fmt, AVDictionary *opts) -{ - int ret; - AVDeviceInfoList *device_list = NULL; - - if (!fmt || !fmt->priv_class || !AV_IS_INPUT_DEVICE(fmt->priv_class->category)) - return AVERROR(EINVAL); - - printf("Auto-detected sources for %s:\n", fmt->name); - if ((ret = avdevice_list_input_sources(fmt, NULL, opts, &device_list)) < 0) { - printf("Cannot list sources: %s\n", av_err2str(ret)); - goto fail; - } - - print_device_list(device_list); - - fail: - avdevice_free_list_devices(&device_list); - return ret; -} - -static int print_device_sinks(const AVOutputFormat *fmt, AVDictionary *opts) -{ - int ret; - AVDeviceInfoList *device_list = NULL; - - if (!fmt || !fmt->priv_class || !AV_IS_OUTPUT_DEVICE(fmt->priv_class->category)) - return AVERROR(EINVAL); - - printf("Auto-detected sinks for %s:\n", fmt->name); - if ((ret = avdevice_list_output_sinks(fmt, NULL, opts, &device_list)) < 0) { - printf("Cannot list sinks: %s\n", av_err2str(ret)); - goto fail; - } - - print_device_list(device_list); - - fail: - avdevice_free_list_devices(&device_list); - return ret; -} - -static int show_sinks_sources_parse_arg(const char *arg, char **dev, AVDictionary **opts) -{ - int ret; - if (arg) { - char *opts_str = NULL; - av_assert0(dev && opts); - *dev = av_strdup(arg); - if (!*dev) - return AVERROR(ENOMEM); - if ((opts_str = strchr(*dev, ','))) { - *(opts_str++) = '\0'; - if (opts_str[0] && ((ret = av_dict_parse_string(opts, opts_str, "=", ":", 0)) < 0)) { - av_freep(dev); - return ret; - } - } - } else - printf("\nDevice name is not provided.\n" - "You can pass devicename[,opt1=val1[,opt2=val2...]] as an argument.\n\n"); - return 0; -} - -int show_sources(void *optctx, const char *opt, const char *arg) -{ - const AVInputFormat *fmt = NULL; - char *dev = NULL; - AVDictionary *opts = NULL; - int ret = 0; - int error_level = av_log_get_level(); - - av_log_set_level(AV_LOG_WARNING); - - 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); - fail: - av_dict_free(&opts); - av_free(dev); - av_log_set_level(error_level); - return ret; -} - -int show_sinks(void *optctx, const char *opt, const char *arg) -{ - const AVOutputFormat *fmt = NULL; - char *dev = NULL; - AVDictionary *opts = NULL; - int ret = 0; - int error_level = av_log_get_level(); - - av_log_set_level(AV_LOG_WARNING); - - 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); - fail: - av_dict_free(&opts); - av_free(dev); - av_log_set_level(error_level); - return ret; -} - -#endif diff --git a/fftools/cmdutils.h b/fftools/cmdutils.h index 50eed9b13..d87e162cc 100644 --- a/fftools/cmdutils.h +++ b/fftools/cmdutils.h @@ -44,8 +44,6 @@ extern const char program_name[]; */ extern const int program_birth_year; -extern AVCodecContext *avcodec_opts[AVMEDIA_TYPE_NB]; -extern AVFormatContext *avformat_opts; extern AVDictionary *sws_dict; extern AVDictionary *swr_opts; extern AVDictionary *format_opts, *codec_opts; @@ -66,11 +64,6 @@ void exit_program(int ret) av_noreturn; */ void init_dynload(void); -/** - * Initialize the cmdutils option system, in particular - * allocate the *_opts contexts. - */ -void init_opts(void); /** * Uninitialize the cmdutils option system, in particular * free the *_opts contexts and their contents. @@ -83,33 +76,12 @@ void uninit_opts(void); */ void log_callback_help(void* ptr, int level, const char* fmt, va_list vl); -/** - * Override the cpuflags. - */ -int opt_cpuflags(void *optctx, const char *opt, const char *arg); - -/** - * Override the cpucount. - */ -int opt_cpucount(void *optctx, const char *opt, const char *arg); - /** * Fallback for options that are not explicitly handled, these will be * parsed through AVOptions. */ int opt_default(void *optctx, const char *opt, const char *arg); -/** - * Set the libav* libraries log level. - */ -int opt_loglevel(void *optctx, const char *opt, const char *arg); - -int opt_report(void *optctx, const char *opt, const char *arg); - -int opt_max_alloc(void *optctx, const char *opt, const char *arg); - -int opt_codec_debug(void *optctx, const char *opt, const char *arg); - /** * Limit the execution time. */ @@ -206,49 +178,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_AVDEVICE -#define CMDUTILS_COMMON_OPTIONS_AVDEVICE \ - { "sources" , OPT_EXIT | HAS_ARG, { .func_arg = show_sources }, \ - "list sources of the input device", "device" }, \ - { "sinks" , OPT_EXIT | HAS_ARG, { .func_arg = show_sinks }, \ - "list sinks of the output device", "device" }, \ - -#else -#define CMDUTILS_COMMON_OPTIONS_AVDEVICE -#endif - -#define CMDUTILS_COMMON_OPTIONS \ - { "L", OPT_EXIT, { .func_arg = show_license }, "show license" }, \ - { "h", OPT_EXIT, { .func_arg = show_help }, "show help", "topic" }, \ - { "?", OPT_EXIT, { .func_arg = show_help }, "show help", "topic" }, \ - { "help", OPT_EXIT, { .func_arg = show_help }, "show help", "topic" }, \ - { "-help", OPT_EXIT, { .func_arg = show_help }, "show help", "topic" }, \ - { "version", OPT_EXIT, { .func_arg = show_version }, "show version" }, \ - { "buildconf", OPT_EXIT, { .func_arg = show_buildconf }, "show build configuration" }, \ - { "formats", OPT_EXIT, { .func_arg = show_formats }, "show available formats" }, \ - { "muxers", OPT_EXIT, { .func_arg = show_muxers }, "show available muxers" }, \ - { "demuxers", OPT_EXIT, { .func_arg = show_demuxers }, "show available demuxers" }, \ - { "devices", OPT_EXIT, { .func_arg = show_devices }, "show available devices" }, \ - { "codecs", OPT_EXIT, { .func_arg = show_codecs }, "show available codecs" }, \ - { "decoders", OPT_EXIT, { .func_arg = show_decoders }, "show available decoders" }, \ - { "encoders", OPT_EXIT, { .func_arg = show_encoders }, "show available encoders" }, \ - { "bsfs", OPT_EXIT, { .func_arg = show_bsfs }, "show available bit stream filters" }, \ - { "protocols", OPT_EXIT, { .func_arg = show_protocols }, "show available protocols" }, \ - { "filters", OPT_EXIT, { .func_arg = show_filters }, "show available filters" }, \ - { "pix_fmts", OPT_EXIT, { .func_arg = show_pix_fmts }, "show available pixel formats" }, \ - { "layouts", OPT_EXIT, { .func_arg = show_layouts }, "show standard channel layouts" }, \ - { "sample_fmts", OPT_EXIT, { .func_arg = show_sample_fmts }, "show available audio sample formats" }, \ - { "dispositions", OPT_EXIT, { .func_arg = show_dispositions}, "show available stream dispositions" }, \ - { "colors", OPT_EXIT, { .func_arg = show_colors }, "show available color names" }, \ - { "loglevel", HAS_ARG, { .func_arg = opt_loglevel }, "set logging level", "loglevel" }, \ - { "v", HAS_ARG, { .func_arg = opt_loglevel }, "set logging level", "loglevel" }, \ - { "report", 0, { .func_arg = opt_report }, "generate a report" }, \ - { "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" }, \ - { "cpucount", HAS_ARG | OPT_EXPERT, { .func_arg = opt_cpucount }, "force specific cpu count", "count" }, \ - { "hide_banner", OPT_BOOL | OPT_EXPERT, {&hide_banner}, "do not show program banner", "hide_banner" }, \ - CMDUTILS_COMMON_OPTIONS_AVDEVICE \ - /** * Show help for all options with given flags in class and all its * children. @@ -261,11 +190,6 @@ void show_help_children(const AVClass *class, int flags); */ void show_help_default(const char *opt, const char *arg); -/** - * Generic -h handler common to all fftools. - */ -int show_help(void *optctx, const char *opt, const char *arg); - /** * Parse the command line arguments. * @@ -454,141 +378,6 @@ void print_error(const char *filename, int err); */ void show_banner(int argc, char **argv, const OptionDef *options); -/** - * Print the version of the program to stdout. The version message - * depends on the current versions of the repository and of the libav* - * libraries. - * This option processing function does not utilize the arguments. - */ -int show_version(void *optctx, const char *opt, const char *arg); - -/** - * Print the build configuration of the program to stdout. The contents - * depend on the definition of FFMPEG_CONFIGURATION. - * This option processing function does not utilize the arguments. - */ -int show_buildconf(void *optctx, const char *opt, const char *arg); - -/** - * Print the license of the program to stdout. The license depends on - * the license of the libraries compiled into the program. - * This option processing function does not utilize the arguments. - */ -int show_license(void *optctx, const char *opt, const char *arg); - -/** - * Print a listing containing all the formats supported by the - * program (including devices). - * This option processing function does not utilize the arguments. - */ -int show_formats(void *optctx, const char *opt, const char *arg); - -/** - * Print a listing containing all the muxers supported by the - * program (including devices). - * This option processing function does not utilize the arguments. - */ -int show_muxers(void *optctx, const char *opt, const char *arg); - -/** - * Print a listing containing all the demuxer supported by the - * program (including devices). - * This option processing function does not utilize the arguments. - */ -int show_demuxers(void *optctx, const char *opt, const char *arg); - -/** - * Print a listing containing all the devices supported by the - * program. - * This option processing function does not utilize the arguments. - */ -int show_devices(void *optctx, const char *opt, const char *arg); - -#if CONFIG_AVDEVICE -/** - * Print a listing containing autodetected sinks of the output device. - * Device name with options may be passed as an argument to limit results. - */ -int show_sinks(void *optctx, const char *opt, const char *arg); - -/** - * Print a listing containing autodetected sources of the input device. - * Device name with options may be passed as an argument to limit results. - */ -int show_sources(void *optctx, const char *opt, const char *arg); -#endif - -/** - * Print a listing containing all the codecs supported by the - * program. - * This option processing function does not utilize the arguments. - */ -int show_codecs(void *optctx, const char *opt, const char *arg); - -/** - * Print a listing containing all the decoders supported by the - * program. - */ -int show_decoders(void *optctx, const char *opt, const char *arg); - -/** - * Print a listing containing all the encoders supported by the - * program. - */ -int show_encoders(void *optctx, const char *opt, const char *arg); - -/** - * Print a listing containing all the filters supported by the - * program. - * This option processing function does not utilize the arguments. - */ -int show_filters(void *optctx, const char *opt, const char *arg); - -/** - * Print a listing containing all the bit stream filters supported by the - * program. - * This option processing function does not utilize the arguments. - */ -int show_bsfs(void *optctx, const char *opt, const char *arg); - -/** - * Print a listing containing all the protocols supported by the - * program. - * This option processing function does not utilize the arguments. - */ -int show_protocols(void *optctx, const char *opt, const char *arg); - -/** - * Print a listing containing all the pixel formats supported by the - * program. - * This option processing function does not utilize the arguments. - */ -int show_pix_fmts(void *optctx, const char *opt, const char *arg); - -/** - * Print a listing containing all the standard channel layouts supported by - * the program. - * This option processing function does not utilize the arguments. - */ -int show_layouts(void *optctx, const char *opt, const char *arg); - -/** - * Print a listing containing all the sample formats supported by the - * program. - */ -int show_sample_fmts(void *optctx, const char *opt, const char *arg); - -/** - * Print a listing containing all supported stream dispositions. - */ -int show_dispositions(void *optctx, const char *opt, const char *arg); - -/** - * Print a listing containing all the color names and values recognized - * by the program. - */ -int show_colors(void *optctx, const char *opt, const char *arg); - /** * Return a positive value if a line read from standard input * starts with [yY], otherwise return 0. @@ -642,8 +431,6 @@ void *grow_array(void *array, int elem_size, int *size, int new_size); */ void *allocate_array_elem(void *array, size_t elem_size, int *nb_elems); -#define media_type_string av_get_media_type_string - #define GROW_ARRAY(array, nb_elems)\ array = grow_array(array, sizeof(*array), &nb_elems, nb_elems + 1) @@ -663,14 +450,6 @@ void *allocate_array_elem(void *array, size_t elem_size, int *nb_elems); char name[16];\ snprintf(name, sizeof(name), "%d", rate); -#define GET_CH_LAYOUT_NAME(ch_layout)\ - char name[16];\ - snprintf(name, sizeof(name), "0x%"PRIx64, ch_layout); - -#define GET_CH_LAYOUT_DESC(ch_layout)\ - char name[128];\ - av_get_channel_layout_string(name, sizeof(name), 0, ch_layout); - double get_rotation(int32_t *displaymatrix); #endif /* FFTOOLS_CMDUTILS_H */ diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index bdeff9a12..e7384f052 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -64,6 +64,7 @@ #include "libavutil/thread.h" #include "libavutil/threadmessage.h" #include "libavcodec/mathops.h" +#include "libavcodec/version.h" #include "libavformat/os_support.h" # include "libavfilter/avfilter.h" @@ -126,19 +127,17 @@ typedef struct BenchmarkTimeStamps { int64_t sys_usec; } BenchmarkTimeStamps; -static void do_video_stats(OutputStream *ost, int frame_size); static BenchmarkTimeStamps get_benchmark_time_stamps(void); static int64_t getmaxrss(void); static int ifilter_has_all_input_formats(FilterGraph *fg); -static int run_as_daemon = 0; -static int nb_frames_dup = 0; -static unsigned dup_warning = 1000; -static int nb_frames_drop = 0; +static int64_t nb_frames_dup = 0; +static uint64_t dup_warning = 1000; +static int64_t nb_frames_drop = 0; static int64_t decode_error_stat[2]; -static unsigned nb_output_dumped = 0; +unsigned nb_output_dumped = 0; -static int want_sdp = 1; +int want_sdp = 1; static BenchmarkTimeStamps current_time; AVIOContext *progress_avio = NULL; @@ -344,7 +343,7 @@ static volatile int received_sigterm = 0; static volatile int received_nb_signals = 0; static atomic_int transcode_init_done = ATOMIC_VAR_INIT(0); static volatile int ffmpeg_exited = 0; -static int main_return_code = 0; +int main_return_code = 0; static int64_t copy_ts_first_pts = AV_NOPTS_VALUE; static void @@ -419,7 +418,7 @@ void term_init(void) #endif #if HAVE_TERMIOS_H - if (!run_as_daemon && stdin_interaction) { + if (stdin_interaction) { struct termios tty; if (tcgetattr (0, &tty) == 0) { oldtty = tty; @@ -528,22 +527,18 @@ static void ffmpeg_cleanup(int ret) InputFilter *ifilter = fg->inputs[j]; struct InputStream *ist = ifilter->ist; - while (av_fifo_size(ifilter->frame_queue)) { + if (ifilter->frame_queue) { AVFrame *frame; - av_fifo_generic_read(ifilter->frame_queue, &frame, - sizeof(frame), NULL); - av_frame_free(&frame); + while (av_fifo_read(ifilter->frame_queue, &frame, 1) >= 0) + av_frame_free(&frame); + av_fifo_freep2(&ifilter->frame_queue); } - av_fifo_freep(&ifilter->frame_queue); av_freep(&ifilter->displaymatrix); if (ist->sub2video.sub_queue) { - while (av_fifo_size(ist->sub2video.sub_queue)) { - AVSubtitle sub; - av_fifo_generic_read(ist->sub2video.sub_queue, - &sub, sizeof(sub), NULL); + AVSubtitle sub; + while (av_fifo_read(ist->sub2video.sub_queue, &sub, 1) >= 0) avsubtitle_free(&sub); - } - av_fifo_freep(&ist->sub2video.sub_queue); + av_fifo_freep2(&ist->sub2video.sub_queue); } av_buffer_unref(&ifilter->hw_frames_ctx); av_freep(&ifilter->name); @@ -555,6 +550,7 @@ static void ffmpeg_cleanup(int ret) avfilter_inout_free(&ofilter->out_tmp); av_freep(&ofilter->name); + av_channel_layout_uninit(&ofilter->ch_layout); av_freep(&fg->outputs[j]); } av_freep(&fg->outputs); @@ -567,19 +563,9 @@ static void ffmpeg_cleanup(int ret) av_freep(&subtitle_out); /* close files */ - for (i = 0; i < nb_output_files; i++) { - OutputFile *of = output_files[i]; - AVFormatContext *s; - if (!of) - continue; - s = of->ctx; - if (s && s->oformat && !(s->oformat->flags & AVFMT_NOFILE)) - avio_closep(&s->pb); - avformat_free_context(s); - av_dict_free(&of->opts); + for (i = 0; i < nb_output_files; i++) + of_close(&output_files[i]); - av_freep(&output_files[i]); - } for (i = 0; i < nb_output_streams; i++) { OutputStream *ost = output_streams[i]; @@ -608,12 +594,10 @@ static void ffmpeg_cleanup(int ret) avcodec_parameters_free(&ost->ref_par); if (ost->muxing_queue) { - while (av_fifo_size(ost->muxing_queue)) { - AVPacket *pkt; - av_fifo_generic_read(ost->muxing_queue, &pkt, sizeof(pkt), NULL); + AVPacket *pkt; + while (av_fifo_read(ost->muxing_queue, &pkt, 1) >= 0) av_packet_free(&pkt); - } - av_fifo_freep(&ost->muxing_queue); + av_fifo_freep2(&ost->muxing_queue); } av_freep(&output_streams[i]); @@ -715,159 +699,6 @@ static void update_benchmark(const char *fmt, ...) } } -static void close_all_output_streams(OutputStream *ost, OSTFinished this_stream, OSTFinished others) -{ - int i; - for (i = 0; i < nb_output_streams; i++) { - OutputStream *ost2 = output_streams[i]; - ost2->finished |= ost == ost2 ? this_stream : others; - } -} - -static void write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int unqueue) -{ - AVFormatContext *s = of->ctx; - AVStream *st = ost->st; - int ret; - - /* - * Audio encoders may split the packets -- #frames in != #packets out. - * But there is no reordering, so we can limit the number of output packets - * by simply dropping them here. - * Counting encoded video frames needs to be done separately because of - * reordering, see do_video_out(). - * Do not count the packet when unqueued because it has been counted when queued. - */ - if (!(st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && ost->encoding_needed) && !unqueue) { - if (ost->frame_number >= ost->max_frames) { - av_packet_unref(pkt); - return; - } - ost->frame_number++; - } - - if (!of->header_written) { - AVPacket *tmp_pkt; - /* the muxer is not initialized yet, buffer the packet */ - if (!av_fifo_space(ost->muxing_queue)) { - size_t cur_size = av_fifo_size(ost->muxing_queue); - unsigned int are_we_over_size = - (ost->muxing_queue_data_size + pkt->size) > ost->muxing_queue_data_threshold; - size_t limit = are_we_over_size ? ost->max_muxing_queue_size : INT_MAX; - size_t new_size = FFMIN(2 * cur_size, limit); - - if (new_size <= cur_size) { - av_log(NULL, AV_LOG_ERROR, - "Too many packets buffered for output stream %d:%d.\n", - ost->file_index, ost->st->index); - exit_program(1); - } - ret = av_fifo_realloc2(ost->muxing_queue, new_size); - if (ret < 0) - exit_program(1); - } - ret = av_packet_make_refcounted(pkt); - if (ret < 0) - exit_program(1); - tmp_pkt = av_packet_alloc(); - if (!tmp_pkt) - exit_program(1); - av_packet_move_ref(tmp_pkt, pkt); - ost->muxing_queue_data_size += tmp_pkt->size; - av_fifo_generic_write(ost->muxing_queue, &tmp_pkt, sizeof(tmp_pkt), NULL); - return; - } - - if ((st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && video_sync_method == VSYNC_DROP) || - (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && audio_sync_method < 0)) - pkt->pts = pkt->dts = AV_NOPTS_VALUE; - - if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { - int i; - uint8_t *sd = av_packet_get_side_data(pkt, AV_PKT_DATA_QUALITY_STATS, - NULL); - ost->quality = sd ? AV_RL32(sd) : -1; - ost->pict_type = sd ? sd[4] : AV_PICTURE_TYPE_NONE; - - for (i = 0; ierror); i++) { - if (sd && i < sd[5]) - ost->error[i] = AV_RL64(sd + 8 + 8*i); - else - ost->error[i] = -1; - } - - if (ost->frame_rate.num && ost->is_cfr) { - if (pkt->duration > 0) - av_log(NULL, AV_LOG_WARNING, "Overriding packet duration by frame rate, this should not happen\n"); - pkt->duration = av_rescale_q(1, av_inv_q(ost->frame_rate), - ost->mux_timebase); - } - } - - av_packet_rescale_ts(pkt, ost->mux_timebase, ost->st->time_base); - - if (!(s->oformat->flags & AVFMT_NOTIMESTAMPS)) { - if (pkt->dts != AV_NOPTS_VALUE && - pkt->pts != AV_NOPTS_VALUE && - pkt->dts > pkt->pts) { - av_log(s, AV_LOG_WARNING, "Invalid DTS: %"PRId64" PTS: %"PRId64" in output stream %d:%d, replacing by guess\n", - pkt->dts, pkt->pts, - ost->file_index, ost->st->index); - pkt->pts = - pkt->dts = pkt->pts + pkt->dts + ost->last_mux_dts + 1 - - FFMIN3(pkt->pts, pkt->dts, ost->last_mux_dts + 1) - - FFMAX3(pkt->pts, pkt->dts, ost->last_mux_dts + 1); - } - if ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) && - pkt->dts != AV_NOPTS_VALUE && - !(st->codecpar->codec_id == AV_CODEC_ID_VP9 && ost->stream_copy) && - ost->last_mux_dts != AV_NOPTS_VALUE) { - int64_t max = ost->last_mux_dts + !(s->oformat->flags & AVFMT_TS_NONSTRICT); - if (pkt->dts < max) { - int loglevel = max - pkt->dts > 2 || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ? AV_LOG_WARNING : AV_LOG_DEBUG; - if (exit_on_error) - loglevel = AV_LOG_ERROR; - av_log(s, loglevel, "Non-monotonous DTS in output stream " - "%d:%d; previous: %"PRId64", current: %"PRId64"; ", - ost->file_index, ost->st->index, ost->last_mux_dts, pkt->dts); - if (exit_on_error) { - av_log(NULL, AV_LOG_FATAL, "aborting.\n"); - exit_program(1); - } - av_log(s, loglevel, "changing to %"PRId64". This may result " - "in incorrect timestamps in the output file.\n", - max); - if (pkt->pts >= pkt->dts) - pkt->pts = FFMAX(pkt->pts, max); - pkt->dts = max; - } - } - } - ost->last_mux_dts = pkt->dts; - - ost->data_size += pkt->size; - ost->packets_written++; - - pkt->stream_index = ost->index; - - if (debug_ts) { - av_log(NULL, AV_LOG_INFO, "muxer <- type:%s " - "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s size:%d\n", - av_get_media_type_string(ost->enc_ctx->codec_type), - av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &ost->st->time_base), - av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &ost->st->time_base), - pkt->size - ); - } - - ret = av_interleaved_write_frame(s, pkt); - if (ret < 0) { - print_error("av_interleaved_write_frame()", ret); - main_return_code = 1; - close_all_output_streams(ost, MUXER_FINISHED | ENCODER_FINISHED, ENCODER_FINISHED); - } -} - static void close_output_stream(OutputStream *ost) { OutputFile *of = output_files[ost->file_index]; @@ -902,11 +733,11 @@ static void output_packet(OutputFile *of, AVPacket *pkt, if (ret < 0) goto finish; while ((ret = av_bsf_receive_packet(ost->bsf_ctx, pkt)) >= 0) - write_packet(of, pkt, ost, 0); + of_write_packet(of, pkt, ost, 0); if (ret == AVERROR(EAGAIN)) ret = 0; } else if (!eof) - write_packet(of, pkt, ost, 0); + of_write_packet(of, pkt, ost, 0); finish: if (ret < 0 && ret != AVERROR_EOF) { @@ -998,11 +829,151 @@ static int init_output_stream_wrapper(OutputStream *ost, AVFrame *frame, return ret; } +static double psnr(double d) +{ + return -10.0 * log10(d); +} + +static void update_video_stats(OutputStream *ost, const AVPacket *pkt, int write_vstats) +{ + const uint8_t *sd = av_packet_get_side_data(pkt, AV_PKT_DATA_QUALITY_STATS, + NULL); + AVCodecContext *enc = ost->enc_ctx; + int64_t frame_number; + double ti1, bitrate, avg_bitrate; + + ost->quality = sd ? AV_RL32(sd) : -1; + ost->pict_type = sd ? sd[4] : AV_PICTURE_TYPE_NONE; + + for (int i = 0; ierror); i++) { + if (sd && i < sd[5]) + ost->error[i] = AV_RL64(sd + 8 + 8*i); + else + ost->error[i] = -1; + } + + if (!write_vstats) + return; + + /* this is executed just the first time update_video_stats is called */ + if (!vstats_file) { + vstats_file = fopen(vstats_filename, "w"); + if (!vstats_file) { + perror("fopen"); + exit_program(1); + } + } + + frame_number = ost->packets_encoded; + if (vstats_version <= 1) { + fprintf(vstats_file, "frame= %5"PRId64" q= %2.1f ", frame_number, + ost->quality / (float)FF_QP2LAMBDA); + } else { + fprintf(vstats_file, "out= %2d st= %2d frame= %5"PRId64" q= %2.1f ", ost->file_index, ost->index, frame_number, + ost->quality / (float)FF_QP2LAMBDA); + } + + if (ost->error[0]>=0 && (enc->flags & AV_CODEC_FLAG_PSNR)) + fprintf(vstats_file, "PSNR= %6.2f ", psnr(ost->error[0] / (enc->width * enc->height * 255.0 * 255.0))); + + fprintf(vstats_file,"f_size= %6d ", pkt->size); + /* compute pts value */ + ti1 = pkt->dts * av_q2d(ost->mux_timebase); + if (ti1 < 0.01) + ti1 = 0.01; + + bitrate = (pkt->size * 8) / av_q2d(enc->time_base) / 1000.0; + avg_bitrate = (double)(ost->data_size * 8) / ti1 / 1000.0; + fprintf(vstats_file, "s_size= %8.0fkB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s ", + (double)ost->data_size / 1024, ti1, bitrate, avg_bitrate); + fprintf(vstats_file, "type= %c\n", av_get_picture_type_char(ost->pict_type)); +} + +static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame) +{ + AVCodecContext *enc = ost->enc_ctx; + AVPacket *pkt = ost->pkt; + const char *type_desc = av_get_media_type_string(enc->codec_type); + const char *action = frame ? "encode" : "flush"; + int ret; + + if (frame) { + ost->frames_encoded++; + + if (debug_ts) { + av_log(NULL, AV_LOG_INFO, "encoder <- type:%s " + "frame_pts:%s frame_pts_time:%s time_base:%d/%d\n", + type_desc, + av_ts2str(frame->pts), av_ts2timestr(frame->pts, &enc->time_base), + enc->time_base.num, enc->time_base.den); + } + } + + update_benchmark(NULL); + + ret = avcodec_send_frame(enc, frame); + if (ret < 0 && !(ret == AVERROR_EOF && !frame)) { + av_log(NULL, AV_LOG_ERROR, "Error submitting %s frame to the encoder\n", + type_desc); + return ret; + } + + while (1) { + ret = avcodec_receive_packet(enc, pkt); + update_benchmark("%s_%s %d.%d", action, type_desc, + ost->file_index, ost->index); + + /* if two pass, output log on success and EOF */ + if ((ret >= 0 || ret == AVERROR_EOF) && ost->logfile && enc->stats_out) + fprintf(ost->logfile, "%s", enc->stats_out); + + if (ret == AVERROR(EAGAIN)) { + av_assert0(frame); // should never happen during flushing + return 0; + } else if (ret == AVERROR_EOF) { + output_packet(of, pkt, ost, 1); + return ret; + } else if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "%s encoding failed\n", type_desc); + return ret; + } + + if (debug_ts) { + av_log(NULL, AV_LOG_INFO, "encoder -> type:%s " + "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s " + "duration:%s duration_time:%s\n", + type_desc, + av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &enc->time_base), + av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &enc->time_base), + av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &enc->time_base)); + } + + av_packet_rescale_ts(pkt, enc->time_base, ost->mux_timebase); + + if (debug_ts) { + av_log(NULL, AV_LOG_INFO, "encoder -> type:%s " + "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s " + "duration:%s duration_time:%s\n", + type_desc, + av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &enc->time_base), + av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &enc->time_base), + av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &enc->time_base)); + } + + if (enc->codec_type == AVMEDIA_TYPE_VIDEO) + update_video_stats(ost, pkt, !!vstats_filename); + + ost->packets_encoded++; + + output_packet(of, pkt, ost, 0); + } + + av_assert0(0); +} + static void do_audio_out(OutputFile *of, OutputStream *ost, AVFrame *frame) { - AVCodecContext *enc = ost->enc_ctx; - AVPacket *pkt = ost->pkt; int ret; adjust_frame_pts_to_encoder_tb(of, ost, frame); @@ -1014,45 +985,10 @@ static void do_audio_out(OutputFile *of, OutputStream *ost, frame->pts = ost->sync_opts; ost->sync_opts = frame->pts + frame->nb_samples; ost->samples_encoded += frame->nb_samples; - ost->frames_encoded++; - update_benchmark(NULL); - if (debug_ts) { - av_log(NULL, AV_LOG_INFO, "encoder <- type:audio " - "frame_pts:%s frame_pts_time:%s time_base:%d/%d\n", - av_ts2str(frame->pts), av_ts2timestr(frame->pts, &enc->time_base), - enc->time_base.num, enc->time_base.den); - } - - ret = avcodec_send_frame(enc, frame); + ret = encode_frame(of, ost, frame); if (ret < 0) - goto error; - - while (1) { - ret = avcodec_receive_packet(enc, pkt); - if (ret == AVERROR(EAGAIN)) - break; - if (ret < 0) - goto error; - - update_benchmark("encode_audio %d.%d", ost->file_index, ost->index); - - av_packet_rescale_ts(pkt, enc->time_base, ost->mux_timebase); - - if (debug_ts) { - av_log(NULL, AV_LOG_INFO, "encoder -> type:audio " - "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s\n", - av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &enc->time_base), - av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &enc->time_base)); - } - - output_packet(of, pkt, ost, 0); - } - - return; -error: - av_log(NULL, AV_LOG_FATAL, "Audio encoding failed\n"); - exit_program(1); + exit_program(1); } static void do_subtitle_out(OutputFile *of, @@ -1144,14 +1080,12 @@ static void do_video_out(OutputFile *of, AVFrame *next_picture) { int ret; - AVPacket *pkt = ost->pkt; AVCodecContext *enc = ost->enc_ctx; AVRational frame_rate; - int nb_frames, nb0_frames, i; + int64_t nb_frames, nb0_frames, i; double delta, delta0; double duration = 0; double sync_ipts = AV_NOPTS_VALUE; - int frame_size = 0; InputStream *ist = NULL; AVFilterContext *filter = ost->filter->filter; @@ -1218,7 +1152,7 @@ static void do_video_out(OutputFile *of, } else if (delta < -1.1) nb_frames = 0; else if (delta > 1.1) { - nb_frames = lrintf(delta); + nb_frames = llrintf(delta); if (delta0 > 1.1) nb0_frames = llrintf(delta0 - 0.6); } @@ -1238,6 +1172,11 @@ static void do_video_out(OutputFile *of, } } + /* + * For video, number of frames in == number of packets out. + * But there may be reordering, so we can't throw away frames on encoder + * flush, we need to limit them here, before they go into encoder. + */ nb_frames = FFMIN(nb_frames, ost->max_frames - ost->frame_number); nb0_frames = FFMIN(nb0_frames, nb_frames); @@ -1249,19 +1188,19 @@ static void do_video_out(OutputFile *of, if (nb0_frames == 0 && ost->last_dropped) { nb_frames_drop++; av_log(NULL, AV_LOG_VERBOSE, - "*** dropping frame %d from stream %d at ts %"PRId64"\n", + "*** dropping frame %"PRId64" from stream %d at ts %"PRId64"\n", ost->frame_number, ost->st->index, ost->last_frame->pts); } if (nb_frames > (nb0_frames && ost->last_dropped) + (nb_frames > nb0_frames)) { if (nb_frames > dts_error_threshold * 30) { - av_log(NULL, AV_LOG_ERROR, "%d frame duplication too large, skipping\n", nb_frames - 1); + av_log(NULL, AV_LOG_ERROR, "%"PRId64" frame duplication too large, skipping\n", nb_frames - 1); nb_frames_drop++; return; } nb_frames_dup += nb_frames - (nb0_frames && ost->last_dropped) - (nb_frames > nb0_frames); - av_log(NULL, AV_LOG_VERBOSE, "*** %d dup!\n", nb_frames - 1); + av_log(NULL, AV_LOG_VERBOSE, "*** %"PRId64" dup!\n", nb_frames - 1); if (nb_frames_dup > dup_warning) { - av_log(NULL, AV_LOG_WARNING, "More than %d frames duplicated\n", dup_warning); + av_log(NULL, AV_LOG_WARNING, "More than %"PRIu64" frames duplicated\n", dup_warning); dup_warning *= 10; } } @@ -1339,125 +1278,17 @@ static void do_video_out(OutputFile *of, av_log(NULL, AV_LOG_DEBUG, "Forced keyframe at time %f\n", pts_time); } - update_benchmark(NULL); - if (debug_ts) { - av_log(NULL, AV_LOG_INFO, "encoder <- type:video " - "frame_pts:%s frame_pts_time:%s time_base:%d/%d\n", - av_ts2str(in_picture->pts), av_ts2timestr(in_picture->pts, &enc->time_base), - enc->time_base.num, enc->time_base.den); - } - - ost->frames_encoded++; - - ret = avcodec_send_frame(enc, in_picture); + ret = encode_frame(of, ost, in_picture); if (ret < 0) - goto error; - // Make sure Closed Captions will not be duplicated - av_frame_remove_side_data(in_picture, AV_FRAME_DATA_A53_CC); + exit_program(1); - while (1) { - ret = avcodec_receive_packet(enc, pkt); - update_benchmark("encode_video %d.%d", ost->file_index, ost->index); - if (ret == AVERROR(EAGAIN)) - break; - if (ret < 0) - goto error; - - if (debug_ts) { - av_log(NULL, AV_LOG_INFO, "encoder -> type:video " - "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s\n", - av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &enc->time_base), - av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &enc->time_base)); - } - - if (pkt->pts == AV_NOPTS_VALUE && !(enc->codec->capabilities & AV_CODEC_CAP_DELAY)) - pkt->pts = ost->sync_opts; - - av_packet_rescale_ts(pkt, enc->time_base, ost->mux_timebase); - - if (debug_ts) { - av_log(NULL, AV_LOG_INFO, "encoder -> type:video " - "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s\n", - av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &ost->mux_timebase), - av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &ost->mux_timebase)); - } - - frame_size = pkt->size; - output_packet(of, pkt, ost, 0); - - /* if two pass, output log */ - if (ost->logfile && enc->stats_out) { - fprintf(ost->logfile, "%s", enc->stats_out); - } - } ost->sync_opts++; - /* - * For video, number of frames in == number of packets out. - * But there may be reordering, so we can't throw away frames on encoder - * flush, we need to limit them here, before they go into encoder. - */ ost->frame_number++; - - if (vstats_filename && frame_size) - do_video_stats(ost, frame_size); } av_frame_unref(ost->last_frame); if (next_picture) av_frame_move_ref(ost->last_frame, next_picture); - - return; -error: - av_log(NULL, AV_LOG_FATAL, "Video encoding failed\n"); - exit_program(1); -} - -static double psnr(double d) -{ - return -10.0 * log10(d); -} - -static void do_video_stats(OutputStream *ost, int frame_size) -{ - AVCodecContext *enc; - int frame_number; - double ti1, bitrate, avg_bitrate; - - /* this is executed just the first time do_video_stats is called */ - if (!vstats_file) { - vstats_file = fopen(vstats_filename, "w"); - if (!vstats_file) { - perror("fopen"); - exit_program(1); - } - } - - enc = ost->enc_ctx; - if (enc->codec_type == AVMEDIA_TYPE_VIDEO) { - frame_number = ost->st->nb_frames; - if (vstats_version <= 1) { - fprintf(vstats_file, "frame= %5d q= %2.1f ", frame_number, - ost->quality / (float)FF_QP2LAMBDA); - } else { - fprintf(vstats_file, "out= %2d st= %2d frame= %5d q= %2.1f ", ost->file_index, ost->index, frame_number, - ost->quality / (float)FF_QP2LAMBDA); - } - - if (ost->error[0]>=0 && (enc->flags & AV_CODEC_FLAG_PSNR)) - fprintf(vstats_file, "PSNR= %6.2f ", psnr(ost->error[0] / (enc->width * enc->height * 255.0 * 255.0))); - - fprintf(vstats_file,"f_size= %6d ", frame_size); - /* compute pts value */ - ti1 = av_stream_get_end_pts(ost->st) * av_q2d(ost->st->time_base); - if (ti1 < 0.01) - ti1 = 0.01; - - bitrate = (frame_size * 8) / av_q2d(enc->time_base) / 1000.0; - avg_bitrate = (double)(ost->data_size * 8) / ti1 / 1000.0; - fprintf(vstats_file, "s_size= %8.0fkB time= %0.3f br= %7.1fkbits/s avg_br= %7.1fkbits/s ", - (double)ost->data_size / 1024, ti1, bitrate, avg_bitrate); - fprintf(vstats_file, "type= %c\n", av_get_picture_type_char(ost->pict_type)); - } } static void finish_output_stream(OutputStream *ost) @@ -1537,7 +1368,7 @@ static int reap_filters(int flush) break; case AVMEDIA_TYPE_AUDIO: if (!(enc->codec->capabilities & AV_CODEC_CAP_PARAM_CHANGE) && - enc->channels != filtered_frame->channels) { + enc->ch_layout.nb_channels != filtered_frame->ch_layout.nb_channels) { av_log(NULL, AV_LOG_ERROR, "Audio filter graph output is not normalized and encoder does not support parameter changes\n"); break; @@ -1611,7 +1442,7 @@ static void print_final_stats(int64_t total_size) total_packets += ist->nb_packets; av_log(NULL, AV_LOG_VERBOSE, " Input stream #%d:%d (%s): ", - i, j, media_type_string(type)); + i, j, av_get_media_type_string(type)); av_log(NULL, AV_LOG_VERBOSE, "%"PRIu64" packets read (%"PRIu64" bytes); ", ist->nb_packets, ist->data_size); @@ -1645,7 +1476,7 @@ static void print_final_stats(int64_t total_size) total_packets += ost->packets_written; av_log(NULL, AV_LOG_VERBOSE, " Output stream #%d:%d (%s): ", - i, j, media_type_string(type)); + i, j, av_get_media_type_string(type)); if (ost->encoding_needed) { av_log(NULL, AV_LOG_VERBOSE, "%"PRIu64" frames encoded", ost->frames_encoded); @@ -1680,7 +1511,7 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti AVFormatContext *oc; int64_t total_size; AVCodecContext *enc; - int frame_number, vid, i; + int vid, i; double bitrate; double speed; int64_t pts = INT64_MIN + 1; @@ -1731,12 +1562,12 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti } if (!vid && enc->codec_type == AVMEDIA_TYPE_VIDEO) { float fps; + int64_t frame_number = ost->frame_number; - frame_number = ost->frame_number; fps = t > 1 ? frame_number / t : 0; - av_bprintf(&buf, "frame=%5d fps=%3.*f q=%3.1f ", + av_bprintf(&buf, "frame=%5"PRId64" 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, "frame=%"PRId64"\n", frame_number); av_bprintf(&buf_script, "fps=%.2f\n", fps); av_bprintf(&buf_script, "stream_%d_%d_q=%.1f\n", ost->file_index, ost->index, q); @@ -1840,9 +1671,9 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti } if (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); + av_bprintf(&buf, " dup=%"PRId64" drop=%"PRId64, nb_frames_dup, nb_frames_drop); + av_bprintf(&buf_script, "dup_frames=%"PRId64"\n", nb_frames_dup); + av_bprintf(&buf_script, "drop_frames=%"PRId64"\n", nb_frames_drop); if (speed < 0) { av_bprintf(&buf, " speed=N/A"); @@ -1883,17 +1714,22 @@ 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) +static int ifilter_parameters_from_codecpar(InputFilter *ifilter, AVCodecParameters *par) { + int ret; + // 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; + ret = av_channel_layout_copy(&ifilter->ch_layout, &par->ch_layout); + if (ret < 0) + return ret; + + return 0; } static void flush_encoders(void) @@ -1921,8 +1757,11 @@ static void flush_encoders(void) int x; for (x = 0; x < fg->nb_inputs; x++) { InputFilter *ifilter = fg->inputs[x]; - if (ifilter->format < 0) - ifilter_parameters_from_codecpar(ifilter, ifilter->ist->st->codecpar); + if (ifilter->format < 0 && + ifilter_parameters_from_codecpar(ifilter, ifilter->ist->st->codecpar) < 0) { + av_log(NULL, AV_LOG_ERROR, "Error copying paramerets from input stream\n"); + exit_program(1); + } } if (!ifilter_has_all_input_formats(fg)) @@ -1943,59 +1782,9 @@ static void flush_encoders(void) if (enc->codec_type != AVMEDIA_TYPE_VIDEO && enc->codec_type != AVMEDIA_TYPE_AUDIO) continue; - for (;;) { - const char *desc = NULL; - AVPacket *pkt = ost->pkt; - int pkt_size; - - switch (enc->codec_type) { - case AVMEDIA_TYPE_AUDIO: - desc = "audio"; - break; - case AVMEDIA_TYPE_VIDEO: - desc = "video"; - break; - default: - av_assert0(0); - } - - update_benchmark(NULL); - - while ((ret = avcodec_receive_packet(enc, pkt)) == AVERROR(EAGAIN)) { - ret = avcodec_send_frame(enc, NULL); - if (ret < 0) { - av_log(NULL, AV_LOG_FATAL, "%s encoding failed: %s\n", - desc, - av_err2str(ret)); - exit_program(1); - } - } - - update_benchmark("flush_%s %d.%d", desc, ost->file_index, ost->index); - if (ret < 0 && ret != AVERROR_EOF) { - av_log(NULL, AV_LOG_FATAL, "%s encoding failed: %s\n", - desc, - av_err2str(ret)); - exit_program(1); - } - if (ost->logfile && enc->stats_out) { - fprintf(ost->logfile, "%s", enc->stats_out); - } - if (ret == AVERROR_EOF) { - output_packet(of, pkt, ost, 1); - break; - } - if (ost->finished & MUXER_FINISHED) { - av_packet_unref(pkt); - continue; - } - av_packet_rescale_ts(pkt, enc->time_base, ost->mux_timebase); - pkt_size = pkt->size; - output_packet(of, pkt, ost, 0); - if (ost->enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO && vstats_filename) { - do_video_stats(ost, pkt_size); - } - } + ret = encode_frame(of, ost, NULL); + if (ret != AVERROR_EOF) + exit_program(1); } } @@ -2010,7 +1799,7 @@ static int check_output_constraints(InputStream *ist, OutputStream *ost) if (ost->source_index != ist_index) return 0; - if (ost->finished) + if (ost->finished & MUXER_FINISHED) return 0; if (of->start_time != AV_NOPTS_VALUE && ist->pts < of->start_time) @@ -2034,11 +1823,11 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p return; } - if ((!ost->frame_number && !(pkt->flags & AV_PKT_FLAG_KEY)) && + if (!ost->streamcopy_started && !(pkt->flags & AV_PKT_FLAG_KEY) && !ost->copy_initial_nonkeyframes) return; - if (!ost->frame_number && !ost->copy_prior_start) { + if (!ost->streamcopy_started && !ost->copy_prior_start) { int64_t comp_start = start_time; if (copy_ts && f->start_time != AV_NOPTS_VALUE) comp_start = FFMAX(start_time, f->start_time + f->ts_offset); @@ -2092,22 +1881,23 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p ost->sync_opts += opkt->duration; output_packet(of, opkt, ost, 0); + + ost->streamcopy_started = 1; } int guess_input_channel_layout(InputStream *ist) { AVCodecContext *dec = ist->dec_ctx; - if (!dec->channel_layout) { + if (dec->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) { char layout_name[256]; - if (dec->channels > ist->guess_layout_max) + if (dec->ch_layout.nb_channels > ist->guess_layout_max) return 0; - dec->channel_layout = av_get_default_channel_layout(dec->channels); - if (!dec->channel_layout) + av_channel_layout_default(&dec->ch_layout, dec->ch_layout.nb_channels); + if (dec->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) return 0; - av_get_channel_layout_string(layout_name, sizeof(layout_name), - dec->channels, dec->channel_layout); + av_channel_layout_describe(&dec->ch_layout, layout_name, sizeof(layout_name)); av_log(NULL, AV_LOG_WARNING, "Guessed Channel Layout for Input Stream " "#%d.%d : %s\n", ist->file_index, ist->st->index, layout_name); } @@ -2160,8 +1950,7 @@ static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_ref switch (ifilter->ist->st->codecpar->codec_type) { case AVMEDIA_TYPE_AUDIO: need_reinit |= ifilter->sample_rate != frame->sample_rate || - ifilter->channels != frame->channels || - ifilter->channel_layout != frame->channel_layout; + av_channel_layout_compare(&ifilter->ch_layout, &frame->ch_layout); break; case AVMEDIA_TYPE_VIDEO: need_reinit |= ifilter->width != frame->width || @@ -2195,15 +1984,11 @@ static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_ref if (!tmp) return AVERROR(ENOMEM); - if (!av_fifo_space(ifilter->frame_queue)) { - ret = av_fifo_realloc2(ifilter->frame_queue, 2 * av_fifo_size(ifilter->frame_queue)); - if (ret < 0) { - av_frame_free(&tmp); - return ret; - } - } - av_fifo_generic_write(ifilter->frame_queue, &tmp, sizeof(tmp), NULL); - return 0; + ret = av_fifo_write(ifilter->frame_queue, &tmp, 1); + if (ret < 0) + av_frame_free(&tmp); + + return ret; } ret = reap_filters(1); @@ -2241,8 +2026,11 @@ static int ifilter_send_eof(InputFilter *ifilter, int64_t pts) return ret; } else { // the filtergraph was never configured - if (ifilter->format < 0) - ifilter_parameters_from_codecpar(ifilter, ifilter->ist->st->codecpar); + if (ifilter->format < 0) { + ret = ifilter_parameters_from_codecpar(ifilter, ifilter->ist->st->codecpar); + if (ret < 0) + return ret; + } 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; @@ -2526,15 +2314,13 @@ static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got_output, sub2video_update(ist, INT64_MIN, &subtitle); } else if (ist->nb_filters) { if (!ist->sub2video.sub_queue) - ist->sub2video.sub_queue = av_fifo_alloc(8 * sizeof(AVSubtitle)); + ist->sub2video.sub_queue = av_fifo_alloc2(8, sizeof(AVSubtitle), AV_FIFO_FLAG_AUTO_GROW); if (!ist->sub2video.sub_queue) exit_program(1); - if (!av_fifo_space(ist->sub2video.sub_queue)) { - ret = av_fifo_realloc2(ist->sub2video.sub_queue, 2 * av_fifo_size(ist->sub2video.sub_queue)); - if (ret < 0) - exit_program(1); - } - av_fifo_generic_write(ist->sub2video.sub_queue, &subtitle, sizeof(subtitle), NULL); + + ret = av_fifo_write(ist->sub2video.sub_queue, &subtitle, 1); + if (ret < 0) + exit_program(1); free_sub = 0; } @@ -2748,7 +2534,9 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo } ist->pts = ist->dts; ist->next_pts = ist->next_dts; - } + } else if (!ist->decoding_needed) + eof_reached = 1; + for (i = 0; i < nb_output_streams; i++) { OutputStream *ost = output_streams[i]; @@ -2761,59 +2549,6 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo return !eof_reached; } -static int print_sdp(void) -{ - char sdp[16384]; - int i; - int j, ret; - AVIOContext *sdp_pb; - AVFormatContext **avc; - - for (i = 0; i < nb_output_files; i++) { - if (!output_files[i]->header_written) - return 0; - } - - avc = av_malloc_array(nb_output_files, sizeof(*avc)); - if (!avc) - exit_program(1); - for (i = 0, j = 0; i < nb_output_files; i++) { - if (!strcmp(output_files[i]->ctx->oformat->name, "rtp")) { - avc[j] = output_files[i]->ctx; - j++; - } - } - - if (!j) { - av_log(NULL, AV_LOG_ERROR, "No output streams in the SDP.\n"); - ret = AVERROR(EINVAL); - goto fail; - } - - ret = av_sdp_create(avc, j, sdp, sizeof(sdp)); - if (ret < 0) - goto fail; - - if (!sdp_filename) { - printf("SDP:\n%s\n", sdp); - fflush(stdout); - } else { - ret = avio_open2(&sdp_pb, sdp_filename, AVIO_FLAG_WRITE, &int_cb, NULL); - if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "Failed to open sdp file '%s'\n", sdp_filename); - goto fail; - } - - avio_print(sdp_pb, sdp); - avio_closep(&sdp_pb); - av_freep(&sdp_filename); - } - -fail: - av_freep(&avc); - return ret; -} - static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat *pix_fmts) { InputStream *ist = s->opaque; @@ -2879,9 +2614,9 @@ static int init_input_stream(int ist_index, char *error, int error_len) ist->dec_ctx->opaque = ist; ist->dec_ctx->get_format = get_format; #if LIBAVCODEC_VERSION_MAJOR < 60 -FF_DISABLE_DEPRECATION_WARNINGS + AV_NOWARN_DEPRECATED({ ist->dec_ctx->thread_safe_callbacks = 1; -FF_ENABLE_DEPRECATION_WARNINGS + }) #endif if (ist->dec_ctx->codec_id == AV_CODEC_ID_DVB_SUBTITLE && @@ -2940,61 +2675,6 @@ static int compare_int64(const void *a, const void *b) return FFDIFFSIGN(*(const int64_t *)a, *(const int64_t *)b); } -/* open the muxer when all the streams are initialized */ -static int check_init_output_file(OutputFile *of, int file_index) -{ - int ret, i; - - for (i = 0; i < of->ctx->nb_streams; i++) { - OutputStream *ost = output_streams[of->ost_index + i]; - if (!ost->initialized) - return 0; - } - - of->ctx->interrupt_callback = int_cb; - - ret = avformat_write_header(of->ctx, &of->opts); - if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, - "Could not write header for output file #%d " - "(incorrect codec parameters ?): %s\n", - file_index, av_err2str(ret)); - return ret; - } - //assert_avoptions(of->opts); - of->header_written = 1; - - av_dump_format(of->ctx, file_index, of->ctx->url, 1); - nb_output_dumped++; - - if (sdp_filename || want_sdp) { - ret = print_sdp(); - if (ret < 0) { - av_log(NULL, AV_LOG_ERROR, "Error writing the SDP.\n"); - return ret; - } - } - - /* flush the muxing queues */ - for (i = 0; i < of->ctx->nb_streams; i++) { - OutputStream *ost = output_streams[of->ost_index + i]; - - /* try to improve muxing time_base (only possible if nothing has been written yet) */ - if (!av_fifo_size(ost->muxing_queue)) - ost->mux_timebase = ost->st->time_base; - - while (av_fifo_size(ost->muxing_queue)) { - AVPacket *pkt; - av_fifo_generic_read(ost->muxing_queue, &pkt, sizeof(pkt), NULL); - ost->muxing_queue_data_size -= pkt->size; - write_packet(of, pkt, ost, 1); - av_packet_free(&pkt); - } - } - - return 0; -} - static int init_output_bsfs(OutputStream *ost) { AVBSFContext *ctx = ost->bsf_ctx; @@ -3054,9 +2734,9 @@ static int init_output_stream_streamcopy(OutputStream *ost) if (!codec_tag) { unsigned int codec_tag_tmp; - if (!of->ctx->oformat->codec_tag || - av_codec_get_id (of->ctx->oformat->codec_tag, par_src->codec_tag) == par_src->codec_id || - !av_codec_get_tag2(of->ctx->oformat->codec_tag, par_src->codec_id, &codec_tag_tmp)) + if (!of->format->codec_tag || + av_codec_get_id (of->format->codec_tag, par_src->codec_tag) == par_src->codec_id || + !av_codec_get_tag2(of->format->codec_tag, par_src->codec_id, &codec_tag_tmp)) codec_tag = par_src->codec_tag; } @@ -3074,7 +2754,7 @@ static int init_output_stream_streamcopy(OutputStream *ost) else ost->st->avg_frame_rate = ist->st->avg_frame_rate; - ret = avformat_transfer_internal_stream_timing_info(of->ctx->oformat, ost->st, ist->st, copy_tb); + ret = avformat_transfer_internal_stream_timing_info(of->format, ost->st, ist->st, copy_tb); if (ret < 0) return ret; @@ -3276,7 +2956,8 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) InputStream *ist = get_input_stream(ost); AVCodecContext *enc_ctx = ost->enc_ctx; AVCodecContext *dec_ctx = NULL; - AVFormatContext *oc = output_files[ost->file_index]->ctx; + OutputFile *of = output_files[ost->file_index]; + AVFormatContext *oc = of->ctx; int ret; set_encoder_id(output_files[ost->file_index], ost); @@ -3318,8 +2999,9 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) case AVMEDIA_TYPE_AUDIO: enc_ctx->sample_fmt = av_buffersink_get_format(ost->filter->filter); enc_ctx->sample_rate = av_buffersink_get_sample_rate(ost->filter->filter); - enc_ctx->channel_layout = av_buffersink_get_channel_layout(ost->filter->filter); - enc_ctx->channels = av_buffersink_get_channels(ost->filter->filter); + ret = av_buffersink_get_ch_layout(ost->filter->filter, &enc_ctx->ch_layout); + if (ret < 0) + return ret; if (ost->bits_per_raw_sample) enc_ctx->bits_per_raw_sample = ost->bits_per_raw_sample; @@ -3335,10 +3017,12 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) if (!(enc_ctx->time_base.num && enc_ctx->time_base.den)) enc_ctx->time_base = av_buffersink_get_time_base(ost->filter->filter); - if ( av_q2d(enc_ctx->time_base) < 0.001 && video_sync_method != VSYNC_PASSTHROUGH - && (video_sync_method == VSYNC_CFR || video_sync_method == VSYNC_VSCFR || (video_sync_method == VSYNC_AUTO && !(oc->oformat->flags & AVFMT_VARIABLE_FPS)))){ + if ( av_q2d(enc_ctx->time_base) < 0.001 && ost->vsync_method != VSYNC_PASSTHROUGH + && (ost->vsync_method == VSYNC_CFR || ost->vsync_method == VSYNC_VSCFR || + (ost->vsync_method == VSYNC_AUTO && !(of->format->flags & AVFMT_VARIABLE_FPS)))){ av_log(oc, AV_LOG_WARNING, "Frame rate very high for a muxer not efficiently supporting it.\n" - "Please consider specifying a lower framerate, a different muxer or -vsync 2\n"); + "Please consider specifying a lower framerate, a different muxer or " + "setting vsync/fps_mode to vfr\n"); } enc_ctx->width = av_buffersink_get_w(ost->filter->filter); @@ -3567,7 +3251,7 @@ static int init_output_stream(OutputStream *ost, AVFrame *frame, ost->initialized = 1; - ret = check_init_output_file(output_files[ost->file_index], ost->file_index); + ret = of_check_init(output_files[ost->file_index]); if (ret < 0) return ret; @@ -3669,8 +3353,8 @@ static int transcode_init(void) /* write headers for files with no streams */ for (i = 0; i < nb_output_files; i++) { oc = output_files[i]->ctx; - if (oc->oformat->flags & AVFMT_NOSTREAMS && oc->nb_streams == 0) { - ret = check_init_output_file(output_files[i], i); + if (output_files[i]->format->flags & AVFMT_NOSTREAMS && oc->nb_streams == 0) { + ret = of_check_init(output_files[i]); if (ret < 0) goto dump_format; } @@ -3847,7 +3531,7 @@ static int check_keyboard_interaction(int64_t cur_time) if (received_nb_signals) return AVERROR_EXIT; /* read_key() returns 0 on EOF */ - if(cur_time - last_time >= 100000 && !run_as_daemon){ + if (cur_time - last_time >= 100000) { key = read_key(); last_time = cur_time; }else @@ -4231,11 +3915,12 @@ static int process_input(int file_index) for (i = 0; i < ifile->nb_streams; i++) { ist = input_streams[ifile->ist_index + i]; avctx = ist->dec_ctx; - if (ist->decoding_needed) { + if (ist->processing_needed) { ret = process_input_packet(ist, NULL, 1); if (ret>0) return 0; - avcodec_flush_buffers(avctx); + if (ist->decoding_needed) + avcodec_flush_buffers(avctx); } } #if HAVE_THREADS @@ -4265,7 +3950,7 @@ static int process_input(int file_index) for (i = 0; i < ifile->nb_streams; i++) { ist = input_streams[ifile->ist_index + i]; - if (ist->decoding_needed) { + if (ist->processing_needed) { ret = process_input_packet(ist, NULL, 0); if (ret>0) return 0; @@ -4315,12 +4000,13 @@ static int process_input(int file_index) if (debug_ts) { av_log(NULL, AV_LOG_INFO, "demuxer -> ist_index:%d type:%s " - "next_dts:%s next_dts_time:%s next_pts:%s next_pts_time:%s pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s off:%s off_time:%s\n", + "next_dts:%s next_dts_time:%s next_pts:%s next_pts_time:%s pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s duration:%s duration_time:%s off:%s off_time:%s\n", ifile->ist_index + pkt->stream_index, av_get_media_type_string(ist->dec_ctx->codec_type), av_ts2str(ist->next_dts), av_ts2timestr(ist->next_dts, &AV_TIME_BASE_Q), av_ts2str(ist->next_pts), av_ts2timestr(ist->next_pts, &AV_TIME_BASE_Q), av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &ist->st->time_base), av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &ist->st->time_base), + av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &ist->st->time_base), av_ts2str(input_files[ist->file_index]->ts_offset), av_ts2timestr(input_files[ist->file_index]->ts_offset, &AV_TIME_BASE_Q)); } @@ -4471,10 +4157,11 @@ static int process_input(int file_index) ifile->last_ts = av_rescale_q(pkt->dts, ist->st->time_base, AV_TIME_BASE_Q); if (debug_ts) { - av_log(NULL, AV_LOG_INFO, "demuxer+ffmpeg -> ist_index:%d type:%s pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s off:%s off_time:%s\n", + av_log(NULL, AV_LOG_INFO, "demuxer+ffmpeg -> ist_index:%d type:%s pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s duration:%s duration_time:%s off:%s off_time:%s\n", ifile->ist_index + pkt->stream_index, av_get_media_type_string(ist->dec_ctx->codec_type), av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &ist->st->time_base), av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &ist->st->time_base), + av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &ist->st->time_base), av_ts2str(input_files[ist->file_index]->ts_offset), av_ts2timestr(input_files[ist->file_index]->ts_offset, &AV_TIME_BASE_Q)); } @@ -4701,19 +4388,9 @@ static int transcode(void) /* write the trailer if needed */ for (i = 0; i < nb_output_files; i++) { - os = output_files[i]->ctx; - if (!output_files[i]->header_written) { - 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->url); - continue; - } - if ((ret = av_write_trailer(os)) < 0) { - 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); - } + ret = of_write_trailer(output_files[i]); + if (ret < 0 && exit_on_error) + exit_program(1); } /* dump report by using the first video and audio streams */ @@ -4836,10 +4513,6 @@ static int64_t getmaxrss(void) #endif } -static void log_callback_null(void *ptr, int level, const char *fmt, va_list vl) -{ -} - int main(int argc, char **argv) { int i, ret; @@ -4854,13 +4527,6 @@ int main(int argc, char **argv) av_log_set_flags(AV_LOG_SKIP_REPEATED); parse_loglevel(argc, argv, options); - if(argc>1 && !strcmp(argv[1], "-d")){ - run_as_daemon=1; - av_log_set_callback(log_callback_null); - argc--; - argv++; - } - #if CONFIG_AVDEVICE avdevice_register_all(); #endif @@ -4886,7 +4552,7 @@ int main(int argc, char **argv) } for (i = 0; i < nb_output_files; i++) { - if (strcmp(output_files[i]->ctx->oformat->name, "rtp")) + if (strcmp(output_files[i]->format->name, "rtp")) want_sdp = 0; } diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 9b200b806..391a35cf5 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -96,6 +96,8 @@ typedef struct OptionsContext { SpecifierOpt *codec_names; int nb_codec_names; + SpecifierOpt *audio_ch_layouts; + int nb_audio_ch_layouts; SpecifierOpt *audio_channels; int nb_audio_channels; SpecifierOpt *audio_sample_rate; @@ -116,6 +118,7 @@ typedef struct OptionsContext { float readrate; int accurate_seek; int thread_queue_size; + int input_sync_ref; SpecifierOpt *ts_scale; int nb_ts_scale; @@ -174,6 +177,8 @@ typedef struct OptionsContext { int nb_qscale; SpecifierOpt *forced_key_frames; int nb_forced_key_frames; + SpecifierOpt *fps_mode; + int nb_fps_mode; SpecifierOpt *force_fps; int nb_force_fps; SpecifierOpt *frame_aspect_ratios; @@ -241,7 +246,7 @@ typedef struct InputFilter { uint8_t *name; enum AVMediaType type; // AVMEDIA_TYPE_SUBTITLE for sub2video - AVFifoBuffer *frame_queue; + AVFifo *frame_queue; // parameters configured for this input int format; @@ -250,8 +255,7 @@ typedef struct InputFilter { AVRational sample_aspect_ratio; int sample_rate; - int channels; - uint64_t channel_layout; + AVChannelLayout ch_layout; AVBufferRef *hw_frames_ctx; int32_t *displaymatrix; @@ -274,12 +278,12 @@ typedef struct OutputFilter { AVRational frame_rate; int format; int sample_rate; - uint64_t channel_layout; + AVChannelLayout ch_layout; // those are only set if no format is specified and the encoder gives us multiple options // They point directly to the relevant lists of the encoder. const int *formats; - const uint64_t *channel_layouts; + const AVChannelLayout *ch_layouts; const int *sample_rates; } OutputFilter; @@ -307,6 +311,7 @@ typedef struct InputStream { int decoding_needed; /* non zero if the packets must be decoded in 'raw_fifo', see DECODING_FOR_* */ #define DECODING_FOR_OST 1 #define DECODING_FOR_FILTER 2 + int processing_needed; /* non zero if the packets must be processed */ AVCodecContext *dec_ctx; const AVCodec *dec; @@ -355,7 +360,7 @@ typedef struct InputStream { struct sub2video { int64_t last_pts; int64_t end_pts; - AVFifoBuffer *sub_queue; ///< queue of AVSubtitle* before filter init + AVFifo *sub_queue; ///< queue of AVSubtitle* before filter init AVFrame *frame; int w, h; unsigned int initialize; ///< marks if sub2video_update should force an initialization @@ -406,6 +411,7 @@ typedef struct InputFile { at the moment when looping happens */ AVRational time_base; /* time base of the duration */ int64_t input_ts_offset; + int input_sync_ref; int64_t ts_offset; int64_t last_ts; @@ -454,7 +460,7 @@ typedef struct OutputStream { int source_index; /* InputStream index */ AVStream *st; /* stream in the output file */ int encoding_needed; /* true if encoding needed for this stream */ - int frame_number; + int64_t frame_number; /* input pts and corresponding output pts for A/V sync */ struct InputStream *sync_ist; /* input stream to sync against */ @@ -477,8 +483,8 @@ typedef struct OutputStream { AVFrame *filtered_frame; AVFrame *last_frame; AVPacket *pkt; - int last_dropped; - int last_nb0_frames[3]; + int64_t last_dropped; + int64_t last_nb0_frames[3]; void *hwaccel_ctx; @@ -487,6 +493,7 @@ typedef struct OutputStream { AVRational max_frame_rate; enum VideoSyncMethod vsync_method; int is_cfr; + const char *fps_mode; int force_fps; int top_field_first; int rotate_overridden; @@ -534,6 +541,7 @@ typedef struct OutputStream { int inputs_done; const char *attachment_filename; + int streamcopy_started; int copy_initial_nonkeyframes; int copy_prior_start; char *disposition; @@ -548,6 +556,8 @@ typedef struct OutputStream { // number of frames/samples sent to the encoder uint64_t frames_encoded; uint64_t samples_encoded; + // number of packets received from the encoder + uint64_t packets_encoded; /* packet quality factor */ int quality; @@ -555,7 +565,7 @@ typedef struct OutputStream { int max_muxing_queue_size; /* the packets are buffered here until the muxer is ready to be initialized */ - AVFifoBuffer *muxing_queue; + AVFifo *muxing_queue; /* * The size of the AVPackets' buffers in queue. @@ -574,6 +584,10 @@ typedef struct OutputStream { } OutputStream; typedef struct OutputFile { + int index; + + const AVOutputFormat *format; + AVFormatContext *ctx; AVDictionary *opts; int ost_index; /* index of the first stream in output_streams */ @@ -642,6 +656,10 @@ extern char *qsv_device; #endif extern HWDevice *filter_hw_device; +extern int want_sdp; +extern unsigned nb_output_dumped; +extern int main_return_code; + void term_init(void); void term_exit(void); @@ -678,4 +696,12 @@ int hw_device_setup_for_filter(FilterGraph *fg); int hwaccel_decode_init(AVCodecContext *avctx); +/* open the muxer when all the streams are initialized */ +int of_check_init(OutputFile *of); +int of_write_trailer(OutputFile *of); +void of_close(OutputFile **pof); + +void of_write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, + int unqueue); + #endif /* FFTOOLS_FFMPEG_H */ diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index 1f6cba2c0..0845c631a 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -153,8 +153,25 @@ DEF_CHOOSE_FORMAT(sample_fmts, enum AVSampleFormat, format, formats, DEF_CHOOSE_FORMAT(sample_rates, int, sample_rate, sample_rates, 0, "%d", ) -DEF_CHOOSE_FORMAT(channel_layouts, uint64_t, channel_layout, channel_layouts, 0, - "0x%"PRIx64, ) +static void choose_channel_layouts(OutputFilter *ofilter, AVBPrint *bprint) +{ + if (av_channel_layout_check(&ofilter->ch_layout)) { + av_bprintf(bprint, "channel_layouts="); + av_channel_layout_describe_bprint(&ofilter->ch_layout, bprint); + } else if (ofilter->ch_layouts) { + const AVChannelLayout *p; + + av_bprintf(bprint, "channel_layouts="); + for (p = ofilter->ch_layouts; p->nb_channels; p++) { + av_channel_layout_describe_bprint(p, bprint); + av_bprintf(bprint, "|"); + } + if (bprint->len > 0) + bprint->str[--bprint->len] = '\0'; + } else + return; + av_bprint_chars(bprint, ':', 1); +} int init_simple_filtergraph(InputStream *ist, OutputStream *ost) { @@ -178,7 +195,7 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost) ifilter->graph = fg; ifilter->format = -1; - ifilter->frame_queue = av_fifo_alloc(8 * sizeof(AVFrame*)); + ifilter->frame_queue = av_fifo_alloc2(8, sizeof(AVFrame*), AV_FIFO_FLAG_AUTO_GROW); if (!ifilter->frame_queue) exit_program(1); @@ -277,6 +294,7 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) ist->discard = 0; ist->decoding_needed |= DECODING_FOR_FILTER; + ist->processing_needed = 1; ist->st->discard = AVDISCARD_NONE; ifilter = ALLOC_ARRAY_ELEM(fg->inputs, fg->nb_inputs); @@ -286,7 +304,7 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) ifilter->type = ist->st->codecpar->codec_type; ifilter->name = describe_filter_link(fg, in, 1); - ifilter->frame_queue = av_fifo_alloc(8 * sizeof(AVFrame*)); + ifilter->frame_queue = av_fifo_alloc2(8, sizeof(AVFrame*), AV_FIFO_FLAG_AUTO_GROW); if (!ifilter->frame_queue) exit_program(1); @@ -541,9 +559,10 @@ static int configure_output_audio_filter(FilterGraph *fg, OutputFilter *ofilter, } while (0) av_bprint_init(&args, 0, AV_BPRINT_SIZE_UNLIMITED); if (ost->audio_channels_mapped) { + AVChannelLayout mapped_layout = { 0 }; int i; - av_bprintf(&args, "0x%"PRIx64, - av_get_default_channel_layout(ost->audio_channels_mapped)); + av_channel_layout_default(&mapped_layout, ost->audio_channels_mapped); + av_channel_layout_describe_bprint(&mapped_layout, &args); for (i = 0; i < ost->audio_channels_mapped; i++) if (ost->audio_channels_map[i] != -1) av_bprintf(&args, "|c%d=c%d", i, ost->audio_channels_map[i]); @@ -552,8 +571,8 @@ static int configure_output_audio_filter(FilterGraph *fg, OutputFilter *ofilter, av_bprint_clear(&args); } - if (codec->channels && !codec->channel_layout) - codec->channel_layout = av_get_default_channel_layout(codec->channels); + if (codec->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) + av_channel_layout_default(&codec->ch_layout, codec->ch_layout.nb_channels); choose_sample_fmts(ofilter, &args); choose_sample_rates(ofilter, &args); @@ -832,11 +851,12 @@ static int configure_input_audio_filter(FilterGraph *fg, InputFilter *ifilter, 1, ifilter->sample_rate, ifilter->sample_rate, av_get_sample_fmt_name(ifilter->format)); - if (ifilter->channel_layout) - av_bprintf(&args, ":channel_layout=0x%"PRIx64, - ifilter->channel_layout); - else - av_bprintf(&args, ":channels=%d", ifilter->channels); + if (av_channel_layout_check(&ifilter->ch_layout) && + ifilter->ch_layout.order != AV_CHANNEL_ORDER_UNSPEC) { + av_bprintf(&args, ":channel_layout="); + av_channel_layout_describe_bprint(&ifilter->ch_layout, &args); + } else + av_bprintf(&args, ":channels=%d", ifilter->ch_layout.nb_channels); snprintf(name, sizeof(name), "graph_%d_in_%d_%d", fg->index, ist->file_index, ist->st->index); @@ -949,8 +969,8 @@ static void cleanup_filtergraph(FilterGraph *fg) static int filter_is_buffersrc(const AVFilterContext *f) { return f->nb_inputs == 0 && - (!strcmp(f->filter->name, "buffersrc") || - !strcmp(f->filter->name, "abuffersrc")); + (!strcmp(f->filter->name, "buffer") || + !strcmp(f->filter->name, "abuffer")); } static int graph_is_meta(AVFilterGraph *graph) @@ -1084,7 +1104,10 @@ int configure_filtergraph(FilterGraph *fg) ofilter->height = av_buffersink_get_h(sink); ofilter->sample_rate = av_buffersink_get_sample_rate(sink); - ofilter->channel_layout = av_buffersink_get_channel_layout(sink); + av_channel_layout_uninit(&ofilter->ch_layout); + ret = av_buffersink_get_ch_layout(sink, &ofilter->ch_layout); + if (ret < 0) + goto fail; } fg->reconfiguration = 1; @@ -1106,9 +1129,8 @@ int configure_filtergraph(FilterGraph *fg) } for (i = 0; i < fg->nb_inputs; i++) { - while (av_fifo_size(fg->inputs[i]->frame_queue)) { - AVFrame *tmp; - av_fifo_generic_read(fg->inputs[i]->frame_queue, &tmp, sizeof(tmp), NULL); + AVFrame *tmp; + while (av_fifo_read(fg->inputs[i]->frame_queue, &tmp, 1) >= 0) { ret = av_buffersrc_add_frame(fg->inputs[i]->filter, tmp); av_frame_free(&tmp); if (ret < 0) @@ -1129,9 +1151,8 @@ int configure_filtergraph(FilterGraph *fg) for (i = 0; i < fg->nb_inputs; i++) { InputStream *ist = fg->inputs[i]->ist; if (ist->sub2video.sub_queue && ist->sub2video.frame) { - while (av_fifo_size(ist->sub2video.sub_queue)) { - AVSubtitle tmp; - av_fifo_generic_read(ist->sub2video.sub_queue, &tmp, sizeof(tmp), NULL); + AVSubtitle tmp; + while (av_fifo_read(ist->sub2video.sub_queue, &tmp, 1) >= 0) { sub2video_update(ist, INT64_MIN, &tmp); avsubtitle_free(&tmp); } @@ -1148,6 +1169,7 @@ fail: int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame) { AVFrameSideData *sd; + int ret; av_buffer_unref(&ifilter->hw_frames_ctx); @@ -1158,8 +1180,9 @@ int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame) ifilter->sample_aspect_ratio = frame->sample_aspect_ratio; ifilter->sample_rate = frame->sample_rate; - ifilter->channels = frame->channels; - ifilter->channel_layout = frame->channel_layout; + ret = av_channel_layout_copy(&ifilter->ch_layout, &frame->ch_layout); + if (ret < 0) + return ret; av_freep(&ifilter->displaymatrix); sd = av_frame_get_side_data(frame, AV_FRAME_DATA_DISPLAYMATRIX); diff --git a/fftools/ffmpeg_mux.c b/fftools/ffmpeg_mux.c new file mode 100644 index 000000000..a55fd18f8 --- /dev/null +++ b/fftools/ffmpeg_mux.c @@ -0,0 +1,317 @@ +/* + * 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 "ffmpeg.h" + +#include "libavutil/fifo.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/log.h" +#include "libavutil/mem.h" +#include "libavutil/timestamp.h" + +#include "libavcodec/packet.h" + +#include "libavformat/avformat.h" +#include "libavformat/avio.h" + +static void close_all_output_streams(OutputStream *ost, OSTFinished this_stream, OSTFinished others) +{ + int i; + for (i = 0; i < nb_output_streams; i++) { + OutputStream *ost2 = output_streams[i]; + ost2->finished |= ost == ost2 ? this_stream : others; + } +} + +void of_write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, + int unqueue) +{ + AVFormatContext *s = of->ctx; + AVStream *st = ost->st; + int ret; + + /* + * Audio encoders may split the packets -- #frames in != #packets out. + * But there is no reordering, so we can limit the number of output packets + * by simply dropping them here. + * Counting encoded video frames needs to be done separately because of + * reordering, see do_video_out(). + * Do not count the packet when unqueued because it has been counted when queued. + */ + if (!(st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && ost->encoding_needed) && !unqueue) { + if (ost->frame_number >= ost->max_frames) { + av_packet_unref(pkt); + return; + } + ost->frame_number++; + } + + if (!of->header_written) { + AVPacket *tmp_pkt; + /* the muxer is not initialized yet, buffer the packet */ + if (!av_fifo_can_write(ost->muxing_queue)) { + size_t cur_size = av_fifo_can_read(ost->muxing_queue); + unsigned int are_we_over_size = + (ost->muxing_queue_data_size + pkt->size) > ost->muxing_queue_data_threshold; + size_t limit = are_we_over_size ? ost->max_muxing_queue_size : SIZE_MAX; + size_t new_size = FFMIN(2 * cur_size, limit); + + if (new_size <= cur_size) { + av_log(NULL, AV_LOG_ERROR, + "Too many packets buffered for output stream %d:%d.\n", + ost->file_index, ost->st->index); + exit_program(1); + } + ret = av_fifo_grow2(ost->muxing_queue, new_size - cur_size); + if (ret < 0) + exit_program(1); + } + ret = av_packet_make_refcounted(pkt); + if (ret < 0) + exit_program(1); + tmp_pkt = av_packet_alloc(); + if (!tmp_pkt) + exit_program(1); + av_packet_move_ref(tmp_pkt, pkt); + ost->muxing_queue_data_size += tmp_pkt->size; + av_fifo_write(ost->muxing_queue, &tmp_pkt, 1); + return; + } + + if ((st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && ost->vsync_method == VSYNC_DROP) || + (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && audio_sync_method < 0)) + pkt->pts = pkt->dts = AV_NOPTS_VALUE; + + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + if (ost->frame_rate.num && ost->is_cfr) { + if (pkt->duration > 0) + av_log(NULL, AV_LOG_WARNING, "Overriding packet duration by frame rate, this should not happen\n"); + pkt->duration = av_rescale_q(1, av_inv_q(ost->frame_rate), + ost->mux_timebase); + } + } + + av_packet_rescale_ts(pkt, ost->mux_timebase, ost->st->time_base); + + if (!(s->oformat->flags & AVFMT_NOTIMESTAMPS)) { + if (pkt->dts != AV_NOPTS_VALUE && + pkt->pts != AV_NOPTS_VALUE && + pkt->dts > pkt->pts) { + av_log(s, AV_LOG_WARNING, "Invalid DTS: %"PRId64" PTS: %"PRId64" in output stream %d:%d, replacing by guess\n", + pkt->dts, pkt->pts, + ost->file_index, ost->st->index); + pkt->pts = + pkt->dts = pkt->pts + pkt->dts + ost->last_mux_dts + 1 + - FFMIN3(pkt->pts, pkt->dts, ost->last_mux_dts + 1) + - FFMAX3(pkt->pts, pkt->dts, ost->last_mux_dts + 1); + } + if ((st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE) && + pkt->dts != AV_NOPTS_VALUE && + ost->last_mux_dts != AV_NOPTS_VALUE) { + int64_t max = ost->last_mux_dts + !(s->oformat->flags & AVFMT_TS_NONSTRICT); + if (pkt->dts < max) { + int loglevel = max - pkt->dts > 2 || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ? AV_LOG_WARNING : AV_LOG_DEBUG; + if (exit_on_error) + loglevel = AV_LOG_ERROR; + av_log(s, loglevel, "Non-monotonous DTS in output stream " + "%d:%d; previous: %"PRId64", current: %"PRId64"; ", + ost->file_index, ost->st->index, ost->last_mux_dts, pkt->dts); + if (exit_on_error) { + av_log(NULL, AV_LOG_FATAL, "aborting.\n"); + exit_program(1); + } + av_log(s, loglevel, "changing to %"PRId64". This may result " + "in incorrect timestamps in the output file.\n", + max); + if (pkt->pts >= pkt->dts) + pkt->pts = FFMAX(pkt->pts, max); + pkt->dts = max; + } + } + } + ost->last_mux_dts = pkt->dts; + + ost->data_size += pkt->size; + ost->packets_written++; + + pkt->stream_index = ost->index; + + if (debug_ts) { + av_log(NULL, AV_LOG_INFO, "muxer <- type:%s " + "pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s duration:%s duration_time:%s size:%d\n", + av_get_media_type_string(ost->enc_ctx->codec_type), + av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &ost->st->time_base), + av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &ost->st->time_base), + av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &ost->st->time_base), + pkt->size + ); + } + + ret = av_interleaved_write_frame(s, pkt); + if (ret < 0) { + print_error("av_interleaved_write_frame()", ret); + main_return_code = 1; + close_all_output_streams(ost, MUXER_FINISHED | ENCODER_FINISHED, ENCODER_FINISHED); + } +} + +static int print_sdp(void) +{ + char sdp[16384]; + int i; + int j, ret; + AVIOContext *sdp_pb; + AVFormatContext **avc; + + for (i = 0; i < nb_output_files; i++) { + if (!output_files[i]->header_written) + return 0; + } + + avc = av_malloc_array(nb_output_files, sizeof(*avc)); + if (!avc) + exit_program(1); + for (i = 0, j = 0; i < nb_output_files; i++) { + if (!strcmp(output_files[i]->ctx->oformat->name, "rtp")) { + avc[j] = output_files[i]->ctx; + j++; + } + } + + if (!j) { + av_log(NULL, AV_LOG_ERROR, "No output streams in the SDP.\n"); + ret = AVERROR(EINVAL); + goto fail; + } + + ret = av_sdp_create(avc, j, sdp, sizeof(sdp)); + if (ret < 0) + goto fail; + + if (!sdp_filename) { + printf("SDP:\n%s\n", sdp); + fflush(stdout); + } else { + ret = avio_open2(&sdp_pb, sdp_filename, AVIO_FLAG_WRITE, &int_cb, NULL); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Failed to open sdp file '%s'\n", sdp_filename); + goto fail; + } + + avio_print(sdp_pb, sdp); + avio_closep(&sdp_pb); + av_freep(&sdp_filename); + } + +fail: + av_freep(&avc); + return ret; +} + +/* open the muxer when all the streams are initialized */ +int of_check_init(OutputFile *of) +{ + int ret, i; + + for (i = 0; i < of->ctx->nb_streams; i++) { + OutputStream *ost = output_streams[of->ost_index + i]; + if (!ost->initialized) + return 0; + } + + ret = avformat_write_header(of->ctx, &of->opts); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, + "Could not write header for output file #%d " + "(incorrect codec parameters ?): %s\n", + of->index, av_err2str(ret)); + return ret; + } + //assert_avoptions(of->opts); + of->header_written = 1; + + av_dump_format(of->ctx, of->index, of->ctx->url, 1); + nb_output_dumped++; + + if (sdp_filename || want_sdp) { + ret = print_sdp(); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Error writing the SDP.\n"); + return ret; + } + } + + /* flush the muxing queues */ + for (i = 0; i < of->ctx->nb_streams; i++) { + OutputStream *ost = output_streams[of->ost_index + i]; + AVPacket *pkt; + + /* try to improve muxing time_base (only possible if nothing has been written yet) */ + if (!av_fifo_can_read(ost->muxing_queue)) + ost->mux_timebase = ost->st->time_base; + + while (av_fifo_read(ost->muxing_queue, &pkt, 1) >= 0) { + ost->muxing_queue_data_size -= pkt->size; + of_write_packet(of, pkt, ost, 1); + av_packet_free(&pkt); + } + } + + return 0; +} + +int of_write_trailer(OutputFile *of) +{ + int ret; + + if (!of->header_written) { + 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", + of->index, of->ctx->url); + return AVERROR(EINVAL); + } + + ret = av_write_trailer(of->ctx); + if (ret < 0) { + av_log(NULL, AV_LOG_ERROR, "Error writing trailer of %s: %s\n", of->ctx->url, av_err2str(ret)); + return ret; + } + + return 0; +} + +void of_close(OutputFile **pof) +{ + OutputFile *of = *pof; + AVFormatContext *s; + + if (!of) + return; + + s = of->ctx; + if (s && s->oformat && !(s->oformat->flags & AVFMT_NOFILE)) + avio_closep(&s->pb); + avformat_free_context(s); + av_dict_free(&of->opts); + + av_freep(pof); +} diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 9c820ab73..ac7fe3b27 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -1,4 +1,3 @@ - /* * ffmpeg option parsing * @@ -19,10 +18,19 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config.h" + #include +#if HAVE_SYS_RESOURCE_H +#include +#include +#endif + #include "ffmpeg.h" +#include "fopen_utf8.h" #include "cmdutils.h" +#include "opt_common.h" #include "libavformat/avformat.h" @@ -36,6 +44,7 @@ #include "libavutil/avutil.h" #include "libavutil/bprint.h" #include "libavutil/channel_layout.h" +#include "libavutil/getenv_utf8.h" #include "libavutil/intreadwrite.h" #include "libavutil/fifo.h" #include "libavutil/mathematics.h" @@ -55,6 +64,7 @@ static const char *const opt_name_codec_names[] = {"c", "codec", "acodec", "vcodec", "scodec", "dcodec", NULL}; static const char *const opt_name_audio_channels[] = {"ac", NULL}; +static const char *const opt_name_audio_ch_layouts[] = {"channel_layout", "ch_layout", NULL}; static const char *const opt_name_audio_sample_rate[] = {"ar", NULL}; static const char *const opt_name_frame_rates[] = {"r", NULL}; static const char *const opt_name_max_frame_rates[] = {"fpsmax", NULL}; @@ -72,6 +82,7 @@ static const char *const opt_name_codec_tags[] = {"tag", "atag", static const char *const opt_name_sample_fmts[] = {"sample_fmt", NULL}; static const char *const opt_name_qscale[] = {"q", "qscale", NULL}; static const char *const opt_name_forced_key_frames[] = {"forced_key_frames", NULL}; +static const char *const opt_name_fps_mode[] = {"fps_mode", NULL}; static const char *const opt_name_force_fps[] = {"force_fps", NULL}; static const char *const opt_name_frame_aspect_ratios[] = {"aspect", NULL}; static const char *const opt_name_rc_overrides[] = {"rc_override", NULL}; @@ -224,6 +235,7 @@ static void init_options(OptionsContext *o) o->chapters_input_file = INT_MAX; o->accurate_seek = 1; o->thread_queue_size = -1; + o->input_sync_ref = -1; } static int show_hwaccels(void *optctx, const char *opt, const char *arg) @@ -256,6 +268,78 @@ static AVDictionary *strip_specifiers(AVDictionary *dict) return ret; } +static int parse_and_set_vsync(const char *arg, int *vsync_var, int file_idx, int st_idx, int is_global) +{ + if (!av_strcasecmp(arg, "cfr")) *vsync_var = VSYNC_CFR; + else if (!av_strcasecmp(arg, "vfr")) *vsync_var = VSYNC_VFR; + else if (!av_strcasecmp(arg, "passthrough")) *vsync_var = VSYNC_PASSTHROUGH; + else if (!av_strcasecmp(arg, "drop")) *vsync_var = VSYNC_DROP; + else if (!is_global && !av_strcasecmp(arg, "auto")) *vsync_var = VSYNC_AUTO; + else if (!is_global) { + av_log(NULL, AV_LOG_FATAL, "Invalid value %s specified for fps_mode of #%d:%d.\n", arg, file_idx, st_idx); + exit_program(1); + } + + if (is_global && *vsync_var == VSYNC_AUTO) { + video_sync_method = parse_number_or_die("vsync", arg, OPT_INT, VSYNC_AUTO, VSYNC_VFR); + av_log(NULL, AV_LOG_WARNING, "Passing a number to -vsync is deprecated," + " use a string argument as described in the manual.\n"); + } + return 0; +} + +static int apply_sync_offsets(void) +{ + for (int i = 0; i < nb_input_files; i++) { + InputFile *ref, *self = input_files[i]; + int64_t adjustment; + int64_t self_start_time, ref_start_time, self_seek_start, ref_seek_start; + int start_times_set = 1; + + if (self->input_sync_ref == -1 || self->input_sync_ref == i) continue; + if (self->input_sync_ref >= nb_input_files || self->input_sync_ref < -1) { + av_log(NULL, AV_LOG_FATAL, "-isync for input %d references non-existent input %d.\n", i, self->input_sync_ref); + exit_program(1); + } + + if (copy_ts && !start_at_zero) { + av_log(NULL, AV_LOG_FATAL, "Use of -isync requires that start_at_zero be set if copyts is set.\n"); + exit_program(1); + } + + ref = input_files[self->input_sync_ref]; + if (ref->input_sync_ref != -1 && ref->input_sync_ref != self->input_sync_ref) { + av_log(NULL, AV_LOG_ERROR, "-isync for input %d references a resynced input %d. Sync not set.\n", i, self->input_sync_ref); + continue; + } + + if (self->ctx->start_time_realtime != AV_NOPTS_VALUE && ref->ctx->start_time_realtime != AV_NOPTS_VALUE) { + self_start_time = self->ctx->start_time_realtime; + ref_start_time = ref->ctx->start_time_realtime; + } else if (self->ctx->start_time != AV_NOPTS_VALUE && ref->ctx->start_time != AV_NOPTS_VALUE) { + self_start_time = self->ctx->start_time; + ref_start_time = ref->ctx->start_time; + } else { + start_times_set = 0; + } + + if (start_times_set) { + self_seek_start = self->start_time == AV_NOPTS_VALUE ? 0 : self->start_time; + ref_seek_start = ref->start_time == AV_NOPTS_VALUE ? 0 : ref->start_time; + + adjustment = (self_start_time - ref_start_time) + !copy_ts*(self_seek_start - ref_seek_start) + ref->input_ts_offset; + + self->ts_offset += adjustment; + + av_log(NULL, AV_LOG_INFO, "Adjusted ts offset for Input #%d by %"PRId64" us to sync with Input #%d.\n", i, adjustment, self->input_sync_ref); + } else { + av_log(NULL, AV_LOG_INFO, "Unable to identify start times for Inputs #%d and %d both. No sync adjustment made.\n", i, self->input_sync_ref); + } + } + + return 0; +} + static int opt_filter_threads(void *optctx, const char *opt, const char *arg) { av_free(filter_nbthreads); @@ -507,7 +591,7 @@ static int opt_map_channel(void *optctx, const char *opt, const char *arg) /* allow trailing ? to map_channel */ if (allow_unused = strchr(mapchan, '?')) *allow_unused = 0; - if (m->channel_idx < 0 || m->channel_idx >= st->codecpar->channels || + if (m->channel_idx < 0 || m->channel_idx >= st->codecpar->ch_layout.nb_channels || input_streams[input_files[m->file_idx]->ist_index + m->stream_idx]->user_set_discard == AVDISCARD_ALL) { if (allow_unused) { av_log(NULL, AV_LOG_VERBOSE, "mapchan: invalid audio channel #%d.%d.%d\n", @@ -784,7 +868,7 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) for (i = 0; i < ic->nb_streams; i++) { AVStream *st = ic->streams[i]; AVCodecParameters *par = st->codecpar; - InputStream *ist = av_mallocz(sizeof(*ist)); + InputStream *ist; char *framerate = NULL, *hwaccel_device = NULL; const char *hwaccel = NULL; char *hwaccel_output_format = NULL; @@ -795,12 +879,7 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) const AVOption *discard_opt = av_opt_find(&cc, "skip_frame", NULL, 0, AV_OPT_SEARCH_FAKE_OBJ); - if (!ist) - exit_program(1); - - GROW_ARRAY(input_streams, nb_input_streams); - input_streams[nb_input_streams - 1] = ist; - + ist = ALLOC_ARRAY_ELEM(input_streams, nb_input_streams); ist->st = st; ist->file_index = nb_input_files; ist->discard = 1; @@ -1120,13 +1199,20 @@ static int open_input_file(OptionsContext *o, const char *filename) } if (o->nb_audio_channels) { const AVClass *priv_class; - /* because we set audio_channels based on both the "ac" and - * "channel_layout" options, we need to check that the specified - * demuxer actually has the "channels" option before setting it */ if (file_iformat && (priv_class = file_iformat->priv_class) && - av_opt_find(&priv_class, "channels", NULL, 0, + av_opt_find(&priv_class, "ch_layout", NULL, 0, AV_OPT_SEARCH_FAKE_OBJ)) { - av_dict_set_int(&o->g->format_opts, "channels", o->audio_channels[o->nb_audio_channels - 1].u.i, 0); + char buf[32]; + snprintf(buf, sizeof(buf), "%dC", o->audio_channels[o->nb_audio_channels - 1].u.i); + av_dict_set(&o->g->format_opts, "ch_layout", buf, 0); + } + } + if (o->nb_audio_ch_layouts) { + const AVClass *priv_class; + if (file_iformat && (priv_class = file_iformat->priv_class) && + av_opt_find(&priv_class, "ch_layout", NULL, 0, + AV_OPT_SEARCH_FAKE_OBJ)) { + av_dict_set(&o->g->format_opts, "ch_layout", o->audio_ch_layouts[o->nb_audio_ch_layouts - 1].u.str, 0); } } if (o->nb_frame_rates) { @@ -1272,6 +1358,7 @@ static int open_input_file(OptionsContext *o, const char *filename) f->ist_index = nb_input_streams - ic->nb_streams; f->start_time = o->start_time; f->recording_time = o->recording_time; + f->input_sync_ref = o->input_sync_ref; f->input_ts_offset = o->input_ts_offset; f->ts_offset = o->input_ts_offset - (copy_ts ? (start_at_zero && ic->start_time != AV_NOPTS_VALUE ? ic->start_time : 0) : timestamp); f->nb_streams = ic->nb_streams; @@ -1370,8 +1457,10 @@ static int get_preset_file_2(const char *preset_name, const char *codec_name, AV { int i, ret = -1; char filename[1000]; - const char *base[3] = { getenv("AVCONV_DATADIR"), - getenv("HOME"), + char *env_avconv_datadir = getenv_utf8("AVCONV_DATADIR"); + char *env_home = getenv_utf8("HOME"); + const char *base[3] = { env_avconv_datadir, + env_home, AVCONV_DATADIR, }; @@ -1389,6 +1478,8 @@ static int get_preset_file_2(const char *preset_name, const char *codec_name, AV ret = avio_open2(s, filename, AVIO_FLAG_READ, &int_cb, NULL); } } + freeenv_utf8(env_home); + freeenv_utf8(env_avconv_datadir); return ret; } @@ -1445,10 +1536,7 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e if (oc->nb_streams - 1 < o->nb_streamid_map) st->id = o->streamid_map[oc->nb_streams - 1]; - GROW_ARRAY(output_streams, nb_output_streams); - if (!(ost = av_mallocz(sizeof(*ost)))) - exit_program(1); - output_streams[nb_output_streams - 1] = ost; + ost = ALLOC_ARRAY_ELEM(output_streams, nb_output_streams); ost->file_index = nb_output_files - 1; ost->index = idx; @@ -1589,8 +1677,6 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e ost->max_muxing_queue_size = 128; MATCH_PER_STREAM_OPT(max_muxing_queue_size, i, ost->max_muxing_queue_size, oc, st); - ost->max_muxing_queue_size = FFMIN(ost->max_muxing_queue_size, INT_MAX / sizeof(ost->pkt)); - ost->max_muxing_queue_size *= sizeof(ost->pkt); ost->muxing_queue_data_size = 0; @@ -1617,10 +1703,13 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e } ost->last_mux_dts = AV_NOPTS_VALUE; - ost->muxing_queue = av_fifo_alloc(8 * sizeof(AVPacket)); + ost->muxing_queue = av_fifo_alloc2(8, sizeof(AVPacket*), 0); if (!ost->muxing_queue) exit_program(1); + MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i, + ost->copy_initial_nonkeyframes, oc, st); + return ost; } @@ -1859,7 +1948,7 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in snprintf(logfilename, sizeof(logfilename), "%s-%d.log", ost->logfile_prefix ? ost->logfile_prefix : DEFAULT_PASS_LOGFILENAME_PREFIX, - i); + nb_output_streams - 1); if (!strcmp(ost->enc->name, "libx264")) { av_dict_set(&ost->encoder_opts, "stats", logfilename, AV_DICT_DONT_OVERWRITE); } else { @@ -1874,7 +1963,7 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in video_enc->stats_in = logbuffer; } if (video_enc->flags & AV_CODEC_FLAG_PASS1) { - f = av_fopen_utf8(logfilename, "wb"); + f = fopen_utf8(logfilename, "wb"); if (!f) { av_log(NULL, AV_LOG_FATAL, "Cannot write log file '%s' for pass-1 encoding: %s\n", @@ -1896,6 +1985,10 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in MATCH_PER_STREAM_OPT(top_field_first, i, ost->top_field_first, oc, st); ost->vsync_method = video_sync_method; + MATCH_PER_STREAM_OPT(fps_mode, str, ost->fps_mode, oc, st); + if (ost->fps_mode) + parse_and_set_vsync(ost->fps_mode, &ost->vsync_method, ost->file_index, ost->index, 0); + if (ost->vsync_method == VSYNC_AUTO) { if (!strcmp(oc->oformat->name, "avi")) { ost->vsync_method = VSYNC_VFR; @@ -1927,8 +2020,6 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in ost->last_frame = av_frame_alloc(); if (!ost->last_frame) exit_program(1); - } else { - MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i, ost->copy_initial_nonkeyframes, oc ,st); } if (ost->stream_copy) @@ -1954,9 +2045,36 @@ static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext *oc, in MATCH_PER_STREAM_OPT(filters, str, ost->filters, oc, st); if (!ost->stream_copy) { + int channels = 0; + char *layout = NULL; char *sample_fmt = NULL; - MATCH_PER_STREAM_OPT(audio_channels, i, audio_enc->channels, oc, st); + MATCH_PER_STREAM_OPT(audio_channels, i, channels, oc, st); + if (channels) { + audio_enc->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + audio_enc->ch_layout.nb_channels = channels; + } + + MATCH_PER_STREAM_OPT(audio_ch_layouts, str, layout, oc, st); + if (layout) { + if (av_channel_layout_from_string(&audio_enc->ch_layout, layout) < 0) { +#if FF_API_OLD_CHANNEL_LAYOUT + uint64_t mask; + AV_NOWARN_DEPRECATED({ + mask = av_get_channel_layout(layout); + }) + if (!mask) { +#endif + av_log(NULL, AV_LOG_FATAL, "Unknown channel layout: %s\n", layout); + exit_program(1); +#if FF_API_OLD_CHANNEL_LAYOUT + } + av_log(NULL, AV_LOG_WARNING, "Channel layout '%s' uses a deprecated syntax.\n", + layout); + av_channel_layout_from_mask(&audio_enc->ch_layout, mask); +#endif + } + } MATCH_PER_STREAM_OPT(sample_fmts, str, sample_fmt, oc, st); if (sample_fmt && @@ -2056,8 +2174,6 @@ static OutputStream *new_subtitle_stream(OptionsContext *o, AVFormatContext *oc, subtitle_enc->codec_type = AVMEDIA_TYPE_SUBTITLE; - MATCH_PER_STREAM_OPT(copy_initial_nonkeyframes, i, ost->copy_initial_nonkeyframes, oc, st); - if (!ost->stream_copy) { char *frame_size = NULL; @@ -2094,10 +2210,10 @@ static int opt_streamid(void *optctx, const char *opt, const char *arg) return 0; } -static int copy_chapters(InputFile *ifile, OutputFile *ofile, int copy_metadata) +static int copy_chapters(InputFile *ifile, OutputFile *ofile, AVFormatContext *os, + int copy_metadata) { AVFormatContext *is = ifile->ctx; - AVFormatContext *os = ofile->ctx; AVChapter **tmp; int i; @@ -2137,14 +2253,14 @@ static int copy_chapters(InputFile *ifile, OutputFile *ofile, int copy_metadata) return 0; } -static int set_dispositions(OutputFile *of) +static int set_dispositions(OutputFile *of, AVFormatContext *ctx) { int nb_streams[AVMEDIA_TYPE_NB] = { 0 }; int have_default[AVMEDIA_TYPE_NB] = { 0 }; int have_manual = 0; // first, copy the input dispositions - for (int i = 0; i< of->ctx->nb_streams; i++) { + for (int i = 0; i < ctx->nb_streams; i++) { OutputStream *ost = output_streams[of->ost_index + i]; nb_streams[ost->st->codecpar->codec_type]++; @@ -2161,7 +2277,7 @@ static int set_dispositions(OutputFile *of) if (have_manual) { // process manually set dispositions - they override the above copy - for (int i = 0; i< of->ctx->nb_streams; i++) { + for (int i = 0; i < ctx->nb_streams; i++) { OutputStream *ost = output_streams[of->ost_index + i]; int ret; @@ -2187,7 +2303,7 @@ static int set_dispositions(OutputFile *of) // For each media type with more than one stream, find a suitable stream to // mark as default, unless one is already marked default. // "Suitable" means the first of that type, skipping attached pictures. - for (int i = 0; i< of->ctx->nb_streams; i++) { + for (int i = 0; i < ctx->nb_streams; i++) { OutputStream *ost = output_streams[of->ost_index + i]; enum AVMediaType type = ost->st->codecpar->codec_type; @@ -2283,6 +2399,7 @@ static int open_output_file(OptionsContext *o, const char *filename) of = ALLOC_ARRAY_ELEM(output_files, nb_output_files); + of->index = nb_output_files - 1; of->ost_index = nb_output_streams; of->recording_time = o->recording_time; of->start_time = o->start_time; @@ -2300,6 +2417,7 @@ static int open_output_file(OptionsContext *o, const char *filename) } of->ctx = oc; + of->format = oc->oformat; if (o->recording_time != INT64_MAX) oc->duration = o->recording_time; @@ -2378,7 +2496,7 @@ static int open_output_file(OptionsContext *o, const char *filename) for (i = 0; i < ifile->nb_streams; i++) { int score; ist = input_streams[ifile->ist_index + i]; - score = ist->st->codecpar->channels + score = ist->st->codecpar->ch_layout.nb_channels + 100000000 * !!(ist->st->event_flags & AVSTREAM_EVENT_FLAG_NEW_PACKETS) + 5000000*!!(ist->st->disposition & AV_DISPOSITION_DEFAULT); if (ist->user_set_discard == AVDISCARD_ALL) @@ -2612,6 +2730,7 @@ loop_end: if (ost->encoding_needed && ost->source_index >= 0) { InputStream *ist = input_streams[ost->source_index]; ist->decoding_needed |= DECODING_FOR_OST; + ist->processing_needed = 1; if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { @@ -2624,6 +2743,9 @@ loop_end: exit_program(1); } } + } else if (ost->stream_copy && ost->source_index >= 0) { + InputStream *ist = input_streams[ost->source_index]; + ist->processing_needed = 1; } /* set the filter output constraints */ @@ -2651,10 +2773,10 @@ loop_end: } else { f->sample_rates = ost->enc->supported_samplerates; } - if (ost->enc_ctx->channels) { - f->channel_layout = av_get_default_channel_layout(ost->enc_ctx->channels); - } else { - f->channel_layouts = ost->enc->channel_layouts; + if (ost->enc_ctx->ch_layout.nb_channels) { + av_channel_layout_default(&f->ch_layout, ost->enc_ctx->ch_layout.nb_channels); + } else if (ost->enc->ch_layouts) { + f->ch_layouts = ost->enc->ch_layouts; } break; } @@ -2725,7 +2847,7 @@ loop_end: } } if (o->chapters_input_file >= 0) - copy_chapters(input_files[o->chapters_input_file], of, + copy_chapters(input_files[o->chapters_input_file], of, oc, !o->metadata_chapters_manual); /* copy global metadata by default */ @@ -2878,7 +3000,7 @@ loop_end: } } - err = set_dispositions(of); + err = set_dispositions(of, oc); if (err < 0) { av_log(NULL, AV_LOG_FATAL, "Error setting output stream dispositions\n"); exit_program(1); @@ -3210,16 +3332,8 @@ static int opt_audio_filters(void *optctx, const char *opt, const char *arg) static int opt_vsync(void *optctx, const char *opt, const char *arg) { - if (!av_strcasecmp(arg, "cfr")) video_sync_method = VSYNC_CFR; - else if (!av_strcasecmp(arg, "vfr")) video_sync_method = VSYNC_VFR; - else if (!av_strcasecmp(arg, "passthrough")) video_sync_method = VSYNC_PASSTHROUGH; - else if (!av_strcasecmp(arg, "drop")) video_sync_method = VSYNC_DROP; - - if (video_sync_method == VSYNC_AUTO) { - video_sync_method = parse_number_or_die("vsync", arg, OPT_INT, VSYNC_AUTO, VSYNC_VFR); - av_log(NULL, AV_LOG_WARNING, "Passing a number to -vsync is deprecated," - " use a string argument as described in the manual.\n"); - } + av_log(NULL, AV_LOG_WARNING, "-vsync is deprecated. Use -fps_mode\n"); + parse_and_set_vsync(arg, &video_sync_method, -1, -1, 1); return 0; } @@ -3237,42 +3351,6 @@ static int opt_timecode(void *optctx, const char *opt, const char *arg) return ret; } -static int opt_channel_layout(void *optctx, const char *opt, const char *arg) -{ - OptionsContext *o = optctx; - char layout_str[32]; - char *stream_str; - char *ac_str; - int ret, channels, ac_str_size; - uint64_t layout; - - layout = av_get_channel_layout(arg); - if (!layout) { - av_log(NULL, AV_LOG_ERROR, "Unknown channel layout: %s\n", arg); - return AVERROR(EINVAL); - } - snprintf(layout_str, sizeof(layout_str), "%"PRIu64, layout); - ret = opt_default_new(o, opt, layout_str); - if (ret < 0) - return ret; - - /* set 'ac' option based on channel layout */ - channels = av_get_channel_layout_nb_channels(layout); - snprintf(layout_str, sizeof(layout_str), "%d", channels); - stream_str = strchr(opt, ':'); - ac_str_size = 3 + (stream_str ? strlen(stream_str) : 0); - ac_str = av_mallocz(ac_str_size); - if (!ac_str) - return AVERROR(ENOMEM); - av_strlcpy(ac_str, "ac", 3); - if (stream_str) - av_strlcat(ac_str, stream_str, ac_str_size); - ret = parse_option(o, ac_str, layout_str, options); - av_free(ac_str); - - return ret; -} - static int opt_audio_qscale(void *optctx, const char *opt, const char *arg) { OptionsContext *o = optctx; @@ -3281,9 +3359,8 @@ static int opt_audio_qscale(void *optctx, const char *opt, const char *arg) static int opt_filter_complex(void *optctx, const char *opt, const char *arg) { - FilterGraph *fg; - ALLOC_ARRAY_ELEM(filtergraphs, nb_filtergraphs); - fg = filtergraphs[nb_filtergraphs - 1]; + FilterGraph *fg = ALLOC_ARRAY_ELEM(filtergraphs, nb_filtergraphs); + fg->index = nb_filtergraphs - 1; fg->graph_desc = av_strdup(arg); if (!fg->graph_desc) @@ -3466,6 +3543,8 @@ int ffmpeg_parse_options(int argc, char **argv) goto fail; } + apply_sync_offsets(); + /* create the complex filtergraphs */ ret = init_complex_filters(); if (ret < 0) { @@ -3508,6 +3587,19 @@ static int opt_progress(void *optctx, const char *opt, const char *arg) return 0; } +int opt_timelimit(void *optctx, const char *opt, const char *arg) +{ +#if HAVE_SETRLIMIT + int lim = parse_number_or_die(opt, arg, OPT_INT64, 0, INT_MAX); + struct rlimit rl = { lim, lim + 1 }; + if (setrlimit(RLIMIT_CPU, &rl)) + perror("setrlimit"); +#else + av_log(NULL, AV_LOG_WARNING, "-%s not implemented on this OS\n", opt); +#endif + return 0; +} + #define OFFSET(x) offsetof(OptionsContext, x) const OptionDef options[] = { /* main options */ @@ -3567,6 +3659,9 @@ const OptionDef options[] = { { "accurate_seek", OPT_BOOL | OPT_OFFSET | OPT_EXPERT | OPT_INPUT, { .off = OFFSET(accurate_seek) }, "enable/disable accurate seeking with -ss" }, + { "isync", HAS_ARG | OPT_INT | OPT_OFFSET | + OPT_EXPERT | OPT_INPUT, { .off = OFFSET(input_sync_ref) }, + "Indicate the input index for sync reference", "sync ref" }, { "itsoffset", HAS_ARG | OPT_TIME | OPT_OFFSET | OPT_EXPERT | OPT_INPUT, { .off = OFFSET(input_ts_offset) }, "set the input ts offset", "time_off" }, @@ -3606,7 +3701,7 @@ const OptionDef options[] = { "specify target file type (\"vcd\", \"svcd\", \"dvd\", \"dv\" or \"dv50\" " "with optional prefixes \"pal-\", \"ntsc-\" or \"film-\")", "type" }, { "vsync", HAS_ARG | OPT_EXPERT, { .func_arg = opt_vsync }, - "video sync method", "" }, + "set video sync method globally; deprecated, use -fps_mode", "" }, { "frame_drop_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, { &frame_drop_threshold }, "frame drop threshold", "" }, { "async", HAS_ARG | OPT_INT | OPT_EXPERT, { &audio_sync_method }, @@ -3763,6 +3858,9 @@ const OptionDef options[] = { "force video tag/fourcc", "fourcc/tag" }, { "qphist", OPT_VIDEO | OPT_BOOL | OPT_EXPERT , { &qp_hist }, "show QP histogram" }, + { "fps_mode", OPT_VIDEO | HAS_ARG | OPT_STRING | OPT_EXPERT | + OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(fps_mode) }, + "set framerate mode for matching video streams; overrides vsync" }, { "force_fps", OPT_VIDEO | OPT_BOOL | OPT_EXPERT | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(force_fps) }, "force the selected framerate, disable the best supported framerate selection" }, @@ -3818,8 +3916,11 @@ const OptionDef options[] = { { "sample_fmt", OPT_AUDIO | HAS_ARG | OPT_EXPERT | OPT_SPEC | OPT_STRING | OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(sample_fmts) }, "set sample format", "format" }, - { "channel_layout", OPT_AUDIO | HAS_ARG | OPT_EXPERT | OPT_PERFILE | - OPT_INPUT | OPT_OUTPUT, { .func_arg = opt_channel_layout }, + { "channel_layout", OPT_AUDIO | HAS_ARG | OPT_EXPERT | OPT_SPEC | + OPT_STRING | OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(audio_ch_layouts) }, + "set channel layout", "layout" }, + { "ch_layout", OPT_AUDIO | HAS_ARG | OPT_EXPERT | OPT_SPEC | + OPT_STRING | OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(audio_ch_layouts) }, "set channel layout", "layout" }, { "af", OPT_AUDIO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_audio_filters }, "set audio filters", "filter_graph" }, diff --git a/fftools/ffplay.c b/fftools/ffplay.c index e7b20be76..9242047f5 100644 --- a/fftools/ffplay.c +++ b/fftools/ffplay.c @@ -24,6 +24,7 @@ */ #include "config.h" +#include "config_components.h" #include #include #include @@ -59,6 +60,7 @@ #include #include "cmdutils.h" +#include "opt_common.h" const char program_name[] = "ffplay"; const int program_birth_year = 2003; @@ -115,7 +117,7 @@ typedef struct MyAVPacketList { } MyAVPacketList; typedef struct PacketQueue { - AVFifoBuffer *pkt_list; + AVFifo *pkt_list; int nb_packets; int size; int64_t duration; @@ -132,8 +134,7 @@ typedef struct PacketQueue { typedef struct AudioParams { int freq; - int channels; - int64_t channel_layout; + AVChannelLayout ch_layout; enum AVSampleFormat fmt; int frame_size; int bytes_per_sec; @@ -412,31 +413,21 @@ int cmp_audio_fmts(enum AVSampleFormat fmt1, int64_t channel_count1, return channel_count1 != channel_count2 || fmt1 != fmt2; } -static inline -int64_t get_valid_channel_layout(int64_t channel_layout, int channels) -{ - if (channel_layout && av_get_channel_layout_nb_channels(channel_layout) == channels) - return channel_layout; - else - return 0; -} - static int packet_queue_put_private(PacketQueue *q, AVPacket *pkt) { MyAVPacketList pkt1; + int ret; if (q->abort_request) return -1; - if (av_fifo_space(q->pkt_list) < sizeof(pkt1)) { - if (av_fifo_grow(q->pkt_list, sizeof(pkt1)) < 0) - return -1; - } pkt1.pkt = pkt; pkt1.serial = q->serial; - av_fifo_generic_write(q->pkt_list, &pkt1, sizeof(pkt1), NULL); + ret = av_fifo_write(q->pkt_list, &pkt1, 1); + if (ret < 0) + return ret; q->nb_packets++; q->size += pkt1.pkt->size + sizeof(pkt1); q->duration += pkt1.pkt->duration; @@ -477,7 +468,7 @@ static int packet_queue_put_nullpacket(PacketQueue *q, AVPacket *pkt, int stream static int packet_queue_init(PacketQueue *q) { memset(q, 0, sizeof(PacketQueue)); - q->pkt_list = av_fifo_alloc(sizeof(MyAVPacketList)); + q->pkt_list = av_fifo_alloc2(1, sizeof(MyAVPacketList), AV_FIFO_FLAG_AUTO_GROW); if (!q->pkt_list) return AVERROR(ENOMEM); q->mutex = SDL_CreateMutex(); @@ -499,10 +490,8 @@ static void packet_queue_flush(PacketQueue *q) MyAVPacketList pkt1; SDL_LockMutex(q->mutex); - while (av_fifo_size(q->pkt_list) >= sizeof(pkt1)) { - av_fifo_generic_read(q->pkt_list, &pkt1, sizeof(pkt1), NULL); + while (av_fifo_read(q->pkt_list, &pkt1, 1) >= 0) av_packet_free(&pkt1.pkt); - } q->nb_packets = 0; q->size = 0; q->duration = 0; @@ -513,7 +502,7 @@ static void packet_queue_flush(PacketQueue *q) static void packet_queue_destroy(PacketQueue *q) { packet_queue_flush(q); - av_fifo_freep(&q->pkt_list); + av_fifo_freep2(&q->pkt_list); SDL_DestroyMutex(q->mutex); SDL_DestroyCond(q->cond); } @@ -551,8 +540,7 @@ static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block, int *seria break; } - if (av_fifo_size(q->pkt_list) >= sizeof(pkt1)) { - av_fifo_generic_read(q->pkt_list, &pkt1, sizeof(pkt1), NULL); + if (av_fifo_read(q->pkt_list, &pkt1, 1) >= 0) { q->nb_packets--; q->size -= pkt1.pkt->size + sizeof(pkt1); q->duration -= pkt1.pkt->duration; @@ -1023,15 +1011,17 @@ static void video_image_display(VideoState *is) } calculate_display_rect(&rect, is->xleft, is->ytop, is->width, is->height, vp->width, vp->height, vp->sar); + set_sdl_yuv_conversion_mode(vp->frame); if (!vp->uploaded) { - if (upload_texture(&is->vid_texture, vp->frame, &is->img_convert_ctx) < 0) + if (upload_texture(&is->vid_texture, vp->frame, &is->img_convert_ctx) < 0) { + set_sdl_yuv_conversion_mode(NULL); return; + } vp->uploaded = 1; vp->flip_v = vp->frame->linesize[0] < 0; } - set_sdl_yuv_conversion_mode(vp->frame); SDL_RenderCopyEx(renderer, is->vid_texture, NULL, &rect, 0, NULL, vp->flip_v ? SDL_FLIP_VERTICAL : 0); set_sdl_yuv_conversion_mode(NULL); if (sp) { @@ -1070,7 +1060,7 @@ static void video_audio_display(VideoState *s) nb_freq = 1 << (rdft_bits - 1); /* compute display index : center on currently output samples */ - channels = s->audio_tgt.channels; + channels = s->audio_tgt.ch_layout.nb_channels; nb_display_channels = channels; if (!s->paused) { int data_used= s->show_mode == SHOW_MODE_WAVES ? s->width : (2*nb_freq); @@ -1468,13 +1458,13 @@ static void check_external_clock_speed(VideoState *is) { } /* seek in the stream */ -static void stream_seek(VideoState *is, int64_t pos, int64_t rel, int seek_by_bytes) +static void stream_seek(VideoState *is, int64_t pos, int64_t rel, int by_bytes) { if (!is->seek_req) { is->seek_pos = pos; is->seek_rel = rel; is->seek_flags &= ~AVSEEK_FLAG_BYTE; - if (seek_by_bytes) + if (by_bytes) is->seek_flags |= AVSEEK_FLAG_BYTE; is->seek_req = 1; SDL_CondSignal(is->continue_read_thread); @@ -1956,11 +1946,10 @@ static int configure_audio_filters(VideoState *is, const char *afilters, int for { static const enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }; int sample_rates[2] = { 0, -1 }; - int64_t channel_layouts[2] = { 0, -1 }; - int channels[2] = { 0, -1 }; AVFilterContext *filt_asrc = NULL, *filt_asink = NULL; char aresample_swr_opts[512] = ""; const AVDictionaryEntry *e = NULL; + AVBPrint bp; char asrc_args[256]; int ret; @@ -1969,20 +1958,20 @@ static int configure_audio_filters(VideoState *is, const char *afilters, int for return AVERROR(ENOMEM); is->agraph->nb_threads = filter_nbthreads; + av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC); + while ((e = av_dict_get(swr_opts, "", e, AV_DICT_IGNORE_SUFFIX))) av_strlcatf(aresample_swr_opts, sizeof(aresample_swr_opts), "%s=%s:", e->key, e->value); if (strlen(aresample_swr_opts)) aresample_swr_opts[strlen(aresample_swr_opts)-1] = '\0'; av_opt_set(is->agraph, "aresample_swr_opts", aresample_swr_opts, 0); + av_channel_layout_describe_bprint(&is->audio_filter_src.ch_layout, &bp); + ret = snprintf(asrc_args, sizeof(asrc_args), - "sample_rate=%d:sample_fmt=%s:channels=%d:time_base=%d/%d", + "sample_rate=%d:sample_fmt=%s:time_base=%d/%d:channel_layout=%s", is->audio_filter_src.freq, av_get_sample_fmt_name(is->audio_filter_src.fmt), - is->audio_filter_src.channels, - 1, is->audio_filter_src.freq); - if (is->audio_filter_src.channel_layout) - snprintf(asrc_args + ret, sizeof(asrc_args) - ret, - ":channel_layout=0x%"PRIx64, is->audio_filter_src.channel_layout); + 1, is->audio_filter_src.freq, bp.str); ret = avfilter_graph_create_filter(&filt_asrc, avfilter_get_by_name("abuffer"), "ffplay_abuffer", @@ -2003,14 +1992,10 @@ static int configure_audio_filters(VideoState *is, const char *afilters, int for goto end; if (force_output_format) { - channel_layouts[0] = is->audio_tgt.channel_layout; - channels [0] = is->audio_tgt.channel_layout ? -1 : is->audio_tgt.channels; sample_rates [0] = is->audio_tgt.freq; if ((ret = av_opt_set_int(filt_asink, "all_channel_counts", 0, AV_OPT_SEARCH_CHILDREN)) < 0) goto end; - if ((ret = av_opt_set_int_list(filt_asink, "channel_layouts", channel_layouts, -1, AV_OPT_SEARCH_CHILDREN)) < 0) - goto end; - if ((ret = av_opt_set_int_list(filt_asink, "channel_counts" , channels , -1, AV_OPT_SEARCH_CHILDREN)) < 0) + if ((ret = av_opt_set(filt_asink, "ch_layouts", bp.str, AV_OPT_SEARCH_CHILDREN)) < 0) goto end; if ((ret = av_opt_set_int_list(filt_asink, "sample_rates" , sample_rates , -1, AV_OPT_SEARCH_CHILDREN)) < 0) goto end; @@ -2026,6 +2011,8 @@ static int configure_audio_filters(VideoState *is, const char *afilters, int for end: if (ret < 0) avfilter_graph_free(&is->agraph); + av_bprint_finalize(&bp, NULL); + return ret; } #endif /* CONFIG_AVFILTER */ @@ -2037,7 +2024,6 @@ static int audio_thread(void *arg) Frame *af; #if CONFIG_AVFILTER int last_serial = -1; - int64_t dec_channel_layout; int reconfigure; #endif int got_frame = 0; @@ -2055,27 +2041,26 @@ static int audio_thread(void *arg) tb = (AVRational){1, frame->sample_rate}; #if CONFIG_AVFILTER - dec_channel_layout = get_valid_channel_layout(frame->channel_layout, frame->channels); - reconfigure = - cmp_audio_fmts(is->audio_filter_src.fmt, is->audio_filter_src.channels, - frame->format, frame->channels) || - is->audio_filter_src.channel_layout != dec_channel_layout || + cmp_audio_fmts(is->audio_filter_src.fmt, is->audio_filter_src.ch_layout.nb_channels, + frame->format, frame->ch_layout.nb_channels) || + av_channel_layout_compare(&is->audio_filter_src.ch_layout, &frame->ch_layout) || is->audio_filter_src.freq != frame->sample_rate || is->auddec.pkt_serial != last_serial; if (reconfigure) { char buf1[1024], buf2[1024]; - av_get_channel_layout_string(buf1, sizeof(buf1), -1, is->audio_filter_src.channel_layout); - av_get_channel_layout_string(buf2, sizeof(buf2), -1, dec_channel_layout); + av_channel_layout_describe(&is->audio_filter_src.ch_layout, buf1, sizeof(buf1)); + av_channel_layout_describe(&frame->ch_layout, buf2, sizeof(buf2)); av_log(NULL, AV_LOG_DEBUG, "Audio frame changed from rate:%d ch:%d fmt:%s layout:%s serial:%d to rate:%d ch:%d fmt:%s layout:%s serial:%d\n", - is->audio_filter_src.freq, is->audio_filter_src.channels, av_get_sample_fmt_name(is->audio_filter_src.fmt), buf1, last_serial, - frame->sample_rate, frame->channels, av_get_sample_fmt_name(frame->format), buf2, is->auddec.pkt_serial); + is->audio_filter_src.freq, is->audio_filter_src.ch_layout.nb_channels, av_get_sample_fmt_name(is->audio_filter_src.fmt), buf1, last_serial, + frame->sample_rate, frame->ch_layout.nb_channels, av_get_sample_fmt_name(frame->format), buf2, is->auddec.pkt_serial); is->audio_filter_src.fmt = frame->format; - is->audio_filter_src.channels = frame->channels; - is->audio_filter_src.channel_layout = dec_channel_layout; + ret = av_channel_layout_copy(&is->audio_filter_src.ch_layout, &frame->ch_layout); + if (ret < 0) + goto the_end; is->audio_filter_src.freq = frame->sample_rate; last_serial = is->auddec.pkt_serial; @@ -2341,7 +2326,6 @@ static int synchronize_audio(VideoState *is, int nb_samples) static int audio_decode_frame(VideoState *is) { int data_size, resampled_data_size; - int64_t dec_channel_layout; av_unused double audio_clock0; int wanted_nb_samples; Frame *af; @@ -2362,34 +2346,31 @@ static int audio_decode_frame(VideoState *is) frame_queue_next(&is->sampq); } while (af->serial != is->audioq.serial); - data_size = av_samples_get_buffer_size(NULL, af->frame->channels, + data_size = av_samples_get_buffer_size(NULL, af->frame->ch_layout.nb_channels, af->frame->nb_samples, af->frame->format, 1); - dec_channel_layout = - (af->frame->channel_layout && af->frame->channels == av_get_channel_layout_nb_channels(af->frame->channel_layout)) ? - af->frame->channel_layout : av_get_default_channel_layout(af->frame->channels); wanted_nb_samples = synchronize_audio(is, af->frame->nb_samples); if (af->frame->format != is->audio_src.fmt || - dec_channel_layout != is->audio_src.channel_layout || + av_channel_layout_compare(&af->frame->ch_layout, &is->audio_src.ch_layout) || af->frame->sample_rate != is->audio_src.freq || (wanted_nb_samples != af->frame->nb_samples && !is->swr_ctx)) { swr_free(&is->swr_ctx); - is->swr_ctx = swr_alloc_set_opts(NULL, - is->audio_tgt.channel_layout, is->audio_tgt.fmt, is->audio_tgt.freq, - dec_channel_layout, af->frame->format, af->frame->sample_rate, - 0, NULL); + swr_alloc_set_opts2(&is->swr_ctx, + &is->audio_tgt.ch_layout, is->audio_tgt.fmt, is->audio_tgt.freq, + &af->frame->ch_layout, af->frame->format, af->frame->sample_rate, + 0, NULL); if (!is->swr_ctx || swr_init(is->swr_ctx) < 0) { av_log(NULL, AV_LOG_ERROR, "Cannot create sample rate converter for conversion of %d Hz %s %d channels to %d Hz %s %d channels!\n", - af->frame->sample_rate, av_get_sample_fmt_name(af->frame->format), af->frame->channels, - is->audio_tgt.freq, av_get_sample_fmt_name(is->audio_tgt.fmt), is->audio_tgt.channels); + af->frame->sample_rate, av_get_sample_fmt_name(af->frame->format), af->frame->ch_layout.nb_channels, + is->audio_tgt.freq, av_get_sample_fmt_name(is->audio_tgt.fmt), is->audio_tgt.ch_layout.nb_channels); swr_free(&is->swr_ctx); return -1; } - is->audio_src.channel_layout = dec_channel_layout; - is->audio_src.channels = af->frame->channels; + if (av_channel_layout_copy(&is->audio_src.ch_layout, &af->frame->ch_layout) < 0) + return -1; is->audio_src.freq = af->frame->sample_rate; is->audio_src.fmt = af->frame->format; } @@ -2398,7 +2379,7 @@ static int audio_decode_frame(VideoState *is) const uint8_t **in = (const uint8_t **)af->frame->extended_data; uint8_t **out = &is->audio_buf1; int out_count = (int64_t)wanted_nb_samples * is->audio_tgt.freq / af->frame->sample_rate + 256; - int out_size = av_samples_get_buffer_size(NULL, is->audio_tgt.channels, out_count, is->audio_tgt.fmt, 0); + int out_size = av_samples_get_buffer_size(NULL, is->audio_tgt.ch_layout.nb_channels, out_count, is->audio_tgt.fmt, 0); int len2; if (out_size < 0) { av_log(NULL, AV_LOG_ERROR, "av_samples_get_buffer_size() failed\n"); @@ -2425,7 +2406,7 @@ static int audio_decode_frame(VideoState *is) swr_free(&is->swr_ctx); } is->audio_buf = is->audio_buf1; - resampled_data_size = len2 * is->audio_tgt.channels * av_get_bytes_per_sample(is->audio_tgt.fmt); + resampled_data_size = len2 * is->audio_tgt.ch_layout.nb_channels * av_get_bytes_per_sample(is->audio_tgt.fmt); } else { is->audio_buf = af->frame->data[0]; resampled_data_size = data_size; @@ -2494,24 +2475,26 @@ static void sdl_audio_callback(void *opaque, Uint8 *stream, int len) } } -static int audio_open(void *opaque, int64_t wanted_channel_layout, int wanted_nb_channels, int wanted_sample_rate, struct AudioParams *audio_hw_params) +static int audio_open(void *opaque, AVChannelLayout *wanted_channel_layout, int wanted_sample_rate, struct AudioParams *audio_hw_params) { SDL_AudioSpec wanted_spec, spec; const char *env; static const int next_nb_channels[] = {0, 0, 1, 6, 2, 6, 4, 6}; static const int next_sample_rates[] = {0, 44100, 48000, 96000, 192000}; int next_sample_rate_idx = FF_ARRAY_ELEMS(next_sample_rates) - 1; + int wanted_nb_channels = wanted_channel_layout->nb_channels; env = SDL_getenv("SDL_AUDIO_CHANNELS"); if (env) { wanted_nb_channels = atoi(env); - wanted_channel_layout = av_get_default_channel_layout(wanted_nb_channels); + av_channel_layout_uninit(wanted_channel_layout); + av_channel_layout_default(wanted_channel_layout, wanted_nb_channels); } - if (!wanted_channel_layout || wanted_nb_channels != av_get_channel_layout_nb_channels(wanted_channel_layout)) { - wanted_channel_layout = av_get_default_channel_layout(wanted_nb_channels); - wanted_channel_layout &= ~AV_CH_LAYOUT_STEREO_DOWNMIX; + if (wanted_channel_layout->order != AV_CHANNEL_ORDER_NATIVE) { + av_channel_layout_uninit(wanted_channel_layout); + av_channel_layout_default(wanted_channel_layout, wanted_nb_channels); } - wanted_nb_channels = av_get_channel_layout_nb_channels(wanted_channel_layout); + wanted_nb_channels = wanted_channel_layout->nb_channels; wanted_spec.channels = wanted_nb_channels; wanted_spec.freq = wanted_sample_rate; if (wanted_spec.freq <= 0 || wanted_spec.channels <= 0) { @@ -2538,7 +2521,7 @@ static int audio_open(void *opaque, int64_t wanted_channel_layout, int wanted_nb return -1; } } - wanted_channel_layout = av_get_default_channel_layout(wanted_spec.channels); + av_channel_layout_default(wanted_channel_layout, wanted_spec.channels); } if (spec.format != AUDIO_S16SYS) { av_log(NULL, AV_LOG_ERROR, @@ -2546,8 +2529,9 @@ static int audio_open(void *opaque, int64_t wanted_channel_layout, int wanted_nb return -1; } if (spec.channels != wanted_spec.channels) { - wanted_channel_layout = av_get_default_channel_layout(spec.channels); - if (!wanted_channel_layout) { + av_channel_layout_uninit(wanted_channel_layout); + av_channel_layout_default(wanted_channel_layout, spec.channels); + if (wanted_channel_layout->order != AV_CHANNEL_ORDER_NATIVE) { av_log(NULL, AV_LOG_ERROR, "SDL advised channel count %d is not supported!\n", spec.channels); return -1; @@ -2556,10 +2540,10 @@ static int audio_open(void *opaque, int64_t wanted_channel_layout, int wanted_nb audio_hw_params->fmt = AV_SAMPLE_FMT_S16; audio_hw_params->freq = spec.freq; - audio_hw_params->channel_layout = wanted_channel_layout; - audio_hw_params->channels = spec.channels; - audio_hw_params->frame_size = av_samples_get_buffer_size(NULL, audio_hw_params->channels, 1, audio_hw_params->fmt, 1); - audio_hw_params->bytes_per_sec = av_samples_get_buffer_size(NULL, audio_hw_params->channels, audio_hw_params->freq, audio_hw_params->fmt, 1); + if (av_channel_layout_copy(&audio_hw_params->ch_layout, wanted_channel_layout) < 0) + return -1; + audio_hw_params->frame_size = av_samples_get_buffer_size(NULL, audio_hw_params->ch_layout.nb_channels, 1, audio_hw_params->fmt, 1); + audio_hw_params->bytes_per_sec = av_samples_get_buffer_size(NULL, audio_hw_params->ch_layout.nb_channels, audio_hw_params->freq, audio_hw_params->fmt, 1); if (audio_hw_params->bytes_per_sec <= 0 || audio_hw_params->frame_size <= 0) { av_log(NULL, AV_LOG_ERROR, "av_samples_get_buffer_size failed\n"); return -1; @@ -2576,8 +2560,8 @@ static int stream_component_open(VideoState *is, int stream_index) const char *forced_codec_name = NULL; AVDictionary *opts = NULL; const AVDictionaryEntry *t = NULL; - int sample_rate, nb_channels; - int64_t channel_layout; + int sample_rate; + AVChannelLayout ch_layout = { 0 }; int ret = 0; int stream_lowres = lowres; @@ -2645,24 +2629,27 @@ static int stream_component_open(VideoState *is, int stream_index) AVFilterContext *sink; is->audio_filter_src.freq = avctx->sample_rate; - is->audio_filter_src.channels = avctx->channels; - is->audio_filter_src.channel_layout = get_valid_channel_layout(avctx->channel_layout, avctx->channels); + ret = av_channel_layout_copy(&is->audio_filter_src.ch_layout, &avctx->ch_layout); + if (ret < 0) + goto fail; is->audio_filter_src.fmt = avctx->sample_fmt; if ((ret = configure_audio_filters(is, afilters, 0)) < 0) goto fail; sink = is->out_audio_filter; sample_rate = av_buffersink_get_sample_rate(sink); - nb_channels = av_buffersink_get_channels(sink); - channel_layout = av_buffersink_get_channel_layout(sink); + ret = av_buffersink_get_ch_layout(sink, &ch_layout); + if (ret < 0) + goto fail; } #else sample_rate = avctx->sample_rate; - nb_channels = avctx->channels; - channel_layout = avctx->channel_layout; + ret = av_channel_layout_copy(&ch_layout, &avctx->ch_layout); + if (ret < 0) + goto fail; #endif /* prepare audio output */ - if ((ret = audio_open(is, channel_layout, nb_channels, sample_rate, &is->audio_tgt)) < 0) + if ((ret = audio_open(is, &ch_layout, sample_rate, &is->audio_tgt)) < 0) goto fail; is->audio_hw_buf_size = ret; is->audio_src = is->audio_tgt; @@ -2716,6 +2703,7 @@ static int stream_component_open(VideoState *is, int stream_index) fail: avcodec_free_context(&avctx); out: + av_channel_layout_uninit(&ch_layout); av_dict_free(&opts); return ret; @@ -2835,7 +2823,9 @@ static int read_thread(void *arg) ic->pb->eof_reached = 0; // FIXME hack, ffplay maybe should not use avio_feof() to test for the end if (seek_by_bytes < 0) - seek_by_bytes = !!(ic->iformat->flags & AVFMT_TS_DISCONT) && strcmp("ogg", ic->iformat->name); + seek_by_bytes = !(ic->iformat->flags & AVFMT_NO_BYTE_SEEK) && + !!(ic->iformat->flags & AVFMT_TS_DISCONT) && + strcmp("ogg", ic->iformat->name); is->max_frame_duration = (ic->iformat->flags & AVFMT_TS_DISCONT) ? 10.0 : 3600.0; @@ -3188,7 +3178,7 @@ static void stream_cycle_channel(VideoState *is, int codec_type) switch (codec_type) { case AVMEDIA_TYPE_AUDIO: if (st->codecpar->sample_rate != 0 && - st->codecpar->channels != 0) + st->codecpar->ch_layout.nb_channels != 0) goto the_end; break; case AVMEDIA_TYPE_VIDEO: @@ -3474,12 +3464,6 @@ static void event_loop(VideoState *cur_stream) } } -static int opt_frame_size(void *optctx, const char *opt, const char *arg) -{ - av_log(NULL, AV_LOG_WARNING, "Option -s is deprecated, use -video_size.\n"); - return opt_default(NULL, "video_size", arg); -} - static int opt_width(void *optctx, const char *opt, const char *arg) { screen_width = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX); @@ -3502,12 +3486,6 @@ static int opt_format(void *optctx, const char *opt, const char *arg) return 0; } -static int opt_frame_pix_fmt(void *optctx, const char *opt, const char *arg) -{ - av_log(NULL, AV_LOG_WARNING, "Option -pix_fmt is deprecated, use -pixel_format.\n"); - return opt_default(NULL, "pixel_format", arg); -} - static int opt_sync(void *optctx, const char *opt, const char *arg) { if (!strcmp(arg, "audio")) @@ -3585,7 +3563,6 @@ static const OptionDef options[] = { CMDUTILS_COMMON_OPTIONS { "x", HAS_ARG, { .func_arg = opt_width }, "force displayed width", "width" }, { "y", HAS_ARG, { .func_arg = opt_height }, "force displayed height", "height" }, - { "s", HAS_ARG | OPT_VIDEO, { .func_arg = opt_frame_size }, "set frame size (WxH or abbreviation)", "size" }, { "fs", OPT_BOOL, { &is_full_screen }, "force full screen" }, { "an", OPT_BOOL, { &audio_disable }, "disable audio" }, { "vn", OPT_BOOL, { &video_disable }, "disable video" }, @@ -3602,7 +3579,6 @@ static const OptionDef options[] = { { "alwaysontop", OPT_BOOL, { &alwaysontop }, "window always on top" }, { "volume", OPT_INT | HAS_ARG, { &startup_volume}, "set startup volume 0=min 100=max", "volume" }, { "f", HAS_ARG, { .func_arg = opt_format }, "force format", "fmt" }, - { "pix_fmt", HAS_ARG | OPT_EXPERT | OPT_VIDEO, { .func_arg = opt_frame_pix_fmt }, "set pixel format", "format" }, { "stats", OPT_BOOL | OPT_EXPERT, { &show_status }, "show status", "" }, { "fast", OPT_BOOL | OPT_EXPERT, { &fast }, "non spec compliant optimizations", "" }, { "genpts", OPT_BOOL | OPT_EXPERT, { &genpts }, "generate pts", "" }, @@ -3624,7 +3600,6 @@ static const OptionDef options[] = { #endif { "rdftspeed", OPT_INT | HAS_ARG| OPT_AUDIO | OPT_EXPERT, { &rdftspeed }, "rdft speed", "msecs" }, { "showmode", HAS_ARG, { .func_arg = opt_show_mode}, "select show mode (0 = video, 1 = waves, 2 = RDFT)", "mode" }, - { "default", HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, { .func_arg = opt_default }, "generic catch all option", "" }, { "i", OPT_BOOL, { &dummy}, "read specified file", "input_file"}, { "codec", HAS_ARG, { .func_arg = opt_codec}, "force decoder", "decoder_name" }, { "acodec", HAS_ARG | OPT_STRING | OPT_EXPERT, { &audio_codec_name }, "force audio decoder", "decoder_name" }, diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index 20582ca7a..f15666301 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -29,7 +29,9 @@ #include #include "libavformat/avformat.h" +#include "libavformat/version.h" #include "libavcodec/avcodec.h" +#include "libavcodec/version.h" #include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/bprint.h" @@ -38,6 +40,7 @@ #include "libavutil/hash.h" #include "libavutil/hdr_dynamic_metadata.h" #include "libavutil/mastering_display_metadata.h" +#include "libavutil/hdr_dynamic_vivid_metadata.h" #include "libavutil/dovi_meta.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" @@ -50,10 +53,16 @@ #include "libavutil/timecode.h" #include "libavutil/timestamp.h" #include "libavdevice/avdevice.h" +#include "libavdevice/version.h" #include "libswscale/swscale.h" +#include "libswscale/version.h" #include "libswresample/swresample.h" +#include "libswresample/version.h" #include "libpostproc/postprocess.h" +#include "libpostproc/version.h" +#include "libavfilter/version.h" #include "cmdutils.h" +#include "opt_common.h" #include "libavutil/thread.h" @@ -223,7 +232,7 @@ static struct section sections[] = { [SECTION_ID_FRAME] = { SECTION_ID_FRAME, "frame", 0, { SECTION_ID_FRAME_TAGS, SECTION_ID_FRAME_SIDE_DATA_LIST, SECTION_ID_FRAME_LOGS, -1 } }, [SECTION_ID_FRAME_TAGS] = { SECTION_ID_FRAME_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "frame_tags" }, [SECTION_ID_FRAME_SIDE_DATA_LIST] ={ SECTION_ID_FRAME_SIDE_DATA_LIST, "side_data_list", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA, -1 }, .element_name = "side_data", .unique_name = "frame_side_data_list" }, - [SECTION_ID_FRAME_SIDE_DATA] = { SECTION_ID_FRAME_SIDE_DATA, "side_data", 0, { SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST, -1 } }, + [SECTION_ID_FRAME_SIDE_DATA] = { SECTION_ID_FRAME_SIDE_DATA, "side_data", 0, { SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST, -1 }, .unique_name = "frame_side_data" }, [SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST] = { SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST, "timecodes", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA_TIMECODE, -1 } }, [SECTION_ID_FRAME_SIDE_DATA_TIMECODE] = { SECTION_ID_FRAME_SIDE_DATA_TIMECODE, "timecode", 0, { -1 } }, [SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST] = { SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST, "components", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA_COMPONENT, -1 } }, @@ -239,7 +248,7 @@ static struct section sections[] = { [SECTION_ID_PACKET] = { SECTION_ID_PACKET, "packet", 0, { SECTION_ID_PACKET_TAGS, SECTION_ID_PACKET_SIDE_DATA_LIST, -1 } }, [SECTION_ID_PACKET_TAGS] = { SECTION_ID_PACKET_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "packet_tags" }, [SECTION_ID_PACKET_SIDE_DATA_LIST] ={ SECTION_ID_PACKET_SIDE_DATA_LIST, "side_data_list", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PACKET_SIDE_DATA, -1 }, .element_name = "side_data", .unique_name = "packet_side_data_list" }, - [SECTION_ID_PACKET_SIDE_DATA] = { SECTION_ID_PACKET_SIDE_DATA, "side_data", 0, { -1 } }, + [SECTION_ID_PACKET_SIDE_DATA] = { SECTION_ID_PACKET_SIDE_DATA, "side_data", 0, { -1 }, .unique_name = "packet_side_data" }, [SECTION_ID_PIXEL_FORMATS] = { SECTION_ID_PIXEL_FORMATS, "pixel_formats", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PIXEL_FORMAT, -1 } }, [SECTION_ID_PIXEL_FORMAT] = { SECTION_ID_PIXEL_FORMAT, "pixel_format", 0, { SECTION_ID_PIXEL_FORMAT_FLAGS, SECTION_ID_PIXEL_FORMAT_COMPONENTS, -1 } }, [SECTION_ID_PIXEL_FORMAT_FLAGS] = { SECTION_ID_PIXEL_FORMAT_FLAGS, "flags", 0, { -1 }, .unique_name = "pixel_format_flags" }, @@ -262,7 +271,7 @@ static struct section sections[] = { [SECTION_ID_STREAM_DISPOSITION] = { SECTION_ID_STREAM_DISPOSITION, "disposition", 0, { -1 }, .unique_name = "stream_disposition" }, [SECTION_ID_STREAM_TAGS] = { SECTION_ID_STREAM_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "stream_tags" }, [SECTION_ID_STREAM_SIDE_DATA_LIST] ={ SECTION_ID_STREAM_SIDE_DATA_LIST, "side_data_list", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_SIDE_DATA, -1 }, .element_name = "side_data", .unique_name = "stream_side_data_list" }, - [SECTION_ID_STREAM_SIDE_DATA] = { SECTION_ID_STREAM_SIDE_DATA, "side_data", 0, { -1 } }, + [SECTION_ID_STREAM_SIDE_DATA] = { SECTION_ID_STREAM_SIDE_DATA, "side_data", 0, { -1 }, .unique_name = "stream_side_data" }, [SECTION_ID_SUBTITLE] = { SECTION_ID_SUBTITLE, "subtitle", 0, { -1 } }, }; @@ -272,6 +281,7 @@ static const OptionDef *options; static const char *input_filename; static const char *print_input_filename; static const AVInputFormat *iformat = NULL; +static const char *output_filename = NULL; static struct AVHashContext *hash; @@ -467,6 +477,12 @@ typedef struct Writer { struct WriterContext { const AVClass *class; ///< class of the writer const Writer *writer; ///< the Writer of which this is an instance + AVIOContext *avio; ///< the I/O context used to write + + void (* writer_w8)(WriterContext *wctx, int b); + void (* writer_put_str)(WriterContext *wctx, const char *str); + void (* writer_printf)(WriterContext *wctx, const char *fmt, ...); + char *name; ///< name of this writer instance void *priv; ///< private data for use by the filter @@ -529,12 +545,13 @@ static const AVClass writer_class = { .child_next = writer_child_next, }; -static void writer_close(WriterContext **wctx) +static int writer_close(WriterContext **wctx) { int i; + int ret = 0; if (!*wctx) - return; + return -1; if ((*wctx)->writer->uninit) (*wctx)->writer->uninit(*wctx); @@ -544,7 +561,12 @@ static void writer_close(WriterContext **wctx) av_opt_free((*wctx)->priv); av_freep(&((*wctx)->priv)); av_opt_free(*wctx); + if ((*wctx)->avio) { + avio_flush((*wctx)->avio); + ret = avio_close((*wctx)->avio); + } av_freep(wctx); + return ret; } static void bprint_bytes(AVBPrint *bp, const uint8_t *ubuf, size_t ubuf_size) @@ -555,9 +577,46 @@ static void bprint_bytes(AVBPrint *bp, const uint8_t *ubuf, size_t ubuf_size) av_bprintf(bp, "%02X", ubuf[i]); } +static inline void writer_w8_avio(WriterContext *wctx, int b) +{ + avio_w8(wctx->avio, b); +} + +static inline void writer_put_str_avio(WriterContext *wctx, const char *str) +{ + avio_write(wctx->avio, str, strlen(str)); +} + +static inline void writer_printf_avio(WriterContext *wctx, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + avio_vprintf(wctx->avio, fmt, ap); + va_end(ap); +} + +static inline void writer_w8_printf(WriterContext *wctx, int b) +{ + printf("%c", b); +} + +static inline void writer_put_str_printf(WriterContext *wctx, const char *str) +{ + printf("%s", str); +} + +static inline void writer_printf_printf(WriterContext *wctx, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); +} static int writer_open(WriterContext **wctx, const Writer *writer, const char *args, - const struct section *sections, int nb_sections) + const struct section *sections, int nb_sections, const char *output) { int i, ret = 0; @@ -628,6 +687,21 @@ static int writer_open(WriterContext **wctx, const Writer *writer, const char *a } } + if (!output_filename) { + (*wctx)->writer_w8 = writer_w8_printf; + (*wctx)->writer_put_str = writer_put_str_printf; + (*wctx)->writer_printf = writer_printf_printf; + } else { + if ((ret = avio_open(&(*wctx)->avio, output, AVIO_FLAG_WRITE)) < 0) { + av_log(*wctx, AV_LOG_ERROR, + "Failed to open output '%s' with error: %s\n", output, av_err2str(ret)); + goto fail; + } + (*wctx)->writer_w8 = writer_w8_avio; + (*wctx)->writer_put_str = writer_put_str_avio; + (*wctx)->writer_printf = writer_printf_avio; + } + for (i = 0; i < SECTION_MAX_NB_LEVELS; i++) av_bprint_init(&(*wctx)->section_pbuf[i], 1, AV_BPRINT_SIZE_UNLIMITED); @@ -827,7 +901,7 @@ static void writer_print_ts(WriterContext *wctx, const char *key, int64_t ts, in } static void writer_print_data(WriterContext *wctx, const char *name, - uint8_t *data, int size) + const uint8_t *data, int size) { AVBPrint bp; int offset = 0, l, i; @@ -855,7 +929,7 @@ static void writer_print_data(WriterContext *wctx, const char *name, } static void writer_print_data_hash(WriterContext *wctx, const char *name, - uint8_t *data, int size) + const uint8_t *data, int size) { char *p, buf[AV_HASH_MAX_SIZE * 2 + 64] = { 0 }; @@ -895,6 +969,10 @@ static void writer_print_integers(WriterContext *wctx, const char *name, av_bprint_finalize(&bp, NULL); } +#define writer_w8(wctx_, b_) (wctx_)->writer_w8(wctx_, b_) +#define writer_put_str(wctx_, str_) (wctx_)->writer_put_str(wctx_, str_) +#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer_printf(wctx_, fmt_, __VA_ARGS__) + #define MAX_REGISTERED_WRITERS_NB 64 static const Writer *registered_writers[MAX_REGISTERED_WRITERS_NB + 1]; @@ -989,7 +1067,7 @@ static void default_print_section_header(WriterContext *wctx) return; if (!(section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY))) - printf("[%s]\n", upcase_string(buf, sizeof(buf), section->name)); + writer_printf(wctx, "[%s]\n", upcase_string(buf, sizeof(buf), section->name)); } static void default_print_section_footer(WriterContext *wctx) @@ -1002,7 +1080,7 @@ static void default_print_section_footer(WriterContext *wctx) return; if (!(section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY))) - printf("[/%s]\n", upcase_string(buf, sizeof(buf), section->name)); + writer_printf(wctx, "[/%s]\n", upcase_string(buf, sizeof(buf), section->name)); } static void default_print_str(WriterContext *wctx, const char *key, const char *value) @@ -1010,8 +1088,8 @@ static void default_print_str(WriterContext *wctx, const char *key, const char * DefaultContext *def = wctx->priv; if (!def->nokey) - printf("%s%s=", wctx->section_pbuf[wctx->level].str, key); - printf("%s\n", value); + writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key); + writer_printf(wctx, "%s\n", value); } static void default_print_int(WriterContext *wctx, const char *key, long long int value) @@ -1019,8 +1097,8 @@ static void default_print_int(WriterContext *wctx, const char *key, long long in DefaultContext *def = wctx->priv; if (!def->nokey) - printf("%s%s=", wctx->section_pbuf[wctx->level].str, key); - printf("%lld\n", value); + writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key); + writer_printf(wctx, "%lld\n", value); } static const Writer default_writer = { @@ -1162,10 +1240,10 @@ static void compact_print_section_header(WriterContext *wctx) } if (parent_section && !(parent_section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY)) && wctx->level && wctx->nb_item[wctx->level-1]) - printf("%c", compact->item_sep); + writer_w8(wctx, compact->item_sep); if (compact->print_section && !(section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY))) - printf("%s%c", section->name, compact->item_sep); + writer_printf(wctx, "%s%c", section->name, compact->item_sep); } } @@ -1176,7 +1254,7 @@ static void compact_print_section_footer(WriterContext *wctx) if (!compact->nested_section[wctx->level] && compact->terminate_line[wctx->level] && !(wctx->section[wctx->level]->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY))) - printf("\n"); + writer_w8(wctx, '\n'); } static void compact_print_str(WriterContext *wctx, const char *key, const char *value) @@ -1184,11 +1262,11 @@ static void compact_print_str(WriterContext *wctx, const char *key, const char * CompactContext *compact = wctx->priv; AVBPrint buf; - if (wctx->nb_item[wctx->level]) printf("%c", compact->item_sep); + if (wctx->nb_item[wctx->level]) writer_w8(wctx, compact->item_sep); if (!compact->nokey) - printf("%s%s=", wctx->section_pbuf[wctx->level].str, key); + writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key); av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED); - printf("%s", compact->escape_str(&buf, value, compact->item_sep, wctx)); + writer_put_str(wctx, compact->escape_str(&buf, value, compact->item_sep, wctx)); av_bprint_finalize(&buf, NULL); } @@ -1196,10 +1274,10 @@ static void compact_print_int(WriterContext *wctx, const char *key, long long in { CompactContext *compact = wctx->priv; - if (wctx->nb_item[wctx->level]) printf("%c", compact->item_sep); + if (wctx->nb_item[wctx->level]) writer_w8(wctx, compact->item_sep); if (!compact->nokey) - printf("%s%s=", wctx->section_pbuf[wctx->level].str, key); - printf("%lld", value); + writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key); + writer_printf(wctx, "%lld", value); } static const Writer compact_writer = { @@ -1342,7 +1420,7 @@ static void flat_print_section_header(WriterContext *wctx) static void flat_print_int(WriterContext *wctx, const char *key, long long int value) { - printf("%s%s=%lld\n", wctx->section_pbuf[wctx->level].str, key, value); + writer_printf(wctx, "%s%s=%lld\n", wctx->section_pbuf[wctx->level].str, key, value); } static void flat_print_str(WriterContext *wctx, const char *key, const char *value) @@ -1350,11 +1428,11 @@ static void flat_print_str(WriterContext *wctx, const char *key, const char *val FlatContext *flat = wctx->priv; AVBPrint buf; - printf("%s", wctx->section_pbuf[wctx->level].str); + writer_put_str(wctx, wctx->section_pbuf[wctx->level].str); av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED); - printf("%s=", flat_escape_key_str(&buf, key, flat->sep)); + writer_printf(wctx, "%s=", flat_escape_key_str(&buf, key, flat->sep)); av_bprint_clear(&buf); - printf("\"%s\"\n", flat_escape_value_str(&buf, value)); + writer_printf(wctx, "\"%s\"\n", flat_escape_value_str(&buf, value)); av_bprint_finalize(&buf, NULL); } @@ -1424,12 +1502,12 @@ static void ini_print_section_header(WriterContext *wctx) av_bprint_clear(buf); if (!parent_section) { - printf("# ffprobe output\n\n"); + writer_put_str(wctx, "# ffprobe output\n\n"); return; } if (wctx->nb_item[wctx->level-1]) - printf("\n"); + writer_w8(wctx, '\n'); av_bprintf(buf, "%s", wctx->section_pbuf[wctx->level-1].str); if (ini->hierarchical || @@ -1444,7 +1522,7 @@ static void ini_print_section_header(WriterContext *wctx) } if (!(section->flags & (SECTION_FLAG_IS_ARRAY|SECTION_FLAG_IS_WRAPPER))) - printf("[%s]\n", buf->str); + writer_printf(wctx, "[%s]\n", buf->str); } static void ini_print_str(WriterContext *wctx, const char *key, const char *value) @@ -1452,15 +1530,15 @@ static void ini_print_str(WriterContext *wctx, const char *key, const char *valu AVBPrint buf; av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED); - printf("%s=", ini_escape_str(&buf, key)); + writer_printf(wctx, "%s=", ini_escape_str(&buf, key)); av_bprint_clear(&buf); - printf("%s\n", ini_escape_str(&buf, value)); + writer_printf(wctx, "%s\n", ini_escape_str(&buf, value)); av_bprint_finalize(&buf, NULL); } static void ini_print_int(WriterContext *wctx, const char *key, long long int value) { - printf("%s=%lld\n", key, value); + writer_printf(wctx, "%s=%lld\n", key, value); } static const Writer ini_writer = { @@ -1523,7 +1601,7 @@ static const char *json_escape_str(AVBPrint *dst, const char *src, void *log_ctx return dst->str; } -#define JSON_INDENT() printf("%*c", json->indent_level * 4, ' ') +#define JSON_INDENT() writer_printf(wctx, "%*c", json->indent_level * 4, ' ') static void json_print_section_header(WriterContext *wctx) { @@ -1534,10 +1612,10 @@ static void json_print_section_header(WriterContext *wctx) wctx->section[wctx->level-1] : NULL; if (wctx->level && wctx->nb_item[wctx->level-1]) - printf(",\n"); + writer_put_str(wctx, ",\n"); if (section->flags & SECTION_FLAG_IS_WRAPPER) { - printf("{\n"); + writer_put_str(wctx, "{\n"); json->indent_level++; } else { av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED); @@ -1546,17 +1624,18 @@ static void json_print_section_header(WriterContext *wctx) json->indent_level++; if (section->flags & SECTION_FLAG_IS_ARRAY) { - printf("\"%s\": [\n", buf.str); + writer_printf(wctx, "\"%s\": [\n", buf.str); } else if (parent_section && !(parent_section->flags & SECTION_FLAG_IS_ARRAY)) { - printf("\"%s\": {%s", buf.str, json->item_start_end); + writer_printf(wctx, "\"%s\": {%s", buf.str, json->item_start_end); } else { - printf("{%s", json->item_start_end); + writer_printf(wctx, "{%s", json->item_start_end); /* this is required so the parser can distinguish between packets and frames */ if (parent_section && parent_section->id == SECTION_ID_PACKETS_AND_FRAMES) { if (!json->compact) JSON_INDENT(); - printf("\"type\": \"%s\"", section->name); + writer_printf(wctx, "\"type\": \"%s\"", section->name); + wctx->nb_item[wctx->level]++; } } av_bprint_finalize(&buf, NULL); @@ -1570,18 +1649,18 @@ static void json_print_section_footer(WriterContext *wctx) if (wctx->level == 0) { json->indent_level--; - printf("\n}\n"); + writer_put_str(wctx, "\n}\n"); } else if (section->flags & SECTION_FLAG_IS_ARRAY) { - printf("\n"); + writer_w8(wctx, '\n'); json->indent_level--; JSON_INDENT(); - printf("]"); + writer_w8(wctx, ']'); } else { - printf("%s", json->item_start_end); + writer_put_str(wctx, json->item_start_end); json->indent_level--; if (!json->compact) JSON_INDENT(); - printf("}"); + writer_w8(wctx, '}'); } } @@ -1591,9 +1670,9 @@ static inline void json_print_item_str(WriterContext *wctx, AVBPrint buf; av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED); - printf("\"%s\":", json_escape_str(&buf, key, wctx)); + writer_printf(wctx, "\"%s\":", json_escape_str(&buf, key, wctx)); av_bprint_clear(&buf); - printf(" \"%s\"", json_escape_str(&buf, value, wctx)); + writer_printf(wctx, " \"%s\"", json_escape_str(&buf, value, wctx)); av_bprint_finalize(&buf, NULL); } @@ -1604,7 +1683,7 @@ static void json_print_str(WriterContext *wctx, const char *key, const char *val wctx->section[wctx->level-1] : NULL; if (wctx->nb_item[wctx->level] || (parent_section && parent_section->id == SECTION_ID_PACKETS_AND_FRAMES)) - printf("%s", json->item_sep); + writer_put_str(wctx, json->item_sep); if (!json->compact) JSON_INDENT(); json_print_item_str(wctx, key, value); @@ -1618,12 +1697,12 @@ static void json_print_int(WriterContext *wctx, const char *key, long long int v AVBPrint buf; if (wctx->nb_item[wctx->level] || (parent_section && parent_section->id == SECTION_ID_PACKETS_AND_FRAMES)) - printf("%s", json->item_sep); + writer_put_str(wctx, json->item_sep); if (!json->compact) JSON_INDENT(); av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED); - printf("\"%s\": %lld", json_escape_str(&buf, key, wctx), value); + writer_printf(wctx, "\"%s\": %lld", json_escape_str(&buf, key, wctx), value); av_bprint_finalize(&buf, NULL); } @@ -1683,7 +1762,7 @@ static av_cold int xml_init(WriterContext *wctx) return 0; } -#define XML_INDENT() printf("%*c", xml->indent_level * 4, ' ') +#define XML_INDENT() writer_printf(wctx, "%*c", xml->indent_level * 4, ' ') static void xml_print_section_header(WriterContext *wctx) { @@ -1697,8 +1776,8 @@ static void xml_print_section_header(WriterContext *wctx) "xmlns:ffprobe=\"http://www.ffmpeg.org/schema/ffprobe\" " "xsi:schemaLocation=\"http://www.ffmpeg.org/schema/ffprobe ffprobe.xsd\""; - printf("\n"); - printf("<%sffprobe%s>\n", + writer_put_str(wctx, "\n"); + writer_printf(wctx, "<%sffprobe%s>\n", xml->fully_qualified ? "ffprobe:" : "", xml->fully_qualified ? qual : ""); return; @@ -1706,20 +1785,20 @@ static void xml_print_section_header(WriterContext *wctx) if (xml->within_tag) { xml->within_tag = 0; - printf(">\n"); + writer_put_str(wctx, ">\n"); } if (section->flags & SECTION_FLAG_HAS_VARIABLE_FIELDS) { xml->indent_level++; } else { if (parent_section && (parent_section->flags & SECTION_FLAG_IS_WRAPPER) && wctx->level && wctx->nb_item[wctx->level-1]) - printf("\n"); + writer_w8(wctx, '\n'); xml->indent_level++; if (section->flags & SECTION_FLAG_IS_ARRAY) { - XML_INDENT(); printf("<%s>\n", section->name); + XML_INDENT(); writer_printf(wctx, "<%s>\n", section->name); } else { - XML_INDENT(); printf("<%s ", section->name); + XML_INDENT(); writer_printf(wctx, "<%s ", section->name); xml->within_tag = 1; } } @@ -1731,15 +1810,15 @@ static void xml_print_section_footer(WriterContext *wctx) const struct section *section = wctx->section[wctx->level]; if (wctx->level == 0) { - printf("\n", xml->fully_qualified ? "ffprobe:" : ""); + writer_printf(wctx, "\n", xml->fully_qualified ? "ffprobe:" : ""); } else if (xml->within_tag) { xml->within_tag = 0; - printf("/>\n"); + writer_put_str(wctx, "/>\n"); xml->indent_level--; } else if (section->flags & SECTION_FLAG_HAS_VARIABLE_FIELDS) { xml->indent_level--; } else { - XML_INDENT(); printf("\n", section->name); + XML_INDENT(); writer_printf(wctx, "\n", section->name); xml->indent_level--; } } @@ -1756,20 +1835,20 @@ static void xml_print_str(WriterContext *wctx, const char *key, const char *valu XML_INDENT(); av_bprint_escape(&buf, key, NULL, AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES); - printf("<%s key=\"%s\"", - section->element_name, buf.str); + writer_printf(wctx, "<%s key=\"%s\"", + section->element_name, buf.str); av_bprint_clear(&buf); av_bprint_escape(&buf, value, NULL, AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES); - printf(" value=\"%s\"/>\n", buf.str); + writer_printf(wctx, " value=\"%s\"/>\n", buf.str); } else { if (wctx->nb_item[wctx->level]) - printf(" "); + writer_w8(wctx, ' '); av_bprint_escape(&buf, value, NULL, AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES); - printf("%s=\"%s\"", key, buf.str); + writer_printf(wctx, "%s=\"%s\"", key, buf.str); } av_bprint_finalize(&buf, NULL); @@ -1778,8 +1857,8 @@ static void xml_print_str(WriterContext *wctx, const char *key, const char *valu static void xml_print_int(WriterContext *wctx, const char *key, long long int value) { if (wctx->nb_item[wctx->level]) - printf(" "); - printf("%s=\"%lld\"", key, value); + writer_w8(wctx, ' '); + writer_printf(wctx, "%s=\"%lld\"", key, value); } static Writer xml_writer = { @@ -2118,6 +2197,74 @@ static void print_dynamic_hdr10_plus(WriterContext *w, const AVDynamicHDRPlus *m } } +static void print_dynamic_hdr_vivid(WriterContext *w, const AVDynamicHDRVivid *metadata) +{ + if (!metadata) + return; + print_int("system_start_code", metadata->system_start_code); + print_int("num_windows", metadata->num_windows); + + for (int n = 0; n < metadata->num_windows; n++) { + const AVHDRVividColorTransformParams *params = &metadata->params[n]; + + print_q("minimum_maxrgb", params->minimum_maxrgb, '/'); + print_q("average_maxrgb", params->average_maxrgb, '/'); + print_q("variance_maxrgb", params->variance_maxrgb, '/'); + print_q("maximum_maxrgb", params->maximum_maxrgb, '/'); + } + + for (int n = 0; n < metadata->num_windows; n++) { + const AVHDRVividColorTransformParams *params = &metadata->params[n]; + + print_int("tone_mapping_mode_flag", params->tone_mapping_mode_flag); + print_int("tone_mapping_param_num", params->tone_mapping_param_num); + if (params->tone_mapping_mode_flag) { + for (int i = 0; i < params->tone_mapping_param_num; i++) { + const AVHDRVividColorToneMappingParams *tm_params = ¶ms->tm_params[i]; + + print_q("targeted_system_display_maximum_luminance", + tm_params->targeted_system_display_maximum_luminance, '/'); + print_int("base_enable_flag", tm_params->base_enable_flag); + if (tm_params->base_enable_flag) { + print_q("base_param_m_p", tm_params->base_param_m_p, '/'); + print_q("base_param_m_m", tm_params->base_param_m_m, '/'); + print_q("base_param_m_a", tm_params->base_param_m_a, '/'); + print_q("base_param_m_b", tm_params->base_param_m_b, '/'); + print_q("base_param_m_n", tm_params->base_param_m_n, '/'); + + print_int("base_param_k1", tm_params->base_param_k1); + print_int("base_param_k2", tm_params->base_param_k2); + print_int("base_param_k3", tm_params->base_param_k3); + print_int("base_param_Delta_enable_mode", + tm_params->base_param_Delta_enable_mode); + print_q("base_param_Delta", tm_params->base_param_Delta, '/'); + } + print_int("3Spline_enable_flag", tm_params->three_Spline_enable_flag); + if (tm_params->three_Spline_enable_flag) { + print_int("3Spline_num", tm_params->three_Spline_num); + print_int("3Spline_TH_mode", tm_params->three_Spline_TH_mode); + + for (int j = 0; j < tm_params->three_Spline_num; j++) { + print_q("3Spline_TH_enable_MB", tm_params->three_Spline_TH_enable_MB, '/'); + print_q("3Spline_TH_enable", tm_params->three_Spline_TH_enable, '/'); + print_q("3Spline_TH_Delta1", tm_params->three_Spline_TH_Delta1, '/'); + print_q("3Spline_TH_Delta2", tm_params->three_Spline_TH_Delta2, '/'); + print_q("3Spline_enable_Strength", tm_params->three_Spline_enable_Strength, '/'); + } + } + } + } + + print_int("color_saturation_mapping_flag", params->color_saturation_mapping_flag); + if (params->color_saturation_mapping_flag) { + print_int("color_saturation_num", params->color_saturation_num); + for (int i = 0; i < params->color_saturation_num; i++) { + print_q("color_saturation_gain", params->color_saturation_gain[i], '/'); + } + } + } +} + static void print_pkt_side_data(WriterContext *w, AVCodecParameters *par, const AVPacketSideData *side_data, @@ -2214,6 +2361,8 @@ static void print_pkt_side_data(WriterContext *w, if (do_show_data) writer_print_data(w, "data", sd->data, sd->size); writer_print_data_hash(w, "data_hash", sd->data, sd->size); + } else if (sd->type == AV_PKT_DATA_AFD && sd->size > 0) { + print_int("active_format", *sd->data); } writer_print_section_footer(w); } @@ -2462,12 +2611,10 @@ static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream, if (s) print_str ("sample_fmt", s); else print_str_opt("sample_fmt", "unknown"); print_int("nb_samples", frame->nb_samples); - print_int("channels", frame->channels); - if (frame->channel_layout) { - av_bprint_clear(&pbuf); - av_bprint_channel_layout(&pbuf, frame->channels, - frame->channel_layout); - print_str ("channel_layout", pbuf.str); + print_int("channels", frame->ch_layout.nb_channels); + if (frame->ch_layout.order != AV_CHANNEL_ORDER_UNSPEC) { + av_channel_layout_describe(&frame->ch_layout, val_str, sizeof(val_str)); + print_str ("channel_layout", val_str); } else print_str_opt("channel_layout", "unknown"); break; @@ -2488,6 +2635,8 @@ static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream, if (sd->type == AV_FRAME_DATA_DISPLAYMATRIX && sd->size >= 9*4) { writer_print_integers(w, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1); print_int("rotation", av_display_rotation_get((int32_t *)sd->data)); + } else if (sd->type == AV_FRAME_DATA_AFD && sd->size > 0) { + print_int("active_format", *sd->data); } else if (sd->type == AV_FRAME_DATA_GOP_TIMECODE && sd->size >= 8) { char tcbuf[AV_TIMECODE_STR_SIZE]; av_timecode_make_mpeg_tc_string(tcbuf, *(int64_t *)(sd->data)); @@ -2537,6 +2686,9 @@ static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream, print_int("size", sd->size); } else if (sd->type == AV_FRAME_DATA_DOVI_METADATA) { print_dovi_metadata(w, (const AVDOVIMetadata *)sd->data); + } else if (sd->type == AV_FRAME_DATA_DYNAMIC_HDR_VIVID) { + AVDynamicHDRVivid *metadata = (AVDynamicHDRVivid *)sd->data; + print_dynamic_hdr_vivid(w, metadata); } writer_print_section_footer(w); } @@ -2561,7 +2713,7 @@ static av_always_inline int process_frame(WriterContext *w, int ret = 0, got_frame = 0; clear_log(1); - if (dec_ctx && dec_ctx->codec) { + if (dec_ctx) { switch (par->codec_type) { case AVMEDIA_TYPE_VIDEO: case AVMEDIA_TYPE_AUDIO: @@ -2730,8 +2882,11 @@ static int read_interval_packets(WriterContext *w, InputFile *ifile, //Flush remaining frames that are cached in the decoder for (i = 0; i < fmt_ctx->nb_streams; i++) { pkt->stream_index = i; - if (do_read_frames) + if (do_read_frames) { while (process_frame(w, ifile, frame, pkt, &(int){1}) > 0); + if (ifile->streams[i].dec_ctx) + avcodec_flush_buffers(ifile->streams[i].dec_ctx); + } } end: @@ -2873,12 +3028,11 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id if (s) print_str ("sample_fmt", s); else print_str_opt("sample_fmt", "unknown"); print_val("sample_rate", par->sample_rate, unit_hertz_str); - print_int("channels", par->channels); + print_int("channels", par->ch_layout.nb_channels); - if (par->channel_layout) { - av_bprint_clear(&pbuf); - av_bprint_channel_layout(&pbuf, par->channels, par->channel_layout); - print_str ("channel_layout", pbuf.str); + if (par->ch_layout.order != AV_CHANNEL_ORDER_UNSPEC) { + av_channel_layout_describe(&par->ch_layout, val_str, sizeof(val_str)); + print_str ("channel_layout", val_str); } else { print_str_opt("channel_layout", "unknown"); } @@ -2898,7 +3052,7 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id break; } - if (dec_ctx && dec_ctx->codec && dec_ctx->codec->priv_class && show_private_data) { + if (dec_ctx && dec_ctx->codec->priv_class && show_private_data) { const AVOption *opt = NULL; while (opt = av_opt_next(dec_ctx->priv_data,opt)) { uint8_t *str; @@ -3337,7 +3491,7 @@ end: static void show_usage(void) { av_log(NULL, AV_LOG_INFO, "Simple multimedia streams analyzer\n"); - av_log(NULL, AV_LOG_INFO, "usage: %s [OPTIONS] [INPUT_FILE]\n", program_name); + av_log(NULL, AV_LOG_INFO, "usage: %s [OPTIONS] INPUT_FILE\n", program_name); av_log(NULL, AV_LOG_INFO, "\n"); } @@ -3542,22 +3696,6 @@ static int opt_show_entries(void *optctx, const char *opt, const char *arg) return ret; } -static int opt_show_format_entry(void *optctx, const char *opt, const char *arg) -{ - char *buf = av_asprintf("format=%s", arg); - int ret; - - if (!buf) - return AVERROR(ENOMEM); - - av_log(NULL, AV_LOG_WARNING, - "Option '%s' is deprecated, use '-show_entries format=%s' instead\n", - opt, arg); - ret = opt_show_entries(optctx, opt, buf); - av_free(buf); - return ret; -} - static void opt_input_file(void *optctx, const char *arg) { if (input_filename) { @@ -3577,6 +3715,25 @@ static int opt_input_file_i(void *optctx, const char *opt, const char *arg) return 0; } +static void opt_output_file(void *optctx, const char *arg) +{ + if (output_filename) { + av_log(NULL, AV_LOG_ERROR, + "Argument '%s' provided as output filename, but '%s' was already specified.\n", + arg, output_filename); + exit_program(1); + } + if (!strcmp(arg, "-")) + arg = "pipe:"; + output_filename = arg; +} + +static int opt_output_file_o(void *optctx, const char *opt, const char *arg) +{ + opt_output_file(optctx, arg); + return 0; +} + static int opt_print_filename(void *optctx, const char *opt, const char *arg) { print_input_filename = arg; @@ -3818,8 +3975,6 @@ static const OptionDef real_options[] = { { "show_error", 0, { .func_arg = &opt_show_error }, "show probing error" }, { "show_format", 0, { .func_arg = &opt_show_format }, "show format/container info" }, { "show_frames", 0, { .func_arg = &opt_show_frames }, "show frames info" }, - { "show_format_entry", HAS_ARG, {.func_arg = opt_show_format_entry}, - "show a particular entry from the format/container info", "entry" }, { "show_entries", HAS_ARG, {.func_arg = opt_show_entries}, "show a set of specified entries", "entry_list" }, #if HAVE_THREADS @@ -3840,8 +3995,8 @@ static const OptionDef real_options[] = { { "private", OPT_BOOL, { &show_private_data }, "same as show_private_data" }, { "bitexact", OPT_BOOL, {&do_bitexact}, "force bitexact output" }, { "read_intervals", HAS_ARG, {.func_arg = opt_read_intervals}, "set read intervals", "read_intervals" }, - { "default", HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, {.func_arg = opt_default}, "generic catch all option", "" }, { "i", HAS_ARG, {.func_arg = opt_input_file_i}, "read specified file", "input_file"}, + { "o", HAS_ARG, {.func_arg = opt_output_file_o}, "write to specified output", "output_file"}, { "print_filename", HAS_ARG, {.func_arg = opt_print_filename}, "override the printed input filename", "print_file"}, { "find_stream_info", OPT_BOOL | OPT_INPUT | OPT_EXPERT, { &find_stream_info }, "read and decode the streams to fill missing information with heuristics" }, @@ -3969,7 +4124,7 @@ int main(int argc, char **argv) } if ((ret = writer_open(&wctx, w, w_args, - sections, FF_ARRAY_ELEMS(sections))) >= 0) { + sections, FF_ARRAY_ELEMS(sections), output_filename)) >= 0) { if (w == &xml_writer) wctx->string_validation_utf8_flags |= AV_UTF8_FLAG_EXCLUDE_XML_INVALID_CONTROL_CODES; @@ -3996,7 +4151,9 @@ int main(int argc, char **argv) } writer_print_section_footer(wctx); - writer_close(&wctx); + ret = writer_close(&wctx); + if (ret < 0) + av_log(NULL, AV_LOG_ERROR, "Writing output failed: %s\n", av_err2str(ret)); } end: diff --git a/fftools/fopen_utf8.h b/fftools/fopen_utf8.h new file mode 100644 index 000000000..e5be84179 --- /dev/null +++ b/fftools/fopen_utf8.h @@ -0,0 +1,71 @@ +/* + * 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_FOPEN_UTF8_H +#define FFTOOLS_FOPEN_UTF8_H + +#include + +/* The fopen_utf8 function here is essentially equivalent to avpriv_fopen_utf8, + * except that it doesn't set O_CLOEXEC, and that it isn't exported + * from a different library. (On Windows, each DLL might use a different + * CRT, and FILE* handles can't be shared across them.) */ + +#ifdef _WIN32 +#include "libavutil/wchar_filename.h" + +static inline FILE *fopen_utf8(const char *path_utf8, const char *mode) +{ + wchar_t *path_w, *mode_w; + FILE *f; + + /* convert UTF-8 to wide chars */ + if (get_extended_win32_path(path_utf8, &path_w)) /* This sets errno on error. */ + return NULL; + if (!path_w) + goto fallback; + + if (utf8towchar(mode, &mode_w)) + return NULL; + if (!mode_w) { + /* If failing to interpret the mode string as utf8, it is an invalid + * parameter. */ + av_freep(&path_w); + errno = EINVAL; + return NULL; + } + + f = _wfopen(path_w, mode_w); + av_freep(&path_w); + av_freep(&mode_w); + + return f; +fallback: + /* path may be in CP_ACP */ + return fopen(path_utf8, mode); +} + +#else + +static inline FILE *fopen_utf8(const char *path, const char *mode) +{ + return fopen(path, mode); +} +#endif + +#endif /* FFTOOLS_FOPEN_UTF8_H */ diff --git a/fftools/opt_common.c b/fftools/opt_common.c new file mode 100644 index 000000000..ae5e28a5a --- /dev/null +++ b/fftools/opt_common.c @@ -0,0 +1,1465 @@ +/* + * Option handlers shared between the tools. + * + * 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 "cmdutils.h" +#include "opt_common.h" + +#include "libavutil/avassert.h" +#include "libavutil/avstring.h" +#include "libavutil/bprint.h" +#include "libavutil/channel_layout.h" +#include "libavutil/cpu.h" +#include "libavutil/dict.h" +#include "libavutil/error.h" +#include "libavutil/ffversion.h" +#include "libavutil/log.h" +#include "libavutil/mem.h" +#include "libavutil/parseutils.h" +#include "libavutil/pixdesc.h" +#include "libavutil/version.h" + +#include "libavcodec/avcodec.h" +#include "libavcodec/bsf.h" +#include "libavcodec/codec.h" +#include "libavcodec/codec_desc.h" +#include "libavcodec/version.h" + +#include "libavformat/avformat.h" +#include "libavformat/version.h" + +#include "libavdevice/avdevice.h" +#include "libavdevice/version.h" + +#include "libavfilter/avfilter.h" +#include "libavfilter/version.h" + +#include "libswscale/swscale.h" +#include "libswscale/version.h" + +#include "libswresample/swresample.h" +#include "libswresample/version.h" + +#include "libpostproc/postprocess.h" +#include "libpostproc/version.h" + +enum show_muxdemuxers { + SHOW_DEFAULT, + SHOW_DEMUXERS, + SHOW_MUXERS, +}; + +static FILE *report_file; +static int report_file_level = AV_LOG_DEBUG; + +int show_license(void *optctx, const char *opt, const char *arg) +{ +#if CONFIG_NONFREE + printf( + "This version of %s has nonfree parts compiled in.\n" + "Therefore it is not legally redistributable.\n", + program_name ); +#elif CONFIG_GPLV3 + printf( + "%s is free software; you can redistribute it and/or modify\n" + "it under the terms of the GNU General Public License as published by\n" + "the Free Software Foundation; either version 3 of the License, or\n" + "(at your option) any later version.\n" + "\n" + "%s is distributed in the hope that it will be useful,\n" + "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + "GNU General Public License for more details.\n" + "\n" + "You should have received a copy of the GNU General Public License\n" + "along with %s. If not, see .\n", + program_name, program_name, program_name ); +#elif CONFIG_GPL + printf( + "%s is free software; you can redistribute it and/or modify\n" + "it under the terms of the GNU General Public License as published by\n" + "the Free Software Foundation; either version 2 of the License, or\n" + "(at your option) any later version.\n" + "\n" + "%s is distributed in the hope that it will be useful,\n" + "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + "GNU General Public License for more details.\n" + "\n" + "You should have received a copy of the GNU General Public License\n" + "along with %s; if not, write to the Free Software\n" + "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n", + program_name, program_name, program_name ); +#elif CONFIG_LGPLV3 + printf( + "%s is free software; you can redistribute it and/or modify\n" + "it under the terms of the GNU Lesser General Public License as published by\n" + "the Free Software Foundation; either version 3 of the License, or\n" + "(at your option) any later version.\n" + "\n" + "%s is distributed in the hope that it will be useful,\n" + "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + "GNU Lesser General Public License for more details.\n" + "\n" + "You should have received a copy of the GNU Lesser General Public License\n" + "along with %s. If not, see .\n", + program_name, program_name, program_name ); +#else + printf( + "%s is free software; you can redistribute it and/or\n" + "modify it under the terms of the GNU Lesser General Public\n" + "License as published by the Free Software Foundation; either\n" + "version 2.1 of the License, or (at your option) any later version.\n" + "\n" + "%s is distributed in the hope that it will be useful,\n" + "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" + "Lesser General Public License for more details.\n" + "\n" + "You should have received a copy of the GNU Lesser General Public\n" + "License along with %s; if not, write to the Free Software\n" + "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n", + program_name, program_name, program_name ); +#endif + + return 0; +} + +static int warned_cfg = 0; + +#define INDENT 1 +#define SHOW_VERSION 2 +#define SHOW_CONFIG 4 +#define SHOW_COPYRIGHT 8 + +#define PRINT_LIB_INFO(libname, LIBNAME, flags, level) \ + if (CONFIG_##LIBNAME) { \ + const char *indent = flags & INDENT? " " : ""; \ + if (flags & SHOW_VERSION) { \ + unsigned int version = libname##_version(); \ + av_log(NULL, level, \ + "%slib%-11s %2d.%3d.%3d / %2d.%3d.%3d\n", \ + indent, #libname, \ + LIB##LIBNAME##_VERSION_MAJOR, \ + LIB##LIBNAME##_VERSION_MINOR, \ + LIB##LIBNAME##_VERSION_MICRO, \ + AV_VERSION_MAJOR(version), AV_VERSION_MINOR(version),\ + AV_VERSION_MICRO(version)); \ + } \ + if (flags & SHOW_CONFIG) { \ + const char *cfg = libname##_configuration(); \ + if (strcmp(FFMPEG_CONFIGURATION, cfg)) { \ + if (!warned_cfg) { \ + av_log(NULL, level, \ + "%sWARNING: library configuration mismatch\n", \ + indent); \ + warned_cfg = 1; \ + } \ + av_log(NULL, level, "%s%-11s configuration: %s\n", \ + indent, #libname, cfg); \ + } \ + } \ + } \ + +static void print_all_libs_info(int flags, int level) +{ + PRINT_LIB_INFO(avutil, AVUTIL, flags, level); + PRINT_LIB_INFO(avcodec, AVCODEC, flags, level); + PRINT_LIB_INFO(avformat, AVFORMAT, flags, level); + PRINT_LIB_INFO(avdevice, AVDEVICE, flags, level); + PRINT_LIB_INFO(avfilter, AVFILTER, flags, level); + PRINT_LIB_INFO(swscale, SWSCALE, flags, level); + PRINT_LIB_INFO(swresample, SWRESAMPLE, flags, level); + PRINT_LIB_INFO(postproc, POSTPROC, flags, level); +} + +static void print_program_info(int flags, int level) +{ + const char *indent = flags & INDENT? " " : ""; + + av_log(NULL, level, "%s version " FFMPEG_VERSION, program_name); + if (flags & SHOW_COPYRIGHT) + av_log(NULL, level, " Copyright (c) %d-%d the FFmpeg developers", + program_birth_year, CONFIG_THIS_YEAR); + av_log(NULL, level, "\n"); + av_log(NULL, level, "%sbuilt with %s\n", indent, CC_IDENT); + + av_log(NULL, level, "%sconfiguration: " FFMPEG_CONFIGURATION "\n", indent); +} + +static void print_buildconf(int flags, int level) +{ + const char *indent = flags & INDENT ? " " : ""; + char str[] = { FFMPEG_CONFIGURATION }; + char *conflist, *remove_tilde, *splitconf; + + // Change all the ' --' strings to '~--' so that + // they can be identified as tokens. + while ((conflist = strstr(str, " --")) != NULL) { + conflist[0] = '~'; + } + + // Compensate for the weirdness this would cause + // when passing 'pkg-config --static'. + while ((remove_tilde = strstr(str, "pkg-config~")) != NULL) { + remove_tilde[sizeof("pkg-config~") - 2] = ' '; + } + + splitconf = strtok(str, "~"); + av_log(NULL, level, "\n%sconfiguration:\n", indent); + while (splitconf != NULL) { + av_log(NULL, level, "%s%s%s\n", indent, indent, splitconf); + splitconf = strtok(NULL, "~"); + } +} + +void show_banner(int argc, char **argv, const OptionDef *options) +{ + int idx = locate_option(argc, argv, options, "version"); + if (hide_banner || idx) + return; + + print_program_info (INDENT|SHOW_COPYRIGHT, AV_LOG_INFO); + print_all_libs_info(INDENT|SHOW_CONFIG, AV_LOG_INFO); + print_all_libs_info(INDENT|SHOW_VERSION, AV_LOG_INFO); +} + +int show_version(void *optctx, const char *opt, const char *arg) +{ + av_log_set_callback(log_callback_help); + print_program_info (SHOW_COPYRIGHT, AV_LOG_INFO); + print_all_libs_info(SHOW_VERSION, AV_LOG_INFO); + + return 0; +} + +int show_buildconf(void *optctx, const char *opt, const char *arg) +{ + av_log_set_callback(log_callback_help); + print_buildconf (INDENT|0, AV_LOG_INFO); + + return 0; +} + +#define PRINT_CODEC_SUPPORTED(codec, field, type, list_name, term, get_name) \ + if (codec->field) { \ + const type *p = codec->field; \ + \ + printf(" Supported " list_name ":"); \ + while (*p != term) { \ + get_name(*p); \ + printf(" %s", name); \ + p++; \ + } \ + printf("\n"); \ + } \ + +static void print_codec(const AVCodec *c) +{ + int encoder = av_codec_is_encoder(c); + + printf("%s %s [%s]:\n", encoder ? "Encoder" : "Decoder", c->name, + c->long_name ? c->long_name : ""); + + printf(" General capabilities: "); + if (c->capabilities & AV_CODEC_CAP_DRAW_HORIZ_BAND) + printf("horizband "); + if (c->capabilities & AV_CODEC_CAP_DR1) + printf("dr1 "); + if (c->capabilities & AV_CODEC_CAP_DELAY) + printf("delay "); + if (c->capabilities & AV_CODEC_CAP_SMALL_LAST_FRAME) + printf("small "); + if (c->capabilities & AV_CODEC_CAP_SUBFRAMES) + printf("subframes "); + if (c->capabilities & AV_CODEC_CAP_EXPERIMENTAL) + printf("exp "); + if (c->capabilities & AV_CODEC_CAP_CHANNEL_CONF) + printf("chconf "); + if (c->capabilities & AV_CODEC_CAP_PARAM_CHANGE) + printf("paramchange "); + if (c->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE) + printf("variable "); + if (c->capabilities & (AV_CODEC_CAP_FRAME_THREADS | + AV_CODEC_CAP_SLICE_THREADS | + AV_CODEC_CAP_OTHER_THREADS)) + printf("threads "); + if (c->capabilities & AV_CODEC_CAP_AVOID_PROBING) + printf("avoidprobe "); + if (c->capabilities & AV_CODEC_CAP_HARDWARE) + printf("hardware "); + if (c->capabilities & AV_CODEC_CAP_HYBRID) + printf("hybrid "); + if (!c->capabilities) + printf("none"); + printf("\n"); + + if (c->type == AVMEDIA_TYPE_VIDEO || + c->type == AVMEDIA_TYPE_AUDIO) { + printf(" Threading capabilities: "); + switch (c->capabilities & (AV_CODEC_CAP_FRAME_THREADS | + AV_CODEC_CAP_SLICE_THREADS | + AV_CODEC_CAP_OTHER_THREADS)) { + case AV_CODEC_CAP_FRAME_THREADS | + AV_CODEC_CAP_SLICE_THREADS: printf("frame and slice"); break; + case AV_CODEC_CAP_FRAME_THREADS: printf("frame"); break; + case AV_CODEC_CAP_SLICE_THREADS: printf("slice"); break; + case AV_CODEC_CAP_OTHER_THREADS: printf("other"); break; + default: printf("none"); break; + } + printf("\n"); + } + + if (avcodec_get_hw_config(c, 0)) { + printf(" Supported hardware devices: "); + for (int i = 0;; i++) { + const AVCodecHWConfig *config = avcodec_get_hw_config(c, i); + if (!config) + break; + printf("%s ", av_hwdevice_get_type_name(config->device_type)); + } + printf("\n"); + } + + if (c->supported_framerates) { + const AVRational *fps = c->supported_framerates; + + printf(" Supported framerates:"); + while (fps->num) { + printf(" %d/%d", fps->num, fps->den); + fps++; + } + printf("\n"); + } + PRINT_CODEC_SUPPORTED(c, pix_fmts, enum AVPixelFormat, "pixel formats", + AV_PIX_FMT_NONE, GET_PIX_FMT_NAME); + PRINT_CODEC_SUPPORTED(c, supported_samplerates, int, "sample rates", 0, + GET_SAMPLE_RATE_NAME); + PRINT_CODEC_SUPPORTED(c, sample_fmts, enum AVSampleFormat, "sample formats", + AV_SAMPLE_FMT_NONE, GET_SAMPLE_FMT_NAME); + + if (c->ch_layouts) { + const AVChannelLayout *p = c->ch_layouts; + + printf(" Supported channel layouts:"); + while (p->nb_channels) { + char name[128]; + av_channel_layout_describe(p, name, sizeof(name)); + printf(" %s", name); + p++; + } + printf("\n"); + } + + if (c->priv_class) { + show_help_children(c->priv_class, + AV_OPT_FLAG_ENCODING_PARAM | + AV_OPT_FLAG_DECODING_PARAM); + } +} + +static const AVCodec *next_codec_for_id(enum AVCodecID id, void **iter, + int encoder) +{ + const AVCodec *c; + while ((c = av_codec_iterate(iter))) { + if (c->id == id && + (encoder ? av_codec_is_encoder(c) : av_codec_is_decoder(c))) + return c; + } + return NULL; +} + +static void show_help_codec(const char *name, int encoder) +{ + const AVCodecDescriptor *desc; + const AVCodec *codec; + + if (!name) { + av_log(NULL, AV_LOG_ERROR, "No codec name specified.\n"); + return; + } + + codec = encoder ? avcodec_find_encoder_by_name(name) : + avcodec_find_decoder_by_name(name); + + if (codec) + print_codec(codec); + else if ((desc = avcodec_descriptor_get_by_name(name))) { + void *iter = NULL; + int printed = 0; + + while ((codec = next_codec_for_id(desc->id, &iter, encoder))) { + printed = 1; + print_codec(codec); + } + + if (!printed) { + av_log(NULL, AV_LOG_ERROR, "Codec '%s' is known to FFmpeg, " + "but no %s for it are available. FFmpeg might need to be " + "recompiled with additional external libraries.\n", + name, encoder ? "encoders" : "decoders"); + } + } else { + av_log(NULL, AV_LOG_ERROR, "Codec '%s' is not recognized by FFmpeg.\n", + name); + } +} + +static void show_help_demuxer(const char *name) +{ + const AVInputFormat *fmt = av_find_input_format(name); + + if (!fmt) { + av_log(NULL, AV_LOG_ERROR, "Unknown format '%s'.\n", name); + return; + } + + printf("Demuxer %s [%s]:\n", fmt->name, fmt->long_name); + + if (fmt->extensions) + printf(" Common extensions: %s.\n", fmt->extensions); + + if (fmt->priv_class) + show_help_children(fmt->priv_class, AV_OPT_FLAG_DECODING_PARAM); +} + +static void show_help_protocol(const char *name) +{ + const AVClass *proto_class; + + if (!name) { + av_log(NULL, AV_LOG_ERROR, "No protocol name specified.\n"); + return; + } + + proto_class = avio_protocol_get_class(name); + if (!proto_class) { + av_log(NULL, AV_LOG_ERROR, "Unknown protocol '%s'.\n", name); + return; + } + + show_help_children(proto_class, AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_ENCODING_PARAM); +} + +static void show_help_muxer(const char *name) +{ + const AVCodecDescriptor *desc; + const AVOutputFormat *fmt = av_guess_format(name, NULL, NULL); + + if (!fmt) { + av_log(NULL, AV_LOG_ERROR, "Unknown format '%s'.\n", name); + return; + } + + printf("Muxer %s [%s]:\n", fmt->name, fmt->long_name); + + if (fmt->extensions) + printf(" Common extensions: %s.\n", fmt->extensions); + if (fmt->mime_type) + printf(" Mime type: %s.\n", fmt->mime_type); + if (fmt->video_codec != AV_CODEC_ID_NONE && + (desc = avcodec_descriptor_get(fmt->video_codec))) { + printf(" Default video codec: %s.\n", desc->name); + } + if (fmt->audio_codec != AV_CODEC_ID_NONE && + (desc = avcodec_descriptor_get(fmt->audio_codec))) { + printf(" Default audio codec: %s.\n", desc->name); + } + if (fmt->subtitle_codec != AV_CODEC_ID_NONE && + (desc = avcodec_descriptor_get(fmt->subtitle_codec))) { + printf(" Default subtitle codec: %s.\n", desc->name); + } + + if (fmt->priv_class) + show_help_children(fmt->priv_class, AV_OPT_FLAG_ENCODING_PARAM); +} + +#if CONFIG_AVFILTER +static void show_help_filter(const char *name) +{ +#if CONFIG_AVFILTER + const AVFilter *f = avfilter_get_by_name(name); + int i, count; + + if (!name) { + av_log(NULL, AV_LOG_ERROR, "No filter name specified.\n"); + return; + } else if (!f) { + av_log(NULL, AV_LOG_ERROR, "Unknown filter '%s'.\n", name); + return; + } + + printf("Filter %s\n", f->name); + if (f->description) + printf(" %s\n", f->description); + + if (f->flags & AVFILTER_FLAG_SLICE_THREADS) + printf(" slice threading supported\n"); + + printf(" Inputs:\n"); + count = avfilter_filter_pad_count(f, 0); + for (i = 0; i < count; i++) { + printf(" #%d: %s (%s)\n", i, avfilter_pad_get_name(f->inputs, i), + av_get_media_type_string(avfilter_pad_get_type(f->inputs, i))); + } + if (f->flags & AVFILTER_FLAG_DYNAMIC_INPUTS) + printf(" dynamic (depending on the options)\n"); + else if (!count) + printf(" none (source filter)\n"); + + printf(" Outputs:\n"); + count = avfilter_filter_pad_count(f, 1); + for (i = 0; i < count; i++) { + printf(" #%d: %s (%s)\n", i, avfilter_pad_get_name(f->outputs, i), + av_get_media_type_string(avfilter_pad_get_type(f->outputs, i))); + } + if (f->flags & AVFILTER_FLAG_DYNAMIC_OUTPUTS) + printf(" dynamic (depending on the options)\n"); + else if (!count) + printf(" none (sink filter)\n"); + + if (f->priv_class) + show_help_children(f->priv_class, AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM | + AV_OPT_FLAG_AUDIO_PARAM); + if (f->flags & AVFILTER_FLAG_SUPPORT_TIMELINE) + printf("This filter has support for timeline through the 'enable' option.\n"); +#else + av_log(NULL, AV_LOG_ERROR, "Build without libavfilter; " + "can not to satisfy request\n"); +#endif +} +#endif + +static void show_help_bsf(const char *name) +{ + const AVBitStreamFilter *bsf = av_bsf_get_by_name(name); + + if (!name) { + av_log(NULL, AV_LOG_ERROR, "No bitstream filter name specified.\n"); + return; + } else if (!bsf) { + av_log(NULL, AV_LOG_ERROR, "Unknown bit stream filter '%s'.\n", name); + return; + } + + 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); +} + +int show_help(void *optctx, const char *opt, const char *arg) +{ + char *topic, *par; + av_log_set_callback(log_callback_help); + + topic = av_strdup(arg ? arg : ""); + if (!topic) + return AVERROR(ENOMEM); + par = strchr(topic, '='); + if (par) + *par++ = 0; + + if (!*topic) { + show_help_default(topic, par); + } else if (!strcmp(topic, "decoder")) { + show_help_codec(par, 0); + } else if (!strcmp(topic, "encoder")) { + show_help_codec(par, 1); + } else if (!strcmp(topic, "demuxer")) { + show_help_demuxer(par); + } else if (!strcmp(topic, "muxer")) { + show_help_muxer(par); + } else if (!strcmp(topic, "protocol")) { + show_help_protocol(par); +#if CONFIG_AVFILTER + } 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); + } + + av_freep(&topic); + return 0; +} + +static void print_codecs_for_id(enum AVCodecID id, int encoder) +{ + void *iter = NULL; + const AVCodec *codec; + + printf(" (%s: ", encoder ? "encoders" : "decoders"); + + while ((codec = next_codec_for_id(id, &iter, encoder))) + printf("%s ", codec->name); + + printf(")"); +} + +static int compare_codec_desc(const void *a, const void *b) +{ + const AVCodecDescriptor * const *da = a; + const AVCodecDescriptor * const *db = b; + + return (*da)->type != (*db)->type ? FFDIFFSIGN((*da)->type, (*db)->type) : + strcmp((*da)->name, (*db)->name); +} + +static unsigned get_codecs_sorted(const AVCodecDescriptor ***rcodecs) +{ + const AVCodecDescriptor *desc = NULL; + const AVCodecDescriptor **codecs; + unsigned nb_codecs = 0, i = 0; + + while ((desc = avcodec_descriptor_next(desc))) + nb_codecs++; + if (!(codecs = av_calloc(nb_codecs, sizeof(*codecs)))) { + av_log(NULL, AV_LOG_ERROR, "Out of memory\n"); + exit_program(1); + } + desc = NULL; + while ((desc = avcodec_descriptor_next(desc))) + codecs[i++] = desc; + av_assert0(i == nb_codecs); + qsort(codecs, nb_codecs, sizeof(*codecs), compare_codec_desc); + *rcodecs = codecs; + return nb_codecs; +} + +static char get_media_type_char(enum AVMediaType type) +{ + switch (type) { + case AVMEDIA_TYPE_VIDEO: return 'V'; + case AVMEDIA_TYPE_AUDIO: return 'A'; + case AVMEDIA_TYPE_DATA: return 'D'; + case AVMEDIA_TYPE_SUBTITLE: return 'S'; + case AVMEDIA_TYPE_ATTACHMENT:return 'T'; + default: return '?'; + } +} + +int show_codecs(void *optctx, const char *opt, const char *arg) +{ + const AVCodecDescriptor **codecs; + unsigned i, nb_codecs = get_codecs_sorted(&codecs); + + printf("Codecs:\n" + " D..... = Decoding supported\n" + " .E.... = Encoding supported\n" + " ..V... = Video codec\n" + " ..A... = Audio codec\n" + " ..S... = Subtitle codec\n" + " ..D... = Data codec\n" + " ..T... = Attachment codec\n" + " ...I.. = Intra frame-only codec\n" + " ....L. = Lossy compression\n" + " .....S = Lossless compression\n" + " -------\n"); + for (i = 0; i < nb_codecs; i++) { + const AVCodecDescriptor *desc = codecs[i]; + const AVCodec *codec; + void *iter = NULL; + + if (strstr(desc->name, "_deprecated")) + continue; + + printf(" "); + printf(avcodec_find_decoder(desc->id) ? "D" : "."); + printf(avcodec_find_encoder(desc->id) ? "E" : "."); + + printf("%c", get_media_type_char(desc->type)); + printf((desc->props & AV_CODEC_PROP_INTRA_ONLY) ? "I" : "."); + printf((desc->props & AV_CODEC_PROP_LOSSY) ? "L" : "."); + printf((desc->props & AV_CODEC_PROP_LOSSLESS) ? "S" : "."); + + printf(" %-20s %s", desc->name, desc->long_name ? desc->long_name : ""); + + /* print decoders/encoders when there's more than one or their + * names are different from codec name */ + while ((codec = next_codec_for_id(desc->id, &iter, 0))) { + if (strcmp(codec->name, desc->name)) { + print_codecs_for_id(desc->id, 0); + break; + } + } + iter = NULL; + while ((codec = next_codec_for_id(desc->id, &iter, 1))) { + if (strcmp(codec->name, desc->name)) { + print_codecs_for_id(desc->id, 1); + break; + } + } + + printf("\n"); + } + av_free(codecs); + return 0; +} + +static void print_codecs(int encoder) +{ + const AVCodecDescriptor **codecs; + unsigned i, nb_codecs = get_codecs_sorted(&codecs); + + printf("%s:\n" + " V..... = Video\n" + " A..... = Audio\n" + " S..... = Subtitle\n" + " .F.... = Frame-level multithreading\n" + " ..S... = Slice-level multithreading\n" + " ...X.. = Codec is experimental\n" + " ....B. = Supports draw_horiz_band\n" + " .....D = Supports direct rendering method 1\n" + " ------\n", + encoder ? "Encoders" : "Decoders"); + for (i = 0; i < nb_codecs; i++) { + const AVCodecDescriptor *desc = codecs[i]; + const AVCodec *codec; + void *iter = NULL; + + while ((codec = next_codec_for_id(desc->id, &iter, encoder))) { + printf(" %c", get_media_type_char(desc->type)); + printf((codec->capabilities & AV_CODEC_CAP_FRAME_THREADS) ? "F" : "."); + printf((codec->capabilities & AV_CODEC_CAP_SLICE_THREADS) ? "S" : "."); + printf((codec->capabilities & AV_CODEC_CAP_EXPERIMENTAL) ? "X" : "."); + printf((codec->capabilities & AV_CODEC_CAP_DRAW_HORIZ_BAND)?"B" : "."); + printf((codec->capabilities & AV_CODEC_CAP_DR1) ? "D" : "."); + + printf(" %-20s %s", codec->name, codec->long_name ? codec->long_name : ""); + if (strcmp(codec->name, desc->name)) + printf(" (codec %s)", desc->name); + + printf("\n"); + } + } + av_free(codecs); +} + +int show_decoders(void *optctx, const char *opt, const char *arg) +{ + print_codecs(0); + return 0; +} + +int show_encoders(void *optctx, const char *opt, const char *arg) +{ + print_codecs(1); + return 0; +} + +int show_bsfs(void *optctx, const char *opt, const char *arg) +{ + const AVBitStreamFilter *bsf = NULL; + void *opaque = NULL; + + printf("Bitstream filters:\n"); + while ((bsf = av_bsf_iterate(&opaque))) + printf("%s\n", bsf->name); + printf("\n"); + return 0; +} + +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; + + printf("Filters:\n" + " T.. = Timeline support\n" + " .S. = Slice threading\n" + " ..C = Command support\n" + " A = Audio input/output\n" + " V = Video input/output\n" + " N = Dynamic number and/or type of input/output\n" + " | = Source or sink filter\n"); + while ((filter = av_filter_iterate(&opaque))) { + descr_cur = descr; + for (i = 0; i < 2; i++) { + unsigned nb_pads; + if (i) { + *(descr_cur++) = '-'; + *(descr_cur++) = '>'; + } + pad = i ? filter->outputs : filter->inputs; + nb_pads = avfilter_filter_pad_count(filter, i); + for (j = 0; j < nb_pads; j++) { + if (descr_cur >= descr + sizeof(descr) - 4) + break; + *(descr_cur++) = get_media_type_char(avfilter_pad_get_type(pad, j)); + } + if (!j) + *(descr_cur++) = ((!i && (filter->flags & AVFILTER_FLAG_DYNAMIC_INPUTS)) || + ( i && (filter->flags & AVFILTER_FLAG_DYNAMIC_OUTPUTS))) ? 'N' : '|'; + } + *descr_cur = 0; + printf(" %c%c%c %-17s %-10s %s\n", + filter->flags & AVFILTER_FLAG_SUPPORT_TIMELINE ? 'T' : '.', + filter->flags & AVFILTER_FLAG_SLICE_THREADS ? 'S' : '.', + filter->process_command ? 'C' : '.', + filter->name, descr, filter->description); + } +#else + printf("No filters available: libavfilter disabled\n"); +#endif + 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) +{ + void *ifmt_opaque = NULL; + const AVInputFormat *ifmt = NULL; + void *ofmt_opaque = NULL; + const AVOutputFormat *ofmt = NULL; + const char *last_name; + int is_dev; + + printf("%s\n" + " D. = Demuxing supported\n" + " .E = Muxing supported\n" + " --\n", device_only ? "Devices:" : "File formats:"); + last_name = "000"; + for (;;) { + int decode = 0; + int encode = 0; + const char *name = NULL; + const char *long_name = NULL; + + if (muxdemuxers !=SHOW_DEMUXERS) { + ofmt_opaque = NULL; + while ((ofmt = av_muxer_iterate(&ofmt_opaque))) { + 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) { + ifmt_opaque = NULL; + while ((ifmt = av_demuxer_iterate(&ifmt_opaque))) { + 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; + + printf(" %c%c %-15s %s\n", + decode ? 'D' : ' ', + encode ? 'E' : ' ', + name, + long_name ? long_name:" "); + } + return 0; +} + +int show_formats(void *optctx, const char *opt, const char *arg) +{ + return show_formats_devices(optctx, opt, arg, 0, SHOW_DEFAULT); +} + +int show_muxers(void *optctx, const char *opt, const char *arg) +{ + return show_formats_devices(optctx, opt, arg, 0, SHOW_MUXERS); +} + +int show_demuxers(void *optctx, const char *opt, const char *arg) +{ + return show_formats_devices(optctx, opt, arg, 0, SHOW_DEMUXERS); +} + +int show_devices(void *optctx, const char *opt, const char *arg) +{ + return show_formats_devices(optctx, opt, arg, 1, SHOW_DEFAULT); +} + +int show_protocols(void *optctx, const char *opt, const char *arg) +{ + void *opaque = NULL; + const char *name; + + printf("Supported file protocols:\n" + "Input:\n"); + while ((name = avio_enum_protocols(&opaque, 0))) + printf(" %s\n", name); + printf("Output:\n"); + while ((name = avio_enum_protocols(&opaque, 1))) + printf(" %s\n", name); + return 0; +} + +int show_colors(void *optctx, const char *opt, const char *arg) +{ + const char *name; + const uint8_t *rgb; + int i; + + printf("%-32s #RRGGBB\n", "name"); + + for (i = 0; name = av_get_known_color_name(i, &rgb); i++) + printf("%-32s #%02x%02x%02x\n", name, rgb[0], rgb[1], rgb[2]); + + return 0; +} + +int show_pix_fmts(void *optctx, const char *opt, const char *arg) +{ + const AVPixFmtDescriptor *pix_desc = NULL; + + printf("Pixel formats:\n" + "I.... = Supported Input format for conversion\n" + ".O... = Supported Output format for conversion\n" + "..H.. = Hardware accelerated format\n" + "...P. = Paletted format\n" + "....B = Bitstream format\n" + "FLAGS NAME NB_COMPONENTS BITS_PER_PIXEL BIT_DEPTHS\n" + "-----\n"); + +#if !CONFIG_SWSCALE +# define sws_isSupportedInput(x) 0 +# define sws_isSupportedOutput(x) 0 +#endif + + while ((pix_desc = av_pix_fmt_desc_next(pix_desc))) { + enum AVPixelFormat av_unused pix_fmt = av_pix_fmt_desc_get_id(pix_desc); + printf("%c%c%c%c%c %-16s %d %3d %d", + sws_isSupportedInput (pix_fmt) ? 'I' : '.', + sws_isSupportedOutput(pix_fmt) ? 'O' : '.', + pix_desc->flags & AV_PIX_FMT_FLAG_HWACCEL ? 'H' : '.', + pix_desc->flags & AV_PIX_FMT_FLAG_PAL ? 'P' : '.', + pix_desc->flags & AV_PIX_FMT_FLAG_BITSTREAM ? 'B' : '.', + pix_desc->name, + pix_desc->nb_components, + av_get_bits_per_pixel(pix_desc), + pix_desc->comp[0].depth); + + for (unsigned i = 1; i < pix_desc->nb_components; i++) + printf("-%d", pix_desc->comp[i].depth); + printf("\n"); + } + return 0; +} + +int show_layouts(void *optctx, const char *opt, const char *arg) +{ + const AVChannelLayout *ch_layout; + void *iter = NULL; + char buf[128], buf2[128]; + int i = 0; + + printf("Individual channels:\n" + "NAME DESCRIPTION\n"); + for (i = 0; i < 63; i++) { + av_channel_name(buf, sizeof(buf), i); + if (strstr(buf, "USR")) + continue; + av_channel_description(buf2, sizeof(buf2), i); + printf("%-14s %s\n", buf, buf2); + } + printf("\nStandard channel layouts:\n" + "NAME DECOMPOSITION\n"); + while (ch_layout = av_channel_layout_standard(&iter)) { + av_channel_layout_describe(ch_layout, buf, sizeof(buf)); + printf("%-14s ", buf); + for (i = 0; i < 63; i++) { + int idx = av_channel_layout_index_from_channel(ch_layout, i); + if (idx >= 0) { + av_channel_name(buf2, sizeof(buf2), i); + printf("%s%s", idx ? "+" : "", buf2); + } + } + printf("\n"); + } + return 0; +} + +int show_sample_fmts(void *optctx, const char *opt, const char *arg) +{ + int i; + char fmt_str[128]; + for (i = -1; i < AV_SAMPLE_FMT_NB; i++) + printf("%s\n", av_get_sample_fmt_string(fmt_str, sizeof(fmt_str), i)); + return 0; +} + +int show_dispositions(void *optctx, const char *opt, const char *arg) +{ + for (int i = 0; i < 32; i++) { + const char *str = av_disposition_to_string(1U << i); + if (str) + printf("%s\n", str); + } + return 0; +} + +int opt_cpuflags(void *optctx, const char *opt, const char *arg) +{ + int ret; + unsigned flags = av_get_cpu_flags(); + + if ((ret = av_parse_cpu_caps(&flags, arg)) < 0) + return ret; + + av_force_cpu_flags(flags); + return 0; +} + +int opt_cpucount(void *optctx, const char *opt, const char *arg) +{ + int ret; + int count; + + static const AVOption opts[] = { + {"count", NULL, 0, AV_OPT_TYPE_INT, { .i64 = -1}, -1, INT_MAX}, + {NULL}, + }; + static const AVClass class = { + .class_name = "cpucount", + .item_name = av_default_item_name, + .option = opts, + .version = LIBAVUTIL_VERSION_INT, + }; + const AVClass *pclass = &class; + + ret = av_opt_eval_int(&pclass, opts, arg, &count); + + if (!ret) { + av_cpu_force_count(count); + } + + return ret; +} + +static void expand_filename_template(AVBPrint *bp, const char *template, + struct tm *tm) +{ + int c; + + while ((c = *(template++))) { + if (c == '%') { + if (!(c = *(template++))) + break; + switch (c) { + case 'p': + av_bprintf(bp, "%s", program_name); + break; + case 't': + av_bprintf(bp, "%04d%02d%02d-%02d%02d%02d", + tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); + break; + case '%': + av_bprint_chars(bp, c, 1); + break; + } + } else { + av_bprint_chars(bp, c, 1); + } + } +} + +static void log_callback_report(void *ptr, int level, const char *fmt, va_list vl) +{ + va_list vl2; + char line[1024]; + static int print_prefix = 1; + + va_copy(vl2, vl); + av_log_default_callback(ptr, level, fmt, vl); + av_log_format_line(ptr, level, fmt, vl2, line, sizeof(line), &print_prefix); + va_end(vl2); + if (report_file_level >= level) { + fputs(line, report_file); + fflush(report_file); + } +} + +int init_report(const char *env, FILE **file) +{ + char *filename_template = NULL; + char *key, *val; + int ret, count = 0; + int prog_loglevel, envlevel = 0; + time_t now; + struct tm *tm; + AVBPrint filename; + + if (report_file) /* already opened */ + return 0; + time(&now); + tm = localtime(&now); + + while (env && *env) { + if ((ret = av_opt_get_key_value(&env, "=", ":", 0, &key, &val)) < 0) { + if (count) + av_log(NULL, AV_LOG_ERROR, + "Failed to parse FFREPORT environment variable: %s\n", + av_err2str(ret)); + break; + } + if (*env) + env++; + count++; + if (!strcmp(key, "file")) { + av_free(filename_template); + filename_template = val; + val = NULL; + } else if (!strcmp(key, "level")) { + char *tail; + report_file_level = strtol(val, &tail, 10); + if (*tail) { + av_log(NULL, AV_LOG_FATAL, "Invalid report file level\n"); + exit_program(1); + } + envlevel = 1; + } else { + av_log(NULL, AV_LOG_ERROR, "Unknown key '%s' in FFREPORT\n", key); + } + av_free(val); + av_free(key); + } + + av_bprint_init(&filename, 0, AV_BPRINT_SIZE_AUTOMATIC); + expand_filename_template(&filename, + av_x_if_null(filename_template, "%p-%t.log"), tm); + av_free(filename_template); + if (!av_bprint_is_complete(&filename)) { + av_log(NULL, AV_LOG_ERROR, "Out of memory building report file name\n"); + return AVERROR(ENOMEM); + } + + prog_loglevel = av_log_get_level(); + if (!envlevel) + report_file_level = FFMAX(report_file_level, prog_loglevel); + + report_file = fopen(filename.str, "w"); + if (!report_file) { + int ret = AVERROR(errno); + av_log(NULL, AV_LOG_ERROR, "Failed to open report \"%s\": %s\n", + filename.str, strerror(errno)); + return ret; + } + av_log_set_callback(log_callback_report); + av_log(NULL, AV_LOG_INFO, + "%s started on %04d-%02d-%02d at %02d:%02d:%02d\n" + "Report written to \"%s\"\n" + "Log level: %d\n", + program_name, + tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec, + filename.str, report_file_level); + av_bprint_finalize(&filename, NULL); + + if (file) + *file = report_file; + + return 0; +} + +int opt_report(void *optctx, const char *opt, const char *arg) +{ + return init_report(NULL, NULL); +} + +int opt_max_alloc(void *optctx, const char *opt, const char *arg) +{ + char *tail; + size_t max; + + max = strtol(arg, &tail, 10); + if (*tail) { + av_log(NULL, AV_LOG_FATAL, "Invalid max_alloc \"%s\".\n", arg); + exit_program(1); + } + av_max_alloc(max); + return 0; +} + +int opt_loglevel(void *optctx, const char *opt, const char *arg) +{ + const struct { const char *name; int level; } log_levels[] = { + { "quiet" , AV_LOG_QUIET }, + { "panic" , AV_LOG_PANIC }, + { "fatal" , AV_LOG_FATAL }, + { "error" , AV_LOG_ERROR }, + { "warning", AV_LOG_WARNING }, + { "info" , AV_LOG_INFO }, + { "verbose", AV_LOG_VERBOSE }, + { "debug" , AV_LOG_DEBUG }, + { "trace" , AV_LOG_TRACE }, + }; + const char *token; + char *tail; + 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 (av_strstart(token, "repeat", &arg)) { + if (cmd == '-') { + flags |= AV_LOG_SKIP_REPEATED; + } else { + flags &= ~AV_LOG_SKIP_REPEATED; + } + } else if (av_strstart(token, "level", &arg)) { + if (cmd == '-') { + flags &= ~AV_LOG_PRINT_LEVEL; + } else { + flags |= AV_LOG_PRINT_LEVEL; + } + } 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)) { + level = log_levels[i].level; + goto end; + } + } + + level = strtol(arg, &tail, 10); + if (*tail) { + av_log(NULL, AV_LOG_FATAL, "Invalid loglevel \"%s\". " + "Possible levels are numbers or:\n", arg); + for (i = 0; i < FF_ARRAY_ELEMS(log_levels); i++) + 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; +} + +#if CONFIG_AVDEVICE +static void print_device_list(const AVDeviceInfoList *device_list) +{ + // print devices + for (int i = 0; i < device_list->nb_devices; i++) { + const AVDeviceInfo *device = device_list->devices[i]; + printf("%c %s [%s] (", device_list->default_device == i ? '*' : ' ', + device->device_name, device->device_description); + if (device->nb_media_types > 0) { + for (int j = 0; j < device->nb_media_types; ++j) { + const char* media_type = av_get_media_type_string(device->media_types[j]); + if (j > 0) + printf(", "); + printf("%s", media_type ? media_type : "unknown"); + } + } else { + printf("none"); + } + printf(")\n"); + } +} + +static int print_device_sources(const AVInputFormat *fmt, AVDictionary *opts) +{ + int ret; + AVDeviceInfoList *device_list = NULL; + + if (!fmt || !fmt->priv_class || !AV_IS_INPUT_DEVICE(fmt->priv_class->category)) + return AVERROR(EINVAL); + + printf("Auto-detected sources for %s:\n", fmt->name); + if ((ret = avdevice_list_input_sources(fmt, NULL, opts, &device_list)) < 0) { + printf("Cannot list sources: %s\n", av_err2str(ret)); + goto fail; + } + + print_device_list(device_list); + + fail: + avdevice_free_list_devices(&device_list); + return ret; +} + +static int print_device_sinks(const AVOutputFormat *fmt, AVDictionary *opts) +{ + int ret; + AVDeviceInfoList *device_list = NULL; + + if (!fmt || !fmt->priv_class || !AV_IS_OUTPUT_DEVICE(fmt->priv_class->category)) + return AVERROR(EINVAL); + + printf("Auto-detected sinks for %s:\n", fmt->name); + if ((ret = avdevice_list_output_sinks(fmt, NULL, opts, &device_list)) < 0) { + printf("Cannot list sinks: %s\n", av_err2str(ret)); + goto fail; + } + + print_device_list(device_list); + + fail: + avdevice_free_list_devices(&device_list); + return ret; +} + +static int show_sinks_sources_parse_arg(const char *arg, char **dev, AVDictionary **opts) +{ + int ret; + if (arg) { + char *opts_str = NULL; + av_assert0(dev && opts); + *dev = av_strdup(arg); + if (!*dev) + return AVERROR(ENOMEM); + if ((opts_str = strchr(*dev, ','))) { + *(opts_str++) = '\0'; + if (opts_str[0] && ((ret = av_dict_parse_string(opts, opts_str, "=", ":", 0)) < 0)) { + av_freep(dev); + return ret; + } + } + } else + printf("\nDevice name is not provided.\n" + "You can pass devicename[,opt1=val1[,opt2=val2...]] as an argument.\n\n"); + return 0; +} + +int show_sources(void *optctx, const char *opt, const char *arg) +{ + const AVInputFormat *fmt = NULL; + char *dev = NULL; + AVDictionary *opts = NULL; + int ret = 0; + int error_level = av_log_get_level(); + + av_log_set_level(AV_LOG_WARNING); + + 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); + fail: + av_dict_free(&opts); + av_free(dev); + av_log_set_level(error_level); + return ret; +} + +int show_sinks(void *optctx, const char *opt, const char *arg) +{ + const AVOutputFormat *fmt = NULL; + char *dev = NULL; + AVDictionary *opts = NULL; + int ret = 0; + int error_level = av_log_get_level(); + + av_log_set_level(AV_LOG_WARNING); + + 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); + fail: + av_dict_free(&opts); + av_free(dev); + av_log_set_level(error_level); + return ret; +} +#endif /* CONFIG_AVDEVICE */ diff --git a/fftools/opt_common.h b/fftools/opt_common.h new file mode 100644 index 000000000..ea1d16e76 --- /dev/null +++ b/fftools/opt_common.h @@ -0,0 +1,231 @@ +/* + * Option handlers shared between the tools. + * + * 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_OPT_COMMON_H +#define FFTOOLS_OPT_COMMON_H + +#include "config.h" + +#include "cmdutils.h" + +#if CONFIG_AVDEVICE +/** + * Print a listing containing autodetected sinks of the output device. + * Device name with options may be passed as an argument to limit results. + */ +int show_sinks(void *optctx, const char *opt, const char *arg); + +/** + * Print a listing containing autodetected sources of the input device. + * Device name with options may be passed as an argument to limit results. + */ +int show_sources(void *optctx, const char *opt, const char *arg); +#endif + +#if CONFIG_AVDEVICE +#define CMDUTILS_COMMON_OPTIONS_AVDEVICE \ + { "sources" , OPT_EXIT | HAS_ARG, { .func_arg = show_sources }, \ + "list sources of the input device", "device" }, \ + { "sinks" , OPT_EXIT | HAS_ARG, { .func_arg = show_sinks }, \ + "list sinks of the output device", "device" }, \ + +#else +#define CMDUTILS_COMMON_OPTIONS_AVDEVICE +#endif + +/** + * Print the license of the program to stdout. The license depends on + * the license of the libraries compiled into the program. + * This option processing function does not utilize the arguments. + */ +int show_license(void *optctx, const char *opt, const char *arg); + +/** + * Generic -h handler common to all fftools. + */ +int show_help(void *optctx, const char *opt, const char *arg); + +/** + * Print the version of the program to stdout. The version message + * depends on the current versions of the repository and of the libav* + * libraries. + * This option processing function does not utilize the arguments. + */ +int show_version(void *optctx, const char *opt, const char *arg); + +/** + * Print the build configuration of the program to stdout. The contents + * depend on the definition of FFMPEG_CONFIGURATION. + * This option processing function does not utilize the arguments. + */ +int show_buildconf(void *optctx, const char *opt, const char *arg); + +/** + * Print a listing containing all the formats supported by the + * program (including devices). + * This option processing function does not utilize the arguments. + */ +int show_formats(void *optctx, const char *opt, const char *arg); + +/** + * Print a listing containing all the muxers supported by the + * program (including devices). + * This option processing function does not utilize the arguments. + */ +int show_muxers(void *optctx, const char *opt, const char *arg); + +/** + * Print a listing containing all the demuxer supported by the + * program (including devices). + * This option processing function does not utilize the arguments. + */ +int show_demuxers(void *optctx, const char *opt, const char *arg); + +/** + * Print a listing containing all the devices supported by the + * program. + * This option processing function does not utilize the arguments. + */ +int show_devices(void *optctx, const char *opt, const char *arg); + +/** + * Print a listing containing all the codecs supported by the + * program. + * This option processing function does not utilize the arguments. + */ +int show_codecs(void *optctx, const char *opt, const char *arg); + +/** + * Print a listing containing all the decoders supported by the + * program. + */ +int show_decoders(void *optctx, const char *opt, const char *arg); + +/** + * Print a listing containing all the encoders supported by the + * program. + */ +int show_encoders(void *optctx, const char *opt, const char *arg); + +/** + * Print a listing containing all the bit stream filters supported by the + * program. + * This option processing function does not utilize the arguments. + */ +int show_bsfs(void *optctx, const char *opt, const char *arg); + +/** + * Print a listing containing all the protocols supported by the + * program. + * This option processing function does not utilize the arguments. + */ +int show_protocols(void *optctx, const char *opt, const char *arg); + +/** + * Print a listing containing all the filters supported by the + * program. + * This option processing function does not utilize the arguments. + */ +int show_filters(void *optctx, const char *opt, const char *arg); + +/** + * Print a listing containing all the pixel formats supported by the + * program. + * This option processing function does not utilize the arguments. + */ +int show_pix_fmts(void *optctx, const char *opt, const char *arg); + +/** + * Print a listing containing all the standard channel layouts supported by + * the program. + * This option processing function does not utilize the arguments. + */ +int show_layouts(void *optctx, const char *opt, const char *arg); + +/** + * Print a listing containing all the sample formats supported by the + * program. + */ +int show_sample_fmts(void *optctx, const char *opt, const char *arg); + +/** + * Print a listing containing all supported stream dispositions. + */ +int show_dispositions(void *optctx, const char *opt, const char *arg); + +/** + * Print a listing containing all the color names and values recognized + * by the program. + */ +int show_colors(void *optctx, const char *opt, const char *arg); + +/** + * Set the libav* libraries log level. + */ +int opt_loglevel(void *optctx, const char *opt, const char *arg); + +int opt_report(void *optctx, const char *opt, const char *arg); +int init_report(const char *env, FILE **file); + +int opt_max_alloc(void *optctx, const char *opt, const char *arg); + +/** + * Override the cpuflags. + */ +int opt_cpuflags(void *optctx, const char *opt, const char *arg); + +/** + * Override the cpucount. + */ +int opt_cpucount(void *optctx, const char *opt, const char *arg); + +#define CMDUTILS_COMMON_OPTIONS \ + { "L", OPT_EXIT, { .func_arg = show_license }, "show license" }, \ + { "h", OPT_EXIT, { .func_arg = show_help }, "show help", "topic" }, \ + { "?", OPT_EXIT, { .func_arg = show_help }, "show help", "topic" }, \ + { "help", OPT_EXIT, { .func_arg = show_help }, "show help", "topic" }, \ + { "-help", OPT_EXIT, { .func_arg = show_help }, "show help", "topic" }, \ + { "version", OPT_EXIT, { .func_arg = show_version }, "show version" }, \ + { "buildconf", OPT_EXIT, { .func_arg = show_buildconf }, "show build configuration" }, \ + { "formats", OPT_EXIT, { .func_arg = show_formats }, "show available formats" }, \ + { "muxers", OPT_EXIT, { .func_arg = show_muxers }, "show available muxers" }, \ + { "demuxers", OPT_EXIT, { .func_arg = show_demuxers }, "show available demuxers" }, \ + { "devices", OPT_EXIT, { .func_arg = show_devices }, "show available devices" }, \ + { "codecs", OPT_EXIT, { .func_arg = show_codecs }, "show available codecs" }, \ + { "decoders", OPT_EXIT, { .func_arg = show_decoders }, "show available decoders" }, \ + { "encoders", OPT_EXIT, { .func_arg = show_encoders }, "show available encoders" }, \ + { "bsfs", OPT_EXIT, { .func_arg = show_bsfs }, "show available bit stream filters" }, \ + { "protocols", OPT_EXIT, { .func_arg = show_protocols }, "show available protocols" }, \ + { "filters", OPT_EXIT, { .func_arg = show_filters }, "show available filters" }, \ + { "pix_fmts", OPT_EXIT, { .func_arg = show_pix_fmts }, "show available pixel formats" }, \ + { "layouts", OPT_EXIT, { .func_arg = show_layouts }, "show standard channel layouts" }, \ + { "sample_fmts", OPT_EXIT, { .func_arg = show_sample_fmts }, "show available audio sample formats" }, \ + { "dispositions", OPT_EXIT, { .func_arg = show_dispositions}, "show available stream dispositions" }, \ + { "colors", OPT_EXIT, { .func_arg = show_colors }, "show available color names" }, \ + { "loglevel", HAS_ARG, { .func_arg = opt_loglevel }, "set logging level", "loglevel" }, \ + { "v", HAS_ARG, { .func_arg = opt_loglevel }, "set logging level", "loglevel" }, \ + { "report", 0, { .func_arg = opt_report }, "generate a report" }, \ + { "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" }, \ + { "cpucount", HAS_ARG | OPT_EXPERT, { .func_arg = opt_cpucount }, "force specific cpu count", "count" }, \ + { "hide_banner", OPT_BOOL | OPT_EXPERT, {&hide_banner}, "do not show program banner", "hide_banner" }, \ + CMDUTILS_COMMON_OPTIONS_AVDEVICE \ + +#endif /* FFTOOLS_OPT_COMMON_H */ diff --git a/libavcodec/012v.c b/libavcodec/012v.c index 08c9938b1..c03afd0bc 100644 --- a/libavcodec/012v.c +++ b/libavcodec/012v.c @@ -21,6 +21,7 @@ */ #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "libavutil/intreadwrite.h" @@ -35,12 +36,11 @@ static av_cold int zero12v_decode_init(AVCodecContext *avctx) return 0; } -static int zero12v_decode_frame(AVCodecContext *avctx, void *data, +static int zero12v_decode_frame(AVCodecContext *avctx, AVFrame *pic, int *got_frame, AVPacket *avpkt) { int line, ret; const int width = avctx->width; - AVFrame *pic = data; uint16_t *y, *u, *v; const uint8_t *line_end, *src = avpkt->data; int stride = avctx->width * 8 / 3; @@ -144,13 +144,13 @@ static int zero12v_decode_frame(AVCodecContext *avctx, void *data, return avpkt->size; } -const AVCodec ff_zero12v_decoder = { - .name = "012v", - .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_012V, +const FFCodec ff_zero12v_decoder = { + .p.name = "012v", + .p.long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_012V, .init = zero12v_decode_init, - .decode = zero12v_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(zero12v_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/4xm.c b/libavcodec/4xm.c index cb315cd7e..7b88631a6 100644 --- a/libavcodec/4xm.c +++ b/libavcodec/4xm.c @@ -36,6 +36,7 @@ #include "blockdsp.h" #include "bswapdsp.h" #include "bytestream.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" @@ -249,7 +250,7 @@ static void idct(int16_t block[64]) static av_cold void init_vlcs(void) { - static VLC_TYPE table[2][4][32][2]; + static VLCElem table[2][4][32]; int i, j; for (i = 0; i < 2; i++) { @@ -833,13 +834,12 @@ static int decode_i_frame(FourXContext *f, const uint8_t *buf, int length) return 0; } -static int decode_frame(AVCodecContext *avctx, void *data, +static int decode_frame(AVCodecContext *avctx, AVFrame *picture, int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; FourXContext *const f = avctx->priv_data; - AVFrame *picture = data; int i, frame_4cc, frame_size, ret; if (buf_size < 20) @@ -1008,10 +1008,8 @@ static av_cold int decode_init(AVCodecContext *avctx) f->frame_buffer = av_mallocz(avctx->width * avctx->height * 2); f->last_frame_buffer = av_mallocz(avctx->width * avctx->height * 2); - if (!f->frame_buffer || !f->last_frame_buffer) { - decode_end(avctx); + if (!f->frame_buffer || !f->last_frame_buffer) return AVERROR(ENOMEM); - } f->version = AV_RL32(avctx->extradata) >> 16; ff_blockdsp_init(&f->bdsp, avctx); @@ -1028,15 +1026,15 @@ static av_cold int decode_init(AVCodecContext *avctx) return 0; } -const AVCodec ff_fourxm_decoder = { - .name = "4xm", - .long_name = NULL_IF_CONFIG_SMALL("4X Movie"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_4XM, +const FFCodec ff_fourxm_decoder = { + .p.name = "4xm", + .p.long_name = NULL_IF_CONFIG_SMALL("4X Movie"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_4XM, .priv_data_size = sizeof(FourXContext), .init = decode_init, .close = decode_end, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/8bps.c b/libavcodec/8bps.c index 6865b9b12..95a35159e 100644 --- a/libavcodec/8bps.c +++ b/libavcodec/8bps.c @@ -37,6 +37,7 @@ #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" #include "avcodec.h" +#include "codec_internal.h" #include "decode.h" #include "internal.h" @@ -53,10 +54,9 @@ typedef struct EightBpsContext { uint32_t pal[256]; } EightBpsContext; -static int decode_frame(AVCodecContext *avctx, void *data, +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt) { - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; EightBpsContext * const c = avctx->priv_data; @@ -173,13 +173,14 @@ static av_cold int decode_init(AVCodecContext *avctx) return 0; } -const AVCodec ff_eightbps_decoder = { - .name = "8bps", - .long_name = NULL_IF_CONFIG_SMALL("QuickTime 8BPS video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_8BPS, +const FFCodec ff_eightbps_decoder = { + .p.name = "8bps", + .p.long_name = NULL_IF_CONFIG_SMALL("QuickTime 8BPS video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_8BPS, .priv_data_size = sizeof(EightBpsContext), .init = decode_init, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/8svx.c b/libavcodec/8svx.c index 6ef8cd73f..6eb90834b 100644 --- a/libavcodec/8svx.c +++ b/libavcodec/8svx.c @@ -37,8 +37,11 @@ * http://aminet.net/mods/smpl/ */ +#include "config_components.h" + #include "libavutil/avassert.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "libavutil/common.h" @@ -83,43 +86,43 @@ static void delta_decode(uint8_t *dst, const uint8_t *src, int src_size, } /** decode a frame */ -static int eightsvx_decode_frame(AVCodecContext *avctx, void *data, +static int eightsvx_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { EightSvxContext *esc = avctx->priv_data; - AVFrame *frame = data; + int channels = avctx->ch_layout.nb_channels; int buf_size; int ch, ret; int hdr_size = 2; /* decode and interleave the first packet */ if (!esc->data[0] && avpkt) { - int chan_size = avpkt->size / avctx->channels - hdr_size; + int chan_size = avpkt->size / channels - hdr_size; - if (avpkt->size % avctx->channels) { + if (avpkt->size % channels) { av_log(avctx, AV_LOG_WARNING, "Packet with odd size, ignoring last byte\n"); } - if (avpkt->size < (hdr_size + 1) * avctx->channels) { + if (avpkt->size < (hdr_size + 1) * channels) { av_log(avctx, AV_LOG_ERROR, "packet size is too small\n"); return AVERROR_INVALIDDATA; } esc->fib_acc[0] = avpkt->data[1] + 128; - if (avctx->channels == 2) + if (channels == 2) esc->fib_acc[1] = avpkt->data[2+chan_size+1] + 128; esc->data_idx = 0; esc->data_size = chan_size; if (!(esc->data[0] = av_malloc(chan_size))) return AVERROR(ENOMEM); - if (avctx->channels == 2) { + if (channels == 2) { if (!(esc->data[1] = av_malloc(chan_size))) { av_freep(&esc->data[0]); return AVERROR(ENOMEM); } } memcpy(esc->data[0], &avpkt->data[hdr_size], chan_size); - if (avctx->channels == 2) + if (channels == 2) memcpy(esc->data[1], &avpkt->data[2*hdr_size+chan_size], chan_size); } if (!esc->data[0]) { @@ -139,7 +142,7 @@ static int eightsvx_decode_frame(AVCodecContext *avctx, void *data, if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; - for (ch = 0; ch < avctx->channels; ch++) { + for (ch = 0; ch < channels; ch++) { delta_decode(frame->data[ch], &esc->data[ch][esc->data_idx], buf_size, &esc->fib_acc[ch], esc->table); } @@ -148,14 +151,14 @@ static int eightsvx_decode_frame(AVCodecContext *avctx, void *data, *got_frame_ptr = 1; - return ((avctx->frame_number == 0)*hdr_size + buf_size)*avctx->channels; + return ((avctx->frame_number == 0) * hdr_size + buf_size) * channels; } static av_cold int eightsvx_decode_init(AVCodecContext *avctx) { EightSvxContext *esc = avctx->priv_data; - if (avctx->channels < 1 || avctx->channels > 2) { + if (avctx->ch_layout.nb_channels < 1 || avctx->ch_layout.nb_channels > 2) { av_log(avctx, AV_LOG_ERROR, "8SVX does not support more than 2 channels\n"); return AVERROR_INVALIDDATA; } @@ -184,33 +187,33 @@ static av_cold int eightsvx_decode_close(AVCodecContext *avctx) } #if CONFIG_EIGHTSVX_FIB_DECODER -const AVCodec ff_eightsvx_fib_decoder = { - .name = "8svx_fib", - .long_name = NULL_IF_CONFIG_SMALL("8SVX fibonacci"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_8SVX_FIB, +const FFCodec ff_eightsvx_fib_decoder = { + .p.name = "8svx_fib", + .p.long_name = NULL_IF_CONFIG_SMALL("8SVX fibonacci"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_8SVX_FIB, .priv_data_size = sizeof (EightSvxContext), .init = eightsvx_decode_init, - .decode = eightsvx_decode_frame, + FF_CODEC_DECODE_CB(eightsvx_decode_frame), .close = eightsvx_decode_close, - .capabilities = AV_CODEC_CAP_DR1, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_U8P, + .p.capabilities = AV_CODEC_CAP_DR1, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_U8P, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_EIGHTSVX_EXP_DECODER -const AVCodec ff_eightsvx_exp_decoder = { - .name = "8svx_exp", - .long_name = NULL_IF_CONFIG_SMALL("8SVX exponential"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_8SVX_EXP, +const FFCodec ff_eightsvx_exp_decoder = { + .p.name = "8svx_exp", + .p.long_name = NULL_IF_CONFIG_SMALL("8SVX exponential"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_8SVX_EXP, .priv_data_size = sizeof (EightSvxContext), .init = eightsvx_decode_init, - .decode = eightsvx_decode_frame, + FF_CODEC_DECODE_CB(eightsvx_decode_frame), .close = eightsvx_decode_close, - .capabilities = AV_CODEC_CAP_DR1, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_U8P, + .p.capabilities = AV_CODEC_CAP_DR1, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_U8P, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 3adf1536d..457ec5837 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -22,6 +22,7 @@ HEADERS = ac3_parser.h \ qsv.h \ vdpau.h \ version.h \ + version_major.h \ videotoolbox.h \ vorbis_parser.h \ xvmc.h \ @@ -42,6 +43,7 @@ OBJS = ac3_parser.o \ dirac.o \ dv_profile.o \ encode.o \ + get_buffer.o \ imgconvert.o \ jni.o \ mathtables.o \ @@ -54,6 +56,8 @@ OBJS = ac3_parser.o \ qsv_api.o \ raw.o \ utils.o \ + version.o \ + vlc.o \ vorbis_parser.o \ xiph.o \ @@ -77,6 +81,7 @@ OBJS-$(CONFIG_CBS_MPEG2) += cbs_mpeg2.o OBJS-$(CONFIG_CBS_VP9) += cbs_vp9.o OBJS-$(CONFIG_CRYSTALHD) += crystalhd.o OBJS-$(CONFIG_DCT) += dct.o dct32_fixed.o dct32_float.o +OBJS-$(CONFIG_DEFLATE_WRAPPER) += zlib_wrapper.o OBJS-$(CONFIG_DOVI_RPU) += dovi_rpu.o OBJS-$(CONFIG_ERROR_RESILIENCE) += error_resilience.o OBJS-$(CONFIG_EXIF) += exif.o tiff_common.o @@ -96,7 +101,7 @@ OBJS-$(CONFIG_H264PARSE) += h264_parse.o h2645_parse.o h264_ps.o OBJS-$(CONFIG_H264PRED) += h264pred.o OBJS-$(CONFIG_H264QPEL) += h264qpel.o OBJS-$(CONFIG_HEVCPARSE) += hevc_parse.o h2645_parse.o hevc_ps.o hevc_sei.o hevc_data.o \ - dynamic_hdr10_plus.o + dynamic_hdr10_plus.o dynamic_hdr_vivid.o OBJS-$(CONFIG_HPELDSP) += hpeldsp.o OBJS-$(CONFIG_HUFFMAN) += huffman.o OBJS-$(CONFIG_HUFFYUVDSP) += huffyuvdsp.o @@ -104,6 +109,7 @@ OBJS-$(CONFIG_HUFFYUVENCDSP) += huffyuvencdsp.o OBJS-$(CONFIG_IDCTDSP) += idctdsp.o simple_idct.o jrevdct.o OBJS-$(CONFIG_IIRFILTER) += iirfilter.o OBJS-$(CONFIG_MDCT15) += mdct15.o +OBJS-$(CONFIG_INFLATE_WRAPPER) += zlib_wrapper.o OBJS-$(CONFIG_INTRAX8) += intrax8.o intrax8dsp.o msmpeg4data.o OBJS-$(CONFIG_IVIDSP) += ivi_dsp.o OBJS-$(CONFIG_JNI) += ffjni.o jni.o @@ -127,9 +133,10 @@ OBJS-$(CONFIG_MPEGAUDIODSP) += mpegaudiodsp.o \ OBJS-$(CONFIG_MPEGAUDIOHEADER) += mpegaudiodecheader.o mpegaudiotabs.o OBJS-$(CONFIG_MPEG4AUDIO) += mpeg4audio.o mpeg4audio_sample_rates.o OBJS-$(CONFIG_MPEGVIDEO) += mpegvideo.o mpegvideodsp.o rl.o \ - mpegvideo_motion.o mpegutils.o \ + mpegvideo_motion.o \ mpegvideodata.o mpegpicture.o \ to_upper4.o +OBJS-$(CONFIG_MPEGVIDEODEC) += mpegvideo_dec.o mpegutils.o OBJS-$(CONFIG_MPEGVIDEOENC) += mpegvideo_enc.o mpeg12data.o \ motion_est.o ratecontrol.o \ mpegvideoencdsp.o @@ -288,6 +295,8 @@ OBJS-$(CONFIG_DERF_DPCM_DECODER) += dpcm.o OBJS-$(CONFIG_DIRAC_DECODER) += diracdec.o dirac.o diracdsp.o diractab.o \ dirac_arith.o dirac_dwt.o dirac_vlc.o OBJS-$(CONFIG_DFA_DECODER) += dfa.o +OBJS-$(CONFIG_DFPWM_DECODER) += dfpwmdec.o +OBJS-$(CONFIG_DFPWM_ENCODER) += dfpwmenc.o OBJS-$(CONFIG_DNXHD_DECODER) += dnxhddec.o dnxhddata.o OBJS-$(CONFIG_DNXHD_ENCODER) += dnxhdenc.o dnxhddata.o OBJS-$(CONFIG_DOLBY_E_DECODER) += dolby_e.o dolby_e_parse.o kbdwin.o @@ -562,6 +571,8 @@ OBJS-$(CONFIG_PGMYUV_DECODER) += pnmdec.o pnm.o OBJS-$(CONFIG_PGMYUV_ENCODER) += pnmenc.o OBJS-$(CONFIG_PGSSUB_DECODER) += pgssubdec.o OBJS-$(CONFIG_PGX_DECODER) += pgxdec.o +OBJS-$(CONFIG_PHM_DECODER) += pnmdec.o pnm.o +OBJS-$(CONFIG_PHM_ENCODER) += pnmenc.o OBJS-$(CONFIG_PHOTOCD_DECODER) += photocd.o OBJS-$(CONFIG_PICTOR_DECODER) += pictordec.o cga_data.o OBJS-$(CONFIG_PIXLET_DECODER) += pixlet.o @@ -584,6 +595,8 @@ OBJS-$(CONFIG_QCELP_DECODER) += qcelpdec.o \ OBJS-$(CONFIG_QDM2_DECODER) += qdm2.o OBJS-$(CONFIG_QDMC_DECODER) += qdmc.o OBJS-$(CONFIG_QDRAW_DECODER) += qdrw.o +OBJS-$(CONFIG_QOI_DECODER) += qoidec.o +OBJS-$(CONFIG_QOI_ENCODER) += qoienc.o OBJS-$(CONFIG_QPEG_DECODER) += qpeg.o OBJS-$(CONFIG_QTRLE_DECODER) += qtrle.o OBJS-$(CONFIG_QTRLE_ENCODER) += qtrleenc.o @@ -701,6 +714,8 @@ OBJS-$(CONFIG_V408_ENCODER) += v408enc.o OBJS-$(CONFIG_V410_DECODER) += v410dec.o OBJS-$(CONFIG_V410_ENCODER) += v410enc.o OBJS-$(CONFIG_VB_DECODER) += vb.o +OBJS-$(CONFIG_VBN_DECODER) += vbndec.o +OBJS-$(CONFIG_VBN_ENCODER) += vbnenc.o OBJS-$(CONFIG_VBLE_DECODER) += vble.o OBJS-$(CONFIG_VC1_DECODER) += vc1dec.o vc1_block.o vc1_loopfilter.o \ vc1_mc.o vc1_pred.o vc1.o vc1data.o \ @@ -799,6 +814,7 @@ OBJS-$(CONFIG_ZMBV_ENCODER) += zmbvenc.o # (AD)PCM decoders/encoders OBJS-$(CONFIG_PCM_ALAW_DECODER) += pcm.o OBJS-$(CONFIG_PCM_ALAW_ENCODER) += pcm.o +OBJS-$(CONFIG_PCM_BLURAY_ENCODER) += pcm-blurayenc.o OBJS-$(CONFIG_PCM_BLURAY_DECODER) += pcm-bluray.o OBJS-$(CONFIG_PCM_DVD_DECODER) += pcm-dvd.o OBJS-$(CONFIG_PCM_DVD_ENCODER) += pcm-dvdenc.o @@ -942,6 +958,7 @@ OBJS-$(CONFIG_AV1_D3D11VA_HWACCEL) += dxva2_av1.o OBJS-$(CONFIG_AV1_DXVA2_HWACCEL) += dxva2_av1.o OBJS-$(CONFIG_AV1_NVDEC_HWACCEL) += nvdec_av1.o OBJS-$(CONFIG_AV1_VAAPI_HWACCEL) += vaapi_av1.o +OBJS-$(CONFIG_AV1_VDPAU_HWACCEL) += vdpau_av1.o OBJS-$(CONFIG_H263_VAAPI_HWACCEL) += vaapi_mpeg4.o OBJS-$(CONFIG_H263_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o OBJS-$(CONFIG_H264_D3D11VA_HWACCEL) += dxva2_h264.o @@ -962,7 +979,6 @@ 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 -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 @@ -970,7 +986,6 @@ OBJS-$(CONFIG_MPEG2_QSV_HWACCEL) += qsvdec.o 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 @@ -1053,6 +1068,8 @@ OBJS-$(CONFIG_LIBGSM_MS_DECODER) += libgsmdec.o OBJS-$(CONFIG_LIBGSM_MS_ENCODER) += libgsmenc.o OBJS-$(CONFIG_LIBILBC_DECODER) += libilbc.o OBJS-$(CONFIG_LIBILBC_ENCODER) += libilbc.o +OBJS-$(CONFIG_LIBJXL_DECODER) += libjxldec.o libjxl.o +OBJS-$(CONFIG_LIBJXL_ENCODER) += libjxlenc.o libjxl.o OBJS-$(CONFIG_LIBKVAZAAR_ENCODER) += libkvazaar.o OBJS-$(CONFIG_LIBMP3LAME_ENCODER) += libmp3lame.o OBJS-$(CONFIG_LIBOPENCORE_AMRNB_DECODER) += libopencore-amr.o @@ -1100,7 +1117,7 @@ OBJS-$(CONFIG_AC3_PARSER) += aac_ac3_parser.o ac3tab.o \ OBJS-$(CONFIG_ADX_PARSER) += adx_parser.o adx.o OBJS-$(CONFIG_AMR_PARSER) += amr_parser.o OBJS-$(CONFIG_AV1_PARSER) += av1_parser.o -OBJS-$(CONFIG_AVS2_PARSER) += avs2_parser.o +OBJS-$(CONFIG_AVS2_PARSER) += avs2.o avs2_parser.o OBJS-$(CONFIG_AVS3_PARSER) += avs3_parser.o OBJS-$(CONFIG_BMP_PARSER) += bmp_parser.o OBJS-$(CONFIG_CAVSVIDEO_PARSER) += cavs_parser.o @@ -1139,6 +1156,7 @@ 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_QOI_PARSER) += qoi_parser.o OBJS-$(CONFIG_RV30_PARSER) += rv34_parser.o OBJS-$(CONFIG_RV40_PARSER) += rv34_parser.o OBJS-$(CONFIG_SBC_PARSER) += sbc_parser.o @@ -1161,6 +1179,7 @@ OBJS-$(CONFIG_AV1_FRAME_SPLIT_BSF) += av1_frame_split_bsf.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_DV_ERROR_MARKER_BSF) += dv_error_marker_bsf.o OBJS-$(CONFIG_EAC3_CORE_BSF) += eac3_core_bsf.o OBJS-$(CONFIG_EXTRACT_EXTRADATA_BSF) += extract_extradata_bsf.o \ av1_parse.o h2645_parse.o @@ -1183,6 +1202,7 @@ OBJS-$(CONFIG_NOISE_BSF) += noise_bsf.o OBJS-$(CONFIG_NULL_BSF) += null_bsf.o OBJS-$(CONFIG_OPUS_METADATA_BSF) += opus_metadata_bsf.o OBJS-$(CONFIG_PCM_RECHUNK_BSF) += pcm_rechunk_bsf.o +OBJS-$(CONFIG_PGS_FRAME_MERGE_BSF) += pgs_frame_merge_bsf.o OBJS-$(CONFIG_PRORES_METADATA_BSF) += prores_metadata_bsf.o OBJS-$(CONFIG_REMOVE_EXTRADATA_BSF) += remove_extradata_bsf.o av1_parse.o OBJS-$(CONFIG_SETTS_BSF) += setts_bsf.o @@ -1217,6 +1237,7 @@ 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 +SKIPHEADERS-$(CONFIG_LIBJXL) += libjxl.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 diff --git a/libavcodec/a64multienc.c b/libavcodec/a64multienc.c index 7bdf4a61b..e80139ee5 100644 --- a/libavcodec/a64multienc.c +++ b/libavcodec/a64multienc.c @@ -24,11 +24,13 @@ * a64 video encoder - multicolor modes */ +#include "config_components.h" + #include "a64colors.h" #include "a64tables.h" +#include "codec_internal.h" #include "elbg.h" #include "encode.h" -#include "internal.h" #include "libavutil/avassert.h" #include "libavutil/common.h" #include "libavutil/intreadwrite.h" @@ -391,32 +393,32 @@ static int a64multi_encode_frame(AVCodecContext *avctx, AVPacket *pkt, } #if CONFIG_A64MULTI_ENCODER -const AVCodec ff_a64multi_encoder = { - .name = "a64multi", - .long_name = NULL_IF_CONFIG_SMALL("Multicolor charset for Commodore 64"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_A64_MULTI, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, +const FFCodec ff_a64multi_encoder = { + .p.name = "a64multi", + .p.long_name = NULL_IF_CONFIG_SMALL("Multicolor charset for Commodore 64"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_A64_MULTI, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, .priv_data_size = sizeof(A64Context), .init = a64multi_encode_init, - .encode2 = a64multi_encode_frame, + FF_CODEC_ENCODE_CB(a64multi_encode_frame), .close = a64multi_close_encoder, - .pix_fmts = (const enum AVPixelFormat[]) {AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE}, + .p.pix_fmts = (const enum AVPixelFormat[]) {AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE}, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_A64MULTI5_ENCODER -const AVCodec ff_a64multi5_encoder = { - .name = "a64multi5", - .long_name = NULL_IF_CONFIG_SMALL("Multicolor charset for Commodore 64, extended with 5th color (colram)"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_A64_MULTI5, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, +const FFCodec ff_a64multi5_encoder = { + .p.name = "a64multi5", + .p.long_name = NULL_IF_CONFIG_SMALL("Multicolor charset for Commodore 64, extended with 5th color (colram)"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_A64_MULTI5, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, .priv_data_size = sizeof(A64Context), .init = a64multi_encode_init, - .encode2 = a64multi_encode_frame, + FF_CODEC_ENCODE_CB(a64multi_encode_frame), .close = a64multi_close_encoder, - .pix_fmts = (const enum AVPixelFormat[]) {AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE}, + .p.pix_fmts = (const enum AVPixelFormat[]) {AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE}, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE, }; #endif diff --git a/libavcodec/aac.h b/libavcodec/aac.h index 1e82f56ca..53be54685 100644 --- a/libavcodec/aac.h +++ b/libavcodec/aac.h @@ -32,6 +32,7 @@ #include "aac_defines.h" +#include "libavutil/channel_layout.h" #include "libavutil/float_dsp.h" #include "libavutil/fixed_dsp.h" #include "libavutil/mem_internal.h" @@ -125,8 +126,7 @@ typedef struct OutputConfiguration { MPEG4AudioConfig m4ac; uint8_t layout_map[MAX_ELEM_ID*4][3]; int layout_map_tags; - int channels; - uint64_t channel_layout; + AVChannelLayout ch_layout; enum OCStatus status; } OutputConfiguration; @@ -288,6 +288,11 @@ typedef struct ChannelElement { SpectralBandReplication sbr; } ChannelElement; +enum AACOutputChannelOrder { + CHANNEL_ORDER_DEFAULT, + CHANNEL_ORDER_CODED, +}; + /** * main AAC context */ @@ -352,6 +357,8 @@ struct AACContext { int dmono_mode; ///< 0->not dmono, 1->use first channel, 2->use second channel /** @} */ + enum AACOutputChannelOrder output_channel_order; + DECLARE_ALIGNED(32, INTFLOAT, temp)[128]; OutputConfiguration oc[2]; diff --git a/libavcodec/aac_ac3_parser.c b/libavcodec/aac_ac3_parser.c index e84d30aea..b14b1e31f 100644 --- a/libavcodec/aac_ac3_parser.c +++ b/libavcodec/aac_ac3_parser.c @@ -20,6 +20,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/channel_layout.h" #include "libavutil/common.h" #include "parser.h" @@ -90,8 +92,19 @@ get_next: if (avctx->codec_id != AV_CODEC_ID_AAC) { avctx->sample_rate = s->sample_rate; if (!CONFIG_EAC3_DECODER || avctx->codec_id != AV_CODEC_ID_EAC3) { - avctx->channels = s->channels; + av_channel_layout_uninit(&avctx->ch_layout); + if (s->channel_layout) { + av_channel_layout_from_mask(&avctx->ch_layout, s->channel_layout); + } else { + avctx->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + avctx->ch_layout.nb_channels = s->channels; + } +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + avctx->channels = avctx->ch_layout.nb_channels; avctx->channel_layout = s->channel_layout; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } s1->duration = s->samples; avctx->audio_service_type = s->service_type; diff --git a/libavcodec/aac_adtstoasc_bsf.c b/libavcodec/aac_adtstoasc_bsf.c index 69453c706..d32fcc5f9 100644 --- a/libavcodec/aac_adtstoasc_bsf.c +++ b/libavcodec/aac_adtstoasc_bsf.c @@ -26,7 +26,6 @@ #include "put_bits.h" #include "get_bits.h" #include "mpeg4audio.h" -#include "internal.h" typedef struct AACBSFContext { int first_frame_done; @@ -149,10 +148,10 @@ static const enum AVCodecID codec_ids[] = { AV_CODEC_ID_AAC, AV_CODEC_ID_NONE, }; -const AVBitStreamFilter ff_aac_adtstoasc_bsf = { - .name = "aac_adtstoasc", +const FFBitStreamFilter ff_aac_adtstoasc_bsf = { + .p.name = "aac_adtstoasc", + .p.codec_ids = codec_ids, .priv_data_size = sizeof(AACBSFContext), .init = aac_adtstoasc_init, .filter = aac_adtstoasc_filter, - .codec_ids = codec_ids, }; diff --git a/libavcodec/aaccoder.c b/libavcodec/aaccoder.c index 7bbd4d5b2..f46047949 100644 --- a/libavcodec/aaccoder.c +++ b/libavcodec/aaccoder.c @@ -397,7 +397,7 @@ static void search_for_quantizers_fast(AVCodecContext *avctx, AACEncContext *s, const float lambda) { int start = 0, i, w, w2, g; - int destbits = avctx->bit_rate * 1024.0 / avctx->sample_rate / avctx->channels * (lambda / 120.f); + int destbits = avctx->bit_rate * 1024.0 / avctx->sample_rate / avctx->ch_layout.nb_channels * (lambda / 120.f); float dists[128] = { 0 }, uplims[128] = { 0 }; float maxvals[128]; int fflag, minscaler; @@ -556,7 +556,7 @@ static void search_for_pns(AACEncContext *s, AVCodecContext *avctx, SingleChanne const float pns_transient_energy_r = FFMIN(0.7f, lambda / 140.f); int refbits = avctx->bit_rate * 1024.0 / avctx->sample_rate - / ((avctx->flags & AV_CODEC_FLAG_QSCALE) ? 2.0f : avctx->channels) + / ((avctx->flags & AV_CODEC_FLAG_QSCALE) ? 2.0f : avctx->ch_layout.nb_channels) * (lambda / 120.f); /** Keep this in sync with twoloop's cutoff selection */ @@ -564,7 +564,7 @@ static void search_for_pns(AACEncContext *s, AVCodecContext *avctx, SingleChanne int prev = -1000, prev_sf = -1; int frame_bit_rate = (avctx->flags & AV_CODEC_FLAG_QSCALE) ? (refbits * rate_bandwidth_multiplier * avctx->sample_rate / 1024) - : (avctx->bit_rate / avctx->channels); + : (avctx->bit_rate / avctx->ch_layout.nb_channels); frame_bit_rate *= 1.15f; @@ -693,14 +693,14 @@ static void mark_pns(AACEncContext *s, AVCodecContext *avctx, SingleChannelEleme const float pns_transient_energy_r = FFMIN(0.7f, lambda / 140.f); int refbits = avctx->bit_rate * 1024.0 / avctx->sample_rate - / ((avctx->flags & AV_CODEC_FLAG_QSCALE) ? 2.0f : avctx->channels) + / ((avctx->flags & AV_CODEC_FLAG_QSCALE) ? 2.0f : avctx->ch_layout.nb_channels) * (lambda / 120.f); /** Keep this in sync with twoloop's cutoff selection */ float rate_bandwidth_multiplier = 1.5f; int frame_bit_rate = (avctx->flags & AV_CODEC_FLAG_QSCALE) ? (refbits * rate_bandwidth_multiplier * avctx->sample_rate / 1024) - : (avctx->bit_rate / avctx->channels); + : (avctx->bit_rate / avctx->ch_layout.nb_channels); frame_bit_rate *= 1.15f; diff --git a/libavcodec/aaccoder_twoloop.h b/libavcodec/aaccoder_twoloop.h index 8e1bc88a8..0504a916a 100644 --- a/libavcodec/aaccoder_twoloop.h +++ b/libavcodec/aaccoder_twoloop.h @@ -71,7 +71,7 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx, { int start = 0, i, w, w2, g, recomprd; int destbits = avctx->bit_rate * 1024.0 / avctx->sample_rate - / ((avctx->flags & AV_CODEC_FLAG_QSCALE) ? 2.0f : avctx->channels) + / ((avctx->flags & AV_CODEC_FLAG_QSCALE) ? 2.0f : avctx->ch_layout.nb_channels) * (lambda / 120.f); int refbits = destbits; int toomanybits, toofewbits; @@ -186,7 +186,7 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx, float rate_bandwidth_multiplier = 1.5f; int frame_bit_rate = (avctx->flags & AV_CODEC_FLAG_QSCALE) ? (refbits * rate_bandwidth_multiplier * avctx->sample_rate / 1024) - : (avctx->bit_rate / avctx->channels); + : (avctx->bit_rate / avctx->ch_layout.nb_channels); /** Compensate for extensions that increase efficiency */ if (s->options.pns || s->options.intensity_stereo) diff --git a/libavcodec/aacdec.c b/libavcodec/aacdec.c index 4dfb38ac8..88c128f39 100644 --- a/libavcodec/aacdec.c +++ b/libavcodec/aacdec.c @@ -38,7 +38,7 @@ #include "libavutil/float_dsp.h" #include "libavutil/opt.h" #include "avcodec.h" -#include "internal.h" +#include "codec_internal.h" #include "get_bits.h" #include "fft.h" #include "mdct15.h" @@ -480,7 +480,7 @@ static int read_audio_mux_element(struct LATMContext *latmctx, } -static int latm_decode_frame(AVCodecContext *avctx, void *out, +static int latm_decode_frame(AVCodecContext *avctx, AVFrame *out, int *got_frame_ptr, AVPacket *avpkt) { struct LATMContext *latmctx = avctx->priv_data; @@ -552,24 +552,27 @@ static av_cold int latm_decode_init(AVCodecContext *avctx) return ret; } -const AVCodec ff_aac_decoder = { - .name = "aac", - .long_name = NULL_IF_CONFIG_SMALL("AAC (Advanced Audio Coding)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_AAC, +const FFCodec ff_aac_decoder = { + .p.name = "aac", + .p.long_name = NULL_IF_CONFIG_SMALL("AAC (Advanced Audio Coding)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_AAC, .priv_data_size = sizeof(AACContext), .init = aac_decode_init, .close = aac_decode_close, - .decode = aac_decode_frame, - .sample_fmts = (const enum AVSampleFormat[]) { + FF_CODEC_DECODE_CB(aac_decode_frame), + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, - .capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .channel_layouts = aac_channel_layout, +#if FF_API_OLD_CHANNEL_LAYOUT + .p.channel_layouts = aac_channel_layout, +#endif + .p.ch_layouts = aac_ch_layout, .flush = flush, - .priv_class = &aac_decoder_class, - .profiles = NULL_IF_CONFIG_SMALL(ff_aac_profiles), + .p.priv_class = &aac_decoder_class, + .p.profiles = NULL_IF_CONFIG_SMALL(ff_aac_profiles), }; /* @@ -577,21 +580,24 @@ const AVCodec ff_aac_decoder = { in MPEG transport streams which only contain one program. To do a more complex LATM demuxing a separate LATM demuxer should be used. */ -const AVCodec ff_aac_latm_decoder = { - .name = "aac_latm", - .long_name = NULL_IF_CONFIG_SMALL("AAC LATM (Advanced Audio Coding LATM syntax)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_AAC_LATM, +const FFCodec ff_aac_latm_decoder = { + .p.name = "aac_latm", + .p.long_name = NULL_IF_CONFIG_SMALL("AAC LATM (Advanced Audio Coding LATM syntax)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_AAC_LATM, .priv_data_size = sizeof(struct LATMContext), .init = latm_decode_init, .close = aac_decode_close, - .decode = latm_decode_frame, - .sample_fmts = (const enum AVSampleFormat[]) { + FF_CODEC_DECODE_CB(latm_decode_frame), + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, - .capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .channel_layouts = aac_channel_layout, +#if FF_API_OLD_CHANNEL_LAYOUT + .p.channel_layouts = aac_channel_layout, +#endif + .p.ch_layouts = aac_ch_layout, .flush = flush, - .profiles = NULL_IF_CONFIG_SMALL(ff_aac_profiles), + .p.profiles = NULL_IF_CONFIG_SMALL(ff_aac_profiles), }; diff --git a/libavcodec/aacdec_fixed.c b/libavcodec/aacdec_fixed.c index cad2fd6ad..c7ac75024 100644 --- a/libavcodec/aacdec_fixed.c +++ b/libavcodec/aacdec_fixed.c @@ -64,7 +64,7 @@ #include "libavutil/fixed_dsp.h" #include "libavutil/opt.h" #include "avcodec.h" -#include "internal.h" +#include "codec_internal.h" #include "get_bits.h" #include "fft.h" #include "lpc.h" @@ -450,21 +450,24 @@ static void apply_independent_coupling_fixed(AACContext *ac, #include "aacdec_template.c" -const AVCodec ff_aac_fixed_decoder = { - .name = "aac_fixed", - .long_name = NULL_IF_CONFIG_SMALL("AAC (Advanced Audio Coding)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_AAC, +const FFCodec ff_aac_fixed_decoder = { + .p.name = "aac_fixed", + .p.long_name = NULL_IF_CONFIG_SMALL("AAC (Advanced Audio Coding)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_AAC, .priv_data_size = sizeof(AACContext), .init = aac_decode_init, .close = aac_decode_close, - .decode = aac_decode_frame, - .sample_fmts = (const enum AVSampleFormat[]) { + FF_CODEC_DECODE_CB(aac_decode_frame), + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_NONE }, - .capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .channel_layouts = aac_channel_layout, - .profiles = NULL_IF_CONFIG_SMALL(ff_aac_profiles), +#if FF_API_OLD_CHANNEL_LAYOUT + .p.channel_layouts = aac_channel_layout, +#endif + .p.ch_layouts = aac_ch_layout, + .p.profiles = NULL_IF_CONFIG_SMALL(ff_aac_profiles), .flush = flush, }; diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c index 7149b331a..10fba3d3b 100644 --- a/libavcodec/aacdec_template.c +++ b/libavcodec/aacdec_template.c @@ -91,6 +91,7 @@ #include "libavutil/channel_layout.h" #include "libavutil/thread.h" +#include "internal.h" static VLC vlc_scalefactors; static VLC vlc_spectral[11]; @@ -174,7 +175,7 @@ static int frame_configure_elements(AVCodecContext *avctx) /* get output buffer */ av_frame_unref(ac->frame); - if (!avctx->channels) + if (!avctx->ch_layout.nb_channels) return 1; ac->frame->nb_samples = 2048; @@ -182,7 +183,7 @@ static int frame_configure_elements(AVCodecContext *avctx) return ret; /* map output channel pointers to AVFrame data */ - for (ch = 0; ch < avctx->channels; ch++) { + for (ch = 0; ch < avctx->ch_layout.nb_channels; ch++) { if (ac->output_element[ch]) ac->output_element[ch]->ret = (INTFLOAT *)ac->frame->extended_data[ch]; } @@ -517,8 +518,7 @@ static int push_output_configuration(AACContext *ac) { static void pop_output_configuration(AACContext *ac) { if (ac->oc[1].status != OC_LOCKED && ac->oc[0].status != OC_NONE) { ac->oc[1] = ac->oc[0]; - ac->avctx->channels = ac->oc[1].channels; - ac->avctx->channel_layout = ac->oc[1].channel_layout; + ac->avctx->ch_layout = ac->oc[1].ch_layout; output_configure(ac, ac->oc[1].layout_map, ac->oc[1].layout_map_tags, ac->oc[1].status, 0); } @@ -555,7 +555,14 @@ static int output_configure(AACContext *ac, } // Try to sniff a reasonable channel order, otherwise output the // channels in the order the PCE declared them. - if (avctx->request_channel_layout != AV_CH_LAYOUT_NATIVE) +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->request_channel_layout == AV_CH_LAYOUT_NATIVE) + ac->output_channel_order = CHANNEL_ORDER_CODED; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + + if (ac->output_channel_order == CHANNEL_ORDER_DEFAULT) layout = sniff_channel_order(layout_map, tags); for (i = 0; i < tags; i++) { int type = layout_map[i][0]; @@ -577,9 +584,15 @@ static int output_configure(AACContext *ac, } } - if (layout) avctx->channel_layout = layout; - ac->oc[1].channel_layout = layout; - avctx->channels = ac->oc[1].channels = channels; + av_channel_layout_uninit(&ac->oc[1].ch_layout); + if (layout) + av_channel_layout_from_mask(&ac->oc[1].ch_layout, layout); + else { + ac->oc[1].ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + ac->oc[1].ch_layout.nb_channels = channels; + } + + av_channel_layout_copy(&avctx->ch_layout, &ac->oc[1].ch_layout); ac->oc[1].status = oc_type; if (get_new_frame) { @@ -688,14 +701,15 @@ static ChannelElement *get_che(AACContext *ac, int type, int elem_id) av_log(ac->avctx, AV_LOG_DEBUG, "stereo with SCE\n"); - if (set_default_channel_config(ac, ac->avctx, layout_map, - &layout_map_tags, 1) < 0) - return NULL; + layout_map_tags = 2; + layout_map[0][0] = layout_map[1][0] = TYPE_SCE; + layout_map[0][2] = layout_map[1][2] = AAC_CHANNEL_FRONT; + layout_map[0][1] = 0; + layout_map[1][1] = 1; if (output_configure(ac, layout_map, layout_map_tags, OC_TRIAL_FRAME, 1) < 0) return NULL; - ac->oc[1].m4ac.chan_config = 1; if (ac->oc[1].m4ac.sbr) ac->oc[1].m4ac.ps = -1; } @@ -773,8 +787,10 @@ static ChannelElement *get_che(AACContext *ac, int type, int elem_id) type == TYPE_CPE) { ac->tags_mapped++; return ac->tag_che_map[TYPE_CPE][elem_id] = ac->che[TYPE_CPE][0]; - } else if (ac->oc[1].m4ac.chan_config == 2) { - return NULL; + } else if (ac->tags_mapped == 1 && ac->oc[1].m4ac.chan_config == 2 && + type == TYPE_SCE) { + ac->tags_mapped++; + return ac->tag_che_map[TYPE_SCE][elem_id] = ac->che[TYPE_SCE][1]; } case 1: if (!ac->tags_mapped && type == TYPE_SCE) { @@ -1208,8 +1224,8 @@ static void aacdec_init(AACContext *ac); static av_cold void aac_static_table_init(void) { - static VLC_TYPE vlc_buf[304 + 270 + 550 + 300 + 328 + - 294 + 306 + 268 + 510 + 366 + 462][2]; + static VLCElem vlc_buf[304 + 270 + 550 + 300 + 328 + + 294 + 306 + 268 + 510 + 366 + 462]; for (unsigned i = 0, offset = 0; i < 11; i++) { vlc_spectral[i].table = &vlc_buf[offset]; vlc_spectral[i].table_allocated = FF_ARRAY_ELEMS(vlc_buf) - offset; @@ -1292,12 +1308,12 @@ static av_cold int aac_decode_init(AVCodecContext *avctx) sr = sample_rate_idx(avctx->sample_rate); ac->oc[1].m4ac.sampling_index = sr; - ac->oc[1].m4ac.channels = avctx->channels; + ac->oc[1].m4ac.channels = avctx->ch_layout.nb_channels; ac->oc[1].m4ac.sbr = -1; ac->oc[1].m4ac.ps = -1; for (i = 0; i < FF_ARRAY_ELEMS(ff_mpeg4audio_channels); i++) - if (ff_mpeg4audio_channels[i] == avctx->channels) + if (ff_mpeg4audio_channels[i] == avctx->ch_layout.nb_channels) break; if (i == FF_ARRAY_ELEMS(ff_mpeg4audio_channels)) { i = 0; @@ -1315,7 +1331,7 @@ static av_cold int aac_decode_init(AVCodecContext *avctx) } } - if (avctx->channels > MAX_CHANNELS) { + if (avctx->ch_layout.nb_channels > MAX_CHANNELS) { av_log(avctx, AV_LOG_ERROR, "Too many channels\n"); return AVERROR_INVALIDDATA; } @@ -1808,7 +1824,7 @@ static int decode_spectrum_and_dequant(AACContext *ac, INTFLOAT coef[1024], #if !USE_FIXED const float *vq = ff_aac_codebook_vector_vals[cbt_m1]; #endif /* !USE_FIXED */ - VLC_TYPE (*vlc_tab)[2] = vlc_spectral[cbt_m1].table; + const VLCElem *vlc_tab = vlc_spectral[cbt_m1].table; OPEN_READER(re, gb); switch (cbt_m1 >> 1) { @@ -2556,7 +2572,8 @@ static int decode_extension_payload(AACContext *ac, GetBitContext *gb, int cnt, av_log(ac->avctx, AV_LOG_ERROR, "Implicit SBR was found with a first occurrence after the first frame.\n"); skip_bits_long(gb, 8 * cnt - 4); return res; - } else if (ac->oc[1].m4ac.ps == -1 && ac->oc[1].status < OC_LOCKED && ac->avctx->channels == 1) { + } else if (ac->oc[1].m4ac.ps == -1 && ac->oc[1].status < OC_LOCKED && + ac->avctx->ch_layout.nb_channels == 1) { ac->oc[1].m4ac.sbr = 1; ac->oc[1].m4ac.ps = 1; ac->avctx->profile = FF_PROFILE_AAC_HE_V2; @@ -3221,7 +3238,7 @@ static int aac_decode_er_frame(AVCodecContext *avctx, void *data, return 0; } -static int aac_decode_frame_int(AVCodecContext *avctx, void *data, +static int aac_decode_frame_int(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, GetBitContext *gb, const AVPacket *avpkt) { @@ -3234,7 +3251,7 @@ static int aac_decode_frame_int(AVCodecContext *avctx, void *data, int payload_alignment; uint8_t che_presence[4][MAX_ELEM_ID] = {{0}}; - ac->frame = data; + ac->frame = frame; if (show_bits(gb, 12) == 0xfff) { if ((err = parse_adts_frame_header(ac, gb)) < 0) { @@ -3264,7 +3281,7 @@ static int aac_decode_frame_int(AVCodecContext *avctx, void *data, if (avctx->debug & FF_DEBUG_STARTCODE) av_log(avctx, AV_LOG_DEBUG, "Elem type:%x id:%x\n", elem_type, elem_id); - if (!avctx->channels && elem_type != TYPE_PCE) { + if (!avctx->ch_layout.nb_channels && elem_type != TYPE_PCE) { err = AVERROR_INVALIDDATA; goto fail; } @@ -3385,7 +3402,7 @@ static int aac_decode_frame_int(AVCodecContext *avctx, void *data, } } - if (!avctx->channels) { + if (!avctx->ch_layout.nb_channels) { *got_frame_ptr = 0; return 0; } @@ -3419,12 +3436,13 @@ static int aac_decode_frame_int(AVCodecContext *avctx, void *data, /* for dual-mono audio (SCE + SCE) */ is_dmono = ac->dmono_mode && sce_count == 2 && - ac->oc[1].channel_layout == (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT); + !av_channel_layout_compare(&ac->oc[1].ch_layout, + &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO); if (is_dmono) { if (ac->dmono_mode == 1) - ((AVFrame *)data)->data[1] =((AVFrame *)data)->data[0]; + frame->data[1] = frame->data[0]; else if (ac->dmono_mode == 2) - ((AVFrame *)data)->data[0] =((AVFrame *)data)->data[1]; + frame->data[0] = frame->data[1]; } return 0; @@ -3433,7 +3451,7 @@ fail: return err; } -static int aac_decode_frame(AVCodecContext *avctx, void *data, +static int aac_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { AACContext *ac = avctx->priv_data; @@ -3480,10 +3498,10 @@ static int aac_decode_frame(AVCodecContext *avctx, void *data, case AOT_ER_AAC_LTP: case AOT_ER_AAC_LD: case AOT_ER_AAC_ELD: - err = aac_decode_er_frame(avctx, data, got_frame_ptr, &gb); + err = aac_decode_er_frame(avctx, frame, got_frame_ptr, &gb); break; default: - err = aac_decode_frame_int(avctx, data, got_frame_ptr, &gb, avpkt); + err = aac_decode_frame_int(avctx, frame, got_frame_ptr, &gb, avpkt); } if (err < 0) return err; @@ -3535,8 +3553,9 @@ static void aacdec_init(AACContext *c) #endif #if !USE_FIXED - if(ARCH_MIPS) - ff_aacdec_init_mips(c); +#if ARCH_MIPS + ff_aacdec_init_mips(c); +#endif #endif /* !USE_FIXED */ } /** @@ -3553,6 +3572,14 @@ static const AVOption options[] = { {"sub" , "Select Sub/Right channel", 0, AV_OPT_TYPE_CONST, {.i64= 2}, INT_MIN, INT_MAX, AACDEC_FLAGS, "dual_mono_mode"}, {"both", "Select both channels", 0, AV_OPT_TYPE_CONST, {.i64= 0}, INT_MIN, INT_MAX, AACDEC_FLAGS, "dual_mono_mode"}, + { "channel_order", "Order in which the channels are to be exported", + offsetof(AACContext, output_channel_order), AV_OPT_TYPE_INT, + { .i64 = CHANNEL_ORDER_DEFAULT }, 0, 1, AACDEC_FLAGS, "channel_order" }, + { "default", "normal libavcodec channel order", 0, AV_OPT_TYPE_CONST, + { .i64 = CHANNEL_ORDER_DEFAULT }, .flags = AACDEC_FLAGS, "channel_order" }, + { "coded", "order in which the channels are coded in the bitstream", + 0, AV_OPT_TYPE_CONST, { .i64 = CHANNEL_ORDER_CODED }, .flags = AACDEC_FLAGS, "channel_order" }, + {NULL}, }; diff --git a/libavcodec/aacdectab.h b/libavcodec/aacdectab.h index c54a3eb94..e03026806 100644 --- a/libavcodec/aacdectab.h +++ b/libavcodec/aacdectab.h @@ -72,6 +72,7 @@ static const uint8_t aac_channel_layout_map[16][16][3] = { /* TODO: Add 7+1 TOP configuration */ }; +#if FF_API_OLD_CHANNEL_LAYOUT static const uint64_t aac_channel_layout[16] = { AV_CH_LAYOUT_MONO, AV_CH_LAYOUT_STEREO, @@ -89,5 +90,24 @@ static const uint64_t aac_channel_layout[16] = { 0, /* AV_CH_LAYOUT_7POINT1_TOP, */ }; +#endif + +static const AVChannelLayout aac_ch_layout[16] = { + AV_CHANNEL_LAYOUT_MONO, + AV_CHANNEL_LAYOUT_STEREO, + AV_CHANNEL_LAYOUT_SURROUND, + AV_CHANNEL_LAYOUT_4POINT0, + AV_CHANNEL_LAYOUT_5POINT0_BACK, + AV_CHANNEL_LAYOUT_5POINT1_BACK, + AV_CHANNEL_LAYOUT_7POINT1_WIDE_BACK, + { 0 }, + { 0 }, + { 0 }, + AV_CHANNEL_LAYOUT_6POINT1, + AV_CHANNEL_LAYOUT_7POINT1, + AV_CHANNEL_LAYOUT_22POINT2, + { 0 }, + /* AV_CHANNEL_LAYOUT_7POINT1_TOP, */ +}; #endif /* AVCODEC_AACDECTAB_H */ diff --git a/libavcodec/aacenc.c b/libavcodec/aacenc.c index a1004c3e9..408c03144 100644 --- a/libavcodec/aacenc.c +++ b/libavcodec/aacenc.c @@ -35,12 +35,13 @@ #include "libavutil/float_dsp.h" #include "libavutil/opt.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" #include "put_bits.h" -#include "internal.h" #include "mpeg4audio.h" #include "sinewin.h" #include "profiles.h" +#include "version.h" #include "aac.h" #include "aactab.h" @@ -962,11 +963,11 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) s->lambda = avctx->global_quality > 0 ? avctx->global_quality : 120; /* Channel map and unspecified bitrate guessing */ - s->channels = avctx->channels; + s->channels = avctx->ch_layout.nb_channels; 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]) { + if (!av_channel_layout_compare(&avctx->ch_layout, &aac_normal_chan_layouts[i])) { s->needs_pce = s->options.pce; break; } @@ -975,10 +976,13 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) if (s->needs_pce) { char buf[64]; for (i = 0; i < FF_ARRAY_ELEMS(aac_pce_configs); i++) - if (avctx->channel_layout == aac_pce_configs[i].layout) + if (!av_channel_layout_compare(&avctx->ch_layout, &aac_pce_configs[i].layout)) break; - av_get_channel_layout_string(buf, sizeof(buf), -1, avctx->channel_layout); - ERROR_IF(i == FF_ARRAY_ELEMS(aac_pce_configs), "Unsupported channel layout \"%s\"\n", buf); + av_channel_layout_describe(&avctx->ch_layout, buf, sizeof(buf)); + if (i == FF_ARRAY_ELEMS(aac_pce_configs)) { + av_log(avctx, AV_LOG_ERROR, "Unsupported channel layout \"%s\"\n", buf); + return AVERROR(EINVAL); + } av_log(avctx, AV_LOG_INFO, "Using a PCE to encode channel layout \"%s\"\n", buf); s->pce = aac_pce_configs[i]; s->reorder_map = s->pce.reorder_map; @@ -1092,11 +1096,13 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) s->abs_pow34 = abs_pow34_v; s->quant_bands = quantize_bands; - if (ARCH_X86) - ff_aac_dsp_init_x86(s); +#if ARCH_X86 + ff_aac_dsp_init_x86(s); +#endif - if (HAVE_MIPSDSP) - ff_aac_coder_init_mips(s); +#if HAVE_MIPSDSP + ff_aac_coder_init_mips(s); +#endif ff_af_queue_init(avctx, &s->afq); ff_aac_tableinit(); @@ -1128,25 +1134,25 @@ static const AVClass aacenc_class = { .version = LIBAVUTIL_VERSION_INT, }; -static const AVCodecDefault aac_encode_defaults[] = { +static const FFCodecDefault aac_encode_defaults[] = { { "b", "0" }, { NULL } }; -const AVCodec ff_aac_encoder = { - .name = "aac", - .long_name = NULL_IF_CONFIG_SMALL("AAC (Advanced Audio Coding)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_AAC, +const FFCodec ff_aac_encoder = { + .p.name = "aac", + .p.long_name = NULL_IF_CONFIG_SMALL("AAC (Advanced Audio Coding)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_AAC, .priv_data_size = sizeof(AACEncContext), .init = aac_encode_init, - .encode2 = aac_encode_frame, + FF_CODEC_ENCODE_CB(aac_encode_frame), .close = aac_encode_end, .defaults = aac_encode_defaults, - .supported_samplerates = ff_mpeg4audio_sample_rates, + .p.supported_samplerates = ff_mpeg4audio_sample_rates, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP, + .p.capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY, + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, - .priv_class = &aacenc_class, + .p.priv_class = &aacenc_class, }; diff --git a/libavcodec/aacenc.h b/libavcodec/aacenc.h index b106910ce..a001c7ca6 100644 --- a/libavcodec/aacenc.h +++ b/libavcodec/aacenc.h @@ -94,7 +94,7 @@ typedef struct AACQuantizeBandCostCacheEntry { } AACQuantizeBandCostCacheEntry; typedef struct AACPCEInfo { - int64_t layout; + AVChannelLayout layout; int num_ele[4]; ///< front, side, back, lfe int pairing[3][8]; ///< front, side, back int index[4][8]; ///< front, side, back, lfe @@ -139,7 +139,7 @@ typedef struct AACPCEInfo { */ static const AACPCEInfo aac_pce_configs[] = { { - .layout = AV_CH_LAYOUT_MONO, + .layout = AV_CHANNEL_LAYOUT_MONO, .num_ele = { 1, 0, 0, 0 }, .pairing = { { 0 }, }, .index = { { 0 }, }, @@ -147,7 +147,7 @@ static const AACPCEInfo aac_pce_configs[] = { .reorder_map = { 0 }, }, { - .layout = AV_CH_LAYOUT_STEREO, + .layout = AV_CHANNEL_LAYOUT_STEREO, .num_ele = { 1, 0, 0, 0 }, .pairing = { { 1 }, }, .index = { { 0 }, }, @@ -155,7 +155,7 @@ static const AACPCEInfo aac_pce_configs[] = { .reorder_map = { 0, 1 }, }, { - .layout = AV_CH_LAYOUT_2POINT1, + .layout = AV_CHANNEL_LAYOUT_2POINT1, .num_ele = { 1, 0, 0, 1 }, .pairing = { { 1 }, }, .index = { { 0 },{ 0 },{ 0 },{ 0 } }, @@ -163,7 +163,7 @@ static const AACPCEInfo aac_pce_configs[] = { .reorder_map = { 0, 1, 2 }, }, { - .layout = AV_CH_LAYOUT_2_1, + .layout = AV_CHANNEL_LAYOUT_2_1, .num_ele = { 1, 0, 1, 0 }, .pairing = { { 1 },{ 0 },{ 0 } }, .index = { { 0 },{ 0 },{ 0 }, }, @@ -171,7 +171,7 @@ static const AACPCEInfo aac_pce_configs[] = { .reorder_map = { 0, 1, 2 }, }, { - .layout = AV_CH_LAYOUT_SURROUND, + .layout = AV_CHANNEL_LAYOUT_SURROUND, .num_ele = { 2, 0, 0, 0 }, .pairing = { { 1, 0 }, }, .index = { { 0, 0 }, }, @@ -179,7 +179,7 @@ static const AACPCEInfo aac_pce_configs[] = { .reorder_map = { 0, 1, 2 }, }, { - .layout = AV_CH_LAYOUT_3POINT1, + .layout = AV_CHANNEL_LAYOUT_3POINT1, .num_ele = { 2, 0, 0, 1 }, .pairing = { { 1, 0 }, }, .index = { { 0, 0 }, { 0 }, { 0 }, { 0 }, }, @@ -187,7 +187,7 @@ static const AACPCEInfo aac_pce_configs[] = { .reorder_map = { 0, 1, 2, 3 }, }, { - .layout = AV_CH_LAYOUT_4POINT0, + .layout = AV_CHANNEL_LAYOUT_4POINT0, .num_ele = { 2, 0, 1, 0 }, .pairing = { { 1, 0 }, { 0 }, { 0 }, }, .index = { { 0, 0 }, { 0 }, { 1 } }, @@ -195,7 +195,7 @@ static const AACPCEInfo aac_pce_configs[] = { .reorder_map = { 0, 1, 2, 3 }, }, { - .layout = AV_CH_LAYOUT_4POINT1, + .layout = AV_CHANNEL_LAYOUT_4POINT1, .num_ele = { 2, 1, 1, 0 }, .pairing = { { 1, 0 }, { 0 }, { 0 }, }, .index = { { 0, 0 }, { 1 }, { 2 }, { 0 } }, @@ -203,7 +203,7 @@ static const AACPCEInfo aac_pce_configs[] = { .reorder_map = { 0, 1, 2, 3, 4 }, }, { - .layout = AV_CH_LAYOUT_2_2, + .layout = AV_CHANNEL_LAYOUT_2_2, .num_ele = { 1, 1, 0, 0 }, .pairing = { { 1 }, { 1 }, }, .index = { { 0 }, { 1 }, }, @@ -211,7 +211,7 @@ static const AACPCEInfo aac_pce_configs[] = { .reorder_map = { 0, 1, 2, 3 }, }, { - .layout = AV_CH_LAYOUT_QUAD, + .layout = AV_CHANNEL_LAYOUT_QUAD, .num_ele = { 1, 0, 1, 0 }, .pairing = { { 1 }, { 0 }, { 1 }, }, .index = { { 0 }, { 0 }, { 1 } }, @@ -219,7 +219,7 @@ static const AACPCEInfo aac_pce_configs[] = { .reorder_map = { 0, 1, 2, 3 }, }, { - .layout = AV_CH_LAYOUT_5POINT0, + .layout = AV_CHANNEL_LAYOUT_5POINT0, .num_ele = { 2, 1, 0, 0 }, .pairing = { { 1, 0 }, { 1 }, }, .index = { { 0, 0 }, { 1 } }, @@ -227,7 +227,7 @@ static const AACPCEInfo aac_pce_configs[] = { .reorder_map = { 0, 1, 2, 3, 4 }, }, { - .layout = AV_CH_LAYOUT_5POINT1, + .layout = AV_CHANNEL_LAYOUT_5POINT1, .num_ele = { 2, 1, 1, 0 }, .pairing = { { 1, 0 }, { 0 }, { 1 }, }, .index = { { 0, 0 }, { 1 }, { 1 } }, @@ -235,7 +235,7 @@ static const AACPCEInfo aac_pce_configs[] = { .reorder_map = { 0, 1, 2, 3, 4, 5 }, }, { - .layout = AV_CH_LAYOUT_5POINT0_BACK, + .layout = AV_CHANNEL_LAYOUT_5POINT0_BACK, .num_ele = { 2, 0, 1, 0 }, .pairing = { { 1, 0 }, { 0 }, { 1 } }, .index = { { 0, 0 }, { 0 }, { 1 } }, @@ -243,7 +243,7 @@ static const AACPCEInfo aac_pce_configs[] = { .reorder_map = { 0, 1, 2, 3, 4 }, }, { - .layout = AV_CH_LAYOUT_5POINT1_BACK, + .layout = AV_CHANNEL_LAYOUT_5POINT1_BACK, .num_ele = { 2, 1, 1, 0 }, .pairing = { { 1, 0 }, { 0 }, { 1 }, }, .index = { { 0, 0 }, { 1 }, { 1 } }, @@ -251,7 +251,7 @@ static const AACPCEInfo aac_pce_configs[] = { .reorder_map = { 0, 1, 2, 3, 4, 5 }, }, { - .layout = AV_CH_LAYOUT_6POINT0, + .layout = AV_CHANNEL_LAYOUT_6POINT0, .num_ele = { 2, 1, 1, 0 }, .pairing = { { 1, 0 }, { 1 }, { 0 }, }, .index = { { 0, 0 }, { 1 }, { 1 } }, @@ -259,7 +259,7 @@ static const AACPCEInfo aac_pce_configs[] = { .reorder_map = { 0, 1, 2, 3, 4, 5 }, }, { - .layout = AV_CH_LAYOUT_6POINT0_FRONT, + .layout = AV_CHANNEL_LAYOUT_6POINT0_FRONT, .num_ele = { 2, 1, 0, 0 }, .pairing = { { 1, 1 }, { 1 } }, .index = { { 1, 0 }, { 2 }, }, @@ -267,7 +267,7 @@ static const AACPCEInfo aac_pce_configs[] = { .reorder_map = { 0, 1, 2, 3, 4, 5 }, }, { - .layout = AV_CH_LAYOUT_HEXAGONAL, + .layout = AV_CHANNEL_LAYOUT_HEXAGONAL, .num_ele = { 2, 0, 2, 0 }, .pairing = { { 1, 0 },{ 0 },{ 1, 0 }, }, .index = { { 0, 0 },{ 0 },{ 1, 1 } }, @@ -275,7 +275,7 @@ static const AACPCEInfo aac_pce_configs[] = { .reorder_map = { 0, 1, 2, 3, 4, 5 }, }, { - .layout = AV_CH_LAYOUT_6POINT1, + .layout = AV_CHANNEL_LAYOUT_6POINT1, .num_ele = { 2, 1, 2, 0 }, .pairing = { { 1, 0 },{ 0 },{ 1, 0 }, }, .index = { { 0, 0 },{ 1 },{ 1, 2 } }, @@ -283,7 +283,7 @@ static const AACPCEInfo aac_pce_configs[] = { .reorder_map = { 0, 1, 2, 3, 4, 5, 6 }, }, { - .layout = AV_CH_LAYOUT_6POINT1_BACK, + .layout = AV_CHANNEL_LAYOUT_6POINT1_BACK, .num_ele = { 2, 1, 2, 0 }, .pairing = { { 1, 0 }, { 0 }, { 1, 0 }, }, .index = { { 0, 0 }, { 1 }, { 1, 2 } }, @@ -291,7 +291,7 @@ static const AACPCEInfo aac_pce_configs[] = { .reorder_map = { 0, 1, 2, 3, 4, 5, 6 }, }, { - .layout = AV_CH_LAYOUT_6POINT1_FRONT, + .layout = AV_CHANNEL_LAYOUT_6POINT1_FRONT, .num_ele = { 2, 1, 2, 0 }, .pairing = { { 1, 0 }, { 0 }, { 1, 0 }, }, .index = { { 0, 0 }, { 1 }, { 1, 2 } }, @@ -299,7 +299,7 @@ static const AACPCEInfo aac_pce_configs[] = { .reorder_map = { 0, 1, 2, 3, 4, 5, 6 }, }, { - .layout = AV_CH_LAYOUT_7POINT0, + .layout = AV_CHANNEL_LAYOUT_7POINT0, .num_ele = { 2, 1, 1, 0 }, .pairing = { { 1, 0 }, { 1 }, { 1 }, }, .index = { { 0, 0 }, { 1 }, { 2 }, }, @@ -307,7 +307,7 @@ static const AACPCEInfo aac_pce_configs[] = { .reorder_map = { 0, 1, 2, 3, 4, 5, 6 }, }, { - .layout = AV_CH_LAYOUT_7POINT0_FRONT, + .layout = AV_CHANNEL_LAYOUT_7POINT0_FRONT, .num_ele = { 2, 1, 1, 0 }, .pairing = { { 1, 0 }, { 1 }, { 1 }, }, .index = { { 0, 0 }, { 1 }, { 2 }, }, @@ -315,7 +315,7 @@ static const AACPCEInfo aac_pce_configs[] = { .reorder_map = { 0, 1, 2, 3, 4, 5, 6 }, }, { - .layout = AV_CH_LAYOUT_7POINT1, + .layout = AV_CHANNEL_LAYOUT_7POINT1, .num_ele = { 2, 1, 2, 0 }, .pairing = { { 1, 0 }, { 0 }, { 1, 1 }, }, .index = { { 0, 0 }, { 1 }, { 1, 2 }, { 0 } }, @@ -323,7 +323,7 @@ static const AACPCEInfo aac_pce_configs[] = { .reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7 }, }, { - .layout = AV_CH_LAYOUT_7POINT1_WIDE, + .layout = AV_CHANNEL_LAYOUT_7POINT1_WIDE, .num_ele = { 2, 1, 2, 0 }, .pairing = { { 1, 0 }, { 0 },{ 1, 1 }, }, .index = { { 0, 0 }, { 1 }, { 1, 2 }, { 0 } }, @@ -331,7 +331,7 @@ static const AACPCEInfo aac_pce_configs[] = { .reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7 }, }, { - .layout = AV_CH_LAYOUT_7POINT1_WIDE_BACK, + .layout = AV_CHANNEL_LAYOUT_7POINT1_WIDE_BACK, .num_ele = { 2, 1, 2, 0 }, .pairing = { { 1, 0 }, { 0 }, { 1, 1 }, }, .index = { { 0, 0 }, { 1 }, { 1, 2 }, { 0 } }, @@ -339,7 +339,7 @@ static const AACPCEInfo aac_pce_configs[] = { .reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7 }, }, { - .layout = AV_CH_LAYOUT_OCTAGONAL, + .layout = AV_CHANNEL_LAYOUT_OCTAGONAL, .num_ele = { 2, 1, 2, 0 }, .pairing = { { 1, 0 }, { 1 }, { 1, 0 }, }, .index = { { 0, 0 }, { 1 }, { 2, 1 } }, @@ -347,7 +347,8 @@ static const AACPCEInfo aac_pce_configs[] = { .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, + .layout = { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 9, + .u.mask = 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 } }, @@ -355,8 +356,9 @@ static const AACPCEInfo aac_pce_configs[] = { .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, + .layout = { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = 10, + .u.mask = 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 } }, @@ -364,7 +366,7 @@ static const AACPCEInfo aac_pce_configs[] = { .reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, }, { - .layout = AV_CH_LAYOUT_HEXADECAGONAL, + .layout = AV_CHANNEL_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 } }, diff --git a/libavcodec/aacenctab.h b/libavcodec/aacenctab.h index 33cb7ae95..2d9662194 100644 --- a/libavcodec/aacenctab.h +++ b/libavcodec/aacenctab.h @@ -45,14 +45,14 @@ extern const uint8_t *const 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_BACK, - AV_CH_LAYOUT_5POINT1_BACK, - AV_CH_LAYOUT_7POINT1, +static const AVChannelLayout aac_normal_chan_layouts[7] = { + AV_CHANNEL_LAYOUT_MONO, + AV_CHANNEL_LAYOUT_STEREO, + AV_CHANNEL_LAYOUT_SURROUND, + AV_CHANNEL_LAYOUT_4POINT0, + AV_CHANNEL_LAYOUT_5POINT0_BACK, + AV_CHANNEL_LAYOUT_5POINT1_BACK, + AV_CHANNEL_LAYOUT_7POINT1, }; /** default channel configurations */ diff --git a/libavcodec/aacps_common.c b/libavcodec/aacps_common.c index 8653b871c..c388d5b9b 100644 --- a/libavcodec/aacps_common.c +++ b/libavcodec/aacps_common.c @@ -78,7 +78,7 @@ static int read_ ## PAR ## _data(AVCodecContext *avctx, GetBitContext *gb, PSCom int8_t (*PAR)[PS_MAX_NR_IIDICC], int table_idx, int e, int dt) \ { \ int b, num = ps->nr_ ## PAR ## _par; \ - VLC_TYPE (*vlc_table)[2] = vlc_ps[table_idx].table; \ + const VLCElem *vlc_table = vlc_ps[table_idx].table; \ if (dt) { \ int e_prev = e ? e - 1 : ps->num_env_old - 1; \ e_prev = FFMAX(e_prev, 0); \ diff --git a/libavcodec/aacpsdsp_template.c b/libavcodec/aacpsdsp_template.c index eef8adc7e..e64403758 100644 --- a/libavcodec/aacpsdsp_template.c +++ b/libavcodec/aacpsdsp_template.c @@ -221,13 +221,14 @@ av_cold void AAC_RENAME(ff_psdsp_init)(PSDSPContext *s) s->stereo_interpolate[1] = ps_stereo_interpolate_ipdopd_c; #if !USE_FIXED - if (ARCH_ARM) - ff_psdsp_init_arm(s); - if (ARCH_AARCH64) - ff_psdsp_init_aarch64(s); - if (ARCH_MIPS) - ff_psdsp_init_mips(s); - if (ARCH_X86) - ff_psdsp_init_x86(s); +#if ARCH_ARM + ff_psdsp_init_arm(s); +#elif ARCH_AARCH64 + ff_psdsp_init_aarch64(s); +#elif ARCH_MIPS + ff_psdsp_init_mips(s); +#elif ARCH_X86 + ff_psdsp_init_x86(s); +#endif #endif /* !USE_FIXED */ } diff --git a/libavcodec/aacpsy.c b/libavcodec/aacpsy.c index 0c64f2c7b..4c5ab2c9d 100644 --- a/libavcodec/aacpsy.c +++ b/libavcodec/aacpsy.c @@ -263,13 +263,13 @@ static av_cold void lame_window_init(AacPsyContext *ctx, AVCodecContext *avctx) { int i, j; - for (i = 0; i < avctx->channels; i++) { + for (i = 0; i < avctx->ch_layout.nb_channels; i++) { AacPsyChannel *pch = &ctx->ch[i]; if (avctx->flags & AV_CODEC_FLAG_QSCALE) pch->attack_threshold = psy_vbr_map[avctx->global_quality / FF_QP2LAMBDA].st_lrm; else - pch->attack_threshold = lame_calc_attack_threshold(avctx->bit_rate / avctx->channels / 1000); + pch->attack_threshold = lame_calc_attack_threshold(avctx->bit_rate / avctx->ch_layout.nb_channels / 1000); for (j = 0; j < AAC_NUM_BLOCKS_SHORT * PSY_LAME_NUM_SUBBLOCKS; j++) pch->prev_energy_subshort[j] = 10.0f; @@ -303,7 +303,7 @@ static av_cold int psy_3gpp_init(FFPsyContext *ctx) { float bark; int i, j, g, start; float prev, minscale, minath, minsnr, pe_min; - int chan_bitrate = ctx->avctx->bit_rate / ((ctx->avctx->flags & AV_CODEC_FLAG_QSCALE) ? 2.0f : ctx->avctx->channels); + int chan_bitrate = ctx->avctx->bit_rate / ((ctx->avctx->flags & AV_CODEC_FLAG_QSCALE) ? 2.0f : ctx->avctx->ch_layout.nb_channels); const int bandwidth = ctx->cutoff ? ctx->cutoff : AAC_CUTOFF(ctx->avctx); const float num_bark = calc_bark((float)bandwidth); @@ -370,7 +370,7 @@ static av_cold int psy_3gpp_init(FFPsyContext *ctx) { } } - pctx->ch = av_calloc(ctx->avctx->channels, sizeof(*pctx->ch)); + pctx->ch = av_calloc(ctx->avctx->ch_layout.nb_channels, sizeof(*pctx->ch)); if (!pctx->ch) { av_freep(&ctx->model_priv_data); return AVERROR(ENOMEM); diff --git a/libavcodec/aacsbr_template.c b/libavcodec/aacsbr_template.c index 774f12e77..b72c94b76 100644 --- a/libavcodec/aacsbr_template.c +++ b/libavcodec/aacsbr_template.c @@ -811,7 +811,7 @@ static int read_sbr_envelope(AACContext *ac, SpectralBandReplication *sbr, GetBi { int bits; int i, j, k; - VLC_TYPE (*t_huff)[2], (*f_huff)[2]; + const VLCElem *t_huff, *f_huff; int t_lav, f_lav; const int delta = (ch == 1 && sbr->bs_coupling == 1) + 1; const int odd = sbr->n[1] & 1; @@ -899,7 +899,7 @@ static int read_sbr_noise(AACContext *ac, SpectralBandReplication *sbr, GetBitCo SBRData *ch_data, int ch) { int i, j; - VLC_TYPE (*t_huff)[2], (*f_huff)[2]; + const VLCElem *t_huff, *f_huff; int t_lav, f_lav; int delta = (ch == 1 && sbr->bs_coupling == 1) + 1; @@ -1573,7 +1573,8 @@ static void aacsbr_func_ptr_init(AACSBRContext *c) c->sbr_hf_inverse_filter = sbr_hf_inverse_filter; #if !USE_FIXED - if(ARCH_MIPS) - ff_aacsbr_func_ptr_init_mips(c); +#if ARCH_MIPS + ff_aacsbr_func_ptr_init_mips(c); +#endif #endif } diff --git a/libavcodec/aactab.c b/libavcodec/aactab.c index 0553f41a6..0f4941d5d 100644 --- a/libavcodec/aactab.c +++ b/libavcodec/aactab.c @@ -28,6 +28,7 @@ */ #include "config.h" +#include "config_components.h" #include "libavutil/mem_internal.h" #include "libavutil/thread.h" #include "aac.h" diff --git a/libavcodec/aarch64/Makefile b/libavcodec/aarch64/Makefile index 954461f81..9ce21566c 100644 --- a/libavcodec/aarch64/Makefile +++ b/libavcodec/aarch64/Makefile @@ -7,6 +7,7 @@ OBJS-$(CONFIG_H264PRED) += aarch64/h264pred_init.o OBJS-$(CONFIG_H264QPEL) += aarch64/h264qpel_init_aarch64.o OBJS-$(CONFIG_HPELDSP) += aarch64/hpeldsp_init_aarch64.o OBJS-$(CONFIG_IDCTDSP) += aarch64/idctdsp_init_aarch64.o +OBJS-$(CONFIG_ME_CMP) += aarch64/me_cmp_init_aarch64.o OBJS-$(CONFIG_MPEGAUDIODSP) += aarch64/mpegaudiodsp_init.o OBJS-$(CONFIG_NEON_CLOBBER_TEST) += aarch64/neontest.o OBJS-$(CONFIG_PIXBLOCKDSP) += aarch64/pixblockdsp_init_aarch64.o @@ -44,10 +45,13 @@ NEON-OBJS-$(CONFIG_H264PRED) += aarch64/h264pred_neon.o NEON-OBJS-$(CONFIG_H264QPEL) += aarch64/h264qpel_neon.o \ aarch64/hpeldsp_neon.o NEON-OBJS-$(CONFIG_HPELDSP) += aarch64/hpeldsp_neon.o -NEON-OBJS-$(CONFIG_IDCTDSP) += aarch64/simple_idct_neon.o +NEON-OBJS-$(CONFIG_IDCTDSP) += aarch64/idctdsp_neon.o \ + aarch64/simple_idct_neon.o NEON-OBJS-$(CONFIG_MDCT) += aarch64/mdct_neon.o +NEON-OBJS-$(CONFIG_ME_CMP) += aarch64/me_cmp_neon.o NEON-OBJS-$(CONFIG_MPEGAUDIODSP) += aarch64/mpegaudiodsp_neon.o NEON-OBJS-$(CONFIG_PIXBLOCKDSP) += aarch64/pixblockdsp_neon.o +NEON-OBJS-$(CONFIG_VC1DSP) += aarch64/vc1dsp_neon.o NEON-OBJS-$(CONFIG_VP8DSP) += aarch64/vp8dsp_neon.o # decoders/encoders diff --git a/libavcodec/aarch64/fft_neon.S b/libavcodec/aarch64/fft_neon.S index b4020fc8c..9ff3f9c52 100644 --- a/libavcodec/aarch64/fft_neon.S +++ b/libavcodec/aarch64/fft_neon.S @@ -341,6 +341,7 @@ endfunc .macro def_fft n, n2, n4 function fft\n\()_neon, align=6 AARCH64_VALID_JUMP_TARGET + AARCH64_SIGN_LINK_REGISTER sub sp, sp, #16 stp x28, x30, [sp] add x28, x0, #\n4*2*8 @@ -351,6 +352,7 @@ function fft\n\()_neon, align=6 bl fft\n4\()_neon sub x0, x28, #\n4*2*8 ldp x28, x30, [sp], #16 + AARCH64_VALIDATE_LINK_REGISTER movrel x4, X(ff_cos_\n) mov x2, #\n4>>1 b fft_pass_neon diff --git a/libavcodec/aarch64/h264cmc_neon.S b/libavcodec/aarch64/h264cmc_neon.S index 8be757800..f8e940785 100644 --- a/libavcodec/aarch64/h264cmc_neon.S +++ b/libavcodec/aarch64/h264cmc_neon.S @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/aarch64/asm.S" /* chroma_mc8(uint8_t *dst, uint8_t *src, ptrdiff_t stride, int h, int x, int y) */ diff --git a/libavcodec/aarch64/h264dsp_neon.S b/libavcodec/aarch64/h264dsp_neon.S index 000ff762a..ea221e686 100644 --- a/libavcodec/aarch64/h264dsp_neon.S +++ b/libavcodec/aarch64/h264dsp_neon.S @@ -960,117 +960,117 @@ function ff_h264_h_loop_filter_chroma422_neon_10, export=1 endfunc .macro h264_loop_filter_chroma_intra_10 - uabd v26.8h, v16.8h, v17.8h // abs(p0 - q0) - uabd v27.8h, v18.8h, v16.8h // abs(p1 - p0) - uabd v28.8h, v19.8h, v17.8h // abs(q1 - q0) - cmhi v26.8h, v30.8h, v26.8h // < alpha - cmhi v27.8h, v31.8h, v27.8h // < beta - cmhi v28.8h, v31.8h, v28.8h // < beta - and v26.16b, v26.16b, v27.16b - and v26.16b, v26.16b, v28.16b - mov x2, v26.d[0] - mov x3, v26.d[1] + uabd v26.8h, v16.8h, v17.8h // abs(p0 - q0) + uabd v27.8h, v18.8h, v16.8h // abs(p1 - p0) + uabd v28.8h, v19.8h, v17.8h // abs(q1 - q0) + cmhi v26.8h, v30.8h, v26.8h // < alpha + cmhi v27.8h, v31.8h, v27.8h // < beta + cmhi v28.8h, v31.8h, v28.8h // < beta + and v26.16b, v26.16b, v27.16b + and v26.16b, v26.16b, v28.16b + mov x2, v26.d[0] + mov x3, v26.d[1] - shl v4.8h, v18.8h, #1 - shl v6.8h, v19.8h, #1 + shl v4.8h, v18.8h, #1 + shl v6.8h, v19.8h, #1 - adds x2, x2, x3 - b.eq 9f + adds x2, x2, x3 + b.eq 9f - add v20.8h, v16.8h, v19.8h - add v22.8h, v17.8h, v18.8h - add v20.8h, v20.8h, v4.8h - add v22.8h, v22.8h, v6.8h - urshr v24.8h, v20.8h, #2 - urshr v25.8h, v22.8h, #2 - bit v16.16b, v24.16b, v26.16b - bit v17.16b, v25.16b, v26.16b + add v20.8h, v16.8h, v19.8h + add v22.8h, v17.8h, v18.8h + add v20.8h, v20.8h, v4.8h + add v22.8h, v22.8h, v6.8h + urshr v24.8h, v20.8h, #2 + urshr v25.8h, v22.8h, #2 + bit v16.16b, v24.16b, v26.16b + bit v17.16b, v25.16b, v26.16b .endm function ff_h264_v_loop_filter_chroma_intra_neon_10, export=1 - h264_loop_filter_start_intra_10 - mov x9, x0 - sub x0, x0, x1, lsl #1 - ld1 {v18.8h}, [x0], x1 - ld1 {v17.8h}, [x9], x1 - ld1 {v16.8h}, [x0], x1 - ld1 {v19.8h}, [x9] + h264_loop_filter_start_intra_10 + mov x9, x0 + sub x0, x0, x1, lsl #1 + ld1 {v18.8h}, [x0], x1 + ld1 {v17.8h}, [x9], x1 + ld1 {v16.8h}, [x0], x1 + ld1 {v19.8h}, [x9] - h264_loop_filter_chroma_intra_10 + h264_loop_filter_chroma_intra_10 - sub x0, x9, x1, lsl #1 - st1 {v16.8h}, [x0], x1 - st1 {v17.8h}, [x0], x1 + sub x0, x9, x1, lsl #1 + st1 {v16.8h}, [x0], x1 + st1 {v17.8h}, [x0], x1 9: - ret + ret endfunc function ff_h264_h_loop_filter_chroma_mbaff_intra_neon_10, export=1 - h264_loop_filter_start_intra_10 + h264_loop_filter_start_intra_10 - sub x4, x0, #4 - sub x0, x0, #2 - add x9, x4, x1, lsl #1 - ld1 {v18.8h}, [x4], x1 - ld1 {v17.8h}, [x9], x1 - ld1 {v16.8h}, [x4], x1 - ld1 {v19.8h}, [x9], x1 + sub x4, x0, #4 + sub x0, x0, #2 + add x9, x4, x1, lsl #1 + ld1 {v18.8h}, [x4], x1 + ld1 {v17.8h}, [x9], x1 + ld1 {v16.8h}, [x4], x1 + ld1 {v19.8h}, [x9], x1 - transpose_4x8H v18, v16, v17, v19, v26, v27, v28, v29 + transpose_4x8H v18, v16, v17, v19, v26, v27, v28, v29 - h264_loop_filter_chroma_intra_10 + h264_loop_filter_chroma_intra_10 - st2 {v16.h,v17.h}[0], [x0], x1 - st2 {v16.h,v17.h}[1], [x0], x1 - st2 {v16.h,v17.h}[2], [x0], x1 - st2 {v16.h,v17.h}[3], [x0], x1 + st2 {v16.h,v17.h}[0], [x0], x1 + st2 {v16.h,v17.h}[1], [x0], x1 + st2 {v16.h,v17.h}[2], [x0], x1 + st2 {v16.h,v17.h}[3], [x0], x1 9: - ret + ret endfunc function ff_h264_h_loop_filter_chroma_intra_neon_10, export=1 - h264_loop_filter_start_intra_10 - sub x4, x0, #4 - sub x0, x0, #2 + h264_loop_filter_start_intra_10 + sub x4, x0, #4 + sub x0, x0, #2 h_loop_filter_chroma420_intra_10: - add x9, x4, x1, lsl #2 - ld1 {v18.4h}, [x4], x1 - ld1 {v18.d}[1], [x9], x1 - ld1 {v16.4h}, [x4], x1 - ld1 {v16.d}[1], [x9], x1 - ld1 {v17.4h}, [x4], x1 - ld1 {v17.d}[1], [x9], x1 - ld1 {v19.4h}, [x4], x1 - ld1 {v19.d}[1], [x9], x1 + add x9, x4, x1, lsl #2 + ld1 {v18.4h}, [x4], x1 + ld1 {v18.d}[1], [x9], x1 + ld1 {v16.4h}, [x4], x1 + ld1 {v16.d}[1], [x9], x1 + ld1 {v17.4h}, [x4], x1 + ld1 {v17.d}[1], [x9], x1 + ld1 {v19.4h}, [x4], x1 + ld1 {v19.d}[1], [x9], x1 - transpose_4x8H v18, v16, v17, v19, v26, v27, v28, v29 + transpose_4x8H v18, v16, v17, v19, v26, v27, v28, v29 - h264_loop_filter_chroma_intra_10 + h264_loop_filter_chroma_intra_10 - st2 {v16.h,v17.h}[0], [x0], x1 - st2 {v16.h,v17.h}[1], [x0], x1 - st2 {v16.h,v17.h}[2], [x0], x1 - st2 {v16.h,v17.h}[3], [x0], x1 - st2 {v16.h,v17.h}[4], [x0], x1 - st2 {v16.h,v17.h}[5], [x0], x1 - st2 {v16.h,v17.h}[6], [x0], x1 - st2 {v16.h,v17.h}[7], [x0], x1 + st2 {v16.h,v17.h}[0], [x0], x1 + st2 {v16.h,v17.h}[1], [x0], x1 + st2 {v16.h,v17.h}[2], [x0], x1 + st2 {v16.h,v17.h}[3], [x0], x1 + st2 {v16.h,v17.h}[4], [x0], x1 + st2 {v16.h,v17.h}[5], [x0], x1 + st2 {v16.h,v17.h}[6], [x0], x1 + st2 {v16.h,v17.h}[7], [x0], x1 9: - ret + ret endfunc function ff_h264_h_loop_filter_chroma422_intra_neon_10, export=1 - h264_loop_filter_start_intra_10 - sub x4, x0, #4 - add x5, x0, x1, lsl #3 - sub x0, x0, #2 - mov x7, x30 - bl h_loop_filter_chroma420_intra_10 - mov x4, x9 - sub x0, x5, #2 - mov x30, x7 - b h_loop_filter_chroma420_intra_10 + h264_loop_filter_start_intra_10 + sub x4, x0, #4 + add x5, x0, x1, lsl #3 + sub x0, x0, #2 + mov x7, x30 + bl h_loop_filter_chroma420_intra_10 + mov x4, x9 + sub x0, x5, #2 + mov x30, x7 + b h_loop_filter_chroma420_intra_10 endfunc diff --git a/libavcodec/aarch64/hevcdsp_init_aarch64.c b/libavcodec/aarch64/hevcdsp_init_aarch64.c index 1e40be740..200253026 100644 --- a/libavcodec/aarch64/hevcdsp_init_aarch64.c +++ b/libavcodec/aarch64/hevcdsp_init_aarch64.c @@ -57,8 +57,10 @@ void ff_hevc_sao_band_filter_8x8_8_neon(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_16x16_8_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride_dst, + int16_t *sao_offset_val, int eo, int width, int height); +void ff_hevc_sao_edge_filter_8x8_8_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride_dst, + int16_t *sao_offset_val, int eo, int width, int height); av_cold void ff_hevc_dsp_init_aarch64(HEVCDSPContext *c, const int bit_depth) { @@ -75,11 +77,16 @@ av_cold void ff_hevc_dsp_init_aarch64(HEVCDSPContext *c, const int bit_depth) 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; - // This function is disabled, as it doesn't handle widths that aren't - // an even multiple of 8 correctly. fate-hevc doesn't exercise that - // for the current size, but if enabled for bigger sizes, the cases - // of non-multiple of 8 seem to arise. -// c->sao_band_filter[0] = ff_hevc_sao_band_filter_8x8_8_neon; + c->sao_band_filter[0] = + c->sao_band_filter[1] = + c->sao_band_filter[2] = + c->sao_band_filter[3] = + c->sao_band_filter[4] = ff_hevc_sao_band_filter_8x8_8_neon; + c->sao_edge_filter[0] = ff_hevc_sao_edge_filter_8x8_8_neon; + c->sao_edge_filter[1] = + c->sao_edge_filter[2] = + c->sao_edge_filter[3] = + c->sao_edge_filter[4] = ff_hevc_sao_edge_filter_16x16_8_neon; } if (bit_depth == 10) { c->add_residual[0] = ff_hevc_add_residual_4x4_10_neon; diff --git a/libavcodec/aarch64/hevcdsp_sao_neon.S b/libavcodec/aarch64/hevcdsp_sao_neon.S index f9fed8345..d4decfde3 100644 --- a/libavcodec/aarch64/hevcdsp_sao_neon.S +++ b/libavcodec/aarch64/hevcdsp_sao_neon.S @@ -3,7 +3,7 @@ * * AArch64 NEON optimised SAO functions for HEVC decoding * - * Copyright (c) 2020 Josh Dekker + * Copyright (c) 2022 J. Dekker * * This file is part of FFmpeg. * @@ -24,30 +24,35 @@ #include "libavutil/aarch64/asm.S" +#define MAX_PB_SIZE 64 +#define AV_INPUT_BUFFER_PADDING_SIZE 64 +#define SAO_STRIDE (2*MAX_PB_SIZE + AV_INPUT_BUFFER_PADDING_SIZE) + // void sao_band_filter(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) function ff_hevc_sao_band_filter_8x8_8_neon, export=1 sub sp, sp, #64 - stp xzr, xzr, [sp] - stp xzr, xzr, [sp, #16] - stp xzr, xzr, [sp, #32] - stp xzr, xzr, [sp, #48] + stp xzr, xzr, [sp] + stp xzr, xzr, [sp, #16] + stp xzr, xzr, [sp, #32] + stp xzr, xzr, [sp, #48] mov w8, #4 -0: - ldrsh x9, [x4, x8, lsl #1] // x9 = sao_offset_val[k+1] +0: ldrsh x9, [x4, x8, lsl #1] // sao_offset_val[k+1] subs w8, w8, #1 - add w10, w8, w5 // x10 = k + sao_left_class - and w10, w10, #0x1F + add w10, w8, w5 // k + sao_left_class + and w10, w10, #0x1F strh w9, [sp, x10, lsl #1] bne 0b - ld1 {v16.16b-v19.16b}, [sp], #64 - movi v20.8h, #1 -1: // beginning of line - mov w8, w6 -2: - // Simple layout for accessing 16bit values + add w6, w6, #7 + bic w6, w6, #7 + ld1 {v16.16b-v19.16b}, [sp], #64 + sub x2, x2, x6 + sub x3, x3, x6 + movi v20.8h, #1 +1: mov w8, w6 // beginning of line +2: // Simple layout for accessing 16bit values // with 8bit LUT. // // 00 01 02 03 04 05 06 07 @@ -55,33 +60,138 @@ function ff_hevc_sao_band_filter_8x8_8_neon, export=1 // |xDE#xAD|xCA#xFE|xBE#xEF|xFE#xED|.... // +-----------------------------------> // i-0 i-1 i-2 i-3 - // dst[x] = av_clip_pixel(src[x] + offset_table[src[x] >> shift]); - ld1 {v2.8b}, [x1] - // load src[x] - uxtl v0.8h, v2.8b - // >> shift - ushr v2.8h, v0.8h, #3 // BIT_DEPTH - 3 - // x2 (access lower short) - shl v1.8h, v2.8h, #1 // low (x2, accessing short) - // +1 access upper short - add v3.8h, v1.8h, v20.8h - // shift insert index to upper byte - sli v1.8h, v3.8h, #8 - // table - tbx v2.16b, {v16.16b-v19.16b}, v1.16b - // src[x] + table - add v1.8h, v0.8h, v2.8h - // clip + narrow - sqxtun v4.8b, v1.8h - // store - st1 {v4.8b}, [x0] - // done 8 pixels + ld1 {v2.8b}, [x1], #8 // dst[x] = av_clip_pixel(src[x] + offset_table[src[x] >> shift]); subs w8, w8, #8 + uxtl v0.8h, v2.8b // load src[x] + ushr v2.8h, v0.8h, #3 // >> BIT_DEPTH - 3 + shl v1.8h, v2.8h, #1 // low (x2, accessing short) + add v3.8h, v1.8h, v20.8h // +1 access upper short + sli v1.8h, v3.8h, #8 // shift insert index to upper byte + tbx v2.16b, {v16.16b-v19.16b}, v1.16b // table + add v1.8h, v0.8h, v2.8h // src[x] + table + sqxtun v4.8b, v1.8h // clip + narrow + st1 {v4.8b}, [x0], #8 // store + // done 8 pixels bne 2b - // finished line - subs w7, w7, #1 - add x0, x0, x2 // dst += stride_dst - add x1, x1, x3 // src += stride_src + subs w7, w7, #1 // finished line, prep. new + add x0, x0, x2 // dst += stride_dst + add x1, x1, x3 // src += stride_src bne 1b ret endfunc + +.Lsao_edge_pos: +.word 1 // horizontal +.word SAO_STRIDE // vertical +.word SAO_STRIDE + 1 // 45 degree +.word SAO_STRIDE - 1 // 135 degree + +// ff_hevc_sao_edge_filter_16x16_8_neon(char *dst, char *src, ptrdiff stride_dst, +// int16 *sao_offset_val, int eo, int width, int height) +function ff_hevc_sao_edge_filter_16x16_8_neon, export=1 + adr x7, .Lsao_edge_pos + ld1 {v3.8h}, [x3] // load sao_offset_val + add w5, w5, #0xF + bic w5, w5, #0xF + ldr w4, [x7, w4, uxtw #2] // stride_src + mov v3.h[7], v3.h[0] // reorder to [1,2,0,3,4] + mov v3.h[0], v3.h[1] + mov v3.h[1], v3.h[2] + mov v3.h[2], v3.h[7] + // split 16bit values into two tables + uzp2 v1.16b, v3.16b, v3.16b // sao_offset_val -> upper + uzp1 v0.16b, v3.16b, v3.16b // sao_offset_val -> lower + movi v2.16b, #2 + mov x15, #SAO_STRIDE + // strides between end of line and next src/dst + sub x15, x15, x5 // stride_src - width + sub x16, x2, x5 // stride_dst - width + mov x11, x1 // copy base src +1: // new line + mov x14, x5 // copy width + sub x12, x11, x4 // src_a (prev) = src - sao_edge_pos + add x13, x11, x4 // src_b (next) = src + sao_edge_pos +2: // process 16 bytes + ld1 {v3.16b}, [x11], #16 // load src + ld1 {v4.16b}, [x12], #16 // load src_a (prev) + ld1 {v5.16b}, [x13], #16 // load src_b (next) + subs x14, x14, #16 + cmhi v16.16b, v4.16b, v3.16b // (prev > cur) + cmhi v17.16b, v3.16b, v4.16b // (cur > prev) + cmhi v18.16b, v5.16b, v3.16b // (next > cur) + cmhi v19.16b, v3.16b, v5.16b // (cur > next) + sub v20.16b, v16.16b, v17.16b // diff0 = CMP(cur, prev) = (cur > prev) - (cur < prev) + sub v21.16b, v18.16b, v19.16b // diff1 = CMP(cur, next) = (cur > next) - (cur < next) + add v20.16b, v20.16b, v21.16b // diff = diff0 + diff1 + add v20.16b, v20.16b, v2.16b // offset_val = diff + 2 + tbl v16.16b, {v0.16b}, v20.16b + tbl v17.16b, {v1.16b}, v20.16b + uxtl v20.8h, v3.8b // src[0:7] + uxtl2 v21.8h, v3.16b // src[7:15] + zip1 v18.16b, v16.16b, v17.16b // sao_offset_val lower -> + zip2 v19.16b, v16.16b, v17.16b // sao_offset_val upper -> + sqadd v20.8h, v18.8h, v20.8h // + sao_offset_val + sqadd v21.8h, v19.8h, v21.8h + sqxtun v3.8b, v20.8h + sqxtun2 v3.16b, v21.8h + st1 {v3.16b}, [x0], #16 + // filtered 16 bytes + b.ne 2b // do we have width to filter? + // no width to filter, setup next line + subs w6, w6, #1 // filtered line + add x11, x11, x15 // stride src to next line + add x0, x0, x16 // stride dst to next line + b.ne 1b // do we have lines to process? + // no lines to filter + ret +endfunc + +// ff_hevc_sao_edge_filter_8x8_8_neon(char *dst, char *src, ptrdiff stride_dst, +// int16 *sao_offset_val, int eo, int width, int height) +function ff_hevc_sao_edge_filter_8x8_8_neon, export=1 + adr x7, .Lsao_edge_pos + ldr w4, [x7, w4, uxtw #2] + ld1 {v3.8h}, [x3] + mov v3.h[7], v3.h[0] + mov v3.h[0], v3.h[1] + mov v3.h[1], v3.h[2] + mov v3.h[2], v3.h[7] + uzp2 v1.16b, v3.16b, v3.16b + uzp1 v0.16b, v3.16b, v3.16b + movi v2.16b, #2 + add x16, x0, x2 + lsl x2, x2, #1 + mov x15, #SAO_STRIDE + mov x8, x1 + sub x9, x1, x4 + add x10, x1, x4 +1: ld1 {v3.d}[0], [ x8], x15 + ld1 {v4.d}[0], [ x9], x15 + ld1 {v5.d}[0], [x10], x15 + ld1 {v3.d}[1], [ x8], x15 + ld1 {v4.d}[1], [ x9], x15 + ld1 {v5.d}[1], [x10], x15 + subs w6, w6, #2 + cmhi v16.16b, v4.16b, v3.16b + cmhi v17.16b, v3.16b, v4.16b + cmhi v18.16b, v5.16b, v3.16b + cmhi v19.16b, v3.16b, v5.16b + sub v20.16b, v16.16b, v17.16b + sub v21.16b, v18.16b, v19.16b + add v20.16b, v20.16b, v21.16b + add v20.16b, v20.16b, v2.16b + tbl v16.16b, {v0.16b}, v20.16b + tbl v17.16b, {v1.16b}, v20.16b + uxtl v20.8h, v3.8b + uxtl2 v21.8h, v3.16b + zip1 v18.16b, v16.16b, v17.16b + zip2 v19.16b, v16.16b, v17.16b + sqadd v20.8h, v18.8h, v20.8h + sqadd v21.8h, v19.8h, v21.8h + sqxtun v6.8b, v20.8h + sqxtun v7.8b, v21.8h + st1 {v6.8b}, [ x0], x2 + st1 {v7.8b}, [x16], x2 + b.ne 1b + ret +endfunc diff --git a/libavcodec/aarch64/idct.h b/libavcodec/aarch64/idct.h index 5c4904614..97ee0a64a 100644 --- a/libavcodec/aarch64/idct.h +++ b/libavcodec/aarch64/idct.h @@ -19,6 +19,7 @@ #ifndef AVCODEC_AARCH64_IDCT_H #define AVCODEC_AARCH64_IDCT_H +#include #include void ff_simple_idct_neon(int16_t *data); diff --git a/libavcodec/aarch64/idctdsp_init_aarch64.c b/libavcodec/aarch64/idctdsp_init_aarch64.c index 742a3372e..eec21aa5a 100644 --- a/libavcodec/aarch64/idctdsp_init_aarch64.c +++ b/libavcodec/aarch64/idctdsp_init_aarch64.c @@ -27,19 +27,29 @@ #include "libavcodec/idctdsp.h" #include "idct.h" +void ff_put_pixels_clamped_neon(const int16_t *, uint8_t *, ptrdiff_t); +void ff_put_signed_pixels_clamped_neon(const int16_t *, uint8_t *, ptrdiff_t); +void ff_add_pixels_clamped_neon(const int16_t *, uint8_t *, ptrdiff_t); + av_cold void ff_idctdsp_init_aarch64(IDCTDSPContext *c, AVCodecContext *avctx, unsigned high_bit_depth) { int cpu_flags = av_get_cpu_flags(); - if (have_neon(cpu_flags) && !avctx->lowres && !high_bit_depth) { - if (avctx->idct_algo == FF_IDCT_AUTO || - avctx->idct_algo == FF_IDCT_SIMPLEAUTO || - avctx->idct_algo == FF_IDCT_SIMPLENEON) { - c->idct_put = ff_simple_idct_put_neon; - c->idct_add = ff_simple_idct_add_neon; - c->idct = ff_simple_idct_neon; - c->perm_type = FF_IDCT_PERM_PARTTRANS; + if (have_neon(cpu_flags)) { + if (!avctx->lowres && !high_bit_depth) { + if (avctx->idct_algo == FF_IDCT_AUTO || + avctx->idct_algo == FF_IDCT_SIMPLEAUTO || + avctx->idct_algo == FF_IDCT_SIMPLENEON) { + c->idct_put = ff_simple_idct_put_neon; + c->idct_add = ff_simple_idct_add_neon; + c->idct = ff_simple_idct_neon; + c->perm_type = FF_IDCT_PERM_PARTTRANS; + } } + + c->add_pixels_clamped = ff_add_pixels_clamped_neon; + c->put_pixels_clamped = ff_put_pixels_clamped_neon; + c->put_signed_pixels_clamped = ff_put_signed_pixels_clamped_neon; } } diff --git a/libavcodec/aarch64/idctdsp_neon.S b/libavcodec/aarch64/idctdsp_neon.S new file mode 100644 index 000000000..7f4761120 --- /dev/null +++ b/libavcodec/aarch64/idctdsp_neon.S @@ -0,0 +1,130 @@ +/* + * IDCT AArch64 NEON optimisations + * + * Copyright (c) 2022 Ben Avison + * + * 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/aarch64/asm.S" + +// Clamp 16-bit signed block coefficients to unsigned 8-bit +// On entry: +// x0 -> array of 64x 16-bit coefficients +// x1 -> 8-bit results +// x2 = row stride for results, bytes +function ff_put_pixels_clamped_neon, export=1 + ld1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x0], #64 + ld1 {v4.16b, v5.16b, v6.16b, v7.16b}, [x0] + sqxtun v0.8b, v0.8h + sqxtun v1.8b, v1.8h + sqxtun v2.8b, v2.8h + sqxtun v3.8b, v3.8h + sqxtun v4.8b, v4.8h + st1 {v0.8b}, [x1], x2 + sqxtun v0.8b, v5.8h + st1 {v1.8b}, [x1], x2 + sqxtun v1.8b, v6.8h + st1 {v2.8b}, [x1], x2 + sqxtun v2.8b, v7.8h + st1 {v3.8b}, [x1], x2 + st1 {v4.8b}, [x1], x2 + st1 {v0.8b}, [x1], x2 + st1 {v1.8b}, [x1], x2 + st1 {v2.8b}, [x1] + ret +endfunc + +// Clamp 16-bit signed block coefficients to signed 8-bit (biased by 128) +// On entry: +// x0 -> array of 64x 16-bit coefficients +// x1 -> 8-bit results +// x2 = row stride for results, bytes +function ff_put_signed_pixels_clamped_neon, export=1 + ld1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x0], #64 + movi v4.8b, #128 + ld1 {v16.16b, v17.16b, v18.16b, v19.16b}, [x0] + sqxtn v0.8b, v0.8h + sqxtn v1.8b, v1.8h + sqxtn v2.8b, v2.8h + sqxtn v3.8b, v3.8h + sqxtn v5.8b, v16.8h + add v0.8b, v0.8b, v4.8b + sqxtn v6.8b, v17.8h + add v1.8b, v1.8b, v4.8b + sqxtn v7.8b, v18.8h + add v2.8b, v2.8b, v4.8b + sqxtn v16.8b, v19.8h + add v3.8b, v3.8b, v4.8b + st1 {v0.8b}, [x1], x2 + add v0.8b, v5.8b, v4.8b + st1 {v1.8b}, [x1], x2 + add v1.8b, v6.8b, v4.8b + st1 {v2.8b}, [x1], x2 + add v2.8b, v7.8b, v4.8b + st1 {v3.8b}, [x1], x2 + add v3.8b, v16.8b, v4.8b + st1 {v0.8b}, [x1], x2 + st1 {v1.8b}, [x1], x2 + st1 {v2.8b}, [x1], x2 + st1 {v3.8b}, [x1] + ret +endfunc + +// Add 16-bit signed block coefficients to unsigned 8-bit +// On entry: +// x0 -> array of 64x 16-bit coefficients +// x1 -> 8-bit input and results +// x2 = row stride for 8-bit input and results, bytes +function ff_add_pixels_clamped_neon, export=1 + ld1 {v0.16b, v1.16b, v2.16b, v3.16b}, [x0], #64 + mov x3, x1 + ld1 {v4.8b}, [x1], x2 + ld1 {v5.8b}, [x1], x2 + ld1 {v6.8b}, [x1], x2 + ld1 {v7.8b}, [x1], x2 + ld1 {v16.16b, v17.16b, v18.16b, v19.16b}, [x0] + uaddw v0.8h, v0.8h, v4.8b + uaddw v1.8h, v1.8h, v5.8b + uaddw v2.8h, v2.8h, v6.8b + ld1 {v4.8b}, [x1], x2 + uaddw v3.8h, v3.8h, v7.8b + ld1 {v5.8b}, [x1], x2 + sqxtun v0.8b, v0.8h + ld1 {v6.8b}, [x1], x2 + sqxtun v1.8b, v1.8h + ld1 {v7.8b}, [x1] + sqxtun v2.8b, v2.8h + sqxtun v3.8b, v3.8h + uaddw v4.8h, v16.8h, v4.8b + st1 {v0.8b}, [x3], x2 + uaddw v0.8h, v17.8h, v5.8b + st1 {v1.8b}, [x3], x2 + uaddw v1.8h, v18.8h, v6.8b + st1 {v2.8b}, [x3], x2 + uaddw v2.8h, v19.8h, v7.8b + sqxtun v4.8b, v4.8h + sqxtun v0.8b, v0.8h + st1 {v3.8b}, [x3], x2 + sqxtun v1.8b, v1.8h + sqxtun v2.8b, v2.8h + st1 {v4.8b}, [x3], x2 + st1 {v0.8b}, [x3], x2 + st1 {v1.8b}, [x3], x2 + st1 {v2.8b}, [x3] + ret +endfunc diff --git a/libavcodec/aarch64/mdct_neon.S b/libavcodec/aarch64/mdct_neon.S index 1fd199c97..6091e7202 100644 --- a/libavcodec/aarch64/mdct_neon.S +++ b/libavcodec/aarch64/mdct_neon.S @@ -25,6 +25,7 @@ function ff_imdct_half_neon, export=1 sub sp, sp, #32 stp x19, x20, [sp] + AARCH64_SIGN_LINK_REGISTER str x30, [sp, #16] mov x12, #1 ldr w14, [x0, #28] // mdct_bits @@ -121,6 +122,7 @@ function ff_imdct_half_neon, export=1 ldp x19, x20, [sp] ldr x30, [sp, #16] + AARCH64_VALIDATE_LINK_REGISTER add sp, sp, #32 ret @@ -129,6 +131,7 @@ endfunc function ff_imdct_calc_neon, export=1 sub sp, sp, #32 stp x19, x20, [sp] + AARCH64_SIGN_LINK_REGISTER str x30, [sp, #16] ldr w3, [x0, #28] // mdct_bits mov x19, #1 @@ -160,8 +163,10 @@ function ff_imdct_calc_neon, export=1 subs x19, x19, #16 b.gt 1b - ldp x19, x20, [sp], #16 - ldr x30, [sp], #16 + ldp x19, x20, [sp] + ldr x30, [sp, #16] + AARCH64_VALIDATE_LINK_REGISTER + add sp, sp, #32 ret endfunc @@ -170,6 +175,7 @@ endfunc function ff_mdct_calc_neon, export=1 sub sp, sp, #32 stp x19, x20, [sp] + AARCH64_SIGN_LINK_REGISTER str x30, [sp, #16] mov x12, #1 @@ -317,7 +323,10 @@ function ff_mdct_calc_neon, export=1 st2 {v4.2s,v5.2s}, [x0] st2 {v6.2s,v7.2s}, [x8] - ldp x19, x20, [sp], #16 - ldr x30, [sp], #16 + ldp x19, x20, [sp] + ldr x30, [sp, #16] + AARCH64_VALIDATE_LINK_REGISTER + add sp, sp, #32 + ret endfunc diff --git a/libavcodec/aarch64/me_cmp_init_aarch64.c b/libavcodec/aarch64/me_cmp_init_aarch64.c new file mode 100644 index 000000000..bec9148a1 --- /dev/null +++ b/libavcodec/aarch64/me_cmp_init_aarch64.c @@ -0,0 +1,41 @@ +/* + * 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/attributes.h" +#include "libavutil/aarch64/cpu.h" +#include "libavcodec/mpegvideo.h" + +int ff_pix_abs16_neon(MpegEncContext *s, uint8_t *blk1, uint8_t *blk2, + ptrdiff_t stride, int h); +int ff_pix_abs16_xy2_neon(MpegEncContext *s, uint8_t *blk1, uint8_t *blk2, + ptrdiff_t stride, int h); + +av_cold void ff_me_cmp_init_aarch64(MECmpContext *c, AVCodecContext *avctx) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_neon(cpu_flags)) { + c->pix_abs[0][0] = ff_pix_abs16_neon; + c->pix_abs[0][3] = ff_pix_abs16_xy2_neon; + + c->sad[0] = ff_pix_abs16_neon; + } +} diff --git a/libavcodec/aarch64/me_cmp_neon.S b/libavcodec/aarch64/me_cmp_neon.S new file mode 100644 index 000000000..a7937bd8b --- /dev/null +++ b/libavcodec/aarch64/me_cmp_neon.S @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2022 Jonathan Swinney + * + * 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/aarch64/asm.S" + +function ff_pix_abs16_neon, export=1 + // x0 unused + // x1 uint8_t *pix1 + // x2 uint8_t *pix2 + // x3 ptrdiff_t stride + // w4 int h + cmp w4, #4 // if h < 4, jump to completion section + movi v18.4S, #0 // clear result accumulator + b.lt 2f +1: + ld1 {v0.16b}, [x1], x3 // load pix1 + ld1 {v4.16b}, [x2], x3 // load pix2 + ld1 {v1.16b}, [x1], x3 // load pix1 + ld1 {v5.16b}, [x2], x3 // load pix2 + uabdl v16.8h, v0.8b, v4.8b // absolute difference accumulate + uabdl2 v17.8h, v0.16b, v4.16b + ld1 {v2.16b}, [x1], x3 // load pix1 + ld1 {v6.16b}, [x2], x3 // load pix2 + uabal v16.8h, v1.8b, v5.8b // absolute difference accumulate + uabal2 v17.8h, v1.16b, v5.16b + ld1 {v3.16b}, [x1], x3 + ld1 {v7.16b}, [x2], x3 + uabal v16.8h, v2.8b, v6.8b + uabal2 v17.8h, v2.16b, v6.16b + sub w4, w4, #4 // h -= 4 + uabal v16.8h, v3.8b, v7.8b + uabal2 v17.8h, v3.16b, v7.16b + cmp w4, #4 // if h >= 4, loop + add v16.8h, v16.8h, v17.8h + uaddlv s16, v16.8h // add up everything in v16 accumulator + add d18, d16, d18 // add to the end result register + + b.ge 1b + cbnz w4, 2f // if iterations remain, jump to completion section + + fmov w0, s18 // copy result to general purpose register + ret + +2: + ld1 {v0.16b}, [x1], x3 // load pix1 + ld1 {v4.16b}, [x2], x3 // load pix2 + uabdl v16.8h, v0.8b, v4.8b // absolute difference accumulate + uabal2 v16.8h, v0.16b, v4.16b + subs w4, w4, #1 // h -= 1 + addv h16, v16.8h // add up v16 + add d18, d16, d18 // add to result + b.ne 2b + + fmov w0, s18 // copy result to general purpose register + ret +endfunc + +function ff_pix_abs16_xy2_neon, export=1 + // x0 unused + // x1 uint8_t *pix1 + // x2 uint8_t *pix2 + // x3 ptrdiff_t stride + // w4 int h + + add x5, x2, x3 // use x5 to hold uint8_t *pix3 + movi v0.2d, #0 // initialize the result register + + // Load initial pix2 values for either the unrolled version or completion version. + ldur q4, [x2, #1] // load pix2+1 + ldr q3, [x2] // load pix2 + uaddl v2.8h, v4.8b, v3.8b // pix2 + pix2+1 0..7 + uaddl2 v3.8h, v4.16b, v3.16b // pix2 + pix2+1 8..15 + cmp w4, #4 // if h < 4 jump to the completion version + b.lt 2f +1: + // This is an unrolled implementation. It completes 4 iterations of the C for each branch. + // In each iteration, pix2[i+1] == pix3[i]. This means we need only three loads per iteration, + // plus two at the beginning to start. + ldur q5, [x5, #1] // load pix3+1 + ld1 {v4.16b}, [x5], x3 // load pix3 + ld1 {v1.16b}, [x1], x3 // load pix1 + + ldur q7, [x5, #1] // load pix3+1 + ld1 {v6.16b}, [x5], x3 // load pix3 + ld1 {v16.16b}, [x1], x3 // load pix1 + + ldur q19, [x5, #1] // load pix3+1 + ld1 {v18.16b}, [x5], x3 // load pix3 + ld1 {v17.16b}, [x1], x3 // load pix1 + + ldur q22, [x5, #1] // load pix3+1 + ld1 {v21.16b}, [x5], x3 // load pix3 + ld1 {v20.16b}, [x1], x3 // load pix1 + + // These blocks compute the average: avg(pix2[n], pix2[n+1], pix3[n], pix3[n+1]) + uaddl v30.8h, v4.8b, v5.8b // pix3 + pix3+1 0..7 + uaddl2 v31.8h, v4.16b, v5.16b // pix3 + pix3+1 8..15 + add v23.8h, v2.8h, v30.8h // add up 0..7, using pix2 + pix2+1 values from previous iteration + add v24.8h, v3.8h, v31.8h // add up 8..15, using pix2 + pix2+1 values from previous iteration + rshrn v23.8b, v23.8h, #2 // shift right 2 0..7 (rounding shift right) + rshrn2 v23.16b, v24.8h, #2 // shift right 2 8..15 + + uaddl v2.8h, v6.8b, v7.8b // pix3 + pix3+1 0..7 + uaddl2 v3.8h, v6.16b, v7.16b // pix3 + pix3+1 8..15 + add v26.8h, v30.8h, v2.8h // add up 0..7, using pix2 + pix2+1 values from pix3 above + add v27.8h, v31.8h, v3.8h // add up 8..15, using pix2 + pix2+1 values from pix3 above + rshrn v26.8b, v26.8h, #2 // shift right 2 0..7 (rounding shift right) + rshrn2 v26.16b, v27.8h, #2 // shift right 2 8..15 + + uaddl v4.8h, v18.8b, v19.8b // pix3 + pix3+1 0..7 + uaddl2 v5.8h, v18.16b, v19.16b // pix3 + pix3+1 8..15 + add v28.8h, v2.8h, v4.8h // add up 0..7, using pix2 + pix2+1 values from pix3 above + add v29.8h, v3.8h, v5.8h // add up 8..15, using pix2 + pix2+1 values from pix3 above + rshrn v28.8b, v28.8h, #2 // shift right 2 0..7 (rounding shift right) + rshrn2 v28.16b, v29.8h, #2 // shift right 2 8..15 + + uaddl v2.8h, v21.8b, v22.8b // pix3 + pix3+1 0..7 + uaddl2 v3.8h, v21.16b, v22.16b // pix3 + pix3+1 8..15 + add v30.8h, v4.8h, v2.8h // add up 0..7, using pix2 + pix2+1 values from pix3 above + add v31.8h, v5.8h, v3.8h // add up 8..15, using pix2 + pix2+1 values from pix3 above + rshrn v30.8b, v30.8h, #2 // shift right 2 0..7 (rounding shift right) + rshrn2 v30.16b, v31.8h, #2 // shift right 2 8..15 + + // Averages are now stored in these registers: + // v23, v16, v28, v30 + // pix1 values in these registers: + // v1, v16, v17, v20 + // available: + // v4, v5, v7, v18, v19, v24, v25, v27, v29, v31 + + sub w4, w4, #4 // h -= 4 + + // Using absolute-difference instructions instead of absolute-difference-accumulate allows + // us to keep the results in 16b vectors instead of widening values with twice the instructions. + // This approach also has fewer data dependencies, allowing better instruction level parallelism. + uabd v4.16b, v1.16b, v23.16b // absolute difference 0..15, i=0 + uabd v5.16b, v16.16b, v26.16b // absolute difference 0..15, i=1 + uabd v6.16b, v17.16b, v28.16b // absolute difference 0..15, i=2 + uabd v7.16b, v20.16b, v30.16b // absolute difference 0..15, i=3 + + cmp w4, #4 // loop if h >= 4 + + // Now add up all the values in each vector, v4-v7 with widening adds + uaddl v19.8h, v4.8b, v5.8b + uaddl2 v18.8h, v4.16b, v5.16b + uaddl v4.8h, v6.8b, v7.8b + uaddl2 v5.8h, v6.16b, v7.16b + add v4.8h, v4.8h, v5.8h + add v4.8h, v4.8h, v18.8h + add v4.8h, v4.8h, v19.8h + uaddlv s4, v4.8h // finish adding up accumulated values + add d0, d0, d4 // add the value to the top level accumulator + + b.ge 1b + cbnz w4, 2f // if iterations remain jump to completion section + + fmov w0, s0 // copy result to general purpose register + ret +2: + // v2 and v3 are set either at the end of this loop or at from the unrolled version + // which branches here to complete iterations when h % 4 != 0. + ldur q5, [x5, #1] // load pix3+1 + ld1 {v4.16b}, [x5], x3 // load pix3 + ld1 {v1.16b}, [x1], x3 // load pix1 + subs w4, w4, #1 // decrement h + + uaddl v18.8h, v4.8b, v5.8b // pix3 + pix3+1 0..7 + uaddl2 v19.8h, v4.16b, v5.16b // pix3 + pix3+1 8..15 + add v16.8h, v2.8h, v18.8h // add up 0..7, using pix2 + pix2+1 values from previous iteration + add v17.8h, v3.8h, v19.8h // add up 8..15, using pix2 + pix2+1 values from previous iteration + // divide by 4 to compute the average of values summed above + urshr v16.8h, v16.8h, #2 // shift right by 2 0..7 (rounding shift right) + urshr v17.8h, v17.8h, #2 // shift right by 2 8..15 + + uxtl2 v8.8h, v1.16b // 8->16 bits pix1 8..15 + uxtl v1.8h, v1.8b // 8->16 bits pix1 0..7 + + uabd v6.8h, v1.8h, v16.8h // absolute difference 0..7 + uaba v6.8h, v8.8h, v17.8h // absolute difference accumulate 8..15 + mov v2.16b, v18.16b // pix3 -> pix2 + mov v3.16b, v19.16b // pix3+1 -> pix2+1 + uaddlv s6, v6.8h // add up accumulator in v6 + add d0, d0, d6 // add to the final result + + b.ne 2b // loop if h > 0 + fmov w0, s0 // copy result to general purpose register + ret +endfunc diff --git a/libavcodec/aarch64/synth_filter_neon.S b/libavcodec/aarch64/synth_filter_neon.S index 8fcd71f25..ba79ba968 100644 --- a/libavcodec/aarch64/synth_filter_neon.S +++ b/libavcodec/aarch64/synth_filter_neon.S @@ -52,6 +52,7 @@ function ff_synth_filter_float_neon, export=1 stp x5, x1, [sp, #16] and x7, x7, #~63 and w8, w8, #511 + AARCH64_SIGN_LINK_REGISTER stp x7, x30, [sp, #32] str w8, [x2] str s0, [sp, #48] @@ -63,6 +64,7 @@ function ff_synth_filter_float_neon, export=1 ldp x2, x4, [sp] // synct_buf_2, window ldp x13, x9, [sp, #16] // out, synth_buf ldp x0, x30, [sp, #32] // *synth_buf_offset + AARCH64_VALIDATE_LINK_REGISTER ldr s0, [sp, #48] add x3, x2, #16*4 // synct_buf_2 + 16 diff --git a/libavcodec/aarch64/vc1dsp_init_aarch64.c b/libavcodec/aarch64/vc1dsp_init_aarch64.c index 13dfd7494..a7976fd59 100644 --- a/libavcodec/aarch64/vc1dsp_init_aarch64.c +++ b/libavcodec/aarch64/vc1dsp_init_aarch64.c @@ -21,10 +21,28 @@ #include "libavutil/attributes.h" #include "libavutil/cpu.h" #include "libavutil/aarch64/cpu.h" +#include "libavutil/intreadwrite.h" #include "libavcodec/vc1dsp.h" #include "config.h" +void ff_vc1_inv_trans_8x8_neon(int16_t *block); +void ff_vc1_inv_trans_8x4_neon(uint8_t *dest, ptrdiff_t stride, int16_t *block); +void ff_vc1_inv_trans_4x8_neon(uint8_t *dest, ptrdiff_t stride, int16_t *block); +void ff_vc1_inv_trans_4x4_neon(uint8_t *dest, ptrdiff_t stride, int16_t *block); + +void ff_vc1_inv_trans_8x8_dc_neon(uint8_t *dest, ptrdiff_t stride, int16_t *block); +void ff_vc1_inv_trans_8x4_dc_neon(uint8_t *dest, ptrdiff_t stride, int16_t *block); +void ff_vc1_inv_trans_4x8_dc_neon(uint8_t *dest, ptrdiff_t stride, int16_t *block); +void ff_vc1_inv_trans_4x4_dc_neon(uint8_t *dest, ptrdiff_t stride, int16_t *block); + +void ff_vc1_v_loop_filter4_neon(uint8_t *src, ptrdiff_t stride, int pq); +void ff_vc1_h_loop_filter4_neon(uint8_t *src, ptrdiff_t stride, int pq); +void ff_vc1_v_loop_filter8_neon(uint8_t *src, ptrdiff_t stride, int pq); +void ff_vc1_h_loop_filter8_neon(uint8_t *src, ptrdiff_t stride, int pq); +void ff_vc1_v_loop_filter16_neon(uint8_t *src, ptrdiff_t stride, int pq); +void ff_vc1_h_loop_filter16_neon(uint8_t *src, ptrdiff_t stride, int pq); + void ff_put_vc1_chroma_mc8_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride, int h, int x, int y); void ff_avg_vc1_chroma_mc8_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride, @@ -34,14 +52,90 @@ void ff_put_vc1_chroma_mc4_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride, void ff_avg_vc1_chroma_mc4_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride, int h, int x, int y); +int ff_vc1_unescape_buffer_helper_neon(const uint8_t *src, int size, uint8_t *dst); + +static int vc1_unescape_buffer_neon(const uint8_t *src, int size, uint8_t *dst) +{ + /* Dealing with starting and stopping, and removing escape bytes, are + * comparatively less time-sensitive, so are more clearly expressed using + * a C wrapper around the assembly inner loop. Note that we assume a + * little-endian machine that supports unaligned loads. */ + int dsize = 0; + while (size >= 4) + { + int found = 0; + while (!found && (((uintptr_t) dst) & 7) && size >= 4) + { + found = (AV_RL32(src) &~ 0x03000000) == 0x00030000; + if (!found) + { + *dst++ = *src++; + --size; + ++dsize; + } + } + if (!found) + { + int skip = size - ff_vc1_unescape_buffer_helper_neon(src, size, dst); + dst += skip; + src += skip; + size -= skip; + dsize += skip; + while (!found && size >= 4) + { + found = (AV_RL32(src) &~ 0x03000000) == 0x00030000; + if (!found) + { + *dst++ = *src++; + --size; + ++dsize; + } + } + } + if (found) + { + *dst++ = *src++; + *dst++ = *src++; + ++src; + size -= 3; + dsize += 2; + } + } + while (size > 0) + { + *dst++ = *src++; + --size; + ++dsize; + } + return dsize; +} + av_cold void ff_vc1dsp_init_aarch64(VC1DSPContext *dsp) { int cpu_flags = av_get_cpu_flags(); if (have_neon(cpu_flags)) { + dsp->vc1_inv_trans_8x8 = ff_vc1_inv_trans_8x8_neon; + dsp->vc1_inv_trans_8x4 = ff_vc1_inv_trans_8x4_neon; + dsp->vc1_inv_trans_4x8 = ff_vc1_inv_trans_4x8_neon; + dsp->vc1_inv_trans_4x4 = ff_vc1_inv_trans_4x4_neon; + dsp->vc1_inv_trans_8x8_dc = ff_vc1_inv_trans_8x8_dc_neon; + dsp->vc1_inv_trans_8x4_dc = ff_vc1_inv_trans_8x4_dc_neon; + dsp->vc1_inv_trans_4x8_dc = ff_vc1_inv_trans_4x8_dc_neon; + dsp->vc1_inv_trans_4x4_dc = ff_vc1_inv_trans_4x4_dc_neon; + + dsp->vc1_v_loop_filter4 = ff_vc1_v_loop_filter4_neon; + dsp->vc1_h_loop_filter4 = ff_vc1_h_loop_filter4_neon; + dsp->vc1_v_loop_filter8 = ff_vc1_v_loop_filter8_neon; + dsp->vc1_h_loop_filter8 = ff_vc1_h_loop_filter8_neon; + dsp->vc1_v_loop_filter16 = ff_vc1_v_loop_filter16_neon; + dsp->vc1_h_loop_filter16 = ff_vc1_h_loop_filter16_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; dsp->put_no_rnd_vc1_chroma_pixels_tab[1] = ff_put_vc1_chroma_mc4_neon; dsp->avg_no_rnd_vc1_chroma_pixels_tab[1] = ff_avg_vc1_chroma_mc4_neon; + + dsp->vc1_unescape_buffer = vc1_unescape_buffer_neon; } } diff --git a/libavcodec/aarch64/vc1dsp_neon.S b/libavcodec/aarch64/vc1dsp_neon.S new file mode 100644 index 000000000..9a96c2523 --- /dev/null +++ b/libavcodec/aarch64/vc1dsp_neon.S @@ -0,0 +1,1546 @@ +/* + * VC1 AArch64 NEON optimisations + * + * Copyright (c) 2022 Ben Avison + * + * 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/aarch64/asm.S" + +// VC-1 8x8 inverse transform +// On entry: +// x0 -> array of 16-bit inverse transform coefficients, in column-major order +// On exit: +// array at x0 updated to hold transformed block; also now held in row-major order +function ff_vc1_inv_trans_8x8_neon, export=1 + ld1 {v1.16b, v2.16b}, [x0], #32 + ld1 {v3.16b, v4.16b}, [x0], #32 + ld1 {v5.16b, v6.16b}, [x0], #32 + shl v1.8h, v1.8h, #2 // 8/2 * src[0] + sub x1, x0, #3*32 + ld1 {v16.16b, v17.16b}, [x0] + shl v7.8h, v2.8h, #4 // 16 * src[8] + shl v18.8h, v2.8h, #2 // 4 * src[8] + shl v19.8h, v4.8h, #4 // 16 * src[24] + ldr d0, .Lcoeffs_it8 + shl v5.8h, v5.8h, #2 // 8/2 * src[32] + shl v20.8h, v6.8h, #4 // 16 * src[40] + shl v21.8h, v6.8h, #2 // 4 * src[40] + shl v22.8h, v17.8h, #4 // 16 * src[56] + ssra v20.8h, v19.8h, #2 // 4 * src[24] + 16 * src[40] + mul v23.8h, v3.8h, v0.h[0] // 6/2 * src[16] + sub v19.8h, v19.8h, v21.8h // 16 * src[24] - 4 * src[40] + ssra v7.8h, v22.8h, #2 // 16 * src[8] + 4 * src[56] + sub v18.8h, v22.8h, v18.8h // - 4 * src[8] + 16 * src[56] + shl v3.8h, v3.8h, #3 // 16/2 * src[16] + mls v20.8h, v2.8h, v0.h[2] // - 15 * src[8] + 4 * src[24] + 16 * src[40] + ssra v1.8h, v1.8h, #1 // 12/2 * src[0] + ssra v5.8h, v5.8h, #1 // 12/2 * src[32] + mla v7.8h, v4.8h, v0.h[2] // 16 * src[8] + 15 * src[24] + 4 * src[56] + shl v21.8h, v16.8h, #3 // 16/2 * src[48] + mls v19.8h, v2.8h, v0.h[1] // - 9 * src[8] + 16 * src[24] - 4 * src[40] + sub v2.8h, v23.8h, v21.8h // t4/2 = 6/2 * src[16] - 16/2 * src[48] + mla v18.8h, v4.8h, v0.h[1] // - 4 * src[8] + 9 * src[24] + 16 * src[56] + add v4.8h, v1.8h, v5.8h // t1/2 = 12/2 * src[0] + 12/2 * src[32] + sub v1.8h, v1.8h, v5.8h // t2/2 = 12/2 * src[0] - 12/2 * src[32] + mla v3.8h, v16.8h, v0.h[0] // t3/2 = 16/2 * src[16] + 6/2 * src[48] + mla v7.8h, v6.8h, v0.h[1] // t1 = 16 * src[8] + 15 * src[24] + 9 * src[40] + 4 * src[56] + add v5.8h, v1.8h, v2.8h // t6/2 = t2/2 + t4/2 + sub v16.8h, v1.8h, v2.8h // t7/2 = t2/2 - t4/2 + mla v20.8h, v17.8h, v0.h[1] // -t2 = - 15 * src[8] + 4 * src[24] + 16 * src[40] + 9 * src[56] + add v21.8h, v1.8h, v2.8h // t6/2 = t2/2 + t4/2 + add v22.8h, v4.8h, v3.8h // t5/2 = t1/2 + t3/2 + mls v19.8h, v17.8h, v0.h[2] // -t3 = - 9 * src[8] + 16 * src[24] - 4 * src[40] - 15 * src[56] + sub v17.8h, v4.8h, v3.8h // t8/2 = t1/2 - t3/2 + add v23.8h, v4.8h, v3.8h // t5/2 = t1/2 + t3/2 + mls v18.8h, v6.8h, v0.h[2] // -t4 = - 4 * src[8] + 9 * src[24] - 15 * src[40] + 16 * src[56] + sub v1.8h, v1.8h, v2.8h // t7/2 = t2/2 - t4/2 + sub v2.8h, v4.8h, v3.8h // t8/2 = t1/2 - t3/2 + neg v3.8h, v7.8h // -t1 + neg v4.8h, v20.8h // +t2 + neg v6.8h, v19.8h // +t3 + ssra v22.8h, v7.8h, #1 // (t5 + t1) >> 1 + ssra v1.8h, v19.8h, #1 // (t7 - t3) >> 1 + neg v7.8h, v18.8h // +t4 + ssra v5.8h, v4.8h, #1 // (t6 + t2) >> 1 + ssra v16.8h, v6.8h, #1 // (t7 + t3) >> 1 + ssra v2.8h, v18.8h, #1 // (t8 - t4) >> 1 + ssra v17.8h, v7.8h, #1 // (t8 + t4) >> 1 + ssra v21.8h, v20.8h, #1 // (t6 - t2) >> 1 + ssra v23.8h, v3.8h, #1 // (t5 - t1) >> 1 + srshr v3.8h, v22.8h, #2 // (t5 + t1 + 4) >> 3 + srshr v4.8h, v5.8h, #2 // (t6 + t2 + 4) >> 3 + srshr v5.8h, v16.8h, #2 // (t7 + t3 + 4) >> 3 + srshr v6.8h, v17.8h, #2 // (t8 + t4 + 4) >> 3 + srshr v2.8h, v2.8h, #2 // (t8 - t4 + 4) >> 3 + srshr v1.8h, v1.8h, #2 // (t7 - t3 + 4) >> 3 + srshr v7.8h, v21.8h, #2 // (t6 - t2 + 4) >> 3 + srshr v16.8h, v23.8h, #2 // (t5 - t1 + 4) >> 3 + trn2 v17.8h, v3.8h, v4.8h + trn2 v18.8h, v5.8h, v6.8h + trn2 v19.8h, v2.8h, v1.8h + trn2 v20.8h, v7.8h, v16.8h + trn1 v21.4s, v17.4s, v18.4s + trn2 v17.4s, v17.4s, v18.4s + trn1 v18.4s, v19.4s, v20.4s + trn2 v19.4s, v19.4s, v20.4s + trn1 v3.8h, v3.8h, v4.8h + trn2 v4.2d, v21.2d, v18.2d + trn1 v20.2d, v17.2d, v19.2d + trn1 v5.8h, v5.8h, v6.8h + trn1 v1.8h, v2.8h, v1.8h + trn1 v2.8h, v7.8h, v16.8h + trn1 v6.2d, v21.2d, v18.2d + trn2 v7.2d, v17.2d, v19.2d + shl v16.8h, v20.8h, #4 // 16 * src[24] + shl v17.8h, v4.8h, #4 // 16 * src[40] + trn1 v18.4s, v3.4s, v5.4s + trn1 v19.4s, v1.4s, v2.4s + shl v21.8h, v7.8h, #4 // 16 * src[56] + shl v22.8h, v6.8h, #2 // 4 * src[8] + shl v23.8h, v4.8h, #2 // 4 * src[40] + trn2 v3.4s, v3.4s, v5.4s + trn2 v1.4s, v1.4s, v2.4s + shl v2.8h, v6.8h, #4 // 16 * src[8] + sub v5.8h, v16.8h, v23.8h // 16 * src[24] - 4 * src[40] + ssra v17.8h, v16.8h, #2 // 4 * src[24] + 16 * src[40] + sub v16.8h, v21.8h, v22.8h // - 4 * src[8] + 16 * src[56] + trn1 v22.2d, v18.2d, v19.2d + trn2 v18.2d, v18.2d, v19.2d + trn1 v19.2d, v3.2d, v1.2d + ssra v2.8h, v21.8h, #2 // 16 * src[8] + 4 * src[56] + mls v17.8h, v6.8h, v0.h[2] // - 15 * src[8] + 4 * src[24] + 16 * src[40] + shl v21.8h, v22.8h, #2 // 8/2 * src[0] + shl v18.8h, v18.8h, #2 // 8/2 * src[32] + mls v5.8h, v6.8h, v0.h[1] // - 9 * src[8] + 16 * src[24] - 4 * src[40] + shl v6.8h, v19.8h, #3 // 16/2 * src[16] + trn2 v1.2d, v3.2d, v1.2d + mla v16.8h, v20.8h, v0.h[1] // - 4 * src[8] + 9 * src[24] + 16 * src[56] + ssra v21.8h, v21.8h, #1 // 12/2 * src[0] + ssra v18.8h, v18.8h, #1 // 12/2 * src[32] + mul v3.8h, v19.8h, v0.h[0] // 6/2 * src[16] + shl v19.8h, v1.8h, #3 // 16/2 * src[48] + mla v2.8h, v20.8h, v0.h[2] // 16 * src[8] + 15 * src[24] + 4 * src[56] + add v20.8h, v21.8h, v18.8h // t1/2 = 12/2 * src[0] + 12/2 * src[32] + mla v6.8h, v1.8h, v0.h[0] // t3/2 = 16/2 * src[16] + 6/2 * src[48] + sub v1.8h, v21.8h, v18.8h // t2/2 = 12/2 * src[0] - 12/2 * src[32] + sub v3.8h, v3.8h, v19.8h // t4/2 = 6/2 * src[16] - 16/2 * src[48] + mla v17.8h, v7.8h, v0.h[1] // -t2 = - 15 * src[8] + 4 * src[24] + 16 * src[40] + 9 * src[56] + mls v5.8h, v7.8h, v0.h[2] // -t3 = - 9 * src[8] + 16 * src[24] - 4 * src[40] - 15 * src[56] + add v7.8h, v1.8h, v3.8h // t6/2 = t2/2 + t4/2 + add v18.8h, v20.8h, v6.8h // t5/2 = t1/2 + t3/2 + mls v16.8h, v4.8h, v0.h[2] // -t4 = - 4 * src[8] + 9 * src[24] - 15 * src[40] + 16 * src[56] + sub v19.8h, v1.8h, v3.8h // t7/2 = t2/2 - t4/2 + neg v21.8h, v17.8h // +t2 + mla v2.8h, v4.8h, v0.h[1] // t1 = 16 * src[8] + 15 * src[24] + 9 * src[40] + 4 * src[56] + sub v0.8h, v20.8h, v6.8h // t8/2 = t1/2 - t3/2 + neg v4.8h, v5.8h // +t3 + sub v22.8h, v1.8h, v3.8h // t7/2 = t2/2 - t4/2 + sub v23.8h, v20.8h, v6.8h // t8/2 = t1/2 - t3/2 + neg v24.8h, v16.8h // +t4 + add v6.8h, v20.8h, v6.8h // t5/2 = t1/2 + t3/2 + add v1.8h, v1.8h, v3.8h // t6/2 = t2/2 + t4/2 + ssra v7.8h, v21.8h, #1 // (t6 + t2) >> 1 + neg v3.8h, v2.8h // -t1 + ssra v18.8h, v2.8h, #1 // (t5 + t1) >> 1 + ssra v19.8h, v4.8h, #1 // (t7 + t3) >> 1 + ssra v0.8h, v24.8h, #1 // (t8 + t4) >> 1 + srsra v23.8h, v16.8h, #1 // (t8 - t4 + 1) >> 1 + srsra v22.8h, v5.8h, #1 // (t7 - t3 + 1) >> 1 + srsra v1.8h, v17.8h, #1 // (t6 - t2 + 1) >> 1 + srsra v6.8h, v3.8h, #1 // (t5 - t1 + 1) >> 1 + srshr v2.8h, v18.8h, #6 // (t5 + t1 + 64) >> 7 + srshr v3.8h, v7.8h, #6 // (t6 + t2 + 64) >> 7 + srshr v4.8h, v19.8h, #6 // (t7 + t3 + 64) >> 7 + srshr v5.8h, v0.8h, #6 // (t8 + t4 + 64) >> 7 + srshr v16.8h, v23.8h, #6 // (t8 - t4 + 65) >> 7 + srshr v17.8h, v22.8h, #6 // (t7 - t3 + 65) >> 7 + st1 {v2.16b, v3.16b}, [x1], #32 + srshr v0.8h, v1.8h, #6 // (t6 - t2 + 65) >> 7 + srshr v1.8h, v6.8h, #6 // (t5 - t1 + 65) >> 7 + st1 {v4.16b, v5.16b}, [x1], #32 + st1 {v16.16b, v17.16b}, [x1], #32 + st1 {v0.16b, v1.16b}, [x1] + ret +endfunc + +// VC-1 8x4 inverse transform +// On entry: +// x0 -> array of 8-bit samples, in row-major order +// x1 = row stride for 8-bit sample array +// x2 -> array of 16-bit inverse transform coefficients, in row-major order +// On exit: +// array at x0 updated by saturated addition of (narrowed) transformed block +function ff_vc1_inv_trans_8x4_neon, export=1 + ld1 {v1.8b, v2.8b, v3.8b, v4.8b}, [x2], #32 + mov x3, x0 + ld1 {v16.8b, v17.8b, v18.8b, v19.8b}, [x2] + ldr q0, .Lcoeffs_it8 // includes 4-point coefficients in upper half of vector + ld1 {v5.8b}, [x0], x1 + trn2 v6.4h, v1.4h, v3.4h + trn2 v7.4h, v2.4h, v4.4h + trn1 v1.4h, v1.4h, v3.4h + trn1 v2.4h, v2.4h, v4.4h + trn2 v3.4h, v16.4h, v18.4h + trn2 v4.4h, v17.4h, v19.4h + trn1 v16.4h, v16.4h, v18.4h + trn1 v17.4h, v17.4h, v19.4h + ld1 {v18.8b}, [x0], x1 + trn1 v19.2s, v6.2s, v3.2s + trn2 v3.2s, v6.2s, v3.2s + trn1 v6.2s, v7.2s, v4.2s + trn2 v4.2s, v7.2s, v4.2s + trn1 v7.2s, v1.2s, v16.2s + trn1 v20.2s, v2.2s, v17.2s + shl v21.4h, v19.4h, #4 // 16 * src[1] + trn2 v1.2s, v1.2s, v16.2s + shl v16.4h, v3.4h, #4 // 16 * src[3] + trn2 v2.2s, v2.2s, v17.2s + shl v17.4h, v6.4h, #4 // 16 * src[5] + ld1 {v22.8b}, [x0], x1 + shl v23.4h, v4.4h, #4 // 16 * src[7] + mul v24.4h, v1.4h, v0.h[0] // 6/2 * src[2] + ld1 {v25.8b}, [x0] + shl v26.4h, v19.4h, #2 // 4 * src[1] + shl v27.4h, v6.4h, #2 // 4 * src[5] + ssra v21.4h, v23.4h, #2 // 16 * src[1] + 4 * src[7] + ssra v17.4h, v16.4h, #2 // 4 * src[3] + 16 * src[5] + sub v23.4h, v23.4h, v26.4h // - 4 * src[1] + 16 * src[7] + sub v16.4h, v16.4h, v27.4h // 16 * src[3] - 4 * src[5] + shl v7.4h, v7.4h, #2 // 8/2 * src[0] + shl v20.4h, v20.4h, #2 // 8/2 * src[4] + mla v21.4h, v3.4h, v0.h[2] // 16 * src[1] + 15 * src[3] + 4 * src[7] + shl v1.4h, v1.4h, #3 // 16/2 * src[2] + mls v17.4h, v19.4h, v0.h[2] // - 15 * src[1] + 4 * src[3] + 16 * src[5] + ssra v7.4h, v7.4h, #1 // 12/2 * src[0] + mls v16.4h, v19.4h, v0.h[1] // - 9 * src[1] + 16 * src[3] - 4 * src[5] + ssra v20.4h, v20.4h, #1 // 12/2 * src[4] + mla v23.4h, v3.4h, v0.h[1] // - 4 * src[1] + 9 * src[3] + 16 * src[7] + shl v3.4h, v2.4h, #3 // 16/2 * src[6] + mla v1.4h, v2.4h, v0.h[0] // t3/2 = 16/2 * src[2] + 6/2 * src[6] + mla v21.4h, v6.4h, v0.h[1] // t1 = 16 * src[1] + 15 * src[3] + 9 * src[5] + 4 * src[7] + mla v17.4h, v4.4h, v0.h[1] // -t2 = - 15 * src[1] + 4 * src[3] + 16 * src[5] + 9 * src[7] + sub v2.4h, v24.4h, v3.4h // t4/2 = 6/2 * src[2] - 16/2 * src[6] + mls v16.4h, v4.4h, v0.h[2] // -t3 = - 9 * src[1] + 16 * src[3] - 4 * src[5] - 15 * src[7] + add v3.4h, v7.4h, v20.4h // t1/2 = 12/2 * src[0] + 12/2 * src[4] + mls v23.4h, v6.4h, v0.h[2] // -t4 = - 4 * src[1] + 9 * src[3] - 15 * src[5] + 16 * src[7] + sub v4.4h, v7.4h, v20.4h // t2/2 = 12/2 * src[0] - 12/2 * src[4] + neg v6.4h, v21.4h // -t1 + add v7.4h, v3.4h, v1.4h // t5/2 = t1/2 + t3/2 + sub v19.4h, v3.4h, v1.4h // t8/2 = t1/2 - t3/2 + add v20.4h, v4.4h, v2.4h // t6/2 = t2/2 + t4/2 + sub v24.4h, v4.4h, v2.4h // t7/2 = t2/2 - t4/2 + add v26.4h, v3.4h, v1.4h // t5/2 = t1/2 + t3/2 + add v27.4h, v4.4h, v2.4h // t6/2 = t2/2 + t4/2 + sub v2.4h, v4.4h, v2.4h // t7/2 = t2/2 - t4/2 + sub v1.4h, v3.4h, v1.4h // t8/2 = t1/2 - t3/2 + neg v3.4h, v17.4h // +t2 + neg v4.4h, v16.4h // +t3 + neg v28.4h, v23.4h // +t4 + ssra v7.4h, v21.4h, #1 // (t5 + t1) >> 1 + ssra v1.4h, v23.4h, #1 // (t8 - t4) >> 1 + ssra v20.4h, v3.4h, #1 // (t6 + t2) >> 1 + ssra v24.4h, v4.4h, #1 // (t7 + t3) >> 1 + ssra v19.4h, v28.4h, #1 // (t8 + t4) >> 1 + ssra v2.4h, v16.4h, #1 // (t7 - t3) >> 1 + ssra v27.4h, v17.4h, #1 // (t6 - t2) >> 1 + ssra v26.4h, v6.4h, #1 // (t5 - t1) >> 1 + trn1 v1.2d, v7.2d, v1.2d + trn1 v2.2d, v20.2d, v2.2d + trn1 v3.2d, v24.2d, v27.2d + trn1 v4.2d, v19.2d, v26.2d + srshr v1.8h, v1.8h, #2 // (t5 + t1 + 4) >> 3, (t8 - t4 + 4) >> 3 + srshr v2.8h, v2.8h, #2 // (t6 + t2 + 4) >> 3, (t7 - t3 + 4) >> 3 + srshr v3.8h, v3.8h, #2 // (t7 + t3 + 4) >> 3, (t6 - t2 + 4) >> 3 + srshr v4.8h, v4.8h, #2 // (t8 + t4 + 4) >> 3, (t5 - t1 + 4) >> 3 + trn2 v6.8h, v1.8h, v2.8h + trn1 v1.8h, v1.8h, v2.8h + trn2 v2.8h, v3.8h, v4.8h + trn1 v3.8h, v3.8h, v4.8h + trn2 v4.4s, v6.4s, v2.4s + trn1 v7.4s, v1.4s, v3.4s + trn2 v1.4s, v1.4s, v3.4s + mul v3.8h, v4.8h, v0.h[5] // 22/2 * src[24] + trn1 v2.4s, v6.4s, v2.4s + mul v4.8h, v4.8h, v0.h[4] // 10/2 * src[24] + mul v6.8h, v7.8h, v0.h[6] // 17 * src[0] + mul v1.8h, v1.8h, v0.h[6] // 17 * src[16] + mls v3.8h, v2.8h, v0.h[4] // t4/2 = - 10/2 * src[8] + 22/2 * src[24] + mla v4.8h, v2.8h, v0.h[5] // t3/2 = 22/2 * src[8] + 10/2 * src[24] + add v0.8h, v6.8h, v1.8h // t1 = 17 * src[0] + 17 * src[16] + sub v1.8h, v6.8h, v1.8h // t2 = 17 * src[0] - 17 * src[16] + neg v2.8h, v3.8h // -t4/2 + neg v6.8h, v4.8h // -t3/2 + ssra v4.8h, v0.8h, #1 // (t1 + t3) >> 1 + ssra v2.8h, v1.8h, #1 // (t2 - t4) >> 1 + ssra v3.8h, v1.8h, #1 // (t2 + t4) >> 1 + ssra v6.8h, v0.8h, #1 // (t1 - t3) >> 1 + srshr v0.8h, v4.8h, #6 // (t1 + t3 + 64) >> 7 + srshr v1.8h, v2.8h, #6 // (t2 - t4 + 64) >> 7 + srshr v2.8h, v3.8h, #6 // (t2 + t4 + 64) >> 7 + srshr v3.8h, v6.8h, #6 // (t1 - t3 + 64) >> 7 + uaddw v0.8h, v0.8h, v5.8b + uaddw v1.8h, v1.8h, v18.8b + uaddw v2.8h, v2.8h, v22.8b + uaddw v3.8h, v3.8h, v25.8b + sqxtun v0.8b, v0.8h + sqxtun v1.8b, v1.8h + sqxtun v2.8b, v2.8h + sqxtun v3.8b, v3.8h + st1 {v0.8b}, [x3], x1 + st1 {v1.8b}, [x3], x1 + st1 {v2.8b}, [x3], x1 + st1 {v3.8b}, [x3] + ret +endfunc + +// VC-1 4x8 inverse transform +// On entry: +// x0 -> array of 8-bit samples, in row-major order +// x1 = row stride for 8-bit sample array +// x2 -> array of 16-bit inverse transform coefficients, in row-major order (row stride is 8 coefficients) +// On exit: +// array at x0 updated by saturated addition of (narrowed) transformed block +function ff_vc1_inv_trans_4x8_neon, export=1 + mov x3, #16 + ldr q0, .Lcoeffs_it8 // includes 4-point coefficients in upper half of vector + mov x4, x0 + ld1 {v1.d}[0], [x2], x3 // 00 01 02 03 + ld1 {v2.d}[0], [x2], x3 // 10 11 12 13 + ld1 {v3.d}[0], [x2], x3 // 20 21 22 23 + ld1 {v4.d}[0], [x2], x3 // 30 31 32 33 + ld1 {v1.d}[1], [x2], x3 // 40 41 42 43 + ld1 {v2.d}[1], [x2], x3 // 50 51 52 53 + ld1 {v3.d}[1], [x2], x3 // 60 61 62 63 + ld1 {v4.d}[1], [x2] // 70 71 72 73 + ld1 {v5.s}[0], [x0], x1 + ld1 {v6.s}[0], [x0], x1 + ld1 {v7.s}[0], [x0], x1 + trn2 v16.8h, v1.8h, v2.8h // 01 11 03 13 41 51 43 53 + trn1 v1.8h, v1.8h, v2.8h // 00 10 02 12 40 50 42 52 + trn2 v2.8h, v3.8h, v4.8h // 21 31 23 33 61 71 63 73 + trn1 v3.8h, v3.8h, v4.8h // 20 30 22 32 60 70 62 72 + ld1 {v4.s}[0], [x0], x1 + trn2 v17.4s, v16.4s, v2.4s // 03 13 23 33 43 53 63 73 + trn1 v18.4s, v1.4s, v3.4s // 00 10 20 30 40 50 60 70 + trn1 v2.4s, v16.4s, v2.4s // 01 11 21 31 41 51 61 71 + mul v16.8h, v17.8h, v0.h[4] // 10/2 * src[3] + ld1 {v5.s}[1], [x0], x1 + mul v17.8h, v17.8h, v0.h[5] // 22/2 * src[3] + ld1 {v6.s}[1], [x0], x1 + trn2 v1.4s, v1.4s, v3.4s // 02 12 22 32 42 52 62 72 + mul v3.8h, v18.8h, v0.h[6] // 17 * src[0] + ld1 {v7.s}[1], [x0], x1 + mul v1.8h, v1.8h, v0.h[6] // 17 * src[2] + ld1 {v4.s}[1], [x0] + mla v16.8h, v2.8h, v0.h[5] // t3/2 = 22/2 * src[1] + 10/2 * src[3] + mls v17.8h, v2.8h, v0.h[4] // t4/2 = - 10/2 * src[1] + 22/2 * src[3] + add v2.8h, v3.8h, v1.8h // t1 = 17 * src[0] + 17 * src[2] + sub v1.8h, v3.8h, v1.8h // t2 = 17 * src[0] - 17 * src[2] + neg v3.8h, v16.8h // -t3/2 + ssra v16.8h, v2.8h, #1 // (t1 + t3) >> 1 + neg v18.8h, v17.8h // -t4/2 + ssra v17.8h, v1.8h, #1 // (t2 + t4) >> 1 + ssra v3.8h, v2.8h, #1 // (t1 - t3) >> 1 + ssra v18.8h, v1.8h, #1 // (t2 - t4) >> 1 + srshr v1.8h, v16.8h, #2 // (t1 + t3 + 64) >> 3 + srshr v2.8h, v17.8h, #2 // (t2 + t4 + 64) >> 3 + srshr v3.8h, v3.8h, #2 // (t1 - t3 + 64) >> 3 + srshr v16.8h, v18.8h, #2 // (t2 - t4 + 64) >> 3 + trn2 v17.8h, v2.8h, v3.8h // 12 13 32 33 52 53 72 73 + trn2 v18.8h, v1.8h, v16.8h // 10 11 30 31 50 51 70 71 + trn1 v1.8h, v1.8h, v16.8h // 00 01 20 21 40 41 60 61 + trn1 v2.8h, v2.8h, v3.8h // 02 03 22 23 42 43 62 63 + trn1 v3.4s, v18.4s, v17.4s // 10 11 12 13 50 51 52 53 + trn2 v16.4s, v18.4s, v17.4s // 30 31 32 33 70 71 72 73 + trn1 v17.4s, v1.4s, v2.4s // 00 01 02 03 40 41 42 43 + mov d18, v3.d[1] // 50 51 52 53 + shl v19.4h, v3.4h, #4 // 16 * src[8] + mov d20, v16.d[1] // 70 71 72 73 + shl v21.4h, v16.4h, #4 // 16 * src[24] + mov d22, v17.d[1] // 40 41 42 43 + shl v23.4h, v3.4h, #2 // 4 * src[8] + shl v24.4h, v18.4h, #4 // 16 * src[40] + shl v25.4h, v20.4h, #4 // 16 * src[56] + shl v26.4h, v18.4h, #2 // 4 * src[40] + trn2 v1.4s, v1.4s, v2.4s // 20 21 22 23 60 61 62 63 + ssra v24.4h, v21.4h, #2 // 4 * src[24] + 16 * src[40] + sub v2.4h, v25.4h, v23.4h // - 4 * src[8] + 16 * src[56] + shl v17.4h, v17.4h, #2 // 8/2 * src[0] + sub v21.4h, v21.4h, v26.4h // 16 * src[24] - 4 * src[40] + shl v22.4h, v22.4h, #2 // 8/2 * src[32] + mov d23, v1.d[1] // 60 61 62 63 + ssra v19.4h, v25.4h, #2 // 16 * src[8] + 4 * src[56] + mul v25.4h, v1.4h, v0.h[0] // 6/2 * src[16] + shl v1.4h, v1.4h, #3 // 16/2 * src[16] + mls v24.4h, v3.4h, v0.h[2] // - 15 * src[8] + 4 * src[24] + 16 * src[40] + ssra v17.4h, v17.4h, #1 // 12/2 * src[0] + mls v21.4h, v3.4h, v0.h[1] // - 9 * src[8] + 16 * src[24] - 4 * src[40] + ssra v22.4h, v22.4h, #1 // 12/2 * src[32] + mla v2.4h, v16.4h, v0.h[1] // - 4 * src[8] + 9 * src[24] + 16 * src[56] + shl v3.4h, v23.4h, #3 // 16/2 * src[48] + mla v19.4h, v16.4h, v0.h[2] // 16 * src[8] + 15 * src[24] + 4 * src[56] + mla v1.4h, v23.4h, v0.h[0] // t3/2 = 16/2 * src[16] + 6/2 * src[48] + mla v24.4h, v20.4h, v0.h[1] // -t2 = - 15 * src[8] + 4 * src[24] + 16 * src[40] + 9 * src[56] + add v16.4h, v17.4h, v22.4h // t1/2 = 12/2 * src[0] + 12/2 * src[32] + sub v3.4h, v25.4h, v3.4h // t4/2 = 6/2 * src[16] - 16/2 * src[48] + sub v17.4h, v17.4h, v22.4h // t2/2 = 12/2 * src[0] - 12/2 * src[32] + mls v21.4h, v20.4h, v0.h[2] // -t3 = - 9 * src[8] + 16 * src[24] - 4 * src[40] - 15 * src[56] + mla v19.4h, v18.4h, v0.h[1] // t1 = 16 * src[8] + 15 * src[24] + 9 * src[40] + 4 * src[56] + add v20.4h, v16.4h, v1.4h // t5/2 = t1/2 + t3/2 + mls v2.4h, v18.4h, v0.h[2] // -t4 = - 4 * src[8] + 9 * src[24] - 15 * src[40] + 16 * src[56] + sub v0.4h, v16.4h, v1.4h // t8/2 = t1/2 - t3/2 + add v18.4h, v17.4h, v3.4h // t6/2 = t2/2 + t4/2 + sub v22.4h, v17.4h, v3.4h // t7/2 = t2/2 - t4/2 + neg v23.4h, v24.4h // +t2 + sub v25.4h, v17.4h, v3.4h // t7/2 = t2/2 - t4/2 + add v3.4h, v17.4h, v3.4h // t6/2 = t2/2 + t4/2 + neg v17.4h, v21.4h // +t3 + sub v26.4h, v16.4h, v1.4h // t8/2 = t1/2 - t3/2 + add v1.4h, v16.4h, v1.4h // t5/2 = t1/2 + t3/2 + neg v16.4h, v19.4h // -t1 + neg v27.4h, v2.4h // +t4 + ssra v20.4h, v19.4h, #1 // (t5 + t1) >> 1 + srsra v0.4h, v2.4h, #1 // (t8 - t4 + 1) >> 1 + ssra v18.4h, v23.4h, #1 // (t6 + t2) >> 1 + srsra v22.4h, v21.4h, #1 // (t7 - t3 + 1) >> 1 + ssra v25.4h, v17.4h, #1 // (t7 + t3) >> 1 + srsra v3.4h, v24.4h, #1 // (t6 - t2 + 1) >> 1 + ssra v26.4h, v27.4h, #1 // (t8 + t4) >> 1 + srsra v1.4h, v16.4h, #1 // (t5 - t1 + 1) >> 1 + trn1 v0.2d, v20.2d, v0.2d + trn1 v2.2d, v18.2d, v22.2d + trn1 v3.2d, v25.2d, v3.2d + trn1 v1.2d, v26.2d, v1.2d + srshr v0.8h, v0.8h, #6 // (t5 + t1 + 64) >> 7, (t8 - t4 + 65) >> 7 + srshr v2.8h, v2.8h, #6 // (t6 + t2 + 64) >> 7, (t7 - t3 + 65) >> 7 + srshr v3.8h, v3.8h, #6 // (t7 + t3 + 64) >> 7, (t6 - t2 + 65) >> 7 + srshr v1.8h, v1.8h, #6 // (t8 + t4 + 64) >> 7, (t5 - t1 + 65) >> 7 + uaddw v0.8h, v0.8h, v5.8b + uaddw v2.8h, v2.8h, v6.8b + uaddw v3.8h, v3.8h, v7.8b + uaddw v1.8h, v1.8h, v4.8b + sqxtun v0.8b, v0.8h + sqxtun v2.8b, v2.8h + sqxtun v3.8b, v3.8h + sqxtun v1.8b, v1.8h + st1 {v0.s}[0], [x4], x1 + st1 {v2.s}[0], [x4], x1 + st1 {v3.s}[0], [x4], x1 + st1 {v1.s}[0], [x4], x1 + st1 {v0.s}[1], [x4], x1 + st1 {v2.s}[1], [x4], x1 + st1 {v3.s}[1], [x4], x1 + st1 {v1.s}[1], [x4] + ret +endfunc + +// VC-1 4x4 inverse transform +// On entry: +// x0 -> array of 8-bit samples, in row-major order +// x1 = row stride for 8-bit sample array +// x2 -> array of 16-bit inverse transform coefficients, in row-major order (row stride is 8 coefficients) +// On exit: +// array at x0 updated by saturated addition of (narrowed) transformed block +function ff_vc1_inv_trans_4x4_neon, export=1 + mov x3, #16 + ldr d0, .Lcoeffs_it4 + mov x4, x0 + ld1 {v1.d}[0], [x2], x3 // 00 01 02 03 + ld1 {v2.d}[0], [x2], x3 // 10 11 12 13 + ld1 {v3.d}[0], [x2], x3 // 20 21 22 23 + ld1 {v4.d}[0], [x2] // 30 31 32 33 + ld1 {v5.s}[0], [x0], x1 + ld1 {v5.s}[1], [x0], x1 + ld1 {v6.s}[0], [x0], x1 + trn2 v7.4h, v1.4h, v2.4h // 01 11 03 13 + trn1 v1.4h, v1.4h, v2.4h // 00 10 02 12 + ld1 {v6.s}[1], [x0] + trn2 v2.4h, v3.4h, v4.4h // 21 31 23 33 + trn1 v3.4h, v3.4h, v4.4h // 20 30 22 32 + trn2 v4.2s, v7.2s, v2.2s // 03 13 23 33 + trn1 v16.2s, v1.2s, v3.2s // 00 10 20 30 + trn1 v2.2s, v7.2s, v2.2s // 01 11 21 31 + trn2 v1.2s, v1.2s, v3.2s // 02 12 22 32 + mul v3.4h, v4.4h, v0.h[0] // 10/2 * src[3] + mul v4.4h, v4.4h, v0.h[1] // 22/2 * src[3] + mul v7.4h, v16.4h, v0.h[2] // 17 * src[0] + mul v1.4h, v1.4h, v0.h[2] // 17 * src[2] + mla v3.4h, v2.4h, v0.h[1] // t3/2 = 22/2 * src[1] + 10/2 * src[3] + mls v4.4h, v2.4h, v0.h[0] // t4/2 = - 10/2 * src[1] + 22/2 * src[3] + add v2.4h, v7.4h, v1.4h // t1 = 17 * src[0] + 17 * src[2] + sub v1.4h, v7.4h, v1.4h // t2 = 17 * src[0] - 17 * src[2] + neg v7.4h, v3.4h // -t3/2 + neg v16.4h, v4.4h // -t4/2 + ssra v3.4h, v2.4h, #1 // (t1 + t3) >> 1 + ssra v4.4h, v1.4h, #1 // (t2 + t4) >> 1 + ssra v16.4h, v1.4h, #1 // (t2 - t4) >> 1 + ssra v7.4h, v2.4h, #1 // (t1 - t3) >> 1 + srshr v1.4h, v3.4h, #2 // (t1 + t3 + 64) >> 3 + srshr v2.4h, v4.4h, #2 // (t2 + t4 + 64) >> 3 + srshr v3.4h, v16.4h, #2 // (t2 - t4 + 64) >> 3 + srshr v4.4h, v7.4h, #2 // (t1 - t3 + 64) >> 3 + trn2 v7.4h, v1.4h, v3.4h // 10 11 30 31 + trn1 v1.4h, v1.4h, v3.4h // 00 01 20 21 + trn2 v3.4h, v2.4h, v4.4h // 12 13 32 33 + trn1 v2.4h, v2.4h, v4.4h // 02 03 22 23 + trn2 v4.2s, v7.2s, v3.2s // 30 31 32 33 + trn1 v16.2s, v1.2s, v2.2s // 00 01 02 03 + trn1 v3.2s, v7.2s, v3.2s // 10 11 12 13 + trn2 v1.2s, v1.2s, v2.2s // 20 21 22 23 + mul v2.4h, v4.4h, v0.h[1] // 22/2 * src[24] + mul v4.4h, v4.4h, v0.h[0] // 10/2 * src[24] + mul v7.4h, v16.4h, v0.h[2] // 17 * src[0] + mul v1.4h, v1.4h, v0.h[2] // 17 * src[16] + mls v2.4h, v3.4h, v0.h[0] // t4/2 = - 10/2 * src[8] + 22/2 * src[24] + mla v4.4h, v3.4h, v0.h[1] // t3/2 = 22/2 * src[8] + 10/2 * src[24] + add v0.4h, v7.4h, v1.4h // t1 = 17 * src[0] + 17 * src[16] + sub v1.4h, v7.4h, v1.4h // t2 = 17 * src[0] - 17 * src[16] + neg v3.4h, v2.4h // -t4/2 + neg v7.4h, v4.4h // -t3/2 + ssra v4.4h, v0.4h, #1 // (t1 + t3) >> 1 + ssra v3.4h, v1.4h, #1 // (t2 - t4) >> 1 + ssra v2.4h, v1.4h, #1 // (t2 + t4) >> 1 + ssra v7.4h, v0.4h, #1 // (t1 - t3) >> 1 + trn1 v0.2d, v4.2d, v3.2d + trn1 v1.2d, v2.2d, v7.2d + srshr v0.8h, v0.8h, #6 // (t1 + t3 + 64) >> 7, (t2 - t4 + 64) >> 7 + srshr v1.8h, v1.8h, #6 // (t2 + t4 + 64) >> 7, (t1 - t3 + 64) >> 7 + uaddw v0.8h, v0.8h, v5.8b + uaddw v1.8h, v1.8h, v6.8b + sqxtun v0.8b, v0.8h + sqxtun v1.8b, v1.8h + st1 {v0.s}[0], [x4], x1 + st1 {v0.s}[1], [x4], x1 + st1 {v1.s}[0], [x4], x1 + st1 {v1.s}[1], [x4] + ret +endfunc + +// VC-1 8x8 inverse transform, DC case +// On entry: +// x0 -> array of 8-bit samples, in row-major order +// x1 = row stride for 8-bit sample array +// x2 -> 16-bit inverse transform DC coefficient +// On exit: +// array at x0 updated by saturated addition of (narrowed) transformed block +function ff_vc1_inv_trans_8x8_dc_neon, export=1 + ldrsh w2, [x2] + mov x3, x0 + ld1 {v0.8b}, [x0], x1 + ld1 {v1.8b}, [x0], x1 + ld1 {v2.8b}, [x0], x1 + add w2, w2, w2, lsl #1 + ld1 {v3.8b}, [x0], x1 + ld1 {v4.8b}, [x0], x1 + add w2, w2, #1 + ld1 {v5.8b}, [x0], x1 + asr w2, w2, #1 + ld1 {v6.8b}, [x0], x1 + add w2, w2, w2, lsl #1 + ld1 {v7.8b}, [x0] + add w0, w2, #16 + asr w0, w0, #5 + dup v16.8h, w0 + uaddw v0.8h, v16.8h, v0.8b + uaddw v1.8h, v16.8h, v1.8b + uaddw v2.8h, v16.8h, v2.8b + uaddw v3.8h, v16.8h, v3.8b + uaddw v4.8h, v16.8h, v4.8b + uaddw v5.8h, v16.8h, v5.8b + sqxtun v0.8b, v0.8h + uaddw v6.8h, v16.8h, v6.8b + sqxtun v1.8b, v1.8h + uaddw v7.8h, v16.8h, v7.8b + sqxtun v2.8b, v2.8h + sqxtun v3.8b, v3.8h + sqxtun v4.8b, v4.8h + st1 {v0.8b}, [x3], x1 + sqxtun v0.8b, v5.8h + st1 {v1.8b}, [x3], x1 + sqxtun v1.8b, v6.8h + st1 {v2.8b}, [x3], x1 + sqxtun v2.8b, v7.8h + st1 {v3.8b}, [x3], x1 + st1 {v4.8b}, [x3], x1 + st1 {v0.8b}, [x3], x1 + st1 {v1.8b}, [x3], x1 + st1 {v2.8b}, [x3] + ret +endfunc + +// VC-1 8x4 inverse transform, DC case +// On entry: +// x0 -> array of 8-bit samples, in row-major order +// x1 = row stride for 8-bit sample array +// x2 -> 16-bit inverse transform DC coefficient +// On exit: +// array at x0 updated by saturated addition of (narrowed) transformed block +function ff_vc1_inv_trans_8x4_dc_neon, export=1 + ldrsh w2, [x2] + mov x3, x0 + ld1 {v0.8b}, [x0], x1 + ld1 {v1.8b}, [x0], x1 + ld1 {v2.8b}, [x0], x1 + add w2, w2, w2, lsl #1 + ld1 {v3.8b}, [x0] + add w0, w2, #1 + asr w0, w0, #1 + add w0, w0, w0, lsl #4 + add w0, w0, #64 + asr w0, w0, #7 + dup v4.8h, w0 + uaddw v0.8h, v4.8h, v0.8b + uaddw v1.8h, v4.8h, v1.8b + uaddw v2.8h, v4.8h, v2.8b + uaddw v3.8h, v4.8h, v3.8b + sqxtun v0.8b, v0.8h + sqxtun v1.8b, v1.8h + sqxtun v2.8b, v2.8h + sqxtun v3.8b, v3.8h + st1 {v0.8b}, [x3], x1 + st1 {v1.8b}, [x3], x1 + st1 {v2.8b}, [x3], x1 + st1 {v3.8b}, [x3] + ret +endfunc + +// VC-1 4x8 inverse transform, DC case +// On entry: +// x0 -> array of 8-bit samples, in row-major order +// x1 = row stride for 8-bit sample array +// x2 -> 16-bit inverse transform DC coefficient +// On exit: +// array at x0 updated by saturated addition of (narrowed) transformed block +function ff_vc1_inv_trans_4x8_dc_neon, export=1 + ldrsh w2, [x2] + mov x3, x0 + ld1 {v0.s}[0], [x0], x1 + ld1 {v1.s}[0], [x0], x1 + ld1 {v2.s}[0], [x0], x1 + add w2, w2, w2, lsl #4 + ld1 {v3.s}[0], [x0], x1 + add w2, w2, #4 + asr w2, w2, #3 + add w2, w2, w2, lsl #1 + ld1 {v0.s}[1], [x0], x1 + add w2, w2, #16 + asr w2, w2, #5 + dup v4.8h, w2 + ld1 {v1.s}[1], [x0], x1 + ld1 {v2.s}[1], [x0], x1 + ld1 {v3.s}[1], [x0] + uaddw v0.8h, v4.8h, v0.8b + uaddw v1.8h, v4.8h, v1.8b + uaddw v2.8h, v4.8h, v2.8b + uaddw v3.8h, v4.8h, v3.8b + sqxtun v0.8b, v0.8h + sqxtun v1.8b, v1.8h + sqxtun v2.8b, v2.8h + sqxtun v3.8b, v3.8h + st1 {v0.s}[0], [x3], x1 + st1 {v1.s}[0], [x3], x1 + st1 {v2.s}[0], [x3], x1 + st1 {v3.s}[0], [x3], x1 + st1 {v0.s}[1], [x3], x1 + st1 {v1.s}[1], [x3], x1 + st1 {v2.s}[1], [x3], x1 + st1 {v3.s}[1], [x3] + ret +endfunc + +// VC-1 4x4 inverse transform, DC case +// On entry: +// x0 -> array of 8-bit samples, in row-major order +// x1 = row stride for 8-bit sample array +// x2 -> 16-bit inverse transform DC coefficient +// On exit: +// array at x0 updated by saturated addition of (narrowed) transformed block +function ff_vc1_inv_trans_4x4_dc_neon, export=1 + ldrsh w2, [x2] + mov x3, x0 + ld1 {v0.s}[0], [x0], x1 + ld1 {v1.s}[0], [x0], x1 + ld1 {v0.s}[1], [x0], x1 + add w2, w2, w2, lsl #4 + ld1 {v1.s}[1], [x0] + add w0, w2, #4 + asr w0, w0, #3 + add w0, w0, w0, lsl #4 + add w0, w0, #64 + asr w0, w0, #7 + dup v2.8h, w0 + uaddw v0.8h, v2.8h, v0.8b + uaddw v1.8h, v2.8h, v1.8b + sqxtun v0.8b, v0.8h + sqxtun v1.8b, v1.8h + st1 {v0.s}[0], [x3], x1 + st1 {v1.s}[0], [x3], x1 + st1 {v0.s}[1], [x3], x1 + st1 {v1.s}[1], [x3] + ret +endfunc + +.align 5 +.Lcoeffs_it8: +.quad 0x000F00090003 +.Lcoeffs_it4: +.quad 0x0011000B0005 +.Lcoeffs: +.quad 0x00050002 + +// VC-1 in-loop deblocking filter for 4 pixel pairs at boundary of vertically-neighbouring blocks +// On entry: +// x0 -> top-left pel of lower block +// x1 = row stride, bytes +// w2 = PQUANT bitstream parameter +function ff_vc1_v_loop_filter4_neon, export=1 + sub x3, x0, w1, sxtw #2 + ldr d0, .Lcoeffs + ld1 {v1.s}[0], [x0], x1 // P5 + ld1 {v2.s}[0], [x3], x1 // P1 + ld1 {v3.s}[0], [x3], x1 // P2 + ld1 {v4.s}[0], [x0], x1 // P6 + ld1 {v5.s}[0], [x3], x1 // P3 + ld1 {v6.s}[0], [x0], x1 // P7 + ld1 {v7.s}[0], [x3] // P4 + ld1 {v16.s}[0], [x0] // P8 + ushll v17.8h, v1.8b, #1 // 2*P5 + dup v18.8h, w2 // pq + ushll v2.8h, v2.8b, #1 // 2*P1 + uxtl v3.8h, v3.8b // P2 + uxtl v4.8h, v4.8b // P6 + uxtl v19.8h, v5.8b // P3 + mls v2.4h, v3.4h, v0.h[1] // 2*P1-5*P2 + uxtl v3.8h, v6.8b // P7 + mls v17.4h, v4.4h, v0.h[1] // 2*P5-5*P6 + ushll v5.8h, v5.8b, #1 // 2*P3 + uxtl v6.8h, v7.8b // P4 + mla v17.4h, v3.4h, v0.h[1] // 2*P5-5*P6+5*P7 + uxtl v3.8h, v16.8b // P8 + mla v2.4h, v19.4h, v0.h[1] // 2*P1-5*P2+5*P3 + uxtl v1.8h, v1.8b // P5 + mls v5.4h, v6.4h, v0.h[1] // 2*P3-5*P4 + mls v17.4h, v3.4h, v0.h[0] // 2*P5-5*P6+5*P7-2*P8 + sub v3.4h, v6.4h, v1.4h // P4-P5 + mls v2.4h, v6.4h, v0.h[0] // 2*P1-5*P2+5*P3-2*P4 + mla v5.4h, v1.4h, v0.h[1] // 2*P3-5*P4+5*P5 + mls v5.4h, v4.4h, v0.h[0] // 2*P3-5*P4+5*P5-2*P6 + abs v4.4h, v3.4h + srshr v7.4h, v17.4h, #3 + srshr v2.4h, v2.4h, #3 + sshr v4.4h, v4.4h, #1 // clip + srshr v5.4h, v5.4h, #3 + abs v7.4h, v7.4h // a2 + sshr v3.4h, v3.4h, #8 // clip_sign + abs v2.4h, v2.4h // a1 + cmeq v16.4h, v4.4h, #0 // test clip == 0 + abs v17.4h, v5.4h // a0 + sshr v5.4h, v5.4h, #8 // a0_sign + cmhs v19.4h, v2.4h, v7.4h // test a1 >= a2 + cmhs v18.4h, v17.4h, v18.4h // test a0 >= pq + sub v3.4h, v3.4h, v5.4h // clip_sign - a0_sign + bsl v19.8b, v7.8b, v2.8b // a3 + orr v2.8b, v16.8b, v18.8b // test clip == 0 || a0 >= pq + uqsub v5.4h, v17.4h, v19.4h // a0 >= a3 ? a0-a3 : 0 (a0 > a3 in all cases where filtering is enabled, so makes more sense to subtract this way round than the opposite and then taking the abs) + cmhs v7.4h, v19.4h, v17.4h // test a3 >= a0 + mul v0.4h, v5.4h, v0.h[1] // a0 >= a3 ? 5*(a0-a3) : 0 + orr v5.8b, v2.8b, v7.8b // test clip == 0 || a0 >= pq || a3 >= a0 + mov w0, v5.s[1] // move to gp reg + ushr v0.4h, v0.4h, #3 // a0 >= a3 ? (5*(a0-a3))>>3 : 0 + cmhs v5.4h, v0.4h, v4.4h + tbnz w0, #0, 1f // none of the 4 pixel pairs should be updated if this one is not filtered + bsl v5.8b, v4.8b, v0.8b // FFMIN(d, clip) + bic v0.8b, v5.8b, v2.8b // set each d to zero if it should not be filtered because clip == 0 || a0 >= pq (a3 > a0 case already zeroed by saturating sub) + mls v6.4h, v0.4h, v3.4h // invert d depending on clip_sign & a0_sign, or zero it if they match, and accumulate into P4 + mla v1.4h, v0.4h, v3.4h // invert d depending on clip_sign & a0_sign, or zero it if they match, and accumulate into P5 + sqxtun v0.8b, v6.8h + sqxtun v1.8b, v1.8h + st1 {v0.s}[0], [x3], x1 + st1 {v1.s}[0], [x3] +1: ret +endfunc + +// VC-1 in-loop deblocking filter for 4 pixel pairs at boundary of horizontally-neighbouring blocks +// On entry: +// x0 -> top-left pel of right block +// x1 = row stride, bytes +// w2 = PQUANT bitstream parameter +function ff_vc1_h_loop_filter4_neon, export=1 + sub x3, x0, #4 // where to start reading + ldr d0, .Lcoeffs + ld1 {v1.8b}, [x3], x1 + sub x0, x0, #1 // where to start writing + ld1 {v2.8b}, [x3], x1 + ld1 {v3.8b}, [x3], x1 + ld1 {v4.8b}, [x3] + dup v5.8h, w2 // pq + trn1 v6.8b, v1.8b, v2.8b + trn2 v1.8b, v1.8b, v2.8b + trn1 v2.8b, v3.8b, v4.8b + trn2 v3.8b, v3.8b, v4.8b + trn1 v4.4h, v6.4h, v2.4h // P1, P5 + trn1 v7.4h, v1.4h, v3.4h // P2, P6 + trn2 v2.4h, v6.4h, v2.4h // P3, P7 + trn2 v1.4h, v1.4h, v3.4h // P4, P8 + ushll v3.8h, v4.8b, #1 // 2*P1, 2*P5 + uxtl v6.8h, v7.8b // P2, P6 + uxtl v7.8h, v2.8b // P3, P7 + uxtl v1.8h, v1.8b // P4, P8 + mls v3.8h, v6.8h, v0.h[1] // 2*P1-5*P2, 2*P5-5*P6 + ushll v2.8h, v2.8b, #1 // 2*P3, 2*P7 + uxtl v4.8h, v4.8b // P1, P5 + mla v3.8h, v7.8h, v0.h[1] // 2*P1-5*P2+5*P3, 2*P5-5*P6+5*P7 + mov d6, v6.d[1] // P6 + mls v3.8h, v1.8h, v0.h[0] // 2*P1-5*P2+5*P3-2*P4, 2*P5-5*P6+5*P7-2*P8 + mov d4, v4.d[1] // P5 + mls v2.4h, v1.4h, v0.h[1] // 2*P3-5*P4 + mla v2.4h, v4.4h, v0.h[1] // 2*P3-5*P4+5*P5 + sub v7.4h, v1.4h, v4.4h // P4-P5 + mls v2.4h, v6.4h, v0.h[0] // 2*P3-5*P4+5*P5-2*P6 + srshr v3.8h, v3.8h, #3 + abs v6.4h, v7.4h + sshr v7.4h, v7.4h, #8 // clip_sign + srshr v2.4h, v2.4h, #3 + abs v3.8h, v3.8h // a1, a2 + sshr v6.4h, v6.4h, #1 // clip + mov d16, v3.d[1] // a2 + abs v17.4h, v2.4h // a0 + cmeq v18.4h, v6.4h, #0 // test clip == 0 + sshr v2.4h, v2.4h, #8 // a0_sign + cmhs v19.4h, v3.4h, v16.4h // test a1 >= a2 + cmhs v5.4h, v17.4h, v5.4h // test a0 >= pq + sub v2.4h, v7.4h, v2.4h // clip_sign - a0_sign + bsl v19.8b, v16.8b, v3.8b // a3 + orr v3.8b, v18.8b, v5.8b // test clip == 0 || a0 >= pq + uqsub v5.4h, v17.4h, v19.4h // a0 >= a3 ? a0-a3 : 0 (a0 > a3 in all cases where filtering is enabled, so makes more sense to subtract this way round than the opposite and then taking the abs) + cmhs v7.4h, v19.4h, v17.4h // test a3 >= a0 + mul v0.4h, v5.4h, v0.h[1] // a0 >= a3 ? 5*(a0-a3) : 0 + orr v5.8b, v3.8b, v7.8b // test clip == 0 || a0 >= pq || a3 >= a0 + mov w2, v5.s[1] // move to gp reg + ushr v0.4h, v0.4h, #3 // a0 >= a3 ? (5*(a0-a3))>>3 : 0 + cmhs v5.4h, v0.4h, v6.4h + tbnz w2, #0, 1f // none of the 4 pixel pairs should be updated if this one is not filtered + bsl v5.8b, v6.8b, v0.8b // FFMIN(d, clip) + bic v0.8b, v5.8b, v3.8b // set each d to zero if it should not be filtered because clip == 0 || a0 >= pq (a3 > a0 case already zeroed by saturating sub) + mla v4.4h, v0.4h, v2.4h // invert d depending on clip_sign & a0_sign, or zero it if they match, and accumulate into P5 + mls v1.4h, v0.4h, v2.4h // invert d depending on clip_sign & a0_sign, or zero it if they match, and accumulate into P4 + sqxtun v3.8b, v4.8h + sqxtun v2.8b, v1.8h + st2 {v2.b, v3.b}[0], [x0], x1 + st2 {v2.b, v3.b}[1], [x0], x1 + st2 {v2.b, v3.b}[2], [x0], x1 + st2 {v2.b, v3.b}[3], [x0] +1: ret +endfunc + +// VC-1 in-loop deblocking filter for 8 pixel pairs at boundary of vertically-neighbouring blocks +// On entry: +// x0 -> top-left pel of lower block +// x1 = row stride, bytes +// w2 = PQUANT bitstream parameter +function ff_vc1_v_loop_filter8_neon, export=1 + sub x3, x0, w1, sxtw #2 + ldr d0, .Lcoeffs + ld1 {v1.8b}, [x0], x1 // P5 + movi v2.2d, #0x0000ffff00000000 + ld1 {v3.8b}, [x3], x1 // P1 + ld1 {v4.8b}, [x3], x1 // P2 + ld1 {v5.8b}, [x0], x1 // P6 + ld1 {v6.8b}, [x3], x1 // P3 + ld1 {v7.8b}, [x0], x1 // P7 + ushll v16.8h, v1.8b, #1 // 2*P5 + ushll v3.8h, v3.8b, #1 // 2*P1 + ld1 {v17.8b}, [x3] // P4 + uxtl v4.8h, v4.8b // P2 + ld1 {v18.8b}, [x0] // P8 + uxtl v5.8h, v5.8b // P6 + dup v19.8h, w2 // pq + uxtl v20.8h, v6.8b // P3 + mls v3.8h, v4.8h, v0.h[1] // 2*P1-5*P2 + uxtl v4.8h, v7.8b // P7 + ushll v6.8h, v6.8b, #1 // 2*P3 + mls v16.8h, v5.8h, v0.h[1] // 2*P5-5*P6 + uxtl v7.8h, v17.8b // P4 + uxtl v17.8h, v18.8b // P8 + mla v16.8h, v4.8h, v0.h[1] // 2*P5-5*P6+5*P7 + uxtl v1.8h, v1.8b // P5 + mla v3.8h, v20.8h, v0.h[1] // 2*P1-5*P2+5*P3 + sub v4.8h, v7.8h, v1.8h // P4-P5 + mls v6.8h, v7.8h, v0.h[1] // 2*P3-5*P4 + mls v16.8h, v17.8h, v0.h[0] // 2*P5-5*P6+5*P7-2*P8 + abs v17.8h, v4.8h + sshr v4.8h, v4.8h, #8 // clip_sign + mls v3.8h, v7.8h, v0.h[0] // 2*P1-5*P2+5*P3-2*P4 + sshr v17.8h, v17.8h, #1 // clip + mla v6.8h, v1.8h, v0.h[1] // 2*P3-5*P4+5*P5 + srshr v16.8h, v16.8h, #3 + mls v6.8h, v5.8h, v0.h[0] // 2*P3-5*P4+5*P5-2*P6 + cmeq v5.8h, v17.8h, #0 // test clip == 0 + srshr v3.8h, v3.8h, #3 + abs v16.8h, v16.8h // a2 + abs v3.8h, v3.8h // a1 + srshr v6.8h, v6.8h, #3 + cmhs v18.8h, v3.8h, v16.8h // test a1 >= a2 + abs v20.8h, v6.8h // a0 + sshr v6.8h, v6.8h, #8 // a0_sign + bsl v18.16b, v16.16b, v3.16b // a3 + cmhs v3.8h, v20.8h, v19.8h // test a0 >= pq + sub v4.8h, v4.8h, v6.8h // clip_sign - a0_sign + uqsub v6.8h, v20.8h, v18.8h // a0 >= a3 ? a0-a3 : 0 (a0 > a3 in all cases where filtering is enabled, so makes more sense to subtract this way round than the opposite and then taking the abs) + cmhs v16.8h, v18.8h, v20.8h // test a3 >= a0 + orr v3.16b, v5.16b, v3.16b // test clip == 0 || a0 >= pq + mul v0.8h, v6.8h, v0.h[1] // a0 >= a3 ? 5*(a0-a3) : 0 + orr v5.16b, v3.16b, v16.16b // test clip == 0 || a0 >= pq || a3 >= a0 + cmtst v2.2d, v5.2d, v2.2d // if 2nd of each group of is not filtered, then none of the others in the group should be either + mov w0, v5.s[1] // move to gp reg + ushr v0.8h, v0.8h, #3 // a0 >= a3 ? (5*(a0-a3))>>3 : 0 + mov w2, v5.s[3] + orr v2.16b, v3.16b, v2.16b + cmhs v3.8h, v0.8h, v17.8h + and w0, w0, w2 + bsl v3.16b, v17.16b, v0.16b // FFMIN(d, clip) + tbnz w0, #0, 1f // none of the 8 pixel pairs should be updated in this case + bic v0.16b, v3.16b, v2.16b // set each d to zero if it should not be filtered + mls v7.8h, v0.8h, v4.8h // invert d depending on clip_sign & a0_sign, or zero it if they match, and accumulate into P4 + mla v1.8h, v0.8h, v4.8h // invert d depending on clip_sign & a0_sign, or zero it if they match, and accumulate into P5 + sqxtun v0.8b, v7.8h + sqxtun v1.8b, v1.8h + st1 {v0.8b}, [x3], x1 + st1 {v1.8b}, [x3] +1: ret +endfunc + +// VC-1 in-loop deblocking filter for 8 pixel pairs at boundary of horizontally-neighbouring blocks +// On entry: +// x0 -> top-left pel of right block +// x1 = row stride, bytes +// w2 = PQUANT bitstream parameter +function ff_vc1_h_loop_filter8_neon, export=1 + sub x3, x0, #4 // where to start reading + ldr d0, .Lcoeffs + ld1 {v1.8b}, [x3], x1 // P1[0], P2[0]... + sub x0, x0, #1 // where to start writing + ld1 {v2.8b}, [x3], x1 + add x4, x0, x1, lsl #2 + ld1 {v3.8b}, [x3], x1 + ld1 {v4.8b}, [x3], x1 + ld1 {v5.8b}, [x3], x1 + ld1 {v6.8b}, [x3], x1 + ld1 {v7.8b}, [x3], x1 + trn1 v16.8b, v1.8b, v2.8b // P1[0], P1[1], P3[0]... + ld1 {v17.8b}, [x3] + trn2 v1.8b, v1.8b, v2.8b // P2[0], P2[1], P4[0]... + trn1 v2.8b, v3.8b, v4.8b // P1[2], P1[3], P3[2]... + trn2 v3.8b, v3.8b, v4.8b // P2[2], P2[3], P4[2]... + dup v4.8h, w2 // pq + trn1 v18.8b, v5.8b, v6.8b // P1[4], P1[5], P3[4]... + trn2 v5.8b, v5.8b, v6.8b // P2[4], P2[5], P4[4]... + trn1 v6.4h, v16.4h, v2.4h // P1[0], P1[1], P1[2], P1[3], P5[0]... + trn1 v19.4h, v1.4h, v3.4h // P2[0], P2[1], P2[2], P2[3], P6[0]... + trn1 v20.8b, v7.8b, v17.8b // P1[6], P1[7], P3[6]... + trn2 v7.8b, v7.8b, v17.8b // P2[6], P2[7], P4[6]... + trn2 v2.4h, v16.4h, v2.4h // P3[0], P3[1], P3[2], P3[3], P7[0]... + trn2 v1.4h, v1.4h, v3.4h // P4[0], P4[1], P4[2], P4[3], P8[0]... + trn1 v3.4h, v18.4h, v20.4h // P1[4], P1[5], P1[6], P1[7], P5[4]... + trn1 v16.4h, v5.4h, v7.4h // P2[4], P2[5], P2[6], P2[7], P6[4]... + trn2 v17.4h, v18.4h, v20.4h // P3[4], P3[5], P3[6], P3[7], P7[4]... + trn2 v5.4h, v5.4h, v7.4h // P4[4], P4[5], P4[6], P4[7], P8[4]... + trn1 v7.2s, v6.2s, v3.2s // P1 + trn1 v18.2s, v19.2s, v16.2s // P2 + trn2 v3.2s, v6.2s, v3.2s // P5 + trn2 v6.2s, v19.2s, v16.2s // P6 + trn1 v16.2s, v2.2s, v17.2s // P3 + trn2 v2.2s, v2.2s, v17.2s // P7 + ushll v7.8h, v7.8b, #1 // 2*P1 + trn1 v17.2s, v1.2s, v5.2s // P4 + ushll v19.8h, v3.8b, #1 // 2*P5 + trn2 v1.2s, v1.2s, v5.2s // P8 + uxtl v5.8h, v18.8b // P2 + uxtl v6.8h, v6.8b // P6 + uxtl v18.8h, v16.8b // P3 + mls v7.8h, v5.8h, v0.h[1] // 2*P1-5*P2 + uxtl v2.8h, v2.8b // P7 + ushll v5.8h, v16.8b, #1 // 2*P3 + mls v19.8h, v6.8h, v0.h[1] // 2*P5-5*P6 + uxtl v16.8h, v17.8b // P4 + uxtl v1.8h, v1.8b // P8 + mla v19.8h, v2.8h, v0.h[1] // 2*P5-5*P6+5*P7 + uxtl v2.8h, v3.8b // P5 + mla v7.8h, v18.8h, v0.h[1] // 2*P1-5*P2+5*P3 + sub v3.8h, v16.8h, v2.8h // P4-P5 + mls v5.8h, v16.8h, v0.h[1] // 2*P3-5*P4 + mls v19.8h, v1.8h, v0.h[0] // 2*P5-5*P6+5*P7-2*P8 + abs v1.8h, v3.8h + sshr v3.8h, v3.8h, #8 // clip_sign + mls v7.8h, v16.8h, v0.h[0] // 2*P1-5*P2+5*P3-2*P4 + sshr v1.8h, v1.8h, #1 // clip + mla v5.8h, v2.8h, v0.h[1] // 2*P3-5*P4+5*P5 + srshr v17.8h, v19.8h, #3 + mls v5.8h, v6.8h, v0.h[0] // 2*P3-5*P4+5*P5-2*P6 + cmeq v6.8h, v1.8h, #0 // test clip == 0 + srshr v7.8h, v7.8h, #3 + abs v17.8h, v17.8h // a2 + abs v7.8h, v7.8h // a1 + srshr v5.8h, v5.8h, #3 + cmhs v18.8h, v7.8h, v17.8h // test a1 >= a2 + abs v19.8h, v5.8h // a0 + sshr v5.8h, v5.8h, #8 // a0_sign + bsl v18.16b, v17.16b, v7.16b // a3 + cmhs v4.8h, v19.8h, v4.8h // test a0 >= pq + sub v3.8h, v3.8h, v5.8h // clip_sign - a0_sign + uqsub v5.8h, v19.8h, v18.8h // a0 >= a3 ? a0-a3 : 0 (a0 > a3 in all cases where filtering is enabled, so makes more sense to subtract this way round than the opposite and then taking the abs) + cmhs v7.8h, v18.8h, v19.8h // test a3 >= a0 + orr v4.16b, v6.16b, v4.16b // test clip == 0 || a0 >= pq + mul v0.8h, v5.8h, v0.h[1] // a0 >= a3 ? 5*(a0-a3) : 0 + orr v5.16b, v4.16b, v7.16b // test clip == 0 || a0 >= pq || a3 >= a0 + mov w2, v5.s[1] // move to gp reg + ushr v0.8h, v0.8h, #3 // a0 >= a3 ? (5*(a0-a3))>>3 : 0 + mov w3, v5.s[3] + cmhs v5.8h, v0.8h, v1.8h + and w5, w2, w3 + bsl v5.16b, v1.16b, v0.16b // FFMIN(d, clip) + tbnz w5, #0, 2f // none of the 8 pixel pairs should be updated in this case + bic v0.16b, v5.16b, v4.16b // set each d to zero if it should not be filtered because clip == 0 || a0 >= pq (a3 > a0 case already zeroed by saturating sub) + mla v2.8h, v0.8h, v3.8h // invert d depending on clip_sign & a0_sign, or zero it if they match, and accumulate into P5 + mls v16.8h, v0.8h, v3.8h // invert d depending on clip_sign & a0_sign, or zero it if they match, and accumulate into P4 + sqxtun v1.8b, v2.8h + sqxtun v0.8b, v16.8h + tbnz w2, #0, 1f // none of the first 4 pixel pairs should be updated if so + st2 {v0.b, v1.b}[0], [x0], x1 + st2 {v0.b, v1.b}[1], [x0], x1 + st2 {v0.b, v1.b}[2], [x0], x1 + st2 {v0.b, v1.b}[3], [x0] +1: tbnz w3, #0, 2f // none of the second 4 pixel pairs should be updated if so + st2 {v0.b, v1.b}[4], [x4], x1 + st2 {v0.b, v1.b}[5], [x4], x1 + st2 {v0.b, v1.b}[6], [x4], x1 + st2 {v0.b, v1.b}[7], [x4] +2: ret +endfunc + +// VC-1 in-loop deblocking filter for 16 pixel pairs at boundary of vertically-neighbouring blocks +// On entry: +// x0 -> top-left pel of lower block +// x1 = row stride, bytes +// w2 = PQUANT bitstream parameter +function ff_vc1_v_loop_filter16_neon, export=1 + sub x3, x0, w1, sxtw #2 + ldr d0, .Lcoeffs + ld1 {v1.16b}, [x0], x1 // P5 + movi v2.2d, #0x0000ffff00000000 + ld1 {v3.16b}, [x3], x1 // P1 + ld1 {v4.16b}, [x3], x1 // P2 + ld1 {v5.16b}, [x0], x1 // P6 + ld1 {v6.16b}, [x3], x1 // P3 + ld1 {v7.16b}, [x0], x1 // P7 + ushll v16.8h, v1.8b, #1 // 2*P5[0..7] + ushll v17.8h, v3.8b, #1 // 2*P1[0..7] + ld1 {v18.16b}, [x3] // P4 + uxtl v19.8h, v4.8b // P2[0..7] + ld1 {v20.16b}, [x0] // P8 + uxtl v21.8h, v5.8b // P6[0..7] + dup v22.8h, w2 // pq + ushll2 v3.8h, v3.16b, #1 // 2*P1[8..15] + mls v17.8h, v19.8h, v0.h[1] // 2*P1[0..7]-5*P2[0..7] + ushll2 v19.8h, v1.16b, #1 // 2*P5[8..15] + uxtl2 v4.8h, v4.16b // P2[8..15] + mls v16.8h, v21.8h, v0.h[1] // 2*P5[0..7]-5*P6[0..7] + uxtl2 v5.8h, v5.16b // P6[8..15] + uxtl v23.8h, v6.8b // P3[0..7] + uxtl v24.8h, v7.8b // P7[0..7] + mls v3.8h, v4.8h, v0.h[1] // 2*P1[8..15]-5*P2[8..15] + ushll v4.8h, v6.8b, #1 // 2*P3[0..7] + uxtl v25.8h, v18.8b // P4[0..7] + mls v19.8h, v5.8h, v0.h[1] // 2*P5[8..15]-5*P6[8..15] + uxtl2 v26.8h, v6.16b // P3[8..15] + mla v17.8h, v23.8h, v0.h[1] // 2*P1[0..7]-5*P2[0..7]+5*P3[0..7] + uxtl2 v7.8h, v7.16b // P7[8..15] + ushll2 v6.8h, v6.16b, #1 // 2*P3[8..15] + mla v16.8h, v24.8h, v0.h[1] // 2*P5[0..7]-5*P6[0..7]+5*P7[0..7] + uxtl2 v18.8h, v18.16b // P4[8..15] + uxtl v23.8h, v20.8b // P8[0..7] + mls v4.8h, v25.8h, v0.h[1] // 2*P3[0..7]-5*P4[0..7] + uxtl v24.8h, v1.8b // P5[0..7] + uxtl2 v20.8h, v20.16b // P8[8..15] + mla v3.8h, v26.8h, v0.h[1] // 2*P1[8..15]-5*P2[8..15]+5*P3[8..15] + uxtl2 v1.8h, v1.16b // P5[8..15] + sub v26.8h, v25.8h, v24.8h // P4[0..7]-P5[0..7] + mla v19.8h, v7.8h, v0.h[1] // 2*P5[8..15]-5*P6[8..15]+5*P7[8..15] + sub v7.8h, v18.8h, v1.8h // P4[8..15]-P5[8..15] + mls v6.8h, v18.8h, v0.h[1] // 2*P3[8..15]-5*P4[8..15] + abs v27.8h, v26.8h + sshr v26.8h, v26.8h, #8 // clip_sign[0..7] + mls v17.8h, v25.8h, v0.h[0] // 2*P1[0..7]-5*P2[0..7]+5*P3[0..7]-2*P4[0..7] + abs v28.8h, v7.8h + sshr v27.8h, v27.8h, #1 // clip[0..7] + mls v16.8h, v23.8h, v0.h[0] // 2*P5[0..7]-5*P6[0..7]+5*P7[0..7]-2*P8[0..7] + sshr v7.8h, v7.8h, #8 // clip_sign[8..15] + sshr v23.8h, v28.8h, #1 // clip[8..15] + mla v4.8h, v24.8h, v0.h[1] // 2*P3[0..7]-5*P4[0..7]+5*P5[0..7] + cmeq v28.8h, v27.8h, #0 // test clip[0..7] == 0 + srshr v17.8h, v17.8h, #3 + mls v3.8h, v18.8h, v0.h[0] // 2*P1[8..15]-5*P2[8..15]+5*P3[8..15]-2*P4[8..15] + cmeq v29.8h, v23.8h, #0 // test clip[8..15] == 0 + srshr v16.8h, v16.8h, #3 + mls v19.8h, v20.8h, v0.h[0] // 2*P5[8..15]-5*P6[8..15]+5*P7[8..15]-2*P8[8..15] + abs v17.8h, v17.8h // a1[0..7] + mla v6.8h, v1.8h, v0.h[1] // 2*P3[8..15]-5*P4[8..15]+5*P5[8..15] + srshr v3.8h, v3.8h, #3 + mls v4.8h, v21.8h, v0.h[0] // 2*P3[0..7]-5*P4[0..7]+5*P5[0..7]-2*P6[0..7] + abs v16.8h, v16.8h // a2[0..7] + srshr v19.8h, v19.8h, #3 + mls v6.8h, v5.8h, v0.h[0] // 2*P3[8..15]-5*P4[8..15]+5*P5[8..15]-2*P6[8..15] + cmhs v5.8h, v17.8h, v16.8h // test a1[0..7] >= a2[0..7] + abs v3.8h, v3.8h // a1[8..15] + srshr v4.8h, v4.8h, #3 + abs v19.8h, v19.8h // a2[8..15] + bsl v5.16b, v16.16b, v17.16b // a3[0..7] + srshr v6.8h, v6.8h, #3 + cmhs v16.8h, v3.8h, v19.8h // test a1[8..15] >= a2[8.15] + abs v17.8h, v4.8h // a0[0..7] + sshr v4.8h, v4.8h, #8 // a0_sign[0..7] + bsl v16.16b, v19.16b, v3.16b // a3[8..15] + uqsub v3.8h, v17.8h, v5.8h // a0[0..7] >= a3[0..7] ? a0[0..7]-a3[0..7] : 0 (a0 > a3 in all cases where filtering is enabled, so makes more sense to subtract this way round than the opposite and then taking the abs) + abs v19.8h, v6.8h // a0[8..15] + cmhs v20.8h, v17.8h, v22.8h // test a0[0..7] >= pq + cmhs v5.8h, v5.8h, v17.8h // test a3[0..7] >= a0[0..7] + sub v4.8h, v26.8h, v4.8h // clip_sign[0..7] - a0_sign[0..7] + sshr v6.8h, v6.8h, #8 // a0_sign[8..15] + mul v3.8h, v3.8h, v0.h[1] // a0[0..7] >= a3[0..7] ? 5*(a0[0..7]-a3[0..7]) : 0 + uqsub v17.8h, v19.8h, v16.8h // a0[8..15] >= a3[8..15] ? a0[8..15]-a3[8..15] : 0 (a0 > a3 in all cases where filtering is enabled, so makes more sense to subtract this way round than the opposite and then taking the abs) + orr v20.16b, v28.16b, v20.16b // test clip[0..7] == 0 || a0[0..7] >= pq + cmhs v21.8h, v19.8h, v22.8h // test a0[8..15] >= pq + cmhs v16.8h, v16.8h, v19.8h // test a3[8..15] >= a0[8..15] + mul v0.8h, v17.8h, v0.h[1] // a0[8..15] >= a3[8..15] ? 5*(a0[8..15]-a3[8..15]) : 0 + sub v6.8h, v7.8h, v6.8h // clip_sign[8..15] - a0_sign[8..15] + orr v5.16b, v20.16b, v5.16b // test clip[0..7] == 0 || a0[0..7] >= pq || a3[0..7] >= a0[0..7] + ushr v3.8h, v3.8h, #3 // a0[0..7] >= a3[0..7] ? (5*(a0[0..7]-a3[0..7]))>>3 : 0 + orr v7.16b, v29.16b, v21.16b // test clip[8..15] == 0 || a0[8..15] >= pq + cmtst v17.2d, v5.2d, v2.2d // if 2nd of each group of is not filtered, then none of the others in the group should be either + mov w0, v5.s[1] // move to gp reg + cmhs v19.8h, v3.8h, v27.8h + ushr v0.8h, v0.8h, #3 // a0[8..15] >= a3[8..15] ? (5*(a0[8..15]-a3[8..15]))>>3 : 0 + mov w2, v5.s[3] + orr v5.16b, v7.16b, v16.16b // test clip[8..15] == 0 || a0[8..15] >= pq || a3[8..15] >= a0[8..15] + orr v16.16b, v20.16b, v17.16b + bsl v19.16b, v27.16b, v3.16b // FFMIN(d[0..7], clip[0..7]) + cmtst v2.2d, v5.2d, v2.2d + cmhs v3.8h, v0.8h, v23.8h + mov w4, v5.s[1] + mov w5, v5.s[3] + and w0, w0, w2 + bic v5.16b, v19.16b, v16.16b // set each d[0..7] to zero if it should not be filtered because clip[0..7] == 0 || a0[0..7] >= pq (a3 > a0 case already zeroed by saturating sub) + orr v2.16b, v7.16b, v2.16b + bsl v3.16b, v23.16b, v0.16b // FFMIN(d[8..15], clip[8..15]) + mls v25.8h, v5.8h, v4.8h // invert d[0..7] depending on clip_sign[0..7] & a0_sign[0..7], or zero it if they match, and accumulate into P4[0..7] + and w2, w4, w5 + bic v0.16b, v3.16b, v2.16b // set each d[8..15] to zero if it should not be filtered because clip[8..15] == 0 || a0[8..15] >= pq (a3 > a0 case already zeroed by saturating sub) + mla v24.8h, v5.8h, v4.8h // invert d[0..7] depending on clip_sign[0..7] & a0_sign[0..7], or zero it if they match, and accumulate into P5[0..7] + and w0, w0, w2 + mls v18.8h, v0.8h, v6.8h // invert d[8..15] depending on clip_sign[8..15] & a0_sign[8..15], or zero it if they match, and accumulate into P4[8..15] + sqxtun v2.8b, v25.8h + tbnz w0, #0, 1f // none of the 16 pixel pairs should be updated in this case + mla v1.8h, v0.8h, v6.8h // invert d[8..15] depending on clip_sign[8..15] & a0_sign[8..15], or zero it if they match, and accumulate into P5[8..15] + sqxtun v0.8b, v24.8h + sqxtun2 v2.16b, v18.8h + sqxtun2 v0.16b, v1.8h + st1 {v2.16b}, [x3], x1 + st1 {v0.16b}, [x3] +1: ret +endfunc + +// VC-1 in-loop deblocking filter for 16 pixel pairs at boundary of horizontally-neighbouring blocks +// On entry: +// x0 -> top-left pel of right block +// x1 = row stride, bytes +// w2 = PQUANT bitstream parameter +function ff_vc1_h_loop_filter16_neon, export=1 + sub x3, x0, #4 // where to start reading + ldr d0, .Lcoeffs + ld1 {v1.8b}, [x3], x1 // P1[0], P2[0]... + sub x0, x0, #1 // where to start writing + ld1 {v2.8b}, [x3], x1 + add x4, x0, x1, lsl #3 + ld1 {v3.8b}, [x3], x1 + add x5, x0, x1, lsl #2 + ld1 {v4.8b}, [x3], x1 + add x6, x4, x1, lsl #2 + ld1 {v5.8b}, [x3], x1 + ld1 {v6.8b}, [x3], x1 + ld1 {v7.8b}, [x3], x1 + trn1 v16.8b, v1.8b, v2.8b // P1[0], P1[1], P3[0]... + ld1 {v17.8b}, [x3], x1 + trn2 v1.8b, v1.8b, v2.8b // P2[0], P2[1], P4[0]... + ld1 {v2.8b}, [x3], x1 + trn1 v18.8b, v3.8b, v4.8b // P1[2], P1[3], P3[2]... + ld1 {v19.8b}, [x3], x1 + trn2 v3.8b, v3.8b, v4.8b // P2[2], P2[3], P4[2]... + ld1 {v4.8b}, [x3], x1 + trn1 v20.8b, v5.8b, v6.8b // P1[4], P1[5], P3[4]... + ld1 {v21.8b}, [x3], x1 + trn2 v5.8b, v5.8b, v6.8b // P2[4], P2[5], P4[4]... + ld1 {v6.8b}, [x3], x1 + trn1 v22.8b, v7.8b, v17.8b // P1[6], P1[7], P3[6]... + ld1 {v23.8b}, [x3], x1 + trn2 v7.8b, v7.8b, v17.8b // P2[6], P2[7], P4[6]... + ld1 {v17.8b}, [x3], x1 + trn1 v24.8b, v2.8b, v19.8b // P1[8], P1[9], P3[8]... + ld1 {v25.8b}, [x3] + trn2 v2.8b, v2.8b, v19.8b // P2[8], P2[9], P4[8]... + trn1 v19.4h, v16.4h, v18.4h // P1[0], P1[1], P1[2], P1[3], P5[0]... + trn1 v26.8b, v4.8b, v21.8b // P1[10], P1[11], P3[10]... + trn2 v4.8b, v4.8b, v21.8b // P2[10], P2[11], P4[10]... + trn1 v21.4h, v1.4h, v3.4h // P2[0], P2[1], P2[2], P2[3], P6[0]... + trn1 v27.4h, v20.4h, v22.4h // P1[4], P1[5], P1[6], P1[7], P5[4]... + trn1 v28.8b, v6.8b, v23.8b // P1[12], P1[13], P3[12]... + trn2 v6.8b, v6.8b, v23.8b // P2[12], P2[13], P4[12]... + trn1 v23.4h, v5.4h, v7.4h // P2[4], P2[5], P2[6], P2[7], P6[4]... + trn1 v29.4h, v24.4h, v26.4h // P1[8], P1[9], P1[10], P1[11], P5[8]... + trn1 v30.8b, v17.8b, v25.8b // P1[14], P1[15], P3[14]... + trn2 v17.8b, v17.8b, v25.8b // P2[14], P2[15], P4[14]... + trn1 v25.4h, v2.4h, v4.4h // P2[8], P2[9], P2[10], P2[11], P6[8]... + trn1 v31.2s, v19.2s, v27.2s // P1[0..7] + trn2 v19.2s, v19.2s, v27.2s // P5[0..7] + trn1 v27.2s, v21.2s, v23.2s // P2[0..7] + trn2 v21.2s, v21.2s, v23.2s // P6[0..7] + trn1 v23.4h, v28.4h, v30.4h // P1[12], P1[13], P1[14], P1[15], P5[12]... + trn2 v16.4h, v16.4h, v18.4h // P3[0], P3[1], P3[2], P3[3], P7[0]... + trn1 v18.4h, v6.4h, v17.4h // P2[12], P2[13], P2[14], P2[15], P6[12]... + trn2 v20.4h, v20.4h, v22.4h // P3[4], P3[5], P3[6], P3[7], P7[4]... + trn2 v22.4h, v24.4h, v26.4h // P3[8], P3[9], P3[10], P3[11], P7[8]... + trn1 v24.2s, v29.2s, v23.2s // P1[8..15] + trn2 v23.2s, v29.2s, v23.2s // P5[8..15] + trn1 v26.2s, v25.2s, v18.2s // P2[8..15] + trn2 v18.2s, v25.2s, v18.2s // P6[8..15] + trn2 v25.4h, v28.4h, v30.4h // P3[12], P3[13], P3[14], P3[15], P7[12]... + trn2 v1.4h, v1.4h, v3.4h // P4[0], P4[1], P4[2], P4[3], P8[0]... + trn2 v3.4h, v5.4h, v7.4h // P4[4], P4[5], P4[6], P4[7], P8[4]... + trn2 v2.4h, v2.4h, v4.4h // P4[8], P4[9], P4[10], P4[11], P8[8]... + trn2 v4.4h, v6.4h, v17.4h // P4[12], P4[13], P4[14], P4[15], P8[12]... + ushll v5.8h, v31.8b, #1 // 2*P1[0..7] + ushll v6.8h, v19.8b, #1 // 2*P5[0..7] + trn1 v7.2s, v16.2s, v20.2s // P3[0..7] + uxtl v17.8h, v27.8b // P2[0..7] + trn2 v16.2s, v16.2s, v20.2s // P7[0..7] + uxtl v20.8h, v21.8b // P6[0..7] + trn1 v21.2s, v22.2s, v25.2s // P3[8..15] + ushll v24.8h, v24.8b, #1 // 2*P1[8..15] + trn2 v22.2s, v22.2s, v25.2s // P7[8..15] + ushll v25.8h, v23.8b, #1 // 2*P5[8..15] + trn1 v27.2s, v1.2s, v3.2s // P4[0..7] + uxtl v26.8h, v26.8b // P2[8..15] + mls v5.8h, v17.8h, v0.h[1] // 2*P1[0..7]-5*P2[0..7] + uxtl v17.8h, v18.8b // P6[8..15] + mls v6.8h, v20.8h, v0.h[1] // 2*P5[0..7]-5*P6[0..7] + trn1 v18.2s, v2.2s, v4.2s // P4[8..15] + uxtl v28.8h, v7.8b // P3[0..7] + mls v24.8h, v26.8h, v0.h[1] // 2*P1[8..15]-5*P2[8..15] + uxtl v16.8h, v16.8b // P7[0..7] + uxtl v26.8h, v21.8b // P3[8..15] + mls v25.8h, v17.8h, v0.h[1] // 2*P5[8..15]-5*P6[8..15] + uxtl v22.8h, v22.8b // P7[8..15] + ushll v7.8h, v7.8b, #1 // 2*P3[0..7] + uxtl v27.8h, v27.8b // P4[0..7] + trn2 v1.2s, v1.2s, v3.2s // P8[0..7] + ushll v3.8h, v21.8b, #1 // 2*P3[8..15] + trn2 v2.2s, v2.2s, v4.2s // P8[8..15] + uxtl v4.8h, v18.8b // P4[8..15] + mla v5.8h, v28.8h, v0.h[1] // 2*P1[0..7]-5*P2[0..7]+5*P3[0..7] + uxtl v1.8h, v1.8b // P8[0..7] + mla v6.8h, v16.8h, v0.h[1] // 2*P5[0..7]-5*P6[0..7]+5*P7[0..7] + uxtl v2.8h, v2.8b // P8[8..15] + uxtl v16.8h, v19.8b // P5[0..7] + mla v24.8h, v26.8h, v0.h[1] // 2*P1[8..15]-5*P2[8..15]+5*P3[8..15] + uxtl v18.8h, v23.8b // P5[8..15] + dup v19.8h, w2 // pq + mla v25.8h, v22.8h, v0.h[1] // 2*P5[8..15]-5*P6[8..15]+5*P7[8..15] + sub v21.8h, v27.8h, v16.8h // P4[0..7]-P5[0..7] + sub v22.8h, v4.8h, v18.8h // P4[8..15]-P5[8..15] + mls v7.8h, v27.8h, v0.h[1] // 2*P3[0..7]-5*P4[0..7] + abs v23.8h, v21.8h + mls v3.8h, v4.8h, v0.h[1] // 2*P3[8..15]-5*P4[8..15] + abs v26.8h, v22.8h + sshr v21.8h, v21.8h, #8 // clip_sign[0..7] + mls v5.8h, v27.8h, v0.h[0] // 2*P1[0..7]-5*P2[0..7]+5*P3[0..7]-2*P4[0..7] + sshr v23.8h, v23.8h, #1 // clip[0..7] + sshr v26.8h, v26.8h, #1 // clip[8..15] + mls v6.8h, v1.8h, v0.h[0] // 2*P5[0..7]-5*P6[0..7]+5*P7[0..7]-2*P8[0..7] + sshr v1.8h, v22.8h, #8 // clip_sign[8..15] + cmeq v22.8h, v23.8h, #0 // test clip[0..7] == 0 + mls v24.8h, v4.8h, v0.h[0] // 2*P1[8..15]-5*P2[8..15]+5*P3[8..15]-2*P4[8..15] + cmeq v28.8h, v26.8h, #0 // test clip[8..15] == 0 + srshr v5.8h, v5.8h, #3 + mls v25.8h, v2.8h, v0.h[0] // 2*P5[8..15]-5*P6[8..15]+5*P7[8..15]-2*P8[8..15] + srshr v2.8h, v6.8h, #3 + mla v7.8h, v16.8h, v0.h[1] // 2*P3[0..7]-5*P4[0..7]+5*P5[0..7] + srshr v6.8h, v24.8h, #3 + mla v3.8h, v18.8h, v0.h[1] // 2*P3[8..15]-5*P4[8..15]+5*P5[8..15] + abs v5.8h, v5.8h // a1[0..7] + srshr v24.8h, v25.8h, #3 + mls v3.8h, v17.8h, v0.h[0] // 2*P3[8..15]-5*P4[8..15]+5*P5[8..15]-2*P6[8..15] + abs v2.8h, v2.8h // a2[0..7] + abs v6.8h, v6.8h // a1[8..15] + mls v7.8h, v20.8h, v0.h[0] // 2*P3[0..7]-5*P4[0..7]+5*P5[0..7]-2*P6[0..7] + abs v17.8h, v24.8h // a2[8..15] + cmhs v20.8h, v5.8h, v2.8h // test a1[0..7] >= a2[0..7] + srshr v3.8h, v3.8h, #3 + cmhs v24.8h, v6.8h, v17.8h // test a1[8..15] >= a2[8.15] + srshr v7.8h, v7.8h, #3 + bsl v20.16b, v2.16b, v5.16b // a3[0..7] + abs v2.8h, v3.8h // a0[8..15] + sshr v3.8h, v3.8h, #8 // a0_sign[8..15] + bsl v24.16b, v17.16b, v6.16b // a3[8..15] + abs v5.8h, v7.8h // a0[0..7] + sshr v6.8h, v7.8h, #8 // a0_sign[0..7] + cmhs v7.8h, v2.8h, v19.8h // test a0[8..15] >= pq + sub v1.8h, v1.8h, v3.8h // clip_sign[8..15] - a0_sign[8..15] + uqsub v3.8h, v2.8h, v24.8h // a0[8..15] >= a3[8..15] ? a0[8..15]-a3[8..15] : 0 (a0 > a3 in all cases where filtering is enabled, so makes more sense to subtract this way round than the opposite and then taking the abs) + cmhs v2.8h, v24.8h, v2.8h // test a3[8..15] >= a0[8..15] + uqsub v17.8h, v5.8h, v20.8h // a0[0..7] >= a3[0..7] ? a0[0..7]-a3[0..7] : 0 (a0 > a3 in all cases where filtering is enabled, so makes more sense to subtract this way round than the opposite and then taking the abs) + cmhs v19.8h, v5.8h, v19.8h // test a0[0..7] >= pq + orr v7.16b, v28.16b, v7.16b // test clip[8..15] == 0 || a0[8..15] >= pq + sub v6.8h, v21.8h, v6.8h // clip_sign[0..7] - a0_sign[0..7] + mul v3.8h, v3.8h, v0.h[1] // a0[8..15] >= a3[8..15] ? 5*(a0[8..15]-a3[8..15]) : 0 + cmhs v5.8h, v20.8h, v5.8h // test a3[0..7] >= a0[0..7] + orr v19.16b, v22.16b, v19.16b // test clip[0..7] == 0 || a0[0..7] >= pq + mul v0.8h, v17.8h, v0.h[1] // a0[0..7] >= a3[0..7] ? 5*(a0[0..7]-a3[0..7]) : 0 + orr v2.16b, v7.16b, v2.16b // test clip[8..15] == 0 || a0[8..15] >= pq || a3[8..15] >= a0[8..15] + orr v5.16b, v19.16b, v5.16b // test clip[0..7] == 0 || a0[0..7] >= pq || a3[0..7] >= a0[0..7] + ushr v3.8h, v3.8h, #3 // a0[8..15] >= a3[8..15] ? (5*(a0[8..15]-a3[8..15]))>>3 : 0 + mov w7, v2.s[1] + mov w8, v2.s[3] + ushr v0.8h, v0.8h, #3 // a0[0..7] >= a3[0..7] ? (5*(a0[0..7]-a3[0..7]))>>3 : 0 + mov w2, v5.s[1] // move to gp reg + cmhs v2.8h, v3.8h, v26.8h + mov w3, v5.s[3] + cmhs v5.8h, v0.8h, v23.8h + bsl v2.16b, v26.16b, v3.16b // FFMIN(d[8..15], clip[8..15]) + and w9, w7, w8 + bsl v5.16b, v23.16b, v0.16b // FFMIN(d[0..7], clip[0..7]) + and w10, w2, w3 + bic v0.16b, v2.16b, v7.16b // set each d[8..15] to zero if it should not be filtered because clip[8..15] == 0 || a0[8..15] >= pq (a3 > a0 case already zeroed by saturating sub) + and w9, w10, w9 + bic v2.16b, v5.16b, v19.16b // set each d[0..7] to zero if it should not be filtered because clip[0..7] == 0 || a0[0..7] >= pq (a3 > a0 case already zeroed by saturating sub) + mls v4.8h, v0.8h, v1.8h // invert d[8..15] depending on clip_sign[8..15] & a0_sign[8..15], or zero it if they match, and accumulate into P4 + tbnz w9, #0, 4f // none of the 16 pixel pairs should be updated in this case + mls v27.8h, v2.8h, v6.8h // invert d[0..7] depending on clip_sign[0..7] & a0_sign[0..7], or zero it if they match, and accumulate into P4 + mla v16.8h, v2.8h, v6.8h // invert d[0..7] depending on clip_sign[0..7] & a0_sign[0..7], or zero it if they match, and accumulate into P5 + sqxtun v2.8b, v4.8h + mla v18.8h, v0.8h, v1.8h // invert d[8..15] depending on clip_sign[8..15] & a0_sign[8..15], or zero it if they match, and accumulate into P5 + sqxtun v0.8b, v27.8h + sqxtun v1.8b, v16.8h + sqxtun v3.8b, v18.8h + tbnz w2, #0, 1f + st2 {v0.b, v1.b}[0], [x0], x1 + st2 {v0.b, v1.b}[1], [x0], x1 + st2 {v0.b, v1.b}[2], [x0], x1 + st2 {v0.b, v1.b}[3], [x0] +1: tbnz w3, #0, 2f + st2 {v0.b, v1.b}[4], [x5], x1 + st2 {v0.b, v1.b}[5], [x5], x1 + st2 {v0.b, v1.b}[6], [x5], x1 + st2 {v0.b, v1.b}[7], [x5] +2: tbnz w7, #0, 3f + st2 {v2.b, v3.b}[0], [x4], x1 + st2 {v2.b, v3.b}[1], [x4], x1 + st2 {v2.b, v3.b}[2], [x4], x1 + st2 {v2.b, v3.b}[3], [x4] +3: tbnz w8, #0, 4f + st2 {v2.b, v3.b}[4], [x6], x1 + st2 {v2.b, v3.b}[5], [x6], x1 + st2 {v2.b, v3.b}[6], [x6], x1 + st2 {v2.b, v3.b}[7], [x6] +4: ret +endfunc + +// Copy at most the specified number of bytes from source to destination buffer, +// stopping at a multiple of 32 bytes, none of which are the start of an escape sequence +// On entry: +// x0 -> source buffer +// w1 = max number of bytes to copy +// x2 -> destination buffer, optimally 8-byte aligned +// On exit: +// w0 = number of bytes not copied +function ff_vc1_unescape_buffer_helper_neon, export=1 + // Offset by 80 to screen out cases that are too short for us to handle, + // and also make it easy to test for loop termination, or to determine + // whether we need an odd number of half-iterations of the loop. + subs w1, w1, #80 + b.mi 90f + + // Set up useful constants + movi v20.4s, #3, lsl #24 + movi v21.4s, #3, lsl #16 + + tst w1, #32 + b.ne 1f + + ld1 {v0.16b, v1.16b, v2.16b}, [x0], #48 + ext v25.16b, v0.16b, v1.16b, #1 + ext v26.16b, v0.16b, v1.16b, #2 + ext v27.16b, v0.16b, v1.16b, #3 + ext v29.16b, v1.16b, v2.16b, #1 + ext v30.16b, v1.16b, v2.16b, #2 + ext v31.16b, v1.16b, v2.16b, #3 + bic v24.16b, v0.16b, v20.16b + bic v25.16b, v25.16b, v20.16b + bic v26.16b, v26.16b, v20.16b + bic v27.16b, v27.16b, v20.16b + bic v28.16b, v1.16b, v20.16b + bic v29.16b, v29.16b, v20.16b + bic v30.16b, v30.16b, v20.16b + bic v31.16b, v31.16b, v20.16b + eor v24.16b, v24.16b, v21.16b + eor v25.16b, v25.16b, v21.16b + eor v26.16b, v26.16b, v21.16b + eor v27.16b, v27.16b, v21.16b + eor v28.16b, v28.16b, v21.16b + eor v29.16b, v29.16b, v21.16b + eor v30.16b, v30.16b, v21.16b + eor v31.16b, v31.16b, v21.16b + cmeq v24.4s, v24.4s, #0 + cmeq v25.4s, v25.4s, #0 + cmeq v26.4s, v26.4s, #0 + cmeq v27.4s, v27.4s, #0 + add w1, w1, #32 + b 3f + +1: ld1 {v3.16b, v4.16b, v5.16b}, [x0], #48 + ext v25.16b, v3.16b, v4.16b, #1 + ext v26.16b, v3.16b, v4.16b, #2 + ext v27.16b, v3.16b, v4.16b, #3 + ext v29.16b, v4.16b, v5.16b, #1 + ext v30.16b, v4.16b, v5.16b, #2 + ext v31.16b, v4.16b, v5.16b, #3 + bic v24.16b, v3.16b, v20.16b + bic v25.16b, v25.16b, v20.16b + bic v26.16b, v26.16b, v20.16b + bic v27.16b, v27.16b, v20.16b + bic v28.16b, v4.16b, v20.16b + bic v29.16b, v29.16b, v20.16b + bic v30.16b, v30.16b, v20.16b + bic v31.16b, v31.16b, v20.16b + eor v24.16b, v24.16b, v21.16b + eor v25.16b, v25.16b, v21.16b + eor v26.16b, v26.16b, v21.16b + eor v27.16b, v27.16b, v21.16b + eor v28.16b, v28.16b, v21.16b + eor v29.16b, v29.16b, v21.16b + eor v30.16b, v30.16b, v21.16b + eor v31.16b, v31.16b, v21.16b + cmeq v24.4s, v24.4s, #0 + cmeq v25.4s, v25.4s, #0 + cmeq v26.4s, v26.4s, #0 + cmeq v27.4s, v27.4s, #0 + // Drop through... +2: mov v0.16b, v5.16b + ld1 {v1.16b, v2.16b}, [x0], #32 + cmeq v28.4s, v28.4s, #0 + cmeq v29.4s, v29.4s, #0 + cmeq v30.4s, v30.4s, #0 + cmeq v31.4s, v31.4s, #0 + orr v24.16b, v24.16b, v25.16b + orr v26.16b, v26.16b, v27.16b + orr v28.16b, v28.16b, v29.16b + orr v30.16b, v30.16b, v31.16b + ext v25.16b, v0.16b, v1.16b, #1 + orr v22.16b, v24.16b, v26.16b + ext v26.16b, v0.16b, v1.16b, #2 + ext v27.16b, v0.16b, v1.16b, #3 + ext v29.16b, v1.16b, v2.16b, #1 + orr v23.16b, v28.16b, v30.16b + ext v30.16b, v1.16b, v2.16b, #2 + ext v31.16b, v1.16b, v2.16b, #3 + bic v24.16b, v0.16b, v20.16b + bic v25.16b, v25.16b, v20.16b + bic v26.16b, v26.16b, v20.16b + orr v22.16b, v22.16b, v23.16b + bic v27.16b, v27.16b, v20.16b + bic v28.16b, v1.16b, v20.16b + bic v29.16b, v29.16b, v20.16b + bic v30.16b, v30.16b, v20.16b + bic v31.16b, v31.16b, v20.16b + addv s22, v22.4s + eor v24.16b, v24.16b, v21.16b + eor v25.16b, v25.16b, v21.16b + eor v26.16b, v26.16b, v21.16b + eor v27.16b, v27.16b, v21.16b + eor v28.16b, v28.16b, v21.16b + mov w3, v22.s[0] + eor v29.16b, v29.16b, v21.16b + eor v30.16b, v30.16b, v21.16b + eor v31.16b, v31.16b, v21.16b + cmeq v24.4s, v24.4s, #0 + cmeq v25.4s, v25.4s, #0 + cmeq v26.4s, v26.4s, #0 + cmeq v27.4s, v27.4s, #0 + cbnz w3, 90f + st1 {v3.16b, v4.16b}, [x2], #32 +3: mov v3.16b, v2.16b + ld1 {v4.16b, v5.16b}, [x0], #32 + cmeq v28.4s, v28.4s, #0 + cmeq v29.4s, v29.4s, #0 + cmeq v30.4s, v30.4s, #0 + cmeq v31.4s, v31.4s, #0 + orr v24.16b, v24.16b, v25.16b + orr v26.16b, v26.16b, v27.16b + orr v28.16b, v28.16b, v29.16b + orr v30.16b, v30.16b, v31.16b + ext v25.16b, v3.16b, v4.16b, #1 + orr v22.16b, v24.16b, v26.16b + ext v26.16b, v3.16b, v4.16b, #2 + ext v27.16b, v3.16b, v4.16b, #3 + ext v29.16b, v4.16b, v5.16b, #1 + orr v23.16b, v28.16b, v30.16b + ext v30.16b, v4.16b, v5.16b, #2 + ext v31.16b, v4.16b, v5.16b, #3 + bic v24.16b, v3.16b, v20.16b + bic v25.16b, v25.16b, v20.16b + bic v26.16b, v26.16b, v20.16b + orr v22.16b, v22.16b, v23.16b + bic v27.16b, v27.16b, v20.16b + bic v28.16b, v4.16b, v20.16b + bic v29.16b, v29.16b, v20.16b + bic v30.16b, v30.16b, v20.16b + bic v31.16b, v31.16b, v20.16b + addv s22, v22.4s + eor v24.16b, v24.16b, v21.16b + eor v25.16b, v25.16b, v21.16b + eor v26.16b, v26.16b, v21.16b + eor v27.16b, v27.16b, v21.16b + eor v28.16b, v28.16b, v21.16b + mov w3, v22.s[0] + eor v29.16b, v29.16b, v21.16b + eor v30.16b, v30.16b, v21.16b + eor v31.16b, v31.16b, v21.16b + cmeq v24.4s, v24.4s, #0 + cmeq v25.4s, v25.4s, #0 + cmeq v26.4s, v26.4s, #0 + cmeq v27.4s, v27.4s, #0 + cbnz w3, 91f + st1 {v0.16b, v1.16b}, [x2], #32 + subs w1, w1, #64 + b.pl 2b + +90: add w0, w1, #80 + ret + +91: sub w1, w1, #32 + b 90b +endfunc diff --git a/libavcodec/aasc.c b/libavcodec/aasc.c index 2177aa8f5..528ee58cd 100644 --- a/libavcodec/aasc.c +++ b/libavcodec/aasc.c @@ -29,6 +29,7 @@ #include #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "msrledec.h" @@ -77,9 +78,8 @@ static av_cold int aasc_decode_init(AVCodecContext *avctx) return 0; } -static int aasc_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int aasc_decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; @@ -104,26 +104,26 @@ static int aasc_decode_frame(AVCodecContext *avctx, ff_msrle_decode(avctx, s->frame, 8, &s->gb); break; case MKTAG('A', 'A', 'S', 'C'): - switch (compr) { - case 0: - stride = (avctx->width * psize + psize) & ~psize; - if (buf_size < stride * avctx->height) + switch (compr) { + case 0: + stride = (avctx->width * psize + psize) & ~psize; + if (buf_size < stride * avctx->height) + return AVERROR_INVALIDDATA; + for (i = avctx->height - 1; i >= 0; i--) { + memcpy(s->frame->data[0] + i * s->frame->linesize[0], buf, avctx->width * psize); + buf += stride; + buf_size -= stride; + } + break; + case 1: + bytestream2_init(&s->gb, buf, buf_size); + ff_msrle_decode(avctx, s->frame, 8, &s->gb); + break; + default: + av_log(avctx, AV_LOG_ERROR, "Unknown compression type %d\n", compr); return AVERROR_INVALIDDATA; - for (i = avctx->height - 1; i >= 0; i--) { - memcpy(s->frame->data[0] + i * s->frame->linesize[0], buf, avctx->width * psize); - buf += stride; - buf_size -= stride; } break; - case 1: - bytestream2_init(&s->gb, buf, buf_size); - ff_msrle_decode(avctx, s->frame, 8, &s->gb); - break; - default: - av_log(avctx, AV_LOG_ERROR, "Unknown compression type %d\n", compr); - return AVERROR_INVALIDDATA; - } - break; default: av_log(avctx, AV_LOG_ERROR, "Unknown FourCC: %X\n", avctx->codec_tag); return -1; @@ -133,7 +133,7 @@ static int aasc_decode_frame(AVCodecContext *avctx, memcpy(s->frame->data[1], s->palette, s->palette_size); *got_frame = 1; - if ((ret = av_frame_ref(data, s->frame)) < 0) + if ((ret = av_frame_ref(rframe, s->frame)) < 0) return ret; /* report that the buffer was completely consumed */ @@ -149,15 +149,15 @@ static av_cold int aasc_decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_aasc_decoder = { - .name = "aasc", - .long_name = NULL_IF_CONFIG_SMALL("Autodesk RLE"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_AASC, +const FFCodec ff_aasc_decoder = { + .p.name = "aasc", + .p.long_name = NULL_IF_CONFIG_SMALL("Autodesk RLE"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_AASC, .priv_data_size = sizeof(AascContext), .init = aasc_decode_init, .close = aasc_decode_end, - .decode = aasc_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(aasc_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/ac3.c b/libavcodec/ac3.c index a0fd00138..60491d1a7 100644 --- a/libavcodec/ac3.c +++ b/libavcodec/ac3.c @@ -24,9 +24,11 @@ * Common code between the AC-3 encoder and decoder. */ -#include "libavutil/common.h" +#include "libavutil/error.h" +#include "libavutil/macros.h" #include "ac3.h" +#include "ac3defs.h" /** * Starting frequency coefficient bin for each critical band. @@ -67,6 +69,88 @@ const uint8_t ff_ac3_bin_to_band_tab[253] = { 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49 }; +static const uint8_t ac3_log_add_tab[260]= { +0x40,0x3f,0x3e,0x3d,0x3c,0x3b,0x3a,0x39,0x38,0x37, +0x36,0x35,0x34,0x34,0x33,0x32,0x31,0x30,0x2f,0x2f, +0x2e,0x2d,0x2c,0x2c,0x2b,0x2a,0x29,0x29,0x28,0x27, +0x26,0x26,0x25,0x24,0x24,0x23,0x23,0x22,0x21,0x21, +0x20,0x20,0x1f,0x1e,0x1e,0x1d,0x1d,0x1c,0x1c,0x1b, +0x1b,0x1a,0x1a,0x19,0x19,0x18,0x18,0x17,0x17,0x16, +0x16,0x15,0x15,0x15,0x14,0x14,0x13,0x13,0x13,0x12, +0x12,0x12,0x11,0x11,0x11,0x10,0x10,0x10,0x0f,0x0f, +0x0f,0x0e,0x0e,0x0e,0x0d,0x0d,0x0d,0x0d,0x0c,0x0c, +0x0c,0x0c,0x0b,0x0b,0x0b,0x0b,0x0a,0x0a,0x0a,0x0a, +0x0a,0x09,0x09,0x09,0x09,0x09,0x08,0x08,0x08,0x08, +0x08,0x08,0x07,0x07,0x07,0x07,0x07,0x07,0x06,0x06, +0x06,0x06,0x06,0x06,0x06,0x06,0x05,0x05,0x05,0x05, +0x05,0x05,0x05,0x05,0x04,0x04,0x04,0x04,0x04,0x04, +0x04,0x04,0x04,0x04,0x04,0x03,0x03,0x03,0x03,0x03, +0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x02, +0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, +0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x01,0x01, +0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, +0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, +0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +}; + +static const uint16_t ac3_hearing_threshold_tab[AC3_CRITICAL_BANDS][3]= { +{ 0x04d0,0x04f0,0x0580 }, +{ 0x04d0,0x04f0,0x0580 }, +{ 0x0440,0x0460,0x04b0 }, +{ 0x0400,0x0410,0x0450 }, +{ 0x03e0,0x03e0,0x0420 }, +{ 0x03c0,0x03d0,0x03f0 }, +{ 0x03b0,0x03c0,0x03e0 }, +{ 0x03b0,0x03b0,0x03d0 }, +{ 0x03a0,0x03b0,0x03c0 }, +{ 0x03a0,0x03a0,0x03b0 }, +{ 0x03a0,0x03a0,0x03b0 }, +{ 0x03a0,0x03a0,0x03b0 }, +{ 0x03a0,0x03a0,0x03a0 }, +{ 0x0390,0x03a0,0x03a0 }, +{ 0x0390,0x0390,0x03a0 }, +{ 0x0390,0x0390,0x03a0 }, +{ 0x0380,0x0390,0x03a0 }, +{ 0x0380,0x0380,0x03a0 }, +{ 0x0370,0x0380,0x03a0 }, +{ 0x0370,0x0380,0x03a0 }, +{ 0x0360,0x0370,0x0390 }, +{ 0x0360,0x0370,0x0390 }, +{ 0x0350,0x0360,0x0390 }, +{ 0x0350,0x0360,0x0390 }, +{ 0x0340,0x0350,0x0380 }, +{ 0x0340,0x0350,0x0380 }, +{ 0x0330,0x0340,0x0380 }, +{ 0x0320,0x0340,0x0370 }, +{ 0x0310,0x0320,0x0360 }, +{ 0x0300,0x0310,0x0350 }, +{ 0x02f0,0x0300,0x0340 }, +{ 0x02f0,0x02f0,0x0330 }, +{ 0x02f0,0x02f0,0x0320 }, +{ 0x02f0,0x02f0,0x0310 }, +{ 0x0300,0x02f0,0x0300 }, +{ 0x0310,0x0300,0x02f0 }, +{ 0x0340,0x0320,0x02f0 }, +{ 0x0390,0x0350,0x02f0 }, +{ 0x03e0,0x0390,0x0300 }, +{ 0x0420,0x03e0,0x0310 }, +{ 0x0460,0x0420,0x0330 }, +{ 0x0490,0x0450,0x0350 }, +{ 0x04a0,0x04a0,0x03c0 }, +{ 0x0460,0x0490,0x0410 }, +{ 0x0440,0x0460,0x0470 }, +{ 0x0440,0x0440,0x04a0 }, +{ 0x0520,0x0480,0x0460 }, +{ 0x0800,0x0630,0x0440 }, +{ 0x0840,0x0840,0x0450 }, +{ 0x0840,0x0840,0x04e0 }, +}; + static inline int calc_lowcomp1(int a, int b0, int b1, int c) { if ((b0 + 256) == b1) { @@ -108,7 +192,7 @@ void ff_ac3_bit_alloc_calc_psd(int8_t *exp, int start, int end, int16_t *psd, int max = FFMAX(v, psd[bin]); /* logadd */ int adr = FFMIN(max - ((v + psd[bin] + 1) >> 1), 255); - v = max + ff_ac3_log_add_tab[adr]; + v = max + ac3_log_add_tab[adr]; } band_psd[band++] = v; } while (end > ff_ac3_band_start_tab[band]); @@ -182,7 +266,7 @@ int ff_ac3_bit_alloc_calc_mask(AC3BitAllocParameters *s, int16_t *band_psd, if (tmp > 0) { excite[band] += tmp >> 2; } - mask[band] = FFMAX(ff_ac3_hearing_threshold_tab[band >> s->sr_shift][s->sr_code], excite[band]); + mask[band] = FFMAX(ac3_hearing_threshold_tab[band >> s->sr_shift][s->sr_code], excite[band]); } /* delta bit allocation */ diff --git a/libavcodec/ac3.h b/libavcodec/ac3.h index 0e5202811..29f9f9df8 100644 --- a/libavcodec/ac3.h +++ b/libavcodec/ac3.h @@ -30,28 +30,8 @@ #include #include -#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 */ - -#define AC3_MAX_COEFS 256 -#define AC3_BLOCK_SIZE 256 -#define AC3_MAX_BLOCKS 6 -#define AC3_FRAME_SIZE (AC3_MAX_BLOCKS * 256) -#define AC3_WINDOW_SIZE (AC3_BLOCK_SIZE * 2) -#define AC3_CRITICAL_BANDS 50 -#define AC3_MAX_CPL_BANDS 18 - #include "ac3tab.h" -/* exponent encoding strategy */ -#define EXP_REUSE 0 -#define EXP_NEW 1 - -#define EXP_D15 1 -#define EXP_D25 2 -#define EXP_D45 3 - #ifndef USE_FIXED #define USE_FIXED 0 #endif @@ -78,6 +58,7 @@ typedef int INTFLOAT; typedef int16_t SHORTFLOAT; #else /* USE_FIXED */ +#include "libavutil/libm.h" #define FIXR(x) ((float)(x)) #define FIXR12(x) ((float)(x)) @@ -111,58 +92,6 @@ typedef float SHORTFLOAT; #define LEVEL_ZERO 0.0000000000000000 #define LEVEL_ONE 1.0000000000000000 -/** Delta bit allocation strategy */ -typedef enum { - DBA_REUSE = 0, - DBA_NEW, - DBA_NONE, - DBA_RESERVED -} AC3DeltaStrategy; - -/** Channel mode (audio coding mode) */ -typedef enum { - AC3_CHMODE_DUALMONO = 0, - AC3_CHMODE_MONO, - AC3_CHMODE_STEREO, - AC3_CHMODE_3F, - AC3_CHMODE_2F1R, - AC3_CHMODE_3F1R, - AC3_CHMODE_2F2R, - AC3_CHMODE_3F2R -} AC3ChannelMode; - -/** Dolby Surround mode */ -typedef enum AC3DolbySurroundMode { - AC3_DSURMOD_NOTINDICATED = 0, - AC3_DSURMOD_OFF, - AC3_DSURMOD_ON, - AC3_DSURMOD_RESERVED -} AC3DolbySurroundMode; - -/** Dolby Surround EX mode */ -typedef enum AC3DolbySurroundEXMode { - AC3_DSUREXMOD_NOTINDICATED = 0, - AC3_DSUREXMOD_OFF, - AC3_DSUREXMOD_ON, - AC3_DSUREXMOD_PLIIZ -} AC3DolbySurroundEXMode; - -/** Dolby Headphone mode */ -typedef enum AC3DolbyHeadphoneMode { - AC3_DHEADPHONMOD_NOTINDICATED = 0, - AC3_DHEADPHONMOD_OFF, - AC3_DHEADPHONMOD_ON, - AC3_DHEADPHONMOD_RESERVED -} AC3DolbyHeadphoneMode; - -/** Preferred Stereo Downmix mode */ -typedef enum AC3PreferredStereoDownmixMode { - AC3_DMIXMOD_NOTINDICATED = 0, - AC3_DMIXMOD_LTRT, - AC3_DMIXMOD_LORO, - AC3_DMIXMOD_DPLII // reserved value in A/52, but used by encoders to indicate DPL2 -} AC3PreferredStereoDownmixMode; - typedef struct AC3BitAllocParameters { int sr_code; int sr_shift; @@ -170,51 +99,6 @@ typedef struct AC3BitAllocParameters { int cpl_fast_leak, cpl_slow_leak; } AC3BitAllocParameters; -/** - * @struct AC3HeaderInfo - * Coded AC-3 header values up to the lfeon element, plus derived values. - */ -typedef struct AC3HeaderInfo { - /** @name Coded elements - * @{ - */ - uint16_t sync_word; - uint16_t crc1; - uint8_t sr_code; - uint8_t bitstream_id; - uint8_t bitstream_mode; - uint8_t channel_mode; - uint8_t lfe_on; - uint8_t frame_type; - int substreamid; ///< substream identification - int center_mix_level; ///< Center mix level index - int surround_mix_level; ///< Surround mix level index - uint16_t channel_map; - int num_blocks; ///< number of audio blocks - int dolby_surround_mode; - /** @} */ - - /** @name Derived values - * @{ - */ - uint8_t sr_shift; - uint16_t sample_rate; - uint32_t bit_rate; - uint8_t channels; - uint16_t frame_size; - uint64_t channel_layout; - /** @} */ -} AC3HeaderInfo; - -typedef enum { - EAC3_FRAME_TYPE_INDEPENDENT = 0, - EAC3_FRAME_TYPE_DEPENDENT, - EAC3_FRAME_TYPE_AC3_CONVERT, - EAC3_FRAME_TYPE_RESERVED -} EAC3FrameType; - -void ff_ac3_common_init(void); - /** * Calculate the log power-spectral density of the input signal. * This gives a rough estimate of signal power in the frequency domain by using diff --git a/libavcodec/ac3_parser.c b/libavcodec/ac3_parser.c index f3c7d27d5..4f154bb7c 100644 --- a/libavcodec/ac3_parser.c +++ b/libavcodec/ac3_parser.c @@ -21,9 +21,12 @@ */ #include "config.h" +#include "config_components.h" #include "libavutil/channel_layout.h" #include "parser.h" +#include "ac3defs.h" +#include "ac3tab.h" #include "ac3_parser.h" #include "ac3_parser_internal.h" #include "aac_ac3_parser.h" @@ -67,6 +70,7 @@ int ff_ac3_parse_header(GetBitContext *gbc, AC3HeaderInfo *hdr) return AAC_AC3_PARSE_ERROR_BSID; hdr->num_blocks = 6; + hdr->ac3_bit_rate_code = -1; /* set default mix levels */ hdr->center_mix_level = 5; // -4.5dB @@ -86,6 +90,8 @@ int ff_ac3_parse_header(GetBitContext *gbc, AC3HeaderInfo *hdr) if(frame_size_code > 37) return AAC_AC3_PARSE_ERROR_FRAME_SIZE; + hdr->ac3_bit_rate_code = (frame_size_code >> 1); + skip_bits(gbc, 5); // skip bsid, already got it hdr->bitstream_mode = get_bits(gbc, 3); @@ -103,7 +109,7 @@ int ff_ac3_parse_header(GetBitContext *gbc, AC3HeaderInfo *hdr) hdr->sr_shift = FFMAX(hdr->bitstream_id, 8) - 8; hdr->sample_rate = ff_ac3_sample_rate_tab[hdr->sr_code] >> hdr->sr_shift; - hdr->bit_rate = (ff_ac3_bitrate_tab[frame_size_code>>1] * 1000) >> hdr->sr_shift; + hdr->bit_rate = (ff_ac3_bitrate_tab[hdr->ac3_bit_rate_code] * 1000) >> hdr->sr_shift; hdr->channels = ff_ac3_channels_tab[hdr->channel_mode] + hdr->lfe_on; hdr->frame_size = ff_ac3_frame_size_tab[frame_size_code][hdr->sr_code] * 2; hdr->frame_type = EAC3_FRAME_TYPE_AC3_CONVERT; //EAC3_FRAME_TYPE_INDEPENDENT; diff --git a/libavcodec/ac3_parser_internal.h b/libavcodec/ac3_parser_internal.h index 3648802a7..bd4e1bbff 100644 --- a/libavcodec/ac3_parser_internal.h +++ b/libavcodec/ac3_parser_internal.h @@ -21,9 +21,49 @@ #ifndef AVCODEC_AC3_PARSER_INTERNAL_H #define AVCODEC_AC3_PARSER_INTERNAL_H -#include "ac3.h" +#include +#include + +#include "ac3defs.h" #include "get_bits.h" +/** + * @struct AC3HeaderInfo + * Coded AC-3 header values up to the lfeon element, plus derived values. + */ +typedef struct AC3HeaderInfo { + /** @name Coded elements + * @{ + */ + uint16_t sync_word; + uint16_t crc1; + uint8_t sr_code; + uint8_t bitstream_id; + uint8_t bitstream_mode; + uint8_t channel_mode; + uint8_t lfe_on; + uint8_t frame_type; + int substreamid; ///< substream identification + int center_mix_level; ///< Center mix level index + int surround_mix_level; ///< Surround mix level index + uint16_t channel_map; + int num_blocks; ///< number of audio blocks + int dolby_surround_mode; + /** @} */ + + /** @name Derived values + * @{ + */ + uint8_t sr_shift; + uint16_t sample_rate; + uint32_t bit_rate; + uint8_t channels; + uint16_t frame_size; + uint64_t channel_layout; + int8_t ac3_bit_rate_code; + /** @} */ +} AC3HeaderInfo; + /** * Parse AC-3 frame header. * Parse the header up to the lfeon element, which is the first 52 or 54 bits diff --git a/libavcodec/ac3dec.c b/libavcodec/ac3dec.c index ae00373dc..ad2b3615c 100644 --- a/libavcodec/ac3dec.c +++ b/libavcodec/ac3dec.c @@ -24,6 +24,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include #include #include @@ -32,6 +34,7 @@ #include "libavutil/channel_layout.h" #include "libavutil/crc.h" #include "libavutil/downmix_info.h" +#include "libavutil/intmath.h" #include "libavutil/opt.h" #include "libavutil/thread.h" #include "bswapdsp.h" @@ -40,6 +43,7 @@ #include "ac3_parser_internal.h" #include "ac3dec.h" #include "ac3dec_data.h" +#include "ac3defs.h" #include "kbdwin.h" /** @@ -186,6 +190,8 @@ static av_cold int ac3_decode_init(AVCodecContext *avctx) { static AVOnce init_static_once = AV_ONCE_INIT; AC3DecodeContext *s = avctx->priv_data; + const AVChannelLayout mono = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; + const AVChannelLayout stereo = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; int i, ret; s->avctx = avctx; @@ -214,12 +220,23 @@ static av_cold int ac3_decode_init(AVCodecContext *avctx) avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; /* allow downmixing to stereo or mono */ - if (avctx->channels > 1 && - avctx->request_channel_layout == AV_CH_LAYOUT_MONO) - avctx->channels = 1; - else if (avctx->channels > 2 && - avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) - avctx->channels = 2; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->request_channel_layout) { + av_channel_layout_uninit(&s->downmix_layout); + av_channel_layout_from_mask(&s->downmix_layout, avctx->request_channel_layout); + } +FF_ENABLE_DEPRECATION_WARNINGS +#endif + if (avctx->ch_layout.nb_channels > 1 && + !av_channel_layout_compare(&s->downmix_layout, &mono)) { + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; + } else if (avctx->ch_layout.nb_channels > 2 && + !av_channel_layout_compare(&s->downmix_layout, &stereo)) { + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; + } s->downmixed = 1; for (i = 0; i < AC3_MAX_CHANNELS; i++) { @@ -1465,10 +1482,9 @@ static int decode_audio_block(AC3DecodeContext *s, int blk, int offset) /** * Decode a single AC-3 frame. */ -static int ac3_decode_frame(AVCodecContext * avctx, void *data, +static int ac3_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size, full_buf_size = avpkt->size; AC3DecodeContext *s = avctx->priv_data; @@ -1480,6 +1496,7 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data, const SHORTFLOAT *output[AC3_MAX_CHANNELS]; enum AVMatrixEncoding matrix_encoding; AVDownmixInfo *downmix_info; + uint64_t mask; s->superframe_size = 0; @@ -1590,11 +1607,11 @@ dependent_frame: if (s->lfe_on) s->output_mode |= AC3_OUTPUT_LFEON; if (s->channels > 1 && - avctx->request_channel_layout == AV_CH_LAYOUT_MONO) { + !av_channel_layout_compare(&s->downmix_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_MONO)) { s->out_channels = 1; s->output_mode = AC3_CHMODE_MONO; } else if (s->channels > 2 && - avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) { + !av_channel_layout_compare(&s->downmix_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO)) { s->out_channels = 2; s->output_mode = AC3_CHMODE_STEREO; } @@ -1615,10 +1632,13 @@ dependent_frame: av_log(avctx, AV_LOG_ERROR, "unable to determine channel mode\n"); return AVERROR_INVALIDDATA; } - avctx->channels = s->out_channels; - avctx->channel_layout = ff_ac3_channel_layout_tab[s->output_mode & ~AC3_OUTPUT_LFEON]; + + mask = ff_ac3_channel_layout_tab[s->output_mode & ~AC3_OUTPUT_LFEON]; if (s->output_mode & AC3_OUTPUT_LFEON) - avctx->channel_layout |= AV_CH_LOW_FREQUENCY; + mask |= AV_CH_LOW_FREQUENCY; + + av_channel_layout_uninit(&avctx->ch_layout); + av_channel_layout_from_mask(&avctx->ch_layout, mask); /* set audio service type based on bitstream mode for AC-3 */ avctx->audio_service_type = s->bitstream_mode; @@ -1714,20 +1734,20 @@ skip: channel_layout |= ff_eac3_custom_channel_map_locations[ch][1]; } } - if (av_get_channel_layout_nb_channels(channel_layout) > EAC3_MAX_CHANNELS) { + if (av_popcount64(channel_layout) > EAC3_MAX_CHANNELS) { av_log(avctx, AV_LOG_ERROR, "Too many channels (%d) coded\n", - av_get_channel_layout_nb_channels(channel_layout)); + av_popcount64(channel_layout)); return AVERROR_INVALIDDATA; } - avctx->channel_layout = channel_layout; - avctx->channels = av_get_channel_layout_nb_channels(channel_layout); + av_channel_layout_uninit(&avctx->ch_layout); + av_channel_layout_from_mask(&avctx->ch_layout, channel_layout); for (ch = 0; ch < EAC3_MAX_CHANNELS; ch++) { if (s->channel_map & (1 << (EAC3_MAX_CHANNELS - ch - 1))) { if (ff_eac3_custom_channel_map_locations[ch][0]) { - int index = av_get_channel_layout_channel_index(channel_layout, - ff_eac3_custom_channel_map_locations[ch][1]); + int index = av_channel_layout_index_from_channel(&avctx->ch_layout, + ff_ctzll(ff_eac3_custom_channel_map_locations[ch][1])); if (index < 0) return AVERROR_INVALIDDATA; if (extend >= channel_map_size) @@ -1739,8 +1759,7 @@ skip: for (i = 0; i < 64; i++) { if ((1ULL << i) & ff_eac3_custom_channel_map_locations[ch][1]) { - int index = av_get_channel_layout_channel_index(channel_layout, - 1ULL << i); + int index = av_channel_layout_index_from_channel(&avctx->ch_layout, i); if (index < 0) return AVERROR_INVALIDDATA; if (extend >= channel_map_size) @@ -1759,7 +1778,7 @@ skip: if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; - for (ch = 0; ch < avctx->channels; ch++) { + for (ch = 0; ch < avctx->ch_layout.nb_channels; ch++) { int map = extended_channel_map[ch]; av_assert0(ch>=AV_NUM_DATA_POINTERS || frame->extended_data[ch] == frame->data[ch]); memcpy((SHORTFLOAT *)frame->extended_data[ch], diff --git a/libavcodec/ac3dec.h b/libavcodec/ac3dec.h index 85653990c..944412497 100644 --- a/libavcodec/ac3dec.h +++ b/libavcodec/ac3dec.h @@ -251,6 +251,8 @@ typedef struct AC3DecodeContext { 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)[EAC3_MAX_CHANNELS][AC3_BLOCK_SIZE * 6]; ///< final output buffer ///@} + + AVChannelLayout downmix_layout; } AC3DecodeContext; /** diff --git a/libavcodec/ac3dec_data.c b/libavcodec/ac3dec_data.c index d0a9b1ec4..a3794ab22 100644 --- a/libavcodec/ac3dec_data.c +++ b/libavcodec/ac3dec_data.c @@ -25,7 +25,6 @@ */ #include "ac3dec_data.h" -#include "ac3.h" /** * Table used to ungroup 3 values stored in 5 bits. diff --git a/libavcodec/ac3dec_fixed.c b/libavcodec/ac3dec_fixed.c index 864595262..4c0d4d6f5 100644 --- a/libavcodec/ac3dec_fixed.c +++ b/libavcodec/ac3dec_fixed.c @@ -50,6 +50,7 @@ #define FFT_FLOAT 0 #define USE_FIXED 1 #include "ac3dec.h" +#include "codec_internal.h" static const int end_freq_inv_tab[8] = @@ -157,6 +158,7 @@ static const AVOption options[] = { { "cons_noisegen", "enable consistent noise generation", OFFSET(consistent_noise_generation), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, PAR }, { "drc_scale", "percentage of dynamic range compression to apply", OFFSET(drc_scale), AV_OPT_TYPE_FLOAT, {.dbl = 1.0}, 0.0, 6.0, PAR }, { "heavy_compr", "enable heavy dynamic range compression", OFFSET(heavy_compression), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, PAR }, + { "downmix", "Request a specific channel layout from the decoder", OFFSET(downmix_layout), AV_OPT_TYPE_CHLAYOUT, {.str = NULL}, .flags = PAR }, { NULL}, }; @@ -167,19 +169,19 @@ static const AVClass ac3_decoder_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_ac3_fixed_decoder = { - .name = "ac3_fixed", - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_AC3, +const FFCodec ff_ac3_fixed_decoder = { + .p.name = "ac3_fixed", + .p.long_name = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_AC3, + .p.priv_class = &ac3_decoder_class, .priv_data_size = sizeof (AC3DecodeContext), .init = ac3_decode_init, .close = ac3_decode_end, - .decode = ac3_decode_frame, - .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + FF_CODEC_DECODE_CB(ac3_decode_frame), + .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1, - .long_name = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"), - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE }, - .priv_class = &ac3_decoder_class, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/ac3dec_float.c b/libavcodec/ac3dec_float.c index 573fbe75b..2147b36af 100644 --- a/libavcodec/ac3dec_float.c +++ b/libavcodec/ac3dec_float.c @@ -27,7 +27,11 @@ /** * Upmix delay samples from stereo to original channel layout. */ + +#include "config_components.h" + #include "ac3dec.h" +#include "codec_internal.h" #include "eac3dec.c" #include "ac3dec.c" @@ -43,6 +47,8 @@ static const AVOption options[] = { {"loro_cmixlev", "Lo/Ro Center Mix Level", OFFSET(loro_center_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, 0}, {"loro_surmixlev", "Lo/Ro Surround Mix Level", OFFSET(loro_surround_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, 0}, + { "downmix", "Request a specific channel layout from the decoder", OFFSET(downmix_layout), AV_OPT_TYPE_CHLAYOUT, {.str = NULL}, .flags = PAR }, + { NULL}, }; @@ -53,38 +59,38 @@ static const AVClass ac3_eac3_decoder_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_ac3_decoder = { - .name = "ac3", - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_AC3, +const FFCodec ff_ac3_decoder = { + .p.name = "ac3", + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_AC3, .priv_data_size = sizeof (AC3DecodeContext), .init = ac3_decode_init, .close = ac3_decode_end, - .decode = ac3_decode_frame, - .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + FF_CODEC_DECODE_CB(ac3_decode_frame), + .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1, - .long_name = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"), - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + .p.long_name = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"), + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, - .priv_class = &ac3_eac3_decoder_class, + .p.priv_class = &ac3_eac3_decoder_class, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; #if CONFIG_EAC3_DECODER -const AVCodec ff_eac3_decoder = { - .name = "eac3", - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_EAC3, +const FFCodec ff_eac3_decoder = { + .p.name = "eac3", + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_EAC3, .priv_data_size = sizeof (AC3DecodeContext), .init = ac3_decode_init, .close = ac3_decode_end, - .decode = ac3_decode_frame, - .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + FF_CODEC_DECODE_CB(ac3_decode_frame), + .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1, - .long_name = NULL_IF_CONFIG_SMALL("ATSC A/52B (AC-3, E-AC-3)"), - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + .p.long_name = NULL_IF_CONFIG_SMALL("ATSC A/52B (AC-3, E-AC-3)"), + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, - .priv_class = &ac3_eac3_decoder_class, + .p.priv_class = &ac3_eac3_decoder_class, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; #endif diff --git a/libavcodec/ac3defs.h b/libavcodec/ac3defs.h new file mode 100644 index 000000000..ff92f0ac4 --- /dev/null +++ b/libavcodec/ac3defs.h @@ -0,0 +1,104 @@ +/* + * Common AC-3 definitions + * 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 AVCODEC_AC3DEFS_H +#define AVCODEC_AC3DEFS_H + +#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 */ + +#define AC3_MAX_COEFS 256 +#define AC3_BLOCK_SIZE 256 +#define AC3_MAX_BLOCKS 6 +#define AC3_FRAME_SIZE (AC3_MAX_BLOCKS * 256) +#define AC3_WINDOW_SIZE (AC3_BLOCK_SIZE * 2) +#define AC3_CRITICAL_BANDS 50 +#define AC3_MAX_CPL_BANDS 18 + +/* exponent encoding strategy */ +#define EXP_REUSE 0 +#define EXP_NEW 1 + +#define EXP_D15 1 +#define EXP_D25 2 +#define EXP_D45 3 + +/** Delta bit allocation strategy */ +typedef enum { + DBA_REUSE = 0, + DBA_NEW, + DBA_NONE, + DBA_RESERVED +} AC3DeltaStrategy; + +/** Channel mode (audio coding mode) */ +typedef enum { + AC3_CHMODE_DUALMONO = 0, + AC3_CHMODE_MONO, + AC3_CHMODE_STEREO, + AC3_CHMODE_3F, + AC3_CHMODE_2F1R, + AC3_CHMODE_3F1R, + AC3_CHMODE_2F2R, + AC3_CHMODE_3F2R +} AC3ChannelMode; + +/** Dolby Surround mode */ +typedef enum AC3DolbySurroundMode { + AC3_DSURMOD_NOTINDICATED = 0, + AC3_DSURMOD_OFF, + AC3_DSURMOD_ON, + AC3_DSURMOD_RESERVED +} AC3DolbySurroundMode; + +/** Dolby Surround EX mode */ +typedef enum AC3DolbySurroundEXMode { + AC3_DSUREXMOD_NOTINDICATED = 0, + AC3_DSUREXMOD_OFF, + AC3_DSUREXMOD_ON, + AC3_DSUREXMOD_PLIIZ +} AC3DolbySurroundEXMode; + +/** Dolby Headphone mode */ +typedef enum AC3DolbyHeadphoneMode { + AC3_DHEADPHONMOD_NOTINDICATED = 0, + AC3_DHEADPHONMOD_OFF, + AC3_DHEADPHONMOD_ON, + AC3_DHEADPHONMOD_RESERVED +} AC3DolbyHeadphoneMode; + +/** Preferred Stereo Downmix mode */ +typedef enum AC3PreferredStereoDownmixMode { + AC3_DMIXMOD_NOTINDICATED = 0, + AC3_DMIXMOD_LTRT, + AC3_DMIXMOD_LORO, + AC3_DMIXMOD_DPLII // reserved value in A/52, but used by encoders to indicate DPL2 +} AC3PreferredStereoDownmixMode; + +typedef enum { + EAC3_FRAME_TYPE_INDEPENDENT = 0, + EAC3_FRAME_TYPE_DEPENDENT, + EAC3_FRAME_TYPE_AC3_CONVERT, + EAC3_FRAME_TYPE_RESERVED +} EAC3FrameType; + +#endif /* AVCODEC_AC3DEFS_H */ diff --git a/libavcodec/ac3dsp.c b/libavcodec/ac3dsp.c index d006ca8c0..afd6b557b 100644 --- a/libavcodec/ac3dsp.c +++ b/libavcodec/ac3dsp.c @@ -29,8 +29,9 @@ #include "libavutil/intmath.h" #include "libavutil/mem_internal.h" -#include "ac3.h" +#include "ac3defs.h" #include "ac3dsp.h" +#include "ac3tab.h" #include "mathops.h" static void ac3_exponent_min_c(uint8_t *exp, int num_reuse_blocks, int nb_coefs) @@ -362,8 +363,9 @@ void ff_ac3dsp_downmix(AC3DSPContext *c, float **samples, float **matrix, c->downmix = ac3_downmix_5_to_1_symmetric_c; } - if (ARCH_X86) - ff_ac3dsp_set_downmix_x86(c); +#if ARCH_X86 + ff_ac3dsp_set_downmix_x86(c); +#endif } if (c->downmix) @@ -387,10 +389,11 @@ av_cold void ff_ac3dsp_init(AC3DSPContext *c, int bit_exact) c->downmix = NULL; c->downmix_fixed = NULL; - if (ARCH_ARM) - ff_ac3dsp_init_arm(c, bit_exact); - if (ARCH_X86) - ff_ac3dsp_init_x86(c, bit_exact); - if (ARCH_MIPS) - ff_ac3dsp_init_mips(c, bit_exact); +#if ARCH_ARM + ff_ac3dsp_init_arm(c, bit_exact); +#elif ARCH_X86 + ff_ac3dsp_init_x86(c, bit_exact); +#elif ARCH_MIPS + ff_ac3dsp_init_mips(c, bit_exact); +#endif } diff --git a/libavcodec/ac3enc.c b/libavcodec/ac3enc.c index 034aa0beb..c57904b01 100644 --- a/libavcodec/ac3enc.c +++ b/libavcodec/ac3enc.c @@ -38,6 +38,8 @@ #include "libavutil/opt.h" #include "libavutil/thread.h" #include "avcodec.h" +#include "codec_internal.h" +#include "config_components.h" #include "encode.h" #include "internal.h" #include "me_cmp.h" @@ -45,6 +47,8 @@ #include "audiodsp.h" #include "ac3dsp.h" #include "ac3.h" +#include "ac3defs.h" +#include "ac3tab.h" #include "fft.h" #include "ac3enc.h" #include "eac3enc.h" @@ -132,7 +136,7 @@ const AVClass ff_ac3enc_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodecDefault ff_ac3_enc_defaults[] = { +const FFCodecDefault ff_ac3_enc_defaults[] = { { "b", "0" }, { NULL } }; @@ -147,6 +151,7 @@ static uint8_t exponent_group_tab[2][3][256]; /** * List of supported channel layouts. */ +#if FF_API_OLD_CHANNEL_LAYOUT const uint64_t ff_ac3_channel_layouts[19] = { AV_CH_LAYOUT_MONO, AV_CH_LAYOUT_STEREO, @@ -168,6 +173,47 @@ const uint64_t ff_ac3_channel_layouts[19] = { AV_CH_LAYOUT_5POINT1_BACK, 0 }; +#endif + +const AVChannelLayout ff_ac3_ch_layouts[19] = { + AV_CHANNEL_LAYOUT_MONO, + AV_CHANNEL_LAYOUT_STEREO, + AV_CHANNEL_LAYOUT_2_1, + AV_CHANNEL_LAYOUT_SURROUND, + AV_CHANNEL_LAYOUT_2_2, + AV_CHANNEL_LAYOUT_QUAD, + AV_CHANNEL_LAYOUT_4POINT0, + AV_CHANNEL_LAYOUT_5POINT0, + AV_CHANNEL_LAYOUT_5POINT0_BACK, + { + .nb_channels = 2, + .order = AV_CHANNEL_ORDER_NATIVE, + .u.mask = AV_CH_LAYOUT_MONO | AV_CH_LOW_FREQUENCY, + }, + { + .nb_channels = 3, + .order = AV_CHANNEL_ORDER_NATIVE, + .u.mask = AV_CH_LAYOUT_STEREO | AV_CH_LOW_FREQUENCY, + }, + { + .nb_channels = 4, + .order = AV_CHANNEL_ORDER_NATIVE, + .u.mask = AV_CH_LAYOUT_2_1 | AV_CH_LOW_FREQUENCY, + }, + { + .nb_channels = 4, + .order = AV_CHANNEL_ORDER_NATIVE, + .u.mask = AV_CH_LAYOUT_SURROUND | AV_CH_LOW_FREQUENCY, + }, + { + .nb_channels = 5, + .order = AV_CHANNEL_ORDER_NATIVE, + .u.mask = AV_CH_LAYOUT_4POINT0 | AV_CH_LOW_FREQUENCY, + }, + AV_CHANNEL_LAYOUT_5POINT1, + AV_CHANNEL_LAYOUT_5POINT1_BACK, + { 0 }, +}; /** * Table to remap channels from SMPTE order to AC-3 order. @@ -1797,7 +1843,7 @@ static void dprint_options(AC3EncodeContext *s) } ff_dlog(avctx, "bitstream_id: %s (%d)\n", strbuf, s->bitstream_id); ff_dlog(avctx, "sample_fmt: %s\n", av_get_sample_fmt_name(avctx->sample_fmt)); - av_get_channel_layout_string(strbuf, 32, s->channels, avctx->channel_layout); + av_channel_layout_describe(&avctx->ch_layout, strbuf, sizeof(strbuf)); ff_dlog(avctx, "channel_layout: %s\n", strbuf); ff_dlog(avctx, "sample_rate: %d\n", s->sample_rate); ff_dlog(avctx, "bit_rate: %d\n", s->bit_rate); @@ -2041,11 +2087,11 @@ int ff_ac3_validate_metadata(AC3EncodeContext *s) /* validate audio service type / channels combination */ if ((avctx->audio_service_type == AV_AUDIO_SERVICE_TYPE_KARAOKE && - avctx->channels == 1) || + avctx->ch_layout.nb_channels == 1) || ((avctx->audio_service_type == AV_AUDIO_SERVICE_TYPE_COMMENTARY || avctx->audio_service_type == AV_AUDIO_SERVICE_TYPE_EMERGENCY || avctx->audio_service_type == AV_AUDIO_SERVICE_TYPE_VOICE_OVER) - && avctx->channels > 1)) { + && avctx->ch_layout.nb_channels > 1)) { av_log(avctx, AV_LOG_ERROR, "invalid audio service type for the " "specified number of channels\n"); return AVERROR(EINVAL); @@ -2167,27 +2213,29 @@ av_cold int ff_ac3_encode_close(AVCodecContext *avctx) /* * Set channel information during initialization. */ -static av_cold int set_channel_info(AC3EncodeContext *s, int channels, - uint64_t *channel_layout) +static av_cold int set_channel_info(AVCodecContext *avctx) { - int ch_layout; + AC3EncodeContext *s = avctx->priv_data; + int channels = avctx->ch_layout.nb_channels; + uint64_t mask = avctx->ch_layout.u.mask; if (channels < 1 || channels > AC3_MAX_CHANNELS) return AVERROR(EINVAL); - if (*channel_layout > 0x7FF) + if (mask > 0x7FF) return AVERROR(EINVAL); - ch_layout = *channel_layout; - if (!ch_layout) - ch_layout = av_get_default_channel_layout(channels); - s->lfe_on = !!(ch_layout & AV_CH_LOW_FREQUENCY); + if (!mask) + av_channel_layout_default(&avctx->ch_layout, channels); + mask = avctx->ch_layout.u.mask; + + s->lfe_on = !!(mask & AV_CH_LOW_FREQUENCY); s->channels = channels; s->fbw_channels = channels - s->lfe_on; s->lfe_channel = s->lfe_on ? s->fbw_channels + 1 : -1; if (s->lfe_on) - ch_layout -= AV_CH_LOW_FREQUENCY; + mask -= AV_CH_LOW_FREQUENCY; - switch (ch_layout) { + switch (mask) { case AV_CH_LAYOUT_MONO: s->channel_mode = AC3_CHMODE_MONO; break; case AV_CH_LAYOUT_STEREO: s->channel_mode = AC3_CHMODE_STEREO; break; case AV_CH_LAYOUT_SURROUND: s->channel_mode = AC3_CHMODE_3F; break; @@ -2204,9 +2252,9 @@ static av_cold int set_channel_info(AC3EncodeContext *s, int channels, s->has_surround = s->channel_mode & 0x04; s->channel_map = ac3_enc_channel_map[s->channel_mode][s->lfe_on]; - *channel_layout = ch_layout; if (s->lfe_on) - *channel_layout |= AV_CH_LOW_FREQUENCY; + mask |= AV_CH_LOW_FREQUENCY; + av_channel_layout_from_mask(&avctx->ch_layout, mask); return 0; } @@ -2218,12 +2266,12 @@ static av_cold int validate_options(AC3EncodeContext *s) int i, ret, max_sr; /* validate channel layout */ - if (!avctx->channel_layout) { + if (!avctx->ch_layout.nb_channels) { av_log(avctx, AV_LOG_WARNING, "No channel layout specified. The " "encoder will guess the layout, but it " "might be incorrect.\n"); } - ret = set_channel_info(s, avctx->channels, &avctx->channel_layout); + ret = set_channel_info(avctx); if (ret) { av_log(avctx, AV_LOG_ERROR, "invalid channel layout\n"); return ret; diff --git a/libavcodec/ac3enc.h b/libavcodec/ac3enc.h index 39a41fe0b..f0dc00675 100644 --- a/libavcodec/ac3enc.h +++ b/libavcodec/ac3enc.h @@ -32,10 +32,11 @@ #include "libavutil/opt.h" #include "ac3.h" +#include "ac3defs.h" #include "ac3dsp.h" #include "avcodec.h" +#include "codec_internal.h" #include "fft.h" -#include "internal.h" #include "mathops.h" #include "me_cmp.h" #include "put_bits.h" @@ -266,11 +267,13 @@ typedef struct AC3EncodeContext { void (*output_frame_header)(struct AC3EncodeContext *s); } AC3EncodeContext; - +#if FF_API_OLD_CHANNEL_LAYOUT extern const uint64_t ff_ac3_channel_layouts[19]; +#endif +extern const AVChannelLayout ff_ac3_ch_layouts[19]; extern const AVOption ff_ac3_enc_options[]; extern const AVClass ff_ac3enc_class; -extern const AVCodecDefault ff_ac3_enc_defaults[]; +extern const FFCodecDefault ff_ac3_enc_defaults[]; int ff_ac3_encode_init(AVCodecContext *avctx); int ff_ac3_float_encode_init(AVCodecContext *avctx); diff --git a/libavcodec/ac3enc_fixed.c b/libavcodec/ac3enc_fixed.c index 80aa98c69..92bf31b03 100644 --- a/libavcodec/ac3enc_fixed.c +++ b/libavcodec/ac3enc_fixed.c @@ -28,9 +28,9 @@ #define AC3ENC_FLOAT 0 #define FFT_FLOAT 0 -#include "internal.h" #include "audiodsp.h" #include "ac3enc.h" +#include "codec_internal.h" #include "eac3enc.h" #include "kbdwin.h" @@ -119,21 +119,26 @@ static av_cold int ac3_fixed_encode_init(AVCodecContext *avctx) } -const AVCodec ff_ac3_fixed_encoder = { - .name = "ac3_fixed", - .long_name = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_AC3, - .capabilities = AV_CODEC_CAP_DR1, +FF_DISABLE_DEPRECATION_WARNINGS +const FFCodec ff_ac3_fixed_encoder = { + .p.name = "ac3_fixed", + .p.long_name = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_AC3, + .p.capabilities = AV_CODEC_CAP_DR1, .priv_data_size = sizeof(AC3EncodeContext), .init = ac3_fixed_encode_init, - .encode2 = ff_ac3_fixed_encode_frame, + FF_CODEC_ENCODE_CB(ff_ac3_fixed_encode_frame), .close = ff_ac3_encode_close, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S32P, + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_NONE }, - .priv_class = &ff_ac3enc_class, + .p.priv_class = &ff_ac3enc_class, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .supported_samplerates = ff_ac3_sample_rate_tab, - .channel_layouts = ff_ac3_channel_layouts, + .p.supported_samplerates = ff_ac3_sample_rate_tab, +#if FF_API_OLD_CHANNEL_LAYOUT + .p.channel_layouts = ff_ac3_channel_layouts, +#endif + .p.ch_layouts = ff_ac3_ch_layouts, .defaults = ff_ac3_enc_defaults, }; +FF_ENABLE_DEPRECATION_WARNINGS diff --git a/libavcodec/ac3enc_float.c b/libavcodec/ac3enc_float.c index e4a3794dd..9f5341cf2 100644 --- a/libavcodec/ac3enc_float.c +++ b/libavcodec/ac3enc_float.c @@ -27,9 +27,9 @@ */ #define AC3ENC_FLOAT 1 -#include "internal.h" #include "audiodsp.h" #include "ac3enc.h" +#include "codec_internal.h" #include "eac3enc.h" #include "kbdwin.h" @@ -123,21 +123,26 @@ av_cold int ff_ac3_float_encode_init(AVCodecContext *avctx) return ff_ac3_encode_init(avctx); } -const AVCodec ff_ac3_encoder = { - .name = "ac3", - .long_name = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_AC3, - .capabilities = AV_CODEC_CAP_DR1, +FF_DISABLE_DEPRECATION_WARNINGS +const FFCodec ff_ac3_encoder = { + .p.name = "ac3", + .p.long_name = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_AC3, + .p.capabilities = AV_CODEC_CAP_DR1, .priv_data_size = sizeof(AC3EncodeContext), .init = ff_ac3_float_encode_init, - .encode2 = ff_ac3_float_encode_frame, + FF_CODEC_ENCODE_CB(ff_ac3_float_encode_frame), .close = ff_ac3_encode_close, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP, + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, - .priv_class = &ff_ac3enc_class, - .supported_samplerates = ff_ac3_sample_rate_tab, - .channel_layouts = ff_ac3_channel_layouts, + .p.priv_class = &ff_ac3enc_class, + .p.supported_samplerates = ff_ac3_sample_rate_tab, +#if FF_API_OLD_CHANNEL_LAYOUT + .p.channel_layouts = ff_ac3_channel_layouts, +#endif + .p.ch_layouts = ff_ac3_ch_layouts, .defaults = ff_ac3_enc_defaults, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; +FF_ENABLE_DEPRECATION_WARNINGS diff --git a/libavcodec/ac3enc_template.c b/libavcodec/ac3enc_template.c index 5ecef3b17..de66964d0 100644 --- a/libavcodec/ac3enc_template.c +++ b/libavcodec/ac3enc_template.c @@ -26,6 +26,8 @@ * AC-3 encoder float/fixed template */ +#include "config_components.h" + #include #include "libavutil/attributes.h" @@ -33,7 +35,6 @@ #include "libavutil/mem_internal.h" #include "audiodsp.h" -#include "internal.h" #include "ac3enc.h" #include "eac3enc.h" diff --git a/libavcodec/ac3tab.c b/libavcodec/ac3tab.c index 766e293a1..48c89a8ba 100644 --- a/libavcodec/ac3tab.c +++ b/libavcodec/ac3tab.c @@ -26,7 +26,6 @@ #include "libavutil/channel_layout.h" -#include "ac3.h" #include "ac3tab.h" /** @@ -114,88 +113,6 @@ const uint8_t ff_eac3_default_cpl_band_struct[18] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1 }; -const uint8_t ff_ac3_log_add_tab[260]= { -0x40,0x3f,0x3e,0x3d,0x3c,0x3b,0x3a,0x39,0x38,0x37, -0x36,0x35,0x34,0x34,0x33,0x32,0x31,0x30,0x2f,0x2f, -0x2e,0x2d,0x2c,0x2c,0x2b,0x2a,0x29,0x29,0x28,0x27, -0x26,0x26,0x25,0x24,0x24,0x23,0x23,0x22,0x21,0x21, -0x20,0x20,0x1f,0x1e,0x1e,0x1d,0x1d,0x1c,0x1c,0x1b, -0x1b,0x1a,0x1a,0x19,0x19,0x18,0x18,0x17,0x17,0x16, -0x16,0x15,0x15,0x15,0x14,0x14,0x13,0x13,0x13,0x12, -0x12,0x12,0x11,0x11,0x11,0x10,0x10,0x10,0x0f,0x0f, -0x0f,0x0e,0x0e,0x0e,0x0d,0x0d,0x0d,0x0d,0x0c,0x0c, -0x0c,0x0c,0x0b,0x0b,0x0b,0x0b,0x0a,0x0a,0x0a,0x0a, -0x0a,0x09,0x09,0x09,0x09,0x09,0x08,0x08,0x08,0x08, -0x08,0x08,0x07,0x07,0x07,0x07,0x07,0x07,0x06,0x06, -0x06,0x06,0x06,0x06,0x06,0x06,0x05,0x05,0x05,0x05, -0x05,0x05,0x05,0x05,0x04,0x04,0x04,0x04,0x04,0x04, -0x04,0x04,0x04,0x04,0x04,0x03,0x03,0x03,0x03,0x03, -0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x02, -0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, -0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x01,0x01, -0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, -0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, -0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -}; - -const uint16_t ff_ac3_hearing_threshold_tab[AC3_CRITICAL_BANDS][3]= { -{ 0x04d0,0x04f0,0x0580 }, -{ 0x04d0,0x04f0,0x0580 }, -{ 0x0440,0x0460,0x04b0 }, -{ 0x0400,0x0410,0x0450 }, -{ 0x03e0,0x03e0,0x0420 }, -{ 0x03c0,0x03d0,0x03f0 }, -{ 0x03b0,0x03c0,0x03e0 }, -{ 0x03b0,0x03b0,0x03d0 }, -{ 0x03a0,0x03b0,0x03c0 }, -{ 0x03a0,0x03a0,0x03b0 }, -{ 0x03a0,0x03a0,0x03b0 }, -{ 0x03a0,0x03a0,0x03b0 }, -{ 0x03a0,0x03a0,0x03a0 }, -{ 0x0390,0x03a0,0x03a0 }, -{ 0x0390,0x0390,0x03a0 }, -{ 0x0390,0x0390,0x03a0 }, -{ 0x0380,0x0390,0x03a0 }, -{ 0x0380,0x0380,0x03a0 }, -{ 0x0370,0x0380,0x03a0 }, -{ 0x0370,0x0380,0x03a0 }, -{ 0x0360,0x0370,0x0390 }, -{ 0x0360,0x0370,0x0390 }, -{ 0x0350,0x0360,0x0390 }, -{ 0x0350,0x0360,0x0390 }, -{ 0x0340,0x0350,0x0380 }, -{ 0x0340,0x0350,0x0380 }, -{ 0x0330,0x0340,0x0380 }, -{ 0x0320,0x0340,0x0370 }, -{ 0x0310,0x0320,0x0360 }, -{ 0x0300,0x0310,0x0350 }, -{ 0x02f0,0x0300,0x0340 }, -{ 0x02f0,0x02f0,0x0330 }, -{ 0x02f0,0x02f0,0x0320 }, -{ 0x02f0,0x02f0,0x0310 }, -{ 0x0300,0x02f0,0x0300 }, -{ 0x0310,0x0300,0x02f0 }, -{ 0x0340,0x0320,0x02f0 }, -{ 0x0390,0x0350,0x02f0 }, -{ 0x03e0,0x0390,0x0300 }, -{ 0x0420,0x03e0,0x0310 }, -{ 0x0460,0x0420,0x0330 }, -{ 0x0490,0x0450,0x0350 }, -{ 0x04a0,0x04a0,0x03c0 }, -{ 0x0460,0x0490,0x0410 }, -{ 0x0440,0x0460,0x0470 }, -{ 0x0440,0x0440,0x04a0 }, -{ 0x0520,0x0480,0x0460 }, -{ 0x0800,0x0630,0x0440 }, -{ 0x0840,0x0840,0x0450 }, -{ 0x0840,0x0840,0x04e0 }, -}; - const uint8_t ff_ac3_bap_tab[64]= { 0, 1, 1, 1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, diff --git a/libavcodec/ac3tab.h b/libavcodec/ac3tab.h index bc470204f..2531d8067 100644 --- a/libavcodec/ac3tab.h +++ b/libavcodec/ac3tab.h @@ -24,7 +24,7 @@ #include -#include "ac3.h" +#include "ac3defs.h" extern const uint16_t ff_ac3_frame_size_tab[38][3]; extern const uint8_t ff_ac3_channels_tab[8]; @@ -34,8 +34,6 @@ extern const int ff_ac3_sample_rate_tab[]; extern const uint16_t ff_ac3_bitrate_tab[19]; extern const uint8_t ff_ac3_rematrix_band_tab[5]; extern const uint8_t ff_eac3_default_cpl_band_struct[18]; -extern const uint8_t ff_ac3_log_add_tab[260]; -extern const uint16_t ff_ac3_hearing_threshold_tab[AC3_CRITICAL_BANDS][3]; extern const uint8_t ff_ac3_bap_tab[64]; extern const uint8_t ff_ac3_slow_decay_tab[4]; extern const uint8_t ff_ac3_fast_decay_tab[4]; diff --git a/libavcodec/acelp_filters.c b/libavcodec/acelp_filters.c index b950ba6cb..918257933 100644 --- a/libavcodec/acelp_filters.c +++ b/libavcodec/acelp_filters.c @@ -152,6 +152,7 @@ void ff_acelp_filter_init(ACELPFContext *c) c->acelp_interpolatef = ff_acelp_interpolatef; c->acelp_apply_order_2_transfer_function = ff_acelp_apply_order_2_transfer_function; - if(HAVE_MIPSFPU) - ff_acelp_filter_init_mips(c); +#if HAVE_MIPSFPU + ff_acelp_filter_init_mips(c); +#endif } diff --git a/libavcodec/acelp_vectors.c b/libavcodec/acelp_vectors.c index 8adea683c..b8a2b50dd 100644 --- a/libavcodec/acelp_vectors.c +++ b/libavcodec/acelp_vectors.c @@ -259,6 +259,7 @@ void ff_acelp_vectors_init(ACELPVContext *c) { c->weighted_vector_sumf = ff_weighted_vector_sumf; - if(HAVE_MIPSFPU) - ff_acelp_vectors_init_mips(c); +#if HAVE_MIPSFPU + ff_acelp_vectors_init_mips(c); +#endif } diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c index cfde5f58b..b2ef7dfbe 100644 --- a/libavcodec/adpcm.c +++ b/libavcodec/adpcm.c @@ -34,11 +34,15 @@ * 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_components.h" + #include "avcodec.h" #include "get_bits.h" #include "bytestream.h" #include "adpcm.h" #include "adpcm_data.h" +#include "codec_internal.h" #include "internal.h" /** @@ -271,14 +275,15 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx) case AV_CODEC_ID_ADPCM_MTAF: min_channels = 2; max_channels = 8; - if (avctx->channels & 1) { - avpriv_request_sample(avctx, "channel count %d", avctx->channels); + if (avctx->ch_layout.nb_channels & 1) { + avpriv_request_sample(avctx, "channel count %d", avctx->ch_layout.nb_channels); return AVERROR_PATCHWELCOME; } break; case AV_CODEC_ID_ADPCM_PSX: max_channels = 8; - if (avctx->channels <= 0 || avctx->block_align % (16 * avctx->channels)) + if (avctx->ch_layout.nb_channels <= 0 || + avctx->block_align % (16 * avctx->ch_layout.nb_channels)) return AVERROR_INVALIDDATA; break; case AV_CODEC_ID_ADPCM_IMA_DAT4: @@ -287,7 +292,8 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx) max_channels = 14; break; } - if (avctx->channels < min_channels || avctx->channels > max_channels) { + if (avctx->ch_layout.nb_channels < min_channels || + avctx->ch_layout.nb_channels > max_channels) { av_log(avctx, AV_LOG_ERROR, "Invalid number of channels\n"); return AVERROR(EINVAL); } @@ -298,7 +304,8 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx) return AVERROR_INVALIDDATA; break; case AV_CODEC_ID_ADPCM_ARGO: - if (avctx->bits_per_coded_sample != 4 || avctx->block_align != 17 * avctx->channels) + if (avctx->bits_per_coded_sample != 4 || + avctx->block_align != 17 * avctx->ch_layout.nb_channels) return AVERROR_INVALIDDATA; break; case AV_CODEC_ID_ADPCM_ZORK: @@ -336,7 +343,7 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx) AV_SAMPLE_FMT_S16; break; case AV_CODEC_ID_ADPCM_MS: - avctx->sample_fmt = avctx->channels > 2 ? AV_SAMPLE_FMT_S16P : + avctx->sample_fmt = avctx->ch_layout.nb_channels > 2 ? AV_SAMPLE_FMT_S16P : AV_SAMPLE_FMT_S16; break; default: @@ -755,6 +762,7 @@ static void adpcm_swf_decode(AVCodecContext *avctx, const uint8_t *buf, int buf_ ADPCMDecodeContext *c = avctx->priv_data; GetBitContext gb; const int8_t *table; + int channels = avctx->ch_layout.nb_channels; int k0, signmask, nb_bits, count; int size = buf_size*8; int i; @@ -767,16 +775,16 @@ static void adpcm_swf_decode(AVCodecContext *avctx, const uint8_t *buf, int buf_ k0 = 1 << (nb_bits-2); signmask = 1 << (nb_bits-1); - while (get_bits_count(&gb) <= size - 22*avctx->channels) { - for (i = 0; i < avctx->channels; i++) { + while (get_bits_count(&gb) <= size - 22 * channels) { + for (i = 0; i < channels; i++) { *samples++ = c->status[i].predictor = get_sbits(&gb, 16); c->status[i].step_index = get_bits(&gb, 6); } - for (count = 0; get_bits_count(&gb) <= size - nb_bits*avctx->channels && count < 4095; count++) { + for (count = 0; get_bits_count(&gb) <= size - nb_bits * channels && count < 4095; count++) { int i; - for (i = 0; i < avctx->channels; i++) { + for (i = 0; i < channels; i++) { // similar to IMA adpcm int delta = get_bits(&gb, nb_bits); int step = ff_adpcm_step_table[c->status[i].step_index]; @@ -840,7 +848,7 @@ static int get_nb_samples(AVCodecContext *avctx, GetByteContext *gb, { ADPCMDecodeContext *s = avctx->priv_data; int nb_samples = 0; - int ch = avctx->channels; + int ch = avctx->ch_layout.nb_channels; int has_coded_samples = 0; int header_size; @@ -1054,13 +1062,13 @@ static int get_nb_samples(AVCodecContext *avctx, GetByteContext *gb, return nb_samples; } -static int adpcm_decode_frame(AVCodecContext *avctx, void *data, +static int adpcm_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; ADPCMDecodeContext *c = avctx->priv_data; + int channels = avctx->ch_layout.nb_channels; int16_t *samples; int16_t **samples_p; int st; /* stereo */ @@ -1089,13 +1097,13 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, frame->nb_samples = nb_samples = coded_samples; } - st = avctx->channels == 2 ? 1 : 0; + st = channels == 2 ? 1 : 0; switch(avctx->codec->id) { CASE(ADPCM_IMA_QT, /* In QuickTime, IMA is encoded by chunks of 34 bytes (=64 samples). Channel data is interleaved per-chunk. */ - for (int channel = 0; channel < avctx->channels; channel++) { + for (int channel = 0; channel < channels; channel++) { ADPCMChannelStatus *cs = &c->status[channel]; int predictor; int step_index; @@ -1134,7 +1142,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, } ) /* End of CASE */ CASE(ADPCM_IMA_WAV, - for (int i = 0; i < avctx->channels; i++) { + for (int i = 0; i < channels; i++) { ADPCMChannelStatus *cs = &c->status[i]; cs->predictor = samples_p[i][0] = sign_extend(bytestream2_get_le16u(&gb), 16); @@ -1153,12 +1161,12 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, GetBitContext g; for (int n = 0; n < (nb_samples - 1) / samples_per_block; n++) { - for (int i = 0; i < avctx->channels; i++) { + for (int i = 0; i < channels; i++) { ADPCMChannelStatus *cs = &c->status[i]; samples = &samples_p[i][1 + n * samples_per_block]; for (int j = 0; j < block_size; j++) { - temp[j] = buf[4 * avctx->channels + block_size * n * avctx->channels + - (j % 4) + (j / 4) * (avctx->channels * 4) + i * 4]; + temp[j] = buf[4 * channels + block_size * n * channels + + (j % 4) + (j / 4) * (channels * 4) + i * 4]; } ret = init_get_bits8(&g, (const uint8_t *)&temp, block_size); if (ret < 0) @@ -1169,10 +1177,10 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, } } } - bytestream2_skip(&gb, avctx->block_align - avctx->channels * 4); + bytestream2_skip(&gb, avctx->block_align - channels * 4); } else { for (int n = 0; n < (nb_samples - 1) / 8; n++) { - for (int i = 0; i < avctx->channels; i++) { + for (int i = 0; i < channels; i++) { ADPCMChannelStatus *cs = &c->status[i]; samples = &samples_p[i][1 + n * 8]; for (int m = 0; m < 8; m += 2) { @@ -1185,10 +1193,10 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, } ) /* End of CASE */ CASE(ADPCM_4XM, - for (int i = 0; i < avctx->channels; i++) + for (int i = 0; i < channels; i++) c->status[i].predictor = sign_extend(bytestream2_get_le16u(&gb), 16); - for (int i = 0; i < avctx->channels; i++) { + for (int i = 0; i < channels; i++) { c->status[i].step_index = sign_extend(bytestream2_get_le16u(&gb), 16); if (c->status[i].step_index > 88u) { av_log(avctx, AV_LOG_ERROR, "ERROR: step_index[%d] = %i\n", @@ -1197,7 +1205,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, } } - for (int i = 0; i < avctx->channels; i++) { + for (int i = 0; i < channels; i++) { ADPCMChannelStatus *cs = &c->status[i]; samples = (int16_t *)frame->data[i]; for (int n = nb_samples >> 1; n > 0; n--) { @@ -1208,9 +1216,9 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, } ) /* End of CASE */ CASE(ADPCM_AGM, - for (int i = 0; i < avctx->channels; i++) + for (int i = 0; i < channels; i++) c->status[i].predictor = sign_extend(bytestream2_get_le16u(&gb), 16); - for (int i = 0; i < avctx->channels; i++) + for (int i = 0; i < channels; i++) c->status[i].step = sign_extend(bytestream2_get_le16u(&gb), 16); for (int n = 0; n < nb_samples >> (1 - st); n++) { @@ -1222,8 +1230,8 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, CASE(ADPCM_MS, int block_predictor; - if (avctx->channels > 2) { - for (int channel = 0; channel < avctx->channels; channel++) { + if (avctx->ch_layout.nb_channels > 2) { + for (int channel = 0; channel < avctx->ch_layout.nb_channels; channel++) { samples = samples_p[channel]; block_predictor = bytestream2_get_byteu(&gb); if (block_predictor > 6) { @@ -1285,7 +1293,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, } ) /* End of CASE */ CASE(ADPCM_MTAF, - for (int channel = 0; channel < avctx->channels; channel += 2) { + for (int channel = 0; channel < channels; channel += 2) { bytestream2_skipu(&gb, 4); c->status[channel ].step = bytestream2_get_le16u(&gb) & 0x1f; c->status[channel + 1].step = bytestream2_get_le16u(&gb) & 0x1f; @@ -1306,7 +1314,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, } ) /* End of CASE */ CASE(ADPCM_IMA_DK4, - for (int channel = 0; channel < avctx->channels; channel++) { + for (int channel = 0; channel < channels; channel++) { ADPCMChannelStatus *cs = &c->status[channel]; cs->predictor = *samples++ = sign_extend(bytestream2_get_le16u(&gb), 16); cs->step_index = sign_extend(bytestream2_get_le16u(&gb), 16); @@ -1338,7 +1346,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, int nibble; int decode_top_nibble_next = 0; int diff_channel; - const int16_t *samples_end = samples + avctx->channels * nb_samples; + const int16_t *samples_end = samples + channels * nb_samples; bytestream2_skipu(&gb, 10); c->status[0].predictor = sign_extend(bytestream2_get_le16u(&gb), 16); @@ -1385,7 +1393,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, bytestream2_skip(&gb, 1); ) /* End of CASE */ CASE(ADPCM_IMA_ISS, - for (int channel = 0; channel < avctx->channels; channel++) { + for (int channel = 0; channel < channels; channel++) { ADPCMChannelStatus *cs = &c->status[channel]; cs->predictor = sign_extend(bytestream2_get_le16u(&gb), 16); cs->step_index = sign_extend(bytestream2_get_le16u(&gb), 16); @@ -1412,7 +1420,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, } ) /* End of CASE */ CASE(ADPCM_IMA_MOFLEX, - for (int channel = 0; channel < avctx->channels; channel++) { + for (int channel = 0; channel < channels; channel++) { ADPCMChannelStatus *cs = &c->status[channel]; cs->step_index = sign_extend(bytestream2_get_le16u(&gb), 16); cs->predictor = sign_extend(bytestream2_get_le16u(&gb), 16); @@ -1424,7 +1432,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, } for (int subframe = 0; subframe < nb_samples / 256; subframe++) { - for (int channel = 0; channel < avctx->channels; channel++) { + for (int channel = 0; channel < channels; channel++) { samples = samples_p[channel] + 256 * subframe; for (int n = 0; n < 256; n += 2) { int v = bytestream2_get_byteu(&gb); @@ -1435,7 +1443,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, } ) /* End of CASE */ CASE(ADPCM_IMA_DAT4, - for (int channel = 0; channel < avctx->channels; channel++) { + for (int channel = 0; channel < channels; channel++) { ADPCMChannelStatus *cs = &c->status[channel]; samples = samples_p[channel]; bytestream2_skip(&gb, 4); @@ -1462,26 +1470,26 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, ) /* End of CASE */ CASE(ADPCM_IMA_APM, for (int n = nb_samples / 2; n > 0; n--) { - for (int channel = 0; channel < avctx->channels; channel++) { + for (int channel = 0; channel < channels; channel++) { int v = bytestream2_get_byteu(&gb); *samples++ = adpcm_ima_qt_expand_nibble(&c->status[channel], v >> 4 ); samples[st] = adpcm_ima_qt_expand_nibble(&c->status[channel], v & 0x0F); } - samples += avctx->channels; + samples += channels; } ) /* End of CASE */ CASE(ADPCM_IMA_ALP, for (int n = nb_samples / 2; n > 0; n--) { - for (int channel = 0; channel < avctx->channels; channel++) { + for (int channel = 0; channel < channels; channel++) { int v = bytestream2_get_byteu(&gb); *samples++ = adpcm_ima_alp_expand_nibble(&c->status[channel], v >> 4 , 2); samples[st] = adpcm_ima_alp_expand_nibble(&c->status[channel], v & 0x0F, 2); } - samples += avctx->channels; + samples += channels; } ) /* End of CASE */ CASE(ADPCM_IMA_CUNNING, - for (int channel = 0; channel < avctx->channels; channel++) { + for (int channel = 0; channel < channels; channel++) { int16_t *smp = samples_p[channel]; for (int n = 0; n < nb_samples / 2; n++) { int v = bytestream2_get_byteu(&gb); @@ -1498,7 +1506,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, } ) /* End of CASE */ CASE(ADPCM_IMA_RAD, - for (int channel = 0; channel < avctx->channels; channel++) { + for (int channel = 0; channel < channels; channel++) { ADPCMChannelStatus *cs = &c->status[channel]; cs->step_index = sign_extend(bytestream2_get_le16u(&gb), 16); cs->predictor = sign_extend(bytestream2_get_le16u(&gb), 16); @@ -1514,17 +1522,17 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, byte[0] = bytestream2_get_byteu(&gb); if (st) byte[1] = bytestream2_get_byteu(&gb); - for (int channel = 0; channel < avctx->channels; channel++) { + for (int channel = 0; channel < channels; channel++) { *samples++ = adpcm_ima_expand_nibble(&c->status[channel], byte[channel] & 0x0F, 3); } - for (int channel = 0; channel < avctx->channels; channel++) { + for (int channel = 0; channel < channels; channel++) { *samples++ = adpcm_ima_expand_nibble(&c->status[channel], byte[channel] >> 4 , 3); } } ) /* End of CASE */ CASE(ADPCM_IMA_WS, if (c->vqa_version == 3) { - for (int channel = 0; channel < avctx->channels; channel++) { + for (int channel = 0; channel < channels; channel++) { int16_t *smp = samples_p[channel]; for (int n = nb_samples / 2; n > 0; n--) { @@ -1535,12 +1543,12 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, } } else { for (int n = nb_samples / 2; n > 0; n--) { - for (int channel = 0; channel < avctx->channels; channel++) { + for (int channel = 0; channel < channels; channel++) { int v = bytestream2_get_byteu(&gb); *samples++ = adpcm_ima_expand_nibble(&c->status[channel], v & 0x0F, 3); samples[st] = adpcm_ima_expand_nibble(&c->status[channel], v >> 4 , 3); } - samples += avctx->channels; + samples += channels; } } bytestream2_seek(&gb, 0, SEEK_END); @@ -1548,13 +1556,13 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, CASE(ADPCM_XA, int16_t *out0 = samples_p[0]; int16_t *out1 = samples_p[1]; - int samples_per_block = 28 * (3 - avctx->channels) * 4; + int samples_per_block = 28 * (3 - 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], - avctx->channels, sample_offset)) < 0) + channels, sample_offset)) < 0) return ret; bytestream2_skipu(&gb, 128); sample_offset += samples_per_block; @@ -1604,7 +1612,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, /* Each EA ADPCM frame has a 12-byte header followed by 30-byte pieces, each coding 28 stereo samples. */ - if(avctx->channels != 2) + if (channels != 2) return AVERROR_INVALIDDATA; current_left_sample = sign_extend(bytestream2_get_le16u(&gb), 16); @@ -1649,7 +1657,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, CASE(ADPCM_EA_MAXIS_XA, int coeff[2][2], shift[2]; - for (int channel = 0; channel < avctx->channels; channel++) { + for (int channel = 0; channel < channels; channel++) { int byte = bytestream2_get_byteu(&gb); for (int i = 0; i < 2; i++) coeff[channel][i] = ea_adpcm_table[(byte >> 4) + 4*i]; @@ -1661,7 +1669,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, byte[0] = bytestream2_get_byteu(&gb); if (st) byte[1] = bytestream2_get_byteu(&gb); for (int i = 4; i >= 0; i-=4) { /* Pairwise samples LL RR (st) or LL LL (mono) */ - for (int channel = 0; channel < avctx->channels; channel++) { + for (int channel = 0; channel < channels; channel++) { int sample = sign_extend(byte[channel] >> i, 4) * (1 << shift[channel]); sample = (sample + c->status[channel].sample1 * coeff[channel][0] + @@ -1690,12 +1698,12 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, int count = 0; int offsets[6]; - for (unsigned channel = 0; channel < avctx->channels; channel++) + for (unsigned channel = 0; channel < channels; channel++) offsets[channel] = (big_endian ? bytestream2_get_be32(&gb) : bytestream2_get_le32(&gb)) + - (avctx->channels + 1) * 4; + (channels + 1) * 4; - for (unsigned channel = 0; channel < avctx->channels; channel++) { + for (unsigned channel = 0; channel < channels; channel++) { int count1; bytestream2_seek(&gb, offsets[channel], SEEK_SET); @@ -1759,7 +1767,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, } #endif /* CONFIG_ADPCM_EA_Rx_DECODER */ CASE(ADPCM_EA_XAS, - for (int channel=0; channel < avctx->channels; channel++) { + for (int channel=0; channel < channels; channel++) { int coeff[2][4], shift[4]; int16_t *s = samples_p[channel]; for (int n = 0; n < 4; n++, s += 32) { @@ -1791,7 +1799,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, } ) /* End of CASE */ CASE(ADPCM_IMA_ACORN, - for (int channel = 0; channel < avctx->channels; channel++) { + for (int channel = 0; channel < channels; channel++) { ADPCMChannelStatus *cs = &c->status[channel]; cs->predictor = sign_extend(bytestream2_get_le16u(&gb), 16); cs->step_index = bytestream2_get_le16u(&gb) & 0xFF; @@ -1808,7 +1816,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, } ) /* End of CASE */ CASE(ADPCM_IMA_AMV, - av_assert0(avctx->channels == 1); + av_assert0(channels == 1); /* * Header format: @@ -1848,7 +1856,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, } ) /* End of CASE */ CASE(ADPCM_IMA_SMJPEG, - for (int i = 0; i < avctx->channels; i++) { + for (int i = 0; i < channels; i++) { c->status[i].predictor = sign_extend(bytestream2_get_be16u(&gb), 16); c->status[i].step_index = bytestream2_get_byteu(&gb); bytestream2_skipu(&gb, 1); @@ -1931,7 +1939,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, } ) /* End of CASE */ CASE(ADPCM_AICA, - for (int channel = 0; channel < avctx->channels; channel++) { + for (int channel = 0; channel < channels; channel++) { samples = samples_p[channel]; for (int n = nb_samples >> 1; n > 0; n--) { int v = bytestream2_get_byteu(&gb); @@ -1953,7 +1961,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, } for (int m = 0; m < blocks; m++) { - for (int channel = 0; channel < avctx->channels; channel++) { + for (int channel = 0; channel < channels; channel++) { int prev1 = c->status[channel].sample1; int prev2 = c->status[channel].sample2; @@ -2005,33 +2013,33 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, if (avctx->extradata) { GetByteContext tb; - if (avctx->extradata_size < 32 * avctx->channels) { + if (avctx->extradata_size < 32 * channels) { av_log(avctx, AV_LOG_ERROR, "Missing coeff table\n"); return AVERROR_INVALIDDATA; } bytestream2_init(&tb, avctx->extradata, avctx->extradata_size); - for (int i = 0; i < avctx->channels; i++) + for (int i = 0; i < channels; i++) for (int n = 0; n < 16; n++) table[i][n] = THP_GET16(tb); } else { - for (int i = 0; i < avctx->channels; i++) + for (int i = 0; i < channels; i++) for (int n = 0; n < 16; n++) table[i][n] = THP_GET16(gb); if (!c->has_status) { /* Initialize the previous sample. */ - for (int i = 0; i < avctx->channels; i++) { + for (int i = 0; i < channels; i++) { c->status[i].sample1 = THP_GET16(gb); c->status[i].sample2 = THP_GET16(gb); } c->has_status = 1; } else { - bytestream2_skip(&gb, avctx->channels * 4); + bytestream2_skip(&gb, channels * 4); } } - for (int ch = 0; ch < avctx->channels; ch++) { + for (int ch = 0; ch < channels; ch++) { samples = samples_p[ch]; /* Read in every sample for this channel. */ @@ -2065,7 +2073,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, } #endif /* CONFIG_ADPCM_THP(_LE)_DECODER */ CASE(ADPCM_DTK, - for (int channel = 0; channel < avctx->channels; channel++) { + for (int channel = 0; channel < channels; channel++) { samples = samples_p[channel]; /* Read in every sample for this channel. */ @@ -2113,9 +2121,9 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, } ) /* End of CASE */ CASE(ADPCM_PSX, - for (int block = 0; block < avpkt->size / FFMAX(avctx->block_align, 16 * avctx->channels); block++) { - int nb_samples_per_block = 28 * FFMAX(avctx->block_align, 16 * avctx->channels) / (16 * avctx->channels); - for (int channel = 0; channel < avctx->channels; channel++) { + for (int block = 0; block < avpkt->size / FFMAX(avctx->block_align, 16 * channels); block++) { + int nb_samples_per_block = 28 * FFMAX(avctx->block_align, 16 * channels) / (16 * channels); + for (int channel = 0; channel < channels; channel++) { samples = samples_p[channel] + block * nb_samples_per_block; av_assert0((block + 1) * nb_samples_per_block <= nb_samples); @@ -2172,7 +2180,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, * They should be 0 initially. */ for (int block = 0; block < avpkt->size / avctx->block_align; block++) { - for (int channel = 0; channel < avctx->channels; channel++) { + for (int channel = 0; channel < avctx->ch_layout.nb_channels; channel++) { ADPCMChannelStatus *cs = c->status + channel; int control, shift; @@ -2191,19 +2199,19 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, } ) /* End of CASE */ CASE(ADPCM_ZORK, - for (int n = 0; n < nb_samples * avctx->channels; n++) { + for (int n = 0; n < nb_samples * channels; n++) { int v = bytestream2_get_byteu(&gb); - *samples++ = adpcm_zork_expand_nibble(&c->status[n % avctx->channels], v); + *samples++ = adpcm_zork_expand_nibble(&c->status[n % channels], v); } ) /* End of CASE */ CASE(ADPCM_IMA_MTF, for (int n = nb_samples / 2; n > 0; n--) { - for (int channel = 0; channel < avctx->channels; channel++) { + for (int channel = 0; channel < channels; channel++) { int v = bytestream2_get_byteu(&gb); *samples++ = adpcm_ima_mtf_expand_nibble(&c->status[channel], v >> 4); samples[st] = adpcm_ima_mtf_expand_nibble(&c->status[channel], v & 0x0F); } - samples += avctx->channels; + samples += channels; } ) /* End of CASE */ default: @@ -2277,17 +2285,17 @@ static const enum AVSampleFormat sample_fmts_both[] = { AV_SAMPLE_FMT_S16, #define ADPCM_DECODER_0(id_, sample_fmts_, name_, long_name_) #define ADPCM_DECODER_1(id_, sample_fmts_, name_, long_name_) \ -const AVCodec ff_ ## name_ ## _decoder = { \ - .name = #name_, \ - .long_name = NULL_IF_CONFIG_SMALL(long_name_), \ - .type = AVMEDIA_TYPE_AUDIO, \ - .id = id_, \ +const FFCodec ff_ ## name_ ## _decoder = { \ + .p.name = #name_, \ + .p.long_name = NULL_IF_CONFIG_SMALL(long_name_), \ + .p.type = AVMEDIA_TYPE_AUDIO, \ + .p.id = id_, \ + .p.capabilities = AV_CODEC_CAP_DR1, \ + .p.sample_fmts = sample_fmts_, \ .priv_data_size = sizeof(ADPCMDecodeContext), \ .init = adpcm_decode_init, \ - .decode = adpcm_decode_frame, \ + FF_CODEC_DECODE_CB(adpcm_decode_frame), \ .flush = adpcm_flush, \ - .capabilities = AV_CODEC_CAP_DR1, \ - .sample_fmts = sample_fmts_, \ .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, \ }; #define ADPCM_DECODER_2(enabled, codec_id, name, sample_fmts, long_name) \ diff --git a/libavcodec/adpcmenc.c b/libavcodec/adpcmenc.c index b0f6f209b..4ff77662b 100644 --- a/libavcodec/adpcmenc.c +++ b/libavcodec/adpcmenc.c @@ -22,6 +22,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/opt.h" #include "avcodec.h" @@ -29,8 +31,8 @@ #include "bytestream.h" #include "adpcm.h" #include "adpcm_data.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" /** * @file @@ -79,11 +81,7 @@ typedef struct ADPCMEncodeContext { static av_cold int adpcm_encode_init(AVCodecContext *avctx) { ADPCMEncodeContext *s = avctx->priv_data; - - if (avctx->channels > 2) { - av_log(avctx, AV_LOG_ERROR, "only stereo or mono is supported\n"); - return AVERROR(EINVAL); - } + int channels = avctx->ch_layout.nb_channels; /* * AMV's block size has to match that of the corresponding video @@ -130,8 +128,8 @@ static av_cold int adpcm_encode_init(AVCodecContext *avctx) CASE(ADPCM_IMA_WAV, /* each 16 bits sample gives one nibble and we have 4 bytes per channel overhead */ - avctx->frame_size = (s->block_size - 4 * avctx->channels) * 8 / - (4 * avctx->channels) + 1; + avctx->frame_size = (s->block_size - 4 * channels) * 8 / + (4 * channels) + 1; /* seems frame_size isn't taken into account... have to buffer the samples :-( */ avctx->block_align = s->block_size; @@ -139,13 +137,13 @@ static av_cold int adpcm_encode_init(AVCodecContext *avctx) ) /* End of CASE */ CASE(ADPCM_IMA_QT, avctx->frame_size = 64; - avctx->block_align = 34 * avctx->channels; + avctx->block_align = 34 * channels; ) /* End of CASE */ CASE(ADPCM_MS, uint8_t *extradata; /* each 16 bits sample gives one nibble and we have 7 bytes per channel overhead */ - avctx->frame_size = (s->block_size - 7 * avctx->channels) * 2 / avctx->channels + 2; + avctx->frame_size = (s->block_size - 7 * channels) * 2 / channels + 2; avctx->bits_per_coded_sample = 4; avctx->block_align = s->block_size; if (!(avctx->extradata = av_malloc(32 + AV_INPUT_BUFFER_PADDING_SIZE))) @@ -160,7 +158,7 @@ static av_cold int adpcm_encode_init(AVCodecContext *avctx) } ) /* End of CASE */ CASE(ADPCM_YAMAHA, - avctx->frame_size = s->block_size * 2 / avctx->channels; + avctx->frame_size = s->block_size * 2 / channels; avctx->block_align = s->block_size; ) /* End of CASE */ CASE(ADPCM_SWF, @@ -172,11 +170,11 @@ static av_cold int adpcm_encode_init(AVCodecContext *avctx) return AVERROR(EINVAL); } avctx->frame_size = 4096; /* Hardcoded according to the SWF spec. */ - avctx->block_align = (2 + avctx->channels * (22 + 4 * (avctx->frame_size - 1)) + 7) / 8; + avctx->block_align = (2 + channels * (22 + 4 * (avctx->frame_size - 1)) + 7) / 8; ) /* End of CASE */ case AV_CODEC_ID_ADPCM_IMA_SSI: case AV_CODEC_ID_ADPCM_IMA_ALP: - avctx->frame_size = s->block_size * 2 / avctx->channels; + avctx->frame_size = s->block_size * 2 / channels; avctx->block_align = s->block_size; break; CASE(ADPCM_IMA_AMV, @@ -185,7 +183,7 @@ static av_cold int adpcm_encode_init(AVCodecContext *avctx) return AVERROR(EINVAL); } - if (avctx->channels != 1) { + if (channels != 1) { av_log(avctx, AV_LOG_ERROR, "Only mono is supported\n"); return AVERROR(EINVAL); } @@ -194,7 +192,7 @@ static av_cold int adpcm_encode_init(AVCodecContext *avctx) avctx->block_align = 8 + (FFALIGN(avctx->frame_size, 2) / 2); ) /* End of CASE */ CASE(ADPCM_IMA_APM, - avctx->frame_size = s->block_size * 2 / avctx->channels; + avctx->frame_size = s->block_size * 2 / channels; avctx->block_align = s->block_size; if (!(avctx->extradata = av_mallocz(28 + AV_INPUT_BUFFER_PADDING_SIZE))) @@ -203,11 +201,11 @@ static av_cold int adpcm_encode_init(AVCodecContext *avctx) ) /* End of CASE */ CASE(ADPCM_ARGO, avctx->frame_size = 32; - avctx->block_align = 17 * avctx->channels; + avctx->block_align = 17 * channels; ) /* End of CASE */ CASE(ADPCM_IMA_WS, /* each 16 bits sample gives one nibble */ - avctx->frame_size = s->block_size * 2 / avctx->channels; + avctx->frame_size = s->block_size * 2 / channels; avctx->block_align = s->block_size; ) /* End of CASE */ default: @@ -606,16 +604,17 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, int16_t **samples_p; uint8_t *dst; ADPCMEncodeContext *c = avctx->priv_data; + int channels = avctx->ch_layout.nb_channels; samples = (const int16_t *)frame->data[0]; samples_p = (int16_t **)frame->extended_data; - st = avctx->channels == 2; + st = channels == 2; if (avctx->codec_id == AV_CODEC_ID_ADPCM_IMA_SSI || avctx->codec_id == AV_CODEC_ID_ADPCM_IMA_ALP || avctx->codec_id == AV_CODEC_ID_ADPCM_IMA_APM || avctx->codec_id == AV_CODEC_ID_ADPCM_IMA_WS) - pkt_size = (frame->nb_samples * avctx->channels) / 2; + pkt_size = (frame->nb_samples * channels) / 2; else pkt_size = avctx->block_align; if ((ret = ff_get_encode_buffer(avctx, avpkt, pkt_size, 0)) < 0) @@ -626,7 +625,7 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, CASE(ADPCM_IMA_WAV, int blocks = (frame->nb_samples - 1) / 8; - for (int ch = 0; ch < avctx->channels; ch++) { + for (int ch = 0; ch < channels; ch++) { ADPCMChannelStatus *status = &c->status[ch]; status->prev_sample = samples_p[ch][0]; /* status->step_index = 0; @@ -639,15 +638,15 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, /* stereo: 4 bytes (8 samples) for left, 4 bytes for right */ if (avctx->trellis > 0) { uint8_t *buf; - if (!FF_ALLOC_TYPED_ARRAY(buf, avctx->channels * blocks * 8)) + if (!FF_ALLOC_TYPED_ARRAY(buf, channels * blocks * 8)) return AVERROR(ENOMEM); - for (int ch = 0; ch < avctx->channels; ch++) { + for (int ch = 0; ch < channels; ch++) { adpcm_compress_trellis(avctx, &samples_p[ch][1], buf + ch * blocks * 8, &c->status[ch], blocks * 8, 1); } for (int i = 0; i < blocks; i++) { - for (int ch = 0; ch < avctx->channels; ch++) { + for (int ch = 0; ch < channels; ch++) { uint8_t *buf1 = buf + ch * blocks * 8 + i * 8; for (int j = 0; j < 8; j += 2) *dst++ = buf1[j] | (buf1[j + 1] << 4); @@ -656,7 +655,7 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, av_free(buf); } else { for (int i = 0; i < blocks; i++) { - for (int ch = 0; ch < avctx->channels; ch++) { + for (int ch = 0; ch < channels; ch++) { ADPCMChannelStatus *status = &c->status[ch]; const int16_t *smp = &samples_p[ch][1 + i * 8]; for (int j = 0; j < 8; j += 2) { @@ -672,7 +671,7 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, PutBitContext pb; init_put_bits(&pb, dst, pkt_size); - for (int ch = 0; ch < avctx->channels; ch++) { + for (int ch = 0; ch < channels; ch++) { ADPCMChannelStatus *status = &c->status[ch]; put_bits(&pb, 9, (status->prev_sample & 0xFFFF) >> 7); put_bits(&pb, 7, status->step_index); @@ -703,7 +702,7 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, av_assert0(avctx->trellis == 0); for (int i = 0; i < frame->nb_samples; i++) { - for (int ch = 0; ch < avctx->channels; ch++) { + for (int ch = 0; ch < channels; ch++) { put_bits(&pb, 4, adpcm_ima_qt_compress_sample(c->status + ch, *samples++)); } } @@ -717,11 +716,11 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, av_assert0(avctx->trellis == 0); for (int n = frame->nb_samples / 2; n > 0; n--) { - for (int ch = 0; ch < avctx->channels; ch++) { + for (int ch = 0; ch < channels; ch++) { put_bits(&pb, 4, adpcm_ima_alp_compress_sample(c->status + ch, *samples++)); put_bits(&pb, 4, adpcm_ima_alp_compress_sample(c->status + ch, samples[st])); } - samples += avctx->channels; + samples += channels; } flush_put_bits(&pb); @@ -738,7 +737,7 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, put_bits(&pb, 2, 2); // set 4-bit flash adpcm format // init the encoder state - for (int i = 0; i < avctx->channels; i++) { + for (int i = 0; i < channels; i++) { // clip step so it fits 6 bits c->status[i].step_index = av_clip_uintp2(c->status[i].step_index, 6); put_sbits(&pb, 16, samples[i]); @@ -748,22 +747,22 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, if (avctx->trellis > 0) { uint8_t buf[8190 /* = 2 * n */]; - adpcm_compress_trellis(avctx, samples + avctx->channels, buf, - &c->status[0], n, avctx->channels); - if (avctx->channels == 2) - adpcm_compress_trellis(avctx, samples + avctx->channels + 1, + adpcm_compress_trellis(avctx, samples + channels, buf, + &c->status[0], n, channels); + if (channels == 2) + adpcm_compress_trellis(avctx, samples + channels + 1, buf + n, &c->status[1], n, - avctx->channels); + channels); for (int i = 0; i < n; i++) { put_bits(&pb, 4, buf[i]); - if (avctx->channels == 2) + if (channels == 2) put_bits(&pb, 4, buf[n + i]); } } else { for (int i = 1; i < frame->nb_samples; i++) { put_bits(&pb, 4, adpcm_ima_compress_sample(&c->status[0], - samples[avctx->channels * i])); - if (avctx->channels == 2) + samples[channels * i])); + if (channels == 2) put_bits(&pb, 4, adpcm_ima_compress_sample(&c->status[1], samples[2 * i + 1])); } @@ -771,47 +770,47 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, flush_put_bits(&pb); ) /* End of CASE */ CASE(ADPCM_MS, - for (int i = 0; i < avctx->channels; i++) { + for (int i = 0; i < channels; i++) { int predictor = 0; *dst++ = predictor; c->status[i].coeff1 = ff_adpcm_AdaptCoeff1[predictor]; c->status[i].coeff2 = ff_adpcm_AdaptCoeff2[predictor]; } - for (int i = 0; i < avctx->channels; i++) { + for (int i = 0; i < channels; i++) { if (c->status[i].idelta < 16) c->status[i].idelta = 16; bytestream_put_le16(&dst, c->status[i].idelta); } - for (int i = 0; i < avctx->channels; i++) + for (int i = 0; i < channels; i++) c->status[i].sample2= *samples++; - for (int i = 0; i < avctx->channels; i++) { + for (int i = 0; i < channels; i++) { c->status[i].sample1 = *samples++; bytestream_put_le16(&dst, c->status[i].sample1); } - for (int i = 0; i < avctx->channels; i++) + for (int i = 0; i < channels; i++) bytestream_put_le16(&dst, c->status[i].sample2); if (avctx->trellis > 0) { - const int n = avctx->block_align - 7 * avctx->channels; + const int n = avctx->block_align - 7 * channels; uint8_t *buf = av_malloc(2 * n); if (!buf) return AVERROR(ENOMEM); - if (avctx->channels == 1) { + if (channels == 1) { adpcm_compress_trellis(avctx, samples, buf, &c->status[0], n, - avctx->channels); + channels); for (int i = 0; i < n; i += 2) *dst++ = (buf[i] << 4) | buf[i + 1]; } else { adpcm_compress_trellis(avctx, samples, buf, - &c->status[0], n, avctx->channels); + &c->status[0], n, channels); adpcm_compress_trellis(avctx, samples + 1, buf + n, - &c->status[1], n, avctx->channels); + &c->status[1], n, channels); for (int i = 0; i < n; i++) *dst++ = (buf[i] << 4) | buf[n + i]; } av_free(buf); } else { - for (int i = 7 * avctx->channels; i < avctx->block_align; i++) { + for (int i = 7 * channels; i < avctx->block_align; i++) { int nibble; nibble = adpcm_ms_compress_sample(&c->status[ 0], *samples++) << 4; nibble |= adpcm_ms_compress_sample(&c->status[st], *samples++); @@ -826,22 +825,22 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, if (!buf) return AVERROR(ENOMEM); n *= 2; - if (avctx->channels == 1) { + if (channels == 1) { adpcm_compress_trellis(avctx, samples, buf, &c->status[0], n, - avctx->channels); + channels); for (int i = 0; i < n; i += 2) *dst++ = buf[i] | (buf[i + 1] << 4); } else { adpcm_compress_trellis(avctx, samples, buf, - &c->status[0], n, avctx->channels); + &c->status[0], n, channels); adpcm_compress_trellis(avctx, samples + 1, buf + n, - &c->status[1], n, avctx->channels); + &c->status[1], n, channels); for (int i = 0; i < n; i++) *dst++ = buf[i] | (buf[n + i] << 4); } av_free(buf); } else - for (n *= avctx->channels; n > 0; n--) { + for (n *= channels; n > 0; n--) { int nibble; nibble = adpcm_yamaha_compress_sample(&c->status[ 0], *samples++); nibble |= adpcm_yamaha_compress_sample(&c->status[st], *samples++) << 4; @@ -855,17 +854,17 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, av_assert0(avctx->trellis == 0); for (int n = frame->nb_samples / 2; n > 0; n--) { - for (int ch = 0; ch < avctx->channels; ch++) { + for (int ch = 0; ch < channels; ch++) { put_bits(&pb, 4, adpcm_ima_qt_compress_sample(c->status + ch, *samples++)); put_bits(&pb, 4, adpcm_ima_qt_compress_sample(c->status + ch, samples[st])); } - samples += avctx->channels; + samples += channels; } flush_put_bits(&pb); ) /* End of CASE */ CASE(ADPCM_IMA_AMV, - av_assert0(avctx->channels == 1); + av_assert0(channels == 1); c->status[0].prev_sample = *samples; bytestream_put_le16(&dst, c->status[0].prev_sample); @@ -880,7 +879,7 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, if (!buf) return AVERROR(ENOMEM); - adpcm_compress_trellis(avctx, samples, buf, &c->status[0], 2 * n, avctx->channels); + adpcm_compress_trellis(avctx, samples, buf, &c->status[0], 2 * n, channels); for (int i = 0; i < n; i++) bytestream_put_byte(&dst, (buf[2 * i] << 4) | buf[2 * i + 1]); @@ -904,7 +903,7 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, av_assert0(frame->nb_samples == 32); - for (int ch = 0; ch < avctx->channels; ch++) { + for (int ch = 0; ch < channels; ch++) { int64_t error = INT64_MAX, tmperr = INT64_MAX; int shift = 2, flag = 0; int saved1 = c->status[ch].sample1; @@ -941,14 +940,14 @@ static int adpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, av_assert0(avctx->trellis == 0); for (int n = frame->nb_samples / 2; n > 0; n--) { /* stereo: 1 byte (2 samples) for left, 1 byte for right */ - for (int ch = 0; ch < avctx->channels; ch++) { + for (int ch = 0; ch < channels; ch++) { int t1, t2; t1 = adpcm_ima_compress_sample(&c->status[ch], *samples++); t2 = adpcm_ima_compress_sample(&c->status[ch], samples[st]); put_bits(&pb, 4, t2); put_bits(&pb, 4, t1); } - samples += avctx->channels; + samples += channels; } flush_put_bits(&pb); ) /* End of CASE */ @@ -968,6 +967,12 @@ static const enum AVSampleFormat sample_fmts_p[] = { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE }; +static const AVChannelLayout ch_layouts[] = { + AV_CHANNEL_LAYOUT_MONO, + AV_CHANNEL_LAYOUT_STEREO, + { 0 }, +}; + static const AVOption options[] = { { .name = "block_size", @@ -991,19 +996,20 @@ static const AVClass adpcm_encoder_class = { #define ADPCM_ENCODER_0(id_, name_, sample_fmts_, capabilities_, long_name_) #define ADPCM_ENCODER_1(id_, name_, sample_fmts_, capabilities_, long_name_) \ -const AVCodec ff_ ## name_ ## _encoder = { \ - .name = #name_, \ - .long_name = NULL_IF_CONFIG_SMALL(long_name_), \ - .type = AVMEDIA_TYPE_AUDIO, \ - .id = id_, \ +const FFCodec ff_ ## name_ ## _encoder = { \ + .p.name = #name_, \ + .p.long_name = NULL_IF_CONFIG_SMALL(long_name_), \ + .p.type = AVMEDIA_TYPE_AUDIO, \ + .p.id = id_, \ + .p.sample_fmts = sample_fmts_, \ + .p.ch_layouts = ch_layouts, \ + .p.capabilities = capabilities_ | AV_CODEC_CAP_DR1, \ + .p.priv_class = &adpcm_encoder_class, \ .priv_data_size = sizeof(ADPCMEncodeContext), \ .init = adpcm_encode_init, \ - .encode2 = adpcm_encode_frame, \ + FF_CODEC_ENCODE_CB(adpcm_encode_frame), \ .close = adpcm_encode_close, \ - .sample_fmts = sample_fmts_, \ - .capabilities = capabilities_ | AV_CODEC_CAP_DR1, \ .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE, \ - .priv_class = &adpcm_encoder_class, \ }; #define ADPCM_ENCODER_2(enabled, codec_id, name, sample_fmts, capabilities, long_name) \ ADPCM_ENCODER_ ## enabled(codec_id, name, sample_fmts, capabilities, long_name) diff --git a/libavcodec/adx.c b/libavcodec/adx.c index cd88b1666..c60fabb40 100644 --- a/libavcodec/adx.c +++ b/libavcodec/adx.c @@ -38,7 +38,7 @@ void ff_adx_calculate_coeffs(int cutoff, int sample_rate, int bits, int *coeff) int ff_adx_decode_header(AVCodecContext *avctx, const uint8_t *buf, int bufsize, int *header_size, int *coeff) { - int offset, cutoff; + int offset, cutoff, channels; if (bufsize < 24) return AVERROR_INVALIDDATA; @@ -58,18 +58,24 @@ int ff_adx_decode_header(AVCodecContext *avctx, const uint8_t *buf, } /* channels */ - avctx->channels = buf[7]; - if (avctx->channels <= 0 || avctx->channels > 2) + channels = buf[7]; + if (channels <= 0 || channels > 2) return AVERROR_INVALIDDATA; + if (avctx->ch_layout.nb_channels != channels) { + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + avctx->ch_layout.nb_channels = channels; + } + /* sample rate */ avctx->sample_rate = AV_RB32(buf + 8); if (avctx->sample_rate < 1 || - avctx->sample_rate > INT_MAX / (avctx->channels * BLOCK_SIZE * 8)) + avctx->sample_rate > INT_MAX / (channels * BLOCK_SIZE * 8)) return AVERROR_INVALIDDATA; /* bit rate */ - avctx->bit_rate = avctx->sample_rate * avctx->channels * BLOCK_SIZE * 8 / BLOCK_SAMPLES; + avctx->bit_rate = avctx->sample_rate * channels * BLOCK_SIZE * 8 / BLOCK_SAMPLES; /* LPC coefficients */ if (coeff) { diff --git a/libavcodec/adxdec.c b/libavcodec/adxdec.c index 20256a092..1ebc250e4 100644 --- a/libavcodec/adxdec.c +++ b/libavcodec/adxdec.c @@ -22,6 +22,7 @@ #include "libavutil/intreadwrite.h" #include "avcodec.h" #include "adx.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" @@ -46,7 +47,7 @@ static av_cold int adx_decode_init(AVCodecContext *avctx) av_log(avctx, AV_LOG_ERROR, "error parsing ADX header\n"); return AVERROR_INVALIDDATA; } - c->channels = avctx->channels; + c->channels = avctx->ch_layout.nb_channels; c->header_parsed = 1; } @@ -92,10 +93,9 @@ static int adx_decode(ADXContext *c, int16_t *out, int offset, return 0; } -static int adx_decode_frame(AVCodecContext *avctx, void *data, +static int adx_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; int buf_size = avpkt->size; ADXContext *c = avctx->priv_data; int16_t **samples; @@ -132,7 +132,7 @@ static int adx_decode_frame(AVCodecContext *avctx, void *data, av_log(avctx, AV_LOG_ERROR, "error parsing ADX header\n"); return AVERROR_INVALIDDATA; } - c->channels = avctx->channels; + c->channels = avctx->ch_layout.nb_channels; c->header_parsed = 1; if (buf_size < header_size) return AVERROR_INVALIDDATA; @@ -147,7 +147,7 @@ static int adx_decode_frame(AVCodecContext *avctx, void *data, /* if the packet is not an even multiple of BLOCK_SIZE, check for an EOF packet */ - if (!num_blocks || buf_size % (BLOCK_SIZE * avctx->channels)) { + if (!num_blocks || buf_size % (BLOCK_SIZE * c->channels)) { if (buf_size >= 4 && (AV_RB16(buf) & 0x8000)) { c->eof = 1; *got_frame_ptr = 0; @@ -190,18 +190,18 @@ static void adx_decode_flush(AVCodecContext *avctx) c->eof = 0; } -const AVCodec ff_adpcm_adx_decoder = { - .name = "adpcm_adx", - .long_name = NULL_IF_CONFIG_SMALL("SEGA CRI ADX ADPCM"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_ADPCM_ADX, +const FFCodec ff_adpcm_adx_decoder = { + .p.name = "adpcm_adx", + .p.long_name = NULL_IF_CONFIG_SMALL("SEGA CRI ADX ADPCM"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_ADPCM_ADX, .priv_data_size = sizeof(ADXContext), .init = adx_decode_init, - .decode = adx_decode_frame, + FF_CODEC_DECODE_CB(adx_decode_frame), .flush = adx_decode_flush, - .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/adxenc.c b/libavcodec/adxenc.c index c5849a40a..9277cab7c 100644 --- a/libavcodec/adxenc.c +++ b/libavcodec/adxenc.c @@ -22,8 +22,8 @@ #include "avcodec.h" #include "adx.h" #include "bytestream.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "put_bits.h" /** @@ -107,7 +107,7 @@ static int adx_encode_header(AVCodecContext *avctx, uint8_t *buf, int bufsize) bytestream_put_byte(&buf, 3); /* encoding */ bytestream_put_byte(&buf, BLOCK_SIZE); /* block size */ bytestream_put_byte(&buf, 4); /* sample size */ - bytestream_put_byte(&buf, avctx->channels); /* channels */ + bytestream_put_byte(&buf, avctx->ch_layout.nb_channels); /* channels */ bytestream_put_be32(&buf, avctx->sample_rate); /* sample rate */ bytestream_put_be32(&buf, 0); /* total sample count */ bytestream_put_be16(&buf, c->cutoff); /* cutoff frequency */ @@ -125,7 +125,7 @@ static av_cold int adx_encode_init(AVCodecContext *avctx) { ADXContext *c = avctx->priv_data; - if (avctx->channels > 2) { + if (avctx->ch_layout.nb_channels > 2) { av_log(avctx, AV_LOG_ERROR, "Invalid number of channels\n"); return AVERROR(EINVAL); } @@ -144,6 +144,7 @@ static int adx_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, ADXContext *c = avctx->priv_data; const int16_t *samples = frame ? (const int16_t *)frame->data[0] : NULL; uint8_t *dst; + int channels = avctx->ch_layout.nb_channels; int ch, out_size, ret; if (!samples) { @@ -162,7 +163,7 @@ static int adx_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, return 0; } - out_size = BLOCK_SIZE * avctx->channels + !c->header_parsed * HEADER_SIZE; + out_size = BLOCK_SIZE * channels + !c->header_parsed * HEADER_SIZE; if ((ret = ff_get_encode_buffer(avctx, avpkt, out_size, 0)) < 0) return ret; dst = avpkt->data; @@ -177,8 +178,8 @@ static int adx_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, c->header_parsed = 1; } - for (ch = 0; ch < avctx->channels; ch++) { - adx_encode(c, dst, samples + ch, &c->prev[ch], avctx->channels); + for (ch = 0; ch < channels; ch++) { + adx_encode(c, dst, samples + ch, &c->prev[ch], channels); dst += BLOCK_SIZE; } @@ -188,16 +189,16 @@ static int adx_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, return 0; } -const AVCodec ff_adpcm_adx_encoder = { - .name = "adpcm_adx", - .long_name = NULL_IF_CONFIG_SMALL("SEGA CRI ADX ADPCM"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_ADPCM_ADX, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, +const FFCodec ff_adpcm_adx_encoder = { + .p.name = "adpcm_adx", + .p.long_name = NULL_IF_CONFIG_SMALL("SEGA CRI ADX ADPCM"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_ADPCM_ADX, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, .priv_data_size = sizeof(ADXContext), .init = adx_encode_init, - .encode2 = adx_encode_frame, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16, + FF_CODEC_ENCODE_CB(adx_encode_frame), + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/agm.c b/libavcodec/agm.c index 7579d9765..27438dd1a 100644 --- a/libavcodec/agm.c +++ b/libavcodec/agm.c @@ -30,6 +30,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "copy_block.h" #include "get_bits.h" #include "idctdsp.h" @@ -1093,13 +1094,12 @@ static int decode_huffman2(AVCodecContext *avctx, int header, int size) return 0; } -static int decode_frame(AVCodecContext *avctx, void *data, +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt) { AGMContext *s = avctx->priv_data; GetBitContext *gb = &s->gb; GetByteContext *gbyte = &s->gbyte; - AVFrame *frame = data; int w, h, width, height, header; unsigned compressed_size; long skip; @@ -1285,17 +1285,17 @@ static av_cold int decode_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_agm_decoder = { - .name = "agm", - .long_name = NULL_IF_CONFIG_SMALL("Amuse Graphics Movie"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_AGM, +const FFCodec ff_agm_decoder = { + .p.name = "agm", + .p.long_name = NULL_IF_CONFIG_SMALL("Amuse Graphics Movie"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_AGM, + .p.capabilities = AV_CODEC_CAP_DR1, .priv_data_size = sizeof(AGMContext), .init = decode_init, .close = decode_close, - .decode = decode_frame, + FF_CODEC_DECODE_CB(decode_frame), .flush = decode_flush, - .capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_EXPORTS_CROPPING, diff --git a/libavcodec/aic.c b/libavcodec/aic.c index c95bdae1e..5f0eec6b8 100644 --- a/libavcodec/aic.c +++ b/libavcodec/aic.c @@ -26,7 +26,7 @@ #include "avcodec.h" #include "bytestream.h" -#include "internal.h" +#include "codec_internal.h" #include "get_bits.h" #include "golomb.h" #include "idctdsp.h" @@ -381,8 +381,8 @@ static int aic_decode_slice(AICContext *ctx, int mb_x, int mb_y, return 0; } -static int aic_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int aic_decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { AICContext *ctx = avctx->priv_data; const uint8_t *buf = avpkt->data; @@ -391,9 +391,8 @@ static int aic_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, uint32_t off; int x, y, ret; int slice_size; - ThreadFrame frame = { .f = data }; - ctx->frame = data; + ctx->frame = frame; ctx->frame->pict_type = AV_PICTURE_TYPE_I; ctx->frame->key_frame = 1; @@ -410,7 +409,7 @@ static int aic_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, return ret; } - if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, ctx->frame, 0)) < 0) return ret; bytestream2_init(&gb, buf + AIC_HDR_SIZE, @@ -496,15 +495,15 @@ static av_cold int aic_decode_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_aic_decoder = { - .name = "aic", - .long_name = NULL_IF_CONFIG_SMALL("Apple Intermediate Codec"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_AIC, +const FFCodec ff_aic_decoder = { + .p.name = "aic", + .p.long_name = NULL_IF_CONFIG_SMALL("Apple Intermediate Codec"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_AIC, .priv_data_size = sizeof(AICContext), .init = aic_decode_init, .close = aic_decode_close, - .decode = aic_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + FF_CODEC_DECODE_CB(aic_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/alac.c b/libavcodec/alac.c index 67fc2a3e4..9aaf7066b 100644 --- a/libavcodec/alac.c +++ b/libavcodec/alac.c @@ -52,7 +52,7 @@ #include "avcodec.h" #include "get_bits.h" #include "bytestream.h" -#include "internal.h" +#include "codec_internal.h" #include "thread.h" #include "unary.h" #include "mathops.h" @@ -270,10 +270,9 @@ static int decode_element(AVCodecContext *avctx, AVFrame *frame, int ch_index, return AVERROR_INVALIDDATA; } if (!alac->nb_samples) { - ThreadFrame tframe = { .f = frame }; /* get output buffer */ frame->nb_samples = output_samples; - if ((ret = ff_thread_get_buffer(avctx, &tframe, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, frame, 0)) < 0) return ret; } else if (output_samples != alac->nb_samples) { av_log(avctx, AV_LOG_ERROR, "sample count mismatch: %"PRIu32" != %d\n", @@ -414,11 +413,10 @@ static int decode_element(AVCodecContext *avctx, AVFrame *frame, int ch_index, return 0; } -static int alac_decode_frame(AVCodecContext *avctx, void *data, +static int alac_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { ALACContext *alac = avctx->priv_data; - AVFrame *frame = data; enum AlacRawDataBlockType element; int channels; int ch, ret, got_end; @@ -576,21 +574,17 @@ static av_cold int alac_decode_init(AVCodecContext * avctx) avctx->bits_per_raw_sample = alac->sample_size; avctx->sample_rate = alac->sample_rate; - if (alac->channels < 1) { + if (alac->channels < 1 || alac->channels > ALAC_MAX_CHANNELS) { av_log(avctx, AV_LOG_WARNING, "Invalid channel count\n"); - alac->channels = avctx->channels; - } else { - if (alac->channels > ALAC_MAX_CHANNELS) - alac->channels = avctx->channels; - else - avctx->channels = alac->channels; + alac->channels = avctx->ch_layout.nb_channels; } - if (avctx->channels > ALAC_MAX_CHANNELS || avctx->channels <= 0 ) { + if (avctx->ch_layout.nb_channels > ALAC_MAX_CHANNELS || avctx->ch_layout.nb_channels <= 0 ) { avpriv_report_missing_feature(avctx, "Channel count %d", - avctx->channels); + avctx->ch_layout.nb_channels); return AVERROR_PATCHWELCOME; } - avctx->channel_layout = ff_alac_channel_layouts[alac->channels - 1]; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = ff_alac_ch_layouts[alac->channels - 1]; if ((ret = allocate_buffers(alac)) < 0) { av_log(avctx, AV_LOG_ERROR, "Error allocating buffers\n"); @@ -616,16 +610,16 @@ static const AVClass alac_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_alac_decoder = { - .name = "alac", - .long_name = NULL_IF_CONFIG_SMALL("ALAC (Apple Lossless Audio Codec)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_ALAC, +const FFCodec ff_alac_decoder = { + .p.name = "alac", + .p.long_name = NULL_IF_CONFIG_SMALL("ALAC (Apple Lossless Audio Codec)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_ALAC, .priv_data_size = sizeof(ALACContext), .init = alac_decode_init, .close = alac_decode_close, - .decode = alac_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_CHANNEL_CONF, + FF_CODEC_DECODE_CB(alac_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_CHANNEL_CONF, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .priv_class = &alac_class + .p.priv_class = &alac_class }; diff --git a/libavcodec/alac_data.c b/libavcodec/alac_data.c index 0bcb06c07..d8ed53f44 100644 --- a/libavcodec/alac_data.c +++ b/libavcodec/alac_data.c @@ -32,16 +32,16 @@ const uint8_t ff_alac_channel_layout_offsets[ALAC_MAX_CHANNELS][ALAC_MAX_CHANNEL { 2, 6, 7, 0, 1, 4, 5, 3 } }; -const uint64_t ff_alac_channel_layouts[ALAC_MAX_CHANNELS + 1] = { - AV_CH_LAYOUT_MONO, - AV_CH_LAYOUT_STEREO, - AV_CH_LAYOUT_SURROUND, - AV_CH_LAYOUT_4POINT0, - AV_CH_LAYOUT_5POINT0_BACK, - AV_CH_LAYOUT_5POINT1_BACK, - AV_CH_LAYOUT_6POINT1_BACK, - AV_CH_LAYOUT_7POINT1_WIDE_BACK, - 0 +const AVChannelLayout ff_alac_ch_layouts[ALAC_MAX_CHANNELS + 1] = { + AV_CHANNEL_LAYOUT_MONO, + AV_CHANNEL_LAYOUT_STEREO, + AV_CHANNEL_LAYOUT_SURROUND, + AV_CHANNEL_LAYOUT_4POINT0, + AV_CHANNEL_LAYOUT_5POINT0_BACK, + AV_CHANNEL_LAYOUT_5POINT1_BACK, + AV_CHANNEL_LAYOUT_6POINT1_BACK, + AV_CHANNEL_LAYOUT_7POINT1_WIDE_BACK, + { 0 } }; const enum AlacRawDataBlockType ff_alac_channel_elements[ALAC_MAX_CHANNELS][5] = { diff --git a/libavcodec/alac_data.h b/libavcodec/alac_data.h index 650d6dcd1..802074639 100644 --- a/libavcodec/alac_data.h +++ b/libavcodec/alac_data.h @@ -23,6 +23,8 @@ #include +#include "libavutil/channel_layout.h" + enum AlacRawDataBlockType { /* At the moment, only SCE, CPE, LFE, and END are recognized. */ TYPE_SCE, @@ -39,7 +41,7 @@ enum AlacRawDataBlockType { extern const uint8_t ff_alac_channel_layout_offsets[ALAC_MAX_CHANNELS][ALAC_MAX_CHANNELS]; -extern const uint64_t ff_alac_channel_layouts[ALAC_MAX_CHANNELS + 1]; +extern const AVChannelLayout ff_alac_ch_layouts[ALAC_MAX_CHANNELS + 1]; extern const enum AlacRawDataBlockType ff_alac_channel_elements[ALAC_MAX_CHANNELS][5]; diff --git a/libavcodec/alacdsp.c b/libavcodec/alacdsp.c index 8718d1b6b..b033a2797 100644 --- a/libavcodec/alacdsp.c +++ b/libavcodec/alacdsp.c @@ -29,12 +29,12 @@ static void decorrelate_stereo(int32_t *buffer[2], int nb_samples, int i; for (i = 0; i < nb_samples; i++) { - int32_t a, b; + uint32_t a, b; a = buffer[0][i]; b = buffer[1][i]; - a -= (int)(b * (unsigned)decorr_left_weight) >> decorr_shift; + a -= (int)(b * decorr_left_weight) >> decorr_shift; b += a; buffer[0][i] = b; @@ -58,6 +58,7 @@ av_cold void ff_alacdsp_init(ALACDSPContext *c) c->append_extra_bits[0] = c->append_extra_bits[1] = append_extra_bits; - if (ARCH_X86) - ff_alacdsp_init_x86(c); +#if ARCH_X86 + ff_alacdsp_init_x86(c); +#endif } diff --git a/libavcodec/alacenc.c b/libavcodec/alacenc.c index a38aa6e7d..72ce65e26 100644 --- a/libavcodec/alacenc.c +++ b/libavcodec/alacenc.c @@ -22,9 +22,9 @@ #include "libavutil/opt.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" #include "put_bits.h" -#include "internal.h" #include "lpc.h" #include "mathops.h" #include "alac_data.h" @@ -462,14 +462,15 @@ static int write_frame(AlacEncodeContext *s, AVPacket *avpkt, uint8_t * const *samples) { PutBitContext *pb = &s->pbctx; - const enum AlacRawDataBlockType *ch_elements = ff_alac_channel_elements[s->avctx->channels - 1]; - const uint8_t *ch_map = ff_alac_channel_layout_offsets[s->avctx->channels - 1]; + int channels = s->avctx->ch_layout.nb_channels; + const enum AlacRawDataBlockType *ch_elements = ff_alac_channel_elements[channels - 1]; + const uint8_t *ch_map = ff_alac_channel_layout_offsets[channels - 1]; int ch, element, sce, cpe; init_put_bits(pb, avpkt->data, avpkt->size); ch = element = sce = cpe = 0; - while (ch < s->avctx->channels) { + while (ch < channels) { if (ch_elements[element] == TYPE_CPE) { write_element(s, TYPE_CPE, cpe, samples[ch_map[ch]], samples[ch_map[ch + 1]]); @@ -532,7 +533,7 @@ static av_cold int alac_encode_init(AVCodecContext *avctx) s->rc.rice_modifier = 4; s->max_coded_frame_size = get_max_frame_size(avctx->frame_size, - avctx->channels, + avctx->ch_layout.nb_channels, avctx->bits_per_raw_sample); avctx->extradata = av_mallocz(ALAC_EXTRADATA_SIZE + AV_INPUT_BUFFER_PADDING_SIZE); @@ -545,10 +546,10 @@ static av_cold int alac_encode_init(AVCodecContext *avctx) AV_WB32(alac_extradata+4, MKBETAG('a','l','a','c')); AV_WB32(alac_extradata+12, avctx->frame_size); AV_WB8 (alac_extradata+17, avctx->bits_per_raw_sample); - AV_WB8 (alac_extradata+21, avctx->channels); + AV_WB8 (alac_extradata+21, avctx->ch_layout.nb_channels); AV_WB32(alac_extradata+24, s->max_coded_frame_size); AV_WB32(alac_extradata+28, - avctx->sample_rate * avctx->channels * avctx->bits_per_raw_sample); // average bitrate + avctx->sample_rate * avctx->ch_layout.nb_channels * avctx->bits_per_raw_sample); // average bitrate AV_WB32(alac_extradata+32, avctx->sample_rate); // Set relevant extradata fields @@ -585,7 +586,7 @@ static int alac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, s->frame_size = frame->nb_samples; if (frame->nb_samples < DEFAULT_FRAME_SIZE) - max_frame_size = get_max_frame_size(s->frame_size, avctx->channels, + max_frame_size = get_max_frame_size(s->frame_size, avctx->ch_layout.nb_channels, avctx->bits_per_raw_sample); else max_frame_size = s->max_coded_frame_size; @@ -616,6 +617,21 @@ static int alac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, return 0; } +#if FF_API_OLD_CHANNEL_LAYOUT +static const uint64_t alac_channel_layouts[ALAC_MAX_CHANNELS + 1] = { + AV_CH_LAYOUT_MONO, + AV_CH_LAYOUT_STEREO, + AV_CH_LAYOUT_SURROUND, + AV_CH_LAYOUT_4POINT0, + AV_CH_LAYOUT_5POINT0_BACK, + AV_CH_LAYOUT_5POINT1_BACK, + AV_CH_LAYOUT_6POINT1_BACK, + AV_CH_LAYOUT_7POINT1_WIDE_BACK, + 0 +}; +#endif + + #define OFFSET(x) offsetof(AlacEncodeContext, x) #define AE AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { @@ -632,20 +648,25 @@ static const AVClass alacenc_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_alac_encoder = { - .name = "alac", - .long_name = NULL_IF_CONFIG_SMALL("ALAC (Apple Lossless Audio Codec)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_ALAC, +FF_DISABLE_DEPRECATION_WARNINGS +const FFCodec ff_alac_encoder = { + .p.name = "alac", + .p.long_name = NULL_IF_CONFIG_SMALL("ALAC (Apple Lossless Audio Codec)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_ALAC, .priv_data_size = sizeof(AlacEncodeContext), - .priv_class = &alacenc_class, + .p.priv_class = &alacenc_class, .init = alac_encode_init, - .encode2 = alac_encode_frame, + FF_CODEC_ENCODE_CB(alac_encode_frame), .close = alac_encode_close, - .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME, - .channel_layouts = ff_alac_channel_layouts, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S32P, + .p.capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME, +#if FF_API_OLD_CHANNEL_LAYOUT + .p.channel_layouts = alac_channel_layouts, +#endif + .p.ch_layouts = ff_alac_ch_layouts, + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; +FF_ENABLE_DEPRECATION_WARNINGS diff --git a/libavcodec/aliaspixdec.c b/libavcodec/aliaspixdec.c index e08891ec1..73c83528f 100644 --- a/libavcodec/aliaspixdec.c +++ b/libavcodec/aliaspixdec.c @@ -23,14 +23,14 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" #define ALIAS_HEADER_SIZE 10 -static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *f, + int *got_frame, AVPacket *avpkt) { - AVFrame *f = data; GetByteContext gb; int width, height, ret, bits_pixel, pixel; uint8_t *out_buf; @@ -121,11 +121,11 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, return avpkt->size; } -const AVCodec ff_alias_pix_decoder = { - .name = "alias_pix", - .long_name = NULL_IF_CONFIG_SMALL("Alias/Wavefront PIX image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_ALIAS_PIX, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, +const FFCodec ff_alias_pix_decoder = { + .p.name = "alias_pix", + .p.long_name = NULL_IF_CONFIG_SMALL("Alias/Wavefront PIX image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_ALIAS_PIX, + .p.capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), }; diff --git a/libavcodec/aliaspixenc.c b/libavcodec/aliaspixenc.c index fa273df9c..9c43cfa9e 100644 --- a/libavcodec/aliaspixenc.c +++ b/libavcodec/aliaspixenc.c @@ -23,8 +23,8 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #define ALIAS_HEADER_SIZE 10 @@ -101,13 +101,13 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, return 0; } -const AVCodec ff_alias_pix_encoder = { - .name = "alias_pix", - .long_name = NULL_IF_CONFIG_SMALL("Alias/Wavefront PIX image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_ALIAS_PIX, - .encode2 = encode_frame, - .pix_fmts = (const enum AVPixelFormat[]) { +const FFCodec ff_alias_pix_encoder = { + .p.name = "alias_pix", + .p.long_name = NULL_IF_CONFIG_SMALL("Alias/Wavefront PIX image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_ALIAS_PIX, + FF_CODEC_ENCODE_CB(encode_frame), + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_BGR24, AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE }, }; diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index d1e10197d..bdfc2f6f4 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -28,750 +28,763 @@ #include #include "config.h" +#include "config_components.h" #include "libavutil/thread.h" #include "codec.h" #include "codec_id.h" +#include "codec_internal.h" -extern const AVCodec ff_a64multi_encoder; -extern const AVCodec ff_a64multi5_encoder; -extern const AVCodec ff_aasc_decoder; -extern const AVCodec ff_aic_decoder; -extern const AVCodec ff_alias_pix_encoder; -extern const AVCodec ff_alias_pix_decoder; -extern const AVCodec ff_agm_decoder; -extern const AVCodec ff_amv_encoder; -extern const AVCodec ff_amv_decoder; -extern const AVCodec ff_anm_decoder; -extern const AVCodec ff_ansi_decoder; -extern const AVCodec ff_apng_encoder; -extern const AVCodec ff_apng_decoder; -extern const AVCodec ff_arbc_decoder; -extern const AVCodec ff_argo_decoder; -extern const AVCodec ff_asv1_encoder; -extern const AVCodec ff_asv1_decoder; -extern const AVCodec ff_asv2_encoder; -extern const AVCodec ff_asv2_decoder; -extern const AVCodec ff_aura_decoder; -extern const AVCodec ff_aura2_decoder; -extern const AVCodec ff_avrp_encoder; -extern const AVCodec ff_avrp_decoder; -extern const AVCodec ff_avrn_decoder; -extern const AVCodec ff_avs_decoder; -extern const AVCodec ff_avui_encoder; -extern const AVCodec ff_avui_decoder; -extern const AVCodec ff_ayuv_encoder; -extern const AVCodec ff_ayuv_decoder; -extern const AVCodec ff_bethsoftvid_decoder; -extern const AVCodec ff_bfi_decoder; -extern const AVCodec ff_bink_decoder; -extern const AVCodec ff_bitpacked_decoder; -extern const AVCodec ff_bitpacked_encoder; -extern const AVCodec ff_bmp_encoder; -extern const AVCodec ff_bmp_decoder; -extern const AVCodec ff_bmv_video_decoder; -extern const AVCodec ff_brender_pix_decoder; -extern const AVCodec ff_c93_decoder; -extern const AVCodec ff_cavs_decoder; -extern const AVCodec ff_cdgraphics_decoder; -extern const AVCodec ff_cdtoons_decoder; -extern const AVCodec ff_cdxl_decoder; -extern const AVCodec ff_cfhd_encoder; -extern const AVCodec ff_cfhd_decoder; -extern const AVCodec ff_cinepak_encoder; -extern const AVCodec ff_cinepak_decoder; -extern const AVCodec ff_clearvideo_decoder; -extern const AVCodec ff_cljr_encoder; -extern const AVCodec ff_cljr_decoder; -extern const AVCodec ff_cllc_decoder; -extern const AVCodec ff_comfortnoise_encoder; -extern const AVCodec ff_comfortnoise_decoder; -extern const AVCodec ff_cpia_decoder; -extern const AVCodec ff_cri_decoder; -extern const AVCodec ff_cscd_decoder; -extern const AVCodec ff_cyuv_decoder; -extern const AVCodec ff_dds_decoder; -extern const AVCodec ff_dfa_decoder; -extern const AVCodec ff_dirac_decoder; -extern const AVCodec ff_dnxhd_encoder; -extern const AVCodec ff_dnxhd_decoder; -extern const AVCodec ff_dpx_encoder; -extern const AVCodec ff_dpx_decoder; -extern const AVCodec ff_dsicinvideo_decoder; -extern const AVCodec ff_dvaudio_decoder; -extern const AVCodec ff_dvvideo_encoder; -extern const AVCodec ff_dvvideo_decoder; -extern const AVCodec ff_dxa_decoder; -extern const AVCodec ff_dxtory_decoder; -extern const AVCodec ff_dxv_decoder; -extern const AVCodec ff_eacmv_decoder; -extern const AVCodec ff_eamad_decoder; -extern const AVCodec ff_eatgq_decoder; -extern const AVCodec ff_eatgv_decoder; -extern const AVCodec ff_eatqi_decoder; -extern const AVCodec ff_eightbps_decoder; -extern const AVCodec ff_eightsvx_exp_decoder; -extern const AVCodec ff_eightsvx_fib_decoder; -extern const AVCodec ff_escape124_decoder; -extern const AVCodec ff_escape130_decoder; -extern const AVCodec ff_exr_encoder; -extern const AVCodec ff_exr_decoder; -extern const AVCodec ff_ffv1_encoder; -extern const AVCodec ff_ffv1_decoder; -extern const AVCodec ff_ffvhuff_encoder; -extern const AVCodec ff_ffvhuff_decoder; -extern const AVCodec ff_fic_decoder; -extern const AVCodec ff_fits_encoder; -extern const AVCodec ff_fits_decoder; -extern const AVCodec ff_flashsv_encoder; -extern const AVCodec ff_flashsv_decoder; -extern const AVCodec ff_flashsv2_encoder; -extern const AVCodec ff_flashsv2_decoder; -extern const AVCodec ff_flic_decoder; -extern const AVCodec ff_flv_encoder; -extern const AVCodec ff_flv_decoder; -extern const AVCodec ff_fmvc_decoder; -extern const AVCodec ff_fourxm_decoder; -extern const AVCodec ff_fraps_decoder; -extern const AVCodec ff_frwu_decoder; -extern const AVCodec ff_g2m_decoder; -extern const AVCodec ff_gdv_decoder; -extern const AVCodec ff_gem_decoder; -extern const AVCodec ff_gif_encoder; -extern const AVCodec ff_gif_decoder; -extern const AVCodec ff_h261_encoder; -extern const AVCodec ff_h261_decoder; -extern const AVCodec ff_h263_encoder; -extern const AVCodec ff_h263_decoder; -extern const AVCodec ff_h263i_decoder; -extern const AVCodec ff_h263p_encoder; -extern const AVCodec ff_h263p_decoder; -extern const AVCodec ff_h263_v4l2m2m_decoder; -extern const AVCodec ff_h264_decoder; -extern const AVCodec ff_h264_crystalhd_decoder; -extern const AVCodec ff_h264_v4l2m2m_decoder; -extern const AVCodec ff_h264_mediacodec_decoder; -extern const AVCodec ff_h264_mmal_decoder; -extern const AVCodec ff_h264_qsv_decoder; -extern const AVCodec ff_h264_rkmpp_decoder; -extern const AVCodec ff_hap_encoder; -extern const AVCodec ff_hap_decoder; -extern const AVCodec ff_hevc_decoder; -extern const AVCodec ff_hevc_qsv_decoder; -extern const AVCodec ff_hevc_rkmpp_decoder; -extern const AVCodec ff_hevc_v4l2m2m_decoder; -extern const AVCodec ff_hnm4_video_decoder; -extern const AVCodec ff_hq_hqa_decoder; -extern const AVCodec ff_hqx_decoder; -extern const AVCodec ff_huffyuv_encoder; -extern const AVCodec ff_huffyuv_decoder; -extern const AVCodec ff_hymt_decoder; -extern const AVCodec ff_idcin_decoder; -extern const AVCodec ff_iff_ilbm_decoder; -extern const AVCodec ff_imm4_decoder; -extern const AVCodec ff_imm5_decoder; -extern const AVCodec ff_indeo2_decoder; -extern const AVCodec ff_indeo3_decoder; -extern const AVCodec ff_indeo4_decoder; -extern const AVCodec ff_indeo5_decoder; -extern const AVCodec ff_interplay_video_decoder; -extern const AVCodec ff_ipu_decoder; -extern const AVCodec ff_jpeg2000_encoder; -extern const AVCodec ff_jpeg2000_decoder; -extern const AVCodec ff_jpegls_encoder; -extern const AVCodec ff_jpegls_decoder; -extern const AVCodec ff_jv_decoder; -extern const AVCodec ff_kgv1_decoder; -extern const AVCodec ff_kmvc_decoder; -extern const AVCodec ff_lagarith_decoder; -extern const AVCodec ff_ljpeg_encoder; -extern const AVCodec ff_loco_decoder; -extern const AVCodec ff_lscr_decoder; -extern const AVCodec ff_m101_decoder; -extern const AVCodec ff_magicyuv_encoder; -extern const AVCodec ff_magicyuv_decoder; -extern const AVCodec ff_mdec_decoder; -extern const AVCodec ff_mimic_decoder; -extern const AVCodec ff_mjpeg_encoder; -extern const AVCodec ff_mjpeg_decoder; -extern const AVCodec ff_mjpegb_decoder; -extern const AVCodec ff_mmvideo_decoder; -extern const AVCodec ff_mobiclip_decoder; -extern const AVCodec ff_motionpixels_decoder; -extern const AVCodec ff_mpeg1video_encoder; -extern const AVCodec ff_mpeg1video_decoder; -extern const AVCodec ff_mpeg2video_encoder; -extern const AVCodec ff_mpeg2video_decoder; -extern const AVCodec ff_mpeg4_encoder; -extern const AVCodec ff_mpeg4_decoder; -extern const AVCodec ff_mpeg4_crystalhd_decoder; -extern const AVCodec ff_mpeg4_v4l2m2m_decoder; -extern const AVCodec ff_mpeg4_mmal_decoder; -extern const AVCodec ff_mpegvideo_decoder; -extern const AVCodec ff_mpeg1_v4l2m2m_decoder; -extern const AVCodec ff_mpeg2_mmal_decoder; -extern const AVCodec ff_mpeg2_crystalhd_decoder; -extern const AVCodec ff_mpeg2_v4l2m2m_decoder; -extern const AVCodec ff_mpeg2_qsv_decoder; -extern const AVCodec ff_mpeg2_mediacodec_decoder; -extern const AVCodec ff_msa1_decoder; -extern const AVCodec ff_mscc_decoder; -extern const AVCodec ff_msmpeg4v1_decoder; -extern const AVCodec ff_msmpeg4v2_encoder; -extern const AVCodec ff_msmpeg4v2_decoder; -extern const AVCodec ff_msmpeg4v3_encoder; -extern const AVCodec ff_msmpeg4v3_decoder; -extern const AVCodec ff_msmpeg4_crystalhd_decoder; -extern const AVCodec ff_msp2_decoder; -extern const AVCodec ff_msrle_decoder; -extern const AVCodec ff_mss1_decoder; -extern const AVCodec ff_mss2_decoder; -extern const AVCodec ff_msvideo1_encoder; -extern const AVCodec ff_msvideo1_decoder; -extern const AVCodec ff_mszh_decoder; -extern const AVCodec ff_mts2_decoder; -extern const AVCodec ff_mv30_decoder; -extern const AVCodec ff_mvc1_decoder; -extern const AVCodec ff_mvc2_decoder; -extern const AVCodec ff_mvdv_decoder; -extern const AVCodec ff_mvha_decoder; -extern const AVCodec ff_mwsc_decoder; -extern const AVCodec ff_mxpeg_decoder; -extern const AVCodec ff_notchlc_decoder; -extern const AVCodec ff_nuv_decoder; -extern const AVCodec ff_paf_video_decoder; -extern const AVCodec ff_pam_encoder; -extern const AVCodec ff_pam_decoder; -extern const AVCodec ff_pbm_encoder; -extern const AVCodec ff_pbm_decoder; -extern const AVCodec ff_pcx_encoder; -extern const AVCodec ff_pcx_decoder; -extern const AVCodec ff_pfm_encoder; -extern const AVCodec ff_pfm_decoder; -extern const AVCodec ff_pgm_encoder; -extern const AVCodec ff_pgm_decoder; -extern const AVCodec ff_pgmyuv_encoder; -extern const AVCodec ff_pgmyuv_decoder; -extern const AVCodec ff_pgx_decoder; -extern const AVCodec ff_photocd_decoder; -extern const AVCodec ff_pictor_decoder; -extern const AVCodec ff_pixlet_decoder; -extern const AVCodec ff_png_encoder; -extern const AVCodec ff_png_decoder; -extern const AVCodec ff_ppm_encoder; -extern const AVCodec ff_ppm_decoder; -extern const AVCodec ff_prores_encoder; -extern const AVCodec ff_prores_decoder; -extern const AVCodec ff_prores_aw_encoder; -extern const AVCodec ff_prores_ks_encoder; -extern const AVCodec ff_prosumer_decoder; -extern const AVCodec ff_psd_decoder; -extern const AVCodec ff_ptx_decoder; -extern const AVCodec ff_qdraw_decoder; -extern const AVCodec ff_qpeg_decoder; -extern const AVCodec ff_qtrle_encoder; -extern const AVCodec ff_qtrle_decoder; -extern const AVCodec ff_r10k_encoder; -extern const AVCodec ff_r10k_decoder; -extern const AVCodec ff_r210_encoder; -extern const AVCodec ff_r210_decoder; -extern const AVCodec ff_rasc_decoder; -extern const AVCodec ff_rawvideo_encoder; -extern const AVCodec ff_rawvideo_decoder; -extern const AVCodec ff_rl2_decoder; -extern const AVCodec ff_roq_encoder; -extern const AVCodec ff_roq_decoder; -extern const AVCodec ff_rpza_encoder; -extern const AVCodec ff_rpza_decoder; -extern const AVCodec ff_rscc_decoder; -extern const AVCodec ff_rv10_encoder; -extern const AVCodec ff_rv10_decoder; -extern const AVCodec ff_rv20_encoder; -extern const AVCodec ff_rv20_decoder; -extern const AVCodec ff_rv30_decoder; -extern const AVCodec ff_rv40_decoder; -extern const AVCodec ff_s302m_encoder; -extern const AVCodec ff_s302m_decoder; -extern const AVCodec ff_sanm_decoder; -extern const AVCodec ff_scpr_decoder; -extern const AVCodec ff_screenpresso_decoder; -extern const AVCodec ff_sga_decoder; -extern const AVCodec ff_sgi_encoder; -extern const AVCodec ff_sgi_decoder; -extern const AVCodec ff_sgirle_decoder; -extern const AVCodec ff_sheervideo_decoder; -extern const AVCodec ff_simbiosis_imx_decoder; -extern const AVCodec ff_smacker_decoder; -extern const AVCodec ff_smc_encoder; -extern const AVCodec ff_smc_decoder; -extern const AVCodec ff_smvjpeg_decoder; -extern const AVCodec ff_snow_encoder; -extern const AVCodec ff_snow_decoder; -extern const AVCodec ff_sp5x_decoder; -extern const AVCodec ff_speedhq_decoder; -extern const AVCodec ff_speedhq_encoder; -extern const AVCodec ff_speex_decoder; -extern const AVCodec ff_srgc_decoder; -extern const AVCodec ff_sunrast_encoder; -extern const AVCodec ff_sunrast_decoder; -extern const AVCodec ff_svq1_encoder; -extern const AVCodec ff_svq1_decoder; -extern const AVCodec ff_svq3_decoder; -extern const AVCodec ff_targa_encoder; -extern const AVCodec ff_targa_decoder; -extern const AVCodec ff_targa_y216_decoder; -extern const AVCodec ff_tdsc_decoder; -extern const AVCodec ff_theora_decoder; -extern const AVCodec ff_thp_decoder; -extern const AVCodec ff_tiertexseqvideo_decoder; -extern const AVCodec ff_tiff_encoder; -extern const AVCodec ff_tiff_decoder; -extern const AVCodec ff_tmv_decoder; -extern const AVCodec ff_truemotion1_decoder; -extern const AVCodec ff_truemotion2_decoder; -extern const AVCodec ff_truemotion2rt_decoder; -extern const AVCodec ff_tscc_decoder; -extern const AVCodec ff_tscc2_decoder; -extern const AVCodec ff_txd_decoder; -extern const AVCodec ff_ulti_decoder; -extern const AVCodec ff_utvideo_encoder; -extern const AVCodec ff_utvideo_decoder; -extern const AVCodec ff_v210_encoder; -extern const AVCodec ff_v210_decoder; -extern const AVCodec ff_v210x_decoder; -extern const AVCodec ff_v308_encoder; -extern const AVCodec ff_v308_decoder; -extern const AVCodec ff_v408_encoder; -extern const AVCodec ff_v408_decoder; -extern const AVCodec ff_v410_encoder; -extern const AVCodec ff_v410_decoder; -extern const AVCodec ff_vb_decoder; -extern const AVCodec ff_vble_decoder; -extern const AVCodec ff_vc1_decoder; -extern const AVCodec ff_vc1_crystalhd_decoder; -extern const AVCodec ff_vc1image_decoder; -extern const AVCodec ff_vc1_mmal_decoder; -extern const AVCodec ff_vc1_qsv_decoder; -extern const AVCodec ff_vc1_v4l2m2m_decoder; -extern const AVCodec ff_vc2_encoder; -extern const AVCodec ff_vcr1_decoder; -extern const AVCodec ff_vmdvideo_decoder; -extern const AVCodec ff_vmnc_decoder; -extern const AVCodec ff_vp3_decoder; -extern const AVCodec ff_vp4_decoder; -extern const AVCodec ff_vp5_decoder; -extern const AVCodec ff_vp6_decoder; -extern const AVCodec ff_vp6a_decoder; -extern const AVCodec ff_vp6f_decoder; -extern const AVCodec ff_vp7_decoder; -extern const AVCodec ff_vp8_decoder; -extern const AVCodec ff_vp8_rkmpp_decoder; -extern const AVCodec ff_vp8_v4l2m2m_decoder; -extern const AVCodec ff_vp9_decoder; -extern const AVCodec ff_vp9_rkmpp_decoder; -extern const AVCodec ff_vp9_v4l2m2m_decoder; -extern const AVCodec ff_vqa_decoder; -extern const AVCodec ff_webp_decoder; -extern const AVCodec ff_wcmv_decoder; -extern const AVCodec ff_wrapped_avframe_encoder; -extern const AVCodec ff_wrapped_avframe_decoder; -extern const AVCodec ff_wmv1_encoder; -extern const AVCodec ff_wmv1_decoder; -extern const AVCodec ff_wmv2_encoder; -extern const AVCodec ff_wmv2_decoder; -extern const AVCodec ff_wmv3_decoder; -extern const AVCodec ff_wmv3_crystalhd_decoder; -extern const AVCodec ff_wmv3image_decoder; -extern const AVCodec ff_wnv1_decoder; -extern const AVCodec ff_xan_wc3_decoder; -extern const AVCodec ff_xan_wc4_decoder; -extern const AVCodec ff_xbm_encoder; -extern const AVCodec ff_xbm_decoder; -extern const AVCodec ff_xface_encoder; -extern const AVCodec ff_xface_decoder; -extern const AVCodec ff_xl_decoder; -extern const AVCodec ff_xpm_decoder; -extern const AVCodec ff_xwd_encoder; -extern const AVCodec ff_xwd_decoder; -extern const AVCodec ff_y41p_encoder; -extern const AVCodec ff_y41p_decoder; -extern const AVCodec ff_ylc_decoder; -extern const AVCodec ff_yop_decoder; -extern const AVCodec ff_yuv4_encoder; -extern const AVCodec ff_yuv4_decoder; -extern const AVCodec ff_zero12v_decoder; -extern const AVCodec ff_zerocodec_decoder; -extern const AVCodec ff_zlib_encoder; -extern const AVCodec ff_zlib_decoder; -extern const AVCodec ff_zmbv_encoder; -extern const AVCodec ff_zmbv_decoder; +extern const FFCodec ff_a64multi_encoder; +extern const FFCodec ff_a64multi5_encoder; +extern const FFCodec ff_aasc_decoder; +extern const FFCodec ff_aic_decoder; +extern const FFCodec ff_alias_pix_encoder; +extern const FFCodec ff_alias_pix_decoder; +extern const FFCodec ff_agm_decoder; +extern const FFCodec ff_amv_encoder; +extern const FFCodec ff_amv_decoder; +extern const FFCodec ff_anm_decoder; +extern const FFCodec ff_ansi_decoder; +extern const FFCodec ff_apng_encoder; +extern const FFCodec ff_apng_decoder; +extern const FFCodec ff_arbc_decoder; +extern const FFCodec ff_argo_decoder; +extern const FFCodec ff_asv1_encoder; +extern const FFCodec ff_asv1_decoder; +extern const FFCodec ff_asv2_encoder; +extern const FFCodec ff_asv2_decoder; +extern const FFCodec ff_aura_decoder; +extern const FFCodec ff_aura2_decoder; +extern const FFCodec ff_avrp_encoder; +extern const FFCodec ff_avrp_decoder; +extern const FFCodec ff_avrn_decoder; +extern const FFCodec ff_avs_decoder; +extern const FFCodec ff_avui_encoder; +extern const FFCodec ff_avui_decoder; +extern const FFCodec ff_ayuv_encoder; +extern const FFCodec ff_ayuv_decoder; +extern const FFCodec ff_bethsoftvid_decoder; +extern const FFCodec ff_bfi_decoder; +extern const FFCodec ff_bink_decoder; +extern const FFCodec ff_bitpacked_decoder; +extern const FFCodec ff_bitpacked_encoder; +extern const FFCodec ff_bmp_encoder; +extern const FFCodec ff_bmp_decoder; +extern const FFCodec ff_bmv_video_decoder; +extern const FFCodec ff_brender_pix_decoder; +extern const FFCodec ff_c93_decoder; +extern const FFCodec ff_cavs_decoder; +extern const FFCodec ff_cdgraphics_decoder; +extern const FFCodec ff_cdtoons_decoder; +extern const FFCodec ff_cdxl_decoder; +extern const FFCodec ff_cfhd_encoder; +extern const FFCodec ff_cfhd_decoder; +extern const FFCodec ff_cinepak_encoder; +extern const FFCodec ff_cinepak_decoder; +extern const FFCodec ff_clearvideo_decoder; +extern const FFCodec ff_cljr_encoder; +extern const FFCodec ff_cljr_decoder; +extern const FFCodec ff_cllc_decoder; +extern const FFCodec ff_comfortnoise_encoder; +extern const FFCodec ff_comfortnoise_decoder; +extern const FFCodec ff_cpia_decoder; +extern const FFCodec ff_cri_decoder; +extern const FFCodec ff_cscd_decoder; +extern const FFCodec ff_cyuv_decoder; +extern const FFCodec ff_dds_decoder; +extern const FFCodec ff_dfa_decoder; +extern const FFCodec ff_dirac_decoder; +extern const FFCodec ff_dnxhd_encoder; +extern const FFCodec ff_dnxhd_decoder; +extern const FFCodec ff_dpx_encoder; +extern const FFCodec ff_dpx_decoder; +extern const FFCodec ff_dsicinvideo_decoder; +extern const FFCodec ff_dvaudio_decoder; +extern const FFCodec ff_dvvideo_encoder; +extern const FFCodec ff_dvvideo_decoder; +extern const FFCodec ff_dxa_decoder; +extern const FFCodec ff_dxtory_decoder; +extern const FFCodec ff_dxv_decoder; +extern const FFCodec ff_eacmv_decoder; +extern const FFCodec ff_eamad_decoder; +extern const FFCodec ff_eatgq_decoder; +extern const FFCodec ff_eatgv_decoder; +extern const FFCodec ff_eatqi_decoder; +extern const FFCodec ff_eightbps_decoder; +extern const FFCodec ff_eightsvx_exp_decoder; +extern const FFCodec ff_eightsvx_fib_decoder; +extern const FFCodec ff_escape124_decoder; +extern const FFCodec ff_escape130_decoder; +extern const FFCodec ff_exr_encoder; +extern const FFCodec ff_exr_decoder; +extern const FFCodec ff_ffv1_encoder; +extern const FFCodec ff_ffv1_decoder; +extern const FFCodec ff_ffvhuff_encoder; +extern const FFCodec ff_ffvhuff_decoder; +extern const FFCodec ff_fic_decoder; +extern const FFCodec ff_fits_encoder; +extern const FFCodec ff_fits_decoder; +extern const FFCodec ff_flashsv_encoder; +extern const FFCodec ff_flashsv_decoder; +extern const FFCodec ff_flashsv2_encoder; +extern const FFCodec ff_flashsv2_decoder; +extern const FFCodec ff_flic_decoder; +extern const FFCodec ff_flv_encoder; +extern const FFCodec ff_flv_decoder; +extern const FFCodec ff_fmvc_decoder; +extern const FFCodec ff_fourxm_decoder; +extern const FFCodec ff_fraps_decoder; +extern const FFCodec ff_frwu_decoder; +extern const FFCodec ff_g2m_decoder; +extern const FFCodec ff_gdv_decoder; +extern const FFCodec ff_gem_decoder; +extern const FFCodec ff_gif_encoder; +extern const FFCodec ff_gif_decoder; +extern const FFCodec ff_h261_encoder; +extern const FFCodec ff_h261_decoder; +extern const FFCodec ff_h263_encoder; +extern const FFCodec ff_h263_decoder; +extern const FFCodec ff_h263i_decoder; +extern const FFCodec ff_h263p_encoder; +extern const FFCodec ff_h263p_decoder; +extern const FFCodec ff_h263_v4l2m2m_decoder; +extern const FFCodec ff_h264_decoder; +extern const FFCodec ff_h264_crystalhd_decoder; +extern const FFCodec ff_h264_v4l2m2m_decoder; +extern const FFCodec ff_h264_mediacodec_decoder; +extern const FFCodec ff_h264_mmal_decoder; +extern const FFCodec ff_h264_qsv_decoder; +extern const FFCodec ff_h264_rkmpp_decoder; +extern const FFCodec ff_hap_encoder; +extern const FFCodec ff_hap_decoder; +extern const FFCodec ff_hevc_decoder; +extern const FFCodec ff_hevc_qsv_decoder; +extern const FFCodec ff_hevc_rkmpp_decoder; +extern const FFCodec ff_hevc_v4l2m2m_decoder; +extern const FFCodec ff_hnm4_video_decoder; +extern const FFCodec ff_hq_hqa_decoder; +extern const FFCodec ff_hqx_decoder; +extern const FFCodec ff_huffyuv_encoder; +extern const FFCodec ff_huffyuv_decoder; +extern const FFCodec ff_hymt_decoder; +extern const FFCodec ff_idcin_decoder; +extern const FFCodec ff_iff_ilbm_decoder; +extern const FFCodec ff_imm4_decoder; +extern const FFCodec ff_imm5_decoder; +extern const FFCodec ff_indeo2_decoder; +extern const FFCodec ff_indeo3_decoder; +extern const FFCodec ff_indeo4_decoder; +extern const FFCodec ff_indeo5_decoder; +extern const FFCodec ff_interplay_video_decoder; +extern const FFCodec ff_ipu_decoder; +extern const FFCodec ff_jpeg2000_encoder; +extern const FFCodec ff_jpeg2000_decoder; +extern const FFCodec ff_jpegls_encoder; +extern const FFCodec ff_jpegls_decoder; +extern const FFCodec ff_jv_decoder; +extern const FFCodec ff_kgv1_decoder; +extern const FFCodec ff_kmvc_decoder; +extern const FFCodec ff_lagarith_decoder; +extern const FFCodec ff_ljpeg_encoder; +extern const FFCodec ff_loco_decoder; +extern const FFCodec ff_lscr_decoder; +extern const FFCodec ff_m101_decoder; +extern const FFCodec ff_magicyuv_encoder; +extern const FFCodec ff_magicyuv_decoder; +extern const FFCodec ff_mdec_decoder; +extern const FFCodec ff_mimic_decoder; +extern const FFCodec ff_mjpeg_encoder; +extern const FFCodec ff_mjpeg_decoder; +extern const FFCodec ff_mjpegb_decoder; +extern const FFCodec ff_mmvideo_decoder; +extern const FFCodec ff_mobiclip_decoder; +extern const FFCodec ff_motionpixels_decoder; +extern const FFCodec ff_mpeg1video_encoder; +extern const FFCodec ff_mpeg1video_decoder; +extern const FFCodec ff_mpeg2video_encoder; +extern const FFCodec ff_mpeg2video_decoder; +extern const FFCodec ff_mpeg4_encoder; +extern const FFCodec ff_mpeg4_decoder; +extern const FFCodec ff_mpeg4_crystalhd_decoder; +extern const FFCodec ff_mpeg4_v4l2m2m_decoder; +extern const FFCodec ff_mpeg4_mmal_decoder; +extern const FFCodec ff_mpegvideo_decoder; +extern const FFCodec ff_mpeg1_v4l2m2m_decoder; +extern const FFCodec ff_mpeg2_mmal_decoder; +extern const FFCodec ff_mpeg2_crystalhd_decoder; +extern const FFCodec ff_mpeg2_v4l2m2m_decoder; +extern const FFCodec ff_mpeg2_qsv_decoder; +extern const FFCodec ff_mpeg2_mediacodec_decoder; +extern const FFCodec ff_msa1_decoder; +extern const FFCodec ff_mscc_decoder; +extern const FFCodec ff_msmpeg4v1_decoder; +extern const FFCodec ff_msmpeg4v2_encoder; +extern const FFCodec ff_msmpeg4v2_decoder; +extern const FFCodec ff_msmpeg4v3_encoder; +extern const FFCodec ff_msmpeg4v3_decoder; +extern const FFCodec ff_msmpeg4_crystalhd_decoder; +extern const FFCodec ff_msp2_decoder; +extern const FFCodec ff_msrle_decoder; +extern const FFCodec ff_mss1_decoder; +extern const FFCodec ff_mss2_decoder; +extern const FFCodec ff_msvideo1_encoder; +extern const FFCodec ff_msvideo1_decoder; +extern const FFCodec ff_mszh_decoder; +extern const FFCodec ff_mts2_decoder; +extern const FFCodec ff_mv30_decoder; +extern const FFCodec ff_mvc1_decoder; +extern const FFCodec ff_mvc2_decoder; +extern const FFCodec ff_mvdv_decoder; +extern const FFCodec ff_mvha_decoder; +extern const FFCodec ff_mwsc_decoder; +extern const FFCodec ff_mxpeg_decoder; +extern const FFCodec ff_notchlc_decoder; +extern const FFCodec ff_nuv_decoder; +extern const FFCodec ff_paf_video_decoder; +extern const FFCodec ff_pam_encoder; +extern const FFCodec ff_pam_decoder; +extern const FFCodec ff_pbm_encoder; +extern const FFCodec ff_pbm_decoder; +extern const FFCodec ff_pcx_encoder; +extern const FFCodec ff_pcx_decoder; +extern const FFCodec ff_pfm_encoder; +extern const FFCodec ff_pfm_decoder; +extern const FFCodec ff_pgm_encoder; +extern const FFCodec ff_pgm_decoder; +extern const FFCodec ff_pgmyuv_encoder; +extern const FFCodec ff_pgmyuv_decoder; +extern const FFCodec ff_pgx_decoder; +extern const FFCodec ff_phm_encoder; +extern const FFCodec ff_phm_decoder; +extern const FFCodec ff_photocd_decoder; +extern const FFCodec ff_pictor_decoder; +extern const FFCodec ff_pixlet_decoder; +extern const FFCodec ff_png_encoder; +extern const FFCodec ff_png_decoder; +extern const FFCodec ff_ppm_encoder; +extern const FFCodec ff_ppm_decoder; +extern const FFCodec ff_prores_encoder; +extern const FFCodec ff_prores_decoder; +extern const FFCodec ff_prores_aw_encoder; +extern const FFCodec ff_prores_ks_encoder; +extern const FFCodec ff_prosumer_decoder; +extern const FFCodec ff_psd_decoder; +extern const FFCodec ff_ptx_decoder; +extern const FFCodec ff_qdraw_decoder; +extern const FFCodec ff_qoi_encoder; +extern const FFCodec ff_qoi_decoder; +extern const FFCodec ff_qpeg_decoder; +extern const FFCodec ff_qtrle_encoder; +extern const FFCodec ff_qtrle_decoder; +extern const FFCodec ff_r10k_encoder; +extern const FFCodec ff_r10k_decoder; +extern const FFCodec ff_r210_encoder; +extern const FFCodec ff_r210_decoder; +extern const FFCodec ff_rasc_decoder; +extern const FFCodec ff_rawvideo_encoder; +extern const FFCodec ff_rawvideo_decoder; +extern const FFCodec ff_rl2_decoder; +extern const FFCodec ff_roq_encoder; +extern const FFCodec ff_roq_decoder; +extern const FFCodec ff_rpza_encoder; +extern const FFCodec ff_rpza_decoder; +extern const FFCodec ff_rscc_decoder; +extern const FFCodec ff_rv10_encoder; +extern const FFCodec ff_rv10_decoder; +extern const FFCodec ff_rv20_encoder; +extern const FFCodec ff_rv20_decoder; +extern const FFCodec ff_rv30_decoder; +extern const FFCodec ff_rv40_decoder; +extern const FFCodec ff_s302m_encoder; +extern const FFCodec ff_s302m_decoder; +extern const FFCodec ff_sanm_decoder; +extern const FFCodec ff_scpr_decoder; +extern const FFCodec ff_screenpresso_decoder; +extern const FFCodec ff_sga_decoder; +extern const FFCodec ff_sgi_encoder; +extern const FFCodec ff_sgi_decoder; +extern const FFCodec ff_sgirle_decoder; +extern const FFCodec ff_sheervideo_decoder; +extern const FFCodec ff_simbiosis_imx_decoder; +extern const FFCodec ff_smacker_decoder; +extern const FFCodec ff_smc_encoder; +extern const FFCodec ff_smc_decoder; +extern const FFCodec ff_smvjpeg_decoder; +extern const FFCodec ff_snow_encoder; +extern const FFCodec ff_snow_decoder; +extern const FFCodec ff_sp5x_decoder; +extern const FFCodec ff_speedhq_decoder; +extern const FFCodec ff_speedhq_encoder; +extern const FFCodec ff_speex_decoder; +extern const FFCodec ff_srgc_decoder; +extern const FFCodec ff_sunrast_encoder; +extern const FFCodec ff_sunrast_decoder; +extern const FFCodec ff_svq1_encoder; +extern const FFCodec ff_svq1_decoder; +extern const FFCodec ff_svq3_decoder; +extern const FFCodec ff_targa_encoder; +extern const FFCodec ff_targa_decoder; +extern const FFCodec ff_targa_y216_decoder; +extern const FFCodec ff_tdsc_decoder; +extern const FFCodec ff_theora_decoder; +extern const FFCodec ff_thp_decoder; +extern const FFCodec ff_tiertexseqvideo_decoder; +extern const FFCodec ff_tiff_encoder; +extern const FFCodec ff_tiff_decoder; +extern const FFCodec ff_tmv_decoder; +extern const FFCodec ff_truemotion1_decoder; +extern const FFCodec ff_truemotion2_decoder; +extern const FFCodec ff_truemotion2rt_decoder; +extern const FFCodec ff_tscc_decoder; +extern const FFCodec ff_tscc2_decoder; +extern const FFCodec ff_txd_decoder; +extern const FFCodec ff_ulti_decoder; +extern const FFCodec ff_utvideo_encoder; +extern const FFCodec ff_utvideo_decoder; +extern const FFCodec ff_v210_encoder; +extern const FFCodec ff_v210_decoder; +extern const FFCodec ff_v210x_decoder; +extern const FFCodec ff_v308_encoder; +extern const FFCodec ff_v308_decoder; +extern const FFCodec ff_v408_encoder; +extern const FFCodec ff_v408_decoder; +extern const FFCodec ff_v410_encoder; +extern const FFCodec ff_v410_decoder; +extern const FFCodec ff_vb_decoder; +extern const FFCodec ff_vbn_encoder; +extern const FFCodec ff_vbn_decoder; +extern const FFCodec ff_vble_decoder; +extern const FFCodec ff_vc1_decoder; +extern const FFCodec ff_vc1_crystalhd_decoder; +extern const FFCodec ff_vc1image_decoder; +extern const FFCodec ff_vc1_mmal_decoder; +extern const FFCodec ff_vc1_qsv_decoder; +extern const FFCodec ff_vc1_v4l2m2m_decoder; +extern const FFCodec ff_vc2_encoder; +extern const FFCodec ff_vcr1_decoder; +extern const FFCodec ff_vmdvideo_decoder; +extern const FFCodec ff_vmnc_decoder; +extern const FFCodec ff_vp3_decoder; +extern const FFCodec ff_vp4_decoder; +extern const FFCodec ff_vp5_decoder; +extern const FFCodec ff_vp6_decoder; +extern const FFCodec ff_vp6a_decoder; +extern const FFCodec ff_vp6f_decoder; +extern const FFCodec ff_vp7_decoder; +extern const FFCodec ff_vp8_decoder; +extern const FFCodec ff_vp8_rkmpp_decoder; +extern const FFCodec ff_vp8_v4l2m2m_decoder; +extern const FFCodec ff_vp9_decoder; +extern const FFCodec ff_vp9_rkmpp_decoder; +extern const FFCodec ff_vp9_v4l2m2m_decoder; +extern const FFCodec ff_vqa_decoder; +extern const FFCodec ff_webp_decoder; +extern const FFCodec ff_wcmv_decoder; +extern const FFCodec ff_wrapped_avframe_encoder; +extern const FFCodec ff_wrapped_avframe_decoder; +extern const FFCodec ff_wmv1_encoder; +extern const FFCodec ff_wmv1_decoder; +extern const FFCodec ff_wmv2_encoder; +extern const FFCodec ff_wmv2_decoder; +extern const FFCodec ff_wmv3_decoder; +extern const FFCodec ff_wmv3_crystalhd_decoder; +extern const FFCodec ff_wmv3image_decoder; +extern const FFCodec ff_wnv1_decoder; +extern const FFCodec ff_xan_wc3_decoder; +extern const FFCodec ff_xan_wc4_decoder; +extern const FFCodec ff_xbm_encoder; +extern const FFCodec ff_xbm_decoder; +extern const FFCodec ff_xface_encoder; +extern const FFCodec ff_xface_decoder; +extern const FFCodec ff_xl_decoder; +extern const FFCodec ff_xpm_decoder; +extern const FFCodec ff_xwd_encoder; +extern const FFCodec ff_xwd_decoder; +extern const FFCodec ff_y41p_encoder; +extern const FFCodec ff_y41p_decoder; +extern const FFCodec ff_ylc_decoder; +extern const FFCodec ff_yop_decoder; +extern const FFCodec ff_yuv4_encoder; +extern const FFCodec ff_yuv4_decoder; +extern const FFCodec ff_zero12v_decoder; +extern const FFCodec ff_zerocodec_decoder; +extern const FFCodec ff_zlib_encoder; +extern const FFCodec ff_zlib_decoder; +extern const FFCodec ff_zmbv_encoder; +extern const FFCodec ff_zmbv_decoder; /* audio codecs */ -extern const AVCodec ff_aac_encoder; -extern const AVCodec ff_aac_decoder; -extern const AVCodec ff_aac_fixed_decoder; -extern const AVCodec ff_aac_latm_decoder; -extern const AVCodec ff_ac3_encoder; -extern const AVCodec ff_ac3_decoder; -extern const AVCodec ff_ac3_fixed_encoder; -extern const AVCodec ff_ac3_fixed_decoder; -extern const AVCodec ff_acelp_kelvin_decoder; -extern const AVCodec ff_alac_encoder; -extern const AVCodec ff_alac_decoder; -extern const AVCodec ff_als_decoder; -extern const AVCodec ff_amrnb_decoder; -extern const AVCodec ff_amrwb_decoder; -extern const AVCodec ff_ape_decoder; -extern const AVCodec ff_aptx_encoder; -extern const AVCodec ff_aptx_decoder; -extern const AVCodec ff_aptx_hd_encoder; -extern const AVCodec ff_aptx_hd_decoder; -extern const AVCodec ff_atrac1_decoder; -extern const AVCodec ff_atrac3_decoder; -extern const AVCodec ff_atrac3al_decoder; -extern const AVCodec ff_atrac3p_decoder; -extern const AVCodec ff_atrac3pal_decoder; -extern const AVCodec ff_atrac9_decoder; -extern const AVCodec ff_binkaudio_dct_decoder; -extern const AVCodec ff_binkaudio_rdft_decoder; -extern const AVCodec ff_bmv_audio_decoder; -extern const AVCodec ff_cook_decoder; -extern const AVCodec ff_dca_encoder; -extern const AVCodec ff_dca_decoder; -extern const AVCodec ff_dolby_e_decoder; -extern const AVCodec ff_dsd_lsbf_decoder; -extern const AVCodec ff_dsd_msbf_decoder; -extern const AVCodec ff_dsd_lsbf_planar_decoder; -extern const AVCodec ff_dsd_msbf_planar_decoder; -extern const AVCodec ff_dsicinaudio_decoder; -extern const AVCodec ff_dss_sp_decoder; -extern const AVCodec ff_dst_decoder; -extern const AVCodec ff_eac3_encoder; -extern const AVCodec ff_eac3_decoder; -extern const AVCodec ff_evrc_decoder; -extern const AVCodec ff_fastaudio_decoder; -extern const AVCodec ff_ffwavesynth_decoder; -extern const AVCodec ff_flac_encoder; -extern const AVCodec ff_flac_decoder; -extern const AVCodec ff_g723_1_encoder; -extern const AVCodec ff_g723_1_decoder; -extern const AVCodec ff_g729_decoder; -extern const AVCodec ff_gsm_decoder; -extern const AVCodec ff_gsm_ms_decoder; -extern const AVCodec ff_hca_decoder; -extern const AVCodec ff_hcom_decoder; -extern const AVCodec ff_iac_decoder; -extern const AVCodec ff_ilbc_decoder; -extern const AVCodec ff_imc_decoder; -extern const AVCodec ff_interplay_acm_decoder; -extern const AVCodec ff_mace3_decoder; -extern const AVCodec ff_mace6_decoder; -extern const AVCodec ff_metasound_decoder; -extern const AVCodec ff_mlp_encoder; -extern const AVCodec ff_mlp_decoder; -extern const AVCodec ff_mp1_decoder; -extern const AVCodec ff_mp1float_decoder; -extern const AVCodec ff_mp2_encoder; -extern const AVCodec ff_mp2_decoder; -extern const AVCodec ff_mp2float_decoder; -extern const AVCodec ff_mp2fixed_encoder; -extern const AVCodec ff_mp3float_decoder; -extern const AVCodec ff_mp3_decoder; -extern const AVCodec ff_mp3adufloat_decoder; -extern const AVCodec ff_mp3adu_decoder; -extern const AVCodec ff_mp3on4float_decoder; -extern const AVCodec ff_mp3on4_decoder; -extern const AVCodec ff_mpc7_decoder; -extern const AVCodec ff_mpc8_decoder; -extern const AVCodec ff_msnsiren_decoder; -extern const AVCodec ff_nellymoser_encoder; -extern const AVCodec ff_nellymoser_decoder; -extern const AVCodec ff_on2avc_decoder; -extern const AVCodec ff_opus_encoder; -extern const AVCodec ff_opus_decoder; -extern const AVCodec ff_paf_audio_decoder; -extern const AVCodec ff_qcelp_decoder; -extern const AVCodec ff_qdm2_decoder; -extern const AVCodec ff_qdmc_decoder; -extern const AVCodec ff_ra_144_encoder; -extern const AVCodec ff_ra_144_decoder; -extern const AVCodec ff_ra_288_decoder; -extern const AVCodec ff_ralf_decoder; -extern const AVCodec ff_sbc_encoder; -extern const AVCodec ff_sbc_decoder; -extern const AVCodec ff_shorten_decoder; -extern const AVCodec ff_sipr_decoder; -extern const AVCodec ff_siren_decoder; -extern const AVCodec ff_smackaud_decoder; -extern const AVCodec ff_sonic_encoder; -extern const AVCodec ff_sonic_decoder; -extern const AVCodec ff_sonic_ls_encoder; -extern const AVCodec ff_tak_decoder; -extern const AVCodec ff_truehd_encoder; -extern const AVCodec ff_truehd_decoder; -extern const AVCodec ff_truespeech_decoder; -extern const AVCodec ff_tta_encoder; -extern const AVCodec ff_tta_decoder; -extern const AVCodec ff_twinvq_decoder; -extern const AVCodec ff_vmdaudio_decoder; -extern const AVCodec ff_vorbis_encoder; -extern const AVCodec ff_vorbis_decoder; -extern const AVCodec ff_wavpack_encoder; -extern const AVCodec ff_wavpack_decoder; -extern const AVCodec ff_wmalossless_decoder; -extern const AVCodec ff_wmapro_decoder; -extern const AVCodec ff_wmav1_encoder; -extern const AVCodec ff_wmav1_decoder; -extern const AVCodec ff_wmav2_encoder; -extern const AVCodec ff_wmav2_decoder; -extern const AVCodec ff_wmavoice_decoder; -extern const AVCodec ff_ws_snd1_decoder; -extern const AVCodec ff_xma1_decoder; -extern const AVCodec ff_xma2_decoder; +extern const FFCodec ff_aac_encoder; +extern const FFCodec ff_aac_decoder; +extern const FFCodec ff_aac_fixed_decoder; +extern const FFCodec ff_aac_latm_decoder; +extern const FFCodec ff_ac3_encoder; +extern const FFCodec ff_ac3_decoder; +extern const FFCodec ff_ac3_fixed_encoder; +extern const FFCodec ff_ac3_fixed_decoder; +extern const FFCodec ff_acelp_kelvin_decoder; +extern const FFCodec ff_alac_encoder; +extern const FFCodec ff_alac_decoder; +extern const FFCodec ff_als_decoder; +extern const FFCodec ff_amrnb_decoder; +extern const FFCodec ff_amrwb_decoder; +extern const FFCodec ff_ape_decoder; +extern const FFCodec ff_aptx_encoder; +extern const FFCodec ff_aptx_decoder; +extern const FFCodec ff_aptx_hd_encoder; +extern const FFCodec ff_aptx_hd_decoder; +extern const FFCodec ff_atrac1_decoder; +extern const FFCodec ff_atrac3_decoder; +extern const FFCodec ff_atrac3al_decoder; +extern const FFCodec ff_atrac3p_decoder; +extern const FFCodec ff_atrac3pal_decoder; +extern const FFCodec ff_atrac9_decoder; +extern const FFCodec ff_binkaudio_dct_decoder; +extern const FFCodec ff_binkaudio_rdft_decoder; +extern const FFCodec ff_bmv_audio_decoder; +extern const FFCodec ff_cook_decoder; +extern const FFCodec ff_dca_encoder; +extern const FFCodec ff_dca_decoder; +extern const FFCodec ff_dfpwm_encoder; +extern const FFCodec ff_dfpwm_decoder; +extern const FFCodec ff_dolby_e_decoder; +extern const FFCodec ff_dsd_lsbf_decoder; +extern const FFCodec ff_dsd_msbf_decoder; +extern const FFCodec ff_dsd_lsbf_planar_decoder; +extern const FFCodec ff_dsd_msbf_planar_decoder; +extern const FFCodec ff_dsicinaudio_decoder; +extern const FFCodec ff_dss_sp_decoder; +extern const FFCodec ff_dst_decoder; +extern const FFCodec ff_eac3_encoder; +extern const FFCodec ff_eac3_decoder; +extern const FFCodec ff_evrc_decoder; +extern const FFCodec ff_fastaudio_decoder; +extern const FFCodec ff_ffwavesynth_decoder; +extern const FFCodec ff_flac_encoder; +extern const FFCodec ff_flac_decoder; +extern const FFCodec ff_g723_1_encoder; +extern const FFCodec ff_g723_1_decoder; +extern const FFCodec ff_g729_decoder; +extern const FFCodec ff_gsm_decoder; +extern const FFCodec ff_gsm_ms_decoder; +extern const FFCodec ff_hca_decoder; +extern const FFCodec ff_hcom_decoder; +extern const FFCodec ff_iac_decoder; +extern const FFCodec ff_ilbc_decoder; +extern const FFCodec ff_imc_decoder; +extern const FFCodec ff_interplay_acm_decoder; +extern const FFCodec ff_mace3_decoder; +extern const FFCodec ff_mace6_decoder; +extern const FFCodec ff_metasound_decoder; +extern const FFCodec ff_mlp_encoder; +extern const FFCodec ff_mlp_decoder; +extern const FFCodec ff_mp1_decoder; +extern const FFCodec ff_mp1float_decoder; +extern const FFCodec ff_mp2_encoder; +extern const FFCodec ff_mp2_decoder; +extern const FFCodec ff_mp2float_decoder; +extern const FFCodec ff_mp2fixed_encoder; +extern const FFCodec ff_mp3float_decoder; +extern const FFCodec ff_mp3_decoder; +extern const FFCodec ff_mp3adufloat_decoder; +extern const FFCodec ff_mp3adu_decoder; +extern const FFCodec ff_mp3on4float_decoder; +extern const FFCodec ff_mp3on4_decoder; +extern const FFCodec ff_mpc7_decoder; +extern const FFCodec ff_mpc8_decoder; +extern const FFCodec ff_msnsiren_decoder; +extern const FFCodec ff_nellymoser_encoder; +extern const FFCodec ff_nellymoser_decoder; +extern const FFCodec ff_on2avc_decoder; +extern const FFCodec ff_opus_encoder; +extern const FFCodec ff_opus_decoder; +extern const FFCodec ff_paf_audio_decoder; +extern const FFCodec ff_qcelp_decoder; +extern const FFCodec ff_qdm2_decoder; +extern const FFCodec ff_qdmc_decoder; +extern const FFCodec ff_ra_144_encoder; +extern const FFCodec ff_ra_144_decoder; +extern const FFCodec ff_ra_288_decoder; +extern const FFCodec ff_ralf_decoder; +extern const FFCodec ff_sbc_encoder; +extern const FFCodec ff_sbc_decoder; +extern const FFCodec ff_shorten_decoder; +extern const FFCodec ff_sipr_decoder; +extern const FFCodec ff_siren_decoder; +extern const FFCodec ff_smackaud_decoder; +extern const FFCodec ff_sonic_encoder; +extern const FFCodec ff_sonic_decoder; +extern const FFCodec ff_sonic_ls_encoder; +extern const FFCodec ff_tak_decoder; +extern const FFCodec ff_truehd_encoder; +extern const FFCodec ff_truehd_decoder; +extern const FFCodec ff_truespeech_decoder; +extern const FFCodec ff_tta_encoder; +extern const FFCodec ff_tta_decoder; +extern const FFCodec ff_twinvq_decoder; +extern const FFCodec ff_vmdaudio_decoder; +extern const FFCodec ff_vorbis_encoder; +extern const FFCodec ff_vorbis_decoder; +extern const FFCodec ff_wavpack_encoder; +extern const FFCodec ff_wavpack_decoder; +extern const FFCodec ff_wmalossless_decoder; +extern const FFCodec ff_wmapro_decoder; +extern const FFCodec ff_wmav1_encoder; +extern const FFCodec ff_wmav1_decoder; +extern const FFCodec ff_wmav2_encoder; +extern const FFCodec ff_wmav2_decoder; +extern const FFCodec ff_wmavoice_decoder; +extern const FFCodec ff_ws_snd1_decoder; +extern const FFCodec ff_xma1_decoder; +extern const FFCodec ff_xma2_decoder; /* PCM codecs */ -extern const AVCodec ff_pcm_alaw_encoder; -extern const AVCodec ff_pcm_alaw_decoder; -extern const AVCodec ff_pcm_bluray_decoder; -extern const AVCodec ff_pcm_dvd_encoder; -extern const AVCodec ff_pcm_dvd_decoder; -extern const AVCodec ff_pcm_f16le_decoder; -extern const AVCodec ff_pcm_f24le_decoder; -extern const AVCodec ff_pcm_f32be_encoder; -extern const AVCodec ff_pcm_f32be_decoder; -extern const AVCodec ff_pcm_f32le_encoder; -extern const AVCodec ff_pcm_f32le_decoder; -extern const AVCodec ff_pcm_f64be_encoder; -extern const AVCodec ff_pcm_f64be_decoder; -extern const AVCodec ff_pcm_f64le_encoder; -extern const AVCodec ff_pcm_f64le_decoder; -extern const AVCodec ff_pcm_lxf_decoder; -extern const AVCodec ff_pcm_mulaw_encoder; -extern const AVCodec ff_pcm_mulaw_decoder; -extern const AVCodec ff_pcm_s8_encoder; -extern const AVCodec ff_pcm_s8_decoder; -extern const AVCodec ff_pcm_s8_planar_encoder; -extern const AVCodec ff_pcm_s8_planar_decoder; -extern const AVCodec ff_pcm_s16be_encoder; -extern const AVCodec ff_pcm_s16be_decoder; -extern const AVCodec ff_pcm_s16be_planar_encoder; -extern const AVCodec ff_pcm_s16be_planar_decoder; -extern const AVCodec ff_pcm_s16le_encoder; -extern const AVCodec ff_pcm_s16le_decoder; -extern const AVCodec ff_pcm_s16le_planar_encoder; -extern const AVCodec ff_pcm_s16le_planar_decoder; -extern const AVCodec ff_pcm_s24be_encoder; -extern const AVCodec ff_pcm_s24be_decoder; -extern const AVCodec ff_pcm_s24daud_encoder; -extern const AVCodec ff_pcm_s24daud_decoder; -extern const AVCodec ff_pcm_s24le_encoder; -extern const AVCodec ff_pcm_s24le_decoder; -extern const AVCodec ff_pcm_s24le_planar_encoder; -extern const AVCodec ff_pcm_s24le_planar_decoder; -extern const AVCodec ff_pcm_s32be_encoder; -extern const AVCodec ff_pcm_s32be_decoder; -extern const AVCodec ff_pcm_s32le_encoder; -extern const AVCodec ff_pcm_s32le_decoder; -extern const AVCodec ff_pcm_s32le_planar_encoder; -extern const AVCodec ff_pcm_s32le_planar_decoder; -extern const AVCodec ff_pcm_s64be_encoder; -extern const AVCodec ff_pcm_s64be_decoder; -extern const AVCodec ff_pcm_s64le_encoder; -extern const AVCodec ff_pcm_s64le_decoder; -extern const AVCodec ff_pcm_sga_decoder; -extern const AVCodec ff_pcm_u8_encoder; -extern const AVCodec ff_pcm_u8_decoder; -extern const AVCodec ff_pcm_u16be_encoder; -extern const AVCodec ff_pcm_u16be_decoder; -extern const AVCodec ff_pcm_u16le_encoder; -extern const AVCodec ff_pcm_u16le_decoder; -extern const AVCodec ff_pcm_u24be_encoder; -extern const AVCodec ff_pcm_u24be_decoder; -extern const AVCodec ff_pcm_u24le_encoder; -extern const AVCodec ff_pcm_u24le_decoder; -extern const AVCodec ff_pcm_u32be_encoder; -extern const AVCodec ff_pcm_u32be_decoder; -extern const AVCodec ff_pcm_u32le_encoder; -extern const AVCodec ff_pcm_u32le_decoder; -extern const AVCodec ff_pcm_vidc_encoder; -extern const AVCodec ff_pcm_vidc_decoder; +extern const FFCodec ff_pcm_alaw_encoder; +extern const FFCodec ff_pcm_alaw_decoder; +extern const FFCodec ff_pcm_bluray_encoder; +extern const FFCodec ff_pcm_bluray_decoder; +extern const FFCodec ff_pcm_dvd_encoder; +extern const FFCodec ff_pcm_dvd_decoder; +extern const FFCodec ff_pcm_f16le_decoder; +extern const FFCodec ff_pcm_f24le_decoder; +extern const FFCodec ff_pcm_f32be_encoder; +extern const FFCodec ff_pcm_f32be_decoder; +extern const FFCodec ff_pcm_f32le_encoder; +extern const FFCodec ff_pcm_f32le_decoder; +extern const FFCodec ff_pcm_f64be_encoder; +extern const FFCodec ff_pcm_f64be_decoder; +extern const FFCodec ff_pcm_f64le_encoder; +extern const FFCodec ff_pcm_f64le_decoder; +extern const FFCodec ff_pcm_lxf_decoder; +extern const FFCodec ff_pcm_mulaw_encoder; +extern const FFCodec ff_pcm_mulaw_decoder; +extern const FFCodec ff_pcm_s8_encoder; +extern const FFCodec ff_pcm_s8_decoder; +extern const FFCodec ff_pcm_s8_planar_encoder; +extern const FFCodec ff_pcm_s8_planar_decoder; +extern const FFCodec ff_pcm_s16be_encoder; +extern const FFCodec ff_pcm_s16be_decoder; +extern const FFCodec ff_pcm_s16be_planar_encoder; +extern const FFCodec ff_pcm_s16be_planar_decoder; +extern const FFCodec ff_pcm_s16le_encoder; +extern const FFCodec ff_pcm_s16le_decoder; +extern const FFCodec ff_pcm_s16le_planar_encoder; +extern const FFCodec ff_pcm_s16le_planar_decoder; +extern const FFCodec ff_pcm_s24be_encoder; +extern const FFCodec ff_pcm_s24be_decoder; +extern const FFCodec ff_pcm_s24daud_encoder; +extern const FFCodec ff_pcm_s24daud_decoder; +extern const FFCodec ff_pcm_s24le_encoder; +extern const FFCodec ff_pcm_s24le_decoder; +extern const FFCodec ff_pcm_s24le_planar_encoder; +extern const FFCodec ff_pcm_s24le_planar_decoder; +extern const FFCodec ff_pcm_s32be_encoder; +extern const FFCodec ff_pcm_s32be_decoder; +extern const FFCodec ff_pcm_s32le_encoder; +extern const FFCodec ff_pcm_s32le_decoder; +extern const FFCodec ff_pcm_s32le_planar_encoder; +extern const FFCodec ff_pcm_s32le_planar_decoder; +extern const FFCodec ff_pcm_s64be_encoder; +extern const FFCodec ff_pcm_s64be_decoder; +extern const FFCodec ff_pcm_s64le_encoder; +extern const FFCodec ff_pcm_s64le_decoder; +extern const FFCodec ff_pcm_sga_decoder; +extern const FFCodec ff_pcm_u8_encoder; +extern const FFCodec ff_pcm_u8_decoder; +extern const FFCodec ff_pcm_u16be_encoder; +extern const FFCodec ff_pcm_u16be_decoder; +extern const FFCodec ff_pcm_u16le_encoder; +extern const FFCodec ff_pcm_u16le_decoder; +extern const FFCodec ff_pcm_u24be_encoder; +extern const FFCodec ff_pcm_u24be_decoder; +extern const FFCodec ff_pcm_u24le_encoder; +extern const FFCodec ff_pcm_u24le_decoder; +extern const FFCodec ff_pcm_u32be_encoder; +extern const FFCodec ff_pcm_u32be_decoder; +extern const FFCodec ff_pcm_u32le_encoder; +extern const FFCodec ff_pcm_u32le_decoder; +extern const FFCodec ff_pcm_vidc_encoder; +extern const FFCodec ff_pcm_vidc_decoder; /* DPCM codecs */ -extern const AVCodec ff_derf_dpcm_decoder; -extern const AVCodec ff_gremlin_dpcm_decoder; -extern const AVCodec ff_interplay_dpcm_decoder; -extern const AVCodec ff_roq_dpcm_encoder; -extern const AVCodec ff_roq_dpcm_decoder; -extern const AVCodec ff_sdx2_dpcm_decoder; -extern const AVCodec ff_sol_dpcm_decoder; -extern const AVCodec ff_xan_dpcm_decoder; +extern const FFCodec ff_derf_dpcm_decoder; +extern const FFCodec ff_gremlin_dpcm_decoder; +extern const FFCodec ff_interplay_dpcm_decoder; +extern const FFCodec ff_roq_dpcm_encoder; +extern const FFCodec ff_roq_dpcm_decoder; +extern const FFCodec ff_sdx2_dpcm_decoder; +extern const FFCodec ff_sol_dpcm_decoder; +extern const FFCodec ff_xan_dpcm_decoder; /* ADPCM codecs */ -extern const AVCodec ff_adpcm_4xm_decoder; -extern const AVCodec ff_adpcm_adx_encoder; -extern const AVCodec ff_adpcm_adx_decoder; -extern const AVCodec ff_adpcm_afc_decoder; -extern const AVCodec ff_adpcm_agm_decoder; -extern const AVCodec ff_adpcm_aica_decoder; -extern const AVCodec ff_adpcm_argo_decoder; -extern const AVCodec ff_adpcm_argo_encoder; -extern const AVCodec ff_adpcm_ct_decoder; -extern const AVCodec ff_adpcm_dtk_decoder; -extern const AVCodec ff_adpcm_ea_decoder; -extern const AVCodec ff_adpcm_ea_maxis_xa_decoder; -extern const AVCodec ff_adpcm_ea_r1_decoder; -extern const AVCodec ff_adpcm_ea_r2_decoder; -extern const AVCodec ff_adpcm_ea_r3_decoder; -extern const AVCodec ff_adpcm_ea_xas_decoder; -extern const AVCodec ff_adpcm_g722_encoder; -extern const AVCodec ff_adpcm_g722_decoder; -extern const AVCodec ff_adpcm_g726_encoder; -extern const AVCodec ff_adpcm_g726_decoder; -extern const AVCodec ff_adpcm_g726le_encoder; -extern const AVCodec ff_adpcm_g726le_decoder; -extern const AVCodec ff_adpcm_ima_acorn_decoder; -extern const AVCodec ff_adpcm_ima_amv_decoder; -extern const AVCodec ff_adpcm_ima_amv_encoder; -extern const AVCodec ff_adpcm_ima_alp_decoder; -extern const AVCodec ff_adpcm_ima_alp_encoder; -extern const AVCodec ff_adpcm_ima_apc_decoder; -extern const AVCodec ff_adpcm_ima_apm_decoder; -extern const AVCodec ff_adpcm_ima_apm_encoder; -extern const AVCodec ff_adpcm_ima_cunning_decoder; -extern const AVCodec ff_adpcm_ima_dat4_decoder; -extern const AVCodec ff_adpcm_ima_dk3_decoder; -extern const AVCodec ff_adpcm_ima_dk4_decoder; -extern const AVCodec ff_adpcm_ima_ea_eacs_decoder; -extern const AVCodec ff_adpcm_ima_ea_sead_decoder; -extern const AVCodec ff_adpcm_ima_iss_decoder; -extern const AVCodec ff_adpcm_ima_moflex_decoder; -extern const AVCodec ff_adpcm_ima_mtf_decoder; -extern const AVCodec ff_adpcm_ima_oki_decoder; -extern const AVCodec ff_adpcm_ima_qt_encoder; -extern const AVCodec ff_adpcm_ima_qt_decoder; -extern const AVCodec ff_adpcm_ima_rad_decoder; -extern const AVCodec ff_adpcm_ima_ssi_decoder; -extern const AVCodec ff_adpcm_ima_ssi_encoder; -extern const AVCodec ff_adpcm_ima_smjpeg_decoder; -extern const AVCodec ff_adpcm_ima_wav_encoder; -extern const AVCodec ff_adpcm_ima_wav_decoder; -extern const AVCodec ff_adpcm_ima_ws_encoder; -extern const AVCodec ff_adpcm_ima_ws_decoder; -extern const AVCodec ff_adpcm_ms_encoder; -extern const AVCodec ff_adpcm_ms_decoder; -extern const AVCodec ff_adpcm_mtaf_decoder; -extern const AVCodec ff_adpcm_psx_decoder; -extern const AVCodec ff_adpcm_sbpro_2_decoder; -extern const AVCodec ff_adpcm_sbpro_3_decoder; -extern const AVCodec ff_adpcm_sbpro_4_decoder; -extern const AVCodec ff_adpcm_swf_encoder; -extern const AVCodec ff_adpcm_swf_decoder; -extern const AVCodec ff_adpcm_thp_decoder; -extern const AVCodec ff_adpcm_thp_le_decoder; -extern const AVCodec ff_adpcm_vima_decoder; -extern const AVCodec ff_adpcm_xa_decoder; -extern const AVCodec ff_adpcm_yamaha_encoder; -extern const AVCodec ff_adpcm_yamaha_decoder; -extern const AVCodec ff_adpcm_zork_decoder; +extern const FFCodec ff_adpcm_4xm_decoder; +extern const FFCodec ff_adpcm_adx_encoder; +extern const FFCodec ff_adpcm_adx_decoder; +extern const FFCodec ff_adpcm_afc_decoder; +extern const FFCodec ff_adpcm_agm_decoder; +extern const FFCodec ff_adpcm_aica_decoder; +extern const FFCodec ff_adpcm_argo_decoder; +extern const FFCodec ff_adpcm_argo_encoder; +extern const FFCodec ff_adpcm_ct_decoder; +extern const FFCodec ff_adpcm_dtk_decoder; +extern const FFCodec ff_adpcm_ea_decoder; +extern const FFCodec ff_adpcm_ea_maxis_xa_decoder; +extern const FFCodec ff_adpcm_ea_r1_decoder; +extern const FFCodec ff_adpcm_ea_r2_decoder; +extern const FFCodec ff_adpcm_ea_r3_decoder; +extern const FFCodec ff_adpcm_ea_xas_decoder; +extern const FFCodec ff_adpcm_g722_encoder; +extern const FFCodec ff_adpcm_g722_decoder; +extern const FFCodec ff_adpcm_g726_encoder; +extern const FFCodec ff_adpcm_g726_decoder; +extern const FFCodec ff_adpcm_g726le_encoder; +extern const FFCodec ff_adpcm_g726le_decoder; +extern const FFCodec ff_adpcm_ima_acorn_decoder; +extern const FFCodec ff_adpcm_ima_amv_decoder; +extern const FFCodec ff_adpcm_ima_amv_encoder; +extern const FFCodec ff_adpcm_ima_alp_decoder; +extern const FFCodec ff_adpcm_ima_alp_encoder; +extern const FFCodec ff_adpcm_ima_apc_decoder; +extern const FFCodec ff_adpcm_ima_apm_decoder; +extern const FFCodec ff_adpcm_ima_apm_encoder; +extern const FFCodec ff_adpcm_ima_cunning_decoder; +extern const FFCodec ff_adpcm_ima_dat4_decoder; +extern const FFCodec ff_adpcm_ima_dk3_decoder; +extern const FFCodec ff_adpcm_ima_dk4_decoder; +extern const FFCodec ff_adpcm_ima_ea_eacs_decoder; +extern const FFCodec ff_adpcm_ima_ea_sead_decoder; +extern const FFCodec ff_adpcm_ima_iss_decoder; +extern const FFCodec ff_adpcm_ima_moflex_decoder; +extern const FFCodec ff_adpcm_ima_mtf_decoder; +extern const FFCodec ff_adpcm_ima_oki_decoder; +extern const FFCodec ff_adpcm_ima_qt_encoder; +extern const FFCodec ff_adpcm_ima_qt_decoder; +extern const FFCodec ff_adpcm_ima_rad_decoder; +extern const FFCodec ff_adpcm_ima_ssi_decoder; +extern const FFCodec ff_adpcm_ima_ssi_encoder; +extern const FFCodec ff_adpcm_ima_smjpeg_decoder; +extern const FFCodec ff_adpcm_ima_wav_encoder; +extern const FFCodec ff_adpcm_ima_wav_decoder; +extern const FFCodec ff_adpcm_ima_ws_encoder; +extern const FFCodec ff_adpcm_ima_ws_decoder; +extern const FFCodec ff_adpcm_ms_encoder; +extern const FFCodec ff_adpcm_ms_decoder; +extern const FFCodec ff_adpcm_mtaf_decoder; +extern const FFCodec ff_adpcm_psx_decoder; +extern const FFCodec ff_adpcm_sbpro_2_decoder; +extern const FFCodec ff_adpcm_sbpro_3_decoder; +extern const FFCodec ff_adpcm_sbpro_4_decoder; +extern const FFCodec ff_adpcm_swf_encoder; +extern const FFCodec ff_adpcm_swf_decoder; +extern const FFCodec ff_adpcm_thp_decoder; +extern const FFCodec ff_adpcm_thp_le_decoder; +extern const FFCodec ff_adpcm_vima_decoder; +extern const FFCodec ff_adpcm_xa_decoder; +extern const FFCodec ff_adpcm_yamaha_encoder; +extern const FFCodec ff_adpcm_yamaha_decoder; +extern const FFCodec ff_adpcm_zork_decoder; /* subtitles */ -extern const AVCodec ff_ssa_encoder; -extern const AVCodec ff_ssa_decoder; -extern const AVCodec ff_ass_encoder; -extern const AVCodec ff_ass_decoder; -extern const AVCodec ff_ccaption_decoder; -extern const AVCodec ff_dvbsub_encoder; -extern const AVCodec ff_dvbsub_decoder; -extern const AVCodec ff_dvdsub_encoder; -extern const AVCodec ff_dvdsub_decoder; -extern const AVCodec ff_jacosub_decoder; -extern const AVCodec ff_microdvd_decoder; -extern const AVCodec ff_movtext_encoder; -extern const AVCodec ff_movtext_decoder; -extern const AVCodec ff_mpl2_decoder; -extern const AVCodec ff_pgssub_decoder; -extern const AVCodec ff_pjs_decoder; -extern const AVCodec ff_realtext_decoder; -extern const AVCodec ff_sami_decoder; -extern const AVCodec ff_srt_encoder; -extern const AVCodec ff_srt_decoder; -extern const AVCodec ff_stl_decoder; -extern const AVCodec ff_subrip_encoder; -extern const AVCodec ff_subrip_decoder; -extern const AVCodec ff_subviewer_decoder; -extern const AVCodec ff_subviewer1_decoder; -extern const AVCodec ff_text_encoder; -extern const AVCodec ff_text_decoder; -extern const AVCodec ff_ttml_encoder; -extern const AVCodec ff_vplayer_decoder; -extern const AVCodec ff_webvtt_encoder; -extern const AVCodec ff_webvtt_decoder; -extern const AVCodec ff_xsub_encoder; -extern const AVCodec ff_xsub_decoder; +extern const FFCodec ff_ssa_encoder; +extern const FFCodec ff_ssa_decoder; +extern const FFCodec ff_ass_encoder; +extern const FFCodec ff_ass_decoder; +extern const FFCodec ff_ccaption_decoder; +extern const FFCodec ff_dvbsub_encoder; +extern const FFCodec ff_dvbsub_decoder; +extern const FFCodec ff_dvdsub_encoder; +extern const FFCodec ff_dvdsub_decoder; +extern const FFCodec ff_jacosub_decoder; +extern const FFCodec ff_microdvd_decoder; +extern const FFCodec ff_movtext_encoder; +extern const FFCodec ff_movtext_decoder; +extern const FFCodec ff_mpl2_decoder; +extern const FFCodec ff_pgssub_decoder; +extern const FFCodec ff_pjs_decoder; +extern const FFCodec ff_realtext_decoder; +extern const FFCodec ff_sami_decoder; +extern const FFCodec ff_srt_encoder; +extern const FFCodec ff_srt_decoder; +extern const FFCodec ff_stl_decoder; +extern const FFCodec ff_subrip_encoder; +extern const FFCodec ff_subrip_decoder; +extern const FFCodec ff_subviewer_decoder; +extern const FFCodec ff_subviewer1_decoder; +extern const FFCodec ff_text_encoder; +extern const FFCodec ff_text_decoder; +extern const FFCodec ff_ttml_encoder; +extern const FFCodec ff_vplayer_decoder; +extern const FFCodec ff_webvtt_encoder; +extern const FFCodec ff_webvtt_decoder; +extern const FFCodec ff_xsub_encoder; +extern const FFCodec ff_xsub_decoder; /* external libraries */ -extern const AVCodec ff_aac_at_encoder; -extern const AVCodec ff_aac_at_decoder; -extern const AVCodec ff_ac3_at_decoder; -extern const AVCodec ff_adpcm_ima_qt_at_decoder; -extern const AVCodec ff_alac_at_encoder; -extern const AVCodec ff_alac_at_decoder; -extern const AVCodec ff_amr_nb_at_decoder; -extern const AVCodec ff_eac3_at_decoder; -extern const AVCodec ff_gsm_ms_at_decoder; -extern const AVCodec ff_ilbc_at_encoder; -extern const AVCodec ff_ilbc_at_decoder; -extern const AVCodec ff_mp1_at_decoder; -extern const AVCodec ff_mp2_at_decoder; -extern const AVCodec ff_mp3_at_decoder; -extern const AVCodec ff_pcm_alaw_at_encoder; -extern const AVCodec ff_pcm_alaw_at_decoder; -extern const AVCodec ff_pcm_mulaw_at_encoder; -extern const AVCodec ff_pcm_mulaw_at_decoder; -extern const AVCodec ff_qdmc_at_decoder; -extern const AVCodec ff_qdm2_at_decoder; -extern AVCodec ff_libaom_av1_encoder; -extern const AVCodec ff_libaribb24_decoder; -extern const AVCodec ff_libcelt_decoder; -extern const AVCodec ff_libcodec2_encoder; -extern const AVCodec ff_libcodec2_decoder; -extern const AVCodec ff_libdav1d_decoder; -extern const AVCodec ff_libdavs2_decoder; -extern const AVCodec ff_libfdk_aac_encoder; -extern const AVCodec ff_libfdk_aac_decoder; -extern const AVCodec ff_libgsm_encoder; -extern const AVCodec ff_libgsm_decoder; -extern const AVCodec ff_libgsm_ms_encoder; -extern const AVCodec ff_libgsm_ms_decoder; -extern const AVCodec ff_libilbc_encoder; -extern const AVCodec ff_libilbc_decoder; -extern const AVCodec ff_libmp3lame_encoder; -extern const AVCodec ff_libopencore_amrnb_encoder; -extern const AVCodec ff_libopencore_amrnb_decoder; -extern const AVCodec ff_libopencore_amrwb_decoder; -extern const AVCodec ff_libopenjpeg_encoder; -extern const AVCodec ff_libopenjpeg_decoder; -extern const AVCodec ff_libopus_encoder; -extern const AVCodec ff_libopus_decoder; -extern const AVCodec ff_librav1e_encoder; -extern const AVCodec ff_librsvg_decoder; -extern const AVCodec ff_libshine_encoder; -extern const AVCodec ff_libspeex_encoder; -extern const AVCodec ff_libspeex_decoder; -extern const AVCodec ff_libsvtav1_encoder; -extern const AVCodec ff_libtheora_encoder; -extern const AVCodec ff_libtwolame_encoder; -extern const AVCodec ff_libuavs3d_decoder; -extern const AVCodec ff_libvo_amrwbenc_encoder; -extern const AVCodec ff_libvorbis_encoder; -extern const AVCodec ff_libvorbis_decoder; -extern const AVCodec ff_libvpx_vp8_encoder; -extern const AVCodec ff_libvpx_vp8_decoder; -extern AVCodec ff_libvpx_vp9_encoder; -extern AVCodec ff_libvpx_vp9_decoder; +extern const FFCodec ff_aac_at_encoder; +extern const FFCodec ff_aac_at_decoder; +extern const FFCodec ff_ac3_at_decoder; +extern const FFCodec ff_adpcm_ima_qt_at_decoder; +extern const FFCodec ff_alac_at_encoder; +extern const FFCodec ff_alac_at_decoder; +extern const FFCodec ff_amr_nb_at_decoder; +extern const FFCodec ff_eac3_at_decoder; +extern const FFCodec ff_gsm_ms_at_decoder; +extern const FFCodec ff_ilbc_at_encoder; +extern const FFCodec ff_ilbc_at_decoder; +extern const FFCodec ff_mp1_at_decoder; +extern const FFCodec ff_mp2_at_decoder; +extern const FFCodec ff_mp3_at_decoder; +extern const FFCodec ff_pcm_alaw_at_encoder; +extern const FFCodec ff_pcm_alaw_at_decoder; +extern const FFCodec ff_pcm_mulaw_at_encoder; +extern const FFCodec ff_pcm_mulaw_at_decoder; +extern const FFCodec ff_qdmc_at_decoder; +extern const FFCodec ff_qdm2_at_decoder; +extern FFCodec ff_libaom_av1_encoder; +extern const FFCodec ff_libaribb24_decoder; +extern const FFCodec ff_libcelt_decoder; +extern const FFCodec ff_libcodec2_encoder; +extern const FFCodec ff_libcodec2_decoder; +extern const FFCodec ff_libdav1d_decoder; +extern const FFCodec ff_libdavs2_decoder; +extern const FFCodec ff_libfdk_aac_encoder; +extern const FFCodec ff_libfdk_aac_decoder; +extern const FFCodec ff_libgsm_encoder; +extern const FFCodec ff_libgsm_decoder; +extern const FFCodec ff_libgsm_ms_encoder; +extern const FFCodec ff_libgsm_ms_decoder; +extern const FFCodec ff_libilbc_encoder; +extern const FFCodec ff_libilbc_decoder; +extern const FFCodec ff_libjxl_decoder; +extern const FFCodec ff_libjxl_encoder; +extern const FFCodec ff_libmp3lame_encoder; +extern const FFCodec ff_libopencore_amrnb_encoder; +extern const FFCodec ff_libopencore_amrnb_decoder; +extern const FFCodec ff_libopencore_amrwb_decoder; +extern const FFCodec ff_libopenjpeg_encoder; +extern const FFCodec ff_libopenjpeg_decoder; +extern const FFCodec ff_libopus_encoder; +extern const FFCodec ff_libopus_decoder; +extern const FFCodec ff_librav1e_encoder; +extern const FFCodec ff_librsvg_decoder; +extern const FFCodec ff_libshine_encoder; +extern const FFCodec ff_libspeex_encoder; +extern const FFCodec ff_libspeex_decoder; +extern const FFCodec ff_libsvtav1_encoder; +extern const FFCodec ff_libtheora_encoder; +extern const FFCodec ff_libtwolame_encoder; +extern const FFCodec ff_libuavs3d_decoder; +extern const FFCodec ff_libvo_amrwbenc_encoder; +extern const FFCodec ff_libvorbis_encoder; +extern const FFCodec ff_libvorbis_decoder; +extern const FFCodec ff_libvpx_vp8_encoder; +extern const FFCodec ff_libvpx_vp8_decoder; +extern FFCodec ff_libvpx_vp9_encoder; +extern FFCodec ff_libvpx_vp9_decoder; /* preferred over libwebp */ -extern const AVCodec ff_libwebp_anim_encoder; -extern const AVCodec ff_libwebp_encoder; -extern const AVCodec ff_libx262_encoder; +extern const FFCodec ff_libwebp_anim_encoder; +extern const FFCodec ff_libwebp_encoder; +extern const FFCodec ff_libx262_encoder; #if CONFIG_LIBX264_ENCODER #include #if X264_BUILD < 153 @@ -779,80 +792,80 @@ extern const AVCodec ff_libx262_encoder; #else #define LIBX264_CONST const #endif -extern LIBX264_CONST AVCodec ff_libx264_encoder; +extern LIBX264_CONST FFCodec ff_libx264_encoder; #endif -extern const AVCodec ff_libx264rgb_encoder; -extern AVCodec ff_libx265_encoder; -extern const AVCodec ff_libxavs_encoder; -extern const AVCodec ff_libxavs2_encoder; -extern const AVCodec ff_libxvid_encoder; -extern const AVCodec ff_libzvbi_teletext_decoder; +extern const FFCodec ff_libx264rgb_encoder; +extern FFCodec ff_libx265_encoder; +extern const FFCodec ff_libxavs_encoder; +extern const FFCodec ff_libxavs2_encoder; +extern const FFCodec ff_libxvid_encoder; +extern const FFCodec ff_libzvbi_teletext_decoder; /* text */ -extern const AVCodec ff_bintext_decoder; -extern const AVCodec ff_xbin_decoder; -extern const AVCodec ff_idf_decoder; +extern const FFCodec ff_bintext_decoder; +extern const FFCodec ff_xbin_decoder; +extern const FFCodec ff_idf_decoder; /* external libraries, that shouldn't be used by default if one of the * above is available */ -extern const AVCodec ff_aac_mf_encoder; -extern const AVCodec ff_ac3_mf_encoder; -extern const AVCodec ff_h263_v4l2m2m_encoder; -extern const AVCodec ff_libaom_av1_decoder; +extern const FFCodec ff_aac_mf_encoder; +extern const FFCodec ff_ac3_mf_encoder; +extern const FFCodec ff_h263_v4l2m2m_encoder; +extern const FFCodec ff_libaom_av1_decoder; /* hwaccel hooks only, so prefer external decoders */ -extern const AVCodec ff_av1_decoder; -extern const AVCodec ff_av1_cuvid_decoder; -extern const AVCodec ff_av1_qsv_decoder; -extern const AVCodec ff_libopenh264_encoder; -extern const AVCodec ff_libopenh264_decoder; -extern const AVCodec ff_h264_amf_encoder; -extern const AVCodec ff_h264_cuvid_decoder; -extern const AVCodec ff_h264_mf_encoder; -extern const AVCodec ff_h264_nvenc_encoder; -extern const AVCodec ff_h264_omx_encoder; -extern const AVCodec ff_h264_qsv_encoder; -extern const AVCodec ff_h264_v4l2m2m_encoder; -extern const AVCodec ff_h264_vaapi_encoder; -extern const AVCodec ff_h264_videotoolbox_encoder; -extern const AVCodec ff_hevc_amf_encoder; -extern const AVCodec ff_hevc_cuvid_decoder; -extern const AVCodec ff_hevc_mediacodec_decoder; -extern const AVCodec ff_hevc_mf_encoder; -extern const AVCodec ff_hevc_nvenc_encoder; -extern const AVCodec ff_hevc_qsv_encoder; -extern const AVCodec ff_hevc_v4l2m2m_encoder; -extern const AVCodec ff_hevc_vaapi_encoder; -extern const AVCodec ff_hevc_videotoolbox_encoder; -extern const AVCodec ff_libkvazaar_encoder; -extern const AVCodec ff_mjpeg_cuvid_decoder; -extern const AVCodec ff_mjpeg_qsv_encoder; -extern const AVCodec ff_mjpeg_qsv_decoder; -extern const AVCodec ff_mjpeg_vaapi_encoder; -extern const AVCodec ff_mp3_mf_encoder; -extern const AVCodec ff_mpeg1_cuvid_decoder; -extern const AVCodec ff_mpeg2_cuvid_decoder; -extern const AVCodec ff_mpeg2_qsv_encoder; -extern const AVCodec ff_mpeg2_vaapi_encoder; -extern const AVCodec ff_mpeg4_cuvid_decoder; -extern const AVCodec ff_mpeg4_mediacodec_decoder; -extern const AVCodec ff_mpeg4_omx_encoder; -extern const AVCodec ff_mpeg4_v4l2m2m_encoder; -extern const AVCodec ff_prores_videotoolbox_encoder; -extern const AVCodec ff_vc1_cuvid_decoder; -extern const AVCodec ff_vp8_cuvid_decoder; -extern const AVCodec ff_vp8_mediacodec_decoder; -extern const AVCodec ff_vp8_qsv_decoder; -extern const AVCodec ff_vp8_v4l2m2m_encoder; -extern const AVCodec ff_vp8_vaapi_encoder; -extern const AVCodec ff_vp9_cuvid_decoder; -extern const AVCodec ff_vp9_mediacodec_decoder; -extern const AVCodec ff_vp9_qsv_decoder; -extern const AVCodec ff_vp9_vaapi_encoder; -extern const AVCodec ff_vp9_qsv_encoder; +extern const FFCodec ff_av1_decoder; +extern const FFCodec ff_av1_cuvid_decoder; +extern const FFCodec ff_av1_qsv_decoder; +extern const FFCodec ff_libopenh264_encoder; +extern const FFCodec ff_libopenh264_decoder; +extern const FFCodec ff_h264_amf_encoder; +extern const FFCodec ff_h264_cuvid_decoder; +extern const FFCodec ff_h264_mf_encoder; +extern const FFCodec ff_h264_nvenc_encoder; +extern const FFCodec ff_h264_omx_encoder; +extern const FFCodec ff_h264_qsv_encoder; +extern const FFCodec ff_h264_v4l2m2m_encoder; +extern const FFCodec ff_h264_vaapi_encoder; +extern const FFCodec ff_h264_videotoolbox_encoder; +extern const FFCodec ff_hevc_amf_encoder; +extern const FFCodec ff_hevc_cuvid_decoder; +extern const FFCodec ff_hevc_mediacodec_decoder; +extern const FFCodec ff_hevc_mf_encoder; +extern const FFCodec ff_hevc_nvenc_encoder; +extern const FFCodec ff_hevc_qsv_encoder; +extern const FFCodec ff_hevc_v4l2m2m_encoder; +extern const FFCodec ff_hevc_vaapi_encoder; +extern const FFCodec ff_hevc_videotoolbox_encoder; +extern const FFCodec ff_libkvazaar_encoder; +extern const FFCodec ff_mjpeg_cuvid_decoder; +extern const FFCodec ff_mjpeg_qsv_encoder; +extern const FFCodec ff_mjpeg_qsv_decoder; +extern const FFCodec ff_mjpeg_vaapi_encoder; +extern const FFCodec ff_mp3_mf_encoder; +extern const FFCodec ff_mpeg1_cuvid_decoder; +extern const FFCodec ff_mpeg2_cuvid_decoder; +extern const FFCodec ff_mpeg2_qsv_encoder; +extern const FFCodec ff_mpeg2_vaapi_encoder; +extern const FFCodec ff_mpeg4_cuvid_decoder; +extern const FFCodec ff_mpeg4_mediacodec_decoder; +extern const FFCodec ff_mpeg4_omx_encoder; +extern const FFCodec ff_mpeg4_v4l2m2m_encoder; +extern const FFCodec ff_prores_videotoolbox_encoder; +extern const FFCodec ff_vc1_cuvid_decoder; +extern const FFCodec ff_vp8_cuvid_decoder; +extern const FFCodec ff_vp8_mediacodec_decoder; +extern const FFCodec ff_vp8_qsv_decoder; +extern const FFCodec ff_vp8_v4l2m2m_encoder; +extern const FFCodec ff_vp8_vaapi_encoder; +extern const FFCodec ff_vp9_cuvid_decoder; +extern const FFCodec ff_vp9_mediacodec_decoder; +extern const FFCodec ff_vp9_qsv_decoder; +extern const FFCodec ff_vp9_vaapi_encoder; +extern const FFCodec ff_vp9_qsv_encoder; // The iterate API is not usable with ossfuzz due to the excessive size of binaries created #if CONFIG_OSSFUZZ -const AVCodec * codec_list[] = { +const FFCodec * codec_list[] = { NULL, NULL, NULL @@ -866,21 +879,22 @@ 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]); + codec_list[i]->init_static_data((FFCodec*)codec_list[i]); } } const AVCodec *av_codec_iterate(void **opaque) { uintptr_t i = (uintptr_t)*opaque; - const AVCodec *c = codec_list[i]; + const FFCodec *c = codec_list[i]; ff_thread_once(&av_codec_static_init, av_codec_init_static); - if (c) + if (c) { *opaque = (void*)(i + 1); - - return c; + return &c->p; + } + return NULL; } static enum AVCodecID remap_deprecated_codec_id(enum AVCodecID id) diff --git a/libavcodec/alsdec.c b/libavcodec/alsdec.c index 9e1aaf065..7031fa0ac 100644 --- a/libavcodec/alsdec.c +++ b/libavcodec/alsdec.c @@ -33,6 +33,7 @@ #include "mpeg4audio.h" #include "bgmc.h" #include "bswapdsp.h" +#include "codec_internal.h" #include "internal.h" #include "mlz.h" #include "libavutil/samplefmt.h" @@ -319,7 +320,13 @@ static av_cold int read_specific_config(ALSDecContext *ctx) avctx->sample_rate = m4ac.sample_rate; skip_bits_long(&gb, 32); // sample rate already known sconf->samples = get_bits_long(&gb, 32); - avctx->channels = m4ac.channels; + + if (avctx->ch_layout.nb_channels != m4ac.channels) { + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + avctx->ch_layout.nb_channels = m4ac.channels; + } + skip_bits(&gb, 16); // number of channels already known skip_bits(&gb, 3); // skip file_type sconf->resolution = get_bits(&gb, 3); @@ -349,11 +356,14 @@ static av_cold int read_specific_config(ALSDecContext *ctx) if (als_id != MKBETAG('A','L','S','\0')) return AVERROR_INVALIDDATA; - if (avctx->channels > FF_SANE_NB_CHANNELS) { + if (avctx->ch_layout.nb_channels > FF_SANE_NB_CHANNELS) { avpriv_request_sample(avctx, "Huge number of channels"); return AVERROR_PATCHWELCOME; } + if (avctx->ch_layout.nb_channels == 0) + return AVERROR_INVALIDDATA; + ctx->cur_frame_length = sconf->frame_length; // read channel config @@ -363,26 +373,26 @@ static av_cold int read_specific_config(ALSDecContext *ctx) // read channel sorting - if (sconf->chan_sort && avctx->channels > 1) { - int chan_pos_bits = av_ceil_log2(avctx->channels); - int bits_needed = avctx->channels * chan_pos_bits + 7; + if (sconf->chan_sort && avctx->ch_layout.nb_channels > 1) { + int chan_pos_bits = av_ceil_log2(avctx->ch_layout.nb_channels); + int bits_needed = avctx->ch_layout.nb_channels * chan_pos_bits + 7; if (get_bits_left(&gb) < bits_needed) return AVERROR_INVALIDDATA; - if (!(sconf->chan_pos = av_malloc_array(avctx->channels, sizeof(*sconf->chan_pos)))) + if (!(sconf->chan_pos = av_malloc_array(avctx->ch_layout.nb_channels, sizeof(*sconf->chan_pos)))) return AVERROR(ENOMEM); ctx->cs_switch = 1; - for (i = 0; i < avctx->channels; i++) { + for (i = 0; i < avctx->ch_layout.nb_channels; i++) { sconf->chan_pos[i] = -1; } - for (i = 0; i < avctx->channels; i++) { + for (i = 0; i < avctx->ch_layout.nb_channels; i++) { int idx; idx = get_bits(&gb, chan_pos_bits); - if (idx >= avctx->channels || sconf->chan_pos[idx] != -1) { + if (idx >= avctx->ch_layout.nb_channels || sconf->chan_pos[idx] != -1) { av_log(avctx, AV_LOG_WARNING, "Invalid channel reordering.\n"); ctx->cs_switch = 0; break; @@ -1228,7 +1238,7 @@ static int read_channel_data(ALSDecContext *ctx, ALSChannelData *cd, int c) { GetBitContext *gb = &ctx->gb; ALSChannelData *current = cd; - unsigned int channels = ctx->avctx->channels; + unsigned int channels = ctx->avctx->ch_layout.nb_channels; int entries = 0; while (entries < channels && !(current->stop_flag = get_bits1(gb))) { @@ -1277,7 +1287,7 @@ static int revert_channel_correlation(ALSDecContext *ctx, ALSBlockData *bd, { ALSChannelData *ch = cd[c]; unsigned int dep = 0; - unsigned int channels = ctx->avctx->channels; + unsigned int channels = ctx->avctx->ch_layout.nb_channels; unsigned int channel_size = ctx->sconf.frame_length + ctx->sconf.max_order; if (reverted[c]) @@ -1475,15 +1485,15 @@ static int read_diff_float_data(ALSDecContext *ctx, unsigned int ra_frame) { use_acf = get_bits1(gb); if (ra_frame) { - memset(last_acf_mantissa, 0, avctx->channels * sizeof(*last_acf_mantissa)); - memset(last_shift_value, 0, avctx->channels * sizeof(*last_shift_value) ); + memset(last_acf_mantissa, 0, avctx->ch_layout.nb_channels * sizeof(*last_acf_mantissa)); + memset(last_shift_value, 0, avctx->ch_layout.nb_channels * sizeof(*last_shift_value) ); ff_mlz_flush_dict(ctx->mlz); } - if (avctx->channels * 8 > get_bits_left(gb)) + if (avctx->ch_layout.nb_channels * 8 > get_bits_left(gb)) return AVERROR_INVALIDDATA; - for (c = 0; c < avctx->channels; ++c) { + for (c = 0; c < avctx->ch_layout.nb_channels; ++c) { if (use_acf) { //acf_flag if (get_bits1(gb)) { @@ -1634,6 +1644,7 @@ static int read_frame_data(ALSDecContext *ctx, unsigned int ra_frame) unsigned int div_blocks[32]; ///< block sizes. int c; unsigned int js_blocks[2]; + int channels = avctx->ch_layout.nb_channels; uint32_t bs_info = 0; int ret; @@ -1649,7 +1660,7 @@ static int read_frame_data(ALSDecContext *ctx, unsigned int ra_frame) if (!sconf->mc_coding || ctx->js_switch) { int independent_bs = !sconf->joint_stereo; - for (c = 0; c < avctx->channels; c++) { + for (c = 0; c < channels; c++) { js_blocks[0] = 0; js_blocks[1] = 0; @@ -1662,7 +1673,7 @@ static int read_frame_data(ALSDecContext *ctx, unsigned int ra_frame) independent_bs = 2; // if this is the last channel, it has to be decoded independently - if (c == avctx->channels - 1 || (c & 1)) + if (c == channels - 1 || (c & 1)) independent_bs = 1; if (independent_bs) { @@ -1691,13 +1702,13 @@ static int read_frame_data(ALSDecContext *ctx, unsigned int ra_frame) int *reverted_channels = ctx->reverted_channels; unsigned int offset = 0; - for (c = 0; c < avctx->channels; c++) + for (c = 0; c < channels; c++) if (ctx->chan_data[c] < ctx->chan_data_buffer) { av_log(ctx->avctx, AV_LOG_ERROR, "Invalid channel data.\n"); return AVERROR_INVALIDDATA; } - memset(reverted_channels, 0, sizeof(*reverted_channels) * avctx->channels); + memset(reverted_channels, 0, sizeof(*reverted_channels) * channels); bd.ra_block = ra_frame; bd.prev_raw_samples = ctx->prev_raw_samples; @@ -1713,7 +1724,7 @@ static int read_frame_data(ALSDecContext *ctx, unsigned int ra_frame) continue; } - for (c = 0; c < avctx->channels; c++) { + for (c = 0; c < channels; c++) { bd.const_block = ctx->const_block + c; bd.shift_lsbs = ctx->shift_lsbs + c; bd.opt_order = ctx->opt_order + c; @@ -1732,13 +1743,13 @@ static int read_frame_data(ALSDecContext *ctx, unsigned int ra_frame) return ret; } - for (c = 0; c < avctx->channels; c++) { + for (c = 0; c < channels; c++) { ret = revert_channel_correlation(ctx, &bd, ctx->chan_data, reverted_channels, offset, c); if (ret < 0) return ret; } - for (c = 0; c < avctx->channels; c++) { + for (c = 0; c < channels; c++) { bd.const_block = ctx->const_block + c; bd.shift_lsbs = ctx->shift_lsbs + c; bd.opt_order = ctx->opt_order + c; @@ -1756,13 +1767,13 @@ static int read_frame_data(ALSDecContext *ctx, unsigned int ra_frame) ctx->highest_decoded_channel = FFMAX(ctx->highest_decoded_channel, c); } - memset(reverted_channels, 0, avctx->channels * sizeof(*reverted_channels)); + memset(reverted_channels, 0, channels * sizeof(*reverted_channels)); offset += div_blocks[b]; bd.ra_block = 0; } // store carryover raw samples - for (c = 0; c < avctx->channels; c++) + for (c = 0; c < channels; c++) memmove(ctx->raw_samples[c] - sconf->max_order, ctx->raw_samples[c] - sconf->max_order + sconf->frame_length, sizeof(*ctx->raw_samples[c]) * sconf->max_order); @@ -1783,15 +1794,15 @@ static int read_frame_data(ALSDecContext *ctx, unsigned int ra_frame) /** Decode an ALS frame. */ -static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame_ptr, AVPacket *avpkt) { ALSDecContext *ctx = avctx->priv_data; - AVFrame *frame = data; ALSSpecificConfig *sconf = &ctx->sconf; const uint8_t *buffer = avpkt->data; int buffer_size = avpkt->size; int invalid_frame, ret; + int channels = avctx->ch_layout.nb_channels; unsigned int c, sample, ra_frame, bytes_read, shift; if ((ret = init_get_bits8(&ctx->gb, buffer, buffer_size)) < 0) @@ -1833,7 +1844,6 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, #define INTERLEAVE_OUTPUT(bps) \ { \ int##bps##_t *dest = (int##bps##_t*)frame->data[0]; \ - int channels = avctx->channels; \ int32_t *raw_samples = ctx->raw_samples[0]; \ int raw_step = channels > 1 ? ctx->raw_samples[1] - raw_samples : 1; \ shift = bps - ctx->avctx->bits_per_raw_sample; \ @@ -1862,7 +1872,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, int32_t *src = (int32_t *)frame->data[0]; for (sample = 0; - sample < ctx->cur_frame_length * avctx->channels; + sample < ctx->cur_frame_length * channels; sample++) { int32_t v; @@ -1883,13 +1893,13 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, int16_t *src = (int16_t*) frame->data[0]; int16_t *dest = (int16_t*) ctx->crc_buffer; for (sample = 0; - sample < ctx->cur_frame_length * avctx->channels; + sample < ctx->cur_frame_length * channels; sample++) *dest++ = av_bswap16(src[sample]); } else { ctx->bdsp.bswap_buf((uint32_t *) ctx->crc_buffer, (uint32_t *) frame->data[0], - ctx->cur_frame_length * avctx->channels); + ctx->cur_frame_length * channels); } crc_source = ctx->crc_buffer; } else { @@ -1897,7 +1907,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, } ctx->crc = av_crc(ctx->crc_table, ctx->crc, crc_source, - ctx->cur_frame_length * avctx->channels * + ctx->cur_frame_length * channels * av_get_bytes_per_sample(avctx->sample_fmt)); } @@ -1960,7 +1970,7 @@ static av_cold int decode_end(AVCodecContext *avctx) av_freep(&ctx->shift_value); av_freep(&ctx->last_shift_value); if (ctx->raw_mantissa) { - for (i = 0; i < avctx->channels; i++) { + for (i = 0; i < avctx->ch_layout.nb_channels; i++) { av_freep(&ctx->raw_mantissa[i]); } av_freep(&ctx->raw_mantissa); @@ -1979,6 +1989,7 @@ static av_cold int decode_init(AVCodecContext *avctx) unsigned int c; unsigned int channel_size; int num_buffers, ret; + int channels; ALSDecContext *ctx = avctx->priv_data; ALSSpecificConfig *sconf = &ctx->sconf; ctx->avctx = avctx; @@ -1990,17 +2001,18 @@ static av_cold int decode_init(AVCodecContext *avctx) if ((ret = read_specific_config(ctx)) < 0) { av_log(avctx, AV_LOG_ERROR, "Reading ALSSpecificConfig failed.\n"); - goto fail; + return ret; } + channels = avctx->ch_layout.nb_channels; if ((ret = check_specific_config(ctx)) < 0) { - goto fail; + return ret; } if (sconf->bgmc) { ret = ff_bgmc_init(avctx, &ctx->bgmc_lut, &ctx->bgmc_lut_status); if (ret < 0) - goto fail; + return ret; } if (sconf->floating) { avctx->sample_fmt = AV_SAMPLE_FMT_FLT; @@ -2012,8 +2024,7 @@ static av_cold int decode_init(AVCodecContext *avctx) if (avctx->bits_per_raw_sample > 32) { av_log(avctx, AV_LOG_ERROR, "Bits per raw sample %d larger than 32.\n", avctx->bits_per_raw_sample); - ret = AVERROR_INVALIDDATA; - goto fail; + return AVERROR_INVALIDDATA; } } @@ -2027,7 +2038,7 @@ static av_cold int decode_init(AVCodecContext *avctx) (avctx->sample_rate >= 192000); // allocate quantized parcor coefficient buffer - num_buffers = sconf->mc_coding ? avctx->channels : 1; + num_buffers = sconf->mc_coding ? channels : 1; if (num_buffers * (uint64_t)num_buffers > INT_MAX) // protect chan_data_buffer allocation return AVERROR_INVALIDDATA; @@ -2044,8 +2055,7 @@ static av_cold int decode_init(AVCodecContext *avctx) !ctx->quant_cof_buffer || !ctx->lpc_cof_buffer || !ctx->lpc_cof_reversed_buffer) { av_log(avctx, AV_LOG_ERROR, "Allocating buffer memory failed.\n"); - ret = AVERROR(ENOMEM); - goto fail; + return AVERROR(ENOMEM); } // assign quantized parcor coefficient buffers @@ -2069,8 +2079,7 @@ static av_cold int decode_init(AVCodecContext *avctx) !ctx->use_ltp || !ctx->ltp_lag || !ctx->ltp_gain || !ctx->ltp_gain_buffer) { av_log(avctx, AV_LOG_ERROR, "Allocating buffer memory failed.\n"); - ret = AVERROR(ENOMEM); - goto fail; + return AVERROR(ENOMEM); } for (c = 0; c < num_buffers; c++) @@ -2086,8 +2095,7 @@ static av_cold int decode_init(AVCodecContext *avctx) if (!ctx->chan_data_buffer || !ctx->chan_data || !ctx->reverted_channels) { av_log(avctx, AV_LOG_ERROR, "Allocating buffer memory failed.\n"); - ret = AVERROR(ENOMEM); - goto fail; + return AVERROR(ENOMEM); } for (c = 0; c < num_buffers; c++) @@ -2098,18 +2106,12 @@ static av_cold int decode_init(AVCodecContext *avctx) ctx->reverted_channels = NULL; } - channel_size = sconf->frame_length + sconf->max_order; - - ctx->prev_raw_samples = av_malloc_array(sconf->max_order, sizeof(*ctx->prev_raw_samples)); - ctx->raw_buffer = av_calloc(avctx->channels * channel_size, sizeof(*ctx->raw_buffer)); - ctx->raw_samples = av_malloc_array(avctx->channels, sizeof(*ctx->raw_samples)); - if (sconf->floating) { - ctx->acf = av_malloc_array(avctx->channels, sizeof(*ctx->acf)); - ctx->shift_value = av_malloc_array(avctx->channels, sizeof(*ctx->shift_value)); - ctx->last_shift_value = av_malloc_array(avctx->channels, sizeof(*ctx->last_shift_value)); - ctx->last_acf_mantissa = av_malloc_array(avctx->channels, sizeof(*ctx->last_acf_mantissa)); - ctx->raw_mantissa = av_calloc(avctx->channels, sizeof(*ctx->raw_mantissa)); + ctx->acf = av_malloc_array(channels, sizeof(*ctx->acf)); + ctx->shift_value = av_malloc_array(channels, sizeof(*ctx->shift_value)); + ctx->last_shift_value = av_malloc_array(channels, sizeof(*ctx->last_shift_value)); + ctx->last_acf_mantissa = av_malloc_array(channels, sizeof(*ctx->last_acf_mantissa)); + ctx->raw_mantissa = av_calloc(channels, sizeof(*ctx->raw_mantissa)); ctx->larray = av_malloc_array(ctx->cur_frame_length * 4, sizeof(*ctx->larray)); ctx->nbits = av_malloc_array(ctx->cur_frame_length, sizeof(*ctx->nbits)); @@ -2118,50 +2120,51 @@ static av_cold int decode_init(AVCodecContext *avctx) if (!ctx->mlz || !ctx->acf || !ctx->shift_value || !ctx->last_shift_value || !ctx->last_acf_mantissa || !ctx->raw_mantissa) { av_log(avctx, AV_LOG_ERROR, "Allocating buffer memory failed.\n"); - ret = AVERROR(ENOMEM); - goto fail; + return AVERROR(ENOMEM); } - ff_mlz_init_dict(avctx, ctx->mlz); + ret = ff_mlz_init_dict(avctx, ctx->mlz); + if (ret < 0) + return ret; ff_mlz_flush_dict(ctx->mlz); - for (c = 0; c < avctx->channels; ++c) { + for (c = 0; c < channels; ++c) { ctx->raw_mantissa[c] = av_calloc(ctx->cur_frame_length, sizeof(**ctx->raw_mantissa)); } } + channel_size = sconf->frame_length + sconf->max_order; + // allocate previous raw sample buffer + ctx->prev_raw_samples = av_malloc_array(sconf->max_order, sizeof(*ctx->prev_raw_samples)); + ctx->raw_buffer = av_calloc(channels * channel_size, sizeof(*ctx->raw_buffer)); + ctx->raw_samples = av_malloc_array(channels, sizeof(*ctx->raw_samples)); if (!ctx->prev_raw_samples || !ctx->raw_buffer|| !ctx->raw_samples) { av_log(avctx, AV_LOG_ERROR, "Allocating buffer memory failed.\n"); - ret = AVERROR(ENOMEM); - goto fail; + return AVERROR(ENOMEM); } // assign raw samples buffers ctx->raw_samples[0] = ctx->raw_buffer + sconf->max_order; - for (c = 1; c < avctx->channels; c++) + for (c = 1; c < channels; c++) ctx->raw_samples[c] = ctx->raw_samples[c - 1] + channel_size; // allocate crc buffer if (HAVE_BIGENDIAN != sconf->msb_first && sconf->crc_enabled && (avctx->err_recognition & (AV_EF_CRCCHECK|AV_EF_CAREFUL))) { ctx->crc_buffer = av_malloc_array(ctx->cur_frame_length * - avctx->channels * + channels * av_get_bytes_per_sample(avctx->sample_fmt), sizeof(*ctx->crc_buffer)); if (!ctx->crc_buffer) { av_log(avctx, AV_LOG_ERROR, "Allocating buffer memory failed.\n"); - ret = AVERROR(ENOMEM); - goto fail; + return AVERROR(ENOMEM); } } ff_bswapdsp_init(&ctx->bdsp); return 0; - -fail: - return ret; } @@ -2175,16 +2178,16 @@ static av_cold void flush(AVCodecContext *avctx) } -const AVCodec ff_als_decoder = { - .name = "als", - .long_name = NULL_IF_CONFIG_SMALL("MPEG-4 Audio Lossless Coding (ALS)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_MP4ALS, +const FFCodec ff_als_decoder = { + .p.name = "als", + .p.long_name = NULL_IF_CONFIG_SMALL("MPEG-4 Audio Lossless Coding (ALS)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_MP4ALS, .priv_data_size = sizeof(ALSDecContext), .init = decode_init, .close = decode_end, - .decode = decode_frame, + FF_CODEC_DECODE_CB(decode_frame), .flush = flush, - .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, - .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, + .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/amfenc.c b/libavcodec/amfenc.c index fb23ed738..a033e1220 100644 --- a/libavcodec/amfenc.c +++ b/libavcodec/amfenc.c @@ -17,6 +17,7 @@ */ #include "config.h" +#include "config_components.h" #include "libavutil/avassert.h" #include "libavutil/imgutils.h" @@ -117,8 +118,9 @@ static int amf_load_library(AVCodecContext *avctx) 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)); + // hardcoded to current HW queue size - will auto-realloc if too small + ctx->timestamp_list = av_fifo_alloc2(avctx->max_b_frames + 16, sizeof(int64_t), + AV_FIFO_FLAG_AUTO_GROW); if (!ctx->timestamp_list) { return AVERROR(ENOMEM); } @@ -403,7 +405,7 @@ int av_cold ff_amf_encode_close(AVCodecContext *avctx) ctx->version = 0; ctx->delayed_drain = 0; av_frame_free(&ctx->delayed_frame); - av_fifo_freep(&ctx->timestamp_list); + av_fifo_freep2(&ctx->timestamp_list); return 0; } @@ -432,18 +434,6 @@ static int amf_copy_surface(AVCodecContext *avctx, const AVFrame *frame, return 0; } -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; @@ -479,21 +469,17 @@ static int amf_copy_buffer(AVCodecContext *avctx, AVPacket *pkt, AMFBuffer *buff 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); + AMF_RETURN_IF_FALSE(ctx, av_fifo_read(ctx->timestamp_list, ×tamp, 1) >= 0, + AVERROR_UNKNOWN, "timestamp_list is empty\n"); // 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, + size_t can_read = av_fifo_can_read(ctx->timestamp_list); + + AMF_RETURN_IF_FALSE(ctx, can_read > 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); + av_fifo_peek(ctx->timestamp_list, ×tamp_last, 1, can_read - 1); if (timestamp < 0 || timestamp_last < AV_NOPTS_VALUE) { return AVERROR(ERANGE); } @@ -710,9 +696,9 @@ int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "SubmitInput() failed with error %d\n", res); av_frame_unref(frame); - if ((ret = timestamp_queue_enqueue(avctx, pts)) < 0) { + ret = av_fifo_write(ctx->timestamp_list, &pts, 1); + if (ret < 0) return ret; - } } } @@ -751,9 +737,9 @@ int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt) 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) { + ret = av_fifo_write(ctx->timestamp_list, &pts, 1); + if (ret < 0) return ret; - } } else { av_log(avctx, AV_LOG_WARNING, "Data acquired but delayed frame submission got AMF_INPUT_FULL- should not happen\n"); } diff --git a/libavcodec/amfenc.h b/libavcodec/amfenc.h index 358b2ef77..1ab98d2f7 100644 --- a/libavcodec/amfenc.h +++ b/libavcodec/amfenc.h @@ -72,7 +72,7 @@ typedef struct AmfContext { AVFrame *delayed_frame; // shift dts back by max_b_frames in timing - AVFifoBuffer *timestamp_list; + AVFifo *timestamp_list; int64_t dts_delay; // common encoder option options diff --git a/libavcodec/amfenc_h264.c b/libavcodec/amfenc_h264.c index aeca99f7c..efb04589f 100644 --- a/libavcodec/amfenc_h264.c +++ b/libavcodec/amfenc_h264.c @@ -20,6 +20,7 @@ #include "libavutil/internal.h" #include "libavutil/opt.h" #include "amfenc.h" +#include "codec_internal.h" #include "internal.h" #define OFFSET(x) offsetof(AmfContext, x) @@ -358,7 +359,7 @@ static av_cold int amf_encode_init_h264(AVCodecContext *avctx) return 0; } -static const AVCodecDefault defaults[] = { +static const FFCodecDefault defaults[] = { { "refs", "-1" }, { "aspect", "0" }, { "qmin", "-1" }, @@ -377,21 +378,21 @@ static const AVClass h264_amf_class = { .version = LIBAVUTIL_VERSION_INT, }; -const 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, +const FFCodec ff_h264_amf_encoder = { + .p.name = "h264_amf", + .p.long_name = NULL_IF_CONFIG_SMALL("AMD AMF H.264 Encoder"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_H264, .init = amf_encode_init_h264, - .receive_packet = ff_amf_receive_packet, + FF_CODEC_RECEIVE_PACKET_CB(ff_amf_receive_packet), .close = ff_amf_encode_close, .priv_data_size = sizeof(AmfContext), - .priv_class = &h264_amf_class, + .p.priv_class = &h264_amf_class, .defaults = defaults, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, - .pix_fmts = ff_amf_pix_fmts, - .wrapper_name = "amf", + .p.pix_fmts = ff_amf_pix_fmts, + .p.wrapper_name = "amf", .hw_configs = ff_amfenc_hw_configs, }; diff --git a/libavcodec/amfenc_hevc.c b/libavcodec/amfenc_hevc.c index 79541b9b2..8ab933073 100644 --- a/libavcodec/amfenc_hevc.c +++ b/libavcodec/amfenc_hevc.c @@ -19,6 +19,7 @@ #include "libavutil/internal.h" #include "libavutil/opt.h" #include "amfenc.h" +#include "codec_internal.h" #include "internal.h" #define OFFSET(x) offsetof(AmfContext, x) @@ -292,7 +293,7 @@ static av_cold int amf_encode_init_hevc(AVCodecContext *avctx) return 0; } -static const AVCodecDefault defaults[] = { +static const FFCodecDefault defaults[] = { { "refs", "-1" }, { "aspect", "0" }, { "b", "2M" }, @@ -309,21 +310,21 @@ static const AVClass hevc_amf_class = { .version = LIBAVUTIL_VERSION_INT, }; -const 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, +const FFCodec ff_hevc_amf_encoder = { + .p.name = "hevc_amf", + .p.long_name = NULL_IF_CONFIG_SMALL("AMD AMF HEVC encoder"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_HEVC, .init = amf_encode_init_hevc, - .receive_packet = ff_amf_receive_packet, + FF_CODEC_RECEIVE_PACKET_CB(ff_amf_receive_packet), .close = ff_amf_encode_close, .priv_data_size = sizeof(AmfContext), - .priv_class = &hevc_amf_class, + .p.priv_class = &hevc_amf_class, .defaults = defaults, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, - .pix_fmts = ff_amf_pix_fmts, - .wrapper_name = "amf", + .p.pix_fmts = ff_amf_pix_fmts, + .p.wrapper_name = "amf", .hw_configs = ff_amfenc_hw_configs, }; diff --git a/libavcodec/amr_parser.c b/libavcodec/amr_parser.c index c0b14700e..9484d720e 100644 --- a/libavcodec/amr_parser.c +++ b/libavcodec/amr_parser.c @@ -63,9 +63,9 @@ static int amr_parse(AVCodecParserContext *s1, *poutbuf_size = 0; *poutbuf = NULL; - if (!avctx->channels) { - avctx->channels = 1; - avctx->channel_layout = AV_CH_LAYOUT_MONO; + if (!avctx->ch_layout.nb_channels) { + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; } if (s1->flags & PARSER_FLAG_COMPLETE_FRAMES) { @@ -73,7 +73,7 @@ static int amr_parse(AVCodecParserContext *s1, } else { int ch, offset = 0; - for (ch = s->current_channel; ch < avctx->channels; ch++) { + for (ch = s->current_channel; ch < avctx->ch_layout.nb_channels; ch++) { if (s->remaining >= 0) { next = s->remaining; } else { @@ -96,7 +96,7 @@ static int amr_parse(AVCodecParserContext *s1, } } - s->current_channel = ch % avctx->channels; + s->current_channel = ch % avctx->ch_layout.nb_channels; if (s->remaining < 0) next = offset; diff --git a/libavcodec/amrnbdec.c b/libavcodec/amrnbdec.c index d8e0370a3..f67ed1d02 100644 --- a/libavcodec/amrnbdec.c +++ b/libavcodec/amrnbdec.c @@ -55,6 +55,7 @@ #include "acelp_pitch_delay.h" #include "lsp.h" #include "amr.h" +#include "codec_internal.h" #include "internal.h" #include "amrnbdata.h" @@ -166,20 +167,20 @@ static av_cold int amrnb_decode_init(AVCodecContext *avctx) AMRChannelsContext *s = avctx->priv_data; int i; - if (avctx->channels > 2) { + if (avctx->ch_layout.nb_channels > 2) { avpriv_report_missing_feature(avctx, ">2 channel AMR"); return AVERROR_PATCHWELCOME; } - if (!avctx->channels) { - avctx->channels = 1; - avctx->channel_layout = AV_CH_LAYOUT_MONO; + if (!avctx->ch_layout.nb_channels) { + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; } if (!avctx->sample_rate) avctx->sample_rate = 8000; avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; - for (int ch = 0; ch < avctx->channels; ch++) { + for (int ch = 0; ch < avctx->ch_layout.nb_channels; ch++) { AMRContext *p = &s->ch[ch]; // p->excitation always points to the same position in p->excitation_buf p->excitation = &p->excitation_buf[PITCH_DELAY_MAX + LP_FILTER_ORDER + 1]; @@ -954,12 +955,11 @@ static void postfilter(AMRContext *p, float *lpc, float *buf_out) /// @} -static int amrnb_decode_frame(AVCodecContext *avctx, void *data, +static int amrnb_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { AMRChannelsContext *s = avctx->priv_data; // pointer to private data - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; int ret; @@ -969,7 +969,7 @@ static int amrnb_decode_frame(AVCodecContext *avctx, void *data, if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; - for (int ch = 0; ch < avctx->channels; ch++) { + for (int ch = 0; ch < avctx->ch_layout.nb_channels; ch++) { AMRContext *p = &s->ch[ch]; float fixed_gain_factor; AMRFixed fixed_sparse = {0}; // fixed vector up to anti-sparseness processing @@ -1096,15 +1096,16 @@ static int amrnb_decode_frame(AVCodecContext *avctx, void *data, } -const AVCodec ff_amrnb_decoder = { - .name = "amrnb", - .long_name = NULL_IF_CONFIG_SMALL("AMR-NB (Adaptive Multi-Rate NarrowBand)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_AMR_NB, +const FFCodec ff_amrnb_decoder = { + .p.name = "amrnb", + .p.long_name = NULL_IF_CONFIG_SMALL("AMR-NB (Adaptive Multi-Rate NarrowBand)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_AMR_NB, .priv_data_size = sizeof(AMRChannelsContext), .init = amrnb_decode_init, - .decode = amrnb_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP, + FF_CODEC_DECODE_CB(amrnb_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/amrwbdec.c b/libavcodec/amrwbdec.c index 3ff4077f7..7566f250d 100644 --- a/libavcodec/amrwbdec.c +++ b/libavcodec/amrwbdec.c @@ -36,6 +36,7 @@ #include "acelp_filters.h" #include "acelp_vectors.h" #include "acelp_pitch_delay.h" +#include "codec_internal.h" #include "internal.h" #define AMR_USE_16BIT_TABLES @@ -102,20 +103,20 @@ static av_cold int amrwb_decode_init(AVCodecContext *avctx) AMRWBChannelsContext *s = avctx->priv_data; int i; - if (avctx->channels > 2) { + if (avctx->ch_layout.nb_channels > 2) { avpriv_report_missing_feature(avctx, ">2 channel AMR"); return AVERROR_PATCHWELCOME; } - if (!avctx->channels) { - avctx->channels = 1; - avctx->channel_layout = AV_CH_LAYOUT_MONO; + if (!avctx->ch_layout.nb_channels) { + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; } if (!avctx->sample_rate) avctx->sample_rate = 16000; avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; - for (int ch = 0; ch < avctx->channels; ch++) { + for (int ch = 0; ch < avctx->ch_layout.nb_channels; ch++) { AMRWBContext *ctx = &s->ch[ch]; av_lfg_init(&ctx->prng, 1); @@ -1101,11 +1102,10 @@ static void update_sub_state(AMRWBContext *ctx) LP_ORDER_16k * sizeof(float)); } -static int amrwb_decode_frame(AVCodecContext *avctx, void *data, +static int amrwb_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { AMRWBChannelsContext *s = avctx->priv_data; - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; int sub, i, ret; @@ -1115,7 +1115,7 @@ static int amrwb_decode_frame(AVCodecContext *avctx, void *data, if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; - for (int ch = 0; ch < avctx->channels; ch++) { + for (int ch = 0; ch < avctx->ch_layout.nb_channels; ch++) { AMRWBContext *ctx = &s->ch[ch]; AMRWBFrame *cf = &ctx->frame; int expected_fr_size, header_size; @@ -1292,15 +1292,16 @@ static int amrwb_decode_frame(AVCodecContext *avctx, void *data, return avpkt->size; } -const AVCodec ff_amrwb_decoder = { - .name = "amrwb", - .long_name = NULL_IF_CONFIG_SMALL("AMR-WB (Adaptive Multi-Rate WideBand)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_AMR_WB, +const FFCodec ff_amrwb_decoder = { + .p.name = "amrwb", + .p.long_name = NULL_IF_CONFIG_SMALL("AMR-WB (Adaptive Multi-Rate WideBand)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_AMR_WB, .priv_data_size = sizeof(AMRWBChannelsContext), .init = amrwb_decode_init, - .decode = amrwb_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLT, + FF_CODEC_DECODE_CB(amrwb_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/anm.c b/libavcodec/anm.c index 494903235..a9006be9c 100644 --- a/libavcodec/anm.c +++ b/libavcodec/anm.c @@ -26,6 +26,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" typedef struct AnmContext { @@ -107,9 +108,8 @@ exhausted: return 1; } -static int decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *avpkt) { AnmContext *s = avctx->priv_data; const int buf_size = avpkt->size; @@ -175,7 +175,7 @@ static int decode_frame(AVCodecContext *avctx, memcpy(s->frame->data[1], s->palette, AVPALETTE_SIZE); *got_frame = 1; - if ((ret = av_frame_ref(data, s->frame)) < 0) + if ((ret = av_frame_ref(rframe, s->frame)) < 0) return ret; return buf_size; @@ -189,15 +189,15 @@ static av_cold int decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_anm_decoder = { - .name = "anm", - .long_name = NULL_IF_CONFIG_SMALL("Deluxe Paint Animation"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_ANM, +const FFCodec ff_anm_decoder = { + .p.name = "anm", + .p.long_name = NULL_IF_CONFIG_SMALL("Deluxe Paint Animation"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_ANM, .priv_data_size = sizeof(AnmContext), .init = decode_init, .close = decode_end, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/ansi.c b/libavcodec/ansi.c index 0965f8cd5..ff4437cc6 100644 --- a/libavcodec/ansi.c +++ b/libavcodec/ansi.c @@ -30,6 +30,7 @@ #include "libavutil/xga_font_data.h" #include "avcodec.h" #include "cga_data.h" +#include "codec_internal.h" #include "internal.h" #define ATTR_BOLD 0x01 /**< Bold/Bright-foreground (mode 1) */ @@ -353,12 +354,11 @@ static int execute_code(AVCodecContext * avctx, int c) return 0; } -static int decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *avpkt) { AnsiContext *s = avctx->priv_data; - uint8_t *buf = avpkt->data; + const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; const uint8_t *buf_end = buf+buf_size; int ret, i, count; @@ -462,7 +462,7 @@ static int decode_frame(AVCodecContext *avctx, } *got_frame = 1; - if ((ret = av_frame_ref(data, s->frame)) < 0) + if ((ret = av_frame_ref(rframe, s->frame)) < 0) return ret; return buf_size; } @@ -475,21 +475,21 @@ static av_cold int decode_close(AVCodecContext *avctx) return 0; } -static const AVCodecDefault ansi_defaults[] = { +static const FFCodecDefault ansi_defaults[] = { { "max_pixels", "640*480" }, { NULL }, }; -const AVCodec ff_ansi_decoder = { - .name = "ansi", - .long_name = NULL_IF_CONFIG_SMALL("ASCII/ANSI art"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_ANSI, +const FFCodec ff_ansi_decoder = { + .p.name = "ansi", + .p.long_name = NULL_IF_CONFIG_SMALL("ASCII/ANSI art"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_ANSI, .priv_data_size = sizeof(AnsiContext), .init = decode_init, .close = decode_close, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, .defaults = ansi_defaults, }; diff --git a/libavcodec/apedec.c b/libavcodec/apedec.c index 8e56b9672..a7c38bce1 100644 --- a/libavcodec/apedec.c +++ b/libavcodec/apedec.c @@ -30,6 +30,7 @@ #include "avcodec.h" #include "bswapdsp.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" #include "get_bits.h" #include "unary.h" @@ -233,13 +234,14 @@ static av_cold int ape_decode_close(AVCodecContext *avctx) static av_cold int ape_decode_init(AVCodecContext *avctx) { APEContext *s = avctx->priv_data; + int channels = avctx->ch_layout.nb_channels; int i; if (avctx->extradata_size != 6) { av_log(avctx, AV_LOG_ERROR, "Incorrect extradata\n"); return AVERROR(EINVAL); } - if (avctx->channels > 2) { + if (channels > 2) { av_log(avctx, AV_LOG_ERROR, "Only mono and stereo is supported\n"); return AVERROR(EINVAL); } @@ -261,7 +263,7 @@ static av_cold int ape_decode_init(AVCodecContext *avctx) return AVERROR_PATCHWELCOME; } s->avctx = avctx; - s->channels = avctx->channels; + s->channels = channels; s->fileversion = AV_RL16(avctx->extradata); s->compression_level = AV_RL16(avctx->extradata + 2); s->flags = AV_RL16(avctx->extradata + 4); @@ -313,7 +315,9 @@ static av_cold int ape_decode_init(AVCodecContext *avctx) ff_bswapdsp_init(&s->bdsp); ff_llauddsp_init(&s->adsp); - avctx->channel_layout = (avctx->channels==2) ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = (channels == 2) ? (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO + : (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; return 0; } @@ -1457,10 +1461,9 @@ static void ape_unpack_stereo(APEContext *ctx, int count) } } -static int ape_decode_frame(AVCodecContext *avctx, void *data, +static int ape_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; const uint8_t *buf = avpkt->data; APEContext *s = avctx->priv_data; uint8_t *sample8; @@ -1655,22 +1658,22 @@ static const AVClass ape_decoder_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_ape_decoder = { - .name = "ape", - .long_name = NULL_IF_CONFIG_SMALL("Monkey's Audio"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_APE, +const FFCodec ff_ape_decoder = { + .p.name = "ape", + .p.long_name = NULL_IF_CONFIG_SMALL("Monkey's Audio"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_APE, .priv_data_size = sizeof(APEContext), .init = ape_decode_init, .close = ape_decode_close, - .decode = ape_decode_frame, - .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DELAY | + FF_CODEC_DECODE_CB(ape_decode_frame), + .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, - .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .flush = ape_flush, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_U8P, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_U8P, AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_NONE }, - .priv_class = &ape_decoder_class, + .p.priv_class = &ape_decoder_class, }; diff --git a/libavcodec/apng.h b/libavcodec/apng.h index 41249e0df..abd879533 100644 --- a/libavcodec/apng.h +++ b/libavcodec/apng.h @@ -38,4 +38,7 @@ enum { APNG_BLEND_OP_OVER = 1, }; +/* Only the payload data, not including length, fourcc and CRC-32. */ +#define APNG_FCTL_CHUNK_SIZE 26 + #endif /* AVCODEC_APNG_H */ diff --git a/libavcodec/aptx.c b/libavcodec/aptx.c index 3aeee1907..f2604be60 100644 --- a/libavcodec/aptx.c +++ b/libavcodec/aptx.c @@ -21,6 +21,7 @@ */ #include "aptx.h" +#include "mathops.h" static const int32_t quantize_intervals_LF[65] = { @@ -509,7 +510,7 @@ av_cold int ff_aptx_init(AVCodecContext *avctx) AptXContext *s = avctx->priv_data; int chan, subband; - if (avctx->channels != 2) + if (avctx->ch_layout.nb_channels != 2) return AVERROR_INVALIDDATA; s->hd = avctx->codec->id == AV_CODEC_ID_APTX_HD; diff --git a/libavcodec/aptx.h b/libavcodec/aptx.h index ce3d7dc6c..abb49e6fa 100644 --- a/libavcodec/aptx.h +++ b/libavcodec/aptx.h @@ -25,7 +25,6 @@ #include "libavutil/intreadwrite.h" #include "avcodec.h" -#include "internal.h" #include "mathops.h" #include "audio_frame_queue.h" diff --git a/libavcodec/aptxdec.c b/libavcodec/aptxdec.c index bdcc076c4..6ac070ba9 100644 --- a/libavcodec/aptxdec.c +++ b/libavcodec/aptxdec.c @@ -20,8 +20,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/channel_layout.h" #include "aptx.h" +#include "codec_internal.h" +#include "internal.h" /* * Half-band QMF synthesis filter realized with a polyphase FIR filter. @@ -133,11 +137,10 @@ static int aptx_decode_samples(AptXContext *ctx, return ret; } -static int aptx_decode_frame(AVCodecContext *avctx, void *data, +static int aptx_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { AptXContext *s = avctx->priv_data; - AVFrame *frame = data; int pos, opos, channel, sample, ret; if (avpkt->size < s->block_size) { @@ -146,7 +149,7 @@ static int aptx_decode_frame(AVCodecContext *avctx, void *data, } /* get output buffer */ - frame->channels = NB_CHANNELS; + frame->ch_layout.nb_channels = NB_CHANNELS; frame->format = AV_SAMPLE_FMT_S32P; frame->nb_samples = 4 * avpkt->size / s->block_size; if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) @@ -171,35 +174,41 @@ static int aptx_decode_frame(AVCodecContext *avctx, void *data, } #if CONFIG_APTX_DECODER -const 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, +const FFCodec ff_aptx_decoder = { + .p.name = "aptx", + .p.long_name = NULL_IF_CONFIG_SMALL("aptX (Audio Processing Technology for Bluetooth)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_APTX, .priv_data_size = sizeof(AptXContext), .init = ff_aptx_init, - .decode = aptx_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(aptx_decode_frame), + .p.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, +#if FF_API_OLD_CHANNEL_LAYOUT + .p.channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_STEREO, 0}, +#endif + .p.ch_layouts = (const AVChannelLayout[]) { AV_CHANNEL_LAYOUT_STEREO, { 0 } }, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_NONE }, }; #endif #if CONFIG_APTX_HD_DECODER -const 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, +const FFCodec ff_aptx_hd_decoder = { + .p.name = "aptx_hd", + .p.long_name = NULL_IF_CONFIG_SMALL("aptX HD (Audio Processing Technology for Bluetooth)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_APTX_HD, .priv_data_size = sizeof(AptXContext), .init = ff_aptx_init, - .decode = aptx_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(aptx_decode_frame), + .p.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, +#if FF_API_OLD_CHANNEL_LAYOUT + .p.channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_STEREO, 0}, +#endif + .p.ch_layouts = (const AVChannelLayout[]) { AV_CHANNEL_LAYOUT_STEREO, { 0 } }, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_NONE }, }; #endif diff --git a/libavcodec/aptxenc.c b/libavcodec/aptxenc.c index 5ea6053c2..89ab3974c 100644 --- a/libavcodec/aptxenc.c +++ b/libavcodec/aptxenc.c @@ -20,8 +20,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/channel_layout.h" #include "aptx.h" +#include "codec_internal.h" #include "encode.h" /* @@ -242,39 +245,45 @@ static av_cold int aptx_close(AVCodecContext *avctx) } #if CONFIG_APTX_ENCODER -const 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, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME, +const FFCodec ff_aptx_encoder = { + .p.name = "aptx", + .p.long_name = NULL_IF_CONFIG_SMALL("aptX (Audio Processing Technology for Bluetooth)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_APTX, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME, .priv_data_size = sizeof(AptXContext), .init = ff_aptx_init, - .encode2 = aptx_encode_frame, + FF_CODEC_ENCODE_CB(aptx_encode_frame), .close = aptx_close, .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, +#if FF_API_OLD_CHANNEL_LAYOUT + .p.channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_STEREO, 0}, +#endif + .p.ch_layouts = (const AVChannelLayout[]) { AV_CHANNEL_LAYOUT_STEREO, { 0 } }, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_NONE }, - .supported_samplerates = (const int[]) {8000, 16000, 24000, 32000, 44100, 48000, 0}, + .p.supported_samplerates = (const int[]) {8000, 16000, 24000, 32000, 44100, 48000, 0}, }; #endif #if CONFIG_APTX_HD_ENCODER -const 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, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME, +const FFCodec ff_aptx_hd_encoder = { + .p.name = "aptx_hd", + .p.long_name = NULL_IF_CONFIG_SMALL("aptX HD (Audio Processing Technology for Bluetooth)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_APTX_HD, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME, .priv_data_size = sizeof(AptXContext), .init = ff_aptx_init, - .encode2 = aptx_encode_frame, + FF_CODEC_ENCODE_CB(aptx_encode_frame), .close = aptx_close, .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, +#if FF_API_OLD_CHANNEL_LAYOUT + .p.channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_STEREO, 0}, +#endif + .p.ch_layouts = (const AVChannelLayout[]) { AV_CHANNEL_LAYOUT_STEREO, { 0 } }, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_NONE }, - .supported_samplerates = (const int[]) {8000, 16000, 24000, 32000, 44100, 48000, 0}, + .p.supported_samplerates = (const int[]) {8000, 16000, 24000, 32000, 44100, 48000, 0}, }; #endif diff --git a/libavcodec/arbc.c b/libavcodec/arbc.c index d03fdf214..78600963e 100644 --- a/libavcodec/arbc.c +++ b/libavcodec/arbc.c @@ -29,6 +29,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" typedef struct ARBCContext { @@ -115,11 +116,10 @@ static int fill_tileX(AVCodecContext *avctx, int tile_width, int tile_height, return pixels_overwritten; } -static int decode_frame(AVCodecContext *avctx, void *data, +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt) { ARBCContext *s = avctx->priv_data; - AVFrame *frame = data; int ret, nb_segments; int prev_pixels = avctx->width * avctx->height; @@ -211,16 +211,16 @@ static av_cold int decode_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_arbc_decoder = { - .name = "arbc", - .long_name = NULL_IF_CONFIG_SMALL("Gryphon's Anim Compressor"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_ARBC, +const FFCodec ff_arbc_decoder = { + .p.name = "arbc", + .p.long_name = NULL_IF_CONFIG_SMALL("Gryphon's Anim Compressor"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_ARBC, .priv_data_size = sizeof(ARBCContext), .init = decode_init, - .decode = decode_frame, + FF_CODEC_DECODE_CB(decode_frame), .flush = decode_flush, .close = decode_close, - .capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/argo.c b/libavcodec/argo.c index 58cc9984b..efd1056f1 100644 --- a/libavcodec/argo.c +++ b/libavcodec/argo.c @@ -29,6 +29,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" typedef struct ArgoContext { @@ -598,7 +599,7 @@ static int decode_rle(AVCodecContext *avctx, AVFrame *frame) return 0; } -static int decode_frame(AVCodecContext *avctx, void *data, +static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, int *got_frame, AVPacket *avpkt) { ArgoContext *s = avctx->priv_data; @@ -664,7 +665,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, if (avctx->pix_fmt == AV_PIX_FMT_PAL8) memcpy(frame->data[1], s->pal, AVPALETTE_SIZE); - if ((ret = av_frame_ref(data, s->frame)) < 0) + if ((ret = av_frame_ref(rframe, s->frame)) < 0) return ret; frame->pict_type = s->key ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; @@ -732,16 +733,16 @@ static av_cold int decode_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_argo_decoder = { - .name = "argo", - .long_name = NULL_IF_CONFIG_SMALL("Argonaut Games Video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_ARGO, +const FFCodec ff_argo_decoder = { + .p.name = "argo", + .p.long_name = NULL_IF_CONFIG_SMALL("Argonaut Games Video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_ARGO, .priv_data_size = sizeof(ArgoContext), .init = decode_init, - .decode = decode_frame, + FF_CODEC_DECODE_CB(decode_frame), .flush = decode_flush, .close = decode_close, - .capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/arm/flacdsp_init_arm.c b/libavcodec/arm/flacdsp_init_arm.c index c4a6e3a53..bac9ff195 100644 --- a/libavcodec/arm/flacdsp_init_arm.c +++ b/libavcodec/arm/flacdsp_init_arm.c @@ -21,6 +21,7 @@ #include "libavutil/attributes.h" #include "libavcodec/flacdsp.h" #include "config.h" +#include "config_components.h" void ff_flac_lpc_16_arm(int32_t *samples, const int coeffs[32], int order, int qlevel, int len); diff --git a/libavcodec/arm/h264cmc_neon.S b/libavcodec/arm/h264cmc_neon.S index 5a4159eed..3687b02ed 100644 --- a/libavcodec/arm/h264cmc_neon.S +++ b/libavcodec/arm/h264cmc_neon.S @@ -18,6 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/arm/asm.S" /* chroma_mc8(uint8_t *dst, uint8_t *src, ptrdiff_t stride, int h, int x, int y) */ diff --git a/libavcodec/arm/hevcdsp_init_neon.c b/libavcodec/arm/hevcdsp_init_neon.c index 201a088da..112edb5ed 100644 --- a/libavcodec/arm/hevcdsp_init_neon.c +++ b/libavcodec/arm/hevcdsp_init_neon.c @@ -270,7 +270,8 @@ av_cold void ff_hevc_dsp_init_neon(HEVCDSPContext *c, const int bit_depth) put_hevc_qpel_uw_neon[3][1] = ff_hevc_put_qpel_uw_h1v3_neon_8; put_hevc_qpel_uw_neon[3][2] = ff_hevc_put_qpel_uw_h2v3_neon_8; put_hevc_qpel_uw_neon[3][3] = ff_hevc_put_qpel_uw_h3v3_neon_8; - for (x = 0; x < 10; x++) { + for (x = 3; x < 10; x++) { + if (x == 4) continue; c->put_hevc_qpel[x][1][0] = ff_hevc_put_qpel_neon_wrapper; c->put_hevc_qpel[x][0][1] = ff_hevc_put_qpel_neon_wrapper; c->put_hevc_qpel[x][1][1] = ff_hevc_put_qpel_neon_wrapper; diff --git a/libavcodec/arm/hevcdsp_qpel_neon.S b/libavcodec/arm/hevcdsp_qpel_neon.S index f71bec05e..caa6efa76 100644 --- a/libavcodec/arm/hevcdsp_qpel_neon.S +++ b/libavcodec/arm/hevcdsp_qpel_neon.S @@ -237,7 +237,7 @@ vld1.8 {d23}, [r2], r3 bne 8b subs r5, #8 - ble 99f + beq 99f mov r4, r12 add r6, #16 mov r0, r6 @@ -280,7 +280,7 @@ vld1.8 {d23}, [r2], r3 bne 8b subs r5, #8 - ble 99f + beq 99f mov r4, r12 add r6, #8 mov r0, r6 @@ -310,7 +310,7 @@ vld1.8 {d23}, [r2], r3 bne 8b subs r5, #8 - ble 99f + beq 99f mov r4, r12 add r6, #8 mov r0, r6 @@ -377,7 +377,7 @@ endfunc vst1.16 {q7}, [r0], r1 bne 8b subs r5, #8 - ble 99f + beq 99f mov r4, r12 add r6, #16 mov r0, r6 @@ -417,7 +417,7 @@ endfunc vst1.8 d0, [r0], r1 bne 8b subs r5, #8 - ble 99f + beq 99f mov r4, r12 add r6, #8 mov r0, r6 @@ -446,7 +446,7 @@ endfunc vst1.8 d0, [r0], r1 bne 8b subs r5, #8 - ble 99f + beq 99f mov r4, r12 add r6, #8 add r10, #16 @@ -533,7 +533,7 @@ endfunc \filterh q7 bne 8b subs r5, #8 - ble 99f + beq 99f mov r4, r12 add r6, #16 mov r0, r6 @@ -594,7 +594,7 @@ endfunc \filterh q7 bne 8b subs r5, #8 - ble 99f + beq 99f mov r4, r12 add r6, #8 mov r0, r6 @@ -641,7 +641,7 @@ endfunc \filterh q7 bne 8b subs r5, #8 - ble 99f + beq 99f mov r4, r12 add r6, #8 mov r0, r6 diff --git a/libavcodec/arm/vc1dsp_init_neon.c b/libavcodec/arm/vc1dsp_init_neon.c index 2cca784f5..48cb816b7 100644 --- a/libavcodec/arm/vc1dsp_init_neon.c +++ b/libavcodec/arm/vc1dsp_init_neon.c @@ -19,6 +19,7 @@ #include #include "libavutil/attributes.h" +#include "libavutil/intreadwrite.h" #include "libavcodec/vc1dsp.h" #include "vc1dsp.h" @@ -32,6 +33,13 @@ void ff_vc1_inv_trans_4x8_dc_neon(uint8_t *dest, ptrdiff_t stride, int16_t *bloc void ff_vc1_inv_trans_8x4_dc_neon(uint8_t *dest, ptrdiff_t stride, int16_t *block); void ff_vc1_inv_trans_4x4_dc_neon(uint8_t *dest, ptrdiff_t stride, int16_t *block); +void ff_vc1_v_loop_filter4_neon(uint8_t *src, int stride, int pq); +void ff_vc1_h_loop_filter4_neon(uint8_t *src, int stride, int pq); +void ff_vc1_v_loop_filter8_neon(uint8_t *src, int stride, int pq); +void ff_vc1_h_loop_filter8_neon(uint8_t *src, int stride, int pq); +void ff_vc1_v_loop_filter16_neon(uint8_t *src, int stride, int pq); +void ff_vc1_h_loop_filter16_neon(uint8_t *src, int stride, int pq); + void ff_put_pixels8x8_neon(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int rnd); @@ -77,6 +85,64 @@ void ff_put_vc1_chroma_mc4_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride, void ff_avg_vc1_chroma_mc4_neon(uint8_t *dst, uint8_t *src, ptrdiff_t stride, int h, int x, int y); +int ff_vc1_unescape_buffer_helper_neon(const uint8_t *src, int size, uint8_t *dst); + +static int vc1_unescape_buffer_neon(const uint8_t *src, int size, uint8_t *dst) +{ + /* Dealing with starting and stopping, and removing escape bytes, are + * comparatively less time-sensitive, so are more clearly expressed using + * a C wrapper around the assembly inner loop. Note that we assume a + * little-endian machine that supports unaligned loads. */ + int dsize = 0; + while (size >= 4) + { + int found = 0; + while (!found && (((uintptr_t) dst) & 7) && size >= 4) + { + found = (AV_RL32(src) &~ 0x03000000) == 0x00030000; + if (!found) + { + *dst++ = *src++; + --size; + ++dsize; + } + } + if (!found) + { + int skip = size - ff_vc1_unescape_buffer_helper_neon(src, size, dst); + dst += skip; + src += skip; + size -= skip; + dsize += skip; + while (!found && size >= 4) + { + found = (AV_RL32(src) &~ 0x03000000) == 0x00030000; + if (!found) + { + *dst++ = *src++; + --size; + ++dsize; + } + } + } + if (found) + { + *dst++ = *src++; + *dst++ = *src++; + ++src; + size -= 3; + dsize += 2; + } + } + while (size > 0) + { + *dst++ = *src++; + --size; + ++dsize; + } + return dsize; +} + #define FN_ASSIGN(X, Y) \ dsp->put_vc1_mspel_pixels_tab[0][X+4*Y] = ff_put_vc1_mspel_mc##X##Y##_16_neon; \ dsp->put_vc1_mspel_pixels_tab[1][X+4*Y] = ff_put_vc1_mspel_mc##X##Y##_neon @@ -92,6 +158,13 @@ av_cold void ff_vc1dsp_init_neon(VC1DSPContext *dsp) dsp->vc1_inv_trans_8x4_dc = ff_vc1_inv_trans_8x4_dc_neon; dsp->vc1_inv_trans_4x4_dc = ff_vc1_inv_trans_4x4_dc_neon; + dsp->vc1_v_loop_filter4 = ff_vc1_v_loop_filter4_neon; + dsp->vc1_h_loop_filter4 = ff_vc1_h_loop_filter4_neon; + dsp->vc1_v_loop_filter8 = ff_vc1_v_loop_filter8_neon; + dsp->vc1_h_loop_filter8 = ff_vc1_h_loop_filter8_neon; + dsp->vc1_v_loop_filter16 = ff_vc1_v_loop_filter16_neon; + dsp->vc1_h_loop_filter16 = ff_vc1_h_loop_filter16_neon; + dsp->put_vc1_mspel_pixels_tab[1][ 0] = ff_put_pixels8x8_neon; FN_ASSIGN(1, 0); FN_ASSIGN(2, 0); @@ -116,4 +189,6 @@ av_cold void ff_vc1dsp_init_neon(VC1DSPContext *dsp) dsp->avg_no_rnd_vc1_chroma_pixels_tab[0] = ff_avg_vc1_chroma_mc8_neon; dsp->put_no_rnd_vc1_chroma_pixels_tab[1] = ff_put_vc1_chroma_mc4_neon; dsp->avg_no_rnd_vc1_chroma_pixels_tab[1] = ff_avg_vc1_chroma_mc4_neon; + + dsp->vc1_unescape_buffer = vc1_unescape_buffer_neon; } diff --git a/libavcodec/arm/vc1dsp_neon.S b/libavcodec/arm/vc1dsp_neon.S index 93f043bf0..96014fbeb 100644 --- a/libavcodec/arm/vc1dsp_neon.S +++ b/libavcodec/arm/vc1dsp_neon.S @@ -1161,3 +1161,764 @@ function ff_vc1_inv_trans_4x4_dc_neon, export=1 vst1.32 {d1[1]}, [r0,:32] bx lr endfunc + +@ VC-1 in-loop deblocking filter for 4 pixel pairs at boundary of vertically-neighbouring blocks +@ On entry: +@ r0 -> top-left pel of lower block +@ r1 = row stride, bytes +@ r2 = PQUANT bitstream parameter +function ff_vc1_v_loop_filter4_neon, export=1 + sub r3, r0, r1, lsl #2 + vldr d0, .Lcoeffs + vld1.32 {d1[0]}, [r0], r1 @ P5 + vld1.32 {d2[0]}, [r3], r1 @ P1 + vld1.32 {d3[0]}, [r3], r1 @ P2 + vld1.32 {d4[0]}, [r0], r1 @ P6 + vld1.32 {d5[0]}, [r3], r1 @ P3 + vld1.32 {d6[0]}, [r0], r1 @ P7 + vld1.32 {d7[0]}, [r3] @ P4 + vld1.32 {d16[0]}, [r0] @ P8 + vshll.u8 q9, d1, #1 @ 2*P5 + vdup.16 d17, r2 @ pq + vshll.u8 q10, d2, #1 @ 2*P1 + vmovl.u8 q11, d3 @ P2 + vmovl.u8 q1, d4 @ P6 + vmovl.u8 q12, d5 @ P3 + vmls.i16 d20, d22, d0[1] @ 2*P1-5*P2 + vmovl.u8 q11, d6 @ P7 + vmls.i16 d18, d2, d0[1] @ 2*P5-5*P6 + vshll.u8 q2, d5, #1 @ 2*P3 + vmovl.u8 q3, d7 @ P4 + vmla.i16 d18, d22, d0[1] @ 2*P5-5*P6+5*P7 + vmovl.u8 q11, d16 @ P8 + vmla.u16 d20, d24, d0[1] @ 2*P1-5*P2+5*P3 + vmovl.u8 q12, d1 @ P5 + vmls.u16 d4, d6, d0[1] @ 2*P3-5*P4 + vmls.u16 d18, d22, d0[0] @ 2*P5-5*P6+5*P7-2*P8 + vsub.i16 d1, d6, d24 @ P4-P5 + vmls.i16 d20, d6, d0[0] @ 2*P1-5*P2+5*P3-2*P4 + vmla.i16 d4, d24, d0[1] @ 2*P3-5*P4+5*P5 + vmls.i16 d4, d2, d0[0] @ 2*P3-5*P4+5*P5-2*P6 + vabs.s16 d2, d1 + vrshr.s16 d3, d18, #3 + vrshr.s16 d5, d20, #3 + vshr.s16 d2, d2, #1 @ clip + vrshr.s16 d4, d4, #3 + vabs.s16 d3, d3 @ a2 + vshr.s16 d1, d1, #8 @ clip_sign + vabs.s16 d5, d5 @ a1 + vceq.i16 d7, d2, #0 @ test clip == 0 + vabs.s16 d16, d4 @ a0 + vshr.s16 d4, d4, #8 @ a0_sign + vcge.s16 d18, d5, d3 @ test a1 >= a2 + vcge.s16 d17, d16, d17 @ test a0 >= pq + vbsl d18, d3, d5 @ a3 + vsub.i16 d1, d1, d4 @ clip_sign - a0_sign + vorr d3, d7, d17 @ test clip == 0 || a0 >= pq + vqsub.u16 d4, d16, d18 @ a0 >= a3 ? a0-a3 : 0 (a0 > a3 in all cases where filtering is enabled, so makes more sense to subtract this way round than the opposite and then taking the abs) + vcge.s16 d5, d18, d16 @ test a3 >= a0 + vmul.i16 d0, d4, d0[1] @ a0 >= a3 ? 5*(a0-a3) : 0 + vorr d4, d3, d5 @ test clip == 0 || a0 >= pq || a3 >= a0 + vmov.32 r0, d4[1] @ move to gp reg + vshr.u16 d0, d0, #3 @ a0 >= a3 ? (5*(a0-a3))>>3 : 0 + vcge.s16 d4, d0, d2 + tst r0, #1 + bne 1f @ none of the 4 pixel pairs should be updated if this one is not filtered + vbsl d4, d2, d0 @ FFMIN(d, clip) + vbic d0, d4, d3 @ set each d to zero if it should not be filtered because clip == 0 || a0 >= pq (a3 > a0 case already zeroed by saturating sub) + vmls.i16 d6, d0, d1 @ invert d depending on clip_sign & a0_sign, or zero it if they match, and accumulate into P4 + vmla.i16 d24, d0, d1 @ invert d depending on clip_sign & a0_sign, or zero it if they match, and accumulate into P5 + vqmovun.s16 d0, q3 + vqmovun.s16 d1, q12 + vst1.32 {d0[0]}, [r3], r1 + vst1.32 {d1[0]}, [r3] +1: bx lr +endfunc + +@ VC-1 in-loop deblocking filter for 4 pixel pairs at boundary of horizontally-neighbouring blocks +@ On entry: +@ r0 -> top-left pel of right block +@ r1 = row stride, bytes +@ r2 = PQUANT bitstream parameter +function ff_vc1_h_loop_filter4_neon, export=1 + sub r3, r0, #4 @ where to start reading + vldr d0, .Lcoeffs + vld1.32 {d2}, [r3], r1 + sub r0, r0, #1 @ where to start writing + vld1.32 {d4}, [r3], r1 + vld1.32 {d3}, [r3], r1 + vld1.32 {d5}, [r3] + vdup.16 d1, r2 @ pq + vtrn.8 q1, q2 + vtrn.16 d2, d3 @ P1, P5, P3, P7 + vtrn.16 d4, d5 @ P2, P6, P4, P8 + vshll.u8 q3, d2, #1 @ 2*P1, 2*P5 + vmovl.u8 q8, d4 @ P2, P6 + vmovl.u8 q9, d3 @ P3, P7 + vmovl.u8 q2, d5 @ P4, P8 + vmls.i16 q3, q8, d0[1] @ 2*P1-5*P2, 2*P5-5*P6 + vshll.u8 q10, d3, #1 @ 2*P3, 2*P7 + vmovl.u8 q1, d2 @ P1, P5 + vmla.i16 q3, q9, d0[1] @ 2*P1-5*P2+5*P3, 2*P5-5*P6+5*P7 + vmls.i16 q3, q2, d0[0] @ 2*P1-5*P2+5*P3-2*P4, 2*P5-5*P6+5*P7-2*P8 + vmov d2, d3 @ needs to be in an even-numbered vector for when we come to narrow it later + vmls.i16 d20, d4, d0[1] @ 2*P3-5*P4 + vmla.i16 d20, d3, d0[1] @ 2*P3-5*P4+5*P5 + vsub.i16 d3, d4, d2 @ P4-P5 + vmls.i16 d20, d17, d0[0] @ 2*P3-5*P4+5*P5-2*P6 + vrshr.s16 q3, q3, #3 + vabs.s16 d5, d3 + vshr.s16 d3, d3, #8 @ clip_sign + vrshr.s16 d16, d20, #3 + vabs.s16 q3, q3 @ a1, a2 + vshr.s16 d5, d5, #1 @ clip + vabs.s16 d17, d16 @ a0 + vceq.i16 d18, d5, #0 @ test clip == 0 + vshr.s16 d16, d16, #8 @ a0_sign + vcge.s16 d19, d6, d7 @ test a1 >= a2 + vcge.s16 d1, d17, d1 @ test a0 >= pq + vsub.i16 d16, d3, d16 @ clip_sign - a0_sign + vbsl d19, d7, d6 @ a3 + vorr d1, d18, d1 @ test clip == 0 || a0 >= pq + vqsub.u16 d3, d17, d19 @ a0 >= a3 ? a0-a3 : 0 (a0 > a3 in all cases where filtering is enabled, so makes more sense to subtract this way round than the opposite and then taking the abs) + vcge.s16 d6, d19, d17 @ test a3 >= a0 @ + vmul.i16 d0, d3, d0[1] @ a0 >= a3 ? 5*(a0-a3) : 0 + vorr d3, d1, d6 @ test clip == 0 || a0 >= pq || a3 >= a0 + vmov.32 r2, d3[1] @ move to gp reg + vshr.u16 d0, d0, #3 @ a0 >= a3 ? (5*(a0-a3))>>3 : 0 + vcge.s16 d3, d0, d5 + tst r2, #1 + bne 1f @ none of the 4 pixel pairs should be updated if this one is not filtered + vbsl d3, d5, d0 @ FFMIN(d, clip) + vbic d0, d3, d1 @ set each d to zero if it should not be filtered because clip == 0 || a0 >= pq (a3 > a0 case already zeroed by saturating sub) + vmla.i16 d2, d0, d16 @ invert d depending on clip_sign & a0_sign, or zero it if they match, and accumulate into P5 + vmls.i16 d4, d0, d16 @ invert d depending on clip_sign & a0_sign, or zero it if they match, and accumulate into P4 + vqmovun.s16 d1, q1 + vqmovun.s16 d0, q2 + vst2.8 {d0[0], d1[0]}, [r0], r1 + vst2.8 {d0[1], d1[1]}, [r0], r1 + vst2.8 {d0[2], d1[2]}, [r0], r1 + vst2.8 {d0[3], d1[3]}, [r0] +1: bx lr +endfunc + +@ VC-1 in-loop deblocking filter for 8 pixel pairs at boundary of vertically-neighbouring blocks +@ On entry: +@ r0 -> top-left pel of lower block +@ r1 = row stride, bytes +@ r2 = PQUANT bitstream parameter +function ff_vc1_v_loop_filter8_neon, export=1 + sub r3, r0, r1, lsl #2 + vldr d0, .Lcoeffs + vld1.32 {d1}, [r0 :64], r1 @ P5 + vld1.32 {d2}, [r3 :64], r1 @ P1 + vld1.32 {d3}, [r3 :64], r1 @ P2 + vld1.32 {d4}, [r0 :64], r1 @ P6 + vld1.32 {d5}, [r3 :64], r1 @ P3 + vld1.32 {d6}, [r0 :64], r1 @ P7 + vshll.u8 q8, d1, #1 @ 2*P5 + vshll.u8 q9, d2, #1 @ 2*P1 + vld1.32 {d7}, [r3 :64] @ P4 + vmovl.u8 q1, d3 @ P2 + vld1.32 {d20}, [r0 :64] @ P8 + vmovl.u8 q11, d4 @ P6 + vdup.16 q12, r2 @ pq + vmovl.u8 q13, d5 @ P3 + vmls.i16 q9, q1, d0[1] @ 2*P1-5*P2 + vmovl.u8 q1, d6 @ P7 + vshll.u8 q2, d5, #1 @ 2*P3 + vmls.i16 q8, q11, d0[1] @ 2*P5-5*P6 + vmovl.u8 q3, d7 @ P4 + vmovl.u8 q10, d20 @ P8 + vmla.i16 q8, q1, d0[1] @ 2*P5-5*P6+5*P7 + vmovl.u8 q1, d1 @ P5 + vmla.i16 q9, q13, d0[1] @ 2*P1-5*P2+5*P3 + vsub.i16 q13, q3, q1 @ P4-P5 + vmls.i16 q2, q3, d0[1] @ 2*P3-5*P4 + vmls.i16 q8, q10, d0[0] @ 2*P5-5*P6+5*P7-2*P8 + vabs.s16 q10, q13 + vshr.s16 q13, q13, #8 @ clip_sign + vmls.i16 q9, q3, d0[0] @ 2*P1-5*P2+5*P3-2*P4 + vshr.s16 q10, q10, #1 @ clip + vmla.i16 q2, q1, d0[1] @ 2*P3-5*P4+5*P5 + vrshr.s16 q8, q8, #3 + vmls.i16 q2, q11, d0[0] @ 2*P3-5*P4+5*P5-2*P6 + vceq.i16 q11, q10, #0 @ test clip == 0 + vrshr.s16 q9, q9, #3 + vabs.s16 q8, q8 @ a2 + vabs.s16 q9, q9 @ a1 + vrshr.s16 q2, q2, #3 + vcge.s16 q14, q9, q8 @ test a1 >= a2 + vabs.s16 q15, q2 @ a0 + vshr.s16 q2, q2, #8 @ a0_sign + vbsl q14, q8, q9 @ a3 + vcge.s16 q8, q15, q12 @ test a0 >= pq + vsub.i16 q2, q13, q2 @ clip_sign - a0_sign + vqsub.u16 q9, q15, q14 @ a0 >= a3 ? a0-a3 : 0 (a0 > a3 in all cases where filtering is enabled, so makes more sense to subtract this way round than the opposite and then taking the abs) + vcge.s16 q12, q14, q15 @ test a3 >= a0 + vorr q8, q11, q8 @ test clip == 0 || a0 >= pq + vmul.i16 q0, q9, d0[1] @ a0 >= a3 ? 5*(a0-a3) : 0 + vorr q9, q8, q12 @ test clip == 0 || a0 >= pq || a3 >= a0 + vshl.i64 q11, q9, #16 + vmov.32 r0, d18[1] @ move to gp reg + vshr.u16 q0, q0, #3 @ a0 >= a3 ? (5*(a0-a3))>>3 : 0 + vmov.32 r2, d19[1] + vshr.s64 q9, q11, #48 + vcge.s16 q11, q0, q10 + vorr q8, q8, q9 + and r0, r0, r2 + vbsl q11, q10, q0 @ FFMIN(d, clip) + tst r0, #1 + bne 1f @ none of the 8 pixel pairs should be updated in this case + vbic q0, q11, q8 @ set each d to zero if it should not be filtered + vmls.i16 q3, q0, q2 @ invert d depending on clip_sign & a0_sign, or zero it if they match, and accumulate into P4 + vmla.i16 q1, q0, q2 @ invert d depending on clip_sign & a0_sign, or zero it if they match, and accumulate into P5 + vqmovun.s16 d0, q3 + vqmovun.s16 d1, q1 + vst1.32 {d0}, [r3 :64], r1 + vst1.32 {d1}, [r3 :64] +1: bx lr +endfunc + +.align 5 +.Lcoeffs: +.quad 0x00050002 + +@ VC-1 in-loop deblocking filter for 8 pixel pairs at boundary of horizontally-neighbouring blocks +@ On entry: +@ r0 -> top-left pel of right block +@ r1 = row stride, bytes +@ r2 = PQUANT bitstream parameter +function ff_vc1_h_loop_filter8_neon, export=1 + push {lr} + sub r3, r0, #4 @ where to start reading + vldr d0, .Lcoeffs + vld1.32 {d2}, [r3], r1 @ P1[0], P2[0]... + sub r0, r0, #1 @ where to start writing + vld1.32 {d4}, [r3], r1 + add r12, r0, r1, lsl #2 + vld1.32 {d3}, [r3], r1 + vld1.32 {d5}, [r3], r1 + vld1.32 {d6}, [r3], r1 + vld1.32 {d16}, [r3], r1 + vld1.32 {d7}, [r3], r1 + vld1.32 {d17}, [r3] + vtrn.8 q1, q2 @ P1[0], P1[1], P3[0]... P1[2], P1[3], P3[2]... P2[0], P2[1], P4[0]... P2[2], P2[3], P4[2]... + vdup.16 q9, r2 @ pq + vtrn.16 d2, d3 @ P1[0], P1[1], P1[2], P1[3], P5[0]... P3[0], P3[1], P3[2], P3[3], P7[0]... + vtrn.16 d4, d5 @ P2[0], P2[1], P2[2], P2[3], P6[0]... P4[0], P4[1], P4[2], P4[3], P8[0]... + vtrn.8 q3, q8 @ P1[4], P1[5], P3[4]... P1[6], P1[7], P3[6]... P2[4], P2[5], P4[4]... P2[6], P2[7], P4[6]... + vtrn.16 d6, d7 @ P1[4], P1[5], P1[6], P1[7], P5[4]... P3[4], P3[5], P3[5], P3[7], P7[4]... + vtrn.16 d16, d17 @ P2[4], P2[5], P2[6], P2[7], P6[4]... P4[4], P4[5], P4[6], P4[7], P8[4]... + vtrn.32 d2, d6 @ P1, P5 + vtrn.32 d4, d16 @ P2, P6 + vtrn.32 d3, d7 @ P3, P7 + vtrn.32 d5, d17 @ P4, P8 + vshll.u8 q10, d2, #1 @ 2*P1 + vshll.u8 q11, d6, #1 @ 2*P5 + vmovl.u8 q12, d4 @ P2 + vmovl.u8 q13, d16 @ P6 + vmovl.u8 q14, d3 @ P3 + vmls.i16 q10, q12, d0[1] @ 2*P1-5*P2 + vmovl.u8 q12, d7 @ P7 + vshll.u8 q1, d3, #1 @ 2*P3 + vmls.i16 q11, q13, d0[1] @ 2*P5-5*P6 + vmovl.u8 q2, d5 @ P4 + vmovl.u8 q8, d17 @ P8 + vmla.i16 q11, q12, d0[1] @ 2*P5-5*P6+5*P7 + vmovl.u8 q3, d6 @ P5 + vmla.i16 q10, q14, d0[1] @ 2*P1-5*P2+5*P3 + vsub.i16 q12, q2, q3 @ P4-P5 + vmls.i16 q1, q2, d0[1] @ 2*P3-5*P4 + vmls.i16 q11, q8, d0[0] @ 2*P5-5*P6+5*P7-2*P8 + vabs.s16 q8, q12 + vshr.s16 q12, q12, #8 @ clip_sign + vmls.i16 q10, q2, d0[0] @ 2*P1-5*P2+5*P3-2*P4 + vshr.s16 q8, q8, #1 @ clip + vmla.i16 q1, q3, d0[1] @ 2*P3-5*P4+5*P5 + vrshr.s16 q11, q11, #3 + vmls.i16 q1, q13, d0[0] @ 2*P3-5*P4+5*P5-2*P6 + vceq.i16 q13, q8, #0 @ test clip == 0 + vrshr.s16 q10, q10, #3 + vabs.s16 q11, q11 @ a2 + vabs.s16 q10, q10 @ a1 + vrshr.s16 q1, q1, #3 + vcge.s16 q14, q10, q11 @ test a1 >= a2 + vabs.s16 q15, q1 @ a0 + vshr.s16 q1, q1, #8 @ a0_sign + vbsl q14, q11, q10 @ a3 + vcge.s16 q9, q15, q9 @ test a0 >= pq + vsub.i16 q1, q12, q1 @ clip_sign - a0_sign + vqsub.u16 q10, q15, q14 @ a0 >= a3 ? a0-a3 : 0 (a0 > a3 in all cases where filtering is enabled, so makes more sense to subtract this way round than the opposite and then taking the abs) + vcge.s16 q11, q14, q15 @ test a3 >= a0 + vorr q9, q13, q9 @ test clip == 0 || a0 >= pq + vmul.i16 q0, q10, d0[1] @ a0 >= a3 ? 5*(a0-a3) : 0 + vorr q10, q9, q11 @ test clip == 0 || a0 >= pq || a3 >= a0 + vmov.32 r2, d20[1] @ move to gp reg + vshr.u16 q0, q0, #3 @ a0 >= a3 ? (5*(a0-a3))>>3 : 0 + vmov.32 r3, d21[1] + vcge.s16 q10, q0, q8 + and r14, r2, r3 + vbsl q10, q8, q0 @ FFMIN(d, clip) + tst r14, #1 + bne 2f @ none of the 8 pixel pairs should be updated in this case + vbic q0, q10, q9 @ set each d to zero if it should not be filtered because clip == 0 || a0 >= pq (a3 > a0 case already zeroed by saturating sub) + vmla.i16 q3, q0, q1 @ invert d depending on clip_sign & a0_sign, or zero it if they match, and accumulate into P5 + vmls.i16 q2, q0, q1 @ invert d depending on clip_sign & a0_sign, or zero it if they match, and accumulate into P4 + vqmovun.s16 d1, q3 + vqmovun.s16 d0, q2 + tst r2, #1 + bne 1f @ none of the first 4 pixel pairs should be updated if so + vst2.8 {d0[0], d1[0]}, [r0], r1 + vst2.8 {d0[1], d1[1]}, [r0], r1 + vst2.8 {d0[2], d1[2]}, [r0], r1 + vst2.8 {d0[3], d1[3]}, [r0] +1: tst r3, #1 + bne 2f @ none of the second 4 pixel pairs should be updated if so + vst2.8 {d0[4], d1[4]}, [r12], r1 + vst2.8 {d0[5], d1[5]}, [r12], r1 + vst2.8 {d0[6], d1[6]}, [r12], r1 + vst2.8 {d0[7], d1[7]}, [r12] +2: pop {pc} +endfunc + +@ VC-1 in-loop deblocking filter for 16 pixel pairs at boundary of vertically-neighbouring blocks +@ On entry: +@ r0 -> top-left pel of lower block +@ r1 = row stride, bytes +@ r2 = PQUANT bitstream parameter +function ff_vc1_v_loop_filter16_neon, export=1 + vpush {d8-d15} + sub r3, r0, r1, lsl #2 + vldr d0, .Lcoeffs + vld1.64 {q1}, [r0 :128], r1 @ P5 + vld1.64 {q2}, [r3 :128], r1 @ P1 + vld1.64 {q3}, [r3 :128], r1 @ P2 + vld1.64 {q4}, [r0 :128], r1 @ P6 + vld1.64 {q5}, [r3 :128], r1 @ P3 + vld1.64 {q6}, [r0 :128], r1 @ P7 + vshll.u8 q7, d2, #1 @ 2*P5[0..7] + vshll.u8 q8, d4, #1 @ 2*P1[0..7] + vld1.64 {q9}, [r3 :128] @ P4 + vmovl.u8 q10, d6 @ P2[0..7] + vld1.64 {q11}, [r0 :128] @ P8 + vmovl.u8 q12, d8 @ P6[0..7] + vdup.16 q13, r2 @ pq + vshll.u8 q2, d5, #1 @ 2*P1[8..15] + vmls.i16 q8, q10, d0[1] @ 2*P1[0..7]-5*P2[0..7] + vshll.u8 q10, d3, #1 @ 2*P5[8..15] + vmovl.u8 q3, d7 @ P2[8..15] + vmls.i16 q7, q12, d0[1] @ 2*P5[0..7]-5*P6[0..7] + vmovl.u8 q4, d9 @ P6[8..15] + vmovl.u8 q14, d10 @ P3[0..7] + vmovl.u8 q15, d12 @ P7[0..7] + vmls.i16 q2, q3, d0[1] @ 2*P1[8..15]-5*P2[8..15] + vshll.u8 q3, d10, #1 @ 2*P3[0..7] + vmls.i16 q10, q4, d0[1] @ 2*P5[8..15]-5*P6[8..15] + vmovl.u8 q6, d13 @ P7[8..15] + vmla.i16 q8, q14, d0[1] @ 2*P1[0..7]-5*P2[0..7]+5*P3[0..7] + vmovl.u8 q14, d18 @ P4[0..7] + vmovl.u8 q9, d19 @ P4[8..15] + vmla.i16 q7, q15, d0[1] @ 2*P5[0..7]-5*P6[0..7]+5*P7[0..7] + vmovl.u8 q15, d11 @ P3[8..15] + vshll.u8 q5, d11, #1 @ 2*P3[8..15] + vmls.i16 q3, q14, d0[1] @ 2*P3[0..7]-5*P4[0..7] + vmla.i16 q2, q15, d0[1] @ 2*P1[8..15]-5*P2[8..15]+5*P3[8..15] + vmovl.u8 q15, d22 @ P8[0..7] + vmovl.u8 q11, d23 @ P8[8..15] + vmla.i16 q10, q6, d0[1] @ 2*P5[8..15]-5*P6[8..15]+5*P7[8..15] + vmovl.u8 q6, d2 @ P5[0..7] + vmovl.u8 q1, d3 @ P5[8..15] + vmls.i16 q5, q9, d0[1] @ 2*P3[8..15]-5*P4[8..15] + vmls.i16 q8, q14, d0[0] @ 2*P1[0..7]-5*P2[0..7]+5*P3[0..7]-2*P4[0..7] + vmls.i16 q7, q15, d0[0] @ 2*P5[0..7]-5*P6[0..7]+5*P7[0..7]-2*P8[0..7] + vsub.i16 q15, q14, q6 @ P4[0..7]-P5[0..7] + vmla.i16 q3, q6, d0[1] @ 2*P3[0..7]-5*P4[0..7]+5*P5[0..7] + vrshr.s16 q8, q8, #3 + vmls.i16 q2, q9, d0[0] @ 2*P1[8..15]-5*P2[8..15]+5*P3[8..15]-2*P4[8..15] + vrshr.s16 q7, q7, #3 + vmls.i16 q10, q11, d0[0] @ 2*P5[8..15]-5*P6[8..15]+5*P7[8..15]-2*P8[8..15] + vabs.s16 q11, q15 + vabs.s16 q8, q8 @ a1[0..7] + vmla.i16 q5, q1, d0[1] @ 2*P3[8..15]-5*P4[8..15]+5*P5[8..15] + vshr.s16 q15, q15, #8 @ clip_sign[0..7] + vrshr.s16 q2, q2, #3 + vmls.i16 q3, q12, d0[0] @ 2*P3[0..7]-5*P4[0..7]+5*P5[0..7]-2*P6[0..7] + vabs.s16 q7, q7 @ a2[0..7] + vrshr.s16 q10, q10, #3 + vsub.i16 q12, q9, q1 @ P4[8..15]-P5[8..15] + vshr.s16 q11, q11, #1 @ clip[0..7] + vmls.i16 q5, q4, d0[0] @ 2*P3[8..15]-5*P4[8..15]+5*P5[8..15]-2*P6[8..15] + vcge.s16 q4, q8, q7 @ test a1[0..7] >= a2[0..7] + vabs.s16 q2, q2 @ a1[8..15] + vrshr.s16 q3, q3, #3 + vabs.s16 q10, q10 @ a2[8..15] + vbsl q4, q7, q8 @ a3[0..7] + vabs.s16 q7, q12 + vshr.s16 q8, q12, #8 @ clip_sign[8..15] + vrshr.s16 q5, q5, #3 + vcge.s16 q12, q2, q10 @ test a1[8..15] >= a2[8.15] + vshr.s16 q7, q7, #1 @ clip[8..15] + vbsl q12, q10, q2 @ a3[8..15] + vabs.s16 q2, q3 @ a0[0..7] + vceq.i16 q10, q11, #0 @ test clip[0..7] == 0 + vshr.s16 q3, q3, #8 @ a0_sign[0..7] + vsub.i16 q3, q15, q3 @ clip_sign[0..7] - a0_sign[0..7] + vcge.s16 q15, q2, q13 @ test a0[0..7] >= pq + vorr q10, q10, q15 @ test clip[0..7] == 0 || a0[0..7] >= pq + vqsub.u16 q15, q2, q4 @ a0[0..7] >= a3[0..7] ? a0[0..7]-a3[0..7] : 0 (a0 > a3 in all cases where filtering is enabled, so makes more sense to subtract this way round than the opposite and then taking the abs) + vcge.s16 q2, q4, q2 @ test a3[0..7] >= a0[0..7] + vabs.s16 q4, q5 @ a0[8..15] + vshr.s16 q5, q5, #8 @ a0_sign[8..15] + vmul.i16 q15, q15, d0[1] @ a0[0..7] >= a3[0..7] ? 5*(a0[0..7]-a3[0..7]) : 0 + vcge.s16 q13, q4, q13 @ test a0[8..15] >= pq + vorr q2, q10, q2 @ test clip[0..7] == 0 || a0[0..7] >= pq || a3[0..7] >= a0[0..7] + vsub.i16 q5, q8, q5 @ clip_sign[8..15] - a0_sign[8..15] + vceq.i16 q8, q7, #0 @ test clip[8..15] == 0 + vshr.u16 q15, q15, #3 @ a0[0..7] >= a3[0..7] ? (5*(a0[0..7]-a3[0..7]))>>3 : 0 + vmov.32 r0, d4[1] @ move to gp reg + vorr q8, q8, q13 @ test clip[8..15] == 0 || a0[8..15] >= pq + vqsub.u16 q13, q4, q12 @ a0[8..15] >= a3[8..15] ? a0[8..15]-a3[8..15] : 0 (a0 > a3 in all cases where filtering is enabled, so makes more sense to subtract this way round than the opposite and then taking the abs) + vmov.32 r2, d5[1] + vcge.s16 q4, q12, q4 @ test a3[8..15] >= a0[8..15] + vshl.i64 q2, q2, #16 + vcge.s16 q12, q15, q11 + vmul.i16 q0, q13, d0[1] @ a0[8..15] >= a3[8..15] ? 5*(a0[8..15]-a3[8..15]) : 0 + vorr q4, q8, q4 @ test clip[8..15] == 0 || a0[8..15] >= pq || a3[8..15] >= a0[8..15] + vshr.s64 q2, q2, #48 + and r0, r0, r2 + vbsl q12, q11, q15 @ FFMIN(d[0..7], clip[0..7]) + vshl.i64 q11, q4, #16 + vmov.32 r2, d8[1] + vshr.u16 q0, q0, #3 @ a0[8..15] >= a3[8..15] ? (5*(a0[8..15]-a3[8..15]))>>3 : 0 + vorr q2, q10, q2 + vmov.32 r12, d9[1] + vshr.s64 q4, q11, #48 + vcge.s16 q10, q0, q7 + vbic q2, q12, q2 @ set each d[0..7] to zero if it should not be filtered because clip[0..7] == 0 || a0[0..7] >= pq (a3 > a0 case already zeroed by saturating sub) + vorr q4, q8, q4 + and r2, r2, r12 + vbsl q10, q7, q0 @ FFMIN(d[8..15], clip[8..15]) + vmls.i16 q14, q2, q3 @ invert d[0..7] depending on clip_sign[0..7] & a0_sign[0..7], or zero it if they match, and accumulate into P4[0..7] + and r0, r0, r2 + vbic q0, q10, q4 @ set each d[8..15] to zero if it should not be filtered because clip[8..15] == 0 || a0[8..15] >= pq (a3 > a0 case already zeroed by saturating sub) + tst r0, #1 + bne 1f @ none of the 16 pixel pairs should be updated in this case + vmla.i16 q6, q2, q3 @ invert d[0..7] depending on clip_sign[0..7] & a0_sign[0..7], or zero it if they match, and accumulate into P5[0..7] + vmls.i16 q9, q0, q5 @ invert d[8..15] depending on clip_sign[8..15] & a0_sign[8..15], or zero it if they match, and accumulate into P4[8..15] + vqmovun.s16 d4, q14 + vmla.i16 q1, q0, q5 @ invert d[8..15] depending on clip_sign[8..15] & a0_sign[8..15], or zero it if they match, and accumulate into P5[8..15] + vqmovun.s16 d0, q6 + vqmovun.s16 d5, q9 + vqmovun.s16 d1, q1 + vst1.64 {q2}, [r3 :128], r1 + vst1.64 {q0}, [r3 :128] +1: vpop {d8-d15} + bx lr +endfunc + +@ VC-1 in-loop deblocking filter for 16 pixel pairs at boundary of horizontally-neighbouring blocks +@ On entry: +@ r0 -> top-left pel of right block +@ r1 = row stride, bytes +@ r2 = PQUANT bitstream parameter +function ff_vc1_h_loop_filter16_neon, export=1 + push {r4-r6,lr} + vpush {d8-d15} + sub r3, r0, #4 @ where to start reading + vldr d0, .Lcoeffs + vld1.32 {d2}, [r3], r1 @ P1[0], P2[0]... + sub r0, r0, #1 @ where to start writing + vld1.32 {d3}, [r3], r1 + add r4, r0, r1, lsl #2 + vld1.32 {d10}, [r3], r1 + vld1.32 {d11}, [r3], r1 + vld1.32 {d16}, [r3], r1 + vld1.32 {d4}, [r3], r1 + vld1.32 {d8}, [r3], r1 + vtrn.8 d2, d3 @ P1[0], P1[1], P3[0]... P2[0], P2[1], P4[0]... + vld1.32 {d14}, [r3], r1 + vld1.32 {d5}, [r3], r1 + vtrn.8 d10, d11 @ P1[2], P1[3], P3[2]... P2[2], P2[3], P4[2]... + vld1.32 {d6}, [r3], r1 + vld1.32 {d12}, [r3], r1 + vtrn.8 d16, d4 @ P1[4], P1[5], P3[4]... P2[4], P2[5], P4[4]... + vld1.32 {d13}, [r3], r1 + vtrn.16 d2, d10 @ P1[0], P1[1], P1[2], P1[3], P5[0]... P3[0], P3[1], P3[2], P3[3], P7[0]... + vld1.32 {d1}, [r3], r1 + vtrn.8 d8, d14 @ P1[6], P1[7], P3[6]... P2[6], P2[7], P4[6]... + vld1.32 {d7}, [r3], r1 + vtrn.16 d3, d11 @ P2[0], P2[1], P2[2], P2[3], P6[0]... P4[0], P4[1], P4[2], P4[3], P8[0]... + vld1.32 {d9}, [r3], r1 + vtrn.8 d5, d6 @ P1[8], P1[9], P3[8]... P2[8], P2[9], P4[8]... + vld1.32 {d15}, [r3] + vtrn.16 d16, d8 @ P1[4], P1[5], P1[6], P1[7], P5[4]... P3[4], P3[5], P3[6], P3[7], P7[4]... + vtrn.16 d4, d14 @ P2[4], P2[5], P2[6], P2[7], P6[4]... P4[4], P4[5], P4[6], P4[7], P8[4]... + vtrn.8 d12, d13 @ P1[10], P1[11], P3[10]... P2[10], P2[11], P4[10]... + vdup.16 q9, r2 @ pq + vtrn.8 d1, d7 @ P1[12], P1[13], P3[12]... P2[12], P2[13], P4[12]... + vtrn.32 d2, d16 @ P1[0..7], P5[0..7] + vtrn.16 d5, d12 @ P1[8], P1[7], P1[10], P1[11], P5[8]... P3[8], P3[9], P3[10], P3[11], P7[8]... + vtrn.16 d6, d13 @ P2[8], P2[7], P2[10], P2[11], P6[8]... P4[8], P4[9], P4[10], P4[11], P8[8]... + vtrn.8 d9, d15 @ P1[14], P1[15], P3[14]... P2[14], P2[15], P4[14]... + vtrn.32 d3, d4 @ P2[0..7], P6[0..7] + vshll.u8 q10, d2, #1 @ 2*P1[0..7] + vtrn.32 d10, d8 @ P3[0..7], P7[0..7] + vshll.u8 q11, d16, #1 @ 2*P5[0..7] + vtrn.32 d11, d14 @ P4[0..7], P8[0..7] + vtrn.16 d1, d9 @ P1[12], P1[13], P1[14], P1[15], P5[12]... P3[12], P3[13], P3[14], P3[15], P7[12]... + vtrn.16 d7, d15 @ P2[12], P2[13], P2[14], P2[15], P6[12]... P4[12], P4[13], P4[14], P4[15], P8[12]... + vmovl.u8 q1, d3 @ P2[0..7] + vmovl.u8 q12, d4 @ P6[0..7] + vtrn.32 d5, d1 @ P1[8..15], P5[8..15] + vtrn.32 d6, d7 @ P2[8..15], P6[8..15] + vtrn.32 d12, d9 @ P3[8..15], P7[8..15] + vtrn.32 d13, d15 @ P4[8..15], P8[8..15] + vmls.i16 q10, q1, d0[1] @ 2*P1[0..7]-5*P2[0..7] + vmovl.u8 q1, d10 @ P3[0..7] + vshll.u8 q2, d5, #1 @ 2*P1[8..15] + vshll.u8 q13, d1, #1 @ 2*P5[8..15] + vmls.i16 q11, q12, d0[1] @ 2*P5[0..7]-5*P6[0..7] + vmovl.u8 q14, d6 @ P2[8..15] + vmovl.u8 q3, d7 @ P6[8..15] + vmovl.u8 q15, d8 @ P7[0..7] + vmla.i16 q10, q1, d0[1] @ 2*P1[0..7]-5*P2[0..7]+5*P3[0..7] + vmovl.u8 q1, d12 @ P3[8..15] + vmls.i16 q2, q14, d0[1] @ 2*P1[8..15]-5*P2[8..15] + vmovl.u8 q4, d9 @ P7[8..15] + vshll.u8 q14, d10, #1 @ 2*P3[0..7] + vmls.i16 q13, q3, d0[1] @ 2*P5[8..15]-5*P6[8..15] + vmovl.u8 q5, d11 @ P4[0..7] + vmla.i16 q11, q15, d0[1] @ 2*P5[0..7]-5*P6[0..7]+5*P7[0..7] + vshll.u8 q15, d12, #1 @ 2*P3[8..15] + vmovl.u8 q6, d13 @ P4[8..15] + vmla.i16 q2, q1, d0[1] @ 2*P1[8..15]-5*P2[8..15]+5*P3[8..15] + vmovl.u8 q1, d14 @ P8[0..7] + vmovl.u8 q7, d15 @ P8[8..15] + vmla.i16 q13, q4, d0[1] @ 2*P5[8..15]-5*P6[8..15]+5*P7[8..15] + vmovl.u8 q4, d16 @ P5[0..7] + vmovl.u8 q8, d1 @ P5[8..15] + vmls.i16 q14, q5, d0[1] @ 2*P3[0..7]-5*P4[0..7] + vmls.i16 q15, q6, d0[1] @ 2*P3[8..15]-5*P4[8..15] + vmls.i16 q10, q5, d0[0] @ 2*P1[0..7]-5*P2[0..7]+5*P3[0..7]-2*P4[0..7] + vmls.i16 q11, q1, d0[0] @ 2*P5[0..7]-5*P6[0..7]+5*P7[0..7]-2*P8[0..7] + vsub.i16 q1, q5, q4 @ P4[0..7]-P5[0..7] + vmls.i16 q2, q6, d0[0] @ 2*P1[8..15]-5*P2[8..15]+5*P3[8..15]-2*P4[8..15] + vrshr.s16 q10, q10, #3 + vmls.i16 q13, q7, d0[0] @ 2*P5[8..15]-5*P6[8..15]+5*P7[8..15]-2*P8[8..15] + vsub.i16 q7, q6, q8 @ P4[8..15]-P5[8..15] + vrshr.s16 q11, q11, #3 + vmla.s16 q14, q4, d0[1] @ 2*P3[0..7]-5*P4[0..7]+5*P5[0..7] + vrshr.s16 q2, q2, #3 + vmla.i16 q15, q8, d0[1] @ 2*P3[8..15]-5*P4[8..15]+5*P5[8..15] + vabs.s16 q10, q10 @ a1[0..7] + vrshr.s16 q13, q13, #3 + vmls.i16 q15, q3, d0[0] @ 2*P3[8..15]-5*P4[8..15]+5*P5[8..15]-2*P6[8..15] + vabs.s16 q3, q11 @ a2[0..7] + vabs.s16 q2, q2 @ a1[8..15] + vmls.i16 q14, q12, d0[0] @ 2*P3[0..7]-5*P4[0..7]+5*P5[0..7]-2*P6[0..7] + vabs.s16 q11, q1 + vabs.s16 q12, q13 @ a2[8..15] + vcge.s16 q13, q10, q3 @ test a1[0..7] >= a2[0..7] + vshr.s16 q1, q1, #8 @ clip_sign[0..7] + vrshr.s16 q15, q15, #3 + vshr.s16 q11, q11, #1 @ clip[0..7] + vrshr.s16 q14, q14, #3 + vbsl q13, q3, q10 @ a3[0..7] + vcge.s16 q3, q2, q12 @ test a1[8..15] >= a2[8.15] + vabs.s16 q10, q15 @ a0[8..15] + vshr.s16 q15, q15, #8 @ a0_sign[8..15] + vbsl q3, q12, q2 @ a3[8..15] + vabs.s16 q2, q14 @ a0[0..7] + vabs.s16 q12, q7 + vshr.s16 q7, q7, #8 @ clip_sign[8..15] + vshr.s16 q14, q14, #8 @ a0_sign[0..7] + vshr.s16 q12, q12, #1 @ clip[8..15] + vsub.i16 q7, q7, q15 @ clip_sign[8..15] - a0_sign[8..15] + vqsub.u16 q15, q10, q3 @ a0[8..15] >= a3[8..15] ? a0[8..15]-a3[8..15] : 0 (a0 > a3 in all cases where filtering is enabled, so makes more sense to subtract this way round than the opposite and then taking the abs) + vcge.s16 q3, q3, q10 @ test a3[8..15] >= a0[8..15] + vcge.s16 q10, q10, q9 @ test a0[8..15] >= pq + vcge.s16 q9, q2, q9 @ test a0[0..7] >= pq + vsub.i16 q1, q1, q14 @ clip_sign[0..7] - a0_sign[0..7] + vqsub.u16 q14, q2, q13 @ a0[0..7] >= a3[0..7] ? a0[0..7]-a3[0..7] : 0 (a0 > a3 in all cases where filtering is enabled, so makes more sense to subtract this way round than the opposite and then taking the abs) + vcge.s16 q2, q13, q2 @ test a3[0..7] >= a0[0..7] + vmul.i16 q13, q15, d0[1] @ a0[8..15] >= a3[8..15] ? 5*(a0[8..15]-a3[8..15]) : 0 + vceq.i16 q15, q11, #0 @ test clip[0..7] == 0 + vmul.i16 q0, q14, d0[1] @ a0[0..7] >= a3[0..7] ? 5*(a0[0..7]-a3[0..7]) : 0 + vorr q9, q15, q9 @ test clip[0..7] == 0 || a0[0..7] >= pq + vceq.i16 q14, q12, #0 @ test clip[8..15] == 0 + vshr.u16 q13, q13, #3 @ a0[8..15] >= a3[8..15] ? (5*(a0[8..15]-a3[8..15]))>>3 : 0 + vorr q2, q9, q2 @ test clip[0..7] == 0 || a0[0..7] >= pq || a3[0..7] >= a0[0..7] + vshr.u16 q0, q0, #3 @ a0[0..7] >= a3[0..7] ? (5*(a0[0..7]-a3[0..7]))>>3 : 0 + vorr q10, q14, q10 @ test clip[8..15] == 0 || a0[8..15] >= pq + vcge.s16 q14, q13, q12 + vmov.32 r2, d4[1] @ move to gp reg + vorr q3, q10, q3 @ test clip[8..15] == 0 || a0[8..15] >= pq || a3[8..15] >= a0[8..15] + vmov.32 r3, d5[1] + vcge.s16 q2, q0, q11 + vbsl q14, q12, q13 @ FFMIN(d[8..15], clip[8..15]) + vbsl q2, q11, q0 @ FFMIN(d[0..7], clip[0..7]) + vmov.32 r5, d6[1] + vbic q0, q14, q10 @ set each d[8..15] to zero if it should not be filtered because clip[8..15] == 0 || a0[8..15] >= pq (a3 > a0 case already zeroed by saturating sub) + vmov.32 r6, d7[1] + and r12, r2, r3 + vbic q2, q2, q9 @ set each d[0..7] to zero if it should not be filtered because clip[0..7] == 0 || a0[0..7] >= pq (a3 > a0 case already zeroed by saturating sub) + vmls.i16 q6, q0, q7 @ invert d[8..15] depending on clip_sign[8..15] & a0_sign[8..15], or zero it if they match, and accumulate into P4 + vmls.i16 q5, q2, q1 @ invert d[0..7] depending on clip_sign[0..7] & a0_sign[0..7], or zero it if they match, and accumulate into P4 + and r14, r5, r6 + vmla.i16 q4, q2, q1 @ invert d[0..7] depending on clip_sign[0..7] & a0_sign[0..7], or zero it if they match, and accumulate into P5 + and r12, r12, r14 + vqmovun.s16 d4, q6 + vmla.i16 q8, q0, q7 @ invert d[8..15] depending on clip_sign[8..15] & a0_sign[8..15], or zero it if they match, and accumulate into P5 + tst r12, #1 + bne 4f @ none of the 16 pixel pairs should be updated in this case + vqmovun.s16 d2, q5 + vqmovun.s16 d3, q4 + vqmovun.s16 d5, q8 + tst r2, #1 + bne 1f + vst2.8 {d2[0], d3[0]}, [r0], r1 + vst2.8 {d2[1], d3[1]}, [r0], r1 + vst2.8 {d2[2], d3[2]}, [r0], r1 + vst2.8 {d2[3], d3[3]}, [r0] +1: add r0, r4, r1, lsl #2 + tst r3, #1 + bne 2f + vst2.8 {d2[4], d3[4]}, [r4], r1 + vst2.8 {d2[5], d3[5]}, [r4], r1 + vst2.8 {d2[6], d3[6]}, [r4], r1 + vst2.8 {d2[7], d3[7]}, [r4] +2: add r4, r0, r1, lsl #2 + tst r5, #1 + bne 3f + vst2.8 {d4[0], d5[0]}, [r0], r1 + vst2.8 {d4[1], d5[1]}, [r0], r1 + vst2.8 {d4[2], d5[2]}, [r0], r1 + vst2.8 {d4[3], d5[3]}, [r0] +3: tst r6, #1 + bne 4f + vst2.8 {d4[4], d5[4]}, [r4], r1 + vst2.8 {d4[5], d5[5]}, [r4], r1 + vst2.8 {d4[6], d5[6]}, [r4], r1 + vst2.8 {d4[7], d5[7]}, [r4] +4: vpop {d8-d15} + pop {r4-r6,pc} +endfunc + +@ Copy at most the specified number of bytes from source to destination buffer, +@ stopping at a multiple of 16 bytes, none of which are the start of an escape sequence +@ On entry: +@ r0 -> source buffer +@ r1 = max number of bytes to copy +@ r2 -> destination buffer, optimally 8-byte aligned +@ On exit: +@ r0 = number of bytes not copied +function ff_vc1_unescape_buffer_helper_neon, export=1 + @ Offset by 48 to screen out cases that are too short for us to handle, + @ and also make it easy to test for loop termination, or to determine + @ whether we need an odd number of half-iterations of the loop. + subs r1, r1, #48 + bmi 90f + + @ Set up useful constants + vmov.i32 q0, #0x3000000 + vmov.i32 q1, #0x30000 + + tst r1, #16 + bne 1f + + vld1.8 {q8, q9}, [r0]! + vbic q12, q8, q0 + vext.8 q13, q8, q9, #1 + vext.8 q14, q8, q9, #2 + vext.8 q15, q8, q9, #3 + veor q12, q12, q1 + vbic q13, q13, q0 + vbic q14, q14, q0 + vbic q15, q15, q0 + vceq.i32 q12, q12, #0 + veor q13, q13, q1 + veor q14, q14, q1 + veor q15, q15, q1 + vceq.i32 q13, q13, #0 + vceq.i32 q14, q14, #0 + vceq.i32 q15, q15, #0 + add r1, r1, #16 + b 3f + +1: vld1.8 {q10, q11}, [r0]! + vbic q12, q10, q0 + vext.8 q13, q10, q11, #1 + vext.8 q14, q10, q11, #2 + vext.8 q15, q10, q11, #3 + veor q12, q12, q1 + vbic q13, q13, q0 + vbic q14, q14, q0 + vbic q15, q15, q0 + vceq.i32 q12, q12, #0 + veor q13, q13, q1 + veor q14, q14, q1 + veor q15, q15, q1 + vceq.i32 q13, q13, #0 + vceq.i32 q14, q14, #0 + vceq.i32 q15, q15, #0 + @ Drop through... +2: vmov q8, q11 + vld1.8 {q9}, [r0]! + vorr q13, q12, q13 + vorr q15, q14, q15 + vbic q12, q8, q0 + vorr q3, q13, q15 + vext.8 q13, q8, q9, #1 + vext.8 q14, q8, q9, #2 + vext.8 q15, q8, q9, #3 + veor q12, q12, q1 + vorr d6, d6, d7 + vbic q13, q13, q0 + vbic q14, q14, q0 + vbic q15, q15, q0 + vceq.i32 q12, q12, #0 + vmov r3, r12, d6 + veor q13, q13, q1 + veor q14, q14, q1 + veor q15, q15, q1 + vceq.i32 q13, q13, #0 + vceq.i32 q14, q14, #0 + vceq.i32 q15, q15, #0 + orrs r3, r3, r12 + bne 90f + vst1.64 {q10}, [r2]! +3: vmov q10, q9 + vld1.8 {q11}, [r0]! + vorr q13, q12, q13 + vorr q15, q14, q15 + vbic q12, q10, q0 + vorr q3, q13, q15 + vext.8 q13, q10, q11, #1 + vext.8 q14, q10, q11, #2 + vext.8 q15, q10, q11, #3 + veor q12, q12, q1 + vorr d6, d6, d7 + vbic q13, q13, q0 + vbic q14, q14, q0 + vbic q15, q15, q0 + vceq.i32 q12, q12, #0 + vmov r3, r12, d6 + veor q13, q13, q1 + veor q14, q14, q1 + veor q15, q15, q1 + vceq.i32 q13, q13, #0 + vceq.i32 q14, q14, #0 + vceq.i32 q15, q15, #0 + orrs r3, r3, r12 + bne 91f + vst1.64 {q8}, [r2]! + subs r1, r1, #32 + bpl 2b + +90: add r0, r1, #48 + bx lr + +91: sub r1, r1, #16 + b 90b +endfunc diff --git a/libavcodec/ass.c b/libavcodec/ass.c index 725e4d42b..a1e560d7f 100644 --- a/libavcodec/ass.c +++ b/libavcodec/ass.c @@ -114,17 +114,34 @@ char *ff_ass_get_dialog(int readorder, int layer, const char *style, speaker ? speaker : "", text); } -int ff_ass_add_rect(AVSubtitle *sub, const char *dialog, +int ff_ass_add_rect2(AVSubtitle *sub, const char *dialog, int readorder, int layer, const char *style, - const char *speaker) + const char *speaker, unsigned *nb_rect_allocated) { - AVSubtitleRect **rects, *rect; + AVSubtitleRect **rects = sub->rects, *rect; char *ass_str; + uint64_t new_nb = 0; - rects = av_realloc_array(sub->rects, sub->num_rects+1, sizeof(*sub->rects)); - if (!rects) + if (sub->num_rects >= UINT_MAX) return AVERROR(ENOMEM); - sub->rects = rects; + + if (nb_rect_allocated && *nb_rect_allocated <= sub->num_rects) { + if (sub->num_rects < UINT_MAX / 17 * 16) { + new_nb = sub->num_rects + sub->num_rects/16 + 1; + } else + new_nb = UINT_MAX; + } else if (!nb_rect_allocated) + new_nb = sub->num_rects + 1; + + if (new_nb) { + rects = av_realloc_array(rects, new_nb, sizeof(*sub->rects)); + if (!rects) + return AVERROR(ENOMEM); + if (nb_rect_allocated) + *nb_rect_allocated = new_nb; + sub->rects = rects; + } + rect = av_mallocz(sizeof(*rect)); if (!rect) return AVERROR(ENOMEM); @@ -137,6 +154,13 @@ int ff_ass_add_rect(AVSubtitle *sub, const char *dialog, return 0; } +int ff_ass_add_rect(AVSubtitle *sub, const char *dialog, + int readorder, int layer, const char *style, + const char *speaker) +{ + return ff_ass_add_rect2(sub, dialog, readorder, layer, style, speaker, NULL); +} + void ff_ass_decoder_flush(AVCodecContext *avctx) { FFASSDecoderContext *s = avctx->priv_data; diff --git a/libavcodec/ass.h b/libavcodec/ass.h index 2c260e4e7..4dffe923d 100644 --- a/libavcodec/ass.h +++ b/libavcodec/ass.h @@ -118,6 +118,13 @@ int ff_ass_add_rect(AVSubtitle *sub, const char *dialog, int readorder, int layer, const char *style, const char *speaker); +/** + * Add an ASS dialog to a subtitle. + */ +int ff_ass_add_rect2(AVSubtitle *sub, const char *dialog, + int readorder, int layer, const char *style, + const char *speaker, unsigned *nb_rect_allocated); + /** * Helper to flush a text subtitles decoder making use of the * FFASSDecoderContext. diff --git a/libavcodec/ass_split.c b/libavcodec/ass_split.c index 05c5453e5..73ef6196c 100644 --- a/libavcodec/ass_split.c +++ b/libavcodec/ass_split.c @@ -19,8 +19,14 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/common.h" +#include +#include +#include +#include +#include + #include "libavutil/error.h" +#include "libavutil/macros.h" #include "libavutil/mem.h" #include "ass_split.h" diff --git a/libavcodec/assdec.c b/libavcodec/assdec.c index 319279490..f43b500aa 100644 --- a/libavcodec/assdec.c +++ b/libavcodec/assdec.c @@ -23,7 +23,8 @@ #include "avcodec.h" #include "ass.h" -#include "internal.h" +#include "codec_internal.h" +#include "config_components.h" #include "libavutil/internal.h" #include "libavutil/mem.h" @@ -39,11 +40,9 @@ static av_cold int ass_decode_init(AVCodecContext *avctx) return 0; } -static int ass_decode_frame(AVCodecContext *avctx, void *data, int *got_sub_ptr, - AVPacket *avpkt) +static int ass_decode_frame(AVCodecContext *avctx, AVSubtitle *sub, + int *got_sub_ptr, const AVPacket *avpkt) { - AVSubtitle *sub = data; - if (avpkt->size <= 0) return avpkt->size; @@ -63,25 +62,25 @@ static int ass_decode_frame(AVCodecContext *avctx, void *data, int *got_sub_ptr, } #if CONFIG_SSA_DECODER -const AVCodec ff_ssa_decoder = { - .name = "ssa", - .long_name = NULL_IF_CONFIG_SMALL("ASS (Advanced SubStation Alpha) subtitle"), - .type = AVMEDIA_TYPE_SUBTITLE, - .id = AV_CODEC_ID_ASS, +const FFCodec ff_ssa_decoder = { + .p.name = "ssa", + .p.long_name = NULL_IF_CONFIG_SMALL("ASS (Advanced SubStation Alpha) subtitle"), + .p.type = AVMEDIA_TYPE_SUBTITLE, + .p.id = AV_CODEC_ID_ASS, .init = ass_decode_init, - .decode = ass_decode_frame, + FF_CODEC_DECODE_SUB_CB(ass_decode_frame), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_ASS_DECODER -const AVCodec ff_ass_decoder = { - .name = "ass", - .long_name = NULL_IF_CONFIG_SMALL("ASS (Advanced SubStation Alpha) subtitle"), - .type = AVMEDIA_TYPE_SUBTITLE, - .id = AV_CODEC_ID_ASS, +const FFCodec ff_ass_decoder = { + .p.name = "ass", + .p.long_name = NULL_IF_CONFIG_SMALL("ASS (Advanced SubStation Alpha) subtitle"), + .p.type = AVMEDIA_TYPE_SUBTITLE, + .p.id = AV_CODEC_ID_ASS, .init = ass_decode_init, - .decode = ass_decode_frame, + FF_CODEC_DECODE_SUB_CB(ass_decode_frame), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif diff --git a/libavcodec/assenc.c b/libavcodec/assenc.c index a6d107ded..2ac40d5af 100644 --- a/libavcodec/assenc.c +++ b/libavcodec/assenc.c @@ -19,11 +19,13 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include #include "avcodec.h" #include "ass.h" -#include "internal.h" +#include "codec_internal.h" #include "libavutil/avstring.h" #include "libavutil/internal.h" #include "libavutil/mem.h" @@ -67,25 +69,25 @@ static int ass_encode_frame(AVCodecContext *avctx, } #if CONFIG_SSA_ENCODER -const AVCodec ff_ssa_encoder = { - .name = "ssa", - .long_name = NULL_IF_CONFIG_SMALL("ASS (Advanced SubStation Alpha) subtitle"), - .type = AVMEDIA_TYPE_SUBTITLE, - .id = AV_CODEC_ID_ASS, +const FFCodec ff_ssa_encoder = { + .p.name = "ssa", + .p.long_name = NULL_IF_CONFIG_SMALL("ASS (Advanced SubStation Alpha) subtitle"), + .p.type = AVMEDIA_TYPE_SUBTITLE, + .p.id = AV_CODEC_ID_ASS, .init = ass_encode_init, - .encode_sub = ass_encode_frame, + FF_CODEC_ENCODE_SUB_CB(ass_encode_frame), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_ASS_ENCODER -const AVCodec ff_ass_encoder = { - .name = "ass", - .long_name = NULL_IF_CONFIG_SMALL("ASS (Advanced SubStation Alpha) subtitle"), - .type = AVMEDIA_TYPE_SUBTITLE, - .id = AV_CODEC_ID_ASS, +const FFCodec ff_ass_encoder = { + .p.name = "ass", + .p.long_name = NULL_IF_CONFIG_SMALL("ASS (Advanced SubStation Alpha) subtitle"), + .p.type = AVMEDIA_TYPE_SUBTITLE, + .p.id = AV_CODEC_ID_ASS, .init = ass_encode_init, - .encode_sub = ass_encode_frame, + FF_CODEC_ENCODE_SUB_CB(ass_encode_frame), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif diff --git a/libavcodec/asvdec.c b/libavcodec/asvdec.c index 60a4e138c..57ba4c5b5 100644 --- a/libavcodec/asvdec.c +++ b/libavcodec/asvdec.c @@ -30,6 +30,8 @@ #include "asv.h" #include "avcodec.h" #include "blockdsp.h" +#include "codec_internal.h" +#include "config_components.h" #include "idctdsp.h" #include "internal.h" #include "mpeg12data.h" @@ -76,7 +78,7 @@ static inline int asv1_get_level(GetBitContext *gb) } // get_vlc2() is big-endian in this file -static inline int asv2_get_vlc2(GetBitContext *gb, VLC_TYPE (*table)[2], int bits) +static inline int asv2_get_vlc2(GetBitContext *gb, const VLCElem *table, int bits) { unsigned int index; int code, n; @@ -85,8 +87,8 @@ static inline int asv2_get_vlc2(GetBitContext *gb, VLC_TYPE (*table)[2], int bit UPDATE_CACHE_LE(re, gb); index = SHOW_UBITS_LE(re, gb, bits); - code = table[index][0]; - n = table[index][1]; + code = table[index].sym; + n = table[index].len; LAST_SKIP_BITS(re, gb, n); CLOSE_READER(re, gb); @@ -211,13 +213,12 @@ static inline void idct_put(ASV1Context *a, AVFrame *frame, int mb_x, int mb_y) } } -static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *p, + int *got_frame, AVPacket *avpkt) { ASV1Context *const a = avctx->priv_data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; - AVFrame *const p = data; int mb_x, mb_y, ret; if (buf_size * 8LL < a->mb_height * a->mb_width * 13LL) @@ -327,30 +328,30 @@ static av_cold int decode_end(AVCodecContext *avctx) } #if CONFIG_ASV1_DECODER -const AVCodec ff_asv1_decoder = { - .name = "asv1", - .long_name = NULL_IF_CONFIG_SMALL("ASUS V1"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_ASV1, +const FFCodec ff_asv1_decoder = { + .p.name = "asv1", + .p.long_name = NULL_IF_CONFIG_SMALL("ASUS V1"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_ASV1, .priv_data_size = sizeof(ASV1Context), .init = decode_init, .close = decode_end, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_ASV2_DECODER -const AVCodec ff_asv2_decoder = { - .name = "asv2", - .long_name = NULL_IF_CONFIG_SMALL("ASUS V2"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_ASV2, +const FFCodec ff_asv2_decoder = { + .p.name = "asv2", + .p.long_name = NULL_IF_CONFIG_SMALL("ASUS V2"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_ASV2, .priv_data_size = sizeof(ASV1Context), .init = decode_init, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif diff --git a/libavcodec/asvenc.c b/libavcodec/asvenc.c index ff96338e8..520173e6c 100644 --- a/libavcodec/asvenc.c +++ b/libavcodec/asvenc.c @@ -23,16 +23,18 @@ * ASUS V1/V2 encoder. */ +#include "config_components.h" + #include "libavutil/attributes.h" #include "libavutil/mem.h" #include "aandcttab.h" #include "asv.h" #include "avcodec.h" +#include "codec_internal.h" #include "dct.h" #include "encode.h" #include "fdctdsp.h" -#include "internal.h" #include "mpeg12data.h" static inline void asv1_put_level(PutBitContext *pb, int level) @@ -341,30 +343,30 @@ static av_cold int encode_init(AVCodecContext *avctx) } #if CONFIG_ASV1_ENCODER -const AVCodec ff_asv1_encoder = { - .name = "asv1", - .long_name = NULL_IF_CONFIG_SMALL("ASUS V1"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_ASV1, +const FFCodec ff_asv1_encoder = { + .p.name = "asv1", + .p.long_name = NULL_IF_CONFIG_SMALL("ASUS V1"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_ASV1, .priv_data_size = sizeof(ASV1Context), .init = encode_init, - .encode2 = encode_frame, - .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, + FF_CODEC_ENCODE_CB(encode_frame), + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_ASV2_ENCODER -const AVCodec ff_asv2_encoder = { - .name = "asv2", - .long_name = NULL_IF_CONFIG_SMALL("ASUS V2"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_ASV2, +const FFCodec ff_asv2_encoder = { + .p.name = "asv2", + .p.long_name = NULL_IF_CONFIG_SMALL("ASUS V2"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_ASV2, .priv_data_size = sizeof(ASV1Context), .init = encode_init, - .encode2 = encode_frame, - .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, + FF_CODEC_ENCODE_CB(encode_frame), + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/atrac1.c b/libavcodec/atrac1.c index 228477d77..7265891ac 100644 --- a/libavcodec/atrac1.c +++ b/libavcodec/atrac1.c @@ -36,6 +36,7 @@ #include "libavutil/mem_internal.h" #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" #include "fft.h" #include "internal.h" @@ -272,18 +273,18 @@ static void at1_subband_synthesis(AT1Ctx *q, AT1SUCtx* su, float *pOut) } -static int atrac1_decode_frame(AVCodecContext *avctx, void *data, +static int atrac1_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; AT1Ctx *q = avctx->priv_data; + int channels = avctx->ch_layout.nb_channels; int ch, ret; GetBitContext gb; - if (buf_size < 212 * avctx->channels) { + if (buf_size < 212 * channels) { av_log(avctx, AV_LOG_ERROR, "Not enough data to decode!\n"); return AVERROR_INVALIDDATA; } @@ -293,7 +294,7 @@ static int atrac1_decode_frame(AVCodecContext *avctx, void *data, if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; - for (ch = 0; ch < avctx->channels; ch++) { + for (ch = 0; ch < channels; ch++) { AT1SUCtx* su = &q->SUs[ch]; init_get_bits(&gb, &buf[212 * ch], 212 * 8); @@ -335,13 +336,14 @@ static av_cold int atrac1_decode_init(AVCodecContext *avctx) { AT1Ctx *q = avctx->priv_data; AVFloatDSPContext *fdsp; + int channels = avctx->ch_layout.nb_channels; int ret; avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; - if (avctx->channels < 1 || avctx->channels > AT1_MAX_CHANNELS) { + if (channels < 1 || channels > AT1_MAX_CHANNELS) { av_log(avctx, AV_LOG_ERROR, "Unsupported number of channels: %d\n", - avctx->channels); + channels); return AVERROR(EINVAL); } @@ -382,17 +384,17 @@ static av_cold int atrac1_decode_init(AVCodecContext *avctx) } -const AVCodec ff_atrac1_decoder = { - .name = "atrac1", - .long_name = NULL_IF_CONFIG_SMALL("ATRAC1 (Adaptive TRansform Acoustic Coding)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_ATRAC1, +const FFCodec ff_atrac1_decoder = { + .p.name = "atrac1", + .p.long_name = NULL_IF_CONFIG_SMALL("ATRAC1 (Adaptive TRansform Acoustic Coding)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_ATRAC1, .priv_data_size = sizeof(AT1Ctx), .init = atrac1_decode_init, .close = atrac1_decode_end, - .decode = atrac1_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + FF_CODEC_DECODE_CB(atrac1_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/atrac3.c b/libavcodec/atrac3.c index 2376a7cd0..d5f6fea4d 100644 --- a/libavcodec/atrac3.c +++ b/libavcodec/atrac3.c @@ -44,6 +44,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "fft.h" #include "get_bits.h" #include "internal.h" @@ -121,7 +122,7 @@ typedef struct ATRAC3Context { } ATRAC3Context; static DECLARE_ALIGNED(32, float, mdct_window)[MDCT_SIZE]; -static VLC_TYPE atrac3_vlc_table[7 * 1 << ATRAC3_VLC_BITS][2]; +static VLCElem atrac3_vlc_table[7 * 1 << ATRAC3_VLC_BITS]; static VLC spectral_coeff_tab[7]; /** @@ -646,6 +647,7 @@ static int decode_frame(AVCodecContext *avctx, const uint8_t *databuf, ATRAC3Context *q = avctx->priv_data; int ret, i, ch; uint8_t *ptr1; + int channels = avctx->ch_layout.nb_channels; if (q->coding_mode == JOINT_STEREO) { /* channel coupling mode */ @@ -655,9 +657,9 @@ static int decode_frame(AVCodecContext *avctx, const uint8_t *databuf, const uint8_t *js_databuf; int js_pair, js_block_align; - js_block_align = (avctx->block_align / avctx->channels) * 2; /* block pair */ + js_block_align = (avctx->block_align / channels) * 2; /* block pair */ - for (ch = 0; ch < avctx->channels; ch = ch + 2) { + for (ch = 0; ch < channels; ch = ch + 2) { js_pair = ch/2; js_databuf = databuf + js_pair * js_block_align; /* align to current pair */ @@ -726,11 +728,11 @@ static int decode_frame(AVCodecContext *avctx, const uint8_t *databuf, } else { /* single channels */ /* Decode the channel sound units. */ - for (i = 0; i < avctx->channels; i++) { + for (i = 0; i < channels; i++) { /* Set the bitstream reader at the start of a channel sound unit. */ init_get_bits(&q->gb, - databuf + i * avctx->block_align / avctx->channels, - avctx->block_align * 8 / avctx->channels); + databuf + i * avctx->block_align / channels, + avctx->block_align * 8 / channels); ret = decode_channel_sound_unit(q, &q->gb, &q->units[i], out_samples[i], i, q->coding_mode); @@ -740,7 +742,7 @@ static int decode_frame(AVCodecContext *avctx, const uint8_t *databuf, } /* Apply the iQMF synthesis filter. */ - for (i = 0; i < avctx->channels; i++) { + for (i = 0; i < channels; i++) { float *p1 = out_samples[i]; float *p2 = p1 + 256; float *p3 = p2 + 256; @@ -757,24 +759,25 @@ static int al_decode_frame(AVCodecContext *avctx, const uint8_t *databuf, int size, float **out_samples) { ATRAC3Context *q = avctx->priv_data; + int channels = avctx->ch_layout.nb_channels; int ret, i; /* Set the bitstream reader at the start of a channel sound unit. */ init_get_bits(&q->gb, databuf, size * 8); /* single channels */ /* Decode the channel sound units. */ - for (i = 0; i < avctx->channels; i++) { + for (i = 0; i < channels; i++) { ret = decode_channel_sound_unit(q, &q->gb, &q->units[i], out_samples[i], i, q->coding_mode); if (ret != 0) return ret; - while (i < avctx->channels && get_bits_left(&q->gb) > 6 && show_bits(&q->gb, 6) != 0x28) { + while (i < channels && get_bits_left(&q->gb) > 6 && show_bits(&q->gb, 6) != 0x28) { skip_bits(&q->gb, 1); } } /* Apply the iQMF synthesis filter. */ - for (i = 0; i < avctx->channels; i++) { + for (i = 0; i < channels; i++) { float *p1 = out_samples[i]; float *p2 = p1 + 256; float *p3 = p2 + 256; @@ -787,10 +790,9 @@ static int al_decode_frame(AVCodecContext *avctx, const uint8_t *databuf, return 0; } -static int atrac3_decode_frame(AVCodecContext *avctx, void *data, +static int atrac3_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; ATRAC3Context *q = avctx->priv_data; @@ -827,10 +829,9 @@ static int atrac3_decode_frame(AVCodecContext *avctx, void *data, return avctx->block_align; } -static int atrac3al_decode_frame(AVCodecContext *avctx, void *data, +static int atrac3al_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; int ret; frame->nb_samples = SAMPLES_PER_FRAME; @@ -851,7 +852,7 @@ static int atrac3al_decode_frame(AVCodecContext *avctx, void *data, static av_cold void atrac3_init_static_data(void) { - VLC_TYPE (*table)[2] = atrac3_vlc_table; + VLCElem *table = atrac3_vlc_table; const uint8_t (*hufftabs)[2] = atrac3_hufftabs; int i; @@ -879,8 +880,9 @@ static av_cold int atrac3_decode_init(AVCodecContext *avctx) const uint8_t *edata_ptr = avctx->extradata; ATRAC3Context *q = avctx->priv_data; AVFloatDSPContext *fdsp; + int channels = avctx->ch_layout.nb_channels; - if (avctx->channels < MIN_CHANNELS || avctx->channels > MAX_CHANNELS) { + if (channels < MIN_CHANNELS || channels > MAX_CHANNELS) { av_log(avctx, AV_LOG_ERROR, "Channel configuration error!\n"); return AVERROR(EINVAL); } @@ -888,7 +890,7 @@ static av_cold int atrac3_decode_init(AVCodecContext *avctx) /* Take care of the codec-specific extradata. */ if (avctx->codec_id == AV_CODEC_ID_ATRAC3AL) { version = 4; - samples_per_frame = SAMPLES_PER_FRAME * avctx->channels; + samples_per_frame = SAMPLES_PER_FRAME * channels; delay = 0x88E; q->coding_mode = SINGLE; } else if (avctx->extradata_size == 14) { @@ -904,18 +906,18 @@ static av_cold int atrac3_decode_init(AVCodecContext *avctx) bytestream_get_le16(&edata_ptr)); // Unknown always 0 /* setup */ - samples_per_frame = SAMPLES_PER_FRAME * avctx->channels; + samples_per_frame = SAMPLES_PER_FRAME * channels; version = 4; delay = 0x88E; q->coding_mode = q->coding_mode ? JOINT_STEREO : SINGLE; q->scrambled_stream = 0; - if (avctx->block_align != 96 * avctx->channels * frame_factor && - avctx->block_align != 152 * avctx->channels * frame_factor && - avctx->block_align != 192 * avctx->channels * frame_factor) { + if (avctx->block_align != 96 * channels * frame_factor && + avctx->block_align != 152 * channels * frame_factor && + avctx->block_align != 192 * channels * frame_factor) { av_log(avctx, AV_LOG_ERROR, "Unknown frame/channel/frame_factor " "configuration %d/%d/%d\n", avctx->block_align, - avctx->channels, frame_factor); + channels, frame_factor); return AVERROR_INVALIDDATA; } } else if (avctx->extradata_size == 12 || avctx->extradata_size == 10) { @@ -939,7 +941,7 @@ static av_cold int atrac3_decode_init(AVCodecContext *avctx) return AVERROR_INVALIDDATA; } - if (samples_per_frame != SAMPLES_PER_FRAME * avctx->channels) { + if (samples_per_frame != SAMPLES_PER_FRAME * channels) { av_log(avctx, AV_LOG_ERROR, "Unknown amount of samples per frame %d.\n", samples_per_frame); return AVERROR_INVALIDDATA; @@ -954,7 +956,7 @@ static av_cold int atrac3_decode_init(AVCodecContext *avctx) if (q->coding_mode == SINGLE) av_log(avctx, AV_LOG_DEBUG, "Single channels detected.\n"); else if (q->coding_mode == JOINT_STEREO) { - if (avctx->channels % 2 == 1) { /* Joint stereo channels must be even */ + if (channels % 2 == 1) { /* Joint stereo channels must be even */ av_log(avctx, AV_LOG_ERROR, "Invalid joint stereo channel configuration.\n"); return AVERROR_INVALIDDATA; } @@ -1004,7 +1006,7 @@ static av_cold int atrac3_decode_init(AVCodecContext *avctx) q->vector_fmul = fdsp->vector_fmul; av_free(fdsp); - q->units = av_calloc(avctx->channels, sizeof(*q->units)); + q->units = av_calloc(channels, sizeof(*q->units)); if (!q->units) return AVERROR(ENOMEM); @@ -1013,32 +1015,32 @@ static av_cold int atrac3_decode_init(AVCodecContext *avctx) return 0; } -const AVCodec ff_atrac3_decoder = { - .name = "atrac3", - .long_name = NULL_IF_CONFIG_SMALL("ATRAC3 (Adaptive TRansform Acoustic Coding 3)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_ATRAC3, +const FFCodec ff_atrac3_decoder = { + .p.name = "atrac3", + .p.long_name = NULL_IF_CONFIG_SMALL("ATRAC3 (Adaptive TRansform Acoustic Coding 3)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_ATRAC3, .priv_data_size = sizeof(ATRAC3Context), .init = atrac3_decode_init, .close = atrac3_decode_close, - .decode = atrac3_decode_frame, - .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + FF_CODEC_DECODE_CB(atrac3_decode_frame), + .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; -const AVCodec ff_atrac3al_decoder = { - .name = "atrac3al", - .long_name = NULL_IF_CONFIG_SMALL("ATRAC3 AL (Adaptive TRansform Acoustic Coding 3 Advanced Lossless)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_ATRAC3AL, +const FFCodec ff_atrac3al_decoder = { + .p.name = "atrac3al", + .p.long_name = NULL_IF_CONFIG_SMALL("ATRAC3 AL (Adaptive TRansform Acoustic Coding 3 Advanced Lossless)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_ATRAC3AL, .priv_data_size = sizeof(ATRAC3Context), .init = atrac3_decode_init, .close = atrac3_decode_close, - .decode = atrac3al_decode_frame, - .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + FF_CODEC_DECODE_CB(atrac3al_decode_frame), + .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/atrac3plus.c b/libavcodec/atrac3plus.c index 3a0a0d5f3..a0836f117 100644 --- a/libavcodec/atrac3plus.c +++ b/libavcodec/atrac3plus.c @@ -31,7 +31,7 @@ #include "atrac3plus.h" #include "atrac3plus_data.h" -static VLC_TYPE tables_data[154276][2]; +static VLCElem tables_data[154276]; static VLC wl_vlc_tabs[4]; static VLC sf_vlc_tabs[8]; static VLC ct_vlc_tabs[4]; diff --git a/libavcodec/atrac3plusdec.c b/libavcodec/atrac3plusdec.c index e342f09fd..f87ffb893 100644 --- a/libavcodec/atrac3plusdec.c +++ b/libavcodec/atrac3plusdec.c @@ -42,6 +42,7 @@ #include "libavutil/mem_internal.h" #include "libavutil/thread.h" #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" #include "atrac.h" @@ -64,7 +65,6 @@ typedef struct ATRAC3PContext { int num_channel_blocks; ///< number of channel blocks uint8_t channel_blocks[5]; ///< channel configuration descriptor - uint64_t my_channel_layout; ///< current channel layout } ATRAC3PContext; static av_cold int atrac3p_decode_close(AVCodecContext *avctx) @@ -83,36 +83,36 @@ static av_cold int atrac3p_decode_close(AVCodecContext *avctx) static av_cold int set_channel_params(ATRAC3PContext *ctx, AVCodecContext *avctx) { + int channels = avctx->ch_layout.nb_channels; memset(ctx->channel_blocks, 0, sizeof(ctx->channel_blocks)); - switch (avctx->channels) { + av_channel_layout_uninit(&avctx->ch_layout); + switch (channels) { case 1: - if (avctx->channel_layout != AV_CH_FRONT_LEFT) - avctx->channel_layout = AV_CH_LAYOUT_MONO; - + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; ctx->num_channel_blocks = 1; ctx->channel_blocks[0] = CH_UNIT_MONO; break; case 2: - avctx->channel_layout = AV_CH_LAYOUT_STEREO; + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; ctx->num_channel_blocks = 1; ctx->channel_blocks[0] = CH_UNIT_STEREO; break; case 3: - avctx->channel_layout = AV_CH_LAYOUT_SURROUND; + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_SURROUND; ctx->num_channel_blocks = 2; ctx->channel_blocks[0] = CH_UNIT_STEREO; ctx->channel_blocks[1] = CH_UNIT_MONO; break; case 4: - avctx->channel_layout = AV_CH_LAYOUT_4POINT0; + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_4POINT0; ctx->num_channel_blocks = 3; ctx->channel_blocks[0] = CH_UNIT_STEREO; ctx->channel_blocks[1] = CH_UNIT_MONO; ctx->channel_blocks[2] = CH_UNIT_MONO; break; case 6: - avctx->channel_layout = AV_CH_LAYOUT_5POINT1_BACK; + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1_BACK; ctx->num_channel_blocks = 4; ctx->channel_blocks[0] = CH_UNIT_STEREO; ctx->channel_blocks[1] = CH_UNIT_MONO; @@ -120,7 +120,7 @@ static av_cold int set_channel_params(ATRAC3PContext *ctx, ctx->channel_blocks[3] = CH_UNIT_MONO; break; case 7: - avctx->channel_layout = AV_CH_LAYOUT_6POINT1_BACK; + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_6POINT1_BACK; ctx->num_channel_blocks = 5; ctx->channel_blocks[0] = CH_UNIT_STEREO; ctx->channel_blocks[1] = CH_UNIT_MONO; @@ -129,7 +129,7 @@ static av_cold int set_channel_params(ATRAC3PContext *ctx, ctx->channel_blocks[4] = CH_UNIT_MONO; break; case 8: - avctx->channel_layout = AV_CH_LAYOUT_7POINT1; + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_7POINT1; ctx->num_channel_blocks = 5; ctx->channel_blocks[0] = CH_UNIT_STEREO; ctx->channel_blocks[1] = CH_UNIT_MONO; @@ -139,7 +139,7 @@ static av_cold int set_channel_params(ATRAC3PContext *ctx, break; default: av_log(avctx, AV_LOG_ERROR, - "Unsupported channel count: %d!\n", avctx->channels); + "Unsupported channel count: %d!\n", channels); return AVERROR_INVALIDDATA; } @@ -173,8 +173,6 @@ static av_cold int atrac3p_decode_init(AVCodecContext *avctx) if ((ret = set_channel_params(ctx, avctx)) < 0) return ret; - ctx->my_channel_layout = avctx->channel_layout; - ctx->ch_units = av_calloc(ctx->num_channel_blocks, sizeof(*ctx->ch_units)); ctx->fdsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT); @@ -333,11 +331,10 @@ static void reconstruct_frame(ATRAC3PContext *ctx, Atrac3pChanUnitCtx *ch_unit, FFSWAP(Atrac3pWaveSynthParams *, ch_unit->waves_info, ch_unit->waves_info_prev); } -static int atrac3p_decode_frame(AVCodecContext *avctx, void *data, +static int atrac3p_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { ATRAC3PContext *ctx = avctx->priv_data; - AVFrame *frame = data; int i, ret, ch_unit_id, ch_block = 0, out_ch_index = 0, channels_to_process; float **samples_p = (float **)frame->extended_data; @@ -393,28 +390,28 @@ static int atrac3p_decode_frame(AVCodecContext *avctx, void *data, return avctx->codec_id == AV_CODEC_ID_ATRAC3P ? FFMIN(avctx->block_align, avpkt->size) : avpkt->size; } -const AVCodec ff_atrac3p_decoder = { - .name = "atrac3plus", - .long_name = NULL_IF_CONFIG_SMALL("ATRAC3+ (Adaptive TRansform Acoustic Coding 3+)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_ATRAC3P, - .capabilities = AV_CODEC_CAP_DR1, +const FFCodec ff_atrac3p_decoder = { + .p.name = "atrac3plus", + .p.long_name = NULL_IF_CONFIG_SMALL("ATRAC3+ (Adaptive TRansform Acoustic Coding 3+)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_ATRAC3P, + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .priv_data_size = sizeof(ATRAC3PContext), .init = atrac3p_decode_init, .close = atrac3p_decode_close, - .decode = atrac3p_decode_frame, + FF_CODEC_DECODE_CB(atrac3p_decode_frame), }; -const AVCodec ff_atrac3pal_decoder = { - .name = "atrac3plusal", - .long_name = NULL_IF_CONFIG_SMALL("ATRAC3+ AL (Adaptive TRansform Acoustic Coding 3+ Advanced Lossless)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_ATRAC3PAL, - .capabilities = AV_CODEC_CAP_DR1, +const FFCodec ff_atrac3pal_decoder = { + .p.name = "atrac3plusal", + .p.long_name = NULL_IF_CONFIG_SMALL("ATRAC3+ AL (Adaptive TRansform Acoustic Coding 3+ Advanced Lossless)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_ATRAC3PAL, + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .priv_data_size = sizeof(ATRAC3PContext), .init = atrac3p_decode_init, .close = atrac3p_decode_close, - .decode = atrac3p_decode_frame, + FF_CODEC_DECODE_CB(atrac3p_decode_frame), }; diff --git a/libavcodec/atrac9dec.c b/libavcodec/atrac9dec.c index 106304481..6c1f0d175 100644 --- a/libavcodec/atrac9dec.c +++ b/libavcodec/atrac9dec.c @@ -22,6 +22,7 @@ #include "libavutil/channel_layout.h" #include "libavutil/thread.h" +#include "codec_internal.h" #include "internal.h" #include "get_bits.h" #include "fft.h" @@ -786,12 +787,11 @@ imdct: return 0; } -static int atrac9_decode_frame(AVCodecContext *avctx, void *data, +static int atrac9_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { int ret; GetBitContext gb; - AVFrame *frame = data; ATRAC9Context *s = avctx->priv_data; const int frames = FFMIN(avpkt->size / s->avg_frame_size, s->frame_count); @@ -844,7 +844,7 @@ static av_cold void atrac9_init_vlc(VLC *vlc, int nb_bits, int nb_codes, const uint8_t (**tab)[2], unsigned *buf_offset, int offset) { - static VLC_TYPE vlc_buf[24812][2]; + static VLCElem vlc_buf[24812]; vlc->table = &vlc_buf[*buf_offset]; vlc->table_allocated = FF_ARRAY_ELEMS(vlc_buf) - *buf_offset; @@ -938,8 +938,8 @@ static av_cold int atrac9_decode_init(AVCodecContext *avctx) } s->block_config = &at9_block_layout[block_config_idx]; - avctx->channel_layout = s->block_config->channel_layout; - avctx->channels = av_get_channel_layout_nb_channels(avctx->channel_layout); + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = s->block_config->channel_layout; avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; if (get_bits1(&gb)) { @@ -987,16 +987,16 @@ static av_cold int atrac9_decode_init(AVCodecContext *avctx) return 0; } -const AVCodec ff_atrac9_decoder = { - .name = "atrac9", - .long_name = NULL_IF_CONFIG_SMALL("ATRAC9 (Adaptive TRansform Acoustic Coding 9)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_ATRAC9, +const FFCodec ff_atrac9_decoder = { + .p.name = "atrac9", + .p.long_name = NULL_IF_CONFIG_SMALL("ATRAC9 (Adaptive TRansform Acoustic Coding 9)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_ATRAC9, .priv_data_size = sizeof(ATRAC9Context), .init = atrac9_decode_init, .close = atrac9_decode_close, - .decode = atrac9_decode_frame, + FF_CODEC_DECODE_CB(atrac9_decode_frame), .flush = atrac9_decode_flush, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, }; diff --git a/libavcodec/atrac9tab.h b/libavcodec/atrac9tab.h index b169035aa..bdd051221 100644 --- a/libavcodec/atrac9tab.h +++ b/libavcodec/atrac9tab.h @@ -33,7 +33,7 @@ enum ATRAC9BlockType { }; typedef struct ATRAC9BlockConfig { - uint64_t channel_layout; + AVChannelLayout channel_layout; enum ATRAC9BlockType type[5]; int plane_map[5][2]; int count; @@ -41,25 +41,25 @@ typedef struct ATRAC9BlockConfig { static const ATRAC9BlockConfig at9_block_layout[] = { { /* Mono */ - .channel_layout = AV_CH_LAYOUT_MONO, + .channel_layout = AV_CHANNEL_LAYOUT_MONO, .type = { ATRAC9_BLOCK_TYPE_SCE, }, .count = 1, }, { /* Dual Mono */ - .channel_layout = AV_CH_LAYOUT_STEREO, + .channel_layout = AV_CHANNEL_LAYOUT_STEREO, .type = { ATRAC9_BLOCK_TYPE_SCE, ATRAC9_BLOCK_TYPE_SCE, }, .plane_map = { { 0 }, { 1 }, }, .count = 2, }, { /* Stereo */ - .channel_layout = AV_CH_LAYOUT_STEREO, + .channel_layout = AV_CHANNEL_LAYOUT_STEREO, .type = { ATRAC9_BLOCK_TYPE_CPE, }, .plane_map = { { 0, 1 }, }, .count = 1, }, { /* 5.1 */ - .channel_layout = AV_CH_LAYOUT_5POINT1, + .channel_layout = AV_CHANNEL_LAYOUT_5POINT1, .type = { ATRAC9_BLOCK_TYPE_CPE, ATRAC9_BLOCK_TYPE_SCE, ATRAC9_BLOCK_TYPE_LFE, @@ -68,7 +68,7 @@ static const ATRAC9BlockConfig at9_block_layout[] = { .count = 4, }, { /* 7.1 */ - .channel_layout = AV_CH_LAYOUT_7POINT1, + .channel_layout = AV_CHANNEL_LAYOUT_7POINT1, .type = { ATRAC9_BLOCK_TYPE_CPE, ATRAC9_BLOCK_TYPE_SCE, ATRAC9_BLOCK_TYPE_LFE, @@ -78,7 +78,7 @@ static const ATRAC9BlockConfig at9_block_layout[] = { .count = 5, }, { /* Quad */ - .channel_layout = AV_CH_LAYOUT_QUAD, + .channel_layout = AV_CHANNEL_LAYOUT_QUAD, .type = { ATRAC9_BLOCK_TYPE_CPE, ATRAC9_BLOCK_TYPE_CPE, }, .plane_map = { { 0, 1 }, { 2, 3 }, }, diff --git a/libavcodec/audiodsp.c b/libavcodec/audiodsp.c index efcb0a8e8..ff43e87dc 100644 --- a/libavcodec/audiodsp.c +++ b/libavcodec/audiodsp.c @@ -109,10 +109,11 @@ av_cold void ff_audiodsp_init(AudioDSPContext *c) c->vector_clip_int32 = vector_clip_int32_c; c->vector_clipf = vector_clipf_c; - if (ARCH_ARM) - ff_audiodsp_init_arm(c); - if (ARCH_PPC) - ff_audiodsp_init_ppc(c); - if (ARCH_X86) - ff_audiodsp_init_x86(c); +#if ARCH_ARM + ff_audiodsp_init_arm(c); +#elif ARCH_PPC + ff_audiodsp_init_ppc(c); +#elif ARCH_X86 + ff_audiodsp_init_x86(c); +#endif } diff --git a/libavcodec/audiotoolboxdec.c b/libavcodec/audiotoolboxdec.c index 9939fef21..daccf4abf 100644 --- a/libavcodec/audiotoolboxdec.c +++ b/libavcodec/audiotoolboxdec.c @@ -23,9 +23,11 @@ #include #include "config.h" +#include "config_components.h" #include "avcodec.h" #include "ac3_parser_internal.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" #include "mpegaudiodecheader.h" #include "libavutil/avassert.h" @@ -166,8 +168,8 @@ static int ffat_update_ctx(AVCodecContext *avctx) &size, &format)) { if (format.mSampleRate) avctx->sample_rate = format.mSampleRate; - avctx->channels = format.mChannelsPerFrame; - avctx->channel_layout = av_get_default_channel_layout(avctx->channels); + av_channel_layout_uninit(&avctx->ch_layout); + av_channel_layout_default(&avctx->ch_layout, format.mChannelsPerFrame); avctx->frame_size = format.mFramesPerPacket; } @@ -175,7 +177,7 @@ static int ffat_update_ctx(AVCodecContext *avctx) kAudioConverterCurrentOutputStreamDescription, &size, &format)) { format.mSampleRate = avctx->sample_rate; - format.mChannelsPerFrame = avctx->channels; + format.mChannelsPerFrame = avctx->ch_layout.nb_channels; AudioConverterSetProperty(at->converter, kAudioConverterCurrentOutputStreamDescription, size, &format); @@ -201,7 +203,8 @@ static int ffat_update_ctx(AVCodecContext *avctx) layout_mask |= 1 << id; layout->mChannelDescriptions[i].mChannelFlags = i; // Abusing flags as index } - avctx->channel_layout = layout_mask; + av_channel_layout_uninit(&avctx->ch_layout); + av_channel_layout_from_mask(&avctx->ch_layout, layout_mask); qsort(layout->mChannelDescriptions, layout->mNumberChannelDescriptions, sizeof(AudioChannelDescription), &ffat_compare_channel_descriptions); for (i = 0; i < layout->mNumberChannelDescriptions; i++) @@ -364,11 +367,18 @@ static av_cold int ffat_create_decoder(AVCodecContext *avctx, #endif } else { in_format.mSampleRate = avctx->sample_rate ? avctx->sample_rate : 44100; - in_format.mChannelsPerFrame = avctx->channels ? avctx->channels : 1; + in_format.mChannelsPerFrame = avctx->ch_layout.nb_channels ? avctx->ch_layout.nb_channels : 1; } avctx->sample_rate = out_format.mSampleRate = in_format.mSampleRate; - avctx->channels = out_format.mChannelsPerFrame = in_format.mChannelsPerFrame; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + avctx->ch_layout.nb_channels = out_format.mChannelsPerFrame = in_format.mChannelsPerFrame; + + out_format.mBytesPerFrame = + out_format.mChannelsPerFrame * (out_format.mBitsPerChannel / 8); + out_format.mBytesPerPacket = + out_format.mBytesPerFrame * out_format.mFramesPerPacket; if (avctx->codec_id == AV_CODEC_ID_ADPCM_IMA_QT) in_format.mFramesPerPacket = 64; @@ -389,7 +399,7 @@ static av_cold int ffat_create_decoder(AVCodecContext *avctx, ffat_update_ctx(avctx); if(!(at->decoded_data = av_malloc(av_get_bytes_per_sample(avctx->sample_fmt) - * avctx->frame_size * avctx->channels))) + * avctx->frame_size * avctx->ch_layout.nb_channels))) return AVERROR(ENOMEM); at->last_pts = AV_NOPTS_VALUE; @@ -408,7 +418,7 @@ static av_cold int ffat_init_decoder(AVCodecContext *avctx) memcpy(at->extradata, avctx->extradata, avctx->extradata_size); } - if ((avctx->channels && avctx->sample_rate) || ffat_usable_extradata(avctx)) + if ((avctx->ch_layout.nb_channels && avctx->sample_rate) || ffat_usable_extradata(avctx)) return ffat_create_decoder(avctx, NULL); else return 0; @@ -455,11 +465,11 @@ static OSStatus ffat_decode_callback(AudioConverterRef converter, UInt32 *nb_pac #define COPY_SAMPLES(type) \ type *in_ptr = (type*)at->decoded_data; \ - type *end_ptr = in_ptr + frame->nb_samples * avctx->channels; \ + type *end_ptr = in_ptr + frame->nb_samples * avctx->ch_layout.nb_channels; \ type *out_ptr = (type*)frame->data[0]; \ - for (; in_ptr < end_ptr; in_ptr += avctx->channels, out_ptr += avctx->channels) { \ + for (; in_ptr < end_ptr; in_ptr += avctx->ch_layout.nb_channels, out_ptr += avctx->ch_layout.nb_channels) { \ int c; \ - for (c = 0; c < avctx->channels; c++) \ + for (c = 0; c < avctx->ch_layout.nb_channels; c++) \ out_ptr[c] = in_ptr[at->channel_map[c]]; \ } @@ -473,11 +483,10 @@ static void ffat_copy_samples(AVCodecContext *avctx, AVFrame *frame) } } -static int ffat_decode(AVCodecContext *avctx, void *data, +static int ffat_decode(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { ATDecodeContext *at = avctx->priv_data; - AVFrame *frame = data; int pkt_size = avpkt->size; OSStatus ret; AudioBufferList out_buffers; @@ -509,9 +518,9 @@ static int ffat_decode(AVCodecContext *avctx, void *data, .mNumberBuffers = 1, .mBuffers = { { - .mNumberChannels = avctx->channels, + .mNumberChannels = avctx->ch_layout.nb_channels, .mDataByteSize = av_get_bytes_per_sample(avctx->sample_fmt) * avctx->frame_size - * avctx->channels, + * avctx->ch_layout.nb_channels, } } }; @@ -580,21 +589,21 @@ static av_cold int ffat_close_decoder(AVCodecContext *avctx) #define FFAT_DEC(NAME, ID, bsf_name) \ FFAT_DEC_CLASS(NAME) \ - const AVCodec ff_##NAME##_at_decoder = { \ - .name = #NAME "_at", \ - .long_name = NULL_IF_CONFIG_SMALL(#NAME " (AudioToolbox)"), \ - .type = AVMEDIA_TYPE_AUDIO, \ - .id = ID, \ + const FFCodec ff_##NAME##_at_decoder = { \ + .p.name = #NAME "_at", \ + .p.long_name = NULL_IF_CONFIG_SMALL(#NAME " (AudioToolbox)"), \ + .p.type = AVMEDIA_TYPE_AUDIO, \ + .p.id = ID, \ .priv_data_size = sizeof(ATDecodeContext), \ .init = ffat_init_decoder, \ .close = ffat_close_decoder, \ - .decode = ffat_decode, \ + FF_CODEC_DECODE_CB(ffat_decode), \ .flush = ffat_decode_flush, \ - .priv_class = &ffat_##NAME##_dec_class, \ + .p.priv_class = &ffat_##NAME##_dec_class, \ .bsfs = bsf_name, \ - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_CHANNEL_CONF, \ + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_CHANNEL_CONF, \ .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, \ - .wrapper_name = "at", \ + .p.wrapper_name = "at", \ }; FFAT_DEC(aac, AV_CODEC_ID_AAC, "aac_adtstoasc") diff --git a/libavcodec/audiotoolboxenc.c b/libavcodec/audiotoolboxenc.c index 9245aa9dc..00293154b 100644 --- a/libavcodec/audiotoolboxenc.c +++ b/libavcodec/audiotoolboxenc.c @@ -29,6 +29,7 @@ #include "audio_frame_queue.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "encode.h" #include "internal.h" #include "libavformat/isom.h" @@ -178,18 +179,17 @@ static av_cold int get_channel_label(int channel) return -1; } -static int remap_layout(AudioChannelLayout *layout, uint64_t in_layout, int count) +static int remap_layout(AudioChannelLayout *layout, const AVChannelLayout *in_layout) { int i; - int c = 0; layout->mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions; - layout->mNumberChannelDescriptions = count; - for (i = 0; i < count; i++) { - int label; - while (!(in_layout & (1 << c)) && c < 64) - c++; - if (c == 64) - return AVERROR(EINVAL); // This should never happen + layout->mNumberChannelDescriptions = in_layout->nb_channels; + for (i = 0; i < in_layout->nb_channels; i++) { + int c, label; + + c = av_channel_layout_channel_from_index(in_layout, i); + if (c < 0 || c >= 64) + return AVERROR(EINVAL); label = get_channel_label(c); layout->mChannelDescriptions[i].mChannelLabel = label; if (label < 0) @@ -199,38 +199,33 @@ static int remap_layout(AudioChannelLayout *layout, uint64_t in_layout, int coun return 0; } -static int get_aac_tag(uint64_t in_layout) +static int get_aac_tag(const AVChannelLayout *in_layout) { - switch (in_layout) { - case AV_CH_LAYOUT_MONO: - return kAudioChannelLayoutTag_Mono; - case AV_CH_LAYOUT_STEREO: - return kAudioChannelLayoutTag_Stereo; - case AV_CH_LAYOUT_QUAD: - return kAudioChannelLayoutTag_AAC_Quadraphonic; - case AV_CH_LAYOUT_OCTAGONAL: - return kAudioChannelLayoutTag_AAC_Octagonal; - case AV_CH_LAYOUT_SURROUND: - return kAudioChannelLayoutTag_AAC_3_0; - case AV_CH_LAYOUT_4POINT0: - return kAudioChannelLayoutTag_AAC_4_0; - case AV_CH_LAYOUT_5POINT0: - return kAudioChannelLayoutTag_AAC_5_0; - case AV_CH_LAYOUT_5POINT1: - return kAudioChannelLayoutTag_AAC_5_1; - case AV_CH_LAYOUT_6POINT0: - return kAudioChannelLayoutTag_AAC_6_0; - case AV_CH_LAYOUT_6POINT1: - return kAudioChannelLayoutTag_AAC_6_1; - case AV_CH_LAYOUT_7POINT0: - return kAudioChannelLayoutTag_AAC_7_0; - case AV_CH_LAYOUT_7POINT1_WIDE_BACK: - return kAudioChannelLayoutTag_AAC_7_1; - case AV_CH_LAYOUT_7POINT1: - return kAudioChannelLayoutTag_MPEG_7_1_C; - default: - return 0; - } + static const struct { + AVChannelLayout chl; + int tag; + } map[] = { + { AV_CHANNEL_LAYOUT_MONO, kAudioChannelLayoutTag_Mono }, + { AV_CHANNEL_LAYOUT_STEREO, kAudioChannelLayoutTag_Stereo }, + { AV_CHANNEL_LAYOUT_QUAD, kAudioChannelLayoutTag_AAC_Quadraphonic }, + { AV_CHANNEL_LAYOUT_OCTAGONAL, kAudioChannelLayoutTag_AAC_Octagonal }, + { AV_CHANNEL_LAYOUT_SURROUND, kAudioChannelLayoutTag_AAC_3_0 }, + { AV_CHANNEL_LAYOUT_4POINT0, kAudioChannelLayoutTag_AAC_4_0 }, + { AV_CHANNEL_LAYOUT_5POINT0, kAudioChannelLayoutTag_AAC_5_0 }, + { AV_CHANNEL_LAYOUT_5POINT1, kAudioChannelLayoutTag_AAC_5_1 }, + { AV_CHANNEL_LAYOUT_6POINT0, kAudioChannelLayoutTag_AAC_6_0 }, + { AV_CHANNEL_LAYOUT_6POINT1, kAudioChannelLayoutTag_AAC_6_1 }, + { AV_CHANNEL_LAYOUT_7POINT0, kAudioChannelLayoutTag_AAC_7_0 }, + { AV_CHANNEL_LAYOUT_7POINT1_WIDE_BACK, kAudioChannelLayoutTag_AAC_7_1 }, + { AV_CHANNEL_LAYOUT_7POINT1, kAudioChannelLayoutTag_MPEG_7_1_C }, + }; + int i; + + for (i = 0; i < FF_ARRAY_ELEMS(map); i++) + if (!av_channel_layout_compare(in_layout, &map[i].chl)) + return map[i].tag; + + return 0; } static av_cold int ffat_init_encoder(AVCodecContext *avctx) @@ -246,10 +241,10 @@ static av_cold int ffat_init_encoder(AVCodecContext *avctx) : avctx->sample_fmt == AV_SAMPLE_FMT_U8 ? 0 : kAudioFormatFlagIsSignedInteger) | kAudioFormatFlagIsPacked, - .mBytesPerPacket = av_get_bytes_per_sample(avctx->sample_fmt) * avctx->channels, + .mBytesPerPacket = av_get_bytes_per_sample(avctx->sample_fmt) * avctx->ch_layout.nb_channels, .mFramesPerPacket = 1, - .mBytesPerFrame = av_get_bytes_per_sample(avctx->sample_fmt) * avctx->channels, - .mChannelsPerFrame = avctx->channels, + .mBytesPerFrame = av_get_bytes_per_sample(avctx->sample_fmt) * avctx->ch_layout.nb_channels, + .mChannelsPerFrame = avctx->ch_layout.nb_channels, .mBitsPerChannel = av_get_bytes_per_sample(avctx->sample_fmt) * 8, }; AudioStreamBasicDescription out_format = { @@ -258,7 +253,7 @@ static av_cold int ffat_init_encoder(AVCodecContext *avctx) .mChannelsPerFrame = in_format.mChannelsPerFrame, }; UInt32 layout_size = sizeof(AudioChannelLayout) + - sizeof(AudioChannelDescription) * avctx->channels; + sizeof(AudioChannelDescription) * avctx->ch_layout.nb_channels; AudioChannelLayout *channel_layout = av_malloc(layout_size); if (!channel_layout) @@ -278,10 +273,10 @@ static av_cold int ffat_init_encoder(AVCodecContext *avctx) return AVERROR_UNKNOWN; } - if (!avctx->channel_layout) - avctx->channel_layout = av_get_default_channel_layout(avctx->channels); + if (avctx->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) + av_channel_layout_default(&avctx->ch_layout, avctx->ch_layout.nb_channels); - if ((status = remap_layout(channel_layout, avctx->channel_layout, avctx->channels)) < 0) { + if ((status = remap_layout(channel_layout, &avctx->ch_layout)) < 0) { av_log(avctx, AV_LOG_ERROR, "Invalid channel layout\n"); av_free(channel_layout); return status; @@ -294,7 +289,7 @@ static av_cold int ffat_init_encoder(AVCodecContext *avctx) return AVERROR(EINVAL); } if (avctx->codec_id == AV_CODEC_ID_AAC) { - int tag = get_aac_tag(avctx->channel_layout); + int tag = get_aac_tag(&avctx->ch_layout); if (tag) { channel_layout->mChannelLayoutTag = tag; channel_layout->mNumberChannelDescriptions = 0; @@ -476,10 +471,10 @@ static OSStatus ffat_encode_callback(AudioConverterRef converter, UInt32 *nb_pac frame = ff_bufqueue_get(&at->frame_queue); data->mNumberBuffers = 1; - data->mBuffers[0].mNumberChannels = avctx->channels; + data->mBuffers[0].mNumberChannels = avctx->ch_layout.nb_channels; data->mBuffers[0].mDataByteSize = frame->nb_samples * av_get_bytes_per_sample(avctx->sample_fmt) * - avctx->channels; + avctx->ch_layout.nb_channels; data->mBuffers[0].mData = frame->data[0]; if (*nb_packets > frame->nb_samples) *nb_packets = frame->nb_samples; @@ -506,7 +501,7 @@ static int ffat_encode(AVCodecContext *avctx, AVPacket *avpkt, .mNumberBuffers = 1, .mBuffers = { { - .mNumberChannels = avctx->channels, + .mNumberChannels = avctx->ch_layout.nb_channels, .mDataByteSize = at->pkt_size, } } @@ -559,11 +554,13 @@ static int ffat_encode(AVCodecContext *avctx, AVPacket *avpkt, avctx->frame_size, &avpkt->pts, &avpkt->duration); + ret = 0; } else if (ret && ret != 1) { - av_log(avctx, AV_LOG_WARNING, "Encode error: %i\n", ret); + av_log(avctx, AV_LOG_ERROR, "Encode error: %i\n", ret); + ret = AVERROR_EXTERNAL; } - return 0; + return ret; } static av_cold void ffat_encode_flush(AVCodecContext *avctx) @@ -616,30 +613,49 @@ static const AVOption options[] = { .version = LIBAVUTIL_VERSION_INT, \ }; -#define FFAT_ENC(NAME, ID, PROFILES, ...) \ +#define FFAT_ENC(NAME, ID, PROFILES, CAPS, CHANNEL_LAYOUTS, CH_LAYOUTS) \ FFAT_ENC_CLASS(NAME) \ - const AVCodec ff_##NAME##_at_encoder = { \ - .name = #NAME "_at", \ - .long_name = NULL_IF_CONFIG_SMALL(#NAME " (AudioToolbox)"), \ - .type = AVMEDIA_TYPE_AUDIO, \ - .id = ID, \ + const FFCodec ff_##NAME##_at_encoder = { \ + .p.name = #NAME "_at", \ + .p.long_name = NULL_IF_CONFIG_SMALL(#NAME " (AudioToolbox)"), \ + .p.type = AVMEDIA_TYPE_AUDIO, \ + .p.id = ID, \ .priv_data_size = sizeof(ATDecodeContext), \ .init = ffat_init_encoder, \ .close = ffat_close_encoder, \ - .encode2 = ffat_encode, \ + FF_CODEC_ENCODE_CB(ffat_encode), \ .flush = ffat_encode_flush, \ - .priv_class = &ffat_##NAME##_enc_class, \ - .capabilities = AV_CODEC_CAP_DELAY | \ - AV_CODEC_CAP_ENCODER_FLUSH __VA_ARGS__, \ - .sample_fmts = (const enum AVSampleFormat[]) { \ + .p.priv_class = &ffat_##NAME##_enc_class, \ + .p.capabilities = AV_CODEC_CAP_DELAY | \ + AV_CODEC_CAP_ENCODER_FLUSH CAPS, \ + .p.channel_layouts = CHANNEL_LAYOUTS, \ + .p.ch_layouts = CH_LAYOUTS, \ + .p.sample_fmts = (const enum AVSampleFormat[]) { \ AV_SAMPLE_FMT_S16, \ AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_NONE \ }, \ .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, \ - .profiles = PROFILES, \ - .wrapper_name = "at", \ + .p.profiles = PROFILES, \ + .p.wrapper_name = "at", \ }; +static const AVChannelLayout aac_at_ch_layouts[] = { + AV_CHANNEL_LAYOUT_MONO, + AV_CHANNEL_LAYOUT_STEREO, + AV_CHANNEL_LAYOUT_SURROUND, + AV_CHANNEL_LAYOUT_4POINT0, + AV_CHANNEL_LAYOUT_5POINT0, + AV_CHANNEL_LAYOUT_5POINT1, + AV_CHANNEL_LAYOUT_6POINT0, + AV_CHANNEL_LAYOUT_6POINT1, + AV_CHANNEL_LAYOUT_7POINT0, + AV_CHANNEL_LAYOUT_7POINT1_WIDE_BACK, + AV_CHANNEL_LAYOUT_QUAD, + AV_CHANNEL_LAYOUT_OCTAGONAL, + { 0 }, +}; + +#if FF_API_OLD_CHANNEL_LAYOUT static const uint64_t aac_at_channel_layouts[] = { AV_CH_LAYOUT_MONO, AV_CH_LAYOUT_STEREO, @@ -655,10 +671,11 @@ static const uint64_t aac_at_channel_layouts[] = { AV_CH_LAYOUT_OCTAGONAL, 0, }; +#endif -FFAT_ENC(aac, AV_CODEC_ID_AAC, aac_profiles, , .channel_layouts = aac_at_channel_layouts) +FFAT_ENC(aac, AV_CODEC_ID_AAC, aac_profiles, , aac_at_channel_layouts, aac_at_ch_layouts) //FFAT_ENC(adpcm_ima_qt, AV_CODEC_ID_ADPCM_IMA_QT, NULL) -FFAT_ENC(alac, AV_CODEC_ID_ALAC, NULL, | AV_CODEC_CAP_VARIABLE_FRAME_SIZE) -FFAT_ENC(ilbc, AV_CODEC_ID_ILBC, NULL) -FFAT_ENC(pcm_alaw, AV_CODEC_ID_PCM_ALAW, NULL) -FFAT_ENC(pcm_mulaw, AV_CODEC_ID_PCM_MULAW, NULL) +FFAT_ENC(alac, AV_CODEC_ID_ALAC, NULL, | AV_CODEC_CAP_VARIABLE_FRAME_SIZE, NULL, NULL) +FFAT_ENC(ilbc, AV_CODEC_ID_ILBC, NULL, , NULL, NULL) +FFAT_ENC(pcm_alaw, AV_CODEC_ID_PCM_ALAW, NULL, , NULL, NULL) +FFAT_ENC(pcm_mulaw, AV_CODEC_ID_PCM_MULAW, NULL, , NULL, NULL) diff --git a/libavcodec/aura.c b/libavcodec/aura.c index 585c710f5..b4167cacf 100644 --- a/libavcodec/aura.c +++ b/libavcodec/aura.c @@ -24,6 +24,7 @@ */ #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "libavutil/internal.h" @@ -37,11 +38,9 @@ static av_cold int aura_decode_init(AVCodecContext *avctx) return 0; } -static int aura_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *pkt) +static int aura_decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *pkt) { - AVFrame *frame = data; uint8_t *Y, *U, *V; uint8_t val; int x, y, ret; @@ -97,13 +96,13 @@ static int aura_decode_frame(AVCodecContext *avctx, return pkt->size; } -const AVCodec ff_aura2_decoder = { - .name = "aura2", - .long_name = NULL_IF_CONFIG_SMALL("Auravision Aura 2"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_AURA2, +const FFCodec ff_aura2_decoder = { + .p.name = "aura2", + .p.long_name = NULL_IF_CONFIG_SMALL("Auravision Aura 2"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_AURA2, .init = aura_decode_init, - .decode = aura_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(aura_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/av1.h b/libavcodec/av1.h index 951a18ecb..384f7cddc 100644 --- a/libavcodec/av1.h +++ b/libavcodec/av1.h @@ -175,4 +175,10 @@ enum { AV1_RESTORE_SWITCHABLE = 3, }; +// Sequence Headers are actually unbounded because one can use +// an arbitrary number of leading zeroes when encoding via uvlc. +// The following estimate is based around using the lowest number +// of bits for uvlc encoding. +#define AV1_SANE_SEQUENCE_HEADER_MAX_BITS 3138 + #endif /* AVCODEC_AV1_H */ diff --git a/libavcodec/av1_frame_merge_bsf.c b/libavcodec/av1_frame_merge_bsf.c index 19b9cd01a..4c54f2167 100644 --- a/libavcodec/av1_frame_merge_bsf.c +++ b/libavcodec/av1_frame_merge_bsf.c @@ -156,12 +156,12 @@ static const enum AVCodecID av1_frame_merge_codec_ids[] = { AV_CODEC_ID_AV1, AV_CODEC_ID_NONE, }; -const AVBitStreamFilter ff_av1_frame_merge_bsf = { - .name = "av1_frame_merge", +const FFBitStreamFilter ff_av1_frame_merge_bsf = { + .p.name = "av1_frame_merge", + .p.codec_ids = av1_frame_merge_codec_ids, .priv_data_size = sizeof(AV1FMergeContext), .init = av1_frame_merge_init, .flush = av1_frame_merge_flush, .close = av1_frame_merge_close, .filter = av1_frame_merge_filter, - .codec_ids = av1_frame_merge_codec_ids, }; diff --git a/libavcodec/av1_frame_split_bsf.c b/libavcodec/av1_frame_split_bsf.c index fa8b887b6..5f6a40316 100644 --- a/libavcodec/av1_frame_split_bsf.c +++ b/libavcodec/av1_frame_split_bsf.c @@ -250,12 +250,12 @@ static const enum AVCodecID av1_frame_split_codec_ids[] = { AV_CODEC_ID_AV1, AV_CODEC_ID_NONE, }; -const AVBitStreamFilter ff_av1_frame_split_bsf = { - .name = "av1_frame_split", +const FFBitStreamFilter ff_av1_frame_split_bsf = { + .p.name = "av1_frame_split", + .p.codec_ids = av1_frame_split_codec_ids, .priv_data_size = sizeof(AV1FSplitContext), .init = av1_frame_split_init, .flush = av1_frame_split_flush, .close = av1_frame_split_close, .filter = av1_frame_split_filter, - .codec_ids = av1_frame_split_codec_ids, }; diff --git a/libavcodec/av1_metadata_bsf.c b/libavcodec/av1_metadata_bsf.c index c52673bf6..41b02cc83 100644 --- a/libavcodec/av1_metadata_bsf.c +++ b/libavcodec/av1_metadata_bsf.c @@ -20,6 +20,7 @@ #include "libavutil/opt.h" #include "bsf.h" +#include "bsf_internal.h" #include "cbs.h" #include "cbs_bsf.h" #include "cbs_av1.h" @@ -219,12 +220,12 @@ static const enum AVCodecID av1_metadata_codec_ids[] = { AV_CODEC_ID_AV1, AV_CODEC_ID_NONE, }; -const AVBitStreamFilter ff_av1_metadata_bsf = { - .name = "av1_metadata", +const FFBitStreamFilter ff_av1_metadata_bsf = { + .p.name = "av1_metadata", + .p.codec_ids = av1_metadata_codec_ids, + .p.priv_class = &av1_metadata_class, .priv_data_size = sizeof(AV1MetadataContext), - .priv_class = &av1_metadata_class, .init = &av1_metadata_init, .close = &ff_cbs_bsf_generic_close, .filter = &ff_cbs_bsf_generic_filter, - .codec_ids = av1_metadata_codec_ids, }; diff --git a/libavcodec/av1_parse.h b/libavcodec/av1_parse.h index 3861d80b4..f4a5d2830 100644 --- a/libavcodec/av1_parse.h +++ b/libavcodec/av1_parse.h @@ -24,9 +24,9 @@ #include #include -#include "libavutil/common.h" #include "libavutil/error.h" #include "libavutil/intmath.h" +#include "libavutil/macros.h" #include "av1.h" #include "get_bits.h" diff --git a/libavcodec/av1_parser.c b/libavcodec/av1_parser.c index d2dfdb358..4cbd7408a 100644 --- a/libavcodec/av1_parser.c +++ b/libavcodec/av1_parser.c @@ -23,7 +23,6 @@ #include "libavutil/avassert.h" #include "cbs.h" #include "cbs_av1.h" -#include "internal.h" #include "parser.h" typedef struct AV1ParseContext { diff --git a/libavcodec/av1dec.c b/libavcodec/av1dec.c index 81f65ff2f..dd83373dd 100644 --- a/libavcodec/av1dec.c +++ b/libavcodec/av1dec.c @@ -18,15 +18,19 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/film_grain_params.h" #include "libavutil/pixdesc.h" #include "libavutil/opt.h" #include "avcodec.h" #include "av1dec.h" #include "bytestream.h" +#include "codec_internal.h" #include "hwconfig.h" #include "internal.h" #include "profiles.h" +#include "thread.h" /**< same with Div_Lut defined in spec 7.11.3.7 */ static const uint16_t div_lut[AV1_DIV_LUT_NUM] = { @@ -437,7 +441,8 @@ static int get_pixel_format(AVCodecContext *avctx) #define HWACCEL_MAX (CONFIG_AV1_DXVA2_HWACCEL + \ CONFIG_AV1_D3D11VA_HWACCEL * 2 + \ CONFIG_AV1_NVDEC_HWACCEL + \ - CONFIG_AV1_VAAPI_HWACCEL) + CONFIG_AV1_VAAPI_HWACCEL + \ + CONFIG_AV1_VDPAU_HWACCEL) enum AVPixelFormat pix_fmts[HWACCEL_MAX + 2], *fmtp = pix_fmts; if (seq->seq_profile == 2 && seq->color_config.high_bitdepth) @@ -514,6 +519,9 @@ static int get_pixel_format(AVCodecContext *avctx) #endif #if CONFIG_AV1_VAAPI_HWACCEL *fmtp++ = AV_PIX_FMT_VAAPI; +#endif +#if CONFIG_AV1_VDPAU_HWACCEL + *fmtp++ = AV_PIX_FMT_VDPAU; #endif break; case AV_PIX_FMT_YUV420P10: @@ -529,6 +537,9 @@ static int get_pixel_format(AVCodecContext *avctx) #endif #if CONFIG_AV1_VAAPI_HWACCEL *fmtp++ = AV_PIX_FMT_VAAPI; +#endif +#if CONFIG_AV1_VDPAU_HWACCEL + *fmtp++ = AV_PIX_FMT_VDPAU; #endif break; case AV_PIX_FMT_GRAY8: @@ -569,7 +580,7 @@ static int get_pixel_format(AVCodecContext *avctx) static void av1_frame_unref(AVCodecContext *avctx, AV1Frame *f) { - ff_thread_release_buffer(avctx, &f->tf); + ff_thread_release_buffer(avctx, f->f); av_buffer_unref(&f->hwaccel_priv_buf); f->hwaccel_picture_private = NULL; av_buffer_unref(&f->header_ref); @@ -585,16 +596,19 @@ static int av1_frame_ref(AVCodecContext *avctx, AV1Frame *dst, const AV1Frame *s { int ret; - ret = ff_thread_ref_frame(&dst->tf, &src->tf); + ret = av_buffer_replace(&dst->header_ref, src->header_ref); if (ret < 0) return ret; - dst->header_ref = av_buffer_ref(src->header_ref); - if (!dst->header_ref) - goto fail; - dst->raw_frame_header = src->raw_frame_header; + if (!src->f->buf[0]) + return 0; + + ret = av_frame_ref(dst->f, src->f); + if (ret < 0) + goto fail; + if (src->hwaccel_picture_private) { dst->hwaccel_priv_buf = av_buffer_ref(src->hwaccel_priv_buf); if (!dst->hwaccel_priv_buf) @@ -634,10 +648,10 @@ static av_cold int av1_decode_free(AVCodecContext *avctx) for (int i = 0; i < FF_ARRAY_ELEMS(s->ref); i++) { av1_frame_unref(avctx, &s->ref[i]); - av_frame_free(&s->ref[i].tf.f); + av_frame_free(&s->ref[i].f); } av1_frame_unref(avctx, &s->cur_frame); - av_frame_free(&s->cur_frame.tf.f); + av_frame_free(&s->cur_frame.f); av_buffer_unref(&s->seq_ref); av_buffer_unref(&s->header_ref); @@ -738,16 +752,16 @@ static av_cold int av1_decode_init(AVCodecContext *avctx) s->pix_fmt = AV_PIX_FMT_NONE; for (int i = 0; i < FF_ARRAY_ELEMS(s->ref); i++) { - s->ref[i].tf.f = av_frame_alloc(); - if (!s->ref[i].tf.f) { + s->ref[i].f = av_frame_alloc(); + if (!s->ref[i].f) { av_log(avctx, AV_LOG_ERROR, "Failed to allocate reference frame buffer %d.\n", i); return AVERROR(ENOMEM); } } - s->cur_frame.tf.f = av_frame_alloc(); - if (!s->cur_frame.tf.f) { + s->cur_frame.f = av_frame_alloc(); + if (!s->cur_frame.f) { av_log(avctx, AV_LOG_ERROR, "Failed to allocate current frame buffer.\n"); return AVERROR(ENOMEM); @@ -800,16 +814,10 @@ static int av1_frame_alloc(AVCodecContext *avctx, AV1Frame *f) return ret; } - f->header_ref = av_buffer_ref(s->header_ref); - if (!f->header_ref) - return AVERROR(ENOMEM); - - f->raw_frame_header = s->raw_frame_header; - - if ((ret = ff_thread_get_buffer(avctx, &f->tf, AV_GET_BUFFER_FLAG_REF)) < 0) + if ((ret = ff_thread_get_buffer(avctx, f->f, AV_GET_BUFFER_FLAG_REF)) < 0) goto fail; - frame = f->tf.f; + frame = f->f; frame->key_frame = header->frame_type == AV1_FRAME_KEY; switch (header->frame_type) { @@ -908,7 +916,7 @@ static int set_output_frame(AVCodecContext *avctx, AVFrame *frame, const AVPacket *pkt, int *got_frame) { AV1DecContext *s = avctx->priv_data; - const AVFrame *srcframe = s->cur_frame.tf.f; + const AVFrame *srcframe = s->cur_frame.f; int ret; // TODO: all layers @@ -945,8 +953,7 @@ static int update_reference_list(AVCodecContext *avctx) for (int i = 0; i < AV1_NUM_REF_FRAMES; i++) { if (header->refresh_frame_flags & (1 << i)) { - if (s->ref[i].tf.f->buf[0]) - av1_frame_unref(avctx, &s->ref[i]); + av1_frame_unref(avctx, &s->ref[i]); if ((ret = av1_frame_ref(avctx, &s->ref[i], &s->cur_frame)) < 0) { av_log(avctx, AV_LOG_ERROR, "Failed to update frame %d in reference list\n", i); @@ -962,8 +969,27 @@ static int get_current_frame(AVCodecContext *avctx) AV1DecContext *s = avctx->priv_data; int ret; - if (s->cur_frame.tf.f->buf[0]) - av1_frame_unref(avctx, &s->cur_frame); + av1_frame_unref(avctx, &s->cur_frame); + + s->cur_frame.header_ref = av_buffer_ref(s->header_ref); + if (!s->cur_frame.header_ref) + return AVERROR(ENOMEM); + + s->cur_frame.raw_frame_header = s->raw_frame_header; + + ret = init_tile_data(s); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to init tile data.\n"); + return ret; + } + + if ((avctx->skip_frame >= AVDISCARD_NONINTRA && + (s->raw_frame_header->frame_type != AV1_FRAME_KEY && + s->raw_frame_header->frame_type != AV1_FRAME_INTRA_ONLY)) || + (avctx->skip_frame >= AVDISCARD_NONKEY && + s->raw_frame_header->frame_type != AV1_FRAME_KEY) || + avctx->skip_frame >= AVDISCARD_ALL) + return 0; ret = av1_frame_alloc(avctx, &s->cur_frame); if (ret < 0) { @@ -972,12 +998,6 @@ static int get_current_frame(AVCodecContext *avctx) return ret; } - ret = init_tile_data(s); - if (ret < 0) { - av_log(avctx, AV_LOG_ERROR, "Failed to init tile data.\n"); - return ret; - } - global_motion_params(s); skip_mode_params(s); coded_lossless_param(s); @@ -986,7 +1006,7 @@ static int get_current_frame(AVCodecContext *avctx) return ret; } -static int av1_decode_frame(AVCodecContext *avctx, void *frame, +static int av1_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *pkt) { AV1DecContext *s = avctx->priv_data; @@ -1077,8 +1097,7 @@ static int av1_decode_frame(AVCodecContext *avctx, void *frame, s->raw_frame_header = &obu->obu.frame_header; if (s->raw_frame_header->show_existing_frame) { - if (s->cur_frame.tf.f->buf[0]) - av1_frame_unref(avctx, &s->cur_frame); + av1_frame_unref(avctx, &s->cur_frame); ret = av1_frame_ref(avctx, &s->cur_frame, &s->ref[s->raw_frame_header->frame_to_show_map_idx]); @@ -1093,9 +1112,11 @@ static int av1_decode_frame(AVCodecContext *avctx, void *frame, goto end; } - ret = set_output_frame(avctx, frame, pkt, got_frame); - if (ret < 0) - av_log(avctx, AV_LOG_ERROR, "Set output frame error.\n"); + if (s->cur_frame.f->buf[0]) { + ret = set_output_frame(avctx, frame, pkt, got_frame); + if (ret < 0) + av_log(avctx, AV_LOG_ERROR, "Set output frame error.\n"); + } s->raw_frame_header = NULL; @@ -1111,7 +1132,7 @@ static int av1_decode_frame(AVCodecContext *avctx, void *frame, s->cur_frame.spatial_id = header->spatial_id; s->cur_frame.temporal_id = header->temporal_id; - if (avctx->hwaccel) { + if (avctx->hwaccel && s->cur_frame.f->buf[0]) { ret = avctx->hwaccel->start_frame(avctx, unit->data, unit->data_size); if (ret < 0) { @@ -1138,7 +1159,7 @@ static int av1_decode_frame(AVCodecContext *avctx, void *frame, if (ret < 0) goto end; - if (avctx->hwaccel) { + if (avctx->hwaccel && s->cur_frame.f->buf[0]) { ret = avctx->hwaccel->decode_slice(avctx, raw_tile_group->tile_data.data, raw_tile_group->tile_data.data_size); @@ -1161,7 +1182,7 @@ static int av1_decode_frame(AVCodecContext *avctx, void *frame, } if (raw_tile_group && (s->tile_num == raw_tile_group->tg_end + 1)) { - if (avctx->hwaccel) { + if (avctx->hwaccel && s->cur_frame.f->buf[0]) { ret = avctx->hwaccel->end_frame(avctx); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "HW accel end frame fail.\n"); @@ -1175,7 +1196,7 @@ static int av1_decode_frame(AVCodecContext *avctx, void *frame, goto end; } - if (s->raw_frame_header->show_frame) { + if (s->raw_frame_header->show_frame && s->cur_frame.f->buf[0]) { ret = set_output_frame(avctx, frame, pkt, got_frame); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Set output frame error\n"); @@ -1224,22 +1245,22 @@ static const AVClass av1_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_av1_decoder = { - .name = "av1", - .long_name = NULL_IF_CONFIG_SMALL("Alliance for Open Media AV1"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_AV1, +const FFCodec ff_av1_decoder = { + .p.name = "av1", + .p.long_name = NULL_IF_CONFIG_SMALL("Alliance for Open Media AV1"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_AV1, .priv_data_size = sizeof(AV1DecContext), .init = av1_decode_init, .close = av1_decode_free, - .decode = av1_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_AVOID_PROBING, + FF_CODEC_DECODE_CB(av1_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_AVOID_PROBING, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_SETS_PKT_DTS, .flush = av1_decode_flush, - .profiles = NULL_IF_CONFIG_SMALL(ff_av1_profiles), - .priv_class = &av1_class, + .p.profiles = NULL_IF_CONFIG_SMALL(ff_av1_profiles), + .p.priv_class = &av1_class, .bsfs = "av1_frame_split", .hw_configs = (const AVCodecHWConfigInternal *const []) { #if CONFIG_AV1_DXVA2_HWACCEL @@ -1257,6 +1278,10 @@ const AVCodec ff_av1_decoder = { #if CONFIG_AV1_VAAPI_HWACCEL HWACCEL_VAAPI(av1), #endif +#if CONFIG_AV1_VDPAU_HWACCEL + HWACCEL_VDPAU(av1), +#endif + NULL }, }; diff --git a/libavcodec/av1dec.h b/libavcodec/av1dec.h index 4e140588b..82c7084e9 100644 --- a/libavcodec/av1dec.h +++ b/libavcodec/av1dec.h @@ -24,14 +24,14 @@ #include #include "libavutil/buffer.h" +#include "libavutil/frame.h" #include "libavutil/pixfmt.h" #include "avcodec.h" #include "cbs.h" #include "cbs_av1.h" -#include "thread.h" typedef struct AV1Frame { - ThreadFrame tf; + AVFrame *f; AVBufferRef *hwaccel_priv_buf; void *hwaccel_picture_private; diff --git a/libavcodec/avcodec.c b/libavcodec/avcodec.c index c00a9b2af..5f6e71a39 100644 --- a/libavcodec/avcodec.c +++ b/libavcodec/avcodec.c @@ -28,42 +28,20 @@ #include "libavutil/avstring.h" #include "libavutil/bprint.h" #include "libavutil/channel_layout.h" +#include "libavutil/fifo.h" #include "libavutil/imgutils.h" #include "libavutil/mem.h" #include "libavutil/opt.h" #include "libavutil/thread.h" #include "avcodec.h" #include "bsf.h" +#include "codec_internal.h" #include "decode.h" #include "encode.h" #include "frame_thread_encoder.h" #include "internal.h" #include "thread.h" -#include "libavutil/ffversion.h" -const char av_codec_ffversion[] = "FFmpeg version " FFMPEG_VERSION; - -unsigned avcodec_version(void) -{ - av_assert0(AV_CODEC_ID_PCM_S8_PLANAR==65563); - av_assert0(AV_CODEC_ID_ADPCM_G722==69660); - av_assert0(AV_CODEC_ID_SRT==94216); - av_assert0(LIBAVCODEC_VERSION_MICRO >= 100); - - return LIBAVCODEC_VERSION_INT; -} - -const char *avcodec_configuration(void) -{ - return FFMPEG_CONFIGURATION; -} - -const char *avcodec_license(void) -{ -#define LICENSE_PREFIX "libavcodec license: " - return &LICENSE_PREFIX FFMPEG_LICENSE[sizeof(LICENSE_PREFIX) - 1]; -} - int avcodec_default_execute(AVCodecContext *c, int (*func)(AVCodecContext *c2, void *arg2), void *arg, int *ret, int count, int size) { int i; @@ -92,13 +70,13 @@ int avcodec_default_execute2(AVCodecContext *c, int (*func)(AVCodecContext *c2, static AVMutex codec_mutex = AV_MUTEX_INITIALIZER; -static void lock_avcodec(const AVCodec *codec) +static void lock_avcodec(const FFCodec *codec) { if (!(codec->caps_internal & FF_CODEC_CAP_INIT_THREADSAFE) && codec->init) ff_mutex_lock(&codec_mutex); } -static void unlock_avcodec(const AVCodec *codec) +static void unlock_avcodec(const FFCodec *codec) { if (!(codec->caps_internal & FF_CODEC_CAP_INIT_THREADSAFE) && codec->init) ff_mutex_unlock(&codec_mutex); @@ -119,7 +97,7 @@ static int64_t get_bit_rate(AVCodecContext *ctx) case AVMEDIA_TYPE_AUDIO: bits_per_sample = av_get_bits_per_sample(ctx->codec_id); if (bits_per_sample) { - bit_rate = ctx->sample_rate * (int64_t)ctx->channels; + bit_rate = ctx->sample_rate * (int64_t)ctx->ch_layout.nb_channels; if (bit_rate > INT64_MAX / bits_per_sample) { bit_rate = 0; } else @@ -138,6 +116,7 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code { int ret = 0; AVCodecInternal *avci; + const FFCodec *codec2; if (avcodec_is_open(avctx)) return 0; @@ -153,24 +132,21 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code } if (!codec) codec = avctx->codec; + codec2 = ffcodec(codec); - if ((avctx->codec_type == AVMEDIA_TYPE_UNKNOWN || avctx->codec_type == codec->type) && - avctx->codec_id == AV_CODEC_ID_NONE) { - avctx->codec_type = codec->type; - avctx->codec_id = codec->id; - } - if (avctx->codec_id != codec->id || (avctx->codec_type != codec->type && - avctx->codec_type != AVMEDIA_TYPE_ATTACHMENT)) { + if ((avctx->codec_type != AVMEDIA_TYPE_UNKNOWN && avctx->codec_type != codec->type) || + (avctx->codec_id != AV_CODEC_ID_NONE && avctx->codec_id != codec->id)) { av_log(avctx, AV_LOG_ERROR, "Codec type or id mismatches\n"); return AVERROR(EINVAL); } - avctx->codec = codec; + + avctx->codec_type = codec->type; + avctx->codec_id = codec->id; + avctx->codec = codec; if (avctx->extradata_size < 0 || avctx->extradata_size >= FF_MAX_EXTRADATA_SIZE) return AVERROR(EINVAL); - lock_avcodec(codec); - avci = av_mallocz(sizeof(*avci)); if (!avci) { ret = AVERROR(ENOMEM); @@ -180,22 +156,16 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code avci->buffer_frame = av_frame_alloc(); avci->buffer_pkt = av_packet_alloc(); - avci->es.in_frame = av_frame_alloc(); - avci->in_pkt = av_packet_alloc(); - avci->last_pkt_props = av_packet_alloc(); - avci->pkt_props = av_fifo_alloc(sizeof(*avci->last_pkt_props)); - if (!avci->buffer_frame || !avci->buffer_pkt || - !avci->es.in_frame || !avci->in_pkt || - !avci->last_pkt_props || !avci->pkt_props) { + if (!avci->buffer_frame || !avci->buffer_pkt) { ret = AVERROR(ENOMEM); goto free_and_end; } avci->skip_samples_multiplier = 1; - if (codec->priv_data_size > 0) { + if (codec2->priv_data_size > 0) { if (!avctx->priv_data) { - avctx->priv_data = av_mallocz(codec->priv_data_size); + avctx->priv_data = av_mallocz(codec2->priv_data_size); if (!avctx->priv_data) { ret = AVERROR(ENOMEM); goto free_and_end; @@ -247,12 +217,6 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code } } - if (avctx->channels > FF_SANE_NB_CHANNELS || avctx->channels < 0) { - av_log(avctx, AV_LOG_ERROR, "Too many or invalid channels: %d\n", avctx->channels); - ret = AVERROR(EINVAL); - goto free_and_end; - } - if (avctx->sample_rate < 0) { av_log(avctx, AV_LOG_ERROR, "Invalid sample rate: %d\n", avctx->sample_rate); ret = AVERROR(EINVAL); @@ -264,6 +228,31 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code goto free_and_end; } +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + /* compat wrapper for old-style callers */ + if (avctx->channel_layout && !avctx->channels) + avctx->channels = av_popcount64(avctx->channel_layout); + + if ((avctx->channels > 0 && avctx->ch_layout.nb_channels != avctx->channels) || + (avctx->channel_layout && (avctx->ch_layout.order != AV_CHANNEL_ORDER_NATIVE || + avctx->ch_layout.u.mask != avctx->channel_layout))) { + if (avctx->channel_layout) { + av_channel_layout_from_mask(&avctx->ch_layout, avctx->channel_layout); + } else { + avctx->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + avctx->ch_layout.nb_channels = avctx->channels; + } + } +FF_ENABLE_DEPRECATION_WARNINGS +#endif + + if (avctx->ch_layout.nb_channels > FF_SANE_NB_CHANNELS) { + av_log(avctx, AV_LOG_ERROR, "Too many channels: %d\n", avctx->ch_layout.nb_channels); + ret = AVERROR(EINVAL); + goto free_and_end; + } + avctx->frame_number = 0; avctx->codec_descriptor = avcodec_descriptor_get(avctx->codec_id); @@ -296,33 +285,33 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code if (ret < 0) goto free_and_end; - if (!HAVE_THREADS) - av_log(avctx, AV_LOG_WARNING, "Warning: not compiled with thread support, using thread emulation\n"); - if (CONFIG_FRAME_THREAD_ENCODER && av_codec_is_encoder(avctx->codec)) { - unlock_avcodec(codec); //we will instantiate a few encoders thus kick the counter to prevent false detection of a problem ret = ff_frame_thread_encoder_init(avctx); - lock_avcodec(codec); if (ret < 0) goto free_and_end; } if (HAVE_THREADS && !(avci->frame_thread_encoder && (avctx->active_thread_type&FF_THREAD_FRAME))) { + /* Frame-threaded decoders call FFCodec.init for their child contexts. */ + lock_avcodec(codec2); ret = ff_thread_init(avctx); + unlock_avcodec(codec2); if (ret < 0) { goto free_and_end; } } - if (!HAVE_THREADS && !(codec->caps_internal & FF_CODEC_CAP_AUTO_THREADS)) + if (!HAVE_THREADS && !(codec2->caps_internal & FF_CODEC_CAP_AUTO_THREADS)) avctx->thread_count = 1; if (!(avctx->active_thread_type & FF_THREAD_FRAME) || avci->frame_thread_encoder) { - if (avctx->codec->init) { - ret = avctx->codec->init(avctx); + if (codec2->init) { + lock_avcodec(codec2); + ret = codec2->init(avctx); + unlock_avcodec(codec2); if (ret < 0) { - avci->needs_close = avctx->codec->caps_internal & FF_CODEC_CAP_INIT_CLEANUP; + avci->needs_close = codec2->caps_internal & FF_CODEC_CAP_INIT_CLEANUP; goto free_and_end; } } @@ -334,6 +323,14 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code if (av_codec_is_decoder(avctx->codec)) { if (!avctx->bit_rate) avctx->bit_rate = get_bit_rate(avctx); + +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + /* update the deprecated fields for old-style callers */ + avctx->channels = avctx->ch_layout.nb_channels; + avctx->channel_layout = avctx->ch_layout.order == AV_CHANNEL_ORDER_NATIVE ? + avctx->ch_layout.u.mask : 0; + /* validate channel layout from the decoder */ if (avctx->channel_layout) { int channels = av_get_channel_layout_nb_channels(avctx->channel_layout); @@ -358,6 +355,8 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code ret = AVERROR(EINVAL); goto free_and_end; } +FF_ENABLE_DEPRECATION_WARNINGS +#endif #if FF_API_AVCTX_TIMEBASE if (avctx->framerate.num > 0 && avctx->framerate.den > 0) @@ -368,7 +367,6 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, const AVCodec *code av_assert0(*(const AVClass **)avctx->priv_data == codec->priv_class); end: - unlock_avcodec(codec); return ret; free_and_end: @@ -390,6 +388,19 @@ void avcodec_flush_buffers(AVCodecContext *avctx) "that doesn't support it\n"); return; } + if (avci->in_frame) + av_frame_unref(avci->in_frame); + } else { + av_packet_unref(avci->last_pkt_props); + while (av_fifo_read(avci->pkt_props, avci->last_pkt_props, 1) >= 0) + av_packet_unref(avci->last_pkt_props); + + av_packet_unref(avci->in_pkt); + + avctx->pts_correction_last_pts = + avctx->pts_correction_last_dts = INT64_MIN; + + av_bsf_flush(avci->bsf); } avci->draining = 0; @@ -398,28 +409,10 @@ void avcodec_flush_buffers(AVCodecContext *avctx) av_frame_unref(avci->buffer_frame); av_packet_unref(avci->buffer_pkt); - av_packet_unref(avci->last_pkt_props); - while (av_fifo_size(avci->pkt_props) >= sizeof(*avci->last_pkt_props)) { - av_fifo_generic_read(avci->pkt_props, - avci->last_pkt_props, sizeof(*avci->last_pkt_props), - NULL); - av_packet_unref(avci->last_pkt_props); - } - av_fifo_reset(avci->pkt_props); - - av_frame_unref(avci->es.in_frame); - av_packet_unref(avci->in_pkt); - if (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME) ff_thread_flush(avctx); - else if (avctx->codec->flush) - avctx->codec->flush(avctx); - - avctx->pts_correction_last_pts = - avctx->pts_correction_last_dts = INT64_MIN; - - if (avci->bsf) - av_bsf_flush(avci->bsf); + else if (ffcodec(avctx->codec)->flush) + ffcodec(avctx->codec)->flush(avctx); } void avsubtitle_free(AVSubtitle *sub) @@ -427,12 +420,15 @@ void avsubtitle_free(AVSubtitle *sub) int i; for (i = 0; i < sub->num_rects; i++) { - av_freep(&sub->rects[i]->data[0]); - av_freep(&sub->rects[i]->data[1]); - av_freep(&sub->rects[i]->data[2]); - av_freep(&sub->rects[i]->data[3]); - av_freep(&sub->rects[i]->text); - av_freep(&sub->rects[i]->ass); + AVSubtitleRect *const rect = sub->rects[i]; + + av_freep(&rect->data[0]); + av_freep(&rect->data[1]); + av_freep(&rect->data[2]); + av_freep(&rect->data[3]); + av_freep(&rect->text); + av_freep(&rect->ass); + av_freep(&sub->rects[i]); } @@ -457,24 +453,23 @@ av_cold int avcodec_close(AVCodecContext *avctx) } if (HAVE_THREADS && avci->thread_ctx) ff_thread_free(avctx); - if (avci->needs_close && avctx->codec->close) - avctx->codec->close(avctx); + if (avci->needs_close && ffcodec(avctx->codec)->close) + ffcodec(avctx->codec)->close(avctx); avci->byte_buffer_size = 0; av_freep(&avci->byte_buffer); av_frame_free(&avci->buffer_frame); av_packet_free(&avci->buffer_pkt); if (avci->pkt_props) { - while (av_fifo_size(avci->pkt_props) >= sizeof(*avci->last_pkt_props)) { + while (av_fifo_can_read(avci->pkt_props)) { av_packet_unref(avci->last_pkt_props); - av_fifo_generic_read(avci->pkt_props, avci->last_pkt_props, - sizeof(*avci->last_pkt_props), NULL); + av_fifo_read(avci->pkt_props, avci->last_pkt_props, 1); } - av_fifo_freep(&avci->pkt_props); + av_fifo_freep2(&avci->pkt_props); } av_packet_free(&avci->last_pkt_props); av_packet_free(&avci->in_pkt); - av_frame_free(&avci->es.in_frame); + av_frame_free(&avci->in_frame); av_buffer_unref(&avci->pool); @@ -484,6 +479,8 @@ av_cold int avcodec_close(AVCodecContext *avctx) av_bsf_free(&avci->bsf); + av_channel_layout_uninit(&avci->initial_ch_layout); + av_freep(&avctx->internal); } @@ -666,7 +663,12 @@ void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode) if (enc->sample_rate) { av_bprintf(&bprint, "%d Hz, ", enc->sample_rate); } - av_bprint_channel_layout(&bprint, enc->channels, enc->channel_layout); + { + char buf[512]; + int ret = av_channel_layout_describe(&enc->ch_layout, buf, sizeof(buf)); + if (ret >= 0) + av_bprintf(&bprint, "%s", buf); + } if (enc->sample_fmt != AV_SAMPLE_FMT_NONE && (str = av_get_sample_fmt_name(enc->sample_fmt))) { av_bprintf(&bprint, ", %s", str); diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 7ee8bc2b7..cb5c25bf6 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -43,7 +43,13 @@ #include "codec_id.h" #include "defs.h" #include "packet.h" +#include "version_major.h" +#ifndef HAVE_AV_CONFIG_H +/* When included as part of the ffmpeg build, only include the major version + * to avoid unnecessary rebuilds. When included externally, keep including + * the full version information. */ #include "version.h" +#endif /** * @defgroup libavc libavcodec @@ -990,7 +996,15 @@ typedef struct AVCodecContext { /* audio only */ int sample_rate; ///< samples per second - int channels; ///< number of audio channels + +#if FF_API_OLD_CHANNEL_LAYOUT + /** + * number of audio channels + * @deprecated use ch_layout.nb_channels + */ + attribute_deprecated + int channels; +#endif /** * audio sample format @@ -1035,19 +1049,25 @@ typedef struct AVCodecContext { */ int cutoff; +#if FF_API_OLD_CHANNEL_LAYOUT /** * Audio channel layout. * - encoding: set by user. * - decoding: set by user, may be overwritten by libavcodec. + * @deprecated use ch_layout */ + attribute_deprecated uint64_t channel_layout; /** * Request decoder to use this channel layout if it can (0 for default) * - encoding: unused * - decoding: Set by user. + * @deprecated use "downmix" codec private option */ + attribute_deprecated uint64_t request_channel_layout; +#endif /** * Type of service that the audio stream conveys. @@ -1407,7 +1427,10 @@ typedef struct AVCodecContext { #define FF_IDCT_SIMPLEARMV6 17 #define FF_IDCT_FAAN 20 #define FF_IDCT_SIMPLENEON 22 -#define FF_IDCT_NONE 24 /* Used by XvMC to extract IDCT coefficients with FF_IDCT_PERM_NONE */ +#if FF_API_IDCT_NONE +// formerly used by xvmc +#define FF_IDCT_NONE 24 +#endif #define FF_IDCT_SIMPLEAUTO 128 /** @@ -1495,7 +1518,6 @@ typedef struct AVCodecContext { * It will return only after finishing all tasks. * The user may replace this with some multithreaded implementation, * the default implementation will execute the parts serially. - * Also see avcodec_thread_init and e.g. the --enable-pthread configure option. * @param c context passed also to func * @param count the number of things to execute * @param arg2 argument passed unchanged to func @@ -2024,9 +2046,15 @@ typedef struct AVCodecContext { * - decoding: unused */ int (*get_encode_buffer)(struct AVCodecContext *s, AVPacket *pkt, int flags); -} AVCodecContext; -struct MpegEncContext; + /** + * Audio channel layout. + * - encoding: must be set by the caller, to one of AVCodec.ch_layouts. + * - decoding: may be set by the caller if known e.g. from the container. + * The decoder can then override during decoding as needed. + */ + AVChannelLayout ch_layout; +} AVCodecContext; /** * @defgroup lavc_hwaccel AVHWAccel @@ -2119,7 +2147,6 @@ typedef struct AVHWAccel { * * Meaningful slice information (codec specific) is guaranteed to * be parsed at this point. This function is mandatory. - * The only exception is XvMC, that works on MB level. * * @param avctx the codec context * @param buf the slice data buffer base @@ -2148,17 +2175,6 @@ typedef struct AVHWAccel { */ int frame_priv_data_size; - /** - * Called for every Macroblock in a slice. - * - * XvMC uses it to replace the ff_mpv_reconstruct_mb(). - * Instead of decoding to raw picture, MB parameters are - * stored in an array provided by the video driver. - * - * @param s the mpeg context - */ - void (*decode_mb)(struct MpegEncContext *s); - /** * Initialize the hwaccel private data. * @@ -2384,8 +2400,6 @@ int avcodec_parameters_to_context(AVCodecContext *codec, * avcodec_find_decoder() and avcodec_find_encoder() provide an easy way for * retrieving a codec. * - * @warning This function is not thread safe! - * * @note Always call this function before using decoding routines (such as * @ref avcodec_receive_frame()). * diff --git a/libavcodec/avpacket.c b/libavcodec/avpacket.c index 4f7a6b255..bcbc4166c 100644 --- a/libavcodec/avpacket.c +++ b/libavcodec/avpacket.c @@ -22,14 +22,12 @@ #include #include "libavutil/avassert.h" -#include "libavutil/common.h" -#include "libavutil/internal.h" +#include "libavutil/intreadwrite.h" #include "libavutil/mathematics.h" #include "libavutil/mem.h" #include "libavutil/rational.h" -#include "bytestream.h" -#include "internal.h" +#include "defs.h" #include "packet.h" #include "packet_internal.h" diff --git a/libavcodec/avrndec.c b/libavcodec/avrndec.c index 70e34c617..9bb0c1ffa 100644 --- a/libavcodec/avrndec.c +++ b/libavcodec/avrndec.c @@ -20,6 +20,7 @@ */ #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "libavutil/imgutils.h" @@ -49,11 +50,10 @@ static av_cold int init(AVCodecContext *avctx) return 0; } -static int decode_frame(AVCodecContext *avctx, void *data, +static int decode_frame(AVCodecContext *avctx, AVFrame *p, int *got_frame, AVPacket *avpkt) { AVRnContext *a = avctx->priv_data; - AVFrame *p = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; int y, ret, true_height; @@ -89,14 +89,14 @@ static int decode_frame(AVCodecContext *avctx, void *data, return buf_size; } -const AVCodec ff_avrn_decoder = { - .name = "avrn", - .long_name = NULL_IF_CONFIG_SMALL("Avid AVI Codec"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_AVRN, +const FFCodec ff_avrn_decoder = { + .p.name = "avrn", + .p.long_name = NULL_IF_CONFIG_SMALL("Avid AVI Codec"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_AVRN, .priv_data_size = sizeof(AVRnContext), .init = init, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/avs.c b/libavcodec/avs.c index 28f5f0b13..6dda3393b 100644 --- a/libavcodec/avs.c +++ b/libavcodec/avs.c @@ -20,6 +20,7 @@ */ #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" @@ -42,15 +43,13 @@ typedef enum { } AvsVideoSubType; -static int -avs_decode_frame(AVCodecContext * avctx, - void *data, int *got_frame, AVPacket *avpkt) +static int avs_decode_frame(AVCodecContext * avctx, AVFrame *picture, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; const uint8_t *buf_end = avpkt->data + avpkt->size; int buf_size = avpkt->size; AvsContext *const avs = avctx->priv_data; - AVFrame *picture = data; AVFrame *const p = avs->frame; const uint8_t *table, *vect; uint8_t *out; @@ -176,15 +175,15 @@ static av_cold int avs_decode_end(AVCodecContext *avctx) } -const AVCodec ff_avs_decoder = { - .name = "avs", - .long_name = NULL_IF_CONFIG_SMALL("AVS (Audio Video Standard) video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_AVS, +const FFCodec ff_avs_decoder = { + .p.name = "avs", + .p.long_name = NULL_IF_CONFIG_SMALL("AVS (Audio Video Standard) video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_AVS, .priv_data_size = sizeof(AvsContext), .init = avs_decode_init, - .decode = avs_decode_frame, + FF_CODEC_DECODE_CB(avs_decode_frame), .close = avs_decode_end, - .capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/avs2.c b/libavcodec/avs2.c new file mode 100644 index 000000000..ead8687d0 --- /dev/null +++ b/libavcodec/avs2.c @@ -0,0 +1,42 @@ +/* + * AVS2 related definitions + * + * Copyright (C) 2022 Zhao Zhili, + * + * 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 "avs2.h" + +const AVRational ff_avs2_frame_rate_tab[16] = { + { 0 , 0 }, // forbid + { 24000, 1001}, + { 24 , 1 }, + { 25 , 1 }, + { 30000, 1001}, + { 30 , 1 }, + { 50 , 1 }, + { 60000, 1001}, + { 60 , 1 }, + { 100 , 1 }, + { 120 , 1 }, + { 200 , 1 }, + { 240 , 1 }, + { 300 , 1 }, + { 0 , 0 }, // reserved + { 0 , 0 } // reserved +}; diff --git a/libavcodec/avs2.h b/libavcodec/avs2.h new file mode 100644 index 000000000..544cf502d --- /dev/null +++ b/libavcodec/avs2.h @@ -0,0 +1,51 @@ +/* + * AVS2 related definitions + * + * Copyright (C) 2022 Zhao Zhili, + * + * 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_AVS2_H +#define AVCODEC_AVS2_H + +#include "libavutil/rational.h" + +#define AVS2_SLICE_MAX_START_CODE 0x000001AF + +enum { + AVS2_SEQ_START_CODE = 0xB0, + AVS2_SEQ_END_CODE = 0xB1, + AVS2_USER_DATA_START_CODE = 0xB2, + AVS2_INTRA_PIC_START_CODE = 0xB3, + // reserved = 0xB4, + AVS2_EXTENSION_START_CODE = 0xB5, + AVS2_INTER_PIC_START_CODE = 0xB6, +}; + +#define AVS2_ISPIC(x) ((x) == AVS2_INTRA_PIC_START_CODE || (x) == AVS2_INTER_PIC_START_CODE) +#define AVS2_ISUNIT(x) ((x) == AVS2_SEQ_START_CODE || AVS2_ISPIC(x)) + +enum AVS2Profile { + AVS2_PROFILE_MAIN_PIC = 0x12, + AVS2_PROFILE_MAIN = 0x20, + AVS2_PROFILE_MAIN10 = 0x22, +}; + +extern const AVRational ff_avs2_frame_rate_tab[16]; + +#endif diff --git a/libavcodec/avs2_parser.c b/libavcodec/avs2_parser.c index b7d5d7774..035051749 100644 --- a/libavcodec/avs2_parser.c +++ b/libavcodec/avs2_parser.c @@ -19,13 +19,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/avutil.h" +#include "avs2.h" +#include "get_bits.h" #include "parser.h" -#define AVS2_SLICE_MAX_START_CODE 0x000001AF - -#define AVS2_ISPIC(x) ((x) == 0xB3 || (x) == 0xB6) -#define AVS2_ISUNIT(x) ((x) == 0xB0 || (x) == 0xB1 || (x) == 0xB2 || AVS2_ISPIC(x)) - static int avs2_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size) { int pic_found = pc->frame_start_found; @@ -35,7 +33,7 @@ static int avs2_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_siz if (!pic_found) { for (; cur < buf_size; ++cur) { state = (state << 8) | buf[cur]; - if (AVS2_ISUNIT(buf[cur])){ + if ((state & 0xFFFFFF00) == 0x100 && AVS2_ISPIC(buf[cur])) { cur++; pic_found = 1; break; @@ -48,7 +46,7 @@ static int avs2_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_siz return END_NOT_FOUND; for (; cur < buf_size; cur++) { state = (state << 8) | buf[cur]; - if ((state & 0xFFFFFF00) == 0x100 && state > AVS2_SLICE_MAX_START_CODE) { + if ((state & 0xFFFFFF00) == 0x100 && AVS2_ISUNIT(buf[cur])) { pc->frame_start_found = 0; pc->state = -1; return cur - 3; @@ -62,6 +60,107 @@ static int avs2_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_siz return END_NOT_FOUND; } +static void parse_avs2_seq_header(AVCodecParserContext *s, const uint8_t *buf, + int buf_size, AVCodecContext *avctx) +{ + GetBitContext gb; + int profile, level; + int width, height; + int chroma, sample_precision, encoding_precision = 1; + // sample_precision and encoding_precision is 3 bits + static const uint8_t precision[8] = { 0, 8, 10 }; + unsigned aspect_ratio; + unsigned frame_rate_code; + int low_delay; + // update buf_size_min if parse more deeper + const int buf_size_min = 15; + + if (buf_size < buf_size_min) + return; + + init_get_bits8(&gb, buf, buf_size_min); + + s->key_frame = 1; + s->pict_type = AV_PICTURE_TYPE_I; + + profile = get_bits(&gb, 8); + level = get_bits(&gb, 8); + + // progressive_sequence u(1) + // field_coded_sequence u(1) + skip_bits(&gb, 2); + + width = get_bits(&gb, 14); + height = get_bits(&gb, 14); + + chroma = get_bits(&gb, 2); + sample_precision = get_bits(&gb, 3); + if (profile == AVS2_PROFILE_MAIN10) + encoding_precision = get_bits(&gb, 3); + + aspect_ratio = get_bits(&gb, 4); + frame_rate_code = get_bits(&gb, 4); + + // bit_rate_lower u(18) + // marker_bit f(1) + // bit_rate_upper u(12) + skip_bits(&gb, 31); + + low_delay = get_bits(&gb, 1); + + s->width = width; + s->height = height; + s->coded_width = FFALIGN(width, 8); + s->coded_height = FFALIGN(height, 8); + avctx->framerate.num = avctx->time_base.den = + ff_avs2_frame_rate_tab[frame_rate_code].num; + avctx->framerate.den = avctx->time_base.num = + ff_avs2_frame_rate_tab[frame_rate_code].den; + avctx->has_b_frames = FFMAX(avctx->has_b_frames, !low_delay); + + av_log(avctx, AV_LOG_DEBUG, + "AVS2 parse seq HDR: profile %x, level %x, " + "width %d, height %d, " + "chroma %d, sample_precision %d bits, encoding_precision %d bits, " + "aspect_ratio 0x%x, framerate %d/%d, low_delay %d\n", + profile, level, + width, height, + chroma, precision[sample_precision], precision[encoding_precision], + aspect_ratio, avctx->framerate.num, avctx->framerate.den, low_delay); +} + +static void parse_avs2_units(AVCodecParserContext *s, const uint8_t *buf, + int buf_size, AVCodecContext *avctx) +{ + if (buf_size < 5) + return; + + if (!(buf[0] == 0x0 && buf[1] == 0x0 && buf[2] == 0x1)) + return; + + switch (buf[3]) { + case AVS2_SEQ_START_CODE: + parse_avs2_seq_header(s, buf + 4, buf_size - 4, avctx); + return; + case AVS2_INTRA_PIC_START_CODE: + s->key_frame = 1; + s->pict_type = AV_PICTURE_TYPE_I; + return; + case AVS2_INTER_PIC_START_CODE: + s->key_frame = 0; + if (buf_size > 9) { + int pic_code_type = buf[8] & 0x3; + if (pic_code_type == 1) + s->pict_type = AV_PICTURE_TYPE_P; + else if (pic_code_type == 3) + s->pict_type = AV_PICTURE_TYPE_S; + else + s->pict_type = AV_PICTURE_TYPE_B; + } + return; + } +} + static int avs2_parse(AVCodecParserContext *s, AVCodecContext *avctx, const uint8_t **poutbuf, int *poutbuf_size, const uint8_t *buf, int buf_size) @@ -80,6 +179,8 @@ static int avs2_parse(AVCodecParserContext *s, AVCodecContext *avctx, } } + parse_avs2_units(s, buf, buf_size, avctx); + *poutbuf = buf; *poutbuf_size = buf_size; diff --git a/libavcodec/avs3_parser.c b/libavcodec/avs3_parser.c index d04d96a03..a9fd879e9 100644 --- a/libavcodec/avs3_parser.c +++ b/libavcodec/avs3_parser.c @@ -71,7 +71,7 @@ static void parse_avs3_nal_units(AVCodecParserContext *s, const uint8_t *buf, if (buf[0] == 0x0 && buf[1] == 0x0 && buf[2] == 0x1) { if (buf[3] == AVS3_SEQ_START_CODE) { GetBitContext gb; - int profile, ratecode; + int profile, ratecode, low_delay; init_get_bits8(&gb, buf + 4, buf_size - 4); @@ -114,7 +114,8 @@ static void parse_avs3_nal_units(AVCodecParserContext *s, const uint8_t *buf, // bitrate_high(12) skip_bits(&gb, 32); - avctx->has_b_frames = !get_bits(&gb, 1); + low_delay = get_bits(&gb, 1); + avctx->has_b_frames = FFMAX(avctx->has_b_frames, !low_delay); avctx->framerate.num = avctx->time_base.den = ff_avs3_frame_rate_tab[ratecode].num; avctx->framerate.den = avctx->time_base.num = ff_avs3_frame_rate_tab[ratecode].den; diff --git a/libavcodec/avuidec.c b/libavcodec/avuidec.c index f7172845c..f545c4115 100644 --- a/libavcodec/avuidec.c +++ b/libavcodec/avuidec.c @@ -21,6 +21,7 @@ */ #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "libavutil/intreadwrite.h" @@ -30,11 +31,10 @@ static av_cold int avui_decode_init(AVCodecContext *avctx) return 0; } -static int avui_decode_frame(AVCodecContext *avctx, void *data, +static int avui_decode_frame(AVCodecContext *avctx, AVFrame *pic, int *got_frame, AVPacket *avpkt) { int ret; - AVFrame *pic = data; const uint8_t *src = avpkt->data, *extradata = avctx->extradata; const uint8_t *srca; uint8_t *y, *u, *v, *a; @@ -119,13 +119,13 @@ static int avui_decode_frame(AVCodecContext *avctx, void *data, return avpkt->size; } -const AVCodec ff_avui_decoder = { - .name = "avui", - .long_name = NULL_IF_CONFIG_SMALL("Avid Meridien Uncompressed"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_AVUI, +const FFCodec ff_avui_decoder = { + .p.name = "avui", + .p.long_name = NULL_IF_CONFIG_SMALL("Avid Meridien Uncompressed"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_AVUI, + .p.capabilities = AV_CODEC_CAP_DR1, .init = avui_decode_init, - .decode = avui_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(avui_decode_frame), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/avuienc.c b/libavcodec/avuienc.c index dac56d1ae..e2bd3181f 100644 --- a/libavcodec/avuienc.c +++ b/libavcodec/avuienc.c @@ -21,8 +21,8 @@ */ #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "libavutil/intreadwrite.h" static av_cold int avui_encode_init(AVCodecContext *avctx) @@ -91,14 +91,14 @@ static int avui_encode_frame(AVCodecContext *avctx, AVPacket *pkt, return 0; } -const AVCodec ff_avui_encoder = { - .name = "avui", - .long_name = NULL_IF_CONFIG_SMALL("Avid Meridien Uncompressed"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_AVUI, +const FFCodec ff_avui_encoder = { + .p.name = "avui", + .p.long_name = NULL_IF_CONFIG_SMALL("Avid Meridien Uncompressed"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_AVUI, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_EXPERIMENTAL, + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_UYVY422, AV_PIX_FMT_NONE }, .init = avui_encode_init, - .encode2 = avui_encode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_EXPERIMENTAL, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_UYVY422, AV_PIX_FMT_NONE }, + FF_CODEC_ENCODE_CB(avui_encode_frame), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/bethsoftvideo.c b/libavcodec/bethsoftvideo.c index b529aba7e..9fc286fb0 100644 --- a/libavcodec/bethsoftvideo.c +++ b/libavcodec/bethsoftvideo.c @@ -31,6 +31,7 @@ #include "avcodec.h" #include "bethsoftvideo.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" typedef struct BethsoftvidContext { @@ -66,9 +67,8 @@ static int set_palette(BethsoftvidContext *ctx) return 0; } -static int bethsoftvid_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int bethsoftvid_decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *avpkt) { BethsoftvidContext * vid = avctx->priv_data; char block_type; @@ -143,7 +143,7 @@ static int bethsoftvid_decode_frame(AVCodecContext *avctx, } end: - if ((ret = av_frame_ref(data, vid->frame)) < 0) + if ((ret = av_frame_ref(rframe, vid->frame)) < 0) return ret; *got_frame = 1; @@ -158,15 +158,15 @@ static av_cold int bethsoftvid_decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_bethsoftvid_decoder = { - .name = "bethsoftvid", - .long_name = NULL_IF_CONFIG_SMALL("Bethesda VID video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_BETHSOFTVID, +const FFCodec ff_bethsoftvid_decoder = { + .p.name = "bethsoftvid", + .p.long_name = NULL_IF_CONFIG_SMALL("Bethesda VID video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_BETHSOFTVID, .priv_data_size = sizeof(BethsoftvidContext), .init = bethsoftvid_decode_init, .close = bethsoftvid_decode_end, - .decode = bethsoftvid_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(bethsoftvid_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/bfi.c b/libavcodec/bfi.c index 78685e877..6f9fbb0e9 100644 --- a/libavcodec/bfi.c +++ b/libavcodec/bfi.c @@ -29,6 +29,7 @@ #include "libavutil/common.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" typedef struct BFIContext { @@ -47,10 +48,9 @@ static av_cold int bfi_decode_init(AVCodecContext *avctx) return 0; } -static int bfi_decode_frame(AVCodecContext *avctx, void *data, +static int bfi_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt) { - AVFrame *frame = data; GetByteContext g; int buf_size = avpkt->size; BFIContext *bfi = avctx->priv_data; @@ -175,15 +175,15 @@ static av_cold int bfi_decode_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_bfi_decoder = { - .name = "bfi", - .long_name = NULL_IF_CONFIG_SMALL("Brute Force & Ignorance"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_BFI, +const FFCodec ff_bfi_decoder = { + .p.name = "bfi", + .p.long_name = NULL_IF_CONFIG_SMALL("Brute Force & Ignorance"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_BFI, .priv_data_size = sizeof(BFIContext), .init = bfi_decode_init, .close = bfi_decode_close, - .decode = bfi_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(bfi_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/bink.c b/libavcodec/bink.c index 45dd8d156..ae2c65f19 100644 --- a/libavcodec/bink.c +++ b/libavcodec/bink.c @@ -31,6 +31,7 @@ #include "binkdata.h" #include "binkdsp.h" #include "blockdsp.h" +#include "codec_internal.h" #include "get_bits.h" #include "hpeldsp.h" #include "internal.h" @@ -1252,10 +1253,10 @@ end: return 0; } -static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *pkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *pkt) { BinkContext * const c = avctx->priv_data; - AVFrame *frame = data; GetBitContext gb; int plane, plane_idx, ret; int bits_count = pkt->size << 3; @@ -1313,7 +1314,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPac static av_cold void bink_init_vlcs(void) { for (int i = 0, offset = 0; i < 16; i++) { - static VLC_TYPE table[976][2]; + static VLCElem table[976]; const int maxbits = bink_tree_lens[i][15]; bink_trees[i].table = table + offset; bink_trees[i].table_allocated = 1 << maxbits; @@ -1418,16 +1419,16 @@ static void flush(AVCodecContext *avctx) c->frame_num = 0; } -const AVCodec ff_bink_decoder = { - .name = "binkvideo", - .long_name = NULL_IF_CONFIG_SMALL("Bink video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_BINKVIDEO, +const FFCodec ff_bink_decoder = { + .p.name = "binkvideo", + .p.long_name = NULL_IF_CONFIG_SMALL("Bink video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_BINKVIDEO, .priv_data_size = sizeof(BinkContext), .init = decode_init, .close = decode_end, - .decode = decode_frame, + FF_CODEC_DECODE_CB(decode_frame), .flush = flush, - .capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/binkaudio.c b/libavcodec/binkaudio.c index f808141ba..8bac8e03f 100644 --- a/libavcodec/binkaudio.c +++ b/libavcodec/binkaudio.c @@ -28,6 +28,8 @@ * http://wiki.multimedia.cx/index.php?title=Bink_Audio */ +#include "config_components.h" + #include "libavutil/channel_layout.h" #include "libavutil/intfloat.h" #include "libavutil/mem_internal.h" @@ -37,10 +39,12 @@ #include "dct.h" #include "decode.h" #include "get_bits.h" +#include "codec_internal.h" #include "internal.h" #include "rdft.h" #include "wma_freqs.h" +#define MAX_DCT_CHANNELS 6 #define MAX_CHANNELS 2 #define BINK_BLOCK_MAX_SIZE (MAX_CHANNELS << 11) @@ -49,13 +53,14 @@ typedef struct BinkAudioContext { int version_b; ///< Bink version 'b' int first; int channels; + int ch_offset; int frame_len; ///< transform size (samples) int overlap_len; ///< overlap size (samples) int block_size; int num_bands; float root; unsigned int bands[26]; - float previous[MAX_CHANNELS][BINK_BLOCK_MAX_SIZE / 16]; ///< coeffs from previous audio block + float previous[MAX_DCT_CHANNELS][BINK_BLOCK_MAX_SIZE / 16]; ///< coeffs from previous audio block float quant_table[96]; AVPacket *pkt; union { @@ -72,6 +77,8 @@ static av_cold int decode_init(AVCodecContext *avctx) int sample_rate_half; int i, ret; int frame_len_bits; + int max_channels = avctx->codec->id == AV_CODEC_ID_BINKAUDIO_RDFT ? MAX_CHANNELS : MAX_DCT_CHANNELS; + int channels = avctx->ch_layout.nb_channels; /* determine frame length */ if (avctx->sample_rate < 22050) { @@ -82,32 +89,32 @@ static av_cold int decode_init(AVCodecContext *avctx) frame_len_bits = 11; } - if (avctx->channels < 1 || avctx->channels > MAX_CHANNELS) { - av_log(avctx, AV_LOG_ERROR, "invalid number of channels: %d\n", avctx->channels); + if (channels < 1 || channels > max_channels) { + av_log(avctx, AV_LOG_ERROR, "invalid number of channels: %d\n", channels); return AVERROR_INVALIDDATA; } - avctx->channel_layout = avctx->channels == 1 ? AV_CH_LAYOUT_MONO : - AV_CH_LAYOUT_STEREO; + av_channel_layout_uninit(&avctx->ch_layout); + av_channel_layout_default(&avctx->ch_layout, channels); s->version_b = avctx->extradata_size >= 4 && avctx->extradata[3] == 'b'; if (avctx->codec->id == AV_CODEC_ID_BINKAUDIO_RDFT) { // audio is already interleaved for the RDFT format variant avctx->sample_fmt = AV_SAMPLE_FMT_FLT; - if (sample_rate > INT_MAX / avctx->channels) + if (sample_rate > INT_MAX / channels) return AVERROR_INVALIDDATA; - sample_rate *= avctx->channels; + sample_rate *= channels; s->channels = 1; if (!s->version_b) - frame_len_bits += av_log2(avctx->channels); + frame_len_bits += av_log2(channels); } else { - s->channels = avctx->channels; + s->channels = channels; avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; } s->frame_len = 1 << frame_len_bits; s->overlap_len = s->frame_len / 16; - s->block_size = (s->frame_len - s->overlap_len) * s->channels; + s->block_size = (s->frame_len - s->overlap_len) * FFMIN(MAX_CHANNELS, s->channels); sample_rate_half = (sample_rate + 1LL) / 2; if (avctx->codec->id == AV_CODEC_ID_BINKAUDIO_RDFT) s->root = 2.0 / (sqrt(s->frame_len) * 32768.0); @@ -163,7 +170,8 @@ static const uint8_t rle_length_tab[16] = { * @param[out] out Output buffer (must contain s->block_size elements) * @return 0 on success, negative error code on failure */ -static int decode_block(BinkAudioContext *s, float **out, int use_dct) +static int decode_block(BinkAudioContext *s, float **out, int use_dct, + int channels, int ch_offset) { int ch, i, j, k; float q, quant[25]; @@ -173,8 +181,8 @@ static int decode_block(BinkAudioContext *s, float **out, int use_dct) if (use_dct) skip_bits(gb, 2); - for (ch = 0; ch < s->channels; ch++) { - FFTSample *coeffs = out[ch]; + for (ch = 0; ch < channels; ch++) { + FFTSample *coeffs = out[ch + ch_offset]; if (s->version_b) { if (get_bits_left(gb) < 64) @@ -249,17 +257,17 @@ static int decode_block(BinkAudioContext *s, float **out, int use_dct) s->trans.rdft.rdft_calc(&s->trans.rdft, coeffs); } - for (ch = 0; ch < s->channels; ch++) { + for (ch = 0; ch < channels; ch++) { int j; - int count = s->overlap_len * s->channels; + int count = s->overlap_len * channels; if (!s->first) { j = ch; - for (i = 0; i < s->overlap_len; i++, j += s->channels) - out[ch][i] = (s->previous[ch][i] * (count - j) + - out[ch][i] * j) / count; + for (i = 0; i < s->overlap_len; i++, j += channels) + out[ch + ch_offset][i] = (s->previous[ch + ch_offset][i] * (count - j) + + out[ch + ch_offset][i] * j) / count; } - memcpy(s->previous[ch], &out[ch][s->frame_len - s->overlap_len], - s->overlap_len * sizeof(*s->previous[ch])); + memcpy(s->previous[ch + ch_offset], &out[ch + ch_offset][s->frame_len - s->overlap_len], + s->overlap_len * sizeof(*s->previous[ch + ch_offset])); } s->first = 0; @@ -290,10 +298,13 @@ static int binkaudio_receive_frame(AVCodecContext *avctx, AVFrame *frame) GetBitContext *gb = &s->gb; int ret; +again: if (!s->pkt->data) { ret = ff_decode_get_packet(avctx, s->pkt); - if (ret < 0) + if (ret < 0) { + s->ch_offset = 0; return ret; + } if (s->pkt->size < 4) { av_log(avctx, AV_LOG_ERROR, "Packet is too small\n"); @@ -310,25 +321,36 @@ static int binkaudio_receive_frame(AVCodecContext *avctx, AVFrame *frame) } /* get output buffer */ - frame->nb_samples = s->frame_len; - if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) - return ret; + if (s->ch_offset == 0) { + frame->nb_samples = s->frame_len; + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + } if (decode_block(s, (float **)frame->extended_data, - avctx->codec->id == AV_CODEC_ID_BINKAUDIO_DCT)) { + avctx->codec->id == AV_CODEC_ID_BINKAUDIO_DCT, + FFMIN(MAX_CHANNELS, s->channels - s->ch_offset), s->ch_offset)) { av_log(avctx, AV_LOG_ERROR, "Incomplete packet\n"); + s->ch_offset = 0; return AVERROR_INVALIDDATA; } + s->ch_offset += MAX_CHANNELS; get_bits_align32(gb); if (!get_bits_left(gb)) { memset(gb, 0, sizeof(*gb)); av_packet_unref(s->pkt); } + if (s->ch_offset >= s->channels) { + s->ch_offset = 0; + } else { + goto again; + } - frame->nb_samples = s->block_size / avctx->channels; + frame->nb_samples = s->block_size / FFMIN(avctx->ch_layout.nb_channels, MAX_CHANNELS); return 0; fail: + s->ch_offset = 0; av_packet_unref(s->pkt); return ret; } @@ -340,32 +362,33 @@ static void decode_flush(AVCodecContext *avctx) /* s->pkt coincides with avctx->internal->in_pkt * and is unreferenced generically when flushing. */ s->first = 1; + s->ch_offset = 0; } -const AVCodec ff_binkaudio_rdft_decoder = { - .name = "binkaudio_rdft", - .long_name = NULL_IF_CONFIG_SMALL("Bink Audio (RDFT)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_BINKAUDIO_RDFT, +const FFCodec ff_binkaudio_rdft_decoder = { + .p.name = "binkaudio_rdft", + .p.long_name = NULL_IF_CONFIG_SMALL("Bink Audio (RDFT)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_BINKAUDIO_RDFT, .priv_data_size = sizeof(BinkAudioContext), .init = decode_init, .flush = decode_flush, .close = decode_end, - .receive_frame = binkaudio_receive_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_RECEIVE_FRAME_CB(binkaudio_receive_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; -const AVCodec ff_binkaudio_dct_decoder = { - .name = "binkaudio_dct", - .long_name = NULL_IF_CONFIG_SMALL("Bink Audio (DCT)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_BINKAUDIO_DCT, +const FFCodec ff_binkaudio_dct_decoder = { + .p.name = "binkaudio_dct", + .p.long_name = NULL_IF_CONFIG_SMALL("Bink Audio (DCT)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_BINKAUDIO_DCT, .priv_data_size = sizeof(BinkAudioContext), .init = decode_init, .flush = decode_flush, .close = decode_end, - .receive_frame = binkaudio_receive_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_RECEIVE_FRAME_CB(binkaudio_receive_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/bintext.c b/libavcodec/bintext.c index 553f02073..e153198c3 100644 --- a/libavcodec/bintext.c +++ b/libavcodec/bintext.c @@ -28,11 +28,14 @@ * iCEDraw File decoder */ +#include "config_components.h" + #include "libavutil/intreadwrite.h" #include "libavutil/xga_font_data.h" #include "avcodec.h" #include "cga_data.h" #include "bintext.h" +#include "codec_internal.h" #include "internal.h" #define FONT_WIDTH 8 @@ -137,9 +140,8 @@ static void draw_char(AVCodecContext *avctx, int c, int a) } } -static int decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { XbinContext *s = avctx->priv_data; const uint8_t *buf = avpkt->data; @@ -150,7 +152,7 @@ static int decode_frame(AVCodecContext *avctx, if ((avctx->width / FONT_WIDTH) * (avctx->height / s->font_height) / 256 > buf_size) return AVERROR_INVALIDDATA; - s->frame = data; + s->frame = frame; s->x = s->y = 0; if ((ret = ff_get_buffer(avctx, s->frame, 0)) < 0) return ret; @@ -215,41 +217,41 @@ static int decode_frame(AVCodecContext *avctx, } #if CONFIG_BINTEXT_DECODER -const AVCodec ff_bintext_decoder = { - .name = "bintext", - .long_name = NULL_IF_CONFIG_SMALL("Binary text"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_BINTEXT, +const FFCodec ff_bintext_decoder = { + .p.name = "bintext", + .p.long_name = NULL_IF_CONFIG_SMALL("Binary text"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_BINTEXT, .priv_data_size = sizeof(XbinContext), .init = decode_init, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_XBIN_DECODER -const AVCodec ff_xbin_decoder = { - .name = "xbin", - .long_name = NULL_IF_CONFIG_SMALL("eXtended BINary text"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_XBIN, +const FFCodec ff_xbin_decoder = { + .p.name = "xbin", + .p.long_name = NULL_IF_CONFIG_SMALL("eXtended BINary text"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_XBIN, .priv_data_size = sizeof(XbinContext), .init = decode_init, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_IDF_DECODER -const AVCodec ff_idf_decoder = { - .name = "idf", - .long_name = NULL_IF_CONFIG_SMALL("iCEDraw text"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_IDF, +const FFCodec ff_idf_decoder = { + .p.name = "idf", + .p.long_name = NULL_IF_CONFIG_SMALL("iCEDraw text"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_IDF, .priv_data_size = sizeof(XbinContext), .init = decode_init, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif diff --git a/libavcodec/bitpacked_dec.c b/libavcodec/bitpacked_dec.c index 69fea9c36..4723a3c7e 100644 --- a/libavcodec/bitpacked_dec.c +++ b/libavcodec/bitpacked_dec.c @@ -27,7 +27,7 @@ */ #include "avcodec.h" -#include "internal.h" +#include "codec_internal.h" #include "get_bits.h" #include "libavutil/imgutils.h" #include "thread.h" @@ -65,12 +65,11 @@ static int bitpacked_decode_yuv422p10(AVCodecContext *avctx, AVFrame *frame, { uint64_t frame_size = (uint64_t)avctx->width * (uint64_t)avctx->height * 20; uint64_t packet_size = (uint64_t)avpkt->size * 8; - ThreadFrame tframe = { .f = frame }; GetBitContext bc; uint16_t *y, *u, *v; int ret, i, j; - ret = ff_thread_get_buffer(avctx, &tframe, 0); + ret = ff_thread_get_buffer(avctx, frame, 0); if (ret < 0) return ret; @@ -123,12 +122,11 @@ static av_cold int bitpacked_init_decoder(AVCodecContext *avctx) return 0; } -static int bitpacked_decode(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int bitpacked_decode(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { struct BitpackedContext *bc = avctx->priv_data; int buf_size = avpkt->size; - AVFrame *frame = data; int res; res = bc->decode(avctx, frame, avpkt); @@ -143,15 +141,15 @@ static int bitpacked_decode(AVCodecContext *avctx, void *data, int *got_frame, } -const AVCodec ff_bitpacked_decoder = { - .name = "bitpacked", - .long_name = NULL_IF_CONFIG_SMALL("Bitpacked"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_BITPACKED, +const FFCodec ff_bitpacked_decoder = { + .p.name = "bitpacked", + .p.long_name = NULL_IF_CONFIG_SMALL("Bitpacked"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_BITPACKED, + .p.capabilities = AV_CODEC_CAP_FRAME_THREADS, .priv_data_size = sizeof(struct BitpackedContext), .init = bitpacked_init_decoder, - .decode = bitpacked_decode, - .capabilities = AV_CODEC_CAP_FRAME_THREADS, + FF_CODEC_DECODE_CB(bitpacked_decode), .codec_tags = (const uint32_t []){ MKTAG('U', 'Y', 'V', 'Y'), FF_CODEC_TAGS_END, diff --git a/libavcodec/bitpacked_enc.c b/libavcodec/bitpacked_enc.c index 6f540f1ae..127f1af59 100644 --- a/libavcodec/bitpacked_enc.c +++ b/libavcodec/bitpacked_enc.c @@ -21,6 +21,7 @@ */ #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" #include "internal.h" #include "put_bits.h" @@ -103,16 +104,16 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, return 0; } -const AVCodec ff_bitpacked_encoder = { - .name = "bitpacked", - .long_name = NULL_IF_CONFIG_SMALL("Bitpacked"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_BITPACKED, +const FFCodec ff_bitpacked_encoder = { + .p.name = "bitpacked", + .p.long_name = NULL_IF_CONFIG_SMALL("Bitpacked"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_BITPACKED, .priv_data_size = sizeof(struct BitpackedContext), - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, .init = encode_init, - .encode2 = encode_frame, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV422P10, + FF_CODEC_ENCODE_CB(encode_frame), + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV422P10, AV_PIX_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/bitstream.c b/libavcodec/bitstream.c index 1f77cafae..360657505 100644 --- a/libavcodec/bitstream.c +++ b/libavcodec/bitstream.c @@ -28,33 +28,13 @@ * bitstream api. */ -#include #include -#include #include #include "config.h" #include "libavutil/avassert.h" -#include "libavutil/bswap.h" -#include "libavutil/common.h" -#include "libavutil/error.h" -#include "libavutil/internal.h" #include "libavutil/intreadwrite.h" -#include "libavutil/log.h" -#include "libavutil/mem.h" -#include "libavutil/qsort.h" -#include "mathops.h" #include "put_bits.h" -#include "vlc.h" - -const uint8_t ff_log2_run[41]={ - 0, 0, 0, 0, 1, 1, 1, 1, - 2, 2, 2, 2, 3, 3, 3, 3, - 4, 4, 5, 5, 6, 6, 7, 7, - 8, 9,10,11,12,13,14,15, -16,17,18,19,20,21,22,23, -24, -}; void ff_put_string(PutBitContext *pb, const char *string, int terminate_string) { @@ -90,345 +70,3 @@ void ff_copy_bits(PutBitContext *pb, const uint8_t *src, int length) put_bits(pb, bits, AV_RB16(src + 2 * words) >> (16 - bits)); } - -/* VLC decoding */ - -#define GET_DATA(v, table, i, wrap, size) \ -{ \ - const uint8_t *ptr = (const uint8_t *)table + i * wrap; \ - switch(size) { \ - case 1: \ - v = *(const uint8_t *)ptr; \ - break; \ - case 2: \ - v = *(const uint16_t *)ptr; \ - break; \ - case 4: \ - default: \ - av_assert1(size == 4); \ - v = *(const uint32_t *)ptr; \ - break; \ - } \ -} - - -static int alloc_table(VLC *vlc, int size, int use_static) -{ - int index = vlc->table_size; - - vlc->table_size += size; - if (vlc->table_size > vlc->table_allocated) { - if (use_static) - abort(); // cannot do anything, init_vlc() is used with too little memory - vlc->table_allocated += (1 << vlc->bits); - vlc->table = av_realloc_f(vlc->table, vlc->table_allocated, sizeof(VLC_TYPE) * 2); - if (!vlc->table) { - vlc->table_allocated = 0; - vlc->table_size = 0; - return AVERROR(ENOMEM); - } - memset(vlc->table + vlc->table_allocated - (1 << vlc->bits), 0, sizeof(VLC_TYPE) * 2 << vlc->bits); - } - return index; -} - -#define LOCALBUF_ELEMS 1500 // the maximum currently needed is 1296 by rv34 - -typedef struct VLCcode { - uint8_t bits; - VLC_TYPE symbol; - /** codeword, with the first bit-to-be-read in the msb - * (even if intended for a little-endian bitstream reader) */ - uint32_t code; -} VLCcode; - -static int vlc_common_init(VLC *vlc_arg, int nb_bits, int nb_codes, - VLC **vlc, VLC *localvlc, VLCcode **buf, - int flags) -{ - *vlc = vlc_arg; - (*vlc)->bits = nb_bits; - if (flags & INIT_VLC_USE_NEW_STATIC) { - av_assert0(nb_codes <= LOCALBUF_ELEMS); - *localvlc = *vlc_arg; - *vlc = localvlc; - (*vlc)->table_size = 0; - } else { - (*vlc)->table = NULL; - (*vlc)->table_allocated = 0; - (*vlc)->table_size = 0; - } - if (nb_codes > LOCALBUF_ELEMS) { - *buf = av_malloc_array(nb_codes, sizeof(VLCcode)); - if (!*buf) - return AVERROR(ENOMEM); - } - - return 0; -} - -static int compare_vlcspec(const void *a, const void *b) -{ - const VLCcode *sa = a, *sb = b; - return (sa->code >> 1) - (sb->code >> 1); -} -/** - * Build VLC decoding tables suitable for use with get_vlc(). - * - * @param vlc the context to be initialized - * - * @param table_nb_bits max length of vlc codes to store directly in this table - * (Longer codes are delegated to subtables.) - * - * @param nb_codes number of elements in codes[] - * - * @param codes descriptions of the vlc codes - * These must be ordered such that codes going into the same subtable are contiguous. - * Sorting by VLCcode.code is sufficient, though not necessary. - */ -static int build_table(VLC *vlc, int table_nb_bits, int nb_codes, - VLCcode *codes, int flags) -{ - int table_size, table_index, index, code_prefix, symbol, subtable_bits; - int i, j, k, n, nb, inc; - uint32_t code; - volatile VLC_TYPE (* volatile table)[2]; // the double volatile is needed to prevent an internal compiler error in gcc 4.2 - - if (table_nb_bits > 30) - return AVERROR(EINVAL); - table_size = 1 << table_nb_bits; - table_index = alloc_table(vlc, table_size, flags & INIT_VLC_USE_NEW_STATIC); - ff_dlog(NULL, "new table index=%d size=%d\n", table_index, table_size); - if (table_index < 0) - return table_index; - table = (volatile VLC_TYPE (*)[2])&vlc->table[table_index]; - - /* first pass: map codes and compute auxiliary table sizes */ - for (i = 0; i < nb_codes; i++) { - n = codes[i].bits; - code = codes[i].code; - symbol = codes[i].symbol; - ff_dlog(NULL, "i=%d n=%d code=0x%"PRIx32"\n", i, n, code); - if (n <= table_nb_bits) { - /* no need to add another table */ - j = code >> (32 - table_nb_bits); - nb = 1 << (table_nb_bits - n); - inc = 1; - if (flags & INIT_VLC_OUTPUT_LE) { - j = bitswap_32(code); - inc = 1 << n; - } - for (k = 0; k < nb; k++) { - int bits = table[j][1]; - int oldsym = table[j][0]; - ff_dlog(NULL, "%4x: code=%d n=%d\n", j, i, n); - if ((bits || oldsym) && (bits != n || oldsym != symbol)) { - av_log(NULL, AV_LOG_ERROR, "incorrect codes\n"); - return AVERROR_INVALIDDATA; - } - table[j][1] = n; //bits - table[j][0] = symbol; - j += inc; - } - } else { - /* fill auxiliary table recursively */ - n -= table_nb_bits; - code_prefix = code >> (32 - table_nb_bits); - subtable_bits = n; - codes[i].bits = n; - codes[i].code = code << table_nb_bits; - for (k = i+1; k < nb_codes; k++) { - n = codes[k].bits - table_nb_bits; - if (n <= 0) - break; - code = codes[k].code; - if (code >> (32 - table_nb_bits) != code_prefix) - break; - codes[k].bits = n; - codes[k].code = code << table_nb_bits; - subtable_bits = FFMAX(subtable_bits, n); - } - subtable_bits = FFMIN(subtable_bits, table_nb_bits); - j = (flags & INIT_VLC_OUTPUT_LE) ? bitswap_32(code_prefix) >> (32 - table_nb_bits) : code_prefix; - table[j][1] = -subtable_bits; - ff_dlog(NULL, "%4x: n=%d (subtable)\n", - j, codes[i].bits + table_nb_bits); - index = build_table(vlc, subtable_bits, k-i, codes+i, flags); - if (index < 0) - return index; - /* note: realloc has been done, so reload tables */ - table = (volatile VLC_TYPE (*)[2])&vlc->table[table_index]; - table[j][0] = index; //code - if (table[j][0] != index) { - avpriv_request_sample(NULL, "strange codes"); - return AVERROR_PATCHWELCOME; - } - i = k-1; - } - } - - for (i = 0; i < table_size; i++) { - if (table[i][1] == 0) //bits - table[i][0] = -1; //codes - } - - return table_index; -} - -static int vlc_common_end(VLC *vlc, int nb_bits, int nb_codes, VLCcode *codes, - int flags, VLC *vlc_arg, VLCcode localbuf[LOCALBUF_ELEMS]) -{ - int ret = build_table(vlc, nb_bits, nb_codes, codes, flags); - - if (flags & INIT_VLC_USE_NEW_STATIC) { - if (vlc->table_size != vlc->table_allocated && - !(flags & (INIT_VLC_STATIC_OVERLONG & ~INIT_VLC_USE_NEW_STATIC))) - av_log(NULL, AV_LOG_ERROR, "needed %d had %d\n", vlc->table_size, vlc->table_allocated); - av_assert0(ret >= 0); - *vlc_arg = *vlc; - } else { - if (codes != localbuf) - av_free(codes); - if (ret < 0) { - av_freep(&vlc->table); - return ret; - } - } - return 0; -} - -/* Build VLC decoding tables suitable for use with get_vlc(). - - 'nb_bits' sets the decoding table size (2^nb_bits) entries. The - bigger it is, the faster is the decoding. But it should not be too - big to save memory and L1 cache. '9' is a good compromise. - - 'nb_codes' : number of vlcs codes - - 'bits' : table which gives the size (in bits) of each vlc code. - - 'codes' : table which gives the bit pattern of of each vlc code. - - 'symbols' : table which gives the values to be returned from get_vlc(). - - 'xxx_wrap' : give the number of bytes between each entry of the - 'bits' or 'codes' tables. - - 'xxx_size' : gives the number of bytes of each entry of the 'bits' - or 'codes' tables. Currently 1,2 and 4 are supported. - - 'wrap' and 'size' make it possible to use any memory configuration and types - (byte/word/long) to store the 'bits', 'codes', and 'symbols' tables. -*/ -int ff_init_vlc_sparse(VLC *vlc_arg, int nb_bits, int nb_codes, - const void *bits, int bits_wrap, int bits_size, - const void *codes, int codes_wrap, int codes_size, - const void *symbols, int symbols_wrap, int symbols_size, - int flags) -{ - VLCcode localbuf[LOCALBUF_ELEMS], *buf = localbuf; - int i, j, ret; - VLC localvlc, *vlc; - - ret = vlc_common_init(vlc_arg, nb_bits, nb_codes, &vlc, &localvlc, - &buf, flags); - if (ret < 0) - return ret; - - av_assert0(symbols_size <= 2 || !symbols); - j = 0; -#define COPY(condition)\ - for (i = 0; i < nb_codes; i++) { \ - unsigned len; \ - GET_DATA(len, bits, i, bits_wrap, bits_size); \ - if (!(condition)) \ - continue; \ - if (len > 3*nb_bits || len > 32) { \ - av_log(NULL, AV_LOG_ERROR, "Too long VLC (%u) in init_vlc\n", len);\ - if (buf != localbuf) \ - av_free(buf); \ - return AVERROR(EINVAL); \ - } \ - buf[j].bits = len; \ - GET_DATA(buf[j].code, codes, i, codes_wrap, codes_size); \ - if (buf[j].code >= (1LL< nb_bits); - // qsort is the slowest part of init_vlc, and could probably be improved or avoided - AV_QSORT(buf, j, struct VLCcode, compare_vlcspec); - COPY(len && len <= nb_bits); - nb_codes = j; - - return vlc_common_end(vlc, nb_bits, nb_codes, buf, - flags, vlc_arg, localbuf); -} - -int ff_init_vlc_from_lengths(VLC *vlc_arg, int nb_bits, int nb_codes, - const int8_t *lens, int lens_wrap, - const void *symbols, int symbols_wrap, int symbols_size, - int offset, int flags, void *logctx) -{ - VLCcode localbuf[LOCALBUF_ELEMS], *buf = localbuf; - VLC localvlc, *vlc; - uint64_t code; - int ret, j, len_max = FFMIN(32, 3 * nb_bits); - - ret = vlc_common_init(vlc_arg, nb_bits, nb_codes, &vlc, &localvlc, - &buf, flags); - if (ret < 0) - return ret; - - j = code = 0; - for (int i = 0; i < nb_codes; i++, lens += lens_wrap) { - int len = *lens; - if (len > 0) { - unsigned sym; - - buf[j].bits = len; - if (symbols) - GET_DATA(sym, symbols, i, symbols_wrap, symbols_size) - else - sym = i; - buf[j].symbol = sym + offset; - buf[j++].code = code; - } else if (len < 0) { - len = -len; - } else - continue; - if (len > len_max || code & ((1U << (32 - len)) - 1)) { - av_log(logctx, AV_LOG_ERROR, "Invalid VLC (length %u)\n", len); - goto fail; - } - code += 1U << (32 - len); - if (code > UINT32_MAX + 1ULL) { - av_log(logctx, AV_LOG_ERROR, "Overdetermined VLC tree\n"); - goto fail; - } - } - return vlc_common_end(vlc, nb_bits, j, buf, - flags, vlc_arg, localbuf); -fail: - if (buf != localbuf) - av_free(buf); - return AVERROR_INVALIDDATA; -} - -void ff_free_vlc(VLC *vlc) -{ - av_freep(&vlc->table); -} diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c index d56528639..444423ae9 100644 --- a/libavcodec/bitstream_filters.c +++ b/libavcodec/bitstream_filters.c @@ -24,55 +24,58 @@ #include "bsf.h" #include "bsf_internal.h" -extern const AVBitStreamFilter ff_aac_adtstoasc_bsf; -extern const AVBitStreamFilter ff_av1_frame_merge_bsf; -extern const AVBitStreamFilter ff_av1_frame_split_bsf; -extern const AVBitStreamFilter ff_av1_metadata_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; -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; -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; -extern const AVBitStreamFilter ff_null_bsf; -extern const AVBitStreamFilter ff_opus_metadata_bsf; -extern const AVBitStreamFilter ff_pcm_rechunk_bsf; -extern const AVBitStreamFilter ff_prores_metadata_bsf; -extern const AVBitStreamFilter ff_remove_extradata_bsf; -extern const AVBitStreamFilter ff_setts_bsf; -extern const AVBitStreamFilter ff_text2movsub_bsf; -extern const AVBitStreamFilter ff_trace_headers_bsf; -extern const AVBitStreamFilter ff_truehd_core_bsf; -extern const AVBitStreamFilter ff_vp9_metadata_bsf; -extern const AVBitStreamFilter ff_vp9_raw_reorder_bsf; -extern const AVBitStreamFilter ff_vp9_superframe_bsf; -extern const AVBitStreamFilter ff_vp9_superframe_split_bsf; +extern const FFBitStreamFilter ff_aac_adtstoasc_bsf; +extern const FFBitStreamFilter ff_av1_frame_merge_bsf; +extern const FFBitStreamFilter ff_av1_frame_split_bsf; +extern const FFBitStreamFilter ff_av1_metadata_bsf; +extern const FFBitStreamFilter ff_chomp_bsf; +extern const FFBitStreamFilter ff_dump_extradata_bsf; +extern const FFBitStreamFilter ff_dca_core_bsf; +extern const FFBitStreamFilter ff_dv_error_marker_bsf; +extern const FFBitStreamFilter ff_eac3_core_bsf; +extern const FFBitStreamFilter ff_extract_extradata_bsf; +extern const FFBitStreamFilter ff_filter_units_bsf; +extern const FFBitStreamFilter ff_h264_metadata_bsf; +extern const FFBitStreamFilter ff_h264_mp4toannexb_bsf; +extern const FFBitStreamFilter ff_h264_redundant_pps_bsf; +extern const FFBitStreamFilter ff_hapqa_extract_bsf; +extern const FFBitStreamFilter ff_hevc_metadata_bsf; +extern const FFBitStreamFilter ff_hevc_mp4toannexb_bsf; +extern const FFBitStreamFilter ff_imx_dump_header_bsf; +extern const FFBitStreamFilter ff_mjpeg2jpeg_bsf; +extern const FFBitStreamFilter ff_mjpega_dump_header_bsf; +extern const FFBitStreamFilter ff_mp3_header_decompress_bsf; +extern const FFBitStreamFilter ff_mpeg2_metadata_bsf; +extern const FFBitStreamFilter ff_mpeg4_unpack_bframes_bsf; +extern const FFBitStreamFilter ff_mov2textsub_bsf; +extern const FFBitStreamFilter ff_noise_bsf; +extern const FFBitStreamFilter ff_null_bsf; +extern const FFBitStreamFilter ff_opus_metadata_bsf; +extern const FFBitStreamFilter ff_pcm_rechunk_bsf; +extern const FFBitStreamFilter ff_pgs_frame_merge_bsf; +extern const FFBitStreamFilter ff_prores_metadata_bsf; +extern const FFBitStreamFilter ff_remove_extradata_bsf; +extern const FFBitStreamFilter ff_setts_bsf; +extern const FFBitStreamFilter ff_text2movsub_bsf; +extern const FFBitStreamFilter ff_trace_headers_bsf; +extern const FFBitStreamFilter ff_truehd_core_bsf; +extern const FFBitStreamFilter ff_vp9_metadata_bsf; +extern const FFBitStreamFilter ff_vp9_raw_reorder_bsf; +extern const FFBitStreamFilter ff_vp9_superframe_bsf; +extern const FFBitStreamFilter ff_vp9_superframe_split_bsf; #include "libavcodec/bsf_list.c" const AVBitStreamFilter *av_bsf_iterate(void **opaque) { uintptr_t i = (uintptr_t)*opaque; - const AVBitStreamFilter *f = bitstream_filters[i]; + const FFBitStreamFilter *f = bitstream_filters[i]; - if (f) + if (f) { *opaque = (void*)(i + 1); - - return f; + return &f->p; + } + return NULL; } const AVBitStreamFilter *av_bsf_get_by_name(const char *name) diff --git a/libavcodec/blockdsp.c b/libavcodec/blockdsp.c index 5fb242ea6..c8f85dd20 100644 --- a/libavcodec/blockdsp.c +++ b/libavcodec/blockdsp.c @@ -64,14 +64,15 @@ av_cold void ff_blockdsp_init(BlockDSPContext *c, AVCodecContext *avctx) c->fill_block_tab[0] = fill_block16_c; c->fill_block_tab[1] = fill_block8_c; - if (ARCH_ALPHA) - ff_blockdsp_init_alpha(c); - if (ARCH_ARM) - ff_blockdsp_init_arm(c); - if (ARCH_PPC) - ff_blockdsp_init_ppc(c); - if (ARCH_X86) - ff_blockdsp_init_x86(c, avctx); - if (ARCH_MIPS) - ff_blockdsp_init_mips(c); +#if ARCH_ALPHA + ff_blockdsp_init_alpha(c); +#elif ARCH_ARM + ff_blockdsp_init_arm(c); +#elif ARCH_PPC + ff_blockdsp_init_ppc(c); +#elif ARCH_X86 + ff_blockdsp_init_x86(c, avctx); +#elif ARCH_MIPS + ff_blockdsp_init_mips(c); +#endif } diff --git a/libavcodec/bmp.c b/libavcodec/bmp.c index c4f6044cb..410065aba 100644 --- a/libavcodec/bmp.c +++ b/libavcodec/bmp.c @@ -24,16 +24,15 @@ #include "avcodec.h" #include "bytestream.h" #include "bmp.h" +#include "codec_internal.h" #include "internal.h" #include "msrledec.h" -static int bmp_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int bmp_decode_frame(AVCodecContext *avctx, AVFrame *p, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; - AVFrame *p = data; unsigned int fsize, hsize; int width, height; unsigned int depth; @@ -365,11 +364,11 @@ static int bmp_decode_frame(AVCodecContext *avctx, return buf_size; } -const AVCodec ff_bmp_decoder = { - .name = "bmp", - .long_name = NULL_IF_CONFIG_SMALL("BMP (Windows and OS/2 bitmap)"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_BMP, - .decode = bmp_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, +const FFCodec ff_bmp_decoder = { + .p.name = "bmp", + .p.long_name = NULL_IF_CONFIG_SMALL("BMP (Windows and OS/2 bitmap)"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_BMP, + .p.capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(bmp_decode_frame), }; diff --git a/libavcodec/bmpenc.c b/libavcodec/bmpenc.c index 672c0e498..f28ce01f5 100644 --- a/libavcodec/bmpenc.c +++ b/libavcodec/bmpenc.c @@ -27,8 +27,8 @@ #include "avcodec.h" #include "bytestream.h" #include "bmp.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" static const uint32_t monoblack_pal[] = { 0x000000, 0xFFFFFF }; static const uint32_t rgb565_masks[] = { 0xF800, 0x07E0, 0x001F }; @@ -155,15 +155,15 @@ static int bmp_encode_frame(AVCodecContext *avctx, AVPacket *pkt, return 0; } -const AVCodec ff_bmp_encoder = { - .name = "bmp", - .long_name = NULL_IF_CONFIG_SMALL("BMP (Windows and OS/2 bitmap)"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_BMP, - .capabilities = AV_CODEC_CAP_DR1, +const FFCodec ff_bmp_encoder = { + .p.name = "bmp", + .p.long_name = NULL_IF_CONFIG_SMALL("BMP (Windows and OS/2 bitmap)"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_BMP, + .p.capabilities = AV_CODEC_CAP_DR1, .init = bmp_encode_init, - .encode2 = bmp_encode_frame, - .pix_fmts = (const enum AVPixelFormat[]){ + FF_CODEC_ENCODE_CB(bmp_encode_frame), + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_BGRA, AV_PIX_FMT_BGR24, AV_PIX_FMT_RGB565, AV_PIX_FMT_RGB555, AV_PIX_FMT_RGB444, AV_PIX_FMT_RGB8, AV_PIX_FMT_BGR8, AV_PIX_FMT_RGB4_BYTE, AV_PIX_FMT_BGR4_BYTE, AV_PIX_FMT_GRAY8, AV_PIX_FMT_PAL8, diff --git a/libavcodec/bmvaudio.c b/libavcodec/bmvaudio.c index a7eae4610..f57ece032 100644 --- a/libavcodec/bmvaudio.c +++ b/libavcodec/bmvaudio.c @@ -23,6 +23,7 @@ #include "libavutil/common.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" static const int bmv_aud_mults[16] = { @@ -31,17 +32,16 @@ static const int bmv_aud_mults[16] = { static av_cold int bmv_aud_decode_init(AVCodecContext *avctx) { - avctx->channels = 2; - avctx->channel_layout = AV_CH_LAYOUT_STEREO; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; avctx->sample_fmt = AV_SAMPLE_FMT_S16; return 0; } -static int bmv_aud_decode_frame(AVCodecContext *avctx, void *data, +static int bmv_aud_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; int blocks = 0, total_blocks, i; @@ -78,13 +78,13 @@ static int bmv_aud_decode_frame(AVCodecContext *avctx, void *data, return buf_size; } -const AVCodec ff_bmv_audio_decoder = { - .name = "bmv_audio", - .long_name = NULL_IF_CONFIG_SMALL("Discworld II BMV audio"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_BMV_AUDIO, +const FFCodec ff_bmv_audio_decoder = { + .p.name = "bmv_audio", + .p.long_name = NULL_IF_CONFIG_SMALL("Discworld II BMV audio"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_BMV_AUDIO, .init = bmv_aud_decode_init, - .decode = bmv_aud_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + FF_CODEC_DECODE_CB(bmv_aud_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/bmvvideo.c b/libavcodec/bmvvideo.c index d76ba442b..c492d7fcf 100644 --- a/libavcodec/bmvvideo.c +++ b/libavcodec/bmvvideo.c @@ -24,6 +24,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" enum BMVFlags{ @@ -195,11 +196,10 @@ static int decode_bmv_frame(const uint8_t *source, int src_len, uint8_t *frame, } } -static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *pkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *pkt) { BMVDecContext * const c = avctx->priv_data; - AVFrame *frame = data; int type, scr_off; int i, ret; uint8_t *srcptr, *outptr; @@ -285,14 +285,14 @@ static av_cold int decode_init(AVCodecContext *avctx) return 0; } -const AVCodec ff_bmv_video_decoder = { - .name = "bmv_video", - .long_name = NULL_IF_CONFIG_SMALL("Discworld II BMV video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_BMV_VIDEO, +const FFCodec ff_bmv_video_decoder = { + .p.name = "bmv_video", + .p.long_name = NULL_IF_CONFIG_SMALL("Discworld II BMV video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_BMV_VIDEO, .priv_data_size = sizeof(BMVDecContext), .init = decode_init, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/brenderpix.c b/libavcodec/brenderpix.c index 4726fd3d7..9807a11cf 100644 --- a/libavcodec/brenderpix.c +++ b/libavcodec/brenderpix.c @@ -25,6 +25,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" #define HEADER1_CHUNK 0x03 @@ -129,11 +130,9 @@ static int pix_decode_header(PixHeader *out, GetByteContext *pgb) return 0; } -static int pix_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int pix_decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { - AVFrame *frame = data; - int ret, i; GetByteContext gb; @@ -285,11 +284,11 @@ static int pix_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, return avpkt->size; } -const AVCodec ff_brender_pix_decoder = { - .name = "brender_pix", - .long_name = NULL_IF_CONFIG_SMALL("BRender PIX image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_BRENDER_PIX, - .decode = pix_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, +const FFCodec ff_brender_pix_decoder = { + .p.name = "brender_pix", + .p.long_name = NULL_IF_CONFIG_SMALL("BRender PIX image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_BRENDER_PIX, + .p.capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(pix_decode_frame), }; diff --git a/libavcodec/bsf.c b/libavcodec/bsf.c index 8ba021cb4..42cc1b5ab 100644 --- a/libavcodec/bsf.c +++ b/libavcodec/bsf.c @@ -18,7 +18,7 @@ #include -#include "config.h" +#include "config_components.h" #include "libavutil/avassert.h" #include "libavutil/log.h" @@ -34,6 +34,11 @@ #define IS_EMPTY(pkt) (!(pkt)->data && !(pkt)->side_data_elems) +static av_always_inline const FFBitStreamFilter *ff_bsf(const AVBitStreamFilter *bsf) +{ + return (const FFBitStreamFilter*)bsf; +} + typedef struct FFBSFContext { AVBSFContext pub; AVPacket *buffer_pkt; @@ -56,8 +61,8 @@ void av_bsf_free(AVBSFContext **pctx) bsfi = ffbsfcontext(ctx); if (ctx->priv_data) { - if (ctx->filter->close) - ctx->filter->close(ctx); + if (ff_bsf(ctx->filter)->close) + ff_bsf(ctx->filter)->close(ctx); if (ctx->filter->priv_class) av_opt_free(ctx->priv_data); av_freep(&ctx->priv_data); @@ -118,8 +123,8 @@ int av_bsf_alloc(const AVBitStreamFilter *filter, AVBSFContext **pctx) goto fail; } /* allocate priv data and init private options */ - if (filter->priv_data_size) { - ctx->priv_data = av_mallocz(filter->priv_data_size); + if (ff_bsf(filter)->priv_data_size) { + ctx->priv_data = av_mallocz(ff_bsf(filter)->priv_data_size); if (!ctx->priv_data) { ret = AVERROR(ENOMEM); goto fail; @@ -174,8 +179,8 @@ int av_bsf_init(AVBSFContext *ctx) ctx->time_base_out = ctx->time_base_in; - if (ctx->filter->init) { - ret = ctx->filter->init(ctx); + if (ff_bsf(ctx->filter)->init) { + ret = ff_bsf(ctx->filter)->init(ctx); if (ret < 0) return ret; } @@ -191,8 +196,8 @@ void av_bsf_flush(AVBSFContext *ctx) av_packet_unref(bsfi->buffer_pkt); - if (ctx->filter->flush) - ctx->filter->flush(ctx); + if (ff_bsf(ctx->filter)->flush) + ff_bsf(ctx->filter)->flush(ctx); } int av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt) @@ -225,7 +230,7 @@ int av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt) int av_bsf_receive_packet(AVBSFContext *ctx, AVPacket *pkt) { - return ctx->filter->filter(ctx, pkt); + return ff_bsf(ctx->filter)->filter(ctx, pkt); } int ff_bsf_get_packet(AVBSFContext *ctx, AVPacket **pkt) @@ -398,10 +403,10 @@ static const AVClass bsf_list_class = { .version = LIBAVUTIL_VERSION_INT, }; -static const AVBitStreamFilter list_bsf = { - .name = "bsf_list", +static const FFBitStreamFilter list_bsf = { + .p.name = "bsf_list", + .p.priv_class = &bsf_list_class, .priv_data_size = sizeof(BSFListContext), - .priv_class = &bsf_list_class, .init = bsf_list_init, .filter = bsf_list_filter, .flush = bsf_list_flush, @@ -494,7 +499,7 @@ int av_bsf_list_finalize(AVBSFList **lst, AVBSFContext **bsf) goto end; } - ret = av_bsf_alloc(&list_bsf, bsf); + ret = av_bsf_alloc(&list_bsf.p, bsf); if (ret < 0) return ret; @@ -549,9 +554,9 @@ end: int av_bsf_get_null_filter(AVBSFContext **bsf) { #if CONFIG_NULL_BSF - extern const AVBitStreamFilter ff_null_bsf; - return av_bsf_alloc(&ff_null_bsf, bsf); + extern const FFBitStreamFilter ff_null_bsf; + return av_bsf_alloc(&ff_null_bsf.p, bsf); #else - return av_bsf_alloc(&list_bsf, bsf); + return av_bsf_alloc(&list_bsf.p, bsf); #endif } diff --git a/libavcodec/bsf.h b/libavcodec/bsf.h index 8c5355d18..69d91a16a 100644 --- a/libavcodec/bsf.h +++ b/libavcodec/bsf.h @@ -30,7 +30,28 @@ #include "packet.h" /** - * @addtogroup lavc_core + * @defgroup lavc_bsf Bitstream filters + * @ingroup libavc + * + * Bitstream filters transform encoded media data without decoding it. This + * allows e.g. manipulating various header values. Bitstream filters operate on + * @ref AVPacket "AVPackets". + * + * The bitstream filtering API is centered around two structures: + * AVBitStreamFilter and AVBSFContext. The former represents a bitstream filter + * in abstract, the latter a specific filtering process. Obtain an + * AVBitStreamFilter using av_bsf_get_by_name() or av_bsf_iterate(), then pass + * it to av_bsf_alloc() to create an AVBSFContext. Fill in the user-settable + * AVBSFContext fields, as described in its documentation, then call + * av_bsf_init() to prepare the filter context for use. + * + * Submit packets for filtering using av_bsf_send_packet(), obtain filtered + * results with av_bsf_receive_packet(). When no more input packets will be + * sent, submit a NULL AVPacket to signal the end of the stream to the filter. + * av_bsf_receive_packet() will then return trailing packets, if any are + * produced by the filter. + * + * Finally, free the filter context with av_bsf_free(). * @{ */ @@ -107,20 +128,6 @@ typedef struct AVBitStreamFilter { * code to this class. */ const AVClass *priv_class; - - /***************************************************************** - * No fields below this line are part of the public API. They - * may not be used outside of libavcodec and can be changed and - * removed at will. - * New public fields should be added right above. - ***************************************************************** - */ - - int priv_data_size; - int (*init)(AVBSFContext *ctx); - int (*filter)(AVBSFContext *ctx, AVPacket *pkt); - void (*close)(AVBSFContext *ctx); - void (*flush)(AVBSFContext *ctx); } AVBitStreamFilter; /** @@ -146,9 +153,9 @@ const AVBitStreamFilter *av_bsf_iterate(void **opaque); * av_bsf_init() before sending any data to the filter. * * @param filter the filter for which to allocate an instance. - * @param ctx a pointer into which the pointer to the newly-allocated context - * will be written. It must be freed with av_bsf_free() after the - * filtering is done. + * @param[out] ctx a pointer into which the pointer to the newly-allocated context + * will be written. It must be freed with av_bsf_free() after the + * filtering is done. * * @return 0 on success, a negative AVERROR code on failure */ @@ -174,9 +181,11 @@ int av_bsf_init(AVBSFContext *ctx); * sending more empty packets does nothing) and will cause the filter to output * any packets it may have buffered internally. * - * @return 0 on success. AVERROR(EAGAIN) if packets need to be retrieved from the - * filter (using av_bsf_receive_packet()) before new input can be consumed. Another - * negative AVERROR value if an error occurs. + * @return + * - 0 on success. + * - AVERROR(EAGAIN) if packets need to be retrieved from the filter (using + * av_bsf_receive_packet()) before new input can be consumed. + * - Another negative AVERROR value if an error occurs. */ int av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt); @@ -193,10 +202,12 @@ int av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt); * overwritten by the returned data. On failure, pkt is not * touched. * - * @return 0 on success. AVERROR(EAGAIN) if more packets need to be sent to the - * filter (using av_bsf_send_packet()) to get more output. AVERROR_EOF if there - * will be no further output from the filter. Another negative AVERROR value if - * an error occurs. + * @return + * - 0 on success. + * - AVERROR(EAGAIN) if more packets need to be sent to the filter (using + * av_bsf_send_packet()) to get more output. + * - AVERROR_EOF if there will be no further output from the filter. + * - Another negative AVERROR value if an error occurs. * * @note one input packet may result in several output packets, so after sending * a packet with av_bsf_send_packet(), this function needs to be called diff --git a/libavcodec/bsf_internal.h b/libavcodec/bsf_internal.h index 06979fdaa..922b03c01 100644 --- a/libavcodec/bsf_internal.h +++ b/libavcodec/bsf_internal.h @@ -24,6 +24,19 @@ #include "bsf.h" #include "packet.h" +typedef struct FFBitStreamFilter { + /** + * The public AVBitStreamFilter. See bsf.h for it. + */ + AVBitStreamFilter p; + + int priv_data_size; + int (*init)(AVBSFContext *ctx); + int (*filter)(AVBSFContext *ctx, AVPacket *pkt); + void (*close)(AVBSFContext *ctx); + void (*flush)(AVBSFContext *ctx); +} FFBitStreamFilter; + /** * Called by the bitstream filters to get the next packet for filtering. * The filter is responsible for either freeing the packet or passing it to the diff --git a/libavcodec/bswapdsp.c b/libavcodec/bswapdsp.c index a6e1ec069..4c4ea10ac 100644 --- a/libavcodec/bswapdsp.c +++ b/libavcodec/bswapdsp.c @@ -51,6 +51,7 @@ av_cold void ff_bswapdsp_init(BswapDSPContext *c) c->bswap_buf = bswap_buf; c->bswap16_buf = bswap16_buf; - if (ARCH_X86) - ff_bswapdsp_init_x86(c); +#if ARCH_X86 + ff_bswapdsp_init_x86(c); +#endif } diff --git a/libavcodec/c93.c b/libavcodec/c93.c index 3464c85e2..050bb4274 100644 --- a/libavcodec/c93.c +++ b/libavcodec/c93.c @@ -21,6 +21,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" typedef struct C93DecoderContext { @@ -119,7 +120,7 @@ static inline void draw_n_color(uint8_t *out, int stride, int width, } } -static int decode_frame(AVCodecContext *avctx, void *data, +static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; @@ -250,22 +251,22 @@ static int decode_frame(AVCodecContext *avctx, void *data, memcpy(newpic->data[1], oldpic->data[1], 256 * 4); } - if ((ret = av_frame_ref(data, newpic)) < 0) + if ((ret = av_frame_ref(rframe, newpic)) < 0) return ret; *got_frame = 1; return buf_size; } -const AVCodec ff_c93_decoder = { - .name = "c93", - .long_name = NULL_IF_CONFIG_SMALL("Interplay C93"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_C93, +const FFCodec ff_c93_decoder = { + .p.name = "c93", + .p.long_name = NULL_IF_CONFIG_SMALL("Interplay C93"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_C93, .priv_data_size = sizeof(C93DecoderContext), .init = decode_init, .close = decode_end, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/cabac.c b/libavcodec/cabac.c index 6649feebe..7d41cd2ae 100644 --- a/libavcodec/cabac.c +++ b/libavcodec/cabac.c @@ -24,13 +24,10 @@ * Context Adaptive Binary Arithmetic Coder. */ -#include - -#include "libavutil/common.h" +#include "libavutil/error.h" #include "libavutil/mem_internal.h" #include "cabac.h" -#include "cabac_functions.h" 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, diff --git a/libavcodec/cabac_functions.h b/libavcodec/cabac_functions.h index 2f2d48a8f..c3f08d341 100644 --- a/libavcodec/cabac_functions.h +++ b/libavcodec/cabac_functions.h @@ -30,6 +30,8 @@ #include #include +#include "libavutil/attributes.h" +#include "libavutil/intmath.h" #include "cabac.h" #include "config.h" diff --git a/libavcodec/cavs.c b/libavcodec/cavs.c index e29d9c659..87bbe26f9 100644 --- a/libavcodec/cavs.c +++ b/libavcodec/cavs.c @@ -25,14 +25,10 @@ * @author Stefan Gehrer */ -#include "libavutil/mem_internal.h" - #include "avcodec.h" -#include "get_bits.h" #include "golomb.h" #include "h264chroma.h" #include "idctdsp.h" -#include "internal.h" #include "mathops.h" #include "qpeldsp.h" #include "cavs.h" @@ -812,10 +808,8 @@ av_cold int ff_cavs_init(AVCodecContext *avctx) h->cur.f = av_frame_alloc(); h->DPB[0].f = av_frame_alloc(); h->DPB[1].f = av_frame_alloc(); - if (!h->cur.f || !h->DPB[0].f || !h->DPB[1].f) { - ff_cavs_end(avctx); + if (!h->cur.f || !h->DPB[0].f || !h->DPB[1].f) return AVERROR(ENOMEM); - } h->luma_scan[0] = 0; h->luma_scan[1] = 8; diff --git a/libavcodec/cavsdec.c b/libavcodec/cavsdec.c index 692c77eb3..6c69c2c94 100644 --- a/libavcodec/cavsdec.c +++ b/libavcodec/cavsdec.c @@ -30,8 +30,11 @@ #include "get_bits.h" #include "golomb.h" #include "cavs.h" +#include "codec_internal.h" #include "internal.h" +#include "mathops.h" #include "mpeg12data.h" +#include "startcode.h" static const uint8_t mv_scan[4] = { MV_FWD_X0, MV_FWD_X1, @@ -504,7 +507,7 @@ static inline int get_ue_code(GetBitContext *gb, int order) { unsigned ret = get_ue_golomb(gb); if (ret >= ((1U<<31)>>order)) { - av_log(NULL, AV_LOG_ERROR, "get_ue_code: value too larger\n"); + av_log(NULL, AV_LOG_ERROR, "get_ue_code: value too large\n"); return AVERROR_INVALIDDATA; } if (order) { @@ -1174,6 +1177,11 @@ static int decode_seq_header(AVSContext *h) int ret; h->profile = get_bits(&h->gb, 8); + if (h->profile != 0x20) { + avpriv_report_missing_feature(h->avctx, + "only supprt JiZhun profile"); + return AVERROR_PATCHWELCOME; + } h->level = get_bits(&h->gb, 8); skip_bits1(&h->gb); //progressive sequence @@ -1223,8 +1231,8 @@ static void cavs_flush(AVCodecContext * avctx) h->got_keyframe = 0; } -static int cavs_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int cavs_decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *avpkt) { AVSContext *h = avctx->priv_data; const uint8_t *buf = avpkt->data; @@ -1238,7 +1246,7 @@ static int cavs_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, if (buf_size == 0) { if (!h->low_delay && h->DPB[0].f->data[0]) { *got_frame = 1; - av_frame_move_ref(data, h->DPB[0].f); + av_frame_move_ref(rframe, h->DPB[0].f); } return 0; } @@ -1271,7 +1279,7 @@ static int cavs_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, return AVERROR_INVALIDDATA; frame_start ++; if (*got_frame) - av_frame_unref(data); + av_frame_unref(rframe); *got_frame = 0; if (!h->got_keyframe) break; @@ -1282,13 +1290,13 @@ static int cavs_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, *got_frame = 1; if (h->cur.f->pict_type != AV_PICTURE_TYPE_B) { if (h->DPB[!h->low_delay].f->data[0]) { - if ((ret = av_frame_ref(data, h->DPB[!h->low_delay].f)) < 0) + if ((ret = av_frame_ref(rframe, h->DPB[!h->low_delay].f)) < 0) return ret; } else { *got_frame = 0; } } else { - av_frame_move_ref(data, h->cur.f); + av_frame_move_ref(rframe, h->cur.f); } break; case EXT_START_CODE: @@ -1307,15 +1315,16 @@ static int cavs_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, } } -const AVCodec ff_cavs_decoder = { - .name = "cavs", - .long_name = NULL_IF_CONFIG_SMALL("Chinese AVS (Audio Video Standard) (AVS1-P2, JiZhun profile)"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_CAVS, +const FFCodec ff_cavs_decoder = { + .p.name = "cavs", + .p.long_name = NULL_IF_CONFIG_SMALL("Chinese AVS (Audio Video Standard) (AVS1-P2, JiZhun profile)"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_CAVS, .priv_data_size = sizeof(AVSContext), .init = ff_cavs_init, .close = ff_cavs_end, - .decode = cavs_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, + FF_CODEC_DECODE_CB(cavs_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, .flush = cavs_flush, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/cavsdsp.c b/libavcodec/cavsdsp.c index ba92121cc..b096de452 100644 --- a/libavcodec/cavsdsp.c +++ b/libavcodec/cavsdsp.c @@ -577,6 +577,7 @@ av_cold void ff_cavsdsp_init(CAVSDSPContext* c, AVCodecContext *avctx) { c->cavs_idct8_add = cavs_idct8_add_c; c->idct_perm = FF_IDCT_PERM_NONE; - if (ARCH_X86) - ff_cavsdsp_init_x86(c, avctx); +#if ARCH_X86 + ff_cavsdsp_init_x86(c, avctx); +#endif } diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c index d7aa67c3a..8c0a5b571 100644 --- a/libavcodec/cbs.c +++ b/libavcodec/cbs.c @@ -73,8 +73,8 @@ const enum AVCodecID ff_cbs_all_codec_ids[] = { AV_CODEC_ID_NONE }; -int ff_cbs_init(CodedBitstreamContext **ctx_ptr, - enum AVCodecID codec_id, void *log_ctx) +av_cold int ff_cbs_init(CodedBitstreamContext **ctx_ptr, + enum AVCodecID codec_id, void *log_ctx) { CodedBitstreamContext *ctx; const CodedBitstreamType *type; @@ -118,13 +118,13 @@ int ff_cbs_init(CodedBitstreamContext **ctx_ptr, return 0; } -void ff_cbs_flush(CodedBitstreamContext *ctx) +av_cold void ff_cbs_flush(CodedBitstreamContext *ctx) { if (ctx->codec->flush) ctx->codec->flush(ctx); } -void ff_cbs_close(CodedBitstreamContext **ctx_ptr) +av_cold void ff_cbs_close(CodedBitstreamContext **ctx_ptr) { CodedBitstreamContext *ctx = *ctx_ptr; @@ -168,7 +168,7 @@ void ff_cbs_fragment_reset(CodedBitstreamFragment *frag) frag->data_bit_padding = 0; } -void ff_cbs_fragment_free(CodedBitstreamFragment *frag) +av_cold void ff_cbs_fragment_free(CodedBitstreamFragment *frag) { ff_cbs_fragment_reset(frag); @@ -789,18 +789,16 @@ int ff_cbs_insert_unit_content(CodedBitstreamFragment *frag, return 0; } -int ff_cbs_insert_unit_data(CodedBitstreamFragment *frag, - int position, - CodedBitstreamUnitType type, - uint8_t *data, size_t data_size, - AVBufferRef *data_buf) +static int cbs_insert_unit_data(CodedBitstreamFragment *frag, + CodedBitstreamUnitType type, + uint8_t *data, size_t data_size, + AVBufferRef *data_buf, + int position) { 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) @@ -828,6 +826,16 @@ int ff_cbs_insert_unit_data(CodedBitstreamFragment *frag, return 0; } +int ff_cbs_append_unit_data(CodedBitstreamFragment *frag, + CodedBitstreamUnitType type, + uint8_t *data, size_t data_size, + AVBufferRef *data_buf) +{ + return cbs_insert_unit_data(frag, type, + data, data_size, data_buf, + frag->nb_units); +} + void ff_cbs_delete_unit(CodedBitstreamFragment *frag, int position) { diff --git a/libavcodec/cbs.h b/libavcodec/cbs.h index 87ea14cd0..5583063b5 100644 --- a/libavcodec/cbs.h +++ b/libavcodec/cbs.h @@ -393,14 +393,13 @@ int ff_cbs_insert_unit_content(CodedBitstreamFragment *frag, AVBufferRef *content_buf); /** - * Insert a new unit into a fragment with the given data bitstream. + * Add a new unit to a fragment with the given data bitstream. * * If data_buf is not supplied then data must have been allocated with * av_malloc() and will on success become owned by the unit after this * call or freed on error. */ -int ff_cbs_insert_unit_data(CodedBitstreamFragment *frag, - int position, +int ff_cbs_append_unit_data(CodedBitstreamFragment *frag, CodedBitstreamUnitType type, uint8_t *data, size_t data_size, AVBufferRef *data_buf); diff --git a/libavcodec/cbs_av1.c b/libavcodec/cbs_av1.c index 302e1f38f..122948056 100644 --- a/libavcodec/cbs_av1.c +++ b/libavcodec/cbs_av1.c @@ -20,10 +20,10 @@ #include "libavutil/opt.h" #include "libavutil/pixfmt.h" +#include "avcodec.h" #include "cbs.h" #include "cbs_internal.h" #include "cbs_av1.h" -#include "internal.h" static int cbs_av1_read_uvlc(CodedBitstreamContext *ctx, GetBitContext *gbc, @@ -828,7 +828,7 @@ static int cbs_av1_split_fragment(CodedBitstreamContext *ctx, goto fail; } - err = ff_cbs_insert_unit_data(frag, -1, header.obu_type, + err = ff_cbs_append_unit_data(frag, header.obu_type, data, obu_length, frag->data_ref); if (err < 0) goto fail; diff --git a/libavcodec/cbs_bsf.h b/libavcodec/cbs_bsf.h index a370be1b5..aa7385c8f 100644 --- a/libavcodec/cbs_bsf.h +++ b/libavcodec/cbs_bsf.h @@ -67,7 +67,7 @@ typedef struct CBSBSFContext { * * Since it calls the update_fragment() function immediately to deal with * extradata, this should be called after any codec-specific setup is done - * (probably at the end of the AVBitStreamFilter.init function). + * (probably at the end of the FFBitStreamFilter.init function). */ int ff_cbs_bsf_generic_init(AVBSFContext *bsf, const CBSBSFType *type); @@ -75,7 +75,7 @@ int ff_cbs_bsf_generic_init(AVBSFContext *bsf, const CBSBSFType *type); * Close a generic CBS BSF instance. * * If no other deinitialisation is required then this function can be used - * directly as AVBitStreamFilter.close. + * directly as FFBitStreamFilter.close. */ void ff_cbs_bsf_generic_close(AVBSFContext *bsf); @@ -88,7 +88,7 @@ void ff_cbs_bsf_generic_close(AVBSFContext *bsf); * the same thing to that new extradata to form the output side-data first. * * If the BSF does not do anything else then this function can be used - * directly as AVBitStreamFilter.filter. + * directly as FFBitStreamFilter.filter. */ int ff_cbs_bsf_generic_filter(AVBSFContext *bsf, AVPacket *pkt); diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c index 3396c059c..12e38c80b 100644 --- a/libavcodec/cbs_h2645.c +++ b/libavcodec/cbs_h2645.c @@ -25,10 +25,8 @@ #include "cbs_h264.h" #include "cbs_h265.h" #include "h264.h" -#include "h264_sei.h" #include "h2645_parse.h" #include "hevc.h" -#include "hevc_sei.h" static int cbs_read_ue_golomb(CodedBitstreamContext *ctx, GetBitContext *gbc, @@ -493,7 +491,7 @@ static int cbs_h2645_fragment_add_nals(CodedBitstreamContext *ctx, ref = (nal->data == nal->raw_data) ? frag->data_ref : packet->rbsp.rbsp_buffer_ref; - err = ff_cbs_insert_unit_data(frag, -1, nal->type, + err = ff_cbs_append_unit_data(frag, nal->type, (uint8_t*)nal->data, size, ref); if (err < 0) return err; diff --git a/libavcodec/cbs_jpeg.c b/libavcodec/cbs_jpeg.c index 7d3e10fcc..da7ee808c 100644 --- a/libavcodec/cbs_jpeg.c +++ b/libavcodec/cbs_jpeg.c @@ -110,7 +110,7 @@ static int cbs_jpeg_split_fragment(CodedBitstreamContext *ctx, AVBufferRef *data_ref; uint8_t *data; size_t data_size; - int unit, start, end, marker, next_start, next_marker; + int start, end, marker, next_start, next_marker; int err, i, j, length; if (frag->data_size < 4) { @@ -144,7 +144,7 @@ static int cbs_jpeg_split_fragment(CodedBitstreamContext *ctx, marker = frag->data[i]; start = i + 1; - for (unit = 0;; unit++) { + do { if (marker == JPEG_MARKER_EOI) { break; } else if (marker == JPEG_MARKER_SOS) { @@ -226,16 +226,14 @@ static int cbs_jpeg_split_fragment(CodedBitstreamContext *ctx, data_ref = frag->data_ref; } - err = ff_cbs_insert_unit_data(frag, unit, marker, + err = ff_cbs_append_unit_data(frag, marker, data, data_size, data_ref); if (err < 0) return err; - if (next_marker == -1) - break; marker = next_marker; start = next_start; - } + } while (next_marker != -1); return 0; } diff --git a/libavcodec/cbs_jpeg.h b/libavcodec/cbs_jpeg.h index 6305f0ee8..9dbebd259 100644 --- a/libavcodec/cbs_jpeg.h +++ b/libavcodec/cbs_jpeg.h @@ -99,7 +99,7 @@ typedef struct JPEGRawHuffmanTable { uint8_t Tc; uint8_t Th; uint8_t L[16]; - uint8_t V[224]; + uint8_t V[256]; } JPEGRawHuffmanTable; typedef struct JPEGRawHuffmanTableSpecification { diff --git a/libavcodec/cbs_jpeg_syntax_template.c b/libavcodec/cbs_jpeg_syntax_template.c index 6eda56d62..e06abdc67 100644 --- a/libavcodec/cbs_jpeg_syntax_template.c +++ b/libavcodec/cbs_jpeg_syntax_template.c @@ -84,12 +84,12 @@ static int FUNC(huffman_table)(CodedBitstreamContext *ctx, RWContext *rw, u(4, Th, 0, 3); for (i = 0; i < 16; i++) - us(8, L[i], i, 0, 224); + us(8, L[i], i, 0, 255); ij = 0; for (i = 0; i < 16; i++) { for (j = 0; j < current->L[i]; j++) { - if (ij >= 224) + if (ij >= FF_ARRAY_ELEMS(current->V)) return AVERROR_INVALIDDATA; us(8, V[ij], ij, 0, 255); ++ij; diff --git a/libavcodec/cbs_mpeg2.c b/libavcodec/cbs_mpeg2.c index 26400f279..33bd3e099 100644 --- a/libavcodec/cbs_mpeg2.c +++ b/libavcodec/cbs_mpeg2.c @@ -21,7 +21,7 @@ #include "cbs.h" #include "cbs_internal.h" #include "cbs_mpeg2.h" -#include "internal.h" +#include "startcode.h" #define HEADER(name) do { \ @@ -144,11 +144,9 @@ static int cbs_mpeg2_split_fragment(CodedBitstreamContext *ctx, CodedBitstreamFragment *frag, int header) { - const uint8_t *start, *end; - CodedBitstreamUnitType unit_type; + const uint8_t *start; uint32_t start_code = -1; - size_t unit_size; - int err, i, final = 0; + int err; start = avpriv_find_start_code(frag->data, frag->data + frag->data_size, &start_code); @@ -157,17 +155,16 @@ static int cbs_mpeg2_split_fragment(CodedBitstreamContext *ctx, return AVERROR_INVALIDDATA; } - for (i = 0;; i++) { - unit_type = start_code & 0xff; - - if (start == frag->data + frag->data_size) { - // The last four bytes form a start code which constitutes - // a unit of its own. In this situation avpriv_find_start_code - // won't modify start_code at all so modify start_code so that - // the next unit will be treated as the last unit. - start_code = 0; - } + do { + CodedBitstreamUnitType unit_type = start_code & 0xff; + const uint8_t *end; + size_t unit_size; + // Reset start_code to ensure that avpriv_find_start_code() + // really reads a new start code and does not reuse the old + // start code in any way (as e.g. happens when there is a + // Sequence End unit at the very end of a packet). + start_code = UINT32_MAX; end = avpriv_find_start_code(start--, frag->data + frag->data_size, &start_code); @@ -182,19 +179,17 @@ static int cbs_mpeg2_split_fragment(CodedBitstreamContext *ctx, } else { // We didn't find a start code, so this is the final unit. unit_size = end - start; - final = 1; } - err = ff_cbs_insert_unit_data(frag, i, unit_type, (uint8_t*)start, + err = ff_cbs_append_unit_data(frag, unit_type, (uint8_t*)start, unit_size, frag->data_ref); if (err < 0) return err; - if (final) - break; - start = end; - } + + // Do we have a further unit to add to the fragment? + } while ((start_code >> 8) == 0x000001); return 0; } diff --git a/libavcodec/cbs_vp9.c b/libavcodec/cbs_vp9.c index e0b8c02ac..ae7f88a8a 100644 --- a/libavcodec/cbs_vp9.c +++ b/libavcodec/cbs_vp9.c @@ -21,7 +21,6 @@ #include "cbs.h" #include "cbs_internal.h" #include "cbs_vp9.h" -#include "internal.h" static int cbs_vp9_read_s(CodedBitstreamContext *ctx, GetBitContext *gbc, @@ -451,7 +450,7 @@ static int cbs_vp9_split_fragment(CodedBitstreamContext *ctx, return AVERROR_INVALIDDATA; } - err = ff_cbs_insert_unit_data(frag, -1, 0, + err = ff_cbs_append_unit_data(frag, 0, frag->data + pos, sfi.frame_sizes[i], frag->data_ref); @@ -469,7 +468,7 @@ static int cbs_vp9_split_fragment(CodedBitstreamContext *ctx, return 0; } else { - err = ff_cbs_insert_unit_data(frag, -1, 0, + err = ff_cbs_append_unit_data(frag, 0, frag->data, frag->data_size, frag->data_ref); if (err < 0) diff --git a/libavcodec/ccaption_dec.c b/libavcodec/ccaption_dec.c index 27c61527f..34f0513b1 100644 --- a/libavcodec/ccaption_dec.c +++ b/libavcodec/ccaption_dec.c @@ -21,7 +21,7 @@ #include "avcodec.h" #include "ass.h" -#include "internal.h" +#include "codec_internal.h" #include "libavutil/opt.h" #define SCREEN_ROWS 15 @@ -838,10 +838,10 @@ static int process_cc608(CCaptionSubContext *ctx, uint8_t hi, uint8_t lo) return ret; } -static int decode(AVCodecContext *avctx, void *data, int *got_sub, AVPacket *avpkt) +static int decode(AVCodecContext *avctx, AVSubtitle *sub, + int *got_sub, const AVPacket *avpkt) { CCaptionSubContext *ctx = avctx->priv_data; - AVSubtitle *sub = data; int64_t in_time = sub->pts; int64_t start_time; int64_t end_time; @@ -850,6 +850,7 @@ static int decode(AVCodecContext *avctx, void *data, int *got_sub, AVPacket *avp int len = avpkt->size; int ret = 0; int i; + unsigned nb_rect_allocated = 0; for (i = 0; i < len; i += 3) { uint8_t hi, cc_type = bptr[i] & 1; @@ -886,7 +887,7 @@ static int decode(AVCodecContext *avctx, void *data, int *got_sub, AVPacket *avp AV_TIME_BASE_Q, ms_tb); else sub->end_display_time = -1; - ret = ff_ass_add_rect(sub, ctx->buffer[bidx].str, ctx->readorder++, 0, NULL, NULL); + ret = ff_ass_add_rect2(sub, ctx->buffer[bidx].str, ctx->readorder++, 0, NULL, NULL, &nb_rect_allocated); if (ret < 0) return ret; ctx->last_real_time = sub->pts; @@ -896,7 +897,7 @@ static int decode(AVCodecContext *avctx, void *data, int *got_sub, AVPacket *avp if (!bptr && !ctx->real_time && ctx->buffer[!ctx->buffer_index].str[0]) { bidx = !ctx->buffer_index; - ret = ff_ass_add_rect(sub, ctx->buffer[bidx].str, ctx->readorder++, 0, NULL, NULL); + ret = ff_ass_add_rect2(sub, ctx->buffer[bidx].str, ctx->readorder++, 0, NULL, NULL, &nb_rect_allocated); if (ret < 0) return ret; sub->pts = ctx->buffer_time[1]; @@ -914,7 +915,7 @@ static int decode(AVCodecContext *avctx, void *data, int *got_sub, AVPacket *avp capture_screen(ctx); ctx->buffer_changed = 0; - ret = ff_ass_add_rect(sub, ctx->buffer[bidx].str, ctx->readorder++, 0, NULL, NULL); + ret = ff_ass_add_rect2(sub, ctx->buffer[bidx].str, ctx->readorder++, 0, NULL, NULL, &nb_rect_allocated); if (ret < 0) return ret; sub->end_display_time = -1; @@ -943,17 +944,17 @@ static const AVClass ccaption_dec_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_ccaption_decoder = { - .name = "cc_dec", - .long_name = NULL_IF_CONFIG_SMALL("Closed Caption (EIA-608 / CEA-708)"), - .type = AVMEDIA_TYPE_SUBTITLE, - .id = AV_CODEC_ID_EIA_608, +const FFCodec ff_ccaption_decoder = { + .p.name = "cc_dec", + .p.long_name = NULL_IF_CONFIG_SMALL("Closed Caption (EIA-608 / CEA-708)"), + .p.type = AVMEDIA_TYPE_SUBTITLE, + .p.id = AV_CODEC_ID_EIA_608, + .p.priv_class = &ccaption_dec_class, + .p.capabilities = AV_CODEC_CAP_DELAY, .priv_data_size = sizeof(CCaptionSubContext), .init = init_decoder, .close = close_decoder, .flush = flush_decoder, - .decode = decode, - .priv_class = &ccaption_dec_class, - .capabilities = AV_CODEC_CAP_DELAY, + FF_CODEC_DECODE_SUB_CB(decode), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/cdgraphics.c b/libavcodec/cdgraphics.c index a83babdf1..73654019e 100644 --- a/libavcodec/cdgraphics.c +++ b/libavcodec/cdgraphics.c @@ -21,6 +21,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" /** @@ -239,7 +240,7 @@ static void cdg_scroll(CDGraphicsContext *cc, uint8_t *data, for (y = FFMAX(0, vinc); y < FFMIN(CDG_FULL_HEIGHT + vinc, CDG_FULL_HEIGHT); y++) memcpy(out + FFMAX(0, hinc) + stride * y, in + FFMAX(0, hinc) - hinc + (y - vinc) * stride, - FFMIN(stride + hinc, stride)); + FFABS(stride) - FFABS(hinc)); if (vinc > 0) cdg_fill_wrapper(0, 0, out, @@ -261,15 +262,14 @@ static void cdg_scroll(CDGraphicsContext *cc, uint8_t *data, } -static int cdg_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, AVPacket *avpkt) +static int cdg_decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { GetByteContext gb; int buf_size = avpkt->size; int ret; uint8_t command, inst; uint8_t cdg_data[CDG_DATA_SIZE] = {0}; - AVFrame *frame = data; CDGraphicsContext *cc = avctx->priv_data; if (buf_size < CDG_MINIMUM_PKT_SIZE) { @@ -387,16 +387,16 @@ static av_cold int cdg_decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_cdgraphics_decoder = { - .name = "cdgraphics", - .long_name = NULL_IF_CONFIG_SMALL("CD Graphics video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_CDGRAPHICS, +const FFCodec ff_cdgraphics_decoder = { + .p.name = "cdgraphics", + .p.long_name = NULL_IF_CONFIG_SMALL("CD Graphics video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_CDGRAPHICS, .priv_data_size = sizeof(CDGraphicsContext), .init = cdg_decode_init, .close = cdg_decode_end, - .decode = cdg_decode_frame, + FF_CODEC_DECODE_CB(cdg_decode_frame), .flush = cdg_decode_flush, - .capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/cdtoons.c b/libavcodec/cdtoons.c index 14c15c457..eb53a324d 100644 --- a/libavcodec/cdtoons.c +++ b/libavcodec/cdtoons.c @@ -31,6 +31,7 @@ #include "libavutil/internal.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" #define CDTOONS_HEADER_SIZE 44 @@ -150,7 +151,7 @@ static int cdtoons_render_sprite(AVCodecContext *avctx, const uint8_t *data, return 0; } -static int cdtoons_decode_frame(AVCodecContext *avctx, void *data, +static int cdtoons_decode_frame(AVCodecContext *avctx, AVFrame *rframe, int *got_frame, AVPacket *avpkt) { CDToonsContext *c = avctx->priv_data; @@ -397,7 +398,7 @@ done: memcpy(c->frame->data[1], c->pal, AVPALETTE_SIZE); - if ((ret = av_frame_ref(data, c->frame)) < 0) + if ((ret = av_frame_ref(rframe, c->frame)) < 0) return ret; *got_frame = 1; @@ -442,16 +443,16 @@ static av_cold int cdtoons_decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_cdtoons_decoder = { - .name = "cdtoons", - .long_name = NULL_IF_CONFIG_SMALL("CDToons video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_CDTOONS, +const FFCodec ff_cdtoons_decoder = { + .p.name = "cdtoons", + .p.long_name = NULL_IF_CONFIG_SMALL("CDToons video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_CDTOONS, .priv_data_size = sizeof(CDToonsContext), .init = cdtoons_decode_init, .close = cdtoons_decode_end, - .decode = cdtoons_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(cdtoons_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .flush = cdtoons_flush, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/cdxl.c b/libavcodec/cdxl.c index 860dc639f..1f25d8eb9 100644 --- a/libavcodec/cdxl.c +++ b/libavcodec/cdxl.c @@ -31,6 +31,7 @@ #include "libavutil/imgutils.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" @@ -242,11 +243,10 @@ static void cdxl_decode_ham8(CDXLVideoContext *c, AVFrame *frame) } } -static int cdxl_decode_frame(AVCodecContext *avctx, void *data, +static int cdxl_decode_frame(AVCodecContext *avctx, AVFrame *p, int *got_frame, AVPacket *pkt) { CDXLVideoContext *c = avctx->priv_data; - AVFrame * const p = data; int ret, w, h, encoding, aligned_width, buf_size = pkt->size; const uint8_t *buf = pkt->data; @@ -336,15 +336,15 @@ static av_cold int cdxl_decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_cdxl_decoder = { - .name = "cdxl", - .long_name = NULL_IF_CONFIG_SMALL("Commodore CDXL video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_CDXL, +const FFCodec ff_cdxl_decoder = { + .p.name = "cdxl", + .p.long_name = NULL_IF_CONFIG_SMALL("Commodore CDXL video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_CDXL, .priv_data_size = sizeof(CDXLVideoContext), .init = cdxl_decode_init, .close = cdxl_decode_end, - .decode = cdxl_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(cdxl_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/celp_filters.c b/libavcodec/celp_filters.c index b96ebcebb..4f627e009 100644 --- a/libavcodec/celp_filters.c +++ b/libavcodec/celp_filters.c @@ -215,6 +215,7 @@ void ff_celp_filter_init(CELPFContext *c) c->celp_lp_synthesis_filterf = ff_celp_lp_synthesis_filterf; c->celp_lp_zero_synthesis_filterf = ff_celp_lp_zero_synthesis_filterf; - if(HAVE_MIPSFPU) - ff_celp_filter_init_mips(c); +#if HAVE_MIPSFPU + ff_celp_filter_init_mips(c); +#endif } diff --git a/libavcodec/celp_math.c b/libavcodec/celp_math.c index 920995a87..a5fe7f2ea 100644 --- a/libavcodec/celp_math.c +++ b/libavcodec/celp_math.c @@ -20,14 +20,13 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include -#include +#include +#include "config.h" #include "libavutil/avassert.h" -#include "avcodec.h" +#include "libavutil/intmath.h" #include "mathops.h" #include "celp_math.h" -#include "libavutil/common.h" #ifdef G729_BITEXACT static const uint16_t exp2a[]= @@ -123,6 +122,7 @@ void ff_celp_math_init(CELPMContext *c) { c->dot_productf = ff_dot_productf; - if(HAVE_MIPSFPU) - ff_celp_math_init_mips(c); +#if HAVE_MIPSFPU + ff_celp_math_init_mips(c); +#endif } diff --git a/libavcodec/cfhd.c b/libavcodec/cfhd.c index ac7826250..5adb0b200 100644 --- a/libavcodec/cfhd.c +++ b/libavcodec/cfhd.c @@ -32,6 +32,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" #include "thread.h" @@ -372,14 +373,12 @@ static int alloc_buffers(AVCodecContext *avctx) return 0; } -static int cfhd_decode(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int cfhd_decode(AVCodecContext *avctx, AVFrame *pic, + int *got_frame, AVPacket *avpkt) { CFHDContext *s = avctx->priv_data; CFHDDSPContext *dsp = &s->dsp; GetByteContext gb; - ThreadFrame frame = { .f = data }; - AVFrame *pic = data; int ret = 0, i, j, plane, got_buffer = 0; int16_t *coeff_data; @@ -681,10 +680,9 @@ static int cfhd_decode(AVCodecContext *avctx, void *data, int *got_frame, return AVERROR_INVALIDDATA; avctx->height = height; } - frame.f->width = - frame.f->height = 0; + pic->width = pic->height = 0; - if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, pic, 0)) < 0) return ret; s->coded_width = 0; @@ -692,10 +690,9 @@ static int cfhd_decode(AVCodecContext *avctx, void *data, int *got_frame, s->coded_format = AV_PIX_FMT_NONE; got_buffer = 1; } else if (tag == FrameIndex && data == 1 && s->sample_type == 1 && s->frame_type == 2) { - frame.f->width = - frame.f->height = 0; + pic->width = pic->height = 0; - if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, pic, 0)) < 0) return ret; s->coded_width = 0; s->coded_height = 0; @@ -1458,16 +1455,16 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src) } #endif -const AVCodec ff_cfhd_decoder = { - .name = "cfhd", - .long_name = NULL_IF_CONFIG_SMALL("GoPro CineForm HD"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_CFHD, +const FFCodec ff_cfhd_decoder = { + .p.name = "cfhd", + .p.long_name = NULL_IF_CONFIG_SMALL("GoPro CineForm HD"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_CFHD, .priv_data_size = sizeof(CFHDContext), .init = cfhd_init, .close = cfhd_close, - .decode = cfhd_decode, + FF_CODEC_DECODE_CB(cfhd_decode), .update_thread_context = ONLY_IF_THREADS_ENABLED(update_thread_context), - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .p.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/cfhddata.c b/libavcodec/cfhddata.c index 5df68d4b3..55c8004bd 100644 --- a/libavcodec/cfhddata.c +++ b/libavcodec/cfhddata.c @@ -308,8 +308,8 @@ av_cold int ff_cfhd_init_vlcs(CFHDContext *s) if (ret < 0) return ret; for (i = 0; i < s->vlc_9.table_size; i++) { - int code = s->vlc_9.table[i][0]; - int len = s->vlc_9.table[i][1]; + int code = s->vlc_9.table[i].sym; + int len = s->vlc_9.table[i].len; int level, run; if (len < 0) { // more bits needed @@ -351,8 +351,8 @@ av_cold int ff_cfhd_init_vlcs(CFHDContext *s) av_assert0(s->vlc_18.table_size == 4572); for (i = 0; i < s->vlc_18.table_size; i++) { - int code = s->vlc_18.table[i][0]; - int len = s->vlc_18.table[i][1]; + int code = s->vlc_18.table[i].sym; + int len = s->vlc_18.table[i].len; int level, run; if (len < 0) { // more bits needed diff --git a/libavcodec/cfhddsp.c b/libavcodec/cfhddsp.c index da9254c71..a141db524 100644 --- a/libavcodec/cfhddsp.c +++ b/libavcodec/cfhddsp.c @@ -112,6 +112,7 @@ av_cold void ff_cfhddsp_init(CFHDDSPContext *c, int depth, int bayer) else c->horiz_filter_clip = horiz_filter_clip; - if (ARCH_X86) - ff_cfhddsp_init_x86(c, depth, bayer); +#if ARCH_X86 + ff_cfhddsp_init_x86(c, depth, bayer); +#endif } diff --git a/libavcodec/cfhdenc.c b/libavcodec/cfhdenc.c index 3d87064a4..6b33b29da 100644 --- a/libavcodec/cfhdenc.c +++ b/libavcodec/cfhdenc.c @@ -33,9 +33,9 @@ #include "bytestream.h" #include "cfhd.h" #include "cfhdencdsp.h" +#include "codec_internal.h" #include "encode.h" #include "put_bits.h" -#include "internal.h" #include "thread.h" /* Derived from existing tables from decoder */ @@ -845,18 +845,18 @@ static const AVClass cfhd_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_cfhd_encoder = { - .name = "cfhd", - .long_name = NULL_IF_CONFIG_SMALL("GoPro CineForm HD"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_CFHD, +const FFCodec ff_cfhd_encoder = { + .p.name = "cfhd", + .p.long_name = NULL_IF_CONFIG_SMALL("GoPro CineForm HD"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_CFHD, .priv_data_size = sizeof(CFHDEncContext), - .priv_class = &cfhd_class, + .p.priv_class = &cfhd_class, .init = cfhd_encode_init, .close = cfhd_encode_close, - .encode2 = cfhd_encode_frame, - .capabilities = AV_CODEC_CAP_FRAME_THREADS, - .pix_fmts = (const enum AVPixelFormat[]) { + FF_CODEC_ENCODE_CB(cfhd_encode_frame), + .p.capabilities = AV_CODEC_CAP_FRAME_THREADS, + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV422P10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRAP12, diff --git a/libavcodec/cfhdencdsp.c b/libavcodec/cfhdencdsp.c index 5bd4d1ba0..3a35522d6 100644 --- a/libavcodec/cfhdencdsp.c +++ b/libavcodec/cfhdencdsp.c @@ -73,6 +73,7 @@ av_cold void ff_cfhdencdsp_init(CFHDEncDSPContext *c) c->horiz_filter = horiz_filter; c->vert_filter = vert_filter; - if (ARCH_X86) - ff_cfhdencdsp_init_x86(c); +#if ARCH_X86 + ff_cfhdencdsp_init_x86(c); +#endif } diff --git a/libavcodec/chomp_bsf.c b/libavcodec/chomp_bsf.c index 48b933646..532b4e6a9 100644 --- a/libavcodec/chomp_bsf.c +++ b/libavcodec/chomp_bsf.c @@ -39,7 +39,7 @@ static int chomp_filter(AVBSFContext *ctx, AVPacket *pkt) /** * This filter removes a string of NULL bytes from the end of a packet. */ -const AVBitStreamFilter ff_chomp_bsf = { - .name = "chomp", +const FFBitStreamFilter ff_chomp_bsf = { + .p.name = "chomp", .filter = chomp_filter, }; diff --git a/libavcodec/cinepak.c b/libavcodec/cinepak.c index 090ab9cea..e69232efb 100644 --- a/libavcodec/cinepak.c +++ b/libavcodec/cinepak.c @@ -40,6 +40,7 @@ #include "libavutil/common.h" #include "libavutil/intreadwrite.h" #include "avcodec.h" +#include "codec_internal.h" #include "decode.h" #include "internal.h" @@ -448,9 +449,8 @@ static av_cold int cinepak_decode_init(AVCodecContext *avctx) return 0; } -static int cinepak_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int cinepak_decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int ret = 0, buf_size = avpkt->size; @@ -488,7 +488,7 @@ static int cinepak_decode_frame(AVCodecContext *avctx, if (s->palette_video) memcpy (s->frame->data[1], s->pal, AVPALETTE_SIZE); - if ((ret = av_frame_ref(data, s->frame)) < 0) + if ((ret = av_frame_ref(rframe, s->frame)) < 0) return ret; *got_frame = 1; @@ -506,15 +506,15 @@ static av_cold int cinepak_decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_cinepak_decoder = { - .name = "cinepak", - .long_name = NULL_IF_CONFIG_SMALL("Cinepak"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_CINEPAK, +const FFCodec ff_cinepak_decoder = { + .p.name = "cinepak", + .p.long_name = NULL_IF_CONFIG_SMALL("Cinepak"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_CINEPAK, .priv_data_size = sizeof(CinepakContext), .init = cinepak_decode_init, .close = cinepak_decode_end, - .decode = cinepak_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(cinepak_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/cinepakenc.c b/libavcodec/cinepakenc.c index 0574b125d..6cfe8de20 100644 --- a/libavcodec/cinepakenc.c +++ b/libavcodec/cinepakenc.c @@ -44,9 +44,9 @@ #include "libavutil/opt.h" #include "avcodec.h" +#include "codec_internal.h" #include "elbg.h" #include "encode.h" -#include "internal.h" #define CVID_HEADER_SIZE 10 #define STRIP_HEADER_SIZE 12 @@ -113,7 +113,7 @@ typedef struct CinepakEncContext { enum AVPixelFormat pix_fmt; int w, h; int frame_buf_size; - int curframe, keyint; + int curframe; AVLFG randctx; uint64_t lambda; int *codebook_input; @@ -215,7 +215,6 @@ static av_cold int cinepak_encode_init(AVCodecContext *avctx) 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 @@ -835,8 +834,7 @@ static void calculate_skip_errors(CinepakEncContext *s, int h, } } -static void write_strip_header(CinepakEncContext *s, int y, int h, int keyframe, - unsigned char *buf, int strip_size) +static void write_strip_keyframe(unsigned char *buf, int keyframe) { // actually we are exclusively using intra strip coding (how much can we win // otherwise? how to choose which part of a codebook to update?), @@ -844,6 +842,12 @@ static void write_strip_header(CinepakEncContext *s, int y, int h, int keyframe, // (besides, the logic here used to be inverted: ) // buf[0] = keyframe ? 0x11: 0x10; buf[0] = keyframe ? 0x10 : 0x11; +} + +static void write_strip_header(CinepakEncContext *s, int y, int h, int keyframe, + unsigned char *buf, int strip_size) +{ + write_strip_keyframe(buf, keyframe); AV_WB24(&buf[1], strip_size + STRIP_HEADER_SIZE); // AV_WB16(&buf[4], y); /* using absolute y values works -- rl */ AV_WB16(&buf[4], 0); /* using relative values works as well -- rl */ @@ -857,7 +861,7 @@ 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) + unsigned char *buf, int64_t *best_score, int *no_skip) { int64_t score = 0; int best_size = 0; @@ -973,6 +977,9 @@ static int rd_strip(CinepakEncContext *s, int y, int h, int keyframe, scratch_data, scratch_linesize, last_data, last_linesize, &info, s->strip_buf + STRIP_HEADER_SIZE); + // in theory we could have MODE_MC without ENC_SKIP, + // but MODE_V1_V4 will always be more efficient + *no_skip = info.mode != MODE_MC; write_strip_header(s, y, h, keyframe, s->strip_buf, best_size); } @@ -999,13 +1006,13 @@ static int write_cvid_header(CinepakEncContext *s, unsigned char *buf, } static int rd_frame(CinepakEncContext *s, const AVFrame *frame, - int isakeyframe, unsigned char *buf, int buf_size) + int isakeyframe, unsigned char *buf, int buf_size, int *got_keyframe) { int num_strips, strip, i, y, nexty, size, temp_size, best_size; 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; + int best_nstrips, best_strip_offsets[MAX_STRIPS]; if (s->pix_fmt == AV_PIX_FMT_RGB24) { int x; @@ -1064,12 +1071,15 @@ static int rd_frame(CinepakEncContext *s, const AVFrame *frame, // 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++) { + int strip_offsets[MAX_STRIPS]; + int all_no_skip = 1; score = 0; size = 0; for (y = 0, strip = 1; y < s->h; strip++, y = nexty) { - int strip_height; + int strip_height, no_skip; + strip_offsets[strip-1] = size + CVID_HEADER_SIZE; nexty = strip * s->h / num_strips; // <= s->h // make nexty the next multiple of 4 if not already there if (nexty & 3) @@ -1099,21 +1109,24 @@ static int rd_frame(CinepakEncContext *s, const AVFrame *frame, 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) + s->frame_buf + strip_offsets[strip-1], + &score_temp, &no_skip)) < 0) return temp_size; score += score_temp; size += temp_size; + all_no_skip &= no_skip; } if (best_score == 0 || score < best_score) { best_score = score; - best_size = size + write_cvid_header(s, s->frame_buf, num_strips, size, isakeyframe); + best_size = size + write_cvid_header(s, s->frame_buf, num_strips, size, all_no_skip); FFSWAP(AVFrame *, s->best_frame, s->scratch_frame); memcpy(buf, s->frame_buf, best_size); best_nstrips = num_strips; + *got_keyframe = all_no_skip; // no skip MBs in any strip -> keyframe + memcpy(best_strip_offsets, strip_offsets, sizeof(strip_offsets)); } // avoid trying too many strip numbers without a real reason // (this makes the processing of the very first frame faster) @@ -1121,6 +1134,11 @@ static int rd_frame(CinepakEncContext *s, const AVFrame *frame, break; } + // update strip headers + for (i = 0; i < best_nstrips; i++) { + write_strip_keyframe(s->frame_buf + best_strip_offsets[i], *got_keyframe); + } + // 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 @@ -1151,21 +1169,23 @@ static int cinepak_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_packet) { CinepakEncContext *s = avctx->priv_data; - int ret; + int ret, got_keyframe; s->lambda = frame->quality ? frame->quality - 1 : 2 * FF_LAMBDA_SCALE; if ((ret = ff_alloc_packet(avctx, 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, &got_keyframe); pkt->size = ret; - if (s->curframe == 0) + if (got_keyframe) { pkt->flags |= AV_PKT_FLAG_KEY; + s->curframe = 0; + } *got_packet = 1; FFSWAP(AVFrame *, s->last_frame, s->best_frame); - if (++s->curframe >= s->keyint) + if (++s->curframe >= avctx->gop_size) s->curframe = 0; return 0; @@ -1194,16 +1214,16 @@ static av_cold int cinepak_encode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_cinepak_encoder = { - .name = "cinepak", - .long_name = NULL_IF_CONFIG_SMALL("Cinepak"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_CINEPAK, +const FFCodec ff_cinepak_encoder = { + .p.name = "cinepak", + .p.long_name = NULL_IF_CONFIG_SMALL("Cinepak"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_CINEPAK, .priv_data_size = sizeof(CinepakEncContext), .init = cinepak_encode_init, - .encode2 = cinepak_encode_frame, + FF_CODEC_ENCODE_CB(cinepak_encode_frame), .close = cinepak_encode_end, - .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_RGB24, AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE }, - .priv_class = &cinepak_class, + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_RGB24, AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE }, + .p.priv_class = &cinepak_class, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/clearvideo.c b/libavcodec/clearvideo.c index 5ed8ac71d..075c6e946 100644 --- a/libavcodec/clearvideo.c +++ b/libavcodec/clearvideo.c @@ -29,6 +29,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "get_bits.h" #include "idctdsp.h" #include "internal.h" @@ -83,7 +84,7 @@ typedef struct CLVContext { static VLC dc_vlc, ac_vlc; static LevelCodes lev[4 + 3 + 3]; // 0..3: Y, 4..6: U, 7..9: V -static VLC_TYPE vlc_buf[16716][2]; +static VLCElem vlc_buf[16716]; static inline int decode_block(CLVContext *ctx, int16_t *blk, int has_ac, int ac_quant) @@ -498,7 +499,7 @@ static void extend_edges(AVFrame *buf, int tile_size) } } -static int clv_decode_frame(AVCodecContext *avctx, void *data, +static int clv_decode_frame(AVCodecContext *avctx, AVFrame *rframe, int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; @@ -637,7 +638,7 @@ static int clv_decode_frame(AVCodecContext *avctx, void *data, c->pic->pict_type = AV_PICTURE_TYPE_P; } - if ((ret = av_frame_ref(data, c->pic)) < 0) + if ((ret = av_frame_ref(rframe, c->pic)) < 0) return ret; FFSWAP(AVFrame *, c->pic, c->prev); @@ -766,15 +767,15 @@ static av_cold int clv_decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_clearvideo_decoder = { - .name = "clearvideo", - .long_name = NULL_IF_CONFIG_SMALL("Iterated Systems ClearVideo"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_CLEARVIDEO, +const FFCodec ff_clearvideo_decoder = { + .p.name = "clearvideo", + .p.long_name = NULL_IF_CONFIG_SMALL("Iterated Systems ClearVideo"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.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, + FF_CODEC_DECODE_CB(clv_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/cljrdec.c b/libavcodec/cljrdec.c index 4a8c9d2ae..bb7c9bfb6 100644 --- a/libavcodec/cljrdec.c +++ b/libavcodec/cljrdec.c @@ -25,17 +25,16 @@ */ #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" -static int decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *p, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; GetBitContext gb; - AVFrame * const p = data; int x, y, ret; if (avctx->height <= 0 || avctx->width <= 0) { @@ -82,14 +81,14 @@ static av_cold int decode_init(AVCodecContext *avctx) return 0; } -const AVCodec ff_cljr_decoder = { - .name = "cljr", - .long_name = NULL_IF_CONFIG_SMALL("Cirrus Logic AccuPak"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_CLJR, +const FFCodec ff_cljr_decoder = { + .p.name = "cljr", + .p.long_name = NULL_IF_CONFIG_SMALL("Cirrus Logic AccuPak"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_CLJR, .init = decode_init, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/cljrenc.c b/libavcodec/cljrenc.c index aa53a110d..2d171a937 100644 --- a/libavcodec/cljrenc.c +++ b/libavcodec/cljrenc.c @@ -24,12 +24,11 @@ * Cirrus Logic AccuPak encoder. */ -#include "libavutil/common.h" #include "libavutil/opt.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "put_bits.h" typedef struct CLJRContext { @@ -109,15 +108,15 @@ static const AVClass cljr_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_cljr_encoder = { - .name = "cljr", - .long_name = NULL_IF_CONFIG_SMALL("Cirrus Logic AccuPak"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_CLJR, - .capabilities = AV_CODEC_CAP_DR1, +const FFCodec ff_cljr_encoder = { + .p.name = "cljr", + .p.long_name = NULL_IF_CONFIG_SMALL("Cirrus Logic AccuPak"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_CLJR, + .p.capabilities = AV_CODEC_CAP_DR1, .priv_data_size = sizeof(CLJRContext), - .encode2 = encode_frame, - .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV411P, + FF_CODEC_ENCODE_CB(encode_frame), + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV411P, AV_PIX_FMT_NONE }, - .priv_class = &cljr_class, + .p.priv_class = &cljr_class, }; diff --git a/libavcodec/cllc.c b/libavcodec/cllc.c index 41b3a4ef8..4866c5b2d 100644 --- a/libavcodec/cllc.c +++ b/libavcodec/cllc.c @@ -27,7 +27,7 @@ #include "canopus.h" #include "get_bits.h" #include "avcodec.h" -#include "internal.h" +#include "codec_internal.h" #include "thread.h" #define VLC_BITS 7 @@ -355,13 +355,11 @@ static int decode_yuv_frame(CLLCContext *ctx, GetBitContext *gb, AVFrame *pic) return 0; } -static int cllc_decode_frame(AVCodecContext *avctx, void *data, +static int cllc_decode_frame(AVCodecContext *avctx, AVFrame *pic, int *got_picture_ptr, AVPacket *avpkt) { CLLCContext *ctx = avctx->priv_data; - AVFrame *pic = data; - ThreadFrame frame = { .f = data }; - uint8_t *src = avpkt->data; + const uint8_t *src = avpkt->data; uint32_t info_tag, info_offset; int data_size; GetBitContext gb; @@ -424,7 +422,7 @@ static int cllc_decode_frame(AVCodecContext *avctx, void *data, avctx->pix_fmt = AV_PIX_FMT_YUV422P; avctx->bits_per_raw_sample = 8; - if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, pic, 0)) < 0) return ret; ret = decode_yuv_frame(ctx, &gb, pic); @@ -437,7 +435,7 @@ static int cllc_decode_frame(AVCodecContext *avctx, void *data, avctx->pix_fmt = AV_PIX_FMT_RGB24; avctx->bits_per_raw_sample = 8; - if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, pic, 0)) < 0) return ret; ret = decode_rgb24_frame(ctx, &gb, pic); @@ -449,7 +447,7 @@ static int cllc_decode_frame(AVCodecContext *avctx, void *data, avctx->pix_fmt = AV_PIX_FMT_ARGB; avctx->bits_per_raw_sample = 8; - if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, pic, 0)) < 0) return ret; ret = decode_argb_frame(ctx, &gb, pic); @@ -493,15 +491,15 @@ static av_cold int cllc_decode_init(AVCodecContext *avctx) return 0; } -const AVCodec ff_cllc_decoder = { - .name = "cllc", - .long_name = NULL_IF_CONFIG_SMALL("Canopus Lossless Codec"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_CLLC, +const FFCodec ff_cllc_decoder = { + .p.name = "cllc", + .p.long_name = NULL_IF_CONFIG_SMALL("Canopus Lossless Codec"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_CLLC, .priv_data_size = sizeof(CLLCContext), .init = cllc_decode_init, - .decode = cllc_decode_frame, + FF_CODEC_DECODE_CB(cllc_decode_frame), .close = cllc_decode_close, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/cngdec.c b/libavcodec/cngdec.c index ecfd4abfc..d549ff4c0 100644 --- a/libavcodec/cngdec.c +++ b/libavcodec/cngdec.c @@ -26,6 +26,7 @@ #include "libavutil/intreadwrite.h" #include "avcodec.h" #include "celp_filters.h" +#include "codec_internal.h" #include "internal.h" #include "libavutil/lfg.h" @@ -56,7 +57,8 @@ static av_cold int cng_decode_init(AVCodecContext *avctx) CNGContext *p = avctx->priv_data; avctx->sample_fmt = AV_SAMPLE_FMT_S16; - avctx->channels = 1; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; avctx->sample_rate = 8000; p->order = 12; @@ -100,10 +102,9 @@ static void cng_decode_flush(AVCodecContext *avctx) p->inited = 0; } -static int cng_decode_frame(AVCodecContext *avctx, void *data, +static int cng_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; CNGContext *p = avctx->priv_data; int buf_size = avpkt->size; int ret, i; @@ -161,19 +162,19 @@ static int cng_decode_frame(AVCodecContext *avctx, void *data, return buf_size; } -const AVCodec ff_comfortnoise_decoder = { - .name = "comfortnoise", - .long_name = NULL_IF_CONFIG_SMALL("RFC 3389 comfort noise generator"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_COMFORT_NOISE, +const FFCodec ff_comfortnoise_decoder = { + .p.name = "comfortnoise", + .p.long_name = NULL_IF_CONFIG_SMALL("RFC 3389 comfort noise generator"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_COMFORT_NOISE, .priv_data_size = sizeof(CNGContext), .init = cng_decode_init, - .decode = cng_decode_frame, + FF_CODEC_DECODE_CB(cng_decode_frame), .flush = cng_decode_flush, .close = cng_decode_close, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/cngenc.c b/libavcodec/cngenc.c index 830311f95..1f5d25e5b 100644 --- a/libavcodec/cngenc.c +++ b/libavcodec/cngenc.c @@ -23,8 +23,8 @@ #include "libavutil/common.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "lpc.h" typedef struct CNGContext { @@ -48,11 +48,6 @@ static av_cold int cng_encode_init(AVCodecContext *avctx) CNGContext *p = avctx->priv_data; int ret; - if (avctx->channels != 1) { - av_log(avctx, AV_LOG_ERROR, "Only mono supported\n"); - return AVERROR(EINVAL); - } - avctx->frame_size = 640; p->order = 10; if ((ret = ff_lpc_init(&p->lpc, avctx->frame_size, p->order, FF_LPC_TYPE_LEVINSON)) < 0) @@ -101,17 +96,18 @@ static int cng_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, return 0; } -const AVCodec ff_comfortnoise_encoder = { - .name = "comfortnoise", - .long_name = NULL_IF_CONFIG_SMALL("RFC 3389 comfort noise generator"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_COMFORT_NOISE, - .capabilities = AV_CODEC_CAP_DR1, +const FFCodec ff_comfortnoise_encoder = { + .p.name = "comfortnoise", + .p.long_name = NULL_IF_CONFIG_SMALL("RFC 3389 comfort noise generator"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_COMFORT_NOISE, + .p.capabilities = AV_CODEC_CAP_DR1, .priv_data_size = sizeof(CNGContext), .init = cng_encode_init, - .encode2 = cng_encode_frame, + FF_CODEC_ENCODE_CB(cng_encode_frame), .close = cng_encode_close, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, + .p.ch_layouts = (const AVChannelLayout[]){ AV_CHANNEL_LAYOUT_MONO, { 0 } }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/codec.h b/libavcodec/codec.h index a8147ec21..03e8be90a 100644 --- a/libavcodec/codec.h +++ b/libavcodec/codec.h @@ -31,7 +31,7 @@ #include "libavutil/samplefmt.h" #include "libavcodec/codec_id.h" -#include "libavcodec/version.h" +#include "libavcodec/version_major.h" /** * @addtogroup lavc_core @@ -190,12 +190,6 @@ typedef struct AVProfile { const char *name; ///< short name for the profile } AVProfile; -typedef struct AVCodecDefault AVCodecDefault; - -struct AVCodecContext; -struct AVSubtitle; -struct AVPacket; - /** * AVCodec. */ @@ -224,7 +218,13 @@ typedef struct AVCodec { const enum AVPixelFormat *pix_fmts; ///< array of supported pixel formats, or NULL if unknown, array is terminated by -1 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 +#if FF_API_OLD_CHANNEL_LAYOUT + /** + * @deprecated use ch_layouts instead + */ + attribute_deprecated const uint64_t *channel_layouts; ///< array of support channel layouts, or NULL if unknown. array is terminated by 0 +#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} @@ -240,120 +240,10 @@ typedef struct AVCodec { */ 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 - * removed at will. - * New public fields should be added right above. - ***************************************************************** - */ /** - * Internal codec capabilities. - * See FF_CODEC_CAP_* in internal.h + * Array of supported channel layouts, terminated with a zeroed layout. */ - int caps_internal; - - int priv_data_size; - /** - * @name Frame-level threading support functions - * @{ - */ - /** - * Copy necessary context variables from a previous thread context to the current one. - * If not defined, the next thread will start automatically; otherwise, the codec - * must call ff_thread_finish_setup(). - * - * dst and src will (rarely) point to the same context, in which case memcpy should be skipped. - */ - int (*update_thread_context)(struct AVCodecContext *dst, const struct AVCodecContext *src); - - /** - * Copy variables back to the user-facing context - */ - int (*update_thread_context_for_user)(struct AVCodecContext *dst, const struct AVCodecContext *src); - /** @} */ - - /** - * Private codec-specific defaults. - */ - const AVCodecDefault *defaults; - - /** - * Initialize codec static data, called from av_codec_iterate(). - * - * 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); - - int (*init)(struct AVCodecContext *); - int (*encode_sub)(struct AVCodecContext *, uint8_t *buf, int buf_size, - const struct AVSubtitle *sub); - /** - * Encode data to an AVPacket. - * - * @param avctx codec context - * @param avpkt output AVPacket - * @param[in] frame AVFrame containing the raw data to be encoded - * @param[out] got_packet_ptr encoder sets to 0 or 1 to indicate that a - * non-empty packet was returned in avpkt. - * @return 0 on success, negative error code on failure - */ - int (*encode2)(struct AVCodecContext *avctx, struct AVPacket *avpkt, - const struct AVFrame *frame, int *got_packet_ptr); - /** - * Decode picture or subtitle data. - * - * @param avctx codec context - * @param outdata codec type dependent output struct - * @param[out] got_frame_ptr decoder sets to 0 or 1 to indicate that a - * non-empty frame or subtitle was returned in - * outdata. - * @param[in] avpkt AVPacket containing the data to be decoded - * @return amount of bytes read from the packet on success, negative error - * code on failure - */ - int (*decode)(struct AVCodecContext *avctx, void *outdata, - int *got_frame_ptr, struct AVPacket *avpkt); - int (*close)(struct AVCodecContext *); - /** - * Encode API with decoupled frame/packet dataflow. This function is called - * to get one output packet. It should call ff_encode_get_frame() to obtain - * input data. - */ - int (*receive_packet)(struct AVCodecContext *avctx, struct AVPacket *avpkt); - - /** - * Decode API with decoupled packet/frame dataflow. This function is called - * to get one output frame. It should call ff_decode_get_packet() to obtain - * input data. - */ - int (*receive_frame)(struct AVCodecContext *avctx, struct AVFrame *frame); - /** - * Flush buffers. - * Will be called when seeking - */ - void (*flush)(struct AVCodecContext *); - - /** - * Decoding only, a comma-separated list of bitstream filters to apply to - * 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 *const *hw_configs; - - /** - * List of supported codec_tags, terminated by FF_CODEC_TAGS_END. - */ - const uint32_t *codec_tags; + const AVChannelLayout *ch_layouts; } AVCodec; /** diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index 0974ee03d..44ad2d1fe 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -19,10 +19,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include -#include "libavutil/common.h" #include "libavutil/internal.h" +#include "libavutil/macros.h" #include "codec_id.h" #include "codec_desc.h" @@ -1862,6 +1863,36 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("GEM Raster image"), .props = AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_VBN, + .type = AVMEDIA_TYPE_VIDEO, + .name = "vbn", + .long_name = NULL_IF_CONFIG_SMALL("Vizrt Binary Image"), + .props = AV_CODEC_PROP_LOSSY, + }, + { + .id = AV_CODEC_ID_JPEGXL, + .type = AVMEDIA_TYPE_VIDEO, + .name = "jpegxl", + .long_name = NULL_IF_CONFIG_SMALL("JPEG XL"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY | + AV_CODEC_PROP_LOSSLESS, + .mime_types= MT("image/jxl"), + }, + { + .id = AV_CODEC_ID_QOI, + .type = AVMEDIA_TYPE_VIDEO, + .name = "qoi", + .long_name = NULL_IF_CONFIG_SMALL("QOI (Quite OK Image)"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, + { + .id = AV_CODEC_ID_PHM, + .type = AVMEDIA_TYPE_VIDEO, + .name = "phm", + .long_name = NULL_IF_CONFIG_SMALL("PHM (Portable HalfFloatMap) image"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, /* various PCM "codecs" */ { @@ -3236,6 +3267,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("MSN Siren"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_DFPWM, + .type = AVMEDIA_TYPE_AUDIO, + .name = "dfpwm", + .long_name = NULL_IF_CONFIG_SMALL("DFPWM (Dynamic Filter Pulse Width Modulation)"), + .props = AV_CODEC_PROP_LOSSY, + }, /* subtitle codecs */ { diff --git a/libavcodec/codec_id.h b/libavcodec/codec_id.h index ab265ec58..81fb316cf 100644 --- a/libavcodec/codec_id.h +++ b/libavcodec/codec_id.h @@ -308,6 +308,10 @@ enum AVCodecID { AV_CODEC_ID_SIMBIOSIS_IMX, AV_CODEC_ID_SGA_VIDEO, AV_CODEC_ID_GEM, + AV_CODEC_ID_VBN, + AV_CODEC_ID_JPEGXL, + AV_CODEC_ID_QOI, + AV_CODEC_ID_PHM, /* various PCM "codecs" */ AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs @@ -516,6 +520,7 @@ enum AVCodecID { AV_CODEC_ID_HCA, AV_CODEC_ID_FASTAUDIO, AV_CODEC_ID_MSNSIREN, + AV_CODEC_ID_DFPWM, /* subtitle codecs */ AV_CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs. diff --git a/libavcodec/codec_internal.h b/libavcodec/codec_internal.h new file mode 100644 index 000000000..5df286ce5 --- /dev/null +++ b/libavcodec/codec_internal.h @@ -0,0 +1,278 @@ +/* + * 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_CODEC_INTERNAL_H +#define AVCODEC_CODEC_INTERNAL_H + +#include + +#include "libavutil/attributes.h" +#include "codec.h" + +/** + * The codec does not modify any global variables in the init function, + * allowing to call the init function without locking any global mutexes. + */ +#define FF_CODEC_CAP_INIT_THREADSAFE (1 << 0) +/** + * The codec allows calling the close function for deallocation even if + * the init function returned a failure. Without this capability flag, a + * codec does such cleanup internally when returning failures from the + * init function and does not expect the close function to be called at + * all. + */ +#define FF_CODEC_CAP_INIT_CLEANUP (1 << 1) +/** + * Decoders marked with FF_CODEC_CAP_SETS_PKT_DTS want to set + * AVFrame.pkt_dts manually. If the flag is set, decode.c won't overwrite + * this field. If it's unset, decode.c tries to guess the pkt_dts field + * from the input AVPacket. + */ +#define FF_CODEC_CAP_SETS_PKT_DTS (1 << 2) +/** + * The decoder extracts and fills its parameters even if the frame is + * skipped due to the skip_frame setting. + */ +#define FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM (1 << 3) +/** + * The decoder sets the cropping fields in the output frames manually. + * If this cap is set, the generic code will initialize output frame + * dimensions to coded rather than display values. + */ +#define FF_CODEC_CAP_EXPORTS_CROPPING (1 << 4) +/** + * Codec initializes slice-based threading with a main function + */ +#define FF_CODEC_CAP_SLICE_THREAD_HAS_MF (1 << 5) +/* + * The codec supports frame threading and has inter-frame dependencies, so it + * uses ff_thread_report/await_progress(). + */ +#define FF_CODEC_CAP_ALLOCATE_PROGRESS (1 << 6) +/** + * Codec handles avctx->thread_count == 0 (auto) internally. + */ +#define FF_CODEC_CAP_AUTO_THREADS (1 << 7) +/** + * Codec handles output frame properties internally instead of letting the + * internal logic derive them from AVCodecInternal.last_pkt_props. + */ +#define FF_CODEC_CAP_SETS_FRAME_PROPS (1 << 8) + +/** + * FFCodec.codec_tags termination value + */ +#define FF_CODEC_TAGS_END -1 + +typedef struct FFCodecDefault { + const char *key; + const char *value; +} FFCodecDefault; + +struct AVCodecContext; +struct AVSubtitle; +struct AVPacket; + +enum FFCodecType { + /* The codec is a decoder using the decode callback; + * audio and video codecs only. */ + FF_CODEC_CB_TYPE_DECODE, + /* The codec is a decoder using the decode_sub callback; + * subtitle codecs only. */ + FF_CODEC_CB_TYPE_DECODE_SUB, + /* The codec is a decoder using the receive_frame callback; + * audio and video codecs only. */ + FF_CODEC_CB_TYPE_RECEIVE_FRAME, + /* The codec is an encoder using the encode callback; + * audio and video codecs only. */ + FF_CODEC_CB_TYPE_ENCODE, + /* The codec is an encoder using the encode_sub callback; + * subtitle codecs only. */ + FF_CODEC_CB_TYPE_ENCODE_SUB, + /* The codec is an encoder using the receive_packet callback; + * audio and video codecs only. */ + FF_CODEC_CB_TYPE_RECEIVE_PACKET, +}; + +typedef struct FFCodec { + /** + * The public AVCodec. See codec.h for it. + */ + AVCodec p; + + /** + * Internal codec capabilities FF_CODEC_CAP_*. + */ + unsigned caps_internal:29; + + /** + * This field determines the type of the codec (decoder/encoder) + * and also the exact callback cb implemented by the codec. + * cb_type uses enum FFCodecType values. + */ + unsigned cb_type:3; + + int priv_data_size; + /** + * @name Frame-level threading support functions + * @{ + */ + /** + * Copy necessary context variables from a previous thread context to the current one. + * If not defined, the next thread will start automatically; otherwise, the codec + * must call ff_thread_finish_setup(). + * + * dst and src will (rarely) point to the same context, in which case memcpy should be skipped. + */ + int (*update_thread_context)(struct AVCodecContext *dst, const struct AVCodecContext *src); + + /** + * Copy variables back to the user-facing context + */ + int (*update_thread_context_for_user)(struct AVCodecContext *dst, const struct AVCodecContext *src); + /** @} */ + + /** + * Private codec-specific defaults. + */ + const FFCodecDefault *defaults; + + /** + * Initialize codec static data, called from av_codec_iterate(). + * + * 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 FFCodec *codec); + + int (*init)(struct AVCodecContext *); + + union { + /** + * Decode to an AVFrame. + * cb is in this state if cb_type is FF_CODEC_CB_TYPE_DECODE. + * + * @param avctx codec context + * @param[out] frame AVFrame for output + * @param[out] got_frame_ptr decoder sets to 0 or 1 to indicate that + * a non-empty frame was returned in frame. + * @param[in] avpkt AVPacket containing the data to be decoded + * @return amount of bytes read from the packet on success, + * negative error code on failure + */ + int (*decode)(struct AVCodecContext *avctx, struct AVFrame *frame, + int *got_frame_ptr, struct AVPacket *avpkt); + /** + * Decode subtitle data to an AVSubtitle. + * cb is in this state if cb_type is FF_CODEC_CB_TYPE_DECODE_SUB. + * + * Apart from that this is like the decode callback. + */ + int (*decode_sub)(struct AVCodecContext *avctx, struct AVSubtitle *sub, + int *got_frame_ptr, const struct AVPacket *avpkt); + /** + * Decode API with decoupled packet/frame dataflow. + * cb is in this state if cb_type is FF_CODEC_CB_TYPE_RECEIVE_FRAME. + * + * This function is called to get one output frame. It should call + * ff_decode_get_packet() to obtain input data. + */ + int (*receive_frame)(struct AVCodecContext *avctx, struct AVFrame *frame); + /** + * Encode data to an AVPacket. + * cb is in this state if cb_type is FF_CODEC_CB_TYPE_ENCODE + * + * @param avctx codec context + * @param[out] avpkt output AVPacket + * @param[in] frame AVFrame containing the input to be encoded + * @param[out] got_packet_ptr encoder sets to 0 or 1 to indicate that a + * non-empty packet was returned in avpkt. + * @return 0 on success, negative error code on failure + */ + int (*encode)(struct AVCodecContext *avctx, struct AVPacket *avpkt, + const struct AVFrame *frame, int *got_packet_ptr); + /** + * Encode subtitles to a raw buffer. + * cb is in this state if cb_type is FF_CODEC_CB_TYPE_ENCODE_SUB. + */ + int (*encode_sub)(struct AVCodecContext *avctx, uint8_t *buf, + int buf_size, const struct AVSubtitle *sub); + /** + * Encode API with decoupled frame/packet dataflow. + * cb is in this state if cb_type is FF_CODEC_CB_TYPE_RECEIVE_PACKET. + * + * This function is called to get one output packet. + * It should call ff_encode_get_frame() to obtain input data. + */ + int (*receive_packet)(struct AVCodecContext *avctx, struct AVPacket *avpkt); + } cb; + + int (*close)(struct AVCodecContext *); + + /** + * Flush buffers. + * Will be called when seeking + */ + void (*flush)(struct AVCodecContext *); + + /** + * Decoding only, a comma-separated list of bitstream filters to apply to + * 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 *const *hw_configs; + + /** + * List of supported codec_tags, terminated by FF_CODEC_TAGS_END. + */ + const uint32_t *codec_tags; +} FFCodec; + +#define FF_CODEC_DECODE_CB(func) \ + .cb_type = FF_CODEC_CB_TYPE_DECODE, \ + .cb.decode = (func) +#define FF_CODEC_DECODE_SUB_CB(func) \ + .cb_type = FF_CODEC_CB_TYPE_DECODE_SUB, \ + .cb.decode_sub = (func) +#define FF_CODEC_RECEIVE_FRAME_CB(func) \ + .cb_type = FF_CODEC_CB_TYPE_RECEIVE_FRAME, \ + .cb.receive_frame = (func) +#define FF_CODEC_ENCODE_CB(func) \ + .cb_type = FF_CODEC_CB_TYPE_ENCODE, \ + .cb.encode = (func) +#define FF_CODEC_ENCODE_SUB_CB(func) \ + .cb_type = FF_CODEC_CB_TYPE_ENCODE_SUB, \ + .cb.encode_sub = (func) +#define FF_CODEC_RECEIVE_PACKET_CB(func) \ + .cb_type = FF_CODEC_CB_TYPE_RECEIVE_PACKET, \ + .cb.receive_packet = (func) + +static av_always_inline const FFCodec *ffcodec(const AVCodec *codec) +{ + return (const FFCodec*)codec; +} + +#endif /* AVCODEC_CODEC_INTERNAL_H */ diff --git a/libavcodec/codec_par.c b/libavcodec/codec_par.c index 1a5168a04..abda649aa 100644 --- a/libavcodec/codec_par.c +++ b/libavcodec/codec_par.c @@ -31,12 +31,14 @@ static void codec_parameters_reset(AVCodecParameters *par) { av_freep(&par->extradata); + av_channel_layout_uninit(&par->ch_layout); memset(par, 0, sizeof(*par)); par->codec_type = AVMEDIA_TYPE_UNKNOWN; par->codec_id = AV_CODEC_ID_NONE; par->format = -1; + par->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; par->field_order = AV_FIELD_UNKNOWN; par->color_range = AVCOL_RANGE_UNSPECIFIED; par->color_primaries = AVCOL_PRI_UNSPECIFIED; @@ -71,9 +73,12 @@ void avcodec_parameters_free(AVCodecParameters **ppar) int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src) { + int ret; + codec_parameters_reset(dst); memcpy(dst, src, sizeof(*dst)); + dst->ch_layout = (AVChannelLayout){0}; dst->extradata = NULL; dst->extradata_size = 0; if (src->extradata) { @@ -84,12 +89,18 @@ int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src dst->extradata_size = src->extradata_size; } + ret = av_channel_layout_copy(&dst->ch_layout, &src->ch_layout); + if (ret < 0) + return ret; + return 0; } int avcodec_parameters_from_context(AVCodecParameters *par, const AVCodecContext *codec) { + int ret; + codec_parameters_reset(par); par->codec_type = codec->codec_type; @@ -118,8 +129,32 @@ int avcodec_parameters_from_context(AVCodecParameters *par, break; case AVMEDIA_TYPE_AUDIO: par->format = codec->sample_fmt; - par->channel_layout = codec->channel_layout; - par->channels = codec->channels; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + // if the old/new fields are set inconsistently, prefer the old ones + if ((codec->channels && codec->channels != codec->ch_layout.nb_channels) || + (codec->channel_layout && (codec->ch_layout.order != AV_CHANNEL_ORDER_NATIVE || + codec->ch_layout.u.mask != codec->channel_layout))) { + if (codec->channel_layout) + av_channel_layout_from_mask(&par->ch_layout, codec->channel_layout); + else { + par->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + par->ch_layout.nb_channels = codec->channels; + } +FF_ENABLE_DEPRECATION_WARNINGS + } else { +#endif + ret = av_channel_layout_copy(&par->ch_layout, &codec->ch_layout); + if (ret < 0) + return ret; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + } + par->channel_layout = par->ch_layout.order == AV_CHANNEL_ORDER_NATIVE ? + par->ch_layout.u.mask : 0; + par->channels = par->ch_layout.nb_channels; +FF_ENABLE_DEPRECATION_WARNINGS +#endif par->sample_rate = codec->sample_rate; par->block_align = codec->block_align; par->frame_size = codec->frame_size; @@ -147,6 +182,8 @@ int avcodec_parameters_from_context(AVCodecParameters *par, int avcodec_parameters_to_context(AVCodecContext *codec, const AVCodecParameters *par) { + int ret; + codec->codec_type = par->codec_type; codec->codec_id = par->codec_id; codec->codec_tag = par->codec_tag; @@ -173,8 +210,32 @@ int avcodec_parameters_to_context(AVCodecContext *codec, break; case AVMEDIA_TYPE_AUDIO: codec->sample_fmt = par->format; - codec->channel_layout = par->channel_layout; - codec->channels = par->channels; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + // if the old/new fields are set inconsistently, prefer the old ones + if ((par->channels && par->channels != par->ch_layout.nb_channels) || + (par->channel_layout && (par->ch_layout.order != AV_CHANNEL_ORDER_NATIVE || + par->ch_layout.u.mask != par->channel_layout))) { + if (par->channel_layout) + av_channel_layout_from_mask(&codec->ch_layout, par->channel_layout); + else { + codec->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + codec->ch_layout.nb_channels = par->channels; + } +FF_ENABLE_DEPRECATION_WARNINGS + } else { +#endif + ret = av_channel_layout_copy(&codec->ch_layout, &par->ch_layout); + if (ret < 0) + return ret; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + } + codec->channel_layout = codec->ch_layout.order == AV_CHANNEL_ORDER_NATIVE ? + codec->ch_layout.u.mask : 0; + codec->channels = codec->ch_layout.nb_channels; +FF_ENABLE_DEPRECATION_WARNINGS +#endif codec->sample_rate = par->sample_rate; codec->block_align = par->block_align; codec->frame_size = par->frame_size; diff --git a/libavcodec/codec_par.h b/libavcodec/codec_par.h index 10cf79dff..7660791a1 100644 --- a/libavcodec/codec_par.h +++ b/libavcodec/codec_par.h @@ -24,6 +24,7 @@ #include #include "libavutil/avutil.h" +#include "libavutil/channel_layout.h" #include "libavutil/rational.h" #include "libavutil/pixfmt.h" @@ -154,16 +155,22 @@ typedef struct AVCodecParameters { */ int video_delay; +#if FF_API_OLD_CHANNEL_LAYOUT /** * Audio only. The channel layout bitmask. May be 0 if the channel layout is * unknown or unspecified, otherwise the number of bits set must be equal to * the channels field. + * @deprecated use ch_layout */ + attribute_deprecated uint64_t channel_layout; /** * Audio only. The number of audio channels. + * @deprecated use ch_layout.nb_channels */ + attribute_deprecated int channels; +#endif /** * Audio only. The number of audio samples per second. */ @@ -198,6 +205,11 @@ typedef struct AVCodecParameters { * Audio only. Number of samples to skip after a discontinuity. */ int seek_preroll; + + /** + * Audio only. The channel layout and number of channels. + */ + AVChannelLayout ch_layout; } AVCodecParameters; /** diff --git a/libavcodec/cook.c b/libavcodec/cook.c index 372077210..7161209db 100644 --- a/libavcodec/cook.c +++ b/libavcodec/cook.c @@ -51,6 +51,7 @@ #include "avcodec.h" #include "get_bits.h" #include "bytestream.h" +#include "codec_internal.h" #include "fft.h" #include "internal.h" #include "sinewin.h" @@ -977,10 +978,9 @@ static int decode_subpacket(COOKContext *q, COOKSubpacket *p, } -static int cook_decode_frame(AVCodecContext *avctx, void *data, +static int cook_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; COOKContext *q = avctx->priv_data; @@ -1054,7 +1054,7 @@ static void dump_cook_context(COOKContext *q) PRINT("js_vlc_bits", q->subpacket[0].js_vlc_bits); } ff_dlog(q->avctx, "COOKContext\n"); - PRINT("nb_channels", q->avctx->channels); + PRINT("nb_channels", q->avctx->ch_layout.nb_channels); PRINT("bit_rate", (int)q->avctx->bit_rate); PRINT("sample_rate", q->avctx->sample_rate); PRINT("samples_per_channel", q->subpacket[0].samples_per_channel); @@ -1079,6 +1079,8 @@ static av_cold int cook_decode_init(AVCodecContext *avctx) unsigned int channel_mask = 0; int samples_per_frame = 0; int ret; + int channels = avctx->ch_layout.nb_channels; + q->avctx = avctx; /* Take care of the codec specific extradata. */ @@ -1091,7 +1093,7 @@ static av_cold int cook_decode_init(AVCodecContext *avctx) bytestream2_init(&gb, avctx->extradata, avctx->extradata_size); /* Take data from the AVCodecContext (RM container). */ - if (!avctx->channels) { + if (!channels) { av_log(avctx, AV_LOG_ERROR, "Invalid number of channels\n"); return AVERROR_INVALIDDATA; } @@ -1123,7 +1125,7 @@ static av_cold int cook_decode_init(AVCodecContext *avctx) q->subpacket[s].js_vlc_bits = bytestream2_get_be16(&gb); /* Initialize extradata related variables. */ - q->subpacket[s].samples_per_channel = samples_per_frame / avctx->channels; + q->subpacket[s].samples_per_channel = samples_per_frame / channels; q->subpacket[s].bits_per_subpacket = avctx->block_align * 8; /* Initialize default data states. */ @@ -1138,21 +1140,21 @@ static av_cold int cook_decode_init(AVCodecContext *avctx) q->subpacket[s].joint_stereo = 0; switch (q->subpacket[s].cookversion) { case MONO: - if (avctx->channels != 1) { + if (channels != 1) { avpriv_request_sample(avctx, "Container channels != 1"); return AVERROR_PATCHWELCOME; } av_log(avctx, AV_LOG_DEBUG, "MONO\n"); break; case STEREO: - if (avctx->channels != 1) { + if (channels != 1) { q->subpacket[s].bits_per_subpdiv = 1; q->subpacket[s].num_channels = 2; } av_log(avctx, AV_LOG_DEBUG, "STEREO\n"); break; case JOINT_STEREO: - if (avctx->channels != 2) { + if (channels != 2) { avpriv_request_sample(avctx, "Container channels != 2"); return AVERROR_PATCHWELCOME; } @@ -1174,7 +1176,7 @@ static av_cold int cook_decode_init(AVCodecContext *avctx) av_log(avctx, AV_LOG_DEBUG, "MULTI_CHANNEL\n"); channel_mask |= q->subpacket[s].channel_mask = bytestream2_get_be32(&gb); - if (av_get_channel_layout_nb_channels(q->subpacket[s].channel_mask) > 1) { + if (av_popcount64(q->subpacket[s].channel_mask) > 1) { q->subpacket[s].total_subbands = q->subpacket[s].subbands + q->subpacket[s].js_subband_start; q->subpacket[s].joint_stereo = 1; @@ -1233,8 +1235,8 @@ static av_cold int cook_decode_init(AVCodecContext *avctx) q->subpacket[s].gains2.now = q->subpacket[s].gain_3; q->subpacket[s].gains2.previous = q->subpacket[s].gain_4; - if (q->num_subpackets + q->subpacket[s].num_channels > q->avctx->channels) { - av_log(avctx, AV_LOG_ERROR, "Too many subpackets %d for channels %d\n", q->num_subpackets, q->avctx->channels); + if (q->num_subpackets + q->subpacket[s].num_channels > channels) { + av_log(avctx, AV_LOG_ERROR, "Too many subpackets %d for channels %d\n", q->num_subpackets, channels); return AVERROR_INVALIDDATA; } @@ -1282,10 +1284,11 @@ static av_cold int cook_decode_init(AVCodecContext *avctx) } avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; + av_channel_layout_uninit(&avctx->ch_layout); if (channel_mask) - avctx->channel_layout = channel_mask; + av_channel_layout_from_mask(&avctx->ch_layout, channel_mask); else - avctx->channel_layout = (avctx->channels == 2) ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO; + av_channel_layout_default(&avctx->ch_layout, channels); dump_cook_context(q); @@ -1293,17 +1296,17 @@ static av_cold int cook_decode_init(AVCodecContext *avctx) return 0; } -const AVCodec ff_cook_decoder = { - .name = "cook", - .long_name = NULL_IF_CONFIG_SMALL("Cook / Cooker / Gecko (RealAudio G2)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_COOK, +const FFCodec ff_cook_decoder = { + .p.name = "cook", + .p.long_name = NULL_IF_CONFIG_SMALL("Cook / Cooker / Gecko (RealAudio G2)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_COOK, .priv_data_size = sizeof(COOKContext), .init = cook_decode_init, .close = cook_decode_close, - .decode = cook_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + FF_CODEC_DECODE_CB(cook_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/cook_parser.c b/libavcodec/cook_parser.c index a05ebf94b..0d9473845 100644 --- a/libavcodec/cook_parser.c +++ b/libavcodec/cook_parser.c @@ -41,8 +41,8 @@ static int cook_parse(AVCodecParserContext *s1, AVCodecContext *avctx, CookParseContext *s = s1->priv_data; if (!s->duration && - avctx->extradata && avctx->extradata_size >= 8 && avctx->channels) - s->duration = AV_RB16(avctx->extradata + 4) / avctx->channels; + avctx->extradata && avctx->extradata_size >= 8 && avctx->ch_layout.nb_channels) + s->duration = AV_RB16(avctx->extradata + 4) / avctx->ch_layout.nb_channels; s1->duration = s->duration; diff --git a/libavcodec/cpia.c b/libavcodec/cpia.c index a2ae16ec2..fcf2621e6 100644 --- a/libavcodec/cpia.c +++ b/libavcodec/cpia.c @@ -23,6 +23,7 @@ */ #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" @@ -47,14 +48,14 @@ typedef struct { } CpiaContext; -static int cpia_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, AVPacket* avpkt) +static int cpia_decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket* avpkt) { CpiaContext* const cpia = avctx->priv_data; int i,j,ret; - uint8_t* const header = avpkt->data; - uint8_t* src; + const uint8_t *const header = avpkt->data; + const uint8_t *src; int src_size; uint16_t linelength; uint8_t skip; @@ -184,7 +185,7 @@ static int cpia_decode_frame(AVCodecContext *avctx, } *got_frame = 1; - if ((ret = av_frame_ref(data, cpia->frame)) < 0) + if ((ret = av_frame_ref(rframe, cpia->frame)) < 0) return ret; return avpkt->size; @@ -221,15 +222,15 @@ static av_cold int cpia_decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_cpia_decoder = { - .name = "cpia", - .long_name = NULL_IF_CONFIG_SMALL("CPiA video format"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_CPIA, +const FFCodec ff_cpia_decoder = { + .p.name = "cpia", + .p.long_name = NULL_IF_CONFIG_SMALL("CPiA video format"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_CPIA, .priv_data_size = sizeof(CpiaContext), .init = cpia_decode_init, .close = cpia_decode_end, - .decode = cpia_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(cpia_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/cri.c b/libavcodec/cri.c index dfea24d97..728983797 100644 --- a/libavcodec/cri.c +++ b/libavcodec/cri.c @@ -31,6 +31,7 @@ #include "libavutil/display.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" #include "thread.h" @@ -169,16 +170,14 @@ static void unpack_10bit(GetByteContext *gb, uint16_t *dst, int shift, } } -static int cri_decode_frame(AVCodecContext *avctx, void *data, +static int cri_decode_frame(AVCodecContext *avctx, AVFrame *p, int *got_frame, AVPacket *avpkt) { CRIContext *s = avctx->priv_data; GetByteContext *gb = &s->gb; - ThreadFrame frame = { .f = data }; int ret, bps, hflip = 0, vflip = 0; AVFrameSideData *rotation; int compressed = 0; - AVFrame *p = data; s->data = NULL; s->data_size = 0; @@ -318,7 +317,7 @@ skip: if (!s->data || !s->data_size) return AVERROR_INVALIDDATA; - if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, p, 0)) < 0) return ret; avctx->bits_per_raw_sample = bps; @@ -424,15 +423,15 @@ static av_cold int cri_decode_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_cri_decoder = { - .name = "cri", - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_CRI, +const FFCodec ff_cri_decoder = { + .p.name = "cri", + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_CRI, .priv_data_size = sizeof(CRIContext), .init = cri_decode_init, - .decode = cri_decode_frame, + FF_CODEC_DECODE_CB(cri_decode_frame), .close = cri_decode_close, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .long_name = NULL_IF_CONFIG_SMALL("Cintel RAW"), + .p.long_name = NULL_IF_CONFIG_SMALL("Cintel RAW"), }; diff --git a/libavcodec/crystalhd.c b/libavcodec/crystalhd.c index 9202a16a7..cf74f22e7 100644 --- a/libavcodec/crystalhd.c +++ b/libavcodec/crystalhd.c @@ -45,6 +45,8 @@ * Includes ****************************************************************************/ +#include "config_components.h" + #define _XOPEN_SOURCE 600 #include #include @@ -55,6 +57,7 @@ #include #include "avcodec.h" +#include "codec_internal.h" #include "decode.h" #include "internal.h" #include "libavutil/imgutils.h" @@ -771,22 +774,22 @@ static int crystalhd_receive_frame(AVCodecContext *avctx, AVFrame *frame) .option = options, \ .version = LIBAVUTIL_VERSION_INT, \ }; \ - const AVCodec ff_##x##_crystalhd_decoder = { \ - .name = #x "_crystalhd", \ - .long_name = NULL_IF_CONFIG_SMALL("CrystalHD " #X " decoder"), \ - .type = AVMEDIA_TYPE_VIDEO, \ - .id = AV_CODEC_ID_##X, \ + const FFCodec ff_##x##_crystalhd_decoder = { \ + .p.name = #x "_crystalhd", \ + .p.long_name = NULL_IF_CONFIG_SMALL("CrystalHD " #X " decoder"), \ + .p.type = AVMEDIA_TYPE_VIDEO, \ + .p.id = AV_CODEC_ID_##X, \ .priv_data_size = sizeof(CHDContext), \ - .priv_class = &x##_crystalhd_class, \ + .p.priv_class = &x##_crystalhd_class, \ .init = init, \ .close = uninit, \ - .receive_frame = crystalhd_receive_frame, \ + FF_CODEC_RECEIVE_FRAME_CB(crystalhd_receive_frame), \ .flush = flush, \ .bsfs = bsf_name, \ - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, \ + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, \ .caps_internal = FF_CODEC_CAP_SETS_FRAME_PROPS, \ - .pix_fmts = (const enum AVPixelFormat[]){AV_PIX_FMT_YUYV422, AV_PIX_FMT_NONE}, \ - .wrapper_name = "crystalhd", \ + .p.pix_fmts = (const enum AVPixelFormat[]){AV_PIX_FMT_YUYV422, AV_PIX_FMT_NONE}, \ + .p.wrapper_name = "crystalhd", \ }; #if CONFIG_H264_CRYSTALHD_DECODER diff --git a/libavcodec/cscd.c b/libavcodec/cscd.c index 1b8262658..ea8471129 100644 --- a/libavcodec/cscd.c +++ b/libavcodec/cscd.c @@ -22,6 +22,7 @@ #include #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "libavutil/common.h" @@ -64,8 +65,8 @@ static void add_frame_default(AVFrame *f, const uint8_t *src, } } -static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; @@ -122,7 +123,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, } *got_frame = 1; - if ((ret = av_frame_ref(data, c->pic)) < 0) + if ((ret = av_frame_ref(rframe, c->pic)) < 0) return ret; return buf_size; @@ -166,15 +167,15 @@ static av_cold int decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_cscd_decoder = { - .name = "camstudio", - .long_name = NULL_IF_CONFIG_SMALL("CamStudio"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_CSCD, +const FFCodec ff_cscd_decoder = { + .p.name = "camstudio", + .p.long_name = NULL_IF_CONFIG_SMALL("CamStudio"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_CSCD, .priv_data_size = sizeof(CamStudioContext), .init = decode_init, .close = decode_end, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/cuviddec.c b/libavcodec/cuviddec.c index f03bbd8c4..b544b3361 100644 --- a/libavcodec/cuviddec.c +++ b/libavcodec/cuviddec.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "compat/cuda/dynlink_loader.h" #include "libavutil/buffer.h" @@ -32,6 +34,8 @@ #include "libavutil/pixdesc.h" #include "avcodec.h" +#include "bsf.h" +#include "codec_internal.h" #include "decode.h" #include "hwconfig.h" #include "nvdec.h" @@ -78,7 +82,7 @@ typedef struct CuvidContext AVBufferRef *hwdevice; AVBufferRef *hwframe; - AVFifoBuffer *frame_queue; + AVFifo *frame_queue; int deint_mode; int deint_mode_current; @@ -363,13 +367,13 @@ static int CUDAAPI cuvid_handle_picture_display(void *opaque, CUVIDPARSERDISPINF parsed_frame.dispinfo.progressive_frame = ctx->progressive_sequence; if (ctx->deint_mode_current == cudaVideoDeinterlaceMode_Weave) { - av_fifo_generic_write(ctx->frame_queue, &parsed_frame, sizeof(CuvidParsedFrame), NULL); + av_fifo_write(ctx->frame_queue, &parsed_frame, 1); } else { parsed_frame.is_deinterlacing = 1; - av_fifo_generic_write(ctx->frame_queue, &parsed_frame, sizeof(CuvidParsedFrame), NULL); + av_fifo_write(ctx->frame_queue, &parsed_frame, 1); if (!ctx->drop_second_field) { parsed_frame.second_field = 1; - av_fifo_generic_write(ctx->frame_queue, &parsed_frame, sizeof(CuvidParsedFrame), NULL); + av_fifo_write(ctx->frame_queue, &parsed_frame, 1); } } @@ -384,7 +388,7 @@ static int cuvid_is_buffer_full(AVCodecContext *avctx) if (ctx->deint_mode != cudaVideoDeinterlaceMode_Weave && !ctx->drop_second_field) delay *= 2; - return (av_fifo_size(ctx->frame_queue) / sizeof(CuvidParsedFrame)) + delay >= ctx->nb_surfaces; + return av_fifo_can_read(ctx->frame_queue) + delay >= ctx->nb_surfaces; } static int cuvid_decode_packet(AVCodecContext *avctx, const AVPacket *avpkt) @@ -458,6 +462,7 @@ static int cuvid_output_frame(AVCodecContext *avctx, AVFrame *frame) AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)ctx->hwdevice->data; AVCUDADeviceContext *device_hwctx = device_ctx->hwctx; CUcontext dummy, cuda_ctx = device_hwctx->cuda_ctx; + CuvidParsedFrame parsed_frame; CUdeviceptr mapped_frame = 0; int ret = 0, eret = 0; @@ -487,16 +492,13 @@ static int cuvid_output_frame(AVCodecContext *avctx, AVFrame *frame) if (ret < 0) return ret; - if (av_fifo_size(ctx->frame_queue)) { + if (av_fifo_read(ctx->frame_queue, &parsed_frame, 1) >= 0) { const AVPixFmtDescriptor *pixdesc; - CuvidParsedFrame parsed_frame; CUVIDPROCPARAMS params; unsigned int pitch = 0; int offset = 0; int i; - av_fifo_generic_read(ctx->frame_queue, &parsed_frame, sizeof(CuvidParsedFrame), NULL); - memset(¶ms, 0, sizeof(params)); params.progressive_frame = parsed_frame.dispinfo.progressive_frame; params.second_field = parsed_frame.second_field; @@ -653,21 +655,23 @@ error: static av_cold int cuvid_decode_end(AVCodecContext *avctx) { CuvidContext *ctx = avctx->priv_data; - AVHWDeviceContext *device_ctx = (AVHWDeviceContext *)ctx->hwdevice->data; - AVCUDADeviceContext *device_hwctx = device_ctx->hwctx; - CUcontext dummy, cuda_ctx = device_hwctx->cuda_ctx; + AVHWDeviceContext *device_ctx = ctx->hwdevice ? (AVHWDeviceContext *)ctx->hwdevice->data : NULL; + AVCUDADeviceContext *device_hwctx = device_ctx ? device_ctx->hwctx : NULL; + CUcontext dummy, cuda_ctx = device_hwctx ? device_hwctx->cuda_ctx : NULL; - av_fifo_freep(&ctx->frame_queue); + av_fifo_freep2(&ctx->frame_queue); - ctx->cudl->cuCtxPushCurrent(cuda_ctx); + if (cuda_ctx) { + ctx->cudl->cuCtxPushCurrent(cuda_ctx); - if (ctx->cuparser) - ctx->cvdl->cuvidDestroyVideoParser(ctx->cuparser); + if (ctx->cuparser) + ctx->cvdl->cuvidDestroyVideoParser(ctx->cuparser); - if (ctx->cudecoder) - ctx->cvdl->cuvidDestroyDecoder(ctx->cudecoder); + if (ctx->cudecoder) + ctx->cvdl->cuvidDestroyDecoder(ctx->cudecoder); - ctx->cudl->cuCtxPopCurrent(&dummy); + ctx->cudl->cuCtxPopCurrent(&dummy); + } ctx->cudl = NULL; @@ -834,7 +838,7 @@ static av_cold int cuvid_decode_init(AVCodecContext *avctx) goto error; } - ctx->frame_queue = av_fifo_alloc(ctx->nb_surfaces * sizeof(CuvidParsedFrame)); + ctx->frame_queue = av_fifo_alloc2(ctx->nb_surfaces, sizeof(CuvidParsedFrame), 0); if (!ctx->frame_queue) { ret = AVERROR(ENOMEM); goto error; @@ -942,7 +946,7 @@ static av_cold int cuvid_decode_init(AVCodecContext *avctx) return AVERROR_BUG; } - if (avctx->codec->bsfs) { + if (ffcodec(avctx->codec)->bsfs) { const AVCodecParameters *par = avctx->internal->bsf->par_out; extradata = par->extradata; extradata_size = par->extradata_size; @@ -951,6 +955,16 @@ static av_cold int cuvid_decode_init(AVCodecContext *avctx) extradata_size = avctx->extradata_size; } + // Check first bit to determine whether it's AV1CodecConfigurationRecord. + // Skip first 4 bytes of AV1CodecConfigurationRecord to keep configOBUs + // only, otherwise cuvidParseVideoData report unknown error. + if (avctx->codec->id == AV_CODEC_ID_AV1 && + extradata_size > 4 && + extradata[0] & 0x80) { + extradata += 4; + extradata_size -= 4; + } + ctx->cuparse_ext = av_mallocz(sizeof(*ctx->cuparse_ext) + FFMAX(extradata_size - (int)sizeof(ctx->cuparse_ext->raw_seqhdr_data), 0)); if (!ctx->cuparse_ext) { @@ -1030,13 +1044,7 @@ static void cuvid_flush(AVCodecContext *avctx) if (ret < 0) goto error; - av_fifo_freep(&ctx->frame_queue); - - ctx->frame_queue = av_fifo_alloc(ctx->nb_surfaces * sizeof(CuvidParsedFrame)); - if (!ctx->frame_queue) { - av_log(avctx, AV_LOG_ERROR, "Failed to recreate frame queue on flush\n"); - return; - } + av_fifo_reset2(ctx->frame_queue); if (ctx->cudecoder) { ctx->cvdl->cuvidDestroyDecoder(ctx->cudecoder); @@ -1108,27 +1116,27 @@ static const AVCodecHWConfigInternal *const cuvid_hw_configs[] = { .option = options, \ .version = LIBAVUTIL_VERSION_INT, \ }; \ - const AVCodec ff_##x##_cuvid_decoder = { \ - .name = #x "_cuvid", \ - .long_name = NULL_IF_CONFIG_SMALL("Nvidia CUVID " #X " decoder"), \ - .type = AVMEDIA_TYPE_VIDEO, \ - .id = AV_CODEC_ID_##X, \ + const FFCodec ff_##x##_cuvid_decoder = { \ + .p.name = #x "_cuvid", \ + .p.long_name = NULL_IF_CONFIG_SMALL("Nvidia CUVID " #X " decoder"), \ + .p.type = AVMEDIA_TYPE_VIDEO, \ + .p.id = AV_CODEC_ID_##X, \ .priv_data_size = sizeof(CuvidContext), \ - .priv_class = &x##_cuvid_class, \ + .p.priv_class = &x##_cuvid_class, \ .init = cuvid_decode_init, \ .close = cuvid_decode_end, \ - .receive_frame = cuvid_output_frame, \ + FF_CODEC_RECEIVE_FRAME_CB(cuvid_output_frame), \ .flush = cuvid_flush, \ .bsfs = bsf_name, \ - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, \ + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, \ .caps_internal = FF_CODEC_CAP_SETS_FRAME_PROPS, \ - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_CUDA, \ + .p.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", \ + .p.wrapper_name = "cuvid", \ }; #if CONFIG_AV1_CUVID_DECODER && defined(CUVID_HAS_AV1_SUPPORT) diff --git a/libavcodec/cyuv.c b/libavcodec/cyuv.c index cfaa5cfa6..8fa4d1f3a 100644 --- a/libavcodec/cyuv.c +++ b/libavcodec/cyuv.c @@ -28,11 +28,14 @@ * Creative YUV (CYUV) Video Decoder. */ +#include "config_components.h" + #include #include #include #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "libavutil/internal.h" @@ -56,14 +59,12 @@ static av_cold int cyuv_decode_init(AVCodecContext *avctx) return 0; } -static int cyuv_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int cyuv_decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; CyuvDecodeContext *s=avctx->priv_data; - AVFrame *frame = data; unsigned char *y_plane; unsigned char *u_plane; @@ -176,29 +177,29 @@ static int cyuv_decode_frame(AVCodecContext *avctx, } #if CONFIG_AURA_DECODER -const AVCodec ff_aura_decoder = { - .name = "aura", - .long_name = NULL_IF_CONFIG_SMALL("Auravision AURA"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_AURA, +const FFCodec ff_aura_decoder = { + .p.name = "aura", + .p.long_name = NULL_IF_CONFIG_SMALL("Auravision AURA"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_AURA, .priv_data_size = sizeof(CyuvDecodeContext), .init = cyuv_decode_init, - .decode = cyuv_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(cyuv_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_CYUV_DECODER -const AVCodec ff_cyuv_decoder = { - .name = "cyuv", - .long_name = NULL_IF_CONFIG_SMALL("Creative YUV (CYUV)"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_CYUV, +const FFCodec ff_cyuv_decoder = { + .p.name = "cyuv", + .p.long_name = NULL_IF_CONFIG_SMALL("Creative YUV (CYUV)"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_CYUV, .priv_data_size = sizeof(CyuvDecodeContext), .init = cyuv_decode_init, - .decode = cyuv_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(cyuv_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif diff --git a/libavcodec/dca_core.c b/libavcodec/dca_core.c index 758e3447a..2b19807ef 100644 --- a/libavcodec/dca_core.c +++ b/libavcodec/dca_core.c @@ -25,6 +25,7 @@ #include "dcahuff.h" #include "dcamath.h" #include "dca_syncwords.h" +#include "internal.h" #if ARCH_ARM #include "arm/dca.h" @@ -1796,7 +1797,7 @@ static int parse_optional_info(DCACoreDecoder *s) return 0; } -int ff_dca_core_parse(DCACoreDecoder *s, uint8_t *data, int size) +int ff_dca_core_parse(DCACoreDecoder *s, const uint8_t *data, int size) { int ret; @@ -1829,7 +1830,7 @@ int ff_dca_core_parse(DCACoreDecoder *s, uint8_t *data, int size) return 0; } -int ff_dca_core_parse_exss(DCACoreDecoder *s, uint8_t *data, DCAExssAsset *asset) +int ff_dca_core_parse_exss(DCACoreDecoder *s, const uint8_t *data, DCAExssAsset *asset) { AVCodecContext *avctx = s->avctx; DCAContext *dca = avctx->priv_data; @@ -2148,7 +2149,7 @@ static int filter_frame_fixed(DCACoreDecoder *s, AVFrame *frame) nsamples, s->ch_mask); } - for (i = 0; i < avctx->channels; i++) { + for (i = 0; i < avctx->ch_layout.nb_channels; i++) { int32_t *samples = s->output_samples[s->ch_remap[i]]; int32_t *plane = (int32_t *)frame->extended_data[i]; for (n = 0; n < nsamples; n++) @@ -2180,11 +2181,11 @@ static int filter_frame_float(DCACoreDecoder *s, AVFrame *frame) return ret; // Build reverse speaker to channel mapping - for (i = 0; i < avctx->channels; i++) + for (i = 0; i < avctx->ch_layout.nb_channels; i++) output_samples[s->ch_remap[i]] = (float *)frame->extended_data[i]; // Allocate space for extra channels - nchannels = av_popcount(s->ch_mask) - avctx->channels; + nchannels = av_popcount(s->ch_mask) - avctx->ch_layout.nb_channels; if (nchannels > 0) { av_fast_malloc(&s->output_buffer, &s->output_size, nsamples * nchannels * sizeof(float)); diff --git a/libavcodec/dca_core.h b/libavcodec/dca_core.h index 86bfa6220..a01d642e7 100644 --- a/libavcodec/dca_core.h +++ b/libavcodec/dca_core.h @@ -21,13 +21,11 @@ #ifndef AVCODEC_DCA_CORE_H #define AVCODEC_DCA_CORE_H -#include "libavutil/common.h" #include "libavutil/float_dsp.h" #include "libavutil/fixed_dsp.h" #include "libavutil/mem_internal.h" #include "avcodec.h" -#include "internal.h" #include "get_bits.h" #include "dca.h" #include "dca_exss.h" @@ -247,8 +245,8 @@ static inline void ff_dca_core_dequantize(int32_t *output, const int32_t *input, } } -int ff_dca_core_parse(DCACoreDecoder *s, uint8_t *data, int size); -int ff_dca_core_parse_exss(DCACoreDecoder *s, uint8_t *data, DCAExssAsset *asset); +int ff_dca_core_parse(DCACoreDecoder *s, const uint8_t *data, int size); +int ff_dca_core_parse_exss(DCACoreDecoder *s, const uint8_t *data, DCAExssAsset *asset); int ff_dca_core_filter_fixed(DCACoreDecoder *s, int x96_synth); int ff_dca_core_filter_frame(DCACoreDecoder *s, AVFrame *frame); av_cold void ff_dca_core_flush(DCACoreDecoder *s); diff --git a/libavcodec/dca_core_bsf.c b/libavcodec/dca_core_bsf.c index b92e6a1ba..1a2db39cb 100644 --- a/libavcodec/dca_core_bsf.c +++ b/libavcodec/dca_core_bsf.c @@ -54,8 +54,8 @@ static const enum AVCodecID codec_ids[] = { AV_CODEC_ID_DTS, AV_CODEC_ID_NONE, }; -const AVBitStreamFilter ff_dca_core_bsf = { - .name = "dca_core", - .filter = dca_core_filter, - .codec_ids = codec_ids, +const FFBitStreamFilter ff_dca_core_bsf = { + .p.name = "dca_core", + .p.codec_ids = codec_ids, + .filter = dca_core_filter, }; diff --git a/libavcodec/dca_exss.h b/libavcodec/dca_exss.h index 208fae1b8..9e91b00bf 100644 --- a/libavcodec/dca_exss.h +++ b/libavcodec/dca_exss.h @@ -21,7 +21,7 @@ #ifndef AVCODEC_DCA_EXSS_H #define AVCODEC_DCA_EXSS_H -#include "libavutil/common.h" +#include #include "avcodec.h" #include "get_bits.h" diff --git a/libavcodec/dca_lbr.c b/libavcodec/dca_lbr.c index 481a8df7e..2b8594cd7 100644 --- a/libavcodec/dca_lbr.c +++ b/libavcodec/dca_lbr.c @@ -28,6 +28,7 @@ #include "dcahuff.h" #include "dca_syncwords.h" #include "bytestream.h" +#include "internal.h" #define AMP_MAX 56 @@ -107,10 +108,6 @@ static const uint8_t lfe_index[7] = { 1, 2, 3, 0, 1, 2, 3 }; -static const uint8_t channel_counts[7] = { - 1, 2, 3, 2, 3, 4, 5 -}; - static const uint16_t channel_layouts[7] = { AV_CH_LAYOUT_MONO, AV_CH_LAYOUT_STEREO, @@ -1159,7 +1156,7 @@ static int parse_decoder_init(DCALbrDecoder *s, GetByteContext *gb) return 0; } -int ff_dca_lbr_parse(DCALbrDecoder *s, uint8_t *data, DCAExssAsset *asset) +int ff_dca_lbr_parse(DCALbrDecoder *s, const uint8_t *data, DCAExssAsset *asset) { struct { LBRChunk lfe; @@ -1731,9 +1728,9 @@ int ff_dca_lbr_filter_frame(DCALbrDecoder *s, AVFrame *frame) AVCodecContext *avctx = s->avctx; int i, ret, nchannels, ch_conf = (s->ch_mask & 0x7) - 1; const int8_t *reorder; + uint64_t channel_mask = channel_layouts[ch_conf]; - avctx->channel_layout = channel_layouts[ch_conf]; - avctx->channels = nchannels = channel_counts[ch_conf]; + nchannels = av_popcount64(channel_mask); avctx->sample_rate = s->sample_rate; avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; avctx->bits_per_raw_sample = 0; @@ -1741,13 +1738,15 @@ int ff_dca_lbr_filter_frame(DCALbrDecoder *s, AVFrame *frame) avctx->bit_rate = s->bit_rate_scaled; if (s->flags & LBR_FLAG_LFE_PRESENT) { - avctx->channel_layout |= AV_CH_LOW_FREQUENCY; - avctx->channels++; + channel_mask |= AV_CH_LOW_FREQUENCY; reorder = channel_reorder_lfe[ch_conf]; } else { reorder = channel_reorder_nolfe[ch_conf]; } + av_channel_layout_uninit(&avctx->ch_layout); + av_channel_layout_from_mask(&avctx->ch_layout, channel_mask); + frame->nb_samples = 1024 << s->freq_range; if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; diff --git a/libavcodec/dca_lbr.h b/libavcodec/dca_lbr.h index 2eccbe1ff..9e1abec0b 100644 --- a/libavcodec/dca_lbr.h +++ b/libavcodec/dca_lbr.h @@ -21,12 +21,10 @@ #ifndef AVCODEC_DCA_LBR_H #define AVCODEC_DCA_LBR_H -#include "libavutil/common.h" #include "libavutil/float_dsp.h" #include "libavutil/mem_internal.h" #include "avcodec.h" -#include "internal.h" #include "get_bits.h" #include "dca.h" #include "dca_exss.h" @@ -126,7 +124,7 @@ typedef struct DCALbrDecoder { DCADSPContext *dcadsp; } DCALbrDecoder; -int ff_dca_lbr_parse(DCALbrDecoder *s, uint8_t *data, DCAExssAsset *asset); +int ff_dca_lbr_parse(DCALbrDecoder *s, const uint8_t *data, DCAExssAsset *asset); int ff_dca_lbr_filter_frame(DCALbrDecoder *s, AVFrame *frame); av_cold void ff_dca_lbr_flush(DCALbrDecoder *s); av_cold void ff_dca_lbr_init_tables(void); diff --git a/libavcodec/dca_xll.c b/libavcodec/dca_xll.c index ab14dbcc8..17626b361 100644 --- a/libavcodec/dca_xll.c +++ b/libavcodec/dca_xll.c @@ -23,6 +23,7 @@ #include "dcadata.h" #include "dcamath.h" #include "dca_syncwords.h" +#include "internal.h" #include "unary.h" static int get_linear(GetBitContext *gb, int n) @@ -1039,7 +1040,7 @@ static int parse_band_data(DCAXllDecoder *s) return 0; } -static int parse_frame(DCAXllDecoder *s, uint8_t *data, int size, DCAExssAsset *asset) +static int parse_frame(DCAXllDecoder *s, const uint8_t *data, int size, DCAExssAsset *asset) { int ret; @@ -1066,7 +1067,7 @@ static void clear_pbr(DCAXllDecoder *s) s->pbr_delay = 0; } -static int copy_to_pbr(DCAXllDecoder *s, uint8_t *data, int size, int delay) +static int copy_to_pbr(DCAXllDecoder *s, const uint8_t *data, int size, int delay) { if (size > DCA_XLL_PBR_BUFFER_MAX) return AVERROR(ENOSPC); @@ -1080,7 +1081,7 @@ static int copy_to_pbr(DCAXllDecoder *s, uint8_t *data, int size, int delay) return 0; } -static int parse_frame_no_pbr(DCAXllDecoder *s, uint8_t *data, int size, DCAExssAsset *asset) +static int parse_frame_no_pbr(DCAXllDecoder *s, const uint8_t *data, int size, DCAExssAsset *asset) { int ret = parse_frame(s, data, size, asset); @@ -1118,7 +1119,7 @@ static int parse_frame_no_pbr(DCAXllDecoder *s, uint8_t *data, int size, DCAExss return 0; } -static int parse_frame_pbr(DCAXllDecoder *s, uint8_t *data, int size, DCAExssAsset *asset) +static int parse_frame_pbr(DCAXllDecoder *s, const uint8_t *data, int size, DCAExssAsset *asset) { int ret; @@ -1159,7 +1160,7 @@ fail: return ret; } -int ff_dca_xll_parse(DCAXllDecoder *s, uint8_t *data, DCAExssAsset *asset) +int ff_dca_xll_parse(DCAXllDecoder *s, const uint8_t *data, DCAExssAsset *asset) { int ret; @@ -1442,7 +1443,7 @@ int ff_dca_xll_filter_frame(DCAXllDecoder *s, AVFrame *frame) s->output_mask); } - for (i = 0; i < avctx->channels; i++) { + for (i = 0; i < avctx->ch_layout.nb_channels; i++) { int32_t *samples = s->output_samples[ch_remap[i]]; if (frame->format == AV_SAMPLE_FMT_S16P) { int16_t *plane = (int16_t *)frame->extended_data[i]; diff --git a/libavcodec/dca_xll.h b/libavcodec/dca_xll.h index 3aaad6d37..d7c1a13ec 100644 --- a/libavcodec/dca_xll.h +++ b/libavcodec/dca_xll.h @@ -21,11 +21,9 @@ #ifndef AVCODEC_DCA_XLL_H #define AVCODEC_DCA_XLL_H -#include "libavutil/common.h" #include "libavutil/mem_internal.h" #include "avcodec.h" -#include "internal.h" #include "get_bits.h" #include "dca.h" #include "dcadsp.h" @@ -141,7 +139,7 @@ typedef struct DCAXllDecoder { int32_t *output_samples[DCA_SPEAKER_COUNT]; } DCAXllDecoder; -int ff_dca_xll_parse(DCAXllDecoder *s, uint8_t *data, DCAExssAsset *asset); +int ff_dca_xll_parse(DCAXllDecoder *s, const uint8_t *data, DCAExssAsset *asset); int ff_dca_xll_filter_frame(DCAXllDecoder *s, AVFrame *frame); av_cold void ff_dca_xll_flush(DCAXllDecoder *s); av_cold void ff_dca_xll_close(DCAXllDecoder *s); diff --git a/libavcodec/dcadct.c b/libavcodec/dcadct.c index 1082aa884..a0eda3d2b 100644 --- a/libavcodec/dcadct.c +++ b/libavcodec/dcadct.c @@ -18,7 +18,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/common.h" +#include #include "dcadct.h" #include "dcamath.h" diff --git a/libavcodec/dcadct.h b/libavcodec/dcadct.h index 518c9f903..2ef60c16d 100644 --- a/libavcodec/dcadct.h +++ b/libavcodec/dcadct.h @@ -21,7 +21,8 @@ #ifndef AVCODEC_DCADCT_H #define AVCODEC_DCADCT_H -#include "libavutil/common.h" +#include +#include "libavutil/attributes.h" typedef struct DCADCTContext { void (*imdct_half[2])(int32_t *output, const int32_t *input); diff --git a/libavcodec/dcadec.c b/libavcodec/dcadec.c index 43694b51f..498e0c86f 100644 --- a/libavcodec/dcadec.c +++ b/libavcodec/dcadec.c @@ -22,6 +22,7 @@ #include "libavutil/channel_layout.h" #include "libavutil/thread.h" +#include "codec_internal.h" #include "dcadec.h" #include "dcahuff.h" #include "dca_syncwords.h" @@ -42,13 +43,17 @@ int ff_dca_set_channel_layout(AVCodecContext *avctx, int *ch_remap, int dca_mask 13, 14, 3, 9, 10, 11, 12, 14, 16, 15, 17, 8, 4, 5, }; + DCAContext *s = avctx->priv_data; + int dca_ch, wav_ch, nchannels = 0; - if (avctx->request_channel_layout & AV_CH_LAYOUT_NATIVE) { + av_channel_layout_uninit(&avctx->ch_layout); + if (s->output_channel_order == CHANNEL_ORDER_CODED) { for (dca_ch = 0; dca_ch < DCA_SPEAKER_COUNT; dca_ch++) if (dca_mask & (1U << dca_ch)) ch_remap[nchannels++] = dca_ch; - avctx->channel_layout = dca_mask; + avctx->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + avctx->ch_layout.nb_channels = nchannels; } else { int wav_mask = 0; int wav_map[18]; @@ -70,10 +75,10 @@ int ff_dca_set_channel_layout(AVCodecContext *avctx, int *ch_remap, int dca_mask for (wav_ch = 0; wav_ch < 18; wav_ch++) if (wav_mask & (1 << wav_ch)) ch_remap[nchannels++] = wav_map[wav_ch]; - avctx->channel_layout = wav_mask; + + av_channel_layout_from_mask(&avctx->ch_layout, wav_mask); } - avctx->channels = nchannels; return nchannels; } @@ -142,12 +147,11 @@ void ff_dca_downmix_to_stereo_float(AVFloatDSPContext *fdsp, float **samples, } } -static int dcadec_decode_frame(AVCodecContext *avctx, void *data, +static int dcadec_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { DCAContext *s = avctx->priv_data; - AVFrame *frame = data; - uint8_t *input = avpkt->data; + const uint8_t *input = avpkt->data; int input_size = avpkt->size; int i, ret, prev_packet = s->packet; uint32_t mrk; @@ -349,23 +353,28 @@ static av_cold int dcadec_init(AVCodecContext *avctx) s->crctab = av_crc_get_table(AV_CRC_16_CCITT); - switch (avctx->request_channel_layout & ~AV_CH_LAYOUT_NATIVE) { - case 0: - s->request_channel_layout = 0; - break; - case AV_CH_LAYOUT_STEREO: - case AV_CH_LAYOUT_STEREO_DOWNMIX: - s->request_channel_layout = DCA_SPEAKER_LAYOUT_STEREO; - break; - case AV_CH_LAYOUT_5POINT0: - s->request_channel_layout = DCA_SPEAKER_LAYOUT_5POINT0; - break; - case AV_CH_LAYOUT_5POINT1: - s->request_channel_layout = DCA_SPEAKER_LAYOUT_5POINT1; - break; - default: - av_log(avctx, AV_LOG_WARNING, "Invalid request_channel_layout\n"); - break; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->request_channel_layout & AV_CH_LAYOUT_NATIVE) + s->output_channel_order = CHANNEL_ORDER_CODED; + + if (avctx->request_channel_layout & ~AV_CH_LAYOUT_NATIVE) { + av_channel_layout_uninit(&s->downmix_layout); + av_channel_layout_from_mask(&s->downmix_layout, avctx->request_channel_layout & ~AV_CH_LAYOUT_NATIVE); + } +FF_ENABLE_DEPRECATION_WARNINGS +#endif + + if (s->downmix_layout.nb_channels) { + if (!av_channel_layout_compare(&s->downmix_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO) || + !av_channel_layout_compare(&s->downmix_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO_DOWNMIX)) + s->request_channel_layout = DCA_SPEAKER_LAYOUT_STEREO; + else if (!av_channel_layout_compare(&s->downmix_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT0)) + s->request_channel_layout = DCA_SPEAKER_LAYOUT_5POINT0; + else if (!av_channel_layout_compare(&s->downmix_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1)) + s->request_channel_layout = DCA_SPEAKER_LAYOUT_5POINT1; + else + av_log(avctx, AV_LOG_WARNING, "Invalid downmix layout\n"); } ff_thread_once(&init_static_once, dcadec_init_static); @@ -378,6 +387,18 @@ static av_cold int dcadec_init(AVCodecContext *avctx) static const AVOption dcadec_options[] = { { "core_only", "Decode core only without extensions", OFFSET(core_only), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, PARAM }, + + { "channel_order", "Order in which the channels are to be exported", + OFFSET(output_channel_order), AV_OPT_TYPE_INT, + { .i64 = CHANNEL_ORDER_DEFAULT }, 0, 1, PARAM, "channel_order" }, + { "default", "normal libavcodec channel order", 0, AV_OPT_TYPE_CONST, + { .i64 = CHANNEL_ORDER_DEFAULT }, .flags = PARAM, "channel_order" }, + { "coded", "order in which the channels are coded in the bitstream", + 0, AV_OPT_TYPE_CONST, { .i64 = CHANNEL_ORDER_CODED }, .flags = PARAM, "channel_order" }, + + { "downmix", "Request a specific channel layout from the decoder", OFFSET(downmix_layout), + AV_OPT_TYPE_CHLAYOUT, {.str = NULL}, .flags = PARAM }, + { NULL } }; @@ -389,20 +410,20 @@ static const AVClass dcadec_class = { .category = AV_CLASS_CATEGORY_DECODER, }; -const AVCodec ff_dca_decoder = { - .name = "dca", - .long_name = NULL_IF_CONFIG_SMALL("DCA (DTS Coherent Acoustics)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_DTS, +const FFCodec ff_dca_decoder = { + .p.name = "dca", + .p.long_name = NULL_IF_CONFIG_SMALL("DCA (DTS Coherent Acoustics)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_DTS, .priv_data_size = sizeof(DCAContext), .init = dcadec_init, - .decode = dcadec_decode_frame, + FF_CODEC_DECODE_CB(dcadec_decode_frame), .close = dcadec_close, .flush = dcadec_flush, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S32P, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, - .priv_class = &dcadec_class, - .profiles = NULL_IF_CONFIG_SMALL(ff_dca_profiles), + .p.priv_class = &dcadec_class, + .p.profiles = NULL_IF_CONFIG_SMALL(ff_dca_profiles), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/dcadec.h b/libavcodec/dcadec.h index 9da8d3b44..0ff28dd4d 100644 --- a/libavcodec/dcadec.h +++ b/libavcodec/dcadec.h @@ -21,9 +21,11 @@ #ifndef AVCODEC_DCADEC_H #define AVCODEC_DCADEC_H -#include "libavutil/common.h" +#include + #include "libavutil/crc.h" #include "libavutil/float_dsp.h" +#include "libavutil/log.h" #include "avcodec.h" #include "get_bits.h" @@ -43,6 +45,11 @@ #define DCA_PACKET_RECOVERY 0x10 ///< Sync error recovery flag #define DCA_PACKET_RESIDUAL 0x20 ///< Core valid for residual decoding +enum DCAOutputChannelOrder { + CHANNEL_ORDER_DEFAULT, + CHANNEL_ORDER_CODED, +}; + typedef struct DCAContext { const AVClass *class; ///< class for AVOptions AVCodecContext *avctx; @@ -63,6 +70,8 @@ typedef struct DCAContext { int request_channel_layout; ///< Converted from avctx.request_channel_layout int core_only; ///< Core only decoding flag + int output_channel_order; + AVChannelLayout downmix_layout; } DCAContext; int ff_dca_set_channel_layout(AVCodecContext *avctx, int *ch_remap, int dca_mask); diff --git a/libavcodec/dcadsp.c b/libavcodec/dcadsp.c index e424a7443..d7e0328c8 100644 --- a/libavcodec/dcadsp.c +++ b/libavcodec/dcadsp.c @@ -485,6 +485,7 @@ av_cold void ff_dcadsp_init(DCADSPContext *s) s->lbr_bank = lbr_bank_c; s->lfe_iir = lfe_iir_c; - if (ARCH_X86) - ff_dcadsp_init_x86(s); +#if ARCH_X86 + ff_dcadsp_init_x86(s); +#endif } diff --git a/libavcodec/dcaenc.c b/libavcodec/dcaenc.c index 884ac896d..aad06adb7 100644 --- a/libavcodec/dcaenc.c +++ b/libavcodec/dcaenc.c @@ -30,6 +30,7 @@ #include "libavutil/mem_internal.h" #include "libavutil/opt.h" #include "avcodec.h" +#include "codec_internal.h" #include "dca.h" #include "dcaadpcm.h" #include "dcamath.h" @@ -163,15 +164,15 @@ static void subband_bufer_free(DCAEncContext *c) static int encode_init(AVCodecContext *avctx) { DCAEncContext *c = avctx->priv_data; - uint64_t layout = avctx->channel_layout; + AVChannelLayout layout = avctx->ch_layout; int i, j, k, min_frame_bits; int ret; if ((ret = subband_bufer_alloc(c)) < 0) return ret; - c->fullband_channels = c->channels = avctx->channels; - c->lfe_channel = (avctx->channels == 3 || avctx->channels == 6); + c->fullband_channels = c->channels = layout.nb_channels; + c->lfe_channel = (c->channels == 3 || c->channels == 6); c->band_interpolation = c->band_interpolation_tab[1]; c->band_spectrum = c->band_spectrum_tab[1]; c->worst_quantization_noise = -2047; @@ -181,19 +182,24 @@ static int encode_init(AVCodecContext *avctx) if (ff_dcaadpcm_init(&c->adpcm_ctx)) return AVERROR(ENOMEM); - if (!layout) { + if (layout.order == AV_CHANNEL_ORDER_UNSPEC) { av_log(avctx, AV_LOG_WARNING, "No channel layout specified. The " "encoder will guess the layout, but it " "might be incorrect.\n"); - layout = av_get_default_channel_layout(avctx->channels); + av_channel_layout_default(&layout, layout.nb_channels); } - switch (layout) { - case AV_CH_LAYOUT_MONO: c->channel_config = 0; break; - case AV_CH_LAYOUT_STEREO: c->channel_config = 2; break; - case AV_CH_LAYOUT_2_2: c->channel_config = 8; break; - case AV_CH_LAYOUT_5POINT0: c->channel_config = 9; break; - case AV_CH_LAYOUT_5POINT1: c->channel_config = 9; break; - default: + + if (!av_channel_layout_compare(&layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_MONO)) + c->channel_config = 0; + else if (!av_channel_layout_compare(&layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO)) + c->channel_config = 2; + else if (!av_channel_layout_compare(&layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_2_2)) + c->channel_config = 8; + else if (!av_channel_layout_compare(&layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT0)) + c->channel_config = 9; + else if (!av_channel_layout_compare(&layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1)) + c->channel_config = 9; + else { av_log(avctx, AV_LOG_ERROR, "Unsupported channel layout!\n"); return AVERROR_PATCHWELCOME; } @@ -1229,31 +1235,41 @@ static const AVClass dcaenc_class = { .version = LIBAVUTIL_VERSION_INT, }; -static const AVCodecDefault defaults[] = { +static const FFCodecDefault defaults[] = { { "b", "1411200" }, { NULL }, }; -const AVCodec ff_dca_encoder = { - .name = "dca", - .long_name = NULL_IF_CONFIG_SMALL("DCA (DTS Coherent Acoustics)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_DTS, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_EXPERIMENTAL, +const FFCodec ff_dca_encoder = { + .p.name = "dca", + .p.long_name = NULL_IF_CONFIG_SMALL("DCA (DTS Coherent Acoustics)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_DTS, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_EXPERIMENTAL, .priv_data_size = sizeof(DCAEncContext), .init = encode_init, .close = encode_close, - .encode2 = encode_frame, + FF_CODEC_ENCODE_CB(encode_frame), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S32, + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE }, - .supported_samplerates = sample_rates, - .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO, + .p.supported_samplerates = sample_rates, +#if FF_API_OLD_CHANNEL_LAYOUT + .p.channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO, AV_CH_LAYOUT_STEREO, AV_CH_LAYOUT_2_2, AV_CH_LAYOUT_5POINT0, AV_CH_LAYOUT_5POINT1, 0 }, +#endif + .p.ch_layouts = (const AVChannelLayout[]){ + AV_CHANNEL_LAYOUT_MONO, + AV_CHANNEL_LAYOUT_STEREO, + AV_CHANNEL_LAYOUT_2_2, + AV_CHANNEL_LAYOUT_5POINT0, + AV_CHANNEL_LAYOUT_5POINT1, + { 0 }, + }, .defaults = defaults, - .priv_class = &dcaenc_class, + .p.priv_class = &dcaenc_class, }; diff --git a/libavcodec/dcahuff.c b/libavcodec/dcahuff.c index fec60771e..8d5541f9d 100644 --- a/libavcodec/dcahuff.c +++ b/libavcodec/dcahuff.c @@ -23,7 +23,7 @@ #include #include "libavutil/avassert.h" -#include "libavutil/common.h" +#include "libavutil/macros.h" #include "dcahuff.h" #include "put_bits.h" @@ -1264,7 +1264,7 @@ VLC ff_dca_vlc_rsd; av_cold void ff_dca_init_vlcs(void) { - static VLC_TYPE dca_table[30214][2]; + static VLCElem dca_table[30214]; int i, j, k = 0; #define DCA_INIT_VLC(vlc, a, b, c, d) \ diff --git a/libavcodec/dct.c b/libavcodec/dct.c index 52f082d06..eeb4d154e 100644 --- a/libavcodec/dct.c +++ b/libavcodec/dct.c @@ -30,7 +30,9 @@ #include #include +#include "libavutil/error.h" #include "libavutil/mathematics.h" +#include "libavutil/mem.h" #include "dct.h" #include "dct32.h" @@ -212,8 +214,9 @@ av_cold int ff_dct_init(DCTContext *s, int nbits, enum DCTTransformType inverse) } s->dct32 = ff_dct32_float; - if (ARCH_X86) - ff_dct_init_x86(s); +#if ARCH_X86 + ff_dct_init_x86(s); +#endif return 0; } diff --git a/libavcodec/dds.c b/libavcodec/dds.c index e5183cade..30788f177 100644 --- a/libavcodec/dds.c +++ b/libavcodec/dds.c @@ -33,6 +33,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" #include "texturedsp.h" #include "thread.h" @@ -105,12 +106,7 @@ typedef struct DDSContext { int bpp; enum DDSPostProc postproc; - const uint8_t *tex_data; // Compressed texture - int tex_ratio; // Compression ratio - int slice_count; // Number of slices for threaded operations - - /* Pointer to the selected compress or decompress function. */ - int (*tex_funct)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block); + TextureDSPThreadContext dec; } DDSContext; static int parse_pixel_format(AVCodecContext *avctx) @@ -169,35 +165,36 @@ static int parse_pixel_format(AVCodecContext *avctx) avctx->pix_fmt = AV_PIX_FMT_RGBA; if (ctx->compressed) { + ctx->dec.raw_ratio = 16; switch (fourcc) { case MKTAG('D', 'X', 'T', '1'): - ctx->tex_ratio = 8; - ctx->tex_funct = ctx->texdsp.dxt1a_block; + ctx->dec.tex_ratio = 8; + ctx->dec.tex_funct = ctx->texdsp.dxt1a_block; break; case MKTAG('D', 'X', 'T', '2'): - ctx->tex_ratio = 16; - ctx->tex_funct = ctx->texdsp.dxt2_block; + ctx->dec.tex_ratio = 16; + ctx->dec.tex_funct = ctx->texdsp.dxt2_block; break; case MKTAG('D', 'X', 'T', '3'): - ctx->tex_ratio = 16; - ctx->tex_funct = ctx->texdsp.dxt3_block; + ctx->dec.tex_ratio = 16; + ctx->dec.tex_funct = ctx->texdsp.dxt3_block; break; case MKTAG('D', 'X', 'T', '4'): - ctx->tex_ratio = 16; - ctx->tex_funct = ctx->texdsp.dxt4_block; + ctx->dec.tex_ratio = 16; + ctx->dec.tex_funct = ctx->texdsp.dxt4_block; break; case MKTAG('D', 'X', 'T', '5'): - ctx->tex_ratio = 16; + ctx->dec.tex_ratio = 16; if (ycocg_scaled) - ctx->tex_funct = ctx->texdsp.dxt5ys_block; + ctx->dec.tex_funct = ctx->texdsp.dxt5ys_block; else if (ycocg_classic) - ctx->tex_funct = ctx->texdsp.dxt5y_block; + ctx->dec.tex_funct = ctx->texdsp.dxt5y_block; else - ctx->tex_funct = ctx->texdsp.dxt5_block; + ctx->dec.tex_funct = ctx->texdsp.dxt5_block; break; case MKTAG('R', 'X', 'G', 'B'): - ctx->tex_ratio = 16; - ctx->tex_funct = ctx->texdsp.dxt5_block; + ctx->dec.tex_ratio = 16; + ctx->dec.tex_funct = ctx->texdsp.dxt5_block; /* This format may be considered as a normal map, * but it is handled differently in a separate postproc. */ ctx->postproc = DDS_SWIZZLE_RXGB; @@ -205,25 +202,25 @@ static int parse_pixel_format(AVCodecContext *avctx) break; case MKTAG('A', 'T', 'I', '1'): case MKTAG('B', 'C', '4', 'U'): - ctx->tex_ratio = 8; - ctx->tex_funct = ctx->texdsp.rgtc1u_block; + ctx->dec.tex_ratio = 8; + ctx->dec.tex_funct = ctx->texdsp.rgtc1u_block; break; case MKTAG('B', 'C', '4', 'S'): - ctx->tex_ratio = 8; - ctx->tex_funct = ctx->texdsp.rgtc1s_block; + ctx->dec.tex_ratio = 8; + ctx->dec.tex_funct = ctx->texdsp.rgtc1s_block; break; case MKTAG('A', 'T', 'I', '2'): /* RGT2 variant with swapped R and G (3Dc)*/ - ctx->tex_ratio = 16; - ctx->tex_funct = ctx->texdsp.dxn3dc_block; + ctx->dec.tex_ratio = 16; + ctx->dec.tex_funct = ctx->texdsp.dxn3dc_block; break; case MKTAG('B', 'C', '5', 'U'): - ctx->tex_ratio = 16; - ctx->tex_funct = ctx->texdsp.rgtc2u_block; + ctx->dec.tex_ratio = 16; + ctx->dec.tex_funct = ctx->texdsp.rgtc2u_block; break; case MKTAG('B', 'C', '5', 'S'): - ctx->tex_ratio = 16; - ctx->tex_funct = ctx->texdsp.rgtc2s_block; + ctx->dec.tex_ratio = 16; + ctx->dec.tex_funct = ctx->texdsp.rgtc2s_block; break; case MKTAG('U', 'Y', 'V', 'Y'): ctx->compressed = 0; @@ -298,40 +295,40 @@ static int parse_pixel_format(AVCodecContext *avctx) avctx->colorspace = AVCOL_SPC_RGB; case DXGI_FORMAT_BC1_TYPELESS: case DXGI_FORMAT_BC1_UNORM: - ctx->tex_ratio = 8; - ctx->tex_funct = ctx->texdsp.dxt1a_block; + ctx->dec.tex_ratio = 8; + ctx->dec.tex_funct = ctx->texdsp.dxt1a_block; break; case DXGI_FORMAT_BC2_UNORM_SRGB: avctx->colorspace = AVCOL_SPC_RGB; case DXGI_FORMAT_BC2_TYPELESS: case DXGI_FORMAT_BC2_UNORM: - ctx->tex_ratio = 16; - ctx->tex_funct = ctx->texdsp.dxt3_block; + ctx->dec.tex_ratio = 16; + ctx->dec.tex_funct = ctx->texdsp.dxt3_block; break; case DXGI_FORMAT_BC3_UNORM_SRGB: avctx->colorspace = AVCOL_SPC_RGB; case DXGI_FORMAT_BC3_TYPELESS: case DXGI_FORMAT_BC3_UNORM: - ctx->tex_ratio = 16; - ctx->tex_funct = ctx->texdsp.dxt5_block; + ctx->dec.tex_ratio = 16; + ctx->dec.tex_funct = ctx->texdsp.dxt5_block; break; case DXGI_FORMAT_BC4_TYPELESS: case DXGI_FORMAT_BC4_UNORM: - ctx->tex_ratio = 8; - ctx->tex_funct = ctx->texdsp.rgtc1u_block; + ctx->dec.tex_ratio = 8; + ctx->dec.tex_funct = ctx->texdsp.rgtc1u_block; break; case DXGI_FORMAT_BC4_SNORM: - ctx->tex_ratio = 8; - ctx->tex_funct = ctx->texdsp.rgtc1s_block; + ctx->dec.tex_ratio = 8; + ctx->dec.tex_funct = ctx->texdsp.rgtc1s_block; break; case DXGI_FORMAT_BC5_TYPELESS: case DXGI_FORMAT_BC5_UNORM: - ctx->tex_ratio = 16; - ctx->tex_funct = ctx->texdsp.rgtc2u_block; + ctx->dec.tex_ratio = 16; + ctx->dec.tex_funct = ctx->texdsp.rgtc2u_block; break; case DXGI_FORMAT_BC5_SNORM: - ctx->tex_ratio = 16; - ctx->tex_funct = ctx->texdsp.rgtc2s_block; + ctx->dec.tex_ratio = 16; + ctx->dec.tex_funct = ctx->texdsp.rgtc2s_block; break; default: av_log(avctx, AV_LOG_ERROR, @@ -433,43 +430,6 @@ static int parse_pixel_format(AVCodecContext *avctx) return 0; } -static int decompress_texture_thread(AVCodecContext *avctx, void *arg, - int slice, int thread_nb) -{ - DDSContext *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 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 still 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_ratio); - } - } - - return 0; -} - static void do_swizzle(AVFrame *frame, int x, int y) { int i; @@ -512,7 +472,7 @@ static void run_postproc(AVCodecContext *avctx, AVFrame *frame) * http://www.realtimecollisiondetection.net/blog/?p=28 */ av_log(avctx, AV_LOG_DEBUG, "Post-processing normal map.\n"); - x_off = ctx->tex_ratio == 8 ? 0 : 3; + x_off = ctx->dec.tex_ratio == 8 ? 0 : 3; for (i = 0; i < frame->linesize[0] * frame->height; i += 4) { uint8_t *src = frame->data[0] + i; int x = src[x_off]; @@ -605,12 +565,11 @@ static void run_postproc(AVCodecContext *avctx, AVFrame *frame) } } -static int dds_decode(AVCodecContext *avctx, void *data, +static int dds_decode(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt) { DDSContext *ctx = avctx->priv_data; GetByteContext *gbc = &ctx->gbc; - AVFrame *frame = data; int mipmap; int ret; int width, height; @@ -663,9 +622,9 @@ static int dds_decode(AVCodecContext *avctx, void *data, if (ctx->compressed) { int size = (avctx->coded_height / TEXTURE_BLOCK_H) * - (avctx->coded_width / TEXTURE_BLOCK_W) * ctx->tex_ratio; - ctx->slice_count = av_clip(avctx->thread_count, 1, - avctx->coded_height / TEXTURE_BLOCK_H); + (avctx->coded_width / TEXTURE_BLOCK_W) * ctx->dec.tex_ratio; + ctx->dec.slice_count = av_clip(avctx->thread_count, 1, + avctx->coded_height / TEXTURE_BLOCK_H); if (bytestream2_get_bytes_left(gbc) < size) { av_log(avctx, AV_LOG_ERROR, @@ -675,8 +634,10 @@ static int dds_decode(AVCodecContext *avctx, void *data, } /* Use the decompress function on the texture, one block per thread. */ - ctx->tex_data = gbc->buffer; - avctx->execute2(avctx, decompress_texture_thread, frame, NULL, ctx->slice_count); + ctx->dec.tex_data.in = gbc->buffer; + ctx->dec.frame_data.out = frame->data[0]; + ctx->dec.stride = frame->linesize[0]; + avctx->execute2(avctx, ff_texturedsp_decompress_thread, &ctx->dec, NULL, ctx->dec.slice_count); } else if (!ctx->paletted && ctx->bpp == 4 && avctx->pix_fmt == AV_PIX_FMT_PAL8) { uint8_t *dst = frame->data[0]; int x, y, i; @@ -748,13 +709,13 @@ static int dds_decode(AVCodecContext *avctx, void *data, return avpkt->size; } -const AVCodec ff_dds_decoder = { - .name = "dds", - .long_name = NULL_IF_CONFIG_SMALL("DirectDraw Surface image decoder"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_DDS, - .decode = dds_decode, +const FFCodec ff_dds_decoder = { + .p.name = "dds", + .p.long_name = NULL_IF_CONFIG_SMALL("DirectDraw Surface image decoder"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_DDS, + FF_CODEC_DECODE_CB(dds_decode), .priv_data_size = sizeof(DDSContext), - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE }; diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 0912f86a1..1893caa6a 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -32,6 +32,7 @@ #include "libavutil/bprint.h" #include "libavutil/channel_layout.h" #include "libavutil/common.h" +#include "libavutil/fifo.h" #include "libavutil/frame.h" #include "libavutil/hwcontext.h" #include "libavutil/imgutils.h" @@ -42,30 +43,12 @@ #include "avcodec.h" #include "bytestream.h" #include "bsf.h" +#include "codec_internal.h" #include "decode.h" #include "hwconfig.h" #include "internal.h" #include "thread.h" -typedef struct FramePool { - /** - * Pools for each data plane. For audio all the planes have the same size, - * so only pools[0] is used. - */ - AVBufferPool *pools[4]; - - /* - * Pool parameters - */ - int format; - int width, height; - int stride_align[AV_NUM_DATA_POINTERS]; - int linesize[4]; - int planes; - int channels; - int samples; -} FramePool; - static int apply_param_change(AVCodecContext *avctx, const AVPacket *avpkt) { int ret; @@ -91,6 +74,8 @@ static int apply_param_change(AVCodecContext *avctx, const AVPacket *avpkt) flags = bytestream_get_le32(&data); size -= 4; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS if (flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT) { if (size < 4) goto fail; @@ -109,6 +94,8 @@ static int apply_param_change(AVCodecContext *avctx, const AVPacket *avpkt) avctx->channel_layout = bytestream_get_le64(&data); size -= 8; } +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (flags & AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE) { if (size < 4) goto fail; @@ -165,39 +152,33 @@ static int extract_packet_props(AVCodecInternal *avci, const AVPacket *pkt) int ret = 0; if (IS_EMPTY(avci->last_pkt_props)) { - if (av_fifo_size(avci->pkt_props) >= sizeof(*pkt)) { - av_fifo_generic_read(avci->pkt_props, avci->last_pkt_props, - sizeof(*avci->last_pkt_props), NULL); - } else + if (av_fifo_read(avci->pkt_props, avci->last_pkt_props, 1) < 0) return copy_packet_props(avci->last_pkt_props, pkt); } - if (av_fifo_space(avci->pkt_props) < sizeof(*pkt)) { - ret = av_fifo_grow(avci->pkt_props, sizeof(*pkt)); - if (ret < 0) - return ret; - } - ret = copy_packet_props(&tmp, pkt); if (ret < 0) return ret; - av_fifo_generic_write(avci->pkt_props, &tmp, sizeof(tmp), NULL); + ret = av_fifo_write(avci->pkt_props, &tmp, 1); + if (ret < 0) + av_packet_unref(&tmp); - return 0; + return ret; } static int decode_bsfs_init(AVCodecContext *avctx) { AVCodecInternal *avci = avctx->internal; + const FFCodec *const codec = ffcodec(avctx->codec); int ret; if (avci->bsf) return 0; - ret = av_bsf_list_parse_str(avctx->codec->bsfs, &avci->bsf); + ret = av_bsf_list_parse_str(codec->bsfs, &avci->bsf); if (ret < 0) { - av_log(avctx, AV_LOG_ERROR, "Error parsing decoder bitstream filters '%s': %s\n", avctx->codec->bsfs, av_err2str(ret)); + av_log(avctx, AV_LOG_ERROR, "Error parsing decoder bitstream filters '%s': %s\n", codec->bsfs, av_err2str(ret)); if (ret != AVERROR(ENOMEM)) ret = AVERROR_BUG; goto fail; @@ -235,7 +216,7 @@ int ff_decode_get_packet(AVCodecContext *avctx, AVPacket *pkt) if (ret < 0) return ret; - if (!(avctx->codec->caps_internal & FF_CODEC_CAP_SETS_FRAME_PROPS)) { + if (!(ffcodec(avctx->codec)->caps_internal & FF_CODEC_CAP_SETS_FRAME_PROPS)) { ret = extract_packet_props(avctx->internal, pkt); if (ret < 0) goto finish; @@ -297,6 +278,7 @@ static inline int decode_simple_internal(AVCodecContext *avctx, AVFrame *frame, { AVCodecInternal *avci = avctx->internal; AVPacket *const pkt = avci->in_pkt; + const FFCodec *const codec = ffcodec(avctx->codec); int got_frame, actual_got_frame; int ret; @@ -322,9 +304,9 @@ static inline int decode_simple_internal(AVCodecContext *avctx, AVFrame *frame, if (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME) { ret = ff_thread_decode_frame(avctx, frame, &got_frame, pkt); } else { - ret = avctx->codec->decode(avctx, frame, &got_frame, pkt); + ret = codec->cb.decode(avctx, frame, &got_frame, pkt); - if (!(avctx->codec->caps_internal & FF_CODEC_CAP_SETS_PKT_DTS)) + if (!(codec->caps_internal & FF_CODEC_CAP_SETS_PKT_DTS)) frame->pkt_dts = pkt->dts; if (avctx->codec->type == AVMEDIA_TYPE_VIDEO) { if(!avctx->has_b_frames) @@ -355,10 +337,22 @@ static inline int decode_simple_internal(AVCodecContext *avctx, AVFrame *frame, if (ret >= 0 && got_frame) { if (frame->format == AV_SAMPLE_FMT_NONE) frame->format = avctx->sample_fmt; + if (!frame->ch_layout.nb_channels) { + int ret2 = av_channel_layout_copy(&frame->ch_layout, &avctx->ch_layout); + if (ret2 < 0) { + ret = ret2; + got_frame = 0; + } + } +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS if (!frame->channel_layout) - frame->channel_layout = avctx->channel_layout; + frame->channel_layout = avctx->ch_layout.order == AV_CHANNEL_ORDER_NATIVE ? + avctx->ch_layout.u.mask : 0; if (!frame->channels) - frame->channels = avctx->channels; + frame->channels = avctx->ch_layout.nb_channels; +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (!frame->sample_rate) frame->sample_rate = avctx->sample_rate; } @@ -366,6 +360,7 @@ static inline int decode_simple_internal(AVCodecContext *avctx, AVFrame *frame, side= av_packet_get_side_data(avci->last_pkt_props, AV_PKT_DATA_SKIP_SAMPLES, &side_size); if(side && side_size>=10) { avci->skip_samples = AV_RL32(side) * avci->skip_samples_multiplier; + avci->skip_samples = FFMAX(0, avci->skip_samples); discard_padding = AV_RL32(side + 4); av_log(avctx, AV_LOG_DEBUG, "skip %d / discard %d samples due to side data\n", avci->skip_samples, (int)discard_padding); @@ -390,7 +385,7 @@ static inline int decode_simple_internal(AVCodecContext *avctx, AVFrame *frame, avci->skip_samples); } else { av_samples_copy(frame->extended_data, frame->extended_data, 0, avci->skip_samples, - frame->nb_samples - avci->skip_samples, avctx->channels, frame->format); + frame->nb_samples - avci->skip_samples, avctx->ch_layout.nb_channels, frame->format); if(avctx->pkt_timebase.num && avctx->sample_rate) { int64_t diff_ts = av_rescale_q(avci->skip_samples, (AVRational){1, avctx->sample_rate}, @@ -496,7 +491,7 @@ static inline int decode_simple_internal(AVCodecContext *avctx, AVFrame *frame, pkt->size -= consumed; pkt->pts = AV_NOPTS_VALUE; pkt->dts = AV_NOPTS_VALUE; - if (!(avctx->codec->caps_internal & FF_CODEC_CAP_SETS_FRAME_PROPS)) { + if (!(codec->caps_internal & FF_CODEC_CAP_SETS_FRAME_PROPS)) { avci->last_pkt_props->size -= consumed; // See extract_packet_props() comment. avci->last_pkt_props->pts = AV_NOPTS_VALUE; avci->last_pkt_props->dts = AV_NOPTS_VALUE; @@ -528,12 +523,13 @@ static int decode_simple_receive_frame(AVCodecContext *avctx, AVFrame *frame) static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame) { AVCodecInternal *avci = avctx->internal; + const FFCodec *const codec = ffcodec(avctx->codec); int ret; av_assert0(!frame->buf[0]); - if (avctx->codec->receive_frame) { - ret = avctx->codec->receive_frame(avctx, frame); + if (codec->cb_type == FF_CODEC_CB_TYPE_RECEIVE_FRAME) { + ret = codec->cb.receive_frame(avctx, frame); if (ret != AVERROR(EAGAIN)) av_packet_unref(avci->last_pkt_props); } else @@ -542,10 +538,11 @@ static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame) if (ret == AVERROR_EOF) avci->draining_done = 1; - if (!(avctx->codec->caps_internal & FF_CODEC_CAP_SETS_FRAME_PROPS) && - IS_EMPTY(avci->last_pkt_props) && av_fifo_size(avci->pkt_props) >= sizeof(*avci->last_pkt_props)) - av_fifo_generic_read(avci->pkt_props, - avci->last_pkt_props, sizeof(*avci->last_pkt_props), NULL); + if (!(codec->caps_internal & FF_CODEC_CAP_SETS_FRAME_PROPS) && + IS_EMPTY(avci->last_pkt_props)) { + // May fail if the FIFO is empty. + av_fifo_read(avci->pkt_props, avci->last_pkt_props, 1); + } if (!ret) { frame->best_effort_timestamp = guess_correct_pts(avctx, @@ -679,8 +676,17 @@ int attribute_align_arg avcodec_receive_frame(AVCodecContext *avctx, AVFrame *fr case AVMEDIA_TYPE_AUDIO: avci->initial_sample_rate = frame->sample_rate ? frame->sample_rate : avctx->sample_rate; - avci->initial_channels = frame->channels; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + avci->initial_channels = frame->ch_layout.nb_channels; avci->initial_channel_layout = frame->channel_layout; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + ret = av_channel_layout_copy(&avci->initial_ch_layout, &frame->ch_layout); + if (ret < 0) { + av_frame_unref(frame); + return ret; + } break; } } @@ -694,10 +700,15 @@ int attribute_align_arg avcodec_receive_frame(AVCodecContext *avctx, AVFrame *fr avci->initial_height != frame->height; break; case AVMEDIA_TYPE_AUDIO: +FF_DISABLE_DEPRECATION_WARNINGS changed |= avci->initial_sample_rate != frame->sample_rate || avci->initial_sample_rate != avctx->sample_rate || +#if FF_API_OLD_CHANNEL_LAYOUT avci->initial_channels != frame->channels || - avci->initial_channel_layout != frame->channel_layout; + avci->initial_channel_layout != frame->channel_layout || +#endif + av_channel_layout_compare(&avci->initial_ch_layout, &frame->ch_layout); +FF_ENABLE_DEPRECATION_WARNINGS break; } @@ -833,7 +844,7 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, if (avctx->pkt_timebase.num && avpkt->pts != AV_NOPTS_VALUE) sub->pts = av_rescale_q(avpkt->pts, avctx->pkt_timebase, AV_TIME_BASE_Q); - ret = avctx->codec->decode(avctx, sub, got_sub_ptr, pkt); + ret = ffcodec(avctx->codec)->cb.decode_sub(avctx, sub, got_sub_ptr, pkt); if (pkt == avci->buffer_pkt) // did we recode? av_packet_unref(avci->buffer_pkt); if (ret < 0) { @@ -883,11 +894,11 @@ enum AVPixelFormat avcodec_default_get_format(struct AVCodecContext *avctx, // 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) { + if (avctx->hw_device_ctx && ffcodec(avctx->codec)->hw_configs) { AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)avctx->hw_device_ctx->data; for (i = 0;; i++) { - config = &avctx->codec->hw_configs[i]->public; + config = &ffcodec(avctx->codec)->hw_configs[i]->public; if (!config) break; if (!(config->methods & @@ -999,7 +1010,7 @@ int avcodec_get_hw_frames_parameters(AVCodecContext *avctx, int i, ret; for (i = 0;; i++) { - hw_config = avctx->codec->hw_configs[i]; + hw_config = ffcodec(avctx->codec)->hw_configs[i]; if (!hw_config) return AVERROR(ENOENT); if (hw_config->public.pix_fmt == hw_pix_fmt) @@ -1143,9 +1154,9 @@ int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt) break; } - if (avctx->codec->hw_configs) { + if (ffcodec(avctx->codec)->hw_configs) { for (i = 0;; i++) { - hw_config = avctx->codec->hw_configs[i]; + hw_config = ffcodec(avctx->codec)->hw_configs[i]; if (!hw_config) break; if (hw_config->public.pix_fmt == user_choice) @@ -1221,259 +1232,6 @@ int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt) return ret; } -static void frame_pool_free(void *opaque, uint8_t *data) -{ - FramePool *pool = (FramePool*)data; - int i; - - for (i = 0; i < FF_ARRAY_ELEMS(pool->pools); i++) - av_buffer_pool_uninit(&pool->pools[i]); - - av_freep(&data); -} - -static AVBufferRef *frame_pool_alloc(void) -{ - FramePool *pool = av_mallocz(sizeof(*pool)); - AVBufferRef *buf; - - if (!pool) - return NULL; - - buf = av_buffer_create((uint8_t*)pool, sizeof(*pool), - frame_pool_free, NULL, 0); - if (!buf) { - av_freep(&pool); - return NULL; - } - - return buf; -} - -static int update_frame_pool(AVCodecContext *avctx, AVFrame *frame) -{ - FramePool *pool = avctx->internal->pool ? - (FramePool*)avctx->internal->pool->data : NULL; - AVBufferRef *pool_buf; - int i, ret, ch, planes; - - if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) { - int planar = av_sample_fmt_is_planar(frame->format); - ch = frame->channels; - planes = planar ? ch : 1; - } - - if (pool && pool->format == frame->format) { - if (avctx->codec_type == AVMEDIA_TYPE_VIDEO && - pool->width == frame->width && pool->height == frame->height) - return 0; - if (avctx->codec_type == AVMEDIA_TYPE_AUDIO && pool->planes == planes && - pool->channels == ch && frame->nb_samples == pool->samples) - return 0; - } - - pool_buf = frame_pool_alloc(); - if (!pool_buf) - return AVERROR(ENOMEM); - pool = (FramePool*)pool_buf->data; - - switch (avctx->codec_type) { - case AVMEDIA_TYPE_VIDEO: { - int linesize[4]; - int w = frame->width; - int h = frame->height; - int unaligned; - ptrdiff_t linesize1[4]; - size_t size[4]; - - avcodec_align_dimensions2(avctx, &w, &h, pool->stride_align); - - do { - // NOTE: do not align linesizes individually, this breaks e.g. assumptions - // that linesize[0] == 2*linesize[1] in the MPEG-encoder for 4:2:2 - ret = av_image_fill_linesizes(linesize, avctx->pix_fmt, w); - if (ret < 0) - goto fail; - // increase alignment of w for next try (rhs gives the lowest bit set in w) - w += w & ~(w - 1); - - unaligned = 0; - for (i = 0; i < 4; i++) - unaligned |= linesize[i] % pool->stride_align[i]; - } while (unaligned); - - for (i = 0; i < 4; i++) - linesize1[i] = linesize[i]; - ret = av_image_fill_plane_sizes(size, avctx->pix_fmt, h, linesize1); - if (ret < 0) - goto fail; - - for (i = 0; i < 4; i++) { - pool->linesize[i] = linesize[i]; - if (size[i]) { - if (size[i] > INT_MAX - (16 + STRIDE_ALIGN - 1)) { - ret = AVERROR(EINVAL); - goto fail; - } - pool->pools[i] = av_buffer_pool_init(size[i] + 16 + STRIDE_ALIGN - 1, - CONFIG_MEMORY_POISONING ? - NULL : - av_buffer_allocz); - if (!pool->pools[i]) { - ret = AVERROR(ENOMEM); - goto fail; - } - } - } - pool->format = frame->format; - pool->width = frame->width; - pool->height = frame->height; - - break; - } - case AVMEDIA_TYPE_AUDIO: { - ret = av_samples_get_buffer_size(&pool->linesize[0], ch, - frame->nb_samples, frame->format, 0); - if (ret < 0) - goto fail; - - pool->pools[0] = av_buffer_pool_init(pool->linesize[0], NULL); - if (!pool->pools[0]) { - ret = AVERROR(ENOMEM); - goto fail; - } - - pool->format = frame->format; - pool->planes = planes; - pool->channels = ch; - pool->samples = frame->nb_samples; - break; - } - default: av_assert0(0); - } - - av_buffer_unref(&avctx->internal->pool); - avctx->internal->pool = pool_buf; - - return 0; -fail: - av_buffer_unref(&pool_buf); - return ret; -} - -static int audio_get_buffer(AVCodecContext *avctx, AVFrame *frame) -{ - FramePool *pool = (FramePool*)avctx->internal->pool->data; - int planes = pool->planes; - int i; - - frame->linesize[0] = pool->linesize[0]; - - if (planes > AV_NUM_DATA_POINTERS) { - frame->extended_data = av_calloc(planes, sizeof(*frame->extended_data)); - frame->nb_extended_buf = planes - AV_NUM_DATA_POINTERS; - frame->extended_buf = av_calloc(frame->nb_extended_buf, - sizeof(*frame->extended_buf)); - if (!frame->extended_data || !frame->extended_buf) { - av_freep(&frame->extended_data); - av_freep(&frame->extended_buf); - return AVERROR(ENOMEM); - } - } else { - frame->extended_data = frame->data; - av_assert0(frame->nb_extended_buf == 0); - } - - for (i = 0; i < FFMIN(planes, AV_NUM_DATA_POINTERS); i++) { - frame->buf[i] = av_buffer_pool_get(pool->pools[0]); - if (!frame->buf[i]) - goto fail; - frame->extended_data[i] = frame->data[i] = frame->buf[i]->data; - } - for (i = 0; i < frame->nb_extended_buf; i++) { - frame->extended_buf[i] = av_buffer_pool_get(pool->pools[0]); - if (!frame->extended_buf[i]) - goto fail; - frame->extended_data[i + AV_NUM_DATA_POINTERS] = frame->extended_buf[i]->data; - } - - if (avctx->debug & FF_DEBUG_BUFFERS) - av_log(avctx, AV_LOG_DEBUG, "default_get_buffer called on frame %p", frame); - - return 0; -fail: - av_frame_unref(frame); - return AVERROR(ENOMEM); -} - -static int video_get_buffer(AVCodecContext *s, AVFrame *pic) -{ - FramePool *pool = (FramePool*)s->internal->pool->data; - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pic->format); - int i; - - if (pic->data[0] || pic->data[1] || pic->data[2] || pic->data[3]) { - av_log(s, AV_LOG_ERROR, "pic->data[*]!=NULL in avcodec_default_get_buffer\n"); - return -1; - } - - if (!desc) { - av_log(s, AV_LOG_ERROR, - "Unable to get pixel format descriptor for format %s\n", - av_get_pix_fmt_name(pic->format)); - return AVERROR(EINVAL); - } - - memset(pic->data, 0, sizeof(pic->data)); - pic->extended_data = pic->data; - - for (i = 0; i < 4 && pool->pools[i]; i++) { - pic->linesize[i] = pool->linesize[i]; - - pic->buf[i] = av_buffer_pool_get(pool->pools[i]); - if (!pic->buf[i]) - goto fail; - - pic->data[i] = pic->buf[i]->data; - } - for (; i < AV_NUM_DATA_POINTERS; i++) { - pic->data[i] = NULL; - pic->linesize[i] = 0; - } - - if (s->debug & FF_DEBUG_BUFFERS) - av_log(s, AV_LOG_DEBUG, "default_get_buffer called on pic %p\n", pic); - - return 0; -fail: - av_frame_unref(pic); - return AVERROR(ENOMEM); -} - -int avcodec_default_get_buffer2(AVCodecContext *avctx, AVFrame *frame, int flags) -{ - int ret; - - 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; - - switch (avctx->codec_type) { - case AVMEDIA_TYPE_VIDEO: - return video_get_buffer(avctx, frame); - case AVMEDIA_TYPE_AUDIO: - return audio_get_buffer(avctx, frame); - default: - return -1; - } -} - static int add_metadata_from_side_data(const AVPacket *avpkt, AVFrame *frame) { size_t size; @@ -1506,7 +1264,7 @@ int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame) { AV_PKT_DATA_DYNAMIC_HDR10_PLUS, AV_FRAME_DATA_DYNAMIC_HDR_PLUS }, }; - if (!(avctx->codec->caps_internal & FF_CODEC_CAP_SETS_FRAME_PROPS)) { + if (!(ffcodec(avctx->codec)->caps_internal & FF_CODEC_CAP_SETS_FRAME_PROPS)) { frame->pts = pkt->pts; frame->pkt_pos = pkt->pos; frame->pkt_duration = pkt->duration; @@ -1567,25 +1325,18 @@ int ff_decode_frame_props(AVCodecContext *avctx, AVFrame *frame) frame->sample_rate = avctx->sample_rate; if (frame->format < 0) frame->format = avctx->sample_fmt; - if (!frame->channel_layout) { - if (avctx->channel_layout) { - if (av_get_channel_layout_nb_channels(avctx->channel_layout) != - avctx->channels) { - av_log(avctx, AV_LOG_ERROR, "Inconsistent channel " - "configuration.\n"); - return AVERROR(EINVAL); - } - - frame->channel_layout = avctx->channel_layout; - } else { - if (avctx->channels > FF_SANE_NB_CHANNELS) { - av_log(avctx, AV_LOG_ERROR, "Too many channels: %d.\n", - avctx->channels); - return AVERROR(ENOSYS); - } - } + if (!frame->ch_layout.nb_channels) { + int ret = av_channel_layout_copy(&frame->ch_layout, &avctx->ch_layout); + if (ret < 0) + return ret; } - frame->channels = avctx->channels; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + frame->channels = frame->ch_layout.nb_channels; + frame->channel_layout = frame->ch_layout.order == AV_CHANNEL_ORDER_NATIVE ? + frame->ch_layout.u.mask : 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif break; } return 0; @@ -1655,6 +1406,8 @@ int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags) int override_dimensions = 1; int ret; + av_assert0(av_codec_is_decoder(avctx->codec)); + if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) { if ((unsigned)avctx->width > INT_MAX - STRIDE_ALIGN || (ret = av_image_check_size2(FFALIGN(avctx->width, STRIDE_ALIGN), avctx->height, avctx->max_pixels, AV_PIX_FMT_NONE, 0, avctx)) < 0 || avctx->pix_fmt<0) { @@ -1675,7 +1428,16 @@ int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags) goto fail; } } else if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) { - if (frame->nb_samples * (int64_t)avctx->channels > avctx->max_samples) { +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + /* compat layer for old-style get_buffer() implementations */ + avctx->channels = avctx->ch_layout.nb_channels; + avctx->channel_layout = (avctx->ch_layout.order == AV_CHANNEL_ORDER_NATIVE) ? + avctx->ch_layout.u.mask : 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + + if (frame->nb_samples * (int64_t)avctx->ch_layout.nb_channels > avctx->max_samples) { av_log(avctx, AV_LOG_ERROR, "samples per frame %d, exceeds max_samples %"PRId64"\n", frame->nb_samples, avctx->max_samples); ret = AVERROR(EINVAL); goto fail; @@ -1705,7 +1467,7 @@ int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags) end: if (avctx->codec_type == AVMEDIA_TYPE_VIDEO && !override_dimensions && - !(avctx->codec->caps_internal & FF_CODEC_CAP_EXPORTS_CROPPING)) { + !(ffcodec(avctx->codec)->caps_internal & FF_CODEC_CAP_EXPORTS_CROPPING)) { frame->width = avctx->width; frame->height = avctx->height; } @@ -1766,6 +1528,7 @@ int ff_reget_buffer(AVCodecContext *avctx, AVFrame *frame, int flags) int ff_decode_preinit(AVCodecContext *avctx) { + AVCodecInternal *avci = avctx->internal; int ret = 0; /* if the decoder init function was already called previously, @@ -1785,7 +1548,7 @@ FF_DISABLE_DEPRECATION_WARNINGS FF_ENABLE_DEPRECATION_WARNINGS #endif - if (avctx->codec_type == AVMEDIA_TYPE_AUDIO && avctx->channels == 0 && + if (avctx->codec_type == AVMEDIA_TYPE_AUDIO && avctx->ch_layout.nb_channels == 0 && !(avctx->codec->capabilities & AV_CODEC_CAP_CHANNEL_CONF)) { av_log(avctx, AV_LOG_ERROR, "Decoder requires channel count but channels not set\n"); return AVERROR(EINVAL); @@ -1844,6 +1607,13 @@ FF_ENABLE_DEPRECATION_WARNINGS avctx->export_side_data |= AV_CODEC_EXPORT_DATA_MVS; } + avci->in_pkt = av_packet_alloc(); + avci->last_pkt_props = av_packet_alloc(); + avci->pkt_props = av_fifo_alloc2(1, sizeof(*avci->last_pkt_props), + AV_FIFO_FLAG_AUTO_GROW); + if (!avci->in_pkt || !avci->last_pkt_props || !avci->pkt_props) + return AVERROR(ENOMEM); + ret = decode_bsfs_init(avctx); if (ret < 0) return ret; diff --git a/libavcodec/decode.h b/libavcodec/decode.h index dee2543b1..1b40f714e 100644 --- a/libavcodec/decode.h +++ b/libavcodec/decode.h @@ -90,7 +90,7 @@ int ff_copy_palette(void *dst, const AVPacket *src, void *logctx); /** * Perform decoder initialization and validation. - * Called when opening the decoder, before the AVCodec.init() call. + * Called when opening the decoder, before the FFCodec.init() call. */ int ff_decode_preinit(AVCodecContext *avctx); diff --git a/libavcodec/dfa.c b/libavcodec/dfa.c index 0cf3641a3..057dfffa2 100644 --- a/libavcodec/dfa.c +++ b/libavcodec/dfa.c @@ -24,6 +24,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" #include "libavutil/avassert.h" @@ -336,11 +337,9 @@ static const char chunk_name[8][5] = { "COPY", "TSW1", "BDLT", "WDLT", "TDLT", "DSW1", "BLCK", "DDS1" }; -static int dfa_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int dfa_decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { - AVFrame *frame = data; DfaContext *s = avctx->priv_data; GetByteContext gb; const uint8_t *buf = avpkt->data; @@ -385,19 +384,27 @@ static int dfa_decode_frame(AVCodecContext *avctx, buf = s->frame_buf; dst = frame->data[0]; - for (i = 0; i < avctx->height; i++) { - if(version == 0x100) { + if (version == 0x100) { + for (i = 0; i < avctx->height; i++) { int j; - for(j = 0; j < avctx->width; j++) { - dst[j] = buf[ (i&3)*(avctx->width /4) + (j/4) + - ((j&3)*(avctx->height/4) + (i/4))*avctx->width]; + const uint8_t *buf1 = buf + (i&3)*(avctx->width/4) + (i/4)*avctx->width; + int stride = (avctx->height/4)*avctx->width; + for(j = 0; j < avctx->width/4; j++) { + dst[4*j+0] = buf1[j + 0*stride]; + dst[4*j+1] = buf1[j + 1*stride]; + dst[4*j+2] = buf1[j + 2*stride]; + dst[4*j+3] = buf1[j + 3*stride]; } - } else { - memcpy(dst, buf, avctx->width); - buf += avctx->width; + j *= 4; + for(; j < avctx->width; j++) { + dst[j] = buf1[(j/4) + (j&3)*stride]; + } + dst += frame->linesize[0]; } - dst += frame->linesize[0]; - } + } else + av_image_copy_plane(dst, frame->linesize[0], buf, avctx->width, + avctx->width, avctx->height); + memcpy(frame->data[1], s->pal, sizeof(s->pal)); *got_frame = 1; @@ -414,15 +421,15 @@ static av_cold int dfa_decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_dfa_decoder = { - .name = "dfa", - .long_name = NULL_IF_CONFIG_SMALL("Chronomaster DFA"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_DFA, +const FFCodec ff_dfa_decoder = { + .p.name = "dfa", + .p.long_name = NULL_IF_CONFIG_SMALL("Chronomaster DFA"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_DFA, .priv_data_size = sizeof(DfaContext), .init = dfa_decode_init, .close = dfa_decode_end, - .decode = dfa_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(dfa_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/dfpwmdec.c b/libavcodec/dfpwmdec.c new file mode 100644 index 000000000..d013d4c21 --- /dev/null +++ b/libavcodec/dfpwmdec.c @@ -0,0 +1,138 @@ +/* + * DFPWM decoder + * Copyright (c) 2022 Jack Bruienne + * Copyright (c) 2012, 2016 Ben "GreaseMonkey" Russell + * + * 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 + * DFPWM1a decoder + */ + +#include "libavutil/internal.h" +#include "avcodec.h" +#include "codec_id.h" +#include "codec_internal.h" +#include "internal.h" + +typedef struct { + int fq, q, s, lt; +} DFPWMState; + +// DFPWM codec from https://github.com/ChenThread/dfpwm/blob/master/1a/ +// Licensed in the public domain + +static void au_decompress(DFPWMState *state, int fs, int len, + uint8_t *outbuf, const uint8_t *inbuf) +{ + unsigned d; + for (int i = 0; i < len; i++) { + // get bits + d = *(inbuf++); + for (int j = 0; j < 8; j++) { + int nq, lq, st, ns, ov; + // set target + int t = ((d&1) ? 127 : -128); + d >>= 1; + + // adjust charge + nq = state->q + ((state->s * (t-state->q) + 512)>>10); + if(nq == state->q && nq != t) + nq += (t == 127 ? 1 : -1); + lq = state->q; + state->q = nq; + + // adjust strength + st = (t != state->lt ? 0 : 1023); + ns = state->s; + if(ns != st) + ns += (st != 0 ? 1 : -1); + if(ns < 8) ns = 8; + state->s = ns; + + // FILTER: perform antijerk + ov = (t != state->lt ? (nq+lq+1)>>1 : nq); + + // FILTER: perform LPF + state->fq += ((fs*(ov-state->fq) + 0x80)>>8); + ov = state->fq; + + // output sample + *(outbuf++) = ov + 128; + + state->lt = t; + } + } +} + +static av_cold int dfpwm_dec_init(struct AVCodecContext *ctx) +{ + DFPWMState *state = ctx->priv_data; + + if (ctx->ch_layout.nb_channels <= 0) { + av_log(ctx, AV_LOG_ERROR, "Invalid number of channels\n"); + return AVERROR(EINVAL); + } + + state->fq = 0; + state->q = 0; + state->s = 0; + state->lt = -128; + + ctx->sample_fmt = AV_SAMPLE_FMT_U8; + ctx->bits_per_raw_sample = 8; + + return 0; +} + +static int dfpwm_dec_frame(struct AVCodecContext *ctx, AVFrame *frame, + int *got_frame, struct AVPacket *packet) +{ + DFPWMState *state = ctx->priv_data; + int ret; + + if (packet->size * 8LL % ctx->ch_layout.nb_channels) + return AVERROR_PATCHWELCOME; + + frame->nb_samples = packet->size * 8LL / ctx->ch_layout.nb_channels; + if (frame->nb_samples <= 0) { + av_log(ctx, AV_LOG_ERROR, "invalid number of samples in packet\n"); + return AVERROR_INVALIDDATA; + } + + if ((ret = ff_get_buffer(ctx, frame, 0)) < 0) + return ret; + + au_decompress(state, 140, packet->size, frame->data[0], packet->data); + + *got_frame = 1; + return packet->size; +} + +const FFCodec ff_dfpwm_decoder = { + .p.name = "dfpwm", + .p.long_name = NULL_IF_CONFIG_SMALL("DFPWM1a audio"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_DFPWM, + .priv_data_size = sizeof(DFPWMState), + .init = dfpwm_dec_init, + FF_CODEC_DECODE_CB(dfpwm_dec_frame), + .p.capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, +}; diff --git a/libavcodec/dfpwmenc.c b/libavcodec/dfpwmenc.c new file mode 100644 index 000000000..85ee1a980 --- /dev/null +++ b/libavcodec/dfpwmenc.c @@ -0,0 +1,121 @@ +/* + * DFPWM encoder + * Copyright (c) 2022 Jack Bruienne + * Copyright (c) 2012, 2016 Ben "GreaseMonkey" Russell + * + * 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 + * DFPWM1a encoder + */ + +#include "libavutil/internal.h" +#include "avcodec.h" +#include "codec_id.h" +#include "codec_internal.h" +#include "encode.h" + +typedef struct { + int fq, q, s, lt; +} DFPWMState; + +// DFPWM codec from https://github.com/ChenThread/dfpwm/blob/master/1a/ +// Licensed in the public domain + +// note, len denotes how many compressed bytes there are (uncompressed bytes / 8). +static void au_compress(DFPWMState *state, int len, uint8_t *outbuf, uint8_t *inbuf) +{ + unsigned d = 0; + for (int i = 0; i < len; i++) { + for (int j = 0; j < 8; j++) { + int nq, st, ns; + // get sample + int v = *(inbuf++) - 128; + // set bit / target + int t = (v > state->q || (v == state->q && v == 127) ? 127 : -128); + d >>= 1; + if(t > 0) + d |= 0x80; + + // adjust charge + nq = state->q + ((state->s * (t-state->q) + 512)>>10); + if(nq == state->q && nq != t) + nq += (t == 127 ? 1 : -1); + state->q = nq; + + // adjust strength + st = (t != state->lt ? 0 : 1023); + ns = state->s; + if(ns != st) + ns += (st != 0 ? 1 : -1); + if(ns < 8) ns = 8; + state->s = ns; + + state->lt = t; + } + + // output bits + *(outbuf++) = d; + } +} + +static av_cold int dfpwm_enc_init(struct AVCodecContext *ctx) +{ + DFPWMState *state = ctx->priv_data; + + state->fq = 0; + state->q = 0; + state->s = 0; + state->lt = -128; + + ctx->bits_per_coded_sample = 1; + + return 0; +} + +static int dfpwm_enc_frame(struct AVCodecContext *ctx, struct AVPacket *packet, + const struct AVFrame *frame, int *got_packet) +{ + DFPWMState *state = ctx->priv_data; + int size = frame->nb_samples * frame->ch_layout.nb_channels / 8 + (frame->nb_samples % 8 > 0 ? 1 : 0); + int ret = ff_get_encode_buffer(ctx, packet, size, 0); + + if (ret) { + *got_packet = 0; + return ret; + } + + au_compress(state, size, packet->data, frame->data[0]); + + *got_packet = 1; + return 0; +} + +const FFCodec ff_dfpwm_encoder = { + .p.name = "dfpwm", + .p.long_name = NULL_IF_CONFIG_SMALL("DFPWM1a audio"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_DFPWM, + .priv_data_size = sizeof(DFPWMState), + .init = dfpwm_enc_init, + FF_CODEC_ENCODE_CB(dfpwm_enc_frame), + .p.sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_NONE}, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_VARIABLE_FRAME_SIZE, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, +}; diff --git a/libavcodec/dirac_dwt.c b/libavcodec/dirac_dwt.c index fffaf82e2..af29932c6 100644 --- a/libavcodec/dirac_dwt.c +++ b/libavcodec/dirac_dwt.c @@ -58,8 +58,10 @@ int ff_spatial_idwt_init(DWTContext *d, DWTPlane *p, enum dwt_type type, return AVERROR_INVALIDDATA; } - if (ARCH_X86 && bit_depth == 8) +#if ARCH_X86 + if (bit_depth == 8) ff_spatial_idwt_init_x86(d, type); +#endif return 0; } diff --git a/libavcodec/dirac_vlc.h b/libavcodec/dirac_vlc.h index bfcfa136a..5adb9ef63 100644 --- a/libavcodec/dirac_vlc.h +++ b/libavcodec/dirac_vlc.h @@ -19,7 +19,7 @@ #ifndef AVCODEC_DIRAC_VLC_H #define AVCODEC_DIRAC_VLC_H -#include "libavutil/avutil.h" +#include int ff_dirac_golomb_read_16bit(const uint8_t *buf, int bytes, uint8_t *_dst, int coeffs); diff --git a/libavcodec/diracdec.c b/libavcodec/diracdec.c index 1a7fa59db..50d1d2e1d 100644 --- a/libavcodec/diracdec.c +++ b/libavcodec/diracdec.c @@ -32,6 +32,7 @@ #include "avcodec.h" #include "get_bits.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" #include "golomb.h" #include "dirac_arith.h" @@ -2259,11 +2260,11 @@ static int dirac_decode_data_unit(AVCodecContext *avctx, const uint8_t *buf, int return 0; } -static int dirac_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *pkt) +static int dirac_decode_frame(AVCodecContext *avctx, AVFrame *picture, + int *got_frame, AVPacket *pkt) { DiracContext *s = avctx->priv_data; - AVFrame *picture = data; - uint8_t *buf = pkt->data; + const uint8_t *buf = pkt->data; int buf_size = pkt->size; int i, buf_idx = 0; int ret; @@ -2281,7 +2282,7 @@ static int dirac_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, /* end of stream, so flush delayed pics */ if (buf_size == 0) - return get_delayed_pic(s, (AVFrame *)data, got_frame); + return get_delayed_pic(s, picture, got_frame); for (;;) { /*[DIRAC_STD] Here starts the code from parse_info() defined in 9.6 @@ -2338,13 +2339,13 @@ static int dirac_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, if (delayed_frame) { delayed_frame->reference ^= DELAYED_PIC_REF; - if((ret=av_frame_ref(data, delayed_frame->avframe)) < 0) + if((ret = av_frame_ref(picture, delayed_frame->avframe)) < 0) return ret; *got_frame = 1; } } else if (s->current_picture->avframe->display_picture_number == s->frame_number) { /* The right frame at the right time :-) */ - if((ret=av_frame_ref(data, s->current_picture->avframe)) < 0) + if((ret = av_frame_ref(picture, s->current_picture->avframe)) < 0) return ret; *got_frame = 1; } @@ -2355,16 +2356,16 @@ static int dirac_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, return buf_idx; } -const AVCodec ff_dirac_decoder = { - .name = "dirac", - .long_name = NULL_IF_CONFIG_SMALL("BBC Dirac VC-2"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_DIRAC, +const FFCodec ff_dirac_decoder = { + .p.name = "dirac", + .p.long_name = NULL_IF_CONFIG_SMALL("BBC Dirac VC-2"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_DIRAC, .priv_data_size = sizeof(DiracContext), .init = dirac_decode_init, .close = dirac_decode_end, - .decode = dirac_decode_frame, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(dirac_decode_frame), + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, .flush = dirac_decode_flush, }; diff --git a/libavcodec/diracdsp.c b/libavcodec/diracdsp.c index a62a218ba..aafdddcdc 100644 --- a/libavcodec/diracdsp.c +++ b/libavcodec/diracdsp.c @@ -247,6 +247,7 @@ av_cold void ff_diracdsp_init(DiracDSPContext *c) PIXFUNC(avg, 16); PIXFUNC(avg, 32); - if (ARCH_X86) - ff_diracdsp_init_x86(c); +#if ARCH_X86 + ff_diracdsp_init_x86(c); +#endif } diff --git a/libavcodec/dnxhddata.c b/libavcodec/dnxhddata.c index cb3d4a4c7..d52abe87d 100644 --- a/libavcodec/dnxhddata.c +++ b/libavcodec/dnxhddata.c @@ -19,9 +19,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include +#include "libavutil/log.h" +#include "libavutil/macros.h" #include "avcodec.h" #include "dnxhddata.h" -#include "libavutil/common.h" /* The quantization tables below are in zigzag order! */ diff --git a/libavcodec/dnxhddata.h b/libavcodec/dnxhddata.h index 861faca4c..ea36feb0a 100644 --- a/libavcodec/dnxhddata.h +++ b/libavcodec/dnxhddata.h @@ -24,8 +24,9 @@ #include #include "avcodec.h" -#include "libavutil/internal.h" +#include "libavutil/attributes.h" #include "libavutil/intreadwrite.h" +#include "libavutil/rational.h" /** Additional profile info flags */ #define DNXHD_INTERLACED (1<<0) diff --git a/libavcodec/dnxhddec.c b/libavcodec/dnxhddec.c index 9ecd220e7..65cd6d939 100644 --- a/libavcodec/dnxhddec.c +++ b/libavcodec/dnxhddec.c @@ -29,6 +29,7 @@ #include "avcodec.h" #include "blockdsp.h" +#include "codec_internal.h" #define UNCHECKED_BITSTREAM_READER 1 #include "get_bits.h" #include "dnxhddata.h" @@ -612,14 +613,12 @@ static int dnxhd_decode_row(AVCodecContext *avctx, void *data, return 0; } -static int dnxhd_decode_frame(AVCodecContext *avctx, void *data, +static int dnxhd_decode_frame(AVCodecContext *avctx, AVFrame *picture, int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; DNXHDContext *ctx = avctx->priv_data; - ThreadFrame frame = { .f = data }; - AVFrame *picture = data; int first_field = 1; int ret, i; @@ -650,7 +649,7 @@ decode_coding_unit: return ret; if (first_field) { - if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, picture, 0)) < 0) return ret; picture->pict_type = AV_PICTURE_TYPE_I; picture->key_frame = 1; @@ -725,17 +724,17 @@ static av_cold int dnxhd_decode_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_dnxhd_decoder = { - .name = "dnxhd", - .long_name = NULL_IF_CONFIG_SMALL("VC3/DNxHD"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_DNXHD, +const FFCodec ff_dnxhd_decoder = { + .p.name = "dnxhd", + .p.long_name = NULL_IF_CONFIG_SMALL("VC3/DNxHD"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_DNXHD, .priv_data_size = sizeof(DNXHDContext), .init = dnxhd_decode_init, .close = dnxhd_decode_close, - .decode = dnxhd_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | + FF_CODEC_DECODE_CB(dnxhd_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_SLICE_THREADS, - .profiles = NULL_IF_CONFIG_SMALL(ff_dnxhd_profiles), + .p.profiles = NULL_IF_CONFIG_SMALL(ff_dnxhd_profiles), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/dnxhdenc.c b/libavcodec/dnxhdenc.c index ca6796433..481793c15 100644 --- a/libavcodec/dnxhdenc.c +++ b/libavcodec/dnxhdenc.c @@ -30,10 +30,12 @@ #include "avcodec.h" #include "blockdsp.h" +#include "codec_internal.h" #include "encode.h" #include "fdctdsp.h" -#include "internal.h" +#include "mathops.h" #include "mpegvideo.h" +#include "mpegvideoenc.h" #include "pixblockdsp.h" #include "packet_internal.h" #include "profiles.h" @@ -443,8 +445,9 @@ static av_cold int dnxhd_encode_init(AVCodecContext *avctx) ctx->block_width_l2 = 3; } - if (ARCH_X86) - ff_dnxhdenc_init_x86(ctx); +#if ARCH_X86 + ff_dnxhdenc_init_x86(ctx); +#endif ctx->m.mb_height = (avctx->height + 15) / 16; ctx->m.mb_width = (avctx->width + 15) / 16; @@ -908,6 +911,7 @@ static int dnxhd_encode_thread(AVCodecContext *avctx, void *arg, if (put_bits_count(&ctx->m.pb) & 31) put_bits(&ctx->m.pb, 32 - (put_bits_count(&ctx->m.pb) & 31), 0); flush_put_bits(&ctx->m.pb); + memset(put_bits_ptr(&ctx->m.pb), 0, put_bytes_left(&ctx->m.pb, 0)); return 0; } @@ -923,7 +927,7 @@ static void dnxhd_setup_threads_slices(DNXHDEncContext *ctx) unsigned mb = mb_y * ctx->m.mb_width + mb_x; ctx->slice_size[mb_y] += ctx->mb_bits[mb]; } - ctx->slice_size[mb_y] = (ctx->slice_size[mb_y] + 31) & ~31; + ctx->slice_size[mb_y] = (ctx->slice_size[mb_y] + 31U) & ~31U; ctx->slice_size[mb_y] >>= 3; thread_size = ctx->slice_size[mb_y]; offset += thread_size; @@ -1219,14 +1223,19 @@ static int dnxhd_encode_fast(AVCodecContext *avctx, DNXHDEncContext *ctx) avctx->execute2(avctx, dnxhd_mb_var_thread, NULL, NULL, ctx->m.mb_height); radix_sort(ctx->mb_cmp, ctx->mb_cmp_tmp, ctx->m.mb_num); +retry: for (x = 0; x < ctx->m.mb_num && max_bits > ctx->frame_bits; x++) { int mb = ctx->mb_cmp[x].mb; int rc = (ctx->qscale * ctx->m.mb_num ) + mb; max_bits -= ctx->mb_rc[rc].bits - ctx->mb_rc[rc + ctx->m.mb_num].bits; - ctx->mb_qscale[mb] = ctx->qscale + 1; + if (ctx->mb_qscale[mb] < 255) + ctx->mb_qscale[mb]++; ctx->mb_bits[mb] = ctx->mb_rc[rc + ctx->m.mb_num].bits; } + + if (max_bits > ctx->frame_bits) + goto retry; } return 0; } @@ -1339,31 +1348,31 @@ static av_cold int dnxhd_encode_end(AVCodecContext *avctx) return 0; } -static const AVCodecDefault dnxhd_defaults[] = { +static const FFCodecDefault dnxhd_defaults[] = { { "qmax", "1024" }, /* Maximum quantization scale factor allowed for VC-3 */ { NULL }, }; -const AVCodec ff_dnxhd_encoder = { - .name = "dnxhd", - .long_name = NULL_IF_CONFIG_SMALL("VC3/DNxHD"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_DNXHD, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | +const FFCodec ff_dnxhd_encoder = { + .p.name = "dnxhd", + .p.long_name = NULL_IF_CONFIG_SMALL("VC3/DNxHD"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_DNXHD, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_SLICE_THREADS, .priv_data_size = sizeof(DNXHDEncContext), .init = dnxhd_encode_init, - .encode2 = dnxhd_encode_picture, + FF_CODEC_ENCODE_CB(dnxhd_encode_picture), .close = dnxhd_encode_end, - .pix_fmts = (const enum AVPixelFormat[]) { + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, AV_PIX_FMT_GBRP10, AV_PIX_FMT_NONE }, - .priv_class = &dnxhd_class, + .p.priv_class = &dnxhd_class, .defaults = dnxhd_defaults, - .profiles = NULL_IF_CONFIG_SMALL(ff_dnxhd_profiles), + .p.profiles = NULL_IF_CONFIG_SMALL(ff_dnxhd_profiles), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/dnxhdenc.h b/libavcodec/dnxhdenc.h index 9e4c869bc..7726a3915 100644 --- a/libavcodec/dnxhdenc.h +++ b/libavcodec/dnxhdenc.h @@ -34,7 +34,7 @@ #include "dnxhddata.h" typedef struct RCCMPEntry { - uint16_t mb; + uint32_t mb; int value; } RCCMPEntry; @@ -100,7 +100,7 @@ typedef struct DNXHDEncContext { unsigned qscale; unsigned lambda; - uint16_t *mb_bits; + uint32_t *mb_bits; uint8_t *mb_qscale; RCCMPEntry *mb_cmp; diff --git a/libavcodec/dolby_e.c b/libavcodec/dolby_e.c index 6c0d54be4..a734af8d4 100644 --- a/libavcodec/dolby_e.c +++ b/libavcodec/dolby_e.c @@ -23,7 +23,9 @@ #include "libavutil/thread.h" #include "libavutil/mem.h" #include "libavutil/mem_internal.h" +#include "libavutil/opt.h" +#include "codec_internal.h" #include "internal.h" #include "get_bits.h" #include "dolby_e.h" @@ -39,6 +41,11 @@ #define MAX_MSTR_EXP 2 #define MAX_BIAS_EXP 50 +enum DBEOutputChannelOrder { + CHANNEL_ORDER_DEFAULT, + CHANNEL_ORDER_CODED, +}; + typedef struct DBEGroup { uint8_t nb_exponent; uint8_t nb_bias_exp[MAX_MSTR_EXP]; @@ -70,6 +77,7 @@ typedef struct DBEChannel { } DBEChannel; typedef struct DBEDecodeContext { + const AVClass *class; AVCodecContext *avctx; DBEContext dectx; @@ -1057,7 +1065,7 @@ static int filter_frame(DBEDecodeContext *s, AVFrame *frame) reorder = ch_reorder_4; else if (metadata->nb_channels == 6) reorder = ch_reorder_6; - else if (metadata->nb_programs == 1 && !(s->avctx->request_channel_layout & AV_CH_LAYOUT_NATIVE)) + else if (metadata->nb_programs == 1 && metadata->output_channel_order == CHANNEL_ORDER_DEFAULT) reorder = ch_reorder_8; else reorder = ch_reorder_n; @@ -1076,7 +1084,7 @@ static int filter_frame(DBEDecodeContext *s, AVFrame *frame) return 0; } -static int dolby_e_decode_frame(AVCodecContext *avctx, void *data, +static int dolby_e_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { DBEDecodeContext *s1 = avctx->priv_data; @@ -1093,19 +1101,23 @@ static int dolby_e_decode_frame(AVCodecContext *avctx, void *data, s->metadata.multi_prog_warned = 1; } + av_channel_layout_uninit(&avctx->ch_layout); switch (s->metadata.nb_channels) { case 4: - avctx->channel_layout = AV_CH_LAYOUT_4POINT0; + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_4POINT0; break; case 6: - avctx->channel_layout = AV_CH_LAYOUT_5POINT1; + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1; break; case 8: - avctx->channel_layout = AV_CH_LAYOUT_7POINT1; + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_7POINT1; + break; + default: + avctx->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + avctx->ch_layout.nb_channels = s->metadata.nb_channels; break; } - avctx->channels = s->metadata.nb_channels; avctx->sample_rate = s->metadata.sample_rate; avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; @@ -1123,7 +1135,7 @@ static int dolby_e_decode_frame(AVCodecContext *avctx, void *data, return ret; if ((ret = parse_meter(s1)) < 0) return ret; - if ((ret = filter_frame(s1, data)) < 0) + if ((ret = filter_frame(s1, frame)) < 0) return ret; *got_frame_ptr = 1; @@ -1252,22 +1264,51 @@ static av_cold int dolby_e_init(AVCodecContext *avctx) if (!(s->fdsp = avpriv_float_dsp_alloc(0))) return AVERROR(ENOMEM); - s->dectx.metadata.multi_prog_warned = !!(avctx->request_channel_layout & AV_CH_LAYOUT_NATIVE); +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->request_channel_layout & AV_CH_LAYOUT_NATIVE) + s->dectx.metadata.output_channel_order = CHANNEL_ORDER_CODED; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + + s->dectx.metadata.multi_prog_warned = s->dectx.metadata.output_channel_order == CHANNEL_ORDER_CODED; s->dectx.avctx = s->avctx = avctx; return 0; } -const AVCodec ff_dolby_e_decoder = { - .name = "dolby_e", - .long_name = NULL_IF_CONFIG_SMALL("Dolby E"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_DOLBY_E, +#define OFFSET(x) offsetof(DBEDecodeContext, x) +#define FLAGS (AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM) +static const AVOption options[] = { + { "channel_order", "Order in which the channels are to be exported", + OFFSET(dectx.metadata.output_channel_order), AV_OPT_TYPE_INT, + { .i64 = CHANNEL_ORDER_DEFAULT }, 0, 1, FLAGS, "channel_order" }, + { "default", "normal libavcodec channel order", 0, AV_OPT_TYPE_CONST, + { .i64 = CHANNEL_ORDER_DEFAULT }, .flags = FLAGS, "channel_order" }, + { "coded", "order in which the channels are coded in the bitstream", + 0, AV_OPT_TYPE_CONST, { .i64 = CHANNEL_ORDER_CODED }, .flags = FLAGS, "channel_order" }, + + { NULL }, +}; + +static const AVClass dolby_e_decoder_class = { + .class_name = "Dolby E decoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +const FFCodec ff_dolby_e_decoder = { + .p.name = "dolby_e", + .p.long_name = NULL_IF_CONFIG_SMALL("Dolby E"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_DOLBY_E, .priv_data_size = sizeof(DBEDecodeContext), + .p.priv_class = &dolby_e_decoder_class, .init = dolby_e_init, - .decode = dolby_e_decode_frame, + FF_CODEC_DECODE_CB(dolby_e_decode_frame), .close = dolby_e_close, .flush = dolby_e_flush, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/dolby_e.h b/libavcodec/dolby_e.h index 9f0c06572..b2eadfea4 100644 --- a/libavcodec/dolby_e.h +++ b/libavcodec/dolby_e.h @@ -59,6 +59,8 @@ typedef struct DolbyEHeaderInfo { */ int multi_prog_warned; + int output_channel_order; + int sample_rate; /** @} */ } DolbyEHeaderInfo; diff --git a/libavcodec/dolby_e_parser.c b/libavcodec/dolby_e_parser.c index 23bddd14f..9f5462735 100644 --- a/libavcodec/dolby_e_parser.c +++ b/libavcodec/dolby_e_parser.c @@ -42,17 +42,20 @@ static int dolby_e_parse(AVCodecParserContext *s2, AVCodecContext *avctx, s2->duration = FRAME_SAMPLES; switch (s->metadata.nb_channels) { case 4: - avctx->channel_layout = AV_CH_LAYOUT_4POINT0; + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_4POINT0; break; case 6: - avctx->channel_layout = AV_CH_LAYOUT_5POINT1; + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1; break; case 8: - avctx->channel_layout = AV_CH_LAYOUT_7POINT1; + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_7POINT1; + break; + default: + avctx->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + avctx->ch_layout.nb_channels = s->metadata.nb_channels; break; } - avctx->channels = s->metadata.nb_channels; avctx->sample_rate = s->metadata.sample_rate; avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; diff --git a/libavcodec/dovi_rpu.c b/libavcodec/dovi_rpu.c index a87562c8a..dd3893655 100644 --- a/libavcodec/dovi_rpu.c +++ b/libavcodec/dovi_rpu.c @@ -172,7 +172,7 @@ static inline int64_t get_se_coef(GetBitContext *gb, const AVDOVIRpuDataHeader * case RPU_COEFF_FIXED: ipart = get_se_golomb_long(gb); fpart.u32 = get_bits_long(gb, hdr->coef_log2_denom); - return (ipart << hdr->coef_log2_denom) + fpart.u32; + return ipart * (1LL << hdr->coef_log2_denom) + fpart.u32; case RPU_COEFF_FLOAT: fpart.u32 = get_bits_long(gb, 32); diff --git a/libavcodec/dpcm.c b/libavcodec/dpcm.c index d9ea23adb..ad020b52f 100644 --- a/libavcodec/dpcm.c +++ b/libavcodec/dpcm.c @@ -40,6 +40,7 @@ #include "libavutil/intreadwrite.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" #include "mathops.h" @@ -132,7 +133,7 @@ static av_cold int dpcm_decode_init(AVCodecContext *avctx) DPCMContext *s = avctx->priv_data; int i; - if (avctx->channels < 1 || avctx->channels > 2) { + if (avctx->ch_layout.nb_channels < 1 || avctx->ch_layout.nb_channels > 2) { av_log(avctx, AV_LOG_ERROR, "invalid number of channels\n"); return AVERROR(EINVAL); } @@ -206,16 +207,15 @@ static av_cold int dpcm_decode_init(AVCodecContext *avctx) } -static int dpcm_decode_frame(AVCodecContext *avctx, void *data, +static int dpcm_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { int buf_size = avpkt->size; DPCMContext *s = avctx->priv_data; - AVFrame *frame = data; int out = 0, ret; int predictor[2]; int ch = 0; - int stereo = avctx->channels - 1; + int stereo = avctx->ch_layout.nb_channels - 1; int16_t *output_samples, *samples_end; GetByteContext gb; @@ -229,10 +229,10 @@ static int dpcm_decode_frame(AVCodecContext *avctx, void *data, out = buf_size - 8; break; case AV_CODEC_ID_INTERPLAY_DPCM: - out = buf_size - 6 - avctx->channels; + out = buf_size - 6 - avctx->ch_layout.nb_channels; break; case AV_CODEC_ID_XAN_DPCM: - out = buf_size - 2 * avctx->channels; + out = buf_size - 2 * avctx->ch_layout.nb_channels; break; case AV_CODEC_ID_SOL_DPCM: if (avctx->codec_tag != 3) @@ -250,12 +250,12 @@ static int dpcm_decode_frame(AVCodecContext *avctx, void *data, av_log(avctx, AV_LOG_ERROR, "packet is too small\n"); return AVERROR(EINVAL); } - if (out % avctx->channels) { + if (out % avctx->ch_layout.nb_channels) { av_log(avctx, AV_LOG_WARNING, "channels have differing number of samples\n"); } /* get output buffer */ - frame->nb_samples = (out + avctx->channels - 1) / avctx->channels; + frame->nb_samples = (out + avctx->ch_layout.nb_channels - 1) / avctx->ch_layout.nb_channels; if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; output_samples = (int16_t *)frame->data[0]; @@ -287,7 +287,7 @@ static int dpcm_decode_frame(AVCodecContext *avctx, void *data, case AV_CODEC_ID_INTERPLAY_DPCM: bytestream2_skipu(&gb, 6); /* skip over the stream mask and stream length */ - for (ch = 0; ch < avctx->channels; ch++) { + for (ch = 0; ch < avctx->ch_layout.nb_channels; ch++) { predictor[ch] = sign_extend(bytestream2_get_le16u(&gb), 16); *output_samples++ = predictor[ch]; } @@ -307,7 +307,7 @@ static int dpcm_decode_frame(AVCodecContext *avctx, void *data, { int shift[2] = { 4, 4 }; - for (ch = 0; ch < avctx->channels; ch++) + for (ch = 0; ch < avctx->ch_layout.nb_channels; ch++) predictor[ch] = sign_extend(bytestream2_get_le16u(&gb), 16); ch = 0; @@ -410,15 +410,15 @@ static int dpcm_decode_frame(AVCodecContext *avctx, void *data, } #define DPCM_DECODER(id_, name_, long_name_) \ -const AVCodec ff_ ## name_ ## _decoder = { \ - .name = #name_, \ - .long_name = NULL_IF_CONFIG_SMALL(long_name_), \ - .type = AVMEDIA_TYPE_AUDIO, \ - .id = id_, \ +const FFCodec ff_ ## name_ ## _decoder = { \ + .p.name = #name_, \ + .p.long_name = NULL_IF_CONFIG_SMALL(long_name_), \ + .p.type = AVMEDIA_TYPE_AUDIO, \ + .p.id = id_, \ + .p.capabilities = AV_CODEC_CAP_DR1, \ .priv_data_size = sizeof(DPCMContext), \ .init = dpcm_decode_init, \ - .decode = dpcm_decode_frame, \ - .capabilities = AV_CODEC_CAP_DR1, \ + FF_CODEC_DECODE_CB(dpcm_decode_frame), \ .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, \ } diff --git a/libavcodec/dpx.c b/libavcodec/dpx.c index 3563bdc53..bb2c5e588 100644 --- a/libavcodec/dpx.c +++ b/libavcodec/dpx.c @@ -26,6 +26,7 @@ #include "libavutil/timecode.h" #include "bytestream.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" enum DPX_TRC { @@ -149,14 +150,11 @@ static uint16_t read12in32(const uint8_t **ptr, uint32_t *lbuf, } } -static int decode_frame(AVCodecContext *avctx, - void *data, - int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *p, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; - AVFrame *const p = data; uint8_t *ptr[AV_NUM_DATA_POINTERS]; uint32_t header_version, version = 0; char creator[101] = { 0 }; @@ -762,11 +760,11 @@ static int decode_frame(AVCodecContext *avctx, return buf_size; } -const AVCodec ff_dpx_decoder = { - .name = "dpx", - .long_name = NULL_IF_CONFIG_SMALL("DPX (Digital Picture Exchange) image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_DPX, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, +const FFCodec ff_dpx_decoder = { + .p.name = "dpx", + .p.long_name = NULL_IF_CONFIG_SMALL("DPX (Digital Picture Exchange) image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_DPX, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/dpxenc.c b/libavcodec/dpxenc.c index 0db6aa832..1f2b1b8f5 100644 --- a/libavcodec/dpxenc.c +++ b/libavcodec/dpxenc.c @@ -23,8 +23,9 @@ #include "libavutil/intreadwrite.h" #include "libavutil/imgutils.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" +#include "version.h" typedef struct DPXContext { int big_endian; @@ -273,16 +274,16 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, return 0; } -const AVCodec ff_dpx_encoder = { - .name = "dpx", - .long_name = NULL_IF_CONFIG_SMALL("DPX (Digital Picture Exchange) image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_DPX, - .capabilities = AV_CODEC_CAP_DR1, +const FFCodec ff_dpx_encoder = { + .p.name = "dpx", + .p.long_name = NULL_IF_CONFIG_SMALL("DPX (Digital Picture Exchange) image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_DPX, + .p.capabilities = AV_CODEC_CAP_DR1, .priv_data_size = sizeof(DPXContext), .init = encode_init, - .encode2 = encode_frame, - .pix_fmts = (const enum AVPixelFormat[]){ + FF_CODEC_ENCODE_CB(encode_frame), + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_GRAY8, AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, AV_PIX_FMT_ABGR, AV_PIX_FMT_GRAY16LE, AV_PIX_FMT_GRAY16BE, diff --git a/libavcodec/dsddec.c b/libavcodec/dsddec.c index 19fb75ee8..f0e54db10 100644 --- a/libavcodec/dsddec.c +++ b/libavcodec/dsddec.c @@ -28,6 +28,7 @@ #include "libavcodec/internal.h" #include "avcodec.h" +#include "codec_internal.h" #include "dsd.h" #define DSD_SILENCE 0x69 @@ -44,17 +45,17 @@ static av_cold int decode_init(AVCodecContext *avctx) int i; uint8_t silence; - if (!avctx->channels) + if (!avctx->ch_layout.nb_channels) return AVERROR_INVALIDDATA; ff_init_dsd_data(); - s = av_malloc_array(sizeof(DSDContext), avctx->channels); + s = av_malloc_array(sizeof(DSDContext), avctx->ch_layout.nb_channels); if (!s) return AVERROR(ENOMEM); silence = avctx->codec_id == AV_CODEC_ID_DSD_LSBF || avctx->codec_id == AV_CODEC_ID_DSD_LSBF_PLANAR ? DSD_SILENCE_REVERSED : DSD_SILENCE; - for (i = 0; i < avctx->channels; i++) { + for (i = 0; i < avctx->ch_layout.nb_channels; i++) { s[i].pos = 0; memset(s[i].buf, silence, sizeof(s[i].buf)); } @@ -84,7 +85,7 @@ static int dsd_channel(AVCodecContext *avctx, void *tdata, int j, int threadnr) src_stride = 1; } else { src_next = 1; - src_stride = avctx->channels; + src_stride = avctx->ch_layout.nb_channels; } ff_dsd2pcm_translate(&s[j], frame->nb_samples, lsbf, @@ -94,36 +95,35 @@ static int dsd_channel(AVCodecContext *avctx, void *tdata, int j, int threadnr) return 0; } -static int decode_frame(AVCodecContext *avctx, void *data, +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { ThreadData td; - AVFrame *frame = data; int ret; - frame->nb_samples = avpkt->size / avctx->channels; + frame->nb_samples = avpkt->size / avctx->ch_layout.nb_channels; if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; td.frame = frame; td.avpkt = avpkt; - avctx->execute2(avctx, dsd_channel, &td, NULL, avctx->channels); + avctx->execute2(avctx, dsd_channel, &td, NULL, avctx->ch_layout.nb_channels); *got_frame_ptr = 1; - return frame->nb_samples * avctx->channels; + return frame->nb_samples * avctx->ch_layout.nb_channels; } #define DSD_DECODER(id_, name_, long_name_) \ -const AVCodec ff_ ## name_ ## _decoder = { \ - .name = #name_, \ - .long_name = NULL_IF_CONFIG_SMALL(long_name_), \ - .type = AVMEDIA_TYPE_AUDIO, \ - .id = AV_CODEC_ID_##id_, \ +const FFCodec ff_ ## name_ ## _decoder = { \ + .p.name = #name_, \ + .p.long_name = NULL_IF_CONFIG_SMALL(long_name_), \ + .p.type = AVMEDIA_TYPE_AUDIO, \ + .p.id = AV_CODEC_ID_##id_, \ .init = decode_init, \ - .decode = decode_frame, \ - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS, \ - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP, \ + FF_CODEC_DECODE_CB(decode_frame), \ + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS, \ + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP, \ AV_SAMPLE_FMT_NONE }, \ .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, \ }; diff --git a/libavcodec/dsicinaudio.c b/libavcodec/dsicinaudio.c index 39869ac0c..2cfaebca4 100644 --- a/libavcodec/dsicinaudio.c +++ b/libavcodec/dsicinaudio.c @@ -28,6 +28,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" #include "mathops.h" @@ -80,16 +81,15 @@ static av_cold int cinaudio_decode_init(AVCodecContext *avctx) cin->initial_decode_frame = 1; cin->delta = 0; avctx->sample_fmt = AV_SAMPLE_FMT_S16; - avctx->channels = 1; - avctx->channel_layout = AV_CH_LAYOUT_MONO; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; return 0; } -static int cinaudio_decode_frame(AVCodecContext *avctx, void *data, +static int cinaudio_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; const uint8_t *buf = avpkt->data; CinAudioContext *cin = avctx->priv_data; const uint8_t *buf_end = buf + avpkt->size; @@ -121,14 +121,14 @@ static int cinaudio_decode_frame(AVCodecContext *avctx, void *data, return avpkt->size; } -const AVCodec ff_dsicinaudio_decoder = { - .name = "dsicinaudio", - .long_name = NULL_IF_CONFIG_SMALL("Delphine Software International CIN audio"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_DSICINAUDIO, +const FFCodec ff_dsicinaudio_decoder = { + .p.name = "dsicinaudio", + .p.long_name = NULL_IF_CONFIG_SMALL("Delphine Software International CIN audio"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_DSICINAUDIO, .priv_data_size = sizeof(CinAudioContext), .init = cinaudio_decode_init, - .decode = cinaudio_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + FF_CODEC_DECODE_CB(cinaudio_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/dsicinvideo.c b/libavcodec/dsicinvideo.c index c58f9a9ef..71f607141 100644 --- a/libavcodec/dsicinvideo.c +++ b/libavcodec/dsicinvideo.c @@ -26,6 +26,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" typedef enum CinVideoBitmapIndex { @@ -193,9 +194,8 @@ static int cin_decode_rle(const unsigned char *src, int src_size, return 0; } -static int cinvideo_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int cinvideo_decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; @@ -302,7 +302,7 @@ static int cinvideo_decode_frame(AVCodecContext *avctx, FFSWAP(uint8_t *, cin->bitmap_table[CIN_CUR_BMP], cin->bitmap_table[CIN_PRE_BMP]); - if ((res = av_frame_ref(data, cin->frame)) < 0) + if ((res = av_frame_ref(rframe, cin->frame)) < 0) return res; *got_frame = 1; @@ -321,15 +321,15 @@ static av_cold int cinvideo_decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_dsicinvideo_decoder = { - .name = "dsicinvideo", - .long_name = NULL_IF_CONFIG_SMALL("Delphine Software International CIN video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_DSICINVIDEO, +const FFCodec ff_dsicinvideo_decoder = { + .p.name = "dsicinvideo", + .p.long_name = NULL_IF_CONFIG_SMALL("Delphine Software International CIN video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_DSICINVIDEO, .priv_data_size = sizeof(CinVideoContext), .init = cinvideo_decode_init, .close = cinvideo_decode_end, - .decode = cinvideo_decode_frame, + FF_CODEC_DECODE_CB(cinvideo_decode_frame), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/dss_sp.c b/libavcodec/dss_sp.c index 050b41249..b465bfe93 100644 --- a/libavcodec/dss_sp.c +++ b/libavcodec/dss_sp.c @@ -25,6 +25,7 @@ #include "libavutil/opt.h" #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" @@ -290,10 +291,10 @@ static const int32_t dss_sp_sinc[67] = { static av_cold int dss_sp_decode_init(AVCodecContext *avctx) { DssSpContext *p = avctx->priv_data; - avctx->channel_layout = AV_CH_LAYOUT_MONO; avctx->sample_fmt = AV_SAMPLE_FMT_S16; - avctx->channels = 1; avctx->sample_rate = 11025; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; p->pulse_dec_mode = 1; p->avctx = avctx; @@ -739,11 +740,10 @@ static int dss_sp_decode_one_frame(DssSpContext *p, return 0; } -static int dss_sp_decode_frame(AVCodecContext *avctx, void *data, +static int dss_sp_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { DssSpContext *p = avctx->priv_data; - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; @@ -772,14 +772,14 @@ static int dss_sp_decode_frame(AVCodecContext *avctx, void *data, return DSS_SP_FRAME_SIZE; } -const AVCodec ff_dss_sp_decoder = { - .name = "dss_sp", - .long_name = NULL_IF_CONFIG_SMALL("Digital Speech Standard - Standard Play mode (DSS SP)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_DSS_SP, +const FFCodec ff_dss_sp_decoder = { + .p.name = "dss_sp", + .p.long_name = NULL_IF_CONFIG_SMALL("Digital Speech Standard - Standard Play mode (DSS SP)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_DSS_SP, .priv_data_size = sizeof(DssSpContext), .init = dss_sp_decode_init, - .decode = dss_sp_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + FF_CODEC_DECODE_CB(dss_sp_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/dstdec.c b/libavcodec/dstdec.c index 6d0b25f4c..93642e34b 100644 --- a/libavcodec/dstdec.c +++ b/libavcodec/dstdec.c @@ -27,6 +27,8 @@ #include "libavutil/intreadwrite.h" #include "libavutil/mem_internal.h" +#include "libavutil/reverse.h" +#include "codec_internal.h" #include "internal.h" #include "get_bits.h" #include "avcodec.h" @@ -80,8 +82,8 @@ static av_cold int decode_init(AVCodecContext *avctx) DSTContext *s = avctx->priv_data; int i; - if (avctx->channels > DST_MAX_CHANNELS) { - avpriv_request_sample(avctx, "Channel count %d", avctx->channels); + if (avctx->ch_layout.nb_channels > DST_MAX_CHANNELS) { + avpriv_request_sample(avctx, "Channel count %d", avctx->ch_layout.nb_channels); return AVERROR_PATCHWELCOME; } @@ -97,7 +99,7 @@ static av_cold int decode_init(AVCodecContext *avctx) avctx->sample_fmt = AV_SAMPLE_FMT_FLT; - for (i = 0; i < avctx->channels; i++) + for (i = 0; i < avctx->ch_layout.nb_channels; i++) memset(s->dsdctx[i].buf, 0x69, sizeof(s->dsdctx[i].buf)); ff_init_dsd_data(); @@ -235,7 +237,7 @@ static void build_filter(int16_t table[DST_MAX_ELEMENTS][16][256], const Table * } } -static int decode_frame(AVCodecContext *avctx, void *data, +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { unsigned samples_per_frame = DST_SAMPLES_PER_FRAME(avctx->sample_rate); @@ -243,11 +245,10 @@ static int decode_frame(AVCodecContext *avctx, void *data, unsigned map_ch_to_pelem[DST_MAX_CHANNELS]; unsigned i, ch, same_map, dst_x_bit; unsigned half_prob[DST_MAX_CHANNELS]; - const int channels = avctx->channels; + const int channels = avctx->ch_layout.nb_channels; DSTContext *s = avctx->priv_data; GetBitContext *gb = &s->gb; ArithCoder *ac = &s->ac; - AVFrame *frame = data; uint8_t *dsd; float *pcm; int ret; @@ -378,16 +379,16 @@ dsd: return avpkt->size; } -const AVCodec ff_dst_decoder = { - .name = "dst", - .long_name = NULL_IF_CONFIG_SMALL("DST (Digital Stream Transfer)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_DST, +const FFCodec ff_dst_decoder = { + .p.name = "dst", + .p.long_name = NULL_IF_CONFIG_SMALL("DST (Digital Stream Transfer)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_DST, .priv_data_size = sizeof(DSTContext), .init = decode_init, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLT, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/dump_extradata_bsf.c b/libavcodec/dump_extradata_bsf.c index b6ef8b3e6..5506d5ed6 100644 --- a/libavcodec/dump_extradata_bsf.c +++ b/libavcodec/dump_extradata_bsf.c @@ -98,9 +98,9 @@ static const AVClass dump_extradata_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVBitStreamFilter ff_dump_extradata_bsf = { - .name = "dump_extra", +const FFBitStreamFilter ff_dump_extradata_bsf = { + .p.name = "dump_extra", + .p.priv_class = &dump_extradata_class, .priv_data_size = sizeof(DumpExtradataContext), - .priv_class = &dump_extradata_class, .filter = dump_extradata, }; diff --git a/libavcodec/dv.c b/libavcodec/dv.c index 8a4cac859..e2550c4cc 100644 --- a/libavcodec/dv.c +++ b/libavcodec/dv.c @@ -38,15 +38,8 @@ * DV codec. */ -#include "libavutil/internal.h" -#include "libavutil/pixdesc.h" - #include "avcodec.h" #include "dv.h" -#include "dvdata.h" -#include "internal.h" -#include "put_bits.h" -#include "simple_idct.h" static inline void dv_calc_mb_coordinates(const AVDVProfile *d, int chan, int seq, int slot, uint16_t *tbl) diff --git a/libavcodec/dv.h b/libavcodec/dv.h index 19290aa38..855afcc75 100644 --- a/libavcodec/dv.h +++ b/libavcodec/dv.h @@ -30,7 +30,6 @@ #include "avcodec.h" #include "dv_profile.h" #include "me_cmp.h" -#include "vlc.h" #include "idctdsp.h" typedef struct DVwork_chunk { diff --git a/libavcodec/dv_error_marker_bsf.c b/libavcodec/dv_error_marker_bsf.c new file mode 100644 index 000000000..131c6fcbe --- /dev/null +++ b/libavcodec/dv_error_marker_bsf.c @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2022 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 "bsf.h" +#include "bsf_internal.h" +#include "libavutil/colorspace.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/opt.h" + +typedef struct DVErrorMarkerContext { + const AVClass *class; + uint8_t color_rgba[4]; + int sta; + uint8_t marked_block[76]; +} DVErrorMarkerContext; + +static void setdc(uint8_t *b, const uint8_t color_rgba[4], int cblocks, int y_step, int v_step, int u_step) { + for (int i=0; i<4; i++) { + b[0] = RGB_TO_Y_JPEG(color_rgba[0], color_rgba[1],color_rgba[2]) + 128; + b[1] = 0x06; + b += y_step; + } + for (int i=0; ipriv_data; + + memset(s->marked_block, -1, 76); + setdc(s->marked_block, s->color_rgba, 1, 14, 10, 10); + setdc(s->marked_block, s->color_rgba, 2, 10, 10, 8); + + return 0; +} + +static int dv_error_marker_filter(AVBSFContext *ctx, AVPacket *pkt) +{ + DVErrorMarkerContext *s = ctx->priv_data; + int ret = ff_bsf_get_packet_ref(ctx, pkt); + uint8_t *p; + int writable = 0; + int stamask = s->sta; + int match_count = 0; + + if (ret < 0) + return ret; + + p = pkt->data; + for(int i = 0; i < pkt->size - 79; i+=80) { + // see page 44-46 or section 5.5 of http://web.archive.org/web/20060927044735/http://www.smpte.org/smpte_store/standards/pdf/s314m.pdf. + if ((p[i] >> 4) == 9 && ((stamask >> (p[i+3] >> 4))&1)) { + if (!writable) { + ret = av_packet_make_writable(pkt); + if (ret < 0) { + av_packet_unref(pkt); + return ret; + } + writable = 1; + p = pkt->data; + } + memcpy(p+i+4, s->marked_block, 76); + match_count ++; + } + } + av_log(ctx, AV_LOG_DEBUG, "%8"PRId64": Replaced %5d blocks by color %X\n", pkt->pts, match_count, AV_RB32(s->color_rgba)); + + return 0; +} + +#define OFFSET(x) offsetof(DVErrorMarkerContext, x) +#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_BSF_PARAM) +static const AVOption options[] = { + { "color" , "set color", OFFSET(color_rgba), AV_OPT_TYPE_COLOR, {.str = "yellow"}, 0, 0, FLAGS }, + { "sta" , "specify which error status value to match" + , OFFSET(sta ), AV_OPT_TYPE_FLAGS, {.i64 = 0xFFFE}, 0, 0xFFFF, FLAGS, "sta" }, + { "ok" , "No error, no concealment", 0, AV_OPT_TYPE_CONST, {.i64 = 0x0001}, 0, 0xFFFF, FLAGS, "sta"}, + { "Aa" , "No error, concealment from previous frame type a",0, AV_OPT_TYPE_CONST, {.i64 = 0x0004}, 0, 0xFFFF, FLAGS, "sta"}, + { "Ba" , "No error, concealment from next frame type a", 0, AV_OPT_TYPE_CONST, {.i64 = 0x0010}, 0, 0xFFFF, FLAGS, "sta"}, + { "Ca" , "No error, unspecified concealment type a", 0, AV_OPT_TYPE_CONST, {.i64 = 0x0040}, 0, 0xFFFF, FLAGS, "sta"}, + { "erri" , "Error with inserted code, No concealment", 0, AV_OPT_TYPE_CONST, {.i64 = 0x0080}, 0, 0xFFFF, FLAGS, "sta"}, + { "erru" , "Error with unidentified pos, No concealment", 0, AV_OPT_TYPE_CONST, {.i64 = 0x8000}, 0, 0xFFFF, FLAGS, "sta"}, + { "err" , "Error, No concealment", 0, AV_OPT_TYPE_CONST, {.i64 = 0x8080}, 0, 0xFFFF, FLAGS, "sta"}, + { "Ab" , "No error, concealment from previous frame type b",0, AV_OPT_TYPE_CONST, {.i64 = 0x0400}, 0, 0xFFFF, FLAGS, "sta"}, + { "Bb" , "No error, concealment from next frame type b", 0, AV_OPT_TYPE_CONST, {.i64 = 0x1000}, 0, 0xFFFF, FLAGS, "sta"}, + { "Cb" , "No error, unspecified concealment type b", 0, AV_OPT_TYPE_CONST, {.i64 = 0x4000}, 0, 0xFFFF, FLAGS, "sta"}, + { "A" , "No error, concealment from previous frame", 0, AV_OPT_TYPE_CONST, {.i64 = 0x0404}, 0, 0xFFFF, FLAGS, "sta"}, + { "B" , "No error, concealment from next frame", 0, AV_OPT_TYPE_CONST, {.i64 = 0x1010}, 0, 0xFFFF, FLAGS, "sta"}, + { "C" , "No error, unspecified concealment", 0, AV_OPT_TYPE_CONST, {.i64 = 0x4040}, 0, 0xFFFF, FLAGS, "sta"}, + { "a" , "No error, concealment type a", 0, AV_OPT_TYPE_CONST, {.i64 = 0x0054}, 0, 0xFFFF, FLAGS, "sta"}, + { "b" , "No error, concealment type b", 0, AV_OPT_TYPE_CONST, {.i64 = 0x5400}, 0, 0xFFFF, FLAGS, "sta"}, + { "res" , "Reserved", 0, AV_OPT_TYPE_CONST, {.i64 = 0x2B2A}, 0, 0xFFFF, FLAGS, "sta"}, + { "notok" , "Error or concealment", 0, AV_OPT_TYPE_CONST, {.i64 = 0xD4D4}, 0, 0xFFFF, FLAGS, "sta"}, + { "notres" , "Not reserved", 0, AV_OPT_TYPE_CONST, {.i64 = 0xD4D5}, 0, 0xFFFF, FLAGS, "sta"}, + { NULL }, +}; + +static const AVClass dv_error_marker_class = { + .class_name = "dv_error_marker", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +const FFBitStreamFilter ff_dv_error_marker_bsf = { + .p.name = "dv_error_marker", + .p.codec_ids = (const enum AVCodecID []){ AV_CODEC_ID_DVVIDEO, AV_CODEC_ID_NONE }, + .p.priv_class = &dv_error_marker_class, + .priv_data_size = sizeof(DVErrorMarkerContext), + .init = dv_error_marker_init, + .filter = dv_error_marker_filter, +}; diff --git a/libavcodec/dv_profile.c b/libavcodec/dv_profile.c index 0fc227dd0..f40311418 100644 --- a/libavcodec/dv_profile.c +++ b/libavcodec/dv_profile.c @@ -18,11 +18,12 @@ #include "config.h" +#include #include -#include "libavutil/common.h" #include "libavutil/intreadwrite.h" #include "libavutil/log.h" +#include "libavutil/macros.h" #include "libavutil/pixdesc.h" #include "avcodec.h" diff --git a/libavcodec/dvaudiodec.c b/libavcodec/dvaudiodec.c index 82e6dbe36..56d9c3573 100644 --- a/libavcodec/dvaudiodec.c +++ b/libavcodec/dvaudiodec.c @@ -21,6 +21,7 @@ #include "libavutil/channel_layout.h" #include "libavutil/intreadwrite.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "dvaudio.h" @@ -36,11 +37,6 @@ static av_cold int decode_init(AVCodecContext *avctx) DVAudioContext *s = avctx->priv_data; int i; - if (avctx->channels != 2) { - av_log(avctx, AV_LOG_ERROR, "invalid number of channels\n"); - return AVERROR(EINVAL); - } - if (avctx->codec_tag == 0x0215) { s->block_size = 7200; } else if (avctx->codec_tag == 0x0216) { @@ -55,7 +51,8 @@ static av_cold int decode_init(AVCodecContext *avctx) s->is_pal = s->block_size == 8640; s->is_12bit = avctx->bits_per_coded_sample == 12; avctx->sample_fmt = AV_SAMPLE_FMT_S16; - avctx->channel_layout = AV_CH_LAYOUT_STEREO; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; for (i = 0; i < FF_ARRAY_ELEMS(s->shuffle); i++) { const unsigned a = s->is_pal ? 18 : 15; @@ -88,11 +85,10 @@ static inline uint16_t dv_audio_12to16(uint16_t sample) return result; } -static int decode_frame(AVCodecContext *avctx, void *data, +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *pkt) { DVAudioContext *s = avctx->priv_data; - AVFrame *frame = data; const uint8_t *src = pkt->data; int16_t *dst; int ret, i; @@ -122,14 +118,14 @@ static int decode_frame(AVCodecContext *avctx, void *data, return s->block_size; } -const AVCodec ff_dvaudio_decoder = { - .name = "dvaudio", - .long_name = NULL_IF_CONFIG_SMALL("Ulead DV Audio"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_DVAUDIO, +const FFCodec ff_dvaudio_decoder = { + .p.name = "dvaudio", + .p.long_name = NULL_IF_CONFIG_SMALL("Ulead DV Audio"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_DVAUDIO, .init = decode_init, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .priv_data_size = sizeof(DVAudioContext), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/dvbsub_parser.c b/libavcodec/dvbsub_parser.c index 88bf5b9d7..b2d544686 100644 --- a/libavcodec/dvbsub_parser.c +++ b/libavcodec/dvbsub_parser.c @@ -25,7 +25,6 @@ #include "libavutil/intreadwrite.h" #include "avcodec.h" -#include "internal.h" /* Parser (mostly) copied from dvdsub.c */ diff --git a/libavcodec/dvbsubdec.c b/libavcodec/dvbsubdec.c index bc741a1de..4d4007ffd 100644 --- a/libavcodec/dvbsubdec.c +++ b/libavcodec/dvbsubdec.c @@ -22,6 +22,7 @@ #include "avcodec.h" #include "get_bits.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" #include "libavutil/colorspace.h" #include "libavutil/imgutils.h" @@ -1380,172 +1381,6 @@ static int dvbsub_parse_page_segment(AVCodecContext *avctx, return 0; } - -#ifdef DEBUG -static void png_save(DVBSubContext *ctx, const char *filename, uint32_t *bitmap, int w, int h) -{ - int x, y, v; - FILE *f; - char fname[40], fname2[40]; - char command[1024]; - - snprintf(fname, sizeof(fname), "%s.ppm", filename); - - f = fopen(fname, "w"); - if (!f) { - perror(fname); - return; - } - fprintf(f, "P6\n" - "%d %d\n" - "%d\n", - w, h, 255); - for(y = 0; y < h; y++) { - for(x = 0; x < w; x++) { - v = bitmap[y * w + x]; - putc((v >> 16) & 0xff, f); - putc((v >> 8) & 0xff, f); - putc((v >> 0) & 0xff, f); - } - } - fclose(f); - - - snprintf(fname2, sizeof(fname2), "%s-a.pgm", filename); - - f = fopen(fname2, "w"); - if (!f) { - perror(fname2); - return; - } - fprintf(f, "P5\n" - "%d %d\n" - "%d\n", - w, h, 255); - for(y = 0; y < h; y++) { - for(x = 0; x < w; x++) { - v = bitmap[y * w + x]; - putc((v >> 24) & 0xff, f); - } - } - fclose(f); - - snprintf(command, sizeof(command), "pnmtopng -alpha %s %s > %s.png 2> /dev/null", fname2, fname, filename); - if (system(command) != 0) { - av_log(ctx, AV_LOG_ERROR, "Error running pnmtopng\n"); - return; - } - - snprintf(command, sizeof(command), "rm %s %s", fname, fname2); - if (system(command) != 0) { - av_log(ctx, AV_LOG_ERROR, "Error removing %s and %s\n", fname, fname2); - return; - } -} - -static int save_display_set(DVBSubContext *ctx) -{ - DVBSubRegion *region; - DVBSubRegionDisplay *display; - const DVBSubCLUT *clut; - const uint32_t *clut_table; - int x_pos, y_pos, width, height; - int x, y, y_off, x_off; - uint32_t *pbuf; - char filename[32]; - static int fileno_index = 0; - - x_pos = -1; - y_pos = -1; - width = 0; - height = 0; - - for (display = ctx->display_list; display; display = display->next) { - region = get_region(ctx, display->region_id); - - if (!region) - return -1; - - if (x_pos == -1) { - x_pos = display->x_pos; - y_pos = display->y_pos; - width = region->width; - height = region->height; - } else { - if (display->x_pos < x_pos) { - width += (x_pos - display->x_pos); - x_pos = display->x_pos; - } - - if (display->y_pos < y_pos) { - height += (y_pos - display->y_pos); - y_pos = display->y_pos; - } - - if (display->x_pos + region->width > x_pos + width) { - width = display->x_pos + region->width - x_pos; - } - - if (display->y_pos + region->height > y_pos + height) { - height = display->y_pos + region->height - y_pos; - } - } - } - - if (x_pos >= 0) { - - pbuf = av_malloc(width * height * 4); - if (!pbuf) - return -1; - - for (display = ctx->display_list; display; display = display->next) { - region = get_region(ctx, display->region_id); - - if (!region) - return -1; - - x_off = display->x_pos - x_pos; - y_off = display->y_pos - y_pos; - - clut = get_clut(ctx, region->clut); - - if (!clut) - clut = &default_clut; - - switch (region->depth) { - case 2: - clut_table = clut->clut4; - break; - case 8: - clut_table = clut->clut256; - break; - case 4: - default: - clut_table = clut->clut16; - break; - } - - for (y = 0; y < region->height; y++) { - for (x = 0; x < region->width; x++) { - pbuf[((y + y_off) * width) + x_off + x] = - clut_table[region->pbuf[y * region->width + x]]; - } - } - - } - - snprintf(filename, sizeof(filename), "dvbs.%d", fileno_index); - - png_save(ctx, filename, pbuf, width, height); - - av_freep(&pbuf); - } - - fileno_index++; - return 0; -} -#endif /* DEBUG */ - static int dvbsub_parse_display_definition_segment(AVCodecContext *avctx, const uint8_t *buf, int buf_size) @@ -1600,20 +1435,15 @@ static int dvbsub_display_end_segment(AVCodecContext *avctx, const uint8_t *buf, if (ctx->compute_edt == 0) save_subtitle_set(avctx, sub, got_output); -#ifdef DEBUG - save_display_set(ctx); -#endif return 0; } -static int dvbsub_decode(AVCodecContext *avctx, - void *data, int *got_sub_ptr, - AVPacket *avpkt) +static int dvbsub_decode(AVCodecContext *avctx, AVSubtitle *sub, + int *got_sub_ptr, const AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; DVBSubContext *ctx = avctx->priv_data; - AVSubtitle *sub = data; const uint8_t *p, *p_end; int segment_type; int page_id; @@ -1739,15 +1569,15 @@ static const AVClass dvbsubdec_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_dvbsub_decoder = { - .name = "dvbsub", - .long_name = NULL_IF_CONFIG_SMALL("DVB subtitles"), - .type = AVMEDIA_TYPE_SUBTITLE, - .id = AV_CODEC_ID_DVB_SUBTITLE, +const FFCodec ff_dvbsub_decoder = { + .p.name = "dvbsub", + .p.long_name = NULL_IF_CONFIG_SMALL("DVB subtitles"), + .p.type = AVMEDIA_TYPE_SUBTITLE, + .p.id = AV_CODEC_ID_DVB_SUBTITLE, .priv_data_size = sizeof(DVBSubContext), .init = dvbsub_init_decoder, .close = dvbsub_close_decoder, - .decode = dvbsub_decode, - .priv_class = &dvbsubdec_class, + FF_CODEC_DECODE_SUB_CB(dvbsub_decode), + .p.priv_class = &dvbsubdec_class, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/dvbsubenc.c b/libavcodec/dvbsubenc.c index 322fc27cb..06087b058 100644 --- a/libavcodec/dvbsubenc.c +++ b/libavcodec/dvbsubenc.c @@ -20,6 +20,7 @@ */ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "libavutil/colorspace.h" typedef struct DVBSubtitleContext { @@ -505,11 +506,11 @@ static int dvbsub_encode(AVCodecContext *avctx, uint8_t *outbuf, int buf_size, return q - outbuf; } -const AVCodec ff_dvbsub_encoder = { - .name = "dvbsub", - .long_name = NULL_IF_CONFIG_SMALL("DVB subtitles"), - .type = AVMEDIA_TYPE_SUBTITLE, - .id = AV_CODEC_ID_DVB_SUBTITLE, +const FFCodec ff_dvbsub_encoder = { + .p.name = "dvbsub", + .p.long_name = NULL_IF_CONFIG_SMALL("DVB subtitles"), + .p.type = AVMEDIA_TYPE_SUBTITLE, + .p.id = AV_CODEC_ID_DVB_SUBTITLE, .priv_data_size = sizeof(DVBSubtitleContext), - .encode_sub = dvbsub_encode, + FF_CODEC_ENCODE_SUB_CB(dvbsub_encode), }; diff --git a/libavcodec/dvdec.c b/libavcodec/dvdec.c index b72a67d01..d6f073058 100644 --- a/libavcodec/dvdec.c +++ b/libavcodec/dvdec.c @@ -43,6 +43,7 @@ #include "libavutil/thread.h" #include "avcodec.h" +#include "codec_internal.h" #include "dv.h" #include "dv_profile_internal.h" #include "dvdata.h" @@ -136,7 +137,7 @@ static RL_VLC_ELEM dv_rl_vlc[1664]; static void dv_init_static(void) { - VLC_TYPE vlc_buf[FF_ARRAY_ELEMS(dv_rl_vlc)][2] = { 0 }; + VLCElem vlc_buf[FF_ARRAY_ELEMS(dv_rl_vlc)] = { 0 }; VLC dv_vlc = { .table = vlc_buf, .table_allocated = FF_ARRAY_ELEMS(vlc_buf) }; uint16_t new_dv_vlc_bits[NB_DV_VLC * 2]; uint8_t new_dv_vlc_len[NB_DV_VLC * 2]; @@ -170,8 +171,8 @@ static void dv_init_static(void) av_assert1(dv_vlc.table_size == 1664); for (int i = 0; i < dv_vlc.table_size; i++) { - int code = dv_vlc.table[i][0]; - int len = dv_vlc.table[i][1]; + int code = dv_vlc.table[i].sym; + int len = dv_vlc.table[i].len; int level, run; if (len < 0) { // more bits needed @@ -606,13 +607,12 @@ retry: /* NOTE: exactly one frame must be given (120000 bytes for NTSC, * 144000 bytes for PAL - or twice those for 50Mbps) */ -static int dvvideo_decode_frame(AVCodecContext *avctx, void *data, +static int dvvideo_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt) { uint8_t *buf = avpkt->data; int buf_size = avpkt->size; DVVideoContext *s = avctx->priv_data; - ThreadFrame frame = { .f = data }; const uint8_t *vsc_pack; int apt, is16_9, ret; const AVDVProfile *sys; @@ -633,9 +633,9 @@ static int dvvideo_decode_frame(AVCodecContext *avctx, void *data, s->sys = sys; } - s->frame = frame.f; - frame.f->key_frame = 1; - frame.f->pict_type = AV_PICTURE_TYPE_I; + s->frame = frame; + frame->key_frame = 1; + frame->pict_type = AV_PICTURE_TYPE_I; avctx->pix_fmt = s->sys->pix_fmt; avctx->framerate = av_inv_q(s->sys->time_base); @@ -652,20 +652,20 @@ static int dvvideo_decode_frame(AVCodecContext *avctx, void *data, ff_set_sar(avctx, s->sys->sar[is16_9]); } - if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, frame, 0)) < 0) return ret; /* Determine the codec's field order from the packet */ if ( *vsc_pack == dv_video_control ) { if (avctx->height == 720) { - frame.f->interlaced_frame = 0; - frame.f->top_field_first = 0; + frame->interlaced_frame = 0; + frame->top_field_first = 0; } else if (avctx->height == 1080) { - frame.f->interlaced_frame = 1; - frame.f->top_field_first = (vsc_pack[3] & 0x40) == 0x40; + frame->interlaced_frame = 1; + frame->top_field_first = (vsc_pack[3] & 0x40) == 0x40; } else { - frame.f->interlaced_frame = (vsc_pack[3] & 0x10) == 0x10; - frame.f->top_field_first = !(vsc_pack[3] & 0x40); + frame->interlaced_frame = (vsc_pack[3] & 0x10) == 0x10; + frame->top_field_first = !(vsc_pack[3] & 0x40); } } @@ -681,15 +681,15 @@ static int dvvideo_decode_frame(AVCodecContext *avctx, void *data, return s->sys->frame_size; } -const AVCodec ff_dvvideo_decoder = { - .name = "dvvideo", - .long_name = NULL_IF_CONFIG_SMALL("DV (Digital Video)"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_DVVIDEO, +const FFCodec ff_dvvideo_decoder = { + .p.name = "dvvideo", + .p.long_name = NULL_IF_CONFIG_SMALL("DV (Digital Video)"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_DVVIDEO, .priv_data_size = sizeof(DVVideoContext), .init = dvvideo_decode_init, - .decode = dvvideo_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_SLICE_THREADS, - .max_lowres = 3, + FF_CODEC_DECODE_CB(dvvideo_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_SLICE_THREADS, + .p.max_lowres = 3, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/dvdsubdec.c b/libavcodec/dvdsubdec.c index 52259f073..97f366cc7 100644 --- a/libavcodec/dvdsubdec.c +++ b/libavcodec/dvdsubdec.c @@ -20,6 +20,7 @@ */ #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" @@ -42,9 +43,6 @@ typedef struct DVDSubContext int buf_size; int forced_subs_only; uint8_t used_color[256]; -#ifdef DEBUG - int sub_id; -#endif } DVDSubContext; static void yuv_a_to_rgba(const uint8_t *ycbcr, const uint8_t *alpha, uint32_t *rgba, int num_values) @@ -400,7 +398,7 @@ static int decode_dvd_subtitles(DVDSubContext *ctx, AVSubtitle *sub_header, } else { sub_header->rects[0]->nb_colors = 4; guess_palette(ctx, (uint32_t*)sub_header->rects[0]->data[1], - 0xffff00); + 0xffffff); } sub_header->rects[0]->x = x1; sub_header->rects[0]->y = y1; @@ -498,38 +496,6 @@ static int find_smallest_bounding_rectangle(DVDSubContext *ctx, AVSubtitle *s) return 1; } -#ifdef DEBUG -#define ALPHA_MIX(A,BACK,FORE) (((255-(A)) * (BACK) + (A) * (FORE)) / 255) -static void ppm_save(const char *filename, uint8_t *bitmap, int w, int h, - uint32_t *rgba_palette) -{ - int x, y, alpha; - uint32_t v; - int back[3] = {0, 255, 0}; /* green background */ - FILE *f; - - f = fopen(filename, "w"); - if (!f) { - perror(filename); - return; - } - fprintf(f, "P6\n" - "%d %d\n" - "%d\n", - w, h, 255); - for(y = 0; y < h; y++) { - for(x = 0; x < w; x++) { - v = rgba_palette[bitmap[y * w + x]]; - alpha = v >> 24; - putc(ALPHA_MIX(alpha, back[0], (v >> 16) & 0xff), f); - putc(ALPHA_MIX(alpha, back[1], (v >> 8) & 0xff), f); - putc(ALPHA_MIX(alpha, back[2], (v >> 0) & 0xff), f); - } - } - fclose(f); -} -#endif - static int append_to_cached_buf(AVCodecContext *avctx, const uint8_t *buf, int buf_size) { @@ -547,14 +513,12 @@ static int append_to_cached_buf(AVCodecContext *avctx, return 0; } -static int dvdsub_decode(AVCodecContext *avctx, - void *data, int *data_size, - AVPacket *avpkt) +static int dvdsub_decode(AVCodecContext *avctx, AVSubtitle *sub, + int *data_size, const AVPacket *avpkt) { DVDSubContext *ctx = avctx->priv_data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; - AVSubtitle *sub = data; int appended = 0; int is_menu; @@ -589,19 +553,6 @@ static int dvdsub_decode(AVCodecContext *avctx, if (ctx->forced_subs_only && !(sub->rects[0]->flags & AV_SUBTITLE_FLAG_FORCED)) goto no_subtitle; -#if defined(DEBUG) - { - char ppm_name[32]; - - snprintf(ppm_name, sizeof(ppm_name), "/tmp/%05d.ppm", ctx->sub_id++); - ff_dlog(NULL, "start=%d ms end =%d ms\n", - sub->start_display_time, - sub->end_display_time); - ppm_save(ppm_name, sub->rects[0]->data[0], - sub->rects[0]->w, sub->rects[0]->h, (uint32_t*) sub->rects[0]->data[1]); - } -#endif - ctx->buf_size = 0; *data_size = 1; return buf_size; @@ -618,7 +569,7 @@ static int parse_ifo_palette(DVDSubContext *ctx, char *p) const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP; ctx->has_palette = 0; - if ((ifo = fopen(p, "r")) == NULL) { + if ((ifo = avpriv_fopen_utf8(p, "r")) == NULL) { av_log(ctx, AV_LOG_WARNING, "Unable to open IFO file \"%s\": %s\n", p, av_err2str(AVERROR(errno))); return AVERROR_EOF; } @@ -754,15 +705,15 @@ static const AVClass dvdsub_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_dvdsub_decoder = { - .name = "dvdsub", - .long_name = NULL_IF_CONFIG_SMALL("DVD subtitles"), - .type = AVMEDIA_TYPE_SUBTITLE, - .id = AV_CODEC_ID_DVD_SUBTITLE, +const FFCodec ff_dvdsub_decoder = { + .p.name = "dvdsub", + .p.long_name = NULL_IF_CONFIG_SMALL("DVD subtitles"), + .p.type = AVMEDIA_TYPE_SUBTITLE, + .p.id = AV_CODEC_ID_DVD_SUBTITLE, .priv_data_size = sizeof(DVDSubContext), .init = dvdsub_init, - .decode = dvdsub_decode, + FF_CODEC_DECODE_SUB_CB(dvdsub_decode), .flush = dvdsub_flush, - .priv_class = &dvdsub_class, + .p.priv_class = &dvdsub_class, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/dvdsubenc.c b/libavcodec/dvdsubenc.c index ff4fbed39..d29db7d49 100644 --- a/libavcodec/dvdsubenc.c +++ b/libavcodec/dvdsubenc.c @@ -20,6 +20,7 @@ */ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" #include "libavutil/avassert.h" #include "libavutil/bprint.h" @@ -375,6 +376,12 @@ static int encode_dvd_subtitles(AVCodecContext *avctx, x2 = vrect.x + vrect.w - 1; y2 = vrect.y + vrect.h - 1; + if (x2 > avctx->width || y2 > avctx->height) { + av_log(avctx, AV_LOG_ERROR, "canvas_size(%d:%d) is too small(%d:%d) for render\n", + avctx->width, avctx->height, x2, y2); + ret = AVERROR(EINVAL);; + goto fail; + } *q++ = 0x05; // x1 x2 -> 6 nibbles *q++ = vrect.x >> 4; @@ -493,14 +500,14 @@ static const AVClass dvdsubenc_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_dvdsub_encoder = { - .name = "dvdsub", - .long_name = NULL_IF_CONFIG_SMALL("DVD subtitles"), - .type = AVMEDIA_TYPE_SUBTITLE, - .id = AV_CODEC_ID_DVD_SUBTITLE, +const FFCodec ff_dvdsub_encoder = { + .p.name = "dvdsub", + .p.long_name = NULL_IF_CONFIG_SMALL("DVD subtitles"), + .p.type = AVMEDIA_TYPE_SUBTITLE, + .p.id = AV_CODEC_ID_DVD_SUBTITLE, .init = dvdsub_init, - .encode_sub = dvdsub_encode, - .priv_class = &dvdsubenc_class, + FF_CODEC_ENCODE_SUB_CB(dvdsub_encode), + .p.priv_class = &dvdsubenc_class, .priv_data_size = sizeof(DVDSubtitleContext), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/dvenc.c b/libavcodec/dvenc.c index 045a29b83..2922829dc 100644 --- a/libavcodec/dvenc.c +++ b/libavcodec/dvenc.c @@ -36,12 +36,12 @@ #include "libavutil/thread.h" #include "avcodec.h" +#include "codec_internal.h" #include "dv.h" #include "dv_profile_internal.h" #include "dv_tablegen.h" #include "encode.h" #include "fdctdsp.h" -#include "internal.h" #include "mathops.h" #include "me_cmp.h" #include "pixblockdsp.h" @@ -1206,20 +1206,20 @@ static const AVClass dvvideo_encode_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_dvvideo_encoder = { - .name = "dvvideo", - .long_name = NULL_IF_CONFIG_SMALL("DV (Digital Video)"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_DVVIDEO, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | +const FFCodec ff_dvvideo_encoder = { + .p.name = "dvvideo", + .p.long_name = NULL_IF_CONFIG_SMALL("DV (Digital Video)"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_DVVIDEO, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_SLICE_THREADS, .priv_data_size = sizeof(DVVideoContext), .init = dvvideo_encode_init, - .encode2 = dvvideo_encode_frame, - .pix_fmts = (const enum AVPixelFormat[]) { + FF_CODEC_ENCODE_CB(dvvideo_encode_frame), + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, - .priv_class = &dvvideo_encode_class, + .p.priv_class = &dvvideo_encode_class, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/dxa.c b/libavcodec/dxa.c index 5615a7d1c..93a172474 100644 --- a/libavcodec/dxa.c +++ b/libavcodec/dxa.c @@ -31,6 +31,7 @@ #include "libavutil/intreadwrite.h" #include "bytestream.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include @@ -207,9 +208,9 @@ static int decode_13(AVCodecContext *avctx, DxaDecContext *c, uint8_t* dst, return 0; } -static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { - AVFrame *frame = data; DxaDecContext * const c = avctx->priv_data; uint8_t *outptr, *srcptr, *tmpptr; unsigned long dsize; @@ -360,15 +361,15 @@ static av_cold int decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_dxa_decoder = { - .name = "dxa", - .long_name = NULL_IF_CONFIG_SMALL("Feeble Files/ScummVM DXA"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_DXA, +const FFCodec ff_dxa_decoder = { + .p.name = "dxa", + .p.long_name = NULL_IF_CONFIG_SMALL("Feeble Files/ScummVM DXA"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_DXA, .priv_data_size = sizeof(DxaDecContext), .init = decode_init, .close = decode_end, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/dxtory.c b/libavcodec/dxtory.c index 914131e74..b7dfff475 100644 --- a/libavcodec/dxtory.c +++ b/libavcodec/dxtory.c @@ -28,8 +28,8 @@ #define BITSTREAM_READER_LE #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "get_bits.h" -#include "internal.h" #include "unary.h" #include "thread.h" @@ -93,7 +93,6 @@ static int dxtory_decode_v1_rgb(AVCodecContext *avctx, AVFrame *pic, const uint8_t *src, int src_size, int id, int bpp, uint32_t vflipped) { - ThreadFrame frame = { .f = pic }; int h; uint8_t *dst; int ret; @@ -104,7 +103,7 @@ static int dxtory_decode_v1_rgb(AVCodecContext *avctx, AVFrame *pic, } avctx->pix_fmt = id; - if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, pic, 0)) < 0) return ret; do_vflip(avctx, pic, vflipped); @@ -125,7 +124,6 @@ static int dxtory_decode_v1_410(AVCodecContext *avctx, AVFrame *pic, const uint8_t *src, int src_size, uint32_t vflipped) { - ThreadFrame frame = { .f = pic }; int h, w; uint8_t *Y1, *Y2, *Y3, *Y4, *U, *V; int height, width, hmargin, vmargin; @@ -138,7 +136,7 @@ static int dxtory_decode_v1_410(AVCodecContext *avctx, AVFrame *pic, } avctx->pix_fmt = AV_PIX_FMT_YUV410P; - if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, pic, 0)) < 0) return ret; do_vflip(avctx, pic, vflipped); @@ -221,7 +219,6 @@ static int dxtory_decode_v1_420(AVCodecContext *avctx, AVFrame *pic, const uint8_t *src, int src_size, uint32_t vflipped) { - ThreadFrame frame = { .f = pic }; int h, w; uint8_t *Y1, *Y2, *U, *V; int height, width, hmargin, vmargin; @@ -234,7 +231,7 @@ static int dxtory_decode_v1_420(AVCodecContext *avctx, AVFrame *pic, } avctx->pix_fmt = AV_PIX_FMT_YUV420P; - if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, pic, 0)) < 0) return ret; do_vflip(avctx, pic, vflipped); @@ -294,7 +291,6 @@ static int dxtory_decode_v1_444(AVCodecContext *avctx, AVFrame *pic, const uint8_t *src, int src_size, uint32_t vflipped) { - ThreadFrame frame = { .f = pic }; int h, w; uint8_t *Y, *U, *V; int ret; @@ -305,7 +301,7 @@ static int dxtory_decode_v1_444(AVCodecContext *avctx, AVFrame *pic, } avctx->pix_fmt = AV_PIX_FMT_YUV444P; - if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, pic, 0)) < 0) return ret; do_vflip(avctx, pic, vflipped); @@ -430,7 +426,6 @@ static int dxtory_decode_v2(AVCodecContext *avctx, AVFrame *pic, enum AVPixelFormat fmt, uint32_t vflipped) { - ThreadFrame frame = { .f = pic }; GetByteContext gb, gb_check; GetBitContext gb2; int nslices, slice, line = 0; @@ -457,7 +452,7 @@ static int dxtory_decode_v2(AVCodecContext *avctx, AVFrame *pic, return AVERROR_INVALIDDATA; avctx->pix_fmt = fmt; - if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, pic, 0)) < 0) return ret; do_vflip(avctx, pic, vflipped); @@ -789,10 +784,9 @@ static int dxtory_decode_v2_444(AVCodecContext *avctx, AVFrame *pic, AV_PIX_FMT_YUV444P, vflipped); } -static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *pic, + int *got_frame, AVPacket *avpkt) { - AVFrame *pic = data; const uint8_t *src = avpkt->data; uint32_t type; int vflipped, ret; @@ -876,11 +870,11 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, return avpkt->size; } -const AVCodec ff_dxtory_decoder = { - .name = "dxtory", - .long_name = NULL_IF_CONFIG_SMALL("Dxtory"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_DXTORY, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, +const FFCodec ff_dxtory_decoder = { + .p.name = "dxtory", + .p.long_name = NULL_IF_CONFIG_SMALL("Dxtory"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_DXTORY, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, }; diff --git a/libavcodec/dxv.c b/libavcodec/dxv.c index 5f1734791..d75f8b040 100644 --- a/libavcodec/dxv.c +++ b/libavcodec/dxv.c @@ -27,7 +27,7 @@ #include "mathops.h" #include "avcodec.h" #include "bytestream.h" -#include "internal.h" +#include "codec_internal.h" #include "lzf.h" #include "texturedsp.h" #include "thread.h" @@ -1038,11 +1038,10 @@ static int dxv_decompress_raw(AVCodecContext *avctx) return 0; } -static int dxv_decode(AVCodecContext *avctx, void *data, +static int dxv_decode(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt) { DXVContext *ctx = avctx->priv_data; - ThreadFrame tframe; GetByteContext *gbc = &ctx->gbc; int (*decompress_tex)(AVCodecContext *avctx); const char *msgcomp, *msgtext; @@ -1211,18 +1210,17 @@ static int dxv_decode(AVCodecContext *avctx, void *data, return AVERROR_INVALIDDATA; } - tframe.f = data; - ret = ff_thread_get_buffer(avctx, &tframe, 0); + ret = ff_thread_get_buffer(avctx, frame, 0); if (ret < 0) return ret; /* Now decompress the texture with the standard functions. */ avctx->execute2(avctx, decompress_texture_thread, - tframe.f, NULL, ctx->slice_count); + frame, NULL, ctx->slice_count); /* Frame is ready to be output. */ - tframe.f->pict_type = AV_PICTURE_TYPE_I; - tframe.f->key_frame = 1; + frame->pict_type = AV_PICTURE_TYPE_I; + frame->key_frame = 1; *got_frame = 1; return avpkt->size; @@ -1262,16 +1260,16 @@ static int dxv_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_dxv_decoder = { - .name = "dxv", - .long_name = NULL_IF_CONFIG_SMALL("Resolume DXV"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_DXV, +const FFCodec ff_dxv_decoder = { + .p.name = "dxv", + .p.long_name = NULL_IF_CONFIG_SMALL("Resolume DXV"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_DXV, .init = dxv_init, - .decode = dxv_decode, + FF_CODEC_DECODE_CB(dxv_decode), .close = dxv_close, .priv_data_size = sizeof(DXVContext), - .capabilities = AV_CODEC_CAP_DR1 | + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | diff --git a/libavcodec/dxva2_av1.c b/libavcodec/dxva2_av1.c index 8a912bf6c..228f72ba1 100644 --- a/libavcodec/dxva2_av1.c +++ b/libavcodec/dxva2_av1.c @@ -20,6 +20,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/avassert.h" #include "libavutil/pixdesc.h" @@ -72,7 +74,7 @@ static int fill_picture_parameters(const AVCodecContext *avctx, AVDXVAContext *c pp->max_width = seq->max_frame_width_minus_1 + 1; pp->max_height = seq->max_frame_height_minus_1 + 1; - pp->CurrPicTextureIndex = ff_dxva2_get_surface_index(avctx, ctx, h->cur_frame.tf.f); + pp->CurrPicTextureIndex = ff_dxva2_get_surface_index(avctx, ctx, h->cur_frame.f); pp->superres_denom = frame_header->use_superres ? frame_header->coded_denom + AV1_SUPERRES_DENOM_MIN : AV1_SUPERRES_NUM; pp->bitdepth = get_bit_depth_from_seq(seq); pp->seq_profile = seq->seq_profile; @@ -132,7 +134,7 @@ static int fill_picture_parameters(const AVCodecContext *avctx, AVDXVAContext *c memset(pp->RefFrameMapTextureIndex, 0xFF, sizeof(pp->RefFrameMapTextureIndex)); for (i = 0; i < AV1_REFS_PER_FRAME; i++) { int8_t ref_idx = frame_header->ref_frame_idx[i]; - AVFrame *ref_frame = h->ref[ref_idx].tf.f; + AVFrame *ref_frame = h->ref[ref_idx].f; pp->frame_refs[i].width = ref_frame->width; pp->frame_refs[i].height = ref_frame->height; @@ -146,7 +148,7 @@ static int fill_picture_parameters(const AVCodecContext *avctx, AVDXVAContext *c } } for (i = 0; i < AV1_NUM_REF_FRAMES; i++) { - AVFrame *ref_frame = h->ref[i].tf.f; + AVFrame *ref_frame = h->ref[i].f; if (ref_frame->buf[0]) pp->RefFrameMapTextureIndex[i] = ff_dxva2_get_surface_index(avctx, ctx, ref_frame); } @@ -436,7 +438,7 @@ static int dxva2_av1_end_frame(AVCodecContext *avctx) if (ctx_pic->bitstream_size <= 0) return -1; - ret = ff_dxva2_common_end_frame(avctx, h->cur_frame.tf.f, + ret = ff_dxva2_common_end_frame(avctx, h->cur_frame.f, &ctx_pic->pp, sizeof(ctx_pic->pp), NULL, 0, commit_bitstream_and_slice_buffer); diff --git a/libavcodec/dxva2_h264.c b/libavcodec/dxva2_h264.c index 5b23b28f1..6300b1418 100644 --- a/libavcodec/dxva2_h264.c +++ b/libavcodec/dxva2_h264.c @@ -20,6 +20,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/avassert.h" #include "dxva2_internal.h" diff --git a/libavcodec/dxva2_hevc.c b/libavcodec/dxva2_hevc.c index dbb701fb1..6b239d991 100644 --- a/libavcodec/dxva2_hevc.c +++ b/libavcodec/dxva2_hevc.c @@ -20,6 +20,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/avassert.h" #include "dxva2_internal.h" @@ -182,7 +184,7 @@ static void fill_picture_parameters(const AVCodecContext *avctx, AVDXVAContext * const HEVCFrame *frame = NULL; \ while (!frame && j < rpl->nb_refs) \ frame = rpl->ref[j++]; \ - if (frame) \ + if (frame && frame->flags & (HEVC_FRAME_FLAG_LONG_REF | HEVC_FRAME_FLAG_SHORT_REF)) \ pp->ref_list[i] = get_refpic_index(pp, ff_dxva2_get_surface_index(avctx, ctx, frame->frame)); \ else \ pp->ref_list[i] = 0xff; \ diff --git a/libavcodec/dxva2_mpeg2.c b/libavcodec/dxva2_mpeg2.c index 8cc21bf19..1989c588d 100644 --- a/libavcodec/dxva2_mpeg2.c +++ b/libavcodec/dxva2_mpeg2.c @@ -20,11 +20,13 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/log.h" #include "dxva2_internal.h" #include "mpegutils.h" -#include "mpegvideo.h" +#include "mpegvideodec.h" #define MAX_SLICES 1024 struct dxva2_picture_context { diff --git a/libavcodec/dxva2_vc1.c b/libavcodec/dxva2_vc1.c index f08ac8b5a..cf660a50d 100644 --- a/libavcodec/dxva2_vc1.c +++ b/libavcodec/dxva2_vc1.c @@ -20,8 +20,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "dxva2_internal.h" #include "mpegutils.h" +#include "mpegvideodec.h" #include "vc1.h" #include "vc1data.h" diff --git a/libavcodec/dxva2_vp9.c b/libavcodec/dxva2_vp9.c index eaeab3af7..dbe6c08ad 100644 --- a/libavcodec/dxva2_vp9.c +++ b/libavcodec/dxva2_vp9.c @@ -20,6 +20,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/avassert.h" #include "libavutil/pixdesc.h" diff --git a/libavcodec/dynamic_hdr_vivid.c b/libavcodec/dynamic_hdr_vivid.c new file mode 100644 index 000000000..d689669de --- /dev/null +++ b/libavcodec/dynamic_hdr_vivid.c @@ -0,0 +1,139 @@ +/* + * 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 "dynamic_hdr_vivid.h" +#include "get_bits.h" + +static const int32_t maxrgb_den = 4095; +static const int32_t color_saturation_gain_den = 128; +static const int32_t maximum_luminance_den = 4095; +static const int32_t base_param_m_p_den = 16383; +static const int32_t base_param_m_m_den = 10; +static const int32_t base_param_m_a_den = 1023; +static const int32_t base_param_m_b_den = 1023; +static const int32_t base_param_m_n_den = 10; +static const int32_t base_param_Delta_den = 127; + +int ff_parse_itu_t_t35_to_dynamic_hdr_vivid(AVDynamicHDRVivid *s, const uint8_t *data, + int size) +{ + GetBitContext gbc, *gb = &gbc; + int ret; + + if (!s) + return AVERROR(ENOMEM); + + ret = init_get_bits8(gb, data, size); + if (ret < 0) + return ret; + + if (get_bits_left(gb) < 8) + return AVERROR_INVALIDDATA; + + s->system_start_code = get_bits(gb, 8); + if (s->system_start_code == 0x01) { + s->num_windows = 1; + + if (get_bits_left(gb) < 12 * 4 * s->num_windows) + return AVERROR_INVALIDDATA; + for (int w = 0; w < s->num_windows; w++) { + AVHDRVividColorTransformParams *params = &s->params[w]; + + params->minimum_maxrgb = (AVRational){get_bits(gb, 12), maxrgb_den}; + params->average_maxrgb = (AVRational){get_bits(gb, 12), maxrgb_den}; + params->variance_maxrgb = (AVRational){get_bits(gb, 12), maxrgb_den}; + params->maximum_maxrgb = (AVRational){get_bits(gb, 12), maxrgb_den}; + } + + if (get_bits_left(gb) < 2 * s->num_windows) + return AVERROR_INVALIDDATA; + for (int w = 0; w < s->num_windows; w++) { + AVHDRVividColorTransformParams *params = &s->params[w]; + + params->tone_mapping_mode_flag = get_bits(gb, 1); + if (params->tone_mapping_mode_flag) { + if (get_bits_left(gb) < 1 ) + return AVERROR_INVALIDDATA; + params->tone_mapping_param_num = get_bits(gb, 1) + 1; + for (int i = 0; i < params->tone_mapping_param_num; i++) { + AVHDRVividColorToneMappingParams *tm_params = ¶ms->tm_params[i]; + + if (get_bits_left(gb) < 13) + return AVERROR_INVALIDDATA; + tm_params->targeted_system_display_maximum_luminance = (AVRational){get_bits(gb, 12), maximum_luminance_den}; + tm_params->base_enable_flag = get_bits(gb, 1); + if (tm_params->base_enable_flag) { + if (get_bits_left(gb) < (14 + 6 + 10 + 10 + 6 + 8 + 10)) + return AVERROR_INVALIDDATA; + tm_params->base_param_m_p = (AVRational){get_bits(gb, 14), base_param_m_p_den}; + tm_params->base_param_m_m = (AVRational){get_bits(gb, 6), base_param_m_m_den}; + tm_params->base_param_m_a = (AVRational){get_bits(gb, 10), base_param_m_a_den}; + tm_params->base_param_m_b = (AVRational){get_bits(gb, 10), base_param_m_b_den}; + tm_params->base_param_m_n = (AVRational){get_bits(gb, 6), base_param_m_n_den}; + tm_params->base_param_k1 = get_bits(gb, 2); + tm_params->base_param_k2 = get_bits(gb, 2); + tm_params->base_param_k3 = get_bits(gb, 4); + tm_params->base_param_Delta_enable_mode = get_bits(gb, 3); + if (tm_params->base_param_Delta_enable_mode == 2 || tm_params->base_param_Delta_enable_mode == 6) + tm_params->base_param_Delta = (AVRational){get_bits(gb, 7) * -1, base_param_Delta_den}; + else + tm_params->base_param_Delta = (AVRational){get_bits(gb, 7), base_param_Delta_den}; + + if (get_bits_left(gb) < 1) + return AVERROR_INVALIDDATA; + tm_params->three_Spline_enable_flag = get_bits(gb, 1); + if (tm_params->three_Spline_enable_flag) { + if (get_bits_left(gb) < 1 + tm_params->three_Spline_num * (2 + 12 + 28 + 1)) + return AVERROR_INVALIDDATA; + tm_params->three_Spline_num = get_bits(gb, 1) + 1; + for (int j = 0; j < tm_params->three_Spline_num; j++) { + tm_params->three_Spline_TH_mode = get_bits(gb, 2); + if (tm_params->three_Spline_TH_mode == 0 || tm_params->three_Spline_TH_mode == 2) { + if (get_bits_left(gb) < 8) + return AVERROR_INVALIDDATA; + tm_params->three_Spline_TH_enable_MB = (AVRational){get_bits(gb, 8), 255}; + } + tm_params->three_Spline_TH_enable = (AVRational){get_bits(gb, 12), 4095}; + tm_params->three_Spline_TH_Delta1 = (AVRational){get_bits(gb, 10), 1023}; + tm_params->three_Spline_TH_Delta2 = (AVRational){get_bits(gb, 10), 1023}; + tm_params->three_Spline_enable_Strength = (AVRational){get_bits(gb, 8), 255}; + } + } else { + tm_params->three_Spline_num = 1; + tm_params->three_Spline_TH_mode = 0; + } + + } + } + } + + params->color_saturation_mapping_flag = get_bits(gb, 1); + if (params->color_saturation_mapping_flag) { + if (get_bits_left(gb) < 3 + params->color_saturation_num * 8) + return AVERROR_INVALIDDATA; + + params->color_saturation_num = get_bits(gb, 3); + for (int i = 0; i < params->color_saturation_num; i++) { + params->color_saturation_gain[i] = (AVRational){get_bits(gb, 8), color_saturation_gain_den}; + } + } + } + } + + return 0; +} diff --git a/libavcodec/dynamic_hdr_vivid.h b/libavcodec/dynamic_hdr_vivid.h new file mode 100644 index 000000000..d521b3d26 --- /dev/null +++ b/libavcodec/dynamic_hdr_vivid.h @@ -0,0 +1,35 @@ +/* + * 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_DYNAMIC_HDR_VIVID_H +#define AVCODEC_DYNAMIC_HDR_VIVID_H + +#include "libavutil/hdr_dynamic_vivid_metadata.h" + +/** + * Parse the user data registered ITU-T T.35 to AVbuffer (AVDynamicHDRVivid). + * @param s A pointer containing the decoded AVDynamicHDRVivid structure. + * @param data The byte array containing the raw ITU-T T.35 data. + * @param size Size of the data array in bytes. + * + * @return 0 if succeed. Otherwise, returns the appropriate AVERROR. + */ +int ff_parse_itu_t_t35_to_dynamic_hdr_vivid(AVDynamicHDRVivid *s, const uint8_t *data, + int size); + +#endif /* AVCODEC_DYNAMIC_HDR_VIVID_H */ diff --git a/libavcodec/eac3_core_bsf.c b/libavcodec/eac3_core_bsf.c index 49c3389ee..1c714b18f 100644 --- a/libavcodec/eac3_core_bsf.c +++ b/libavcodec/eac3_core_bsf.c @@ -79,8 +79,8 @@ 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, +const FFBitStreamFilter ff_eac3_core_bsf = { + .p.name = "eac3_core", + .p.codec_ids = codec_ids, + .filter = eac3_core_filter, }; diff --git a/libavcodec/eac3_data.c b/libavcodec/eac3_data.c index 2ef0e2053..d556d35b8 100644 --- a/libavcodec/eac3_data.c +++ b/libavcodec/eac3_data.c @@ -27,7 +27,7 @@ #include #include "eac3_data.h" -#include "ac3.h" +#include "ac3defs.h" const uint8_t ff_eac3_bits_vs_hebap[20] = { 0, 2, 3, 4, 5, 7, 8, 9, 3, 4, diff --git a/libavcodec/eac3dec.c b/libavcodec/eac3dec.c index 3a5c7989b..d360b0269 100644 --- a/libavcodec/eac3dec.c +++ b/libavcodec/eac3dec.c @@ -39,7 +39,6 @@ #include "avcodec.h" -#include "internal.h" #include "aac_ac3_parser.h" #include "ac3.h" #include "ac3dec.h" diff --git a/libavcodec/eac3enc.c b/libavcodec/eac3enc.c index 96ef00ea4..79611cee0 100644 --- a/libavcodec/eac3enc.c +++ b/libavcodec/eac3enc.c @@ -28,6 +28,7 @@ #include "libavutil/attributes.h" #include "ac3enc.h" +#include "codec_internal.h" #include "eac3enc.h" #include "eac3_data.h" @@ -248,21 +249,26 @@ void ff_eac3_output_frame_header(AC3EncodeContext *s) } -const AVCodec ff_eac3_encoder = { - .name = "eac3", - .long_name = NULL_IF_CONFIG_SMALL("ATSC A/52 E-AC-3"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_EAC3, - .capabilities = AV_CODEC_CAP_DR1, +FF_DISABLE_DEPRECATION_WARNINGS +const FFCodec ff_eac3_encoder = { + .p.name = "eac3", + .p.long_name = NULL_IF_CONFIG_SMALL("ATSC A/52 E-AC-3"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_EAC3, + .p.capabilities = AV_CODEC_CAP_DR1, .priv_data_size = sizeof(AC3EncodeContext), .init = ff_ac3_float_encode_init, - .encode2 = ff_ac3_float_encode_frame, + FF_CODEC_ENCODE_CB(ff_ac3_float_encode_frame), .close = ff_ac3_encode_close, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP, + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, - .priv_class = &eac3enc_class, - .supported_samplerates = ff_ac3_sample_rate_tab, - .channel_layouts = ff_ac3_channel_layouts, + .p.priv_class = &eac3enc_class, + .p.supported_samplerates = ff_ac3_sample_rate_tab, +#if FF_API_OLD_CHANNEL_LAYOUT + .p.channel_layouts = ff_ac3_channel_layouts, +#endif + .p.ch_layouts = ff_ac3_ch_layouts, .defaults = ff_ac3_enc_defaults, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; +FF_ENABLE_DEPRECATION_WARNINGS diff --git a/libavcodec/eacmv.c b/libavcodec/eacmv.c index 572eb8e1b..0a13a74bb 100644 --- a/libavcodec/eacmv.c +++ b/libavcodec/eacmv.c @@ -32,6 +32,7 @@ #include "libavutil/intreadwrite.h" #include "libavutil/imgutils.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" typedef struct CmvContext { @@ -168,15 +169,13 @@ static int cmv_process_header(CmvContext *s, const uint8_t *buf, const uint8_t * #define EA_PREAMBLE_SIZE 8 #define MVIh_TAG MKTAG('M', 'V', 'I', 'h') -static int cmv_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int cmv_decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; CmvContext *s = avctx->priv_data; const uint8_t *buf_end = buf + buf_size; - AVFrame *frame = data; int ret; if (buf_end - buf < EA_PREAMBLE_SIZE) @@ -230,15 +229,15 @@ static av_cold int cmv_decode_end(AVCodecContext *avctx){ return 0; } -const AVCodec ff_eacmv_decoder = { - .name = "eacmv", - .long_name = NULL_IF_CONFIG_SMALL("Electronic Arts CMV video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_CMV, +const FFCodec ff_eacmv_decoder = { + .p.name = "eacmv", + .p.long_name = NULL_IF_CONFIG_SMALL("Electronic Arts CMV video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_CMV, .priv_data_size = sizeof(CmvContext), .init = cmv_decode_init, .close = cmv_decode_end, - .decode = cmv_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(cmv_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/eamad.c b/libavcodec/eamad.c index 896f94073..337a9c144 100644 --- a/libavcodec/eamad.c +++ b/libavcodec/eamad.c @@ -34,6 +34,7 @@ #include "blockdsp.h" #include "bytestream.h" #include "bswapdsp.h" +#include "codec_internal.h" #include "get_bits.h" #include "aandcttab.h" #include "eaidct.h" @@ -246,14 +247,12 @@ static void calc_quant_matrix(MadContext *s, int qscale) s->quant_matrix[i] = (ff_inv_aanscales[i]*ff_mpeg1_default_intra_matrix[i]*qscale + 32) >> 10; } -static int decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; MadContext *s = avctx->priv_data; - AVFrame *frame = data; GetByteContext gb; int width, height; int chunk_type; @@ -341,15 +340,15 @@ static av_cold int decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_eamad_decoder = { - .name = "eamad", - .long_name = NULL_IF_CONFIG_SMALL("Electronic Arts Madcow Video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MAD, +const FFCodec ff_eamad_decoder = { + .p.name = "eamad", + .p.long_name = NULL_IF_CONFIG_SMALL("Electronic Arts Madcow Video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MAD, .priv_data_size = sizeof(MadContext), .init = decode_init, .close = decode_end, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/eatgq.c b/libavcodec/eatgq.c index 2658f0cf8..2e9d2fe13 100644 --- a/libavcodec/eatgq.c +++ b/libavcodec/eatgq.c @@ -35,6 +35,7 @@ #include "aandcttab.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "eaidct.h" #include "get_bits.h" #include "idctdsp.h" @@ -200,14 +201,12 @@ static void tgq_calculate_qtable(TgqContext *s, int quant) ff_inv_aanscales[j * 8 + i]) >> (14 - 4); } -static int tgq_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int tgq_decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; TgqContext *s = avctx->priv_data; - AVFrame *frame = data; int x, y, ret; int big_endian; @@ -247,14 +246,14 @@ static int tgq_decode_frame(AVCodecContext *avctx, return avpkt->size; } -const AVCodec ff_eatgq_decoder = { - .name = "eatgq", - .long_name = NULL_IF_CONFIG_SMALL("Electronic Arts TGQ video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_TGQ, +const FFCodec ff_eatgq_decoder = { + .p.name = "eatgq", + .p.long_name = NULL_IF_CONFIG_SMALL("Electronic Arts TGQ video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_TGQ, .priv_data_size = sizeof(TgqContext), .init = tgq_decode_init, - .decode = tgq_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(tgq_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/eatgv.c b/libavcodec/eatgv.c index 20a90a090..23cf7300c 100644 --- a/libavcodec/eatgv.c +++ b/libavcodec/eatgv.c @@ -34,6 +34,7 @@ #define BITSTREAM_READER_LE #include "avcodec.h" #include "get_bits.h" +#include "codec_internal.h" #include "internal.h" #define EA_PREAMBLE_SIZE 8 @@ -261,15 +262,13 @@ static int tgv_decode_inter(TgvContext *s, AVFrame *frame, return 0; } -static int tgv_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int tgv_decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; TgvContext *s = avctx->priv_data; const uint8_t *buf_end = buf + buf_size; - AVFrame *frame = data; int chunk_type, ret; if (buf_end - buf < EA_PREAMBLE_SIZE) @@ -359,15 +358,15 @@ static av_cold int tgv_decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_eatgv_decoder = { - .name = "eatgv", - .long_name = NULL_IF_CONFIG_SMALL("Electronic Arts TGV video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_TGV, +const FFCodec ff_eatgv_decoder = { + .p.name = "eatgv", + .p.long_name = NULL_IF_CONFIG_SMALL("Electronic Arts TGV video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_TGV, .priv_data_size = sizeof(TgvContext), .init = tgv_decode_init, .close = tgv_decode_end, - .decode = tgv_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(tgv_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/eatqi.c b/libavcodec/eatqi.c index 9beab58a8..305ea4ba2 100644 --- a/libavcodec/eatqi.c +++ b/libavcodec/eatqi.c @@ -31,12 +31,14 @@ #include "avcodec.h" #include "blockdsp.h" #include "bswapdsp.h" +#include "codec_internal.h" #include "get_bits.h" #include "aandcttab.h" #include "eaidct.h" #include "idctdsp.h" #include "internal.h" -#include "mpeg12.h" +#include "mpeg12data.h" +#include "mpeg12dec.h" typedef struct TqiContext { AVCodecContext *avctx; @@ -122,15 +124,13 @@ static void tqi_calculate_qtable(TqiContext *t, int quant) t->intra_matrix[i] = (ff_inv_aanscales[i] * ff_mpeg1_default_intra_matrix[i] * qscale + 32) >> 14; } -static int tqi_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int tqi_decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; const uint8_t *buf_end = buf+buf_size; TqiContext *t = avctx->priv_data; - AVFrame *frame = data; int ret, w, h; if (buf_size < 12) @@ -181,15 +181,15 @@ static av_cold int tqi_decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_eatqi_decoder = { - .name = "eatqi", - .long_name = NULL_IF_CONFIG_SMALL("Electronic Arts TQI Video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_TQI, +const FFCodec ff_eatqi_decoder = { + .p.name = "eatqi", + .p.long_name = NULL_IF_CONFIG_SMALL("Electronic Arts TQI Video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_TQI, .priv_data_size = sizeof(TqiContext), .init = tqi_decode_init, .close = tqi_decode_end, - .decode = tqi_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(tqi_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/elsdec.c b/libavcodec/elsdec.c index ecb575706..9ae932cdf 100644 --- a/libavcodec/elsdec.c +++ b/libavcodec/elsdec.c @@ -25,11 +25,14 @@ * Entropy Logarithmic-Scale binary arithmetic decoder */ -#include +#include #include +#include -#include "libavutil/common.h" +#include "libavutil/error.h" #include "libavutil/intreadwrite.h" +#include "libavutil/macros.h" +#include "libavutil/mem.h" #include "elsdec.h" diff --git a/libavcodec/encode.c b/libavcodec/encode.c index 618be0573..1f39ab1a2 100644 --- a/libavcodec/encode.c +++ b/libavcodec/encode.c @@ -27,6 +27,7 @@ #include "libavutil/samplefmt.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" #include "frame_thread_encoder.h" #include "internal.h" @@ -114,9 +115,10 @@ static int pad_last_frame(AVCodecContext *s, AVFrame *frame, const AVFrame *src) int ret; frame->format = src->format; - frame->channel_layout = src->channel_layout; - frame->channels = src->channels; frame->nb_samples = s->frame_size; + ret = av_channel_layout_copy(&frame->ch_layout, &s->ch_layout); + if (ret < 0) + goto fail; ret = av_frame_get_buffer(frame, 0); if (ret < 0) goto fail; @@ -126,11 +128,12 @@ static int pad_last_frame(AVCodecContext *s, AVFrame *frame, const AVFrame *src) goto fail; if ((ret = av_samples_copy(frame->extended_data, src->extended_data, 0, 0, - src->nb_samples, s->channels, s->sample_fmt)) < 0) + src->nb_samples, s->ch_layout.nb_channels, + s->sample_fmt)) < 0) goto fail; if ((ret = av_samples_set_silence(frame->extended_data, src->nb_samples, frame->nb_samples - src->nb_samples, - s->channels, s->sample_fmt)) < 0) + s->ch_layout.nb_channels, s->sample_fmt)) < 0) goto fail; return 0; @@ -149,7 +152,7 @@ int avcodec_encode_subtitle(AVCodecContext *avctx, uint8_t *buf, int buf_size, return -1; } - ret = avctx->codec->encode_sub(avctx, buf, buf_size, sub); + ret = ffcodec(avctx->codec)->cb.encode_sub(avctx, buf, buf_size, sub); avctx->frame_number++; return ret; } @@ -172,8 +175,8 @@ int ff_encode_get_frame(AVCodecContext *avctx, AVFrame *frame) static int encode_simple_internal(AVCodecContext *avctx, AVPacket *avpkt) { AVCodecInternal *avci = avctx->internal; - EncodeSimpleContext *es = &avci->es; - AVFrame *frame = es->in_frame; + AVFrame *frame = avci->in_frame; + const FFCodec *const codec = ffcodec(avctx->codec); int got_packet; int ret; @@ -198,7 +201,7 @@ static int encode_simple_internal(AVCodecContext *avctx, AVPacket *avpkt) got_packet = 0; - av_assert0(avctx->codec->encode2); + av_assert0(codec->cb_type == FF_CODEC_CB_TYPE_ENCODE); if (CONFIG_FRAME_THREAD_ENCODER && avci->frame_thread_encoder && (avctx->active_thread_type & FF_THREAD_FRAME)) @@ -208,7 +211,7 @@ static int encode_simple_internal(AVCodecContext *avctx, AVPacket *avpkt) * no sense to use the properties of the current frame anyway). */ ret = ff_thread_video_encode_frame(avctx, avpkt, frame, &got_packet); else { - ret = avctx->codec->encode2(avctx, avpkt, frame, &got_packet); + ret = codec->cb.encode(avctx, avpkt, frame, &got_packet); if (avctx->codec->type == AVMEDIA_TYPE_VIDEO && !ret && got_packet && !(avctx->codec->capabilities & AV_CODEC_CAP_DELAY)) avpkt->pts = avpkt->dts = frame->pts; @@ -288,8 +291,8 @@ static int encode_receive_packet_internal(AVCodecContext *avctx, AVPacket *avpkt return AVERROR(EINVAL); } - if (avctx->codec->receive_packet) { - ret = avctx->codec->receive_packet(avctx, avpkt); + if (ffcodec(avctx->codec)->cb_type == FF_CODEC_CB_TYPE_RECEIVE_PACKET) { + ret = ffcodec(avctx->codec)->cb.receive_packet(avctx, avpkt); if (ret < 0) av_packet_unref(avpkt); else @@ -336,6 +339,7 @@ static int encode_send_frame_internal(AVCodecContext *avctx, const AVFrame *src) return ret; avctx->internal->last_audio_frame = 1; + return 0; } else if (src->nb_samples > avctx->frame_size) { av_log(avctx, AV_LOG_ERROR, "nb_samples (%d) != frame_size (%d)\n", src->nb_samples, avctx->frame_size); return AVERROR(EINVAL); @@ -343,11 +347,9 @@ static int encode_send_frame_internal(AVCodecContext *avctx, const AVFrame *src) } } - if (!dst->data[0]) { - ret = av_frame_ref(dst, src); - if (ret < 0) - return ret; - } + ret = av_frame_ref(dst, src); + if (ret < 0) + return ret; return 0; } @@ -406,34 +408,11 @@ int attribute_align_arg avcodec_receive_packet(AVCodecContext *avctx, AVPacket * return 0; } -int ff_encode_preinit(AVCodecContext *avctx) +static int encode_preinit_video(AVCodecContext *avctx) { + const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(avctx->pix_fmt); int i; - if (avctx->time_base.num <= 0 || avctx->time_base.den <= 0) { - av_log(avctx, AV_LOG_ERROR, "The encoder timebase is not set.\n"); - return AVERROR(EINVAL); - } - - if (avctx->codec->sample_fmts) { - for (i = 0; avctx->codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++) { - if (avctx->sample_fmt == avctx->codec->sample_fmts[i]) - break; - if (avctx->channels == 1 && - av_get_planar_sample_fmt(avctx->sample_fmt) == - av_get_planar_sample_fmt(avctx->codec->sample_fmts[i])) { - avctx->sample_fmt = avctx->codec->sample_fmts[i]; - break; - } - } - if (avctx->codec->sample_fmts[i] == AV_SAMPLE_FMT_NONE) { - char buf[128]; - snprintf(buf, sizeof(buf), "%d", avctx->sample_fmt); - av_log(avctx, AV_LOG_ERROR, "Specified sample format %s is invalid or not supported\n", - (char *)av_x_if_null(av_get_sample_fmt_name(avctx->sample_fmt), buf)); - return AVERROR(EINVAL); - } - } if (avctx->codec->pix_fmts) { for (i = 0; avctx->codec->pix_fmts[i] != AV_PIX_FMT_NONE; i++) if (avctx->pix_fmt == avctx->codec->pix_fmts[i]) @@ -452,74 +431,17 @@ int ff_encode_preinit(AVCodecContext *avctx) avctx->codec->pix_fmts[i] == AV_PIX_FMT_YUVJ444P) avctx->color_range = AVCOL_RANGE_JPEG; } - if (avctx->codec->supported_samplerates) { - for (i = 0; avctx->codec->supported_samplerates[i] != 0; i++) - if (avctx->sample_rate == avctx->codec->supported_samplerates[i]) - break; - if (avctx->codec->supported_samplerates[i] == 0) { - av_log(avctx, AV_LOG_ERROR, "Specified sample rate %d is not supported\n", - avctx->sample_rate); - return AVERROR(EINVAL); - } - } - if (avctx->sample_rate < 0) { - av_log(avctx, AV_LOG_ERROR, "Specified sample rate %d is not supported\n", - avctx->sample_rate); - return AVERROR(EINVAL); - } - if (avctx->codec->channel_layouts) { - if (!avctx->channel_layout) { - av_log(avctx, AV_LOG_WARNING, "Channel layout not specified\n"); - } else { - for (i = 0; avctx->codec->channel_layouts[i] != 0; i++) - if (avctx->channel_layout == avctx->codec->channel_layouts[i]) - break; - if (avctx->codec->channel_layouts[i] == 0) { - char buf[512]; - av_get_channel_layout_string(buf, sizeof(buf), -1, avctx->channel_layout); - av_log(avctx, AV_LOG_ERROR, "Specified channel layout '%s' is not supported\n", buf); - return AVERROR(EINVAL); - } - } - } - if (avctx->channel_layout && avctx->channels) { - int channels = av_get_channel_layout_nb_channels(avctx->channel_layout); - if (channels != avctx->channels) { - char buf[512]; - av_get_channel_layout_string(buf, sizeof(buf), -1, avctx->channel_layout); - av_log(avctx, AV_LOG_ERROR, - "Channel layout '%s' with %d channels does not match number of specified channels %d\n", - buf, channels, avctx->channels); - return AVERROR(EINVAL); - } - } else if (avctx->channel_layout) { - avctx->channels = av_get_channel_layout_nb_channels(avctx->channel_layout); - } - if (avctx->channels < 0) { - av_log(avctx, AV_LOG_ERROR, "Specified number of channels %d is not supported\n", - avctx->channels); - return AVERROR(EINVAL); - } - if(avctx->codec_type == AVMEDIA_TYPE_VIDEO) { - const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(avctx->pix_fmt); - if ( avctx->bits_per_raw_sample < 0 - || (avctx->bits_per_raw_sample > 8 && pixdesc->comp[0].depth <= 8)) { - av_log(avctx, AV_LOG_WARNING, "Specified bit depth %d not possible with the specified pixel formats depth %d\n", - avctx->bits_per_raw_sample, pixdesc->comp[0].depth); - avctx->bits_per_raw_sample = pixdesc->comp[0].depth; - } - if (avctx->width <= 0 || avctx->height <= 0) { - av_log(avctx, AV_LOG_ERROR, "dimensions not set\n"); - return AVERROR(EINVAL); - } - } - if ( (avctx->codec_type == AVMEDIA_TYPE_VIDEO || avctx->codec_type == AVMEDIA_TYPE_AUDIO) - && avctx->bit_rate>0 && avctx->bit_rate<1000) { - av_log(avctx, AV_LOG_WARNING, "Bitrate %"PRId64" is extremely low, maybe you mean %"PRId64"k\n", avctx->bit_rate, avctx->bit_rate); - } - if (!avctx->rc_initial_buffer_occupancy) - avctx->rc_initial_buffer_occupancy = avctx->rc_buffer_size * 3LL / 4; + if ( avctx->bits_per_raw_sample < 0 + || (avctx->bits_per_raw_sample > 8 && pixdesc->comp[0].depth <= 8)) { + av_log(avctx, AV_LOG_WARNING, "Specified bit depth %d not possible with the specified pixel formats depth %d\n", + avctx->bits_per_raw_sample, pixdesc->comp[0].depth); + avctx->bits_per_raw_sample = pixdesc->comp[0].depth; + } + if (avctx->width <= 0 || avctx->height <= 0) { + av_log(avctx, AV_LOG_ERROR, "dimensions not set\n"); + return AVERROR(EINVAL); + } if (avctx->ticks_per_frame && avctx->time_base.num && avctx->ticks_per_frame > INT_MAX / avctx->time_base.num) { @@ -549,8 +471,162 @@ int ff_encode_preinit(AVCodecContext *avctx) } avctx->sw_pix_fmt = frames_ctx->sw_format; } + + return 0; +} + +static int encode_preinit_audio(AVCodecContext *avctx) +{ + int i; + + if (avctx->codec->sample_fmts) { + for (i = 0; avctx->codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++) { + if (avctx->sample_fmt == avctx->codec->sample_fmts[i]) + break; + if (avctx->ch_layout.nb_channels == 1 && + av_get_planar_sample_fmt(avctx->sample_fmt) == + av_get_planar_sample_fmt(avctx->codec->sample_fmts[i])) { + avctx->sample_fmt = avctx->codec->sample_fmts[i]; + break; + } + } + if (avctx->codec->sample_fmts[i] == AV_SAMPLE_FMT_NONE) { + char buf[128]; + snprintf(buf, sizeof(buf), "%d", avctx->sample_fmt); + av_log(avctx, AV_LOG_ERROR, "Specified sample format %s is invalid or not supported\n", + (char *)av_x_if_null(av_get_sample_fmt_name(avctx->sample_fmt), buf)); + return AVERROR(EINVAL); + } + } + if (avctx->codec->supported_samplerates) { + for (i = 0; avctx->codec->supported_samplerates[i] != 0; i++) + if (avctx->sample_rate == avctx->codec->supported_samplerates[i]) + break; + if (avctx->codec->supported_samplerates[i] == 0) { + av_log(avctx, AV_LOG_ERROR, "Specified sample rate %d is not supported\n", + avctx->sample_rate); + return AVERROR(EINVAL); + } + } + if (avctx->sample_rate < 0) { + av_log(avctx, AV_LOG_ERROR, "Specified sample rate %d is not supported\n", + avctx->sample_rate); + return AVERROR(EINVAL); + } + if (avctx->codec->ch_layouts) { + if (!av_channel_layout_check(&avctx->ch_layout)) { + av_log(avctx, AV_LOG_WARNING, "Channel layout not specified correctly\n"); + return AVERROR(EINVAL); + } + + for (i = 0; avctx->codec->ch_layouts[i].nb_channels; i++) { + if (!av_channel_layout_compare(&avctx->ch_layout, &avctx->codec->ch_layouts[i])) + break; + } + if (!avctx->codec->ch_layouts[i].nb_channels) { + char buf[512]; + int ret = av_channel_layout_describe(&avctx->ch_layout, buf, sizeof(buf)); + if (ret > 0) + av_log(avctx, AV_LOG_ERROR, "Specified channel layout '%s' is not supported\n", buf); + return AVERROR(EINVAL); + } + } +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->channel_layout && avctx->channels) { + int channels = av_get_channel_layout_nb_channels(avctx->channel_layout); + if (channels != avctx->channels) { + char buf[512]; + av_get_channel_layout_string(buf, sizeof(buf), -1, avctx->channel_layout); + av_log(avctx, AV_LOG_ERROR, + "Channel layout '%s' with %d channels does not match number of specified channels %d\n", + buf, channels, avctx->channels); + return AVERROR(EINVAL); + } + } else if (avctx->channel_layout) { + avctx->channels = av_get_channel_layout_nb_channels(avctx->channel_layout); + } + if (avctx->channels < 0) { + av_log(avctx, AV_LOG_ERROR, "Specified number of channels %d is not supported\n", + avctx->channels); + return AVERROR(EINVAL); + } +FF_ENABLE_DEPRECATION_WARNINGS +#endif + + if (!avctx->bits_per_raw_sample) + avctx->bits_per_raw_sample = 8 * av_get_bytes_per_sample(avctx->sample_fmt); + + return 0; +} + +int ff_encode_preinit(AVCodecContext *avctx) +{ + AVCodecInternal *avci = avctx->internal; + int ret = 0; + + if (avctx->time_base.num <= 0 || avctx->time_base.den <= 0) { + av_log(avctx, AV_LOG_ERROR, "The encoder timebase is not set.\n"); + return AVERROR(EINVAL); + } + + switch (avctx->codec_type) { + case AVMEDIA_TYPE_VIDEO: ret = encode_preinit_video(avctx); break; + case AVMEDIA_TYPE_AUDIO: ret = encode_preinit_audio(avctx); break; + } + if (ret < 0) + return ret; + + if ( (avctx->codec_type == AVMEDIA_TYPE_VIDEO || avctx->codec_type == AVMEDIA_TYPE_AUDIO) + && avctx->bit_rate>0 && avctx->bit_rate<1000) { + av_log(avctx, AV_LOG_WARNING, "Bitrate %"PRId64" is extremely low, maybe you mean %"PRId64"k\n", avctx->bit_rate, avctx->bit_rate); + } + + if (!avctx->rc_initial_buffer_occupancy) + avctx->rc_initial_buffer_occupancy = avctx->rc_buffer_size * 3LL / 4; + if (avctx->codec_descriptor->props & AV_CODEC_PROP_INTRA_ONLY) avctx->internal->intra_only_flag = AV_PKT_FLAG_KEY; + + if (ffcodec(avctx->codec)->cb_type == FF_CODEC_CB_TYPE_ENCODE) { + avci->in_frame = av_frame_alloc(); + if (!avci->in_frame) + return AVERROR(ENOMEM); + } + + return 0; +} + +int ff_encode_alloc_frame(AVCodecContext *avctx, AVFrame *frame) +{ + int ret; + + switch (avctx->codec->type) { + case AVMEDIA_TYPE_VIDEO: + frame->format = avctx->pix_fmt; + if (frame->width <= 0 || frame->height <= 0) { + frame->width = FFMAX(avctx->width, avctx->coded_width); + frame->height = FFMAX(avctx->height, avctx->coded_height); + } + + break; + case AVMEDIA_TYPE_AUDIO: + frame->sample_rate = avctx->sample_rate; + frame->format = avctx->sample_fmt; + if (!frame->ch_layout.nb_channels) { + ret = av_channel_layout_copy(&frame->ch_layout, &avctx->ch_layout); + if (ret < 0) + return ret; + } + break; + } + + ret = avcodec_default_get_buffer2(avctx, frame, 0); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); + av_frame_unref(frame); + return ret; + } return 0; } diff --git a/libavcodec/encode.h b/libavcodec/encode.h index c9cec0cc8..b2536bf0f 100644 --- a/libavcodec/encode.h +++ b/libavcodec/encode.h @@ -44,10 +44,15 @@ int ff_encode_get_frame(AVCodecContext *avctx, AVFrame *frame); */ int ff_get_encode_buffer(AVCodecContext *avctx, AVPacket *avpkt, int64_t size, int flags); +/** + * Allocate buffers for a frame. Encoder equivalent to ff_get_buffer(). + */ +int ff_encode_alloc_frame(AVCodecContext *avctx, AVFrame *frame); + /** * Check AVPacket size and allocate data. * - * Encoders supporting AVCodec.encode2() can use this as a convenience to + * Encoders supporting FFCodec.encode2() can use this as a convenience to * obtain a big enough buffer for the encoded bitstream. * * @param avctx the AVCodecContext of the encoder @@ -61,7 +66,7 @@ int ff_alloc_packet(AVCodecContext *avctx, AVPacket *avpkt, int64_t size); /* * Perform encoder initialization and validation. - * Called when opening the encoder, before the AVCodec.init() call. + * Called when opening the encoder, before the FFCodec.init() call. */ int ff_encode_preinit(AVCodecContext *avctx); diff --git a/libavcodec/error_resilience.c b/libavcodec/error_resilience.c index 91cd8a444..f957c68d2 100644 --- a/libavcodec/error_resilience.c +++ b/libavcodec/error_resilience.c @@ -34,7 +34,7 @@ #include "mpegutils.h" #include "mpegvideo.h" #include "rectangle.h" -#include "thread.h" +#include "threadframe.h" /** * @param stride the number of MVs to get to the next row @@ -736,12 +736,6 @@ static int is_intra_more_likely(ERContext *s) if (undamaged_count < 5) return 0; // almost all MBs damaged -> use temporal prediction - // prevent dsp.sad() check, that requires access to the image - if (CONFIG_XVMC && - s->avctx->hwaccel && s->avctx->hwaccel->decode_mb && - s->cur_pic.f->pict_type == AV_PICTURE_TYPE_I) - return 1; - skip_amount = FFMAX(undamaged_count / 50, 1); // check only up to 50 MBs is_intra_likely = 0; @@ -772,12 +766,12 @@ static int is_intra_more_likely(ERContext *s) } else { ff_thread_await_progress(s->last_pic.tf, mb_y, 0); } - is_intra_likely += s->mecc.sad[0](NULL, last_mb_ptr, mb_ptr, - linesize[0], 16); + is_intra_likely += s->sad(NULL, last_mb_ptr, mb_ptr, + linesize[0], 16); // FIXME need await_progress() here - is_intra_likely -= s->mecc.sad[0](NULL, last_mb_ptr, - last_mb_ptr + linesize[0] * 16, - linesize[0], 16); + is_intra_likely -= s->sad(NULL, last_mb_ptr, + last_mb_ptr + linesize[0] * 16, + linesize[0], 16); } else { if (IS_INTRA(s->cur_pic.mb_type[mb_xy])) is_intra_likely++; @@ -796,7 +790,9 @@ void ff_er_frame_start(ERContext *s) return; if (!s->mecc_inited) { - ff_me_cmp_init(&s->mecc, s->avctx); + MECmpContext mecc; + ff_me_cmp_init(&mecc, s->avctx); + s->sad = mecc.sad[0]; s->mecc_inited = 1; } @@ -1229,9 +1225,6 @@ void ff_er_frame_end(ERContext *s) } else guess_mv(s); - /* the filters below manipulate raw image, skip them */ - if (CONFIG_XVMC && s->avctx->hwaccel && s->avctx->hwaccel->decode_mb) - goto ec_clean; /* 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++) { @@ -1336,7 +1329,6 @@ void ff_er_frame_end(ERContext *s) } } -ec_clean: /* clean a few tables */ for (i = 0; i < s->mb_num; i++) { const int mb_xy = s->mb_index2xy[i]; diff --git a/libavcodec/error_resilience.h b/libavcodec/error_resilience.h index 664a76565..53e5cf262 100644 --- a/libavcodec/error_resilience.h +++ b/libavcodec/error_resilience.h @@ -24,7 +24,7 @@ #include "avcodec.h" #include "me_cmp.h" -#include "thread.h" +#include "threadframe.h" ///< current MB is the first after a resync marker #define VP_START 1 @@ -52,7 +52,8 @@ typedef struct ERPicture { typedef struct ERContext { AVCodecContext *avctx; - MECmpContext mecc; + + me_cmp_func sad; int mecc_inited; int *mb_index2xy; @@ -81,7 +82,6 @@ typedef struct ERContext { uint16_t pb_time; int quarter_sample; int partitioned_frame; - int ref_count; void (*decode_mb)(void *opaque, int ref, int mv_dir, int mv_type, int (*mv)[2][4][2], diff --git a/libavcodec/escape124.c b/libavcodec/escape124.c index ab5c8d224..2fdffff13 100644 --- a/libavcodec/escape124.c +++ b/libavcodec/escape124.c @@ -21,6 +21,7 @@ #define BITSTREAM_READER_LE #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" @@ -195,13 +196,11 @@ static const uint16_t mask_matrix[] = {0x1, 0x2, 0x10, 0x20, 0x100, 0x200, 0x1000, 0x2000, 0x400, 0x800, 0x4000, 0x8000}; -static int escape124_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int escape124_decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { int buf_size = avpkt->size; Escape124Context *s = avctx->priv_data; - AVFrame *frame = data; GetBitContext gb; unsigned frame_flags, frame_size; @@ -376,15 +375,15 @@ static int escape124_decode_frame(AVCodecContext *avctx, } -const AVCodec ff_escape124_decoder = { - .name = "escape124", - .long_name = NULL_IF_CONFIG_SMALL("Escape 124"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_ESCAPE124, +const FFCodec ff_escape124_decoder = { + .p.name = "escape124", + .p.long_name = NULL_IF_CONFIG_SMALL("Escape 124"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_ESCAPE124, .priv_data_size = sizeof(Escape124Context), .init = escape124_decode_init, .close = escape124_decode_close, - .decode = escape124_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(escape124_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/escape130.c b/libavcodec/escape130.c index ee1eafe86..cd6dd7690 100644 --- a/libavcodec/escape130.c +++ b/libavcodec/escape130.c @@ -24,6 +24,7 @@ #define BITSTREAM_READER_LE #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" @@ -186,12 +187,11 @@ static int decode_skip_count(GetBitContext* gb) return -1; } -static int escape130_decode_frame(AVCodecContext *avctx, void *data, +static int escape130_decode_frame(AVCodecContext *avctx, AVFrame *pic, int *got_frame, AVPacket *avpkt) { int buf_size = avpkt->size; Escape130Context *s = avctx->priv_data; - AVFrame *pic = data; GetBitContext gb; int ret; @@ -345,15 +345,15 @@ static int escape130_decode_frame(AVCodecContext *avctx, void *data, return buf_size; } -const AVCodec ff_escape130_decoder = { - .name = "escape130", - .long_name = NULL_IF_CONFIG_SMALL("Escape 130"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_ESCAPE130, +const FFCodec ff_escape130_decoder = { + .p.name = "escape130", + .p.long_name = NULL_IF_CONFIG_SMALL("Escape 130"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_ESCAPE130, .priv_data_size = sizeof(Escape130Context), .init = escape130_decode_init, .close = escape130_decode_close, - .decode = escape130_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(escape130_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/evrcdec.c b/libavcodec/evrcdec.c index 59fcb14c5..a6475199c 100644 --- a/libavcodec/evrcdec.c +++ b/libavcodec/evrcdec.c @@ -29,6 +29,7 @@ #include "libavutil/mathematics.h" #include "libavutil/opt.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "get_bits.h" #include "evrcdata.h" @@ -235,8 +236,8 @@ static av_cold int evrc_decode_init(AVCodecContext *avctx) int i, n, idx = 0; float denom = 2.0 / (2.0 * 8.0 + 1.0); - avctx->channels = 1; - avctx->channel_layout = AV_CH_LAYOUT_MONO; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; avctx->sample_fmt = AV_SAMPLE_FMT_FLT; for (i = 0; i < FILTER_ORDER; i++) { @@ -740,11 +741,10 @@ static void frame_erasure(EVRCContext *e, float *samples) } } -static int evrc_decode_frame(AVCodecContext *avctx, void *data, +static int evrc_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; - AVFrame *frame = data; EVRCContext *e = avctx->priv_data; int buf_size = avpkt->size; float ilspf[FILTER_ORDER], ilpc[FILTER_ORDER], idelay[NB_SUBFRAMES]; @@ -929,15 +929,15 @@ static const AVClass evrcdec_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_evrc_decoder = { - .name = "evrc", - .long_name = NULL_IF_CONFIG_SMALL("EVRC (Enhanced Variable Rate Codec)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_EVRC, +const FFCodec ff_evrc_decoder = { + .p.name = "evrc", + .p.long_name = NULL_IF_CONFIG_SMALL("EVRC (Enhanced Variable Rate Codec)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_EVRC, .init = evrc_decode_init, - .decode = evrc_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + FF_CODEC_DECODE_CB(evrc_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .priv_data_size = sizeof(EVRCContext), - .priv_class = &evrcdec_class, + .p.priv_class = &evrcdec_class, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/exif.c b/libavcodec/exif.c index 0b656fd09..959d114d0 100644 --- a/libavcodec/exif.c +++ b/libavcodec/exif.c @@ -26,7 +26,135 @@ */ #include "exif.h" +#include "tiff_common.h" +#define EXIF_TAG_NAME_LENGTH 32 + +struct exif_tag { + char name[EXIF_TAG_NAME_LENGTH]; + uint16_t id; +}; + +static const struct exif_tag tag_list[] = { // JEITA CP-3451 EXIF specification: + {"GPSVersionID", 0x00}, // <- Table 12 GPS Attribute Information + {"GPSLatitudeRef", 0x01}, + {"GPSLatitude", 0x02}, + {"GPSLongitudeRef", 0x03}, + {"GPSLongitude", 0x04}, + {"GPSAltitudeRef", 0x05}, + {"GPSAltitude", 0x06}, + {"GPSTimeStamp", 0x07}, + {"GPSSatellites", 0x08}, + {"GPSStatus", 0x09}, + {"GPSMeasureMode", 0x0A}, + {"GPSDOP", 0x0B}, + {"GPSSpeedRef", 0x0C}, + {"GPSSpeed", 0x0D}, + {"GPSTrackRef", 0x0E}, + {"GPSTrack", 0x0F}, + {"GPSImgDirectionRef", 0x10}, + {"GPSImgDirection", 0x11}, + {"GPSMapDatum", 0x12}, + {"GPSDestLatitudeRef", 0x13}, + {"GPSDestLatitude", 0x14}, + {"GPSDestLongitudeRef", 0x15}, + {"GPSDestLongitude", 0x16}, + {"GPSDestBearingRef", 0x17}, + {"GPSDestBearing", 0x18}, + {"GPSDestDistanceRef", 0x19}, + {"GPSDestDistance", 0x1A}, + {"GPSProcessingMethod", 0x1B}, + {"GPSAreaInformation", 0x1C}, + {"GPSDateStamp", 0x1D}, + {"GPSDifferential", 0x1E}, + {"ImageWidth", 0x100}, // <- Table 3 TIFF Rev. 6.0 Attribute Information Used in Exif + {"ImageLength", 0x101}, + {"BitsPerSample", 0x102}, + {"Compression", 0x103}, + {"PhotometricInterpretation", 0x106}, + {"Orientation", 0x112}, + {"SamplesPerPixel", 0x115}, + {"PlanarConfiguration", 0x11C}, + {"YCbCrSubSampling", 0x212}, + {"YCbCrPositioning", 0x213}, + {"XResolution", 0x11A}, + {"YResolution", 0x11B}, + {"ResolutionUnit", 0x128}, + {"StripOffsets", 0x111}, + {"RowsPerStrip", 0x116}, + {"StripByteCounts", 0x117}, + {"JPEGInterchangeFormat", 0x201}, + {"JPEGInterchangeFormatLength",0x202}, + {"TransferFunction", 0x12D}, + {"WhitePoint", 0x13E}, + {"PrimaryChromaticities", 0x13F}, + {"YCbCrCoefficients", 0x211}, + {"ReferenceBlackWhite", 0x214}, + {"DateTime", 0x132}, + {"ImageDescription", 0x10E}, + {"Make", 0x10F}, + {"Model", 0x110}, + {"Software", 0x131}, + {"Artist", 0x13B}, + {"Copyright", 0x8298}, + {"ExifVersion", 0x9000}, // <- Table 4 Exif IFD Attribute Information (1) + {"FlashpixVersion", 0xA000}, + {"ColorSpace", 0xA001}, + {"ComponentsConfiguration", 0x9101}, + {"CompressedBitsPerPixel", 0x9102}, + {"PixelXDimension", 0xA002}, + {"PixelYDimension", 0xA003}, + {"MakerNote", 0x927C}, + {"UserComment", 0x9286}, + {"RelatedSoundFile", 0xA004}, + {"DateTimeOriginal", 0x9003}, + {"DateTimeDigitized", 0x9004}, + {"SubSecTime", 0x9290}, + {"SubSecTimeOriginal", 0x9291}, + {"SubSecTimeDigitized", 0x9292}, + {"ImageUniqueID", 0xA420}, + {"ExposureTime", 0x829A}, // <- Table 5 Exif IFD Attribute Information (2) + {"FNumber", 0x829D}, + {"ExposureProgram", 0x8822}, + {"SpectralSensitivity", 0x8824}, + {"ISOSpeedRatings", 0x8827}, + {"OECF", 0x8828}, + {"ShutterSpeedValue", 0x9201}, + {"ApertureValue", 0x9202}, + {"BrightnessValue", 0x9203}, + {"ExposureBiasValue", 0x9204}, + {"MaxApertureValue", 0x9205}, + {"SubjectDistance", 0x9206}, + {"MeteringMode", 0x9207}, + {"LightSource", 0x9208}, + {"Flash", 0x9209}, + {"FocalLength", 0x920A}, + {"SubjectArea", 0x9214}, + {"FlashEnergy", 0xA20B}, + {"SpatialFrequencyResponse", 0xA20C}, + {"FocalPlaneXResolution", 0xA20E}, + {"FocalPlaneYResolution", 0xA20F}, + {"FocalPlaneResolutionUnit", 0xA210}, + {"SubjectLocation", 0xA214}, + {"ExposureIndex", 0xA215}, + {"SensingMethod", 0xA217}, + {"FileSource", 0xA300}, + {"SceneType", 0xA301}, + {"CFAPattern", 0xA302}, + {"CustomRendered", 0xA401}, + {"ExposureMode", 0xA402}, + {"WhiteBalance", 0xA403}, + {"DigitalZoomRatio", 0xA404}, + {"FocalLengthIn35mmFilm", 0xA405}, + {"SceneCaptureType", 0xA406}, + {"GainControl", 0xA407}, + {"Contrast", 0xA408}, + {"Saturation", 0xA409}, + {"Sharpness", 0xA40A}, + {"DeviceSettingDescription", 0xA40B}, + {"SubjectDistanceRange", 0xA40C} +// {"InteroperabilityIndex", 0x1}, // <- Table 13 Interoperability IFD Attribute Information +}; static const char *exif_get_tag_name(uint16_t id) { diff --git a/libavcodec/exif.h b/libavcodec/exif.h index 4db84a1c2..f70d21391 100644 --- a/libavcodec/exif.h +++ b/libavcodec/exif.h @@ -30,137 +30,7 @@ #include #include "libavutil/dict.h" -#include "tiff.h" - -#define EXIF_MAX_IFD_RECURSION 2 -#define EXIF_TAG_NAME_LENGTH 32 - -struct exif_tag { - char name[EXIF_TAG_NAME_LENGTH]; - uint16_t id; -}; - -static const struct exif_tag tag_list[] = { // JEITA CP-3451 EXIF specification: - {"GPSVersionID", 0x00}, // <- Table 12 GPS Attribute Information - {"GPSLatitudeRef", 0x01}, - {"GPSLatitude", 0x02}, - {"GPSLongitudeRef", 0x03}, - {"GPSLongitude", 0x04}, - {"GPSAltitudeRef", 0x05}, - {"GPSAltitude", 0x06}, - {"GPSTimeStamp", 0x07}, - {"GPSSatellites", 0x08}, - {"GPSStatus", 0x09}, - {"GPSMeasureMode", 0x0A}, - {"GPSDOP", 0x0B}, - {"GPSSpeedRef", 0x0C}, - {"GPSSpeed", 0x0D}, - {"GPSTrackRef", 0x0E}, - {"GPSTrack", 0x0F}, - {"GPSImgDirectionRef", 0x10}, - {"GPSImgDirection", 0x11}, - {"GPSMapDatum", 0x12}, - {"GPSDestLatitudeRef", 0x13}, - {"GPSDestLatitude", 0x14}, - {"GPSDestLongitudeRef", 0x15}, - {"GPSDestLongitude", 0x16}, - {"GPSDestBearingRef", 0x17}, - {"GPSDestBearing", 0x18}, - {"GPSDestDistanceRef", 0x19}, - {"GPSDestDistance", 0x1A}, - {"GPSProcessingMethod", 0x1B}, - {"GPSAreaInformation", 0x1C}, - {"GPSDateStamp", 0x1D}, - {"GPSDifferential", 0x1E}, - {"ImageWidth", 0x100}, // <- Table 3 TIFF Rev. 6.0 Attribute Information Used in Exif - {"ImageLength", 0x101}, - {"BitsPerSample", 0x102}, - {"Compression", 0x103}, - {"PhotometricInterpretation", 0x106}, - {"Orientation", 0x112}, - {"SamplesPerPixel", 0x115}, - {"PlanarConfiguration", 0x11C}, - {"YCbCrSubSampling", 0x212}, - {"YCbCrPositioning", 0x213}, - {"XResolution", 0x11A}, - {"YResolution", 0x11B}, - {"ResolutionUnit", 0x128}, - {"StripOffsets", 0x111}, - {"RowsPerStrip", 0x116}, - {"StripByteCounts", 0x117}, - {"JPEGInterchangeFormat", 0x201}, - {"JPEGInterchangeFormatLength",0x202}, - {"TransferFunction", 0x12D}, - {"WhitePoint", 0x13E}, - {"PrimaryChromaticities", 0x13F}, - {"YCbCrCoefficients", 0x211}, - {"ReferenceBlackWhite", 0x214}, - {"DateTime", 0x132}, - {"ImageDescription", 0x10E}, - {"Make", 0x10F}, - {"Model", 0x110}, - {"Software", 0x131}, - {"Artist", 0x13B}, - {"Copyright", 0x8298}, - {"ExifVersion", 0x9000}, // <- Table 4 Exif IFD Attribute Information (1) - {"FlashpixVersion", 0xA000}, - {"ColorSpace", 0xA001}, - {"ComponentsConfiguration", 0x9101}, - {"CompressedBitsPerPixel", 0x9102}, - {"PixelXDimension", 0xA002}, - {"PixelYDimension", 0xA003}, - {"MakerNote", 0x927C}, - {"UserComment", 0x9286}, - {"RelatedSoundFile", 0xA004}, - {"DateTimeOriginal", 0x9003}, - {"DateTimeDigitized", 0x9004}, - {"SubSecTime", 0x9290}, - {"SubSecTimeOriginal", 0x9291}, - {"SubSecTimeDigitized", 0x9292}, - {"ImageUniqueID", 0xA420}, - {"ExposureTime", 0x829A}, // <- Table 5 Exif IFD Attribute Information (2) - {"FNumber", 0x829D}, - {"ExposureProgram", 0x8822}, - {"SpectralSensitivity", 0x8824}, - {"ISOSpeedRatings", 0x8827}, - {"OECF", 0x8828}, - {"ShutterSpeedValue", 0x9201}, - {"ApertureValue", 0x9202}, - {"BrightnessValue", 0x9203}, - {"ExposureBiasValue", 0x9204}, - {"MaxApertureValue", 0x9205}, - {"SubjectDistance", 0x9206}, - {"MeteringMode", 0x9207}, - {"LightSource", 0x9208}, - {"Flash", 0x9209}, - {"FocalLength", 0x920A}, - {"SubjectArea", 0x9214}, - {"FlashEnergy", 0xA20B}, - {"SpatialFrequencyResponse", 0xA20C}, - {"FocalPlaneXResolution", 0xA20E}, - {"FocalPlaneYResolution", 0xA20F}, - {"FocalPlaneResolutionUnit", 0xA210}, - {"SubjectLocation", 0xA214}, - {"ExposureIndex", 0xA215}, - {"SensingMethod", 0xA217}, - {"FileSource", 0xA300}, - {"SceneType", 0xA301}, - {"CFAPattern", 0xA302}, - {"CustomRendered", 0xA401}, - {"ExposureMode", 0xA402}, - {"WhiteBalance", 0xA403}, - {"DigitalZoomRatio", 0xA404}, - {"FocalLengthIn35mmFilm", 0xA405}, - {"SceneCaptureType", 0xA406}, - {"GainControl", 0xA407}, - {"Contrast", 0xA408}, - {"Saturation", 0xA409}, - {"Sharpness", 0xA40A}, - {"DeviceSettingDescription", 0xA40B}, - {"SubjectDistanceRange", 0xA40C} -// {"InteroperabilityIndex", 0x1}, // <- Table 13 Interoperability IFD Attribute Information -// {"", 0x0} -}; +#include "bytestream.h" /** Recursively decodes all IFD's and * adds included TAGS into the metadata dictionary. */ diff --git a/libavcodec/exr.c b/libavcodec/exr.c index ded9d8500..c25bae8cd 100644 --- a/libavcodec/exr.c +++ b/libavcodec/exr.c @@ -49,6 +49,7 @@ #include "bswapdsp.h" #endif +#include "codec_internal.h" #include "exrdsp.h" #include "get_bits.h" #include "internal.h" @@ -1240,7 +1241,8 @@ static int decode_block(AVCodecContext *avctx, void *tdata, td->ysize = FFMIN(s->tile_attr.ySize, s->ydelta - tile_y * s->tile_attr.ySize); td->xsize = FFMIN(s->tile_attr.xSize, s->xdelta - tile_x * s->tile_attr.xSize); - if (td->xsize * (uint64_t)s->current_channel_offset > INT_MAX) + if (td->xsize * (uint64_t)s->current_channel_offset > INT_MAX || + av_image_check_size2(td->xsize, td->ysize, s->avctx->max_pixels, AV_PIX_FMT_NONE, 0, s->avctx) < 0) return AVERROR_INVALIDDATA; td->channel_line_size = td->xsize * s->current_channel_offset;/* uncompress size of one line */ @@ -1264,7 +1266,8 @@ static int decode_block(AVCodecContext *avctx, void *tdata, td->ysize = FFMIN(s->scan_lines_per_block, s->ymax - line + 1); /* s->ydelta - line ?? */ td->xsize = s->xdelta; - if (td->xsize * (uint64_t)s->current_channel_offset > INT_MAX) + if (td->xsize * (uint64_t)s->current_channel_offset > INT_MAX || + av_image_check_size2(td->xsize, td->ysize, s->avctx->max_pixels, AV_PIX_FMT_NONE, 0, s->avctx) < 0) return AVERROR_INVALIDDATA; td->channel_line_size = td->xsize * s->current_channel_offset;/* uncompress size of one line */ @@ -2022,13 +2025,11 @@ fail: return ret; } -static int decode_frame(AVCodecContext *avctx, void *data, +static int decode_frame(AVCodecContext *avctx, AVFrame *picture, int *got_frame, AVPacket *avpkt) { EXRContext *s = avctx->priv_data; GetByteContext *gb = &s->gb; - ThreadFrame frame = { .f = data }; - AVFrame *picture = data; uint8_t *ptr; int i, y, ret, ymax; @@ -2149,7 +2150,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, s->scan_lines_per_block; } - if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, picture, 0)) < 0) return ret; if (bytestream2_get_bytes_left(gb)/8 < nb_blocks) @@ -2341,16 +2342,17 @@ static const AVClass exr_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_exr_decoder = { - .name = "exr", - .long_name = NULL_IF_CONFIG_SMALL("OpenEXR image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_EXR, +const FFCodec ff_exr_decoder = { + .p.name = "exr", + .p.long_name = NULL_IF_CONFIG_SMALL("OpenEXR image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_EXR, .priv_data_size = sizeof(EXRContext), .init = decode_init, .close = decode_end, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_SLICE_THREADS, - .priv_class = &exr_class, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + .p.priv_class = &exr_class, }; diff --git a/libavcodec/exrdsp.c b/libavcodec/exrdsp.c index 42dbf1f54..8259da484 100644 --- a/libavcodec/exrdsp.c +++ b/libavcodec/exrdsp.c @@ -51,6 +51,7 @@ av_cold void ff_exrdsp_init(ExrDSPContext *c) c->reorder_pixels = reorder_pixels_scalar; c->predictor = predictor_scalar; - if (ARCH_X86) - ff_exrdsp_init_x86(c); +#if ARCH_X86 + ff_exrdsp_init_x86(c); +#endif } diff --git a/libavcodec/exrdsp.h b/libavcodec/exrdsp.h index 2c4dc3af8..aba3d3cf5 100644 --- a/libavcodec/exrdsp.h +++ b/libavcodec/exrdsp.h @@ -19,8 +19,8 @@ #ifndef AVCODEC_EXRDSP_H #define AVCODEC_EXRDSP_H +#include #include -#include "libavutil/common.h" typedef struct ExrDSPContext { void (*reorder_pixels)(uint8_t *dst, const uint8_t *src, ptrdiff_t size); diff --git a/libavcodec/exrenc.c b/libavcodec/exrenc.c index 8bb2ea838..8eb138ea0 100644 --- a/libavcodec/exrenc.c +++ b/libavcodec/exrenc.c @@ -33,8 +33,8 @@ #include "libavutil/pixdesc.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "float2half.h" enum ExrCompr { @@ -54,8 +54,10 @@ enum ExrPixelType { static const char abgr_chlist[4] = { 'A', 'B', 'G', 'R' }; static const char bgr_chlist[4] = { 'B', 'G', 'R', 'A' }; +static const char y_chlist[4] = { 'Y' }; static const uint8_t gbra_order[4] = { 3, 1, 0, 2 }; static const uint8_t gbr_order[4] = { 1, 0, 2, 0 }; +static const uint8_t y_order[4] = { 0 }; typedef struct EXRScanlineData { uint8_t *compressed_data; @@ -89,7 +91,7 @@ typedef struct EXRContext { uint8_t shifttable[512]; } EXRContext; -static int encode_init(AVCodecContext *avctx) +static av_cold int encode_init(AVCodecContext *avctx) { EXRContext *s = avctx->priv_data; @@ -106,6 +108,11 @@ static int encode_init(AVCodecContext *avctx) s->ch_names = abgr_chlist; s->ch_order = gbra_order; break; + case AV_PIX_FMT_GRAYF32: + s->planes = 1; + s->ch_names = y_chlist; + s->ch_order = y_order; + break; default: av_assert0(0); } @@ -132,7 +139,7 @@ static int encode_init(AVCodecContext *avctx) return 0; } -static int encode_close(AVCodecContext *avctx) +static av_cold int encode_close(AVCodecContext *avctx) { EXRContext *s = avctx->priv_data; @@ -534,18 +541,19 @@ static const AVClass exr_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_exr_encoder = { - .name = "exr", - .long_name = NULL_IF_CONFIG_SMALL("OpenEXR image"), +const FFCodec ff_exr_encoder = { + .p.name = "exr", + .p.long_name = NULL_IF_CONFIG_SMALL("OpenEXR image"), .priv_data_size = sizeof(EXRContext), - .priv_class = &exr_class, - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_EXR, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .p.priv_class = &exr_class, + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_EXR, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, .init = encode_init, - .encode2 = encode_frame, + FF_CODEC_ENCODE_CB(encode_frame), .close = encode_close, - .pix_fmts = (const enum AVPixelFormat[]) { + .p.pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_GRAYF32, AV_PIX_FMT_GBRPF32, AV_PIX_FMT_GBRAPF32, AV_PIX_FMT_NONE }, diff --git a/libavcodec/extract_extradata_bsf.c b/libavcodec/extract_extradata_bsf.c index dbcb8508b..329b1a617 100644 --- a/libavcodec/extract_extradata_bsf.c +++ b/libavcodec/extract_extradata_bsf.c @@ -18,8 +18,6 @@ #include -#include "libavutil/common.h" -#include "libavutil/intreadwrite.h" #include "libavutil/log.h" #include "libavutil/opt.h" @@ -31,6 +29,7 @@ #include "h2645_parse.h" #include "h264.h" #include "hevc.h" +#include "startcode.h" #include "vc1_common.h" typedef struct ExtractExtradataContext { @@ -423,11 +422,11 @@ static const AVClass extract_extradata_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVBitStreamFilter ff_extract_extradata_bsf = { - .name = "extract_extradata", - .codec_ids = codec_ids, +const FFBitStreamFilter ff_extract_extradata_bsf = { + .p.name = "extract_extradata", + .p.codec_ids = codec_ids, + .p.priv_class = &extract_extradata_class, .priv_data_size = sizeof(ExtractExtradataContext), - .priv_class = &extract_extradata_class, .init = extract_extradata_init, .filter = extract_extradata_filter, .close = extract_extradata_close, diff --git a/libavcodec/fastaudio.c b/libavcodec/fastaudio.c index a07c5e60a..46fffaf8b 100644 --- a/libavcodec/fastaudio.c +++ b/libavcodec/fastaudio.c @@ -25,6 +25,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" #include "mathops.h" @@ -78,7 +79,7 @@ static av_cold int fastaudio_init(AVCodecContext *avctx) for (int i = 0; i < 8; i++) s->table[7][i] = i * 0.34f / 3.f - 0.2f; - s->ch = av_calloc(avctx->channels, sizeof(*s->ch)); + s->ch = av_calloc(avctx->ch_layout.nb_channels, sizeof(*s->ch)); if (!s->ch) return AVERROR(ENOMEM); @@ -104,16 +105,15 @@ static void set_sample(int i, int j, int v, float *result, int *pads, float valu result[i * 64 + pads[i] + j * 3] = value * (2 * v - 7); } -static int fastaudio_decode(AVCodecContext *avctx, void *data, +static int fastaudio_decode(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *pkt) { FastAudioContext *s = avctx->priv_data; GetByteContext gb; - AVFrame *frame = data; int subframes; int ret; - subframes = pkt->size / (40 * avctx->channels); + subframes = pkt->size / (40 * avctx->ch_layout.nb_channels); frame->nb_samples = subframes * 256; if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; @@ -121,7 +121,7 @@ static int fastaudio_decode(AVCodecContext *avctx, void *data, bytestream2_init(&gb, pkt->data, pkt->size); for (int subframe = 0; subframe < subframes; subframe++) { - for (int channel = 0; channel < avctx->channels; channel++) { + for (int channel = 0; channel < avctx->ch_layout.nb_channels; channel++) { ChannelItems *ch = &s->ch[channel]; float result[256] = { 0 }; unsigned src[10]; @@ -187,17 +187,17 @@ static av_cold int fastaudio_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_fastaudio_decoder = { - .name = "fastaudio", - .long_name = NULL_IF_CONFIG_SMALL("MobiClip FastAudio"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_FASTAUDIO, +const FFCodec ff_fastaudio_decoder = { + .p.name = "fastaudio", + .p.long_name = NULL_IF_CONFIG_SMALL("MobiClip FastAudio"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_FASTAUDIO, .priv_data_size = sizeof(FastAudioContext), .init = fastaudio_init, - .decode = fastaudio_decode, + FF_CODEC_DECODE_CB(fastaudio_decode), .close = fastaudio_close, - .capabilities = AV_CODEC_CAP_DR1, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + .p.capabilities = AV_CODEC_CAP_DR1, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/faxcompr.c b/libavcodec/faxcompr.c index b283831da..d9dec3fcb 100644 --- a/libavcodec/faxcompr.c +++ b/libavcodec/faxcompr.c @@ -99,8 +99,8 @@ static VLC ccitt_vlc[2], ccitt_group3_2d_vlc; static av_cold void ccitt_unpack_init(void) { - static VLC_TYPE code_table1[528][2]; - static VLC_TYPE code_table2[648][2]; + static VLCElem code_table1[528]; + static VLCElem code_table2[648]; int i; ccitt_vlc[0].table = code_table1; diff --git a/libavcodec/fdctdsp.c b/libavcodec/fdctdsp.c index b9c2c8632..5306c9d04 100644 --- a/libavcodec/fdctdsp.c +++ b/libavcodec/fdctdsp.c @@ -25,7 +25,7 @@ av_cold void ff_fdctdsp_init(FDCTDSPContext *c, AVCodecContext *avctx) { - const unsigned high_bit_depth = avctx->bits_per_raw_sample > 8; + av_unused const unsigned high_bit_depth = avctx->bits_per_raw_sample > 8; if (avctx->bits_per_raw_sample == 10 || avctx->bits_per_raw_sample == 9) { c->fdct = ff_jpeg_fdct_islow_10; @@ -43,8 +43,9 @@ av_cold void ff_fdctdsp_init(FDCTDSPContext *c, AVCodecContext *avctx) c->fdct248 = ff_fdct248_islow_8; } - if (ARCH_PPC) - ff_fdctdsp_init_ppc(c, avctx, high_bit_depth); - if (ARCH_X86) - ff_fdctdsp_init_x86(c, avctx, high_bit_depth); +#if ARCH_PPC + ff_fdctdsp_init_ppc(c, avctx, high_bit_depth); +#elif ARCH_X86 + ff_fdctdsp_init_x86(c, avctx, high_bit_depth); +#endif } diff --git a/libavcodec/ffjni.c b/libavcodec/ffjni.c index f5b581f0f..154be9ae9 100644 --- a/libavcodec/ffjni.c +++ b/libavcodec/ffjni.c @@ -26,6 +26,7 @@ #include "libavutil/bprint.h" #include "libavutil/log.h" +#include "libavutil/mem.h" #include "config.h" #include "jni.h" diff --git a/libavcodec/fft_template.c b/libavcodec/fft_template.c index 0bd64192c..f2742a3ae 100644 --- a/libavcodec/fft_template.c +++ b/libavcodec/fft_template.c @@ -227,11 +227,18 @@ av_cold int ff_fft_init(FFTContext *s, int nbits, int inverse) #endif #if FFT_FLOAT - if (ARCH_AARCH64) ff_fft_init_aarch64(s); - if (ARCH_ARM) ff_fft_init_arm(s); - if (ARCH_PPC) ff_fft_init_ppc(s); - if (ARCH_X86) ff_fft_init_x86(s); - if (HAVE_MIPSFPU) ff_fft_init_mips(s); +#if ARCH_AARCH64 + ff_fft_init_aarch64(s); +#elif ARCH_ARM + ff_fft_init_arm(s); +#elif ARCH_PPC + ff_fft_init_ppc(s); +#elif ARCH_X86 + ff_fft_init_x86(s); +#endif +#if HAVE_MIPSFPU + ff_fft_init_mips(s); +#endif for(j=4; j<=nbits; j++) { ff_init_ff_cos_tabs(j); } diff --git a/libavcodec/ffv1.c b/libavcodec/ffv1.c index d8a0c3925..c8781cdaa 100644 --- a/libavcodec/ffv1.c +++ b/libavcodec/ffv1.c @@ -27,16 +27,11 @@ #include "libavutil/attributes.h" #include "libavutil/avassert.h" -#include "libavutil/crc.h" -#include "libavutil/opt.h" -#include "libavutil/imgutils.h" -#include "libavutil/pixdesc.h" #include "avcodec.h" -#include "internal.h" #include "rangecoder.h" -#include "mathops.h" #include "ffv1.h" +#include "threadframe.h" av_cold int ff_ffv1_common_init(AVCodecContext *avctx) { @@ -204,11 +199,11 @@ av_cold int ff_ffv1_close(AVCodecContext *avctx) int i, j; if (s->picture.f) - ff_thread_release_buffer(avctx, &s->picture); + ff_thread_release_ext_buffer(avctx, &s->picture); av_frame_free(&s->picture.f); if (s->last_picture.f) - ff_thread_release_buffer(avctx, &s->last_picture); + ff_thread_release_ext_buffer(avctx, &s->last_picture); av_frame_free(&s->last_picture.f); for (j = 0; j < s->max_slice_count; j++) { diff --git a/libavcodec/ffv1.h b/libavcodec/ffv1.h index 8ffe5ab43..ac80fa85c 100644 --- a/libavcodec/ffv1.h +++ b/libavcodec/ffv1.h @@ -28,17 +28,13 @@ * FF Video Codec 1 (a lossless codec) */ -#include "libavutil/crc.h" -#include "libavutil/opt.h" #include "libavutil/imgutils.h" -#include "libavutil/pixdesc.h" #include "avcodec.h" #include "get_bits.h" -#include "internal.h" #include "mathops.h" #include "put_bits.h" #include "rangecoder.h" -#include "thread.h" +#include "threadframe.h" #ifdef __INTEL_COMPILER #undef av_flatten diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c index 810b2e18f..930029726 100644 --- a/libavcodec/ffv1dec.c +++ b/libavcodec/ffv1dec.c @@ -31,12 +31,14 @@ #include "libavutil/imgutils.h" #include "libavutil/pixdesc.h" #include "avcodec.h" -#include "internal.h" +#include "codec_internal.h" #include "get_bits.h" #include "rangecoder.h" #include "golomb.h" #include "mathops.h" #include "ffv1.h" +#include "thread.h" +#include "threadframe.h" static inline av_flatten int get_symbol_inline(RangeCoder *c, uint8_t *state, int is_signed) @@ -185,6 +187,9 @@ static int decode_slice_header(const FFV1Context *f, FFV1Context *fs) || (unsigned)fs->slice_y + (uint64_t)fs->slice_height > f->height) return -1; + if (fs->ac == AC_GOLOMB_RICE && fs->slice_width >= (1<<23)) + return AVERROR_INVALIDDATA; + for (i = 0; i < f->plane_count; i++) { PlaneContext * const p = &fs->plane[i]; int idx = get_symbol(c, state, 0); @@ -829,7 +834,8 @@ static av_cold int decode_init(AVCodecContext *avctx) return 0; } -static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *avpkt) { uint8_t *buf = avpkt->data; int buf_size = avpkt->size; @@ -841,7 +847,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPac AVFrame *p; if (f->last_picture.f) - ff_thread_release_buffer(avctx, &f->last_picture); + ff_thread_release_ext_buffer(avctx, &f->last_picture); FFSWAP(ThreadFrame, f->picture, f->last_picture); f->cur = p = f->picture.f; @@ -873,7 +879,23 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPac p->key_frame = 0; } - if ((ret = ff_thread_get_buffer(avctx, &f->picture, AV_GET_BUFFER_FLAG_REF)) < 0) + if (f->ac != AC_GOLOMB_RICE) { + if (buf_size < avctx->width * avctx->height / (128*8)) + return AVERROR_INVALIDDATA; + } else { + int w = avctx->width; + int s = 1 + w / (1<<23); + + w /= s; + + for (i = 0; w > (1<height + i + 6) / 8 * s) + return AVERROR_INVALIDDATA; + } + + ret = ff_thread_get_ext_buffer(avctx, &f->picture, AV_GET_BUFFER_FLAG_REF); + if (ret < 0) return ret; if (avctx->debug & FF_DEBUG_PICT_INFO) @@ -965,8 +987,8 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPac ff_thread_report_progress(&f->picture, INT_MAX, 0); if (f->last_picture.f) - ff_thread_release_buffer(avctx, &f->last_picture); - if ((ret = av_frame_ref(data, f->picture.f)) < 0) + ff_thread_release_ext_buffer(avctx, &f->last_picture); + if ((ret = av_frame_ref(rframe, f->picture.f)) < 0) return ret; *got_frame = 1; @@ -1036,7 +1058,7 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src) av_assert1(fdst->max_slice_count == fsrc->max_slice_count); - ff_thread_release_buffer(dst, &fdst->picture); + ff_thread_release_ext_buffer(dst, &fdst->picture); if (fsrc->picture.f->data[0]) { if ((ret = ff_thread_ref_frame(&fdst->picture, &fsrc->picture)) < 0) return ret; @@ -1048,17 +1070,17 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src) } #endif -const AVCodec ff_ffv1_decoder = { - .name = "ffv1", - .long_name = NULL_IF_CONFIG_SMALL("FFmpeg video codec #1"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_FFV1, +const FFCodec ff_ffv1_decoder = { + .p.name = "ffv1", + .p.long_name = NULL_IF_CONFIG_SMALL("FFmpeg video codec #1"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_FFV1, .priv_data_size = sizeof(FFV1Context), .init = decode_init, .close = ff_ffv1_close, - .decode = decode_frame, + FF_CODEC_DECODE_CB(decode_frame), .update_thread_context = ONLY_IF_THREADS_ENABLED(update_thread_context), - .capabilities = AV_CODEC_CAP_DR1 /*| AV_CODEC_CAP_DRAW_HORIZ_BAND*/ | + .p.capabilities = AV_CODEC_CAP_DR1 /*| AV_CODEC_CAP_DRAW_HORIZ_BAND*/ | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_SLICE_THREADS, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_ALLOCATE_PROGRESS, diff --git a/libavcodec/ffv1dec_template.c b/libavcodec/ffv1dec_template.c index 0b1d176ba..9b1d65e82 100644 --- a/libavcodec/ffv1dec_template.c +++ b/libavcodec/ffv1dec_template.c @@ -93,11 +93,11 @@ static av_always_inline int RENAME(decode_line)(FFV1Context *s, int w, run_count--; } } else { - while (run_count > 1 && w-x > 1) { - sample[1][x] = RENAME(predict)(sample[1] + x, sample[0] + x); - x++; - run_count--; - } + while (run_count > 1 && w-x > 1) { + sample[1][x] = RENAME(predict)(sample[1] + x, sample[0] + x); + x++; + run_count--; + } } run_count--; if (run_count < 0) { diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c index 69b906534..9849082e4 100644 --- a/libavcodec/ffv1enc.c +++ b/libavcodec/ffv1enc.c @@ -34,10 +34,10 @@ #include "avcodec.h" #include "encode.h" -#include "internal.h" +#include "codec_internal.h" #include "put_bits.h" +#include "put_golomb.h" #include "rangecoder.h" -#include "golomb.h" #include "mathops.h" #include "ffv1.h" @@ -140,32 +140,31 @@ static void find_best_state(uint8_t best_state[256][256], const uint8_t one_state[256]) { int i, j, k, m; - double l2tab[256]; + uint32_t l2tab[256]; for (i = 1; i < 256; i++) - l2tab[i] = log2(i / 256.0); + l2tab[i] = -log2(i / 256.0) * ((1U << 31) / 8); for (i = 0; i < 256; i++) { - double best_len[256]; - double p = i / 256.0; + uint64_t best_len[256]; for (j = 0; j < 256; j++) - best_len[j] = 1 << 30; + best_len[j] = UINT64_MAX; for (j = FFMAX(i - 10, 1); j < FFMIN(i + 11, 256); j++) { - double occ[256] = { 0 }; - double len = 0; - occ[j] = 1.0; + uint32_t occ[256] = { 0 }; + uint64_t len = 0; + occ[j] = UINT32_MAX; if (!one_state[j]) continue; for (k = 0; k < 256; k++) { - double newocc[256] = { 0 }; + uint32_t newocc[256] = { 0 }; for (m = 1; m < 256; m++) if (occ[m]) { - len -=occ[m]*( p *l2tab[ m] - + (1-p)*l2tab[256-m]); + len += (occ[m]*(( i *(uint64_t)l2tab[ m] + + (256-i)*(uint64_t)l2tab[256-m])>>8)) >> 8; } if (len < best_len[k]) { best_len[k] = len; @@ -173,8 +172,8 @@ static void find_best_state(uint8_t best_state[256][256], } for (m = 1; m < 256; m++) if (occ[m]) { - newocc[ one_state[ m]] += occ[m] * p; - newocc[256 - one_state[256 - m]] += occ[m] * (1 - p); + newocc[ one_state[ m]] += occ[m] * (uint64_t) i >> 8; + newocc[256 - one_state[256 - m]] += occ[m] * (uint64_t)(256 - i) >> 8; } memcpy(occ, newocc, sizeof(occ)); } @@ -1277,17 +1276,17 @@ static const AVClass ffv1_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_ffv1_encoder = { - .name = "ffv1", - .long_name = NULL_IF_CONFIG_SMALL("FFmpeg video codec #1"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_FFV1, +const FFCodec ff_ffv1_encoder = { + .p.name = "ffv1", + .p.long_name = NULL_IF_CONFIG_SMALL("FFmpeg video codec #1"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_FFV1, .priv_data_size = sizeof(FFV1Context), .init = encode_init, - .encode2 = encode_frame, + FF_CODEC_ENCODE_CB(encode_frame), .close = encode_close, - .capabilities = AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_DELAY, - .pix_fmts = (const enum AVPixelFormat[]) { + .p.capabilities = AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_DELAY, + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P, AV_PIX_FMT_0RGB32, AV_PIX_FMT_RGB32, AV_PIX_FMT_YUV420P16, @@ -1310,6 +1309,6 @@ const AVCodec ff_ffv1_encoder = { AV_PIX_FMT_NONE }, - .priv_class = &ffv1_class, + .p.priv_class = &ffv1_class, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/ffwavesynth.c b/libavcodec/ffwavesynth.c index a1211facb..67e867b44 100644 --- a/libavcodec/ffwavesynth.c +++ b/libavcodec/ffwavesynth.c @@ -22,6 +22,7 @@ #include "libavutil/intreadwrite.h" #include "libavutil/log.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" @@ -314,7 +315,7 @@ static av_cold int wavesynth_init(AVCodecContext *avc) struct wavesynth_context *ws = avc->priv_data; int i, r; - if (avc->channels > WS_MAX_CHANNELS) { + if (avc->ch_layout.nb_channels > WS_MAX_CHANNELS) { av_log(avc, AV_LOG_ERROR, "This implementation is limited to %d channels.\n", WS_MAX_CHANNELS); @@ -412,11 +413,10 @@ static void wavesynth_enter_intervals(struct wavesynth_context *ws, int64_t ts) *last = -1; } -static int wavesynth_decode(AVCodecContext *avc, void *rframe, int *rgot_frame, - AVPacket *packet) +static int wavesynth_decode(AVCodecContext *avc, AVFrame *frame, + int *rgot_frame, AVPacket *packet) { struct wavesynth_context *ws = avc->priv_data; - AVFrame *frame = rframe; int64_t ts; int duration; int s, c, r; @@ -438,11 +438,11 @@ static int wavesynth_decode(AVCodecContext *avc, void *rframe, int *rgot_frame, return r; pcm = (int16_t *)frame->data[0]; for (s = 0; s < duration; s++, ts+=(uint64_t)1) { - memset(channels, 0, avc->channels * sizeof(*channels)); + memset(channels, 0, avc->ch_layout.nb_channels * sizeof(*channels)); if (ts >= ws->next_ts) wavesynth_enter_intervals(ws, ts); wavesynth_synth_sample(ws, ts, channels); - for (c = 0; c < avc->channels; c++) + for (c = 0; c < avc->ch_layout.nb_channels; c++) *(pcm++) = channels[c] >> 16; } ws->cur_ts += (uint64_t)duration; @@ -459,15 +459,15 @@ static av_cold int wavesynth_close(AVCodecContext *avc) return 0; } -const AVCodec ff_ffwavesynth_decoder = { - .name = "wavesynth", - .long_name = NULL_IF_CONFIG_SMALL("Wave synthesis pseudo-codec"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_FFWAVESYNTH, +const FFCodec ff_ffwavesynth_decoder = { + .p.name = "wavesynth", + .p.long_name = NULL_IF_CONFIG_SMALL("Wave synthesis pseudo-codec"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_FFWAVESYNTH, .priv_data_size = sizeof(struct wavesynth_context), .init = wavesynth_init, .close = wavesynth_close, - .decode = wavesynth_decode, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(wavesynth_decode), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/fic.c b/libavcodec/fic.c index d29f6d16f..491f63ea0 100644 --- a/libavcodec/fic.c +++ b/libavcodec/fic.c @@ -25,13 +25,14 @@ #include "libavutil/mem_internal.h" #include "libavutil/opt.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "get_bits.h" #include "golomb.h" typedef struct FICThreadContext { DECLARE_ALIGNED(16, int16_t, block)[64]; - uint8_t *src; + const uint8_t *src; int slice_h; int src_size; int y_off; @@ -173,7 +174,7 @@ static int fic_decode_slice(AVCodecContext *avctx, void *tdata) FICContext *ctx = avctx->priv_data; FICThreadContext *tctx = tdata; GetBitContext gb; - uint8_t *src = tctx->src; + const uint8_t *src = tctx->src; int slice_h = tctx->slice_h; int src_size = tctx->src_size; int y_off = tctx->y_off; @@ -266,18 +267,18 @@ static void fic_draw_cursor(AVCodecContext *avctx, int cur_x, int cur_y) } } -static int fic_decode_frame(AVCodecContext *avctx, void *data, +static int fic_decode_frame(AVCodecContext *avctx, AVFrame *rframe, int *got_frame, AVPacket *avpkt) { FICContext *ctx = avctx->priv_data; - uint8_t *src = avpkt->data; + const uint8_t *src = avpkt->data; int ret; int slice, nslices; int msize; int tsize; int cur_x, cur_y; int skip_cursor = ctx->skip_cursor; - uint8_t *sdata; + const uint8_t *sdata; if ((ret = ff_reget_buffer(avctx, ctx->frame, 0)) < 0) return ret; @@ -435,7 +436,7 @@ static int fic_decode_frame(AVCodecContext *avctx, void *data, skip: *got_frame = 1; - if ((ret = av_frame_ref(data, ctx->final_frame)) < 0) + if ((ret = av_frame_ref(rframe, ctx->final_frame)) < 0) return ret; return avpkt->size; @@ -483,16 +484,16 @@ static const AVClass fic_decoder_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_fic_decoder = { - .name = "fic", - .long_name = NULL_IF_CONFIG_SMALL("Mirillis FIC"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_FIC, +const FFCodec ff_fic_decoder = { + .p.name = "fic", + .p.long_name = NULL_IF_CONFIG_SMALL("Mirillis FIC"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_FIC, .priv_data_size = sizeof(FICContext), .init = fic_decode_init, - .decode = fic_decode_frame, + FF_CODEC_DECODE_CB(fic_decode_frame), .close = fic_decode_close, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS, - .priv_class = &fic_decoder_class, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS, + .p.priv_class = &fic_decoder_class, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/filter_units_bsf.c b/libavcodec/filter_units_bsf.c index 354594ac5..38756baf4 100644 --- a/libavcodec/filter_units_bsf.c +++ b/libavcodec/filter_units_bsf.c @@ -235,12 +235,12 @@ static const AVClass filter_units_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVBitStreamFilter ff_filter_units_bsf = { - .name = "filter_units", +const FFBitStreamFilter ff_filter_units_bsf = { + .p.name = "filter_units", + .p.codec_ids = ff_cbs_all_codec_ids, + .p.priv_class = &filter_units_class, .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, }; diff --git a/libavcodec/fitsdec.c b/libavcodec/fitsdec.c index af60217a8..b60c2bd44 100644 --- a/libavcodec/fitsdec.c +++ b/libavcodec/fitsdec.c @@ -31,6 +31,7 @@ */ #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include #include "libavutil/intreadwrite.h" @@ -180,9 +181,9 @@ static int fits_read_header(AVCodecContext *avctx, const uint8_t **ptr, FITSHead return 0; } -static int fits_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) +static int fits_decode_frame(AVCodecContext *avctx, AVFrame *p, + int *got_frame, AVPacket *avpkt) { - AVFrame *p=data; const uint8_t *ptr8 = avpkt->data, *end; uint8_t t8; int16_t t16; @@ -320,13 +321,13 @@ static const AVClass fits_decoder_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_fits_decoder = { - .name = "fits", - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_FITS, +const FFCodec ff_fits_decoder = { + .p.name = "fits", + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_FITS, + .p.capabilities = AV_CODEC_CAP_DR1, + .p.long_name = NULL_IF_CONFIG_SMALL("Flexible Image Transport System"), + .p.priv_class = &fits_decoder_class, .priv_data_size = sizeof(FITSContext), - .decode = fits_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, - .long_name = NULL_IF_CONFIG_SMALL("Flexible Image Transport System"), - .priv_class = &fits_decoder_class + FF_CODEC_DECODE_CB(fits_decode_frame), }; diff --git a/libavcodec/fitsenc.c b/libavcodec/fitsenc.c index dfaa04cdb..5e9100be8 100644 --- a/libavcodec/fitsenc.c +++ b/libavcodec/fitsenc.c @@ -32,8 +32,8 @@ #include "libavutil/intreadwrite.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" static int fits_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pict, int *got_packet) @@ -110,14 +110,14 @@ static int fits_encode_frame(AVCodecContext *avctx, AVPacket *pkt, return 0; } -const AVCodec ff_fits_encoder = { - .name = "fits", - .long_name = NULL_IF_CONFIG_SMALL("Flexible Image Transport System"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_FITS, - .capabilities = AV_CODEC_CAP_DR1, - .encode2 = fits_encode_frame, - .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_GBRAP16BE, +const FFCodec ff_fits_encoder = { + .p.name = "fits", + .p.long_name = NULL_IF_CONFIG_SMALL("Flexible Image Transport System"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_FITS, + .p.capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_ENCODE_CB(fits_encode_frame), + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_GBRAP16BE, AV_PIX_FMT_GBRP16BE, AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, diff --git a/libavcodec/flac.c b/libavcodec/flac.c index 7b075d4bd..dd6883062 100644 --- a/libavcodec/flac.c +++ b/libavcodec/flac.c @@ -29,15 +29,15 @@ static const int8_t sample_size_table[] = { 0, 8, 12, 0, 16, 20, 24, 0 }; -static const uint64_t flac_channel_layouts[8] = { - AV_CH_LAYOUT_MONO, - AV_CH_LAYOUT_STEREO, - AV_CH_LAYOUT_SURROUND, - AV_CH_LAYOUT_QUAD, - AV_CH_LAYOUT_5POINT0, - AV_CH_LAYOUT_5POINT1, - AV_CH_LAYOUT_6POINT1, - AV_CH_LAYOUT_7POINT1 +static const AVChannelLayout flac_channel_layouts[8] = { + AV_CHANNEL_LAYOUT_MONO, + AV_CHANNEL_LAYOUT_STEREO, + AV_CHANNEL_LAYOUT_SURROUND, + AV_CHANNEL_LAYOUT_QUAD, + AV_CHANNEL_LAYOUT_5POINT0, + AV_CHANNEL_LAYOUT_5POINT1, + AV_CHANNEL_LAYOUT_6POINT1, + AV_CHANNEL_LAYOUT_7POINT1 }; static int64_t get_utf8(GetBitContext *gb) @@ -193,12 +193,18 @@ int ff_flac_is_extradata_valid(AVCodecContext *avctx, return 1; } -void ff_flac_set_channel_layout(AVCodecContext *avctx) +void ff_flac_set_channel_layout(AVCodecContext *avctx, int channels) { - if (avctx->channels <= FF_ARRAY_ELEMS(flac_channel_layouts)) - avctx->channel_layout = flac_channel_layouts[avctx->channels - 1]; + if (channels == avctx->ch_layout.nb_channels && + avctx->ch_layout.order != AV_CHANNEL_ORDER_UNSPEC) + return; + + av_channel_layout_uninit(&avctx->ch_layout); + if (channels <= FF_ARRAY_ELEMS(flac_channel_layouts)) + avctx->ch_layout = flac_channel_layouts[channels - 1]; else - avctx->channel_layout = 0; + avctx->ch_layout = (AVChannelLayout){ .order = AV_CHANNEL_ORDER_UNSPEC, + .nb_channels = channels }; } int ff_flac_parse_streaminfo(AVCodecContext *avctx, struct FLACStreaminfo *s, @@ -229,13 +235,9 @@ int ff_flac_parse_streaminfo(AVCodecContext *avctx, struct FLACStreaminfo *s, return AVERROR_INVALIDDATA; } - avctx->channels = s->channels; avctx->sample_rate = s->samplerate; avctx->bits_per_raw_sample = s->bps; - - if (!avctx->channel_layout || - av_get_channel_layout_nb_channels(avctx->channel_layout) != avctx->channels) - ff_flac_set_channel_layout(avctx); + ff_flac_set_channel_layout(avctx, s->channels); s->samples = get_bits64(&gb, 36); diff --git a/libavcodec/flac.h b/libavcodec/flac.h index 991ab43f3..cb220ab4c 100644 --- a/libavcodec/flac.h +++ b/libavcodec/flac.h @@ -131,7 +131,7 @@ int ff_flac_get_max_frame_size(int blocksize, int ch, int bps); int ff_flac_decode_frame_header(AVCodecContext *avctx, GetBitContext *gb, FLACFrameInfo *fi, int log_level_offset); -void ff_flac_set_channel_layout(AVCodecContext *avctx); +void ff_flac_set_channel_layout(AVCodecContext *avctx, int channels); /** * Parse the metadata block parameters from the header. diff --git a/libavcodec/flac_parser.c b/libavcodec/flac_parser.c index 3b27b152f..81b6f12ab 100644 --- a/libavcodec/flac_parser.c +++ b/libavcodec/flac_parser.c @@ -34,7 +34,6 @@ #include "libavutil/attributes.h" #include "libavutil/crc.h" -#include "libavutil/fifo.h" #include "bytestream.h" #include "parser.h" #include "flac.h" @@ -57,6 +56,14 @@ #define MAX_FRAME_HEADER_SIZE 16 #define MAX_FRAME_VERIFY_SIZE (MAX_FRAME_HEADER_SIZE + 1) +typedef struct FifoBuffer { + uint8_t *buffer; + uint8_t *end; + uint8_t *rptr; + uint8_t *wptr; + int empty; +} FifoBuffer; + typedef struct FLACHeaderMarker { int offset; /**< byte offset from start of FLACParseContext->buffer */ int link_penalty[FLAC_MAX_SEQUENTIAL_HEADERS]; /**< array of local scores @@ -84,7 +91,7 @@ typedef struct FLACParseContext { int nb_headers_buffered; /**< number of headers that are buffered */ int best_header_valid; /**< flag set when the parser returns junk; if set return best_header next time */ - AVFifoBuffer *fifo_buf; /**< buffer to store all data until headers + FifoBuffer fifo_buf; /**< buffer to store all data until headers can be verified */ int end_padded; /**< specifies if fifo_buf's end is padded */ uint8_t *wrap_buf; /**< general fifo read buffer when wrapped */ @@ -127,6 +134,18 @@ static int frame_header_is_valid(AVCodecContext *avctx, const uint8_t *buf, return 1; } +static size_t flac_fifo_size(const FifoBuffer *f) +{ + if (f->wptr <= f->rptr && !f->empty) + return (f->wptr - f->buffer) + (f->end - f->rptr); + return f->wptr - f->rptr; +} + +static size_t flac_fifo_space(const FifoBuffer *f) +{ + return f->end - f->buffer - flac_fifo_size(f); +} + /** * Non-destructive fast fifo pointer fetching * Returns a pointer from the specified offset. @@ -143,7 +162,7 @@ static int frame_header_is_valid(AVCodecContext *avctx, const uint8_t *buf, static uint8_t *flac_fifo_read_wrap(FLACParseContext *fpc, int offset, int len, uint8_t **wrap_buf, int *allocated_size) { - AVFifoBuffer *f = fpc->fifo_buf; + FifoBuffer *f = &fpc->fifo_buf; uint8_t *start = f->rptr + offset; uint8_t *tmp_buf; @@ -180,9 +199,8 @@ static uint8_t *flac_fifo_read_wrap(FLACParseContext *fpc, int offset, int len, * A second call to flac_fifo_read (with new offset and len) should be called * to get the post-wrap buf if the returned len is less than the requested. **/ -static uint8_t *flac_fifo_read(FLACParseContext *fpc, int offset, int *len) +static uint8_t *flac_fifo_read(FifoBuffer *f, int offset, int *len) { - AVFifoBuffer *f = fpc->fifo_buf; uint8_t *start = f->rptr + offset; if (start >= f->end) @@ -191,6 +209,108 @@ static uint8_t *flac_fifo_read(FLACParseContext *fpc, int offset, int *len) return start; } +static int flac_fifo_grow(FifoBuffer *f, size_t inc) +{ + size_t size_old = f->end - f->buffer; + size_t offset_r = f->rptr - f->buffer; + size_t offset_w = f->wptr - f->buffer; + size_t size_new; + + uint8_t *tmp; + + if (size_old > SIZE_MAX - inc) + return AVERROR(EINVAL); + size_new = size_old + inc; + + tmp = av_realloc(f->buffer, size_new); + if (!tmp) + return AVERROR(ENOMEM); + + // move the data from the beginning of the ring buffer + // to the newly allocated space + if (offset_w <= offset_r && !f->empty) { + const size_t copy = FFMIN(inc, offset_w); + memcpy(tmp + size_old, tmp, copy); + if (copy < offset_w) { + memmove(tmp, tmp + copy, offset_w - copy); + offset_w -= copy; + } else + offset_w = size_old + copy; + } + + f->buffer = tmp; + f->end = f->buffer + size_new; + f->rptr = f->buffer + offset_r; + f->wptr = f->buffer + offset_w; + + return 0; +} + +static int flac_fifo_write(FifoBuffer *f, const uint8_t *src, size_t size) +{ + uint8_t *wptr; + + if (flac_fifo_space(f) < size) { + int ret = flac_fifo_grow(f, FFMAX(flac_fifo_size(f), size)); + if (ret < 0) + return ret; + } + + if (size) + f->empty = 0; + + wptr = f->wptr; + do { + size_t len = FFMIN(f->end - wptr, size); + memcpy(wptr, src, len); + src += len; + wptr += len; + if (wptr >= f->end) + wptr = f->buffer; + size -= len; + } while (size > 0); + + f->wptr = wptr; + + return 0; +} + +static void flac_fifo_drain(FifoBuffer *f, size_t size) +{ + size_t size_cur = flac_fifo_size(f); + + av_assert0(size_cur >= size); + if (size_cur == size) + f->empty = 1; + + f->rptr += size; + if (f->rptr >= f->end) + f->rptr -= f->end - f->buffer; +} + +static int flac_fifo_alloc(FifoBuffer *f, size_t size) +{ + memset(f, 0, sizeof(*f)); + + f->buffer = av_realloc(NULL, size); + if (!f->buffer) + return AVERROR(ENOMEM); + + f->wptr = f->buffer; + f->rptr = f->buffer; + f->end = f->buffer + size; + + f->empty = 1; + + return 0; +} + +static void flac_fifo_free(FifoBuffer *f) +{ + av_freep(&f->buffer); + memset(f, 0, sizeof(*f)); +} + static int find_headers_search_validate(FLACParseContext *fpc, int offset) { FLACFrameInfo fi; @@ -263,9 +383,9 @@ static int find_new_headers(FLACParseContext *fpc, int search_start) fpc->nb_headers_found = 0; /* Search for a new header of at most 16 bytes. */ - search_end = av_fifo_size(fpc->fifo_buf) - (MAX_FRAME_HEADER_SIZE - 1); + search_end = flac_fifo_size(&fpc->fifo_buf) - (MAX_FRAME_HEADER_SIZE - 1); read_len = search_end - search_start + 1; - buf = flac_fifo_read(fpc, search_start, &read_len); + buf = flac_fifo_read(&fpc->fifo_buf, search_start, &read_len); size = find_headers_search(fpc, buf, read_len, search_start); search_start += read_len - 1; @@ -277,7 +397,7 @@ static int find_new_headers(FLACParseContext *fpc, int search_start) /* search_start + 1 is the post-wrap offset in the fifo. */ read_len = search_end - (search_start + 1) + 1; - buf = flac_fifo_read(fpc, search_start + 1, &read_len); + buf = flac_fifo_read(&fpc->fifo_buf, search_start + 1, &read_len); wrap[1] = buf[0]; if ((AV_RB16(wrap) & 0xFFFE) == 0xFFF8) { @@ -406,12 +526,12 @@ static int check_header_mismatch(FLACParseContext *fpc, } read_len = end->offset - start->offset; - buf = flac_fifo_read(fpc, start->offset, &read_len); + buf = flac_fifo_read(&fpc->fifo_buf, start->offset, &read_len); crc = av_crc(av_crc_get_table(AV_CRC_16_ANSI), 0, buf, read_len); read_len = (end->offset - start->offset) - read_len; if (read_len) { - buf = flac_fifo_read(fpc, end->offset - read_len, &read_len); + buf = flac_fifo_read(&fpc->fifo_buf, end->offset - read_len, &read_len); crc = av_crc(av_crc_get_table(AV_CRC_16_ANSI), crc, buf, read_len); } } @@ -500,7 +620,7 @@ static int get_best_header(FLACParseContext *fpc, const uint8_t **poutbuf, FLACHeaderMarker *header = fpc->best_header; FLACHeaderMarker *child = header->best_child; if (!child) { - *poutbuf_size = av_fifo_size(fpc->fifo_buf) - header->offset; + *poutbuf_size = flac_fifo_size(&fpc->fifo_buf) - header->offset; } else { *poutbuf_size = child->offset - header->offset; @@ -508,18 +628,14 @@ static int get_best_header(FLACParseContext *fpc, const uint8_t **poutbuf, check_header_mismatch(fpc, header, child, 0); } - if (header->fi.channels != fpc->avctx->channels || - !fpc->avctx->channel_layout) { - fpc->avctx->channels = header->fi.channels; - ff_flac_set_channel_layout(fpc->avctx); - } + ff_flac_set_channel_layout(fpc->avctx, header->fi.channels); + fpc->avctx->sample_rate = header->fi.samplerate; fpc->pc->duration = header->fi.blocksize; *poutbuf = flac_fifo_read_wrap(fpc, header->offset, *poutbuf_size, &fpc->wrap_buf, &fpc->wrap_buf_allocated_size); - if (fpc->pc->flags & PARSER_FLAG_USE_CODEC_TS) { if (header->fi.is_var_size) fpc->pc->pts = header->fi.frame_or_sample_num; @@ -534,7 +650,7 @@ static int get_best_header(FLACParseContext *fpc, const uint8_t **poutbuf, /* Return the negative overread index so the client can compute pos. This should be the amount overread to the beginning of the child */ if (child) - return child->offset - av_fifo_size(fpc->fifo_buf); + return child->offset - flac_fifo_size(&fpc->fifo_buf); return 0; } @@ -586,7 +702,7 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx, fpc->nb_headers_buffered--; } /* Release returned data from ring buffer. */ - av_fifo_drain(fpc->fifo_buf, best_child->offset); + flac_fifo_drain(&fpc->fifo_buf, best_child->offset); /* Fix the offset for the headers remaining to match the new buffer. */ for (curr = best_child->next; curr; curr = curr->next) @@ -620,7 +736,7 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx, while ((buf_size && read_end < buf + buf_size && fpc->nb_headers_buffered < FLAC_MIN_HEADERS) || (!buf_size && !fpc->end_padded)) { - int start_offset; + int start_offset, ret; /* Pad the end once if EOF, to check the final region for headers. */ if (!buf_size) { @@ -634,8 +750,8 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx, nb_desired * FLAC_AVG_FRAME_SIZE); } - if (!av_fifo_space(fpc->fifo_buf) && - av_fifo_size(fpc->fifo_buf) / FLAC_AVG_FRAME_SIZE > + if (!flac_fifo_space(&fpc->fifo_buf) && + flac_fifo_size(&fpc->fifo_buf) / FLAC_AVG_FRAME_SIZE > fpc->nb_headers_buffered * 20) { /* There is less than one valid flac header buffered for 20 headers * buffered. Therefore the fifo is most likely filled with invalid @@ -644,24 +760,20 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx, } /* Fill the buffer. */ - if ( av_fifo_space(fpc->fifo_buf) < read_end - read_start - && av_fifo_realloc2(fpc->fifo_buf, (read_end - read_start) + 2*av_fifo_size(fpc->fifo_buf)) < 0) { - av_log(avctx, AV_LOG_ERROR, - "couldn't reallocate buffer of size %"PTRDIFF_SPECIFIER"\n", - (read_end - read_start) + av_fifo_size(fpc->fifo_buf)); + if (buf_size) { + ret = flac_fifo_write(&fpc->fifo_buf, read_start, + read_end - read_start); + } else { + int8_t pad[MAX_FRAME_HEADER_SIZE] = { 0 }; + ret = flac_fifo_write(&fpc->fifo_buf, pad, sizeof(pad)); + } + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Error buffering data\n"); goto handle_error; } - if (buf_size) { - av_fifo_generic_write(fpc->fifo_buf, (void*) read_start, - read_end - read_start, NULL); - } else { - int8_t pad[MAX_FRAME_HEADER_SIZE] = { 0 }; - av_fifo_generic_write(fpc->fifo_buf, pad, sizeof(pad), NULL); - } - /* Tag headers and update sequences. */ - start_offset = av_fifo_size(fpc->fifo_buf) - + start_offset = flac_fifo_size(&fpc->fifo_buf) - ((read_end - read_start) + (MAX_FRAME_HEADER_SIZE - 1)); start_offset = FFMAX(0, start_offset); nb_headers = find_new_headers(fpc, start_offset); @@ -689,14 +801,15 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx, /* restore the state pre-padding */ if (fpc->end_padded) { - int warp = fpc->fifo_buf->wptr - fpc->fifo_buf->buffer < MAX_FRAME_HEADER_SIZE; + int empty = flac_fifo_size(&fpc->fifo_buf) == MAX_FRAME_HEADER_SIZE; + int warp = fpc->fifo_buf.wptr - fpc->fifo_buf.buffer < MAX_FRAME_HEADER_SIZE; /* HACK: drain the tail of the fifo */ - fpc->fifo_buf->wptr -= MAX_FRAME_HEADER_SIZE; - fpc->fifo_buf->wndx -= MAX_FRAME_HEADER_SIZE; + fpc->fifo_buf.wptr -= MAX_FRAME_HEADER_SIZE; if (warp) { - fpc->fifo_buf->wptr += fpc->fifo_buf->end - - fpc->fifo_buf->buffer; + fpc->fifo_buf.wptr += fpc->fifo_buf.end - + fpc->fifo_buf.buffer; } + fpc->fifo_buf.empty = empty; read_start = read_end = NULL; } } @@ -727,7 +840,7 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx, &fpc->wrap_buf, &fpc->wrap_buf_allocated_size); return buf_size ? (read_end - buf) : (fpc->best_header->offset - - av_fifo_size(fpc->fifo_buf)); + flac_fifo_size(&fpc->fifo_buf)); } if (!buf_size) return get_best_header(fpc, poutbuf, poutbuf_size); @@ -742,11 +855,13 @@ handle_error: static av_cold int flac_parse_init(AVCodecParserContext *c) { FLACParseContext *fpc = c->priv_data; + int ret; + fpc->pc = c; /* There will generally be FLAC_MIN_HEADERS buffered in the fifo before it drains. This is allocated early to avoid slow reallocation. */ - fpc->fifo_buf = av_fifo_alloc_array(FLAC_MIN_HEADERS + 3, FLAC_AVG_FRAME_SIZE); - if (!fpc->fifo_buf) { + ret = flac_fifo_alloc(&fpc->fifo_buf, (FLAC_MIN_HEADERS + 3) * FLAC_AVG_FRAME_SIZE); + if (ret < 0) { av_log(fpc->avctx, AV_LOG_ERROR, "couldn't allocate fifo_buf\n"); return AVERROR(ENOMEM); @@ -765,7 +880,7 @@ static void flac_parse_close(AVCodecParserContext *c) curr = temp; } fpc->headers = NULL; - av_fifo_freep(&fpc->fifo_buf); + flac_fifo_free(&fpc->fifo_buf); av_freep(&fpc->wrap_buf); } diff --git a/libavcodec/flacdata.c b/libavcodec/flacdata.c index 1954f32d3..d96e3e096 100644 --- a/libavcodec/flacdata.c +++ b/libavcodec/flacdata.c @@ -19,7 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "internal.h" +#include "flacdata.h" const int ff_flac_sample_rate_table[16] = { 0, diff --git a/libavcodec/flacdata.h b/libavcodec/flacdata.h index e2c1e5d7f..ef2184077 100644 --- a/libavcodec/flacdata.h +++ b/libavcodec/flacdata.h @@ -22,7 +22,7 @@ #ifndef AVCODEC_FLACDATA_H #define AVCODEC_FLACDATA_H -#include "internal.h" +#include extern const int ff_flac_sample_rate_table[16]; diff --git a/libavcodec/flacdec.c b/libavcodec/flacdec.c index 09051cc66..87f20c742 100644 --- a/libavcodec/flacdec.c +++ b/libavcodec/flacdec.c @@ -37,7 +37,7 @@ #include "libavutil/crc.h" #include "libavutil/opt.h" #include "avcodec.h" -#include "internal.h" +#include "codec_internal.h" #include "get_bits.h" #include "bytestream.h" #include "golomb.h" @@ -260,7 +260,7 @@ static int decode_residuals(FLACContext *s, int32_t *decoded, int pred_order) for (; i < samples; i++) *decoded++ = get_sbits_long(&gb, tmp); } else { - int real_limit = tmp ? (INT_MAX >> tmp) + 2 : INT_MAX; + int real_limit = (tmp > 1) ? (INT_MAX >> (tmp - 1)) + 2 : INT_MAX; for (; i < samples; i++) { int v = get_sr_golomb_flac(&gb, tmp, real_limit, 1); if (v == 0x80000000){ @@ -483,15 +483,14 @@ static int decode_frame(FLACContext *s) if ( s->flac_stream_info.channels && fi.channels != s->flac_stream_info.channels && s->got_streaminfo) { - s->flac_stream_info.channels = s->avctx->channels = fi.channels; - ff_flac_set_channel_layout(s->avctx); + s->flac_stream_info.channels = fi.channels; + ff_flac_set_channel_layout(s->avctx, fi.channels); ret = allocate_buffers(s); if (ret < 0) return ret; } - s->flac_stream_info.channels = s->avctx->channels = fi.channels; - if (!s->avctx->channel_layout) - ff_flac_set_channel_layout(s->avctx); + s->flac_stream_info.channels = fi.channels; + ff_flac_set_channel_layout(s->avctx, fi.channels); s->ch_mode = fi.ch_mode; if (!s->flac_stream_info.bps && !fi.bps) { @@ -555,11 +554,9 @@ static int decode_frame(FLACContext *s) return 0; } -static int flac_decode_frame(AVCodecContext *avctx, void *data, +static int flac_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; - ThreadFrame tframe = { .f = data }; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; FLACContext *s = avctx->priv_data; @@ -618,7 +615,7 @@ static int flac_decode_frame(AVCodecContext *avctx, void *data, /* get output buffer */ frame->nb_samples = s->blocksize; - if ((ret = ff_thread_get_buffer(avctx, &tframe, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, frame, 0)) < 0) return ret; s->dsp.decorrelate[s->ch_mode](frame->data, s->decoded, @@ -660,23 +657,23 @@ static const AVClass flac_decoder_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_flac_decoder = { - .name = "flac", - .long_name = NULL_IF_CONFIG_SMALL("FLAC (Free Lossless Audio Codec)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_FLAC, +const FFCodec ff_flac_decoder = { + .p.name = "flac", + .p.long_name = NULL_IF_CONFIG_SMALL("FLAC (Free Lossless Audio Codec)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_FLAC, .priv_data_size = sizeof(FLACContext), .init = flac_decode_init, .close = flac_decode_close, - .decode = flac_decode_frame, - .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + FF_CODEC_DECODE_CB(flac_decode_frame), + .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_NONE }, - .priv_class = &flac_decoder_class, + .p.priv_class = &flac_decoder_class, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/flacdsp.c b/libavcodec/flacdsp.c index bc9a5dbed..79002dcac 100644 --- a/libavcodec/flacdsp.c +++ b/libavcodec/flacdsp.c @@ -19,6 +19,7 @@ */ #include "libavutil/attributes.h" +#include "libavutil/internal.h" #include "libavutil/samplefmt.h" #include "flacdsp.h" #include "config.h" @@ -123,8 +124,9 @@ av_cold void ff_flacdsp_init(FLACDSPContext *c, enum AVSampleFormat fmt, int cha break; } - if (ARCH_ARM) - ff_flacdsp_init_arm(c, fmt, channels, bps); - if (ARCH_X86) - ff_flacdsp_init_x86(c, fmt, channels, bps); +#if ARCH_ARM + ff_flacdsp_init_arm(c, fmt, channels, bps); +#elif ARCH_X86 + ff_flacdsp_init_x86(c, fmt, channels, bps); +#endif } diff --git a/libavcodec/flacdsp.h b/libavcodec/flacdsp.h index 7bb0dd0e9..4a7a36064 100644 --- a/libavcodec/flacdsp.h +++ b/libavcodec/flacdsp.h @@ -20,7 +20,7 @@ #define AVCODEC_FLACDSP_H #include -#include "libavutil/internal.h" + #include "libavutil/samplefmt.h" typedef struct FLACDSPContext { diff --git a/libavcodec/flacdsp_lpc_template.c b/libavcodec/flacdsp_lpc_template.c index 5d532e067..dd847d3b3 100644 --- a/libavcodec/flacdsp_lpc_template.c +++ b/libavcodec/flacdsp_lpc_template.c @@ -17,7 +17,7 @@ */ #include -#include "libavutil/avutil.h" +#include "libavutil/common.h" #include "mathops.h" #undef FUNC diff --git a/libavcodec/flacdsp_template.c b/libavcodec/flacdsp_template.c index 892418cdd..0a6fe59e2 100644 --- a/libavcodec/flacdsp_template.c +++ b/libavcodec/flacdsp_template.c @@ -19,7 +19,7 @@ */ #include -#include "libavutil/avutil.h" +#include "libavutil/macros.h" #undef FUNC #undef FSUF diff --git a/libavcodec/flacenc.c b/libavcodec/flacenc.c index 595928927..e9edd8476 100644 --- a/libavcodec/flacenc.c +++ b/libavcodec/flacenc.c @@ -28,9 +28,10 @@ #include "avcodec.h" #include "bswapdsp.h" +#include "codec_internal.h" #include "encode.h" #include "put_bits.h" -#include "golomb.h" +#include "put_golomb.h" #include "internal.h" #include "lpc.h" #include "flac.h" @@ -241,7 +242,7 @@ static av_cold void dprint_compression_options(FlacEncodeContext *s) static av_cold int flac_encode_init(AVCodecContext *avctx) { int freq = avctx->sample_rate; - int channels = avctx->channels; + int channels = avctx->ch_layout.nb_channels; FlacEncodeContext *s = avctx->priv_data; int i, level, ret; uint8_t *streaminfo; @@ -398,18 +399,18 @@ static av_cold int flac_encode_init(AVCodecContext *avctx) s->frame_count = 0; s->min_framesize = s->max_framesize; - if (channels == 3 && - avctx->channel_layout != (AV_CH_LAYOUT_STEREO|AV_CH_FRONT_CENTER) || - channels == 4 && - avctx->channel_layout != AV_CH_LAYOUT_2_2 && - avctx->channel_layout != AV_CH_LAYOUT_QUAD || - channels == 5 && - avctx->channel_layout != AV_CH_LAYOUT_5POINT0 && - avctx->channel_layout != AV_CH_LAYOUT_5POINT0_BACK || - channels == 6 && - avctx->channel_layout != AV_CH_LAYOUT_5POINT1 && - avctx->channel_layout != AV_CH_LAYOUT_5POINT1_BACK) { - if (avctx->channel_layout) { + if ((channels == 3 && + av_channel_layout_compare(&avctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_SURROUND)) || + (channels == 4 && + av_channel_layout_compare(&avctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_2_2) && + av_channel_layout_compare(&avctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_QUAD)) || + (channels == 5 && + av_channel_layout_compare(&avctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT0) && + av_channel_layout_compare(&avctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT0_BACK)) || + (channels == 6 && + av_channel_layout_compare(&avctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1) && + av_channel_layout_compare(&avctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1_BACK))) { + if (avctx->ch_layout.order != AV_CHANNEL_ORDER_UNSPEC) { av_log(avctx, AV_LOG_ERROR, "Channel layout not supported by Flac, " "output stream will have incorrect " "channel layout.\n"); @@ -1457,20 +1458,20 @@ static const AVClass flac_encoder_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_flac_encoder = { - .name = "flac", - .long_name = NULL_IF_CONFIG_SMALL("FLAC (Free Lossless Audio Codec)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_FLAC, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | +const FFCodec ff_flac_encoder = { + .p.name = "flac", + .p.long_name = NULL_IF_CONFIG_SMALL("FLAC (Free Lossless Audio Codec)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_FLAC, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SMALL_LAST_FRAME, .priv_data_size = sizeof(FlacEncodeContext), .init = flac_encode_init, - .encode2 = flac_encode_frame, + FF_CODEC_ENCODE_CB(flac_encode_frame), .close = flac_encode_close, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE }, - .priv_class = &flac_encoder_class, + .p.priv_class = &flac_encoder_class, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/flashsv.c b/libavcodec/flashsv.c index 00f77f490..4357b25d0 100644 --- a/libavcodec/flashsv.c +++ b/libavcodec/flashsv.c @@ -33,6 +33,8 @@ * downloaded from http://www.adobe.com/devnet/swf.html. */ +#include "config_components.h" + #include #include #include @@ -40,11 +42,13 @@ #include "libavutil/intreadwrite.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" +#include "zlib_wrapper.h" typedef struct BlockInfo { - uint8_t *pos; + const uint8_t *pos; int size; } BlockInfo; @@ -55,18 +59,18 @@ typedef struct FlashSVContext { int block_width, block_height; uint8_t *tmpblock; int block_size; - z_stream zstream; int ver; const uint32_t *pal; int is_keyframe; - uint8_t *keyframedata; + const uint8_t *keyframedata; + AVBufferRef *keyframedata_buf; uint8_t *keyframe; BlockInfo *blocks; - uint8_t *deflate_block; - int deflate_block_size; int color_depth; int zlibprime_curr, zlibprime_prev; int diff_start, diff_height; + FFZStream zstream; + uint8_t tmp[UINT16_MAX]; } FlashSVContext; static int decode_hybrid(const uint8_t *sptr, const uint8_t *sptr_end, uint8_t *dptr, int dx, int dy, @@ -104,7 +108,8 @@ static int decode_hybrid(const uint8_t *sptr, const uint8_t *sptr_end, uint8_t * static av_cold int flashsv_decode_end(AVCodecContext *avctx) { FlashSVContext *s = avctx->priv_data; - inflateEnd(&s->zstream); + + ff_inflate_end(&s->zstream); /* release the frame if needed */ av_frame_free(&s->frame); @@ -117,17 +122,8 @@ static av_cold int flashsv_decode_end(AVCodecContext *avctx) static av_cold int flashsv_decode_init(AVCodecContext *avctx) { FlashSVContext *s = avctx->priv_data; - int zret; // Zlib return code s->avctx = avctx; - s->zstream.zalloc = Z_NULL; - s->zstream.zfree = Z_NULL; - s->zstream.opaque = Z_NULL; - zret = inflateInit(&s->zstream); - if (zret != Z_OK) { - av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret); - return AVERROR_EXTERNAL; - } avctx->pix_fmt = AV_PIX_FMT_BGR24; s->frame = av_frame_alloc(); @@ -135,46 +131,69 @@ static av_cold int flashsv_decode_init(AVCodecContext *avctx) return AVERROR(ENOMEM); } - return 0; + return ff_inflate_init(&s->zstream, avctx); } -static int flashsv2_prime(FlashSVContext *s, uint8_t *src, int size) +static int flashsv2_prime(FlashSVContext *s, const uint8_t *src, int size) { - z_stream zs; int zret; // Zlib return code + static const uint8_t zlib_header[] = { 0x78, 0x01 }; + z_stream *const zstream = &s->zstream.zstream; + uint8_t *data = s->tmpblock; + unsigned remaining; if (!src) return AVERROR_INVALIDDATA; - zs.zalloc = NULL; - zs.zfree = NULL; - zs.opaque = NULL; + zstream->next_in = src; + zstream->avail_in = size; + zstream->next_out = data; + zstream->avail_out = s->block_size * 3; + zret = inflate(zstream, Z_SYNC_FLUSH); + if (zret != Z_OK && zret != Z_STREAM_END) + return AVERROR_UNKNOWN; + remaining = s->block_size * 3 - zstream->avail_out; - s->zstream.next_in = src; - s->zstream.avail_in = size; - s->zstream.next_out = s->tmpblock; - s->zstream.avail_out = s->block_size * 3; - inflate(&s->zstream, Z_SYNC_FLUSH); - - if (deflateInit(&zs, 0) != Z_OK) - return -1; - zs.next_in = s->tmpblock; - zs.avail_in = s->block_size * 3 - s->zstream.avail_out; - zs.next_out = s->deflate_block; - zs.avail_out = s->deflate_block_size; - deflate(&zs, Z_SYNC_FLUSH); - deflateEnd(&zs); - - if ((zret = inflateReset(&s->zstream)) != Z_OK) { + if ((zret = inflateReset(zstream)) != Z_OK) { av_log(s->avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", zret); return AVERROR_UNKNOWN; } - s->zstream.next_in = s->deflate_block; - s->zstream.avail_in = s->deflate_block_size - zs.avail_out; - s->zstream.next_out = s->tmpblock; - s->zstream.avail_out = s->block_size * 3; - inflate(&s->zstream, Z_SYNC_FLUSH); + /* Create input for zlib that is equivalent to encoding the output + * from above and decoding it again (the net result of this is that + * the dictionary of past decoded data is correctly primed and + * the adler32 checksum is correctly initialized). + * This is accomplished by synthetizing blocks of uncompressed data + * out of the output from above. See section 3.2.4 of RFC 1951. */ + zstream->next_in = zlib_header; + zstream->avail_in = sizeof(zlib_header); + zret = inflate(zstream, Z_SYNC_FLUSH); + if (zret != Z_OK) + return AVERROR_UNKNOWN; + while (remaining > 0) { + unsigned block_size = FFMIN(UINT16_MAX, remaining); + uint8_t header[5]; + /* Bit 0: Non-last-block, bits 1-2: BTYPE for uncompressed block */ + header[0] = 0; + /* Block size */ + AV_WL16(header + 1, block_size); + /* Block size (one's complement) */ + AV_WL16(header + 3, block_size ^ 0xFFFF); + zstream->next_in = header; + zstream->avail_in = sizeof(header); + zstream->next_out = s->tmp; + zstream->avail_out = sizeof(s->tmp); + zret = inflate(zstream, Z_SYNC_FLUSH); + if (zret != Z_OK) + return AVERROR_UNKNOWN; + zstream->next_in = data; + zstream->avail_in = block_size; + zret = inflate(zstream, Z_SYNC_FLUSH); + if (zret != Z_OK) + return AVERROR_UNKNOWN; + data += block_size; + remaining -= block_size; + } return 0; } @@ -185,9 +204,10 @@ static int flashsv_decode_block(AVCodecContext *avctx, const AVPacket *avpkt, int blk_idx) { struct FlashSVContext *s = avctx->priv_data; + z_stream *const zstream = &s->zstream.zstream; uint8_t *line = s->tmpblock; int k; - int ret = inflateReset(&s->zstream); + int ret = inflateReset(zstream); if (ret != Z_OK) { av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", ret); return AVERROR_UNKNOWN; @@ -199,15 +219,15 @@ static int flashsv_decode_block(AVCodecContext *avctx, const AVPacket *avpkt, if (ret < 0) return ret; } - s->zstream.next_in = avpkt->data + get_bits_count(gb) / 8; - s->zstream.avail_in = block_size; - s->zstream.next_out = s->tmpblock; - s->zstream.avail_out = s->block_size * 3; - ret = inflate(&s->zstream, Z_FINISH); + zstream->next_in = avpkt->data + get_bits_count(gb) / 8; + zstream->avail_in = block_size; + zstream->next_out = s->tmpblock; + zstream->avail_out = s->block_size * 3; + ret = inflate(zstream, Z_FINISH); if (ret == Z_DATA_ERROR) { av_log(avctx, AV_LOG_ERROR, "Zlib resync occurred\n"); - inflateSync(&s->zstream); - ret = inflate(&s->zstream, Z_FINISH); + inflateSync(zstream); + ret = inflate(zstream, Z_FINISH); } if (ret != Z_OK && ret != Z_STREAM_END) { @@ -233,7 +253,7 @@ static int flashsv_decode_block(AVCodecContext *avctx, const AVPacket *avpkt, } } else { /* hybrid 15-bit/palette mode */ - ret = decode_hybrid(s->tmpblock, s->zstream.next_out, + ret = decode_hybrid(s->tmpblock, zstream->next_out, s->frame->data[0], s->image_height - (y_pos + 1 + s->diff_height), x_pos, s->diff_height, width, @@ -247,23 +267,7 @@ static int flashsv_decode_block(AVCodecContext *avctx, const AVPacket *avpkt, return 0; } -static int calc_deflate_block_size(int tmpblock_size) -{ - z_stream zstream; - int size; - - zstream.zalloc = Z_NULL; - zstream.zfree = Z_NULL; - zstream.opaque = Z_NULL; - if (deflateInit(&zstream, 0) != Z_OK) - return -1; - size = deflateBound(&zstream, tmpblock_size); - deflateEnd(&zstream); - - return size; -} - -static int flashsv_decode_frame(AVCodecContext *avctx, void *data, +static int flashsv_decode_frame(AVCodecContext *avctx, AVFrame *rframe, int *got_frame, AVPacket *avpkt) { int buf_size = avpkt->size; @@ -321,19 +325,6 @@ static int flashsv_decode_frame(AVCodecContext *avctx, void *data, "Cannot allocate decompression buffer.\n"); return err; } - if (s->ver == 2) { - s->deflate_block_size = calc_deflate_block_size(tmpblock_size); - if (s->deflate_block_size <= 0) { - av_log(avctx, AV_LOG_ERROR, - "Cannot determine deflate buffer size.\n"); - return -1; - } - if ((err = av_reallocp(&s->deflate_block, s->deflate_block_size)) < 0) { - s->block_size = 0; - av_log(avctx, AV_LOG_ERROR, "Cannot allocate deflate buffer.\n"); - return err; - } - } } s->block_size = s->block_width * s->block_height; @@ -355,10 +346,13 @@ static int flashsv_decode_frame(AVCodecContext *avctx, void *data, /* we care for keyframes only in Screen Video v2 */ s->is_keyframe = (avpkt->flags & AV_PKT_FLAG_KEY) && (s->ver == 2); if (s->is_keyframe) { - int err; - if ((err = av_reallocp(&s->keyframedata, avpkt->size)) < 0) + int err = av_buffer_replace(&s->keyframedata_buf, avpkt->buf); + if (err < 0) return err; - memcpy(s->keyframedata, avpkt->data, avpkt->size); + s->keyframedata = avpkt->data; + if (s->blocks) + memset(s->blocks, 0, (v_blocks + !!v_part) * (h_blocks + !!h_part) * + sizeof(s->blocks[0])); } if(s->ver == 2 && !s->blocks) s->blocks = av_mallocz((v_blocks + !!v_part) * (h_blocks + !!h_part) * @@ -493,7 +487,7 @@ static int flashsv_decode_frame(AVCodecContext *avctx, void *data, s->frame->linesize[0] * avctx->height); } - if ((ret = av_frame_ref(data, s->frame)) < 0) + if ((ret = av_frame_ref(rframe, s->frame)) < 0) return ret; *got_frame = 1; @@ -507,18 +501,18 @@ static int flashsv_decode_frame(AVCodecContext *avctx, void *data, } #if CONFIG_FLASHSV_DECODER -const AVCodec ff_flashsv_decoder = { - .name = "flashsv", - .long_name = NULL_IF_CONFIG_SMALL("Flash Screen Video v1"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_FLASHSV, +const FFCodec ff_flashsv_decoder = { + .p.name = "flashsv", + .p.long_name = NULL_IF_CONFIG_SMALL("Flash Screen Video v1"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_FLASHSV, .priv_data_size = sizeof(FlashSVContext), .init = flashsv_decode_init, .close = flashsv_decode_end, - .decode = flashsv_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(flashsv_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE }, + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE }, }; #endif /* CONFIG_FLASHSV_DECODER */ @@ -566,26 +560,26 @@ static av_cold int flashsv2_decode_end(AVCodecContext *avctx) { FlashSVContext *s = avctx->priv_data; - av_freep(&s->keyframedata); + av_buffer_unref(&s->keyframedata_buf); + s->keyframedata = NULL; av_freep(&s->blocks); av_freep(&s->keyframe); - av_freep(&s->deflate_block); flashsv_decode_end(avctx); return 0; } -const AVCodec ff_flashsv2_decoder = { - .name = "flashsv2", - .long_name = NULL_IF_CONFIG_SMALL("Flash Screen Video v2"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_FLASHSV2, +const FFCodec ff_flashsv2_decoder = { + .p.name = "flashsv2", + .p.long_name = NULL_IF_CONFIG_SMALL("Flash Screen Video v2"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_FLASHSV2, .priv_data_size = sizeof(FlashSVContext), .init = flashsv2_decode_init, .close = flashsv2_decode_end, - .decode = flashsv_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(flashsv_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE }, + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE }, }; #endif /* CONFIG_FLASHSV2_DECODER */ diff --git a/libavcodec/flashsv2enc.c b/libavcodec/flashsv2enc.c index 56ea0ed0a..07fa9945f 100644 --- a/libavcodec/flashsv2enc.c +++ b/libavcodec/flashsv2enc.c @@ -48,10 +48,11 @@ #include "libavutil/imgutils.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "put_bits.h" #include "bytestream.h" +#include "zlib_wrapper.h" #define HAS_IFRAME_IMAGE 0x02 #define HAS_PALLET_INFO 0x01 @@ -112,6 +113,7 @@ typedef struct FlashSV2Context { uint8_t use_custom_palette; uint8_t palette_type; ///< 0=>default, 1=>custom - changed when palette regenerated. Palette palette; + FFZStream zstream; #ifndef FLASHSV2_DUMB double tot_blocks; ///< blocks encoded since last keyframe double diff_blocks; ///< blocks that were different since last keyframe @@ -136,6 +138,7 @@ static av_cold void cleanup(FlashSV2Context * s) av_freep(&s->frame_blocks); av_freep(&s->key_blocks); + ff_deflate_end(&s->zstream); } static void init_blocks(FlashSV2Context * s, Block * blocks, @@ -234,7 +237,9 @@ static av_cold int flashsv2_encode_init(AVCodecContext * avctx) if ((ret = av_image_check_size(avctx->width, avctx->height, 0, avctx)) < 0) return ret; - + ret = ff_deflate_init(&s->zstream, s->comp, avctx); + if (ret < 0) + return ret; s->last_key_frame = 0; s->image_width = avctx->width; @@ -357,41 +362,47 @@ static int write_block(Block * b, uint8_t * buf, int buf_size) return buf_pos; } -static int encode_zlib(Block * b, uint8_t * buf, unsigned long *buf_size, int comp) +static int encode_zlib(Block *b, uint8_t *buf, unsigned long *buf_size, + z_stream *zstream) { - int res = compress2(buf, buf_size, b->sl_begin, b->sl_end - b->sl_begin, comp); - return res == Z_OK ? 0 : -1; + int res; + + if (deflateReset(zstream) != Z_OK) + return AVERROR_EXTERNAL; + zstream->next_out = buf; + zstream->avail_out = *buf_size; + zstream->next_in = b->sl_begin; + zstream->avail_in = b->sl_end - b->sl_begin; + res = deflate(zstream, Z_FINISH); + if (res != Z_STREAM_END) + return AVERROR_EXTERNAL; + *buf_size -= zstream->avail_out; + return 0; } static int encode_zlibprime(Block * b, Block * prime, uint8_t * buf, - int *buf_size, int comp) + int *buf_size, z_stream *zstream) { - z_stream s; int res; - s.zalloc = NULL; - s.zfree = NULL; - s.opaque = NULL; - res = deflateInit(&s, comp); - if (res < 0) - return -1; - s.next_in = prime->enc; - s.avail_in = prime->enc_size; - while (s.avail_in > 0) { - s.next_out = buf; - s.avail_out = *buf_size; - res = deflate(&s, Z_SYNC_FLUSH); + if (deflateReset(zstream) != Z_OK) + return AVERROR_EXTERNAL; + zstream->next_in = prime->enc; + zstream->avail_in = prime->enc_size; + while (zstream->avail_in > 0) { + zstream->next_out = buf; + zstream->avail_out = *buf_size; + res = deflate(zstream, Z_SYNC_FLUSH); if (res < 0) return -1; } - s.next_in = b->sl_begin; - s.avail_in = b->sl_end - b->sl_begin; - s.next_out = buf; - s.avail_out = *buf_size; - res = deflate(&s, Z_FINISH); - deflateEnd(&s); - *buf_size -= s.avail_out; + zstream->next_in = b->sl_begin; + zstream->avail_in = b->sl_end - b->sl_begin; + zstream->next_out = buf; + zstream->avail_out = *buf_size; + res = deflate(zstream, Z_FINISH); + *buf_size -= zstream->avail_out; if (res != Z_STREAM_END) return -1; return 0; @@ -559,7 +570,7 @@ static int encode_15_7(Palette * palette, Block * b, const uint8_t * src, } static int encode_block(FlashSV2Context *s, Palette * palette, Block * b, - Block * prev, const uint8_t * src, int stride, int comp, + Block *prev, const uint8_t *src, int stride, int dist, int keyframe) { unsigned buf_size = b->width * b->height * 6; @@ -574,12 +585,12 @@ static int encode_block(FlashSV2Context *s, Palette * palette, Block * b, if (b->len > 0) { b->data_size = buf_size; - res = encode_zlib(b, b->data, &b->data_size, comp); + res = encode_zlib(b, b->data, &b->data_size, &s->zstream.zstream); if (res) return res; if (!keyframe) { - res = encode_zlibprime(b, prev, buf, &buf_size, comp); + res = encode_zlibprime(b, prev, buf, &buf_size, &s->zstream.zstream); if (res) return res; @@ -656,7 +667,8 @@ static int encode_all_blocks(FlashSV2Context * s, int keyframe) b->flags |= HAS_DIFF_BLOCKS; } data = s->current_frame + s->image_width * 3 * s->block_height * row + s->block_width * col * 3; - res = encode_block(s, &s->palette, b, prev, data, s->image_width * 3, s->comp, s->dist, keyframe); + res = encode_block(s, &s->palette, b, prev, data, + s->image_width * 3, s->dist, keyframe); #ifndef FLASHSV2_DUMB if (b->dirty) s->diff_blocks++; @@ -898,15 +910,15 @@ static av_cold int flashsv2_encode_end(AVCodecContext * avctx) return 0; } -const AVCodec ff_flashsv2_encoder = { - .name = "flashsv2", - .long_name = NULL_IF_CONFIG_SMALL("Flash Screen Video Version 2"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_FLASHSV2, +const FFCodec ff_flashsv2_encoder = { + .p.name = "flashsv2", + .p.long_name = NULL_IF_CONFIG_SMALL("Flash Screen Video Version 2"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_FLASHSV2, .priv_data_size = sizeof(FlashSV2Context), .init = flashsv2_encode_init, - .encode2 = flashsv2_encode_frame, + FF_CODEC_ENCODE_CB(flashsv2_encode_frame), .close = flashsv2_encode_end, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE }, + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/flashsvenc.c b/libavcodec/flashsvenc.c index 171a66ee1..592bb061c 100644 --- a/libavcodec/flashsvenc.c +++ b/libavcodec/flashsvenc.c @@ -49,8 +49,8 @@ #include #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "put_bits.h" #include "bytestream.h" @@ -257,15 +257,15 @@ static int flashsv_encode_frame(AVCodecContext *avctx, AVPacket *pkt, return 0; } -const AVCodec ff_flashsv_encoder = { - .name = "flashsv", - .long_name = NULL_IF_CONFIG_SMALL("Flash Screen Video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_FLASHSV, +const FFCodec ff_flashsv_encoder = { + .p.name = "flashsv", + .p.long_name = NULL_IF_CONFIG_SMALL("Flash Screen Video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_FLASHSV, .priv_data_size = sizeof(FlashSVContext), .init = flashsv_encode_init, - .encode2 = flashsv_encode_frame, + FF_CODEC_ENCODE_CB(flashsv_encode_frame), .close = flashsv_encode_end, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE }, + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/flicvideo.c b/libavcodec/flicvideo.c index e122fe231..b841050a8 100644 --- a/libavcodec/flicvideo.c +++ b/libavcodec/flicvideo.c @@ -41,6 +41,7 @@ #include "libavutil/intreadwrite.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" #include "mathops.h" @@ -148,7 +149,7 @@ static av_cold int flic_decode_init(AVCodecContext *avctx) } static int flic_decode_frame_8BPP(AVCodecContext *avctx, - void *data, int *got_frame, + AVFrame *rframe, int *got_frame, const uint8_t *buf, int buf_size) { FlicDecodeContext *s = avctx->priv_data; @@ -478,7 +479,7 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx, s->new_palette = 0; } - if ((ret = av_frame_ref(data, s->frame)) < 0) + if ((ret = av_frame_ref(rframe, s->frame)) < 0) return ret; *got_frame = 1; @@ -487,7 +488,7 @@ static int flic_decode_frame_8BPP(AVCodecContext *avctx, } static int flic_decode_frame_15_16BPP(AVCodecContext *avctx, - void *data, int *got_frame, + AVFrame *rframe, int *got_frame, const uint8_t *buf, int buf_size) { /* Note, the only difference between the 15Bpp and 16Bpp */ @@ -780,7 +781,7 @@ static int flic_decode_frame_15_16BPP(AVCodecContext *avctx, av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \ "and final chunk ptr = %d\n", buf_size, bytestream2_tell(&g2)); - if ((ret = av_frame_ref(data, s->frame)) < 0) + if ((ret = av_frame_ref(rframe, s->frame)) < 0) return ret; *got_frame = 1; @@ -789,7 +790,7 @@ static int flic_decode_frame_15_16BPP(AVCodecContext *avctx, } static int flic_decode_frame_24BPP(AVCodecContext *avctx, - void *data, int *got_frame, + AVFrame *rframe, int *got_frame, const uint8_t *buf, int buf_size) { FlicDecodeContext *s = avctx->priv_data; @@ -1060,7 +1061,7 @@ static int flic_decode_frame_24BPP(AVCodecContext *avctx, av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \ "and final chunk ptr = %d\n", buf_size, bytestream2_tell(&g2)); - if ((ret = av_frame_ref(data, s->frame)) < 0) + if ((ret = av_frame_ref(rframe, s->frame)) < 0) return ret; *got_frame = 1; @@ -1068,21 +1069,20 @@ static int flic_decode_frame_24BPP(AVCodecContext *avctx, return buf_size; } -static int flic_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int flic_decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; if (avctx->pix_fmt == AV_PIX_FMT_PAL8) { - return flic_decode_frame_8BPP(avctx, data, got_frame, + return flic_decode_frame_8BPP(avctx, frame, got_frame, buf, buf_size); } else if ((avctx->pix_fmt == AV_PIX_FMT_RGB555) || (avctx->pix_fmt == AV_PIX_FMT_RGB565)) { - return flic_decode_frame_15_16BPP(avctx, data, got_frame, + return flic_decode_frame_15_16BPP(avctx, frame, got_frame, buf, buf_size); } else if (avctx->pix_fmt == AV_PIX_FMT_BGR24) { - return flic_decode_frame_24BPP(avctx, data, got_frame, + return flic_decode_frame_24BPP(avctx, frame, got_frame, buf, buf_size); } @@ -1104,15 +1104,15 @@ static av_cold int flic_decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_flic_decoder = { - .name = "flic", - .long_name = NULL_IF_CONFIG_SMALL("Autodesk Animator Flic video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_FLIC, +const FFCodec ff_flic_decoder = { + .p.name = "flic", + .p.long_name = NULL_IF_CONFIG_SMALL("Autodesk Animator Flic video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_FLIC, .priv_data_size = sizeof(FlicDecodeContext), .init = flic_decode_init, .close = flic_decode_end, - .decode = flic_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(flic_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/flvdec.c b/libavcodec/flvdec.c index 6258c1c0a..cc016d129 100644 --- a/libavcodec/flvdec.c +++ b/libavcodec/flvdec.c @@ -20,8 +20,9 @@ #include "libavutil/imgutils.h" -#include "flv.h" -#include "h263.h" +#include "codec_internal.h" +#include "flvdec.h" +#include "h263dec.h" #include "mpegvideo.h" #include "mpegvideodata.h" @@ -90,7 +91,6 @@ int ff_flv_decode_picture_header(MpegEncContext *s) s->h263_plus = 0; - s->unrestricted_mv = 1; s->h263_long_vectors = 0; /* PEI */ @@ -113,18 +113,19 @@ int ff_flv_decode_picture_header(MpegEncContext *s) return 0; } -const AVCodec ff_flv_decoder = { - .name = "flv", - .long_name = NULL_IF_CONFIG_SMALL("FLV / Sorenson Spark / Sorenson H.263 (Flash Video)"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_FLV1, +const FFCodec ff_flv_decoder = { + .p.name = "flv", + .p.long_name = NULL_IF_CONFIG_SMALL("FLV / Sorenson Spark / Sorenson H.263 (Flash Video)"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_FLV1, .priv_data_size = sizeof(MpegEncContext), .init = ff_h263_decode_init, .close = ff_h263_decode_end, - .decode = ff_h263_decode_frame, - .capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1, - .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, - .max_lowres = 3, - .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, + FF_CODEC_DECODE_CB(ff_h263_decode_frame), + .p.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, + .p.max_lowres = 3, + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, }; diff --git a/libavcodec/flvdec.h b/libavcodec/flvdec.h new file mode 100644 index 000000000..d5aff74a9 --- /dev/null +++ b/libavcodec/flvdec.h @@ -0,0 +1,28 @@ +/* + * FLV decoder header. + * + * 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_FLVDEC_H +#define AVCODEC_FLVDEC_H + +#include "mpegvideo.h" + +int ff_flv_decode_picture_header(MpegEncContext *s); + +#endif /* AVCODEC_FLVDEC_H */ diff --git a/libavcodec/flvenc.c b/libavcodec/flvenc.c index 614ef2024..74ed321e2 100644 --- a/libavcodec/flvenc.c +++ b/libavcodec/flvenc.c @@ -18,11 +18,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "flv.h" -#include "h263.h" +#include "codec_internal.h" +#include "flvenc.h" #include "h263data.h" #include "mpegvideo.h" #include "mpegvideodata.h" +#include "mpegvideoenc.h" void ff_flv_encode_picture_header(MpegEncContext *s, int picture_number) { @@ -91,17 +92,17 @@ void ff_flv2_encode_ac_esc(PutBitContext *pb, int slevel, int level, } } -const AVCodec ff_flv_encoder = { - .name = "flv", - .long_name = NULL_IF_CONFIG_SMALL("FLV / Sorenson Spark / Sorenson H.263 (Flash Video)"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_FLV1, - .priv_class = &ff_mpv_enc_class, +const FFCodec ff_flv_encoder = { + .p.name = "flv", + .p.long_name = NULL_IF_CONFIG_SMALL("FLV / Sorenson Spark / Sorenson H.263 (Flash Video)"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_FLV1, + .p.priv_class = &ff_mpv_enc_class, .priv_data_size = sizeof(MpegEncContext), .init = ff_mpv_encode_init, - .encode2 = ff_mpv_encode_picture, + FF_CODEC_ENCODE_CB(ff_mpv_encode_picture), .close = ff_mpv_encode_end, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE}, }; diff --git a/libavcodec/flvenc.h b/libavcodec/flvenc.h new file mode 100644 index 000000000..aaa0fcffa --- /dev/null +++ b/libavcodec/flvenc.h @@ -0,0 +1,31 @@ +/* + * FLV encoder header. + * + * 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_FLVENC_H +#define AVCODEC_FLVENC_H + +#include "mpegvideo.h" +#include "put_bits.h" + +void ff_flv_encode_picture_header(MpegEncContext *s, int picture_number); +void ff_flv2_encode_ac_esc(PutBitContext *pb, int slevel, int level, int run, + int last); + +#endif /* AVCODEC_FLV_H */ diff --git a/libavcodec/fmtconvert.c b/libavcodec/fmtconvert.c index 3b33af61e..fd56a63c7 100644 --- a/libavcodec/fmtconvert.c +++ b/libavcodec/fmtconvert.c @@ -20,9 +20,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config.h" +#include "libavutil/attributes.h" #include "avcodec.h" #include "fmtconvert.h" -#include "libavutil/common.h" static void int32_to_float_fmul_scalar_c(float *dst, const int32_t *src, float mul, int len) @@ -55,14 +56,16 @@ av_cold void ff_fmt_convert_init(FmtConvertContext *c, AVCodecContext *avctx) c->int32_to_float_fmul_scalar = int32_to_float_fmul_scalar_c; c->int32_to_float_fmul_array8 = int32_to_float_fmul_array8_c; - if (ARCH_AARCH64) - ff_fmt_convert_init_aarch64(c, avctx); - if (ARCH_ARM) - ff_fmt_convert_init_arm(c, avctx); - if (ARCH_PPC) - ff_fmt_convert_init_ppc(c, avctx); - if (ARCH_X86) - ff_fmt_convert_init_x86(c, avctx); - if (HAVE_MIPSFPU) - ff_fmt_convert_init_mips(c); +#if ARCH_AARCH64 + ff_fmt_convert_init_aarch64(c, avctx); +#elif ARCH_ARM + ff_fmt_convert_init_arm(c, avctx); +#elif ARCH_PPC + ff_fmt_convert_init_ppc(c, avctx); +#elif ARCH_X86 + ff_fmt_convert_init_x86(c, avctx); +#endif +#if HAVE_MIPSFPU + ff_fmt_convert_init_mips(c); +#endif } diff --git a/libavcodec/fmvc.c b/libavcodec/fmvc.c index aab46da9c..4abf6d704 100644 --- a/libavcodec/fmvc.c +++ b/libavcodec/fmvc.c @@ -26,6 +26,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" #define BLOCK_HEIGHT 112u @@ -393,13 +394,12 @@ static int decode_type1(GetByteContext *gb, PutByteContext *pb) return 0; } -static int decode_frame(AVCodecContext *avctx, void *data, +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, 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 (avpkt->size < 8) @@ -626,16 +626,16 @@ static av_cold int decode_close(AVCodecContext *avctx) return 0; } -const 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, +const FFCodec ff_fmvc_decoder = { + .p.name = "fmvc", + .p.long_name = NULL_IF_CONFIG_SMALL("FM Screen Capture Codec"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_FMVC, .priv_data_size = sizeof(FMVCContext), .init = decode_init, .close = decode_close, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/frame_thread_encoder.c b/libavcodec/frame_thread_encoder.c index d4f86f741..07d310a98 100644 --- a/libavcodec/frame_thread_encoder.c +++ b/libavcodec/frame_thread_encoder.c @@ -28,6 +28,7 @@ #include "libavutil/opt.h" #include "libavutil/thread.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "pthread_internal.h" #include "thread.h" @@ -103,7 +104,7 @@ static void * attribute_align_arg worker(void *v){ frame = task->indata; pkt = task->outdata; - ret = avctx->codec->encode2(avctx, pkt, frame, &got_packet); + ret = ffcodec(avctx->codec)->cb.encode(avctx, pkt, frame, &got_packet); if(got_packet) { int ret2 = av_packet_make_refcounted(pkt); if (ret >= 0 && ret2 < 0) diff --git a/libavcodec/fraps.c b/libavcodec/fraps.c index b3262a4b2..7f695305f 100644 --- a/libavcodec/fraps.c +++ b/libavcodec/fraps.c @@ -40,7 +40,7 @@ #include "huffman.h" #include "bytestream.h" #include "bswapdsp.h" -#include "internal.h" +#include "codec_internal.h" #include "thread.h" #define FPS_TAG MKTAG('F', 'P', 'S', 'x') @@ -133,15 +133,12 @@ static int fraps2_decode_plane(FrapsContext *s, uint8_t *dst, int stride, int w, return 0; } -static int decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *f, + int *got_frame, AVPacket *avpkt) { FrapsContext * const s = avctx->priv_data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; - ThreadFrame frame = { .f = data }; - AVFrame * const f = data; uint32_t header; unsigned int version,header_size; unsigned int x, y; @@ -227,7 +224,7 @@ static int decode_frame(AVCodecContext *avctx, : AVCOL_RANGE_JPEG; avctx->colorspace = version & 1 ? AVCOL_SPC_UNSPECIFIED : AVCOL_SPC_BT709; - if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, f, 0)) < 0) return ret; switch (version) { @@ -342,15 +339,15 @@ static av_cold int decode_end(AVCodecContext *avctx) } -const AVCodec ff_fraps_decoder = { - .name = "fraps", - .long_name = NULL_IF_CONFIG_SMALL("Fraps"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_FRAPS, +const FFCodec ff_fraps_decoder = { + .p.name = "fraps", + .p.long_name = NULL_IF_CONFIG_SMALL("Fraps"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_FRAPS, .priv_data_size = sizeof(FrapsContext), .init = decode_init, .close = decode_end, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/frwu.c b/libavcodec/frwu.c index 82a8ec211..766fda745 100644 --- a/libavcodec/frwu.c +++ b/libavcodec/frwu.c @@ -22,6 +22,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" #include "libavutil/opt.h" @@ -41,12 +42,11 @@ static av_cold int decode_init(AVCodecContext *avctx) return 0; } -static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *pic, + int *got_frame, AVPacket *avpkt) { FRWUContext *s = avctx->priv_data; int field, ret; - AVFrame *pic = data; const uint8_t *buf = avpkt->data; const uint8_t *buf_end = buf + avpkt->size; @@ -115,15 +115,15 @@ static const AVClass frwu_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_frwu_decoder = { - .name = "frwu", - .long_name = NULL_IF_CONFIG_SMALL("Forward Uncompressed"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_FRWU, +const FFCodec ff_frwu_decoder = { + .p.name = "frwu", + .p.long_name = NULL_IF_CONFIG_SMALL("Forward Uncompressed"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_FRWU, .priv_data_size = sizeof(FRWUContext), .init = decode_init, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, - .priv_class = &frwu_class, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, + .p.priv_class = &frwu_class, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/g2meet.c b/libavcodec/g2meet.c index 4c53838af..00964369c 100644 --- a/libavcodec/g2meet.c +++ b/libavcodec/g2meet.c @@ -35,6 +35,7 @@ #include "avcodec.h" #include "blockdsp.h" #include "bytestream.h" +#include "codec_internal.h" #include "elsdec.h" #include "get_bits.h" #include "idctdsp.h" @@ -1371,13 +1372,12 @@ static void g2m_paint_cursor(G2MContext *c, uint8_t *dst, int stride) } } -static int g2m_decode_frame(AVCodecContext *avctx, void *data, +static int g2m_decode_frame(AVCodecContext *avctx, AVFrame *pic, int *got_picture_ptr, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; G2MContext *c = avctx->priv_data; - AVFrame *pic = data; GetByteContext bc, tbc; int magic; int got_header = 0; @@ -1592,7 +1592,6 @@ static av_cold int g2m_decode_init(AVCodecContext *avctx) if ((ret = jpg_init(avctx, &c->jc)) != 0) { av_log(avctx, AV_LOG_ERROR, "Cannot initialise VLCs\n"); - jpg_free_context(&c->jc); return AVERROR(ENOMEM); } @@ -1623,15 +1622,15 @@ static av_cold int g2m_decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_g2m_decoder = { - .name = "g2m", - .long_name = NULL_IF_CONFIG_SMALL("Go2Meeting"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_G2M, +const FFCodec ff_g2m_decoder = { + .p.name = "g2m", + .p.long_name = NULL_IF_CONFIG_SMALL("Go2Meeting"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_G2M, .priv_data_size = sizeof(G2MContext), .init = g2m_decode_init, .close = g2m_decode_end, - .decode = g2m_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + FF_CODEC_DECODE_CB(g2m_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/g722dec.c b/libavcodec/g722dec.c index 5ca0d0e2b..8a02ec523 100644 --- a/libavcodec/g722dec.c +++ b/libavcodec/g722dec.c @@ -37,6 +37,7 @@ #include "libavutil/channel_layout.h" #include "libavutil/opt.h" #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" #include "g722.h" #include "internal.h" @@ -59,8 +60,8 @@ static av_cold int g722_decode_init(AVCodecContext * avctx) { G722Context *c = avctx->priv_data; - avctx->channels = 1; - avctx->channel_layout = AV_CH_LAYOUT_MONO; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; avctx->sample_fmt = AV_SAMPLE_FMT_S16; c->band[0].scale_factor = 8; @@ -83,11 +84,10 @@ static const int16_t * const low_inv_quants[3] = { ff_g722_low_inv_quant6, low_inv_quant5, ff_g722_low_inv_quant4 }; -static int g722_decode_frame(AVCodecContext *avctx, void *data, +static int g722_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { G722Context *c = avctx->priv_data; - AVFrame *frame = data; int16_t *out_buf; int j, ret; const int skip = 8 - c->bits_per_codeword; @@ -139,15 +139,15 @@ static int g722_decode_frame(AVCodecContext *avctx, void *data, return avpkt->size; } -const AVCodec ff_adpcm_g722_decoder = { - .name = "g722", - .long_name = NULL_IF_CONFIG_SMALL("G.722 ADPCM"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_ADPCM_G722, +const FFCodec ff_adpcm_g722_decoder = { + .p.name = "g722", + .p.long_name = NULL_IF_CONFIG_SMALL("G.722 ADPCM"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_ADPCM_G722, .priv_data_size = sizeof(G722Context), .init = g722_decode_init, - .decode = g722_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, - .priv_class = &g722_decoder_class, + FF_CODEC_DECODE_CB(g722_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .p.priv_class = &g722_decoder_class, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/g722dsp.c b/libavcodec/g722dsp.c index f1480536d..c770bfbdf 100644 --- a/libavcodec/g722dsp.c +++ b/libavcodec/g722dsp.c @@ -69,8 +69,9 @@ av_cold void ff_g722dsp_init(G722DSPContext *c) { c->apply_qmf = g722_apply_qmf; - if (ARCH_ARM) - ff_g722dsp_init_arm(c); - if (ARCH_X86) - ff_g722dsp_init_x86(c); +#if ARCH_ARM + ff_g722dsp_init_arm(c); +#elif ARCH_X86 + ff_g722dsp_init_x86(c); +#endif } diff --git a/libavcodec/g722enc.c b/libavcodec/g722enc.c index 75b926ef8..325c3927d 100644 --- a/libavcodec/g722enc.c +++ b/libavcodec/g722enc.c @@ -30,6 +30,7 @@ #include "libavutil/avassert.h" #include "libavutil/channel_layout.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" #include "internal.h" #include "g722.h" @@ -370,17 +371,22 @@ static int g722_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, return 0; } -const AVCodec ff_adpcm_g722_encoder = { - .name = "g722", - .long_name = NULL_IF_CONFIG_SMALL("G.722 ADPCM"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_ADPCM_G722, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME, +const FFCodec ff_adpcm_g722_encoder = { + .p.name = "g722", + .p.long_name = NULL_IF_CONFIG_SMALL("G.722 ADPCM"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_ADPCM_G722, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME, .priv_data_size = sizeof(G722Context), .init = g722_encode_init, .close = g722_encode_close, - .encode2 = g722_encode_frame, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, - .channel_layouts = (const uint64_t[]){ AV_CH_LAYOUT_MONO, 0 }, + FF_CODEC_ENCODE_CB(g722_encode_frame), + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, +#if FF_API_OLD_CHANNEL_LAYOUT + .p.channel_layouts = (const uint64_t[]){ AV_CH_LAYOUT_MONO, 0 }, +#endif + .p.ch_layouts = (const AVChannelLayout[]){ + AV_CHANNEL_LAYOUT_MONO, { 0 } + }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/g723_1_parser.c b/libavcodec/g723_1_parser.c index b6b3fcb84..2ed1a8ab1 100644 --- a/libavcodec/g723_1_parser.c +++ b/libavcodec/g723_1_parser.c @@ -37,7 +37,7 @@ static int g723_1_parse(AVCodecParserContext *s1, AVCodecContext *avctx, int next = END_NOT_FOUND; if (buf_size > 0) - next = frame_size[buf[0] & 3] * FFMAX(1, avctx->channels); + next = frame_size[buf[0] & 3] * FFMAX(1, avctx->ch_layout.nb_channels); if (ff_combine_frame(pc, next, &buf, &buf_size) < 0 || !buf_size) { *poutbuf = NULL; diff --git a/libavcodec/g723_1dec.c b/libavcodec/g723_1dec.c index 7d75adbd7..d095f09fe 100644 --- a/libavcodec/g723_1dec.c +++ b/libavcodec/g723_1dec.c @@ -34,6 +34,7 @@ #include "avcodec.h" #include "celp_filters.h" #include "celp_math.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" #include "g723_1.h" @@ -117,12 +118,12 @@ static av_cold int g723_1_decode_init(AVCodecContext *avctx) G723_1_Context *s = avctx->priv_data; avctx->sample_fmt = AV_SAMPLE_FMT_S16P; - if (avctx->channels < 1 || avctx->channels > 2) { - av_log(avctx, AV_LOG_ERROR, "Only mono and stereo are supported (requested channels: %d).\n", avctx->channels); + if (avctx->ch_layout.nb_channels < 1 || avctx->ch_layout.nb_channels > 2) { + av_log(avctx, AV_LOG_ERROR, "Only mono and stereo are supported (requested channels: %d).\n", + avctx->ch_layout.nb_channels); return AVERROR(EINVAL); } - avctx->channel_layout = avctx->channels == 1 ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO; - for (int ch = 0; ch < avctx->channels; ch++) { + for (int ch = 0; ch < avctx->ch_layout.nb_channels; ch++) { G723_1_ChannelContext *p = &s->ch[ch]; p->pf_gain = 1 << 12; @@ -924,14 +925,14 @@ static void generate_noise(G723_1_ChannelContext *p) PITCH_MAX * sizeof(*p->excitation)); } -static int g723_1_decode_frame(AVCodecContext *avctx, void *data, +static int g723_1_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { G723_1_Context *s = avctx->priv_data; - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; int dec_mode = buf[0] & 3; + int channels = avctx->ch_layout.nb_channels; PPFParam ppf[SUBFRAMES]; int16_t cur_lsp[LPC_ORDER]; @@ -940,7 +941,7 @@ static int g723_1_decode_frame(AVCodecContext *avctx, void *data, int16_t *out; int bad_frame = 0, i, j, ret; - if (buf_size < frame_size[dec_mode] * avctx->channels) { + if (buf_size < frame_size[dec_mode] * channels) { if (buf_size) av_log(avctx, AV_LOG_WARNING, "Expected %d bytes, got %d - skipping packet\n", @@ -953,12 +954,12 @@ static int g723_1_decode_frame(AVCodecContext *avctx, void *data, if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; - for (int ch = 0; ch < avctx->channels; ch++) { + for (int ch = 0; ch < channels; ch++) { G723_1_ChannelContext *p = &s->ch[ch]; int16_t *audio = p->audio; - if (unpack_bitstream(p, buf + ch * (buf_size / avctx->channels), - buf_size / avctx->channels) < 0) { + if (unpack_bitstream(p, buf + ch * (buf_size / channels), + buf_size / channels) < 0) { bad_frame = 1; if (p->past_frame_type == ACTIVE_FRAME) p->cur_frame_type = ACTIVE_FRAME; @@ -1090,7 +1091,7 @@ static int g723_1_decode_frame(AVCodecContext *avctx, void *data, *got_frame_ptr = 1; - return frame_size[dec_mode] * avctx->channels; + return frame_size[dec_mode] * channels; } #define OFFSET(x) offsetof(G723_1_Context, x) @@ -1110,15 +1111,15 @@ static const AVClass g723_1dec_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_g723_1_decoder = { - .name = "g723_1", - .long_name = NULL_IF_CONFIG_SMALL("G.723.1"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_G723_1, +const FFCodec ff_g723_1_decoder = { + .p.name = "g723_1", + .p.long_name = NULL_IF_CONFIG_SMALL("G.723.1"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_G723_1, .priv_data_size = sizeof(G723_1_Context), .init = g723_1_decode_init, - .decode = g723_1_decode_frame, - .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1, - .priv_class = &g723_1dec_class, + FF_CODEC_DECODE_CB(g723_1_decode_frame), + .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1, + .p.priv_class = &g723_1dec_class, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/g723_1enc.c b/libavcodec/g723_1enc.c index 2a8149b4c..e8fb8429c 100644 --- a/libavcodec/g723_1enc.c +++ b/libavcodec/g723_1enc.c @@ -34,9 +34,9 @@ #include "avcodec.h" #include "celp_math.h" +#include "codec_internal.h" #include "encode.h" #include "g723_1.h" -#include "internal.h" #define BITSTREAM_WRITER_LE #include "put_bits.h" @@ -99,11 +99,6 @@ static av_cold int g723_1_encode_init(AVCodecContext *avctx) return AVERROR(EINVAL); } - if (avctx->channels != 1) { - av_log(avctx, AV_LOG_ERROR, "Only mono supported\n"); - return AVERROR(EINVAL); - } - if (avctx->bit_rate == 6300) { p->cur_rate = RATE_6300; } else if (avctx->bit_rate == 5300) { @@ -1238,23 +1233,26 @@ static int g723_1_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, return 0; } -static const AVCodecDefault defaults[] = { +static const FFCodecDefault defaults[] = { { "b", "6300" }, { NULL }, }; -const AVCodec ff_g723_1_encoder = { - .name = "g723_1", - .long_name = NULL_IF_CONFIG_SMALL("G.723.1"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_G723_1, - .capabilities = AV_CODEC_CAP_DR1, +const FFCodec ff_g723_1_encoder = { + .p.name = "g723_1", + .p.long_name = NULL_IF_CONFIG_SMALL("G.723.1"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_G723_1, + .p.capabilities = AV_CODEC_CAP_DR1, .priv_data_size = sizeof(G723_1_Context), .init = g723_1_encode_init, - .encode2 = g723_1_encode_frame, + FF_CODEC_ENCODE_CB(g723_1_encode_frame), .defaults = defaults, - .sample_fmts = (const enum AVSampleFormat[]) { + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, + .p.ch_layouts = (const AVChannelLayout[]){ + AV_CHANNEL_LAYOUT_MONO, { 0 } + }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/g726.c b/libavcodec/g726.c index 2a0148c1d..3bf0da394 100644 --- a/libavcodec/g726.c +++ b/libavcodec/g726.c @@ -21,11 +21,15 @@ * 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_components.h" + #include #include "libavutil/channel_layout.h" #include "libavutil/opt.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" #include "internal.h" #include "get_bits.h" @@ -324,7 +328,7 @@ static av_cold int g726_encode_init(AVCodecContext *avctx) return AVERROR(EINVAL); } - if(avctx->channels != 1){ + if (avctx->ch_layout.nb_channels != 1) { av_log(avctx, AV_LOG_ERROR, "Only mono is supported\n"); return AVERROR(EINVAL); } @@ -389,43 +393,43 @@ static const AVClass g726_class = { .version = LIBAVUTIL_VERSION_INT, }; -static const AVCodecDefault defaults[] = { +static const FFCodecDefault defaults[] = { { "b", "0" }, { NULL }, }; #endif #if CONFIG_ADPCM_G726_ENCODER -const AVCodec ff_adpcm_g726_encoder = { - .name = "g726", - .long_name = NULL_IF_CONFIG_SMALL("G.726 ADPCM"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_ADPCM_G726, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME, +const FFCodec ff_adpcm_g726_encoder = { + .p.name = "g726", + .p.long_name = NULL_IF_CONFIG_SMALL("G.726 ADPCM"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_ADPCM_G726, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME, .priv_data_size = sizeof(G726Context), .init = g726_encode_init, - .encode2 = g726_encode_frame, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + FF_CODEC_ENCODE_CB(g726_encode_frame), + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, - .priv_class = &g726_class, + .p.priv_class = &g726_class, .defaults = defaults, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_ADPCM_G726LE_ENCODER -const AVCodec ff_adpcm_g726le_encoder = { - .name = "g726le", - .long_name = NULL_IF_CONFIG_SMALL("G.726 little endian ADPCM (\"right-justified\")"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_ADPCM_G726LE, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME, +const FFCodec ff_adpcm_g726le_encoder = { + .p.name = "g726le", + .p.long_name = NULL_IF_CONFIG_SMALL("G.726 little endian ADPCM (\"right-justified\")"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_ADPCM_G726LE, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME, .priv_data_size = sizeof(G726Context), .init = g726_encode_init, - .encode2 = g726_encode_frame, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + FF_CODEC_ENCODE_CB(g726_encode_frame), + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, - .priv_class = &g726_class, + .p.priv_class = &g726_class, .defaults = defaults, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; @@ -436,12 +440,12 @@ static av_cold int g726_decode_init(AVCodecContext *avctx) { G726Context* c = avctx->priv_data; - if(avctx->channels > 1){ + if (avctx->ch_layout.nb_channels > 1){ avpriv_request_sample(avctx, "Decoding more than one channel"); return AVERROR_PATCHWELCOME; } - avctx->channels = 1; - avctx->channel_layout = AV_CH_LAYOUT_MONO; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; c->little_endian = !strcmp(avctx->codec->name, "g726le"); @@ -457,10 +461,9 @@ static av_cold int g726_decode_init(AVCodecContext *avctx) return 0; } -static int g726_decode_frame(AVCodecContext *avctx, void *data, +static int g726_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; G726Context *c = avctx->priv_data; @@ -499,31 +502,31 @@ static void g726_decode_flush(AVCodecContext *avctx) #endif #if CONFIG_ADPCM_G726_DECODER -const AVCodec ff_adpcm_g726_decoder = { - .name = "g726", - .long_name = NULL_IF_CONFIG_SMALL("G.726 ADPCM"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_ADPCM_G726, +const FFCodec ff_adpcm_g726_decoder = { + .p.name = "g726", + .p.long_name = NULL_IF_CONFIG_SMALL("G.726 ADPCM"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_ADPCM_G726, .priv_data_size = sizeof(G726Context), .init = g726_decode_init, - .decode = g726_decode_frame, + FF_CODEC_DECODE_CB(g726_decode_frame), .flush = g726_decode_flush, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_ADPCM_G726LE_DECODER -const AVCodec ff_adpcm_g726le_decoder = { - .name = "g726le", - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_ADPCM_G726LE, +const FFCodec ff_adpcm_g726le_decoder = { + .p.name = "g726le", + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_ADPCM_G726LE, .priv_data_size = sizeof(G726Context), .init = g726_decode_init, - .decode = g726_decode_frame, + FF_CODEC_DECODE_CB(g726_decode_frame), .flush = g726_decode_flush, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, - .long_name = NULL_IF_CONFIG_SMALL("G.726 ADPCM little-endian"), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .p.long_name = NULL_IF_CONFIG_SMALL("G.726 ADPCM little-endian"), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif diff --git a/libavcodec/g729_parser.c b/libavcodec/g729_parser.c index 4dcdeab65..d51a78877 100644 --- a/libavcodec/g729_parser.c +++ b/libavcodec/g729_parser.c @@ -49,9 +49,9 @@ static int g729_parse(AVCodecParserContext *s1, AVCodecContext *avctx, if (avctx->codec_id == AV_CODEC_ID_ACELP_KELVIN) s->block_size++; // channels > 2 is invalid, we pass the packet on unchanged - if (avctx->channels > 2) + if (avctx->ch_layout.nb_channels > 2) s->block_size = 0; - s->block_size *= avctx->channels; + s->block_size *= avctx->ch_layout.nb_channels; s->duration = avctx->frame_size; } diff --git a/libavcodec/g729dec.c b/libavcodec/g729dec.c index 7525ab749..a306456f0 100644 --- a/libavcodec/g729dec.c +++ b/libavcodec/g729dec.c @@ -26,6 +26,7 @@ #include "libavutil/avutil.h" #include "get_bits.h" #include "audiodsp.h" +#include "codec_internal.h" #include "internal.h" @@ -350,10 +351,11 @@ static av_cold int decoder_init(AVCodecContext * avctx) { G729Context *s = avctx->priv_data; G729ChannelContext *ctx; + int channels = avctx->ch_layout.nb_channels; int c,i,k; - if (avctx->channels < 1 || avctx->channels > 2) { - av_log(avctx, AV_LOG_ERROR, "Only mono and stereo are supported (requested channels: %d).\n", avctx->channels); + if (channels < 1 || channels > 2) { + av_log(avctx, AV_LOG_ERROR, "Only mono and stereo are supported (requested channels: %d).\n", channels); return AVERROR(EINVAL); } avctx->sample_fmt = AV_SAMPLE_FMT_S16P; @@ -362,11 +364,11 @@ static av_cold int decoder_init(AVCodecContext * avctx) avctx->frame_size = SUBFRAME_SIZE << 1; ctx = - s->channel_context = av_mallocz(sizeof(G729ChannelContext) * avctx->channels); + s->channel_context = av_mallocz(sizeof(G729ChannelContext) * channels); if (!ctx) return AVERROR(ENOMEM); - for (c = 0; c < avctx->channels; c++) { + for (c = 0; c < channels; c++) { ctx->gain_coeff = 16384; // 1.0 in (1.14) for (k = 0; k < MA_NP + 1; k++) { @@ -399,8 +401,8 @@ static av_cold int decoder_init(AVCodecContext * avctx) return 0; } -static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame_ptr, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; @@ -412,6 +414,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, G729Formats packet_type; G729Context *s = avctx->priv_data; G729ChannelContext *ctx = s->channel_context; + int channels = avctx->ch_layout.nb_channels; int16_t lp[2][11]; // (3.12) uint8_t ma_predictor; ///< switched MA predictor of LSP quantizer uint8_t quantizer_1st; ///< first stage vector of quantizer @@ -424,20 +427,19 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, int16_t synth[SUBFRAME_SIZE+10]; // fixed-codebook vector int j, ret; int gain_before, gain_after; - AVFrame *frame = data; frame->nb_samples = SUBFRAME_SIZE<<1; if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; - if (buf_size && buf_size % ((G729_8K_BLOCK_SIZE + (avctx->codec_id == AV_CODEC_ID_ACELP_KELVIN)) * avctx->channels) == 0) { + if (buf_size && buf_size % ((G729_8K_BLOCK_SIZE + (avctx->codec_id == AV_CODEC_ID_ACELP_KELVIN)) * channels) == 0) { packet_type = FORMAT_G729_8K; format = &format_g729_8k; //Reset voice decision ctx->onset = 0; ctx->voice_decision = DECISION_VOICE; av_log(avctx, AV_LOG_DEBUG, "Packet type: %s\n", "G.729 @ 8kbit/s"); - } else if (buf_size == G729D_6K4_BLOCK_SIZE * avctx->channels && avctx->codec_id != AV_CODEC_ID_ACELP_KELVIN) { + } else if (buf_size == G729D_6K4_BLOCK_SIZE * channels && avctx->codec_id != AV_CODEC_ID_ACELP_KELVIN) { packet_type = FORMAT_G729D_6K4; format = &format_g729d_6k4; av_log(avctx, AV_LOG_DEBUG, "Packet type: %s\n", "G.729D @ 6.4kbit/s"); @@ -446,13 +448,13 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, return AVERROR_INVALIDDATA; } - for (c = 0; c < avctx->channels; c++) { + for (c = 0; c < channels; c++) { int frame_erasure = 0; ///< frame erasure detected during decoding int bad_pitch = 0; ///< parity check failed int is_periodic = 0; ///< whether one of the subframes is declared as periodic or not out_frame = (int16_t*)frame->data[c]; if (avctx->codec_id == AV_CODEC_ID_ACELP_KELVIN) { - if (*buf != ((avctx->channels - 1 - c) * 0x80 | 2)) + if (*buf != ((avctx->ch_layout.nb_channels - 1 - c) * 0x80 | 2)) avpriv_request_sample(avctx, "First byte value %x for channel %d", *buf, c); buf++; } @@ -739,7 +741,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, } *got_frame_ptr = 1; - return (format->block_size + (avctx->codec_id == AV_CODEC_ID_ACELP_KELVIN)) * avctx->channels; + return (format->block_size + (avctx->codec_id == AV_CODEC_ID_ACELP_KELVIN)) * channels; } static av_cold int decode_close(AVCodecContext *avctx) @@ -750,28 +752,28 @@ static av_cold int decode_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_g729_decoder = { - .name = "g729", - .long_name = NULL_IF_CONFIG_SMALL("G.729"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_G729, +const FFCodec ff_g729_decoder = { + .p.name = "g729", + .p.long_name = NULL_IF_CONFIG_SMALL("G.729"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_G729, .priv_data_size = sizeof(G729Context), .init = decoder_init, - .decode = decode_frame, + FF_CODEC_DECODE_CB(decode_frame), .close = decode_close, - .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; -const AVCodec ff_acelp_kelvin_decoder = { - .name = "acelp.kelvin", - .long_name = NULL_IF_CONFIG_SMALL("Sipro ACELP.KELVIN"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_ACELP_KELVIN, +const FFCodec ff_acelp_kelvin_decoder = { + .p.name = "acelp.kelvin", + .p.long_name = NULL_IF_CONFIG_SMALL("Sipro ACELP.KELVIN"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_ACELP_KELVIN, .priv_data_size = sizeof(G729Context), .init = decoder_init, - .decode = decode_frame, + FF_CODEC_DECODE_CB(decode_frame), .close = decode_close, - .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/gdv.c b/libavcodec/gdv.c index 222e604c8..70c2ad4bd 100644 --- a/libavcodec/gdv.c +++ b/libavcodec/gdv.c @@ -23,6 +23,7 @@ #include "libavutil/common.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "decode.h" #include "internal.h" @@ -455,13 +456,12 @@ static int decompress_68(AVCodecContext *avctx, unsigned skip, unsigned use8) return 0; } -static int gdv_decode_frame(AVCodecContext *avctx, void *data, +static int gdv_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt) { GDVContext *gdv = avctx->priv_data; GetByteContext *gb = &gdv->gb; PutByteContext *pb = &gdv->pb; - AVFrame *frame = data; int ret, i; int compression; unsigned flags; @@ -560,15 +560,15 @@ static av_cold int gdv_decode_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_gdv_decoder = { - .name = "gdv", - .long_name = NULL_IF_CONFIG_SMALL("Gremlin Digital Video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_GDV, +const FFCodec ff_gdv_decoder = { + .p.name = "gdv", + .p.long_name = NULL_IF_CONFIG_SMALL("Gremlin Digital Video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_GDV, .priv_data_size = sizeof(GDVContext), .init = gdv_decode_init, .close = gdv_decode_close, - .decode = gdv_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(gdv_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/gemdec.c b/libavcodec/gemdec.c index fd14b2239..0d6acd530 100644 --- a/libavcodec/gemdec.c +++ b/libavcodec/gemdec.c @@ -26,6 +26,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" static const uint32_t gem_color_palette[16]={ @@ -84,14 +85,12 @@ static void put_lines_bytes(AVCodecContext *avctx, int planes, int row_width, in state->vdup = 1; } -static int gem_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int gem_decode_frame(AVCodecContext *avctx, AVFrame *p, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; const uint8_t *buf_end = buf + buf_size; - AVFrame *p = data; int header_size, planes, pattern_size, tag = 0, count_scalar = 1, ret; unsigned int x, count, v; GetByteContext gb; @@ -351,12 +350,12 @@ static av_cold int gem_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_gem_decoder = { - .name = "gem", - .long_name = NULL_IF_CONFIG_SMALL("GEM Raster image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_GEM, - .decode = gem_decode_frame, +const FFCodec ff_gem_decoder = { + .p.name = "gem", + .p.long_name = NULL_IF_CONFIG_SMALL("GEM Raster image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_GEM, + .p.capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(gem_decode_frame), .close = gem_close, - .capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/get_bits.h b/libavcodec/get_bits.h index d4e9276da..992765dc9 100644 --- a/libavcodec/get_bits.h +++ b/libavcodec/get_bits.h @@ -31,7 +31,6 @@ #include "libavutil/common.h" #include "libavutil/intreadwrite.h" -#include "libavutil/log.h" #include "libavutil/avassert.h" #include "defs.h" @@ -610,16 +609,6 @@ static inline unsigned int show_bits_long(GetBitContext *s, int n) } } -static inline int check_marker(void *logctx, GetBitContext *s, const char *msg) -{ - int bit = get_bits1(s); - if (!bit) - av_log(logctx, AV_LOG_INFO, "Marker bit missing at %d of %d %s\n", - get_bits_count(s) - 1, s->size_in_bits, msg); - - return bit; -} - static inline int init_get_bits_xe(GetBitContext *s, const uint8_t *buffer, int bit_size, int is_le) { @@ -710,8 +699,8 @@ static inline const uint8_t *align_get_bits(GetBitContext *s) unsigned int index; \ \ index = SHOW_UBITS(name, gb, bits); \ - code = table[index][0]; \ - n = table[index][1]; \ + code = table[index].sym; \ + n = table[index].len; \ \ if (max_depth > 1 && n < 0) { \ LAST_SKIP_BITS(name, gb, bits); \ @@ -720,8 +709,8 @@ static inline const uint8_t *align_get_bits(GetBitContext *s) nb_bits = -n; \ \ index = SHOW_UBITS(name, gb, nb_bits) + code; \ - code = table[index][0]; \ - n = table[index][1]; \ + code = table[index].sym; \ + n = table[index].len; \ if (max_depth > 2 && n < 0) { \ LAST_SKIP_BITS(name, gb, nb_bits); \ UPDATE_CACHE(name, gb); \ @@ -729,8 +718,8 @@ static inline const uint8_t *align_get_bits(GetBitContext *s) nb_bits = -n; \ \ index = SHOW_UBITS(name, gb, nb_bits) + code; \ - code = table[index][0]; \ - n = table[index][1]; \ + code = table[index].sym; \ + n = table[index].len; \ } \ } \ SKIP_BITS(name, gb, n); \ @@ -775,15 +764,15 @@ static inline const uint8_t *align_get_bits(GetBitContext *s) /* Return the LUT element for the given bitstream configuration. */ static inline int set_idx(GetBitContext *s, int code, int *n, int *nb_bits, - VLC_TYPE (*table)[2]) + const VLCElem *table) { unsigned idx; *nb_bits = -*n; idx = show_bits(s, *nb_bits) + code; - *n = table[idx][1]; + *n = table[idx].len; - return table[idx][0]; + return table[idx].sym; } /** @@ -795,14 +784,14 @@ static inline int set_idx(GetBitContext *s, int code, int *n, int *nb_bits, * = (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], +static av_always_inline int get_vlc2(GetBitContext *s, const VLCElem *table, int bits, int max_depth) { #if CACHED_BITSTREAM_READER int nb_bits; unsigned idx = show_bits(s, bits); - int code = table[idx][0]; - int n = table[idx][1]; + int code = table[idx].sym; + int n = table[idx].len; if (max_depth > 1 && n < 0) { skip_remaining(s, bits); diff --git a/libavcodec/get_buffer.c b/libavcodec/get_buffer.c new file mode 100644 index 000000000..3e45a0479 --- /dev/null +++ b/libavcodec/get_buffer.c @@ -0,0 +1,312 @@ +/* + * The default get_buffer2() implementation + * + * 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/avutil.h" +#include "libavutil/buffer.h" +#include "libavutil/frame.h" +#include "libavutil/hwcontext.h" +#include "libavutil/imgutils.h" +#include "libavutil/mem.h" +#include "libavutil/samplefmt.h" +#include "libavutil/version.h" + +#include "avcodec.h" +#include "internal.h" + +typedef struct FramePool { + /** + * Pools for each data plane. For audio all the planes have the same size, + * so only pools[0] is used. + */ + AVBufferPool *pools[4]; + + /* + * Pool parameters + */ + int format; + int width, height; + int stride_align[AV_NUM_DATA_POINTERS]; + int linesize[4]; + int planes; + int channels; + int samples; +} FramePool; + +static void frame_pool_free(void *opaque, uint8_t *data) +{ + FramePool *pool = (FramePool*)data; + int i; + + for (i = 0; i < FF_ARRAY_ELEMS(pool->pools); i++) + av_buffer_pool_uninit(&pool->pools[i]); + + av_freep(&data); +} + +static AVBufferRef *frame_pool_alloc(void) +{ + FramePool *pool = av_mallocz(sizeof(*pool)); + AVBufferRef *buf; + + if (!pool) + return NULL; + + buf = av_buffer_create((uint8_t*)pool, sizeof(*pool), + frame_pool_free, NULL, 0); + if (!buf) { + av_freep(&pool); + return NULL; + } + + return buf; +} + +static int update_frame_pool(AVCodecContext *avctx, AVFrame *frame) +{ + FramePool *pool = avctx->internal->pool ? + (FramePool*)avctx->internal->pool->data : NULL; + AVBufferRef *pool_buf; + int i, ret, ch, planes; + + if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) { + int planar = av_sample_fmt_is_planar(frame->format); + ch = frame->ch_layout.nb_channels; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + if (!ch) + ch = frame->channels; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + planes = planar ? ch : 1; + } + + if (pool && pool->format == frame->format) { + if (avctx->codec_type == AVMEDIA_TYPE_VIDEO && + pool->width == frame->width && pool->height == frame->height) + return 0; + if (avctx->codec_type == AVMEDIA_TYPE_AUDIO && pool->planes == planes && + pool->channels == ch && frame->nb_samples == pool->samples) + return 0; + } + + pool_buf = frame_pool_alloc(); + if (!pool_buf) + return AVERROR(ENOMEM); + pool = (FramePool*)pool_buf->data; + + switch (avctx->codec_type) { + case AVMEDIA_TYPE_VIDEO: { + int linesize[4]; + int w = frame->width; + int h = frame->height; + int unaligned; + ptrdiff_t linesize1[4]; + size_t size[4]; + + avcodec_align_dimensions2(avctx, &w, &h, pool->stride_align); + + do { + // NOTE: do not align linesizes individually, this breaks e.g. assumptions + // that linesize[0] == 2*linesize[1] in the MPEG-encoder for 4:2:2 + ret = av_image_fill_linesizes(linesize, avctx->pix_fmt, w); + if (ret < 0) + goto fail; + // increase alignment of w for next try (rhs gives the lowest bit set in w) + w += w & ~(w - 1); + + unaligned = 0; + for (i = 0; i < 4; i++) + unaligned |= linesize[i] % pool->stride_align[i]; + } while (unaligned); + + for (i = 0; i < 4; i++) + linesize1[i] = linesize[i]; + ret = av_image_fill_plane_sizes(size, avctx->pix_fmt, h, linesize1); + if (ret < 0) + goto fail; + + for (i = 0; i < 4; i++) { + pool->linesize[i] = linesize[i]; + if (size[i]) { + if (size[i] > INT_MAX - (16 + STRIDE_ALIGN - 1)) { + ret = AVERROR(EINVAL); + goto fail; + } + pool->pools[i] = av_buffer_pool_init(size[i] + 16 + STRIDE_ALIGN - 1, + CONFIG_MEMORY_POISONING ? + NULL : + av_buffer_allocz); + if (!pool->pools[i]) { + ret = AVERROR(ENOMEM); + goto fail; + } + } + } + pool->format = frame->format; + pool->width = frame->width; + pool->height = frame->height; + + break; + } + case AVMEDIA_TYPE_AUDIO: { + ret = av_samples_get_buffer_size(&pool->linesize[0], ch, + frame->nb_samples, frame->format, 0); + if (ret < 0) + goto fail; + + pool->pools[0] = av_buffer_pool_init(pool->linesize[0], NULL); + if (!pool->pools[0]) { + ret = AVERROR(ENOMEM); + goto fail; + } + + pool->format = frame->format; + pool->planes = planes; + pool->channels = ch; + pool->samples = frame->nb_samples; + break; + } + default: av_assert0(0); + } + + av_buffer_unref(&avctx->internal->pool); + avctx->internal->pool = pool_buf; + + return 0; +fail: + av_buffer_unref(&pool_buf); + return ret; +} + +static int audio_get_buffer(AVCodecContext *avctx, AVFrame *frame) +{ + FramePool *pool = (FramePool*)avctx->internal->pool->data; + int planes = pool->planes; + int i; + + frame->linesize[0] = pool->linesize[0]; + + if (planes > AV_NUM_DATA_POINTERS) { + frame->extended_data = av_calloc(planes, sizeof(*frame->extended_data)); + frame->nb_extended_buf = planes - AV_NUM_DATA_POINTERS; + frame->extended_buf = av_calloc(frame->nb_extended_buf, + sizeof(*frame->extended_buf)); + if (!frame->extended_data || !frame->extended_buf) { + av_freep(&frame->extended_data); + av_freep(&frame->extended_buf); + return AVERROR(ENOMEM); + } + } else { + frame->extended_data = frame->data; + av_assert0(frame->nb_extended_buf == 0); + } + + for (i = 0; i < FFMIN(planes, AV_NUM_DATA_POINTERS); i++) { + frame->buf[i] = av_buffer_pool_get(pool->pools[0]); + if (!frame->buf[i]) + goto fail; + frame->extended_data[i] = frame->data[i] = frame->buf[i]->data; + } + for (i = 0; i < frame->nb_extended_buf; i++) { + frame->extended_buf[i] = av_buffer_pool_get(pool->pools[0]); + if (!frame->extended_buf[i]) + goto fail; + frame->extended_data[i + AV_NUM_DATA_POINTERS] = frame->extended_buf[i]->data; + } + + if (avctx->debug & FF_DEBUG_BUFFERS) + av_log(avctx, AV_LOG_DEBUG, "default_get_buffer called on frame %p", frame); + + return 0; +fail: + av_frame_unref(frame); + return AVERROR(ENOMEM); +} + +static int video_get_buffer(AVCodecContext *s, AVFrame *pic) +{ + FramePool *pool = (FramePool*)s->internal->pool->data; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pic->format); + int i; + + if (pic->data[0] || pic->data[1] || pic->data[2] || pic->data[3]) { + av_log(s, AV_LOG_ERROR, "pic->data[*]!=NULL in avcodec_default_get_buffer\n"); + return -1; + } + + if (!desc) { + av_log(s, AV_LOG_ERROR, + "Unable to get pixel format descriptor for format %s\n", + av_get_pix_fmt_name(pic->format)); + return AVERROR(EINVAL); + } + + memset(pic->data, 0, sizeof(pic->data)); + pic->extended_data = pic->data; + + for (i = 0; i < 4 && pool->pools[i]; i++) { + pic->linesize[i] = pool->linesize[i]; + + pic->buf[i] = av_buffer_pool_get(pool->pools[i]); + if (!pic->buf[i]) + goto fail; + + pic->data[i] = pic->buf[i]->data; + } + for (; i < AV_NUM_DATA_POINTERS; i++) { + pic->data[i] = NULL; + pic->linesize[i] = 0; + } + + if (s->debug & FF_DEBUG_BUFFERS) + av_log(s, AV_LOG_DEBUG, "default_get_buffer called on pic %p\n", pic); + + return 0; +fail: + av_frame_unref(pic); + return AVERROR(ENOMEM); +} + +int avcodec_default_get_buffer2(AVCodecContext *avctx, AVFrame *frame, int flags) +{ + int ret; + + 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; + + switch (avctx->codec_type) { + case AVMEDIA_TYPE_VIDEO: + return video_get_buffer(avctx, frame); + case AVMEDIA_TYPE_AUDIO: + return audio_get_buffer(avctx, frame); + default: + return -1; + } +} diff --git a/libavcodec/gif.c b/libavcodec/gif.c index 5e7cc4720..8c52c865a 100644 --- a/libavcodec/gif.c +++ b/libavcodec/gif.c @@ -35,8 +35,8 @@ #include "libavutil/imgutils.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "lzw.h" #include "gif.h" @@ -552,19 +552,19 @@ static const AVClass gif_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_gif_encoder = { - .name = "gif", - .long_name = NULL_IF_CONFIG_SMALL("GIF (Graphics Interchange Format)"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_GIF, +const FFCodec ff_gif_encoder = { + .p.name = "gif", + .p.long_name = NULL_IF_CONFIG_SMALL("GIF (Graphics Interchange Format)"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_GIF, .priv_data_size = sizeof(GIFContext), .init = gif_encode_init, - .encode2 = gif_encode_frame, + FF_CODEC_ENCODE_CB(gif_encode_frame), .close = gif_encode_close, - .pix_fmts = (const enum AVPixelFormat[]){ + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_RGB8, AV_PIX_FMT_BGR8, AV_PIX_FMT_RGB4_BYTE, AV_PIX_FMT_BGR4_BYTE, AV_PIX_FMT_GRAY8, AV_PIX_FMT_PAL8, AV_PIX_FMT_NONE }, - .priv_class = &gif_class, + .p.priv_class = &gif_class, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/gifdec.c b/libavcodec/gifdec.c index 80f1ba0cc..3936de1cd 100644 --- a/libavcodec/gifdec.c +++ b/libavcodec/gifdec.c @@ -25,6 +25,7 @@ #include "libavutil/opt.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" #include "lzw.h" #include "gif.h" @@ -464,7 +465,8 @@ static av_cold int gif_decode_init(AVCodecContext *avctx) return 0; } -static int gif_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) +static int gif_decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *avpkt) { GifState *s = avctx->priv_data; int ret; @@ -519,7 +521,7 @@ static int gif_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, A if (ret < 0) return ret; - if ((ret = av_frame_ref(data, s->frame)) < 0) + if ((ret = av_frame_ref(rframe, s->frame)) < 0) return ret; *got_frame = 1; @@ -554,17 +556,17 @@ static const AVClass decoder_class = { .category = AV_CLASS_CATEGORY_DECODER, }; -const AVCodec ff_gif_decoder = { - .name = "gif", - .long_name = NULL_IF_CONFIG_SMALL("GIF (Graphics Interchange Format)"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_GIF, +const FFCodec ff_gif_decoder = { + .p.name = "gif", + .p.long_name = NULL_IF_CONFIG_SMALL("GIF (Graphics Interchange Format)"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_GIF, .priv_data_size = sizeof(GifState), .init = gif_decode_init, .close = gif_decode_close, - .decode = gif_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(gif_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .priv_class = &decoder_class, + .p.priv_class = &decoder_class, }; diff --git a/libavcodec/golomb.c b/libavcodec/golomb.c index 937ac22ce..f9ca8149e 100644 --- a/libavcodec/golomb.c +++ b/libavcodec/golomb.c @@ -26,7 +26,7 @@ * @author Michael Niedermayer */ -#include "libavutil/common.h" +#include const uint8_t ff_golomb_vlc_len[512]={ 19,17,15,15,13,13,13,13,11,11,11,11,11,11,11,11,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, diff --git a/libavcodec/golomb.h b/libavcodec/golomb.h index 4d531cf80..164c2583b 100644 --- a/libavcodec/golomb.h +++ b/libavcodec/golomb.h @@ -33,14 +33,12 @@ #include #include "get_bits.h" -#include "put_bits.h" #define INVALID_VLC 0x80000000 extern const uint8_t ff_golomb_vlc_len[512]; extern const uint8_t ff_ue_golomb_vlc_code[512]; extern const int8_t ff_se_golomb_vlc_code[512]; -extern const uint8_t ff_ue_golomb_len[256]; extern const uint8_t ff_interleaved_golomb_vlc_len[256]; extern const uint8_t ff_interleaved_ue_golomb_vlc_code[256]; @@ -615,135 +613,4 @@ static inline int get_te(GetBitContext *s, int r, char *file, const char *func, #define get_te0_golomb(a, r) get_te(a, r, __FILE__, __func__, __LINE__) #endif /* TRACE */ - -/** - * write unsigned exp golomb code. 2^16 - 2 at most - */ -static inline void set_ue_golomb(PutBitContext *pb, int i) -{ - av_assert2(i >= 0); - av_assert2(i <= 0xFFFE); - - if (i < 256) - put_bits(pb, ff_ue_golomb_len[i], i + 1); - else { - int e = av_log2(i + 1); - put_bits(pb, 2 * e + 1, i + 1); - } -} - -/** - * write unsigned exp golomb code. 2^32-2 at most. - */ -static inline void set_ue_golomb_long(PutBitContext *pb, uint32_t i) -{ - av_assert2(i <= (UINT32_MAX - 1)); - - if (i < 256) - put_bits(pb, ff_ue_golomb_len[i], i + 1); - else { - int e = av_log2(i + 1); - put_bits64(pb, 2 * e + 1, i + 1); - } -} - -/** - * write truncated unsigned exp golomb code. - */ -static inline void set_te_golomb(PutBitContext *pb, int i, int range) -{ - av_assert2(range >= 1); - av_assert2(i <= range); - - if (range == 2) - put_bits(pb, 1, i ^ 1); - else - set_ue_golomb(pb, i); -} - -/** - * write signed exp golomb code. 16 bits at most. - */ -static inline void set_se_golomb(PutBitContext *pb, int i) -{ - i = 2 * i - 1; - if (i < 0) - i ^= -1; //FIXME check if gcc does the right thing - set_ue_golomb(pb, i); -} - -/** - * write unsigned golomb rice code (ffv1). - */ -static inline void set_ur_golomb(PutBitContext *pb, int i, int k, int limit, - int esc_len) -{ - int e; - - av_assert2(i >= 0); - - e = i >> k; - if (e < limit) - put_bits(pb, e + k + 1, (1 << k) + av_mod_uintp2(i, k)); - else - put_bits(pb, limit + esc_len, i - limit + 1); -} - -/** - * write unsigned golomb rice code (jpegls). - */ -static inline void set_ur_golomb_jpegls(PutBitContext *pb, int i, int k, - int limit, int esc_len) -{ - int e; - - av_assert2(i >= 0); - - e = (i >> k) + 1; - if (e < limit) { - while (e > 31) { - put_bits(pb, 31, 0); - e -= 31; - } - put_bits(pb, e, 1); - if (k) - put_sbits(pb, k, i); - } else { - while (limit > 31) { - put_bits(pb, 31, 0); - limit -= 31; - } - put_bits(pb, limit, 1); - put_bits(pb, esc_len, i - 1); - } -} - -/** - * write signed golomb rice code (ffv1). - */ -static inline void set_sr_golomb(PutBitContext *pb, int i, int k, int limit, - int esc_len) -{ - int v; - - v = -2 * i - 1; - v ^= (v >> 31); - - set_ur_golomb(pb, v, k, limit, esc_len); -} - -/** - * write signed golomb rice code (flac). - */ -static inline void set_sr_golomb_flac(PutBitContext *pb, int i, int k, - int limit, int esc_len) -{ - int v; - - v = -2 * i - 1; - v ^= (v >> 31); - - set_ur_golomb_jpegls(pb, v, k, limit, esc_len); -} - #endif /* AVCODEC_GOLOMB_H */ diff --git a/libavcodec/gsmdec.c b/libavcodec/gsmdec.c index c16911231..e5b8d6f41 100644 --- a/libavcodec/gsmdec.c +++ b/libavcodec/gsmdec.c @@ -24,8 +24,11 @@ * GSM decoder */ +#include "config_components.h" + #include "libavutil/channel_layout.h" #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" #include "msgsmdec.h" @@ -34,8 +37,8 @@ static av_cold int gsm_init(AVCodecContext *avctx) { - avctx->channels = 1; - avctx->channel_layout = AV_CH_LAYOUT_MONO; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; if (!avctx->sample_rate) avctx->sample_rate = 8000; avctx->sample_fmt = AV_SAMPLE_FMT_S16; @@ -62,10 +65,9 @@ static av_cold int gsm_init(AVCodecContext *avctx) return 0; } -static int gsm_decode_frame(AVCodecContext *avctx, void *data, +static int gsm_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; int res; GetBitContext gb; const uint8_t *buf = avpkt->data; @@ -111,30 +113,30 @@ static void gsm_flush(AVCodecContext *avctx) } #if CONFIG_GSM_DECODER -const AVCodec ff_gsm_decoder = { - .name = "gsm", - .long_name = NULL_IF_CONFIG_SMALL("GSM"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_GSM, +const FFCodec ff_gsm_decoder = { + .p.name = "gsm", + .p.long_name = NULL_IF_CONFIG_SMALL("GSM"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_GSM, .priv_data_size = sizeof(GSMContext), .init = gsm_init, - .decode = gsm_decode_frame, + FF_CODEC_DECODE_CB(gsm_decode_frame), .flush = gsm_flush, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_GSM_MS_DECODER -const AVCodec ff_gsm_ms_decoder = { - .name = "gsm_ms", - .long_name = NULL_IF_CONFIG_SMALL("GSM Microsoft variant"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_GSM_MS, +const FFCodec ff_gsm_ms_decoder = { + .p.name = "gsm_ms", + .p.long_name = NULL_IF_CONFIG_SMALL("GSM Microsoft variant"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_GSM_MS, .priv_data_size = sizeof(GSMContext), .init = gsm_init, - .decode = gsm_decode_frame, + FF_CODEC_DECODE_CB(gsm_decode_frame), .flush = gsm_flush, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif diff --git a/libavcodec/h261.c b/libavcodec/h261.c index 1290c040c..7dfaee7dc 100644 --- a/libavcodec/h261.c +++ b/libavcodec/h261.c @@ -60,7 +60,7 @@ static void h261_loop_filter(uint8_t *src, int stride) void ff_h261_loop_filter(MpegEncContext *s) { - H261Context *h = (H261Context *)s; + H261Context *const h = s->private_ctx; const int linesize = s->linesize; const int uvlinesize = s->uvlinesize; uint8_t *dest_y = s->dest[0]; diff --git a/libavcodec/h261.h b/libavcodec/h261.h index 25728a295..67c362be9 100644 --- a/libavcodec/h261.h +++ b/libavcodec/h261.h @@ -35,15 +35,7 @@ * H261Context */ typedef struct H261Context { - MpegEncContext s; - - int current_mba; - int mba_diff; int mtype; - int current_mv_x; - int current_mv_y; - int gob_number; - int gob_start_code_skipped; // 1 if gob start code is already read before gob header is read } H261Context; #define MB_TYPE_H261_FIL 0x800000 @@ -59,11 +51,4 @@ extern RLTable ff_h261_rl_tcoeff; void ff_h261_loop_filter(MpegEncContext *s); -int ff_h261_get_picture_format(int width, int height); -void ff_h261_reorder_mb_index(MpegEncContext *s); -void ff_h261_encode_mb(MpegEncContext *s, int16_t block[6][64], - int motion_x, int motion_y); -void ff_h261_encode_picture_header(MpegEncContext *s, int picture_number); -void ff_h261_encode_init(MpegEncContext *s); - #endif /* AVCODEC_H261_H */ diff --git a/libavcodec/h261dec.c b/libavcodec/h261dec.c index 80ec1c881..169917276 100644 --- a/libavcodec/h261dec.c +++ b/libavcodec/h261dec.c @@ -28,10 +28,11 @@ #include "libavutil/avassert.h" #include "libavutil/thread.h" #include "avcodec.h" +#include "codec_internal.h" #include "mpeg_er.h" #include "mpegutils.h" #include "mpegvideo.h" -#include "h263.h" +#include "mpegvideodec.h" #include "h261.h" #include "internal.h" @@ -48,6 +49,19 @@ static VLC h261_mtype_vlc; static VLC h261_mv_vlc; static VLC h261_cbp_vlc; +typedef struct H261DecContext { + MpegEncContext s; + + H261Context common; + + int current_mba; + int mba_diff; + int current_mv_x; + int current_mv_y; + int gob_number; + int gob_start_code_skipped; // 1 if gob start code is already read before gob header is read +} H261DecContext; + static av_cold void h261_decode_init_static(void) { INIT_VLC_STATIC(&h261_mba_vlc, H261_MBA_VLC_BITS, 35, @@ -68,9 +82,10 @@ static av_cold void h261_decode_init_static(void) static av_cold int h261_decode_init(AVCodecContext *avctx) { static AVOnce init_static_once = AV_ONCE_INIT; - H261Context *h = avctx->priv_data; + H261DecContext *const h = avctx->priv_data; MpegEncContext *const s = &h->s; + s->private_ctx = &h->common; // set defaults ff_mpv_decode_init(s, avctx); @@ -90,7 +105,7 @@ static av_cold int h261_decode_init(AVCodecContext *avctx) * Decode the group of blocks header or slice header. * @return <0 if an error occurred */ -static int h261_decode_gob_header(H261Context *h) +static int h261_decode_gob_header(H261DecContext *h) { unsigned int val; MpegEncContext *const s = &h->s; @@ -144,7 +159,7 @@ static int h261_decode_gob_header(H261Context *h) * Decode the group of blocks / video packet header. * @return <0 if no resync found */ -static int h261_resync(H261Context *h) +static int h261_resync(H261DecContext *h) { MpegEncContext *const s = &h->s; int left, ret; @@ -185,7 +200,7 @@ static int h261_resync(H261Context *h) * Decode skipped macroblocks. * @return 0 */ -static int h261_decode_mb_skipped(H261Context *h, int mba1, int mba2) +static int h261_decode_mb_skipped(H261DecContext *h, int mba1, int mba2) { MpegEncContext *const s = &h->s; int i; @@ -210,7 +225,7 @@ static int h261_decode_mb_skipped(H261Context *h, int mba1, int mba2) s->mv[0][0][0] = 0; s->mv[0][0][1] = 0; s->mb_skipped = 1; - h->mtype &= ~MB_TYPE_H261_FIL; + h->common.mtype &= ~MB_TYPE_H261_FIL; if (s->current_picture.motion_val[0]) { int b_stride = 2*s->mb_width + 1; @@ -255,7 +270,7 @@ static int decode_mv_component(GetBitContext *gb, int v) * Decode a macroblock. * @return <0 if an error occurred */ -static int h261_decode_block(H261Context *h, int16_t *block, int n, int coded) +static int h261_decode_block(H261DecContext *h, int16_t *block, int n, int coded) { MpegEncContext *const s = &h->s; int level, i, j, run; @@ -347,9 +362,10 @@ static int h261_decode_block(H261Context *h, int16_t *block, int n, int coded) return 0; } -static int h261_decode_mb(H261Context *h) +static int h261_decode_mb(H261DecContext *h) { MpegEncContext *const s = &h->s; + H261Context *const com = &h->common; int i, cbp, xy; cbp = 63; @@ -387,23 +403,23 @@ static int h261_decode_mb(H261Context *h) ff_update_block_index(s); // Read mtype - h->mtype = get_vlc2(&s->gb, h261_mtype_vlc.table, H261_MTYPE_VLC_BITS, 2); - if (h->mtype < 0) { + com->mtype = get_vlc2(&s->gb, h261_mtype_vlc.table, H261_MTYPE_VLC_BITS, 2); + if (com->mtype < 0) { av_log(s->avctx, AV_LOG_ERROR, "Invalid mtype index %d\n", - h->mtype); + com->mtype); return SLICE_ERROR; } - av_assert0(h->mtype < FF_ARRAY_ELEMS(ff_h261_mtype_map)); - h->mtype = ff_h261_mtype_map[h->mtype]; + av_assert0(com->mtype < FF_ARRAY_ELEMS(ff_h261_mtype_map)); + com->mtype = ff_h261_mtype_map[com->mtype]; // Read mquant - if (IS_QUANT(h->mtype)) + if (IS_QUANT(com->mtype)) ff_set_qscale(s, get_bits(&s->gb, 5)); - s->mb_intra = IS_INTRA4x4(h->mtype); + s->mb_intra = IS_INTRA4x4(com->mtype); // Read mv - if (IS_16X16(h->mtype)) { + if (IS_16X16(com->mtype)) { /* Motion vector data is included for all MC macroblocks. MVD is * obtained from the macroblock vector by subtracting the vector * of the preceding macroblock. For this calculation the vector @@ -426,7 +442,7 @@ static int h261_decode_mb(H261Context *h) } // Read cbp - if (HAS_CBP(h->mtype)) + if (HAS_CBP(com->mtype)) cbp = get_vlc2(&s->gb, h261_cbp_vlc.table, H261_CBP_VLC_BITS, 1) + 1; if (s->mb_intra) { @@ -450,7 +466,7 @@ static int h261_decode_mb(H261Context *h) intra: /* decode each block */ - if (s->mb_intra || HAS_CBP(h->mtype)) { + if (s->mb_intra || HAS_CBP(com->mtype)) { s->bdsp.clear_blocks(s->block[0]); for (i = 0; i < 6; i++) { if (h261_decode_block(h, s->block[i], i, cbp & 32) < 0) @@ -471,7 +487,7 @@ intra: * Decode the H.261 picture header. * @return <0 if no startcode found */ -static int h261_decode_picture_header(H261Context *h) +static int h261_decode_picture_header(H261DecContext *h) { MpegEncContext *const s = &h->s; int format, i; @@ -535,7 +551,7 @@ static int h261_decode_picture_header(H261Context *h) return 0; } -static int h261_decode_gob(H261Context *h) +static int h261_decode_gob(H261DecContext *h) { MpegEncContext *const s = &h->s; @@ -578,15 +594,14 @@ static int get_consumed_bytes(MpegEncContext *s, int buf_size) return pos; } -static int h261_decode_frame(AVCodecContext *avctx, void *data, +static int h261_decode_frame(AVCodecContext *avctx, AVFrame *pict, int *got_frame, AVPacket *avpkt) { + H261DecContext *const h = avctx->priv_data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; - H261Context *h = avctx->priv_data; MpegEncContext *s = &h->s; int ret; - AVFrame *pict = data; ff_dlog(avctx, "*****frame %d size=%d\n", avctx->frame_number, buf_size); ff_dlog(avctx, "bytes=%x %x %x %x\n", buf[0], buf[1], buf[2], buf[3]); @@ -658,23 +673,23 @@ retry: static av_cold int h261_decode_end(AVCodecContext *avctx) { - H261Context *h = avctx->priv_data; + H261DecContext *const h = avctx->priv_data; MpegEncContext *s = &h->s; ff_mpv_common_end(s); return 0; } -const AVCodec ff_h261_decoder = { - .name = "h261", - .long_name = NULL_IF_CONFIG_SMALL("H.261"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_H261, - .priv_data_size = sizeof(H261Context), +const FFCodec ff_h261_decoder = { + .p.name = "h261", + .p.long_name = NULL_IF_CONFIG_SMALL("H.261"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_H261, + .priv_data_size = sizeof(H261DecContext), .init = h261_decode_init, .close = h261_decode_end, - .decode = h261_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(h261_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, - .max_lowres = 3, + .p.max_lowres = 3, }; diff --git a/libavcodec/h261enc.c b/libavcodec/h261enc.c index 79f680f81..007bb4aa3 100644 --- a/libavcodec/h261enc.c +++ b/libavcodec/h261enc.c @@ -29,15 +29,25 @@ #include "libavutil/avassert.h" #include "libavutil/thread.h" #include "avcodec.h" +#include "codec_internal.h" #include "mpegutils.h" #include "mpegvideo.h" -#include "h263.h" #include "h261.h" +#include "h261enc.h" #include "mpegvideodata.h" +#include "mpegvideoenc.h" static uint8_t uni_h261_rl_len [64*64*2*2]; #define UNI_ENC_INDEX(last,run,level) ((last)*128*64 + (run)*128 + (level)) +typedef struct H261EncContext { + MpegEncContext s; + + H261Context common; + + int gob_number; +} H261EncContext; + int ff_h261_get_picture_format(int width, int height) { // QCIF @@ -53,7 +63,7 @@ int ff_h261_get_picture_format(int width, int height) void ff_h261_encode_picture_header(MpegEncContext *s, int picture_number) { - H261Context *h = (H261Context *)s; + H261EncContext *const h = (H261EncContext *)s; int format, temp_ref; align_put_bits(&s->pb); @@ -91,7 +101,7 @@ void ff_h261_encode_picture_header(MpegEncContext *s, int picture_number) */ static void h261_encode_gob_header(MpegEncContext *s, int mb_line) { - H261Context *h = (H261Context *)s; + H261EncContext *const h = (H261EncContext *)s; if (ff_h261_get_picture_format(s->width, s->height) == 0) { h->gob_number += 2; // QCIF } else { @@ -133,13 +143,12 @@ void ff_h261_reorder_mb_index(MpegEncContext *s) } } -static void h261_encode_motion(H261Context *h, int val) +static void h261_encode_motion(PutBitContext *pb, int val) { - MpegEncContext *const s = &h->s; int sign, code; if (val == 0) { code = 0; - put_bits(&s->pb, ff_h261_mv_tab[code][1], ff_h261_mv_tab[code][0]); + put_bits(pb, ff_h261_mv_tab[code][1], ff_h261_mv_tab[code][0]); } else { if (val > 15) val -= 32; @@ -147,8 +156,8 @@ static void h261_encode_motion(H261Context *h, int val) val += 32; sign = val < 0; code = sign ? -val : val; - put_bits(&s->pb, ff_h261_mv_tab[code][1], ff_h261_mv_tab[code][0]); - put_bits(&s->pb, 1, sign); + put_bits(pb, ff_h261_mv_tab[code][1], ff_h261_mv_tab[code][0]); + put_bits(pb, 1, sign); } } @@ -167,7 +176,7 @@ static inline int get_cbp(MpegEncContext *s, int16_t block[6][64]) * @param block the 8x8 block * @param n block index (0-3 are luma, 4-5 are chroma) */ -static void h261_encode_block(H261Context *h, int16_t *block, int n) +static void h261_encode_block(H261EncContext *h, int16_t *block, int n) { MpegEncContext *const s = &h->s; int level, run, i, j, last_index, last_non_zero, sign, slevel, code; @@ -238,12 +247,15 @@ static void h261_encode_block(H261Context *h, int16_t *block, int n) void ff_h261_encode_mb(MpegEncContext *s, int16_t block[6][64], int motion_x, int motion_y) { - H261Context *h = (H261Context *)s; + /* The following is only allowed because this encoder + * does not use slice threading. */ + H261EncContext *const h = (H261EncContext *)s; + H261Context *const com = &h->common; int mvd, mv_diff_x, mv_diff_y, i, cbp; cbp = 63; // avoid warning mvd = 0; - h->mtype = 0; + com->mtype = 0; if (!s->mb_intra) { /* compute cbp */ @@ -271,43 +283,43 @@ void ff_h261_encode_mb(MpegEncContext *s, int16_t block[6][64], /* calculate MTYPE */ if (!s->mb_intra) { - h->mtype++; + com->mtype++; if (mvd || s->loop_filter) - h->mtype += 3; + com->mtype += 3; if (s->loop_filter) - h->mtype += 3; + com->mtype += 3; if (cbp) - h->mtype++; - av_assert1(h->mtype > 1); + com->mtype++; + av_assert1(com->mtype > 1); } if (s->dquant && cbp) { - h->mtype++; + com->mtype++; } else s->qscale -= s->dquant; put_bits(&s->pb, - ff_h261_mtype_bits[h->mtype], - ff_h261_mtype_code[h->mtype]); + ff_h261_mtype_bits[com->mtype], + ff_h261_mtype_code[com->mtype]); - h->mtype = ff_h261_mtype_map[h->mtype]; + com->mtype = ff_h261_mtype_map[com->mtype]; - if (IS_QUANT(h->mtype)) { + if (IS_QUANT(com->mtype)) { ff_set_qscale(s, s->qscale + s->dquant); put_bits(&s->pb, 5, s->qscale); } - if (IS_16X16(h->mtype)) { + if (IS_16X16(com->mtype)) { mv_diff_x = (motion_x >> 1) - s->last_mv[0][0][0]; mv_diff_y = (motion_y >> 1) - s->last_mv[0][0][1]; s->last_mv[0][0][0] = (motion_x >> 1); s->last_mv[0][0][1] = (motion_y >> 1); - h261_encode_motion(h, mv_diff_x); - h261_encode_motion(h, mv_diff_y); + h261_encode_motion(&s->pb, mv_diff_x); + h261_encode_motion(&s->pb, mv_diff_y); } - if (HAS_CBP(h->mtype)) { + if (HAS_CBP(com->mtype)) { av_assert1(cbp > 0); put_bits(&s->pb, ff_h261_cbp_tab[cbp - 1][1], @@ -317,7 +329,7 @@ void ff_h261_encode_mb(MpegEncContext *s, int16_t block[6][64], /* encode each block */ h261_encode_block(h, block[i], i); - if (!IS_16X16(h->mtype)) { + if (!IS_16X16(com->mtype)) { s->last_mv[0][0][0] = 0; s->last_mv[0][0][1] = 0; } @@ -372,8 +384,11 @@ static av_cold void h261_encode_init_static(void) av_cold void ff_h261_encode_init(MpegEncContext *s) { + H261EncContext *const h = (H261EncContext*)s; static AVOnce init_static_once = AV_ONCE_INIT; + s->private_ctx = &h->common; + s->min_qcoeff = -127; s->max_qcoeff = 127; s->y_dc_scale_table = @@ -385,17 +400,17 @@ av_cold void ff_h261_encode_init(MpegEncContext *s) ff_thread_once(&init_static_once, h261_encode_init_static); } -const AVCodec ff_h261_encoder = { - .name = "h261", - .long_name = NULL_IF_CONFIG_SMALL("H.261"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_H261, - .priv_class = &ff_mpv_enc_class, - .priv_data_size = sizeof(H261Context), +const FFCodec ff_h261_encoder = { + .p.name = "h261", + .p.long_name = NULL_IF_CONFIG_SMALL("H.261"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_H261, + .p.priv_class = &ff_mpv_enc_class, + .priv_data_size = sizeof(H261EncContext), .init = ff_mpv_encode_init, - .encode2 = ff_mpv_encode_picture, + FF_CODEC_ENCODE_CB(ff_mpv_encode_picture), .close = ff_mpv_encode_end, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, }; diff --git a/libavcodec/h261enc.h b/libavcodec/h261enc.h new file mode 100644 index 000000000..0a01858be --- /dev/null +++ b/libavcodec/h261enc.h @@ -0,0 +1,40 @@ +/* + * H.261 encoder + * Copyright (c) 2002-2004 Michael Niedermayer + * Copyright (c) 2004 Maarten Daniels + * + * 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.261 encoder header. + */ + +#ifndef AVCODEC_H261ENC_H +#define AVCODEC_H261ENC_H + +#include "mpegvideo.h" + +int ff_h261_get_picture_format(int width, int height); +void ff_h261_reorder_mb_index(MpegEncContext *s); +void ff_h261_encode_mb(MpegEncContext *s, int16_t block[6][64], + int motion_x, int motion_y); +void ff_h261_encode_picture_header(MpegEncContext *s, int picture_number); +void ff_h261_encode_init(MpegEncContext *s); + +#endif diff --git a/libavcodec/h263.c b/libavcodec/h263.c index f8fba3c9f..b30ffaf87 100644 --- a/libavcodec/h263.c +++ b/libavcodec/h263.c @@ -102,47 +102,6 @@ void ff_h263_update_motion_val(MpegEncContext * s){ } } -int ff_h263_pred_dc(MpegEncContext * s, int n, int16_t **dc_val_ptr) -{ - int x, y, wrap, a, c, pred_dc; - int16_t *dc_val; - - /* find prediction */ - if (n < 4) { - x = 2 * s->mb_x + (n & 1); - y = 2 * s->mb_y + ((n & 2) >> 1); - wrap = s->b8_stride; - dc_val = s->dc_val[0]; - } else { - x = s->mb_x; - y = s->mb_y; - wrap = s->mb_stride; - dc_val = s->dc_val[n - 4 + 1]; - } - /* B C - * A X - */ - a = dc_val[(x - 1) + (y) * wrap]; - c = dc_val[(x) + (y - 1) * wrap]; - - /* No prediction outside GOB boundary */ - if(s->first_slice_line && n!=3){ - if(n!=2) c= 1024; - if(n!=1 && s->mb_x == s->resync_mb_x) a= 1024; - } - /* just DC prediction */ - if (a != 1024 && c != 1024) - pred_dc = (a + c) >> 1; - else if (a != 1024) - pred_dc = a; - else - pred_dc = c; - - /* we assume pred is positive */ - *dc_val_ptr = &dc_val[x + y * wrap]; - return pred_dc; -} - void ff_h263_loop_filter(MpegEncContext * s){ int qp_c; const int linesize = s->linesize; @@ -228,93 +187,6 @@ void ff_h263_loop_filter(MpegEncContext * s){ } } -void ff_h263_pred_acdc(MpegEncContext * s, int16_t *block, int n) -{ - int x, y, wrap, a, c, pred_dc, scale, i; - int16_t *dc_val, *ac_val, *ac_val1; - - /* find prediction */ - if (n < 4) { - x = 2 * s->mb_x + (n & 1); - y = 2 * s->mb_y + (n>> 1); - wrap = s->b8_stride; - dc_val = s->dc_val[0]; - ac_val = s->ac_val[0][0]; - scale = s->y_dc_scale; - } else { - x = s->mb_x; - y = s->mb_y; - wrap = s->mb_stride; - dc_val = s->dc_val[n - 4 + 1]; - ac_val = s->ac_val[n - 4 + 1][0]; - scale = s->c_dc_scale; - } - - ac_val += ((y) * wrap + (x)) * 16; - ac_val1 = ac_val; - - /* B C - * A X - */ - a = dc_val[(x - 1) + (y) * wrap]; - c = dc_val[(x) + (y - 1) * wrap]; - - /* No prediction outside GOB boundary */ - if(s->first_slice_line && n!=3){ - if(n!=2) c= 1024; - if(n!=1 && s->mb_x == s->resync_mb_x) a= 1024; - } - - if (s->ac_pred) { - pred_dc = 1024; - if (s->h263_aic_dir) { - /* left prediction */ - if (a != 1024) { - ac_val -= 16; - for(i=1;i<8;i++) { - block[s->idsp.idct_permutation[i << 3]] += ac_val[i]; - } - pred_dc = a; - } - } else { - /* top prediction */ - if (c != 1024) { - ac_val -= 16 * wrap; - for(i=1;i<8;i++) { - block[s->idsp.idct_permutation[i]] += ac_val[i + 8]; - } - pred_dc = c; - } - } - } else { - /* just DC prediction */ - if (a != 1024 && c != 1024) - pred_dc = (a + c) >> 1; - else if (a != 1024) - pred_dc = a; - else - pred_dc = c; - } - - /* we assume pred is positive */ - block[0]=block[0]*scale + pred_dc; - - if (block[0] < 0) - block[0] = 0; - else - block[0] |= 1; - - /* Update AC/DC tables */ - dc_val[(x) + (y) * wrap] = block[0]; - - /* left copy */ - for(i=1;i<8;i++) - ac_val1[i] = block[s->idsp.idct_permutation[i << 3]]; - /* top copy */ - for(i=1;i<8;i++) - ac_val1[8 + i] = block[s->idsp.idct_permutation[i]]; -} - int16_t *ff_h263_pred_motion(MpegEncContext * s, int block, int dir, int *px, int *py) { diff --git a/libavcodec/h263.h b/libavcodec/h263.h index 84a3a1951..27a5f31c5 100644 --- a/libavcodec/h263.h +++ b/libavcodec/h263.h @@ -20,162 +20,18 @@ #ifndef AVCODEC_H263_H #define AVCODEC_H263_H -#include #include "libavutil/rational.h" -#include "get_bits.h" #include "mpegvideo.h" -#include "h263data.h" -#include "rl.h" #define FF_ASPECT_EXTENDED 15 -#define INT_BIT (CHAR_BIT * sizeof(int)) - -// The defines below define the number of bits that are read at once for -// reading vlc values. Changing these may improve speed and data cache needs -// be aware though that decreasing them may need the number of stages that is -// passed to get_vlc* to be increased. -#define H263_MV_VLC_BITS 9 -#define INTRA_MCBPC_VLC_BITS 6 -#define INTER_MCBPC_VLC_BITS 7 -#define CBPY_VLC_BITS 6 -#define TEX_VLC_BITS 9 #define H263_GOB_HEIGHT(h) ((h) <= 400 ? 1 : (h) <= 800 ? 2 : 4) -extern VLC ff_h263_intra_MCBPC_vlc; -extern VLC ff_h263_inter_MCBPC_vlc; -extern VLC ff_h263_cbpy_vlc; -extern VLC ff_h263_mv_vlc; - -extern const enum AVPixelFormat ff_h263_hwaccel_pixfmt_list_420[]; - - -int ff_h263_decode_motion(MpegEncContext * s, int pred, int f_code); av_const int ff_h263_aspect_to_info(AVRational aspect); -int ff_h263_decode_init(AVCodecContext *avctx); -int ff_h263_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt); -int ff_h263_decode_end(AVCodecContext *avctx); -void ff_h263_encode_mb(MpegEncContext *s, - int16_t block[6][64], - int motion_x, int motion_y); -void ff_h263_encode_picture_header(MpegEncContext *s, int picture_number); -void ff_h263_encode_gob_header(MpegEncContext * s, int mb_line); int16_t *ff_h263_pred_motion(MpegEncContext * s, int block, int dir, int *px, int *py); -void ff_h263_encode_init(MpegEncContext *s); -void ff_h263_decode_init_vlc(void); void ff_h263_init_rl_inter(void); -int ff_h263_decode_picture_header(MpegEncContext *s); -int ff_h263_decode_gob_header(MpegEncContext *s); void ff_h263_update_motion_val(MpegEncContext * s); void ff_h263_loop_filter(MpegEncContext * s); -int ff_h263_decode_mba(MpegEncContext *s); -void ff_h263_encode_mba(MpegEncContext *s); -void ff_init_qscale_tab(MpegEncContext *s); -int ff_h263_pred_dc(MpegEncContext * s, int n, int16_t **dc_val_ptr); -void ff_h263_pred_acdc(MpegEncContext * s, int16_t *block, int n); - - -/** - * Print picture info if FF_DEBUG_PICT_INFO is set. - */ -void ff_h263_show_pict_info(MpegEncContext *s); - -int ff_intel_h263_decode_picture_header(MpegEncContext *s); -int ff_h263_decode_mb(MpegEncContext *s, - int16_t block[6][64]); - -void ff_clean_h263_qscales(MpegEncContext *s); -int ff_h263_resync(MpegEncContext *s); -void ff_h263_encode_motion(PutBitContext *pb, int val, int f_code); - - -static inline int h263_get_motion_length(int val, int f_code){ - int bit_size, code, sign; - - if (val == 0) { - return 1; /* ff_mvtab[0][1] */ - } else { - bit_size = f_code - 1; - /* modulo encoding */ - val = sign_extend(val, 6 + bit_size); - sign = val >> 31; - val = (val ^ sign) - sign; /* val = FFABS(val) */ - val--; - code = (val >> bit_size) + 1; - - return ff_mvtab[code][1] + 1 + bit_size; - } -} - -static inline void ff_h263_encode_motion_vector(MpegEncContext * s, int x, int y, int f_code){ - if (s->avctx->flags2 & AV_CODEC_FLAG2_NO_OUTPUT) { - skip_put_bits(&s->pb, - h263_get_motion_length(x, f_code) - +h263_get_motion_length(y, f_code)); - }else{ - ff_h263_encode_motion(&s->pb, x, f_code); - ff_h263_encode_motion(&s->pb, y, f_code); - } -} - -static inline int get_p_cbp(MpegEncContext * s, - int16_t block[6][64], - int motion_x, int motion_y){ - int cbp, i; - - if (s->mpv_flags & FF_MPV_FLAG_CBP_RD) { - int best_cbpy_score= INT_MAX; - int best_cbpc_score= INT_MAX; - int cbpc = (-1), cbpy= (-1); - const int offset= (s->mv_type==MV_TYPE_16X16 ? 0 : 16) + (s->dquant ? 8 : 0); - const int lambda= s->lambda2 >> (FF_LAMBDA_SHIFT - 6); - - for(i=0; i<4; i++){ - int score= ff_h263_inter_MCBPC_bits[i + offset] * lambda; - if(i&1) score += s->coded_score[5]; - if(i&2) score += s->coded_score[4]; - - if(score < best_cbpc_score){ - best_cbpc_score= score; - cbpc= i; - } - } - - for(i=0; i<16; i++){ - int score= ff_h263_cbpy_tab[i ^ 0xF][1] * lambda; - if(i&1) score += s->coded_score[3]; - if(i&2) score += s->coded_score[2]; - if(i&4) score += s->coded_score[1]; - if(i&8) score += s->coded_score[0]; - - if(score < best_cbpy_score){ - best_cbpy_score= score; - cbpy= i; - } - } - cbp= cbpc + 4*cbpy; - if ((motion_x | motion_y | s->dquant) == 0 && s->mv_type==MV_TYPE_16X16){ - if(best_cbpy_score + best_cbpc_score + 2*lambda >= 0) - cbp= 0; - } - - for (i = 0; i < 6; i++) { - if (s->block_last_index[i] >= 0 && ((cbp >> (5 - i))&1)==0 ){ - s->block_last_index[i]= -1; - s->bdsp.clear_block(s->block[i]); - } - } - }else{ - cbp= 0; - for (i = 0; i < 6; i++) { - if (s->block_last_index[i] >= 0) - cbp |= 1 << (5 - i); - } - } - return cbp; -} #endif /* AVCODEC_H263_H */ diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c index 2682a7f43..1f9f3e5e9 100644 --- a/libavcodec/h263dec.c +++ b/libavcodec/h263dec.c @@ -27,12 +27,14 @@ #define UNCHECKED_BITSTREAM_READER 1 -#include "libavutil/video_enc_params.h" +#include "config_components.h" #include "avcodec.h" +#include "codec_internal.h" #include "error_resilience.h" -#include "flv.h" +#include "flvdec.h" #include "h263.h" +#include "h263dec.h" #if FF_API_FLAG_TRUNCATED #include "h263_parser.h" #endif @@ -40,15 +42,17 @@ #include "internal.h" #include "mpeg_er.h" #include "mpeg4video.h" +#include "mpeg4videodec.h" #if FF_API_FLAG_TRUNCATED #include "mpeg4video_parser.h" #endif #include "mpegutils.h" #include "mpegvideo.h" -#include "msmpeg4.h" +#include "mpegvideodec.h" +#include "msmpeg4dec.h" #include "qpeldsp.h" #include "thread.h" -#include "wmv2.h" +#include "wmv2dec.h" static enum AVPixelFormat h263_get_format(AVCodecContext *avctx) { @@ -83,13 +87,11 @@ av_cold int ff_h263_decode_init(AVCodecContext *avctx) s->quant_precision = 5; s->decode_mb = ff_h263_decode_mb; s->low_delay = 1; - s->unrestricted_mv = 1; /* select sub codec */ switch (avctx->codec->id) { case AV_CODEC_ID_H263: case AV_CODEC_ID_H263P: - s->unrestricted_mv = 0; avctx->chroma_sample_location = AVCHROMA_LOC_CENTER; break; case AV_CODEC_ID_MPEG4: @@ -423,15 +425,14 @@ static int decode_slice(MpegEncContext *s) return AVERROR_INVALIDDATA; } -int ff_h263_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +int ff_h263_decode_frame(AVCodecContext *avctx, AVFrame *pict, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; MpegEncContext *s = avctx->priv_data; int ret; int slice_ret = 0; - AVFrame *pict = data; /* no supplementary picture */ if (buf_size == 0) { @@ -507,9 +508,9 @@ retry: GetBitContext gb; if (init_get_bits8(&gb, s->avctx->extradata, s->avctx->extradata_size) >= 0 ) - ff_mpeg4_decode_picture_header(avctx->priv_data, &gb, 1); + ff_mpeg4_decode_picture_header(avctx->priv_data, &gb, 1, 0); } - ret = ff_mpeg4_decode_picture_header(avctx->priv_data, &s->gb, 0); + ret = ff_mpeg4_decode_picture_header(avctx->priv_data, &s->gb, 0, 0); } else if (CONFIG_H263I_DECODER && s->codec_id == AV_CODEC_ID_H263I) { ret = ff_intel_h263_decode_picture_header(s); } else if (CONFIG_FLV_DECODER && s->h263_flv) { @@ -603,13 +604,6 @@ retry: avctx->skip_frame >= AVDISCARD_ALL) return get_consumed_bytes(s, buf_size); - if (s->next_p_frame_damaged) { - if (s->pict_type == AV_PICTURE_TYPE_B) - return get_consumed_bytes(s, buf_size); - else - s->next_p_frame_damaged = 0; - } - if ((!s->no_rounding) || s->pict_type == AV_PICTURE_TYPE_B) { s->me.qpel_put = s->qdsp.put_qpel_pixels_tab; s->me.qpel_avg = s->qdsp.avg_qpel_pixels_tab; @@ -700,28 +694,22 @@ frame_end: if ((ret = av_frame_ref(pict, s->current_picture_ptr->f)) < 0) return ret; ff_print_debug_info(s, s->current_picture_ptr, pict); - ff_mpv_export_qp_table(s, pict, s->current_picture_ptr, FF_QSCALE_TYPE_MPEG1); + ff_mpv_export_qp_table(s, pict, s->current_picture_ptr, FF_MPV_QSCALE_TYPE_MPEG1); } else if (s->last_picture_ptr) { if ((ret = av_frame_ref(pict, s->last_picture_ptr->f)) < 0) return ret; ff_print_debug_info(s, s->last_picture_ptr, pict); - ff_mpv_export_qp_table(s, pict, s->last_picture_ptr, FF_QSCALE_TYPE_MPEG1); + ff_mpv_export_qp_table(s, pict, s->last_picture_ptr, FF_MPV_QSCALE_TYPE_MPEG1); } if (s->last_picture_ptr || s->low_delay) { if ( pict->format == AV_PIX_FMT_YUV420P && (s->codec_tag == AV_RL32("GEOV") || s->codec_tag == AV_RL32("GEOX"))) { - int x, y, p; - av_frame_make_writable(pict); - for (p=0; p<3; p++) { - int w = AV_CEIL_RSHIFT(pict-> width, !!p); + for (int p = 0; p < 3; p++) { int h = AV_CEIL_RSHIFT(pict->height, !!p); - int linesize = pict->linesize[p]; - for (y=0; y<(h>>1); y++) - for (x=0; xdata[p][x + y*linesize], - pict->data[p][x + (h-1-y)*linesize]); + + pict->data[p] += (h - 1) * pict->linesize[p]; + pict->linesize[p] *= -1; } } *got_frame = 1; @@ -766,44 +754,46 @@ static const AVCodecHWConfigInternal *const h263_hw_config_list[] = { NULL }; -const AVCodec ff_h263_decoder = { - .name = "h263", - .long_name = NULL_IF_CONFIG_SMALL("H.263 / H.263-1996, H.263+ / H.263-1998 / H.263 version 2"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_H263, +const FFCodec ff_h263_decoder = { + .p.name = "h263", + .p.long_name = NULL_IF_CONFIG_SMALL("H.263 / H.263-1996, H.263+ / H.263-1998 / H.263 version 2"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_H263, .priv_data_size = sizeof(MpegEncContext), .init = ff_h263_decode_init, .close = ff_h263_decode_end, - .decode = ff_h263_decode_frame, - .capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 | + FF_CODEC_DECODE_CB(ff_h263_decode_frame), + .p.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 | #if FF_API_FLAG_TRUNCATED AV_CODEC_CAP_TRUNCATED | #endif AV_CODEC_CAP_DELAY, - .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, .flush = ff_mpeg_flush, - .max_lowres = 3, - .pix_fmts = ff_h263_hwaccel_pixfmt_list_420, + .p.max_lowres = 3, + .p.pix_fmts = ff_h263_hwaccel_pixfmt_list_420, .hw_configs = h263_hw_config_list, }; -const AVCodec ff_h263p_decoder = { - .name = "h263p", - .long_name = NULL_IF_CONFIG_SMALL("H.263 / H.263-1996, H.263+ / H.263-1998 / H.263 version 2"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_H263P, +const FFCodec ff_h263p_decoder = { + .p.name = "h263p", + .p.long_name = NULL_IF_CONFIG_SMALL("H.263 / H.263-1996, H.263+ / H.263-1998 / H.263 version 2"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_H263P, .priv_data_size = sizeof(MpegEncContext), .init = ff_h263_decode_init, .close = ff_h263_decode_end, - .decode = ff_h263_decode_frame, - .capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 | + FF_CODEC_DECODE_CB(ff_h263_decode_frame), + .p.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 | #if FF_API_FLAG_TRUNCATED AV_CODEC_CAP_TRUNCATED | #endif AV_CODEC_CAP_DELAY, - .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, .flush = ff_mpeg_flush, - .max_lowres = 3, - .pix_fmts = ff_h263_hwaccel_pixfmt_list_420, + .p.max_lowres = 3, + .p.pix_fmts = ff_h263_hwaccel_pixfmt_list_420, .hw_configs = h263_hw_config_list, }; diff --git a/libavcodec/h263dec.h b/libavcodec/h263dec.h new file mode 100644 index 000000000..9f1db7290 --- /dev/null +++ b/libavcodec/h263dec.h @@ -0,0 +1,64 @@ +/* + * H.263 decoder internal header + * + * 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_H263DEC_H +#define AVCODEC_H263DEC_H + +#include "mpegvideo.h" +#include "vlc.h" + +// The defines below define the number of bits that are read at once for +// reading vlc values. Changing these may improve speed and data cache needs +// be aware though that decreasing them may need the number of stages that is +// passed to get_vlc* to be increased. +#define H263_MV_VLC_BITS 9 +#define INTRA_MCBPC_VLC_BITS 6 +#define INTER_MCBPC_VLC_BITS 7 +#define CBPY_VLC_BITS 6 +#define TEX_VLC_BITS 9 + +extern VLC ff_h263_intra_MCBPC_vlc; +extern VLC ff_h263_inter_MCBPC_vlc; +extern VLC ff_h263_cbpy_vlc; +extern VLC ff_h263_mv_vlc; + +extern const enum AVPixelFormat ff_h263_hwaccel_pixfmt_list_420[]; + +int ff_h263_decode_motion(MpegEncContext * s, int pred, int f_code); +int ff_h263_decode_init(AVCodecContext *avctx); +int ff_h263_decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt); +int ff_h263_decode_end(AVCodecContext *avctx); +void ff_h263_decode_init_vlc(void); +int ff_h263_decode_picture_header(MpegEncContext *s); +int ff_h263_decode_gob_header(MpegEncContext *s); +int ff_h263_decode_mba(MpegEncContext *s); + +/** + * Print picture info if FF_DEBUG_PICT_INFO is set. + */ +void ff_h263_show_pict_info(MpegEncContext *s); + +int ff_intel_h263_decode_picture_header(MpegEncContext *s); +int ff_h263_decode_mb(MpegEncContext *s, + int16_t block[6][64]); + +int ff_h263_resync(MpegEncContext *s); + +#endif diff --git a/libavcodec/h263dsp.c b/libavcodec/h263dsp.c index b3c0bcd45..8fa2d3c29 100644 --- a/libavcodec/h263dsp.c +++ b/libavcodec/h263dsp.c @@ -119,8 +119,9 @@ av_cold void ff_h263dsp_init(H263DSPContext *ctx) ctx->h263_h_loop_filter = h263_h_loop_filter_c; ctx->h263_v_loop_filter = h263_v_loop_filter_c; - if (ARCH_X86) - ff_h263dsp_init_x86(ctx); - if (ARCH_MIPS) - ff_h263dsp_init_mips(ctx); +#if ARCH_X86 + ff_h263dsp_init_x86(ctx); +#elif ARCH_MIPS + ff_h263dsp_init_mips(ctx); +#endif } diff --git a/libavcodec/h263enc.h b/libavcodec/h263enc.h new file mode 100644 index 000000000..fff85a18f --- /dev/null +++ b/libavcodec/h263enc.h @@ -0,0 +1,130 @@ +/* + * H.263 encoder header + * + * 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_H263ENC_H +#define AVCODEC_H263ENC_H + +#include +#include "h263data.h" +#include "mpegvideoenc.h" + +void ff_h263_encode_init(MpegEncContext *s); +void ff_h263_encode_picture_header(MpegEncContext *s, int picture_number); +void ff_h263_encode_gob_header(MpegEncContext * s, int mb_line); +void ff_h263_encode_mb(MpegEncContext *s, + int16_t block[6][64], + int motion_x, int motion_y); +void ff_h263_encode_mba(MpegEncContext *s); + +void ff_init_qscale_tab(MpegEncContext *s); +void ff_clean_h263_qscales(MpegEncContext *s); + +void ff_h263_encode_motion(PutBitContext *pb, int val, int f_code); + + +static inline int h263_get_motion_length(int val, int f_code) +{ + int bit_size, code, sign; + + if (val == 0) { + return 1; /* ff_mvtab[0][1] */ + } else { + bit_size = f_code - 1; + /* modulo encoding */ + val = sign_extend(val, 6 + bit_size); + sign = val >> 31; + val = (val ^ sign) - sign; /* val = FFABS(val) */ + val--; + code = (val >> bit_size) + 1; + + return ff_mvtab[code][1] + 1 + bit_size; + } +} + +static inline void ff_h263_encode_motion_vector(MpegEncContext * s, + int x, int y, int f_code) +{ + if (s->avctx->flags2 & AV_CODEC_FLAG2_NO_OUTPUT) { + skip_put_bits(&s->pb, + h263_get_motion_length(x, f_code) + + h263_get_motion_length(y, f_code)); + } else { + ff_h263_encode_motion(&s->pb, x, f_code); + ff_h263_encode_motion(&s->pb, y, f_code); + } +} + +static inline int get_p_cbp(MpegEncContext * s, + int16_t block[6][64], + int motion_x, int motion_y){ + int cbp; + + if (s->mpv_flags & FF_MPV_FLAG_CBP_RD) { + int best_cbpy_score = INT_MAX; + int best_cbpc_score = INT_MAX; + int cbpc = (-1), cbpy = (-1); + const int offset = (s->mv_type == MV_TYPE_16X16 ? 0 : 16) + (s->dquant ? 8 : 0); + const int lambda = s->lambda2 >> (FF_LAMBDA_SHIFT - 6); + + for (int i = 0; i < 4; i++) { + int score = ff_h263_inter_MCBPC_bits[i + offset] * lambda; + if (i & 1) score += s->coded_score[5]; + if (i & 2) score += s->coded_score[4]; + + if (score < best_cbpc_score) { + best_cbpc_score = score; + cbpc = i; + } + } + + for (int i = 0; i < 16; i++) { + int score= ff_h263_cbpy_tab[i ^ 0xF][1] * lambda; + if (i & 1) score += s->coded_score[3]; + if (i & 2) score += s->coded_score[2]; + if (i & 4) score += s->coded_score[1]; + if (i & 8) score += s->coded_score[0]; + + if (score < best_cbpy_score) { + best_cbpy_score = score; + cbpy = i; + } + } + cbp = cbpc + 4 * cbpy; + if (!(motion_x | motion_y | s->dquant) && s->mv_type == MV_TYPE_16X16) { + if (best_cbpy_score + best_cbpc_score + 2 * lambda >= 0) + cbp= 0; + } + + for (int i = 0; i < 6; i++) { + if (s->block_last_index[i] >= 0 && !((cbp >> (5 - i)) & 1)) { + s->block_last_index[i] = -1; + s->bdsp.clear_block(s->block[i]); + } + } + } else { + cbp = 0; + for (int i = 0; i < 6; i++) { + if (s->block_last_index[i] >= 0) + cbp |= 1 << (5 - i); + } + } + return cbp; +} + +#endif diff --git a/libavcodec/h2645_parse.c b/libavcodec/h2645_parse.c index 03780680c..90944177c 100644 --- a/libavcodec/h2645_parse.c +++ b/libavcodec/h2645_parse.c @@ -259,10 +259,10 @@ static const char *h264_nal_unit_name(int nal_type) return h264_nal_type_name[nal_type]; } -static int get_bit_length(H2645NAL *nal, int skip_trailing_zeros) +static int get_bit_length(H2645NAL *nal, int min_size, int skip_trailing_zeros) { int size = nal->size; - int v; + int trailing_padding = 0; while (skip_trailing_zeros && size > 0 && nal->data[size - 1] == 0) size--; @@ -270,18 +270,23 @@ static int get_bit_length(H2645NAL *nal, int skip_trailing_zeros) if (!size) return 0; - v = nal->data[size - 1]; + if (size <= min_size) { + if (nal->size < min_size) + return AVERROR_INVALIDDATA; + size = min_size; + } else { + int v = nal->data[size - 1]; + /* remove the stop bit and following trailing zeros, + * or nothing for damaged bitstreams */ + if (v) + trailing_padding = ff_ctz(v) + 1; + } if (size > INT_MAX / 8) return AVERROR(ERANGE); size *= 8; - /* remove the stop bit and following trailing zeros, - * or nothing for damaged bitstreams */ - if (v) - size -= ff_ctz(v) + 1; - - return size; + return size - trailing_padding; } /** @@ -491,7 +496,8 @@ int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length, bytestream2_peek_be32(&bc) == 0x000001E0) skip_trailing_zeros = 0; - nal->size_bits = get_bit_length(nal, skip_trailing_zeros); + nal->size_bits = get_bit_length(nal, 1 + (codec_id == AV_CODEC_ID_HEVC), + skip_trailing_zeros); if (nal->size <= 0 || nal->size_bits <= 0) continue; diff --git a/libavcodec/h264_cabac.c b/libavcodec/h264_cabac.c index 040fa0a25..703b27aa9 100644 --- a/libavcodec/h264_cabac.c +++ b/libavcodec/h264_cabac.c @@ -34,7 +34,6 @@ #include "config.h" #include "cabac.h" #include "cabac_functions.h" -#include "internal.h" #include "h264dec.h" #include "h264data.h" #include "h264_mvpred.h" @@ -1281,6 +1280,15 @@ void ff_h264_init_cabac_states(const H264Context *h, H264SliceContext *sl) } } +static av_always_inline uint16_t pack8to16(unsigned a, unsigned b) +{ +#if HAVE_BIGENDIAN + return (b & 0xFF) + (a << 8); +#else + return (a & 0xFF) + (b << 8); +#endif +} + static int decode_cabac_field_decoding_flag(const H264Context *h, H264SliceContext *sl) { const int mbb_xy = sl->mb_xy - 2*h->mb_stride; diff --git a/libavcodec/h264_cavlc.c b/libavcodec/h264_cavlc.c index fa8ba5dac..d061a5953 100644 --- a/libavcodec/h264_cavlc.c +++ b/libavcodec/h264_cavlc.c @@ -28,7 +28,6 @@ #define CABAC(h) 0 #define UNCHECKED_BITSTREAM_READER 1 -#include "internal.h" #include "h264dec.h" #include "h264_mvpred.h" #include "h264data.h" @@ -236,35 +235,35 @@ static const uint8_t run_bits[7][16]={ }; static VLC coeff_token_vlc[4]; -static VLC_TYPE coeff_token_vlc_tables[520+332+280+256][2]; +static VLCElem coeff_token_vlc_tables[520+332+280+256]; static const int coeff_token_vlc_tables_size[4]={520,332,280,256}; static VLC chroma_dc_coeff_token_vlc; -static VLC_TYPE chroma_dc_coeff_token_vlc_table[256][2]; +static VLCElem chroma_dc_coeff_token_vlc_table[256]; static const int chroma_dc_coeff_token_vlc_table_size = 256; static VLC chroma422_dc_coeff_token_vlc; -static VLC_TYPE chroma422_dc_coeff_token_vlc_table[8192][2]; +static VLCElem chroma422_dc_coeff_token_vlc_table[8192]; static const int chroma422_dc_coeff_token_vlc_table_size = 8192; static VLC total_zeros_vlc[15+1]; -static VLC_TYPE total_zeros_vlc_tables[15][512][2]; +static VLCElem total_zeros_vlc_tables[15][512]; static const int total_zeros_vlc_tables_size = 512; static VLC chroma_dc_total_zeros_vlc[3+1]; -static VLC_TYPE chroma_dc_total_zeros_vlc_tables[3][8][2]; +static VLCElem chroma_dc_total_zeros_vlc_tables[3][8]; static const int chroma_dc_total_zeros_vlc_tables_size = 8; static VLC chroma422_dc_total_zeros_vlc[7+1]; -static VLC_TYPE chroma422_dc_total_zeros_vlc_tables[7][32][2]; +static VLCElem chroma422_dc_total_zeros_vlc_tables[7][32]; static const int chroma422_dc_total_zeros_vlc_tables_size = 32; static VLC run_vlc[6+1]; -static VLC_TYPE run_vlc_tables[6][8][2]; +static VLCElem run_vlc_tables[6][8]; static const int run_vlc_tables_size = 8; static VLC run7_vlc; -static VLC_TYPE run7_vlc_table[96][2]; +static VLCElem run7_vlc_table[96]; static const int run7_vlc_table_size = 96; #define LEVEL_TAB_BITS 8 diff --git a/libavcodec/h264_direct.c b/libavcodec/h264_direct.c index 8f0798113..014491e29 100644 --- a/libavcodec/h264_direct.c +++ b/libavcodec/h264_direct.c @@ -25,13 +25,12 @@ * @author Michael Niedermayer */ -#include "internal.h" #include "avcodec.h" #include "h264dec.h" #include "h264_ps.h" #include "mpegutils.h" #include "rectangle.h" -#include "thread.h" +#include "threadframe.h" #include diff --git a/libavcodec/h264_levels.c b/libavcodec/h264_levels.c index 1b9f78da0..f7ed9a6e3 100644 --- a/libavcodec/h264_levels.c +++ b/libavcodec/h264_levels.c @@ -17,7 +17,7 @@ */ #include -#include "libavutil/common.h" +#include "libavutil/macros.h" #include "h264_levels.h" // H.264 table A-1. diff --git a/libavcodec/h264_loopfilter.c b/libavcodec/h264_loopfilter.c index 558ec6c02..2440cfa83 100644 --- a/libavcodec/h264_loopfilter.c +++ b/libavcodec/h264_loopfilter.c @@ -28,13 +28,10 @@ #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" #include "libavutil/mem_internal.h" -#include "internal.h" #include "avcodec.h" #include "h264dec.h" #include "h264_ps.h" -#include "mathops.h" #include "mpegutils.h" -#include "rectangle.h" /* Deblocking filter (p153) */ static const uint8_t alpha_table[52*3] = { diff --git a/libavcodec/h264_mb.c b/libavcodec/h264_mb.c index 3cd17b7e4..0b3177455 100644 --- a/libavcodec/h264_mb.c +++ b/libavcodec/h264_mb.c @@ -34,7 +34,7 @@ #include "h264dec.h" #include "h264_ps.h" #include "qpeldsp.h" -#include "thread.h" +#include "threadframe.h" static inline int get_lowest_part_list_y(H264SliceContext *sl, int n, int height, int y_offset, int list) diff --git a/libavcodec/h264_metadata_bsf.c b/libavcodec/h264_metadata_bsf.c index 9df99cbae..6efdc9247 100644 --- a/libavcodec/h264_metadata_bsf.c +++ b/libavcodec/h264_metadata_bsf.c @@ -22,6 +22,7 @@ #include "libavutil/opt.h" #include "bsf.h" +#include "bsf_internal.h" #include "cbs.h" #include "cbs_bsf.h" #include "cbs_h264.h" @@ -624,7 +625,7 @@ static const AVOption h264_metadata_options[] = { { "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, FLAGS }, + { .i64 = -1 }, -1, 5, FLAGS }, { "tick_rate", "Set VUI tick rate (time_scale / num_units_in_tick)", OFFSET(tick_rate), AV_OPT_TYPE_RATIONAL, @@ -716,12 +717,12 @@ 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", +const FFBitStreamFilter ff_h264_metadata_bsf = { + .p.name = "h264_metadata", + .p.codec_ids = h264_metadata_codec_ids, + .p.priv_class = &h264_metadata_class, .priv_data_size = sizeof(H264MetadataContext), - .priv_class = &h264_metadata_class, .init = &h264_metadata_init, .close = &ff_cbs_bsf_generic_close, .filter = &ff_cbs_bsf_generic_filter, - .codec_ids = h264_metadata_codec_ids, }; diff --git a/libavcodec/h264_mp4toannexb_bsf.c b/libavcodec/h264_mp4toannexb_bsf.c index 5a2656197..d11be455c 100644 --- a/libavcodec/h264_mp4toannexb_bsf.c +++ b/libavcodec/h264_mp4toannexb_bsf.c @@ -312,11 +312,11 @@ static const enum AVCodecID codec_ids[] = { AV_CODEC_ID_H264, AV_CODEC_ID_NONE, }; -const AVBitStreamFilter ff_h264_mp4toannexb_bsf = { - .name = "h264_mp4toannexb", +const FFBitStreamFilter ff_h264_mp4toannexb_bsf = { + .p.name = "h264_mp4toannexb", + .p.codec_ids = codec_ids, .priv_data_size = sizeof(H264BSFContext), .init = h264_mp4toannexb_init, .filter = h264_mp4toannexb_filter, .flush = h264_mp4toannexb_flush, - .codec_ids = codec_ids, }; diff --git a/libavcodec/h264_mvpred.h b/libavcodec/h264_mvpred.h index 19d9ee462..46ae2738f 100644 --- a/libavcodec/h264_mvpred.h +++ b/libavcodec/h264_mvpred.h @@ -28,8 +28,6 @@ #ifndef AVCODEC_H264_MVPRED_H #define AVCODEC_H264_MVPRED_H -#include "internal.h" -#include "avcodec.h" #include "h264dec.h" #include "mpegutils.h" #include "libavutil/avassert.h" diff --git a/libavcodec/h264_parse.c b/libavcodec/h264_parse.c index 1c1d1c04b..97ddf0e43 100644 --- a/libavcodec/h264_parse.c +++ b/libavcodec/h264_parse.c @@ -20,9 +20,11 @@ #include "get_bits.h" #include "golomb.h" #include "h264.h" -#include "h264dec.h" +#include "h264pred.h" #include "h264_parse.h" #include "h264_ps.h" +#include "h2645_parse.h" +#include "mpegutils.h" int ff_h264_pred_weight_table(GetBitContext *gb, const SPS *sps, const int *ref_count, int slice_type_nos, diff --git a/libavcodec/h264_parse.h b/libavcodec/h264_parse.h index 4d0162012..4ee863df6 100644 --- a/libavcodec/h264_parse.h +++ b/libavcodec/h264_parse.h @@ -24,9 +24,48 @@ #ifndef AVCODEC_H264_PARSE_H #define AVCODEC_H264_PARSE_H +#include "config.h" + +#include + +#include "libavutil/attributes.h" + #include "get_bits.h" #include "h264_ps.h" +#define MB_TYPE_REF0 MB_TYPE_ACPRED // dirty but it fits in 16 bit +#define MB_TYPE_8x8DCT 0x01000000 + +// This table must be here because scan8[constant] must be known at compiletime +static const uint8_t scan8[16 * 3 + 3] = { + 4 + 1 * 8, 5 + 1 * 8, 4 + 2 * 8, 5 + 2 * 8, + 6 + 1 * 8, 7 + 1 * 8, 6 + 2 * 8, 7 + 2 * 8, + 4 + 3 * 8, 5 + 3 * 8, 4 + 4 * 8, 5 + 4 * 8, + 6 + 3 * 8, 7 + 3 * 8, 6 + 4 * 8, 7 + 4 * 8, + 4 + 6 * 8, 5 + 6 * 8, 4 + 7 * 8, 5 + 7 * 8, + 6 + 6 * 8, 7 + 6 * 8, 6 + 7 * 8, 7 + 7 * 8, + 4 + 8 * 8, 5 + 8 * 8, 4 + 9 * 8, 5 + 9 * 8, + 6 + 8 * 8, 7 + 8 * 8, 6 + 9 * 8, 7 + 9 * 8, + 4 + 11 * 8, 5 + 11 * 8, 4 + 12 * 8, 5 + 12 * 8, + 6 + 11 * 8, 7 + 11 * 8, 6 + 12 * 8, 7 + 12 * 8, + 4 + 13 * 8, 5 + 13 * 8, 4 + 14 * 8, 5 + 14 * 8, + 6 + 13 * 8, 7 + 13 * 8, 6 + 14 * 8, 7 + 14 * 8, + 0 + 0 * 8, 0 + 5 * 8, 0 + 10 * 8 +}; + +/** + * Memory management control operation opcode. + */ +typedef enum MMCOOpcode { + MMCO_END = 0, + MMCO_SHORT2UNUSED, + MMCO_LONG2UNUSED, + MMCO_SHORT2LONG, + MMCO_SET_MAX_LONG, + MMCO_RESET, + MMCO_LONG, +} MMCOOpcode; + typedef struct H264PredWeightTable { int use_weight; int use_weight_chroma; @@ -85,9 +124,13 @@ int ff_h264_decode_extradata(const uint8_t *data, int size, H264ParamSets *ps, int *is_avc, int *nal_length_size, int err_recognition, void *logctx); -/** - * compute profile from sps - */ -int ff_h264_get_profile(const SPS *sps); +static av_always_inline uint32_t pack16to32(unsigned a, unsigned b) +{ +#if HAVE_BIGENDIAN + return (b & 0xFFFF) + (a << 16); +#else + return (a & 0xFFFF) + (b << 16); +#endif +} #endif /* AVCODEC_H264_PARSE_H */ diff --git a/libavcodec/h264_parser.c b/libavcodec/h264_parser.c index cfbf6f448..50810f178 100644 --- a/libavcodec/h264_parser.c +++ b/libavcodec/h264_parser.c @@ -27,7 +27,6 @@ #define UNCHECKED_BITSTREAM_READER 1 -#include #include #include "libavutil/avutil.h" @@ -40,12 +39,15 @@ #include "get_bits.h" #include "golomb.h" #include "h264.h" +#include "h264dsp.h" +#include "h264_parse.h" #include "h264_sei.h" #include "h264_ps.h" +#include "h2645_parse.h" #include "h264data.h" -#include "internal.h" #include "mpegutils.h" #include "parser.h" +#include "startcode.h" typedef struct H264ParseContext { ParseContext pc; @@ -64,6 +66,15 @@ typedef struct H264ParseContext { int last_frame_num, last_picture_structure; } H264ParseContext; +static int find_start_code(const uint8_t *buf, int buf_size, + int buf_index, int next_avc) +{ + uint32_t state = -1; + + buf_index = avpriv_find_start_code(buf + buf_index, buf + next_avc + 1, &state) - buf - 1; + + return FFMIN(buf_index, buf_size); +} static int h264_find_frame_end(H264ParseContext *p, const uint8_t *buf, int buf_size, void *logctx) @@ -210,7 +221,7 @@ static int scan_mmco_reset(AVCodecParserContext *s, GetBitContext *gb, if (get_bits1(gb)) { // adaptive_ref_pic_marking_mode_flag int i; - for (i = 0; i < MAX_MMCO_COUNT; i++) { + for (i = 0; i < H264_MAX_MMCO_COUNT; i++) { MMCOOpcode opcode = get_ue_golomb_31(gb); if (opcode > (unsigned) MMCO_LONG) { av_log(logctx, AV_LOG_ERROR, diff --git a/libavcodec/h264_picture.c b/libavcodec/h264_picture.c index adf8a3237..2661ff469 100644 --- a/libavcodec/h264_picture.c +++ b/libavcodec/h264_picture.c @@ -26,31 +26,23 @@ */ #include "libavutil/avassert.h" -#include "libavutil/imgutils.h" -#include "internal.h" -#include "cabac.h" -#include "cabac_functions.h" #include "error_resilience.h" #include "avcodec.h" #include "h264dec.h" -#include "h264data.h" -#include "h264chroma.h" -#include "h264_mvpred.h" -#include "mathops.h" #include "mpegutils.h" -#include "rectangle.h" #include "thread.h" +#include "threadframe.h" void ff_h264_unref_picture(H264Context *h, H264Picture *pic) { - int off = offsetof(H264Picture, tf_grain) + sizeof(pic->tf_grain); + int off = offsetof(H264Picture, f_grain) + sizeof(pic->f_grain); int i; if (!pic->f || !pic->f->buf[0]) return; - ff_thread_release_buffer(h->avctx, &pic->tf); - ff_thread_release_buffer(h->avctx, &pic->tf_grain); + ff_thread_release_ext_buffer(h->avctx, &pic->tf); + ff_thread_release_buffer(h->avctx, pic->f_grain); av_buffer_unref(&pic->hwaccel_priv_buf); av_buffer_unref(&pic->qscale_table_buf); @@ -111,9 +103,7 @@ int ff_h264_ref_picture(H264Context *h, H264Picture *dst, H264Picture *src) goto fail; if (src->needs_fg) { - av_assert0(src->tf_grain.f == src->f_grain); - dst->tf_grain.f = dst->f_grain; - ret = ff_thread_ref_frame(&dst->tf_grain, &src->tf_grain); + ret = av_frame_ref(dst->f_grain, src->f_grain); if (ret < 0) goto fail; } @@ -164,16 +154,14 @@ int ff_h264_replace_picture(H264Context *h, H264Picture *dst, const H264Picture av_assert0(src->tf.f == src->f); dst->tf.f = dst->f; - ff_thread_release_buffer(h->avctx, &dst->tf); + ff_thread_release_ext_buffer(h->avctx, &dst->tf); ret = ff_thread_ref_frame(&dst->tf, &src->tf); if (ret < 0) goto fail; if (src->needs_fg) { - av_assert0(src->tf_grain.f == src->f_grain); - dst->tf_grain.f = dst->f_grain; - ff_thread_release_buffer(h->avctx, &dst->tf_grain); - ret = ff_thread_ref_frame(&dst->tf_grain, &src->tf_grain); + ff_thread_release_buffer(h->avctx, dst->f_grain); + ret = av_frame_ref(dst->f_grain, src->f_grain); if (ret < 0) goto fail; } diff --git a/libavcodec/h264_ps.c b/libavcodec/h264_ps.c index e21c2b56a..e16da68de 100644 --- a/libavcodec/h264_ps.c +++ b/libavcodec/h264_ps.c @@ -28,7 +28,6 @@ #include #include "libavutil/imgutils.h" -#include "internal.h" #include "mathops.h" #include "avcodec.h" #include "h264data.h" @@ -352,6 +351,10 @@ int ff_h264_decode_seq_parameter_set(GetBitContext *gb, AVCodecContext *avctx, } memcpy(sps->data, gb->buffer, sps->data_size); + // Re-add the removed stop bit (may be used by hwaccels). + if (!(gb->size_in_bits & 7) && sps->data_size < sizeof(sps->data)) + sps->data[sps->data_size++] = 0x80; + profile_idc = get_bits(gb, 8); constraint_set_flags |= get_bits1(gb) << 0; // constraint_set0_flag constraint_set_flags |= get_bits1(gb) << 1; // constraint_set1_flag @@ -485,7 +488,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')) sps->ref_frame_count = FFMAX(2, sps->ref_frame_count); - if (sps->ref_frame_count > MAX_DELAYED_PIC_COUNT) { + if (sps->ref_frame_count > H264_MAX_DPB_FRAMES) { av_log(avctx, AV_LOG_ERROR, "too many reference frames %d\n", sps->ref_frame_count); goto fail; @@ -517,11 +520,6 @@ int ff_h264_decode_seq_parameter_set(GetBitContext *gb, AVCodecContext *avctx, sps->direct_8x8_inference_flag = get_bits1(gb); -#ifndef ALLOW_INTERLACE - if (sps->mb_aff) - av_log(avctx, AV_LOG_ERROR, - "MBAFF support not included; enable it at compile-time.\n"); -#endif sps->crop = get_bits1(gb); if (sps->crop) { unsigned int crop_left = get_ue_golomb(gb); @@ -590,7 +588,7 @@ int ff_h264_decode_seq_parameter_set(GetBitContext *gb, AVCodecContext *avctx, * level */ if (!sps->bitstream_restriction_flag && (sps->ref_frame_count || avctx->strict_std_compliance >= FF_COMPLIANCE_STRICT)) { - sps->num_reorder_frames = MAX_DELAYED_PIC_COUNT - 1; + sps->num_reorder_frames = H264_MAX_DPB_FRAMES - 1; for (i = 0; i < FF_ARRAY_ELEMS(level_max_dpb_mbs); i++) { if (level_max_dpb_mbs[i][0] == sps->level_idc) { sps->num_reorder_frames = FFMIN(level_max_dpb_mbs[i][1] / (sps->mb_width * sps->mb_height), @@ -781,6 +779,10 @@ int ff_h264_decode_picture_parameter_set(GetBitContext *gb, AVCodecContext *avct } memcpy(pps->data, gb->buffer, pps->data_size); + // Re-add the removed stop bit (may be used by hwaccels). + if (!(bit_length & 7) && pps->data_size < sizeof(pps->data)) + pps->data[pps->data_size++] = 0x80; + pps->sps_id = get_ue_golomb_31(gb); if ((unsigned)pps->sps_id >= MAX_SPS_COUNT || !ps->sps_list[pps->sps_id]) { diff --git a/libavcodec/h264_ps.h b/libavcodec/h264_ps.h index 3f1ab72e3..dc52835ed 100644 --- a/libavcodec/h264_ps.h +++ b/libavcodec/h264_ps.h @@ -152,6 +152,11 @@ typedef struct H264ParamSets { int overread_warning_printed[2]; } H264ParamSets; +/** + * compute profile from sps + */ +int ff_h264_get_profile(const SPS *sps); + /** * Decode SPS */ diff --git a/libavcodec/h264_redundant_pps_bsf.c b/libavcodec/h264_redundant_pps_bsf.c index 769946abf..f8bab1f10 100644 --- a/libavcodec/h264_redundant_pps_bsf.c +++ b/libavcodec/h264_redundant_pps_bsf.c @@ -16,16 +16,18 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include +#include -#include "libavutil/common.h" +#include "libavutil/log.h" #include "bsf.h" #include "bsf_internal.h" #include "cbs.h" #include "cbs_bsf.h" #include "cbs_h264.h" +#include "codec_id.h" #include "h264.h" +#include "packet.h" #define NEW_GLOBAL_PIC_INIT_QP 26 @@ -125,11 +127,11 @@ 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", +const FFBitStreamFilter ff_h264_redundant_pps_bsf = { + .p.name = "h264_redundant_pps", + .p.codec_ids = h264_redundant_pps_codec_ids, .priv_data_size = sizeof(H264RedundantPPSContext), .init = &h264_redundant_pps_init, .close = &ff_cbs_bsf_generic_close, .filter = &ff_cbs_bsf_generic_filter, - .codec_ids = h264_redundant_pps_codec_ids, }; diff --git a/libavcodec/h264_refs.c b/libavcodec/h264_refs.c index dae8bd278..50bbe9491 100644 --- a/libavcodec/h264_refs.c +++ b/libavcodec/h264_refs.c @@ -28,7 +28,6 @@ #include #include "libavutil/avassert.h" -#include "internal.h" #include "avcodec.h" #include "h264.h" #include "h264dec.h" @@ -729,7 +728,7 @@ int ff_h264_execute_ref_pic_marking(H264Context *h) h->poc.frame_num = h->cur_pic_ptr->frame_num = 0; h->mmco_reset = 1; h->cur_pic_ptr->mmco_reset = 1; - for (j = 0; j < MAX_DELAYED_PIC_COUNT; j++) + for (j = 0; j < FF_ARRAY_ELEMS(h->last_pocs); j++) h->last_pocs[j] = INT_MIN; break; default: av_assert0(0); @@ -849,7 +848,7 @@ int ff_h264_decode_ref_pic_marking(H264SliceContext *sl, GetBitContext *gb, } else { sl->explicit_ref_marking = get_bits1(gb); if (sl->explicit_ref_marking) { - for (i = 0; i < MAX_MMCO_COUNT; i++) { + for (i = 0; i < FF_ARRAY_ELEMS(sl->mmco); i++) { MMCOOpcode opcode = get_ue_golomb_31(gb); mmco[i].opcode = opcode; diff --git a/libavcodec/h264_sei.c b/libavcodec/h264_sei.c index 329c2ea4f..034ddb8f1 100644 --- a/libavcodec/h264_sei.c +++ b/libavcodec/h264_sei.c @@ -28,9 +28,9 @@ #include #include #include -#include "libavutil/common.h" #include "libavutil/error.h" #include "libavutil/log.h" +#include "libavutil/macros.h" #include "libavutil/mem.h" #include "atsc_a53.h" #include "get_bits.h" diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index c21004df9..d56722a5c 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -25,10 +25,12 @@ * @author Michael Niedermayer */ +#include "config_components.h" + #include "libavutil/avassert.h" #include "libavutil/display.h" -#include "libavutil/imgutils.h" #include "libavutil/film_grain_params.h" +#include "libavutil/pixdesc.h" #include "libavutil/stereo3d.h" #include "libavutil/timecode.h" #include "internal.h" @@ -40,13 +42,13 @@ #include "h264dec.h" #include "h264data.h" #include "h264chroma.h" -#include "h264_mvpred.h" #include "h264_ps.h" #include "golomb.h" #include "mathops.h" #include "mpegutils.h" #include "rectangle.h" #include "thread.h" +#include "threadframe.h" static const uint8_t field_scan[16+1] = { 0 + 0 * 4, 0 + 1 * 4, 1 + 0 * 4, 0 + 2 * 4, @@ -192,17 +194,16 @@ static int alloc_picture(H264Context *h, H264Picture *pic) av_assert0(!pic->f->data[0]); pic->tf.f = pic->f; - ret = ff_thread_get_buffer(h->avctx, &pic->tf, pic->reference ? - AV_GET_BUFFER_FLAG_REF : 0); + ret = ff_thread_get_ext_buffer(h->avctx, &pic->tf, + pic->reference ? AV_GET_BUFFER_FLAG_REF : 0); if (ret < 0) goto fail; if (pic->needs_fg) { - pic->tf_grain.f = pic->f_grain; pic->f_grain->format = pic->f->format; pic->f_grain->width = pic->f->width; pic->f_grain->height = pic->f->height; - ret = ff_thread_get_buffer(h->avctx, &pic->tf_grain, 0); + ret = ff_thread_get_buffer(h->avctx, pic->f_grain, 0); if (ret < 0) goto fail; } @@ -428,7 +429,7 @@ int ff_h264_update_thread_context(AVCodecContext *dst, copy_picture_range(h->short_ref, h1->short_ref, 32, h, h1); copy_picture_range(h->long_ref, h1->long_ref, 32, h, h1); copy_picture_range(h->delayed_pic, h1->delayed_pic, - MAX_DELAYED_PIC_COUNT + 2, h, h1); + FF_ARRAY_ELEMS(h->delayed_pic), h, h1); h->frame_recovered = h1->frame_recovered; @@ -536,7 +537,7 @@ static int h264_frame_start(H264Context *h) h->cur_pic_ptr = pic; ff_h264_unref_picture(h, &h->cur_pic); if (CONFIG_ERROR_RESILIENCE) { - ff_h264_set_erpic(&h->slice_ctx[0].er.cur_pic, NULL); + ff_h264_set_erpic(&h->er.cur_pic, NULL); } if ((ret = ff_h264_ref_picture(h, &h->cur_pic, h->cur_pic_ptr)) < 0) @@ -548,9 +549,9 @@ static int h264_frame_start(H264Context *h) } if (CONFIG_ERROR_RESILIENCE && h->enable_er) { - ff_er_frame_start(&h->slice_ctx[0].er); - ff_h264_set_erpic(&h->slice_ctx[0].er.last_pic, NULL); - ff_h264_set_erpic(&h->slice_ctx[0].er.next_pic, NULL); + ff_er_frame_start(&h->er); + ff_h264_set_erpic(&h->er.last_pic, NULL); + ff_h264_set_erpic(&h->er.next_pic, NULL); } for (i = 0; i < 16; i++) { @@ -998,16 +999,12 @@ static int h264_slice_header_init(H264Context *h) sps->chroma_format_idc); ff_h264chroma_init(&h->h264chroma, sps->bit_depth_chroma); ff_h264qpel_init(&h->h264qpel, sps->bit_depth_luma); - ff_h264_pred_init(&h->hpc, h->avctx->codec_id, sps->bit_depth_luma, + ff_h264_pred_init(&h->hpc, AV_CODEC_ID_H264, sps->bit_depth_luma, sps->chroma_format_idc); ff_videodsp_init(&h->vdsp, sps->bit_depth_luma); if (!HAVE_THREADS || !(h->avctx->active_thread_type & FF_THREAD_SLICE)) { - ret = ff_h264_slice_context_init(h, &h->slice_ctx[0]); - if (ret < 0) { - av_log(h->avctx, AV_LOG_ERROR, "context_init() failed.\n"); - goto fail; - } + ff_h264_slice_context_init(h, &h->slice_ctx[0]); } else { for (i = 0; i < h->nb_slice_ctx; i++) { H264SliceContext *sl = &h->slice_ctx[i]; @@ -1017,10 +1014,7 @@ static int h264_slice_header_init(H264Context *h) sl->mvd_table[0] = h->mvd_table[0] + i * 8 * 2 * h->mb_stride; sl->mvd_table[1] = h->mvd_table[1] + i * 8 * 2 * h->mb_stride; - if ((ret = ff_h264_slice_context_init(h, sl)) < 0) { - av_log(h->avctx, AV_LOG_ERROR, "context_init() failed.\n"); - goto fail; - } + ff_h264_slice_context_init(h, sl); } } @@ -1456,7 +1450,7 @@ static int h264_select_output_frame(H264Context *h) } for (i = 0; 1; i++) { - if(i == MAX_DELAYED_PIC_COUNT || cur->poc < h->last_pocs[i]){ + if(i == H264_MAX_DPB_FRAMES || cur->poc < h->last_pocs[i]){ if(i) h->last_pocs[i-1] = cur->poc; break; @@ -1464,13 +1458,13 @@ static int h264_select_output_frame(H264Context *h) h->last_pocs[i-1]= h->last_pocs[i]; } } - out_of_order = MAX_DELAYED_PIC_COUNT - i; + out_of_order = H264_MAX_DPB_FRAMES - 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] - (int64_t)h->last_pocs[MAX_DELAYED_PIC_COUNT-2] > 2)) + || (h->last_pocs[H264_MAX_DPB_FRAMES-2] > INT_MIN && h->last_pocs[H264_MAX_DPB_FRAMES-1] - (int64_t)h->last_pocs[H264_MAX_DPB_FRAMES-2] > 2)) out_of_order = FFMAX(out_of_order, 1); - if (out_of_order == MAX_DELAYED_PIC_COUNT) { + if (out_of_order == H264_MAX_DPB_FRAMES) { av_log(h->avctx, AV_LOG_VERBOSE, "Invalid POC %d<%d\n", cur->poc, h->last_pocs[0]); - for (i = 1; i < MAX_DELAYED_PIC_COUNT; i++) + for (i = 1; i < H264_MAX_DPB_FRAMES; i++) h->last_pocs[i] = INT_MIN; h->last_pocs[0] = cur->poc; cur->mmco_reset = 1; @@ -1484,7 +1478,7 @@ static int h264_select_output_frame(H264Context *h) while (h->delayed_pic[pics]) pics++; - av_assert0(pics <= MAX_DELAYED_PIC_COUNT); + av_assert0(pics <= H264_MAX_DPB_FRAMES); h->delayed_pic[pics++] = cur; if (cur->reference == 0) @@ -1700,7 +1694,7 @@ static int h264_field_start(H264Context *h, const H264SliceContext *sl, ff_thread_await_progress(&prev->tf, INT_MAX, 0); if (prev->field_picture) ff_thread_await_progress(&prev->tf, INT_MAX, 1); - ff_thread_release_buffer(h->avctx, &h->short_ref[0]->tf); + ff_thread_release_ext_buffer(h->avctx, &h->short_ref[0]->tf); h->short_ref[0]->tf.f = h->short_ref[0]->f; ret = ff_thread_ref_frame(&h->short_ref[0]->tf, &prev->tf); if (ret < 0) @@ -2168,9 +2162,9 @@ static int h264_slice_init(H264Context *h, H264SliceContext *sl, if (h->avctx->debug & FF_DEBUG_PICT_INFO) { av_log(h->avctx, AV_LOG_DEBUG, - "slice:%d %s mb:%d %c%s%s frame:%d poc:%d/%d ref:%d/%d qp:%d loop:%d:%d:%d weight:%d%s %s\n", + "slice:%d %c mb:%d %c%s%s frame:%d poc:%d/%d ref:%d/%d qp:%d loop:%d:%d:%d weight:%d%s %s\n", sl->slice_num, - (h->picture_structure == PICT_FRAME ? "F" : h->picture_structure == PICT_TOP_FIELD ? "T" : "B"), + (h->picture_structure == PICT_FRAME ? 'F' : h->picture_structure == PICT_TOP_FIELD ? 'T' : 'B'), sl->mb_y * h->mb_width + sl->mb_x, av_get_picture_type_char(sl->slice_type), sl->slice_type_fixed ? " fix" : "", @@ -2666,7 +2660,7 @@ static void decode_finish_row(const H264Context *h, H264SliceContext *sl) ff_h264_draw_horiz_band(h, sl, top, height); - if (h->droppable || sl->h264->slice_ctx[0].er.error_occurred) + if (h->droppable || h->er.error_occurred) return; ff_thread_report_progress(&h->cur_pic_ptr->tf, top + height - 1, @@ -2681,9 +2675,7 @@ static void er_add_slice(H264SliceContext *sl, return; if (CONFIG_ERROR_RESILIENCE) { - ERContext *er = &sl->h264->slice_ctx[0].er; - - ff_er_add_slice(er, startx, starty, endx, endy, status); + ff_er_add_slice(sl->er, startx, starty, endx, endy, status); } } @@ -2712,13 +2704,13 @@ static int decode_slice(struct AVCodecContext *avctx, void *arg) sl->is_complex = FRAME_MBAFF(h) || h->picture_structure != PICT_FRAME || (CONFIG_GRAY && (h->flags & AV_CODEC_FLAG_GRAY)); - if (!(h->avctx->active_thread_type & FF_THREAD_SLICE) && h->picture_structure == PICT_FRAME && h->slice_ctx[0].er.error_status_table) { + if (!(h->avctx->active_thread_type & FF_THREAD_SLICE) && h->picture_structure == PICT_FRAME && sl->er->error_status_table) { const int start_i = av_clip(sl->resync_mb_x + sl->resync_mb_y * h->mb_width, 0, h->mb_num - 1); if (start_i) { - int prev_status = h->slice_ctx[0].er.error_status_table[h->slice_ctx[0].er.mb_index2xy[start_i - 1]]; + int prev_status = sl->er->error_status_table[sl->er->mb_index2xy[start_i - 1]]; prev_status &= ~ VP_START; if (prev_status != (ER_MV_END | ER_DC_END | ER_AC_END)) - h->slice_ctx[0].er.error_occurred = 1; + sl->er->error_occurred = 1; } } @@ -2930,9 +2922,6 @@ int ff_h264_execute_decode_slices(H264Context *h) int slice_idx; sl = &h->slice_ctx[i]; - if (CONFIG_ERROR_RESILIENCE) { - sl->er.error_count = 0; - } /* make sure none of those slices overlap */ slice_idx = sl->mb_y * h->mb_width + sl->mb_x; @@ -2953,10 +2942,6 @@ int ff_h264_execute_decode_slices(H264Context *h) /* pull back stuff from slices to master context */ sl = &h->slice_ctx[context_count - 1]; h->mb_y = sl->mb_y; - if (CONFIG_ERROR_RESILIENCE) { - for (i = 1; i < context_count; i++) - h->slice_ctx[0].er.error_count += h->slice_ctx[i].er.error_count; - } if (h->postpone_filter) { h->postpone_filter = 0; diff --git a/libavcodec/h264chroma.c b/libavcodec/h264chroma.c index 0ae6c793e..60b86b6fb 100644 --- a/libavcodec/h264chroma.c +++ b/libavcodec/h264chroma.c @@ -46,16 +46,17 @@ av_cold void ff_h264chroma_init(H264ChromaContext *c, int bit_depth) SET_CHROMA(8); } - if (ARCH_AARCH64) - ff_h264chroma_init_aarch64(c, bit_depth); - if (ARCH_ARM) - ff_h264chroma_init_arm(c, bit_depth); - if (ARCH_PPC) - ff_h264chroma_init_ppc(c, bit_depth); - if (ARCH_X86) - ff_h264chroma_init_x86(c, bit_depth); - if (ARCH_MIPS) - ff_h264chroma_init_mips(c, bit_depth); - if (ARCH_LOONGARCH64) - ff_h264chroma_init_loongarch(c, bit_depth); +#if ARCH_AARCH64 + ff_h264chroma_init_aarch64(c, bit_depth); +#elif ARCH_ARM + ff_h264chroma_init_arm(c, bit_depth); +#elif ARCH_PPC + ff_h264chroma_init_ppc(c, bit_depth); +#elif ARCH_X86 + ff_h264chroma_init_x86(c, bit_depth); +#elif ARCH_MIPS + ff_h264chroma_init_mips(c, bit_depth); +#elif ARCH_LOONGARCH64 + ff_h264chroma_init_loongarch(c, bit_depth); +#endif } diff --git a/libavcodec/h264data.c b/libavcodec/h264data.c index eb8728a9d..3e9e68cb0 100644 --- a/libavcodec/h264data.c +++ b/libavcodec/h264data.c @@ -30,7 +30,7 @@ #include "libavutil/avutil.h" -#include "h264dec.h" +#include "h264_parse.h" #include "h264data.h" #include "mpegutils.h" diff --git a/libavcodec/h264data.h b/libavcodec/h264data.h index 2968b08b7..4efe76a34 100644 --- a/libavcodec/h264data.h +++ b/libavcodec/h264data.h @@ -21,7 +21,8 @@ #include -#include "h264dec.h" +#include "libavutil/rational.h" +#include "h264.h" extern const uint8_t ff_h264_golomb_to_pict_type[5]; extern const uint8_t ff_h264_golomb_to_intra4x4_cbp[48]; diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c index 6a5bf51f5..2a5b53ea5 100644 --- a/libavcodec/h264dec.c +++ b/libavcodec/h264dec.c @@ -27,34 +27,30 @@ #define UNCHECKED_BITSTREAM_READER 1 +#include "config_components.h" + #include "libavutil/avassert.h" -#include "libavutil/display.h" #include "libavutil/imgutils.h" #include "libavutil/opt.h" -#include "libavutil/stereo3d.h" +#include "libavutil/thread.h" #include "libavutil/video_enc_params.h" +#include "codec_internal.h" #include "internal.h" -#include "bytestream.h" -#include "cabac.h" -#include "cabac_functions.h" #include "error_resilience.h" #include "avcodec.h" #include "h264.h" #include "h264dec.h" #include "h2645_parse.h" #include "h264data.h" -#include "h264chroma.h" -#include "h264_mvpred.h" #include "h264_ps.h" #include "golomb.h" #include "hwconfig.h" -#include "mathops.h" -#include "me_cmp.h" #include "mpegutils.h" #include "profiles.h" #include "rectangle.h" #include "thread.h" +#include "threadframe.h" const uint16_t ff_h264_mb_sizes[4] = { 256, 384, 512, 768 }; @@ -158,14 +154,16 @@ void ff_h264_free_tables(H264Context *h) av_buffer_pool_uninit(&h->motion_val_pool); av_buffer_pool_uninit(&h->ref_index_pool); +#if CONFIG_ERROR_RESILIENCE + av_freep(&h->er.mb_index2xy); + av_freep(&h->er.error_status_table); + av_freep(&h->er.er_temp_buffer); + av_freep(&h->dc_val_base); +#endif + for (i = 0; i < h->nb_slice_ctx; i++) { H264SliceContext *sl = &h->slice_ctx[i]; - av_freep(&sl->dc_val_base); - av_freep(&sl->er.mb_index2xy); - av_freep(&sl->er.error_status_table); - av_freep(&sl->er.er_temp_buffer); - av_freep(&sl->bipred_scratchpad); av_freep(&sl->edge_emu_buffer); av_freep(&sl->top_borders[0]); @@ -180,6 +178,7 @@ void ff_h264_free_tables(H264Context *h) int ff_h264_alloc_tables(H264Context *h) { + ERContext *const er = &h->er; const int big_mb_num = h->mb_stride * (h->mb_height + 1); const int row_mb_num = 2*h->mb_stride*FFMAX(h->nb_slice_ctx, 1); const int st_size = big_mb_num + h->mb_stride; @@ -212,33 +211,11 @@ int ff_h264_alloc_tables(H264Context *h) h->mb2br_xy[mb_xy] = 8 * (FMO ? mb_xy : (mb_xy % (2 * h->mb_stride))); } - return 0; -} - -/** - * Init context - * Allocate buffers which are not shared amongst multiple threads. - */ -int ff_h264_slice_context_init(H264Context *h, H264SliceContext *sl) -{ - ERContext *er = &sl->er; - int mb_array_size = h->mb_height * h->mb_stride; - int y_size = (2 * h->mb_width + 1) * (2 * h->mb_height + 1); - int c_size = h->mb_stride * (h->mb_height + 1); - int yc_size = y_size + 2 * c_size; - int x, y, i; - - sl->ref_cache[0][scan8[5] + 1] = - sl->ref_cache[0][scan8[7] + 1] = - sl->ref_cache[0][scan8[13] + 1] = - sl->ref_cache[1][scan8[5] + 1] = - sl->ref_cache[1][scan8[7] + 1] = - sl->ref_cache[1][scan8[13] + 1] = PART_NOT_AVAILABLE; - - if (sl != h->slice_ctx) { - memset(er, 0, sizeof(*er)); - } else if (CONFIG_ERROR_RESILIENCE) { + if (CONFIG_ERROR_RESILIENCE) { const int er_size = h->mb_height * h->mb_stride * (4*sizeof(int) + 1); + int mb_array_size = h->mb_height * h->mb_stride; + int y_size = (2 * h->mb_width + 1) * (2 * h->mb_height + 1); + int yc_size = y_size + 2 * big_mb_num; /* init ER */ er->avctx = h->avctx; @@ -256,7 +233,7 @@ int ff_h264_slice_context_init(H264Context *h, H264SliceContext *sl) if (!FF_ALLOCZ_TYPED_ARRAY(er->mb_index2xy, h->mb_num + 1) || !FF_ALLOCZ_TYPED_ARRAY(er->error_status_table, mb_array_size) || !FF_ALLOCZ_TYPED_ARRAY(er->er_temp_buffer, er_size) || - !FF_ALLOCZ_TYPED_ARRAY(sl->dc_val_base, yc_size)) + !FF_ALLOCZ_TYPED_ARRAY(h->dc_val_base, yc_size)) return AVERROR(ENOMEM); // ff_h264_free_tables will clean up for us for (y = 0; y < h->mb_height; y++) @@ -265,16 +242,31 @@ int ff_h264_slice_context_init(H264Context *h, H264SliceContext *sl) er->mb_index2xy[h->mb_height * h->mb_width] = (h->mb_height - 1) * h->mb_stride + h->mb_width; - er->dc_val[0] = sl->dc_val_base + h->mb_width * 2 + 2; - er->dc_val[1] = sl->dc_val_base + y_size + h->mb_stride + 1; - er->dc_val[2] = er->dc_val[1] + c_size; - for (i = 0; i < yc_size; i++) - sl->dc_val_base[i] = 1024; + er->dc_val[0] = h->dc_val_base + h->mb_width * 2 + 2; + er->dc_val[1] = h->dc_val_base + y_size + h->mb_stride + 1; + er->dc_val[2] = er->dc_val[1] + big_mb_num; + for (int i = 0; i < yc_size; i++) + h->dc_val_base[i] = 1024; } return 0; } +/** + * Init slice context + */ +void ff_h264_slice_context_init(H264Context *h, H264SliceContext *sl) +{ + sl->ref_cache[0][scan8[5] + 1] = + sl->ref_cache[0][scan8[7] + 1] = + sl->ref_cache[0][scan8[13] + 1] = + sl->ref_cache[1][scan8[5] + 1] = + sl->ref_cache[1][scan8[7] + 1] = + sl->ref_cache[1][scan8[13] + 1] = PART_NOT_AVAILABLE; + + sl->er = &h->er; +} + static int h264_init_pic(H264Picture *pic) { pic->f = av_frame_alloc(); @@ -308,7 +300,7 @@ static int h264_init_context(AVCodecContext *avctx, H264Context *h) h->sei.unregistered.x264_build = -1; h->next_outputed_poc = INT_MIN; - for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++) + for (i = 0; i < FF_ARRAY_ELEMS(h->last_pocs); i++) h->last_pocs[i] = INT_MIN; ff_h264_sei_uninit(&h->sei); @@ -445,7 +437,7 @@ static void idr(H264Context *h) h->poc.prev_frame_num_offset = 0; h->poc.prev_poc_msb = 1<<16; h->poc.prev_poc_lsb = -1; - for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++) + for (i = 0; i < FF_ARRAY_ELEMS(h->last_pocs); i++) h->last_pocs[i] = INT_MIN; } @@ -680,6 +672,10 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size) avpriv_request_sample(avctx, "data partitioning"); break; case H264_NAL_SEI: + if (h->setup_finished) { + avpriv_request_sample(avctx, "Late SEI"); + break; + } ret = ff_h264_sei_decode(&h->sei, &nal->gb, &h->ps, avctx); h->has_recovery_point = h->has_recovery_point || h->sei.recovery_point.recovery_frame_cnt != -1; if (avctx->debug & FF_DEBUG_GREEN_MD) @@ -743,7 +739,7 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size) goto end; // set decode_error_flags to allow users to detect concealed decoding errors - if ((ret < 0 || h->slice_ctx->er.error_occurred) && h->cur_pic_ptr) { + if ((ret < 0 || h->er.error_occurred) && h->cur_pic_ptr) { h->cur_pic_ptr->f->decode_error_flags |= FF_DECODE_ERROR_DECODE_SLICES; } @@ -768,25 +764,23 @@ end: H264SliceContext *sl = h->slice_ctx; int use_last_pic = h->last_pic_for_ec.f->buf[0] && !sl->ref_count[0]; - ff_h264_set_erpic(&sl->er.cur_pic, h->cur_pic_ptr); + ff_h264_set_erpic(&h->er.cur_pic, h->cur_pic_ptr); if (use_last_pic) { - ff_h264_set_erpic(&sl->er.last_pic, &h->last_pic_for_ec); + ff_h264_set_erpic(&h->er.last_pic, &h->last_pic_for_ec); sl->ref_list[0][0].parent = &h->last_pic_for_ec; memcpy(sl->ref_list[0][0].data, h->last_pic_for_ec.f->data, sizeof(sl->ref_list[0][0].data)); memcpy(sl->ref_list[0][0].linesize, h->last_pic_for_ec.f->linesize, sizeof(sl->ref_list[0][0].linesize)); sl->ref_list[0][0].reference = h->last_pic_for_ec.reference; } else if (sl->ref_count[0]) { - ff_h264_set_erpic(&sl->er.last_pic, sl->ref_list[0][0].parent); + ff_h264_set_erpic(&h->er.last_pic, sl->ref_list[0][0].parent); } else - ff_h264_set_erpic(&sl->er.last_pic, NULL); + ff_h264_set_erpic(&h->er.last_pic, NULL); if (sl->ref_count[1]) - ff_h264_set_erpic(&sl->er.next_pic, sl->ref_list[1][0].parent); + ff_h264_set_erpic(&h->er.next_pic, sl->ref_list[1][0].parent); - sl->er.ref_count = sl->ref_count[0]; - - ff_er_frame_end(&sl->er); + ff_er_frame_end(&h->er); if (use_last_pic) memset(&sl->ref_list[0][0], 0, sizeof(sl->ref_list[0][0])); } @@ -939,7 +933,7 @@ static int finalize_frame(H264Context *h, AVFrame *dst, H264Picture *out, int *g *got_frame = 1; - if (CONFIG_MPEGVIDEO) { + if (CONFIG_MPEGVIDEODEC) { ff_print_debug_info2(h->avctx, dst, NULL, out->mb_type, out->qscale_table, @@ -984,13 +978,12 @@ static int send_next_delayed_frame(H264Context *h, AVFrame *dst_frame, return buf_index; } -static int h264_decode_frame(AVCodecContext *avctx, void *data, +static int h264_decode_frame(AVCodecContext *avctx, AVFrame *pict, int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; H264Context *h = avctx->priv_data; - AVFrame *pict = data; int buf_index; int ret; @@ -1073,16 +1066,16 @@ static const AVClass h264_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_h264_decoder = { - .name = "h264", - .long_name = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_H264, +const FFCodec ff_h264_decoder = { + .p.name = "h264", + .p.long_name = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_H264, .priv_data_size = sizeof(H264Context), .init = h264_decode_init, .close = h264_decode_end, - .decode = h264_decode_frame, - .capabilities = /*AV_CODEC_CAP_DRAW_HORIZ_BAND |*/ AV_CODEC_CAP_DR1 | + FF_CODEC_DECODE_CB(h264_decode_frame), + .p.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 *const []) { @@ -1114,6 +1107,6 @@ const AVCodec ff_h264_decoder = { .flush = h264_decode_flush, .update_thread_context = ONLY_IF_THREADS_ENABLED(ff_h264_update_thread_context), .update_thread_context_for_user = ONLY_IF_THREADS_ENABLED(ff_h264_update_thread_context_for_user), - .profiles = NULL_IF_CONFIG_SMALL(ff_h264_profiles), - .priv_class = &h264_class, + .p.profiles = NULL_IF_CONFIG_SMALL(ff_h264_profiles), + .p.priv_class = &h264_class, }; diff --git a/libavcodec/h264dec.h b/libavcodec/h264dec.h index 87c4e4e53..9a1ec1bac 100644 --- a/libavcodec/h264dec.h +++ b/libavcodec/h264dec.h @@ -31,7 +31,6 @@ #include "libavutil/buffer.h" #include "libavutil/intreadwrite.h" #include "libavutil/mem_internal.h" -#include "libavutil/thread.h" #include "cabac.h" #include "error_resilience.h" @@ -44,19 +43,12 @@ #include "h264pred.h" #include "h264qpel.h" #include "h274.h" -#include "internal.h" #include "mpegutils.h" -#include "parser.h" -#include "qpeldsp.h" #include "rectangle.h" #include "videodsp.h" #define H264_MAX_PICTURE_COUNT 36 -#define MAX_MMCO_COUNT 66 - -#define MAX_DELAYED_PIC_COUNT 16 - /* Compiling in interlaced support reduces the speed * of progressive decoding by about 2%. */ #define ALLOW_INTERLACE @@ -100,24 +92,9 @@ #define CHROMA422(h) ((h)->ps.sps->chroma_format_idc == 2) #define CHROMA444(h) ((h)->ps.sps->chroma_format_idc == 3) -#define MB_TYPE_REF0 MB_TYPE_ACPRED // dirty but it fits in 16 bit -#define MB_TYPE_8x8DCT 0x01000000 #define IS_REF0(a) ((a) & MB_TYPE_REF0) #define IS_8x8DCT(a) ((a) & MB_TYPE_8x8DCT) -/** - * Memory management control operation opcode. - */ -typedef enum MMCOOpcode { - MMCO_END = 0, - MMCO_SHORT2UNUSED, - MMCO_LONG2UNUSED, - MMCO_SHORT2LONG, - MMCO_SET_MAX_LONG, - MMCO_RESET, - MMCO_LONG, -} MMCOOpcode; - /** * Memory management control operation. */ @@ -132,7 +109,6 @@ typedef struct H264Picture { ThreadFrame tf; AVFrame *f_grain; - ThreadFrame tf_grain; AVBufferRef *qscale_table_buf; int8_t *qscale_table; @@ -162,6 +138,11 @@ typedef struct H264Picture { int mbaff; ///< 1 -> MBAFF frame 0-> not MBAFF int field_picture; ///< whether or not picture was encoded in separate fields +/** + * H264Picture.reference has this flag set, + * when the picture is held for delayed output. + */ +#define DELAYED_PIC_REF (1 << 2) int reference; int recovered; ///< picture at IDR or recovery point + recovery count int invalid_gap; @@ -187,9 +168,9 @@ typedef struct H264Ref { } H264Ref; typedef struct H264SliceContext { - struct H264Context *h264; + const struct H264Context *h264; GetBitContext gb; - ERContext er; + ERContext *er; int slice_num; int slice_type; @@ -290,7 +271,6 @@ typedef struct H264SliceContext { unsigned int pps_id; const uint8_t *intra_pcm_ptr; - int16_t *dc_val_base; uint8_t *bipred_scratchpad; uint8_t *edge_emu_buffer; @@ -331,7 +311,7 @@ typedef struct H264SliceContext { uint8_t cabac_state[1024]; int cabac_init_idc; - MMCO mmco[MAX_MMCO_COUNT]; + MMCO mmco[H264_MAX_MMCO_COUNT]; int nb_mmco; int explicit_ref_marking; @@ -407,7 +387,6 @@ typedef struct H264Context { uint8_t (*non_zero_count)[48]; #define LIST_NOT_USED -1 // FIXME rename? -#define PART_NOT_AVAILABLE -2 /** * block_offset[ 0..23] for frame macroblocks @@ -481,8 +460,8 @@ typedef struct H264Context { H264Ref default_ref[2]; H264Picture *short_ref[32]; H264Picture *long_ref[32]; - H264Picture *delayed_pic[MAX_DELAYED_PIC_COUNT + 2]; // FIXME size? - int last_pocs[MAX_DELAYED_PIC_COUNT]; + H264Picture *delayed_pic[H264_MAX_DPB_FRAMES + 2]; // FIXME size? + int last_pocs[H264_MAX_DPB_FRAMES]; H264Picture *next_output_pic; int next_outputed_poc; int poc_offset; ///< PicOrderCnt_offset from SMPTE RDD-2006 @@ -490,7 +469,7 @@ typedef struct H264Context { /** * memory management control operations buffer. */ - MMCO mmco[MAX_MMCO_COUNT]; + MMCO mmco[H264_MAX_MMCO_COUNT]; int nb_mmco; int mmco_reset; int explicit_ref_marking; @@ -563,6 +542,8 @@ typedef struct H264Context { int height_from_caller; int enable_er; + ERContext er; + int16_t *dc_val_base; H264SEIContext sei; @@ -660,41 +641,6 @@ void ff_h264_filter_mb(const H264Context *h, H264SliceContext *sl, int mb_x, int #define LUMA_DC_BLOCK_INDEX 48 #define CHROMA_DC_BLOCK_INDEX 49 -// This table must be here because scan8[constant] must be known at compiletime -static const uint8_t scan8[16 * 3 + 3] = { - 4 + 1 * 8, 5 + 1 * 8, 4 + 2 * 8, 5 + 2 * 8, - 6 + 1 * 8, 7 + 1 * 8, 6 + 2 * 8, 7 + 2 * 8, - 4 + 3 * 8, 5 + 3 * 8, 4 + 4 * 8, 5 + 4 * 8, - 6 + 3 * 8, 7 + 3 * 8, 6 + 4 * 8, 7 + 4 * 8, - 4 + 6 * 8, 5 + 6 * 8, 4 + 7 * 8, 5 + 7 * 8, - 6 + 6 * 8, 7 + 6 * 8, 6 + 7 * 8, 7 + 7 * 8, - 4 + 8 * 8, 5 + 8 * 8, 4 + 9 * 8, 5 + 9 * 8, - 6 + 8 * 8, 7 + 8 * 8, 6 + 9 * 8, 7 + 9 * 8, - 4 + 11 * 8, 5 + 11 * 8, 4 + 12 * 8, 5 + 12 * 8, - 6 + 11 * 8, 7 + 11 * 8, 6 + 12 * 8, 7 + 12 * 8, - 4 + 13 * 8, 5 + 13 * 8, 4 + 14 * 8, 5 + 14 * 8, - 6 + 13 * 8, 7 + 13 * 8, 6 + 14 * 8, 7 + 14 * 8, - 0 + 0 * 8, 0 + 5 * 8, 0 + 10 * 8 -}; - -static av_always_inline uint32_t pack16to32(unsigned a, unsigned b) -{ -#if HAVE_BIGENDIAN - return (b & 0xFFFF) + (a << 16); -#else - return (a & 0xFFFF) + (b << 16); -#endif -} - -static av_always_inline uint16_t pack8to16(unsigned a, unsigned b) -{ -#if HAVE_BIGENDIAN - return (b & 0xFF) + (a << 8); -#else - return (a & 0xFF) + (b << 8); -#endif -} - /** * Get the chroma qp. */ @@ -833,23 +779,13 @@ static av_always_inline int get_dct8x8_allowed(const H264Context *h, H264SliceCo 0x0001000100010001ULL)); } -static inline int find_start_code(const uint8_t *buf, int buf_size, - int buf_index, int next_avc) -{ - uint32_t state = -1; - - buf_index = avpriv_find_start_code(buf + buf_index, buf + next_avc + 1, &state) - buf - 1; - - return FFMIN(buf_index, buf_size); -} - int ff_h264_field_end(H264Context *h, H264SliceContext *sl, int in_setup); int ff_h264_ref_picture(H264Context *h, H264Picture *dst, H264Picture *src); int ff_h264_replace_picture(H264Context *h, H264Picture *dst, const H264Picture *src); void ff_h264_unref_picture(H264Context *h, H264Picture *pic); -int ff_h264_slice_context_init(H264Context *h, H264SliceContext *sl); +void ff_h264_slice_context_init(H264Context *h, H264SliceContext *sl); void ff_h264_draw_horiz_band(const H264Context *h, H264SliceContext *sl, int y, int height); diff --git a/libavcodec/h264dsp.c b/libavcodec/h264dsp.c index f97ac2823..4d2ee10ba 100644 --- a/libavcodec/h264dsp.c +++ b/libavcodec/h264dsp.c @@ -152,10 +152,17 @@ av_cold void ff_h264dsp_init(H264DSPContext *c, const int bit_depth, } c->startcode_find_candidate = ff_startcode_find_candidate_c; - if (ARCH_AARCH64) ff_h264dsp_init_aarch64(c, bit_depth, chroma_format_idc); - if (ARCH_ARM) ff_h264dsp_init_arm(c, bit_depth, chroma_format_idc); - if (ARCH_PPC) ff_h264dsp_init_ppc(c, bit_depth, chroma_format_idc); - if (ARCH_X86) ff_h264dsp_init_x86(c, bit_depth, chroma_format_idc); - if (ARCH_MIPS) ff_h264dsp_init_mips(c, bit_depth, chroma_format_idc); - if (ARCH_LOONGARCH) ff_h264dsp_init_loongarch(c, bit_depth, chroma_format_idc); +#if ARCH_AARCH64 + ff_h264dsp_init_aarch64(c, bit_depth, chroma_format_idc); +#elif ARCH_ARM + ff_h264dsp_init_arm(c, bit_depth, chroma_format_idc); +#elif ARCH_PPC + ff_h264dsp_init_ppc(c, bit_depth, chroma_format_idc); +#elif ARCH_X86 + ff_h264dsp_init_x86(c, bit_depth, chroma_format_idc); +#elif ARCH_MIPS + ff_h264dsp_init_mips(c, bit_depth, chroma_format_idc); +#elif ARCH_LOONGARCH + ff_h264dsp_init_loongarch(c, bit_depth, chroma_format_idc); +#endif } diff --git a/libavcodec/h264pred.c b/libavcodec/h264pred.c index bd0d4a3d0..25f9995a0 100644 --- a/libavcodec/h264pred.c +++ b/libavcodec/h264pred.c @@ -53,6 +53,30 @@ #include "h264pred_template.c" #undef BIT_DEPTH +static void pred4x4_127_dc_c(uint8_t *src, const uint8_t *topright, + ptrdiff_t _stride) +{ + int stride = _stride; + const uint32_t a = 0x7F7F7F7FU; + + AV_WN32A(src + 0 * stride, a); + AV_WN32A(src + 1 * stride, a); + AV_WN32A(src + 2 * stride, a); + AV_WN32A(src + 3 * stride, a); +} + +static void pred4x4_129_dc_c(uint8_t *src, const uint8_t *topright, + ptrdiff_t _stride) +{ + int stride = _stride; + const uint32_t a = 0x81818181U; + + AV_WN32A(src + 0 * stride, a); + AV_WN32A(src + 1 * stride, a); + AV_WN32A(src + 2 * stride, a); + AV_WN32A(src + 3 * stride, a); +} + static void pred4x4_vertical_vp8_c(uint8_t *src, const uint8_t *topright, ptrdiff_t stride) { @@ -421,56 +445,19 @@ av_cold void ff_h264_pred_init(H264PredContext *h, int codec_id, #define FUNCD(a) a ## _c #define H264_PRED(depth) \ - if(codec_id != AV_CODEC_ID_RV40){\ - if (codec_id == AV_CODEC_ID_VP7 || codec_id == AV_CODEC_ID_VP8) {\ - h->pred4x4[VERT_PRED ]= FUNCD(pred4x4_vertical_vp8);\ - h->pred4x4[HOR_PRED ]= FUNCD(pred4x4_horizontal_vp8);\ - } else {\ - h->pred4x4[VERT_PRED ]= FUNCC(pred4x4_vertical , depth);\ - h->pred4x4[HOR_PRED ]= FUNCC(pred4x4_horizontal , depth);\ - }\ - h->pred4x4[DC_PRED ]= FUNCC(pred4x4_dc , depth);\ - if(codec_id == AV_CODEC_ID_SVQ3)\ - h->pred4x4[DIAG_DOWN_LEFT_PRED ]= FUNCD(pred4x4_down_left_svq3);\ - else\ - h->pred4x4[DIAG_DOWN_LEFT_PRED ]= FUNCC(pred4x4_down_left , depth);\ - h->pred4x4[DIAG_DOWN_RIGHT_PRED]= FUNCC(pred4x4_down_right , depth);\ - h->pred4x4[VERT_RIGHT_PRED ]= FUNCC(pred4x4_vertical_right , depth);\ - h->pred4x4[HOR_DOWN_PRED ]= FUNCC(pred4x4_horizontal_down , depth);\ - if (codec_id == AV_CODEC_ID_VP7 || codec_id == AV_CODEC_ID_VP8) {\ - h->pred4x4[VERT_LEFT_PRED ]= FUNCD(pred4x4_vertical_left_vp8);\ - } else\ - h->pred4x4[VERT_LEFT_PRED ]= FUNCC(pred4x4_vertical_left , depth);\ - h->pred4x4[HOR_UP_PRED ]= FUNCC(pred4x4_horizontal_up , depth);\ - if (codec_id != AV_CODEC_ID_VP7 && codec_id != AV_CODEC_ID_VP8) {\ - h->pred4x4[LEFT_DC_PRED ]= FUNCC(pred4x4_left_dc , depth);\ - h->pred4x4[TOP_DC_PRED ]= FUNCC(pred4x4_top_dc , depth);\ - } else {\ - h->pred4x4[TM_VP8_PRED ]= FUNCD(pred4x4_tm_vp8);\ - h->pred4x4[DC_127_PRED ]= FUNCC(pred4x4_127_dc , depth);\ - h->pred4x4[DC_129_PRED ]= FUNCC(pred4x4_129_dc , depth);\ - h->pred4x4[VERT_VP8_PRED ]= FUNCC(pred4x4_vertical , depth);\ - h->pred4x4[HOR_VP8_PRED ]= FUNCC(pred4x4_horizontal , depth);\ - }\ - if (codec_id != AV_CODEC_ID_VP8)\ - h->pred4x4[DC_128_PRED ]= FUNCC(pred4x4_128_dc , depth);\ - }else{\ - h->pred4x4[VERT_PRED ]= FUNCC(pred4x4_vertical , depth);\ - h->pred4x4[HOR_PRED ]= FUNCC(pred4x4_horizontal , depth);\ - h->pred4x4[DC_PRED ]= FUNCC(pred4x4_dc , depth);\ - h->pred4x4[DIAG_DOWN_LEFT_PRED ]= FUNCD(pred4x4_down_left_rv40);\ - h->pred4x4[DIAG_DOWN_RIGHT_PRED]= FUNCC(pred4x4_down_right , depth);\ - h->pred4x4[VERT_RIGHT_PRED ]= FUNCC(pred4x4_vertical_right , depth);\ - h->pred4x4[HOR_DOWN_PRED ]= FUNCC(pred4x4_horizontal_down , depth);\ - h->pred4x4[VERT_LEFT_PRED ]= FUNCD(pred4x4_vertical_left_rv40);\ - h->pred4x4[HOR_UP_PRED ]= FUNCD(pred4x4_horizontal_up_rv40);\ - h->pred4x4[LEFT_DC_PRED ]= FUNCC(pred4x4_left_dc , depth);\ - h->pred4x4[TOP_DC_PRED ]= FUNCC(pred4x4_top_dc , depth);\ - h->pred4x4[DC_128_PRED ]= FUNCC(pred4x4_128_dc , depth);\ - h->pred4x4[DIAG_DOWN_LEFT_PRED_RV40_NODOWN]= FUNCD(pred4x4_down_left_rv40_nodown);\ - h->pred4x4[HOR_UP_PRED_RV40_NODOWN]= FUNCD(pred4x4_horizontal_up_rv40_nodown);\ - h->pred4x4[VERT_LEFT_PRED_RV40_NODOWN]= FUNCD(pred4x4_vertical_left_rv40_nodown);\ - }\ + h->pred4x4[VERT_PRED ] = FUNCC(pred4x4_vertical, depth);\ + h->pred4x4[HOR_PRED ] = FUNCC(pred4x4_horizontal, depth);\ + h->pred4x4[DC_PRED ] = FUNCC(pred4x4_dc, depth);\ + h->pred4x4[DIAG_DOWN_LEFT_PRED ] = FUNCC(pred4x4_down_left, depth);\ + h->pred4x4[DIAG_DOWN_RIGHT_PRED] = FUNCC(pred4x4_down_right, depth);\ + h->pred4x4[VERT_RIGHT_PRED ] = FUNCC(pred4x4_vertical_right, depth);\ + h->pred4x4[HOR_DOWN_PRED ] = FUNCC(pred4x4_horizontal_down, depth);\ + h->pred4x4[VERT_LEFT_PRED ] = FUNCC(pred4x4_vertical_left, depth);\ + h->pred4x4[HOR_UP_PRED ] = FUNCC(pred4x4_horizontal_up, depth);\ + h->pred4x4[LEFT_DC_PRED ] = FUNCC(pred4x4_left_dc, depth);\ + h->pred4x4[TOP_DC_PRED ] = FUNCC(pred4x4_top_dc, depth);\ + if (depth > 8 || codec_id != AV_CODEC_ID_VP8)\ + h->pred4x4[DC_128_PRED ] = FUNCC(pred4x4_128_dc, depth);\ \ h->pred8x8l[VERT_PRED ]= FUNCC(pred8x8l_vertical , depth);\ h->pred8x8l[HOR_PRED ]= FUNCC(pred8x8l_horizontal , depth);\ @@ -488,20 +475,15 @@ av_cold void ff_h264_pred_init(H264PredContext *h, int codec_id, if (chroma_format_idc <= 1) {\ h->pred8x8[VERT_PRED8x8 ]= FUNCC(pred8x8_vertical , depth);\ h->pred8x8[HOR_PRED8x8 ]= FUNCC(pred8x8_horizontal , depth);\ + h->pred8x8[PLANE_PRED8x8] = FUNCC(pred8x8_plane, depth);\ } else {\ h->pred8x8[VERT_PRED8x8 ]= FUNCC(pred8x16_vertical , depth);\ h->pred8x8[HOR_PRED8x8 ]= FUNCC(pred8x16_horizontal , depth);\ + h->pred8x8[PLANE_PRED8x8] = FUNCC(pred8x16_plane, depth);\ }\ - if (codec_id != AV_CODEC_ID_VP7 && codec_id != AV_CODEC_ID_VP8) {\ - if (chroma_format_idc <= 1) {\ - h->pred8x8[PLANE_PRED8x8]= FUNCC(pred8x8_plane , depth);\ - } else {\ - h->pred8x8[PLANE_PRED8x8]= FUNCC(pred8x16_plane , depth);\ - }\ - } else\ - h->pred8x8[PLANE_PRED8x8]= FUNCD(pred8x8_tm_vp8);\ - if (codec_id != AV_CODEC_ID_RV40 && codec_id != AV_CODEC_ID_VP7 && \ - codec_id != AV_CODEC_ID_VP8) {\ + if (depth > 8 || (codec_id != AV_CODEC_ID_RV40 && \ + codec_id != AV_CODEC_ID_VP7 && \ + codec_id != AV_CODEC_ID_VP8)) { \ if (chroma_format_idc <= 1) {\ h->pred8x8[DC_PRED8x8 ]= FUNCC(pred8x8_dc , depth);\ h->pred8x8[LEFT_DC_PRED8x8]= FUNCC(pred8x8_left_dc , depth);\ @@ -523,10 +505,6 @@ av_cold void ff_h264_pred_init(H264PredContext *h, int codec_id, h->pred8x8[DC_PRED8x8 ]= FUNCD(pred8x8_dc_rv40);\ h->pred8x8[LEFT_DC_PRED8x8]= FUNCD(pred8x8_left_dc_rv40);\ h->pred8x8[TOP_DC_PRED8x8 ]= FUNCD(pred8x8_top_dc_rv40);\ - if (codec_id == AV_CODEC_ID_VP7 || codec_id == AV_CODEC_ID_VP8) {\ - h->pred8x8[DC_127_PRED8x8]= FUNCC(pred8x8_127_dc , depth);\ - h->pred8x8[DC_129_PRED8x8]= FUNCC(pred8x8_129_dc , depth);\ - }\ }\ if (chroma_format_idc <= 1) {\ h->pred8x8[DC_128_PRED8x8 ]= FUNCC(pred8x8_128_dc , depth);\ @@ -537,23 +515,7 @@ av_cold void ff_h264_pred_init(H264PredContext *h, int codec_id, h->pred16x16[DC_PRED8x8 ]= FUNCC(pred16x16_dc , depth);\ h->pred16x16[VERT_PRED8x8 ]= FUNCC(pred16x16_vertical , depth);\ h->pred16x16[HOR_PRED8x8 ]= FUNCC(pred16x16_horizontal , depth);\ - switch(codec_id){\ - case AV_CODEC_ID_SVQ3:\ - h->pred16x16[PLANE_PRED8x8 ]= FUNCD(pred16x16_plane_svq3);\ - break;\ - case AV_CODEC_ID_RV40:\ - h->pred16x16[PLANE_PRED8x8 ]= FUNCD(pred16x16_plane_rv40);\ - break;\ - case AV_CODEC_ID_VP7:\ - case AV_CODEC_ID_VP8:\ - h->pred16x16[PLANE_PRED8x8 ]= FUNCD(pred16x16_tm_vp8);\ - h->pred16x16[DC_127_PRED8x8]= FUNCC(pred16x16_127_dc , depth);\ - h->pred16x16[DC_129_PRED8x8]= FUNCC(pred16x16_129_dc , depth);\ - break;\ - default:\ - h->pred16x16[PLANE_PRED8x8 ]= FUNCC(pred16x16_plane , depth);\ - break;\ - }\ + h->pred16x16[PLANE_PRED8x8 ]= FUNCC(pred16x16_plane , depth);\ h->pred16x16[LEFT_DC_PRED8x8]= FUNCC(pred16x16_left_dc , depth);\ h->pred16x16[TOP_DC_PRED8x8 ]= FUNCC(pred16x16_top_dc , depth);\ h->pred16x16[DC_128_PRED8x8 ]= FUNCC(pred16x16_128_dc , depth);\ @@ -566,8 +528,8 @@ av_cold void ff_h264_pred_init(H264PredContext *h, int codec_id, 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);\ + h->pred8x8_add[VERT_PRED8x8] = FUNCC(pred8x8_vertical_add, depth);\ + h->pred8x8_add[ HOR_PRED8x8] = FUNCC(pred8x8_horizontal_add, depth);\ } else {\ h->pred8x8_add [VERT_PRED8x8]= FUNCC(pred8x16_vertical_add , depth);\ h->pred8x8_add [ HOR_PRED8x8]= FUNCC(pred8x16_horizontal_add , depth);\ @@ -591,17 +553,50 @@ av_cold void ff_h264_pred_init(H264PredContext *h, int codec_id, default: av_assert0(bit_depth<=8); H264_PRED(8) + switch (codec_id) { + case AV_CODEC_ID_SVQ3: + h->pred4x4[DIAG_DOWN_LEFT_PRED] = FUNCD(pred4x4_down_left_svq3); + h->pred16x16[PLANE_PRED8x8 ] = FUNCD(pred16x16_plane_svq3); + break; + case AV_CODEC_ID_RV40: + h->pred4x4[DIAG_DOWN_LEFT_PRED] = FUNCD(pred4x4_down_left_rv40); + h->pred4x4[VERT_LEFT_PRED ] = FUNCD(pred4x4_vertical_left_rv40); + h->pred4x4[HOR_UP_PRED ] = FUNCD(pred4x4_horizontal_up_rv40); + h->pred4x4[DIAG_DOWN_LEFT_PRED_RV40_NODOWN] = FUNCD(pred4x4_down_left_rv40_nodown); + h->pred4x4[HOR_UP_PRED_RV40_NODOWN] = FUNCD(pred4x4_horizontal_up_rv40_nodown); + h->pred4x4[VERT_LEFT_PRED_RV40_NODOWN] = FUNCD(pred4x4_vertical_left_rv40_nodown); + h->pred16x16[PLANE_PRED8x8 ] = FUNCD(pred16x16_plane_rv40); + break; + case AV_CODEC_ID_VP7: + case AV_CODEC_ID_VP8: + h->pred4x4[VERT_PRED ] = FUNCD(pred4x4_vertical_vp8); + h->pred4x4[HOR_PRED ] = FUNCD(pred4x4_horizontal_vp8); + h->pred4x4[VERT_LEFT_PRED ] = FUNCD(pred4x4_vertical_left_vp8); + h->pred4x4[TM_VP8_PRED ] = FUNCD(pred4x4_tm_vp8); + h->pred4x4[VERT_VP8_PRED ] = FUNCC(pred4x4_vertical, 8); + h->pred4x4[DC_127_PRED ] = FUNCD(pred4x4_127_dc); + h->pred4x4[DC_129_PRED ] = FUNCD(pred4x4_129_dc); + h->pred4x4[HOR_VP8_PRED ] = FUNCC(pred4x4_horizontal, 8); + h->pred8x8[PLANE_PRED8x8 ] = FUNCD(pred8x8_tm_vp8); + h->pred8x8[DC_127_PRED8x8 ] = FUNCC(pred8x8_127_dc, 8); + h->pred8x8[DC_129_PRED8x8 ] = FUNCC(pred8x8_129_dc, 8); + h->pred16x16[PLANE_PRED8x8 ] = FUNCD(pred16x16_tm_vp8); + h->pred16x16[DC_127_PRED8x8] = FUNCC(pred16x16_127_dc, 8); + h->pred16x16[DC_129_PRED8x8] = FUNCC(pred16x16_129_dc, 8); + break; + } break; } - if (ARCH_AARCH64) - ff_h264_pred_init_aarch64(h, codec_id, bit_depth, chroma_format_idc); - if (ARCH_ARM) - ff_h264_pred_init_arm(h, codec_id, bit_depth, chroma_format_idc); - if (ARCH_X86) - ff_h264_pred_init_x86(h, codec_id, bit_depth, chroma_format_idc); - if (ARCH_MIPS) - ff_h264_pred_init_mips(h, codec_id, bit_depth, chroma_format_idc); - if (ARCH_LOONGARCH) - ff_h264_pred_init_loongarch(h, codec_id, bit_depth, chroma_format_idc); +#if ARCH_AARCH64 + ff_h264_pred_init_aarch64(h, codec_id, bit_depth, chroma_format_idc); +#elif ARCH_ARM + ff_h264_pred_init_arm(h, codec_id, bit_depth, chroma_format_idc); +#elif ARCH_X86 + ff_h264_pred_init_x86(h, codec_id, bit_depth, chroma_format_idc); +#elif ARCH_MIPS + ff_h264_pred_init_mips(h, codec_id, bit_depth, chroma_format_idc); +#elif ARCH_LOONGARCH + ff_h264_pred_init_loongarch(h, codec_id, bit_depth, chroma_format_idc); +#endif } diff --git a/libavcodec/h264pred.h b/libavcodec/h264pred.h index 4583052df..cb008548f 100644 --- a/libavcodec/h264pred.h +++ b/libavcodec/h264pred.h @@ -86,6 +86,8 @@ #define DC_129_PRED8x8 8 //@} +#define PART_NOT_AVAILABLE -2 + /** * Context for storing H.264 prediction functions */ diff --git a/libavcodec/h264pred_template.c b/libavcodec/h264pred_template.c index 2b30fff70..b5bc942a5 100644 --- a/libavcodec/h264pred_template.c +++ b/libavcodec/h264pred_template.c @@ -111,32 +111,6 @@ static void FUNCC(pred4x4_128_dc)(uint8_t *_src, const uint8_t *topright, AV_WN4PA(src+3*stride, a); } -static void FUNCC(pred4x4_127_dc)(uint8_t *_src, const uint8_t *topright, - ptrdiff_t _stride) -{ - pixel *src = (pixel*)_src; - int stride = _stride>>(sizeof(pixel)-1); - const pixel4 a = PIXEL_SPLAT_X4((1<<(BIT_DEPTH-1))-1); - - AV_WN4PA(src+0*stride, a); - AV_WN4PA(src+1*stride, a); - AV_WN4PA(src+2*stride, a); - AV_WN4PA(src+3*stride, a); -} - -static void FUNCC(pred4x4_129_dc)(uint8_t *_src, const uint8_t *topright, - ptrdiff_t _stride) -{ - pixel *src = (pixel*)_src; - int stride = _stride>>(sizeof(pixel)-1); - const pixel4 a = PIXEL_SPLAT_X4((1<<(BIT_DEPTH-1))+1); - - AV_WN4PA(src+0*stride, a); - AV_WN4PA(src+1*stride, a); - AV_WN4PA(src+2*stride, a); - AV_WN4PA(src+3*stride, a); -} - #define LOAD_TOP_RIGHT_EDGE\ const unsigned av_unused t4 = topright[0];\ @@ -427,9 +401,11 @@ static void FUNCC(pred16x16_##n##_dc)(uint8_t *_src, ptrdiff_t stride)\ PREDICT_16x16_DC(PIXEL_SPLAT_X4(v));\ } -PRED16x16_X(127, (1<<(BIT_DEPTH-1))-1) PRED16x16_X(128, (1<<(BIT_DEPTH-1))+0) +#if BIT_DEPTH == 8 +PRED16x16_X(127, (1<<(BIT_DEPTH-1))-1) PRED16x16_X(129, (1<<(BIT_DEPTH-1))+1) +#endif static inline void FUNCC(pred16x16_plane_compat)(uint8_t *_src, ptrdiff_t _stride, @@ -551,9 +527,11 @@ static void FUNCC(pred8x8_##n##_dc)(uint8_t *_src, ptrdiff_t stride)\ }\ } -PRED8x8_X(127, (1<<(BIT_DEPTH-1))-1) PRED8x8_X(128, (1<<(BIT_DEPTH-1))+0) +#if BIT_DEPTH == 8 +PRED8x8_X(127, (1<<(BIT_DEPTH-1))-1) PRED8x8_X(129, (1<<(BIT_DEPTH-1))+1) +#endif static void FUNCC(pred8x16_128_dc)(uint8_t *_src, ptrdiff_t stride) { diff --git a/libavcodec/h264qpel.c b/libavcodec/h264qpel.c index 535ebd25b..65fef0330 100644 --- a/libavcodec/h264qpel.c +++ b/libavcodec/h264qpel.c @@ -96,16 +96,17 @@ av_cold void ff_h264qpel_init(H264QpelContext *c, int bit_depth) break; } - if (ARCH_AARCH64) - ff_h264qpel_init_aarch64(c, bit_depth); - if (ARCH_ARM) - ff_h264qpel_init_arm(c, bit_depth); - if (ARCH_PPC) - ff_h264qpel_init_ppc(c, bit_depth); - if (ARCH_X86) - ff_h264qpel_init_x86(c, bit_depth); - if (ARCH_MIPS) - ff_h264qpel_init_mips(c, bit_depth); - if (ARCH_LOONGARCH64) - ff_h264qpel_init_loongarch(c, bit_depth); +#if ARCH_AARCH64 + ff_h264qpel_init_aarch64(c, bit_depth); +#elif ARCH_ARM + ff_h264qpel_init_arm(c, bit_depth); +#elif ARCH_PPC + ff_h264qpel_init_ppc(c, bit_depth); +#elif ARCH_X86 + ff_h264qpel_init_x86(c, bit_depth); +#elif ARCH_MIPS + ff_h264qpel_init_mips(c, bit_depth); +#elif ARCH_LOONGARCH64 + ff_h264qpel_init_loongarch(c, bit_depth); +#endif } diff --git a/libavcodec/h265_metadata_bsf.c b/libavcodec/h265_metadata_bsf.c index e5f70cfbc..ffcbbf012 100644 --- a/libavcodec/h265_metadata_bsf.c +++ b/libavcodec/h265_metadata_bsf.c @@ -20,6 +20,7 @@ #include "libavutil/opt.h" #include "bsf.h" +#include "bsf_internal.h" #include "cbs.h" #include "cbs_bsf.h" #include "cbs_h265.h" @@ -436,7 +437,7 @@ static const AVOption h265_metadata_options[] = { { "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, FLAGS }, + { .i64 = -1 }, -1, 5, FLAGS }, { "tick_rate", "Set VPS and VUI tick rate (time_scale / num_units_in_tick)", @@ -498,12 +499,12 @@ 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", +const FFBitStreamFilter ff_hevc_metadata_bsf = { + .p.name = "hevc_metadata", + .p.codec_ids = h265_metadata_codec_ids, + .p.priv_class = &h265_metadata_class, .priv_data_size = sizeof(H265MetadataContext), - .priv_class = &h265_metadata_class, .init = &h265_metadata_init, .close = &ff_cbs_bsf_generic_close, .filter = &ff_cbs_bsf_generic_filter, - .codec_ids = h265_metadata_codec_ids, }; diff --git a/libavcodec/hap.h b/libavcodec/hap.h index 00c3dbb32..fb5a4c412 100644 --- a/libavcodec/hap.h +++ b/libavcodec/hap.h @@ -72,23 +72,16 @@ typedef struct HapContext { HapChunk *chunks; 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 */ size_t max_snappy; /* Maximum compressed size for snappy buffer */ - 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) */ - 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); - int (*tex_fun2)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block); + TextureDSPThreadContext enc; + TextureDSPThreadContext dec[2]; } HapContext; /* diff --git a/libavcodec/hapdec.c b/libavcodec/hapdec.c index 2c8c5c36b..0aab1ab87 100644 --- a/libavcodec/hapdec.c +++ b/libavcodec/hapdec.c @@ -37,8 +37,8 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "hap.h" -#include "internal.h" #include "snappy.h" #include "texturedsp.h" #include "thread.h" @@ -247,75 +247,17 @@ static int decompress_chunks_thread(AVCodecContext *avctx, void *arg, return 0; } -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; - 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 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 still 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++) { - if (texture_num == 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 * 4 * ctx->uncompress_pix_size, frame->linesize[0], - d + (off + x) * ctx->tex_rat2); - } - } - } - - 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 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, +static int hap_decode(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt) { HapContext *ctx = avctx->priv_data; - ThreadFrame tframe; int ret, i, t; int section_size; enum HapSectionType section_type; int start_texture_section = 0; - int tex_rat[2] = {0, 0}; bytestream2_init(&ctx->gbc, avpkt->data, avpkt->size); - tex_rat[0] = ctx->tex_rat; - /* check for multi texture header */ if (ctx->texture_count == 2) { ret = ff_hap_parse_section_header(&ctx->gbc, §ion_size, §ion_type); @@ -326,12 +268,10 @@ static int hap_decode(AVCodecContext *avctx, void *data, 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); + ret = ff_thread_get_buffer(avctx, frame, 0); if (ret < 0) return ret; @@ -345,25 +285,22 @@ static int hap_decode(AVCodecContext *avctx, void *data, if (ctx->tex_size != (avctx->coded_width / TEXTURE_BLOCK_W) *(avctx->coded_height / TEXTURE_BLOCK_H) - *tex_rat[t]) { + *ctx->dec[t].tex_ratio) { av_log(avctx, AV_LOG_ERROR, "uncompressed size mismatches\n"); return AVERROR_INVALIDDATA; } start_texture_section += ctx->texture_section_size + 4; - if (avctx->codec->update_thread_context) - ff_thread_finish_setup(avctx); - /* Unpack the DXT texture */ if (hap_can_use_tex_in_place(ctx)) { int tex_size; /* Only DXTC texture compression in a contiguous block */ - ctx->tex_data = ctx->gbc.buffer; + ctx->dec[t].tex_data.in = ctx->gbc.buffer; tex_size = FFMIN(ctx->texture_section_size, bytestream2_get_bytes_left(&ctx->gbc)); if (tex_size < (avctx->coded_width / TEXTURE_BLOCK_W) *(avctx->coded_height / TEXTURE_BLOCK_H) - *tex_rat[t]) { + *ctx->dec[t].tex_ratio) { av_log(avctx, AV_LOG_ERROR, "Insufficient data\n"); return AVERROR_INVALIDDATA; } @@ -381,21 +318,17 @@ static int hap_decode(AVCodecContext *avctx, void *data, return ctx->chunk_results[i]; } - ctx->tex_data = ctx->tex_buf; + ctx->dec[t].tex_data.in = ctx->tex_buf; } - /* 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); - } + ctx->dec[t].frame_data.out = frame->data[0]; + ctx->dec[t].stride = frame->linesize[0]; + avctx->execute2(avctx, ff_texturedsp_decompress_thread, &ctx->dec[t], NULL, ctx->dec[t].slice_count); } /* Frame is ready to be output */ - tframe.f->pict_type = AV_PICTURE_TYPE_I; - tframe.f->key_frame = 1; + frame->pict_type = AV_PICTURE_TYPE_I; + frame->key_frame = 1; *got_frame = 1; return avpkt->size; @@ -420,40 +353,44 @@ static av_cold int hap_init(AVCodecContext *avctx) ff_texturedsp_init(&ctx->dxtc); ctx->texture_count = 1; - ctx->uncompress_pix_size = 4; + ctx->dec[0].raw_ratio = 16; + ctx->dec[0].slice_count = av_clip(avctx->thread_count, 1, + avctx->coded_height / TEXTURE_BLOCK_H); switch (avctx->codec_tag) { case MKTAG('H','a','p','1'): texture_name = "DXT1"; - ctx->tex_rat = 8; - ctx->tex_fun = ctx->dxtc.dxt1_block; + ctx->dec[0].tex_ratio = 8; + ctx->dec[0].tex_funct = ctx->dxtc.dxt1_block; avctx->pix_fmt = AV_PIX_FMT_RGB0; break; case MKTAG('H','a','p','5'): texture_name = "DXT5"; - ctx->tex_rat = 16; - ctx->tex_fun = ctx->dxtc.dxt5_block; + ctx->dec[0].tex_ratio = 16; + ctx->dec[0].tex_funct = ctx->dxtc.dxt5_block; avctx->pix_fmt = AV_PIX_FMT_RGBA; break; case MKTAG('H','a','p','Y'): texture_name = "DXT5-YCoCg-scaled"; - ctx->tex_rat = 16; - ctx->tex_fun = ctx->dxtc.dxt5ys_block; + ctx->dec[0].tex_ratio = 16; + ctx->dec[0].tex_funct = ctx->dxtc.dxt5ys_block; avctx->pix_fmt = AV_PIX_FMT_RGB0; break; case MKTAG('H','a','p','A'): texture_name = "RGTC1"; - ctx->tex_rat = 8; - ctx->tex_fun = ctx->dxtc.rgtc1u_gray_block; + ctx->dec[0].tex_ratio = 8; + ctx->dec[0].tex_funct = ctx->dxtc.rgtc1u_gray_block; + ctx->dec[0].raw_ratio = 4; 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"; - ctx->tex_rat = 16; - ctx->tex_rat2 = 8; - ctx->tex_fun = ctx->dxtc.dxt5ys_block; - ctx->tex_fun2 = ctx->dxtc.rgtc1u_alpha_block; + ctx->dec[0].tex_ratio = 16; + ctx->dec[1].tex_ratio = 8; + ctx->dec[0].tex_funct = ctx->dxtc.dxt5ys_block; + ctx->dec[1].tex_funct = ctx->dxtc.rgtc1u_alpha_block; + ctx->dec[1].raw_ratio = 16; + ctx->dec[1].slice_count = ctx->dec[0].slice_count; avctx->pix_fmt = AV_PIX_FMT_RGBA; ctx->texture_count = 2; break; @@ -463,9 +400,6 @@ static av_cold int hap_init(AVCodecContext *avctx) av_log(avctx, AV_LOG_DEBUG, "%s texture\n", texture_name); - ctx->slice_count = av_clip(avctx->thread_count, 1, - avctx->coded_height / TEXTURE_BLOCK_H); - return 0; } @@ -478,16 +412,16 @@ static av_cold int hap_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_hap_decoder = { - .name = "hap", - .long_name = NULL_IF_CONFIG_SMALL("Vidvox Hap"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_HAP, +const FFCodec ff_hap_decoder = { + .p.name = "hap", + .p.long_name = NULL_IF_CONFIG_SMALL("Vidvox Hap"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_HAP, .init = hap_init, - .decode = hap_decode, + FF_CODEC_DECODE_CB(hap_decode), .close = hap_close, .priv_data_size = sizeof(HapContext), - .capabilities = AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_SLICE_THREADS | + .p.capabilities = AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, diff --git a/libavcodec/hapenc.c b/libavcodec/hapenc.c index 8db0af3a4..6a9d4e06c 100644 --- a/libavcodec/hapenc.c +++ b/libavcodec/hapenc.c @@ -39,9 +39,9 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "encode.h" #include "hap.h" -#include "internal.h" #include "texturedsp.h" #define HAP_MAX_CHUNKS 64 @@ -56,18 +56,14 @@ enum HapHeaderLength { static int compress_texture(AVCodecContext *avctx, uint8_t *out, int out_length, const AVFrame *f) { HapContext *ctx = avctx->priv_data; - int i, j; if (ctx->tex_size > out_length) return AVERROR_BUFFER_TOO_SMALL; - for (j = 0; j < avctx->height; j += 4) { - for (i = 0; i < avctx->width; i += 4) { - uint8_t *p = f->data[0] + i * 4 + j * f->linesize[0]; - const int step = ctx->tex_fun(out, f->linesize[0], p); - out += step; - } - } + ctx->enc.tex_data.out = out; + ctx->enc.frame_data.in = f->data[0]; + ctx->enc.stride = f->linesize[0]; + avctx->execute2(avctx, ff_texturedsp_compress_thread, &ctx->enc, NULL, ctx->enc.slice_count); return 0; } @@ -236,7 +232,6 @@ static int hap_encode(AVCodecContext *avctx, AVPacket *pkt, static av_cold int hap_init(AVCodecContext *avctx) { HapContext *ctx = avctx->priv_data; - int ratio; int corrected_chunk_count; int ret = av_image_check_size(avctx->width, avctx->height, 0, avctx); @@ -256,32 +251,34 @@ static av_cold int hap_init(AVCodecContext *avctx) switch (ctx->opt_tex_fmt) { case HAP_FMT_RGBDXT1: - ratio = 8; + ctx->enc.tex_ratio = 8; avctx->codec_tag = MKTAG('H', 'a', 'p', '1'); avctx->bits_per_coded_sample = 24; - ctx->tex_fun = ctx->dxtc.dxt1_block; + ctx->enc.tex_funct = ctx->dxtc.dxt1_block; break; case HAP_FMT_RGBADXT5: - ratio = 4; + ctx->enc.tex_ratio = 16; avctx->codec_tag = MKTAG('H', 'a', 'p', '5'); avctx->bits_per_coded_sample = 32; - ctx->tex_fun = ctx->dxtc.dxt5_block; + ctx->enc.tex_funct = ctx->dxtc.dxt5_block; break; case HAP_FMT_YCOCGDXT5: - ratio = 4; + ctx->enc.tex_ratio = 16; avctx->codec_tag = MKTAG('H', 'a', 'p', 'Y'); avctx->bits_per_coded_sample = 24; - ctx->tex_fun = ctx->dxtc.dxt5ys_block; + ctx->enc.tex_funct = ctx->dxtc.dxt5ys_block; break; default: av_log(avctx, AV_LOG_ERROR, "Invalid format %02X\n", ctx->opt_tex_fmt); return AVERROR_INVALIDDATA; } + ctx->enc.raw_ratio = 16; + ctx->enc.slice_count = av_clip(avctx->thread_count, 1, avctx->height / TEXTURE_BLOCK_H); /* Texture compression ratio is constant, so can we computer * beforehand the final size of the uncompressed buffer. */ - ctx->tex_size = FFALIGN(avctx->width, TEXTURE_BLOCK_W) * - FFALIGN(avctx->height, TEXTURE_BLOCK_H) * 4 / ratio; + ctx->tex_size = avctx->width / TEXTURE_BLOCK_W * + avctx->height / TEXTURE_BLOCK_H * ctx->enc.tex_ratio; switch (ctx->opt_compressor) { case HAP_COMP_NONE: @@ -294,7 +291,7 @@ static av_cold int hap_init(AVCodecContext *avctx) case HAP_COMP_SNAPPY: /* Round the chunk count to divide evenly on DXT block edges */ corrected_chunk_count = av_clip(ctx->opt_chunk_count, 1, HAP_MAX_CHUNKS); - while ((ctx->tex_size / (64 / ratio)) % corrected_chunk_count != 0) { + while ((ctx->tex_size / ctx->enc.tex_ratio) % corrected_chunk_count != 0) { corrected_chunk_count--; } @@ -349,17 +346,18 @@ static const AVClass hapenc_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_hap_encoder = { - .name = "hap", - .long_name = NULL_IF_CONFIG_SMALL("Vidvox Hap"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_HAP, +const FFCodec ff_hap_encoder = { + .p.name = "hap", + .p.long_name = NULL_IF_CONFIG_SMALL("Vidvox Hap"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_HAP, .priv_data_size = sizeof(HapContext), - .priv_class = &hapenc_class, + .p.priv_class = &hapenc_class, + .p.capabilities = AV_CODEC_CAP_SLICE_THREADS, .init = hap_init, - .encode2 = hap_encode, + FF_CODEC_ENCODE_CB(hap_encode), .close = hap_close, - .pix_fmts = (const enum AVPixelFormat[]) { + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_RGBA, AV_PIX_FMT_NONE, }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | diff --git a/libavcodec/hapqa_extract_bsf.c b/libavcodec/hapqa_extract_bsf.c index 1c8b0669b..0d9b40aaa 100644 --- a/libavcodec/hapqa_extract_bsf.c +++ b/libavcodec/hapqa_extract_bsf.c @@ -125,10 +125,10 @@ static const AVClass hapqa_extract_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVBitStreamFilter ff_hapqa_extract_bsf = { - .name = "hapqa_extract", - .filter = hapqa_extract, +const FFBitStreamFilter ff_hapqa_extract_bsf = { + .p.name = "hapqa_extract", + .p.codec_ids = codec_ids, + .p.priv_class = &hapqa_extract_class, .priv_data_size = sizeof(HapqaExtractContext), - .priv_class = &hapqa_extract_class, - .codec_ids = codec_ids, + .filter = hapqa_extract, }; diff --git a/libavcodec/hcadec.c b/libavcodec/hcadec.c index c98f8eb37..705457587 100644 --- a/libavcodec/hcadec.c +++ b/libavcodec/hcadec.c @@ -23,6 +23,8 @@ #include "libavutil/tx.h" #include "avcodec.h" +#include "bytestream.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" #include "hca_data.h" @@ -41,8 +43,6 @@ typedef struct ChannelContext { } ChannelContext; typedef struct HCAContext { - GetBitContext gb; - const AVCRC *crc_table; ChannelContext ch[16]; @@ -105,7 +105,7 @@ static inline unsigned ceil2(unsigned a, unsigned b) static av_cold int decode_init(AVCodecContext *avctx) { HCAContext *c = avctx->priv_data; - GetBitContext *gb = &c->gb; + GetByteContext gb0, *const gb = &gb0; int8_t r[16] = { 0 }; float scale = 1.f / 8.f; unsigned b, chunk; @@ -114,44 +114,45 @@ static av_cold int decode_init(AVCodecContext *avctx) avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; c->crc_table = av_crc_get_table(AV_CRC_16_ANSI); - if (avctx->channels <= 0 || avctx->channels > 16) + if (avctx->ch_layout.nb_channels <= 0 || avctx->ch_layout.nb_channels > 16) return AVERROR(EINVAL); - ret = init_get_bits8(gb, avctx->extradata, avctx->extradata_size); - if (ret < 0) - return ret; - skip_bits_long(gb, 32); - version = get_bits(gb, 16); - skip_bits_long(gb, 16); + if (avctx->extradata_size < 36) + return AVERROR_INVALIDDATA; + bytestream2_init(gb, avctx->extradata, avctx->extradata_size); + + bytestream2_skipu(gb, 4); + version = bytestream2_get_be16(gb); + bytestream2_skipu(gb, 2); c->ath_type = version >= 0x200 ? 0 : 1; - if (get_bits_long(gb, 32) != MKBETAG('f', 'm', 't', 0)) + if (bytestream2_get_be32u(gb) != MKBETAG('f', 'm', 't', 0)) return AVERROR_INVALIDDATA; - skip_bits_long(gb, 32); - skip_bits_long(gb, 32); - skip_bits_long(gb, 32); + bytestream2_skipu(gb, 4); + bytestream2_skipu(gb, 4); + bytestream2_skipu(gb, 4); - chunk = get_bits_long(gb, 32); + chunk = bytestream2_get_be32u(gb); if (chunk == MKBETAG('c', 'o', 'm', 'p')) { - skip_bits_long(gb, 16); - skip_bits_long(gb, 8); - skip_bits_long(gb, 8); - c->track_count = get_bits(gb, 8); - c->channel_config = get_bits(gb, 8); - c->total_band_count = get_bits(gb, 8); - c->base_band_count = get_bits(gb, 8); - c->stereo_band_count = get_bits(gb, 8); - c->bands_per_hfr_group = get_bits(gb, 8); + bytestream2_skipu(gb, 2); + bytestream2_skipu(gb, 1); + bytestream2_skipu(gb, 1); + c->track_count = bytestream2_get_byteu(gb); + c->channel_config = bytestream2_get_byteu(gb); + c->total_band_count = bytestream2_get_byteu(gb); + c->base_band_count = bytestream2_get_byteu(gb); + c->stereo_band_count = bytestream2_get_byte (gb); + c->bands_per_hfr_group = bytestream2_get_byte (gb); } else if (chunk == MKBETAG('d', 'e', 'c', 0)) { - skip_bits_long(gb, 16); - skip_bits_long(gb, 8); - skip_bits_long(gb, 8); - c->total_band_count = get_bits(gb, 8) + 1; - c->base_band_count = get_bits(gb, 8) + 1; - c->track_count = get_bits(gb, 4); - c->channel_config = get_bits(gb, 4); - if (!get_bits(gb, 8)) + bytestream2_skipu(gb, 2); + bytestream2_skipu(gb, 1); + bytestream2_skipu(gb, 1); + c->total_band_count = bytestream2_get_byteu(gb) + 1; + c->base_band_count = bytestream2_get_byteu(gb) + 1; + c->track_count = bytestream2_peek_byteu(gb) >> 4; + c->channel_config = bytestream2_get_byteu(gb) & 0xF; + if (!bytestream2_get_byteu(gb)) c->base_band_count = c->total_band_count; c->stereo_band_count = c->total_band_count - c->base_band_count; c->bands_per_hfr_group = 0; @@ -162,24 +163,20 @@ static av_cold int decode_init(AVCodecContext *avctx) return AVERROR_INVALIDDATA; - while (get_bits_left(gb) >= 32) { - chunk = get_bits_long(gb, 32); + while (bytestream2_get_bytes_left(gb) >= 4) { + chunk = bytestream2_get_be32u(gb); if (chunk == MKBETAG('v', 'b', 'r', 0)) { - skip_bits_long(gb, 16); - skip_bits_long(gb, 16); + bytestream2_skip(gb, 2 + 2); } else if (chunk == MKBETAG('a', 't', 'h', 0)) { - c->ath_type = get_bits(gb, 16); + c->ath_type = bytestream2_get_be16(gb); } else if (chunk == MKBETAG('r', 'v', 'a', 0)) { - skip_bits_long(gb, 32); + bytestream2_skip(gb, 4); } else if (chunk == MKBETAG('c', 'o', 'm', 'm')) { - skip_bits_long(gb, get_bits(gb, 8) * 8); + bytestream2_skip(gb, bytestream2_get_byte(gb) * 8); } else if (chunk == MKBETAG('c', 'i', 'p', 'h')) { - skip_bits_long(gb, 16); + bytestream2_skip(gb, 2); } else if (chunk == MKBETAG('l', 'o', 'o', 'p')) { - skip_bits_long(gb, 32); - skip_bits_long(gb, 32); - skip_bits_long(gb, 16); - skip_bits_long(gb, 16); + bytestream2_skip(gb, 4 + 4 + 2 + 2); } else if (chunk == MKBETAG('p', 'a', 'd', 0)) { break; } else { @@ -194,7 +191,7 @@ static av_cold int decode_init(AVCodecContext *avctx) if (!c->track_count) c->track_count = 1; - b = avctx->channels / c->track_count; + b = avctx->ch_layout.nb_channels / c->track_count; if (c->stereo_band_count && b > 1) { int8_t *x = r; @@ -239,7 +236,7 @@ static av_cold int decode_init(AVCodecContext *avctx) if (c->base_band_count + c->stereo_band_count + (unsigned long)c->hfr_group_count > 128ULL) return AVERROR_INVALIDDATA; - for (int i = 0; i < avctx->channels; i++) { + for (int i = 0; i < avctx->ch_layout.nb_channels; i++) { c->ch[i].chan_type = r[i]; c->ch[i].count = c->base_band_count + ((r[i] != 2) ? c->stereo_band_count : 0); c->ch[i].hfr_scale = &c->ch[i].scale_factors[c->base_band_count + c->stereo_band_count]; @@ -300,10 +297,9 @@ static void reconstruct_hfr(HCAContext *s, ChannelContext *ch, ch->imdct_in[127] = 0; } -static void dequantize_coefficients(HCAContext *c, ChannelContext *ch) +static void dequantize_coefficients(HCAContext *c, ChannelContext *ch, + GetBitContext *gb) { - GetBitContext *gb = &c->gb; - for (int i = 0; i < ch->count; i++) { unsigned scale = ch->scale[i]; int nb_bits = max_bits_table[scale]; @@ -327,11 +323,11 @@ static void dequantize_coefficients(HCAContext *c, ChannelContext *ch) } static void unpack(HCAContext *c, ChannelContext *ch, + GetBitContext *gb, unsigned hfr_group_count, int packed_noise_level, const uint8_t *ath) { - GetBitContext *gb = &c->gb; int delta_bits = get_bits(gb, 3); if (delta_bits > 5) { @@ -386,13 +382,12 @@ static void unpack(HCAContext *c, ChannelContext *ch, ch->base[i] = dequantizer_scaling_table[ch->scale_factors[i]] * quant_step_size[ch->scale[i]]; } -static int decode_frame(AVCodecContext *avctx, void *data, +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; HCAContext *c = avctx->priv_data; int ch, ret, packed_noise_level; - GetBitContext *gb = &c->gb; + GetBitContext gb0, *const gb = &gb0; float **samples; if (avctx->err_recognition & AV_EF_CRCCHECK) { @@ -413,20 +408,20 @@ static int decode_frame(AVCodecContext *avctx, void *data, packed_noise_level = (get_bits(gb, 9) << 8) - get_bits(gb, 7); - for (ch = 0; ch < avctx->channels; ch++) - unpack(c, &c->ch[ch], c->hfr_group_count, packed_noise_level, c->ath); + for (ch = 0; ch < avctx->ch_layout.nb_channels; ch++) + unpack(c, &c->ch[ch], gb, c->hfr_group_count, packed_noise_level, c->ath); for (int i = 0; i < 8; i++) { - for (ch = 0; ch < avctx->channels; ch++) - dequantize_coefficients(c, &c->ch[ch]); - for (ch = 0; ch < avctx->channels; ch++) + for (ch = 0; ch < avctx->ch_layout.nb_channels; ch++) + dequantize_coefficients(c, &c->ch[ch], gb); + for (ch = 0; ch < avctx->ch_layout.nb_channels; ch++) reconstruct_hfr(c, &c->ch[ch], c->hfr_group_count, c->bands_per_hfr_group, c->stereo_band_count + c->base_band_count, c->total_band_count); - for (ch = 0; ch < avctx->channels - 1; ch++) + for (ch = 0; ch < avctx->ch_layout.nb_channels - 1; ch++) apply_intensity_stereo(c, &c->ch[ch], &c->ch[ch+1], i, c->total_band_count - c->base_band_count, c->base_band_count, c->stereo_band_count); - for (ch = 0; ch < avctx->channels; ch++) + for (ch = 0; ch < avctx->ch_layout.nb_channels; ch++) run_imdct(c, &c->ch[ch], i, samples[ch] + i * 128); } @@ -445,16 +440,17 @@ static av_cold int decode_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_hca_decoder = { - .name = "hca", - .long_name = NULL_IF_CONFIG_SMALL("CRI HCA"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_HCA, +const FFCodec ff_hca_decoder = { + .p.name = "hca", + .p.long_name = NULL_IF_CONFIG_SMALL("CRI HCA"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_HCA, .priv_data_size = sizeof(HCAContext), .init = decode_init, - .decode = decode_frame, + FF_CODEC_DECODE_CB(decode_frame), .close = decode_close, - .capabilities = AV_CODEC_CAP_DR1, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + .p.capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, }; diff --git a/libavcodec/hcom.c b/libavcodec/hcom.c index 3030e37d4..74a13e004 100644 --- a/libavcodec/hcom.c +++ b/libavcodec/hcom.c @@ -21,6 +21,7 @@ #include "libavutil/intreadwrite.h" #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" @@ -44,7 +45,7 @@ static av_cold int hcom_init(AVCodecContext *avctx) { HCOMContext *s = avctx->priv_data; - if (avctx->channels != 1) { + if (avctx->ch_layout.nb_channels != 1) { av_log(avctx, AV_LOG_ERROR, "invalid number of channels\n"); return AVERROR_INVALIDDATA; } @@ -79,11 +80,10 @@ static av_cold int hcom_init(AVCodecContext *avctx) return 0; } -static int hcom_decode(AVCodecContext *avctx, void *data, +static int hcom_decode(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *pkt) { HCOMContext *s = avctx->priv_data; - AVFrame *frame = data; GetBitContext gb; int ret, n = 0; @@ -134,15 +134,15 @@ static av_cold int hcom_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_hcom_decoder = { - .name = "hcom", - .long_name = NULL_IF_CONFIG_SMALL("HCOM Audio"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_HCOM, +const FFCodec ff_hcom_decoder = { + .p.name = "hcom", + .p.long_name = NULL_IF_CONFIG_SMALL("HCOM Audio"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_HCOM, .priv_data_size = sizeof(HCOMContext), .init = hcom_init, .close = hcom_close, - .decode = hcom_decode, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(hcom_decode), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/hevc_cabac.c b/libavcodec/hevc_cabac.c index 9b8c8e342..a194f8a02 100644 --- a/libavcodec/hevc_cabac.c +++ b/libavcodec/hevc_cabac.c @@ -1282,7 +1282,7 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, int scf_offset = 0; if (s->ps.sps->transform_skip_context_enabled_flag && (transform_skip_flag || lc->cu.cu_transquant_bypass_flag)) { - ctx_idx_map_p = (uint8_t*) &ctx_idx_map[4 * 16]; + ctx_idx_map_p = &ctx_idx_map[4 * 16]; if (c_idx == 0) { scf_offset = 40; } else { @@ -1292,9 +1292,9 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, if (c_idx != 0) scf_offset = 27; if (log2_trafo_size == 2) { - ctx_idx_map_p = (uint8_t*) &ctx_idx_map[0]; + ctx_idx_map_p = &ctx_idx_map[0]; } else { - ctx_idx_map_p = (uint8_t*) &ctx_idx_map[(prev_sig + 1) << 4]; + ctx_idx_map_p = &ctx_idx_map[(prev_sig + 1) << 4]; if (c_idx == 0) { if ((x_cg > 0 || y_cg > 0)) scf_offset += 3; diff --git a/libavcodec/hevc_filter.c b/libavcodec/hevc_filter.c index 3c45b5a39..1ae561db9 100644 --- a/libavcodec/hevc_filter.c +++ b/libavcodec/hevc_filter.c @@ -26,6 +26,7 @@ #include "libavutil/internal.h" #include "hevcdec.h" +#include "threadframe.h" #define LUMA 0 #define CB 1 @@ -142,11 +143,22 @@ static void copy_CTB(uint8_t *dst, const uint8_t *src, int width, int height, if (((intptr_t)dst | (intptr_t)src | stride_dst | stride_src) & 15) { for (i = 0; i < height; i++) { - for (j = 0; j < width; j+=8) + for (j = 0; j < width - 7; j+=8) AV_COPY64U(dst+j, src+j); dst += stride_dst; src += stride_src; } + if (width&7) { + dst += ((width>>3)<<3) - stride_dst * height; + src += ((width>>3)<<3) - stride_src * height; + width &= 7; + for (i = 0; i < height; i++) { + for (j = 0; j < width; j++) + dst[j] = src[j]; + dst += stride_dst; + src += stride_src; + } + } } else { for (i = 0; i < height; i++) { for (j = 0; j < width; j+=16) @@ -644,8 +656,8 @@ static void deblocking_filter_CTB(HEVCContext *s, int x0, int y0) } } -static int boundary_strength(HEVCContext *s, MvField *curr, MvField *neigh, - RefPicList *neigh_refPicList) +static int boundary_strength(const HEVCContext *s, const MvField *curr, const MvField *neigh, + const RefPicList *neigh_refPicList) { if (curr->pred_flag == PF_BI && neigh->pred_flag == PF_BI) { // same L0 and L1 @@ -733,9 +745,9 @@ void ff_hevc_deblocking_boundary_strengths(HEVCContext *s, int x0, int y0, boundary_upper = 0; if (boundary_upper) { - RefPicList *rpl_top = (lc->boundary_flags & BOUNDARY_UPPER_SLICE) ? - ff_hevc_get_ref_list(s, s->ref, x0, y0 - 1) : - s->ref->refPicList; + const RefPicList *rpl_top = (lc->boundary_flags & BOUNDARY_UPPER_SLICE) ? + ff_hevc_get_ref_list(s, s->ref, x0, y0 - 1) : + s->ref->refPicList; int yp_pu = (y0 - 1) >> log2_min_pu_size; int yq_pu = y0 >> log2_min_pu_size; int yp_tu = (y0 - 1) >> log2_min_tu_size; @@ -771,9 +783,9 @@ void ff_hevc_deblocking_boundary_strengths(HEVCContext *s, int x0, int y0, boundary_left = 0; if (boundary_left) { - RefPicList *rpl_left = (lc->boundary_flags & BOUNDARY_LEFT_SLICE) ? - ff_hevc_get_ref_list(s, s->ref, x0 - 1, y0) : - s->ref->refPicList; + const RefPicList *rpl_left = (lc->boundary_flags & BOUNDARY_LEFT_SLICE) ? + ff_hevc_get_ref_list(s, s->ref, x0 - 1, y0) : + s->ref->refPicList; int xp_pu = (x0 - 1) >> log2_min_pu_size; int xq_pu = x0 >> log2_min_pu_size; int xp_tu = (x0 - 1) >> log2_min_tu_size; diff --git a/libavcodec/hevc_mp4toannexb_bsf.c b/libavcodec/hevc_mp4toannexb_bsf.c index 790dfb039..f9a025a36 100644 --- a/libavcodec/hevc_mp4toannexb_bsf.c +++ b/libavcodec/hevc_mp4toannexb_bsf.c @@ -195,10 +195,10 @@ static const enum AVCodecID codec_ids[] = { AV_CODEC_ID_HEVC, AV_CODEC_ID_NONE, }; -const AVBitStreamFilter ff_hevc_mp4toannexb_bsf = { - .name = "hevc_mp4toannexb", +const FFBitStreamFilter ff_hevc_mp4toannexb_bsf = { + .p.name = "hevc_mp4toannexb", + .p.codec_ids = codec_ids, .priv_data_size = sizeof(HEVCBSFContext), .init = hevc_mp4toannexb_init, .filter = hevc_mp4toannexb_filter, - .codec_ids = codec_ids, }; diff --git a/libavcodec/hevc_mvs.c b/libavcodec/hevc_mvs.c index 1f6ca5a31..516e4a6b7 100644 --- a/libavcodec/hevc_mvs.c +++ b/libavcodec/hevc_mvs.c @@ -23,6 +23,7 @@ #include "hevc.h" #include "hevcdec.h" +#include "threadframe.h" static const uint8_t l0_l1_cand_idx[12][2] = { { 0, 1, }, @@ -112,7 +113,7 @@ static av_always_inline int compare_mv_ref_idx(struct MvField A, struct MvField return 0; } -static av_always_inline void mv_scale(Mv *dst, Mv *src, int td, int tb) +static av_always_inline void mv_scale(Mv *dst, const Mv *src, int td, int tb) { int tx, scale_factor; @@ -126,10 +127,10 @@ static av_always_inline void mv_scale(Mv *dst, Mv *src, int td, int tb) (scale_factor * src->y < 0)) >> 8); } -static int check_mvset(Mv *mvLXCol, Mv *mvCol, +static int check_mvset(Mv *mvLXCol, const Mv *mvCol, int colPic, int poc, - RefPicList *refPicList, int X, int refIdxLx, - RefPicList *refPicList_col, int listCol, int refidxCol) + const RefPicList *refPicList, int X, int refIdxLx, + const RefPicList *refPicList_col, int listCol, int refidxCol) { int cur_lt = refPicList[X].isLongTerm[refIdxLx]; int col_lt = refPicList_col[listCol].isLongTerm[refidxCol]; @@ -162,7 +163,7 @@ static int check_mvset(Mv *mvLXCol, Mv *mvCol, // derive the motion vectors section 8.5.3.1.8 static int derive_temporal_colocated_mvs(HEVCContext *s, MvField temp_col, int refIdxLx, Mv *mvLXCol, int X, - int colPic, RefPicList *refPicList_col) + int colPic, const RefPicList *refPicList_col) { RefPicList *refPicList = s->ref->refPicList; diff --git a/libavcodec/hevc_parser.c b/libavcodec/hevc_parser.c index c944a6aac..59f9a0ff3 100644 --- a/libavcodec/hevc_parser.c +++ b/libavcodec/hevc_parser.c @@ -28,7 +28,6 @@ #include "hevc_ps.h" #include "hevc_sei.h" #include "h2645_parse.h" -#include "internal.h" #include "parser.h" #define START_CODE 0x000001 ///< start_code_prefix_one_3bytes diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index 764c4849e..f665d8053 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -1,8 +1,8 @@ /* * HEVC Parameter Set decoding * - * Copyright (C) 2012 - 2103 Guillaume Martres - * Copyright (C) 2012 - 2103 Mickael Raulet + * Copyright (C) 2012 - 2013 Guillaume Martres + * Copyright (C) 2012 - 2013 Mickael Raulet * Copyright (C) 2012 - 2013 Gildas Cocherel * Copyright (C) 2013 Vittorio Giovara * @@ -122,7 +122,6 @@ int ff_hevc_decode_short_term_rps(GetBitContext *gb, AVCodecContext *avctx, uint8_t rps_predict = 0; int delta_poc; int k0 = 0; - int k1 = 0; int k = 0; int i; @@ -172,8 +171,6 @@ int ff_hevc_decode_short_term_rps(GetBitContext *gb, AVCodecContext *avctx, rps->delta_poc[k] = delta_poc; if (delta_poc < 0) k0++; - else - k1++; k++; } } @@ -659,7 +656,7 @@ static void decode_vui(GetBitContext *gb, AVCodecContext *avctx, // Backup context in case an alternate header is detected memcpy(&backup, gb, sizeof(backup)); memcpy(&backup_vui, vui, sizeof(backup_vui)); - if (get_bits_left(gb) >= 68 && show_bits_long(gb, 21) == 0x100000) { + if (get_bits_left(gb) >= 68 && show_bits(gb, 21) == 0x100000) { vui->default_display_window_flag = 0; av_log(avctx, AV_LOG_WARNING, "Invalid default display window\n"); } else diff --git a/libavcodec/hevc_ps_enc.c b/libavcodec/hevc_ps_enc.c index 47f252dd2..72641b2ff 100644 --- a/libavcodec/hevc_ps_enc.c +++ b/libavcodec/hevc_ps_enc.c @@ -18,7 +18,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "golomb.h" +#include "put_golomb.h" #include "hevc_ps.h" #include "put_bits.h" diff --git a/libavcodec/hevc_refs.c b/libavcodec/hevc_refs.c index 06e42d9c5..6a70c817b 100644 --- a/libavcodec/hevc_refs.c +++ b/libavcodec/hevc_refs.c @@ -22,12 +22,11 @@ */ #include "libavutil/avassert.h" -#include "libavutil/pixdesc.h" -#include "internal.h" #include "thread.h" #include "hevc.h" #include "hevcdec.h" +#include "threadframe.h" void ff_hevc_unref_frame(HEVCContext *s, HEVCFrame *frame, int flags) { @@ -37,8 +36,8 @@ void ff_hevc_unref_frame(HEVCContext *s, HEVCFrame *frame, int flags) frame->flags &= ~flags; if (!frame->flags) { - ff_thread_release_buffer(s->avctx, &frame->tf); - ff_thread_release_buffer(s->avctx, &frame->tf_grain); + ff_thread_release_ext_buffer(s->avctx, &frame->tf); + ff_thread_release_buffer(s->avctx, frame->frame_grain); frame->needs_fg = 0; av_buffer_unref(&frame->tab_mvf_buf); @@ -56,13 +55,14 @@ void ff_hevc_unref_frame(HEVCContext *s, HEVCFrame *frame, int flags) } } -RefPicList *ff_hevc_get_ref_list(HEVCContext *s, HEVCFrame *ref, int x0, int y0) +const RefPicList *ff_hevc_get_ref_list(const HEVCContext *s, + const HEVCFrame *ref, int x0, int y0) { int x_cb = x0 >> s->ps.sps->log2_ctb_size; int y_cb = y0 >> s->ps.sps->log2_ctb_size; int pic_width_cb = s->ps.sps->ctb_width; int ctb_addr_ts = s->ps.pps->ctb_addr_rs_to_ts[y_cb * pic_width_cb + x_cb]; - return (RefPicList *)ref->rpl_tab[ctb_addr_ts]; + return &ref->rpl_tab[ctb_addr_ts]->refPicList[0]; } void ff_hevc_clear_refs(HEVCContext *s) @@ -89,8 +89,8 @@ static HEVCFrame *alloc_frame(HEVCContext *s) if (frame->frame->buf[0]) continue; - ret = ff_thread_get_buffer(s->avctx, &frame->tf, - AV_GET_BUFFER_FLAG_REF); + ret = ff_thread_get_ext_buffer(s->avctx, &frame->tf, + AV_GET_BUFFER_FLAG_REF); if (ret < 0) return NULL; @@ -402,9 +402,9 @@ static HEVCFrame *generate_missing_ref(HEVCContext *s, int poc) if (!s->avctx->hwaccel) { if (!s->ps.sps->pixel_shift) { - for (i = 0; frame->frame->buf[i]; i++) - memset(frame->frame->buf[i]->data, 1 << (s->ps.sps->bit_depth - 1), - frame->frame->buf[i]->size); + for (i = 0; frame->frame->data[i]; i++) + memset(frame->frame->data[i], 1 << (s->ps.sps->bit_depth - 1), + frame->frame->linesize[i] * AV_CEIL_RSHIFT(s->ps.sps->height, s->ps.sps->vshift[i])); } else { for (i = 0; frame->frame->data[i]; i++) for (y = 0; y < (s->ps.sps->height >> s->ps.sps->vshift[i]); y++) { diff --git a/libavcodec/hevc_sei.c b/libavcodec/hevc_sei.c index 7fd822652..631373e06 100644 --- a/libavcodec/hevc_sei.c +++ b/libavcodec/hevc_sei.c @@ -23,80 +23,78 @@ */ #include "atsc_a53.h" +#include "bytestream.h" #include "dynamic_hdr10_plus.h" +#include "dynamic_hdr_vivid.h" #include "golomb.h" #include "hevc_ps.h" #include "hevc_sei.h" -static int decode_nal_sei_decoded_picture_hash(HEVCSEIPictureHash *s, GetBitContext *gb) +static int decode_nal_sei_decoded_picture_hash(HEVCSEIPictureHash *s, + GetByteContext *gb) { - int cIdx, i; + int cIdx; uint8_t hash_type; //uint16_t picture_crc; //uint32_t picture_checksum; - hash_type = get_bits(gb, 8); + hash_type = bytestream2_get_byte(gb); for (cIdx = 0; cIdx < 3/*((s->sps->chroma_format_idc == 0) ? 1 : 3)*/; cIdx++) { if (hash_type == 0) { s->is_md5 = 1; - for (i = 0; i < 16; i++) - s->md5[cIdx][i] = get_bits(gb, 8); + bytestream2_get_buffer(gb, s->md5[cIdx], sizeof(s->md5[cIdx])); } else if (hash_type == 1) { // picture_crc = get_bits(gb, 16); - skip_bits(gb, 16); } else if (hash_type == 2) { // picture_checksum = get_bits_long(gb, 32); - skip_bits(gb, 32); } } return 0; } -static int decode_nal_sei_mastering_display_info(HEVCSEIMasteringDisplay *s, GetBitContext *gb, int size) +static int decode_nal_sei_mastering_display_info(HEVCSEIMasteringDisplay *s, + GetByteContext *gb) { int i; - if (size < 24) + if (bytestream2_get_bytes_left(gb) < 24) return AVERROR_INVALIDDATA; // Mastering primaries for (i = 0; i < 3; i++) { - s->display_primaries[i][0] = get_bits(gb, 16); - s->display_primaries[i][1] = get_bits(gb, 16); + s->display_primaries[i][0] = bytestream2_get_be16u(gb); + s->display_primaries[i][1] = bytestream2_get_be16u(gb); } // White point (x, y) - s->white_point[0] = get_bits(gb, 16); - s->white_point[1] = get_bits(gb, 16); + s->white_point[0] = bytestream2_get_be16u(gb); + s->white_point[1] = bytestream2_get_be16u(gb); // Max and min luminance of mastering display - s->max_luminance = get_bits_long(gb, 32); - s->min_luminance = get_bits_long(gb, 32); - size -= 24; + s->max_luminance = bytestream2_get_be32u(gb); + s->min_luminance = bytestream2_get_be32u(gb); // As this SEI message comes before the first frame that references it, // initialize the flag to 2 and decrement on IRAP access unit so it // persists for the coded video sequence (e.g., between two IRAPs) s->present = 2; - skip_bits_long(gb, 8 * size); return 0; } -static int decode_nal_sei_content_light_info(HEVCSEIContentLight *s, GetBitContext *gb, int size) +static int decode_nal_sei_content_light_info(HEVCSEIContentLight *s, + GetByteContext *gb) { - if (size < 4) + if (bytestream2_get_bytes_left(gb) < 4) return AVERROR_INVALIDDATA; // Max and average light levels - s->max_content_light_level = get_bits(gb, 16); - s->max_pic_average_light_level = get_bits(gb, 16); - size -= 4; + s->max_content_light_level = bytestream2_get_be16u(gb); + s->max_pic_average_light_level = bytestream2_get_be16u(gb); // As this SEI message comes before the first frame that references it, // initialize the flag to 2 and decrement on IRAP access unit so it // persists for the coded video sequence (e.g., between two IRAPs) s->present = 2; - skip_bits_long(gb, 8 * size); return 0; } @@ -113,15 +111,7 @@ static int decode_nal_sei_frame_packing_arrangement(HEVCSEIFramePacking *s, GetB // 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] - skip_bits(gb, 8); // frame_packing_arrangement_reserved_byte - skip_bits1(gb); // frame_packing_arrangement_persistence_flag } - skip_bits1(gb); // upsampled_aspect_ratio_flag return 0; } @@ -134,14 +124,14 @@ static int decode_nal_sei_display_orientation(HEVCSEIDisplayOrientation *s, GetB s->vflip = get_bits1(gb); // ver_flip s->anticlockwise_rotation = get_bits(gb, 16); - skip_bits1(gb); // display_orientation_persistence_flag + // skip_bits1(gb); // display_orientation_persistence_flag } return 0; } -static int decode_nal_sei_pic_timing(HEVCSEI *s, GetBitContext *gb, const HEVCParamSets *ps, - void *logctx, int size) +static int decode_nal_sei_pic_timing(HEVCSEI *s, GetBitContext *gb, + const HEVCParamSets *ps, void *logctx) { HEVCSEIPictureTiming *h = &s->picture_timing; HEVCSPS *sps; @@ -166,35 +156,29 @@ static int decode_nal_sei_pic_timing(HEVCSEI *s, GetBitContext *gb, const HEVCPa av_log(logctx, AV_LOG_DEBUG, "Frame/Field Tripling\n"); h->picture_struct = HEVC_SEI_PIC_STRUCT_FRAME_TRIPLING; } - get_bits(gb, 2); // source_scan_type - get_bits(gb, 1); // duplicate_flag - skip_bits1(gb); - size--; } - skip_bits_long(gb, 8 * size); return 0; } -static int decode_registered_user_data_closed_caption(HEVCSEIA53Caption *s, GetBitContext *gb, - int size) +static int decode_registered_user_data_closed_caption(HEVCSEIA53Caption *s, + GetByteContext *gb) { int ret; - ret = ff_parse_a53_cc(&s->buf_ref, gb->buffer + get_bits_count(gb) / 8, size); - + ret = ff_parse_a53_cc(&s->buf_ref, gb->buffer, + bytestream2_get_bytes_left(gb)); if (ret < 0) return ret; - skip_bits_long(gb, size * 8); - return 0; } -static int decode_nal_sei_user_data_unregistered(HEVCSEIUnregistered *s, GetBitContext *gb, - int size) +static int decode_nal_sei_user_data_unregistered(HEVCSEIUnregistered *s, + GetByteContext *gb) { AVBufferRef *buf_ref, **tmp; + int size = bytestream2_get_bytes_left(gb); if (size < 16 || size >= INT_MAX - 1) return AVERROR_INVALIDDATA; @@ -208,8 +192,7 @@ static int decode_nal_sei_user_data_unregistered(HEVCSEIUnregistered *s, GetBitC if (!buf_ref) return AVERROR(ENOMEM); - for (int i = 0; i < size; i++) - buf_ref->data[i] = get_bits(gb, 8); + bytestream2_get_bufferu(gb, buf_ref->data, size); buf_ref->data[size] = 0; buf_ref->size = size; s->buf_ref[s->nb_buf_ref++] = buf_ref; @@ -218,7 +201,7 @@ static int decode_nal_sei_user_data_unregistered(HEVCSEIUnregistered *s, GetBitC } static int decode_registered_user_data_dynamic_hdr_plus(HEVCSEIDynamicHDRPlus *s, - GetBitContext *gb, int size) + GetByteContext *gb) { size_t meta_size; int err; @@ -226,8 +209,8 @@ static int decode_registered_user_data_dynamic_hdr_plus(HEVCSEIDynamicHDRPlus *s if (!metadata) return AVERROR(ENOMEM); - err = ff_parse_itu_t_t35_to_dynamic_hdr10_plus(metadata, - gb->buffer + get_bits_count(gb) / 8, size); + err = ff_parse_itu_t_t35_to_dynamic_hdr10_plus(metadata, gb->buffer, + bytestream2_get_bytes_left(gb)); if (err < 0) { av_free(metadata); return err; @@ -240,39 +223,74 @@ static int decode_registered_user_data_dynamic_hdr_plus(HEVCSEIDynamicHDRPlus *s return AVERROR(ENOMEM); } - skip_bits_long(gb, size * 8); + return 0; +} + +static int decode_registered_user_data_dynamic_hdr_vivid(HEVCSEIDynamicHDRVivid *s, + GetByteContext *gb) +{ + size_t meta_size; + int err; + AVDynamicHDRVivid *metadata = av_dynamic_hdr_vivid_alloc(&meta_size); + if (!metadata) + return AVERROR(ENOMEM); + + err = ff_parse_itu_t_t35_to_dynamic_hdr_vivid(metadata, + gb->buffer, bytestream2_get_bytes_left(gb)); + if (err < 0) { + av_free(metadata); + return err; + } + + av_buffer_unref(&s->info); + s->info = av_buffer_create((uint8_t *)metadata, meta_size, NULL, NULL, 0); + if (!s->info) { + av_free(metadata); + return AVERROR(ENOMEM); + } return 0; } -static int decode_nal_sei_user_data_registered_itu_t_t35(HEVCSEI *s, GetBitContext *gb, - void *logctx, int size) +static int decode_nal_sei_user_data_registered_itu_t_t35(HEVCSEI *s, GetByteContext *gb, + void *logctx) { int country_code, provider_code; - if (size < 3) + if (bytestream2_get_bytes_left(gb) < 3) return AVERROR_INVALIDDATA; - size -= 3; - country_code = get_bits(gb, 8); + country_code = bytestream2_get_byteu(gb); if (country_code == 0xFF) { - if (size < 1) + if (bytestream2_get_bytes_left(gb) < 3) return AVERROR_INVALIDDATA; - skip_bits(gb, 8); - size--; + bytestream2_skipu(gb, 1); } - if (country_code != 0xB5) { // usa_country_code + if (country_code != 0xB5 && country_code != 0x26) { // usa_country_code and cn_country_code av_log(logctx, AV_LOG_VERBOSE, - "Unsupported User Data Registered ITU-T T35 SEI message (country_code = %d)\n", + "Unsupported User Data Registered ITU-T T35 SEI message (country_code = 0x%x)\n", country_code); - goto end; + return 0; } - provider_code = get_bits(gb, 16); + provider_code = bytestream2_get_be16u(gb); switch (provider_code) { + case 0x04: { // cuva_provider_code + const uint16_t cuva_provider_oriented_code = 0x0005; + uint16_t provider_oriented_code; + + if (bytestream2_get_bytes_left(gb) < 2) + return AVERROR_INVALIDDATA; + + provider_oriented_code = bytestream2_get_be16u(gb); + if (provider_oriented_code == cuva_provider_oriented_code) { + return decode_registered_user_data_dynamic_hdr_vivid(&s->dynamic_hdr_vivid, gb); + } + break; + } case 0x3C: { // smpte_provider_code // A/341 Amendment - 2094-40 const uint16_t smpte2094_40_provider_oriented_code = 0x0001; @@ -280,29 +298,27 @@ static int decode_nal_sei_user_data_registered_itu_t_t35(HEVCSEI *s, GetBitConte uint16_t provider_oriented_code; uint8_t application_identifier; - if (size < 3) + if (bytestream2_get_bytes_left(gb) < 3) return AVERROR_INVALIDDATA; - size -= 3; - provider_oriented_code = get_bits(gb, 16); - application_identifier = get_bits(gb, 8); + provider_oriented_code = bytestream2_get_be16u(gb); + application_identifier = bytestream2_get_byteu(gb); if (provider_oriented_code == smpte2094_40_provider_oriented_code && application_identifier == smpte2094_40_application_identifier) { - return decode_registered_user_data_dynamic_hdr_plus(&s->dynamic_hdr_plus, gb, size); + return decode_registered_user_data_dynamic_hdr_plus(&s->dynamic_hdr_plus, gb); } break; } case 0x31: { // atsc_provider_code uint32_t user_identifier; - if (size < 4) + if (bytestream2_get_bytes_left(gb) < 4) return AVERROR_INVALIDDATA; - size -= 4; - user_identifier = get_bits_long(gb, 32); + user_identifier = bytestream2_get_be32u(gb); switch (user_identifier) { case MKBETAG('G', 'A', '9', '4'): - return decode_registered_user_data_closed_caption(&s->a53_caption, gb, size); + return decode_registered_user_data_closed_caption(&s->a53_caption, gb); default: av_log(logctx, AV_LOG_VERBOSE, "Unsupported User Data Registered ITU-T T35 SEI message (atsc user_identifier = 0x%04x)\n", @@ -318,15 +334,12 @@ static int decode_nal_sei_user_data_registered_itu_t_t35(HEVCSEI *s, GetBitConte break; } -end: - skip_bits_long(gb, size * 8); return 0; } static int decode_nal_sei_active_parameter_sets(HEVCSEI *s, GetBitContext *gb, void *logctx) { int num_sps_ids_minus1; - int i; unsigned active_seq_parameter_set_id; get_bits(gb, 4); // active_video_parameter_set_id @@ -346,22 +359,18 @@ static int decode_nal_sei_active_parameter_sets(HEVCSEI *s, GetBitContext *gb, v } s->active_seq_parameter_set_id = active_seq_parameter_set_id; - for (i = 1; i <= num_sps_ids_minus1; i++) - get_ue_golomb_long(gb); // active_seq_parameter_set_id[i] - return 0; } -static int decode_nal_sei_alternative_transfer(HEVCSEIAlternativeTransfer *s, GetBitContext *gb, int size) +static int decode_nal_sei_alternative_transfer(HEVCSEIAlternativeTransfer *s, + GetByteContext *gb) { - if (size < 1) + if (bytestream2_get_bytes_left(gb) < 1) return AVERROR_INVALIDDATA; s->present = 1; - s->preferred_transfer_characteristics = get_bits(gb, 8); - size--; + s->preferred_transfer_characteristics = bytestream2_get_byteu(gb); - skip_bits_long(gb, 8 * size); return 0; } @@ -454,99 +463,107 @@ static int decode_film_grain_characteristics(HEVCSEIFilmGrainCharacteristics *h, return 0; } -static int decode_nal_sei_prefix(GetBitContext *gb, void *logctx, HEVCSEI *s, - const HEVCParamSets *ps, int type, int size) +static int decode_nal_sei_prefix(GetBitContext *gb, GetByteContext *gbyte, + void *logctx, HEVCSEI *s, + const HEVCParamSets *ps, int type) { switch (type) { case 256: // Mismatched value from HM 8.1 - return decode_nal_sei_decoded_picture_hash(&s->picture_hash, gb); + return decode_nal_sei_decoded_picture_hash(&s->picture_hash, gbyte); case SEI_TYPE_FRAME_PACKING_ARRANGEMENT: return decode_nal_sei_frame_packing_arrangement(&s->frame_packing, gb); case SEI_TYPE_DISPLAY_ORIENTATION: return decode_nal_sei_display_orientation(&s->display_orientation, gb); case SEI_TYPE_PIC_TIMING: - return decode_nal_sei_pic_timing(s, gb, ps, logctx, size); + return decode_nal_sei_pic_timing(s, gb, ps, logctx); case SEI_TYPE_MASTERING_DISPLAY_COLOUR_VOLUME: - return decode_nal_sei_mastering_display_info(&s->mastering_display, gb, size); + return decode_nal_sei_mastering_display_info(&s->mastering_display, gbyte); case SEI_TYPE_CONTENT_LIGHT_LEVEL_INFO: - return decode_nal_sei_content_light_info(&s->content_light, gb, size); + return decode_nal_sei_content_light_info(&s->content_light, gbyte); case SEI_TYPE_ACTIVE_PARAMETER_SETS: return decode_nal_sei_active_parameter_sets(s, gb, logctx); case SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35: - return decode_nal_sei_user_data_registered_itu_t_t35(s, gb, logctx, size); + return decode_nal_sei_user_data_registered_itu_t_t35(s, gbyte, logctx); case SEI_TYPE_USER_DATA_UNREGISTERED: - return decode_nal_sei_user_data_unregistered(&s->unregistered, gb, size); + return decode_nal_sei_user_data_unregistered(&s->unregistered, gbyte); case SEI_TYPE_ALTERNATIVE_TRANSFER_CHARACTERISTICS: - return decode_nal_sei_alternative_transfer(&s->alternative_transfer, gb, size); + return decode_nal_sei_alternative_transfer(&s->alternative_transfer, gbyte); case SEI_TYPE_TIME_CODE: return decode_nal_sei_timecode(&s->timecode, gb); case SEI_TYPE_FILM_GRAIN_CHARACTERISTICS: return decode_film_grain_characteristics(&s->film_grain_characteristics, gb); default: 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(GetBitContext *gb, void *logctx, HEVCSEI *s, - int type, int size) +static int decode_nal_sei_suffix(GetBitContext *gb, GetByteContext *gbyte, + void *logctx, HEVCSEI *s, int type) { switch (type) { case SEI_TYPE_DECODED_PICTURE_HASH: - return decode_nal_sei_decoded_picture_hash(&s->picture_hash, gb); + return decode_nal_sei_decoded_picture_hash(&s->picture_hash, gbyte); default: 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(GetBitContext *gb, void *logctx, HEVCSEI *s, +static int decode_nal_sei_message(GetByteContext *gb, void *logctx, HEVCSEI *s, const HEVCParamSets *ps, int nal_unit_type) { + GetByteContext message_gbyte; + GetBitContext message_gb; int payload_type = 0; int payload_size = 0; int byte = 0xFF; + av_unused int ret; av_log(logctx, AV_LOG_DEBUG, "Decoding SEI\n"); while (byte == 0xFF) { - if (get_bits_left(gb) < 16 || payload_type > INT_MAX - 255) + if (bytestream2_get_bytes_left(gb) < 2 || payload_type > INT_MAX - 255) return AVERROR_INVALIDDATA; - byte = get_bits(gb, 8); + byte = bytestream2_get_byteu(gb); payload_type += byte; } byte = 0xFF; while (byte == 0xFF) { - if (get_bits_left(gb) < 8 + 8LL*payload_size) + if (bytestream2_get_bytes_left(gb) < 1 + payload_size) return AVERROR_INVALIDDATA; - byte = get_bits(gb, 8); + byte = bytestream2_get_byteu(gb); payload_size += byte; } - if (get_bits_left(gb) < 8LL*payload_size) + if (bytestream2_get_bytes_left(gb) < payload_size) return AVERROR_INVALIDDATA; + bytestream2_init(&message_gbyte, gb->buffer, payload_size); + ret = init_get_bits8(&message_gb, gb->buffer, payload_size); + av_assert1(ret >= 0); + bytestream2_skipu(gb, payload_size); if (nal_unit_type == HEVC_NAL_SEI_PREFIX) { - return decode_nal_sei_prefix(gb, logctx, s, ps, payload_type, payload_size); + return decode_nal_sei_prefix(&message_gb, &message_gbyte, + logctx, s, ps, payload_type); } else { /* nal_unit_type == NAL_SEI_SUFFIX */ - return decode_nal_sei_suffix(gb, logctx, s, payload_type, payload_size); + return decode_nal_sei_suffix(&message_gb, &message_gbyte, + logctx, s, payload_type); } } -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, HEVCSEI *s, - const HEVCParamSets *ps, int type) + const HEVCParamSets *ps, enum HEVCNALUnitType type) { + GetByteContext gbyte; int ret; + av_assert1((get_bits_count(gb) % 8) == 0); + bytestream2_init(&gbyte, gb->buffer + get_bits_count(gb) / 8, + get_bits_left(gb) / 8); + do { - ret = decode_nal_sei_message(gb, logctx, s, ps, type); + ret = decode_nal_sei_message(&gbyte, logctx, s, ps, type); if (ret < 0) return ret; - } while (more_rbsp_data(gb)); + } while (bytestream2_get_bytes_left(&gbyte) > 0); return 1; } @@ -559,4 +576,5 @@ void ff_hevc_reset_sei(HEVCSEI *s) s->unregistered.nb_buf_ref = 0; av_freep(&s->unregistered.buf_ref); av_buffer_unref(&s->dynamic_hdr_plus.info); + av_buffer_unref(&s->dynamic_hdr_vivid.info); } diff --git a/libavcodec/hevc_sei.h b/libavcodec/hevc_sei.h index ac8c61c1f..ef987f678 100644 --- a/libavcodec/hevc_sei.h +++ b/libavcodec/hevc_sei.h @@ -26,6 +26,7 @@ #include "libavutil/buffer.h" #include "get_bits.h" +#include "hevc.h" #include "sei.h" @@ -78,6 +79,10 @@ typedef struct HEVCSEIDynamicHDRPlus { AVBufferRef *info; } HEVCSEIDynamicHDRPlus; +typedef struct HEVCSEIDynamicHDRVivid { + AVBufferRef *info; +} HEVCSEIDynamicHDRVivid; + typedef struct HEVCSEIContentLight { int present; uint16_t max_content_light_level; @@ -139,6 +144,7 @@ typedef struct HEVCSEI { HEVCSEIUnregistered unregistered; HEVCSEIMasteringDisplay mastering_display; HEVCSEIDynamicHDRPlus dynamic_hdr_plus; + HEVCSEIDynamicHDRVivid dynamic_hdr_vivid; HEVCSEIContentLight content_light; int active_seq_parameter_set_id; HEVCSEIAlternativeTransfer alternative_transfer; @@ -149,7 +155,7 @@ typedef struct HEVCSEI { struct HEVCParamSets; int ff_hevc_decode_nal_sei(GetBitContext *gb, void *logctx, HEVCSEI *s, - const struct HEVCParamSets *ps, int type); + const struct HEVCParamSets *ps, enum HEVCNALUnitType type); /** * Reset SEI values that are stored on the Context. diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index 8d7a4f714..f222f2070 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -23,6 +23,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/attributes.h" #include "libavutil/common.h" #include "libavutil/display.h" @@ -38,15 +40,19 @@ #include "bswapdsp.h" #include "bytestream.h" #include "cabac_functions.h" +#include "codec_internal.h" #include "golomb.h" #include "hevc.h" #include "hevc_data.h" #include "hevc_parse.h" #include "hevcdec.h" #include "hwconfig.h" +#include "internal.h" #include "profiles.h" +#include "thread.h" +#include "threadframe.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 }; +static const uint8_t hevc_pel_weight[65] = { [2] = 0, [4] = 1, [6] = 2, [8] = 3, [12] = 4, [16] = 5, [24] = 6, [32] = 7, [48] = 8, [64] = 9 }; /** * NOTE: Each function hls_foo correspond to the function foo in the @@ -1503,7 +1509,7 @@ static void luma_mc_uni(HEVCContext *s, uint8_t *dst, ptrdiff_t dststride, int my = mv->y & 3; int weight_flag = (s->sh.slice_type == HEVC_SLICE_P && s->ps.pps->weighted_pred_flag) || (s->sh.slice_type == HEVC_SLICE_B && s->ps.pps->weighted_bipred_flag); - int idx = ff_hevc_pel_weight[block_w]; + int idx = hevc_pel_weight[block_w]; x_off += mv->x >> 2; y_off += mv->y >> 2; @@ -1570,7 +1576,7 @@ static void luma_mc_uni(HEVCContext *s, uint8_t *dst, ptrdiff_t dststride, int y_off0 = y_off + (mv0->y >> 2); int x_off1 = x_off + (mv1->x >> 2); int y_off1 = y_off + (mv1->y >> 2); - int idx = ff_hevc_pel_weight[block_w]; + int idx = hevc_pel_weight[block_w]; uint8_t *src0 = ref0->data[0] + y_off0 * src0stride + (int)((unsigned)x_off0 << s->ps.sps->pixel_shift); uint8_t *src1 = ref1->data[0] + y_off1 * src1stride + (int)((unsigned)x_off1 << s->ps.sps->pixel_shift); @@ -1652,7 +1658,7 @@ static void chroma_mc_uni(HEVCContext *s, uint8_t *dst0, const Mv *mv = ¤t_mv->mv[reflist]; int weight_flag = (s->sh.slice_type == HEVC_SLICE_P && s->ps.pps->weighted_pred_flag) || (s->sh.slice_type == HEVC_SLICE_B && s->ps.pps->weighted_bipred_flag); - int idx = ff_hevc_pel_weight[block_w]; + int idx = hevc_pel_weight[block_w]; int hshift = s->ps.sps->hshift[1]; int vshift = s->ps.sps->vshift[1]; intptr_t mx = av_mod_uintp2(mv->x, 2 + hshift); @@ -1737,7 +1743,7 @@ static void chroma_mc_bi(HEVCContext *s, uint8_t *dst0, ptrdiff_t dststride, AVF int y_off0 = y_off + (mv0->y >> (2 + vshift)); int x_off1 = x_off + (mv1->x >> (2 + hshift)); int y_off1 = y_off + (mv1->y >> (2 + vshift)); - int idx = ff_hevc_pel_weight[block_w]; + int idx = hevc_pel_weight[block_w]; src1 += y_off0 * src1stride + (int)((unsigned)x_off0 << s->ps.sps->pixel_shift); src2 += y_off1 * src2stride + (int)((unsigned)x_off1 << s->ps.sps->pixel_shift); @@ -2981,6 +2987,17 @@ static int set_side_data(HEVCContext *s) if ((ret = ff_dovi_attach_side_data(&s->dovi_ctx, out)) < 0) return ret; + if (s->sei.dynamic_hdr_vivid.info) { + AVBufferRef *info_ref = av_buffer_ref(s->sei.dynamic_hdr_vivid.info); + if (!info_ref) + return AVERROR(ENOMEM); + + if (!av_frame_new_side_data_from_buf(out, AV_FRAME_DATA_DYNAMIC_HDR_VIVID, info_ref)) { + av_buffer_unref(&info_ref); + return AVERROR(ENOMEM); + } + } + return 0; } @@ -3025,7 +3042,7 @@ static int hevc_frame_start(HEVCContext *s) s->ref->frame_grain->format = s->ref->frame->format; s->ref->frame_grain->width = s->ref->frame->width; s->ref->frame_grain->height = s->ref->frame->height; - if ((ret = ff_thread_get_buffer(s->avctx, &s->ref->tf_grain, 0)) < 0) + if ((ret = ff_thread_get_buffer(s->avctx, s->ref->frame_grain, 0)) < 0) goto fail; } @@ -3457,8 +3474,8 @@ static int hevc_decode_extradata(HEVCContext *s, uint8_t *buf, int length, int f return 0; } -static int hevc_decode_frame(AVCodecContext *avctx, void *data, int *got_output, - AVPacket *avpkt) +static int hevc_decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_output, AVPacket *avpkt) { int ret; uint8_t *sd; @@ -3466,7 +3483,7 @@ static int hevc_decode_frame(AVCodecContext *avctx, void *data, int *got_output, HEVCContext *s = avctx->priv_data; if (!avpkt->size) { - ret = ff_hevc_output_frame(s, data, 1); + ret = ff_hevc_output_frame(s, rframe, 1); if (ret < 0) return ret; @@ -3516,7 +3533,7 @@ static int hevc_decode_frame(AVCodecContext *avctx, void *data, int *got_output, } if (s->output_frame->buf[0]) { - av_frame_move_ref(data, s->output_frame); + av_frame_move_ref(rframe, s->output_frame); *got_output = 1; } @@ -3532,7 +3549,7 @@ static int hevc_ref_frame(HEVCContext *s, HEVCFrame *dst, HEVCFrame *src) return ret; if (src->needs_fg) { - ret = ff_thread_ref_frame(&dst->tf_grain, &src->tf_grain); + ret = av_frame_ref(dst->frame_grain, src->frame_grain); if (ret < 0) return ret; dst->needs_fg = 1; @@ -3630,49 +3647,43 @@ static av_cold int hevc_init_context(AVCodecContext *avctx) s->HEVClcList = av_mallocz(sizeof(HEVCLocalContext*) * s->threads_number); s->sList = av_mallocz(sizeof(HEVCContext*) * s->threads_number); if (!s->HEVClc || !s->HEVClcList || !s->sList) - goto fail; + return AVERROR(ENOMEM); s->HEVClcList[0] = s->HEVClc; s->sList[0] = s; s->cabac_state = av_malloc(HEVC_CONTEXTS); if (!s->cabac_state) - goto fail; + return AVERROR(ENOMEM); s->output_frame = av_frame_alloc(); if (!s->output_frame) - goto fail; + return AVERROR(ENOMEM); for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) { s->DPB[i].frame = av_frame_alloc(); if (!s->DPB[i].frame) - goto fail; + return AVERROR(ENOMEM); s->DPB[i].tf.f = s->DPB[i].frame; s->DPB[i].frame_grain = av_frame_alloc(); if (!s->DPB[i].frame_grain) - goto fail; - s->DPB[i].tf_grain.f = s->DPB[i].frame_grain; + return AVERROR(ENOMEM); } s->max_ra = INT_MAX; s->md5_ctx = av_md5_alloc(); if (!s->md5_ctx) - goto fail; + return AVERROR(ENOMEM); ff_bswapdsp_init(&s->bdsp); s->dovi_ctx.logctx = avctx; - s->context_initialized = 1; s->eos = 0; ff_hevc_reset_sei(&s->sei); return 0; - -fail: - hevc_decode_free(avctx); - return AVERROR(ENOMEM); } #if HAVE_THREADS @@ -3683,12 +3694,6 @@ static int hevc_update_thread_context(AVCodecContext *dst, HEVCContext *s0 = src->priv_data; int i, ret; - if (!s->context_initialized) { - ret = hevc_init_context(dst); - if (ret < 0) - return ret; - } - for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) { ff_hevc_unref_frame(s, &s->DPB[i], ~0); if (s0->DPB[i].frame->buf[0]) { @@ -3775,6 +3780,10 @@ static int hevc_update_thread_context(AVCodecContext *dst, if (ret < 0) return ret; + ret = av_buffer_replace(&s->sei.dynamic_hdr_vivid.info, s0->sei.dynamic_hdr_vivid.info); + if (ret < 0) + return ret; + s->sei.frame_packing = s0->sei.frame_packing; s->sei.display_orientation = s0->sei.display_orientation; s->sei.mastering_display = s0->sei.mastering_display; @@ -3794,9 +3803,12 @@ static av_cold int hevc_decode_init(AVCodecContext *avctx) HEVCContext *s = avctx->priv_data; int ret; - if(avctx->active_thread_type & FF_THREAD_SLICE) + if (avctx->active_thread_type & FF_THREAD_SLICE) { s->threads_number = avctx->thread_count; - else + ret = ff_slice_thread_init_progress(avctx); + if (ret < 0) + return ret; + } else s->threads_number = 1; if((avctx->active_thread_type & FF_THREAD_FRAME) && avctx->thread_count > 1) @@ -3855,23 +3867,23 @@ static const AVClass hevc_decoder_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_hevc_decoder = { - .name = "hevc", - .long_name = NULL_IF_CONFIG_SMALL("HEVC (High Efficiency Video Coding)"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_HEVC, +const FFCodec ff_hevc_decoder = { + .p.name = "hevc", + .p.long_name = NULL_IF_CONFIG_SMALL("HEVC (High Efficiency Video Coding)"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_HEVC, .priv_data_size = sizeof(HEVCContext), - .priv_class = &hevc_decoder_class, + .p.priv_class = &hevc_decoder_class, .init = hevc_decode_init, .close = hevc_decode_free, - .decode = hevc_decode_frame, + FF_CODEC_DECODE_CB(hevc_decode_frame), .flush = hevc_decode_flush, .update_thread_context = ONLY_IF_THREADS_ENABLED(hevc_update_thread_context), - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_EXPORTS_CROPPING | FF_CODEC_CAP_ALLOCATE_PROGRESS | FF_CODEC_CAP_INIT_CLEANUP, - .profiles = NULL_IF_CONFIG_SMALL(ff_hevc_profiles), + .p.profiles = NULL_IF_CONFIG_SMALL(ff_hevc_profiles), .hw_configs = (const AVCodecHWConfigInternal *const []) { #if CONFIG_HEVC_DXVA2_HWACCEL HWACCEL_DXVA2(hevc), diff --git a/libavcodec/hevcdec.h b/libavcodec/hevcdec.h index 157bc6926..f6acf845a 100644 --- a/libavcodec/hevcdec.h +++ b/libavcodec/hevcdec.h @@ -26,7 +26,6 @@ #include #include "libavutil/buffer.h" -#include "libavutil/md5.h" #include "libavutil/mem_internal.h" #include "avcodec.h" @@ -41,8 +40,7 @@ #include "hevc_sei.h" #include "hevcdsp.h" #include "h274.h" -#include "internal.h" -#include "thread.h" +#include "threadframe.h" #include "videodsp.h" #define SHIFT_CTB_WPP 2 @@ -396,7 +394,6 @@ typedef struct HEVCFrame { AVFrame *frame; AVFrame *frame_grain; ThreadFrame tf; - ThreadFrame tf_grain; int needs_fg; /* 1 if grain needs to be applied by the decoder */ MvField *tab_mvf; RefPicList *refPicList; @@ -566,7 +563,6 @@ typedef struct HEVCContext { // type of the first VCL NAL of the current frame enum HEVCNALUnitType first_nal_type; - uint8_t context_initialized; int is_nalff; ///< this flag is != 0 if bitstream is encapsulated ///< as a format defined in 14496-15 int apply_defdispwin; @@ -588,8 +584,8 @@ void ff_hevc_clear_refs(HEVCContext *s); */ void ff_hevc_flush_dpb(HEVCContext *s); -RefPicList *ff_hevc_get_ref_list(HEVCContext *s, HEVCFrame *frame, - int x0, int y0); +const RefPicList *ff_hevc_get_ref_list(const HEVCContext *s, const HEVCFrame *frame, + int x0, int y0); /** * Construct the reference picture sets for the current frame. diff --git a/libavcodec/hevcdsp.c b/libavcodec/hevcdsp.c index fe272ac1c..2ca551df1 100644 --- a/libavcodec/hevcdsp.c +++ b/libavcodec/hevcdsp.c @@ -257,14 +257,17 @@ int i = 0; break; } - if (ARCH_AARCH64) - ff_hevc_dsp_init_aarch64(hevcdsp, bit_depth); - 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) - ff_hevc_dsp_init_x86(hevcdsp, bit_depth); - if (ARCH_MIPS) - ff_hevc_dsp_init_mips(hevcdsp, bit_depth); +#if ARCH_AARCH64 + ff_hevc_dsp_init_aarch64(hevcdsp, bit_depth); +#elif ARCH_ARM + ff_hevc_dsp_init_arm(hevcdsp, bit_depth); +#elif ARCH_PPC + ff_hevc_dsp_init_ppc(hevcdsp, bit_depth); +#elif ARCH_X86 + ff_hevc_dsp_init_x86(hevcdsp, bit_depth); +#elif ARCH_MIPS + ff_hevc_dsp_init_mips(hevcdsp, bit_depth); +#elif ARCH_LOONGARCH + ff_hevc_dsp_init_loongarch(hevcdsp, bit_depth); +#endif } diff --git a/libavcodec/hevcdsp.h b/libavcodec/hevcdsp.h index 0e013a832..d642ecf9c 100644 --- a/libavcodec/hevcdsp.h +++ b/libavcodec/hevcdsp.h @@ -134,5 +134,6 @@ 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); void ff_hevc_dsp_init_mips(HEVCDSPContext *c, const int bit_depth); +void ff_hevc_dsp_init_loongarch(HEVCDSPContext *c, const int bit_depth); #endif /* AVCODEC_HEVCDSP_H */ diff --git a/libavcodec/hevcdsp_template.c b/libavcodec/hevcdsp_template.c index 56cd9e605..61425975c 100644 --- a/libavcodec/hevcdsp_template.c +++ b/libavcodec/hevcdsp_template.c @@ -313,7 +313,7 @@ static void FUNC(sao_band_filter)(uint8_t *_dst, uint8_t *_src, offset_table[(k + sao_left_class) & 31] = sao_offset_val[k + 1]; for (y = 0; y < height; y++) { for (x = 0; x < width; x++) - dst[x] = av_clip_pixel(src[x] + offset_table[src[x] >> shift]); + dst[x] = av_clip_pixel(src[x] + offset_table[(src[x] >> shift) & 31]); dst += stride_dst; src += stride_src; } diff --git a/libavcodec/hevcpred.c b/libavcodec/hevcpred.c index 7a86ed3d3..16b012f46 100644 --- a/libavcodec/hevcpred.c +++ b/libavcodec/hevcpred.c @@ -75,6 +75,7 @@ void ff_hevc_pred_init(HEVCPredContext *hpc, int bit_depth) break; } - if (ARCH_MIPS) - ff_hevc_pred_init_mips(hpc, bit_depth); +#if ARCH_MIPS + ff_hevc_pred_init_mips(hpc, bit_depth); +#endif } diff --git a/libavcodec/hnm4video.c b/libavcodec/hnm4video.c index dd7504c51..1326d5f87 100644 --- a/libavcodec/hnm4video.c +++ b/libavcodec/hnm4video.c @@ -28,6 +28,7 @@ #include "libavutil/mem.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" #define HNM4_CHUNK_ID_PL 19536 @@ -63,7 +64,7 @@ static int getbit(GetByteContext *gb, uint32_t *bitbuf, int *bits) return ret; } -static void unpack_intraframe(AVCodecContext *avctx, uint8_t *src, +static void unpack_intraframe(AVCodecContext *avctx, const uint8_t *src, uint32_t size) { Hnm4VideoContext *hnm = avctx->priv_data; @@ -146,7 +147,7 @@ static void copy_processed_frame(AVCodecContext *avctx, AVFrame *frame) } } -static int decode_interframe_v4(AVCodecContext *avctx, uint8_t *src, uint32_t size) +static int decode_interframe_v4(AVCodecContext *avctx, const uint8_t *src, uint32_t size) { Hnm4VideoContext *hnm = avctx->priv_data; GetByteContext gb; @@ -275,7 +276,7 @@ static int decode_interframe_v4(AVCodecContext *avctx, uint8_t *src, uint32_t si return 0; } -static void decode_interframe_v4a(AVCodecContext *avctx, uint8_t *src, +static void decode_interframe_v4a(AVCodecContext *avctx, const uint8_t *src, uint32_t size) { Hnm4VideoContext *hnm = avctx->priv_data; @@ -354,7 +355,7 @@ static void decode_interframe_v4a(AVCodecContext *avctx, uint8_t *src, } } -static void hnm_update_palette(AVCodecContext *avctx, uint8_t *src, +static void hnm_update_palette(AVCodecContext *avctx, const uint8_t *src, uint32_t size) { Hnm4VideoContext *hnm = avctx->priv_data; @@ -387,10 +388,9 @@ static void hnm_update_palette(AVCodecContext *avctx, uint8_t *src, } } -static int hnm_decode_frame(AVCodecContext *avctx, void *data, +static int hnm_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt) { - AVFrame *frame = data; Hnm4VideoContext *hnm = avctx->priv_data; int ret; uint16_t chunk_id; @@ -497,15 +497,15 @@ static av_cold int hnm_decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_hnm4_video_decoder = { - .name = "hnm4video", - .long_name = NULL_IF_CONFIG_SMALL("HNM 4 video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_HNM4_VIDEO, +const FFCodec ff_hnm4_video_decoder = { + .p.name = "hnm4video", + .p.long_name = NULL_IF_CONFIG_SMALL("HNM 4 video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_HNM4_VIDEO, .priv_data_size = sizeof(Hnm4VideoContext), .init = hnm_decode_init, .close = hnm_decode_end, - .decode = hnm_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(hnm_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/hpeldsp.c b/libavcodec/hpeldsp.c index 8e2fd8fcf..1ec76e7a4 100644 --- a/libavcodec/hpeldsp.c +++ b/libavcodec/hpeldsp.c @@ -355,16 +355,19 @@ av_cold void ff_hpeldsp_init(HpelDSPContext *c, int flags) hpel_funcs(avg, [3], 2); hpel_funcs(avg_no_rnd,, 16); - if (ARCH_AARCH64) - ff_hpeldsp_init_aarch64(c, flags); - if (ARCH_ALPHA) - ff_hpeldsp_init_alpha(c, flags); - if (ARCH_ARM) - ff_hpeldsp_init_arm(c, flags); - if (ARCH_PPC) - ff_hpeldsp_init_ppc(c, flags); - if (ARCH_X86) - ff_hpeldsp_init_x86(c, flags); - if (ARCH_MIPS) - ff_hpeldsp_init_mips(c, flags); +#if ARCH_AARCH64 + ff_hpeldsp_init_aarch64(c, flags); +#elif ARCH_ALPHA + ff_hpeldsp_init_alpha(c, flags); +#elif ARCH_ARM + ff_hpeldsp_init_arm(c, flags); +#elif ARCH_PPC + ff_hpeldsp_init_ppc(c, flags); +#elif ARCH_X86 + ff_hpeldsp_init_x86(c, flags); +#elif ARCH_MIPS + ff_hpeldsp_init_mips(c, flags); +#elif ARCH_LOONGARCH64 + ff_hpeldsp_init_loongarch(c, flags); +#endif } diff --git a/libavcodec/hpeldsp.h b/libavcodec/hpeldsp.h index 768139bfc..45e81b10a 100644 --- a/libavcodec/hpeldsp.h +++ b/libavcodec/hpeldsp.h @@ -102,5 +102,6 @@ void ff_hpeldsp_init_arm(HpelDSPContext *c, int flags); void ff_hpeldsp_init_ppc(HpelDSPContext *c, int flags); void ff_hpeldsp_init_x86(HpelDSPContext *c, int flags); void ff_hpeldsp_init_mips(HpelDSPContext *c, int flags); +void ff_hpeldsp_init_loongarch(HpelDSPContext *c, int flags); #endif /* AVCODEC_HPELDSP_H */ diff --git a/libavcodec/hq_hqa.c b/libavcodec/hq_hqa.c index 71753e7cc..cea2475bb 100644 --- a/libavcodec/hq_hqa.c +++ b/libavcodec/hq_hqa.c @@ -25,6 +25,7 @@ #include "avcodec.h" #include "canopus.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" @@ -300,11 +301,10 @@ static int hqa_decode_frame(HQContext *ctx, AVFrame *pic, size_t data_size) return 0; } -static int hq_hqa_decode_frame(AVCodecContext *avctx, void *data, +static int hq_hqa_decode_frame(AVCodecContext *avctx, AVFrame *pic, int *got_frame, AVPacket *avpkt) { HQContext *ctx = avctx->priv_data; - AVFrame *pic = data; uint32_t info_tag; unsigned int data_size; int ret; @@ -381,16 +381,16 @@ static av_cold int hq_hqa_decode_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_hq_hqa_decoder = { - .name = "hq_hqa", - .long_name = NULL_IF_CONFIG_SMALL("Canopus HQ/HQA"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_HQ_HQA, +const FFCodec ff_hq_hqa_decoder = { + .p.name = "hq_hqa", + .p.long_name = NULL_IF_CONFIG_SMALL("Canopus HQ/HQA"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_HQ_HQA, .priv_data_size = sizeof(HQContext), .init = hq_hqa_decode_init, - .decode = hq_hqa_decode_frame, + FF_CODEC_DECODE_CB(hq_hqa_decode_frame), .close = hq_hqa_decode_close, - .capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/hqx.c b/libavcodec/hqx.c index 3a4db1b6c..596b8a7ed 100644 --- a/libavcodec/hqx.c +++ b/libavcodec/hqx.c @@ -25,8 +25,8 @@ #include "avcodec.h" #include "canopus.h" +#include "codec_internal.h" #include "get_bits.h" -#include "internal.h" #include "thread.h" #include "hqx.h" @@ -400,12 +400,11 @@ static int decode_slice_thread(AVCodecContext *avctx, void *arg, return decode_slice(ctx, slice_no); } -static int hqx_decode_frame(AVCodecContext *avctx, void *data, +static int hqx_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_picture_ptr, AVPacket *avpkt) { HQXContext *ctx = avctx->priv_data; - ThreadFrame frame = { .f = data }; - uint8_t *src = avpkt->data; + const uint8_t *src = avpkt->data; uint32_t info_tag; int data_start; int i, ret; @@ -433,7 +432,7 @@ static int hqx_decode_frame(AVCodecContext *avctx, void *data, data_start = src - avpkt->data; ctx->data_size = avpkt->size - data_start; ctx->src = src; - ctx->pic = data; + ctx->pic = frame; if (ctx->data_size < HQX_HEADER_SIZE) { av_log(avctx, AV_LOG_ERROR, "Frame too small.\n"); @@ -499,7 +498,7 @@ static int hqx_decode_frame(AVCodecContext *avctx, void *data, return AVERROR_INVALIDDATA; } - ret = ff_thread_get_buffer(avctx, &frame, 0); + ret = ff_thread_get_buffer(avctx, frame, 0); if (ret < 0) return ret; @@ -535,16 +534,16 @@ static av_cold int hqx_decode_init(AVCodecContext *avctx) return ff_hqx_init_vlcs(ctx); } -const AVCodec ff_hqx_decoder = { - .name = "hqx", - .long_name = NULL_IF_CONFIG_SMALL("Canopus HQX"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_HQX, +const FFCodec ff_hqx_decoder = { + .p.name = "hqx", + .p.long_name = NULL_IF_CONFIG_SMALL("Canopus HQX"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_HQX, .priv_data_size = sizeof(HQXContext), .init = hqx_decode_init, - .decode = hqx_decode_frame, + FF_CODEC_DECODE_CB(hqx_decode_frame), .close = hqx_decode_close, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS | + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, diff --git a/libavcodec/hqx.h b/libavcodec/hqx.h index 3eddaafb2..155ec7f84 100644 --- a/libavcodec/hqx.h +++ b/libavcodec/hqx.h @@ -70,7 +70,7 @@ typedef struct HQXContext { int format, dcb, width, height; int interlaced; - uint8_t *src; + const uint8_t *src; unsigned int data_size; uint32_t slice_off[17]; diff --git a/libavcodec/huffman.c b/libavcodec/huffman.c index be351ba2d..99aa39c56 100644 --- a/libavcodec/huffman.c +++ b/libavcodec/huffman.c @@ -26,8 +26,11 @@ #include +#include "libavutil/error.h" +#include "libavutil/log.h" +#include "libavutil/macros.h" +#include "libavutil/mem.h" #include "libavutil/qsort.h" -#include "libavutil/common.h" #include "huffman.h" #include "vlc.h" diff --git a/libavcodec/huffyuvdec.c b/libavcodec/huffyuvdec.c index 0abf73b21..acc4aafdc 100644 --- a/libavcodec/huffyuvdec.c +++ b/libavcodec/huffyuvdec.c @@ -32,11 +32,13 @@ #define UNCHECKED_BITSTREAM_READER 1 +#include "config_components.h" + #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" #include "huffyuv.h" #include "huffyuvdsp.h" -#include "internal.h" #include "lossless_videodsp.h" #include "thread.h" #include "libavutil/imgutils.h" @@ -564,24 +566,24 @@ static av_cold int decode_init(AVCodecContext *avctx) /** Subset of GET_VLC for use in hand-roller VLC code */ #define VLC_INTERN(dst, table, gb, name, bits, max_depth) \ - code = table[index][0]; \ - n = table[index][1]; \ + code = table[index].sym; \ + n = table[index].len; \ if (max_depth > 1 && n < 0) { \ LAST_SKIP_BITS(name, gb, bits); \ UPDATE_CACHE(name, gb); \ \ nb_bits = -n; \ index = SHOW_UBITS(name, gb, nb_bits) + code; \ - code = table[index][0]; \ - n = table[index][1]; \ + code = table[index].sym; \ + n = table[index].len; \ if (max_depth > 2 && n < 0) { \ LAST_SKIP_BITS(name, gb, nb_bits); \ UPDATE_CACHE(name, gb); \ \ nb_bits = -n; \ index = SHOW_UBITS(name, gb, nb_bits) + code; \ - code = table[index][0]; \ - n = table[index][1]; \ + code = table[index].sym; \ + n = table[index].len; \ } \ } \ dst = code; \ @@ -592,7 +594,7 @@ static av_cold int decode_init(AVCodecContext *avctx) bits, max_depth, OP) \ do { \ unsigned int index = SHOW_UBITS(name, gb, bits); \ - int code, n = dtable[index][1]; \ + int code, n = dtable[index].len; \ \ if (n<=0) { \ int nb_bits; \ @@ -602,7 +604,7 @@ static av_cold int decode_init(AVCodecContext *avctx) index = SHOW_UBITS(name, gb, bits); \ VLC_INTERN(dst1, table2, gb, name, bits, max_depth); \ } else { \ - code = dtable[index][0]; \ + code = dtable[index].sym; \ OP(dst0, dst1, code); \ LAST_SKIP_BITS(name, gb, n); \ } \ @@ -750,10 +752,10 @@ static av_always_inline void decode_bgr_1(HYuvContext *s, int count, UPDATE_CACHE(re, &s->gb); index = SHOW_UBITS(re, &s->gb, VLC_BITS); - n = s->vlc[4].table[index][1]; + n = s->vlc[4].table[index].len; if (n>0) { - code = s->vlc[4].table[index][0]; + code = s->vlc[4].table[index].sym; *(uint32_t *) &s->temp[0][4 * i] = s->pix_bgr_map[code]; LAST_SKIP_BITS(re, &s->gb, n); } else { @@ -1177,16 +1179,14 @@ static int decode_slice(AVCodecContext *avctx, AVFrame *p, int height, return 0; } -static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *p, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; HYuvContext *s = avctx->priv_data; const int width = s->width; const int height = s->height; - ThreadFrame frame = { .f = data }; - AVFrame *const p = data; int slice, table_size = 0, ret, nb_slices; unsigned slices_info_offset; int slice_height; @@ -1203,7 +1203,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, s->bdsp.bswap_buf((uint32_t *) s->bitstream_buffer, (const uint32_t *) buf, buf_size / 4); - if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, p, 0)) < 0) return ret; if (s->context) { @@ -1262,47 +1262,47 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, return (get_bits_count(&s->gb) + 31) / 32 * 4 + table_size; } -const AVCodec ff_huffyuv_decoder = { - .name = "huffyuv", - .long_name = NULL_IF_CONFIG_SMALL("Huffyuv / HuffYUV"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_HUFFYUV, +const FFCodec ff_huffyuv_decoder = { + .p.name = "huffyuv", + .p.long_name = NULL_IF_CONFIG_SMALL("Huffyuv / HuffYUV"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_HUFFYUV, .priv_data_size = sizeof(HYuvContext), .init = decode_init, .close = decode_end, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DRAW_HORIZ_BAND | + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_FRAME_THREADS, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; #if CONFIG_FFVHUFF_DECODER -const AVCodec ff_ffvhuff_decoder = { - .name = "ffvhuff", - .long_name = NULL_IF_CONFIG_SMALL("Huffyuv FFmpeg variant"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_FFVHUFF, +const FFCodec ff_ffvhuff_decoder = { + .p.name = "ffvhuff", + .p.long_name = NULL_IF_CONFIG_SMALL("Huffyuv FFmpeg variant"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_FFVHUFF, .priv_data_size = sizeof(HYuvContext), .init = decode_init, .close = decode_end, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DRAW_HORIZ_BAND | + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_FRAME_THREADS, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; #endif /* CONFIG_FFVHUFF_DECODER */ #if CONFIG_HYMT_DECODER -const AVCodec ff_hymt_decoder = { - .name = "hymt", - .long_name = NULL_IF_CONFIG_SMALL("HuffYUV MT"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_HYMT, +const FFCodec ff_hymt_decoder = { + .p.name = "hymt", + .p.long_name = NULL_IF_CONFIG_SMALL("HuffYUV MT"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_HYMT, .priv_data_size = sizeof(HYuvContext), .init = decode_init, .close = decode_end, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DRAW_HORIZ_BAND | + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_FRAME_THREADS, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/huffyuvdsp.c b/libavcodec/huffyuvdsp.c index 7b865fe40..10723b2fc 100644 --- a/libavcodec/huffyuvdsp.c +++ b/libavcodec/huffyuvdsp.c @@ -86,6 +86,7 @@ av_cold void ff_huffyuvdsp_init(HuffYUVDSPContext *c, enum AVPixelFormat pix_fmt c->add_hfyu_median_pred_int16 = add_hfyu_median_pred_int16_c; c->add_hfyu_left_pred_bgr32 = add_hfyu_left_pred_bgr32_c; - if (ARCH_X86) - ff_huffyuvdsp_init_x86(c, pix_fmt); +#if ARCH_X86 + ff_huffyuvdsp_init_x86(c, pix_fmt); +#endif } diff --git a/libavcodec/huffyuvenc.c b/libavcodec/huffyuvenc.c index 97497a8e7..195d45c91 100644 --- a/libavcodec/huffyuvenc.c +++ b/libavcodec/huffyuvenc.c @@ -28,12 +28,14 @@ * huffyuv encoder */ +#include "config_components.h" + #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" #include "huffyuv.h" #include "huffman.h" #include "huffyuvencdsp.h" -#include "internal.h" #include "lossless_videoencdsp.h" #include "put_bits.h" #include "libavutil/opt.h" @@ -1047,18 +1049,18 @@ static const AVClass ff_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_huffyuv_encoder = { - .name = "huffyuv", - .long_name = NULL_IF_CONFIG_SMALL("Huffyuv / HuffYUV"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_HUFFYUV, +const FFCodec ff_huffyuv_encoder = { + .p.name = "huffyuv", + .p.long_name = NULL_IF_CONFIG_SMALL("Huffyuv / HuffYUV"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_HUFFYUV, .priv_data_size = sizeof(HYuvContext), .init = encode_init, - .encode2 = encode_frame, + FF_CODEC_ENCODE_CB(encode_frame), .close = encode_end, - .capabilities = AV_CODEC_CAP_FRAME_THREADS, - .priv_class = &normal_class, - .pix_fmts = (const enum AVPixelFormat[]){ + .p.capabilities = AV_CODEC_CAP_FRAME_THREADS, + .p.priv_class = &normal_class, + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV422P, AV_PIX_FMT_RGB24, AV_PIX_FMT_RGB32, AV_PIX_FMT_NONE }, @@ -1067,18 +1069,18 @@ const AVCodec ff_huffyuv_encoder = { }; #if CONFIG_FFVHUFF_ENCODER -const AVCodec ff_ffvhuff_encoder = { - .name = "ffvhuff", - .long_name = NULL_IF_CONFIG_SMALL("Huffyuv FFmpeg variant"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_FFVHUFF, +const FFCodec ff_ffvhuff_encoder = { + .p.name = "ffvhuff", + .p.long_name = NULL_IF_CONFIG_SMALL("Huffyuv FFmpeg variant"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_FFVHUFF, .priv_data_size = sizeof(HYuvContext), .init = encode_init, - .encode2 = encode_frame, + FF_CODEC_ENCODE_CB(encode_frame), .close = encode_end, - .capabilities = AV_CODEC_CAP_FRAME_THREADS, - .priv_class = &ff_class, - .pix_fmts = (const enum AVPixelFormat[]){ + .p.capabilities = AV_CODEC_CAP_FRAME_THREADS, + .p.priv_class = &ff_class, + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV440P, AV_PIX_FMT_GBRP, diff --git a/libavcodec/huffyuvencdsp.c b/libavcodec/huffyuvencdsp.c index 427d118be..ea1ef911b 100644 --- a/libavcodec/huffyuvencdsp.c +++ b/libavcodec/huffyuvencdsp.c @@ -73,6 +73,7 @@ av_cold void ff_huffyuvencdsp_init(HuffYUVEncDSPContext *c, AVCodecContext *avct c->diff_int16 = diff_int16_c; c->sub_hfyu_median_pred_int16 = sub_hfyu_median_pred_int16_c; - if (ARCH_X86) - ff_huffyuvencdsp_init_x86(c, avctx); +#if ARCH_X86 + ff_huffyuvencdsp_init_x86(c, avctx); +#endif } diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h index 1e7b46495..aca55831f 100644 --- a/libavcodec/hwaccels.h +++ b/libavcodec/hwaccels.h @@ -26,6 +26,7 @@ extern const AVHWAccel ff_av1_d3d11va2_hwaccel; extern const AVHWAccel ff_av1_dxva2_hwaccel; extern const AVHWAccel ff_av1_nvdec_hwaccel; extern const AVHWAccel ff_av1_vaapi_hwaccel; +extern const AVHWAccel ff_av1_vdpau_hwaccel; extern const AVHWAccel ff_h263_vaapi_hwaccel; extern const AVHWAccel ff_h263_videotoolbox_hwaccel; extern const AVHWAccel ff_h264_d3d11va_hwaccel; @@ -47,7 +48,6 @@ 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; -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; @@ -55,7 +55,6 @@ 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; diff --git a/libavcodec/hwconfig.h b/libavcodec/hwconfig.h index f421dc909..721424912 100644 --- a/libavcodec/hwconfig.h +++ b/libavcodec/hwconfig.h @@ -78,8 +78,6 @@ typedef struct AVCodecHWConfigInternal { HW_CONFIG_HWACCEL(1, 1, 1, VIDEOTOOLBOX, VIDEOTOOLBOX, ff_ ## codec ## _videotoolbox_hwaccel) #define HWACCEL_D3D11VA(codec) \ HW_CONFIG_HWACCEL(0, 0, 1, D3D11VA_VLD, NONE, ff_ ## codec ## _d3d11va_hwaccel) -#define HWACCEL_XVMC(codec) \ - HW_CONFIG_HWACCEL(0, 0, 1, XVMC, NONE, ff_ ## codec ## _xvmc_hwaccel) #define HW_CONFIG_ENCODER(device, frames, ad_hoc, format, device_type_) \ &(const AVCodecHWConfigInternal) { \ diff --git a/libavcodec/idcinvideo.c b/libavcodec/idcinvideo.c index 41df54554..ecd4ab2fe 100644 --- a/libavcodec/idcinvideo.c +++ b/libavcodec/idcinvideo.c @@ -49,6 +49,7 @@ #include #include "avcodec.h" +#include "codec_internal.h" #include "decode.h" #include "internal.h" #include "libavutil/internal.h" @@ -208,14 +209,12 @@ static int idcin_decode_vlcs(IdcinContext *s, AVFrame *frame) return 0; } -static int idcin_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int idcin_decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; IdcinContext *s = avctx->priv_data; - AVFrame *frame = data; int ret; s->buf = buf; @@ -237,20 +236,20 @@ static int idcin_decode_frame(AVCodecContext *avctx, return buf_size; } -static const AVCodecDefault idcin_defaults[] = { +static const FFCodecDefault idcin_defaults[] = { { "max_pixels", "320*240" }, { NULL }, }; -const AVCodec ff_idcin_decoder = { - .name = "idcinvideo", - .long_name = NULL_IF_CONFIG_SMALL("id Quake II CIN video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_IDCIN, +const FFCodec ff_idcin_decoder = { + .p.name = "idcinvideo", + .p.long_name = NULL_IF_CONFIG_SMALL("id Quake II CIN video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_IDCIN, .priv_data_size = sizeof(IdcinContext), .init = idcin_decode_init, - .decode = idcin_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(idcin_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .defaults = idcin_defaults, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/idctdsp.c b/libavcodec/idctdsp.c index 846ed0b0f..9035003b7 100644 --- a/libavcodec/idctdsp.c +++ b/libavcodec/idctdsp.c @@ -17,6 +17,7 @@ */ #include "config.h" +#include "config_components.h" #include "libavutil/attributes.h" #include "libavutil/common.h" #include "avcodec.h" @@ -26,7 +27,7 @@ #include "simple_idct.h" #include "xvididct.h" -av_cold void ff_init_scantable(uint8_t *permutation, ScanTable *st, +av_cold void ff_init_scantable(const uint8_t *permutation, ScanTable *st, const uint8_t *src_scantable) { int i, end; @@ -52,10 +53,11 @@ av_cold void ff_init_scantable_permutation(uint8_t *idct_permutation, { int i; - if (ARCH_X86) - if (ff_init_scantable_permutation_x86(idct_permutation, - perm_type)) - return; +#if ARCH_X86 + if (ff_init_scantable_permutation_x86(idct_permutation, + perm_type)) + return; +#endif switch (perm_type) { case FF_IDCT_PERM_NONE: @@ -237,7 +239,7 @@ static void ff_jref_idct1_add(uint8_t *dest, ptrdiff_t line_size, int16_t *block av_cold void ff_idctdsp_init(IDCTDSPContext *c, AVCodecContext *avctx) { - const unsigned high_bit_depth = avctx->bits_per_raw_sample > 8; + av_unused const unsigned high_bit_depth = avctx->bits_per_raw_sample > 8; if (avctx->lowres==1) { c->idct_put = ff_jref_idct4_put; @@ -287,7 +289,6 @@ 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_int16_8bit; c->idct_add = ff_simple_idct_add_int16_8bit; c->idct = ff_simple_idct_int16_8bit; @@ -303,18 +304,21 @@ av_cold void ff_idctdsp_init(IDCTDSPContext *c, AVCodecContext *avctx) if (CONFIG_MPEG4_DECODER && avctx->idct_algo == FF_IDCT_XVID) ff_xvid_idct_init(c, avctx); - if (ARCH_AARCH64) - ff_idctdsp_init_aarch64(c, avctx, high_bit_depth); - if (ARCH_ALPHA) - ff_idctdsp_init_alpha(c, avctx, high_bit_depth); - if (ARCH_ARM) - ff_idctdsp_init_arm(c, avctx, high_bit_depth); - if (ARCH_PPC) - ff_idctdsp_init_ppc(c, avctx, high_bit_depth); - if (ARCH_X86) - ff_idctdsp_init_x86(c, avctx, high_bit_depth); - if (ARCH_MIPS) - ff_idctdsp_init_mips(c, avctx, high_bit_depth); +#if ARCH_AARCH64 + ff_idctdsp_init_aarch64(c, avctx, high_bit_depth); +#elif ARCH_ALPHA + ff_idctdsp_init_alpha(c, avctx, high_bit_depth); +#elif ARCH_ARM + ff_idctdsp_init_arm(c, avctx, high_bit_depth); +#elif ARCH_PPC + ff_idctdsp_init_ppc(c, avctx, high_bit_depth); +#elif ARCH_X86 + ff_idctdsp_init_x86(c, avctx, high_bit_depth); +#elif ARCH_MIPS + ff_idctdsp_init_mips(c, avctx, high_bit_depth); +#elif ARCH_LOONGARCH + ff_idctdsp_init_loongarch(c, avctx, high_bit_depth); +#endif ff_init_scantable_permutation(c->idct_permutation, c->perm_type); diff --git a/libavcodec/idctdsp.h b/libavcodec/idctdsp.h index ca21a31a0..e8f20acaf 100644 --- a/libavcodec/idctdsp.h +++ b/libavcodec/idctdsp.h @@ -43,7 +43,7 @@ enum idct_permutation_type { FF_IDCT_PERM_SSE2, }; -void ff_init_scantable(uint8_t *permutation, ScanTable *st, +void ff_init_scantable(const uint8_t *permutation, ScanTable *st, const uint8_t *src_scantable); void ff_init_scantable_permutation(uint8_t *idct_permutation, enum idct_permutation_type perm_type); @@ -118,5 +118,7 @@ void ff_idctdsp_init_x86(IDCTDSPContext *c, AVCodecContext *avctx, unsigned high_bit_depth); void ff_idctdsp_init_mips(IDCTDSPContext *c, AVCodecContext *avctx, unsigned high_bit_depth); +void ff_idctdsp_init_loongarch(IDCTDSPContext *c, AVCodecContext *avctx, + unsigned high_bit_depth); #endif /* AVCODEC_IDCTDSP_H */ diff --git a/libavcodec/iff.c b/libavcodec/iff.c index 1dcf0e00e..74ebddc62 100644 --- a/libavcodec/iff.c +++ b/libavcodec/iff.c @@ -32,6 +32,7 @@ #include "bytestream.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "mathops.h" @@ -1524,12 +1525,10 @@ static int unsupported(AVCodecContext *avctx) return AVERROR_INVALIDDATA; } -static int decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { IffContext *s = avctx->priv_data; - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; const uint8_t *buf_end = buf + buf_size; @@ -1907,17 +1906,15 @@ static int decode_frame(AVCodecContext *avctx, return buf_size; } -#if CONFIG_IFF_ILBM_DECODER -const AVCodec ff_iff_ilbm_decoder = { - .name = "iff", - .long_name = NULL_IF_CONFIG_SMALL("IFF ACBM/ANIM/DEEP/ILBM/PBM/RGB8/RGBN"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_IFF_ILBM, +const FFCodec ff_iff_ilbm_decoder = { + .p.name = "iff", + .p.long_name = NULL_IF_CONFIG_SMALL("IFF ACBM/ANIM/DEEP/ILBM/PBM/RGB8/RGBN"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_IFF_ILBM, .priv_data_size = sizeof(IffContext), .init = decode_init, .close = decode_end, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; -#endif diff --git a/libavcodec/iirfilter.c b/libavcodec/iirfilter.c index 900893d2f..903d64e8d 100644 --- a/libavcodec/iirfilter.c +++ b/libavcodec/iirfilter.c @@ -330,6 +330,7 @@ av_cold void ff_iir_filter_free_coeffsp(struct FFIIRFilterCoeffs **coeffsp) void ff_iir_filter_init(FFIIRFilterContext *f) { f->filter_flt = iir_filter_flt; - if (HAVE_MIPSFPU) - ff_iir_filter_init_mips(f); +#if HAVE_MIPSFPU + ff_iir_filter_init_mips(f); +#endif } diff --git a/libavcodec/ilbcdec.c b/libavcodec/ilbcdec.c index 4d0465087..62a9ad19b 100644 --- a/libavcodec/ilbcdec.c +++ b/libavcodec/ilbcdec.c @@ -32,6 +32,7 @@ #include "libavutil/channel_layout.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "get_bits.h" #include "ilbcdata.h" @@ -1355,11 +1356,10 @@ static void hp_output(int16_t *signal, const int16_t *ba, int16_t *y, } } -static int ilbc_decode_frame(AVCodecContext *avctx, void *data, +static int ilbc_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; - AVFrame *frame = data; ILBCContext *s = avctx->priv_data; int mode = s->mode, ret; int16_t *plc_data = &s->plc_residual[LPC_FILTERORDER]; @@ -1456,8 +1456,8 @@ static av_cold int ilbc_decode_init(AVCodecContext *avctx) else return AVERROR_INVALIDDATA; - avctx->channels = 1; - avctx->channel_layout = AV_CH_LAYOUT_MONO; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; avctx->sample_rate = 8000; avctx->sample_fmt = AV_SAMPLE_FMT_S16; @@ -1478,14 +1478,14 @@ static av_cold int ilbc_decode_init(AVCodecContext *avctx) return 0; } -const AVCodec ff_ilbc_decoder = { - .name = "ilbc", - .long_name = NULL_IF_CONFIG_SMALL("iLBC (Internet Low Bitrate Codec)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_ILBC, +const FFCodec ff_ilbc_decoder = { + .p.name = "ilbc", + .p.long_name = NULL_IF_CONFIG_SMALL("iLBC (Internet Low Bitrate Codec)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_ILBC, .init = ilbc_decode_init, - .decode = ilbc_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + FF_CODEC_DECODE_CB(ilbc_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .priv_data_size = sizeof(ILBCContext), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/imc.c b/libavcodec/imc.c index 116c273ba..978ea74b7 100644 --- a/libavcodec/imc.c +++ b/libavcodec/imc.c @@ -29,6 +29,7 @@ * Only mono is supported. */ +#include "config_components.h" #include #include @@ -43,6 +44,7 @@ #include "avcodec.h" #include "bswapdsp.h" +#include "codec_internal.h" #include "get_bits.h" #include "fft.h" #include "internal.h" @@ -116,7 +118,7 @@ static VLC huffman_vlc[4][4]; #define IMC_VLC_BITS 9 #define VLC_TABLES_SIZE 9512 -static VLC_TYPE vlc_tables[VLC_TABLES_SIZE][2]; +static VLCElem vlc_tables[VLC_TABLES_SIZE]; static inline double freq2bark(double freq) { @@ -206,15 +208,17 @@ static av_cold int imc_decode_init(AVCodecContext *avctx) return AVERROR_PATCHWELCOME; } - if (avctx->codec_id == AV_CODEC_ID_IMC) - avctx->channels = 1; + if (avctx->codec_id == AV_CODEC_ID_IMC) { + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; + } - if (avctx->channels > 2) { + if (avctx->ch_layout.nb_channels > 2) { avpriv_request_sample(avctx, "Number of channels > 2"); return AVERROR_PATCHWELCOME; } - for (j = 0; j < avctx->channels; j++) { + for (j = 0; j < avctx->ch_layout.nb_channels; j++) { q->chctx[j].decoder_reset = 1; for (i = 0; i < BANDS; i++) @@ -270,8 +274,6 @@ static av_cold int imc_decode_init(AVCodecContext *avctx) ff_bswapdsp_init(&q->bdsp); avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; - avctx->channel_layout = avctx->channels == 1 ? AV_CH_LAYOUT_MONO - : AV_CH_LAYOUT_STEREO; ff_thread_once(&init_static_once, imc_init_static); @@ -875,7 +877,7 @@ static int imc_decode_block(AVCodecContext *avctx, IMCContext *q, int ch) int imc_hdr, i, j, ret; int flag; int bits; - int counter, bitscount; + int bitscount; IMCChannel *chctx = q->chctx + ch; @@ -924,7 +926,6 @@ static int imc_decode_block(AVCodecContext *avctx, IMCContext *q, int ch) memcpy(chctx->old_floor, chctx->flcoeffs1, 32 * sizeof(float)); - counter = 0; if (stream_format_code & 0x1) { for (i = 0; i < BANDS; i++) { chctx->bandWidthT[i] = band_tab[i + 1] - band_tab[i]; @@ -936,7 +937,6 @@ static int imc_decode_block(AVCodecContext *avctx, IMCContext *q, int ch) for (i = 0; i < BANDS; i++) { if (chctx->levlCoeffBuf[i] == 16) { chctx->bandWidthT[i] = 0; - counter++; } else chctx->bandWidthT[i] = band_tab[i + 1] - band_tab[i]; } @@ -1013,15 +1013,14 @@ static int imc_decode_block(AVCodecContext *avctx, IMCContext *q, int ch) memset(chctx->skipFlags, 0, sizeof(chctx->skipFlags)); - imc_imdct256(q, chctx, avctx->channels); + imc_imdct256(q, chctx, avctx->ch_layout.nb_channels); return 0; } -static int imc_decode_frame(AVCodecContext *avctx, void *data, +static int imc_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; int ret, i; @@ -1032,7 +1031,7 @@ static int imc_decode_frame(AVCodecContext *avctx, void *data, q->avctx = avctx; - if (buf_size < IMC_BLOCK_SIZE * avctx->channels) { + if (buf_size < IMC_BLOCK_SIZE * avctx->ch_layout.nb_channels) { av_log(avctx, AV_LOG_ERROR, "frame too small!\n"); return AVERROR_INVALIDDATA; } @@ -1042,7 +1041,7 @@ static int imc_decode_frame(AVCodecContext *avctx, void *data, if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; - for (i = 0; i < avctx->channels; i++) { + for (i = 0; i < avctx->ch_layout.nb_channels; i++) { q->out_samples = (float *)frame->extended_data[i]; q->bdsp.bswap16_buf(buf16, (const uint16_t *) buf, IMC_BLOCK_SIZE / 2); @@ -1055,14 +1054,14 @@ static int imc_decode_frame(AVCodecContext *avctx, void *data, return ret; } - if (avctx->channels == 2) { + if (avctx->ch_layout.nb_channels == 2) { q->butterflies_float((float *)frame->extended_data[0], (float *)frame->extended_data[1], COEFFS); } *got_frame_ptr = 1; - return IMC_BLOCK_SIZE * avctx->channels; + return IMC_BLOCK_SIZE * avctx->ch_layout.nb_channels; } static av_cold int imc_decode_close(AVCodecContext * avctx) @@ -1083,35 +1082,35 @@ static av_cold void flush(AVCodecContext *avctx) } #if CONFIG_IMC_DECODER -const AVCodec ff_imc_decoder = { - .name = "imc", - .long_name = NULL_IF_CONFIG_SMALL("IMC (Intel Music Coder)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_IMC, +const FFCodec ff_imc_decoder = { + .p.name = "imc", + .p.long_name = NULL_IF_CONFIG_SMALL("IMC (Intel Music Coder)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_IMC, .priv_data_size = sizeof(IMCContext), .init = imc_decode_init, .close = imc_decode_close, - .decode = imc_decode_frame, + FF_CODEC_DECODE_CB(imc_decode_frame), .flush = flush, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_IAC_DECODER -const AVCodec ff_iac_decoder = { - .name = "iac", - .long_name = NULL_IF_CONFIG_SMALL("IAC (Indeo Audio Coder)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_IAC, +const FFCodec ff_iac_decoder = { + .p.name = "iac", + .p.long_name = NULL_IF_CONFIG_SMALL("IAC (Indeo Audio Coder)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_IAC, .priv_data_size = sizeof(IMCContext), .init = imc_decode_init, .close = imc_decode_close, - .decode = imc_decode_frame, + FF_CODEC_DECODE_CB(imc_decode_frame), .flush = flush, - .capabilities = AV_CODEC_CAP_DR1, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + .p.capabilities = AV_CODEC_CAP_DR1, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/imm4.c b/libavcodec/imm4.c index a47c1e1ed..d82681886 100644 --- a/libavcodec/imm4.c +++ b/libavcodec/imm4.c @@ -29,6 +29,7 @@ #include "avcodec.h" #include "bswapdsp.h" +#include "codec_internal.h" #include "copy_block.h" #include "get_bits.h" #include "idctdsp.h" @@ -352,12 +353,11 @@ static int decode_inter(AVCodecContext *avctx, GetBitContext *gb, return 0; } -static int decode_frame(AVCodecContext *avctx, void *data, +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt) { IMM4Context *s = avctx->priv_data; GetBitContext *gb = &s->gb; - AVFrame *frame = data; int width, height; unsigned type; int ret, scaled; @@ -532,17 +532,17 @@ static av_cold int decode_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_imm4_decoder = { - .name = "imm4", - .long_name = NULL_IF_CONFIG_SMALL("Infinity IMM4"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_IMM4, +const FFCodec ff_imm4_decoder = { + .p.name = "imm4", + .p.long_name = NULL_IF_CONFIG_SMALL("Infinity IMM4"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_IMM4, .priv_data_size = sizeof(IMM4Context), .init = decode_init, .close = decode_close, - .decode = decode_frame, + FF_CODEC_DECODE_CB(decode_frame), .flush = decode_flush, - .capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/imm5.c b/libavcodec/imm5.c index cb8a619a4..9b7ac17aa 100644 --- a/libavcodec/imm5.c +++ b/libavcodec/imm5.c @@ -21,7 +21,7 @@ #include "libavutil/intreadwrite.h" #include "avcodec.h" -#include "internal.h" +#include "codec_internal.h" typedef struct IMM5Context { AVCodecContext *h264_avctx; // wrapper context for H264 @@ -83,11 +83,10 @@ static av_cold int imm5_init(AVCodecContext *avctx) return 0; } -static int imm5_decode_frame(AVCodecContext *avctx, void *data, +static int imm5_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt) { IMM5Context *ctx = avctx->priv_data; - AVFrame *frame = data; AVCodecContext *codec_avctx = ctx->h264_avctx; int ret; @@ -178,13 +177,13 @@ static av_cold int imm5_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_imm5_decoder = { - .name = "imm5", - .long_name = NULL_IF_CONFIG_SMALL("Infinity IMM5"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_IMM5, +const FFCodec ff_imm5_decoder = { + .p.name = "imm5", + .p.long_name = NULL_IF_CONFIG_SMALL("Infinity IMM5"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_IMM5, .init = imm5_init, - .decode = imm5_decode_frame, + FF_CODEC_DECODE_CB(imm5_decode_frame), .close = imm5_close, .flush = imm5_flush, .priv_data_size = sizeof(IMM5Context), diff --git a/libavcodec/imx.c b/libavcodec/imx.c index d81a0de7b..4ee600686 100644 --- a/libavcodec/imx.c +++ b/libavcodec/imx.c @@ -21,6 +21,7 @@ #include "libavutil/common.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "decode.h" #include "internal.h" @@ -46,7 +47,7 @@ static av_cold int imx_decode_init(AVCodecContext *avctx) return 0; } -static int imx_decode_frame(AVCodecContext *avctx, void *data, +static int imx_decode_frame(AVCodecContext *avctx, AVFrame *rframe, int *got_frame, AVPacket *avpkt) { SimbiosisIMXContext *imx = avctx->priv_data; @@ -152,7 +153,7 @@ static int imx_decode_frame(AVCodecContext *avctx, void *data, frame->pict_type = frame->key_frame ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; - if ((ret = av_frame_ref(data, frame)) < 0) + if ((ret = av_frame_ref(rframe, frame)) < 0) return ret; *got_frame = 1; @@ -179,17 +180,17 @@ static int imx_decode_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_simbiosis_imx_decoder = { - .name = "simbiosis_imx", - .long_name = NULL_IF_CONFIG_SMALL("Simbiosis Interactive IMX Video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_SIMBIOSIS_IMX, +const FFCodec ff_simbiosis_imx_decoder = { + .p.name = "simbiosis_imx", + .p.long_name = NULL_IF_CONFIG_SMALL("Simbiosis Interactive IMX Video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_SIMBIOSIS_IMX, .priv_data_size = sizeof(SimbiosisIMXContext), .init = imx_decode_init, - .decode = imx_decode_frame, + FF_CODEC_DECODE_CB(imx_decode_frame), .close = imx_decode_close, .flush = imx_decode_flush, - .capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/imx_dump_header_bsf.c b/libavcodec/imx_dump_header_bsf.c index e2b6a1559..241415a0e 100644 --- a/libavcodec/imx_dump_header_bsf.c +++ b/libavcodec/imx_dump_header_bsf.c @@ -69,8 +69,8 @@ static const enum AVCodecID codec_ids[] = { AV_CODEC_ID_MPEG2VIDEO, AV_CODEC_ID_NONE, }; -const AVBitStreamFilter ff_imx_dump_header_bsf = { - .name = "imxdump", - .filter = imx_dump_header, - .codec_ids = codec_ids, +const FFBitStreamFilter ff_imx_dump_header_bsf = { + .p.name = "imxdump", + .p.codec_ids = codec_ids, + .filter = imx_dump_header, }; diff --git a/libavcodec/indeo2.c b/libavcodec/indeo2.c index 02fc7fefa..79028975e 100644 --- a/libavcodec/indeo2.c +++ b/libavcodec/indeo2.c @@ -29,6 +29,7 @@ #define BITSTREAM_READER_LE #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" #include "indeo2data.h" #include "internal.h" @@ -150,14 +151,12 @@ static int ir2_decode_plane_inter(Ir2Context *ctx, int width, int height, uint8_ return 0; } -static int ir2_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int ir2_decode_frame(AVCodecContext *avctx, AVFrame *picture, + int *got_frame, AVPacket *avpkt) { Ir2Context * const s = avctx->priv_data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; - AVFrame *picture = data; AVFrame * const p = s->picture; int start, ret; int ltab, ctab; @@ -260,15 +259,15 @@ static av_cold int ir2_decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_indeo2_decoder = { - .name = "indeo2", - .long_name = NULL_IF_CONFIG_SMALL("Intel Indeo 2"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_INDEO2, +const FFCodec ff_indeo2_decoder = { + .p.name = "indeo2", + .p.long_name = NULL_IF_CONFIG_SMALL("Intel Indeo 2"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_INDEO2, .priv_data_size = sizeof(Ir2Context), .init = ir2_decode_init, .close = ir2_decode_end, - .decode = ir2_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(ir2_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/indeo3.c b/libavcodec/indeo3.c index 326b3141e..43669f46b 100644 --- a/libavcodec/indeo3.c +++ b/libavcodec/indeo3.c @@ -33,6 +33,7 @@ #include "libavutil/intreadwrite.h" #include "libavutil/thread.h" #include "avcodec.h" +#include "codec_internal.h" #include "copy_block.h" #include "bytestream.h" #include "get_bits.h" @@ -1064,13 +1065,12 @@ static av_cold int decode_init(AVCodecContext *avctx) } -static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { Indeo3DecodeContext *ctx = avctx->priv_data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; - AVFrame *frame = data; int res; res = decode_frame_headers(ctx, avctx, buf, buf_size); @@ -1133,15 +1133,15 @@ static av_cold int decode_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_indeo3_decoder = { - .name = "indeo3", - .long_name = NULL_IF_CONFIG_SMALL("Intel Indeo 3"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_INDEO3, +const FFCodec ff_indeo3_decoder = { + .p.name = "indeo3", + .p.long_name = NULL_IF_CONFIG_SMALL("Intel Indeo 3"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_INDEO3, .priv_data_size = sizeof(Indeo3DecodeContext), .init = decode_init, .close = decode_close, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/indeo4.c b/libavcodec/indeo4.c index 3d3579d76..f0cdff0e2 100644 --- a/libavcodec/indeo4.c +++ b/libavcodec/indeo4.c @@ -29,10 +29,10 @@ #define BITSTREAM_READER_LE #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" #include "libavutil/imgutils.h" #include "indeo4data.h" -#include "internal.h" #include "ivi.h" #include "ivi_dsp.h" @@ -703,15 +703,15 @@ static av_cold int decode_init(AVCodecContext *avctx) } -const AVCodec ff_indeo4_decoder = { - .name = "indeo4", - .long_name = NULL_IF_CONFIG_SMALL("Intel Indeo Video Interactive 4"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_INDEO4, +const FFCodec ff_indeo4_decoder = { + .p.name = "indeo4", + .p.long_name = NULL_IF_CONFIG_SMALL("Intel Indeo Video Interactive 4"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_INDEO4, .priv_data_size = sizeof(IVI45DecContext), .init = decode_init, .close = ff_ivi_decode_close, - .decode = ff_ivi_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(ff_ivi_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/indeo5.c b/libavcodec/indeo5.c index fbf0c004d..aff110221 100644 --- a/libavcodec/indeo5.c +++ b/libavcodec/indeo5.c @@ -29,8 +29,8 @@ #define BITSTREAM_READER_LE #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" -#include "internal.h" #include "ivi.h" #include "ivi_dsp.h" #include "indeo5data.h" @@ -683,15 +683,15 @@ static av_cold int decode_init(AVCodecContext *avctx) return 0; } -const AVCodec ff_indeo5_decoder = { - .name = "indeo5", - .long_name = NULL_IF_CONFIG_SMALL("Intel Indeo Video Interactive 5"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_INDEO5, +const FFCodec ff_indeo5_decoder = { + .p.name = "indeo5", + .p.long_name = NULL_IF_CONFIG_SMALL("Intel Indeo Video Interactive 5"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_INDEO5, .priv_data_size = sizeof(IVI45DecContext), .init = decode_init, .close = ff_ivi_decode_close, - .decode = ff_ivi_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(ff_ivi_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/intelh263dec.c b/libavcodec/intelh263dec.c index 7c794dc5e..ded0a7f61 100644 --- a/libavcodec/intelh263dec.c +++ b/libavcodec/intelh263dec.c @@ -18,9 +18,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "codec_internal.h" #include "mpegutils.h" #include "mpegvideo.h" -#include "h263.h" +#include "mpegvideodec.h" +#include "h263data.h" +#include "h263dec.h" #include "mpegvideodata.h" /* don't understand why they choose a different header ! */ @@ -66,7 +69,6 @@ int ff_intel_h263_decode_picture_header(MpegEncContext *s) return -1; /* SAC: off */ } s->obmc= get_bits1(&s->gb); - s->unrestricted_mv = s->obmc || s->h263_long_vectors; s->pb_frame = get_bits1(&s->gb); if (format < 6) { @@ -128,18 +130,19 @@ int ff_intel_h263_decode_picture_header(MpegEncContext *s) return 0; } -const AVCodec ff_h263i_decoder = { - .name = "h263i", - .long_name = NULL_IF_CONFIG_SMALL("Intel H.263"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_H263I, +const FFCodec ff_h263i_decoder = { + .p.name = "h263i", + .p.long_name = NULL_IF_CONFIG_SMALL("Intel H.263"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_H263I, .priv_data_size = sizeof(MpegEncContext), .init = ff_h263_decode_init, .close = ff_h263_decode_end, - .decode = ff_h263_decode_frame, - .capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1, - .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, - .pix_fmts = (const enum AVPixelFormat[]) { + FF_CODEC_DECODE_CB(ff_h263_decode_frame), + .p.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, diff --git a/libavcodec/internal.h b/libavcodec/internal.h index 72ca1553f..17e1de812 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -28,80 +28,13 @@ #include "libavutil/buffer.h" #include "libavutil/channel_layout.h" -#include "libavutil/fifo.h" #include "libavutil/mathematics.h" #include "libavutil/pixfmt.h" #include "avcodec.h" -#include "bsf.h" #include "config.h" -/** - * The codec does not modify any global variables in the init function, - * allowing to call the init function without locking any global mutexes. - */ -#define FF_CODEC_CAP_INIT_THREADSAFE (1 << 0) -/** - * The codec allows calling the close function for deallocation even if - * the init function returned a failure. Without this capability flag, a - * codec does such cleanup internally when returning failures from the - * init function and does not expect the close function to be called at - * all. - */ -#define FF_CODEC_CAP_INIT_CLEANUP (1 << 1) -/** - * Decoders marked with FF_CODEC_CAP_SETS_PKT_DTS want to set - * AVFrame.pkt_dts manually. If the flag is set, decode.c won't overwrite - * this field. If it's unset, decode.c tries to guess the pkt_dts field - * from the input AVPacket. - */ -#define FF_CODEC_CAP_SETS_PKT_DTS (1 << 2) -/** - * The decoder extracts and fills its parameters even if the frame is - * skipped due to the skip_frame setting. - */ -#define FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM (1 << 3) -/** - * The decoder sets the cropping fields in the output frames manually. - * If this cap is set, the generic code will initialize output frame - * dimensions to coded rather than display values. - */ -#define FF_CODEC_CAP_EXPORTS_CROPPING (1 << 4) -/** - * Codec initializes slice-based threading with a main function - */ -#define FF_CODEC_CAP_SLICE_THREAD_HAS_MF (1 << 5) -/* - * The codec supports frame threading and has inter-frame dependencies, so it - * uses ff_thread_report/await_progress(). - */ -#define FF_CODEC_CAP_ALLOCATE_PROGRESS (1 << 6) -/** - * Codec handles avctx->thread_count == 0 (auto) internally. - */ -#define FF_CODEC_CAP_AUTO_THREADS (1 << 7) -/** - * Codec handles output frame properties internally instead of letting the - * internal logic derive them from AVCodecInternal.last_pkt_props. - */ -#define FF_CODEC_CAP_SETS_FRAME_PROPS (1 << 8) - -/** - * AVCodec.codec_tags termination value - */ -#define FF_CODEC_TAGS_END -1 - - -#define FF_DEFAULT_QUANT_BIAS 999999 - -#define FF_QSCALE_TYPE_MPEG1 0 -#define FF_QSCALE_TYPE_MPEG2 1 -#define FF_QSCALE_TYPE_H264 2 -#define FF_QSCALE_TYPE_VP56 3 - #define FF_SANE_NB_CHANNELS 512U -#define FF_SIGNBIT(x) ((x) >> CHAR_BIT * sizeof(x) - 1) - #if HAVE_SIMD_ALIGN_64 # define STRIDE_ALIGN 64 /* AVX-512 */ #elif HAVE_SIMD_ALIGN_32 @@ -112,10 +45,6 @@ # define STRIDE_ALIGN 8 #endif -typedef struct EncodeSimpleContext { - AVFrame *in_frame; -} EncodeSimpleContext; - typedef struct AVCodecInternal { /** * When using frame-threaded decoding, this field is set for the first @@ -142,14 +71,14 @@ typedef struct AVCodecInternal { * avcodec_flush_buffers(). */ AVPacket *in_pkt; - AVBSFContext *bsf; + struct AVBSFContext *bsf; /** * Properties (timestamps+side data) extracted from the last packet passed * for decoding. */ AVPacket *last_pkt_props; - AVFifoBuffer *pkt_props; + struct AVFifo *pkt_props; /** * temporary buffer used for encoders to store their bitstream @@ -166,10 +95,16 @@ typedef struct AVCodecInternal { void *frame_thread_encoder; - EncodeSimpleContext es; + /** + * The input frame is stored here for encoders implementing the simple + * encode API. + * + * Not allocated in other cases. + */ + AVFrame *in_frame; /** - * If this is set, then AVCodec->close (if existing) needs to be called + * If this is set, then FFCodec->close (if existing) needs to be called * for the parent AVCodecContext. */ int needs_close; @@ -208,17 +143,13 @@ typedef struct AVCodecInternal { int initial_format; int initial_width, initial_height; int initial_sample_rate; +#if FF_API_OLD_CHANNEL_LAYOUT int initial_channels; uint64_t initial_channel_layout; +#endif + AVChannelLayout initial_ch_layout; } AVCodecInternal; -struct AVCodecDefault { - const uint8_t *key; - const uint8_t *value; -}; - -extern const uint8_t ff_log2_run[41]; - /** * Return the index into tab at which {a,b} match elements {[0],[1]} of tab. * If there is no such matching pair then size is returned. @@ -285,10 +216,6 @@ int ff_thread_can_start_frame(AVCodecContext *avctx); int avpriv_h264_has_num_reorder_frames(AVCodecContext *avctx); -const uint8_t *avpriv_find_start_code(const uint8_t *p, - const uint8_t *end, - uint32_t *state); - int avpriv_codec_get_cap_skip_frame_fill_param(const AVCodec *codec); /** diff --git a/libavcodec/interplayacm.c b/libavcodec/interplayacm.c index c11178a9e..3c482e4c8 100644 --- a/libavcodec/interplayacm.c +++ b/libavcodec/interplayacm.c @@ -23,6 +23,7 @@ #define BITSTREAM_READER_LE #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" @@ -79,12 +80,12 @@ static av_cold int decode_init(AVCodecContext *avctx) if (avctx->extradata_size < 14) return AVERROR_INVALIDDATA; - if (avctx->channels <= 0) { - av_log(avctx, AV_LOG_ERROR, "Invalid number of channels: %d\n", avctx->channels); + if (avctx->ch_layout.nb_channels <= 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid number of channels: %d\n", avctx->ch_layout.nb_channels); return AVERROR_INVALIDDATA; } - s->max_samples = AV_RL32(avctx->extradata + 4) / avctx->channels; + s->max_samples = AV_RL32(avctx->extradata + 4) / avctx->ch_layout.nb_channels; if (s->max_samples == 0) s->max_samples = UINT64_MAX; s->level = AV_RL16(avctx->extradata + 12) & 0xf; @@ -551,12 +552,11 @@ static int decode_block(InterplayACMContext *s) return 0; } -static int decode_frame(AVCodecContext *avctx, void *data, +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *pkt) { InterplayACMContext *s = avctx->priv_data; GetBitContext *gb = &s->gb; - AVFrame *frame = data; const uint8_t *buf; int16_t *samples; int ret, n, buf_size, input_buf_size; @@ -585,7 +585,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, if ((ret = init_get_bits8(gb, buf, buf_size)) < 0) return ret; - frame->nb_samples = FFMIN(s->block_len / avctx->channels, s->max_samples); + frame->nb_samples = FFMIN(s->block_len / avctx->ch_layout.nb_channels, s->max_samples); s->max_samples -= FFMIN(frame->nb_samples, s->max_samples); if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; @@ -596,7 +596,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, return ret; samples = (int16_t *)frame->data[0]; - for (n = 0; n < frame->nb_samples * avctx->channels; n++) { + for (n = 0; n < frame->nb_samples * avctx->ch_layout.nb_channels; n++) { int val = s->block[n] >> s->level; *samples++ = val; } @@ -632,15 +632,15 @@ static av_cold int decode_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_interplay_acm_decoder = { - .name = "interplayacm", - .long_name = NULL_IF_CONFIG_SMALL("Interplay ACM"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_INTERPLAY_ACM, +const FFCodec ff_interplay_acm_decoder = { + .p.name = "interplayacm", + .p.long_name = NULL_IF_CONFIG_SMALL("Interplay ACM"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_INTERPLAY_ACM, .init = decode_init, .close = decode_close, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .priv_data_size = sizeof(InterplayACMContext), }; diff --git a/libavcodec/interplayvideo.c b/libavcodec/interplayvideo.c index 6da7538b3..fe2a9e1e6 100644 --- a/libavcodec/interplayvideo.c +++ b/libavcodec/interplayvideo.c @@ -43,6 +43,7 @@ #define BITSTREAM_READER_LE #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "decode.h" #include "get_bits.h" #include "hpeldsp.h" @@ -1188,14 +1189,12 @@ static av_cold int ipvideo_decode_init(AVCodecContext *avctx) return 0; } -static int ipvideo_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int ipvideo_decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; IpvideoContext *s = avctx->priv_data; - AVFrame *frame = data; int ret; int send_buffer; int frame_format; @@ -1357,15 +1356,15 @@ static av_cold int ipvideo_decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_interplay_video_decoder = { - .name = "interplayvideo", - .long_name = NULL_IF_CONFIG_SMALL("Interplay MVE video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_INTERPLAY_VIDEO, +const FFCodec ff_interplay_video_decoder = { + .p.name = "interplayvideo", + .p.long_name = NULL_IF_CONFIG_SMALL("Interplay MVE video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_INTERPLAY_VIDEO, .priv_data_size = sizeof(IpvideoContext), .init = ipvideo_decode_init, .close = ipvideo_decode_end, - .decode = ipvideo_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_PARAM_CHANGE, + FF_CODEC_DECODE_CB(ipvideo_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_PARAM_CHANGE, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/intrax8.c b/libavcodec/intrax8.c index 0bd0db29c..73b8aeea7 100644 --- a/libavcodec/intrax8.c +++ b/libavcodec/intrax8.c @@ -52,7 +52,7 @@ static VLC j_orient_vlc[2][4]; // [quant], [select] static av_cold void x8_init_vlc(VLC *vlc, int nb_bits, int nb_codes, int *offset, const uint8_t table[][2]) { - static VLC_TYPE vlc_buf[VLC_BUFFER_SIZE][2]; + static VLCElem vlc_buf[VLC_BUFFER_SIZE]; vlc->table = &vlc_buf[*offset]; vlc->table_allocated = VLC_BUFFER_SIZE - *offset; diff --git a/libavcodec/ituh263dec.c b/libavcodec/ituh263dec.c index 3f982f414..af054360d 100644 --- a/libavcodec/ituh263dec.c +++ b/libavcodec/ituh263dec.c @@ -28,25 +28,28 @@ */ #define UNCHECKED_BITSTREAM_READER 1 -#include + +#include "config_components.h" #include "libavutil/attributes.h" #include "libavutil/imgutils.h" #include "libavutil/internal.h" #include "libavutil/mathematics.h" #include "libavutil/mem_internal.h" +#include "libavutil/thread.h" #include "avcodec.h" #include "mpegvideo.h" #include "h263.h" #include "h263data.h" -#include "internal.h" +#include "h263dec.h" #include "mathops.h" #include "mpegutils.h" #include "unary.h" -#include "flv.h" -#include "rv10.h" +#include "rv10dec.h" #include "mpeg4video.h" #include "mpegvideodata.h" +#include "mpegvideodec.h" +#include "mpeg4videodec.h" // The defines below define the number of bits that are read at once for // reading vlc values. Changing these may improve speed and data cache needs @@ -104,35 +107,35 @@ static VLC cbpc_b_vlc; /* init vlcs */ -/* XXX: find a better solution to handle static init */ +static av_cold void h263_decode_init_vlc(void) +{ + INIT_VLC_STATIC(&ff_h263_intra_MCBPC_vlc, INTRA_MCBPC_VLC_BITS, 9, + ff_h263_intra_MCBPC_bits, 1, 1, + ff_h263_intra_MCBPC_code, 1, 1, 72); + INIT_VLC_STATIC(&ff_h263_inter_MCBPC_vlc, INTER_MCBPC_VLC_BITS, 28, + ff_h263_inter_MCBPC_bits, 1, 1, + ff_h263_inter_MCBPC_code, 1, 1, 198); + INIT_VLC_STATIC(&ff_h263_cbpy_vlc, CBPY_VLC_BITS, 16, + &ff_h263_cbpy_tab[0][1], 2, 1, + &ff_h263_cbpy_tab[0][0], 2, 1, 64); + INIT_VLC_STATIC(&ff_h263_mv_vlc, H263_MV_VLC_BITS, 33, + &ff_mvtab[0][1], 2, 1, + &ff_mvtab[0][0], 2, 1, 538); + ff_h263_init_rl_inter(); + INIT_VLC_RL(ff_h263_rl_inter, 554); + INIT_FIRST_VLC_RL(ff_rl_intra_aic, 554); + INIT_VLC_STATIC(&h263_mbtype_b_vlc, H263_MBTYPE_B_VLC_BITS, 15, + &ff_h263_mbtype_b_tab[0][1], 2, 1, + &ff_h263_mbtype_b_tab[0][0], 2, 1, 80); + INIT_VLC_STATIC(&cbpc_b_vlc, CBPC_B_VLC_BITS, 4, + &ff_cbpc_b_tab[0][1], 2, 1, + &ff_cbpc_b_tab[0][0], 2, 1, 8); +} + av_cold void ff_h263_decode_init_vlc(void) { - static volatile int done = 0; - - if (!done) { - INIT_VLC_STATIC(&ff_h263_intra_MCBPC_vlc, INTRA_MCBPC_VLC_BITS, 9, - ff_h263_intra_MCBPC_bits, 1, 1, - ff_h263_intra_MCBPC_code, 1, 1, 72); - INIT_VLC_STATIC(&ff_h263_inter_MCBPC_vlc, INTER_MCBPC_VLC_BITS, 28, - ff_h263_inter_MCBPC_bits, 1, 1, - ff_h263_inter_MCBPC_code, 1, 1, 198); - INIT_VLC_STATIC(&ff_h263_cbpy_vlc, CBPY_VLC_BITS, 16, - &ff_h263_cbpy_tab[0][1], 2, 1, - &ff_h263_cbpy_tab[0][0], 2, 1, 64); - INIT_VLC_STATIC(&ff_h263_mv_vlc, H263_MV_VLC_BITS, 33, - &ff_mvtab[0][1], 2, 1, - &ff_mvtab[0][0], 2, 1, 538); - ff_h263_init_rl_inter(); - INIT_VLC_RL(ff_h263_rl_inter, 554); - INIT_FIRST_VLC_RL(ff_rl_intra_aic, 554); - INIT_VLC_STATIC(&h263_mbtype_b_vlc, H263_MBTYPE_B_VLC_BITS, 15, - &ff_h263_mbtype_b_tab[0][1], 2, 1, - &ff_h263_mbtype_b_tab[0][0], 2, 1, 80); - INIT_VLC_STATIC(&cbpc_b_vlc, CBPC_B_VLC_BITS, 4, - &ff_cbpc_b_tab[0][1], 2, 1, - &ff_cbpc_b_tab[0][0], 2, 1, 8); - done = 1; - } + static AVOnce init_static_once = AV_ONCE_INIT; + ff_thread_once(&init_static_once, h263_decode_init_vlc); } int ff_h263_decode_mba(MpegEncContext *s) @@ -439,6 +442,93 @@ static void h263_decode_dquant(MpegEncContext *s){ ff_set_qscale(s, s->qscale); } +static void h263_pred_acdc(MpegEncContext * s, int16_t *block, int n) +{ + int x, y, wrap, a, c, pred_dc, scale; + int16_t *dc_val, *ac_val, *ac_val1; + + /* find prediction */ + if (n < 4) { + x = 2 * s->mb_x + (n & 1); + y = 2 * s->mb_y + (n>> 1); + wrap = s->b8_stride; + dc_val = s->dc_val[0]; + ac_val = s->ac_val[0][0]; + scale = s->y_dc_scale; + } else { + x = s->mb_x; + y = s->mb_y; + wrap = s->mb_stride; + dc_val = s->dc_val[n - 4 + 1]; + ac_val = s->ac_val[n - 4 + 1][0]; + scale = s->c_dc_scale; + } + + ac_val += ((y) * wrap + (x)) * 16; + ac_val1 = ac_val; + + /* B C + * A X + */ + a = dc_val[(x - 1) + (y) * wrap]; + c = dc_val[(x) + (y - 1) * wrap]; + + /* No prediction outside GOB boundary */ + if (s->first_slice_line && n != 3) { + if (n != 2) c= 1024; + if (n != 1 && s->mb_x == s->resync_mb_x) a= 1024; + } + + if (s->ac_pred) { + pred_dc = 1024; + if (s->h263_aic_dir) { + /* left prediction */ + if (a != 1024) { + ac_val -= 16; + for (int i = 1; i < 8; i++) { + block[s->idsp.idct_permutation[i << 3]] += ac_val[i]; + } + pred_dc = a; + } + } else { + /* top prediction */ + if (c != 1024) { + ac_val -= 16 * wrap; + for (int i = 1; i < 8; i++) { + block[s->idsp.idct_permutation[i]] += ac_val[i + 8]; + } + pred_dc = c; + } + } + } else { + /* just DC prediction */ + if (a != 1024 && c != 1024) + pred_dc = (a + c) >> 1; + else if (a != 1024) + pred_dc = a; + else + pred_dc = c; + } + + /* we assume pred is positive */ + block[0] = block[0] * scale + pred_dc; + + if (block[0] < 0) + block[0] = 0; + else + block[0] |= 1; + + /* Update AC/DC tables */ + dc_val[(x) + (y) * wrap] = block[0]; + + /* left copy */ + for (int i = 1; i < 8; i++) + ac_val1[i] = block[s->idsp.idct_permutation[i << 3]]; + /* top copy */ + for (int i = 1; i < 8; i++) + ac_val1[8 + i] = block[s->idsp.idct_permutation[i]]; +} + static int h263_decode_block(MpegEncContext * s, int16_t * block, int n, int coded) { @@ -579,7 +669,7 @@ retry: } not_coded: if (s->mb_intra && s->h263_aic) { - ff_h263_pred_acdc(s, block, n); + h263_pred_acdc(s, block, n); i = 63; } s->block_last_index[n] = i; @@ -1063,7 +1153,6 @@ int ff_h263_decode_picture_header(MpegEncContext *s) return -1; /* SAC: off */ } s->obmc= get_bits1(&s->gb); /* Advanced prediction mode */ - s->unrestricted_mv = s->h263_long_vectors || s->obmc; s->pb_frame = get_bits1(&s->gb); s->chroma_qscale= s->qscale = get_bits(&s->gb, 5); @@ -1093,7 +1182,6 @@ int ff_h263_decode_picture_header(MpegEncContext *s) s->obmc= get_bits1(&s->gb); /* Advanced prediction mode */ s->h263_aic = get_bits1(&s->gb); /* Advanced Intra Coding (AIC) */ s->loop_filter= get_bits1(&s->gb); - s->unrestricted_mv = s->umvplus || s->obmc || s->loop_filter; if(s->avctx->lowres) s->loop_filter = 0; @@ -1136,8 +1224,8 @@ int ff_h263_decode_picture_header(MpegEncContext *s) if (ufep) { if (format == 6) { /* Custom Picture Format (CPFMT) */ - s->aspect_ratio_info = get_bits(&s->gb, 4); - ff_dlog(s->avctx, "aspect: %d\n", s->aspect_ratio_info); + int aspect_ratio_info = get_bits(&s->gb, 4); + ff_dlog(s->avctx, "aspect: %d\n", aspect_ratio_info); /* aspect ratios: 0 - forbidden 1 - 1:1 @@ -1151,12 +1239,12 @@ int ff_h263_decode_picture_header(MpegEncContext *s) check_marker(s->avctx, &s->gb, "in dimensions"); height = get_bits(&s->gb, 9) * 4; ff_dlog(s->avctx, "\nH.263+ Custom picture: %dx%d\n",width,height); - if (s->aspect_ratio_info == FF_ASPECT_EXTENDED) { + if (aspect_ratio_info == FF_ASPECT_EXTENDED) { /* expected dimensions */ s->avctx->sample_aspect_ratio.num= get_bits(&s->gb, 8); s->avctx->sample_aspect_ratio.den= get_bits(&s->gb, 8); }else{ - s->avctx->sample_aspect_ratio= ff_h263_pixel_aspect[s->aspect_ratio_info]; + s->avctx->sample_aspect_ratio= ff_h263_pixel_aspect[aspect_ratio_info]; } } else { width = ff_h263_format[format][0]; diff --git a/libavcodec/ituh263enc.c b/libavcodec/ituh263enc.c index 79c8c9999..2fcd001db 100644 --- a/libavcodec/ituh263enc.c +++ b/libavcodec/ituh263enc.c @@ -27,19 +27,23 @@ * H.263 bitstream encoder. */ +#include "config_components.h" + #include #include "libavutil/attributes.h" #include "libavutil/thread.h" #include "avcodec.h" +#include "codec_internal.h" #include "mpegvideo.h" #include "mpegvideodata.h" +#include "flvenc.h" +#include "mpegvideoenc.h" #include "h263.h" +#include "h263enc.h" #include "h263data.h" #include "mathops.h" #include "mpegutils.h" -#include "flv.h" -#include "mpeg4video.h" #include "internal.h" /** @@ -107,6 +111,7 @@ void ff_h263_encode_picture_header(MpegEncContext * s, int picture_number) int best_clock_code=1; int best_divisor=60; int best_error= INT_MAX; + int custom_pcf; if(s->h263_plus){ for(i=0; i<2; i++){ @@ -121,7 +126,7 @@ void ff_h263_encode_picture_header(MpegEncContext * s, int picture_number) } } } - s->custom_pcf= best_clock_code!=1 || best_divisor!=60; + custom_pcf = best_clock_code != 1 || best_divisor != 60; coded_frame_rate= 1800000; coded_frame_rate_base= (1000+best_clock_code)*best_divisor; @@ -166,7 +171,7 @@ void ff_h263_encode_picture_header(MpegEncContext * s, int picture_number) else put_bits(&s->pb, 3, format); - put_bits(&s->pb,1, s->custom_pcf); + put_bits(&s->pb,1, custom_pcf); put_bits(&s->pb,1, s->umvplus); /* Unrestricted Motion Vector */ put_bits(&s->pb,1,0); /* SAC: off */ put_bits(&s->pb,1,s->obmc); /* Advanced Prediction Mode */ @@ -193,18 +198,18 @@ void ff_h263_encode_picture_header(MpegEncContext * s, int picture_number) if (format == 8) { /* Custom Picture Format (CPFMT) */ - s->aspect_ratio_info= ff_h263_aspect_to_info(s->avctx->sample_aspect_ratio); + unsigned aspect_ratio_info = ff_h263_aspect_to_info(s->avctx->sample_aspect_ratio); - put_bits(&s->pb,4,s->aspect_ratio_info); + put_bits(&s->pb,4, aspect_ratio_info); put_bits(&s->pb,9,(s->width >> 2) - 1); put_bits(&s->pb,1,1); /* "1" to prevent start code emulation */ put_bits(&s->pb,9,(s->height >> 2)); - if (s->aspect_ratio_info == FF_ASPECT_EXTENDED){ + if (aspect_ratio_info == FF_ASPECT_EXTENDED){ put_bits(&s->pb, 8, s->avctx->sample_aspect_ratio.num); put_bits(&s->pb, 8, s->avctx->sample_aspect_ratio.den); } } - if(s->custom_pcf){ + if (custom_pcf) { if(ufep){ put_bits(&s->pb, 1, best_clock_code); put_bits(&s->pb, 7, best_divisor); @@ -445,6 +450,47 @@ static void h263p_encode_umotion(PutBitContext *pb, int val) } } +static int h263_pred_dc(MpegEncContext * s, int n, int16_t **dc_val_ptr) +{ + int x, y, wrap, a, c, pred_dc; + int16_t *dc_val; + + /* find prediction */ + if (n < 4) { + x = 2 * s->mb_x + (n & 1); + y = 2 * s->mb_y + ((n & 2) >> 1); + wrap = s->b8_stride; + dc_val = s->dc_val[0]; + } else { + x = s->mb_x; + y = s->mb_y; + wrap = s->mb_stride; + dc_val = s->dc_val[n - 4 + 1]; + } + /* B C + * A X + */ + a = dc_val[(x - 1) + (y) * wrap]; + c = dc_val[(x) + (y - 1) * wrap]; + + /* No prediction outside GOB boundary */ + if (s->first_slice_line && n != 3) { + if (n != 2) c = 1024; + if (n != 1 && s->mb_x == s->resync_mb_x) a = 1024; + } + /* just DC prediction */ + if (a != 1024 && c != 1024) + pred_dc = (a + c) >> 1; + else if (a != 1024) + pred_dc = a; + else + pred_dc = c; + + /* we assume pred is positive */ + *dc_val_ptr = &dc_val[x + y * wrap]; + return pred_dc; +} + void ff_h263_encode_mb(MpegEncContext * s, int16_t block[6][64], int motion_x, int motion_y) @@ -552,7 +598,7 @@ void ff_h263_encode_mb(MpegEncContext * s, if(i<4) scale= s->y_dc_scale; else scale= s->c_dc_scale; - pred_dc = ff_h263_pred_dc(s, i, &dc_ptr[i]); + pred_dc = h263_pred_dc(s, i, &dc_ptr[i]); level -= pred_dc; /* Quant */ if (level >= 0) @@ -636,7 +682,6 @@ void ff_h263_encode_mb(MpegEncContext * s, if(interleaved_stats){ if (!s->mb_intra) { s->p_tex_bits+= get_bits_diff(s); - s->f_count++; }else{ s->i_tex_bits+= get_bits_diff(s); s->i_count++; @@ -833,3 +878,65 @@ void ff_h263_encode_mba(MpegEncContext *s) mb_pos= s->mb_x + s->mb_width*s->mb_y; put_bits(&s->pb, ff_mba_length[i], mb_pos); } + +#define OFFSET(x) offsetof(MpegEncContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption h263_options[] = { + { "obmc", "use overlapped block motion compensation.", OFFSET(obmc), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, + { "mb_info", "emit macroblock info for RFC 2190 packetization, the parameter value is the maximum payload size", OFFSET(mb_info), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, + FF_MPV_COMMON_OPTS + FF_MPV_COMMON_MOTION_EST_OPTS + { NULL }, +}; + +static const AVClass h263_class = { + .class_name = "H.263 encoder", + .item_name = av_default_item_name, + .option = h263_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +const FFCodec ff_h263_encoder = { + .p.name = "h263", + .p.long_name = NULL_IF_CONFIG_SMALL("H.263 / H.263-1996"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_H263, + .p.pix_fmts = (const enum AVPixelFormat[]){AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE}, + .p.priv_class = &h263_class, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, + .priv_data_size = sizeof(MpegEncContext), + .init = ff_mpv_encode_init, + FF_CODEC_ENCODE_CB(ff_mpv_encode_picture), + .close = ff_mpv_encode_end, +}; + +static const AVOption h263p_options[] = { + { "umv", "Use unlimited motion vectors.", OFFSET(umvplus), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, + { "aiv", "Use alternative inter VLC.", OFFSET(alt_inter_vlc), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, + { "obmc", "use overlapped block motion compensation.", OFFSET(obmc), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, + { "structured_slices", "Write slice start position at every GOB header instead of just GOB number.", OFFSET(h263_slice_structured), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE}, + FF_MPV_COMMON_OPTS + FF_MPV_COMMON_MOTION_EST_OPTS + { NULL }, +}; +static const AVClass h263p_class = { + .class_name = "H.263p encoder", + .item_name = av_default_item_name, + .option = h263p_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +const FFCodec ff_h263p_encoder = { + .p.name = "h263p", + .p.long_name = NULL_IF_CONFIG_SMALL("H.263+ / H.263-1998 / H.263 version 2"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_H263P, + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, + .p.priv_class = &h263p_class, + .p.capabilities = AV_CODEC_CAP_SLICE_THREADS, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, + .priv_data_size = sizeof(MpegEncContext), + .init = ff_mpv_encode_init, + FF_CODEC_ENCODE_CB(ff_mpv_encode_picture), + .close = ff_mpv_encode_end, +}; diff --git a/libavcodec/ivi.c b/libavcodec/ivi.c index 77979d04e..6577fa335 100644 --- a/libavcodec/ivi.c +++ b/libavcodec/ivi.c @@ -161,7 +161,7 @@ static int ivi_create_huff_from_desc(const IVIHuffDesc *cb, VLC *vlc, int flag) static av_cold void ivi_init_static_vlc(void) { int i; - static VLC_TYPE table_data[8192 * 16][2]; + static VLCElem table_data[8192 * 16]; for (i = 0; i < 8; i++) { ivi_mb_vlc_tabs[i].table = table_data + i * 2 * 8192; @@ -1065,12 +1065,11 @@ static int decode_band(IVI45DecContext *ctx, return result; } -int ff_ivi_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +int ff_ivi_decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { IVI45DecContext *ctx = avctx->priv_data; const uint8_t *buf = avpkt->data; - AVFrame *frame = data; int buf_size = avpkt->size; int result, p, b; @@ -1091,7 +1090,7 @@ int ff_ivi_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, if (ctx->is_indeo4 && ctx->frame_type == IVI4_FRAMETYPE_NULL_LAST) { if (ctx->got_p_frame) { - av_frame_move_ref(data, ctx->p_frame); + av_frame_move_ref(frame, ctx->p_frame); *got_frame = 1; ctx->got_p_frame = 0; } else { diff --git a/libavcodec/ivi.h b/libavcodec/ivi.h index 142753554..06cd4d95f 100644 --- a/libavcodec/ivi.h +++ b/libavcodec/ivi.h @@ -335,8 +335,8 @@ int ff_ivi_init_planes(AVCodecContext *avctx, IVIPlaneDesc *planes, */ int ff_ivi_init_tiles(IVIPlaneDesc *planes, int tile_width, int tile_height); -int ff_ivi_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt); +int ff_ivi_decode_frame(AVCodecContext *avctx, AVFrame *data, + int *got_frame, AVPacket *avpkt); int ff_ivi_decode_close(AVCodecContext *avctx); #endif /* AVCODEC_IVI_H */ diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c index c06752f43..ce77a6d96 100644 --- a/libavcodec/j2kenc.c +++ b/libavcodec/j2kenc.c @@ -66,10 +66,11 @@ #include #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "bytestream.h" #include "jpeg2000.h" +#include "version.h" #include "libavutil/common.h" #include "libavutil/pixdesc.h" #include "libavutil/opt.h" @@ -287,13 +288,11 @@ static void tag_tree_code(Jpeg2000EncoderContext *s, Jpeg2000TgtNode *node, int /** update the value in node */ static void tag_tree_update(Jpeg2000TgtNode *node) { - int lev = 0; while (node->parent){ if (node->parent->val <= node->val) break; node->parent->val = node->val; node = node->parent; - lev++; } } @@ -1831,16 +1830,16 @@ static const AVClass j2k_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_jpeg2000_encoder = { - .name = "jpeg2000", - .long_name = NULL_IF_CONFIG_SMALL("JPEG 2000"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_JPEG2000, +const FFCodec ff_jpeg2000_encoder = { + .p.name = "jpeg2000", + .p.long_name = NULL_IF_CONFIG_SMALL("JPEG 2000"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_JPEG2000, .priv_data_size = sizeof(Jpeg2000EncoderContext), .init = j2kenc_init, - .encode2 = encode_frame, + FF_CODEC_ENCODE_CB(encode_frame), .close = j2kenc_destroy, - .pix_fmts = (const enum AVPixelFormat[]) { + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_RGB24, AV_PIX_FMT_YUV444P, AV_PIX_FMT_GRAY8, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, @@ -1848,6 +1847,6 @@ const AVCodec ff_jpeg2000_encoder = { AV_PIX_FMT_RGB48, AV_PIX_FMT_GRAY16, AV_PIX_FMT_NONE }, - .priv_class = &j2k_class, + .p.priv_class = &j2k_class, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/jacosubdec.c b/libavcodec/jacosubdec.c index 698895a86..e3bf9f422 100644 --- a/libavcodec/jacosubdec.c +++ b/libavcodec/jacosubdec.c @@ -26,7 +26,7 @@ #include #include "ass.h" -#include "internal.h" +#include "codec_internal.h" #include "jacosub.h" #include "libavutil/avstring.h" #include "libavutil/bprint.h" @@ -162,11 +162,10 @@ static void jacosub_to_ass(AVCodecContext *avctx, AVBPrint *dst, const char *src } } -static int jacosub_decode_frame(AVCodecContext *avctx, - void *data, int *got_sub_ptr, AVPacket *avpkt) +static int jacosub_decode_frame(AVCodecContext *avctx, AVSubtitle *sub, + int *got_sub_ptr, const AVPacket *avpkt) { int ret; - AVSubtitle *sub = data; const char *ptr = avpkt->data; FFASSDecoderContext *s = avctx->priv_data; @@ -194,13 +193,13 @@ end: return avpkt->size; } -const AVCodec ff_jacosub_decoder = { - .name = "jacosub", - .long_name = NULL_IF_CONFIG_SMALL("JACOsub subtitle"), - .type = AVMEDIA_TYPE_SUBTITLE, - .id = AV_CODEC_ID_JACOSUB, +const FFCodec ff_jacosub_decoder = { + .p.name = "jacosub", + .p.long_name = NULL_IF_CONFIG_SMALL("JACOsub subtitle"), + .p.type = AVMEDIA_TYPE_SUBTITLE, + .p.id = AV_CODEC_ID_JACOSUB, .init = ff_ass_subtitle_header_default, - .decode = jacosub_decode_frame, + FF_CODEC_DECODE_SUB_CB(jacosub_decode_frame), .flush = ff_ass_decoder_flush, .priv_data_size = sizeof(FFASSDecoderContext), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, diff --git a/libavcodec/jfdctfst.c b/libavcodec/jfdctfst.c index bbcf59849..805e05808 100644 --- a/libavcodec/jfdctfst.c +++ b/libavcodec/jfdctfst.c @@ -66,9 +66,8 @@ * Independent JPEG Group's fast AAN dct. */ -#include -#include -#include "libavutil/common.h" +#include +#include "libavutil/attributes.h" #include "dct.h" #define DCTSIZE 8 diff --git a/libavcodec/jpeg2000_parser.c b/libavcodec/jpeg2000_parser.c index 2975e7148..e96efc28e 100644 --- a/libavcodec/jpeg2000_parser.c +++ b/libavcodec/jpeg2000_parser.c @@ -51,7 +51,7 @@ static inline void reset_context(JPEG2000ParserContext *m) ParseContext *pc = &m->pc; pc->frame_start_found= 0; - pc->state = 0; + pc->state64 = 0; m->bytes_read = 0; m->ft = 0; m->skipped_codestream = 0; @@ -65,13 +65,25 @@ static inline void reset_context(JPEG2000ParserContext *m) */ static uint8_t info_marker(uint16_t marker) { - if (marker == 0xFF92 || marker == 0xFF4F || - marker == 0xFF90 || marker == 0xFF93 || - marker == 0xFFD9) - return 0; - else - if (marker > 0xFF00) return 1; - return 0; + static const uint8_t lut[256] = { + 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, 0, // 0xFF4F + 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, + 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xFF90 0xFF92 0xFF93 + 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, 0, 1, 1, 1, 1, 1, 1, // 0xFFD9 + 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, + }; + return marker < 0xFF00 ? 0 : lut[marker & 0xFF]; } /** @@ -82,19 +94,28 @@ static int find_frame_end(JPEG2000ParserContext *m, const uint8_t *buf, int buf_ { ParseContext *pc= &m->pc; int i; - uint32_t state, next_state; - uint64_t state64; - state= pc->state; - state64 = pc->state64; + uint64_t state64 = pc->state64; + uint64_t bytes_read = m->bytes_read; + if (buf_size == 0) { return 0; } for (i = 0; i < buf_size; i++) { - state = state << 8 | buf[i]; state64 = state64 << 8 | buf[i]; - m->bytes_read++; + bytes_read++; if (m->skip_bytes) { + // handle long skips + if (m->skip_bytes > 8) { + // need -9 else buf_size - i == 8 ==> i == buf_size after this, + // and thus i == buf_size + 1 after the loop + int skip = FFMIN(FFMIN((int64_t)m->skip_bytes - 8, buf_size - i - 9), INT_MAX); + if (skip > 0) { + m->skip_bytes -= skip; + i += skip; + bytes_read += skip; + } + } m->skip_bytes--; continue; } @@ -121,9 +142,9 @@ static int find_frame_end(JPEG2000ParserContext *m, const uint8_t *buf, int buf_ } m->fheader_read--; } - if (state == 0x0000000C && m->bytes_read >= 3) { // Indicates start of JP2 file. Check signature next. + if ((state64 & 0xFFFFFFFF) == 0x0000000C && bytes_read >= 3) { // Indicates start of JP2 file. Check signature next. m->fheader_read = 8; - } else if ((state & 0xFFFF) == 0xFF4F) { + } else if ((state64 & 0xFFFF) == 0xFF4F) { m->in_codestream = 1; if (!pc->frame_start_found) { pc->frame_start_found = 1; @@ -132,7 +153,7 @@ static int find_frame_end(JPEG2000ParserContext *m, const uint8_t *buf, int buf_ reset_context(m); return i - 1; } - } else if ((state & 0xFFFF) == 0xFFD9) { + } else if ((state64 & 0xFFFF) == 0xFFD9) { if (pc->frame_start_found && m->ft == jp2_file) { m->skipped_codestream = 1; } else if (pc->frame_start_found && m->ft == j2k_cstream) { @@ -140,25 +161,27 @@ static int find_frame_end(JPEG2000ParserContext *m, const uint8_t *buf, int buf_ return i + 1; // End of frame detected, return frame size. } m->in_codestream = 0; - } else if (m->in_codestream && (state & 0xFFFF) == 0xFF90) { // Are we in tile part header? - m->read_tp = 8; - } else if (pc->frame_start_found && info_marker((state & 0xFFFF0000)>>16) && m->in_codestream && (state & 0xFFFF)) { - // Calculate number of bytes to skip to get to end of the next marker. - m->skip_bytes = (state & 0xFFFF)-1; + } else if (m->in_codestream) { + if ((state64 & 0xFFFF) == 0xFF90) { // Are we in tile part header? + m->read_tp = 8; + } else if (info_marker((state64 & 0xFFFF0000)>>16) && pc->frame_start_found && (state64 & 0xFFFF)) { + // Calculate number of bytes to skip to get to end of the next marker. + m->skip_bytes = (state64 & 0xFFFF)-1; - // If the next marker is an info marker, skip to the end of of the marker length. - if (i + m->skip_bytes + 1 < buf_size) { - next_state = (buf[i + m->skip_bytes] << 8) | buf[i + m->skip_bytes + 1]; - if (info_marker(next_state)) { - // Skip an additional 2 bytes to get to the end of the marker length. - m->skip_bytes += 2; + // If the next marker is an info marker, skip to the end of of the marker length. + if (i + m->skip_bytes + 1 < buf_size) { + uint32_t next_state = (buf[i + m->skip_bytes] << 8) | buf[i + m->skip_bytes + 1]; + if (info_marker(next_state)) { + // Skip an additional 2 bytes to get to the end of the marker length. + m->skip_bytes += 2; + } } } } } - pc->state = state; pc->state64 = state64; + m->bytes_read = bytes_read; return END_NOT_FOUND; } diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c index 80b2e2d62..92966b11f 100644 --- a/libavcodec/jpeg2000dec.c +++ b/libavcodec/jpeg2000dec.c @@ -36,6 +36,7 @@ #include "libavutil/pixdesc.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" #include "thread.h" #include "jpeg2000.h" @@ -2080,7 +2081,6 @@ static int jpeg2000_decode_tile(AVCodecContext *avctx, void *td, Jpeg2000DecoderContext *s = avctx->priv_data; AVFrame *picture = td; Jpeg2000Tile *tile = s->tile + jobnr; - int x; tile_codeblocks(s, tile); @@ -2088,17 +2088,6 @@ static int jpeg2000_decode_tile(AVCodecContext *avctx, void *td, if (tile->codsty[0].mct) mct_decode(s, tile); - for (x = 0; x < s->ncomponents; x++) { - if (s->cdef[x] < 0) { - for (x = 0; x < s->ncomponents; x++) { - s->cdef[x] = x + 1; - } - if ((s->ncomponents & 1) == 0) - s->cdef[s->ncomponents-1] = 0; - break; - } - } - if (s->precision <= 8) { write_frame_8(s, tile, picture, 8); } else { @@ -2484,12 +2473,10 @@ static av_cold int jpeg2000_decode_init(AVCodecContext *avctx) return 0; } -static int jpeg2000_decode_frame(AVCodecContext *avctx, void *data, +static int jpeg2000_decode_frame(AVCodecContext *avctx, AVFrame *picture, int *got_frame, AVPacket *avpkt) { Jpeg2000DecoderContext *s = avctx->priv_data; - ThreadFrame frame = { .f = data }; - AVFrame *picture = data; int ret; s->avctx = avctx; @@ -2529,7 +2516,7 @@ static int jpeg2000_decode_frame(AVCodecContext *avctx, void *data, goto end; /* get picture buffer */ - if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, picture, 0)) < 0) goto end; picture->pict_type = AV_PICTURE_TYPE_I; picture->key_frame = 1; @@ -2537,6 +2524,17 @@ static int jpeg2000_decode_frame(AVCodecContext *avctx, void *data, if (ret = jpeg2000_read_bitstream_packets(s)) goto end; + for (int x = 0; x < s->ncomponents; x++) { + if (s->cdef[x] < 0) { + for (x = 0; x < s->ncomponents; x++) { + s->cdef[x] = x + 1; + } + if ((s->ncomponents & 1) == 0) + s->cdef[s->ncomponents-1] = 0; + break; + } + } + avctx->execute2(avctx, jpeg2000_decode_tile, picture, NULL, s->numXtiles * s->numYtiles); jpeg2000_dec_cleanup(s); @@ -2572,17 +2570,17 @@ static const AVClass jpeg2000_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_jpeg2000_decoder = { - .name = "jpeg2000", - .long_name = NULL_IF_CONFIG_SMALL("JPEG 2000"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_JPEG2000, - .capabilities = AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_DR1, +const FFCodec ff_jpeg2000_decoder = { + .p.name = "jpeg2000", + .p.long_name = NULL_IF_CONFIG_SMALL("JPEG 2000"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_JPEG2000, + .p.capabilities = AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_DR1, .priv_data_size = sizeof(Jpeg2000DecoderContext), .init = jpeg2000_decode_init, - .decode = jpeg2000_decode_frame, - .priv_class = &jpeg2000_class, - .max_lowres = 5, - .profiles = NULL_IF_CONFIG_SMALL(ff_jpeg2000_profiles), + FF_CODEC_DECODE_CB(jpeg2000_decode_frame), + .p.priv_class = &jpeg2000_class, + .p.max_lowres = 5, + .p.profiles = NULL_IF_CONFIG_SMALL(ff_jpeg2000_profiles), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/jpeg2000dsp.c b/libavcodec/jpeg2000dsp.c index 90e73b1e2..b61be3b72 100644 --- a/libavcodec/jpeg2000dsp.c +++ b/libavcodec/jpeg2000dsp.c @@ -96,6 +96,7 @@ av_cold void ff_jpeg2000dsp_init(Jpeg2000DSPContext *c) c->mct_decode[FF_DWT53] = rct_int; c->mct_decode[FF_DWT97_INT] = ict_int; - if (ARCH_X86) - ff_jpeg2000dsp_init_x86(c); +#if ARCH_X86 + ff_jpeg2000dsp_init_x86(c); +#endif } diff --git a/libavcodec/jpeg2000dwt.c b/libavcodec/jpeg2000dwt.c index f9a097740..f2da7307c 100644 --- a/libavcodec/jpeg2000dwt.c +++ b/libavcodec/jpeg2000dwt.c @@ -25,10 +25,10 @@ * Discrete wavelet transform */ -#include "libavutil/common.h" +#include "libavutil/error.h" +#include "libavutil/macros.h" #include "libavutil/mem.h" #include "jpeg2000dwt.h" -#include "internal.h" /* Defines for 9/7 DWT lifting parameters. * Parameters are in float. */ diff --git a/libavcodec/jpeglsdec.c b/libavcodec/jpeglsdec.c index bae8ea89f..ab663dc1f 100644 --- a/libavcodec/jpeglsdec.c +++ b/libavcodec/jpeglsdec.c @@ -26,11 +26,10 @@ */ #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" #include "golomb.h" -#include "internal.h" #include "mathops.h" -#include "mjpeg.h" #include "mjpegdec.h" #include "jpegls.h" #include "jpeglsdec.h" @@ -279,7 +278,7 @@ static inline int ls_decode_line(JLSState *state, MJpegDecodeContext *s, /* decode aborted run */ r = ff_log2_run[state->run_index[comp]]; if (r) - r = get_bits_long(&s->gb, r); + r = get_bits(&s->gb, r); if (x + r * stride > w) { r = (w - x) / stride; } @@ -485,19 +484,19 @@ int ff_jpegls_decode_picture(MJpegDecodeContext *s, int near, for (i = 0; i < s->height; i++) { switch(s->xfrm) { case 1: - for (x = off; x < w; x += 3) { + for (x = off; x + 2 < w; x += 3) { src[x ] += src[x+1] + 128; src[x+2] += src[x+1] + 128; } break; case 2: - for (x = off; x < w; x += 3) { + for (x = off; x + 2 < w; x += 3) { src[x ] += src[x+1] + 128; src[x+2] += ((src[x ] + src[x+1])>>1) + 128; } break; case 3: - for (x = off; x < w; x += 3) { + for (x = off; x + 2 < w; x += 3) { int g = src[x+0] - ((src[x+2]+src[x+1])>>2) + 64; src[x+0] = src[x+2] + g + 128; src[x+2] = src[x+1] + g + 128; @@ -505,7 +504,7 @@ int ff_jpegls_decode_picture(MJpegDecodeContext *s, int near, } break; case 4: - for (x = off; x < w; x += 3) { + for (x = off; x + 2 < w; x += 3) { int r = src[x+0] - (( 359 * (src[x+2]-128) + 490) >> 8); int g = src[x+0] - (( 88 * (src[x+1]-128) - 183 * (src[x+2]-128) + 30) >> 8); int b = src[x+0] + ((454 * (src[x+1]-128) + 574) >> 8); @@ -551,16 +550,16 @@ end: return ret; } -const AVCodec ff_jpegls_decoder = { - .name = "jpegls", - .long_name = NULL_IF_CONFIG_SMALL("JPEG-LS"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_JPEGLS, +const FFCodec ff_jpegls_decoder = { + .p.name = "jpegls", + .p.long_name = NULL_IF_CONFIG_SMALL("JPEG-LS"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_JPEGLS, .priv_data_size = sizeof(MJpegDecodeContext), .init = ff_mjpeg_decode_init, .close = ff_mjpeg_decode_end, - .receive_frame = ff_mjpeg_receive_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_RECEIVE_FRAME_CB(ff_mjpeg_receive_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_SETS_PKT_DTS, }; diff --git a/libavcodec/jpeglsenc.c b/libavcodec/jpeglsenc.c index beae3bb77..577e8a19d 100644 --- a/libavcodec/jpeglsenc.c +++ b/libavcodec/jpeglsenc.c @@ -29,11 +29,11 @@ #include "libavutil/opt.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "encode.h" #include "get_bits.h" #include "put_bits.h" -#include "golomb.h" -#include "internal.h" +#include "put_golomb.h" #include "mathops.h" #include "mjpeg.h" #include "jpegls.h" @@ -473,18 +473,18 @@ static const AVClass jpegls_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_jpegls_encoder = { - .name = "jpegls", - .long_name = NULL_IF_CONFIG_SMALL("JPEG-LS"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_JPEGLS, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, +const FFCodec ff_jpegls_encoder = { + .p.name = "jpegls", + .p.long_name = NULL_IF_CONFIG_SMALL("JPEG-LS"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_JPEGLS, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, .priv_data_size = sizeof(JPEGLSContext), - .priv_class = &jpegls_class, + .p.priv_class = &jpegls_class, .init = encode_jpegls_init, - .encode2 = encode_picture_ls, + FF_CODEC_ENCODE_CB(encode_picture_ls), .close = encode_jpegls_close, - .pix_fmts = (const enum AVPixelFormat[]) { + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_BGR24, AV_PIX_FMT_RGB24, AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY16, AV_PIX_FMT_NONE diff --git a/libavcodec/jrevdct.c b/libavcodec/jrevdct.c index a1a0f571a..36160cb66 100644 --- a/libavcodec/jrevdct.c +++ b/libavcodec/jrevdct.c @@ -62,7 +62,9 @@ * Independent JPEG Group's LLM idct. */ -#include "libavutil/common.h" +#include +#include + #include "libavutil/intreadwrite.h" #include "dct.h" diff --git a/libavcodec/jvdec.c b/libavcodec/jvdec.c index 71049bbeb..06015ba59 100644 --- a/libavcodec/jvdec.c +++ b/libavcodec/jvdec.c @@ -29,6 +29,7 @@ #include "avcodec.h" #include "blockdsp.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" @@ -143,8 +144,8 @@ static inline void decode8x8(GetBitContext *gb, uint8_t *dst, int linesize, } } -static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *avpkt) { JvContext *s = avctx->priv_data; const uint8_t *buf = avpkt->data; @@ -216,7 +217,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, s->palette_has_changed = 0; memcpy(s->frame->data[1], s->palette, AVPALETTE_SIZE); - if ((ret = av_frame_ref(data, s->frame)) < 0) + if ((ret = av_frame_ref(rframe, s->frame)) < 0) return ret; *got_frame = 1; } @@ -233,15 +234,15 @@ static av_cold int decode_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_jv_decoder = { - .name = "jv", - .long_name = NULL_IF_CONFIG_SMALL("Bitmap Brothers JV video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_JV, +const FFCodec ff_jv_decoder = { + .p.name = "jv", + .p.long_name = NULL_IF_CONFIG_SMALL("Bitmap Brothers JV video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_JV, .priv_data_size = sizeof(JvContext), .init = decode_init, .close = decode_close, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/kgv1dec.c b/libavcodec/kgv1dec.c index f865771b7..08e92c710 100644 --- a/libavcodec/kgv1dec.c +++ b/libavcodec/kgv1dec.c @@ -28,6 +28,7 @@ #include "libavutil/intreadwrite.h" #include "libavutil/imgutils.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" typedef struct KgvContext { @@ -43,10 +44,9 @@ static void decode_flush(AVCodecContext *avctx) av_freep(&c->last_frame_buffer); } -static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { - AVFrame *frame = data; const uint8_t *buf = avpkt->data; const uint8_t *buf_end = buf + avpkt->size; KgvContext * const c = avctx->priv_data; @@ -176,16 +176,16 @@ static av_cold int decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_kgv1_decoder = { - .name = "kgv1", - .long_name = NULL_IF_CONFIG_SMALL("Kega Game Video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_KGV1, +const FFCodec ff_kgv1_decoder = { + .p.name = "kgv1", + .p.long_name = NULL_IF_CONFIG_SMALL("Kega Game Video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_KGV1, .priv_data_size = sizeof(KgvContext), .init = decode_init, .close = decode_end, - .decode = decode_frame, + FF_CODEC_DECODE_CB(decode_frame), .flush = decode_flush, - .capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/kmvc.c b/libavcodec/kmvc.c index a47afed8f..a009ba0ce 100644 --- a/libavcodec/kmvc.c +++ b/libavcodec/kmvc.c @@ -29,6 +29,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "decode.h" #include "internal.h" #include "libavutil/common.h" @@ -260,11 +261,10 @@ static int kmvc_decode_inter_8x8(KmvcContext * ctx, int w, int h) return 0; } -static int decode_frame(AVCodecContext * avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext * avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { KmvcContext *const ctx = avctx->priv_data; - AVFrame *frame = data; uint8_t *out, *src; int i, ret; int header; @@ -404,14 +404,14 @@ static av_cold int decode_init(AVCodecContext * avctx) return 0; } -const AVCodec ff_kmvc_decoder = { - .name = "kmvc", - .long_name = NULL_IF_CONFIG_SMALL("Karl Morton's video codec"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_KMVC, +const FFCodec ff_kmvc_decoder = { + .p.name = "kmvc", + .p.long_name = NULL_IF_CONFIG_SMALL("Karl Morton's video codec"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_KMVC, .priv_data_size = sizeof(KmvcContext), .init = decode_init, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/lagarith.c b/libavcodec/lagarith.c index 7220648bc..00e800522 100644 --- a/libavcodec/lagarith.c +++ b/libavcodec/lagarith.c @@ -28,8 +28,8 @@ #include #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" -#include "internal.h" #include "mathops.h" #include "lagarithrac.h" #include "lossless_videodsp.h" @@ -409,6 +409,9 @@ output_zeros: if (zero_run) { zero_run = 0; i += esc_count; + if (i > end - dst || + i >= src_end - src) + return AVERROR_INVALIDDATA; memcpy(dst, src, i); dst += i; l->zeros_rem = lag_calc_zero_run(src[i]); @@ -534,14 +537,12 @@ static int lag_decode_arith_plane(LagarithContext *l, uint8_t *dst, * @param avpkt input packet * @return number of consumed bytes on success or negative if decode fails */ -static int lag_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, AVPacket *avpkt) +static int lag_decode_frame(AVCodecContext *avctx, AVFrame *p, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; unsigned int buf_size = avpkt->size; LagarithContext *l = avctx->priv_data; - ThreadFrame frame = { .f = data }; - AVFrame *const p = data; uint8_t frametype; uint32_t offset_gu = 0, offset_bv = 0, offset_ry = 9; uint32_t offs[4]; @@ -569,7 +570,7 @@ static int lag_decode_frame(AVCodecContext *avctx, planes = 4; } - if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, p, 0)) < 0) return ret; if (frametype == FRAME_SOLID_RGBA) { @@ -593,7 +594,7 @@ static int lag_decode_frame(AVCodecContext *avctx, avctx->pix_fmt = AV_PIX_FMT_GBRAP; } - if ((ret = ff_thread_get_buffer(avctx, &frame,0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, p,0)) < 0) return ret; for (i = 0; i < avctx->height; i++) { @@ -614,7 +615,7 @@ static int lag_decode_frame(AVCodecContext *avctx, if (frametype == FRAME_ARITH_RGB24 || frametype == FRAME_U_RGB24) avctx->pix_fmt = AV_PIX_FMT_GBRP; - if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, p, 0)) < 0) return ret; offs[0] = offset_bv; @@ -650,7 +651,7 @@ static int lag_decode_frame(AVCodecContext *avctx, case FRAME_ARITH_YUY2: avctx->pix_fmt = AV_PIX_FMT_YUV422P; - if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, p, 0)) < 0) return ret; if (offset_ry >= buf_size || @@ -678,7 +679,7 @@ static int lag_decode_frame(AVCodecContext *avctx, case FRAME_ARITH_YV12: avctx->pix_fmt = AV_PIX_FMT_YUV420P; - if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, p, 0)) < 0) return ret; if (offset_ry >= buf_size || @@ -727,14 +728,14 @@ static av_cold int lag_decode_init(AVCodecContext *avctx) return 0; } -const AVCodec ff_lagarith_decoder = { - .name = "lagarith", - .long_name = NULL_IF_CONFIG_SMALL("Lagarith lossless"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_LAGARITH, +const FFCodec ff_lagarith_decoder = { + .p.name = "lagarith", + .p.long_name = NULL_IF_CONFIG_SMALL("Lagarith lossless"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_LAGARITH, .priv_data_size = sizeof(LagarithContext), .init = lag_decode_init, - .decode = lag_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + FF_CODEC_DECODE_CB(lag_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/lagarithrac.h b/libavcodec/lagarithrac.h index ee836d01d..a31b054db 100644 --- a/libavcodec/lagarithrac.h +++ b/libavcodec/lagarithrac.h @@ -31,7 +31,6 @@ #define AVCODEC_LAGARITHRAC_H #include -#include "libavutil/common.h" #include "libavutil/intreadwrite.h" #include "avcodec.h" #include "get_bits.h" diff --git a/libavcodec/lcldec.c b/libavcodec/lcldec.c index a47e3bd78..ffa2fe5a6 100644 --- a/libavcodec/lcldec.c +++ b/libavcodec/lcldec.c @@ -37,6 +37,8 @@ * Supports: BGR24 (RGB 24bpp) */ +#include "config_components.h" + #include #include @@ -44,11 +46,12 @@ #include "libavutil/pixdesc.h" #include "avcodec.h" #include "bytestream.h" -#include "internal.h" +#include "codec_internal.h" #include "lcl.h" #include "thread.h" #if CONFIG_ZLIB_DECODER +#include "zlib_wrapper.h" #include #endif @@ -64,7 +67,7 @@ typedef struct LclDecContext { // Decompression buffer unsigned char* decomp_buf; #if CONFIG_ZLIB_DECODER - z_stream zstream; + FFZStream zstream; #endif } LclDecContext; @@ -131,34 +134,34 @@ static unsigned int mszh_decomp(const unsigned char * srcptr, int srclen, unsign static int zlib_decomp(AVCodecContext *avctx, const uint8_t *src, int src_len, int offset, int expected) { LclDecContext *c = avctx->priv_data; - int zret = inflateReset(&c->zstream); + z_stream *const zstream = &c->zstream.zstream; + int zret = inflateReset(zstream); if (zret != Z_OK) { av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", zret); return AVERROR_UNKNOWN; } - c->zstream.next_in = src; - c->zstream.avail_in = src_len; - c->zstream.next_out = c->decomp_buf + offset; - c->zstream.avail_out = c->decomp_size - offset; - zret = inflate(&c->zstream, Z_FINISH); + zstream->next_in = src; + zstream->avail_in = src_len; + zstream->next_out = c->decomp_buf + offset; + zstream->avail_out = c->decomp_size - offset; + zret = inflate(zstream, Z_FINISH); if (zret != Z_OK && zret != Z_STREAM_END) { av_log(avctx, AV_LOG_ERROR, "Inflate error: %d\n", zret); return AVERROR_UNKNOWN; } - if (expected != (unsigned int)c->zstream.total_out) { + if (expected != (unsigned int)zstream->total_out) { av_log(avctx, AV_LOG_ERROR, "Decoded size differs (%d != %lu)\n", - expected, c->zstream.total_out); + expected, zstream->total_out); return AVERROR_UNKNOWN; } - return c->zstream.total_out; + return zstream->total_out; } #endif -static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { - AVFrame *frame = data; - ThreadFrame tframe = { .f = data }; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; LclDecContext * const c = avctx->priv_data; @@ -175,7 +178,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPac unsigned int len = buf_size; int linesize, offset; - if ((ret = ff_thread_get_buffer(avctx, &tframe, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, frame, 0)) < 0) return ret; outptr = frame->data[0]; // Output image pointer @@ -607,18 +610,8 @@ static av_cold int decode_init(AVCodecContext *avctx) /* If needed init zlib */ #if CONFIG_ZLIB_DECODER - if (avctx->codec_id == AV_CODEC_ID_ZLIB) { - int zret; - c->zstream.zalloc = Z_NULL; - c->zstream.zfree = Z_NULL; - c->zstream.opaque = Z_NULL; - zret = inflateInit(&c->zstream); - if (zret != Z_OK) { - av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret); - av_freep(&c->decomp_buf); - return AVERROR_UNKNOWN; - } - } + if (avctx->codec_id == AV_CODEC_ID_ZLIB) + return ff_inflate_init(&c->zstream, avctx); #endif return 0; @@ -630,39 +623,38 @@ static av_cold int decode_end(AVCodecContext *avctx) av_freep(&c->decomp_buf); #if CONFIG_ZLIB_DECODER - if (avctx->codec_id == AV_CODEC_ID_ZLIB) - inflateEnd(&c->zstream); + ff_inflate_end(&c->zstream); #endif return 0; } #if CONFIG_MSZH_DECODER -const AVCodec ff_mszh_decoder = { - .name = "mszh", - .long_name = NULL_IF_CONFIG_SMALL("LCL (LossLess Codec Library) MSZH"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MSZH, +const FFCodec ff_mszh_decoder = { + .p.name = "mszh", + .p.long_name = NULL_IF_CONFIG_SMALL("LCL (LossLess Codec Library) MSZH"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MSZH, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, .priv_data_size = sizeof(LclDecContext), .init = decode_init, .close = decode_end, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + FF_CODEC_DECODE_CB(decode_frame), + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; #endif #if CONFIG_ZLIB_DECODER -const AVCodec ff_zlib_decoder = { - .name = "zlib", - .long_name = NULL_IF_CONFIG_SMALL("LCL (LossLess Codec Library) ZLIB"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_ZLIB, +const FFCodec ff_zlib_decoder = { + .p.name = "zlib", + .p.long_name = NULL_IF_CONFIG_SMALL("LCL (LossLess Codec Library) ZLIB"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_ZLIB, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, .priv_data_size = sizeof(LclDecContext), .init = decode_init, .close = decode_end, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + FF_CODEC_DECODE_CB(decode_frame), + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; #endif diff --git a/libavcodec/lclenc.c b/libavcodec/lclenc.c index 7deea4f20..bd42c155a 100644 --- a/libavcodec/lclenc.c +++ b/libavcodec/lclenc.c @@ -42,9 +42,10 @@ #include "libavutil/avassert.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "lcl.h" +#include "zlib_wrapper.h" #include "libavutil/internal.h" #include "libavutil/mem.h" @@ -60,16 +61,17 @@ typedef struct LclEncContext { int compression; // Flags int flags; - z_stream zstream; + FFZStream zstream; } LclEncContext; static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *p, int *got_packet) { LclEncContext *c = avctx->priv_data; + z_stream *const zstream = &c->zstream.zstream; int i, ret; int zret; // Zlib return code - int max_size = deflateBound(&c->zstream, avctx->width * avctx->height * 3); + int max_size = deflateBound(zstream, avctx->width * avctx->height * 3); if ((ret = ff_alloc_packet(avctx, pkt, max_size)) < 0) return ret; @@ -79,30 +81,30 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, return -1; } - zret = deflateReset(&c->zstream); + zret = deflateReset(zstream); if (zret != Z_OK) { av_log(avctx, AV_LOG_ERROR, "Deflate reset error: %d\n", zret); return -1; } - c->zstream.next_out = pkt->data; - c->zstream.avail_out = pkt->size; + zstream->next_out = pkt->data; + zstream->avail_out = pkt->size; for(i = avctx->height - 1; i >= 0; i--) { - c->zstream.next_in = p->data[0]+p->linesize[0]*i; - c->zstream.avail_in = avctx->width*3; - zret = deflate(&c->zstream, Z_NO_FLUSH); + zstream->next_in = p->data[0] + p->linesize[0] * i; + zstream->avail_in = avctx->width * 3; + zret = deflate(zstream, Z_NO_FLUSH); if (zret != Z_OK) { av_log(avctx, AV_LOG_ERROR, "Deflate error: %d\n", zret); return -1; } } - zret = deflate(&c->zstream, Z_FINISH); + zret = deflate(zstream, Z_FINISH); if (zret != Z_STREAM_END) { av_log(avctx, AV_LOG_ERROR, "Deflate error: %d\n", zret); return -1; } - pkt->size = c->zstream.total_out; + pkt->size = zstream->total_out; *got_packet = 1; return 0; @@ -111,7 +113,6 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, static av_cold int encode_init(AVCodecContext *avctx) { LclEncContext *c = avctx->priv_data; - int zret; // Zlib return code c->avctx= avctx; @@ -138,38 +139,29 @@ static av_cold int encode_init(AVCodecContext *avctx) avctx->extradata[7]= CODEC_ZLIB; c->avctx->extradata_size= 8; - c->zstream.zalloc = Z_NULL; - c->zstream.zfree = Z_NULL; - c->zstream.opaque = Z_NULL; - zret = deflateInit(&c->zstream, c->compression); - if (zret != Z_OK) { - av_log(avctx, AV_LOG_ERROR, "Deflate init error: %d\n", zret); - return AVERROR_UNKNOWN; - } - - return 0; + return ff_deflate_init(&c->zstream, c->compression, avctx); } static av_cold int encode_end(AVCodecContext *avctx) { LclEncContext *c = avctx->priv_data; - deflateEnd(&c->zstream); + ff_deflate_end(&c->zstream); return 0; } -const AVCodec ff_zlib_encoder = { - .name = "zlib", - .long_name = NULL_IF_CONFIG_SMALL("LCL (LossLess Codec Library) ZLIB"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_ZLIB, +const FFCodec ff_zlib_encoder = { + .p.name = "zlib", + .p.long_name = NULL_IF_CONFIG_SMALL("LCL (LossLess Codec Library) ZLIB"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_ZLIB, .priv_data_size = sizeof(LclEncContext), .init = encode_init, - .encode2 = encode_frame, + FF_CODEC_ENCODE_CB(encode_frame), .close = encode_end, - .capabilities = AV_CODEC_CAP_FRAME_THREADS, - .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE }, + .p.capabilities = AV_CODEC_CAP_FRAME_THREADS, + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/libaomdec.c b/libavcodec/libaomdec.c index 64a627ed1..52a8bf19e 100644 --- a/libavcodec/libaomdec.c +++ b/libavcodec/libaomdec.c @@ -31,6 +31,7 @@ #include "libavutil/imgutils.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "profiles.h" @@ -155,11 +156,10 @@ static int set_pix_fmt(AVCodecContext *avctx, struct aom_image *img) } } -static int aom_decode(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int aom_decode(AVCodecContext *avctx, AVFrame *picture, + int *got_frame, AVPacket *avpkt) { AV1DecodeContext *ctx = avctx->priv_data; - AVFrame *picture = data; const void *iter = NULL; struct aom_image *img; int ret; @@ -248,17 +248,17 @@ static av_cold int av1_init(AVCodecContext *avctx) return aom_init(avctx, aom_codec_av1_dx()); } -const 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, +const FFCodec ff_libaom_av1_decoder = { + .p.name = "libaom-av1", + .p.long_name = NULL_IF_CONFIG_SMALL("libaom AV1"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_AV1, .priv_data_size = sizeof(AV1DecodeContext), .init = av1_init, .close = aom_free, - .decode = aom_decode, - .capabilities = AV_CODEC_CAP_OTHER_THREADS | AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(aom_decode), + .p.capabilities = AV_CODEC_CAP_OTHER_THREADS | AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_AUTO_THREADS, - .profiles = NULL_IF_CONFIG_SMALL(ff_av1_profiles), - .wrapper_name = "libaom", + .p.profiles = NULL_IF_CONFIG_SMALL(ff_av1_profiles), + .p.wrapper_name = "libaom", }; diff --git a/libavcodec/libaomenc.c b/libavcodec/libaomenc.c index 963cc1bcb..6b7e426bf 100644 --- a/libavcodec/libaomenc.c +++ b/libavcodec/libaomenc.c @@ -38,6 +38,7 @@ #include "av1.h" #include "avcodec.h" #include "bsf.h" +#include "codec_internal.h" #include "encode.h" #include "internal.h" #include "packet_internal.h" @@ -99,6 +100,7 @@ typedef struct AOMEncoderContext { int enable_restoration; int usage; int tune; + int still_picture; int enable_rect_partitions; int enable_1to4_partitions; int enable_ab_partitions; @@ -197,6 +199,15 @@ static const char *const ctlidstr[] = { [AV1E_SET_ENABLE_SMOOTH_INTERINTRA] = "AV1E_SET_ENABLE_SMOOTH_INTERINTRA", [AV1E_SET_ENABLE_REF_FRAME_MVS] = "AV1E_SET_ENABLE_REF_FRAME_MVS", #endif +#ifdef AOM_CTRL_AV1E_GET_NUM_OPERATING_POINTS + [AV1E_GET_NUM_OPERATING_POINTS] = "AV1E_GET_NUM_OPERATING_POINTS", +#endif +#ifdef AOM_CTRL_AV1E_GET_SEQ_LEVEL_IDX + [AV1E_GET_SEQ_LEVEL_IDX] = "AV1E_GET_SEQ_LEVEL_IDX", +#endif +#ifdef AOM_CTRL_AV1E_GET_TARGET_SEQ_LEVEL_IDX + [AV1E_GET_TARGET_SEQ_LEVEL_IDX] = "AV1E_GET_TARGET_SEQ_LEVEL_IDX", +#endif }; static av_cold void log_encoder_error(AVCodecContext *avctx, const char *desc) @@ -322,10 +333,73 @@ static av_cold int codecctl_int(AVCodecContext *avctx, return 0; } +#if defined(AOM_CTRL_AV1E_GET_NUM_OPERATING_POINTS) && \ + defined(AOM_CTRL_AV1E_GET_SEQ_LEVEL_IDX) && \ + defined(AOM_CTRL_AV1E_GET_TARGET_SEQ_LEVEL_IDX) +static av_cold int codecctl_intp(AVCodecContext *avctx, +#ifdef UENUM1BYTE + aome_enc_control_id id, +#else + enum aome_enc_control_id id, +#endif + int* ptr) +{ + 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, *ptr); + + res = aom_codec_control(&ctx->encoder, id, ptr); + 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; +} +#endif + static av_cold int aom_free(AVCodecContext *avctx) { AOMContext *ctx = avctx->priv_data; +#if defined(AOM_CTRL_AV1E_GET_NUM_OPERATING_POINTS) && \ + defined(AOM_CTRL_AV1E_GET_SEQ_LEVEL_IDX) && \ + defined(AOM_CTRL_AV1E_GET_TARGET_SEQ_LEVEL_IDX) + if (!(avctx->flags & AV_CODEC_FLAG_PASS1)) { + int num_operating_points; + int levels[32]; + int target_levels[32]; + + if (!codecctl_intp(avctx, AV1E_GET_NUM_OPERATING_POINTS, + &num_operating_points) && + !codecctl_intp(avctx, AV1E_GET_SEQ_LEVEL_IDX, levels) && + !codecctl_intp(avctx, AV1E_GET_TARGET_SEQ_LEVEL_IDX, + target_levels)) { + for (int i = 0; i < num_operating_points; i++) { + if (levels[i] > target_levels[i]) { + // Warn when the target level was not met + av_log(avctx, AV_LOG_WARNING, + "Could not encode to target level %d.%d for " + "operating point %d. The output level is %d.%d.\n", + 2 + (target_levels[i] >> 2), target_levels[i] & 3, + i, 2 + (levels[i] >> 2), levels[i] & 3); + } else if (target_levels[i] < 31) { + // Log the encoded level if a target level was given + av_log(avctx, AV_LOG_INFO, + "Output level for operating point %d is %d.%d.\n", + i, 2 + (levels[i] >> 2), levels[i] & 3); + } + } + } + } +#endif + aom_codec_destroy(&ctx->encoder); av_freep(&ctx->twopass_stats.buf); av_freep(&avctx->stats_out); @@ -746,6 +820,18 @@ static av_cold int aom_init(AVCodecContext *avctx, if (res < 0) return res; + if (ctx->still_picture) { + // Set the maximum number of frames to 1. This will let libaom set + // still_picture and reduced_still_picture_header to 1 in the Sequence + // Header as required by AVIF still images. + enccfg.g_limit = 1; + // Reduce memory usage for still images. + enccfg.g_lag_in_frames = 0; + // All frames will be key frames. + enccfg.kf_max_dist = 0; + enccfg.kf_mode = AOM_KF_DISABLED; + } + /* Construct Encoder Context */ res = aom_codec_enc_init(&ctx->encoder, iface, &enccfg, flags); if (res != AOM_CODEC_OK) { @@ -1228,19 +1314,19 @@ static const enum AVPixelFormat av1_pix_fmts_highbd_with_gray[] = { AV_PIX_FMT_NONE }; -static av_cold void av1_init_static(AVCodec *codec) +static av_cold void av1_init_static(FFCodec *codec) { int supports_monochrome = aom_codec_version() >= 20001; aom_codec_caps_t codec_caps = aom_codec_get_caps(aom_codec_av1_cx()); if (codec_caps & AOM_CODEC_CAP_HIGHBITDEPTH) - codec->pix_fmts = supports_monochrome ? av1_pix_fmts_highbd_with_gray : - av1_pix_fmts_highbd; + codec->p.pix_fmts = supports_monochrome ? av1_pix_fmts_highbd_with_gray : + av1_pix_fmts_highbd; else - codec->pix_fmts = supports_monochrome ? av1_pix_fmts_with_gray : - av1_pix_fmts; + codec->p.pix_fmts = supports_monochrome ? av1_pix_fmts_with_gray : + av1_pix_fmts; if (aom_codec_version_major() < 2) - codec->capabilities |= AV_CODEC_CAP_EXPERIMENTAL; + codec->p.capabilities |= AV_CODEC_CAP_EXPERIMENTAL; } static av_cold int av1_init(AVCodecContext *avctx) @@ -1286,10 +1372,12 @@ static const AVOption options[] = { { "usage", "Quality and compression efficiency vs speed trade-off", OFFSET(usage), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, VE, "usage"}, { "good", "Good quality", 0, AV_OPT_TYPE_CONST, {.i64 = 0 /* AOM_USAGE_GOOD_QUALITY */}, 0, 0, VE, "usage"}, { "realtime", "Realtime encoding", 0, AV_OPT_TYPE_CONST, {.i64 = 1 /* AOM_USAGE_REALTIME */}, 0, 0, VE, "usage"}, + { "allintra", "All Intra encoding", 0, AV_OPT_TYPE_CONST, {.i64 = 2 /* AOM_USAGE_ALL_INTRA */}, 0, 0, VE, "usage"}, { "tune", "The metric that the encoder tunes for. Automatically chosen by the encoder by default", OFFSET(tune), AV_OPT_TYPE_INT, {.i64 = -1}, -1, AOM_TUNE_SSIM, VE, "tune"}, { "psnr", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AOM_TUNE_PSNR}, 0, 0, VE, "tune"}, { "ssim", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AOM_TUNE_SSIM}, 0, 0, VE, "tune"}, FF_AV1_PROFILE_OPTS + { "still-picture", "Encode in single frame mode (typically used for still AVIF images).", OFFSET(still_picture), AV_OPT_TYPE_BOOL, {.i64 = 0}, -1, 1, VE }, { "enable-rect-partitions", "Enable rectangular partitions", OFFSET(enable_rect_partitions), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, { "enable-1to4-partitions", "Enable 1:4/4:1 partitions", OFFSET(enable_1to4_partitions), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, { "enable-ab-partitions", "Enable ab shape partitions", OFFSET(enable_ab_partitions), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, @@ -1324,7 +1412,7 @@ static const AVOption options[] = { { NULL }, }; -static const AVCodecDefault defaults[] = { +static const FFCodecDefault defaults[] = { { "b", "0" }, { "qmin", "-1" }, { "qmax", "-1" }, @@ -1340,21 +1428,21 @@ static const AVClass class_aom = { .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, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | +FFCodec ff_libaom_av1_encoder = { + .p.name = "libaom-av1", + .p.long_name = NULL_IF_CONFIG_SMALL("libaom AV1"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_AV1, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS, + .p.profiles = NULL_IF_CONFIG_SMALL(ff_av1_profiles), + .p.priv_class = &class_aom, + .p.wrapper_name = "libaom", .priv_data_size = sizeof(AOMContext), .init = av1_init, - .encode2 = aom_encode, + FF_CODEC_ENCODE_CB(aom_encode), .close = aom_free, .caps_internal = FF_CODEC_CAP_AUTO_THREADS, - .profiles = NULL_IF_CONFIG_SMALL(ff_av1_profiles), - .priv_class = &class_aom, .defaults = defaults, .init_static_data = av1_init_static, - .wrapper_name = "libaom", }; diff --git a/libavcodec/libaribb24.c b/libavcodec/libaribb24.c index 0766c0079..9658e1d5a 100644 --- a/libavcodec/libaribb24.c +++ b/libavcodec/libaribb24.c @@ -21,6 +21,7 @@ #include "avcodec.h" #include "libavcodec/ass.h" +#include "codec_internal.h" #include "libavutil/log.h" #include "libavutil/opt.h" @@ -282,10 +283,10 @@ next_region: return ret; } -static int libaribb24_decode(AVCodecContext *avctx, void *data, int *got_sub_ptr, AVPacket *pkt) +static int libaribb24_decode(AVCodecContext *avctx, AVSubtitle *sub, + int *got_sub_ptr, const AVPacket *pkt) { Libaribb24Context *b24 = avctx->priv_data; - AVSubtitle *sub = data; size_t parsed_data_size = 0; size_t decoded_subtitle_size = 0; const unsigned char *parsed_data = NULL; @@ -380,16 +381,16 @@ static const AVClass aribb24_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_libaribb24_decoder = { - .name = "libaribb24", - .long_name = NULL_IF_CONFIG_SMALL("libaribb24 ARIB STD-B24 caption decoder"), - .type = AVMEDIA_TYPE_SUBTITLE, - .id = AV_CODEC_ID_ARIB_CAPTION, +const FFCodec ff_libaribb24_decoder = { + .p.name = "libaribb24", + .p.long_name = NULL_IF_CONFIG_SMALL("libaribb24 ARIB STD-B24 caption decoder"), + .p.type = AVMEDIA_TYPE_SUBTITLE, + .p.id = AV_CODEC_ID_ARIB_CAPTION, + .p.priv_class = &aribb24_class, + .p.wrapper_name = "libaribb24", .priv_data_size = sizeof(Libaribb24Context), .init = libaribb24_init, .close = libaribb24_close, - .decode = libaribb24_decode, + FF_CODEC_DECODE_SUB_CB(libaribb24_decode), .flush = libaribb24_flush, - .priv_class= &aribb24_class, - .wrapper_name = "libaribb24", }; diff --git a/libavcodec/libcelt_dec.c b/libavcodec/libcelt_dec.c index c0fb4013c..d659d80ed 100644 --- a/libavcodec/libcelt_dec.c +++ b/libavcodec/libcelt_dec.c @@ -22,6 +22,7 @@ #include #include #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "libavutil/intreadwrite.h" @@ -61,13 +62,13 @@ static av_cold int libcelt_dec_init(AVCodecContext *c) struct libcelt_context *celt = c->priv_data; int err; - if (!c->channels || !c->frame_size || - c->frame_size > INT_MAX / sizeof(int16_t) / c->channels) + if (!c->ch_layout.nb_channels || !c->frame_size || + c->frame_size > INT_MAX / sizeof(int16_t) / c->ch_layout.nb_channels) return AVERROR(EINVAL); celt->mode = celt_mode_create(c->sample_rate, c->frame_size, &err); if (!celt->mode) return ff_celt_error_to_averror(err); - celt->dec = celt_decoder_create_custom(celt->mode, c->channels, &err); + celt->dec = celt_decoder_create_custom(celt->mode, c->ch_layout.nb_channels, &err); if (!celt->dec) { celt_mode_destroy(celt->mode); return ff_celt_error_to_averror(err); @@ -102,11 +103,10 @@ static av_cold int libcelt_dec_close(AVCodecContext *c) return 0; } -static int libcelt_dec_decode(AVCodecContext *c, void *data, +static int libcelt_dec_decode(AVCodecContext *c, AVFrame *frame, int *got_frame_ptr, AVPacket *pkt) { struct libcelt_context *celt = c->priv_data; - AVFrame *frame = data; int err; int16_t *pcm; @@ -119,23 +119,23 @@ static int libcelt_dec_decode(AVCodecContext *c, void *data, return ff_celt_error_to_averror(err); if (celt->discard) { frame->nb_samples -= celt->discard; - memmove(pcm, pcm + celt->discard * c->channels, - frame->nb_samples * c->channels * sizeof(int16_t)); + memmove(pcm, pcm + celt->discard * c->ch_layout.nb_channels, + frame->nb_samples * c->ch_layout.nb_channels * sizeof(int16_t)); celt->discard = 0; } *got_frame_ptr = 1; return pkt->size; } -const AVCodec ff_libcelt_decoder = { - .name = "libcelt", - .long_name = NULL_IF_CONFIG_SMALL("Xiph CELT decoder using libcelt"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_CELT, +const FFCodec ff_libcelt_decoder = { + .p.name = "libcelt", + .p.long_name = NULL_IF_CONFIG_SMALL("Xiph CELT decoder using libcelt"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_CELT, + .p.capabilities = AV_CODEC_CAP_DR1, + .p.wrapper_name = "libcelt", .priv_data_size = sizeof(struct libcelt_context), .init = libcelt_dec_init, .close = libcelt_dec_close, - .decode = libcelt_dec_decode, - .capabilities = AV_CODEC_CAP_DR1, - .wrapper_name = "libcelt", + FF_CODEC_DECODE_CB(libcelt_dec_decode), }; diff --git a/libavcodec/libcodec2.c b/libavcodec/libcodec2.c index eb66867f8..abb1130e8 100644 --- a/libavcodec/libcodec2.c +++ b/libavcodec/libcodec2.c @@ -23,6 +23,7 @@ #include "libavutil/channel_layout.h" #include "avcodec.h" #include "libavutil/opt.h" +#include "codec_internal.h" #include "encode.h" #include "internal.h" #include "codec2utils.h" @@ -85,9 +86,9 @@ libcodec2_init_common_error: 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; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; if (avctx->extradata_size != CODEC2_EXTRADATA_SIZE) { av_log(avctx, AV_LOG_ERROR, "must have exactly %i bytes of extradata (got %i)\n", @@ -104,7 +105,7 @@ static av_cold int libcodec2_init_encoder(AVCodecContext *avctx) //will need to be smarter once we get wideband support if (avctx->sample_rate != 8000 || - avctx->channels != 1 || + avctx->ch_layout.nb_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); @@ -129,13 +130,12 @@ static av_cold int libcodec2_close(AVCodecContext *avctx) return 0; } -static int libcodec2_decode(AVCodecContext *avctx, void *data, +static int libcodec2_decode(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *pkt) { LibCodec2Context *c2 = avctx->priv_data; - AVFrame *frame = data; int ret, nframes, i; - uint8_t *input; + const uint8_t *input; int16_t *output; nframes = pkt->size / avctx->block_align; @@ -176,33 +176,39 @@ static int libcodec2_encode(AVCodecContext *avctx, AVPacket *avpkt, return 0; } -const 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, +const FFCodec ff_libcodec2_decoder = { + .p.name = "libcodec2", + .p.long_name = NULL_IF_CONFIG_SMALL("codec2 decoder using libcodec2"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_CODEC2, + .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF, + .p.supported_samplerates = (const int[]){ 8000, 0 }, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, + .p.ch_layouts = (const AVChannelLayout[]) { AV_CHANNEL_LAYOUT_MONO, { 0 } }, .priv_data_size = sizeof(LibCodec2Context), .init = libcodec2_init_decoder, .close = libcodec2_close, - .decode = libcodec2_decode, - .capabilities = AV_CODEC_CAP_CHANNEL_CONF, - .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 }, + FF_CODEC_DECODE_CB(libcodec2_decode), +#if FF_API_OLD_CHANNEL_LAYOUT + .p.channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO, 0 }, +#endif }; -const 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, - .capabilities = AV_CODEC_CAP_DR1, +const FFCodec ff_libcodec2_encoder = { + .p.name = "libcodec2", + .p.long_name = NULL_IF_CONFIG_SMALL("codec2 encoder using libcodec2"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_CODEC2, + .p.capabilities = AV_CODEC_CAP_DR1, + .p.supported_samplerates = (const int[]){ 8000, 0 }, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, + .p.ch_layouts = (const AVChannelLayout[]) { AV_CHANNEL_LAYOUT_MONO, { 0 } }, + .p.priv_class = &libcodec2_enc_class, .priv_data_size = sizeof(LibCodec2Context), .init = libcodec2_init_encoder, .close = libcodec2_close, - .encode2 = libcodec2_encode, - .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, + FF_CODEC_ENCODE_CB(libcodec2_encode), +#if FF_API_OLD_CHANNEL_LAYOUT + .p.channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO, 0 }, +#endif }; diff --git a/libavcodec/libdav1d.c b/libavcodec/libdav1d.c index 872e60e00..0a46cf226 100644 --- a/libavcodec/libdav1d.c +++ b/libavcodec/libdav1d.c @@ -31,6 +31,7 @@ #include "atsc_a53.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "decode.h" #include "internal.h" @@ -381,7 +382,8 @@ static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame) #if FF_DAV1D_VERSION_AT_LEAST(5,1) dav1d_get_event_flags(dav1d->c, &event_flags); - if (event_flags & DAV1D_EVENT_FLAG_NEW_SEQUENCE) + if (c->pix_fmt == AV_PIX_FMT_NONE || + event_flags & DAV1D_EVENT_FLAG_NEW_SEQUENCE) #endif libdav1d_init_params(c, p->seq_hdr); res = ff_decode_frame_props(c, frame); @@ -572,19 +574,19 @@ static const AVClass libdav1d_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_libdav1d_decoder = { - .name = "libdav1d", - .long_name = NULL_IF_CONFIG_SMALL("dav1d AV1 decoder by VideoLAN"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_AV1, +const FFCodec ff_libdav1d_decoder = { + .p.name = "libdav1d", + .p.long_name = NULL_IF_CONFIG_SMALL("dav1d AV1 decoder by VideoLAN"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_AV1, .priv_data_size = sizeof(Libdav1dContext), .init = libdav1d_init, .close = libdav1d_close, .flush = libdav1d_flush, - .receive_frame = libdav1d_receive_frame, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS, + FF_CODEC_RECEIVE_FRAME_CB(libdav1d_receive_frame), + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_SETS_PKT_DTS | FF_CODEC_CAP_AUTO_THREADS, - .priv_class = &libdav1d_class, - .wrapper_name = "libdav1d", + .p.priv_class = &libdav1d_class, + .p.wrapper_name = "libdav1d", }; diff --git a/libavcodec/libdavs2.c b/libavcodec/libdavs2.c index a1672d1c9..918e48502 100644 --- a/libavcodec/libdavs2.c +++ b/libavcodec/libdavs2.c @@ -24,7 +24,8 @@ #include "libavutil/cpu.h" #include "avcodec.h" -#include "internal.h" +#include "codec_internal.h" +#include "avs2.h" #include "davs2.h" typedef struct DAVS2Context { @@ -78,8 +79,15 @@ static int davs2_dump_frames(AVCodecContext *avctx, davs2_picture_t *pic, int *g avctx->height = headerset->height; avctx->pix_fmt = headerset->output_bit_depth == 10 ? AV_PIX_FMT_YUV420P10 : AV_PIX_FMT_YUV420P; + /* It should be picture_reorder_delay, but libdavs2 doesn't export that + * info. + * Use FFMAX since has_b_frames could be set by AVS2 parser in theory, + * which doesn't do it yet. + */ + avctx->has_b_frames = FFMAX(avctx->has_b_frames, !headerset->low_delay); - avctx->framerate = av_d2q(headerset->frame_rate,4096); + if (headerset->frame_rate_id < 16) + avctx->framerate = ff_avs2_frame_rate_tab[headerset->frame_rate_id]; *got_frame = 0; return 0; } @@ -169,6 +177,7 @@ static av_cold int davs2_end(AVCodecContext *avctx) /* close the decoder */ if (cad->decoder) { + davs2_flush(avctx); davs2_decoder_close(cad->decoder); cad->decoder = NULL; } @@ -176,13 +185,12 @@ static av_cold int davs2_end(AVCodecContext *avctx) return 0; } -static int davs2_decode_frame(AVCodecContext *avctx, void *data, +static int davs2_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt) { DAVS2Context *cad = avctx->priv_data; int buf_size = avpkt->size; - uint8_t *buf_ptr = avpkt->data; - AVFrame *frame = data; + const uint8_t *buf_ptr = avpkt->data; int ret = DAVS2_DEFAULT; /* end of stream, output what is still in the buffers */ @@ -213,19 +221,19 @@ static int davs2_decode_frame(AVCodecContext *avctx, void *data, return ret == 0 ? buf_size : ret; } -const AVCodec ff_libdavs2_decoder = { - .name = "libdavs2", - .long_name = NULL_IF_CONFIG_SMALL("libdavs2 AVS2-P2/IEEE1857.4"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_AVS2, +const FFCodec ff_libdavs2_decoder = { + .p.name = "libdavs2", + .p.long_name = NULL_IF_CONFIG_SMALL("libdavs2 AVS2-P2/IEEE1857.4"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_AVS2, .priv_data_size = sizeof(DAVS2Context), .init = davs2_init, .close = davs2_end, - .decode = davs2_decode_frame, + FF_CODEC_DECODE_CB(davs2_decode_frame), .flush = davs2_flush, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS, + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS, .caps_internal = FF_CODEC_CAP_AUTO_THREADS, - .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, - .wrapper_name = "libdavs2", + .p.wrapper_name = "libdavs2", }; diff --git a/libavcodec/libfdk-aacdec.c b/libavcodec/libfdk-aacdec.c index ffa1fdcce..11eee51a9 100644 --- a/libavcodec/libfdk-aacdec.c +++ b/libavcodec/libfdk-aacdec.c @@ -23,6 +23,7 @@ #include "libavutil/common.h" #include "libavutil/opt.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #ifdef AACDECODER_LIB_VL0 @@ -56,8 +57,14 @@ typedef struct FDKAACDecContext { int drc_heavy; int drc_effect; int drc_cut; + int album_mode; int level_limit; - int output_delay; +#if FDKDEC_VER_AT_LEAST(2, 5) // 2.5.10 + int output_delay_set; + int flush_samples; + int delay_samples; +#endif + AVChannelLayout downmix_layout; } FDKAACDecContext; @@ -88,6 +95,11 @@ static const AVOption fdk_aac_dec_options[] = { { "drc_effect","Dynamic Range Control: effect type, where e.g. [0] is none and [6] is general", OFFSET(drc_effect), AV_OPT_TYPE_INT, { .i64 = -1}, -1, 8, AD, NULL }, #endif +#if FDKDEC_VER_AT_LEAST(3, 1) // 3.1.0 + { "album_mode","Dynamic Range Control: album mode, where [0] is off and [1] is on", + OFFSET(album_mode), AV_OPT_TYPE_INT, { .i64 = -1}, -1, 1, AD, NULL }, +#endif + { "downmix", "Request a specific channel layout from the decoder", OFFSET(downmix_layout), AV_OPT_TYPE_CHLAYOUT, {.str = NULL}, .flags = AD }, { NULL } }; @@ -118,7 +130,12 @@ static int get_stream_info(AVCodecContext *avctx) avctx->sample_rate = info->sampleRate; avctx->frame_size = info->frameSize; #if FDKDEC_VER_AT_LEAST(2, 5) // 2.5.10 - s->output_delay = info->outputDelay; + if (!s->output_delay_set && info->outputDelay) { + // Set this only once. + s->flush_samples = info->outputDelay; + s->delay_samples = info->outputDelay; + s->output_delay_set = 1; + } #endif for (i = 0; i < info->numChannels; i++) { @@ -197,17 +214,15 @@ static int get_stream_info(AVCodecContext *avctx) ch_error = 1; } } - if (!ch_error && - av_get_channel_layout_nb_channels(ch_layout) != info->numChannels) { + + av_channel_layout_uninit(&avctx->ch_layout); + av_channel_layout_from_mask(&avctx->ch_layout, ch_layout); + if (!ch_error && avctx->ch_layout.nb_channels != info->numChannels) { av_log(avctx, AV_LOG_WARNING, "unsupported channel configuration\n"); ch_error = 1; } if (ch_error) - avctx->channel_layout = 0; - else - avctx->channel_layout = ch_layout; - - avctx->channels = info->numChannels; + avctx->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; return 0; } @@ -249,11 +264,19 @@ static av_cold int fdk_aac_decode_init(AVCodecContext *avctx) return AVERROR_UNKNOWN; } - if (avctx->request_channel_layout > 0 && - avctx->request_channel_layout != AV_CH_LAYOUT_NATIVE) { +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->request_channel_layout) { + av_channel_layout_uninit(&s->downmix_layout); + av_channel_layout_from_mask(&s->downmix_layout, avctx->request_channel_layout); + } +FF_ENABLE_DEPRECATION_WARNINGS +#endif + if (s->downmix_layout.nb_channels > 0 && + s->downmix_layout.order != AV_CHANNEL_ORDER_NATIVE) { int downmix_channels = -1; - switch (avctx->request_channel_layout) { + switch (s->downmix_layout.u.mask) { case AV_CH_LAYOUT_STEREO: case AV_CH_LAYOUT_STEREO_DOWNMIX: downmix_channels = 2; @@ -262,7 +285,7 @@ static av_cold int fdk_aac_decode_init(AVCodecContext *avctx) downmix_channels = 1; break; default: - av_log(avctx, AV_LOG_WARNING, "Invalid request_channel_layout\n"); + av_log(avctx, AV_LOG_WARNING, "Invalid downmix option\n"); break; } @@ -335,6 +358,15 @@ static av_cold int fdk_aac_decode_init(AVCodecContext *avctx) } #endif +#if FDKDEC_VER_AT_LEAST(3, 1) // 3.1.0 + if (s->album_mode != -1) { + if (aacDecoder_SetParam(s->handle, AAC_UNIDRC_ALBUM_MODE, s->album_mode) != AAC_DEC_OK) { + av_log(avctx, AV_LOG_ERROR, "Unable to set album mode in the decoder\n"); + return AVERROR_UNKNOWN; + } + } +#endif + avctx->sample_fmt = AV_SAMPLE_FMT_S16; s->decoder_buffer_size = DECODER_BUFFSIZE * DECODER_MAX_CHANNELS; @@ -345,22 +377,38 @@ static av_cold int fdk_aac_decode_init(AVCodecContext *avctx) return 0; } -static int fdk_aac_decode_frame(AVCodecContext *avctx, void *data, +static int fdk_aac_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { FDKAACDecContext *s = avctx->priv_data; - AVFrame *frame = data; int ret; AAC_DECODER_ERROR err; UINT valid = avpkt->size; + UINT flags = 0; + int input_offset = 0; - err = aacDecoder_Fill(s->handle, &avpkt->data, &avpkt->size, &valid); - if (err != AAC_DEC_OK) { - av_log(avctx, AV_LOG_ERROR, "aacDecoder_Fill() failed: %x\n", err); - return AVERROR_INVALIDDATA; + if (avpkt->size) { + err = aacDecoder_Fill(s->handle, &avpkt->data, &avpkt->size, &valid); + if (err != AAC_DEC_OK) { + av_log(avctx, AV_LOG_ERROR, "aacDecoder_Fill() failed: %x\n", err); + return AVERROR_INVALIDDATA; + } + } else { +#if FDKDEC_VER_AT_LEAST(2, 5) // 2.5.10 + /* Handle decoder draining */ + if (s->flush_samples > 0) { + flags |= AACDEC_FLUSH; + } else { + return AVERROR_EOF; + } +#else + return AVERROR_EOF; +#endif } - err = aacDecoder_DecodeFrame(s->handle, (INT_PCM *) s->decoder_buffer, s->decoder_buffer_size / sizeof(INT_PCM), 0); + err = aacDecoder_DecodeFrame(s->handle, (INT_PCM *) s->decoder_buffer, + s->decoder_buffer_size / sizeof(INT_PCM), + flags); if (err == AAC_DEC_NOT_ENOUGH_BITS) { ret = avpkt->size - valid; goto end; @@ -376,16 +424,36 @@ static int fdk_aac_decode_frame(AVCodecContext *avctx, void *data, goto end; frame->nb_samples = avctx->frame_size; +#if FDKDEC_VER_AT_LEAST(2, 5) // 2.5.10 + if (flags & AACDEC_FLUSH) { + // Only return the right amount of samples at the end; if calling the + // decoder with AACDEC_FLUSH, it will keep returning frames indefinitely. + frame->nb_samples = FFMIN(s->flush_samples, frame->nb_samples); + av_log(s, AV_LOG_DEBUG, "Returning %d/%d delayed samples.\n", + frame->nb_samples, s->flush_samples); + s->flush_samples -= frame->nb_samples; + } else { + // Trim off samples from the start to compensate for extra decoder + // delay. We could also just adjust the pts, but this avoids + // including the extra samples in the output altogether. + if (s->delay_samples) { + int drop_samples = FFMIN(s->delay_samples, frame->nb_samples); + av_log(s, AV_LOG_DEBUG, "Dropping %d/%d delayed samples.\n", + drop_samples, s->delay_samples); + s->delay_samples -= drop_samples; + frame->nb_samples -= drop_samples; + input_offset = drop_samples * avctx->ch_layout.nb_channels; + if (frame->nb_samples <= 0) + return 0; + } + } +#endif + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) goto end; - if (frame->pts != AV_NOPTS_VALUE) - frame->pts -= av_rescale_q(s->output_delay, - (AVRational){1, avctx->sample_rate}, - avctx->time_base); - - memcpy(frame->extended_data[0], s->decoder_buffer, - avctx->channels * avctx->frame_size * + memcpy(frame->extended_data[0], s->decoder_buffer + input_offset, + avctx->ch_layout.nb_channels * frame->nb_samples * av_get_bytes_per_sample(avctx->sample_fmt)); *got_frame_ptr = 1; @@ -408,19 +476,23 @@ static av_cold void fdk_aac_decode_flush(AVCodecContext *avctx) av_log(avctx, AV_LOG_WARNING, "failed to clear buffer when flushing\n"); } -const AVCodec ff_libfdk_aac_decoder = { - .name = "libfdk_aac", - .long_name = NULL_IF_CONFIG_SMALL("Fraunhofer FDK AAC"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_AAC, +const FFCodec ff_libfdk_aac_decoder = { + .p.name = "libfdk_aac", + .p.long_name = NULL_IF_CONFIG_SMALL("Fraunhofer FDK AAC"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_AAC, .priv_data_size = sizeof(FDKAACDecContext), .init = fdk_aac_decode_init, - .decode = fdk_aac_decode_frame, + FF_CODEC_DECODE_CB(fdk_aac_decode_frame), .close = fdk_aac_decode_close, .flush = fdk_aac_decode_flush, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, - .priv_class = &fdk_aac_dec_class, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF +#if FDKDEC_VER_AT_LEAST(2, 5) // 2.5.10 + | AV_CODEC_CAP_DELAY +#endif + , + .p.priv_class = &fdk_aac_dec_class, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .wrapper_name = "libfdk", + .p.wrapper_name = "libfdk", }; diff --git a/libavcodec/libfdk-aacenc.c b/libavcodec/libfdk-aacenc.c index 7ee2f13ac..a5697bde5 100644 --- a/libavcodec/libfdk-aacenc.c +++ b/libavcodec/libfdk-aacenc.c @@ -24,8 +24,8 @@ #include "libavutil/opt.h" #include "avcodec.h" #include "audio_frame_queue.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "profiles.h" #ifdef AACENCODER_LIB_VL0 @@ -128,7 +128,7 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) int aot = FF_PROFILE_AAC_LOW + 1; int sce = 0, cpe = 0; - if ((err = aacEncOpen(&s->handle, 0, avctx->channels)) != AACENC_OK) { + if ((err = aacEncOpen(&s->handle, 0, avctx->ch_layout.nb_channels)) != AACENC_OK) { av_log(avctx, AV_LOG_ERROR, "Unable to open the encoder: %s\n", aac_get_error(err)); goto error; @@ -159,7 +159,7 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) goto error; } - switch (avctx->channels) { + switch (avctx->ch_layout.nb_channels) { case 1: mode = MODE_1; sce = 1; cpe = 0; break; case 2: #if FDKENC_VER_AT_LEAST(4, 0) // 4.0.0 @@ -193,7 +193,7 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) case 8: sce = 2; cpe = 3; - if (avctx->channel_layout == AV_CH_LAYOUT_7POINT1) { + if (!av_channel_layout_compare(&avctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_7POINT1)) { mode = MODE_7_1_REAR_SURROUND; } else { // MODE_1_2_2_2_1 and MODE_7_1_FRONT_CENTER use the same channel layout @@ -203,7 +203,7 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) #endif default: av_log(avctx, AV_LOG_ERROR, - "Unsupported number of channels %d\n", avctx->channels); + "Unsupported number of channels %d\n", avctx->ch_layout.nb_channels); goto error; } @@ -375,9 +375,9 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, in_args.numInSamples = -1; } else { in_ptr = frame->data[0]; - in_buffer_size = 2 * avctx->channels * frame->nb_samples; + in_buffer_size = 2 * avctx->ch_layout.nb_channels * frame->nb_samples; - in_args.numInSamples = avctx->channels * frame->nb_samples; + in_args.numInSamples = avctx->ch_layout.nb_channels * frame->nb_samples; /* add current frame to the queue */ if ((ret = ff_af_queue_add(&s->afq, frame)) < 0) @@ -392,7 +392,7 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, in_buf.bufElSizes = &in_buffer_element_size; /* The maximum packet size is 6144 bits aka 768 bytes per channel. */ - ret = ff_alloc_packet(avctx, avpkt, FFMAX(8192, 768 * avctx->channels)); + ret = ff_alloc_packet(avctx, avpkt, FFMAX(8192, 768 * avctx->ch_layout.nb_channels)); if (ret < 0) return ret; @@ -435,11 +435,12 @@ static const AVProfile profiles[] = { { FF_PROFILE_UNKNOWN }, }; -static const AVCodecDefault aac_encode_defaults[] = { +static const FFCodecDefault aac_encode_defaults[] = { { "b", "0" }, { NULL } }; +#if FF_API_OLD_CHANNEL_LAYOUT static const uint64_t aac_channel_layout[] = { AV_CH_LAYOUT_MONO, AV_CH_LAYOUT_STEREO, @@ -453,28 +454,46 @@ static const uint64_t aac_channel_layout[] = { #endif 0, }; +#endif /* FF_API_OLD_CHANNEL_LAYOUT */ + +static const AVChannelLayout aac_ch_layouts[16] = { + AV_CHANNEL_LAYOUT_MONO, + AV_CHANNEL_LAYOUT_STEREO, + AV_CHANNEL_LAYOUT_SURROUND, + AV_CHANNEL_LAYOUT_4POINT0, + AV_CHANNEL_LAYOUT_5POINT0_BACK, + AV_CHANNEL_LAYOUT_5POINT1_BACK, +#ifdef AACENCODER_LIB_VL0 + AV_CHANNEL_LAYOUT_7POINT1_WIDE_BACK, + AV_CHANNEL_LAYOUT_7POINT1, +#endif + { 0 }, +}; static const int aac_sample_rates[] = { 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 0 }; -const AVCodec ff_libfdk_aac_encoder = { - .name = "libfdk_aac", - .long_name = NULL_IF_CONFIG_SMALL("Fraunhofer FDK AAC"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_AAC, +const FFCodec ff_libfdk_aac_encoder = { + .p.name = "libfdk_aac", + .p.long_name = NULL_IF_CONFIG_SMALL("Fraunhofer FDK AAC"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_AAC, .priv_data_size = sizeof(AACContext), .init = aac_encode_init, - .encode2 = aac_encode_frame, + FF_CODEC_ENCODE_CB(aac_encode_frame), .close = aac_encode_close, - .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + .p.capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY, + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, - .priv_class = &aac_enc_class, + .p.priv_class = &aac_enc_class, .defaults = aac_encode_defaults, - .profiles = profiles, - .supported_samplerates = aac_sample_rates, - .channel_layouts = aac_channel_layout, - .wrapper_name = "libfdk", + .p.profiles = profiles, + .p.supported_samplerates = aac_sample_rates, + .p.wrapper_name = "libfdk", +#if FF_API_OLD_CHANNEL_LAYOUT + .p.channel_layouts = aac_channel_layout, +#endif + .p.ch_layouts = aac_ch_layouts, }; diff --git a/libavcodec/libgsmdec.c b/libavcodec/libgsmdec.c index ae4a952d9..9c2304f7a 100644 --- a/libavcodec/libgsmdec.c +++ b/libavcodec/libgsmdec.c @@ -28,6 +28,7 @@ // The idiosyncrasies of GSM-in-WAV are explained at http://kbs.cs.tu-berlin.de/~jutta/toast.html #include "config.h" +#include "config_components.h" #if HAVE_GSM_H #include #else @@ -38,6 +39,7 @@ #include "libavutil/common.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "gsm.h" @@ -48,8 +50,8 @@ typedef struct LibGSMDecodeContext { static av_cold int libgsm_decode_init(AVCodecContext *avctx) { LibGSMDecodeContext *s = avctx->priv_data; - avctx->channels = 1; - avctx->channel_layout = AV_CH_LAYOUT_MONO; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; if (!avctx->sample_rate) avctx->sample_rate = 8000; avctx->sample_fmt = AV_SAMPLE_FMT_S16; @@ -80,12 +82,11 @@ static av_cold int libgsm_decode_close(AVCodecContext *avctx) { return 0; } -static int libgsm_decode_frame(AVCodecContext *avctx, void *data, +static int libgsm_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { int i, ret; LibGSMDecodeContext *s = avctx->priv_data; - AVFrame *frame = data; uint8_t *buf = avpkt->data; int buf_size = avpkt->size; int16_t *samples; @@ -124,32 +125,32 @@ static void libgsm_flush(AVCodecContext *avctx) { } #if CONFIG_LIBGSM_DECODER -const AVCodec ff_libgsm_decoder = { - .name = "libgsm", - .long_name = NULL_IF_CONFIG_SMALL("libgsm GSM"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_GSM, +const FFCodec ff_libgsm_decoder = { + .p.name = "libgsm", + .p.long_name = NULL_IF_CONFIG_SMALL("libgsm GSM"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_GSM, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .p.wrapper_name = "libgsm", .priv_data_size = sizeof(LibGSMDecodeContext), .init = libgsm_decode_init, .close = libgsm_decode_close, - .decode = libgsm_decode_frame, + FF_CODEC_DECODE_CB(libgsm_decode_frame), .flush = libgsm_flush, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, - .wrapper_name = "libgsm", }; #endif #if CONFIG_LIBGSM_MS_DECODER -const AVCodec ff_libgsm_ms_decoder = { - .name = "libgsm_ms", - .long_name = NULL_IF_CONFIG_SMALL("libgsm GSM Microsoft variant"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_GSM_MS, +const FFCodec ff_libgsm_ms_decoder = { + .p.name = "libgsm_ms", + .p.long_name = NULL_IF_CONFIG_SMALL("libgsm GSM Microsoft variant"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_GSM_MS, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .p.wrapper_name = "libgsm", .priv_data_size = sizeof(LibGSMDecodeContext), .init = libgsm_decode_init, .close = libgsm_decode_close, - .decode = libgsm_decode_frame, + FF_CODEC_DECODE_CB(libgsm_decode_frame), .flush = libgsm_flush, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, - .wrapper_name = "libgsm", }; #endif diff --git a/libavcodec/libgsmenc.c b/libavcodec/libgsmenc.c index a2f6c1c62..a45b77be9 100644 --- a/libavcodec/libgsmenc.c +++ b/libavcodec/libgsmenc.c @@ -28,6 +28,7 @@ // The idiosyncrasies of GSM-in-WAV are explained at http://kbs.cs.tu-berlin.de/~jutta/toast.html #include "config.h" +#include "config_components.h" #if HAVE_GSM_H #include #else @@ -38,8 +39,8 @@ #include "libavutil/common.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "gsm.h" static av_cold int libgsm_encode_close(AVCodecContext *avctx) { @@ -49,12 +50,6 @@ static av_cold int libgsm_encode_close(AVCodecContext *avctx) { } static av_cold int libgsm_encode_init(AVCodecContext *avctx) { - if (avctx->channels > 1) { - av_log(avctx, AV_LOG_ERROR, "Mono required for GSM, got %d channels\n", - avctx->channels); - return -1; - } - if (avctx->sample_rate != 8000) { av_log(avctx, AV_LOG_ERROR, "Sample rate 8000Hz required for GSM, got %dHz\n", avctx->sample_rate); @@ -116,42 +111,48 @@ static int libgsm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, return 0; } -static const AVCodecDefault libgsm_defaults[] = { +static const FFCodecDefault libgsm_defaults[] = { { "b", "13000" }, { NULL }, }; #if CONFIG_LIBGSM_ENCODER -const AVCodec ff_libgsm_encoder = { - .name = "libgsm", - .long_name = NULL_IF_CONFIG_SMALL("libgsm GSM"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_GSM, - .capabilities = AV_CODEC_CAP_DR1, +const FFCodec ff_libgsm_encoder = { + .p.name = "libgsm", + .p.long_name = NULL_IF_CONFIG_SMALL("libgsm GSM"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_GSM, + .p.capabilities = AV_CODEC_CAP_DR1, .init = libgsm_encode_init, - .encode2 = libgsm_encode_frame, + FF_CODEC_ENCODE_CB(libgsm_encode_frame), .close = libgsm_encode_close, .defaults = libgsm_defaults, - .channel_layouts= (const uint64_t[]) { AV_CH_LAYOUT_MONO, 0 }, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, +#if FF_API_OLD_CHANNEL_LAYOUT + .p.channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO, 0 }, +#endif + .p.ch_layouts = (const AVChannelLayout[]) { AV_CHANNEL_LAYOUT_MONO, { 0 } }, + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, - .wrapper_name = "libgsm", + .p.wrapper_name = "libgsm", }; #endif #if CONFIG_LIBGSM_MS_ENCODER -const AVCodec ff_libgsm_ms_encoder = { - .name = "libgsm_ms", - .long_name = NULL_IF_CONFIG_SMALL("libgsm GSM Microsoft variant"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_GSM_MS, - .capabilities = AV_CODEC_CAP_DR1, +const FFCodec ff_libgsm_ms_encoder = { + .p.name = "libgsm_ms", + .p.long_name = NULL_IF_CONFIG_SMALL("libgsm GSM Microsoft variant"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_GSM_MS, + .p.capabilities = AV_CODEC_CAP_DR1, .init = libgsm_encode_init, - .encode2 = libgsm_encode_frame, + FF_CODEC_ENCODE_CB(libgsm_encode_frame), .close = libgsm_encode_close, .defaults = libgsm_defaults, - .channel_layouts= (const uint64_t[]) { AV_CH_LAYOUT_MONO, 0 }, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, +#if FF_API_OLD_CHANNEL_LAYOUT + .p.channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO, 0 }, +#endif + .p.ch_layouts = (const AVChannelLayout[]) { AV_CHANNEL_LAYOUT_MONO, { 0 } }, + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, - .wrapper_name = "libgsm", + .p.wrapper_name = "libgsm", }; #endif diff --git a/libavcodec/libilbc.c b/libavcodec/libilbc.c index 04192e304..a7b1eaf28 100644 --- a/libavcodec/libilbc.c +++ b/libavcodec/libilbc.c @@ -25,6 +25,7 @@ #include "libavutil/common.h" #include "libavutil/opt.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" #include "internal.h" @@ -78,21 +79,20 @@ static av_cold int ilbc_decode_init(AVCodecContext *avctx) WebRtcIlbcfix_InitDecode(&s->decoder, mode, s->enhance); - avctx->channels = 1; - avctx->channel_layout = AV_CH_LAYOUT_MONO; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; avctx->sample_rate = 8000; avctx->sample_fmt = AV_SAMPLE_FMT_S16; return 0; } -static int ilbc_decode_frame(AVCodecContext *avctx, void *data, +static int ilbc_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; ILBCDecContext *s = avctx->priv_data; - AVFrame *frame = data; int ret; if (s->decoder.no_of_bytes > buf_size) { @@ -117,16 +117,16 @@ static int ilbc_decode_frame(AVCodecContext *avctx, void *data, return s->decoder.no_of_bytes; } -const AVCodec ff_libilbc_decoder = { - .name = "libilbc", - .long_name = NULL_IF_CONFIG_SMALL("iLBC (Internet Low Bitrate Codec)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_ILBC, +const FFCodec ff_libilbc_decoder = { + .p.name = "libilbc", + .p.long_name = NULL_IF_CONFIG_SMALL("iLBC (Internet Low Bitrate Codec)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_ILBC, .priv_data_size = sizeof(ILBCDecContext), .init = ilbc_decode_init, - .decode = ilbc_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, - .priv_class = &ilbc_dec_class, + FF_CODEC_DECODE_CB(ilbc_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .p.priv_class = &ilbc_dec_class, }; typedef struct ILBCEncContext { @@ -161,7 +161,7 @@ static av_cold int ilbc_encode_init(AVCodecContext *avctx) return AVERROR(EINVAL); } - if (avctx->channels != 1) { + if (avctx->ch_layout.nb_channels != 1) { av_log(avctx, AV_LOG_ERROR, "Only mono supported\n"); return AVERROR(EINVAL); } @@ -194,22 +194,22 @@ static int ilbc_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, return 0; } -static const AVCodecDefault ilbc_encode_defaults[] = { +static const FFCodecDefault ilbc_encode_defaults[] = { { "b", "0" }, { NULL } }; -const AVCodec ff_libilbc_encoder = { - .name = "libilbc", - .long_name = NULL_IF_CONFIG_SMALL("iLBC (Internet Low Bitrate Codec)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_ILBC, +const FFCodec ff_libilbc_encoder = { + .p.name = "libilbc", + .p.long_name = NULL_IF_CONFIG_SMALL("iLBC (Internet Low Bitrate Codec)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_ILBC, .priv_data_size = sizeof(ILBCEncContext), .init = ilbc_encode_init, - .encode2 = ilbc_encode_frame, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + FF_CODEC_ENCODE_CB(ilbc_encode_frame), + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, .defaults = ilbc_encode_defaults, - .priv_class = &ilbc_enc_class, - .wrapper_name = "libbilbc", + .p.priv_class = &ilbc_enc_class, + .p.wrapper_name = "libbilbc", }; diff --git a/libavcodec/libjxl.c b/libavcodec/libjxl.c new file mode 100644 index 000000000..204d91d8a --- /dev/null +++ b/libavcodec/libjxl.c @@ -0,0 +1,70 @@ +/* + * JPEG XL de/encoding via libjxl, common support implementation + * Copyright (c) 2021 Leo Izen + * + * 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 + * JPEG XL via libjxl common support implementation + */ + +#include "libavutil/cpu.h" +#include "libavutil/mem.h" + +#include +#include "libjxl.h" + +size_t ff_libjxl_get_threadcount(int threads) +{ + if (threads <= 0) + return av_cpu_count(); + if (threads == 1) + return 0; + return threads; +} + +/** + * Wrapper around av_malloc used as a jpegxl_alloc_func. + * + * @param opaque opaque pointer for jpegxl_alloc_func, always ignored + * @param size Size in bytes for the memory block to be allocated + * @return Pointer to the allocated block, or `NULL` if it cannot be allocated + */ +static void *libjxl_av_malloc(void *opaque, size_t size) +{ + return av_malloc(size); +} + +/** + * Wrapper around av_free used as a jpegxl_free_func. + * + * @param opaque opaque pointer for jpegxl_free_func, always ignored + * @param address Pointer to the allocated block, to free. `NULL` permitted as a no-op. + */ +static void libjxl_av_free(void *opaque, void *address) +{ + av_free(address); +} + +void ff_libjxl_init_memory_manager(JxlMemoryManager *manager) +{ + manager->opaque = NULL; + manager->alloc = &libjxl_av_malloc; + manager->free = &libjxl_av_free; +} diff --git a/libavcodec/libjxl.h b/libavcodec/libjxl.h new file mode 100644 index 000000000..5387c438f --- /dev/null +++ b/libavcodec/libjxl.h @@ -0,0 +1,48 @@ +/* + * JPEG XL de/encoding via libjxl, common support header + * Copyright (c) 2021 Leo Izen + * + * 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 + * JPEG XL via libjxl common support header + */ + +#ifndef AVCODEC_LIBJXL_H +#define AVCODEC_LIBJXL_H + +#include + +/** + * Transform threadcount in ffmpeg to one used by libjxl. + * + * @param threads ffmpeg's threads AVOption + * @return thread count for libjxl's parallel runner + */ +size_t ff_libjxl_get_threadcount(int threads); + +/** + * Initialize and populate a JxlMemoryManager + * with av_malloc() and av_free() so libjxl will use these + * functions. + * @param manager a pointer to a JxlMemoryManager struct + */ +void ff_libjxl_init_memory_manager(JxlMemoryManager *manager); + +#endif /* AVCODEC_LIBJXL_H */ diff --git a/libavcodec/libjxldec.c b/libavcodec/libjxldec.c new file mode 100644 index 000000000..829478bbd --- /dev/null +++ b/libavcodec/libjxldec.c @@ -0,0 +1,460 @@ +/* + * JPEG XL decoding support via libjxl + * Copyright (c) 2021 Leo Izen + * + * 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 + * JPEG XL decoder using libjxl + */ + +#include "libavutil/avassert.h" +#include "libavutil/buffer.h" +#include "libavutil/common.h" +#include "libavutil/csp.h" +#include "libavutil/error.h" +#include "libavutil/mem.h" +#include "libavutil/pixdesc.h" +#include "libavutil/pixfmt.h" +#include "libavutil/frame.h" + +#include "avcodec.h" +#include "codec_internal.h" +#include "internal.h" + +#include +#include +#include "libjxl.h" + +typedef struct LibJxlDecodeContext { + void *runner; + JxlDecoder *decoder; + JxlBasicInfo basic_info; + JxlPixelFormat jxl_pixfmt; + JxlDecoderStatus events; + AVBufferRef *iccp; +} LibJxlDecodeContext; + +static int libjxl_init_jxl_decoder(AVCodecContext *avctx) +{ + LibJxlDecodeContext *ctx = avctx->priv_data; + + ctx->events = JXL_DEC_BASIC_INFO | JXL_DEC_FULL_IMAGE | JXL_DEC_COLOR_ENCODING; + if (JxlDecoderSubscribeEvents(ctx->decoder, ctx->events) != JXL_DEC_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Error subscribing to JXL events\n"); + return AVERROR_EXTERNAL; + } + + if (JxlDecoderSetParallelRunner(ctx->decoder, JxlThreadParallelRunner, ctx->runner) != JXL_DEC_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to set JxlThreadParallelRunner\n"); + return AVERROR_EXTERNAL; + } + + memset(&ctx->basic_info, 0, sizeof(JxlBasicInfo)); + memset(&ctx->jxl_pixfmt, 0, sizeof(JxlPixelFormat)); + + return 0; +} + +static av_cold int libjxl_decode_init(AVCodecContext *avctx) +{ + LibJxlDecodeContext *ctx = avctx->priv_data; + JxlMemoryManager manager; + + ff_libjxl_init_memory_manager(&manager); + ctx->decoder = JxlDecoderCreate(&manager); + if (!ctx->decoder) { + av_log(avctx, AV_LOG_ERROR, "Failed to create JxlDecoder\n"); + return AVERROR_EXTERNAL; + } + + ctx->runner = JxlThreadParallelRunnerCreate(&manager, ff_libjxl_get_threadcount(avctx->thread_count)); + if (!ctx->runner) { + av_log(avctx, AV_LOG_ERROR, "Failed to create JxlThreadParallelRunner\n"); + return AVERROR_EXTERNAL; + } + + return libjxl_init_jxl_decoder(avctx); +} + +static enum AVPixelFormat libjxl_get_pix_fmt(void *avctx, const JxlBasicInfo *basic_info, JxlPixelFormat *format) +{ + format->endianness = JXL_NATIVE_ENDIAN; + format->num_channels = basic_info->num_color_channels + (basic_info->alpha_bits > 0); + /* Gray */ + if (basic_info->num_color_channels == 1) { + if (basic_info->bits_per_sample <= 8) { + format->data_type = JXL_TYPE_UINT8; + return basic_info->alpha_bits ? AV_PIX_FMT_YA8 : AV_PIX_FMT_GRAY8; + } + if (basic_info->exponent_bits_per_sample || basic_info->bits_per_sample > 16) { + if (basic_info->alpha_bits) + return AV_PIX_FMT_NONE; + format->data_type = JXL_TYPE_FLOAT; + return AV_PIX_FMT_GRAYF32; + } + format->data_type = JXL_TYPE_UINT16; + return basic_info->alpha_bits ? AV_PIX_FMT_YA16 : AV_PIX_FMT_GRAY16; + } + /* rgb only */ + /* libjxl only supports packed RGB and gray output at the moment */ + if (basic_info->num_color_channels == 3) { + if (basic_info->bits_per_sample <= 8) { + format->data_type = JXL_TYPE_UINT8; + return basic_info->alpha_bits ? AV_PIX_FMT_RGBA : AV_PIX_FMT_RGB24; + } + if (basic_info->bits_per_sample > 16) + av_log(avctx, AV_LOG_WARNING, "Downsampling larger integer to 16-bit via libjxl\n"); + if (basic_info->exponent_bits_per_sample) + av_log(avctx, AV_LOG_WARNING, "Downsampling float to 16-bit integer via libjxl\n"); + format->data_type = JXL_TYPE_UINT16; + return basic_info->alpha_bits ? AV_PIX_FMT_RGBA64 : AV_PIX_FMT_RGB48; + } + + return AV_PIX_FMT_NONE; +} + +static enum AVColorPrimaries libjxl_get_primaries(void *avctx, const JxlColorEncoding *jxl_color) +{ + AVColorPrimariesDesc desc; + enum AVColorPrimaries prim; + + /* libjxl populates these double values even if it uses an enum space */ + desc.prim.r.x = av_d2q(jxl_color->primaries_red_xy[0], 300000); + desc.prim.r.y = av_d2q(jxl_color->primaries_red_xy[1], 300000); + desc.prim.g.x = av_d2q(jxl_color->primaries_green_xy[0], 300000); + desc.prim.g.y = av_d2q(jxl_color->primaries_green_xy[1], 300000); + desc.prim.b.x = av_d2q(jxl_color->primaries_blue_xy[0], 300000); + desc.prim.b.y = av_d2q(jxl_color->primaries_blue_xy[1], 300000); + desc.wp.x = av_d2q(jxl_color->white_point_xy[0], 300000); + desc.wp.y = av_d2q(jxl_color->white_point_xy[1], 300000); + + prim = av_csp_primaries_id_from_desc(&desc); + if (prim == AVCOL_PRI_UNSPECIFIED) { + /* try D65 with the same primaries */ + /* BT.709 uses D65 white point */ + desc.wp = av_csp_primaries_desc_from_id(AVCOL_PRI_BT709)->wp; + av_log(avctx, AV_LOG_WARNING, "Changing unknown white point to D65\n"); + prim = av_csp_primaries_id_from_desc(&desc); + } + + return prim; +} + +static enum AVColorTransferCharacteristic libjxl_get_trc(void *avctx, const JxlColorEncoding *jxl_color) +{ + switch (jxl_color->transfer_function) { + case JXL_TRANSFER_FUNCTION_709: return AVCOL_TRC_BT709; + case JXL_TRANSFER_FUNCTION_LINEAR: return AVCOL_TRC_LINEAR; + case JXL_TRANSFER_FUNCTION_SRGB: return AVCOL_TRC_IEC61966_2_1; + case JXL_TRANSFER_FUNCTION_PQ: return AVCOL_TRC_SMPTE2084; + case JXL_TRANSFER_FUNCTION_DCI: return AVCOL_TRC_SMPTE428; + case JXL_TRANSFER_FUNCTION_HLG: return AVCOL_TRC_ARIB_STD_B67; + case JXL_TRANSFER_FUNCTION_GAMMA: + if (jxl_color->gamma > 2.199 && jxl_color->gamma < 2.201) + return AVCOL_TRC_GAMMA22; + else if (jxl_color->gamma > 2.799 && jxl_color->gamma < 2.801) + return AVCOL_TRC_GAMMA28; + else + av_log(avctx, AV_LOG_WARNING, "Unsupported gamma transfer: %f\n", jxl_color->gamma); + break; + default: + av_log(avctx, AV_LOG_WARNING, "Unknown transfer function: %d\n", jxl_color->transfer_function); + } + + return AVCOL_TRC_UNSPECIFIED; +} + +static int libjxl_get_icc(AVCodecContext *avctx) +{ + LibJxlDecodeContext *ctx = avctx->priv_data; + size_t icc_len; + JxlDecoderStatus jret; + /* an ICC profile is present, and we can meaningfully get it, + * because the pixel data is not XYB-encoded */ + jret = JxlDecoderGetICCProfileSize(ctx->decoder, &ctx->jxl_pixfmt, JXL_COLOR_PROFILE_TARGET_DATA, &icc_len); + if (jret == JXL_DEC_SUCCESS && icc_len > 0) { + av_buffer_unref(&ctx->iccp); + ctx->iccp = av_buffer_alloc(icc_len); + if (!ctx->iccp) + return AVERROR(ENOMEM); + jret = JxlDecoderGetColorAsICCProfile(ctx->decoder, &ctx->jxl_pixfmt, JXL_COLOR_PROFILE_TARGET_DATA, + ctx->iccp->data, icc_len); + if (jret != JXL_DEC_SUCCESS) { + av_log(avctx, AV_LOG_WARNING, "Unable to obtain ICC Profile\n"); + av_buffer_unref(&ctx->iccp); + } + } + + return 0; +} + +/* + * There's generally four cases when it comes to decoding a libjxl image + * with regard to color encoding: + * (a) There is an embedded ICC profile in the image, and the image is XYB-encoded. + * (b) There is an embedded ICC profile in the image, and the image is not XYB-encoded. + * (c) There is no embedded ICC profile, and FFmpeg supports the tagged colorspace. + * (d) There is no embedded ICC profile, and FFmpeg does not support the tagged colorspace. + * + * In case (b), we forward the pixel data as is and forward the ICC Profile as-is. + * In case (c), we request the pixel data in the space it's tagged as, + * and tag the space accordingly. + * In case (a), libjxl does not support getting the pixel data in the space described by the ICC + * profile, so instead we request the pixel data in BT.2020/PQ as it is the widest + * space that FFmpeg supports. + * In case (d), we also request wide-gamut pixel data as a fallback since FFmpeg doesn't support + * the custom primaries tagged in the space. + */ +static int libjxl_color_encoding_event(AVCodecContext *avctx, AVFrame *frame) +{ + LibJxlDecodeContext *ctx = avctx->priv_data; + JxlDecoderStatus jret; + int ret; + JxlColorEncoding jxl_color; + /* set this flag if we need to fall back on wide gamut */ + int fallback = 0; + + jret = JxlDecoderGetColorAsEncodedProfile(ctx->decoder, NULL, JXL_COLOR_PROFILE_TARGET_ORIGINAL, &jxl_color); + if (jret == JXL_DEC_SUCCESS) { + /* enum values describe the colors of this image */ + jret = JxlDecoderSetPreferredColorProfile(ctx->decoder, &jxl_color); + if (jret == JXL_DEC_SUCCESS) + jret = JxlDecoderGetColorAsEncodedProfile(ctx->decoder, &ctx->jxl_pixfmt, JXL_COLOR_PROFILE_TARGET_DATA, &jxl_color); + /* if we couldn't successfully request the pixel data space, we fall back on wide gamut */ + /* this code path is very unlikely to happen in practice */ + if (jret != JXL_DEC_SUCCESS) + fallback = 1; + } else { + /* an ICC Profile is present in the stream */ + if (ctx->basic_info.uses_original_profile) { + /* uses_original_profile is the same as !xyb_encoded */ + av_log(avctx, AV_LOG_VERBOSE, "Using embedded ICC Profile\n"); + if ((ret = libjxl_get_icc(avctx)) < 0) + return ret; + } else { + /* + * an XYB-encoded image with an embedded ICC profile can't always have the + * pixel data requested in the original space, so libjxl has no feature + * to allow this to happen, so we fall back on wide gamut + */ + fallback = 1; + } + } + + avctx->color_range = frame->color_range = AVCOL_RANGE_JPEG; + if (ctx->jxl_pixfmt.num_channels >= 3) + avctx->colorspace = AVCOL_SPC_RGB; + avctx->color_primaries = AVCOL_PRI_UNSPECIFIED; + avctx->color_trc = AVCOL_TRC_UNSPECIFIED; + + if (!ctx->iccp) { + /* checking enum values */ + if (!fallback) { + if (avctx->colorspace == AVCOL_SPC_RGB) + avctx->color_primaries = libjxl_get_primaries(avctx, &jxl_color); + avctx->color_trc = libjxl_get_trc(avctx, &jxl_color); + } + /* fall back on wide gamut if enum values fail */ + if (avctx->color_primaries == AVCOL_PRI_UNSPECIFIED) { + if (avctx->colorspace == AVCOL_SPC_RGB) { + av_log(avctx, AV_LOG_WARNING, "Falling back on wide gamut output\n"); + jxl_color.primaries = JXL_PRIMARIES_2100; + avctx->color_primaries = AVCOL_PRI_BT2020; + } + /* libjxl requires this set even for grayscale */ + jxl_color.white_point = JXL_WHITE_POINT_D65; + } + if (avctx->color_trc == AVCOL_TRC_UNSPECIFIED) { + if (ctx->jxl_pixfmt.data_type == JXL_TYPE_FLOAT + || ctx->jxl_pixfmt.data_type == JXL_TYPE_FLOAT16) { + av_log(avctx, AV_LOG_WARNING, "Falling back on Linear Light transfer\n"); + jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_LINEAR; + avctx->color_trc = AVCOL_TRC_LINEAR; + } else { + av_log(avctx, AV_LOG_WARNING, "Falling back on iec61966-2-1/sRGB transfer\n"); + jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_SRGB; + avctx->color_trc = AVCOL_TRC_IEC61966_2_1; + } + } + /* all colors will be in-gamut so we want accurate colors */ + jxl_color.rendering_intent = JXL_RENDERING_INTENT_RELATIVE; + jxl_color.color_space = avctx->colorspace == AVCOL_SPC_RGB ? JXL_COLOR_SPACE_RGB : JXL_COLOR_SPACE_GRAY; + jret = JxlDecoderSetPreferredColorProfile(ctx->decoder, &jxl_color); + if (jret != JXL_DEC_SUCCESS) { + av_log(avctx, AV_LOG_WARNING, "Unable to set fallback color encoding\n"); + /* + * This should only happen if there's a non-XYB encoded image with custom primaries + * embedded as enums and no embedded ICC Profile. + * In this case, libjxl will synthesize an ICC Profile for us. + */ + avctx->color_trc = AVCOL_TRC_UNSPECIFIED; + avctx->color_primaries = AVCOL_PRI_UNSPECIFIED; + if ((ret = libjxl_get_icc(avctx)) < 0) + return ret; + } + } + + frame->color_trc = avctx->color_trc; + frame->color_primaries = avctx->color_primaries; + frame->colorspace = avctx->colorspace; + + return 0; +} + +static int libjxl_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt) +{ + LibJxlDecodeContext *ctx = avctx->priv_data; + const uint8_t *buf = avpkt->data; + size_t remaining = avpkt->size; + JxlDecoderStatus jret; + int ret; + *got_frame = 0; + + while (1) { + + jret = JxlDecoderSetInput(ctx->decoder, buf, remaining); + + if (jret == JXL_DEC_ERROR) { + /* this should never happen here unless there's a bug in libjxl */ + av_log(avctx, AV_LOG_ERROR, "Unknown libjxl decode error\n"); + return AVERROR_EXTERNAL; + } + + jret = JxlDecoderProcessInput(ctx->decoder); + /* + * JxlDecoderReleaseInput returns the number + * of bytes remaining to be read, rather than + * the number of bytes that it did read + */ + remaining = JxlDecoderReleaseInput(ctx->decoder); + buf = avpkt->data + avpkt->size - remaining; + + switch(jret) { + case JXL_DEC_ERROR: + av_log(avctx, AV_LOG_ERROR, "Unknown libjxl decode error\n"); + return AVERROR_INVALIDDATA; + case JXL_DEC_NEED_MORE_INPUT: + if (remaining == 0) { + av_log(avctx, AV_LOG_ERROR, "Unexpected end of JXL codestream\n"); + return AVERROR_INVALIDDATA; + } + av_log(avctx, AV_LOG_DEBUG, "NEED_MORE_INPUT event emitted\n"); + continue; + case JXL_DEC_BASIC_INFO: + av_log(avctx, AV_LOG_DEBUG, "BASIC_INFO event emitted\n"); + if (JxlDecoderGetBasicInfo(ctx->decoder, &ctx->basic_info) != JXL_DEC_SUCCESS) { + /* + * this should never happen + * if it does it is likely a libjxl decoder bug + */ + av_log(avctx, AV_LOG_ERROR, "Bad libjxl basic info event\n"); + return AVERROR_EXTERNAL; + } + avctx->pix_fmt = libjxl_get_pix_fmt(avctx, &ctx->basic_info, &ctx->jxl_pixfmt); + if (avctx->pix_fmt == AV_PIX_FMT_NONE) { + av_log(avctx, AV_LOG_ERROR, "Bad libjxl pixel format\n"); + return AVERROR_EXTERNAL; + } + if ((ret = ff_set_dimensions(avctx, ctx->basic_info.xsize, ctx->basic_info.ysize)) < 0) + return ret; + continue; + case JXL_DEC_COLOR_ENCODING: + av_log(avctx, AV_LOG_DEBUG, "COLOR_ENCODING event emitted\n"); + if ((ret = libjxl_color_encoding_event(avctx, frame)) < 0) + return ret; + continue; + case JXL_DEC_NEED_IMAGE_OUT_BUFFER: + av_log(avctx, AV_LOG_DEBUG, "NEED_IMAGE_OUT_BUFFER event emitted\n"); + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + ctx->jxl_pixfmt.align = frame->linesize[0]; + if (JxlDecoderSetImageOutBuffer(ctx->decoder, &ctx->jxl_pixfmt, frame->data[0], frame->buf[0]->size) + != JXL_DEC_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Bad libjxl dec need image out buffer event\n"); + return AVERROR_EXTERNAL; + } + continue; + case JXL_DEC_FULL_IMAGE: + /* full image is one frame, even if animated */ + av_log(avctx, AV_LOG_DEBUG, "FULL_IMAGE event emitted\n"); + frame->pict_type = AV_PICTURE_TYPE_I; + frame->key_frame = 1; + if (ctx->iccp) { + AVFrameSideData *sd = av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_ICC_PROFILE, ctx->iccp); + if (!sd) + return AVERROR(ENOMEM); + /* ownership is transfered, and it is not ref-ed */ + ctx->iccp = NULL; + } + *got_frame = 1; + return avpkt->size - remaining; + case JXL_DEC_SUCCESS: + av_log(avctx, AV_LOG_DEBUG, "SUCCESS event emitted\n"); + /* + * The SUCCESS event isn't fired until after JXL_DEC_FULL_IMAGE. If this + * stream only contains one JXL image then JXL_DEC_SUCCESS will never fire. + * If the image2 sequence being decoded contains several JXL files, then + * libjxl will fire this event after the next AVPacket has been passed, + * which means the current packet is actually the next image in the sequence. + * This is why we reset the decoder and populate the packet data now, since + * this is the next packet and it has not been decoded yet. The decoder does + * have to be reset to allow us to use it for the next image, or libjxl + * will become very confused if the header information is not identical. + */ + JxlDecoderReset(ctx->decoder); + libjxl_init_jxl_decoder(avctx); + buf = avpkt->data; + remaining = avpkt->size; + continue; + default: + av_log(avctx, AV_LOG_ERROR, "Bad libjxl event: %d\n", jret); + return AVERROR_EXTERNAL; + } + } +} + +static av_cold int libjxl_decode_close(AVCodecContext *avctx) +{ + LibJxlDecodeContext *ctx = avctx->priv_data; + + if (ctx->runner) + JxlThreadParallelRunnerDestroy(ctx->runner); + ctx->runner = NULL; + if (ctx->decoder) + JxlDecoderDestroy(ctx->decoder); + ctx->decoder = NULL; + av_buffer_unref(&ctx->iccp); + + return 0; +} + +const FFCodec ff_libjxl_decoder = { + .p.name = "libjxl", + .p.long_name = NULL_IF_CONFIG_SMALL("libjxl JPEG XL"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_JPEGXL, + .priv_data_size = sizeof(LibJxlDecodeContext), + .init = libjxl_decode_init, + FF_CODEC_DECODE_CB(libjxl_decode_frame), + .close = libjxl_decode_close, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_OTHER_THREADS, + .caps_internal = FF_CODEC_CAP_AUTO_THREADS | FF_CODEC_CAP_INIT_CLEANUP, + .p.wrapper_name = "libjxl", +}; diff --git a/libavcodec/libjxlenc.c b/libavcodec/libjxlenc.c new file mode 100644 index 000000000..6a948cc3a --- /dev/null +++ b/libavcodec/libjxlenc.c @@ -0,0 +1,477 @@ +/* + * JPEG XL encoding support via libjxl + * Copyright (c) 2021 Leo Izen + * + * 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 + * JPEG XL encoder using libjxl + */ + +#include + +#include "libavutil/avutil.h" +#include "libavutil/csp.h" +#include "libavutil/error.h" +#include "libavutil/frame.h" +#include "libavutil/libm.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" +#include "libavutil/pixfmt.h" +#include "libavutil/version.h" + +#include "avcodec.h" +#include "encode.h" +#include "codec_internal.h" + +#include +#include +#include "libjxl.h" + +typedef struct LibJxlEncodeContext { + AVClass *class; + void *runner; + JxlEncoder *encoder; + JxlEncoderFrameSettings *options; + int effort; + float distance; + int modular; + uint8_t *buffer; + size_t buffer_size; +} LibJxlEncodeContext; + +/** + * Map a quality setting for -qscale roughly from libjpeg + * quality numbers to libjxl's butteraugli distance for + * photographic content. + * + * Setting distance explicitly is preferred, but this will + * allow qscale to be used as a fallback. + * + * This function is continuous and injective on [0, 100] which + * makes it monotonic. + * + * @param quality 0.0 to 100.0 quality setting, libjpeg quality + * @return Butteraugli distance between 0.0 and 15.0 + */ +static float quality_to_distance(float quality) +{ + if (quality >= 100.0) + return 0.0; + else if (quality >= 90.0) + return (100.0 - quality) * 0.10; + else if (quality >= 30.0) + return 0.1 + (100.0 - quality) * 0.09; + else if (quality > 0.0) + return 15.0 + (59.0 * quality - 4350.0) * quality / 9000.0; + else + return 15.0; +} + +/** + * Initalize the decoder on a per-frame basis. All of these need to be set + * once each time the decoder is reset, which it must be each frame to make + * the image2 muxer work. + * + * @return 0 upon success, negative on failure. + */ +static int libjxl_init_jxl_encoder(AVCodecContext *avctx) +{ + LibJxlEncodeContext *ctx = avctx->priv_data; + + /* reset the encoder every frame for image2 muxer */ + JxlEncoderReset(ctx->encoder); + + ctx->options = JxlEncoderFrameSettingsCreate(ctx->encoder, NULL); + if (!ctx->options) { + av_log(avctx, AV_LOG_ERROR, "Failed to create JxlEncoderOptions\n"); + return AVERROR_EXTERNAL; + } + + /* This needs to be set each time the decoder is reset */ + if (JxlEncoderSetParallelRunner(ctx->encoder, JxlThreadParallelRunner, ctx->runner) + != JXL_ENC_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to set JxlThreadParallelRunner\n"); + return AVERROR_EXTERNAL; + } + + /* these shouldn't fail, libjxl bug notwithstanding */ + if (JxlEncoderFrameSettingsSetOption(ctx->options, JXL_ENC_FRAME_SETTING_EFFORT, ctx->effort) + != JXL_ENC_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to set effort to: %d\n", ctx->effort); + return AVERROR_EXTERNAL; + } + + /* check for negative, our default */ + if (ctx->distance < 0.0) { + /* use ffmpeg.c -q option if passed */ + if (avctx->flags & AV_CODEC_FLAG_QSCALE) + ctx->distance = quality_to_distance((float)avctx->global_quality / FF_QP2LAMBDA); + else + /* default 1.0 matches cjxl */ + ctx->distance = 1.0; + } + + /* + * 0.01 is the minimum distance accepted for lossy + * interpreting any positive value less than this as minimum + */ + if (ctx->distance > 0.0 && ctx->distance < 0.01) + ctx->distance = 0.01; + if (JxlEncoderSetFrameDistance(ctx->options, ctx->distance) != JXL_ENC_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to set distance: %f\n", ctx->distance); + return AVERROR_EXTERNAL; + } + + /* + * In theory the library should automatically enable modular if necessary, + * but it appears it won't at the moment due to a bug. This will still + * work even if that is patched. + */ + if (JxlEncoderFrameSettingsSetOption(ctx->options, JXL_ENC_FRAME_SETTING_MODULAR, + ctx->modular || ctx->distance <= 0.0 ? 1 : -1) != JXL_ENC_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to set modular\n"); + return AVERROR_EXTERNAL; + } + + return 0; +} + +/** + * Global encoder initialization. This only needs to be run once, + * not every frame. + */ +static av_cold int libjxl_encode_init(AVCodecContext *avctx) +{ + LibJxlEncodeContext *ctx = avctx->priv_data; + JxlMemoryManager manager; + + ff_libjxl_init_memory_manager(&manager); + ctx->encoder = JxlEncoderCreate(&manager); + if (!ctx->encoder) { + av_log(avctx, AV_LOG_ERROR, "Failed to create JxlEncoder\n"); + return AVERROR_EXTERNAL; + } + + ctx->runner = JxlThreadParallelRunnerCreate(&manager, ff_libjxl_get_threadcount(avctx->thread_count)); + if (!ctx->runner) { + av_log(avctx, AV_LOG_ERROR, "Failed to create JxlThreadParallelRunner\n"); + return AVERROR_EXTERNAL; + } + + ctx->buffer_size = 4096; + ctx->buffer = av_realloc(NULL, ctx->buffer_size); + + if (!ctx->buffer) { + av_log(avctx, AV_LOG_ERROR, "Could not allocate encoding buffer\n"); + return AVERROR(ENOMEM); + } + + return 0; +} + +/** + * Populate a JxlColorEncoding with the given enum AVColorPrimaries. + * @return < 0 upon failure, >= 0 upon success + */ +static int libjxl_populate_primaries(JxlColorEncoding *jxl_color, enum AVColorPrimaries prm) +{ + const AVColorPrimariesDesc *desc; + + switch (prm) { + case AVCOL_PRI_BT709: + jxl_color->primaries = JXL_PRIMARIES_SRGB; + jxl_color->white_point = JXL_WHITE_POINT_D65; + return 0; + case AVCOL_PRI_BT2020: + jxl_color->primaries = JXL_PRIMARIES_2100; + jxl_color->white_point = JXL_WHITE_POINT_D65; + return 0; + case AVCOL_PRI_SMPTE431: + jxl_color->primaries = JXL_PRIMARIES_P3; + jxl_color->white_point = JXL_WHITE_POINT_DCI; + return 0; + case AVCOL_PRI_SMPTE432: + jxl_color->primaries = JXL_PRIMARIES_P3; + jxl_color->white_point = JXL_WHITE_POINT_D65; + return 0; + } + + desc = av_csp_primaries_desc_from_id(prm); + if (!desc) + return AVERROR(EINVAL); + + jxl_color->primaries = JXL_PRIMARIES_CUSTOM; + jxl_color->white_point = JXL_WHITE_POINT_CUSTOM; + + jxl_color->primaries_red_xy[0] = av_q2d(desc->prim.r.x); + jxl_color->primaries_red_xy[1] = av_q2d(desc->prim.r.y); + jxl_color->primaries_green_xy[0] = av_q2d(desc->prim.g.x); + jxl_color->primaries_green_xy[1] = av_q2d(desc->prim.g.y); + jxl_color->primaries_blue_xy[0] = av_q2d(desc->prim.b.x); + jxl_color->primaries_blue_xy[1] = av_q2d(desc->prim.b.y); + jxl_color->white_point_xy[0] = av_q2d(desc->wp.x); + jxl_color->white_point_xy[1] = av_q2d(desc->wp.y); + + return 0; +} + +/** + * Encode an entire frame. Currently animation, is not supported by + * this encoder, so this will always reinitialize a new still image + * and encode a one-frame image (for image2 and image2pipe). + */ +static int libjxl_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_packet) +{ + LibJxlEncodeContext *ctx = avctx->priv_data; + AVFrameSideData *sd; + const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(frame->format); + JxlBasicInfo info; + JxlColorEncoding jxl_color; + JxlPixelFormat jxl_fmt; + JxlEncoderStatus jret; + int ret; + size_t available = ctx->buffer_size; + size_t bytes_written = 0; + uint8_t *next_out = ctx->buffer; + + ret = libjxl_init_jxl_encoder(avctx); + if (ret) { + av_log(avctx, AV_LOG_ERROR, "Error frame-initializing JxlEncoder\n"); + return ret; + } + + /* populate the basic info settings */ + JxlEncoderInitBasicInfo(&info); + jxl_fmt.num_channels = pix_desc->nb_components; + info.xsize = frame->width; + info.ysize = frame->height; + info.num_extra_channels = (jxl_fmt.num_channels + 1) % 2; + info.num_color_channels = jxl_fmt.num_channels - info.num_extra_channels; + info.bits_per_sample = av_get_bits_per_pixel(pix_desc) / jxl_fmt.num_channels; + info.alpha_bits = (info.num_extra_channels > 0) * info.bits_per_sample; + if (pix_desc->flags & AV_PIX_FMT_FLAG_FLOAT) { + info.exponent_bits_per_sample = info.bits_per_sample > 16 ? 8 : 5; + info.alpha_exponent_bits = info.alpha_bits ? info.exponent_bits_per_sample : 0; + jxl_fmt.data_type = info.bits_per_sample > 16 ? JXL_TYPE_FLOAT : JXL_TYPE_FLOAT16; + } else { + info.exponent_bits_per_sample = 0; + info.alpha_exponent_bits = 0; + jxl_fmt.data_type = info.bits_per_sample <= 8 ? JXL_TYPE_UINT8 : JXL_TYPE_UINT16; + } + + /* JPEG XL format itself does not support limited range */ + if (avctx->color_range == AVCOL_RANGE_MPEG || + avctx->color_range == AVCOL_RANGE_UNSPECIFIED && frame->color_range == AVCOL_RANGE_MPEG) + av_log(avctx, AV_LOG_WARNING, "This encoder does not support limited (tv) range, colors will be wrong!\n"); + else if (avctx->color_range != AVCOL_RANGE_JPEG && frame->color_range != AVCOL_RANGE_JPEG) + av_log(avctx, AV_LOG_WARNING, "Unknown color range, assuming full (pc)\n"); + + /* bitexact lossless requires there to be no XYB transform */ + info.uses_original_profile = ctx->distance == 0.0; + + if (JxlEncoderSetBasicInfo(ctx->encoder, &info) != JXL_ENC_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to set JxlBasicInfo\n"); + return AVERROR_EXTERNAL; + } + + /* rendering intent doesn't matter here + * but libjxl will whine if we don't set it */ + jxl_color.rendering_intent = JXL_RENDERING_INTENT_RELATIVE; + + switch (frame->color_trc && frame->color_trc != AVCOL_TRC_UNSPECIFIED + ? frame->color_trc : avctx->color_trc) { + case AVCOL_TRC_BT709: + jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_709; + break; + case AVCOL_TRC_LINEAR: + jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_LINEAR; + break; + case AVCOL_TRC_IEC61966_2_1: + jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_SRGB; + break; + case AVCOL_TRC_SMPTE428: + jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_DCI; + break; + case AVCOL_TRC_SMPTE2084: + jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_PQ; + break; + case AVCOL_TRC_ARIB_STD_B67: + jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_HLG; + break; + case AVCOL_TRC_GAMMA22: + jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_GAMMA; + jxl_color.gamma = 2.2; + break; + case AVCOL_TRC_GAMMA28: + jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_GAMMA; + jxl_color.gamma = 2.8; + break; + default: + if (pix_desc->flags & AV_PIX_FMT_FLAG_FLOAT) { + av_log(avctx, AV_LOG_WARNING, "Unknown transfer function, assuming Linear Light. Colors may be wrong.\n"); + jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_LINEAR; + } else { + av_log(avctx, AV_LOG_WARNING, "Unknown transfer function, assuming IEC61966-2-1/sRGB. Colors may be wrong.\n"); + jxl_color.transfer_function = JXL_TRANSFER_FUNCTION_SRGB; + } + } + + /* This should be implied to be honest + * but a libjxl bug makes it fail otherwise */ + if (info.num_color_channels == 1) + jxl_color.color_space = JXL_COLOR_SPACE_GRAY; + else + jxl_color.color_space = JXL_COLOR_SPACE_RGB; + + ret = libjxl_populate_primaries(&jxl_color, + frame->color_primaries && frame->color_primaries != AVCOL_PRI_UNSPECIFIED + ? frame->color_primaries : avctx->color_primaries); + if (ret < 0) + return ret; + + sd = av_frame_get_side_data(frame, AV_FRAME_DATA_ICC_PROFILE); + if (sd && sd->size && JxlEncoderSetICCProfile(ctx->encoder, sd->data, sd->size) != JXL_ENC_SUCCESS) + av_log(avctx, AV_LOG_WARNING, "Could not set ICC Profile\n"); + if (JxlEncoderSetColorEncoding(ctx->encoder, &jxl_color) != JXL_ENC_SUCCESS) + av_log(avctx, AV_LOG_WARNING, "Failed to set JxlColorEncoding\n"); + + /* depending on basic info, level 10 might + * be required instead of level 5 */ + if (JxlEncoderGetRequiredCodestreamLevel(ctx->encoder) > 5) { + if (JxlEncoderSetCodestreamLevel(ctx->encoder, 10) != JXL_ENC_SUCCESS) + av_log(avctx, AV_LOG_WARNING, "Could not increase codestream level\n"); + } + + jxl_fmt.endianness = JXL_NATIVE_ENDIAN; + jxl_fmt.align = frame->linesize[0]; + + if (JxlEncoderAddImageFrame(ctx->options, &jxl_fmt, frame->data[0], jxl_fmt.align * info.ysize) != JXL_ENC_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to add Image Frame\n"); + return AVERROR_EXTERNAL; + } + + /* + * Run this after the last frame in the image has been passed. + * TODO support animation + */ + JxlEncoderCloseInput(ctx->encoder); + + while (1) { + jret = JxlEncoderProcessOutput(ctx->encoder, &next_out, &available); + if (jret == JXL_ENC_ERROR) { + av_log(avctx, AV_LOG_ERROR, "Unspecified libjxl error occurred\n"); + return AVERROR_EXTERNAL; + } + bytes_written = ctx->buffer_size - available; + /* all data passed has been encoded */ + if (jret == JXL_ENC_SUCCESS) + break; + if (jret == JXL_ENC_NEED_MORE_OUTPUT) { + /* + * at the moment, libjxl has no way to + * tell us how much space it actually needs + * so we need to malloc loop + */ + uint8_t *temp; + size_t new_size = ctx->buffer_size * 2; + temp = av_realloc(ctx->buffer, new_size); + if (!temp) + return AVERROR(ENOMEM); + ctx->buffer = temp; + ctx->buffer_size = new_size; + next_out = ctx->buffer + bytes_written; + available = new_size - bytes_written; + continue; + } + av_log(avctx, AV_LOG_ERROR, "Bad libjxl event: %d\n", jret); + return AVERROR_EXTERNAL; + } + + ret = ff_get_encode_buffer(avctx, pkt, bytes_written, 0); + if (ret < 0) + return ret; + + memcpy(pkt->data, ctx->buffer, bytes_written); + *got_packet = 1; + + return 0; +} + +static av_cold int libjxl_encode_close(AVCodecContext *avctx) +{ + LibJxlEncodeContext *ctx = avctx->priv_data; + + if (ctx->runner) + JxlThreadParallelRunnerDestroy(ctx->runner); + ctx->runner = NULL; + + /* + * destroying the decoder also frees + * ctx->options so we don't need to + */ + if (ctx->encoder) + JxlEncoderDestroy(ctx->encoder); + ctx->encoder = NULL; + + av_freep(&ctx->buffer); + + return 0; +} + +#define OFFSET(x) offsetof(LibJxlEncodeContext, x) +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM + +static const AVOption libjxl_encode_options[] = { + { "effort", "Encoding effort", OFFSET(effort), AV_OPT_TYPE_INT, { .i64 = 7 }, 1, 9, VE }, + { "distance", "Maximum Butteraugli distance (quality setting, " + "lower = better, zero = lossless, default 1.0)", OFFSET(distance), AV_OPT_TYPE_FLOAT, { .dbl = -1.0 }, -1.0, 15.0, VE }, + { "modular", "Force modular mode", OFFSET(modular), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + { NULL }, +}; + +static const AVClass libjxl_encode_class = { + .class_name = "libjxl", + .item_name = av_default_item_name, + .option = libjxl_encode_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +const FFCodec ff_libjxl_encoder = { + .p.name = "libjxl", + .p.long_name = NULL_IF_CONFIG_SMALL("libjxl JPEG XL"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_JPEGXL, + .priv_data_size = sizeof(LibJxlEncodeContext), + .init = libjxl_encode_init, + FF_CODEC_ENCODE_CB(libjxl_encode_frame), + .close = libjxl_encode_close, + .p.capabilities = AV_CODEC_CAP_OTHER_THREADS, + .caps_internal = FF_CODEC_CAP_AUTO_THREADS | FF_CODEC_CAP_INIT_CLEANUP, + .p.pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, + AV_PIX_FMT_RGB48, AV_PIX_FMT_RGBA64, + AV_PIX_FMT_GRAY8, AV_PIX_FMT_YA8, + AV_PIX_FMT_GRAY16, AV_PIX_FMT_YA16, + AV_PIX_FMT_GRAYF32, + AV_PIX_FMT_NONE + }, + .p.priv_class = &libjxl_encode_class, + .p.wrapper_name = "libjxl", +}; diff --git a/libavcodec/libkvazaar.c b/libavcodec/libkvazaar.c index 5f9ab4309..7fd0e9523 100644 --- a/libavcodec/libkvazaar.c +++ b/libavcodec/libkvazaar.c @@ -36,8 +36,8 @@ #include "libavutil/opt.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "packet_internal.h" typedef struct LibkvazaarContext { @@ -313,30 +313,30 @@ static const AVClass class = { .version = LIBAVUTIL_VERSION_INT, }; -static const AVCodecDefault defaults[] = { +static const FFCodecDefault defaults[] = { { "b", "0" }, { NULL }, }; -const AVCodec ff_libkvazaar_encoder = { - .name = "libkvazaar", - .long_name = NULL_IF_CONFIG_SMALL("libkvazaar H.265 / HEVC"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_HEVC, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | +const FFCodec ff_libkvazaar_encoder = { + .p.name = "libkvazaar", + .p.long_name = NULL_IF_CONFIG_SMALL("libkvazaar H.265 / HEVC"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_HEVC, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS, - .pix_fmts = pix_fmts, + .p.pix_fmts = pix_fmts, - .priv_class = &class, + .p.priv_class = &class, .priv_data_size = sizeof(LibkvazaarContext), .defaults = defaults, .init = libkvazaar_init, - .encode2 = libkvazaar_encode, + FF_CODEC_ENCODE_CB(libkvazaar_encode), .close = libkvazaar_close, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_AUTO_THREADS, - .wrapper_name = "libkvazaar", + .p.wrapper_name = "libkvazaar", }; diff --git a/libavcodec/libmp3lame.c b/libavcodec/libmp3lame.c index 5675864bb..02a256c76 100644 --- a/libavcodec/libmp3lame.c +++ b/libavcodec/libmp3lame.c @@ -34,8 +34,8 @@ #include "libavutil/opt.h" #include "avcodec.h" #include "audio_frame_queue.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "mpegaudio.h" #include "mpegaudiodecheader.h" @@ -101,8 +101,9 @@ static av_cold int mp3lame_encode_init(AVCodecContext *avctx) return AVERROR(ENOMEM); - lame_set_num_channels(s->gfp, avctx->channels); - lame_set_mode(s->gfp, avctx->channels > 1 ? s->joint_stereo ? JOINT_STEREO : STEREO : MONO); + lame_set_num_channels(s->gfp, avctx->ch_layout.nb_channels); + lame_set_mode(s->gfp, avctx->ch_layout.nb_channels > 1 ? + s->joint_stereo ? JOINT_STEREO : STEREO : MONO); /* sample rate */ lame_set_in_samplerate (s->gfp, avctx->sample_rate); @@ -138,7 +139,7 @@ static av_cold int mp3lame_encode_init(AVCodecContext *avctx) /* set specified parameters */ if (lame_init_params(s->gfp) < 0) { - ret = -1; + ret = AVERROR_EXTERNAL; goto error; } @@ -151,7 +152,7 @@ static av_cold int mp3lame_encode_init(AVCodecContext *avctx) /* allocate float sample buffers */ if (avctx->sample_fmt == AV_SAMPLE_FMT_FLTP) { int ch; - for (ch = 0; ch < avctx->channels; ch++) { + for (ch = 0; ch < avctx->ch_layout.nb_channels; ch++) { s->samples_flt[ch] = av_malloc_array(avctx->frame_size, sizeof(*s->samples_flt[ch])); if (!s->samples_flt[ch]) { @@ -208,7 +209,7 @@ static int mp3lame_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, av_log(avctx, AV_LOG_ERROR, "inadequate AVFrame plane padding\n"); return AVERROR(EINVAL); } - for (ch = 0; ch < avctx->channels; ch++) { + for (ch = 0; ch < avctx->ch_layout.nb_channels; ch++) { s->fdsp->vector_fmul_scalar(s->samples_flt[ch], (const float *)frame->data[ch], 32768.0f, @@ -231,7 +232,7 @@ static int mp3lame_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, "lame: output buffer too small (buffer index: %d, free bytes: %d)\n", s->buffer_index, s->buffer_size - s->buffer_index); } - return -1; + return AVERROR(ENOMEM); } s->buffer_index += lame_result; ret = realloc_buffer(s); @@ -259,7 +260,7 @@ static int mp3lame_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, return AVERROR_BUG; } else if (ret) { av_log(avctx, AV_LOG_ERROR, "free format output not supported\n"); - return -1; + return AVERROR_INVALIDDATA; } len = hdr.frame_size; ff_dlog(avctx, "in:%d packet-len:%d index:%d\n", avctx->frame_size, len, @@ -318,7 +319,7 @@ static const AVClass libmp3lame_class = { .version = LIBAVUTIL_VERSION_INT, }; -static const AVCodecDefault libmp3lame_defaults[] = { +static const FFCodecDefault libmp3lame_defaults[] = { { "b", "0" }, { NULL }, }; @@ -327,26 +328,32 @@ static const int libmp3lame_sample_rates[] = { 44100, 48000, 32000, 22050, 24000, 16000, 11025, 12000, 8000, 0 }; -const AVCodec ff_libmp3lame_encoder = { - .name = "libmp3lame", - .long_name = NULL_IF_CONFIG_SMALL("libmp3lame MP3 (MPEG audio layer 3)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_MP3, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | +const FFCodec ff_libmp3lame_encoder = { + .p.name = "libmp3lame", + .p.long_name = NULL_IF_CONFIG_SMALL("libmp3lame MP3 (MPEG audio layer 3)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_MP3, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SMALL_LAST_FRAME, .priv_data_size = sizeof(LAMEContext), .init = mp3lame_encode_init, - .encode2 = mp3lame_encode_frame, + FF_CODEC_ENCODE_CB(mp3lame_encode_frame), .close = mp3lame_encode_close, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32P, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE }, - .supported_samplerates = libmp3lame_sample_rates, - .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO, + .p.supported_samplerates = libmp3lame_sample_rates, +#if FF_API_OLD_CHANNEL_LAYOUT + .p.channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO, AV_CH_LAYOUT_STEREO, 0 }, - .priv_class = &libmp3lame_class, +#endif + .p.ch_layouts = (const AVChannelLayout[]) { AV_CHANNEL_LAYOUT_MONO, + AV_CHANNEL_LAYOUT_STEREO, + { 0 }, + }, + .p.priv_class = &libmp3lame_class, .defaults = libmp3lame_defaults, - .wrapper_name = "libmp3lame", + .p.wrapper_name = "libmp3lame", }; diff --git a/libavcodec/libopencore-amr.c b/libavcodec/libopencore-amr.c index 2df1c5090..539f0ded3 100644 --- a/libavcodec/libopencore-amr.c +++ b/libavcodec/libopencore-amr.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include #include "libavutil/avstring.h" @@ -27,6 +29,7 @@ #include "libavutil/opt.h" #include "avcodec.h" #include "audio_frame_queue.h" +#include "codec_internal.h" #include "encode.h" #include "internal.h" @@ -38,13 +41,13 @@ static int amr_decode_fix_avctx(AVCodecContext *avctx) if (!avctx->sample_rate) avctx->sample_rate = 8000 * is_amr_wb; - if (avctx->channels > 1) { + if (avctx->ch_layout.nb_channels > 1) { avpriv_report_missing_feature(avctx, "multi-channel AMR"); return AVERROR_PATCHWELCOME; } - avctx->channels = 1; - avctx->channel_layout = AV_CH_LAYOUT_MONO; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; avctx->sample_fmt = AV_SAMPLE_FMT_S16; return 0; } @@ -93,10 +96,9 @@ static av_cold int amr_nb_decode_close(AVCodecContext *avctx) return 0; } -static int amr_nb_decode_frame(AVCodecContext *avctx, void *data, +static int amr_nb_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; AMRContext *s = avctx->priv_data; @@ -131,16 +133,16 @@ static int amr_nb_decode_frame(AVCodecContext *avctx, void *data, return packet_size; } -const AVCodec ff_libopencore_amrnb_decoder = { - .name = "libopencore_amrnb", - .long_name = NULL_IF_CONFIG_SMALL("OpenCORE AMR-NB (Adaptive Multi-Rate Narrow-Band)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_AMR_NB, +const FFCodec ff_libopencore_amrnb_decoder = { + .p.name = "libopencore_amrnb", + .p.long_name = NULL_IF_CONFIG_SMALL("OpenCORE AMR-NB (Adaptive Multi-Rate Narrow-Band)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_AMR_NB, .priv_data_size = sizeof(AMRContext), .init = amr_nb_decode_init, .close = amr_nb_decode_close, - .decode = amr_nb_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + FF_CODEC_DECODE_CB(amr_nb_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, }; #endif /* CONFIG_LIBOPENCORE_AMRNB_DECODER */ @@ -201,7 +203,7 @@ static av_cold int amr_nb_encode_init(AVCodecContext *avctx) return AVERROR(ENOSYS); } - if (avctx->channels != 1) { + if (avctx->ch_layout.nb_channels != 1) { av_log(avctx, AV_LOG_ERROR, "Only mono supported\n"); return AVERROR(ENOSYS); } @@ -286,19 +288,19 @@ static int amr_nb_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, return 0; } -const AVCodec ff_libopencore_amrnb_encoder = { - .name = "libopencore_amrnb", - .long_name = NULL_IF_CONFIG_SMALL("OpenCORE AMR-NB (Adaptive Multi-Rate Narrow-Band)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_AMR_NB, +const FFCodec ff_libopencore_amrnb_encoder = { + .p.name = "libopencore_amrnb", + .p.long_name = NULL_IF_CONFIG_SMALL("OpenCORE AMR-NB (Adaptive Multi-Rate Narrow-Band)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_AMR_NB, .priv_data_size = sizeof(AMRContext), .init = amr_nb_encode_init, - .encode2 = amr_nb_encode_frame, + FF_CODEC_ENCODE_CB(amr_nb_encode_frame), .close = amr_nb_encode_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SMALL_LAST_FRAME, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SMALL_LAST_FRAME, + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, - .priv_class = &amrnb_class, + .p.priv_class = &amrnb_class, }; #endif /* CONFIG_LIBOPENCORE_AMRNB_ENCODER */ @@ -327,10 +329,9 @@ static av_cold int amr_wb_decode_init(AVCodecContext *avctx) return 0; } -static int amr_wb_decode_frame(AVCodecContext *avctx, void *data, +static int amr_wb_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; AMRWBContext *s = avctx->priv_data; @@ -371,17 +372,17 @@ static int amr_wb_decode_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_libopencore_amrwb_decoder = { - .name = "libopencore_amrwb", - .long_name = NULL_IF_CONFIG_SMALL("OpenCORE AMR-WB (Adaptive Multi-Rate Wide-Band)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_AMR_WB, +const FFCodec ff_libopencore_amrwb_decoder = { + .p.name = "libopencore_amrwb", + .p.long_name = NULL_IF_CONFIG_SMALL("OpenCORE AMR-WB (Adaptive Multi-Rate Wide-Band)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_AMR_WB, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .p.wrapper_name = "libopencore_amrwb", .priv_data_size = sizeof(AMRWBContext), .init = amr_wb_decode_init, .close = amr_wb_decode_close, - .decode = amr_wb_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, - .wrapper_name = "libopencore_amrwb", + FF_CODEC_DECODE_CB(amr_wb_decode_frame), }; #endif /* CONFIG_LIBOPENCORE_AMRWB_DECODER */ diff --git a/libavcodec/libopenh264.c b/libavcodec/libopenh264.c index 59c61a3a4..0f6d28ed8 100644 --- a/libavcodec/libopenh264.c +++ b/libavcodec/libopenh264.c @@ -23,6 +23,7 @@ #include #include +#include "libavutil/error.h" #include "libavutil/log.h" #include "libopenh264.h" diff --git a/libavcodec/libopenh264dec.c b/libavcodec/libopenh264dec.c index 7f5e85402..007f86b61 100644 --- a/libavcodec/libopenh264dec.c +++ b/libavcodec/libopenh264dec.c @@ -30,6 +30,7 @@ #include "libavutil/opt.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "libopenh264.h" @@ -56,7 +57,7 @@ static av_cold int svc_decode_init(AVCodecContext *avctx) WelsTraceCallback callback_function; if ((err = ff_libopenh264_check_version(avctx)) < 0) - return err; + return AVERROR_DECODER_NOT_FOUND; if (WelsCreateDecoder(&s->decoder)) { av_log(avctx, AV_LOG_ERROR, "Unable to create decoder\n"); @@ -86,14 +87,13 @@ static av_cold int svc_decode_init(AVCodecContext *avctx) return 0; } -static int svc_decode_frame(AVCodecContext *avctx, void *data, +static int svc_decode_frame(AVCodecContext *avctx, AVFrame *avframe, int *got_frame, AVPacket *avpkt) { SVCContext *s = avctx->priv_data; SBufferInfo info = { 0 }; uint8_t *ptrs[4] = { NULL }; int ret, linesize[4]; - AVFrame *avframe = data; DECODING_STATE state; #if OPENH264_VER_AT_LEAST(1, 7) int opt; @@ -156,18 +156,18 @@ static int svc_decode_frame(AVCodecContext *avctx, void *data, return avpkt->size; } -const AVCodec ff_libopenh264_decoder = { - .name = "libopenh264", - .long_name = NULL_IF_CONFIG_SMALL("OpenH264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_H264, +const FFCodec ff_libopenh264_decoder = { + .p.name = "libopenh264", + .p.long_name = NULL_IF_CONFIG_SMALL("OpenH264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_H264, .priv_data_size = sizeof(SVCContext), .init = svc_decode_init, - .decode = svc_decode_frame, + FF_CODEC_DECODE_CB(svc_decode_frame), .close = svc_decode_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS | FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .bsfs = "h264_mp4toannexb", - .wrapper_name = "libopenh264", + .p.wrapper_name = "libopenh264", }; diff --git a/libavcodec/libopenh264enc.c b/libavcodec/libopenh264enc.c index de4b85c41..db252aace 100644 --- a/libavcodec/libopenh264enc.c +++ b/libavcodec/libopenh264enc.c @@ -30,6 +30,7 @@ #include "libavutil/mathematics.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" #include "internal.h" #include "libopenh264.h" @@ -137,7 +138,7 @@ static av_cold int svc_encode_init(AVCodecContext *avctx) AVCPBProperties *props; if ((err = ff_libopenh264_check_version(avctx)) < 0) - return err; + return AVERROR_ENCODER_NOT_FOUND; if (WelsCreateSVCEncoder(&s->encoder)) { av_log(avctx, AV_LOG_ERROR, "Unable to create encoder\n"); @@ -193,7 +194,7 @@ static av_cold int svc_encode_init(AVCodecContext *avctx) #endif param.bPrefixNalAddingCtrl = 0; param.iLoopFilterDisableIdc = !s->loopfilter; - param.iEntropyCodingModeFlag = 0; + param.iEntropyCodingModeFlag = s->coder >= 0 ? s->coder : 1; param.iMultipleThreadIdc = avctx->thread_count; /* Allow specifying the libopenh264 profile through AVCodecContext. */ @@ -220,26 +221,25 @@ static av_cold int svc_encode_init(AVCodecContext *avctx) #endif switch (s->profile) { -#if OPENH264_VER_AT_LEAST(1, 8) case FF_PROFILE_H264_HIGH: - param.iEntropyCodingModeFlag = 1; - av_log(avctx, AV_LOG_VERBOSE, "Using CABAC, " - "select EProfileIdc PRO_HIGH in libopenh264.\n"); + av_log(avctx, AV_LOG_VERBOSE, "Using %s, " + "select EProfileIdc PRO_HIGH in libopenh264.\n", + param.iEntropyCodingModeFlag ? "CABAC" : "CAVLC"); break; -#else case FF_PROFILE_H264_MAIN: - param.iEntropyCodingModeFlag = 1; - av_log(avctx, AV_LOG_VERBOSE, "Using CABAC, " - "select EProfileIdc PRO_MAIN in libopenh264.\n"); + av_log(avctx, AV_LOG_VERBOSE, "Using %s, " + "select EProfileIdc PRO_MAIN in libopenh264.\n", + param.iEntropyCodingModeFlag ? "CABAC" : "CAVLC"); break; -#endif case FF_PROFILE_H264_CONSTRAINED_BASELINE: case FF_PROFILE_UNKNOWN: + s->profile = FF_PROFILE_H264_CONSTRAINED_BASELINE; param.iEntropyCodingModeFlag = 0; av_log(avctx, AV_LOG_VERBOSE, "Using CAVLC, " "select EProfileIdc PRO_BASELINE in libopenh264.\n"); break; default: + s->profile = FF_PROFILE_H264_CONSTRAINED_BASELINE; param.iEntropyCodingModeFlag = 0; av_log(avctx, AV_LOG_WARNING, "Unsupported profile, " "select EProfileIdc PRO_BASELINE in libopenh264.\n"); @@ -251,6 +251,7 @@ static av_cold int svc_encode_init(AVCodecContext *avctx) param.sSpatialLayers[0].fFrameRate = param.fMaxFrameRate; param.sSpatialLayers[0].iSpatialBitrate = param.iTargetBitrate; param.sSpatialLayers[0].iMaxSpatialBitrate = param.iMaxBitrate; + param.sSpatialLayers[0].uiProfileIdc = s->profile; #if OPENH264_VER_AT_LEAST(1, 7) if (avctx->sample_aspect_ratio.num && avctx->sample_aspect_ratio.den) { @@ -330,6 +331,28 @@ static av_cold int svc_encode_init(AVCodecContext *avctx) } } +#if OPENH264_VER_AT_LEAST(1, 6) + param.sSpatialLayers[0].uiVideoFormat = VF_UNDEF; + if (avctx->color_range != AVCOL_RANGE_UNSPECIFIED) { + param.sSpatialLayers[0].bVideoSignalTypePresent = true; + param.sSpatialLayers[0].bFullRange = (avctx->color_range == AVCOL_RANGE_JPEG); + } + + if (avctx->colorspace != AVCOL_SPC_UNSPECIFIED || + avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || + avctx->color_trc != AVCOL_TRC_UNSPECIFIED) { + param.sSpatialLayers[0].bVideoSignalTypePresent = true; + param.sSpatialLayers[0].bColorDescriptionPresent = true; + } + + if (avctx->colorspace != AVCOL_SPC_UNSPECIFIED) + param.sSpatialLayers[0].uiColorMatrix = avctx->colorspace; + if (avctx->color_primaries != AVCOL_PRI_UNSPECIFIED) + param.sSpatialLayers[0].uiColorPrimaries = avctx->color_primaries; + if (avctx->color_trc != AVCOL_TRC_UNSPECIFIED) + param.sSpatialLayers[0].uiTransferCharacteristics = avctx->color_trc; +#endif + if ((*s->encoder)->InitializeExt(s->encoder, ¶m) != cmResultSuccess) { av_log(avctx, AV_LOG_ERROR, "Initialize failed\n"); return AVERROR_UNKNOWN; @@ -420,7 +443,7 @@ static int svc_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, return 0; } -static const AVCodecDefault svc_enc_defaults[] = { +static const FFCodecDefault svc_enc_defaults[] = { { "b", "0" }, { "g", "-1" }, { "qmin", "-1" }, @@ -428,21 +451,21 @@ static const AVCodecDefault svc_enc_defaults[] = { { NULL }, }; -const AVCodec ff_libopenh264_encoder = { - .name = "libopenh264", - .long_name = NULL_IF_CONFIG_SMALL("OpenH264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_H264, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_OTHER_THREADS, +const FFCodec ff_libopenh264_encoder = { + .p.name = "libopenh264", + .p.long_name = NULL_IF_CONFIG_SMALL("OpenH264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_H264, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_OTHER_THREADS, .priv_data_size = sizeof(SVCContext), .init = svc_encode_init, - .encode2 = svc_encode_frame, + FF_CODEC_ENCODE_CB(svc_encode_frame), .close = svc_encode_close, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_AUTO_THREADS, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, .defaults = svc_enc_defaults, - .priv_class = &class, - .wrapper_name = "libopenh264", + .p.priv_class = &class, + .p.wrapper_name = "libopenh264", }; diff --git a/libavcodec/libopenjpegdec.c b/libavcodec/libopenjpegdec.c index 8982d21be..58ac6c413 100644 --- a/libavcodec/libopenjpegdec.c +++ b/libavcodec/libopenjpegdec.c @@ -31,6 +31,7 @@ #include "libavutil/pixfmt.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "thread.h" @@ -317,15 +318,12 @@ static av_cold int libopenjpeg_decode_init(AVCodecContext *avctx) return 0; } -static int libopenjpeg_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int libopenjpeg_decode_frame(AVCodecContext *avctx, AVFrame *picture, + int *got_frame, AVPacket *avpkt) { - uint8_t *buf = avpkt->data; + const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; LibOpenJPEGContext *ctx = avctx->priv_data; - ThreadFrame frame = { .f = data }; - AVFrame *picture = data; const AVPixFmtDescriptor *desc; int width, height, ret; int pixel_size = 0; @@ -417,7 +415,7 @@ static int libopenjpeg_decode_frame(AVCodecContext *avctx, if (image->comps[i].prec > avctx->bits_per_raw_sample) avctx->bits_per_raw_sample = image->comps[i].prec; - if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, picture, 0)) < 0) goto done; ret = !opj_decode(dec, stream, image); @@ -502,16 +500,16 @@ static const AVClass openjpeg_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_libopenjpeg_decoder = { - .name = "libopenjpeg", - .long_name = NULL_IF_CONFIG_SMALL("OpenJPEG JPEG 2000"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_JPEG2000, +const FFCodec ff_libopenjpeg_decoder = { + .p.name = "libopenjpeg", + .p.long_name = NULL_IF_CONFIG_SMALL("OpenJPEG JPEG 2000"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_JPEG2000, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .p.max_lowres = 31, + .p.priv_class = &openjpeg_class, + .p.wrapper_name = "libopenjpeg", .priv_data_size = sizeof(LibOpenJPEGContext), .init = libopenjpeg_decode_init, - .decode = libopenjpeg_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, - .max_lowres = 31, - .priv_class = &openjpeg_class, - .wrapper_name = "libopenjpeg", + FF_CODEC_DECODE_CB(libopenjpeg_decode_frame), }; diff --git a/libavcodec/libopenjpegenc.c b/libavcodec/libopenjpegenc.c index 3e52bcd4e..06338e882 100644 --- a/libavcodec/libopenjpegenc.c +++ b/libavcodec/libopenjpegenc.c @@ -29,8 +29,8 @@ #include "libavutil/intreadwrite.h" #include "libavutil/opt.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include typedef struct LibOpenJPEGContext { @@ -345,7 +345,8 @@ static av_cold int libopenjpeg_encode_init(AVCodecContext *avctx) return 0; } -static int libopenjpeg_copy_packed8(AVCodecContext *avctx, const AVFrame *frame, opj_image_t *image) +static int libopenjpeg_copy_packed8(AVCodecContext *avctx, const uint8_t *src[4], + const int linesize[4], opj_image_t *image) { int compno; int x; @@ -355,7 +356,7 @@ static int libopenjpeg_copy_packed8(AVCodecContext *avctx, const AVFrame *frame, const int numcomps = image->numcomps; for (compno = 0; compno < numcomps; ++compno) { - if (image->comps[compno].w > frame->linesize[0] / numcomps) { + if (image->comps[compno].w > linesize[0] / numcomps) { av_log(avctx, AV_LOG_ERROR, "Error: frame's linesize is too small for the image\n"); return 0; } @@ -364,9 +365,9 @@ static int libopenjpeg_copy_packed8(AVCodecContext *avctx, const AVFrame *frame, for (compno = 0; compno < numcomps; ++compno) { for (y = 0; y < avctx->height; ++y) { image_line = image->comps[compno].data + y * image->comps[compno].w; - frame_index = y * frame->linesize[0] + compno; + frame_index = y * linesize[0] + compno; for (x = 0; x < avctx->width; ++x) { - image_line[x] = frame->data[0][frame_index]; + image_line[x] = src[0][frame_index]; frame_index += numcomps; } for (; x < image->comps[compno].w; ++x) { @@ -385,17 +386,18 @@ static int libopenjpeg_copy_packed8(AVCodecContext *avctx, const AVFrame *frame, } // for XYZ 12 bit -static int libopenjpeg_copy_packed12(AVCodecContext *avctx, const AVFrame *frame, opj_image_t *image) +static int libopenjpeg_copy_packed12(AVCodecContext *avctx, const uint8_t *src[4], + const int linesize[4], opj_image_t *image) { int compno; int x, y; int *image_line; int frame_index; const int numcomps = image->numcomps; - uint16_t *frame_ptr = (uint16_t *)frame->data[0]; + const uint16_t *frame_ptr = (const uint16_t *)src[0]; for (compno = 0; compno < numcomps; ++compno) { - if (image->comps[compno].w > frame->linesize[0] / numcomps) { + if (image->comps[compno].w > linesize[0] / numcomps) { av_log(avctx, AV_LOG_ERROR, "Error: frame's linesize is too small for the image\n"); return 0; } @@ -404,7 +406,7 @@ static int libopenjpeg_copy_packed12(AVCodecContext *avctx, const AVFrame *frame for (compno = 0; compno < numcomps; ++compno) { for (y = 0; y < avctx->height; ++y) { image_line = image->comps[compno].data + y * image->comps[compno].w; - frame_index = y * (frame->linesize[0] / 2) + compno; + frame_index = y * (linesize[0] / 2) + compno; for (x = 0; x < avctx->width; ++x) { image_line[x] = frame_ptr[frame_index] >> 4; frame_index += numcomps; @@ -424,7 +426,8 @@ static int libopenjpeg_copy_packed12(AVCodecContext *avctx, const AVFrame *frame return 1; } -static int libopenjpeg_copy_packed16(AVCodecContext *avctx, const AVFrame *frame, opj_image_t *image) +static int libopenjpeg_copy_packed16(AVCodecContext *avctx, const uint8_t *src[4], + const int linesize[4], opj_image_t *image) { int compno; int x; @@ -432,10 +435,10 @@ static int libopenjpeg_copy_packed16(AVCodecContext *avctx, const AVFrame *frame int *image_line; int frame_index; const int numcomps = image->numcomps; - uint16_t *frame_ptr = (uint16_t*)frame->data[0]; + const uint16_t *frame_ptr = (const uint16_t*)src[0]; for (compno = 0; compno < numcomps; ++compno) { - if (image->comps[compno].w > frame->linesize[0] / numcomps) { + if (image->comps[compno].w > linesize[0] / numcomps) { av_log(avctx, AV_LOG_ERROR, "Error: frame's linesize is too small for the image\n"); return 0; } @@ -444,7 +447,7 @@ static int libopenjpeg_copy_packed16(AVCodecContext *avctx, const AVFrame *frame for (compno = 0; compno < numcomps; ++compno) { for (y = 0; y < avctx->height; ++y) { image_line = image->comps[compno].data + y * image->comps[compno].w; - frame_index = y * (frame->linesize[0] / 2) + compno; + frame_index = y * (linesize[0] / 2) + compno; for (x = 0; x < avctx->width; ++x) { image_line[x] = frame_ptr[frame_index]; frame_index += numcomps; @@ -464,7 +467,8 @@ static int libopenjpeg_copy_packed16(AVCodecContext *avctx, const AVFrame *frame return 1; } -static int libopenjpeg_copy_unpacked8(AVCodecContext *avctx, const AVFrame *frame, opj_image_t *image) +static int libopenjpeg_copy_unpacked8(AVCodecContext *avctx, const uint8_t *src[4], + const int linesize[4], opj_image_t *image) { int compno; int x; @@ -476,7 +480,7 @@ static int libopenjpeg_copy_unpacked8(AVCodecContext *avctx, const AVFrame *fram const int numcomps = image->numcomps; for (compno = 0; compno < numcomps; ++compno) { - if (image->comps[compno].w > frame->linesize[compno]) { + if (image->comps[compno].w > linesize[compno]) { av_log(avctx, AV_LOG_ERROR, "Error: frame's linesize is too small for the image\n"); return 0; } @@ -487,9 +491,9 @@ static int libopenjpeg_copy_unpacked8(AVCodecContext *avctx, const AVFrame *fram height = (avctx->height + image->comps[compno].dy - 1) / image->comps[compno].dy; for (y = 0; y < height; ++y) { image_line = image->comps[compno].data + y * image->comps[compno].w; - frame_index = y * frame->linesize[compno]; + frame_index = y * linesize[compno]; for (x = 0; x < width; ++x) - image_line[x] = frame->data[compno][frame_index++]; + image_line[x] = src[compno][frame_index++]; for (; x < image->comps[compno].w; ++x) { image_line[x] = image_line[x - 1]; } @@ -505,7 +509,8 @@ static int libopenjpeg_copy_unpacked8(AVCodecContext *avctx, const AVFrame *fram return 1; } -static int libopenjpeg_copy_unpacked16(AVCodecContext *avctx, const AVFrame *frame, opj_image_t *image) +static int libopenjpeg_copy_unpacked16(AVCodecContext *avctx, const uint8_t *src[4], + const int linesize[4], opj_image_t *image) { int compno; int x; @@ -515,22 +520,21 @@ static int libopenjpeg_copy_unpacked16(AVCodecContext *avctx, const AVFrame *fra int *image_line; int frame_index; const int numcomps = image->numcomps; - uint16_t *frame_ptr; for (compno = 0; compno < numcomps; ++compno) { - if (image->comps[compno].w > frame->linesize[compno]) { + if (image->comps[compno].w > linesize[compno]) { av_log(avctx, AV_LOG_ERROR, "Error: frame's linesize is too small for the image\n"); return 0; } } for (compno = 0; compno < numcomps; ++compno) { + const uint16_t *frame_ptr = (const uint16_t *)src[compno]; width = (avctx->width + image->comps[compno].dx - 1) / image->comps[compno].dx; height = (avctx->height + image->comps[compno].dy - 1) / image->comps[compno].dy; - frame_ptr = (uint16_t *)frame->data[compno]; for (y = 0; y < height; ++y) { image_line = image->comps[compno].data + y * image->comps[compno].w; - frame_index = y * (frame->linesize[compno] / 2); + frame_index = y * (linesize[compno] / 2); for (x = 0; x < width; ++x) image_line[x] = frame_ptr[frame_index++]; for (; x < image->comps[compno].w; ++x) { @@ -553,12 +557,15 @@ static int libopenjpeg_encode_frame(AVCodecContext *avctx, AVPacket *pkt, { LibOpenJPEGContext *ctx = avctx->priv_data; int ret; - AVFrame *gbrframe; int cpyresult = 0; PacketWriter writer = { 0 }; opj_codec_t *compress = NULL; opj_stream_t *stream = NULL; opj_image_t *image = mj2_create_image(avctx, &ctx->enc_params); + const uint8_t *data[4] = { frame->data[0], frame->data[1], + frame->data[2], frame->data[3] }; + int linesize[4] = { frame->linesize[0], frame->linesize[1], + frame->linesize[2], frame->linesize[3] }; if (!image) { av_log(avctx, AV_LOG_ERROR, "Error creating the mj2 image\n"); ret = AVERROR(EINVAL); @@ -569,15 +576,15 @@ static int libopenjpeg_encode_frame(AVCodecContext *avctx, AVPacket *pkt, case AV_PIX_FMT_RGB24: case AV_PIX_FMT_RGBA: case AV_PIX_FMT_YA8: - cpyresult = libopenjpeg_copy_packed8(avctx, frame, image); + cpyresult = libopenjpeg_copy_packed8(avctx, data, linesize, image); break; case AV_PIX_FMT_XYZ12: - cpyresult = libopenjpeg_copy_packed12(avctx, frame, image); + cpyresult = libopenjpeg_copy_packed12(avctx, data, linesize, image); break; case AV_PIX_FMT_RGB48: case AV_PIX_FMT_RGBA64: case AV_PIX_FMT_YA16: - cpyresult = libopenjpeg_copy_packed16(avctx, frame, image); + cpyresult = libopenjpeg_copy_packed16(avctx, data, linesize, image); break; case AV_PIX_FMT_GBR24P: case AV_PIX_FMT_GBRP9: @@ -585,23 +592,17 @@ static int libopenjpeg_encode_frame(AVCodecContext *avctx, AVPacket *pkt, case AV_PIX_FMT_GBRP12: case AV_PIX_FMT_GBRP14: case AV_PIX_FMT_GBRP16: - gbrframe = av_frame_clone(frame); - if (!gbrframe) { - ret = AVERROR(ENOMEM); - goto done; - } - gbrframe->data[0] = frame->data[2]; // swap to be rgb - gbrframe->data[1] = frame->data[0]; - gbrframe->data[2] = frame->data[1]; - gbrframe->linesize[0] = frame->linesize[2]; - gbrframe->linesize[1] = frame->linesize[0]; - gbrframe->linesize[2] = frame->linesize[1]; + data[0] = frame->data[2]; // swap to be rgb + data[1] = frame->data[0]; + data[2] = frame->data[1]; + linesize[0] = frame->linesize[2]; + linesize[1] = frame->linesize[0]; + linesize[2] = frame->linesize[1]; if (avctx->pix_fmt == AV_PIX_FMT_GBR24P) { - cpyresult = libopenjpeg_copy_unpacked8(avctx, gbrframe, image); + cpyresult = libopenjpeg_copy_unpacked8(avctx, data, linesize, image); } else { - cpyresult = libopenjpeg_copy_unpacked16(avctx, gbrframe, image); + cpyresult = libopenjpeg_copy_unpacked16(avctx, data, linesize, image); } - av_frame_free(&gbrframe); break; case AV_PIX_FMT_GRAY8: case AV_PIX_FMT_YUV410P: @@ -613,7 +614,7 @@ static int libopenjpeg_encode_frame(AVCodecContext *avctx, AVPacket *pkt, case AV_PIX_FMT_YUVA420P: case AV_PIX_FMT_YUVA422P: case AV_PIX_FMT_YUVA444P: - cpyresult = libopenjpeg_copy_unpacked8(avctx, frame, image); + cpyresult = libopenjpeg_copy_unpacked8(avctx, data, linesize, image); break; case AV_PIX_FMT_GRAY10: case AV_PIX_FMT_GRAY12: @@ -643,7 +644,7 @@ static int libopenjpeg_encode_frame(AVCodecContext *avctx, AVPacket *pkt, case AV_PIX_FMT_YUVA444P16: case AV_PIX_FMT_YUVA422P16: case AV_PIX_FMT_YUVA420P16: - cpyresult = libopenjpeg_copy_unpacked16(avctx, frame, image); + cpyresult = libopenjpeg_copy_unpacked16(avctx, data, linesize, image); break; default: av_log(avctx, AV_LOG_ERROR, @@ -753,16 +754,16 @@ static const AVClass openjpeg_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_libopenjpeg_encoder = { - .name = "libopenjpeg", - .long_name = NULL_IF_CONFIG_SMALL("OpenJPEG JPEG 2000"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_JPEG2000, +const FFCodec ff_libopenjpeg_encoder = { + .p.name = "libopenjpeg", + .p.long_name = NULL_IF_CONFIG_SMALL("OpenJPEG JPEG 2000"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_JPEG2000, .priv_data_size = sizeof(LibOpenJPEGContext), .init = libopenjpeg_encode_init, - .encode2 = libopenjpeg_encode_frame, - .capabilities = AV_CODEC_CAP_FRAME_THREADS, - .pix_fmts = (const enum AVPixelFormat[]) { + FF_CODEC_ENCODE_CB(libopenjpeg_encode_frame), + .p.capabilities = AV_CODEC_CAP_FRAME_THREADS, + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, AV_PIX_FMT_RGB48, AV_PIX_FMT_RGBA64, AV_PIX_FMT_GBR24P, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, @@ -782,6 +783,6 @@ const AVCodec ff_libopenjpeg_encoder = { AV_PIX_FMT_XYZ12, AV_PIX_FMT_NONE }, - .priv_class = &openjpeg_class, - .wrapper_name = "libopenjpeg", + .p.priv_class = &openjpeg_class, + .p.wrapper_name = "libopenjpeg", }; diff --git a/libavcodec/libopus.c b/libavcodec/libopus.c index 16395c73d..3d3b740a8 100644 --- a/libavcodec/libopus.c +++ b/libavcodec/libopus.c @@ -21,7 +21,6 @@ #include -#include "libavutil/common.h" #include "libavutil/error.h" #include "libopus.h" diff --git a/libavcodec/libopusdec.c b/libavcodec/libopusdec.c index 86ef71520..316ab0f2a 100644 --- a/libavcodec/libopusdec.c +++ b/libavcodec/libopusdec.c @@ -28,6 +28,7 @@ #include "libavutil/opt.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "vorbis.h" #include "mathops.h" @@ -50,55 +51,60 @@ struct libopus_context { static av_cold int libopus_decode_init(AVCodecContext *avc) { struct libopus_context *opus = avc->priv_data; - int ret, channel_map = 0, gain_db = 0, nb_streams, nb_coupled; + int ret, channel_map = 0, gain_db = 0, nb_streams, nb_coupled, channels; uint8_t mapping_arr[8] = { 0, 1 }, *mapping; - avc->channels = avc->extradata_size >= 10 ? avc->extradata[9] : (avc->channels == 1) ? 1 : 2; - if (avc->channels <= 0) { + channels = avc->extradata_size >= 10 ? avc->extradata[9] : (avc->ch_layout.nb_channels == 1) ? 1 : 2; + if (channels <= 0) { av_log(avc, AV_LOG_WARNING, - "Invalid number of channels %d, defaulting to stereo\n", avc->channels); - avc->channels = 2; + "Invalid number of channels %d, defaulting to stereo\n", channels); + channels = 2; } 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]; + av_channel_layout_uninit(&avc->ch_layout); + if (channels > 8) { + avc->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + avc->ch_layout.nb_channels = channels; + } else { + av_channel_layout_copy(&avc->ch_layout, &ff_vorbis_ch_layouts[channels - 1]); + } if (avc->extradata_size >= OPUS_HEAD_SIZE) { opus->pre_skip = AV_RL16(avc->extradata + 10); gain_db = sign_extend(AV_RL16(avc->extradata + 16), 16); channel_map = AV_RL8 (avc->extradata + 18); } - if (avc->extradata_size >= OPUS_HEAD_SIZE + 2 + avc->channels) { + if (avc->extradata_size >= OPUS_HEAD_SIZE + 2 + channels) { nb_streams = avc->extradata[OPUS_HEAD_SIZE + 0]; nb_coupled = avc->extradata[OPUS_HEAD_SIZE + 1]; - if (nb_streams + nb_coupled != avc->channels) + if (nb_streams + nb_coupled != channels) av_log(avc, AV_LOG_WARNING, "Inconsistent channel mapping.\n"); mapping = avc->extradata + OPUS_HEAD_SIZE + 2; } else { - if (avc->channels > 2 || channel_map) { + if (channels > 2 || channel_map) { av_log(avc, AV_LOG_ERROR, - "No channel mapping for %d channels.\n", avc->channels); + "No channel mapping for %d channels.\n", channels); return AVERROR(EINVAL); } nb_streams = 1; - nb_coupled = avc->channels > 1; + nb_coupled = channels > 1; mapping = mapping_arr; } - if (avc->channels > 2 && avc->channels <= 8) { - const uint8_t *vorbis_offset = ff_vorbis_channel_layout_offsets[avc->channels - 1]; + if (channels > 2 && channels <= 8) { + const uint8_t *vorbis_offset = ff_vorbis_channel_layout_offsets[channels - 1]; int ch; /* Remap channels from Vorbis order to ffmpeg order */ - for (ch = 0; ch < avc->channels; ch++) + for (ch = 0; ch < channels; ch++) mapping_arr[ch] = mapping[vorbis_offset[ch]]; mapping = mapping_arr; } - opus->dec = opus_multistream_decoder_create(avc->sample_rate, avc->channels, + opus->dec = opus_multistream_decoder_create(avc->sample_rate, channels, nb_streams, nb_coupled, mapping, &ret); if (!opus->dec) { @@ -150,11 +156,10 @@ static av_cold int libopus_decode_close(AVCodecContext *avc) #define MAX_FRAME_SIZE (960 * 6) -static int libopus_decode(AVCodecContext *avc, void *data, +static int libopus_decode(AVCodecContext *avc, AVFrame *frame, int *got_frame_ptr, AVPacket *pkt) { struct libopus_context *opus = avc->priv_data; - AVFrame *frame = data; int ret, nb_samples; frame->nb_samples = MAX_FRAME_SIZE; @@ -178,7 +183,7 @@ static int libopus_decode(AVCodecContext *avc, void *data, #ifndef OPUS_SET_GAIN { - int i = avc->channels * nb_samples; + int i = avc->ch_layout.nb_channels * nb_samples; if (avc->sample_fmt == AV_SAMPLE_FMT_FLT) { float *pcm = (float *)frame->data[0]; for (; i > 0; i--, pcm++) @@ -225,21 +230,21 @@ static const AVClass libopusdec_class = { }; -const AVCodec ff_libopus_decoder = { - .name = "libopus", - .long_name = NULL_IF_CONFIG_SMALL("libopus Opus"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_OPUS, +const FFCodec ff_libopus_decoder = { + .p.name = "libopus", + .p.long_name = NULL_IF_CONFIG_SMALL("libopus Opus"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_OPUS, .priv_data_size = sizeof(struct libopus_context), .init = libopus_decode_init, .close = libopus_decode_close, - .decode = libopus_decode, + FF_CODEC_DECODE_CB(libopus_decode), .flush = libopus_flush, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLT, + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, - .priv_class = &libopusdec_class, - .wrapper_name = "libopus", + .p.priv_class = &libopusdec_class, + .p.wrapper_name = "libopus", }; diff --git a/libavcodec/libopusenc.c b/libavcodec/libopusenc.c index 45b23fcbb..c884075ff 100644 --- a/libavcodec/libopusenc.c +++ b/libavcodec/libopusenc.c @@ -26,8 +26,8 @@ #include "libavutil/opt.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "libopus.h" #include "vorbis.h" #include "audio_frame_queue.h" @@ -91,7 +91,7 @@ static void libopus_write_header(AVCodecContext *avctx, int stream_count, const uint8_t *channel_mapping) { uint8_t *p = avctx->extradata; - int channels = avctx->channels; + int channels = avctx->ch_layout.nb_channels; bytestream_put_buffer(&p, "OpusHead", 8); bytestream_put_byte(&p, 1); /* Version */ @@ -180,9 +180,9 @@ static int libopus_configure_encoder(AVCodecContext *avctx, OpusMSEncoder *enc, static int libopus_check_max_channels(AVCodecContext *avctx, int max_channels) { - if (avctx->channels > max_channels) { + if (avctx->ch_layout.nb_channels > max_channels) { av_log(avctx, AV_LOG_ERROR, "Opus mapping family undefined for %d channels.\n", - avctx->channels); + avctx->ch_layout.nb_channels); return AVERROR(EINVAL); } @@ -190,16 +190,16 @@ static int libopus_check_max_channels(AVCodecContext *avctx, } static int libopus_check_vorbis_layout(AVCodecContext *avctx, int mapping_family) { - av_assert2(avctx->channels < FF_ARRAY_ELEMS(ff_vorbis_channel_layouts)); + av_assert2(avctx->ch_layout.nb_channels < FF_ARRAY_ELEMS(ff_vorbis_ch_layouts)); - if (!avctx->channel_layout) { + if (avctx->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) { av_log(avctx, AV_LOG_WARNING, "No channel layout specified. Opus encoder will use Vorbis " - "channel layout for %d channels.\n", avctx->channels); - } else if (avctx->channel_layout != ff_vorbis_channel_layouts[avctx->channels - 1]) { + "channel layout for %d channels.\n", avctx->ch_layout.nb_channels); + } else if (av_channel_layout_compare(&avctx->ch_layout, &ff_vorbis_ch_layouts[avctx->ch_layout.nb_channels - 1])) { char name[32]; - av_get_channel_layout_string(name, sizeof(name), avctx->channels, - avctx->channel_layout); + + av_channel_layout_describe(&avctx->ch_layout, name, sizeof(name)); av_log(avctx, AV_LOG_ERROR, "Invalid channel layout %s for specified mapping family %d.\n", name, mapping_family); @@ -238,7 +238,7 @@ static int libopus_validate_layout_and_get_channel_map( ret = libopus_check_max_channels(avctx, 8); if (ret == 0) { ret = libopus_check_vorbis_layout(avctx, mapping_family); - channel_map = ff_vorbis_channel_layout_offsets[avctx->channels - 1]; + channel_map = ff_vorbis_channel_layout_offsets[avctx->ch_layout.nb_channels - 1]; } break; case 255: @@ -261,6 +261,7 @@ static av_cold int libopus_encode_init(AVCodecContext *avctx) OpusMSEncoder *enc; uint8_t libopus_channel_mapping[255]; int ret = OPUS_OK; + int channels = avctx->ch_layout.nb_channels; int av_ret; int coupled_stream_count, header_size, frame_size; int mapping_family; @@ -348,17 +349,17 @@ static av_cold int libopus_encode_init(AVCodecContext *avctx) * libopus multistream API to avoid surround masking. */ /* Set the mapping family so that the value is correct in the header */ - mapping_family = avctx->channels > 2 ? 1 : 0; - coupled_stream_count = opus_coupled_streams[avctx->channels - 1]; - opus->stream_count = avctx->channels - coupled_stream_count; + mapping_family = channels > 2 ? 1 : 0; + coupled_stream_count = opus_coupled_streams[channels - 1]; + opus->stream_count = channels - coupled_stream_count; memcpy(libopus_channel_mapping, - opus_vorbis_channel_map[avctx->channels - 1], - avctx->channels * sizeof(*libopus_channel_mapping)); + opus_vorbis_channel_map[channels - 1], + channels * sizeof(*libopus_channel_mapping)); enc = opus_multistream_encoder_create( - avctx->sample_rate, avctx->channels, opus->stream_count, + avctx->sample_rate, channels, opus->stream_count, coupled_stream_count, - libavcodec_libopus_channel_map[avctx->channels - 1], + libavcodec_libopus_channel_map[channels - 1], opus->opts.application, &ret); } else { /* Use the newer multistream API. The encoder will set the channel @@ -366,7 +367,7 @@ static av_cold int libopus_encode_init(AVCodecContext *avctx) * use surround masking analysis to save bits. */ mapping_family = opus->opts.mapping_family; enc = opus_multistream_surround_encoder_create( - avctx->sample_rate, avctx->channels, mapping_family, + avctx->sample_rate, channels, mapping_family, &opus->stream_count, &coupled_stream_count, libopus_channel_mapping, opus->opts.application, &ret); } @@ -385,10 +386,10 @@ static av_cold int libopus_encode_init(AVCodecContext *avctx) "No bit rate set. Defaulting to %"PRId64" bps.\n", avctx->bit_rate); } - if (avctx->bit_rate < 500 || avctx->bit_rate > 256000 * avctx->channels) { + if (avctx->bit_rate < 500 || avctx->bit_rate > 256000 * channels) { av_log(avctx, AV_LOG_ERROR, "The bit rate %"PRId64" bps is unsupported. " "Please choose a value between 500 and %d.\n", avctx->bit_rate, - 256000 * avctx->channels); + 256000 * channels); ret = AVERROR(EINVAL); goto fail; } @@ -400,7 +401,7 @@ static av_cold int libopus_encode_init(AVCodecContext *avctx) } /* Header includes channel mapping table if and only if mapping family is NOT 0 */ - header_size = 19 + (mapping_family == 0 ? 0 : 2 + avctx->channels); + header_size = 19 + (mapping_family == 0 ? 0 : 2 + channels); avctx->extradata = av_malloc(header_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!avctx->extradata) { av_log(avctx, AV_LOG_ERROR, "Failed to allocate extradata.\n"); @@ -409,7 +410,7 @@ static av_cold int libopus_encode_init(AVCodecContext *avctx) } avctx->extradata_size = header_size; - opus->samples = av_calloc(frame_size, avctx->channels * + opus->samples = av_calloc(frame_size, channels * av_get_bytes_per_sample(avctx->sample_fmt)); if (!opus->samples) { av_log(avctx, AV_LOG_ERROR, "Failed to allocate samples buffer.\n"); @@ -456,7 +457,8 @@ static int libopus_encode(AVCodecContext *avctx, AVPacket *avpkt, { LibopusEncContext *opus = avctx->priv_data; const int bytes_per_sample = av_get_bytes_per_sample(avctx->sample_fmt); - const int sample_size = avctx->channels * bytes_per_sample; + const int channels = avctx->ch_layout.nb_channels; + const int sample_size = channels * bytes_per_sample; uint8_t *audio; int ret; int discard_padding; @@ -469,7 +471,7 @@ static int libopus_encode(AVCodecContext *avctx, AVPacket *avpkt, audio = opus->samples; libopus_copy_samples_with_channel_map( audio, frame->data[0], opus->encoder_channel_map, - avctx->channels, frame->nb_samples, bytes_per_sample); + channels, frame->nb_samples, bytes_per_sample); } else if (frame->nb_samples < opus->opts.packet_size) { audio = opus->samples; memcpy(audio, frame->data[0], frame->nb_samples * sample_size); @@ -571,7 +573,7 @@ static const AVClass libopus_class = { .version = LIBAVUTIL_VERSION_INT, }; -static const AVCodecDefault libopus_defaults[] = { +static const FFCodecDefault libopus_defaults[] = { { "b", "0" }, { "compression_level", "10" }, { NULL }, @@ -581,21 +583,21 @@ static const int libopus_sample_rates[] = { 48000, 24000, 16000, 12000, 8000, 0, }; -const AVCodec ff_libopus_encoder = { - .name = "libopus", - .long_name = NULL_IF_CONFIG_SMALL("libopus Opus"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_OPUS, +const FFCodec ff_libopus_encoder = { + .p.name = "libopus", + .p.long_name = NULL_IF_CONFIG_SMALL("libopus Opus"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_OPUS, .priv_data_size = sizeof(LibopusEncContext), .init = libopus_encode_init, - .encode2 = libopus_encode, + FF_CODEC_ENCODE_CB(libopus_encode), .close = libopus_encode_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SMALL_LAST_FRAME, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SMALL_LAST_FRAME, + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_NONE }, - .supported_samplerates = libopus_sample_rates, - .priv_class = &libopus_class, + .p.supported_samplerates = libopus_sample_rates, + .p.priv_class = &libopus_class, .defaults = libopus_defaults, - .wrapper_name = "libopus", + .p.wrapper_name = "libopus", }; diff --git a/libavcodec/librav1e.c b/libavcodec/librav1e.c index a368ee508..9d811ba81 100644 --- a/libavcodec/librav1e.c +++ b/libavcodec/librav1e.c @@ -31,6 +31,7 @@ #include "libavutil/pixdesc.h" #include "avcodec.h" #include "bsf.h" +#include "codec_internal.h" #include "encode.h" #include "internal.h" @@ -581,7 +582,7 @@ static const AVOption options[] = { { NULL } }; -static const AVCodecDefault librav1e_defaults[] = { +static const FFCodecDefault librav1e_defaults[] = { { "b", "0" }, { "g", "0" }, { "keyint_min", "0" }, @@ -613,20 +614,20 @@ static const AVClass class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_librav1e_encoder = { - .name = "librav1e", - .long_name = NULL_IF_CONFIG_SMALL("librav1e AV1"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_AV1, +const FFCodec ff_librav1e_encoder = { + .p.name = "librav1e", + .p.long_name = NULL_IF_CONFIG_SMALL("librav1e AV1"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_AV1, .init = librav1e_encode_init, - .receive_packet = librav1e_receive_packet, + FF_CODEC_RECEIVE_PACKET_CB(librav1e_receive_packet), .close = librav1e_encode_close, .priv_data_size = sizeof(librav1eContext), - .priv_class = &class, + .p.priv_class = &class, .defaults = librav1e_defaults, - .pix_fmts = librav1e_pix_fmts, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS | + .p.pix_fmts = librav1e_pix_fmts, + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS | AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_AUTO_THREADS, - .wrapper_name = "librav1e", + .p.wrapper_name = "librav1e", }; diff --git a/libavcodec/librsvgdec.c b/libavcodec/librsvgdec.c index 2895bbf28..6e949fe3d 100644 --- a/libavcodec/librsvgdec.c +++ b/libavcodec/librsvgdec.c @@ -20,6 +20,7 @@ */ #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "libavutil/opt.h" #include "librsvg-2.0/librsvg/rsvg.h" @@ -32,11 +33,11 @@ typedef struct LibRSVGContext { int keep_ar; } LibRSVGContext; -static int librsvg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *pkt) +static int librsvg_decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *pkt) { int ret; LibRSVGContext *s = avctx->priv_data; - AVFrame *frame = data; RsvgHandle *handle; RsvgDimensionData unscaled_dimensions, dimensions; @@ -117,14 +118,14 @@ static const AVClass librsvg_decoder_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_librsvg_decoder = { - .name = "librsvg", - .long_name = NULL_IF_CONFIG_SMALL("Librsvg rasterizer"), - .priv_class = &librsvg_decoder_class, - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_SVG, - .decode = librsvg_decode_frame, +const FFCodec ff_librsvg_decoder = { + .p.name = "librsvg", + .p.long_name = NULL_IF_CONFIG_SMALL("Librsvg rasterizer"), + .p.priv_class = &librsvg_decoder_class, + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_SVG, + .p.capabilities = AV_CODEC_CAP_DR1, + .p.wrapper_name = "librsvg", + FF_CODEC_DECODE_CB(librsvg_decode_frame), .priv_data_size = sizeof(LibRSVGContext), - .capabilities = AV_CODEC_CAP_DR1, - .wrapper_name = "librsvg", }; diff --git a/libavcodec/libshine.c b/libavcodec/libshine.c index fbc84846a..9bc545689 100644 --- a/libavcodec/libshine.c +++ b/libavcodec/libshine.c @@ -25,8 +25,8 @@ #include "libavutil/intreadwrite.h" #include "audio_frame_queue.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "mpegaudio.h" #include "mpegaudiodecheader.h" @@ -44,7 +44,7 @@ static av_cold int libshine_encode_init(AVCodecContext *avctx) { SHINEContext *s = avctx->priv_data; - if (avctx->channels <= 0 || avctx->channels > 2){ + if (avctx->ch_layout.nb_channels <= 0 || avctx->ch_layout.nb_channels > 2){ av_log(avctx, AV_LOG_ERROR, "only mono or stereo is supported\n"); return AVERROR(EINVAL); } @@ -52,9 +52,9 @@ static av_cold int libshine_encode_init(AVCodecContext *avctx) shine_set_config_mpeg_defaults(&s->config.mpeg); if (avctx->bit_rate) s->config.mpeg.bitr = avctx->bit_rate / 1000; - s->config.mpeg.mode = avctx->channels == 2 ? STEREO : MONO; + s->config.mpeg.mode = avctx->ch_layout.nb_channels == 2 ? STEREO : MONO; s->config.wave.samplerate = avctx->sample_rate; - s->config.wave.channels = avctx->channels == 2 ? PCM_STEREO : PCM_MONO; + s->config.wave.channels = avctx->ch_layout.nb_channels == 2 ? PCM_STEREO : PCM_MONO; if (shine_check_config(s->config.wave.samplerate, s->config.mpeg.bitr) < 0) { av_log(avctx, AV_LOG_ERROR, "invalid configuration\n"); return AVERROR(EINVAL); @@ -131,21 +131,27 @@ static const int libshine_sample_rates[] = { 44100, 48000, 32000, 0 }; -const AVCodec ff_libshine_encoder = { - .name = "libshine", - .long_name = NULL_IF_CONFIG_SMALL("libshine MP3 (MPEG audio layer 3)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_MP3, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, +const FFCodec ff_libshine_encoder = { + .p.name = "libshine", + .p.long_name = NULL_IF_CONFIG_SMALL("libshine MP3 (MPEG audio layer 3)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_MP3, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, .priv_data_size = sizeof(SHINEContext), .init = libshine_encode_init, - .encode2 = libshine_encode_frame, + FF_CODEC_ENCODE_CB(libshine_encode_frame), .close = libshine_encode_close, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16P, + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE }, - .supported_samplerates = libshine_sample_rates, - .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO, + .p.supported_samplerates = libshine_sample_rates, +#if FF_API_OLD_CHANNEL_LAYOUT + .p.channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO, AV_CH_LAYOUT_STEREO, 0 }, - .wrapper_name = "libshine", +#endif + .p.ch_layouts = (const AVChannelLayout[]) { AV_CHANNEL_LAYOUT_MONO, + AV_CHANNEL_LAYOUT_STEREO, + { 0 }, + }, + .p.wrapper_name = "libshine", }; diff --git a/libavcodec/libspeexdec.c b/libavcodec/libspeexdec.c index 6f032907f..8c9e05e51 100644 --- a/libavcodec/libspeexdec.c +++ b/libavcodec/libspeexdec.c @@ -26,6 +26,7 @@ #include "libavutil/channel_layout.h" #include "libavutil/common.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" typedef struct LibSpeexContext { @@ -42,7 +43,7 @@ static av_cold int libspeex_decode_init(AVCodecContext *avctx) LibSpeexContext *s = avctx->priv_data; const SpeexMode *mode; SpeexHeader *header = NULL; - int spx_mode; + int spx_mode, channels; if (avctx->extradata && avctx->extradata_size >= 80) { header = speex_packet_to_header(avctx->extradata, @@ -68,7 +69,7 @@ static av_cold int libspeex_decode_init(AVCodecContext *avctx) spx_mode = 0; } else if (header) { avctx->sample_rate = header->rate; - avctx->channels = header->nb_channels; + channels = header->nb_channels; spx_mode = header->mode; speex_header_free(header); } else { @@ -94,14 +95,15 @@ static av_cold int libspeex_decode_init(AVCodecContext *avctx) if (!avctx->sample_rate) avctx->sample_rate = 8000 << spx_mode; - if (avctx->channels < 1 || avctx->channels > 2) { + if (channels < 1 || channels > 2) { /* libspeex can handle mono or stereo if initialized as stereo */ av_log(avctx, AV_LOG_ERROR, "Invalid channel count: %d.\n" - "Decoding as stereo.\n", avctx->channels); - avctx->channels = 2; + "Decoding as stereo.\n", channels); + channels = 2; } - avctx->channel_layout = avctx->channels == 2 ? AV_CH_LAYOUT_STEREO : - AV_CH_LAYOUT_MONO; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = channels == 2 ? (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO : + (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; speex_bits_init(&s->bits); s->dec_state = speex_decoder_init(mode); @@ -110,7 +112,7 @@ static av_cold int libspeex_decode_init(AVCodecContext *avctx) return -1; } - if (avctx->channels == 2) { + if (channels == 2) { SpeexCallback callback; callback.callback_id = SPEEX_INBAND_STEREO; callback.func = speex_std_stereo_request_handler; @@ -122,13 +124,12 @@ static av_cold int libspeex_decode_init(AVCodecContext *avctx) return 0; } -static int libspeex_decode_frame(AVCodecContext *avctx, void *data, +static int libspeex_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { uint8_t *buf = avpkt->data; int buf_size = avpkt->size; LibSpeexContext *s = avctx->priv_data; - AVFrame *frame = data; int16_t *output; int ret, consumed = 0; avctx->sample_fmt = AV_SAMPLE_FMT_S16; @@ -163,7 +164,7 @@ static int libspeex_decode_frame(AVCodecContext *avctx, void *data, av_log(avctx, AV_LOG_ERROR, "Error decoding Speex frame.\n"); return AVERROR_INVALIDDATA; } - if (avctx->channels == 2) + if (avctx->ch_layout.nb_channels == 2) speex_decode_stereo_int(output, s->frame_size, &s->stereo); *got_frame_ptr = 1; @@ -189,16 +190,16 @@ static av_cold void libspeex_decode_flush(AVCodecContext *avctx) speex_bits_reset(&s->bits); } -const AVCodec ff_libspeex_decoder = { - .name = "libspeex", - .long_name = NULL_IF_CONFIG_SMALL("libspeex Speex"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_SPEEX, +const FFCodec ff_libspeex_decoder = { + .p.name = "libspeex", + .p.long_name = NULL_IF_CONFIG_SMALL("libspeex Speex"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_SPEEX, + .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .p.wrapper_name = "libspeex", .priv_data_size = sizeof(LibSpeexContext), .init = libspeex_decode_init, .close = libspeex_decode_close, - .decode = libspeex_decode_frame, + FF_CODEC_DECODE_CB(libspeex_decode_frame), .flush = libspeex_decode_flush, - .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, - .wrapper_name = "libspeex", }; diff --git a/libavcodec/libspeexenc.c b/libavcodec/libspeexenc.c index d095b41be..ec4b3c6a8 100644 --- a/libavcodec/libspeexenc.c +++ b/libavcodec/libspeexenc.c @@ -28,8 +28,8 @@ * order to control various encoding parameters. * * Channels - * Speex only supports mono or stereo, so avctx->channels must be set to - * 1 or 2. + * Speex only supports mono or stereo, so avctx->ch_layout.nb_channels must + * be set to 1 or 2. * * Sample Rate / Encoding Mode * Speex has 3 modes, each of which uses a specific sample rate. @@ -89,8 +89,8 @@ #include "libavutil/common.h" #include "libavutil/opt.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "audio_frame_queue.h" /* TODO: Think about converting abr, vad, dtx and such flags to a bit field */ @@ -114,7 +114,7 @@ static av_cold void print_enc_params(AVCodecContext *avctx, { const char *mode_str = "unknown"; - av_log(avctx, AV_LOG_DEBUG, "channels: %d\n", avctx->channels); + av_log(avctx, AV_LOG_DEBUG, "channels: %d\n", avctx->ch_layout.nb_channels); switch (s->header.mode) { case SPEEX_MODEID_NB: mode_str = "narrowband"; break; case SPEEX_MODEID_WB: mode_str = "wideband"; break; @@ -146,15 +146,16 @@ static av_cold void print_enc_params(AVCodecContext *avctx, static av_cold int encode_init(AVCodecContext *avctx) { LibSpeexEncContext *s = avctx->priv_data; + int channels = avctx->ch_layout.nb_channels; const SpeexMode *mode; uint8_t *header_data; int header_size; int32_t complexity; /* channels */ - if (avctx->channels < 1 || avctx->channels > 2) { + if (channels < 1 || channels > 2) { av_log(avctx, AV_LOG_ERROR, "Invalid channels (%d). Only stereo and " - "mono are supported\n", avctx->channels); + "mono are supported\n", channels); return AVERROR(EINVAL); } @@ -175,7 +176,7 @@ static av_cold int encode_init(AVCodecContext *avctx) av_log(avctx, AV_LOG_ERROR, "Error initializing libspeex\n"); return -1; } - speex_init_header(&s->header, avctx->sample_rate, avctx->channels, mode); + speex_init_header(&s->header, avctx->sample_rate, channels, mode); /* rate control method and parameters */ if (avctx->flags & AV_CODEC_FLAG_QSCALE) { @@ -210,7 +211,7 @@ static av_cold int encode_init(AVCodecContext *avctx) } /* stereo side information adds about 800 bps to the base bitrate */ /* TODO: this should be calculated exactly */ - avctx->bit_rate = s->header.bitrate + (avctx->channels == 2 ? 800 : 0); + avctx->bit_rate = s->header.bitrate + (channels == 2 ? 800 : 0); } /* VAD is activated with VBR or can be turned on by itself */ @@ -275,7 +276,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *avpkt, if (samples) { /* encode Speex frame */ - if (avctx->channels == 2) + if (avctx->ch_layout.nb_channels == 2) speex_encode_stereo_int(samples, s->header.frame_size, &s->bits); speex_encode_int(s->enc_state, samples, &s->bits); s->pkt_frame_count++; @@ -341,29 +342,35 @@ static const AVClass speex_class = { .version = LIBAVUTIL_VERSION_INT, }; -static const AVCodecDefault defaults[] = { +static const FFCodecDefault defaults[] = { { "b", "0" }, { "compression_level", "3" }, { NULL }, }; -const AVCodec ff_libspeex_encoder = { - .name = "libspeex", - .long_name = NULL_IF_CONFIG_SMALL("libspeex Speex"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_SPEEX, +const FFCodec ff_libspeex_encoder = { + .p.name = "libspeex", + .p.long_name = NULL_IF_CONFIG_SMALL("libspeex Speex"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_SPEEX, .priv_data_size = sizeof(LibSpeexEncContext), .init = encode_init, - .encode2 = encode_frame, + FF_CODEC_ENCODE_CB(encode_frame), .close = encode_close, - .capabilities = AV_CODEC_CAP_DELAY, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + .p.capabilities = AV_CODEC_CAP_DELAY, + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, - .channel_layouts = (const uint64_t[]){ AV_CH_LAYOUT_MONO, +#if FF_API_OLD_CHANNEL_LAYOUT + .p.channel_layouts = (const uint64_t[]){ AV_CH_LAYOUT_MONO, AV_CH_LAYOUT_STEREO, 0 }, - .supported_samplerates = (const int[]){ 8000, 16000, 32000, 0 }, - .priv_class = &speex_class, +#endif + .p.ch_layouts = (const AVChannelLayout[]) { AV_CHANNEL_LAYOUT_MONO, + AV_CHANNEL_LAYOUT_STEREO, + { 0 }, + }, + .p.supported_samplerates = (const int[]){ 8000, 16000, 32000, 0 }, + .p.priv_class = &speex_class, .defaults = defaults, - .wrapper_name = "libspeex", + .p.wrapper_name = "libspeex", }; diff --git a/libavcodec/libsvtav1.c b/libavcodec/libsvtav1.c index 6196da25e..d9ebb6aa5 100644 --- a/libavcodec/libsvtav1.c +++ b/libavcodec/libsvtav1.c @@ -31,6 +31,7 @@ #include "libavutil/pixdesc.h" #include "libavutil/avassert.h" +#include "codec_internal.h" #include "internal.h" #include "encode.h" #include "packet_internal.h" @@ -60,17 +61,20 @@ typedef struct SvtContext { EOS_STATUS eos_flag; // User options. + AVDictionary *svtav1_opts; +#if FF_API_SVTAV1_OPTS int hierarchical_level; int la_depth; - int enc_mode; - int rc_mode; int scd; - int qp; int tier; int tile_columns; int tile_rows; +#endif + int enc_mode; + int crf; + int qp; } SvtContext; static const struct { @@ -151,11 +155,126 @@ static int config_enc_params(EbSvtAv1EncConfiguration *param, { SvtContext *svt_enc = avctx->priv_data; const AVPixFmtDescriptor *desc; + AVDictionaryEntry *en = NULL; + + // Update param from options +#if FF_API_SVTAV1_OPTS + param->hierarchical_levels = svt_enc->hierarchical_level; + param->tier = svt_enc->tier; + param->scene_change_detection = svt_enc->scd; + param->tile_columns = svt_enc->tile_columns; + param->tile_rows = svt_enc->tile_rows; + + if (svt_enc->la_depth >= 0) + param->look_ahead_distance = svt_enc->la_depth; +#endif + + if (svt_enc->enc_mode >= 0) + param->enc_mode = svt_enc->enc_mode; + + if (avctx->bit_rate) { + param->target_bit_rate = avctx->bit_rate; + if (avctx->rc_max_rate != avctx->bit_rate) + param->rate_control_mode = 1; + else + param->rate_control_mode = 2; + + param->max_qp_allowed = avctx->qmax; + param->min_qp_allowed = avctx->qmin; + } + param->max_bit_rate = avctx->rc_max_rate; + param->vbv_bufsize = avctx->rc_buffer_size; + + if (svt_enc->crf > 0) { + param->qp = svt_enc->crf; + param->rate_control_mode = 0; + } else if (svt_enc->qp > 0) { + param->qp = svt_enc->qp; + param->rate_control_mode = 0; + param->enable_adaptive_quantization = 0; + } + + desc = av_pix_fmt_desc_get(avctx->pix_fmt); + param->color_primaries = avctx->color_primaries; + param->matrix_coefficients = (desc->flags & AV_PIX_FMT_FLAG_RGB) ? + AVCOL_SPC_RGB : avctx->colorspace; + param->transfer_characteristics = avctx->color_trc; + + if (avctx->color_range != AVCOL_RANGE_UNSPECIFIED) + param->color_range = avctx->color_range == AVCOL_RANGE_JPEG; + else + param->color_range = !!(desc->flags & AV_PIX_FMT_FLAG_RGB); + +#if SVT_AV1_CHECK_VERSION(1, 0, 0) + if (avctx->chroma_sample_location != AVCHROMA_LOC_UNSPECIFIED) { + const char *name = + av_chroma_location_name(avctx->chroma_sample_location); + + switch (avctx->chroma_sample_location) { + case AVCHROMA_LOC_LEFT: + param->chroma_sample_position = EB_CSP_VERTICAL; + break; + case AVCHROMA_LOC_TOPLEFT: + param->chroma_sample_position = EB_CSP_COLOCATED; + break; + default: + if (!name) + break; + + av_log(avctx, AV_LOG_WARNING, + "Specified chroma sample location %s is unsupported " + "on the AV1 bit stream level. Usage of a container that " + "allows passing this information - such as Matroska - " + "is recommended.\n", + name); + break; + } + } +#endif + + if (avctx->profile != FF_PROFILE_UNKNOWN) + param->profile = avctx->profile; + + if (avctx->level != FF_LEVEL_UNKNOWN) + param->level = avctx->level; + + if (avctx->gop_size > 0) + param->intra_period_length = avctx->gop_size - 1; + + if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { + param->frame_rate_numerator = avctx->framerate.num; + param->frame_rate_denominator = avctx->framerate.den; + } else { + param->frame_rate_numerator = avctx->time_base.den; + param->frame_rate_denominator = avctx->time_base.num * avctx->ticks_per_frame; + } + + /* 2 = IDR, closed GOP, 1 = CRA, open GOP */ + param->intra_refresh_type = avctx->flags & AV_CODEC_FLAG_CLOSED_GOP ? 2 : 1; + +#if SVT_AV1_CHECK_VERSION(0, 9, 1) + while ((en = av_dict_get(svt_enc->svtav1_opts, "", en, AV_DICT_IGNORE_SUFFIX))) { + EbErrorType ret = svt_av1_enc_parse_parameter(param, en->key, en->value); + if (ret != EB_ErrorNone) { + int level = (avctx->err_recognition & AV_EF_EXPLODE) ? AV_LOG_ERROR : AV_LOG_WARNING; + av_log(avctx, level, "Error parsing option %s: %s.\n", en->key, en->value); + if (avctx->err_recognition & AV_EF_EXPLODE) + return AVERROR(EINVAL); + } + } +#else + if ((en = av_dict_get(svt_enc->svtav1_opts, "", NULL, AV_DICT_IGNORE_SUFFIX))) { + int level = (avctx->err_recognition & AV_EF_EXPLODE) ? AV_LOG_ERROR : AV_LOG_WARNING; + av_log(avctx, level, "svt-params needs libavcodec to be compiled with SVT-AV1 " + "headers >= 0.9.1.\n"); + if (avctx->err_recognition & AV_EF_EXPLODE) + return AVERROR(ENOSYS); + } +#endif param->source_width = avctx->width; param->source_height = avctx->height; - desc = av_pix_fmt_desc_get(avctx->pix_fmt); param->encoder_bit_depth = desc->comp[0].depth; if (desc->log2_chroma_w == 1 && desc->log2_chroma_h == 1) @@ -169,12 +288,6 @@ static int config_enc_params(EbSvtAv1EncConfiguration *param, return AVERROR(EINVAL); } - if (avctx->profile != FF_PROFILE_UNKNOWN) - param->profile = avctx->profile; - - if (avctx->level != FF_LEVEL_UNKNOWN) - param->level = avctx->level; - if ((param->encoder_color_format == EB_YUV422 || param->encoder_bit_depth > 10) && param->profile != FF_PROFILE_AV1_PROFESSIONAL ) { av_log(avctx, AV_LOG_WARNING, "Forcing Professional profile\n"); @@ -184,42 +297,21 @@ static int config_enc_params(EbSvtAv1EncConfiguration *param, param->profile = FF_PROFILE_AV1_HIGH; } - // Update param from options - param->hierarchical_levels = svt_enc->hierarchical_level; - param->enc_mode = svt_enc->enc_mode; - param->tier = svt_enc->tier; - param->rate_control_mode = svt_enc->rc_mode; - param->scene_change_detection = svt_enc->scd; - param->qp = svt_enc->qp; + avctx->bit_rate = param->rate_control_mode > 0 ? + param->target_bit_rate : 0; + avctx->rc_max_rate = param->max_bit_rate; + avctx->rc_buffer_size = param->vbv_bufsize; - param->target_bit_rate = avctx->bit_rate; + if (avctx->bit_rate || avctx->rc_max_rate || avctx->rc_buffer_size) { + AVCPBProperties *cpb_props = ff_add_cpb_side_data(avctx); + if (!cpb_props) + return AVERROR(ENOMEM); - if (avctx->gop_size > 0) - param->intra_period_length = avctx->gop_size - 1; - - if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { - param->frame_rate_numerator = avctx->framerate.num; - param->frame_rate_denominator = avctx->framerate.den; - } else { - param->frame_rate_numerator = avctx->time_base.den; - param->frame_rate_denominator = avctx->time_base.num * avctx->ticks_per_frame; + cpb_props->buffer_size = avctx->rc_buffer_size; + cpb_props->max_bitrate = avctx->rc_max_rate; + cpb_props->avg_bitrate = avctx->bit_rate; } - param->enable_tpl_la = !!param->rate_control_mode; - if (param->rate_control_mode) { - param->max_qp_allowed = avctx->qmax; - param->min_qp_allowed = avctx->qmin; - } - - /* 2 = IDR, closed GOP, 1 = CRA, open GOP */ - param->intra_refresh_type = avctx->flags & AV_CODEC_FLAG_CLOSED_GOP ? 2 : 1; - - if (svt_enc->la_depth >= 0) - param->look_ahead_distance = svt_enc->la_depth; - - param->tile_columns = svt_enc->tile_columns; - param->tile_rows = svt_enc->tile_rows; - return 0; } @@ -352,6 +444,16 @@ static int eb_send_frame(AVCodecContext *avctx, const AVFrame *frame) headerPtr->p_app_private = NULL; headerPtr->pts = frame->pts; + switch (frame->pict_type) { + case AV_PICTURE_TYPE_I: + headerPtr->pic_type = EB_AV1_KEY_PICTURE; + break; + default: + // Actually means auto, or default. + headerPtr->pic_type = EB_AV1_INVALID_PICTURE; + break; + } + svt_av1_enc_send_picture(svt_enc->svt_handle, headerPtr); return 0; @@ -474,21 +576,22 @@ static av_cold int eb_enc_close(AVCodecContext *avctx) #define OFFSET(x) offsetof(SvtContext, x) #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { - { "hielevel", "Hierarchical prediction levels setting", OFFSET(hierarchical_level), - AV_OPT_TYPE_INT, { .i64 = 4 }, 3, 4, VE , "hielevel"}, +#if FF_API_SVTAV1_OPTS + { "hielevel", "Hierarchical prediction levels setting (Deprecated, use svtav1-params)", OFFSET(hierarchical_level), + AV_OPT_TYPE_INT, { .i64 = 4 }, 3, 4, VE | AV_OPT_FLAG_DEPRECATED , "hielevel"}, { "3level", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 3 }, INT_MIN, INT_MAX, VE, "hielevel" }, { "4level", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 4 }, INT_MIN, INT_MAX, VE, "hielevel" }, - { "la_depth", "Look ahead distance [0, 120]", OFFSET(la_depth), - AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 120, VE }, + { "la_depth", "Look ahead distance [0, 120] (Deprecated, use svtav1-params)", OFFSET(la_depth), + AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 120, VE | AV_OPT_FLAG_DEPRECATED }, - { "preset", "Encoding preset [0, 8]", - OFFSET(enc_mode), AV_OPT_TYPE_INT, { .i64 = MAX_ENC_PRESET }, 0, MAX_ENC_PRESET, VE }, - - { "tier", "Set operating point tier", OFFSET(tier), - AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE, "tier" }, + { "tier", "Set operating point tier (Deprecated, use svtav1-params)", OFFSET(tier), + AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE | AV_OPT_FLAG_DEPRECATED, "tier" }, { "main", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, VE, "tier" }, { "high", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, VE, "tier" }, +#endif + { "preset", "Encoding preset", + OFFSET(enc_mode), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, MAX_ENC_PRESET, VE }, FF_AV1_PROFILE_OPTS @@ -520,20 +623,19 @@ static const AVOption options[] = { { LEVEL("7.3", 73) }, #undef LEVEL - { "rc", "Bit rate control mode", OFFSET(rc_mode), - AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, VE , "rc"}, - { "cqp", "Constant quantizer", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, VE, "rc" }, - { "vbr", "Variable Bit Rate, use a target bitrate for the entire stream", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, VE, "rc" }, - { "cvbr", "Constrained Variable Bit Rate, use a target bitrate for each GOP", 0, AV_OPT_TYPE_CONST,{ .i64 = 2 }, INT_MIN, INT_MAX, VE, "rc" }, + { "crf", "Constant Rate Factor value", OFFSET(crf), + AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 63, VE }, + { "qp", "Initial Quantizer level value", OFFSET(qp), + AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 63, VE }, +#if FF_API_SVTAV1_OPTS + { "sc_detection", "Scene change detection (Deprecated, use svtav1-params)", OFFSET(scd), + AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE | AV_OPT_FLAG_DEPRECATED }, - { "qp", "Quantizer to use with cqp rate control mode", OFFSET(qp), - AV_OPT_TYPE_INT, { .i64 = 50 }, 0, 63, VE }, + { "tile_columns", "Log2 of number of tile columns to use (Deprecated, use svtav1-params)", OFFSET(tile_columns), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 4, VE | AV_OPT_FLAG_DEPRECATED }, + { "tile_rows", "Log2 of number of tile rows to use (Deprecated, use svtav1-params)", OFFSET(tile_rows), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 6, VE | AV_OPT_FLAG_DEPRECATED }, +#endif - { "sc_detection", "Scene change detection", OFFSET(scd), - AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, - - { "tile_columns", "Log2 of number of tile columns to use", OFFSET(tile_columns), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 4, VE}, - { "tile_rows", "Log2 of number of tile rows to use", OFFSET(tile_rows), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 6, VE}, + { "svtav1-params", "Set the SVT-AV1 configuration using a :-separated list of key=value parameters", OFFSET(svtav1_opts), AV_OPT_TYPE_DICT, { 0 }, 0, 0, VE }, {NULL}, }; @@ -545,30 +647,30 @@ static const AVClass class = { .version = LIBAVUTIL_VERSION_INT, }; -static const AVCodecDefault eb_enc_defaults[] = { - { "b", "7M" }, +static const FFCodecDefault eb_enc_defaults[] = { + { "b", "0" }, { "flags", "+cgop" }, { "g", "-1" }, - { "qmin", "0" }, + { "qmin", "1" }, { "qmax", "63" }, { NULL }, }; -const AVCodec ff_libsvtav1_encoder = { - .name = "libsvtav1", - .long_name = NULL_IF_CONFIG_SMALL("SVT-AV1(Scalable Video Technology for AV1) encoder"), +const FFCodec ff_libsvtav1_encoder = { + .p.name = "libsvtav1", + .p.long_name = NULL_IF_CONFIG_SMALL("SVT-AV1(Scalable Video Technology for AV1) encoder"), .priv_data_size = sizeof(SvtContext), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_AV1, + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_AV1, .init = eb_enc_init, - .receive_packet = eb_receive_packet, + FF_CODEC_RECEIVE_PACKET_CB(eb_receive_packet), .close = eb_enc_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS, + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS, .caps_internal = FF_CODEC_CAP_AUTO_THREADS | FF_CODEC_CAP_INIT_CLEANUP, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P10, AV_PIX_FMT_NONE }, - .priv_class = &class, + .p.priv_class = &class, .defaults = eb_enc_defaults, - .wrapper_name = "libsvtav1", + .p.wrapper_name = "libsvtav1", }; diff --git a/libavcodec/libtheoraenc.c b/libavcodec/libtheoraenc.c index a74fab9ef..162d170b0 100644 --- a/libavcodec/libtheoraenc.c +++ b/libavcodec/libtheoraenc.c @@ -37,8 +37,8 @@ #include "libavutil/log.h" #include "libavutil/base64.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" /* libtheora includes */ #include @@ -367,19 +367,19 @@ static av_cold int encode_close(AVCodecContext* avc_context) } /** AVCodec struct exposed to libavcodec */ -const AVCodec ff_libtheora_encoder = { - .name = "libtheora", - .long_name = NULL_IF_CONFIG_SMALL("libtheora Theora"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_THEORA, - .capabilities = AV_CODEC_CAP_DR1 | +const FFCodec ff_libtheora_encoder = { + .p.name = "libtheora", + .p.long_name = NULL_IF_CONFIG_SMALL("libtheora Theora"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_THEORA, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY /* for statsfile summary */, .priv_data_size = sizeof(TheoraContext), .init = encode_init, .close = encode_close, - .encode2 = encode_frame, - .pix_fmts = (const enum AVPixelFormat[]){ + FF_CODEC_ENCODE_CB(encode_frame), + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_NONE }, - .wrapper_name = "libtheora", + .p.wrapper_name = "libtheora", }; diff --git a/libavcodec/libtwolame.c b/libavcodec/libtwolame.c index a71febc91..1e53cf225 100644 --- a/libavcodec/libtwolame.c +++ b/libavcodec/libtwolame.c @@ -31,6 +31,7 @@ #include "libavutil/opt.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" #include "internal.h" #include "mpegaudio.h" @@ -76,12 +77,12 @@ static av_cold int twolame_encode_init(AVCodecContext *avctx) twolame_set_copyright(s->glopts, s->copyright); twolame_set_original(s->glopts, s->original); - twolame_set_num_channels(s->glopts, avctx->channels); + twolame_set_num_channels(s->glopts, avctx->ch_layout.nb_channels); twolame_set_in_samplerate(s->glopts, avctx->sample_rate); twolame_set_out_samplerate(s->glopts, avctx->sample_rate); if (!avctx->bit_rate) { - if ((s->mode == TWOLAME_AUTO_MODE && avctx->channels == 1) || s->mode == TWOLAME_MONO) + if ((s->mode == TWOLAME_AUTO_MODE && avctx->ch_layout.nb_channels == 1) || s->mode == TWOLAME_MONO) avctx->bit_rate = avctx->sample_rate < 28000 ? 80000 : 192000; else avctx->bit_rate = avctx->sample_rate < 28000 ? 160000 : 384000; @@ -199,7 +200,7 @@ static const AVClass twolame_class = { .version = LIBAVUTIL_VERSION_INT, }; -static const AVCodecDefault twolame_defaults[] = { +static const FFCodecDefault twolame_defaults[] = { { "b", "0" }, { NULL }, }; @@ -208,29 +209,36 @@ static const int twolame_samplerates[] = { 16000, 22050, 24000, 32000, 44100, 48000, 0 }; -const AVCodec ff_libtwolame_encoder = { - .name = "libtwolame", - .long_name = NULL_IF_CONFIG_SMALL("libtwolame MP2 (MPEG audio layer 2)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_MP2, +const FFCodec ff_libtwolame_encoder = { + .p.name = "libtwolame", + .p.long_name = NULL_IF_CONFIG_SMALL("libtwolame MP2 (MPEG audio layer 2)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_MP2, .priv_data_size = sizeof(TWOLAMEContext), .init = twolame_encode_init, - .encode2 = twolame_encode_frame, + FF_CODEC_ENCODE_CB(twolame_encode_frame), .close = twolame_encode_close, - .capabilities = AV_CODEC_CAP_DELAY, + .p.capabilities = AV_CODEC_CAP_DELAY, .defaults = twolame_defaults, - .priv_class = &twolame_class, - .sample_fmts = (const enum AVSampleFormat[]) { + .p.priv_class = &twolame_class, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE }, - .channel_layouts = (const uint64_t[]) { +#if FF_API_OLD_CHANNEL_LAYOUT + .p.channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO, AV_CH_LAYOUT_STEREO, 0 }, - .supported_samplerates = twolame_samplerates, - .wrapper_name = "libtwolame", +#endif + .p.ch_layouts = (const AVChannelLayout[]) { + AV_CHANNEL_LAYOUT_MONO, + AV_CHANNEL_LAYOUT_STEREO, + { 0 }, + }, + .p.supported_samplerates = twolame_samplerates, + .p.wrapper_name = "libtwolame", }; diff --git a/libavcodec/libuavs3d.c b/libavcodec/libuavs3d.c index d8d09cacb..7c6c3f044 100644 --- a/libavcodec/libuavs3d.c +++ b/libavcodec/libuavs3d.c @@ -1,5 +1,5 @@ /* - * RAW AVS3-P2/IEEE1857.10 video demuxer + * AVS3-P2/IEEE1857.10 video decoder (using the uavs3d library) * Copyright (c) 2020 Zhenyu Wang * Bingjie Han * Huiwen Ren @@ -29,6 +29,7 @@ #include "libavutil/opt.h" #include "avcodec.h" #include "avs3.h" +#include "codec_internal.h" #include "internal.h" #include "uavs3d.h" @@ -83,13 +84,13 @@ static void uavs3d_output_callback(uavs3d_io_frm_t *dec_frame) { frm->coded_picture_number = dec_frame->dtr; frm->display_picture_number = dec_frame->ptr; - if (dec_frame->type < 0 || dec_frame->type >= 4) { + if (dec_frame->type < 0 || dec_frame->type >= FF_ARRAY_ELEMS(ff_avs3_image_type)) { av_log(NULL, AV_LOG_WARNING, "Error frame type in uavs3d: %d.\n", dec_frame->type); + } else { + frm->pict_type = ff_avs3_image_type[dec_frame->type]; + frm->key_frame = (frm->pict_type == AV_PICTURE_TYPE_I); } - frm->pict_type = ff_avs3_image_type[dec_frame->type]; - frm->key_frame = (frm->pict_type == AV_PICTURE_TYPE_I); - for (i = 0; i < 3; i++) { frm_out.width [i] = dec_frame->width[i]; frm_out.height[i] = dec_frame->height[i]; @@ -141,14 +142,14 @@ static void libuavs3d_flush(AVCodecContext * avctx) } #define UAVS3D_CHECK_INVALID_RANGE(v, l, r) ((v)<(l)||(v)>(r)) -static int libuavs3d_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) +static int libuavs3d_decode_frame(AVCodecContext *avctx, AVFrame *frm, + int *got_frame, AVPacket *avpkt) { uavs3d_context *h = avctx->priv_data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; const uint8_t *buf_end; - const uint8_t *buf_ptr; - AVFrame *frm = data; + const uint8_t *buf_ptr = buf; int left_bytes; int ret, finish = 0; @@ -161,7 +162,7 @@ static int libuavs3d_decode_frame(AVCodecContext *avctx, void *data, int *got_fr if (!frm->data[0] && (ret = ff_get_buffer(avctx, frm, 0)) < 0) { return ret; } - h->dec_frame.priv = data; // AVFrame + h->dec_frame.priv = frm; // AVFrame } do { ret = uavs3d_flush(h->dec_handle, &h->dec_frame); @@ -169,7 +170,6 @@ static int libuavs3d_decode_frame(AVCodecContext *avctx, void *data, int *got_fr } else { uavs3d_io_frm_t *frm_dec = &h->dec_frame; - buf_ptr = buf; buf_end = buf + buf_size; frm_dec->pkt_pos = avpkt->pos; frm_dec->pkt_size = avpkt->size; @@ -181,7 +181,7 @@ static int libuavs3d_decode_frame(AVCodecContext *avctx, void *data, int *got_fr if (!frm->data[0] && (ret = ff_get_buffer(avctx, frm, 0)) < 0) { return ret; } - h->dec_frame.priv = data; // AVFrame + h->dec_frame.priv = frm; // AVFrame } if (uavs3d_find_next_start_code(buf_ptr, buf_end - buf_ptr, &left_bytes)) { @@ -206,7 +206,7 @@ static int libuavs3d_decode_frame(AVCodecContext *avctx, void *data, int *got_fr avctx->framerate.num = ff_avs3_frame_rate_tab[seqh->frame_rate_code].num; avctx->framerate.den = ff_avs3_frame_rate_tab[seqh->frame_rate_code].den; } - avctx->has_b_frames = !seqh->low_delay; + avctx->has_b_frames = seqh->output_reorder_delay; avctx->pix_fmt = seqh->bit_depth_internal == 8 ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_YUV420P10LE; ret = ff_set_dimensions(avctx, seqh->horizontal_size, seqh->vertical_size); if (ret < 0) @@ -246,20 +246,20 @@ static int libuavs3d_decode_frame(AVCodecContext *avctx, void *data, int *got_fr return buf_ptr - buf; } -const AVCodec ff_libuavs3d_decoder = { - .name = "libuavs3d", - .long_name = NULL_IF_CONFIG_SMALL("libuavs3d AVS3-P2/IEEE1857.10"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_AVS3, +const FFCodec ff_libuavs3d_decoder = { + .p.name = "libuavs3d", + .p.long_name = NULL_IF_CONFIG_SMALL("libuavs3d AVS3-P2/IEEE1857.10"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_AVS3, .priv_data_size = sizeof(uavs3d_context), .init = libuavs3d_init, .close = libuavs3d_end, - .decode = libuavs3d_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS, + FF_CODEC_DECODE_CB(libuavs3d_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS, .caps_internal = FF_CODEC_CAP_AUTO_THREADS, .flush = libuavs3d_flush, - .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P10LE, AV_PIX_FMT_NONE }, - .wrapper_name = "libuavs3d", + .p.wrapper_name = "libuavs3d", }; diff --git a/libavcodec/libvo-amrwbenc.c b/libavcodec/libvo-amrwbenc.c index 9c7c91b61..12ef6d7fe 100644 --- a/libavcodec/libvo-amrwbenc.c +++ b/libavcodec/libvo-amrwbenc.c @@ -27,6 +27,7 @@ #include "libavutil/internal.h" #include "libavutil/opt.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" #include "internal.h" @@ -87,7 +88,7 @@ static av_cold int amr_wb_encode_init(AVCodecContext *avctx) return AVERROR(ENOSYS); } - if (avctx->channels != 1) { + if (avctx->ch_layout.nb_channels != 1) { av_log(avctx, AV_LOG_ERROR, "Only mono supported\n"); return AVERROR(ENOSYS); } @@ -139,18 +140,18 @@ static int amr_wb_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, return 0; } -const AVCodec ff_libvo_amrwbenc_encoder = { - .name = "libvo_amrwbenc", - .long_name = NULL_IF_CONFIG_SMALL("Android VisualOn AMR-WB " +const FFCodec ff_libvo_amrwbenc_encoder = { + .p.name = "libvo_amrwbenc", + .p.long_name = NULL_IF_CONFIG_SMALL("Android VisualOn AMR-WB " "(Adaptive Multi-Rate Wide-Band)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_AMR_WB, + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_AMR_WB, + .p.priv_class = &amrwb_class, + .p.wrapper_name = "libvo_amrwbenc", .priv_data_size = sizeof(AMRWBContext), .init = amr_wb_encode_init, - .encode2 = amr_wb_encode_frame, + FF_CODEC_ENCODE_CB(amr_wb_encode_frame), .close = amr_wb_encode_close, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + .p.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/libvorbisdec.c b/libavcodec/libvorbisdec.c index 5686aaf09..81c4ac1c0 100644 --- a/libavcodec/libvorbisdec.c +++ b/libavcodec/libvorbisdec.c @@ -22,6 +22,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" typedef struct OggVorbisDecContext { @@ -112,7 +113,9 @@ static int oggvorbis_decode_init(AVCodecContext *avccontext) { } } - avccontext->channels = context->vi.channels; + av_channel_layout_uninit(&avccontext->ch_layout); + avccontext->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + avccontext->ch_layout.nb_channels = context->vi.channels; avccontext->sample_rate = context->vi.rate; avccontext->sample_fmt = AV_SAMPLE_FMT_S16; avccontext->time_base= (AVRational){1, avccontext->sample_rate}; @@ -146,11 +149,10 @@ static inline int conv(int samples, float **pcm, char *buf, int channels) { return 0 ; } -static int oggvorbis_decode_frame(AVCodecContext *avccontext, void *data, - int *got_frame_ptr, AVPacket *avpkt) +static int oggvorbis_decode_frame(AVCodecContext *avccontext, AVFrame *frame, + int *got_frame_ptr, AVPacket *avpkt) { OggVorbisDecContext *context = avccontext->priv_data ; - AVFrame *frame = data; float **pcm ; ogg_packet *op= &context->op; int samples, total_samples, total_bytes; @@ -208,14 +210,14 @@ static int oggvorbis_decode_close(AVCodecContext *avccontext) { } -const AVCodec ff_libvorbis_decoder = { - .name = "libvorbis", - .long_name = NULL_IF_CONFIG_SMALL("libvorbis"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_VORBIS, +const FFCodec ff_libvorbis_decoder = { + .p.name = "libvorbis", + .p.long_name = NULL_IF_CONFIG_SMALL("libvorbis"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_VORBIS, + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_CHANNEL_CONF, .priv_data_size = sizeof(OggVorbisDecContext), .init = oggvorbis_decode_init, - .decode = oggvorbis_decode_frame, + FF_CODEC_DECODE_CB(oggvorbis_decode_frame), .close = oggvorbis_decode_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_CHANNEL_CONF, }; diff --git a/libavcodec/libvorbisenc.c b/libavcodec/libvorbisenc.c index fa0d5f4b4..9460d3267 100644 --- a/libavcodec/libvorbisenc.c +++ b/libavcodec/libvorbisenc.c @@ -26,8 +26,10 @@ #include "libavutil/opt.h" #include "avcodec.h" #include "audio_frame_queue.h" +#include "codec_internal.h" #include "encode.h" #include "internal.h" +#include "version.h" #include "vorbis.h" #include "vorbis_parser.h" @@ -46,7 +48,7 @@ typedef struct LibvorbisEncContext { vorbis_info vi; /**< vorbis_info used during init */ vorbis_dsp_state vd; /**< DSP state used for analysis */ vorbis_block vb; /**< vorbis_block used for analysis */ - AVFifoBuffer *pkt_fifo; /**< output packet buffer */ + AVFifo *pkt_fifo; /**< output packet buffer */ int eof; /**< end-of-file flag */ int dsp_initialized; /**< vd has been initialized */ vorbis_comment vc; /**< VorbisComment info */ @@ -60,7 +62,7 @@ static const AVOption options[] = { { NULL } }; -static const AVCodecDefault defaults[] = { +static const FFCodecDefault defaults[] = { { "b", "0" }, { NULL }, }; @@ -96,6 +98,7 @@ static int vorbis_error_to_averror(int ov_err) static av_cold int libvorbis_setup(vorbis_info *vi, AVCodecContext *avctx) { LibvorbisEncContext *s = avctx->priv_data; + int channels = avctx->ch_layout.nb_channels; double cfreq; int ret; @@ -108,7 +111,7 @@ static av_cold int libvorbis_setup(vorbis_info *vi, AVCodecContext *avctx) /* default to 3 if the user did not set quality or bitrate */ if (!(avctx->flags & AV_CODEC_FLAG_QSCALE)) q = 3.0; - if ((ret = vorbis_encode_setup_vbr(vi, avctx->channels, + if ((ret = vorbis_encode_setup_vbr(vi, channels, avctx->sample_rate, q / 10.0))) goto error; @@ -117,7 +120,7 @@ static av_cold int libvorbis_setup(vorbis_info *vi, AVCodecContext *avctx) int maxrate = avctx->rc_max_rate > 0 ? avctx->rc_max_rate : -1; /* average bitrate */ - if ((ret = vorbis_encode_setup_managed(vi, avctx->channels, + if ((ret = vorbis_encode_setup_managed(vi, channels, avctx->sample_rate, maxrate, avctx->bit_rate, minrate))) goto error; @@ -141,32 +144,31 @@ static av_cold int libvorbis_setup(vorbis_info *vi, AVCodecContext *avctx) goto error; } - if (avctx->channels == 3 && - avctx->channel_layout != (AV_CH_LAYOUT_STEREO|AV_CH_FRONT_CENTER) || - avctx->channels == 4 && - avctx->channel_layout != AV_CH_LAYOUT_2_2 && - avctx->channel_layout != AV_CH_LAYOUT_QUAD || - avctx->channels == 5 && - avctx->channel_layout != AV_CH_LAYOUT_5POINT0 && - avctx->channel_layout != AV_CH_LAYOUT_5POINT0_BACK || - avctx->channels == 6 && - avctx->channel_layout != AV_CH_LAYOUT_5POINT1 && - avctx->channel_layout != AV_CH_LAYOUT_5POINT1_BACK || - avctx->channels == 7 && - avctx->channel_layout != (AV_CH_LAYOUT_5POINT1|AV_CH_BACK_CENTER) || - avctx->channels == 8 && - avctx->channel_layout != AV_CH_LAYOUT_7POINT1) { - if (avctx->channel_layout) { + if ((channels == 3 && + av_channel_layout_compare(&avctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_SURROUND)) || + (channels == 4 && + av_channel_layout_compare(&avctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_2_2) && + av_channel_layout_compare(&avctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_QUAD)) || + (channels == 5 && + av_channel_layout_compare(&avctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT0) && + av_channel_layout_compare(&avctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT0_BACK)) || + (channels == 6 && + av_channel_layout_compare(&avctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1) && + av_channel_layout_compare(&avctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1_BACK)) || + (channels == 7 && + av_channel_layout_compare(&avctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_6POINT1)) || + (channels == 8 && + av_channel_layout_compare(&avctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_7POINT1))) { + if (avctx->ch_layout.order != AV_CHANNEL_ORDER_UNSPEC) { char name[32]; - av_get_channel_layout_string(name, sizeof(name), avctx->channels, - avctx->channel_layout); + av_channel_layout_describe(&avctx->ch_layout, name, sizeof(name)); av_log(avctx, AV_LOG_ERROR, "%s not supported by Vorbis: " "output stream will have incorrect " "channel layout.\n", name); } else { av_log(avctx, AV_LOG_WARNING, "No channel layout specified. The encoder " "will use Vorbis channel layout for " - "%d channels.\n", avctx->channels); + "%d channels.\n", channels); } } @@ -196,7 +198,7 @@ static av_cold int libvorbis_encode_close(AVCodecContext *avctx) vorbis_dsp_clear(&s->vd); vorbis_info_clear(&s->vi); - av_fifo_freep(&s->pkt_fifo); + av_fifo_freep2(&s->pkt_fifo); ff_af_queue_close(&s->afq); av_vorbis_parse_free(&s->vp); @@ -271,7 +273,7 @@ static av_cold int libvorbis_encode_init(AVCodecContext *avctx) avctx->frame_size = LIBVORBIS_FRAME_SIZE; ff_af_queue_init(avctx, &s->afq); - s->pkt_fifo = av_fifo_alloc(BUFFER_SIZE); + s->pkt_fifo = av_fifo_alloc2(BUFFER_SIZE, 1, 0); if (!s->pkt_fifo) { ret = AVERROR(ENOMEM); goto error; @@ -327,12 +329,12 @@ static int libvorbis_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, /* add any available packets to the output packet buffer */ while ((ret = vorbis_bitrate_flushpacket(&s->vd, &op)) == 1) { - if (av_fifo_space(s->pkt_fifo) < sizeof(ogg_packet) + op.bytes) { + if (av_fifo_can_write(s->pkt_fifo) < sizeof(ogg_packet) + op.bytes) { av_log(avctx, AV_LOG_ERROR, "packet buffer is too small\n"); return AVERROR_BUG; } - av_fifo_generic_write(s->pkt_fifo, &op, sizeof(ogg_packet), NULL); - av_fifo_generic_write(s->pkt_fifo, op.packet, op.bytes, NULL); + av_fifo_write(s->pkt_fifo, &op, sizeof(ogg_packet)); + av_fifo_write(s->pkt_fifo, op.packet, op.bytes); } if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "error getting available packets\n"); @@ -344,15 +346,13 @@ static int libvorbis_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, return vorbis_error_to_averror(ret); } - /* check for available packets */ - if (av_fifo_size(s->pkt_fifo) < sizeof(ogg_packet)) + /* Read an available packet if possible */ + if (av_fifo_read(s->pkt_fifo, &op, sizeof(ogg_packet)) < 0) return 0; - av_fifo_generic_read(s->pkt_fifo, &op, sizeof(ogg_packet), NULL); - if ((ret = ff_get_encode_buffer(avctx, avpkt, op.bytes, 0)) < 0) return ret; - av_fifo_generic_read(s->pkt_fifo, avpkt->data, op.bytes, NULL); + av_fifo_read(s->pkt_fifo, avpkt->data, op.bytes); avpkt->pts = ff_samples_to_time_base(avctx, op.granulepos); @@ -375,20 +375,20 @@ static int libvorbis_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, return 0; } -const AVCodec ff_libvorbis_encoder = { - .name = "libvorbis", - .long_name = NULL_IF_CONFIG_SMALL("libvorbis"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_VORBIS, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | +const FFCodec ff_libvorbis_encoder = { + .p.name = "libvorbis", + .p.long_name = NULL_IF_CONFIG_SMALL("libvorbis"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_VORBIS, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SMALL_LAST_FRAME, .priv_data_size = sizeof(LibvorbisEncContext), .init = libvorbis_encode_init, - .encode2 = libvorbis_encode_frame, + FF_CODEC_ENCODE_CB(libvorbis_encode_frame), .close = libvorbis_encode_close, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, - .priv_class = &vorbis_class, + .p.priv_class = &vorbis_class, .defaults = defaults, - .wrapper_name = "libvorbis", + .p.wrapper_name = "libvorbis", }; diff --git a/libavcodec/libvpx.c b/libavcodec/libvpx.c index cc055a003..8601f82bd 100644 --- a/libavcodec/libvpx.c +++ b/libavcodec/libvpx.c @@ -21,6 +21,7 @@ #include #include "libvpx.h" #include "config.h" +#include "config_components.h" #if CONFIG_LIBVPX_VP9_ENCODER #include @@ -65,16 +66,16 @@ static const enum AVPixelFormat vp9_pix_fmts_highbd[] = { }; #endif -av_cold void ff_vp9_init_static(AVCodec *codec) +av_cold void ff_vp9_init_static(FFCodec *codec) { - codec->pix_fmts = vp9_pix_fmts_def; + codec->p.pix_fmts = vp9_pix_fmts_def; #if CONFIG_LIBVPX_VP9_ENCODER { 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; + codec->p.pix_fmts = vp9_pix_fmts_highbd; else - codec->pix_fmts = vp9_pix_fmts_highcol; + codec->p.pix_fmts = vp9_pix_fmts_highcol; } #endif } diff --git a/libavcodec/libvpx.h b/libavcodec/libvpx.h index 22b697fa0..0caed8cdc 100644 --- a/libavcodec/libvpx.h +++ b/libavcodec/libvpx.h @@ -23,9 +23,9 @@ #include -#include "avcodec.h" +#include "codec_internal.h" -void ff_vp9_init_static(AVCodec *codec); +void ff_vp9_init_static(FFCodec *codec); #if 0 enum AVPixelFormat ff_vpx_imgfmt_to_pixfmt(vpx_img_fmt_t img); vpx_img_fmt_t ff_vpx_pixfmt_to_imgfmt(enum AVPixelFormat pix); diff --git a/libavcodec/libvpxdec.c b/libavcodec/libvpxdec.c index b2aa20503..0b279e7ed 100644 --- a/libavcodec/libvpxdec.c +++ b/libavcodec/libvpxdec.c @@ -23,6 +23,8 @@ * VP8/9 decoder support via libvpx */ +#include "config_components.h" + #define VPX_CODEC_DISABLE_COMPAT 1 #include #include @@ -33,6 +35,7 @@ #include "libavutil/imgutils.h" #include "libavutil/intreadwrite.h" #include "avcodec.h" +#include "codec_internal.h" #include "decode.h" #include "internal.h" #include "libvpx.h" @@ -196,7 +199,7 @@ static int set_pix_fmt(AVCodecContext *avctx, struct vpx_image *img, } static int decode_frame(AVCodecContext *avctx, vpx_codec_ctx_t *decoder, - uint8_t *data, uint32_t data_sz) + const uint8_t *data, uint32_t data_sz) { if (vpx_codec_decode(decoder, data, data_sz, NULL, 0) != VPX_CODEC_OK) { const char *error = vpx_codec_error(decoder); @@ -212,11 +215,10 @@ static int decode_frame(AVCodecContext *avctx, vpx_codec_ctx_t *decoder, return 0; } -static int vpx_decode(AVCodecContext *avctx, - void *data, int *got_frame, AVPacket *avpkt) +static int vpx_decode(AVCodecContext *avctx, AVFrame *picture, + int *got_frame, AVPacket *avpkt) { VPxContext *ctx = avctx->priv_data; - AVFrame *picture = data; const void *iter = NULL; const void *iter_alpha = NULL; struct vpx_image *img, *img_alpha; @@ -353,18 +355,18 @@ static av_cold int vp8_init(AVCodecContext *avctx) return vpx_init(avctx, &ctx->decoder, vpx_codec_vp8_dx()); } -const AVCodec ff_libvpx_vp8_decoder = { - .name = "libvpx", - .long_name = NULL_IF_CONFIG_SMALL("libvpx VP8"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_VP8, +const FFCodec ff_libvpx_vp8_decoder = { + .p.name = "libvpx", + .p.long_name = NULL_IF_CONFIG_SMALL("libvpx VP8"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_VP8, + .p.capabilities = AV_CODEC_CAP_OTHER_THREADS | AV_CODEC_CAP_DR1, + .p.wrapper_name = "libvpx", .priv_data_size = sizeof(VPxContext), .init = vp8_init, .close = vpx_free, - .decode = vpx_decode, - .capabilities = AV_CODEC_CAP_OTHER_THREADS | AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(vpx_decode), .caps_internal = FF_CODEC_CAP_AUTO_THREADS, - .wrapper_name = "libvpx", }; #endif /* CONFIG_LIBVPX_VP8_DECODER */ @@ -375,19 +377,19 @@ static av_cold int vp9_init(AVCodecContext *avctx) return vpx_init(avctx, &ctx->decoder, vpx_codec_vp9_dx()); } -AVCodec ff_libvpx_vp9_decoder = { - .name = "libvpx-vp9", - .long_name = NULL_IF_CONFIG_SMALL("libvpx VP9"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_VP9, +FFCodec ff_libvpx_vp9_decoder = { + .p.name = "libvpx-vp9", + .p.long_name = NULL_IF_CONFIG_SMALL("libvpx VP9"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_VP9, + .p.capabilities = AV_CODEC_CAP_OTHER_THREADS, + .p.profiles = NULL_IF_CONFIG_SMALL(ff_vp9_profiles), + .p.wrapper_name = "libvpx", .priv_data_size = sizeof(VPxContext), .init = vp9_init, .close = vpx_free, - .decode = vpx_decode, - .capabilities = AV_CODEC_CAP_OTHER_THREADS, + FF_CODEC_DECODE_CB(vpx_decode), .caps_internal = FF_CODEC_CAP_AUTO_THREADS, .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 10e5a22fa..187a9e9a3 100644 --- a/libavcodec/libvpxenc.c +++ b/libavcodec/libvpxenc.c @@ -23,12 +23,15 @@ * VP8/9 encoder support via libvpx */ +#include "config_components.h" + #define VPX_DISABLE_CTRL_TYPECHECKS 1 #define VPX_CODEC_DISABLE_COMPAT 1 #include #include #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" #include "internal.h" #include "libavutil/avassert.h" @@ -39,6 +42,7 @@ #include "libavutil/base64.h" #include "libavutil/common.h" #include "libavutil/cpu.h" +#include "libavutil/fifo.h" #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" #include "libavutil/mathematics.h" @@ -127,8 +131,7 @@ typedef struct VPxEncoderContext { int tune_content; int corpus_complexity; int tpl_model; - int discard_hdr10_plus; - AVFifoBuffer *hdr10_plus_fifo; + AVFifo *hdr10_plus_fifo; /** * If the driver does not support ROI then warn the first time we * encounter a frame with ROI side data. @@ -324,39 +327,23 @@ static av_cold void free_frame_list(struct FrameListData *list) } } -static av_cold int add_hdr10_plus(AVFifoBuffer *fifo, struct FrameHDR10Plus *data) -{ - int err = av_fifo_grow(fifo, sizeof(*data)); - if (err < 0) - return err; - av_fifo_generic_write(fifo, data, sizeof(*data), NULL); - return 0; -} - -static av_cold void free_hdr10_plus_fifo(AVFifoBuffer **fifo) +static av_cold void free_hdr10_plus_fifo(AVFifo **fifo) { FrameHDR10Plus frame_hdr10_plus; - while (av_fifo_size(*fifo) >= sizeof(frame_hdr10_plus)) { - av_fifo_generic_read(*fifo, &frame_hdr10_plus, sizeof(frame_hdr10_plus), NULL); + while (av_fifo_read(*fifo, &frame_hdr10_plus, 1) >= 0) av_buffer_unref(&frame_hdr10_plus.hdr10_plus); - } - av_fifo_freep(fifo); + av_fifo_freep2(fifo); } -static int copy_hdr10_plus_to_pkt(AVFifoBuffer *fifo, AVPacket *pkt) +static int copy_hdr10_plus_to_pkt(AVFifo *fifo, AVPacket *pkt) { FrameHDR10Plus frame_hdr10_plus; uint8_t *data; - if (!pkt) + if (!pkt || av_fifo_peek(fifo, &frame_hdr10_plus, 1, 0) < 0) return 0; - if (av_fifo_size(fifo) < sizeof(frame_hdr10_plus)) - return 0; - av_fifo_generic_peek(fifo, &frame_hdr10_plus, sizeof(frame_hdr10_plus), NULL); if (!frame_hdr10_plus.hdr10_plus || frame_hdr10_plus.pts != pkt->pts) return 0; - av_fifo_generic_read(fifo, &frame_hdr10_plus, sizeof(frame_hdr10_plus), NULL); - if (!frame_hdr10_plus.hdr10_plus) - return 0; + av_fifo_drain2(fifo, 1); data = av_packet_new_side_data(pkt, AV_PKT_DATA_DYNAMIC_HDR10_PLUS, frame_hdr10_plus.hdr10_plus->size); if (!data) { @@ -912,7 +899,6 @@ static av_cold int vpx_init(AVCodecContext *avctx, #endif AVDictionaryEntry* en = NULL; - ctx->discard_hdr10_plus = 1; av_log(avctx, AV_LOG_INFO, "%s\n", vpx_codec_version_str()); av_log(avctx, AV_LOG_VERBOSE, "%s\n", vpx_codec_build_config()); @@ -932,8 +918,8 @@ static av_cold int vpx_init(AVCodecContext *avctx, // Keep HDR10+ if it has bit depth higher than 8 and // it has PQ trc (SMPTE2084). if (enccfg.g_bit_depth > 8 && avctx->color_trc == AVCOL_TRC_SMPTE2084) { - ctx->discard_hdr10_plus = 0; - ctx->hdr10_plus_fifo = av_fifo_alloc(sizeof(FrameHDR10Plus)); + ctx->hdr10_plus_fifo = av_fifo_alloc2(1, sizeof(FrameHDR10Plus), + AV_FIFO_FLAG_AUTO_GROW); if (!ctx->hdr10_plus_fifo) return AVERROR(ENOMEM); } @@ -1262,9 +1248,11 @@ static inline void cx_pktcpy(struct FrameListData *dst, static int storeframe(AVCodecContext *avctx, struct FrameListData *cx_frame, AVPacket *pkt) { + VPxContext *ctx = avctx->priv_data; int ret = ff_get_encode_buffer(avctx, pkt, cx_frame->sz, 0); uint8_t *side_data; int pict_type; + int quality; if (ret < 0) return ret; @@ -1279,7 +1267,10 @@ static int storeframe(AVCodecContext *avctx, struct FrameListData *cx_frame, pict_type = AV_PICTURE_TYPE_P; } - ff_side_data_set_encoder_stats(pkt, 0, cx_frame->sse + 1, + ret = vpx_codec_control(&ctx->encoder, VP8E_GET_LAST_QUANTIZER_64, &quality); + if (ret != VPX_CODEC_OK) + quality = 0; + ff_side_data_set_encoder_stats(pkt, quality * FF_QP2LAMBDA, cx_frame->sse + 1, cx_frame->have_sse ? 3 : 0, pict_type); if (cx_frame->have_sse) { @@ -1300,8 +1291,7 @@ static int storeframe(AVCodecContext *avctx, struct FrameListData *cx_frame, memcpy(side_data + 8, cx_frame->buf_alpha, cx_frame->sz_alpha); } if (cx_frame->frame_number != -1) { - VPxContext *ctx = avctx->priv_data; - if (!ctx->discard_hdr10_plus) { + if (ctx->hdr10_plus_fifo) { int err = copy_hdr10_plus_to_pkt(ctx->hdr10_plus_fifo, pkt); if (err < 0) return err; @@ -1640,6 +1630,16 @@ static int vpx_encode(AVCodecContext *avctx, AVPacket *pkt, vpx_svc_layer_id_t layer_id; int layer_id_valid = 0; + if (avctx->qmax >= 0 && enccfg->rc_max_quantizer != avctx->qmax) { + struct vpx_codec_enc_cfg cfg = *enccfg; + cfg.rc_max_quantizer = avctx->qmax; + res = vpx_codec_enc_config_set(&ctx->encoder, &cfg); + if (res != VPX_CODEC_OK) { + log_encoder_error(avctx, "Error reconfiguring encoder"); + return AVERROR_INVALIDDATA; + } + } + if (frame) { const AVFrameSideData *sd = av_frame_get_side_data(frame, AV_FRAME_DATA_REGIONS_OF_INTEREST); rawimg = &ctx->rawimg; @@ -1716,7 +1716,7 @@ static int vpx_encode(AVCodecContext *avctx, AVPacket *pkt, } } - if (!ctx->discard_hdr10_plus) { + if (ctx->hdr10_plus_fifo) { AVFrameSideData *hdr10_plus_metadata; // Add HDR10+ metadata to queue. hdr10_plus_metadata = av_frame_get_side_data(frame, AV_FRAME_DATA_DYNAMIC_HDR_PLUS); @@ -1727,7 +1727,7 @@ static int vpx_encode(AVCodecContext *avctx, AVPacket *pkt, data.hdr10_plus = av_buffer_ref(hdr10_plus_metadata->buf); if (!data.hdr10_plus) return AVERROR(ENOMEM); - err = add_hdr10_plus(ctx->hdr10_plus_fifo, &data); + err = av_fifo_write(ctx->hdr10_plus_fifo, &data, 1); if (err < 0) { av_buffer_unref(&data.hdr10_plus); return err; @@ -1918,7 +1918,7 @@ static const AVOption vp9_options[] = { #undef COMMON_OPTIONS #undef LEGACY_OPTIONS -static const AVCodecDefault defaults[] = { +static const FFCodecDefault defaults[] = { { "b", "0" }, { "qmin", "-1" }, { "qmax", "-1" }, @@ -1940,22 +1940,22 @@ static const AVClass class_vp8 = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_libvpx_vp8_encoder = { - .name = "libvpx", - .long_name = NULL_IF_CONFIG_SMALL("libvpx VP8"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_VP8, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | +const FFCodec ff_libvpx_vp8_encoder = { + .p.name = "libvpx", + .p.long_name = NULL_IF_CONFIG_SMALL("libvpx VP8"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_VP8, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS, .priv_data_size = sizeof(VPxContext), .init = vp8_init, - .encode2 = vpx_encode, + FF_CODEC_ENCODE_CB(vpx_encode), .close = vpx_free, .caps_internal = FF_CODEC_CAP_AUTO_THREADS, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVA420P, AV_PIX_FMT_NONE }, - .priv_class = &class_vp8, + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVA420P, AV_PIX_FMT_NONE }, + .p.priv_class = &class_vp8, .defaults = defaults, - .wrapper_name = "libvpx", + .p.wrapper_name = "libvpx", }; #endif /* CONFIG_LIBVPX_VP8_ENCODER */ @@ -1972,22 +1972,22 @@ static const AVClass class_vp9 = { .version = LIBAVUTIL_VERSION_INT, }; -AVCodec ff_libvpx_vp9_encoder = { - .name = "libvpx-vp9", - .long_name = NULL_IF_CONFIG_SMALL("libvpx VP9"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_VP9, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | +FFCodec ff_libvpx_vp9_encoder = { + .p.name = "libvpx-vp9", + .p.long_name = NULL_IF_CONFIG_SMALL("libvpx VP9"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_VP9, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS, + .p.profiles = NULL_IF_CONFIG_SMALL(ff_vp9_profiles), + .p.priv_class = &class_vp9, + .p.wrapper_name = "libvpx", .priv_data_size = sizeof(VPxContext), .init = vp9_init, - .encode2 = vpx_encode, + FF_CODEC_ENCODE_CB(vpx_encode), .close = vpx_free, .caps_internal = FF_CODEC_CAP_AUTO_THREADS, - .profiles = NULL_IF_CONFIG_SMALL(ff_vp9_profiles), - .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/libwebpenc.c b/libavcodec/libwebpenc.c index 180fff93f..c5dc1b160 100644 --- a/libavcodec/libwebpenc.c +++ b/libavcodec/libwebpenc.c @@ -24,6 +24,7 @@ * WebP encoder using libwebp (WebPEncode API) */ +#include "codec_internal.h" #include "encode.h" #include "libwebpenc_common.h" @@ -86,18 +87,18 @@ static int libwebp_encode_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_libwebp_encoder = { - .name = "libwebp", - .long_name = NULL_IF_CONFIG_SMALL("libwebp WebP image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_WEBP, - .capabilities = AV_CODEC_CAP_DR1, - .pix_fmts = ff_libwebpenc_pix_fmts, - .priv_class = &ff_libwebpenc_class, +const FFCodec ff_libwebp_encoder = { + .p.name = "libwebp", + .p.long_name = NULL_IF_CONFIG_SMALL("libwebp WebP image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_WEBP, + .p.capabilities = AV_CODEC_CAP_DR1, + .p.pix_fmts = ff_libwebpenc_pix_fmts, + .p.priv_class = &ff_libwebpenc_class, + .p.wrapper_name = "libwebp", .priv_data_size = sizeof(LibWebPContext), .defaults = ff_libwebp_defaults, .init = libwebp_encode_init, - .encode2 = libwebp_encode_frame, + FF_CODEC_ENCODE_CB(libwebp_encode_frame), .close = libwebp_encode_close, - .wrapper_name = "libwebp", }; diff --git a/libavcodec/libwebpenc_animencoder.c b/libavcodec/libwebpenc_animencoder.c index f75e5636b..765fcf70d 100644 --- a/libavcodec/libwebpenc_animencoder.c +++ b/libavcodec/libwebpenc_animencoder.c @@ -25,6 +25,7 @@ */ #include "config.h" +#include "codec_internal.h" #include "encode.h" #include "libwebpenc_common.h" @@ -69,14 +70,18 @@ static int libwebp_anim_encode_frame(AVCodecContext *avctx, AVPacket *pkt, ret = WebPAnimEncoderAssemble(s->enc, &assembled_data); if (ret) { ret = ff_get_encode_buffer(avctx, pkt, assembled_data.size, 0); - if (ret < 0) + if (ret < 0) { + WebPDataClear(&assembled_data); return ret; + } memcpy(pkt->data, assembled_data.bytes, assembled_data.size); + WebPDataClear(&assembled_data); s->done = 1; pkt->pts = pkt->dts = s->first_frame_pts; *got_packet = 1; return 0; } else { + WebPDataClear(&assembled_data); av_log(s, AV_LOG_ERROR, "WebPAnimEncoderAssemble() failed with error: %d\n", VP8_ENC_ERROR_OUT_OF_MEMORY); @@ -124,18 +129,18 @@ static int libwebp_anim_encode_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_libwebp_anim_encoder = { - .name = "libwebp_anim", - .long_name = NULL_IF_CONFIG_SMALL("libwebp WebP image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_WEBP, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, - .pix_fmts = ff_libwebpenc_pix_fmts, - .priv_class = &ff_libwebpenc_class, +const FFCodec ff_libwebp_anim_encoder = { + .p.name = "libwebp_anim", + .p.long_name = NULL_IF_CONFIG_SMALL("libwebp WebP image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_WEBP, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, + .p.pix_fmts = ff_libwebpenc_pix_fmts, + .p.priv_class = &ff_libwebpenc_class, + .p.wrapper_name = "libwebp", .priv_data_size = sizeof(LibWebPAnimContext), .defaults = ff_libwebp_defaults, .init = libwebp_anim_encode_init, - .encode2 = libwebp_anim_encode_frame, + FF_CODEC_ENCODE_CB(libwebp_anim_encode_frame), .close = libwebp_anim_encode_close, - .wrapper_name = "libwebp", }; diff --git a/libavcodec/libwebpenc_common.c b/libavcodec/libwebpenc_common.c index 6a5fa70dc..761219e50 100644 --- a/libavcodec/libwebpenc_common.c +++ b/libavcodec/libwebpenc_common.c @@ -27,7 +27,7 @@ #include "libavutil/opt.h" #include "libwebpenc_common.h" -const AVCodecDefault ff_libwebp_defaults[] = { +const FFCodecDefault ff_libwebp_defaults[] = { { "compression_level", "4" }, { "global_quality", "-1" }, { NULL }, diff --git a/libavcodec/libwebpenc_common.h b/libavcodec/libwebpenc_common.h index 0c13176b7..2735ccc88 100644 --- a/libavcodec/libwebpenc_common.h +++ b/libavcodec/libwebpenc_common.h @@ -34,8 +34,7 @@ #include "libavutil/log.h" #include "libavutil/pixfmt.h" #include "avcodec.h" -#include "codec.h" -#include "internal.h" +#include "codec_internal.h" typedef struct LibWebPContextCommon { AVClass *class; // class for AVOptions @@ -60,6 +59,6 @@ int ff_libwebp_get_frame(AVCodecContext *avctx, LibWebPContextCommon *s, extern const enum AVPixelFormat ff_libwebpenc_pix_fmts[]; extern const AVClass ff_libwebpenc_class; -extern const AVCodecDefault ff_libwebp_defaults[]; +extern const FFCodecDefault ff_libwebp_defaults[]; #endif /* AVCODEC_LIBWEBPENC_COMMON_H */ diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index c5e0231b1..98ec03086 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/eval.h" #include "libavutil/internal.h" #include "libavutil/opt.h" @@ -28,16 +30,13 @@ #include "libavutil/time.h" #include "libavutil/intreadwrite.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" #include "internal.h" #include "packet_internal.h" #include "atsc_a53.h" #include "sei.h" -#if defined(_MSC_VER) -#define X264_API_IMPORTS 1 -#endif - #include #include #include @@ -63,7 +62,8 @@ typedef struct X264Context { int sei_size; char *preset; char *tune; - char *profile; + const char *profile; + char *profile_opt; char *level; int fastfirstpass; char *wpredp; @@ -833,26 +833,27 @@ static av_cold int X264_init(AVCodecContext *avctx) if (x4->fastfirstpass) x264_param_apply_fastfirstpass(&x4->params); + x4->profile = x4->profile_opt; /* Allow specifying the x264 profile through AVCodecContext. */ if (!x4->profile) switch (avctx->profile) { case FF_PROFILE_H264_BASELINE: - x4->profile = av_strdup("baseline"); + x4->profile = "baseline"; break; case FF_PROFILE_H264_HIGH: - x4->profile = av_strdup("high"); + x4->profile = "high"; break; case FF_PROFILE_H264_HIGH_10: - x4->profile = av_strdup("high10"); + x4->profile = "high10"; break; case FF_PROFILE_H264_HIGH_422: - x4->profile = av_strdup("high422"); + x4->profile = "high422"; break; case FF_PROFILE_H264_HIGH_444: - x4->profile = av_strdup("high444"); + x4->profile = "high444"; break; case FF_PROFILE_H264_MAIN: - x4->profile = av_strdup("main"); + x4->profile = "main"; break; default: break; @@ -941,7 +942,9 @@ static av_cold int X264_init(AVCodecContext *avctx) return ret; } p= strchr(p, ':'); - p+=!!p; + if (p) { + ++p; + } } } @@ -1081,14 +1084,14 @@ static const enum AVPixelFormat pix_fmts_8bit_rgb[] = { #endif #if X264_BUILD < 153 -static av_cold void X264_init_static(AVCodec *codec) +static av_cold void X264_init_static(FFCodec *codec) { if (x264_bit_depth == 8) - codec->pix_fmts = pix_fmts_8bit; + codec->p.pix_fmts = pix_fmts_8bit; else if (x264_bit_depth == 9) - codec->pix_fmts = pix_fmts_9bit; + codec->p.pix_fmts = pix_fmts_9bit; else if (x264_bit_depth == 10) - codec->pix_fmts = pix_fmts_10bit; + codec->p.pix_fmts = pix_fmts_10bit; } #endif @@ -1097,7 +1100,7 @@ static av_cold void X264_init_static(AVCodec *codec) static const AVOption options[] = { { "preset", "Set the encoding preset (cf. x264 --fullhelp)", OFFSET(preset), AV_OPT_TYPE_STRING, { .str = "medium" }, 0, 0, VE}, { "tune", "Tune the encoding params (cf. x264 --fullhelp)", OFFSET(tune), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE}, - { "profile", "Set profile restrictions (cf. x264 --fullhelp) ", OFFSET(profile), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE}, + { "profile", "Set profile restrictions (cf. x264 --fullhelp)", OFFSET(profile_opt), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE}, { "fastfirstpass", "Use fast settings when encoding first pass", OFFSET(fastfirstpass), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE}, {"level", "Specify level (as defined by Annex A)", OFFSET(level), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, VE}, {"passlogfile", "Filename for 2 pass stats", OFFSET(stats), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, VE}, @@ -1176,7 +1179,7 @@ static const AVOption options[] = { { NULL }, }; -static const AVCodecDefault x264_defaults[] = { +static const FFCodecDefault x264_defaults[] = { { "b", "0" }, { "bf", "-1" }, { "flags2", "0" }, @@ -1213,31 +1216,31 @@ static const AVClass x264_class = { #if X264_BUILD >= 153 const #endif -AVCodec ff_libx264_encoder = { - .name = "libx264", - .long_name = NULL_IF_CONFIG_SMALL("libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_H264, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | +FFCodec ff_libx264_encoder = { + .p.name = "libx264", + .p.long_name = NULL_IF_CONFIG_SMALL("libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_H264, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, + .p.priv_class = &x264_class, + .p.wrapper_name = "libx264", .priv_data_size = sizeof(X264Context), .init = X264_init, - .encode2 = X264_frame, + FF_CODEC_ENCODE_CB(X264_frame), .close = X264_close, - .priv_class = &x264_class, .defaults = x264_defaults, #if X264_BUILD < 153 .init_static_data = X264_init_static, #else - .pix_fmts = pix_fmts_all, + .p.pix_fmts = pix_fmts_all, #endif .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_AUTO_THREADS #if X264_BUILD >= 158 | FF_CODEC_CAP_INIT_THREADSAFE #endif , - .wrapper_name = "libx264", }; #endif @@ -1249,27 +1252,27 @@ static const AVClass rgbclass = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_libx264rgb_encoder = { - .name = "libx264rgb", - .long_name = NULL_IF_CONFIG_SMALL("libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 RGB"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_H264, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | +const FFCodec ff_libx264rgb_encoder = { + .p.name = "libx264rgb", + .p.long_name = NULL_IF_CONFIG_SMALL("libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 RGB"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_H264, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, + .p.pix_fmts = pix_fmts_8bit_rgb, + .p.priv_class = &rgbclass, + .p.wrapper_name = "libx264", .priv_data_size = sizeof(X264Context), .init = X264_init, - .encode2 = X264_frame, + FF_CODEC_ENCODE_CB(X264_frame), .close = X264_close, - .priv_class = &rgbclass, .defaults = x264_defaults, - .pix_fmts = pix_fmts_8bit_rgb, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_AUTO_THREADS #if X264_BUILD >= 158 | FF_CODEC_CAP_INIT_THREADSAFE #endif , - .wrapper_name = "libx264", }; #endif @@ -1281,22 +1284,22 @@ static const AVClass X262_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_libx262_encoder = { - .name = "libx262", - .long_name = NULL_IF_CONFIG_SMALL("libx262 MPEG2VIDEO"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MPEG2VIDEO, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | +const FFCodec ff_libx262_encoder = { + .p.name = "libx262", + .p.long_name = NULL_IF_CONFIG_SMALL("libx262 MPEG2VIDEO"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MPEG2VIDEO, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, + .p.pix_fmts = pix_fmts_8bit, + .p.priv_class = &X262_class, + .p.wrapper_name = "libx264", .priv_data_size = sizeof(X264Context), .init = X264_init, - .encode2 = X264_frame, + FF_CODEC_ENCODE_CB(X264_frame), .close = X264_close, - .priv_class = &X262_class, .defaults = x264_defaults, - .pix_fmts = pix_fmts_8bit, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_AUTO_THREADS, - .wrapper_name = "libx264", }; #endif diff --git a/libavcodec/libx265.c b/libavcodec/libx265.c index 851f09934..f68ecb309 100644 --- a/libavcodec/libx265.c +++ b/libavcodec/libx265.c @@ -32,6 +32,7 @@ #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" #include "internal.h" #include "packet_internal.h" @@ -239,39 +240,40 @@ static av_cold int libx265_encode_init(AVCodecContext *avctx) } } - switch (avctx->pix_fmt) { - case AV_PIX_FMT_YUV420P: - case AV_PIX_FMT_YUV420P10: - case AV_PIX_FMT_YUV420P12: - ctx->params->internalCsp = X265_CSP_I420; - break; - case AV_PIX_FMT_YUV422P: - case AV_PIX_FMT_YUV422P10: - case AV_PIX_FMT_YUV422P12: - ctx->params->internalCsp = X265_CSP_I422; - break; - case AV_PIX_FMT_GBRP: - case AV_PIX_FMT_GBRP10: - case AV_PIX_FMT_GBRP12: - ctx->params->vui.matrixCoeffs = AVCOL_SPC_RGB; - ctx->params->vui.bEnableVideoSignalTypePresentFlag = 1; - ctx->params->vui.bEnableColorDescriptionPresentFlag = 1; - case AV_PIX_FMT_YUV444P: - case AV_PIX_FMT_YUV444P10: - case AV_PIX_FMT_YUV444P12: + switch (desc->log2_chroma_w) { + // 4:4:4, RGB. gray + case 0: + // gray + if (desc->nb_components == 1) { + if (ctx->api->api_build_number < 85) { + av_log(avctx, AV_LOG_ERROR, + "libx265 version is %d, must be at least 85 for gray encoding.\n", + ctx->api->api_build_number); + return AVERROR_INVALIDDATA; + } + ctx->params->internalCsp = X265_CSP_I400; + break; + } + + // set identity matrix for RGB + if (desc->flags & AV_PIX_FMT_FLAG_RGB) { + ctx->params->vui.matrixCoeffs = AVCOL_SPC_RGB; + ctx->params->vui.bEnableVideoSignalTypePresentFlag = 1; + ctx->params->vui.bEnableColorDescriptionPresentFlag = 1; + } + ctx->params->internalCsp = X265_CSP_I444; break; - case AV_PIX_FMT_GRAY8: - case AV_PIX_FMT_GRAY10: - case AV_PIX_FMT_GRAY12: - if (ctx->api->api_build_number < 85) { - av_log(avctx, AV_LOG_ERROR, - "libx265 version is %d, must be at least 85 for gray encoding.\n", - ctx->api->api_build_number); - return AVERROR_INVALIDDATA; - } - ctx->params->internalCsp = X265_CSP_I400; + // 4:2:0, 4:2:2 + case 1: + ctx->params->internalCsp = desc->log2_chroma_h == 1 ? + X265_CSP_I420 : X265_CSP_I422; break; + default: + av_log(avctx, AV_LOG_ERROR, + "Pixel format '%s' cannot be mapped to a libx265 CSP!\n", + desc->name); + return AVERROR_BUG; } if (ctx->crf >= 0) { @@ -692,14 +694,14 @@ static const enum AVPixelFormat x265_csp_twelve[] = { AV_PIX_FMT_NONE }; -static av_cold void libx265_encode_init_csp(AVCodec *codec) +static av_cold void libx265_encode_init_csp(FFCodec *codec) { if (x265_api_get(12)) - codec->pix_fmts = x265_csp_twelve; + codec->p.pix_fmts = x265_csp_twelve; else if (x265_api_get(10)) - codec->pix_fmts = x265_csp_ten; + codec->p.pix_fmts = x265_csp_ten; else if (x265_api_get(8)) - codec->pix_fmts = x265_csp_eight; + codec->p.pix_fmts = x265_csp_eight; } #define OFFSET(x) offsetof(libx265Context, x) @@ -723,7 +725,7 @@ static const AVClass class = { .version = LIBAVUTIL_VERSION_INT, }; -static const AVCodecDefault x265_defaults[] = { +static const FFCodecDefault x265_defaults[] = { { "b", "0" }, { "bf", "-1" }, { "g", "-1" }, @@ -739,21 +741,21 @@ static const AVCodecDefault x265_defaults[] = { { NULL }, }; -AVCodec ff_libx265_encoder = { - .name = "libx265", - .long_name = NULL_IF_CONFIG_SMALL("libx265 H.265 / HEVC"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_HEVC, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | +FFCodec ff_libx265_encoder = { + .p.name = "libx265", + .p.long_name = NULL_IF_CONFIG_SMALL("libx265 H.265 / HEVC"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_HEVC, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE, + .p.priv_class = &class, + .p.wrapper_name = "libx265", .init = libx265_encode_init, .init_static_data = libx265_encode_init_csp, - .encode2 = libx265_encode_frame, + FF_CODEC_ENCODE_CB(libx265_encode_frame), .close = libx265_encode_close, .priv_data_size = sizeof(libx265Context), - .priv_class = &class, .defaults = x265_defaults, .caps_internal = FF_CODEC_CAP_AUTO_THREADS, - .wrapper_name = "libx265", }; diff --git a/libavcodec/libxavs.c b/libavcodec/libxavs.c index 20b3b0f80..a3efbcb4a 100644 --- a/libavcodec/libxavs.c +++ b/libavcodec/libxavs.c @@ -27,8 +27,8 @@ #include #include #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "packet_internal.h" #include "libavutil/internal.h" #include "libavutil/mem.h" @@ -416,25 +416,25 @@ static const AVClass xavs_class = { .version = LIBAVUTIL_VERSION_INT, }; -static const AVCodecDefault xavs_defaults[] = { +static const FFCodecDefault xavs_defaults[] = { { "b", "0" }, { NULL }, }; -const AVCodec ff_libxavs_encoder = { - .name = "libxavs", - .long_name = NULL_IF_CONFIG_SMALL("libxavs Chinese AVS (Audio Video Standard)"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_CAVS, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | +const FFCodec ff_libxavs_encoder = { + .p.name = "libxavs", + .p.long_name = NULL_IF_CONFIG_SMALL("libxavs Chinese AVS (Audio Video Standard)"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_CAVS, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS, .priv_data_size = sizeof(XavsContext), .init = XAVS_init, - .encode2 = XAVS_frame, + FF_CODEC_ENCODE_CB(XAVS_frame), .close = XAVS_close, .caps_internal = FF_CODEC_CAP_AUTO_THREADS, - .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, - .priv_class = &xavs_class, + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, + .p.priv_class = &xavs_class, .defaults = xavs_defaults, - .wrapper_name = "libxavs", + .p.wrapper_name = "libxavs", }; diff --git a/libavcodec/libxavs2.c b/libavcodec/libxavs2.c index 9c5a576e9..bf34b7acb 100644 --- a/libavcodec/libxavs2.c +++ b/libavcodec/libxavs2.c @@ -23,9 +23,11 @@ */ #include "xavs2.h" +#include "codec_internal.h" #include "encode.h" #include "mpeg12.h" #include "libavutil/avstring.h" +#include "libavutil/opt.h" #define xavs2_opt_set2(name, format, ...) do{ \ char opt_str[16] = {0}; \ @@ -206,7 +208,7 @@ static int xavs2_encode_frame(AVCodecContext *avctx, AVPacket *pkt, ret = cae->api->encoder_encode(cae->encoder, &pic, &cae->packet); if (ret) { - av_log(avctx, AV_LOG_ERROR, "Encoding error occured.\n"); + av_log(avctx, AV_LOG_ERROR, "Encoding error occurred.\n"); return AVERROR_EXTERNAL; } @@ -277,28 +279,28 @@ static const AVClass libxavs2 = { .version = LIBAVUTIL_VERSION_INT, }; -static const AVCodecDefault xavs2_defaults[] = { +static const FFCodecDefault xavs2_defaults[] = { { "b", "0" }, { "g", "48"}, { "bf", "7" }, { NULL }, }; -const AVCodec ff_libxavs2_encoder = { - .name = "libxavs2", - .long_name = NULL_IF_CONFIG_SMALL("libxavs2 AVS2-P2/IEEE1857.4"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_AVS2, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | +const FFCodec ff_libxavs2_encoder = { + .p.name = "libxavs2", + .p.long_name = NULL_IF_CONFIG_SMALL("libxavs2 AVS2-P2/IEEE1857.4"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_AVS2, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS, .priv_data_size = sizeof(XAVS2EContext), .init = xavs2_init, - .encode2 = xavs2_encode_frame, + FF_CODEC_ENCODE_CB(xavs2_encode_frame), .close = xavs2_close, .caps_internal = FF_CODEC_CAP_AUTO_THREADS, - .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, - .priv_class = &libxavs2, + .p.priv_class = &libxavs2, .defaults = xavs2_defaults, - .wrapper_name = "libxavs2", + .p.wrapper_name = "libxavs2", } ; diff --git a/libavcodec/libxvid.c b/libavcodec/libxvid.c index 7cf9d7661..4b3dd71bc 100644 --- a/libavcodec/libxvid.c +++ b/libavcodec/libxvid.c @@ -38,8 +38,8 @@ #include "libavutil/opt.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "mpegutils.h" #include "packet_internal.h" @@ -657,7 +657,6 @@ static av_cold int xvid_encode_init(AVCodecContext *avctx) if (xvid_flags & AV_CODEC_FLAG_GLOBAL_HEADER) { /* In this case, we are claiming to be MPEG-4 */ x->quicktime_format = 1; - avctx->codec_id = AV_CODEC_ID_MPEG4; } else { /* We are claiming to be Xvid */ x->quicktime_format = 0; @@ -898,18 +897,18 @@ static const AVClass xvid_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_libxvid_encoder = { - .name = "libxvid", - .long_name = NULL_IF_CONFIG_SMALL("libxvidcore MPEG-4 part 2"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MPEG4, +const FFCodec ff_libxvid_encoder = { + .p.name = "libxvid", + .p.long_name = NULL_IF_CONFIG_SMALL("libxvidcore MPEG-4 part 2"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MPEG4, .priv_data_size = sizeof(struct xvid_context), .init = xvid_encode_init, - .encode2 = xvid_encode_frame, + FF_CODEC_ENCODE_CB(xvid_encode_frame), .close = xvid_encode_close, - .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, - .priv_class = &xvid_class, + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, + .p.priv_class = &xvid_class, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .wrapper_name = "libxvid", + .p.wrapper_name = "libxvid", }; diff --git a/libavcodec/libzvbi-teletextdec.c b/libavcodec/libzvbi-teletextdec.c index 1073d6a0b..514e76f1b 100644 --- a/libavcodec/libzvbi-teletextdec.c +++ b/libavcodec/libzvbi-teletextdec.c @@ -20,6 +20,7 @@ #include "avcodec.h" #include "libavcodec/ass.h" +#include "codec_internal.h" #include "libavcodec/dvbtxt.h" #include "libavutil/opt.h" #include "libavutil/bprint.h" @@ -580,7 +581,7 @@ static void handler(vbi_event *ev, void *user_data) vbi_unref_page(&page); } -static int slice_to_vbi_lines(TeletextContext *ctx, uint8_t* buf, int size) +static int slice_to_vbi_lines(TeletextContext *ctx, const uint8_t *buf, int size) { int lines = 0; while (size >= 2 && lines < MAX_SLICES) { @@ -636,10 +637,10 @@ static int slice_to_vbi_lines(TeletextContext *ctx, uint8_t* buf, int size) return lines; } -static int teletext_decode_frame(AVCodecContext *avctx, void *data, int *got_sub_ptr, AVPacket *pkt) +static int teletext_decode_frame(AVCodecContext *avctx, AVSubtitle *sub, + int *got_sub_ptr, const AVPacket *pkt) { TeletextContext *ctx = avctx->priv_data; - AVSubtitle *sub = data; int ret = 0; if (!ctx->vbi) { @@ -810,17 +811,17 @@ static const AVClass teletext_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_libzvbi_teletext_decoder = { - .name = "libzvbi_teletextdec", - .long_name = NULL_IF_CONFIG_SMALL("Libzvbi DVB teletext decoder"), - .type = AVMEDIA_TYPE_SUBTITLE, - .id = AV_CODEC_ID_DVB_TELETEXT, +const FFCodec ff_libzvbi_teletext_decoder = { + .p.name = "libzvbi_teletextdec", + .p.long_name = NULL_IF_CONFIG_SMALL("Libzvbi DVB teletext decoder"), + .p.type = AVMEDIA_TYPE_SUBTITLE, + .p.id = AV_CODEC_ID_DVB_TELETEXT, + .p.capabilities = AV_CODEC_CAP_DELAY, + .p.priv_class = &teletext_class, + .p.wrapper_name = "libzvbi", .priv_data_size = sizeof(TeletextContext), .init = teletext_init_decoder, .close = teletext_close_decoder, - .decode = teletext_decode_frame, - .capabilities = AV_CODEC_CAP_DELAY, + FF_CODEC_DECODE_SUB_CB(teletext_decode_frame), .flush = teletext_flush, - .priv_class= &teletext_class, - .wrapper_name = "libzvbi", }; diff --git a/libavcodec/ljpegenc.c b/libavcodec/ljpegenc.c index ecdedeb6a..fc7a46273 100644 --- a/libavcodec/ljpegenc.c +++ b/libavcodec/ljpegenc.c @@ -36,9 +36,9 @@ #include "libavutil/pixdesc.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" #include "idctdsp.h" -#include "internal.h" #include "jpegtables.h" #include "mathops.h" #include "mjpegenc_common.h" @@ -220,7 +220,7 @@ static int ljpeg_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const int height = avctx->height; const int mb_width = (width + s->hsample[0] - 1) / s->hsample[0]; const int mb_height = (height + s->vsample[0] - 1) / s->vsample[0]; - int max_pkt_size = AV_INPUT_BUFFER_MIN_SIZE; + size_t max_pkt_size = AV_INPUT_BUFFER_MIN_SIZE; int ret, header_bits; if( avctx->pix_fmt == AV_PIX_FMT_BGR0 @@ -233,13 +233,15 @@ static int ljpeg_encode_frame(AVCodecContext *avctx, AVPacket *pkt, * s->hsample[0] * s->vsample[0]; } + if ((ret = ff_mjpeg_add_icc_profile_size(avctx, pict, &max_pkt_size)) < 0) + return ret; if ((ret = ff_alloc_packet(avctx, pkt, max_pkt_size)) < 0) return ret; init_put_bits(&pb, pkt->data, pkt->size); - ff_mjpeg_encode_picture_header(avctx, &pb, &s->scantable, - s->pred, s->matrix, s->matrix); + ff_mjpeg_encode_picture_header(avctx, &pb, pict, NULL, &s->scantable, + s->pred, s->matrix, s->matrix, 0); header_bits = put_bits_count(&pb); @@ -321,18 +323,18 @@ static const AVClass ljpeg_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_ljpeg_encoder = { - .name = "ljpeg", - .long_name = NULL_IF_CONFIG_SMALL("Lossless JPEG"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_LJPEG, +const FFCodec ff_ljpeg_encoder = { + .p.name = "ljpeg", + .p.long_name = NULL_IF_CONFIG_SMALL("Lossless JPEG"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_LJPEG, .priv_data_size = sizeof(LJpegEncContext), - .priv_class = &ljpeg_class, + .p.priv_class = &ljpeg_class, .init = ljpeg_encode_init, - .encode2 = ljpeg_encode_frame, + FF_CODEC_ENCODE_CB(ljpeg_encode_frame), .close = ljpeg_encode_close, - .capabilities = AV_CODEC_CAP_FRAME_THREADS, - .pix_fmts = (const enum AVPixelFormat[]){ + .p.capabilities = AV_CODEC_CAP_FRAME_THREADS, + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_BGR24 , AV_PIX_FMT_BGRA , AV_PIX_FMT_BGR0, AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUV420P , AV_PIX_FMT_YUV444P , AV_PIX_FMT_YUV422P, diff --git a/libavcodec/loco.c b/libavcodec/loco.c index ebd81f43f..9cadc9d00 100644 --- a/libavcodec/loco.c +++ b/libavcodec/loco.c @@ -25,6 +25,7 @@ */ #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" #include "golomb.h" #include "internal.h" @@ -195,14 +196,12 @@ static void rotate_faulty_loco(uint8_t *data, int width, int height, int stride) } } -static int decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *p, + int *got_frame, AVPacket *avpkt) { LOCOContext * const l = avctx->priv_data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; - AVFrame * const p = data; int decoded, ret; if ((ret = ff_get_buffer(avctx, p, 0)) < 0) @@ -337,14 +336,14 @@ static av_cold int decode_init(AVCodecContext *avctx) return 0; } -const AVCodec ff_loco_decoder = { - .name = "loco", - .long_name = NULL_IF_CONFIG_SMALL("LOCO"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_LOCO, +const FFCodec ff_loco_decoder = { + .p.name = "loco", + .p.long_name = NULL_IF_CONFIG_SMALL("LOCO"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_LOCO, .priv_data_size = sizeof(LOCOContext), .init = decode_init, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/loongarch/Makefile b/libavcodec/loongarch/Makefile index baf5f92e8..c1b5de5c4 100644 --- a/libavcodec/loongarch/Makefile +++ b/libavcodec/loongarch/Makefile @@ -5,6 +5,10 @@ OBJS-$(CONFIG_H264PRED) += loongarch/h264_intrapred_init_loongarch OBJS-$(CONFIG_VP8_DECODER) += loongarch/vp8dsp_init_loongarch.o OBJS-$(CONFIG_VP9_DECODER) += loongarch/vp9dsp_init_loongarch.o OBJS-$(CONFIG_VC1DSP) += loongarch/vc1dsp_init_loongarch.o +OBJS-$(CONFIG_HPELDSP) += loongarch/hpeldsp_init_loongarch.o +OBJS-$(CONFIG_IDCTDSP) += loongarch/idctdsp_init_loongarch.o +OBJS-$(CONFIG_VIDEODSP) += loongarch/videodsp_init.o +OBJS-$(CONFIG_HEVC_DECODER) += loongarch/hevcdsp_init_loongarch.o LASX-OBJS-$(CONFIG_H264CHROMA) += loongarch/h264chroma_lasx.o LASX-OBJS-$(CONFIG_H264QPEL) += loongarch/h264qpel_lasx.o LASX-OBJS-$(CONFIG_H264DSP) += loongarch/h264dsp_lasx.o \ @@ -12,9 +16,18 @@ LASX-OBJS-$(CONFIG_H264DSP) += loongarch/h264dsp_lasx.o \ loongarch/h264_deblock_lasx.o LASX-OBJS-$(CONFIG_H264PRED) += loongarch/h264_intrapred_lasx.o LASX-OBJS-$(CONFIG_VC1_DECODER) += loongarch/vc1dsp_lasx.o +LASX-OBJS-$(CONFIG_HPELDSP) += loongarch/hpeldsp_lasx.o +LASX-OBJS-$(CONFIG_IDCTDSP) += loongarch/simple_idct_lasx.o \ + loongarch/idctdsp_lasx.o LSX-OBJS-$(CONFIG_VP8_DECODER) += loongarch/vp8_mc_lsx.o \ loongarch/vp8_lpf_lsx.o LSX-OBJS-$(CONFIG_VP9_DECODER) += loongarch/vp9_mc_lsx.o \ loongarch/vp9_intra_lsx.o \ loongarch/vp9_lpf_lsx.o \ loongarch/vp9_idct_lsx.o +LSX-OBJS-$(CONFIG_HEVC_DECODER) += loongarch/hevcdsp_lsx.o \ + loongarch/hevc_idct_lsx.o \ + loongarch/hevc_lpf_sao_lsx.o \ + loongarch/hevc_mc_bi_lsx.o \ + loongarch/hevc_mc_uni_lsx.o \ + loongarch/hevc_mc_uniw_lsx.o diff --git a/libavcodec/loongarch/hevc_idct_lsx.c b/libavcodec/loongarch/hevc_idct_lsx.c new file mode 100644 index 000000000..2193b2754 --- /dev/null +++ b/libavcodec/loongarch/hevc_idct_lsx.c @@ -0,0 +1,842 @@ +/* + * Copyright (c) 2022 Loongson Technology Corporation Limited + * Contributed by Shiyou Yin + * Hao Chen + * + * 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/loongarch/loongson_intrinsics.h" +#include "hevcdsp_lsx.h" + +static const int16_t gt8x8_cnst[16] __attribute__ ((aligned (64))) = { + 64, 64, 83, 36, 89, 50, 18, 75, 64, -64, 36, -83, 75, -89, -50, -18 +}; + +static const int16_t gt16x16_cnst[64] __attribute__ ((aligned (64))) = { + 64, 83, 64, 36, 89, 75, 50, 18, 90, 80, 57, 25, 70, 87, 9, 43, + 64, 36, -64, -83, 75, -18, -89, -50, 87, 9, -80, -70, -43, 57, -25, -90, + 64, -36, -64, 83, 50, -89, 18, 75, 80, -70, -25, 90, -87, 9, 43, 57, + 64, -83, 64, -36, 18, -50, 75, -89, 70, -87, 90, -80, 9, -43, -57, 25 +}; + +static const int16_t gt32x32_cnst0[256] __attribute__ ((aligned (64))) = { + 90, 90, 88, 85, 82, 78, 73, 67, 61, 54, 46, 38, 31, 22, 13, 4, + 90, 82, 67, 46, 22, -4, -31, -54, -73, -85, -90, -88, -78, -61, -38, -13, + 88, 67, 31, -13, -54, -82, -90, -78, -46, -4, 38, 73, 90, 85, 61, 22, + 85, 46, -13, -67, -90, -73, -22, 38, 82, 88, 54, -4, -61, -90, -78, -31, + 82, 22, -54, -90, -61, 13, 78, 85, 31, -46, -90, -67, 4, 73, 88, 38, + 78, -4, -82, -73, 13, 85, 67, -22, -88, -61, 31, 90, 54, -38, -90, -46, + 73, -31, -90, -22, 78, 67, -38, -90, -13, 82, 61, -46, -88, -4, 85, 54, + 67, -54, -78, 38, 85, -22, -90, 4, 90, 13, -88, -31, 82, 46, -73, -61, + 61, -73, -46, 82, 31, -88, -13, 90, -4, -90, 22, 85, -38, -78, 54, 67, + 54, -85, -4, 88, -46, -61, 82, 13, -90, 38, 67, -78, -22, 90, -31, -73, + 46, -90, 38, 54, -90, 31, 61, -88, 22, 67, -85, 13, 73, -82, 4, 78, + 38, -88, 73, -4, -67, 90, -46, -31, 85, -78, 13, 61, -90, 54, 22, -82, + 31, -78, 90, -61, 4, 54, -88, 82, -38, -22, 73, -90, 67, -13, -46, 85, + 22, -61, 85, -90, 73, -38, -4, 46, -78, 90, -82, 54, -13, -31, 67, -88, + 13, -38, 61, -78, 88, -90, 85, -73, 54, -31, 4, 22, -46, 67, -82, 90, + 4, -13, 22, -31, 38, -46, 54, -61, 67, -73, 78, -82, 85, -88, 90, -90 +}; + +static const int16_t gt32x32_cnst1[64] __attribute__ ((aligned (64))) = { + 90, 87, 80, 70, 57, 43, 25, 9, 87, 57, 9, -43, -80, -90, -70, -25, + 80, 9, -70, -87, -25, 57, 90, 43, 70, -43, -87, 9, 90, 25, -80, -57, + 57, -80, -25, 90, -9, -87, 43, 70, 43, -90, 57, 25, -87, 70, 9, -80, + 25, -70, 90, -80, 43, 9, -57, 87, 9, -25, 43, -57, 70, -80, 87, -90 +}; + +static const int16_t gt32x32_cnst2[16] __attribute__ ((aligned (64))) = { + 89, 75, 50, 18, 75, -18, -89, -50, 50, -89, 18, 75, 18, -50, 75, -89 +}; + +#define HEVC_IDCT4x4_COL(in_r0, in_l0, in_r1, in_l1, \ + sum0, sum1, sum2, sum3, shift) \ +{ \ + __m128i vec0, vec1, vec2, vec3, vec4, vec5; \ + __m128i cnst64 = __lsx_vldi(0x0840); \ + __m128i cnst83 = __lsx_vldi(0x0853); \ + __m128i cnst36 = __lsx_vldi(0x0824); \ + \ + vec0 = __lsx_vdp2_w_h(in_r0, cnst64); \ + vec1 = __lsx_vdp2_w_h(in_l0, cnst83); \ + vec2 = __lsx_vdp2_w_h(in_r1, cnst64); \ + vec3 = __lsx_vdp2_w_h(in_l1, cnst36); \ + vec4 = __lsx_vdp2_w_h(in_l0, cnst36); \ + vec5 = __lsx_vdp2_w_h(in_l1, cnst83); \ + \ + sum0 = __lsx_vadd_w(vec0, vec2); \ + sum1 = __lsx_vsub_w(vec0, vec2); \ + vec1 = __lsx_vadd_w(vec1, vec3); \ + vec4 = __lsx_vsub_w(vec4, vec5); \ + sum2 = __lsx_vsub_w(sum1, vec4); \ + sum3 = __lsx_vsub_w(sum0, vec1); \ + sum0 = __lsx_vadd_w(sum0, vec1); \ + sum1 = __lsx_vadd_w(sum1, vec4); \ + \ + sum0 = __lsx_vsrari_w(sum0, shift); \ + sum1 = __lsx_vsrari_w(sum1, shift); \ + sum2 = __lsx_vsrari_w(sum2, shift); \ + sum3 = __lsx_vsrari_w(sum3, shift); \ + sum0 = __lsx_vsat_w(sum0, 15); \ + sum1 = __lsx_vsat_w(sum1, 15); \ + sum2 = __lsx_vsat_w(sum2, 15); \ + sum3 = __lsx_vsat_w(sum3, 15); \ +} + +#define HEVC_IDCT8x8_COL(in0, in1, in2, in3, in4, in5, in6, in7, shift) \ +{ \ + __m128i src0_r, src1_r, src2_r, src3_r; \ + __m128i src0_l, src1_l, src2_l, src3_l; \ + __m128i filter0, filter1, filter2, filter3; \ + __m128i temp0_r, temp1_r, temp2_r, temp3_r, temp4_r, temp5_r; \ + __m128i temp0_l, temp1_l, temp2_l, temp3_l, temp4_l, temp5_l; \ + __m128i sum0_r, sum1_r, sum2_r, sum3_r; \ + __m128i sum0_l, sum1_l, sum2_l, sum3_l; \ + \ + DUP4_ARG2(__lsx_vilvl_h, in4, in0, in6, in2, in5, in1, in3, in7, \ + src0_r, src1_r, src2_r, src3_r); \ + DUP4_ARG2(__lsx_vilvh_h, in4, in0, in6, in2, in5, in1, in3, in7, \ + src0_l, src1_l, src2_l, src3_l); \ + \ + DUP4_ARG2(__lsx_vldrepl_w, filter, 0, filter, 4, filter, 8, \ + filter, 12, filter0, filter1, filter2, filter3); \ + DUP4_ARG2(__lsx_vdp2_w_h, src0_r, filter0, src0_l, filter0, \ + src1_r, filter1, src1_l, filter1, temp0_r, temp0_l, \ + temp1_r, temp1_l); \ + \ + LSX_BUTTERFLY_4_W(temp0_r, temp0_l, temp1_l, temp1_r, sum0_r, sum0_l,\ + sum1_l, sum1_r); \ + sum2_r = sum1_r; \ + sum2_l = sum1_l; \ + sum3_r = sum0_r; \ + sum3_l = sum0_l; \ + \ + DUP4_ARG2(__lsx_vdp2_w_h, src2_r, filter2, src2_l, filter2, \ + src3_r, filter3, src3_l, filter3, temp2_r, temp2_l, \ + temp3_r, temp3_l); \ + temp2_r = __lsx_vadd_w(temp2_r, temp3_r); \ + temp2_l = __lsx_vadd_w(temp2_l, temp3_l); \ + sum0_r = __lsx_vadd_w(sum0_r, temp2_r); \ + sum0_l = __lsx_vadd_w(sum0_l, temp2_l); \ + sum3_r = __lsx_vsub_w(sum3_r, temp2_r); \ + sum3_l = __lsx_vsub_w(sum3_l, temp2_l); \ + \ + in0 = __lsx_vssrarni_h_w(sum0_l, sum0_r, shift); \ + in7 = __lsx_vssrarni_h_w(sum3_l, sum3_r, shift); \ + \ + DUP4_ARG2(__lsx_vdp2_w_h, src2_r, filter3, src2_l, filter3, \ + src3_r, filter2, src3_l, filter2, temp4_r, temp4_l, \ + temp5_r, temp5_l); \ + temp4_r = __lsx_vsub_w(temp4_r, temp5_r); \ + temp4_l = __lsx_vsub_w(temp4_l, temp5_l); \ + sum1_r = __lsx_vadd_w(sum1_r, temp4_r); \ + sum1_l = __lsx_vadd_w(sum1_l, temp4_l); \ + sum2_r = __lsx_vsub_w(sum2_r, temp4_r); \ + sum2_l = __lsx_vsub_w(sum2_l, temp4_l); \ + \ + in3 = __lsx_vssrarni_h_w(sum1_l, sum1_r, shift); \ + in4 = __lsx_vssrarni_h_w(sum2_l, sum2_r, shift); \ + \ + DUP4_ARG2(__lsx_vldrepl_w, filter, 16, filter, 20, filter, 24, \ + filter, 28, filter0, filter1, filter2, filter3); \ + DUP4_ARG2(__lsx_vdp2_w_h, src0_r, filter0, src0_l, filter0, \ + src1_r, filter1, src1_l, filter1, temp0_r, temp0_l, \ + temp1_r, temp1_l); \ + \ + LSX_BUTTERFLY_4_W(temp0_r, temp0_l, temp1_l, temp1_r, sum0_r, sum0_l,\ + sum1_l, sum1_r); \ + sum2_r = sum1_r; \ + sum2_l = sum1_l; \ + sum3_r = sum0_r; \ + sum3_l = sum0_l; \ + \ + DUP4_ARG2(__lsx_vdp2_w_h, src2_r, filter2, src2_l, filter2, \ + src3_r, filter3, src3_l, filter3, temp2_r, temp2_l, \ + temp3_r, temp3_l); \ + temp2_r = __lsx_vadd_w(temp2_r, temp3_r); \ + temp2_l = __lsx_vadd_w(temp2_l, temp3_l); \ + sum0_r = __lsx_vadd_w(sum0_r, temp2_r); \ + sum0_l = __lsx_vadd_w(sum0_l, temp2_l); \ + sum3_r = __lsx_vsub_w(sum3_r, temp2_r); \ + sum3_l = __lsx_vsub_w(sum3_l, temp2_l); \ + \ + in1 = __lsx_vssrarni_h_w(sum0_l, sum0_r, shift); \ + in6 = __lsx_vssrarni_h_w(sum3_l, sum3_r, shift); \ + \ + DUP4_ARG2(__lsx_vdp2_w_h, src2_r, filter3, src2_l, filter3, \ + src3_r, filter2, src3_l, filter2, temp4_r, temp4_l, \ + temp5_r, temp5_l); \ + temp4_r = __lsx_vsub_w(temp4_r, temp5_r); \ + temp4_l = __lsx_vsub_w(temp4_l, temp5_l); \ + sum1_r = __lsx_vsub_w(sum1_r, temp4_r); \ + sum1_l = __lsx_vsub_w(sum1_l, temp4_l); \ + sum2_r = __lsx_vadd_w(sum2_r, temp4_r); \ + sum2_l = __lsx_vadd_w(sum2_l, temp4_l); \ + \ + in2 = __lsx_vssrarni_h_w(sum1_l, sum1_r, shift); \ + in5 = __lsx_vssrarni_h_w(sum2_l, sum2_r, shift); \ +} + +#define HEVC_IDCT16x16_COL(src0_r, src1_r, src2_r, src3_r, \ + src4_r, src5_r, src6_r, src7_r, \ + src0_l, src1_l, src2_l, src3_l, \ + src4_l, src5_l, src6_l, src7_l, shift) \ +{ \ + int16_t *ptr0, *ptr1; \ + __m128i dst0, dst1; \ + __m128i filter0, filter1, filter2, filter3; \ + __m128i temp0_r, temp1_r, temp0_l, temp1_l; \ + __m128i sum0_r, sum1_r, sum2_r, sum3_r, sum0_l, sum1_l, sum2_l; \ + __m128i sum3_l, res0_r, res1_r, res0_l, res1_l; \ + \ + ptr0 = (buf_ptr + 112); \ + ptr1 = (buf_ptr + 128); \ + k = -1; \ + \ + for (j = 0; j < 4; j++) \ + { \ + DUP4_ARG2(__lsx_vldrepl_w, filter, 0, filter, 4, filter, 16, \ + filter, 20, filter0, filter1, filter2, filter3); \ + DUP4_ARG2(__lsx_vdp2_w_h, src0_r, filter0, src0_l, filter0, \ + src4_r, filter2, src4_l, filter2, sum0_r, sum0_l, \ + sum2_r, sum2_l); \ + DUP2_ARG2(__lsx_vdp2_w_h, src7_r, filter2, src7_l, filter2, \ + sum3_r, sum3_l); \ + DUP4_ARG3(__lsx_vdp2add_w_h, sum0_r, src1_r, filter1, sum0_l, \ + src1_l, filter1, sum2_r, src5_r, filter3, sum2_l, \ + src5_l, filter3, sum0_r, sum0_l, sum2_r, sum2_l); \ + DUP2_ARG3(__lsx_vdp2add_w_h, sum3_r, src6_r, filter3, sum3_l, \ + src6_l, filter3, sum3_r, sum3_l); \ + \ + sum1_r = sum0_r; \ + sum1_l = sum0_l; \ + \ + DUP4_ARG2(__lsx_vldrepl_w, filter, 8, filter, 12, filter, 24, \ + filter, 28, filter0, filter1, filter2, filter3); \ + filter += 16; \ + DUP2_ARG2(__lsx_vdp2_w_h, src2_r, filter0, src2_l, filter0, \ + temp0_r, temp0_l); \ + DUP2_ARG3(__lsx_vdp2add_w_h, sum2_r, src6_r, filter2, sum2_l, \ + src6_l, filter2, sum2_r, sum2_l); \ + DUP2_ARG2(__lsx_vdp2_w_h, src5_r, filter2, src5_l, filter2, \ + temp1_r, temp1_l); \ + \ + sum0_r = __lsx_vadd_w(sum0_r, temp0_r); \ + sum0_l = __lsx_vadd_w(sum0_l, temp0_l); \ + sum1_r = __lsx_vsub_w(sum1_r, temp0_r); \ + sum1_l = __lsx_vsub_w(sum1_l, temp0_l); \ + sum3_r = __lsx_vsub_w(temp1_r, sum3_r); \ + sum3_l = __lsx_vsub_w(temp1_l, sum3_l); \ + \ + DUP2_ARG2(__lsx_vdp2_w_h, src3_r, filter1, src3_l, filter1, \ + temp0_r, temp0_l); \ + DUP4_ARG3(__lsx_vdp2add_w_h, sum2_r, src7_r, filter3, sum2_l, \ + src7_l, filter3, sum3_r, src4_r, filter3, sum3_l, \ + src4_l, filter3, sum2_r, sum2_l, sum3_r, sum3_l); \ + \ + sum0_r = __lsx_vadd_w(sum0_r, temp0_r); \ + sum0_l = __lsx_vadd_w(sum0_l, temp0_l); \ + sum1_r = __lsx_vsub_w(sum1_r, temp0_r); \ + sum1_l = __lsx_vsub_w(sum1_l, temp0_l); \ + \ + LSX_BUTTERFLY_4_W(sum0_r, sum0_l, sum2_l, sum2_r, res0_r, res0_l, \ + res1_l, res1_r); \ + dst0 = __lsx_vssrarni_h_w(res0_l, res0_r, shift); \ + dst1 = __lsx_vssrarni_h_w(res1_l, res1_r, shift); \ + __lsx_vst(dst0, buf_ptr, 0); \ + __lsx_vst(dst1, (buf_ptr + ((15 - (j * 2)) << 4)), 0); \ + \ + LSX_BUTTERFLY_4_W(sum1_r, sum1_l, sum3_l, sum3_r, res0_r, res0_l, \ + res1_l, res1_r); \ + \ + dst0 = __lsx_vssrarni_h_w(res0_l, res0_r, shift); \ + dst1 = __lsx_vssrarni_h_w(res1_l, res1_r, shift); \ + __lsx_vst(dst0, (ptr0 + ((((j + 1) >> 1) * 2 * k) << 4)), 0); \ + __lsx_vst(dst1, (ptr1 - ((((j + 1) >> 1) * 2 * k) << 4)), 0); \ + \ + k *= -1; \ + buf_ptr += 16; \ + } \ +} + +#define HEVC_EVEN16_CALC(input, sum0_r, sum0_l, load_idx, store_idx) \ +{ \ + tmp0_r = __lsx_vld(input + load_idx * 8, 0); \ + tmp0_l = __lsx_vld(input + load_idx * 8, 16); \ + tmp1_r = sum0_r; \ + tmp1_l = sum0_l; \ + sum0_r = __lsx_vadd_w(sum0_r, tmp0_r); \ + sum0_l = __lsx_vadd_w(sum0_l, tmp0_l); \ + __lsx_vst(sum0_r, (input + load_idx * 8), 0); \ + __lsx_vst(sum0_l, (input + load_idx * 8), 16); \ + tmp1_r = __lsx_vsub_w(tmp1_r, tmp0_r); \ + tmp1_l = __lsx_vsub_w(tmp1_l, tmp0_l); \ + __lsx_vst(tmp1_r, (input + store_idx * 8), 0); \ + __lsx_vst(tmp1_l, (input + store_idx * 8), 16); \ +} + +#define HEVC_IDCT_LUMA4x4_COL(in_r0, in_l0, in_r1, in_l1, \ + res0, res1, res2, res3, shift) \ +{ \ + __m128i vec0, vec1, vec2, vec3; \ + __m128i cnst74 = __lsx_vldi(0x84a); \ + __m128i cnst55 = __lsx_vldi(0x837); \ + __m128i cnst29 = __lsx_vldi(0x81d); \ + \ + vec0 = __lsx_vadd_w(in_r0, in_r1); \ + vec2 = __lsx_vsub_w(in_r0, in_l1); \ + res0 = __lsx_vmul_w(vec0, cnst29); \ + res1 = __lsx_vmul_w(vec2, cnst55); \ + res2 = __lsx_vsub_w(in_r0, in_r1); \ + vec1 = __lsx_vadd_w(in_r1, in_l1); \ + res2 = __lsx_vadd_w(res2, in_l1); \ + vec3 = __lsx_vmul_w(in_l0, cnst74); \ + res3 = __lsx_vmul_w(vec0, cnst55); \ + \ + res0 = __lsx_vadd_w(res0, __lsx_vmul_w(vec1, cnst55)); \ + res1 = __lsx_vsub_w(res1, __lsx_vmul_w(vec1, cnst29)); \ + res2 = __lsx_vmul_w(res2, cnst74); \ + res3 = __lsx_vadd_w(res3, __lsx_vmul_w(vec2, cnst29)); \ + \ + res0 = __lsx_vadd_w(res0, vec3); \ + res1 = __lsx_vadd_w(res1, vec3); \ + res3 = __lsx_vsub_w(res3, vec3); \ + \ + res0 = __lsx_vsrari_w(res0, shift); \ + res1 = __lsx_vsrari_w(res1, shift); \ + res2 = __lsx_vsrari_w(res2, shift); \ + res3 = __lsx_vsrari_w(res3, shift); \ + res0 = __lsx_vsat_w(res0, 15); \ + res1 = __lsx_vsat_w(res1, 15); \ + res2 = __lsx_vsat_w(res2, 15); \ + res3 = __lsx_vsat_w(res3, 15); \ +} + +void ff_hevc_idct_4x4_lsx(int16_t *coeffs, int col_limit) +{ + __m128i in0, in1; + __m128i in_r0, in_l0, in_r1, in_l1; + __m128i sum0, sum1, sum2, sum3; + __m128i zero = __lsx_vldi(0x00); + + in0 = __lsx_vld(coeffs, 0); + in1 = __lsx_vld(coeffs, 16); + in_r0 = __lsx_vilvl_h(zero, in0); + in_l0 = __lsx_vilvh_h(zero, in0); + in_r1 = __lsx_vilvl_h(zero, in1); + in_l1 = __lsx_vilvh_h(zero, in1); + + HEVC_IDCT4x4_COL(in_r0, in_l0, in_r1, in_l1, sum0, sum1, sum2, sum3, 7); + LSX_TRANSPOSE4x4_W(sum0, sum1, sum2, sum3, in_r0, in_l0, in_r1, in_l1); + HEVC_IDCT4x4_COL(in_r0, in_l0, in_r1, in_l1, sum0, sum1, sum2, sum3, 12); + + /* Pack and transpose */ + in0 = __lsx_vpickev_h(sum2, sum0); + in1 = __lsx_vpickev_h(sum3, sum1); + sum0 = __lsx_vilvl_h(in1, in0); + sum1 = __lsx_vilvh_h(in1, in0); + in0 = __lsx_vilvl_w(sum1, sum0); + in1 = __lsx_vilvh_w(sum1, sum0); + + __lsx_vst(in0, coeffs, 0); + __lsx_vst(in1, coeffs, 16); +} + +void ff_hevc_idct_8x8_lsx(int16_t *coeffs, int col_limit) +{ + const int16_t *filter = >8x8_cnst[0]; + __m128i in0, in1, in2, in3, in4, in5, in6, in7; + + DUP4_ARG2(__lsx_vld, coeffs, 0, coeffs, 16, coeffs, 32, + coeffs, 48, in0, in1, in2, in3); + DUP4_ARG2(__lsx_vld, coeffs, 64, coeffs, 80, coeffs, 96, + coeffs, 112, in4, in5, in6, in7); + HEVC_IDCT8x8_COL(in0, in1, in2, in3, in4, in5, in6, in7, 7); + LSX_TRANSPOSE8x8_H(in0, in1, in2, in3, in4, in5, in6, in7, + in0, in1, in2, in3, in4, in5, in6, in7); + HEVC_IDCT8x8_COL(in0, in1, in2, in3, in4, in5, in6, in7, 12); + LSX_TRANSPOSE8x8_H(in0, in1, in2, in3, in4, in5, in6, in7, + in0, in1, in2, in3, in4, in5, in6, in7); + + __lsx_vst(in0, coeffs, 0); + __lsx_vst(in1, coeffs, 16); + __lsx_vst(in2, coeffs, 32); + __lsx_vst(in3, coeffs, 48); + __lsx_vst(in4, coeffs, 64); + __lsx_vst(in5, coeffs, 80); + __lsx_vst(in6, coeffs, 96); + __lsx_vst(in7, coeffs, 112); +} + +void ff_hevc_idct_16x16_lsx(int16_t *coeffs, int col_limit) +{ + int16_t i, j, k; + int16_t buf[256]; + int16_t *buf_ptr = &buf[0]; + int16_t *src = coeffs; + const int16_t *filter = >16x16_cnst[0]; + __m128i in0, in1, in2, in3, in4, in5, in6, in7; + __m128i in8, in9, in10, in11, in12, in13, in14, in15; + __m128i vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + __m128i src0_r, src1_r, src2_r, src3_r, src4_r, src5_r, src6_r, src7_r; + __m128i src0_l, src1_l, src2_l, src3_l, src4_l, src5_l, src6_l, src7_l; + + for (i = 2; i--;) { + DUP4_ARG2(__lsx_vld, src, 0, src, 32, src, 64, src, 96, + in0, in1, in2, in3); + DUP4_ARG2(__lsx_vld, src, 128, src, 160, src, 192, src, 224, + in4, in5, in6, in7); + DUP4_ARG2(__lsx_vld, src, 256, src, 288, src, 320, src, 352, + in8, in9, in10, in11); + DUP4_ARG2(__lsx_vld, src, 384, src, 416, src, 448, src, 480, + in12, in13, in14, in15); + + DUP4_ARG2(__lsx_vilvl_h, in4, in0, in12, in8, in6, in2, in14, in10, + src0_r, src1_r, src2_r, src3_r); + DUP4_ARG2(__lsx_vilvl_h, in5, in1, in13, in9, in3, in7, in11, in15, + src4_r, src5_r, src6_r, src7_r); + DUP4_ARG2(__lsx_vilvh_h, in4, in0, in12, in8, in6, in2, in14, in10, + src0_l, src1_l, src2_l, src3_l); + DUP4_ARG2(__lsx_vilvh_h, in5, in1, in13, in9, in3, in7, in11, in15, + src4_l, src5_l, src6_l, src7_l); + + HEVC_IDCT16x16_COL(src0_r, src1_r, src2_r, src3_r, src4_r, src5_r, + src6_r, src7_r, src0_l, src1_l, src2_l, src3_l, + src4_l, src5_l, src6_l, src7_l, 7); + + src += 8; + buf_ptr = (&buf[0] + 8); + filter = >16x16_cnst[0]; + } + + src = &buf[0]; + buf_ptr = coeffs; + filter = >16x16_cnst[0]; + + for (i = 2; i--;) { + DUP4_ARG2(__lsx_vld, src, 0, src, 16, src, 32, src, 48, + in0, in8, in1, in9); + DUP4_ARG2(__lsx_vld, src, 64, src, 80, src, 96, src, 112, + in2, in10, in3, in11); + DUP4_ARG2(__lsx_vld, src, 128, src, 144, src, 160, src, 176, + in4, in12, in5, in13); + DUP4_ARG2(__lsx_vld, src, 192, src, 208, src, 224, src, 240, + in6, in14, in7, in15); + LSX_TRANSPOSE8x8_H(in0, in1, in2, in3, in4, in5, in6, in7, + in0, in1, in2, in3, in4, in5, in6, in7); + LSX_TRANSPOSE8x8_H(in8, in9, in10, in11, in12, in13, in14, in15, + in8, in9, in10, in11, in12, in13, in14, in15); + DUP4_ARG2(__lsx_vilvl_h, in4, in0, in12, in8, in6, in2, in14, in10, + src0_r, src1_r, src2_r, src3_r); + DUP4_ARG2(__lsx_vilvl_h, in5, in1, in13, in9, in3, in7, in11, in15, + src4_r, src5_r, src6_r, src7_r); + DUP4_ARG2(__lsx_vilvh_h, in4, in0, in12, in8, in6, in2, in14, in10, + src0_l, src1_l, src2_l, src3_l); + DUP4_ARG2(__lsx_vilvh_h, in5, in1, in13, in9, in3, in7, in11, in15, + src4_l, src5_l, src6_l, src7_l); + HEVC_IDCT16x16_COL(src0_r, src1_r, src2_r, src3_r, src4_r, src5_r, + src6_r, src7_r, src0_l, src1_l, src2_l, src3_l, + src4_l, src5_l, src6_l, src7_l, 12); + + src += 128; + buf_ptr = coeffs + 8; + filter = >16x16_cnst[0]; + } + + DUP4_ARG2(__lsx_vld, coeffs, 0, coeffs, 32, coeffs, 64, coeffs, 96, + in0, in1, in2, in3); + DUP4_ARG2(__lsx_vld, coeffs, 128, coeffs, 160, coeffs, 192, coeffs, 224, + in4, in5, in6, in7); + LSX_TRANSPOSE8x8_H(in0, in1, in2, in3, in4, in5, in6, in7, + vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7); + __lsx_vst(vec0, coeffs, 0); + __lsx_vst(vec1, coeffs, 32); + __lsx_vst(vec2, coeffs, 64); + __lsx_vst(vec3, coeffs, 96); + __lsx_vst(vec4, coeffs, 128); + __lsx_vst(vec5, coeffs, 160); + __lsx_vst(vec6, coeffs, 192); + __lsx_vst(vec7, coeffs, 224); + + src = coeffs + 8; + DUP4_ARG2(__lsx_vld, src, 0, src, 32, src, 64, src, 96, in0, in1, in2, in3); + DUP4_ARG2(__lsx_vld, src, 128, src, 160, src, 192, src, 224, + in4, in5, in6, in7); + LSX_TRANSPOSE8x8_H(in0, in1, in2, in3, in4, in5, in6, in7, + vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7); + src = coeffs + 128; + DUP4_ARG2(__lsx_vld, src, 0, src, 32, src, 64, src, 96, + in8, in9, in10, in11); + DUP4_ARG2(__lsx_vld, src, 128, src, 160, src, 192, src, 224, + in12, in13, in14, in15); + + __lsx_vst(vec0, src, 0); + __lsx_vst(vec1, src, 32); + __lsx_vst(vec2, src, 64); + __lsx_vst(vec3, src, 96); + __lsx_vst(vec4, src, 128); + __lsx_vst(vec5, src, 160); + __lsx_vst(vec6, src, 192); + __lsx_vst(vec7, src, 224); + LSX_TRANSPOSE8x8_H(in8, in9, in10, in11, in12, in13, in14, in15, + vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7); + src = coeffs + 8; + __lsx_vst(vec0, src, 0); + __lsx_vst(vec1, src, 32); + __lsx_vst(vec2, src, 64); + __lsx_vst(vec3, src, 96); + __lsx_vst(vec4, src, 128); + __lsx_vst(vec5, src, 160); + __lsx_vst(vec6, src, 192); + __lsx_vst(vec7, src, 224); + + src = coeffs + 136; + DUP4_ARG2(__lsx_vld, src, 0, src, 32, src, 64, src, 96, + in0, in1, in2, in3); + DUP4_ARG2(__lsx_vld, src, 128, src, 160, src, 192, src, 224, + in4, in5, in6, in7); + LSX_TRANSPOSE8x8_H(in0, in1, in2, in3, in4, in5, in6, in7, + vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7); + __lsx_vst(vec0, src, 0); + __lsx_vst(vec1, src, 32); + __lsx_vst(vec2, src, 64); + __lsx_vst(vec3, src, 96); + __lsx_vst(vec4, src, 128); + __lsx_vst(vec5, src, 160); + __lsx_vst(vec6, src, 192); + __lsx_vst(vec7, src, 224); +} + +static void hevc_idct_8x32_column_lsx(int16_t *coeffs, int32_t buf_pitch, + uint8_t round) +{ + uint8_t i; + int32_t buf_pitch_2 = buf_pitch << 1; + int32_t buf_pitch_4 = buf_pitch << 2; + int32_t buf_pitch_8 = buf_pitch << 3; + int32_t buf_pitch_16 = buf_pitch << 4; + + const int16_t *filter_ptr0 = >32x32_cnst0[0]; + const int16_t *filter_ptr1 = >32x32_cnst1[0]; + const int16_t *filter_ptr2 = >32x32_cnst2[0]; + const int16_t *filter_ptr3 = >8x8_cnst[0]; + int16_t *src0 = (coeffs + buf_pitch); + int16_t *src1 = (coeffs + buf_pitch_2); + int16_t *src2 = (coeffs + buf_pitch_4); + int16_t *src3 = (coeffs); + int32_t tmp_buf[8 * 32 + 15]; + int32_t *tmp_buf_ptr = tmp_buf + 15; + __m128i in0, in1, in2, in3, in4, in5, in6, in7; + __m128i src0_r, src1_r, src2_r, src3_r, src4_r, src5_r, src6_r, src7_r; + __m128i src0_l, src1_l, src2_l, src3_l, src4_l, src5_l, src6_l, src7_l; + __m128i filter0, filter1, filter2, filter3; + __m128i sum0_r, sum0_l, sum1_r, sum1_l, tmp0_r, tmp0_l, tmp1_r, tmp1_l; + + /* Align pointer to 64 byte boundary */ + tmp_buf_ptr = (int32_t *)(((uintptr_t) tmp_buf_ptr) & ~(uintptr_t) 63); + + /* process coeff 4, 12, 20, 28 */ + in0 = __lsx_vld(src2, 0); + in1 = __lsx_vld(src2 + buf_pitch_8, 0); + in2 = __lsx_vld(src2 + buf_pitch_16, 0); + in3 = __lsx_vld(src2 + buf_pitch_16 + buf_pitch_8, 0); + in4 = __lsx_vld(src3, 0); + in5 = __lsx_vld(src3 + buf_pitch_8, 0); + in6 = __lsx_vld(src3 + buf_pitch_16, 0); + in7 = __lsx_vld(src3 + buf_pitch_16 + buf_pitch_8, 0); + DUP4_ARG2(__lsx_vilvl_h, in1, in0, in3, in2, in6, in4, in7, in5, + src0_r, src1_r, src2_r, src3_r); + DUP4_ARG2(__lsx_vilvh_h, in1, in0, in3, in2, in6, in4, in7, in5, + src0_l, src1_l, src2_l, src3_l); + + filter0 = __lsx_vldrepl_w(filter_ptr2, 0); + filter1 = __lsx_vldrepl_w(filter_ptr2, 4); + sum0_r = __lsx_vdp2_w_h(src0_r, filter0); + sum0_l = __lsx_vdp2_w_h(src0_l, filter0); + sum0_r = __lsx_vdp2add_w_h(sum0_r, src1_r, filter1); + sum0_l = __lsx_vdp2add_w_h(sum0_l, src1_l, filter1); + __lsx_vst(sum0_r, tmp_buf_ptr, 0); + __lsx_vst(sum0_l, tmp_buf_ptr, 16); + + filter0 = __lsx_vldrepl_w(filter_ptr2, 8); + filter1 = __lsx_vldrepl_w(filter_ptr2, 12); + sum0_r = __lsx_vdp2_w_h(src0_r, filter0); + sum0_l = __lsx_vdp2_w_h(src0_l, filter0); + sum0_r = __lsx_vdp2add_w_h(sum0_r, src1_r, filter1); + sum0_l = __lsx_vdp2add_w_h(sum0_l, src1_l, filter1); + __lsx_vst(sum0_r, tmp_buf_ptr, 32); + __lsx_vst(sum0_l, tmp_buf_ptr, 48); + + filter0 = __lsx_vldrepl_w(filter_ptr2, 16); + filter1 = __lsx_vldrepl_w(filter_ptr2, 20); + sum0_r = __lsx_vdp2_w_h(src0_r, filter0); + sum0_l = __lsx_vdp2_w_h(src0_l, filter0); + sum0_r = __lsx_vdp2add_w_h(sum0_r, src1_r, filter1); + sum0_l = __lsx_vdp2add_w_h(sum0_l, src1_l, filter1); + __lsx_vst(sum0_r, tmp_buf_ptr, 64); + __lsx_vst(sum0_l, tmp_buf_ptr, 80); + + filter0 = __lsx_vldrepl_w(filter_ptr2, 24); + filter1 = __lsx_vldrepl_w(filter_ptr2, 28); + sum0_r = __lsx_vdp2_w_h(src0_r, filter0); + sum0_l = __lsx_vdp2_w_h(src0_l, filter0); + sum0_r = __lsx_vdp2add_w_h(sum0_r, src1_r, filter1); + sum0_l = __lsx_vdp2add_w_h(sum0_l, src1_l, filter1); + __lsx_vst(sum0_r, tmp_buf_ptr, 96); + __lsx_vst(sum0_l, tmp_buf_ptr, 112); + + /* process coeff 0, 8, 16, 24 */ + filter0 = __lsx_vldrepl_w(filter_ptr3, 0); + filter1 = __lsx_vldrepl_w(filter_ptr3, 4); + + DUP4_ARG2(__lsx_vdp2_w_h, src2_r, filter0, src2_l, filter0, + src3_r, filter1, src3_l, filter1, sum0_r, sum0_l, tmp1_r, tmp1_l); + sum1_r = __lsx_vsub_w(sum0_r, tmp1_r); + sum1_l = __lsx_vsub_w(sum0_l, tmp1_l); + sum0_r = __lsx_vadd_w(sum0_r, tmp1_r); + sum0_l = __lsx_vadd_w(sum0_l, tmp1_l); + + HEVC_EVEN16_CALC(tmp_buf_ptr, sum0_r, sum0_l, 0, 7); + HEVC_EVEN16_CALC(tmp_buf_ptr, sum1_r, sum1_l, 3, 4); + + filter0 = __lsx_vldrepl_w(filter_ptr3, 16); + filter1 = __lsx_vldrepl_w(filter_ptr3, 20); + + DUP4_ARG2(__lsx_vdp2_w_h, src2_r, filter0, src2_l, filter0, + src3_r, filter1, src3_l, filter1, sum0_r, sum0_l, tmp1_r, tmp1_l); + sum1_r = __lsx_vsub_w(sum0_r, tmp1_r); + sum1_l = __lsx_vsub_w(sum0_l, tmp1_l); + sum0_r = __lsx_vadd_w(sum0_r, tmp1_r); + sum0_l = __lsx_vadd_w(sum0_l, tmp1_l); + + HEVC_EVEN16_CALC(tmp_buf_ptr, sum0_r, sum0_l, 1, 6); + HEVC_EVEN16_CALC(tmp_buf_ptr, sum1_r, sum1_l, 2, 5); + + /* process coeff 2 6 10 14 18 22 26 30 */ + in0 = __lsx_vld(src1, 0); + in1 = __lsx_vld(src1 + buf_pitch_4, 0); + in2 = __lsx_vld(src1 + buf_pitch_8, 0); + in3 = __lsx_vld(src1 + buf_pitch_8 + buf_pitch_4, 0); + in4 = __lsx_vld(src1 + buf_pitch_16, 0); + in5 = __lsx_vld(src1 + buf_pitch_16 + buf_pitch_4, 0); + in6 = __lsx_vld(src1 + buf_pitch_16 + buf_pitch_8, 0); + in7 = __lsx_vld(src1 + buf_pitch_16 + buf_pitch_8 + buf_pitch_4, 0); + + DUP4_ARG2(__lsx_vilvl_h, in1, in0, in3, in2, in5, in4, in7, in6, + src0_r, src1_r, src2_r, src3_r); + DUP4_ARG2(__lsx_vilvh_h, in1, in0, in3, in2, in5, in4, in7, in6, + src0_l, src1_l, src2_l, src3_l); + + /* loop for all columns of constants */ + for (i = 0; i < 8; i++) { + /* processing single column of constants */ + filter0 = __lsx_vldrepl_w(filter_ptr1, 0); + filter1 = __lsx_vldrepl_w(filter_ptr1, 4); + filter2 = __lsx_vldrepl_w(filter_ptr1, 8); + filter3 = __lsx_vldrepl_w(filter_ptr1, 12); + sum0_r = __lsx_vdp2_w_h(src0_r, filter0); + sum0_l = __lsx_vdp2_w_h(src0_l, filter0); + sum0_r = __lsx_vdp2add_w_h(sum0_r, src1_r, filter1); + sum0_l = __lsx_vdp2add_w_h(sum0_l, src1_l, filter1); + sum0_r = __lsx_vdp2add_w_h(sum0_r, src2_r, filter2); + sum0_l = __lsx_vdp2add_w_h(sum0_l, src2_l, filter2); + sum0_r = __lsx_vdp2add_w_h(sum0_r, src3_r, filter3); + sum0_l = __lsx_vdp2add_w_h(sum0_l, src3_l, filter3); + + tmp0_r = __lsx_vld(tmp_buf_ptr + (i << 3), 0); + tmp0_l = __lsx_vld(tmp_buf_ptr + (i << 3), 16); + tmp1_r = tmp0_r; + tmp1_l = tmp0_l; + tmp0_r = __lsx_vadd_w(tmp0_r, sum0_r); + tmp0_l = __lsx_vadd_w(tmp0_l, sum0_l); + tmp1_r = __lsx_vsub_w(tmp1_r, sum0_r); + tmp1_l = __lsx_vsub_w(tmp1_l, sum0_l); + __lsx_vst(tmp0_r, tmp_buf_ptr + (i << 3), 0); + __lsx_vst(tmp0_l, tmp_buf_ptr + (i << 3), 16); + __lsx_vst(tmp1_r, tmp_buf_ptr + ((15 - i) * 8), 0); + __lsx_vst(tmp1_l, tmp_buf_ptr + ((15 - i) * 8), 16); + + filter_ptr1 += 8; + } + + /* process coeff 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 */ + in0 = __lsx_vld(src0, 0); + in1 = __lsx_vld(src0 + buf_pitch_2, 0); + in2 = __lsx_vld(src0 + buf_pitch_4, 0); + in3 = __lsx_vld(src0 + buf_pitch_4 + buf_pitch_2, 0); + in4 = __lsx_vld(src0 + buf_pitch_8, 0); + in5 = __lsx_vld(src0 + buf_pitch_8 + buf_pitch_2, 0); + in6 = __lsx_vld(src0 + buf_pitch_8 + buf_pitch_4, 0); + in7 = __lsx_vld(src0 + buf_pitch_8 + buf_pitch_4 + buf_pitch_2, 0); + + src0 += 16 * buf_pitch; + DUP4_ARG2(__lsx_vilvl_h, in1, in0, in3, in2, in5, in4, in7, in6, + src0_r, src1_r, src2_r, src3_r); + DUP4_ARG2(__lsx_vilvh_h, in1, in0, in3, in2, in5, in4, in7, in6, + src0_l, src1_l, src2_l, src3_l); + in0 = __lsx_vld(src0, 0); + in1 = __lsx_vld(src0 + buf_pitch_2, 0); + in2 = __lsx_vld(src0 + buf_pitch_4, 0); + in3 = __lsx_vld(src0 + buf_pitch_4 + buf_pitch_2, 0); + in4 = __lsx_vld(src0 + buf_pitch_8, 0); + in5 = __lsx_vld(src0 + buf_pitch_8 + buf_pitch_2, 0); + in6 = __lsx_vld(src0 + buf_pitch_8 + buf_pitch_4, 0); + in7 = __lsx_vld(src0 + buf_pitch_8 + buf_pitch_4 + buf_pitch_2, 0); + + DUP4_ARG2(__lsx_vilvl_h, in1, in0, in3, in2, in5, in4, in7, in6, + src4_r, src5_r, src6_r, src7_r); + DUP4_ARG2(__lsx_vilvh_h, in1, in0, in3, in2, in5, in4, in7, in6, + src4_l, src5_l, src6_l, src7_l); + + /* loop for all columns of filter constants */ + for (i = 0; i < 16; i++) { + /* processing single column of constants */ + filter0 = __lsx_vldrepl_w(filter_ptr0, 0); + filter1 = __lsx_vldrepl_w(filter_ptr0, 4); + filter2 = __lsx_vldrepl_w(filter_ptr0, 8); + filter3 = __lsx_vldrepl_w(filter_ptr0, 12); + sum0_r = __lsx_vdp2_w_h(src0_r, filter0); + sum0_l = __lsx_vdp2_w_h(src0_l, filter0); + sum0_r = __lsx_vdp2add_w_h(sum0_r, src1_r, filter1); + sum0_l = __lsx_vdp2add_w_h(sum0_l, src1_l, filter1); + sum0_r = __lsx_vdp2add_w_h(sum0_r, src2_r, filter2); + sum0_l = __lsx_vdp2add_w_h(sum0_l, src2_l, filter2); + sum0_r = __lsx_vdp2add_w_h(sum0_r, src3_r, filter3); + sum0_l = __lsx_vdp2add_w_h(sum0_l, src3_l, filter3); + tmp1_r = sum0_r; + tmp1_l = sum0_l; + + filter0 = __lsx_vldrepl_w(filter_ptr0, 16); + filter1 = __lsx_vldrepl_w(filter_ptr0, 20); + filter2 = __lsx_vldrepl_w(filter_ptr0, 24); + filter3 = __lsx_vldrepl_w(filter_ptr0, 28); + sum0_r = __lsx_vdp2_w_h(src4_r, filter0); + sum0_l = __lsx_vdp2_w_h(src4_l, filter0); + sum0_r = __lsx_vdp2add_w_h(sum0_r, src5_r, filter1); + sum0_l = __lsx_vdp2add_w_h(sum0_l, src5_l, filter1); + sum0_r = __lsx_vdp2add_w_h(sum0_r, src6_r, filter2); + sum0_l = __lsx_vdp2add_w_h(sum0_l, src6_l, filter2); + sum0_r = __lsx_vdp2add_w_h(sum0_r, src7_r, filter3); + sum0_l = __lsx_vdp2add_w_h(sum0_l, src7_l, filter3); + sum0_r = __lsx_vadd_w(sum0_r, tmp1_r); + sum0_l = __lsx_vadd_w(sum0_l, tmp1_l); + + tmp0_r = __lsx_vld(tmp_buf_ptr + i * 8, 0); + tmp0_l = __lsx_vld(tmp_buf_ptr + i * 8, 16); + tmp1_r = tmp0_r; + tmp1_l = tmp0_l; + tmp0_r = __lsx_vadd_w(tmp0_r, sum0_r); + tmp0_l = __lsx_vadd_w(tmp0_l, sum0_l); + sum1_r = __lsx_vreplgr2vr_w(round); + tmp0_r = __lsx_vssrarn_h_w(tmp0_r, sum1_r); + tmp0_l = __lsx_vssrarn_h_w(tmp0_l, sum1_r); + in0 = __lsx_vpackev_d(tmp0_l, tmp0_r); + __lsx_vst(in0, (coeffs + i * buf_pitch), 0); + tmp1_r = __lsx_vsub_w(tmp1_r, sum0_r); + tmp1_l = __lsx_vsub_w(tmp1_l, sum0_l); + tmp1_r = __lsx_vssrarn_h_w(tmp1_r, sum1_r); + tmp1_l = __lsx_vssrarn_h_w(tmp1_l, sum1_r); + in0 = __lsx_vpackev_d(tmp1_l, tmp1_r); + __lsx_vst(in0, (coeffs + (31 - i) * buf_pitch), 0); + + filter_ptr0 += 16; + } +} + +static void hevc_idct_transpose_32x8_to_8x32(int16_t *coeffs, int16_t *tmp_buf) +{ + uint8_t i; + __m128i in0, in1, in2, in3, in4, in5, in6, in7; + + for (i = 0; i < 4; i++) { + DUP4_ARG2(__lsx_vld, coeffs, 0, coeffs, 64, coeffs, 128, + coeffs, 192, in0, in1, in2, in3); + DUP4_ARG2(__lsx_vld, coeffs, 256, coeffs, 320, coeffs, 384, + coeffs, 448, in4, in5, in6, in7); + coeffs += 8; + LSX_TRANSPOSE8x8_H(in0, in1, in2, in3, in4, in5, in6, in7, + in0, in1, in2, in3, in4, in5, in6, in7); + __lsx_vst(in0, tmp_buf, 0); + __lsx_vst(in1, tmp_buf, 16); + __lsx_vst(in2, tmp_buf, 32); + __lsx_vst(in3, tmp_buf, 48); + __lsx_vst(in4, tmp_buf, 64); + __lsx_vst(in5, tmp_buf, 80); + __lsx_vst(in6, tmp_buf, 96); + __lsx_vst(in7, tmp_buf, 112); + tmp_buf += 64; + } +} + +static void hevc_idct_transpose_8x32_to_32x8(int16_t *tmp_buf, int16_t *coeffs) +{ + uint8_t i; + __m128i in0, in1, in2, in3, in4, in5, in6, in7; + + for (i = 0; i < 4; i++) { + DUP4_ARG2(__lsx_vld, tmp_buf, 0, tmp_buf, 16, tmp_buf, 32, + tmp_buf, 48, in0, in1, in2, in3); + DUP4_ARG2(__lsx_vld, tmp_buf, 64, tmp_buf, 80, tmp_buf, 96, + tmp_buf, 112, in4, in5, in6, in7); + tmp_buf += 64; + LSX_TRANSPOSE8x8_H(in0, in1, in2, in3, in4, in5, in6, in7, + in0, in1, in2, in3, in4, in5, in6, in7); + __lsx_vst(in0, coeffs, 0); + __lsx_vst(in1, coeffs, 64); + __lsx_vst(in2, coeffs, 128); + __lsx_vst(in3, coeffs, 192); + __lsx_vst(in4, coeffs, 256); + __lsx_vst(in5, coeffs, 320); + __lsx_vst(in6, coeffs, 384); + __lsx_vst(in7, coeffs, 448); + coeffs += 8; + } +} + +void ff_hevc_idct_32x32_lsx(int16_t *coeffs, int col_limit) +{ + uint8_t row_cnt, col_cnt; + int16_t *src = coeffs; + int16_t tmp_buf[8 * 32 + 31]; + int16_t *tmp_buf_ptr = tmp_buf + 31; + uint8_t round; + int32_t buf_pitch; + + /* Align pointer to 64 byte boundary */ + tmp_buf_ptr = (int16_t *)(((uintptr_t) tmp_buf_ptr) & ~(uintptr_t) 63); + + /* column transform */ + round = 7; + buf_pitch = 32; + for (col_cnt = 0; col_cnt < 4; col_cnt++) { + /* process 8x32 blocks */ + hevc_idct_8x32_column_lsx((coeffs + col_cnt * 8), buf_pitch, round); + } + + /* row transform */ + round = 12; + buf_pitch = 8; + for (row_cnt = 0; row_cnt < 4; row_cnt++) { + /* process 32x8 blocks */ + src = (coeffs + 32 * 8 * row_cnt); + + hevc_idct_transpose_32x8_to_8x32(src, tmp_buf_ptr); + hevc_idct_8x32_column_lsx(tmp_buf_ptr, buf_pitch, round); + hevc_idct_transpose_8x32_to_32x8(tmp_buf_ptr, src); + } +} diff --git a/libavcodec/loongarch/hevc_lpf_sao_lsx.c b/libavcodec/loongarch/hevc_lpf_sao_lsx.c new file mode 100644 index 000000000..fc10e8eda --- /dev/null +++ b/libavcodec/loongarch/hevc_lpf_sao_lsx.c @@ -0,0 +1,2485 @@ +/* + * Copyright (c) 2022 Loongson Technology Corporation Limited + * Contributed by Lu Wang + * Hao Chen + * + * 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/loongarch/loongson_intrinsics.h" +#include "hevcdsp_lsx.h" + +void ff_hevc_loop_filter_luma_h_8_lsx(uint8_t *src, ptrdiff_t stride, + int32_t beta, int32_t *tc, + uint8_t *p_is_pcm, uint8_t *q_is_pcm) +{ + ptrdiff_t stride_2x = (stride << 1); + ptrdiff_t stride_4x = (stride << 2); + ptrdiff_t stride_3x = stride_2x + stride; + uint8_t *p3 = src - stride_4x; + uint8_t *p2 = src - stride_3x; + uint8_t *p1 = src - stride_2x; + uint8_t *p0 = src - stride; + uint8_t *q0 = src; + uint8_t *q1 = src + stride; + uint8_t *q2 = src + stride_2x; + uint8_t *q3 = src + stride_3x; + uint8_t flag0, flag1; + int32_t dp00, dq00, dp30, dq30, d00, d30, d0030, d0434; + int32_t dp04, dq04, dp34, dq34, d04, d34; + int32_t tc0, p_is_pcm0, q_is_pcm0, beta30, beta20, tc250; + int32_t tc4, p_is_pcm4, q_is_pcm4, tc254, tmp; + + __m128i dst0, dst1, dst2, dst3, dst4, dst5; + __m128i cmp0, cmp1, cmp2, cmp3, p_is_pcm_vec, q_is_pcm_vec; + __m128i temp0, temp1; + __m128i temp2, tc_pos, tc_neg; + __m128i diff0, diff1, delta0, delta1, delta2, abs_delta0; + __m128i zero = {0}; + __m128i p3_src, p2_src, p1_src, p0_src, q0_src, q1_src, q2_src, q3_src; + + dp00 = abs(p2[0] - (p1[0] << 1) + p0[0]); + dq00 = abs(q2[0] - (q1[0] << 1) + q0[0]); + dp30 = abs(p2[3] - (p1[3] << 1) + p0[3]); + dq30 = abs(q2[3] - (q1[3] << 1) + q0[3]); + d00 = dp00 + dq00; + d30 = dp30 + dq30; + dp04 = abs(p2[4] - (p1[4] << 1) + p0[4]); + dq04 = abs(q2[4] - (q1[4] << 1) + q0[4]); + dp34 = abs(p2[7] - (p1[7] << 1) + p0[7]); + dq34 = abs(q2[7] - (q1[7] << 1) + q0[7]); + d04 = dp04 + dq04; + d34 = dp34 + dq34; + + p_is_pcm0 = p_is_pcm[0]; + p_is_pcm4 = p_is_pcm[1]; + q_is_pcm0 = q_is_pcm[0]; + q_is_pcm4 = q_is_pcm[1]; + + DUP2_ARG1(__lsx_vreplgr2vr_d, p_is_pcm0, p_is_pcm4, cmp0, cmp1); + p_is_pcm_vec = __lsx_vpackev_d(cmp1, cmp0); + p_is_pcm_vec = __lsx_vseqi_d(p_is_pcm_vec, 0); + d0030 = (d00 + d30) >= beta; + d0434 = (d04 + d34) >= beta; + DUP2_ARG1(__lsx_vreplgr2vr_w, d0030, d0434, cmp0, cmp1); + cmp3 = __lsx_vpackev_w(cmp1, cmp0); + cmp3 = __lsx_vseqi_w(cmp3, 0); + + if ((!p_is_pcm0 || !p_is_pcm4 || !q_is_pcm0 || !q_is_pcm4) && + (!d0030 || !d0434)) { + DUP4_ARG2(__lsx_vld, p3, 0, p2, 0, p1, 0, p0, 0, + p3_src, p2_src, p1_src, p0_src); + DUP2_ARG1(__lsx_vreplgr2vr_d, q_is_pcm0, q_is_pcm4, cmp0, cmp1); + q_is_pcm_vec = __lsx_vpackev_d(cmp1, cmp0); + q_is_pcm_vec = __lsx_vseqi_d(q_is_pcm_vec, 0); + + tc0 = tc[0]; + beta30 = beta >> 3; + beta20 = beta >> 2; + tc250 = (((tc0 << 2) + tc0 + 1) >> 1); + tc4 = tc[1]; + tc254 = (((tc4 << 2) + tc4 + 1) >> 1); + + DUP2_ARG1(__lsx_vreplgr2vr_h, tc0, tc4, cmp0, cmp1); + DUP4_ARG2(__lsx_vilvl_b, zero, p3_src, zero, p2_src, zero, p1_src, zero, + p0_src, p3_src, p2_src, p1_src, p0_src); + DUP4_ARG2(__lsx_vld, q0, 0, q1, 0, q2, 0, q3, 0, + q0_src, q1_src, q2_src, q3_src); + flag0 = abs(p3[0] - p0[0]) + abs(q3[0] - q0[0]) < beta30 && + abs(p0[0] - q0[0]) < tc250; + flag0 = flag0 && (abs(p3[3] - p0[3]) + abs(q3[3] - q0[3]) < beta30 && + abs(p0[3] - q0[3]) < tc250 && (d00 << 1) < beta20 && + (d30 << 1) < beta20); + tc_pos = __lsx_vpackev_d(cmp1, cmp0); + DUP4_ARG2(__lsx_vilvl_b, zero, q0_src, zero, q1_src, zero, q2_src, + zero, q3_src, q0_src, q1_src, q2_src, q3_src); + + flag1 = abs(p3[4] - p0[4]) + abs(q3[4] - q0[4]) < beta30 && + abs(p0[4] - q0[4]) < tc254; + flag1 = flag1 && (abs(p3[7] - p0[7]) + abs(q3[7] - q0[7]) < beta30 && + abs(p0[7] - q0[7]) < tc254 && (d04 << 1) < beta20 && + (d34 << 1) < beta20); + DUP2_ARG1(__lsx_vreplgr2vr_w, flag0, flag1, cmp0, cmp1); + cmp2 = __lsx_vpackev_w(cmp1, cmp0); + cmp2 = __lsx_vseqi_w(cmp2, 0); + + if (flag0 && flag1) { /* strong only */ + /* strong filter */ + tc_pos = __lsx_vslli_h(tc_pos, 1); + tc_neg = __lsx_vneg_h(tc_pos); + + /* p part */ + DUP2_ARG2(__lsx_vadd_h, p1_src, p0_src, temp0, q0_src, + temp0, temp0); + temp1 = __lsx_vadd_h(p3_src, p2_src); + temp1 = __lsx_vslli_h(temp1, 1); + DUP2_ARG2(__lsx_vadd_h, temp1, p2_src, temp1, temp0, temp1, temp1); + temp1 = __lsx_vsrari_h(temp1, 3); + temp2 = __lsx_vsub_h(temp1, p2_src); + temp2 = __lsx_vclip_h(temp2, tc_neg, tc_pos); + dst0 = __lsx_vadd_h(temp2, p2_src); + + temp1 = __lsx_vadd_h(temp0, p2_src); + temp1 = __lsx_vsrari_h(temp1, 2); + temp2 = __lsx_vsub_h(temp1, p1_src); + temp2 = __lsx_vclip_h(temp2, tc_neg, tc_pos); + dst1 = __lsx_vadd_h(temp2, p1_src); + + temp1 = __lsx_vslli_h(temp0, 1); + DUP2_ARG2(__lsx_vadd_h, temp1, p2_src, temp1, q1_src, + temp1, temp1); + temp1 = __lsx_vsrari_h(temp1, 3); + temp2 = __lsx_vsub_h(temp1, p0_src); + temp2 = __lsx_vclip_h(temp2, tc_neg, tc_pos); + dst2 = __lsx_vadd_h(temp2, p0_src); + + p_is_pcm_vec = __lsx_vnor_v(p_is_pcm_vec, p_is_pcm_vec); + DUP2_ARG3(__lsx_vbitsel_v, dst0, p2_src, p_is_pcm_vec, dst1, + p1_src, p_is_pcm_vec, dst0, dst1); + dst2 = __lsx_vbitsel_v(dst2, p0_src, p_is_pcm_vec); + + /* q part */ + DUP2_ARG2(__lsx_vadd_h, q1_src, p0_src, temp0, q0_src, + temp0, temp0); + temp1 = __lsx_vadd_h(q3_src, q2_src); + temp1 = __lsx_vslli_h(temp1, 1); + DUP2_ARG2(__lsx_vadd_h, temp1, q2_src, temp1, temp0, temp1, temp1); + temp1 = __lsx_vsrari_h(temp1, 3); + temp2 = __lsx_vsub_h(temp1, q2_src); + temp2 = __lsx_vclip_h(temp2, tc_neg, tc_pos); + dst5 = __lsx_vadd_h(temp2, q2_src); + + temp1 = __lsx_vadd_h(temp0, q2_src); + temp1 = __lsx_vsrari_h(temp1, 2); + temp2 = __lsx_vsub_h(temp1, q1_src); + temp2 = __lsx_vclip_h(temp2, tc_neg, tc_pos); + dst4 = __lsx_vadd_h(temp2, q1_src); + + temp0 = __lsx_vslli_h(temp0, 1); + DUP2_ARG2(__lsx_vadd_h, temp0, p1_src, temp1, q2_src, + temp1, temp1); + temp1 = __lsx_vsrari_h(temp1, 3); + temp2 = __lsx_vsub_h(temp1, q0_src); + temp2 = __lsx_vclip_h(temp2, tc_neg, tc_pos); + dst3 = __lsx_vadd_h(temp2, q0_src); + + q_is_pcm_vec = __lsx_vnor_v(q_is_pcm_vec, q_is_pcm_vec); + DUP2_ARG3(__lsx_vbitsel_v, dst3, q0_src, q_is_pcm_vec, dst4, + q1_src, q_is_pcm_vec, dst3, dst4); + dst5 = __lsx_vbitsel_v(dst5, q2_src, q_is_pcm_vec); + + /* pack results to 8 bit */ + DUP2_ARG2(__lsx_vpickev_b, dst1, dst0, dst3, dst2, dst0, dst1); + dst2 = __lsx_vpickev_b(dst5, dst4); + + /* pack src to 8 bit */ + DUP2_ARG2(__lsx_vpickev_b, p1_src, p2_src, q0_src, p0_src, + dst3, dst4); + dst5 = __lsx_vpickev_b(q2_src, q1_src); + + cmp3 = __lsx_vnor_v(cmp3, cmp3); + DUP2_ARG3(__lsx_vbitsel_v, dst0, dst3, cmp3, dst1, dst4, cmp3, + dst0, dst1); + dst2 = __lsx_vbitsel_v(dst2, dst5, cmp3); + + __lsx_vstelm_d(dst0, p2, 0, 0); + __lsx_vstelm_d(dst0, p2 + stride, 0, 1); + __lsx_vstelm_d(dst1, p2 + stride_2x, 0, 0); + __lsx_vstelm_d(dst1, p2 + stride_3x, 0, 1); + __lsx_vstelm_d(dst2, p2 + stride_4x, 0, 0); + __lsx_vstelm_d(dst2, p2 + stride_4x + stride, 0, 1); + /* strong filter ends */ + } else if (flag0 == flag1) { /* weak only */ + /* weak filter */ + tc_neg = __lsx_vneg_h(tc_pos); + DUP2_ARG2(__lsx_vsub_h, q0_src, p0_src, q1_src, p1_src, + diff0, diff1); + DUP2_ARG2(__lsx_vadd_h, __lsx_vslli_h(diff0, 3), diff0, + __lsx_vslli_h(diff1, 1), diff1, diff0, diff1); + delta0 = __lsx_vsub_h(diff0, diff1); + delta0 = __lsx_vsrari_h(delta0, 4); + temp1 = __lsx_vadd_h(__lsx_vslli_h(tc_pos, 3), + __lsx_vslli_h(tc_pos, 1)); + abs_delta0 = __lsx_vadda_h(delta0, zero); + abs_delta0 = __lsx_vsle_hu(temp1, abs_delta0); + abs_delta0 = __lsx_vnor_v(abs_delta0, abs_delta0); + + delta0 = __lsx_vclip_h(delta0, tc_neg, tc_pos); + temp2 = __lsx_vadd_h(delta0, p0_src); + temp2 = __lsx_vclip255_h(temp2); + temp0 = __lsx_vbitsel_v(temp2, p0_src, + __lsx_vnor_v(p_is_pcm_vec, p_is_pcm_vec)); + temp2 = __lsx_vsub_h(q0_src, delta0); + temp2 = __lsx_vclip255_h(temp2); + temp2 = __lsx_vbitsel_v(temp2, q0_src, __lsx_vnor_v(q_is_pcm_vec, + q_is_pcm_vec)); + DUP2_ARG2(__lsx_vnor_v, p_is_pcm_vec, p_is_pcm_vec, q_is_pcm_vec, + q_is_pcm_vec, p_is_pcm_vec, q_is_pcm_vec); + + tmp = (beta + (beta >> 1)) >> 3; + DUP2_ARG1(__lsx_vreplgr2vr_d, dp00 + dp30 < tmp, dp04 + dp34 < tmp, + cmp0, cmp1); + cmp0 = __lsx_vpackev_d(cmp1, cmp0); + cmp0 = __lsx_vseqi_d(cmp0, 0); + p_is_pcm_vec = __lsx_vor_v(p_is_pcm_vec, cmp0); + + DUP2_ARG1(__lsx_vreplgr2vr_d, dq00 + dq30 < tmp, dq04 + dq34 < tmp, + cmp0, cmp1); + cmp0 = __lsx_vpackev_d(cmp1, cmp0); + cmp0 = __lsx_vseqi_d(cmp0, 0); + q_is_pcm_vec = __lsx_vor_v(q_is_pcm_vec, cmp0); + tc_pos = __lsx_vsrai_h(tc_pos, 1); + tc_neg = __lsx_vneg_h(tc_pos); + + DUP2_ARG2(__lsx_vavgr_hu, p2_src, p0_src, q0_src, q2_src, + delta1, delta2); + DUP2_ARG2(__lsx_vsub_h, delta1, p1_src, delta2, q1_src, + delta1, delta2); + delta1 = __lsx_vadd_h(delta1, delta0); + delta2 = __lsx_vsub_h(delta2, delta0); + DUP2_ARG2(__lsx_vsrai_h, delta1, 1, delta2, 1, delta1, delta2); + DUP2_ARG3(__lsx_vclip_h, delta1, tc_neg, tc_pos, delta2, + tc_neg, tc_pos, delta1, delta2); + DUP2_ARG2(__lsx_vadd_h, p1_src, delta1, q1_src, delta2, + delta1, delta2); + DUP2_ARG1(__lsx_vclip255_h, delta1, delta2, delta1, delta2); + DUP2_ARG3(__lsx_vbitsel_v, delta1, p1_src, p_is_pcm_vec, delta2, + q1_src, q_is_pcm_vec, delta1, delta2); + + abs_delta0 = __lsx_vnor_v(abs_delta0, abs_delta0); + DUP4_ARG3(__lsx_vbitsel_v, delta1, p1_src, abs_delta0, temp0, + p0_src, abs_delta0, temp2, q0_src, abs_delta0, delta2, + q1_src, abs_delta0, dst1, dst2, dst3, dst4); + /* pack results to 8 bit */ + DUP2_ARG2(__lsx_vpickev_b, dst2, dst1, dst4, dst3, dst0, dst1); + /* pack src to 8 bit */ + DUP2_ARG2(__lsx_vpickev_b, p0_src, p1_src, q1_src, q0_src, + dst2, dst3); + cmp3 = __lsx_vnor_v(cmp3, cmp3); + DUP2_ARG3(__lsx_vbitsel_v, dst0, dst2, cmp3, dst1, dst3, cmp3, + dst0, dst1); + + p2 += stride; + __lsx_vstelm_d(dst0, p2, 0, 0); + __lsx_vstelm_d(dst0, p2 + stride, 0, 1); + __lsx_vstelm_d(dst1, p2 + stride_2x, 0, 0); + __lsx_vstelm_d(dst1, p2 + stride_3x, 0, 1); + /* weak filter ends */ + } else { /* strong + weak */ + /* strong filter */ + tc_pos = __lsx_vslli_h(tc_pos, 1); + tc_neg = __lsx_vneg_h(tc_pos); + + /* p part */ + DUP2_ARG2(__lsx_vadd_h, p1_src, p0_src, temp0, q0_src, + temp0, temp0); + temp1 = __lsx_vadd_h(p3_src, p2_src); + temp1 = __lsx_vslli_h(temp1, 1); + DUP2_ARG2(__lsx_vadd_h, temp1, p2_src, temp1, temp0, temp1, temp1); + temp1 = __lsx_vsrari_h(temp1, 3); + temp2 = __lsx_vsub_h(temp1, p2_src); + temp2 = __lsx_vclip_h(temp2, tc_neg, tc_pos); + dst0 = __lsx_vadd_h(temp2, p2_src); + + temp1 = __lsx_vadd_h(temp0, p2_src); + temp1 = __lsx_vsrari_h(temp1, 2); + temp2 = __lsx_vsub_h(temp1, p1_src); + temp2 = __lsx_vclip_h(temp2, tc_neg, tc_pos); + dst1 = __lsx_vadd_h(temp2, p1_src); + + temp1 = __lsx_vslli_h(temp0, 1); + DUP2_ARG2(__lsx_vadd_h, temp1, p2_src, temp1, q1_src, temp1, temp1); + temp1 = __lsx_vsrari_h(temp1, 3); + temp2 = __lsx_vsub_h(temp1, p0_src); + temp2 = __lsx_vclip_h(temp2, tc_neg, tc_pos); + dst2 = __lsx_vadd_h(temp2, p0_src); + + p_is_pcm_vec = __lsx_vnor_v(p_is_pcm_vec, p_is_pcm_vec); + DUP2_ARG3(__lsx_vbitsel_v, dst0, p2_src, p_is_pcm_vec, dst1, + p1_src, p_is_pcm_vec, dst0, dst1); + dst2 = __lsx_vbitsel_v(dst2, p0_src, p_is_pcm_vec); + + /* q part */ + DUP2_ARG2(__lsx_vadd_h, q1_src, p0_src, temp0, q0_src, + temp0, temp0); + temp1 = __lsx_vadd_h(q3_src, q2_src); + temp1 = __lsx_vslli_h(temp1, 1); + DUP2_ARG2(__lsx_vadd_h, temp1, q2_src, temp1, temp0, temp1, temp1); + temp1 = __lsx_vsrari_h(temp1, 3); + temp2 = __lsx_vsub_h(temp1, q2_src); + temp2 = __lsx_vclip_h(temp2, tc_neg, tc_pos); + dst5 = __lsx_vadd_h(temp2, q2_src); + + temp1 = __lsx_vadd_h(temp0, q2_src); + temp1 = __lsx_vsrari_h(temp1, 2); + temp2 = __lsx_vsub_h(temp1, q1_src); + temp2 = __lsx_vclip_h(temp2, tc_neg, tc_pos); + dst4 = __lsx_vadd_h(temp2, q1_src); + + temp1 = __lsx_vslli_h(temp0, 1); + DUP2_ARG2(__lsx_vadd_h, temp1, p1_src, temp1, q2_src, temp1, temp1); + temp1 = __lsx_vsrari_h(temp1, 3); + temp2 = __lsx_vsub_h(temp1, q0_src); + temp2 = __lsx_vclip_h(temp2, tc_neg, tc_pos); + dst3 = __lsx_vadd_h(temp2, q0_src); + + q_is_pcm_vec = __lsx_vnor_v(q_is_pcm_vec, q_is_pcm_vec); + DUP2_ARG3(__lsx_vbitsel_v, dst3, q0_src, q_is_pcm_vec, dst4, + q1_src, q_is_pcm_vec, dst3, dst4); + dst5 = __lsx_vbitsel_v(dst5, q2_src, q_is_pcm_vec); + + /* pack strong results to 8 bit */ + DUP2_ARG2(__lsx_vpickev_b, dst1, dst0, dst3, dst2, dst0, dst1); + dst2 = __lsx_vpickev_b(dst5, dst4); + /* strong filter ends */ + + /* weak filter */ + tc_pos = __lsx_vsrai_h(tc_pos, 1); + tc_neg = __lsx_vneg_h(tc_pos); + + DUP2_ARG2(__lsx_vsub_h, q0_src, p0_src, q1_src, p1_src, + diff0, diff1); + DUP2_ARG2(__lsx_vadd_h, __lsx_vslli_h(diff0, 3), diff0, + __lsx_vslli_h(diff1, 1), diff1, diff0, diff1); + delta0 = __lsx_vsub_h(diff0, diff1); + delta0 = __lsx_vsrari_h(delta0, 4); + temp1 = __lsx_vadd_h(__lsx_vslli_h(tc_pos, 3), + __lsx_vslli_h(tc_pos, 1)); + abs_delta0 = __lsx_vadda_h(delta0, zero); + abs_delta0 = __lsx_vsle_hu(temp1, abs_delta0); + abs_delta0 = __lsx_vnor_v(abs_delta0, abs_delta0); + + delta0 = __lsx_vclip_h(delta0, tc_neg, tc_pos); + temp2 = __lsx_vadd_h(delta0, p0_src); + temp2 = __lsx_vclip255_h(temp2); + temp0 = __lsx_vbitsel_v(temp2, p0_src, p_is_pcm_vec); + + temp2 = __lsx_vsub_h(q0_src, delta0); + temp2 = __lsx_vclip255_h(temp2); + temp2 = __lsx_vbitsel_v(temp2, q0_src, q_is_pcm_vec); + + tmp = (beta + (beta >> 1)) >> 3; + DUP2_ARG1(__lsx_vreplgr2vr_d, dp00 + dp30 < tmp, dp04 + dp34 < tmp, + cmp0, cmp1); + cmp0 = __lsx_vpackev_d(cmp1, cmp0); + p_is_pcm_vec = __lsx_vor_v(p_is_pcm_vec, __lsx_vseqi_d(cmp0, 0)); + DUP2_ARG1(__lsx_vreplgr2vr_d, dq00 + dq30 < tmp, dq04 + dq34 < tmp, + cmp0, cmp1); + cmp0 = __lsx_vpackev_d(cmp1, cmp0); + q_is_pcm_vec = __lsx_vor_v(q_is_pcm_vec, __lsx_vseqi_d(cmp0, 0)); + + tc_pos = __lsx_vsrai_h(tc_pos, 1); + tc_neg = __lsx_vneg_h(tc_pos); + + DUP2_ARG2(__lsx_vavgr_hu, p2_src, p0_src, q0_src, q2_src, + delta1, delta2); + DUP2_ARG2(__lsx_vsub_h, delta1, p1_src, delta2, q1_src, + delta1, delta2); + delta1 = __lsx_vadd_h(delta1, delta0); + delta2 = __lsx_vsub_h(delta2, delta0); + DUP2_ARG2(__lsx_vsrai_h, delta1, 1, delta2, 1, delta1, delta2); + DUP2_ARG3(__lsx_vclip_h, delta1, tc_neg, tc_pos, delta2, tc_neg, + tc_pos, delta1, delta2); + DUP2_ARG2(__lsx_vadd_h, p1_src, delta1, q1_src, delta2, + delta1, delta2); + DUP2_ARG1(__lsx_vclip255_h, delta1, delta2, delta1, delta2); + DUP2_ARG3(__lsx_vbitsel_v, delta1, p1_src, p_is_pcm_vec, delta2, + q1_src, q_is_pcm_vec, delta1, delta2); + abs_delta0 = __lsx_vnor_v(abs_delta0, abs_delta0); + DUP4_ARG3(__lsx_vbitsel_v, delta1, p1_src, abs_delta0, delta2, + q1_src, abs_delta0, temp0, p0_src, abs_delta0, temp2, + q0_src, abs_delta0, delta1, delta2, temp0, temp2); + /* weak filter ends */ + + /* pack weak results to 8 bit */ + DUP2_ARG2(__lsx_vpickev_b, delta1, p2_src, temp2, temp0, + dst3, dst4); + dst5 = __lsx_vpickev_b(q2_src, delta2); + + /* select between weak or strong */ + DUP2_ARG3(__lsx_vbitsel_v, dst0, dst3, cmp2, dst1, dst4, cmp2, + dst0, dst1); + dst2 = __lsx_vbitsel_v(dst2, dst5, cmp2); + + /* pack src to 8 bit */ + DUP2_ARG2(__lsx_vpickev_b, p1_src, p2_src, q0_src, p0_src, + dst3, dst4); + dst5 = __lsx_vpickev_b(q2_src, q1_src); + + cmp3 = __lsx_vnor_v(cmp3, cmp3); + DUP2_ARG3(__lsx_vbitsel_v, dst0, dst3, cmp3, dst1, dst4, cmp3, + dst0, dst1); + dst2 = __lsx_vbitsel_v(dst2, dst5, cmp3); + + __lsx_vstelm_d(dst0, p2, 0, 0); + __lsx_vstelm_d(dst0, p2 + stride, 0, 1); + __lsx_vstelm_d(dst1, p2 + stride_2x, 0, 0); + __lsx_vstelm_d(dst1, p2 + stride_3x, 0, 1); + __lsx_vstelm_d(dst2, p2 + stride_4x, 0, 0); + __lsx_vstelm_d(dst2, p2 + stride_4x + stride, 0, 1); + } + } +} + +void ff_hevc_loop_filter_luma_v_8_lsx(uint8_t *src, ptrdiff_t stride, + int32_t beta, int32_t *tc, + uint8_t *p_is_pcm, uint8_t *q_is_pcm) +{ + ptrdiff_t stride_2x = (stride << 1); + ptrdiff_t stride_4x = (stride << 2); + ptrdiff_t stride_3x = stride_2x + stride; + uint8_t *p3 = src; + uint8_t *p2 = src + stride_3x; + uint8_t *p1 = src + stride_4x; + uint8_t *p0 = src + stride_4x + stride_3x; + uint8_t flag0, flag1; + int32_t dp00, dq00, dp30, dq30, d00, d30; + int32_t d0030, d0434; + int32_t dp04, dq04, dp34, dq34, d04, d34; + int32_t tc0, p_is_pcm0, q_is_pcm0, beta30, beta20, tc250; + int32_t tc4, p_is_pcm4, q_is_pcm4, tc254, tmp; + + __m128i dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + __m128i cmp0, cmp1, cmp2, p_is_pcm_vec, q_is_pcm_vec; + __m128i cmp3; + __m128i temp0, temp1; + __m128i temp2; + __m128i tc_pos, tc_neg; + __m128i diff0, diff1, delta0, delta1, delta2, abs_delta0; + __m128i zero = {0}; + __m128i p3_src, p2_src, p1_src, p0_src, q0_src, q1_src, q2_src, q3_src; + + dp00 = abs(p3[-3] - (p3[-2] << 1) + p3[-1]); + dq00 = abs(p3[2] - (p3[1] << 1) + p3[0]); + dp30 = abs(p2[-3] - (p2[-2] << 1) + p2[-1]); + dq30 = abs(p2[2] - (p2[1] << 1) + p2[0]); + d00 = dp00 + dq00; + d30 = dp30 + dq30; + p_is_pcm0 = p_is_pcm[0]; + q_is_pcm0 = q_is_pcm[0]; + + dp04 = abs(p1[-3] - (p1[-2] << 1) + p1[-1]); + dq04 = abs(p1[2] - (p1[1] << 1) + p1[0]); + dp34 = abs(p0[-3] - (p0[-2] << 1) + p0[-1]); + dq34 = abs(p0[2] - (p0[1] << 1) + p0[0]); + d04 = dp04 + dq04; + d34 = dp34 + dq34; + p_is_pcm4 = p_is_pcm[1]; + q_is_pcm4 = q_is_pcm[1]; + + DUP2_ARG1(__lsx_vreplgr2vr_d, p_is_pcm0, p_is_pcm4, cmp0, cmp1); + p_is_pcm_vec = __lsx_vpackev_d(cmp1, cmp0); + p_is_pcm_vec = __lsx_vseqi_d(p_is_pcm_vec, 0); + + d0030 = (d00 + d30) >= beta; + d0434 = (d04 + d34) >= beta; + + DUP2_ARG1(__lsx_vreplgr2vr_d, d0030, d0434, cmp0, cmp1); + cmp3 = __lsx_vpackev_d(cmp1, cmp0); + cmp3 = __lsx_vseqi_d(cmp3, 0); + + if ((!p_is_pcm0 || !p_is_pcm4 || !q_is_pcm0 || !q_is_pcm4) && + (!d0030 || !d0434)) { + src -= 4; + DUP4_ARG2(__lsx_vld, src, 0, src + stride, 0, src + stride_2x, 0, + src + stride_3x, 0, p3_src, p2_src, p1_src, p0_src); + src += stride_4x; + DUP4_ARG2(__lsx_vld, src, 0, src + stride, 0, src + stride_2x, 0, + src + stride_3x, 0, q0_src, q1_src, q2_src, q3_src); + src -= stride_4x; + + DUP2_ARG1(__lsx_vreplgr2vr_d, q_is_pcm0, q_is_pcm4, cmp0, cmp1); + q_is_pcm_vec = __lsx_vpackev_d(cmp1, cmp0); + q_is_pcm_vec = __lsx_vseqi_d(q_is_pcm_vec, 0); + + tc0 = tc[0]; + beta30 = beta >> 3; + beta20 = beta >> 2; + tc250 = (((tc0 << 2) + tc0 + 1) >> 1); + tc4 = tc[1]; + tc254 = (((tc4 << 2) + tc4 + 1) >> 1); + DUP2_ARG1( __lsx_vreplgr2vr_h, tc0 << 1, tc4 << 1, cmp0, cmp1); + tc_pos = __lsx_vpackev_d(cmp1, cmp0); + LSX_TRANSPOSE8x8_B(p3_src, p2_src, p1_src, p0_src, q0_src, q1_src, + q2_src, q3_src, p3_src, p2_src, p1_src, p0_src, + q0_src, q1_src, q2_src, q3_src); + + flag0 = abs(p3[-4] - p3[-1]) + abs(p3[3] - p3[0]) < beta30 && + abs(p3[-1] - p3[0]) < tc250; + flag0 = flag0 && (abs(p2[-4] - p2[-1]) + abs(p2[3] - p2[0]) < beta30 && + abs(p2[-1] - p2[0]) < tc250 && (d00 << 1) < beta20 && + (d30 << 1) < beta20); + cmp0 = __lsx_vreplgr2vr_d(flag0); + DUP4_ARG2(__lsx_vilvl_b, zero, p3_src, zero, p2_src, zero, p1_src, zero, + p0_src, p3_src, p2_src, p1_src, p0_src); + + flag1 = abs(p1[-4] - p1[-1]) + abs(p1[3] - p1[0]) < beta30 && + abs(p1[-1] - p1[0]) < tc254; + flag1 = flag1 && (abs(p0[-4] - p0[-1]) + abs(p0[3] - p0[0]) < beta30 && + abs(p0[-1] - p0[0]) < tc254 && (d04 << 1) < beta20 && + (d34 << 1) < beta20); + DUP4_ARG2(__lsx_vilvl_b, zero, q0_src, zero, q1_src, zero, q2_src, zero, + q3_src, q0_src, q1_src, q2_src, q3_src); + + cmp1 = __lsx_vreplgr2vr_d(flag1); + cmp2 = __lsx_vpackev_d(cmp1, cmp0); + cmp2 = __lsx_vseqi_d(cmp2, 0); + + if (flag0 && flag1) { /* strong only */ + /* strong filter */ + tc_neg = __lsx_vneg_h(tc_pos); + /* p part */ + DUP2_ARG2(__lsx_vadd_h, p1_src, p0_src, temp0, q0_src, + temp0, temp0); + temp1 = __lsx_vadd_h(p3_src, p2_src); + temp1 = __lsx_vslli_h(temp1, 1); + DUP2_ARG2(__lsx_vadd_h, temp1, p2_src, temp1, temp0, temp1, temp1); + temp1 = __lsx_vsrari_h(temp1, 3); + temp2 = __lsx_vsub_h(temp1, p2_src); + temp2 = __lsx_vclip_h(temp2, tc_neg, tc_pos); + dst0 = __lsx_vadd_h(temp2, p2_src); + + temp1 = __lsx_vadd_h(temp0, p2_src); + temp1 = __lsx_vsrari_h(temp1, 2); + temp2 = __lsx_vsub_h(temp1, p1_src); + temp2 = __lsx_vclip_h(temp2, tc_neg, tc_pos); + dst1 = __lsx_vadd_h(temp2, p1_src); + + temp1 = __lsx_vslli_h(temp0, 1); + DUP2_ARG2(__lsx_vadd_h, temp1, p2_src, temp1, q1_src, temp1, temp1); + temp1 = __lsx_vsrari_h(temp1, 3); + temp2 = __lsx_vsub_h(temp1, p0_src); + temp2 = __lsx_vclip_h(temp2, tc_neg, tc_pos); + dst2 = __lsx_vadd_h(temp2, p0_src); + + p_is_pcm_vec = __lsx_vnor_v(p_is_pcm_vec, p_is_pcm_vec); + DUP2_ARG3(__lsx_vbitsel_v, dst0, p2_src, p_is_pcm_vec, dst1, p1_src, + p_is_pcm_vec, dst0, dst1); + dst2 = __lsx_vbitsel_v(dst2, p0_src, p_is_pcm_vec); + + /* q part */ + DUP2_ARG2(__lsx_vadd_h, q1_src, p0_src, temp0, q0_src, + temp0, temp0); + temp1 = __lsx_vadd_h(q3_src, q2_src); + temp1 = __lsx_vslli_h(temp1, 1); + DUP2_ARG2(__lsx_vadd_h, temp1, q2_src, temp1, temp0, temp1, temp1); + temp1 = __lsx_vsrari_h(temp1, 3); + temp2 = __lsx_vsub_h(temp1, q2_src); + temp2 = __lsx_vclip_h(temp2, tc_neg, tc_pos); + dst5 = __lsx_vadd_h(temp2, q2_src); + + temp1 = __lsx_vadd_h(temp0, q2_src); + temp1 = __lsx_vsrari_h(temp1, 2); + temp2 = __lsx_vsub_h(temp1, q1_src); + temp2 = __lsx_vclip_h(temp2, tc_neg, tc_pos); + dst4 = __lsx_vadd_h(temp2, q1_src); + + temp1 = __lsx_vslli_h(temp0, 1); + DUP2_ARG2(__lsx_vadd_h, temp1, p1_src, temp1, q2_src, temp1, temp1); + temp1 = __lsx_vsrari_h(temp1, 3); + temp2 = __lsx_vsub_h(temp1, q0_src); + temp2 = __lsx_vclip_h(temp2, tc_neg, tc_pos); + dst3 = __lsx_vadd_h(temp2, q0_src); + + q_is_pcm_vec = __lsx_vnor_v(q_is_pcm_vec, q_is_pcm_vec); + DUP2_ARG3(__lsx_vbitsel_v, dst3, q0_src, q_is_pcm_vec, dst4, q1_src, + q_is_pcm_vec, dst3, dst4); + dst5 = __lsx_vbitsel_v(dst5, q2_src, q_is_pcm_vec); + /* strong filter ends */ + } else if (flag0 == flag1) { /* weak only */ + /* weak filter */ + tc_pos = __lsx_vsrai_h(tc_pos, 1); + tc_neg = __lsx_vneg_h(tc_pos); + + DUP2_ARG2(__lsx_vsub_h, q0_src, p0_src, q1_src, p1_src, + diff0, diff1); + DUP2_ARG2(__lsx_vadd_h, __lsx_vslli_h(diff0, 3), diff0, + __lsx_vslli_h(diff1, 1), diff1, diff0, diff1); + delta0 = __lsx_vsub_h(diff0, diff1); + delta0 = __lsx_vsrari_h(delta0, 4); + temp1 = __lsx_vadd_h(__lsx_vslli_h(tc_pos, 3), + __lsx_vslli_h(tc_pos, 1)); + abs_delta0 = __lsx_vadda_h(delta0, zero); + abs_delta0 = __lsx_vsle_hu(temp1, abs_delta0); + abs_delta0 = __lsx_vnor_v(abs_delta0, abs_delta0); + + delta0 = __lsx_vclip_h(delta0, tc_neg, tc_pos); + temp2 = __lsx_vadd_h(delta0, p0_src); + temp2 = __lsx_vclip255_h(temp2); + p_is_pcm_vec = __lsx_vnor_v(p_is_pcm_vec, p_is_pcm_vec); + temp0 = __lsx_vbitsel_v(temp2, p0_src, p_is_pcm_vec); + + temp2 = __lsx_vsub_h(q0_src, delta0); + temp2 = __lsx_vclip255_h(temp2); + q_is_pcm_vec = __lsx_vnor_v(q_is_pcm_vec, q_is_pcm_vec); + temp2 = __lsx_vbitsel_v(temp2, q0_src, q_is_pcm_vec); + + tmp = ((beta + (beta >> 1)) >> 3); + DUP2_ARG1(__lsx_vreplgr2vr_d, !p_is_pcm0 && ((dp00 + dp30) < tmp), + !p_is_pcm4 && ((dp04 + dp34) < tmp), cmp0, cmp1); + p_is_pcm_vec = __lsx_vpackev_d(cmp1, cmp0); + p_is_pcm_vec = __lsx_vseqi_d(p_is_pcm_vec, 0); + + DUP2_ARG1(__lsx_vreplgr2vr_h, (!q_is_pcm0) && (dq00 + dq30 < tmp), + (!q_is_pcm4) && (dq04 + dq34 < tmp), cmp0, cmp1); + q_is_pcm_vec = __lsx_vpackev_d(cmp1, cmp0); + q_is_pcm_vec = __lsx_vseqi_d(q_is_pcm_vec, 0); + tc_pos = __lsx_vsrai_h(tc_pos, 1); + tc_neg = __lsx_vneg_h(tc_pos); + + DUP2_ARG2(__lsx_vavgr_hu, p2_src, p0_src, q0_src, q2_src, + delta1, delta2); + DUP2_ARG2(__lsx_vsub_h, delta1, p1_src, delta2, q1_src, + delta1, delta2); + delta1 = __lsx_vadd_h(delta1, delta0); + delta2 = __lsx_vsub_h(delta2, delta0); + DUP2_ARG2(__lsx_vsrai_h, delta1, 1, delta2, 1, delta1, delta2); + DUP2_ARG3(__lsx_vclip_h, delta1, tc_neg, tc_pos, delta2, tc_neg, + tc_pos, delta1, delta2); + DUP2_ARG2(__lsx_vadd_h, p1_src, delta1, q1_src, delta2, + delta1, delta2); + DUP2_ARG1(__lsx_vclip255_h, delta1, delta2, delta1, delta2); + DUP2_ARG3(__lsx_vbitsel_v, delta1, p1_src, p_is_pcm_vec, delta2, + q1_src, q_is_pcm_vec, delta1, delta2); + + abs_delta0 = __lsx_vnor_v(abs_delta0, abs_delta0); + DUP4_ARG3(__lsx_vbitsel_v, delta1, p1_src, abs_delta0, temp0, + p0_src, abs_delta0, temp2, q0_src, abs_delta0, delta2, + q1_src, abs_delta0, dst0, dst1, dst2, dst3); + /* weak filter ends */ + + cmp3 = __lsx_vnor_v(cmp3, cmp3); + DUP4_ARG3(__lsx_vbitsel_v, dst0, p1_src, cmp3, dst1, p0_src, + cmp3, dst2, q0_src, cmp3, dst3, q1_src, cmp3, + dst0, dst1, dst2, dst3); + DUP2_ARG2(__lsx_vpickev_b, dst2, dst0, dst3, dst1, dst0, dst1); + + /* transpose */ + dst4 = __lsx_vilvl_b(dst1, dst0); + dst5 = __lsx_vilvh_b(dst1, dst0); + dst0 = __lsx_vilvl_h(dst5, dst4); + dst1 = __lsx_vilvh_h(dst5, dst4); + + src += 2; + __lsx_vstelm_w(dst0, src, 0, 0); + __lsx_vstelm_w(dst0, src + stride, 0, 1); + __lsx_vstelm_w(dst0, src + stride_2x, 0, 2); + __lsx_vstelm_w(dst0, src + stride_3x, 0, 3); + src += stride_4x; + __lsx_vstelm_w(dst1, src, 0, 0); + __lsx_vstelm_w(dst1, src + stride, 0, 1); + __lsx_vstelm_w(dst1, src + stride_2x, 0, 2); + __lsx_vstelm_w(dst1, src + stride_3x, 0, 3); + return; + } else { /* strong + weak */ + /* strong filter */ + tc_neg = __lsx_vneg_h(tc_pos); + + /* p part */ + DUP2_ARG2(__lsx_vadd_h, p1_src, p0_src, temp0, q0_src, + temp0, temp0); + + temp1 = __lsx_vadd_h(p3_src, p2_src); + temp1 = __lsx_vslli_h(temp1, 1); + DUP2_ARG2(__lsx_vadd_h, temp1, p2_src, temp1, temp0, temp1, temp1); + temp1 = __lsx_vsrari_h(temp1, 3); + temp2 = __lsx_vsub_h(temp1, p2_src); + temp2 = __lsx_vclip_h(temp2, tc_neg, tc_pos); + dst0 = __lsx_vadd_h(temp2, p2_src); + + temp1 = __lsx_vadd_h(temp0, p2_src); + temp1 = __lsx_vsrari_h(temp1, 2); + temp2 = __lsx_vsub_h(temp1, p1_src); + temp2 = __lsx_vclip_h(temp2, tc_neg, tc_pos); + dst1 = __lsx_vadd_h(temp2, p1_src); + + temp1 = __lsx_vslli_h(temp0, 1); + DUP2_ARG2(__lsx_vadd_h, temp1, p2_src, temp1, q1_src, temp1, temp1); + temp1 = __lsx_vsrari_h(temp1, 3); + temp2 = __lsx_vsub_h(temp1, p0_src); + temp2 = __lsx_vclip_h(temp2, tc_neg, tc_pos); + dst2 = __lsx_vadd_h(temp2, p0_src); + + p_is_pcm_vec = __lsx_vnor_v(p_is_pcm_vec, p_is_pcm_vec); + DUP2_ARG3(__lsx_vbitsel_v, dst0, p2_src, p_is_pcm_vec, dst1, p1_src, + p_is_pcm_vec, dst0, dst1); + dst2 = __lsx_vbitsel_v(dst2, p0_src, p_is_pcm_vec); + + /* q part */ + DUP2_ARG2(__lsx_vadd_h, q1_src, p0_src, temp0, q0_src, temp0, temp0); + temp1 = __lsx_vadd_h(q3_src, q2_src); + temp1 = __lsx_vslli_h(temp1, 1); + DUP2_ARG2(__lsx_vadd_h, temp1, q2_src, temp1, temp0, temp1, temp1); + temp1 = __lsx_vsrari_h(temp1, 3); + temp2 = __lsx_vsub_h(temp1, q2_src); + temp2 = __lsx_vclip_h(temp2, tc_neg, tc_pos); + dst5 = __lsx_vadd_h(temp2, q2_src); + + temp1 = __lsx_vadd_h(temp0, q2_src); + temp1 = __lsx_vsrari_h(temp1, 2); + temp2 = __lsx_vsub_h(temp1, q1_src); + temp2 = __lsx_vclip_h(temp2, tc_neg, tc_pos); + dst4 = __lsx_vadd_h(temp2, q1_src); + + temp1 = __lsx_vslli_h(temp0, 1); + DUP2_ARG2(__lsx_vadd_h, temp1, p1_src, temp1, q2_src, temp1, temp1); + temp1 = __lsx_vsrari_h(temp1, 3); + temp2 = __lsx_vsub_h(temp1, q0_src); + temp2 = __lsx_vclip_h(temp2, tc_neg, tc_pos); + dst3 = __lsx_vadd_h(temp2, q0_src); + + q_is_pcm_vec = __lsx_vnor_v(q_is_pcm_vec, q_is_pcm_vec); + DUP2_ARG3(__lsx_vbitsel_v, dst3, q0_src, q_is_pcm_vec, dst4, q1_src, + q_is_pcm_vec, dst3, dst4); + dst5 = __lsx_vbitsel_v(dst5, q2_src, q_is_pcm_vec); + /* strong filter ends */ + + /* weak filter */ + tc_pos = __lsx_vsrai_h(tc_pos, 1); + tc_neg = __lsx_vneg_h(tc_pos); + + DUP2_ARG2(__lsx_vsub_h, q0_src, p0_src, q1_src, p1_src, + diff0, diff1); + DUP2_ARG2(__lsx_vadd_h, __lsx_vslli_h(diff0, 3), diff0, + __lsx_vslli_h(diff1, 1), diff1, diff0, diff1); + delta0 = __lsx_vsub_h(diff0, diff1); + delta0 = __lsx_vsrari_h(delta0, 4); + + temp1 = __lsx_vadd_h(__lsx_vslli_h(tc_pos, 3), + __lsx_vslli_h(tc_pos, 1)); + abs_delta0 = __lsx_vadda_h(delta0, zero); + abs_delta0 = __lsx_vsle_hu(temp1, abs_delta0); + abs_delta0 = __lsx_vnor_v(abs_delta0, abs_delta0); + delta0 = __lsx_vclip_h(delta0, tc_neg, tc_pos); + temp2 = __lsx_vadd_h(delta0, p0_src); + temp2 = __lsx_vclip255_h(temp2); + temp0 = __lsx_vbitsel_v(temp2, p0_src, p_is_pcm_vec); + temp2 = __lsx_vsub_h(q0_src, delta0); + temp2 = __lsx_vclip255_h(temp2); + temp2 = __lsx_vbitsel_v(temp2, q0_src, q_is_pcm_vec); + + tmp = (beta + (beta >> 1)) >> 3; + DUP2_ARG1(__lsx_vreplgr2vr_d, !p_is_pcm0 && ((dp00 + dp30) < tmp), + !p_is_pcm4 && ((dp04 + dp34) < tmp), cmp0, cmp1); + p_is_pcm_vec = __lsx_vpackev_d(cmp1, cmp0); + p_is_pcm_vec = __lsx_vseqi_d(p_is_pcm_vec, 0); + + DUP2_ARG1(__lsx_vreplgr2vr_h, (!q_is_pcm0) && (dq00 + dq30 < tmp), + (!q_is_pcm4) && (dq04 + dq34 < tmp), cmp0, cmp1); + q_is_pcm_vec = __lsx_vpackev_d(cmp1, cmp0); + q_is_pcm_vec = __lsx_vseqi_d(q_is_pcm_vec, 0); + tc_pos = __lsx_vsrai_h(tc_pos, 1); + tc_neg = __lsx_vneg_h(tc_pos); + + DUP2_ARG2(__lsx_vavgr_hu, p2_src, p0_src, q0_src, q2_src, + delta1, delta2); + DUP2_ARG2(__lsx_vsub_h, delta1, p1_src, delta2, q1_src, + delta1, delta2); + delta1 = __lsx_vadd_h(delta1, delta0); + delta2 = __lsx_vsub_h(delta2, delta0); + DUP2_ARG2(__lsx_vsrai_h, delta1, 1, delta2, 1, delta1, delta2); + DUP2_ARG3(__lsx_vclip_h, delta1, tc_neg, tc_pos, delta2, tc_neg, + tc_pos, delta1, delta2); + DUP2_ARG2(__lsx_vadd_h, p1_src, delta1, q1_src, delta2, + delta1, delta2); + DUP2_ARG1(__lsx_vclip255_h, delta1, delta2, delta1, delta2); + DUP2_ARG3(__lsx_vbitsel_v, delta1, p1_src, p_is_pcm_vec, delta2, + q1_src, q_is_pcm_vec, delta1, delta2); + + abs_delta0 = __lsx_vnor_v(abs_delta0, abs_delta0); + DUP4_ARG3(__lsx_vbitsel_v, delta1, p1_src, abs_delta0, delta2, + q1_src, abs_delta0, temp0, p0_src, abs_delta0, temp2, + q0_src, abs_delta0, delta1, delta2, temp0, temp2); + /* weak filter ends*/ + + /* select between weak or strong */ + DUP4_ARG3(__lsx_vbitsel_v, dst0, p2_src, cmp2, dst1, delta1, + cmp2, dst2, temp0, cmp2, dst3, temp2, cmp2, + dst0, dst1, dst2, dst3); + DUP2_ARG3(__lsx_vbitsel_v, dst4, delta2, cmp2, dst5, q2_src, cmp2, + dst4, dst5); + } + + cmp3 = __lsx_vnor_v(cmp3, cmp3); + DUP4_ARG3(__lsx_vbitsel_v, dst0, p2_src, cmp3, dst1, p1_src, cmp3, dst2, + p0_src, cmp3, dst3, q0_src, cmp3, dst0, dst1, dst2, dst3); + DUP2_ARG3(__lsx_vbitsel_v, dst4, q1_src, cmp3, dst5, q2_src, cmp3, + dst4, dst5); + + /* pack results to 8 bit */ + DUP4_ARG2(__lsx_vpickev_b, dst2, dst0, dst3, dst1, dst4, dst4, dst5, + dst5, dst0, dst1, dst2, dst3); + + /* transpose */ + DUP2_ARG2(__lsx_vilvl_b, dst1, dst0, dst3, dst2, dst4, dst6); + DUP2_ARG2(__lsx_vilvh_b, dst1, dst0, dst3, dst2, dst5, dst7); + DUP2_ARG2(__lsx_vilvl_h, dst5, dst4, dst7, dst6, dst0, dst2); + DUP2_ARG2(__lsx_vilvh_h, dst5, dst4, dst7, dst6, dst1, dst3); + + src += 1; + __lsx_vstelm_w(dst0, src, 0, 0); + __lsx_vstelm_h(dst2, src, 4, 0); + src += stride; + __lsx_vstelm_w(dst0, src, 0, 1); + __lsx_vstelm_h(dst2, src, 4, 2); + src += stride; + + __lsx_vstelm_w(dst0, src, 0, 2); + __lsx_vstelm_h(dst2, src, 4, 4); + src += stride; + __lsx_vstelm_w(dst0, src, 0, 3); + __lsx_vstelm_h(dst2, src, 4, 6); + src += stride; + + __lsx_vstelm_w(dst1, src, 0, 0); + __lsx_vstelm_h(dst3, src, 4, 0); + src += stride; + __lsx_vstelm_w(dst1, src, 0, 1); + __lsx_vstelm_h(dst3, src, 4, 2); + src += stride; + + __lsx_vstelm_w(dst1, src, 0, 2); + __lsx_vstelm_h(dst3, src, 4, 4); + src += stride; + __lsx_vstelm_w(dst1, src, 0, 3); + __lsx_vstelm_h(dst3, src, 4, 6); + } +} + +void ff_hevc_loop_filter_chroma_h_8_lsx(uint8_t *src, ptrdiff_t stride, + int32_t *tc, uint8_t *p_is_pcm, + uint8_t *q_is_pcm) +{ + uint8_t *p1_ptr = src - (stride << 1); + uint8_t *p0_ptr = src - stride; + uint8_t *q0_ptr = src; + uint8_t *q1_ptr = src + stride; + __m128i cmp0, cmp1, p_is_pcm_vec, q_is_pcm_vec; + __m128i p1, p0, q0, q1; + __m128i tc_pos, tc_neg; + __m128i zero = {0}; + __m128i temp0, temp1, delta; + + if (!(tc[0] <= 0) || !(tc[1] <= 0)) { + DUP2_ARG1(__lsx_vreplgr2vr_h, tc[0], tc[1], cmp0, cmp1); + tc_pos = __lsx_vpackev_d(cmp1, cmp0); + tc_neg = __lsx_vneg_h(tc_pos); + DUP2_ARG1(__lsx_vreplgr2vr_d, p_is_pcm[0], p_is_pcm[1], cmp0, cmp1); + p_is_pcm_vec = __lsx_vpackev_d(cmp1, cmp0); + p_is_pcm_vec = __lsx_vseqi_d(p_is_pcm_vec, 0); + + DUP2_ARG1(__lsx_vreplgr2vr_d, q_is_pcm[0], q_is_pcm[1], cmp0, cmp1); + q_is_pcm_vec = __lsx_vpackev_d(cmp1, cmp0); + q_is_pcm_vec = __lsx_vseqi_d(q_is_pcm_vec, 0); + + DUP4_ARG2(__lsx_vld, p1_ptr, 0, p0_ptr, 0, q0_ptr, 0, q1_ptr, 0, + p1, p0, q0, q1); + DUP4_ARG2(__lsx_vilvl_b, zero, p1, zero, p0, zero, q0, zero, q1, + p1, p0, q0, q1); + DUP2_ARG2(__lsx_vsub_h, q0, p0, p1, q1, temp0, temp1); + temp0 = __lsx_vslli_h(temp0, 2); + temp0 = __lsx_vadd_h(temp0, temp1); + delta = __lsx_vsrari_h(temp0, 3); + delta = __lsx_vclip_h(delta, tc_neg, tc_pos); + temp0 = __lsx_vadd_h(p0, delta); + temp0 = __lsx_vclip255_h(temp0); + p_is_pcm_vec = __lsx_vnor_v(p_is_pcm_vec, p_is_pcm_vec); + temp0 = __lsx_vbitsel_v(temp0, p0, p_is_pcm_vec); + + temp1 = __lsx_vsub_h(q0, delta); + temp1 = __lsx_vclip255_h(temp1); + q_is_pcm_vec = __lsx_vnor_v(q_is_pcm_vec, q_is_pcm_vec); + temp1 = __lsx_vbitsel_v(temp1, q0, q_is_pcm_vec); + + tc_pos = __lsx_vslei_d(tc_pos, 0); + DUP2_ARG3(__lsx_vbitsel_v, temp0, p0, tc_pos, temp1, q0, tc_pos, + temp0, temp1); + temp0 = __lsx_vpickev_b(temp1, temp0); + __lsx_vstelm_d(temp0, p0_ptr, 0, 0); + __lsx_vstelm_d(temp0, p0_ptr + stride, 0, 1); + } +} + +void ff_hevc_loop_filter_chroma_v_8_lsx(uint8_t *src, ptrdiff_t stride, + int32_t *tc, uint8_t *p_is_pcm, + uint8_t *q_is_pcm) +{ + ptrdiff_t stride_2x = (stride << 1); + ptrdiff_t stride_4x = (stride << 2); + ptrdiff_t stride_3x = stride_2x + stride; + __m128i cmp0, cmp1, p_is_pcm_vec, q_is_pcm_vec; + __m128i src0, src1, src2, src3, src4, src5, src6, src7; + __m128i p1, p0, q0, q1; + __m128i tc_pos, tc_neg; + __m128i zero = {0}; + __m128i temp0, temp1, delta; + + if (!(tc[0] <= 0) || !(tc[1] <= 0)) { + DUP2_ARG1(__lsx_vreplgr2vr_h, tc[0], tc[1], cmp0, cmp1); + tc_pos = __lsx_vpackev_d(cmp1, cmp0); + tc_neg = __lsx_vneg_h(tc_pos); + + DUP2_ARG1(__lsx_vreplgr2vr_d, p_is_pcm[0], p_is_pcm[1], cmp0, cmp1); + p_is_pcm_vec = __lsx_vpackev_d(cmp1, cmp0); + p_is_pcm_vec = __lsx_vseqi_d(p_is_pcm_vec, 0); + DUP2_ARG1(__lsx_vreplgr2vr_d, q_is_pcm[0], q_is_pcm[1], cmp0, cmp1); + q_is_pcm_vec = __lsx_vpackev_d(cmp1, cmp0); + q_is_pcm_vec = __lsx_vseqi_d(q_is_pcm_vec, 0); + + src -= 2; + DUP4_ARG2(__lsx_vld, src, 0, src + stride, 0, src + stride_2x, 0, + src + stride_3x, 0, src0, src1, src2, src3); + src += stride_4x; + DUP4_ARG2(__lsx_vld, src, 0, src + stride, 0, src + stride_2x, 0, + src + stride_3x, 0, src4, src5, src6, src7); + src -= stride_4x; + LSX_TRANSPOSE8x4_B(src0, src1, src2, src3, src4, src5, src6, src7, + p1, p0, q0, q1); + DUP4_ARG2(__lsx_vilvl_b, zero, p1, zero, p0, zero, q0, zero, q1, + p1, p0, q0, q1); + + DUP2_ARG2(__lsx_vsub_h, q0, p0, p1, q1, temp0, temp1); + temp0 = __lsx_vslli_h(temp0, 2); + temp0 = __lsx_vadd_h(temp0, temp1); + delta = __lsx_vsrari_h(temp0, 3); + delta = __lsx_vclip_h(delta, tc_neg, tc_pos); + + temp0 = __lsx_vadd_h(p0, delta); + temp1 = __lsx_vsub_h(q0, delta); + DUP2_ARG1(__lsx_vclip255_h, temp0, temp1, temp0, temp1); + DUP2_ARG2(__lsx_vnor_v, p_is_pcm_vec, p_is_pcm_vec, q_is_pcm_vec, + q_is_pcm_vec, p_is_pcm_vec, q_is_pcm_vec); + DUP2_ARG3(__lsx_vbitsel_v, temp0, p0, p_is_pcm_vec, temp1, q0, + q_is_pcm_vec, temp0, temp1); + + tc_pos = __lsx_vslei_d(tc_pos, 0); + DUP2_ARG3(__lsx_vbitsel_v, temp0, p0, tc_pos, temp1, q0, tc_pos, + temp0, temp1); + temp0 = __lsx_vpackev_b(temp1, temp0); + + src += 1; + __lsx_vstelm_h(temp0, src, 0, 0); + __lsx_vstelm_h(temp0, src + stride, 0, 1); + __lsx_vstelm_h(temp0, src + stride_2x, 0, 2); + __lsx_vstelm_h(temp0, src + stride_3x, 0, 3); + src += stride_4x; + __lsx_vstelm_h(temp0, src, 0, 4); + __lsx_vstelm_h(temp0, src + stride, 0, 5); + __lsx_vstelm_h(temp0, src + stride_2x, 0, 6); + __lsx_vstelm_h(temp0, src + stride_3x, 0, 7); + src -= stride_4x; + } +} + +static void hevc_sao_edge_filter_0degree_4width_lsx(uint8_t *dst, + int32_t dst_stride, + uint8_t *src, + int32_t src_stride, + int16_t *sao_offset_val, + int32_t height) +{ + const int32_t src_stride_2x = (src_stride << 1); + const int32_t dst_stride_2x = (dst_stride << 1); + __m128i shuf1 = {0x807060504030201, 0x100F0E0D0C0B0A09}; + __m128i shuf2 = {0x908070605040302, 0x11100F0E0D0C0B0A}; + __m128i edge_idx = {0x403000201, 0x0}; + __m128i cmp_minus10, cmp_minus11, diff_minus10, diff_minus11; + __m128i sao_offset = __lsx_vld(sao_offset_val, 0); + __m128i src_minus10, src_minus11, src_plus10, offset, src0, dst0; + __m128i const1 = __lsx_vldi(1); + __m128i zero = {0}; + + sao_offset = __lsx_vpickev_b(sao_offset, sao_offset); + src -= 1; + + /* load in advance */ + DUP2_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src_minus10, src_minus11); + + for (height -= 2; height; height -= 2) { + src += src_stride_2x; + src_minus10 = __lsx_vpickev_d(src_minus11, src_minus10); + src0 = __lsx_vshuf_b(zero, src_minus10, shuf1); + src_plus10 = __lsx_vshuf_b(zero, src_minus10, shuf2); + + DUP2_ARG2(__lsx_vseq_b, src0, src_minus10, src0, src_plus10, + cmp_minus10, cmp_minus11); + DUP2_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_minus11, + cmp_minus11, diff_minus10, diff_minus11); + DUP2_ARG2(__lsx_vsle_bu, src0, src_minus10, src0, src_plus10, + cmp_minus10, cmp_minus11); + DUP2_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_minus11, + cmp_minus11, cmp_minus10, cmp_minus11); + DUP2_ARG3(__lsx_vbitsel_v, diff_minus10, const1, cmp_minus10, + diff_minus11, const1, cmp_minus11, diff_minus10, diff_minus11); + + offset = __lsx_vadd_b(diff_minus10, diff_minus11); + offset = __lsx_vaddi_bu(offset, 2); + + /* load in advance */ + DUP2_ARG2(__lsx_vld, src, 0, src + src_stride, 0, + src_minus10, src_minus11); + DUP2_ARG3(__lsx_vshuf_b, edge_idx, edge_idx, offset, + sao_offset, sao_offset, offset, offset, offset); + src0 = __lsx_vxori_b(src0, 128); + dst0 = __lsx_vsadd_b(src0, offset); + dst0 = __lsx_vxori_b(dst0, 128); + + __lsx_vstelm_w(dst0, dst, 0, 0); + __lsx_vstelm_w(dst0, dst + dst_stride, 0, 2); + dst += dst_stride_2x; + } + + src_minus10 = __lsx_vpickev_d(src_minus11, src_minus10); + src0 = __lsx_vshuf_b(zero, src_minus10, shuf1); + src_plus10 = __lsx_vshuf_b(zero, src_minus10, shuf2); + + DUP2_ARG2(__lsx_vseq_b, src0, src_minus10, src0, src_plus10, cmp_minus10, + cmp_minus11); + DUP2_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_minus11, cmp_minus11, + diff_minus10, diff_minus11); + DUP2_ARG2(__lsx_vsle_bu, src0, src_minus10, src0, src_plus10, cmp_minus10, + cmp_minus11); + DUP2_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_minus11, cmp_minus11, + cmp_minus10, cmp_minus11); + DUP2_ARG3(__lsx_vbitsel_v, diff_minus10, const1, cmp_minus10, diff_minus11, + const1, cmp_minus11, diff_minus10, diff_minus11); + + offset = __lsx_vadd_b(diff_minus10, diff_minus11); + offset = __lsx_vaddi_bu(offset, 2); + DUP2_ARG3(__lsx_vshuf_b, edge_idx, edge_idx, offset, sao_offset, sao_offset, + offset, offset, offset); + src0 = __lsx_vxori_b(src0, 128); + dst0 = __lsx_vsadd_b(src0, offset); + dst0 = __lsx_vxori_b(dst0, 128); + + __lsx_vstelm_w(dst0, dst, 0, 0); + __lsx_vstelm_w(dst0, dst + dst_stride, 0, 2); +} + +static void hevc_sao_edge_filter_0degree_8width_lsx(uint8_t *dst, + int32_t dst_stride, + uint8_t *src, + int32_t src_stride, + int16_t *sao_offset_val, + int32_t height) +{ + const int32_t src_stride_2x = (src_stride << 1); + const int32_t dst_stride_2x = (dst_stride << 1); + __m128i shuf1 = {0x807060504030201, 0x100F0E0D0C0B0A09}; + __m128i shuf2 = {0x908070605040302, 0x11100F0E0D0C0B0A}; + __m128i edge_idx = {0x403000201, 0x0}; + __m128i const1 = __lsx_vldi(1); + __m128i cmp_minus10, cmp_minus11, diff_minus10, diff_minus11; + __m128i src0, src1, dst0, src_minus10, src_minus11, src_plus10, src_plus11; + __m128i offset, sao_offset = __lsx_vld(sao_offset_val, 0); + __m128i zeros = {0}; + + sao_offset = __lsx_vpickev_b(sao_offset, sao_offset); + src -= 1; + + /* load in advance */ + DUP2_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src_minus10, src_minus11); + + for (height -= 2; height; height -= 2) { + src += src_stride_2x; + DUP2_ARG3(__lsx_vshuf_b, zeros, src_minus10, shuf1, zeros, + src_minus11, shuf1, src0, src1); + DUP2_ARG3(__lsx_vshuf_b, zeros, src_minus10, shuf2, zeros, + src_minus11, shuf2, src_plus10, src_plus11); + DUP2_ARG2(__lsx_vpickev_d, src_minus11, src_minus10, src_plus11, + src_plus10, src_minus10, src_plus10); + src0 = __lsx_vpickev_d(src1, src0); + + DUP2_ARG2(__lsx_vseq_b, src0, src_minus10, src0, src_plus10, + cmp_minus10, cmp_minus11); + DUP2_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_minus11, + cmp_minus11, diff_minus10, diff_minus11); + DUP2_ARG2(__lsx_vsle_bu, src0, src_minus10, src0, src_plus10, + cmp_minus10, cmp_minus11); + DUP2_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_minus11, + cmp_minus11, cmp_minus10, cmp_minus11); + DUP2_ARG3(__lsx_vbitsel_v, diff_minus10, const1, cmp_minus10, + diff_minus11, const1, cmp_minus11, diff_minus10, diff_minus11); + + offset = __lsx_vadd_b(diff_minus10, diff_minus11); + offset = __lsx_vaddi_bu(offset, 2); + + /* load in advance */ + DUP2_ARG2(__lsx_vld, src, 0, src + src_stride, 0, + src_minus10, src_minus11); + DUP2_ARG3(__lsx_vshuf_b, edge_idx, edge_idx, offset, sao_offset, + sao_offset, offset, offset, offset); + src0 = __lsx_vxori_b(src0, 128); + dst0 = __lsx_vsadd_b(src0, offset); + dst0 = __lsx_vxori_b(dst0, 128); + + __lsx_vstelm_d(dst0, dst, 0, 0); + __lsx_vstelm_d(dst0, dst + dst_stride, 0, 1); + dst += dst_stride_2x; + } + + DUP2_ARG3(__lsx_vshuf_b, zeros, src_minus10, shuf1, zeros, src_minus11, + shuf1, src0, src1); + DUP2_ARG3(__lsx_vshuf_b, zeros, src_minus10, shuf2, zeros, src_minus11, + shuf2, src_plus10, src_plus11); + DUP2_ARG2(__lsx_vpickev_d, src_minus11, src_minus10, src_plus11, + src_plus10, src_minus10, src_plus10); + src0 = __lsx_vpickev_d(src1, src0); + + DUP2_ARG2(__lsx_vseq_b, src0, src_minus10, src0, src_plus10, cmp_minus10, + cmp_minus11); + DUP2_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_minus11, cmp_minus11, + diff_minus10, diff_minus11); + DUP2_ARG2(__lsx_vsle_bu, src0, src_minus10, src0, src_plus10, cmp_minus10, + cmp_minus11); + DUP2_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_minus11, cmp_minus11, + cmp_minus10, cmp_minus11); + DUP2_ARG3(__lsx_vbitsel_v, diff_minus10, const1, cmp_minus10, diff_minus11, + const1, cmp_minus11, diff_minus10, diff_minus11); + + offset = __lsx_vadd_b(diff_minus10, diff_minus11); + offset = __lsx_vaddi_bu(offset, 2); + DUP2_ARG3(__lsx_vshuf_b, edge_idx, edge_idx, offset, sao_offset, + sao_offset, offset, offset, offset); + src0 = __lsx_vxori_b(src0, 128); + dst0 = __lsx_vsadd_b(src0, offset); + dst0 = __lsx_vxori_b(dst0, 128); + + __lsx_vstelm_d(dst0, dst, 0, 0); + __lsx_vstelm_d(dst0, dst + dst_stride, 0, 1); +} + +static void hevc_sao_edge_filter_0degree_16multiple_lsx(uint8_t *dst, + int32_t dst_stride, + uint8_t *src, + int32_t src_stride, + int16_t *sao_offset_val, + int32_t width, + int32_t height) +{ + uint8_t *dst_ptr, *src_minus1; + int32_t v_cnt; + const int32_t src_stride_2x = (src_stride << 1); + const int32_t dst_stride_2x = (dst_stride << 1); + const int32_t src_stride_4x = (src_stride << 2); + const int32_t dst_stride_4x = (dst_stride << 2); + const int32_t src_stride_3x = src_stride_2x + src_stride; + const int32_t dst_stride_3x = dst_stride_2x + dst_stride; + + __m128i shuf1 = {0x807060504030201, 0x100F0E0D0C0B0A09}; + __m128i shuf2 = {0x908070605040302, 0x11100F0E0D0C0B0A}; + __m128i edge_idx = {0x403000201, 0x0}; + __m128i const1 = __lsx_vldi(1); + __m128i sao_offset; + __m128i cmp_minus10, cmp_plus10, diff_minus10, diff_plus10, cmp_minus11; + __m128i cmp_plus11, diff_minus11, diff_plus11, cmp_minus12, cmp_plus12; + __m128i diff_minus12, diff_plus12, cmp_minus13, cmp_plus13, diff_minus13; + __m128i diff_plus13; + __m128i src10, src11, src12, src13, dst0, dst1, dst2, dst3; + __m128i src_minus10, src_minus11, src_minus12, src_minus13; + __m128i offset_mask0, offset_mask1, offset_mask2, offset_mask3; + __m128i src_zero0, src_zero1, src_zero2, src_zero3; + __m128i src_plus10, src_plus11, src_plus12, src_plus13; + + sao_offset = __lsx_vld(sao_offset_val, 0); + sao_offset = __lsx_vpickev_b(sao_offset, sao_offset); + + for (; height; height -= 4) { + src_minus1 = src - 1; + src_minus10 = __lsx_vld(src_minus1, 0); + DUP2_ARG2(__lsx_vldx, src_minus1, src_stride, src_minus1, + src_stride_2x, src_minus11, src_minus12); + src_minus13 = __lsx_vldx(src_minus1, src_stride_3x); + + for (v_cnt = 0; v_cnt < width; v_cnt += 16) { + src_minus1 += 16; + dst_ptr = dst + v_cnt; + src10 = __lsx_vld(src_minus1, 0); + DUP2_ARG2(__lsx_vldx, src_minus1, src_stride, src_minus1, + src_stride_2x, src11, src12); + src13 = __lsx_vldx(src_minus1, src_stride_3x); + DUP4_ARG3(__lsx_vshuf_b, src10, src_minus10, shuf1, src11, + src_minus11, shuf1, src12, src_minus12, shuf1, src13, + src_minus13, shuf1, src_zero0, src_zero1, + src_zero2, src_zero3); + DUP4_ARG3(__lsx_vshuf_b, src10, src_minus10, shuf2, src11, + src_minus11, shuf2, src12, src_minus12, shuf2, src13, + src_minus13, shuf2, src_plus10, src_plus11, + src_plus12, src_plus13); + DUP4_ARG2(__lsx_vseq_b, src_zero0, src_minus10, src_zero0, + src_plus10, src_zero1, src_minus11, src_zero1, src_plus11, + cmp_minus10, cmp_plus10, cmp_minus11, cmp_plus11); + DUP4_ARG2(__lsx_vseq_b, src_zero2, src_minus12, src_zero2, + src_plus12, src_zero3, src_minus13, src_zero3, src_plus13, + cmp_minus12, cmp_plus12, cmp_minus13, cmp_plus13); + DUP4_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_plus10, + cmp_plus10, cmp_minus11, cmp_minus11, cmp_plus11, + cmp_plus11, diff_minus10, diff_plus10, diff_minus11, + diff_plus11); + DUP4_ARG2(__lsx_vnor_v, cmp_minus12, cmp_minus12, cmp_plus12, + cmp_plus12, cmp_minus13, cmp_minus13, cmp_plus13, + cmp_plus13, diff_minus12, diff_plus12, diff_minus13, + diff_plus13); + DUP4_ARG2(__lsx_vsle_bu, src_zero0, src_minus10, src_zero0, + src_plus10, src_zero1, src_minus11, src_zero1, src_plus11, + cmp_minus10, cmp_plus10, cmp_minus11, cmp_plus11); + DUP4_ARG2(__lsx_vsle_bu, src_zero2, src_minus12, src_zero2, + src_plus12, src_zero3, src_minus13, src_zero3, src_plus13, + cmp_minus12, cmp_plus12, cmp_minus13, cmp_plus13); + DUP4_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_plus10, + cmp_plus10, cmp_minus11, cmp_minus11, cmp_plus11, + cmp_plus11, cmp_minus10, cmp_plus10, cmp_minus11, + cmp_plus11); + DUP4_ARG2(__lsx_vnor_v, cmp_minus12, cmp_minus12, cmp_plus12, + cmp_plus12, cmp_minus13, cmp_minus13, cmp_plus13, + cmp_plus13, cmp_minus12, cmp_plus12, cmp_minus13, + cmp_plus13); + DUP4_ARG3(__lsx_vbitsel_v, diff_minus10, const1, cmp_minus10, + diff_plus10, const1, cmp_plus10, diff_minus11, const1, + cmp_minus11, diff_plus11, const1, cmp_plus11, + diff_minus10, diff_plus10, diff_minus11, diff_plus11); + DUP4_ARG3(__lsx_vbitsel_v, diff_minus12, const1, cmp_minus12, + diff_plus12, const1, cmp_plus12, diff_minus13, const1, + cmp_minus13, diff_plus13, const1, cmp_plus13, + diff_minus12, diff_plus12, diff_minus13, diff_plus13); + + DUP4_ARG2(__lsx_vadd_b, diff_minus10, diff_plus10, diff_minus11, + diff_plus11, diff_minus12, diff_plus12, diff_minus13, + diff_plus13, offset_mask0, offset_mask1, offset_mask2, + offset_mask3); + DUP4_ARG2(__lsx_vaddi_bu, offset_mask0, 2, offset_mask1, 2, + offset_mask2, 2, offset_mask3, 2, offset_mask0, + offset_mask1, offset_mask2, offset_mask3); + DUP2_ARG3(__lsx_vshuf_b, edge_idx, edge_idx, offset_mask0, + sao_offset, sao_offset, offset_mask0, offset_mask0, + offset_mask0); + DUP2_ARG3(__lsx_vshuf_b, edge_idx, edge_idx, offset_mask1, + sao_offset, sao_offset, offset_mask1, offset_mask1, + offset_mask1); + DUP2_ARG3(__lsx_vshuf_b, edge_idx, edge_idx, offset_mask2, + sao_offset, sao_offset, offset_mask2, offset_mask2, + offset_mask2); + DUP2_ARG3(__lsx_vshuf_b, edge_idx, edge_idx, offset_mask3, + sao_offset, sao_offset, offset_mask3, offset_mask3, + offset_mask3); + + DUP4_ARG2(__lsx_vxori_b, src_zero0, 128, src_zero1, 128, + src_zero2, 128, src_zero3, 128, src_zero0, src_zero1, + src_zero2, src_zero3); + DUP4_ARG2(__lsx_vsadd_b, src_zero0, offset_mask0, src_zero1, + offset_mask1, src_zero2, offset_mask2, src_zero3, + offset_mask3, dst0, dst1, dst2, dst3); + DUP4_ARG2(__lsx_vxori_b, dst0, 128, dst1, 128, dst2, 128, dst3, + 128, dst0, dst1, dst2, dst3); + + src_minus10 = src10; + src_minus11 = src11; + src_minus12 = src12; + src_minus13 = src13; + + __lsx_vst(dst0, dst_ptr, 0); + __lsx_vst(dst1, dst_ptr + dst_stride, 0); + __lsx_vst(dst2, dst_ptr + dst_stride_2x, 0); + __lsx_vst(dst3, dst_ptr + dst_stride_3x, 0); + } + src += src_stride_4x; + dst += dst_stride_4x; + } +} + +static void hevc_sao_edge_filter_90degree_4width_lsx(uint8_t *dst, + int32_t dst_stride, + uint8_t *src, + int32_t src_stride, + int16_t *sao_offset_val, + int32_t height) +{ + const int32_t src_stride_2x = (src_stride << 1); + const int32_t dst_stride_2x = (dst_stride << 1); + __m128i edge_idx = {0x403000201, 0x0}; + __m128i const1 = __lsx_vldi(1); + __m128i dst0; + __m128i sao_offset = __lsx_vld(sao_offset_val, 0); + __m128i cmp_minus10, diff_minus10, cmp_minus11, diff_minus11; + __m128i src_minus10, src_minus11, src10, src11; + __m128i src_zero0, src_zero1; + __m128i offset; + __m128i offset_mask0, offset_mask1; + + sao_offset = __lsx_vpickev_b(sao_offset, sao_offset); + + /* load in advance */ + DUP4_ARG2(__lsx_vld, src - src_stride, 0, src, 0, src + src_stride, 0, + src + src_stride_2x, 0, src_minus10, src_minus11, src10, src11); + + for (height -= 2; height; height -= 2) { + src += src_stride_2x; + DUP4_ARG2(__lsx_vilvl_b, src10, src_minus10, src_minus11, src_minus11, + src11, src_minus11, src10, src10, src_minus10, src_zero0, + src_minus11, src_zero1); + DUP2_ARG2(__lsx_vseq_b, src_zero0, src_minus10, src_zero1, src_minus11, + cmp_minus10, cmp_minus11); + DUP2_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_minus11, + cmp_minus11, diff_minus10, diff_minus11); + DUP2_ARG2(__lsx_vsle_bu, src_zero0, src_minus10, src_zero1, + src_minus11, cmp_minus10, cmp_minus11); + DUP2_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_minus11, + cmp_minus11, cmp_minus10, cmp_minus11); + DUP2_ARG3(__lsx_vbitsel_v, diff_minus10, const1, cmp_minus10, + diff_minus11, const1, cmp_minus11, diff_minus10, diff_minus11); + + DUP2_ARG2(__lsx_vhaddw_hu_bu, diff_minus10, diff_minus10, diff_minus11, + diff_minus11, offset_mask0, offset_mask1); + DUP2_ARG2(__lsx_vaddi_hu, offset_mask0, 2, offset_mask1, 2, + offset_mask0, offset_mask1); + DUP2_ARG2(__lsx_vpickev_b, offset_mask1, offset_mask0, src_zero1, + src_zero0, offset, dst0); + DUP2_ARG3(__lsx_vshuf_b, edge_idx, edge_idx, offset, sao_offset, + sao_offset, offset, offset, offset); + + dst0 = __lsx_vxori_b(dst0, 128); + dst0 = __lsx_vsadd_b(dst0, offset); + dst0 = __lsx_vxori_b(dst0, 128); + src_minus10 = src10; + src_minus11 = src11; + + /* load in advance */ + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, + src10, src11); + + __lsx_vstelm_w(dst0, dst, 0, 0); + __lsx_vstelm_w(dst0, dst + dst_stride, 0, 2); + dst += dst_stride_2x; + } + + DUP4_ARG2(__lsx_vilvl_b, src10, src_minus10, src_minus11, src_minus11, + src11, src_minus11, src10, src10, src_minus10, src_zero0, + src_minus11, src_zero1); + DUP2_ARG2(__lsx_vseq_b, src_zero0, src_minus10, src_zero1, src_minus11, + cmp_minus10, cmp_minus11); + DUP2_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_minus11, cmp_minus11, + diff_minus10, diff_minus11); + DUP2_ARG2(__lsx_vsle_bu, src_zero0, src_minus10, src_zero1, src_minus11, + cmp_minus10, cmp_minus11); + DUP2_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_minus11, cmp_minus11, + cmp_minus10, cmp_minus11); + DUP2_ARG3(__lsx_vbitsel_v, diff_minus10, const1, cmp_minus10, diff_minus11, + const1, cmp_minus11, diff_minus10, diff_minus11); + + DUP2_ARG2(__lsx_vhaddw_hu_bu, diff_minus10, diff_minus10, diff_minus11, + diff_minus11, offset_mask0, offset_mask1); + DUP2_ARG2(__lsx_vaddi_bu, offset_mask0, 2, offset_mask1, 2, + offset_mask0, offset_mask1); + DUP2_ARG2(__lsx_vpickev_b, offset_mask1, offset_mask0, src_zero1, + src_zero0, offset, dst0); + DUP2_ARG3(__lsx_vshuf_b, edge_idx, edge_idx, offset, sao_offset, + sao_offset, offset, offset, offset); + dst0 = __lsx_vxori_b(dst0, 128); + dst0 = __lsx_vsadd_b(dst0, offset); + dst0 = __lsx_vxori_b(dst0, 128); + + __lsx_vstelm_w(dst0, dst, 0, 0); + __lsx_vstelm_w(dst0, dst + dst_stride, 0, 2); +} + +static void hevc_sao_edge_filter_90degree_8width_lsx(uint8_t *dst, + int32_t dst_stride, + uint8_t *src, + int32_t src_stride, + int16_t *sao_offset_val, + int32_t height) +{ + const int32_t src_stride_2x = (src_stride << 1); + const int32_t dst_stride_2x = (dst_stride << 1); + __m128i edge_idx = {0x403000201, 0x0}; + __m128i const1 = __lsx_vldi(1); + __m128i offset, sao_offset = __lsx_vld(sao_offset_val, 0); + __m128i src_zero0, src_zero1, dst0; + __m128i cmp_minus10, diff_minus10, cmp_minus11, diff_minus11; + __m128i src_minus10, src_minus11, src10, src11; + __m128i offset_mask0, offset_mask1; + + sao_offset = __lsx_vpickev_b(sao_offset, sao_offset); + + /* load in advance */ + DUP2_ARG2(__lsx_vld, src - src_stride, 0, src, 0, src_minus10, src_minus11); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src10, src11); + + for (height -= 2; height; height -= 2) { + src += src_stride_2x; + DUP4_ARG2(__lsx_vilvl_b, src10, src_minus10, src_minus11, src_minus11, + src11, src_minus11, src10, src10, src_minus10, src_zero0, + src_minus11, src_zero1); + DUP2_ARG2(__lsx_vseq_b, src_zero0, src_minus10, src_zero1, src_minus11, + cmp_minus10, cmp_minus11); + DUP2_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_minus11, + cmp_minus11, diff_minus10, diff_minus11); + DUP2_ARG2(__lsx_vsle_bu, src_zero0, src_minus10, src_zero1, + src_minus11, cmp_minus10, cmp_minus11); + DUP2_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_minus11, + cmp_minus11, cmp_minus10, cmp_minus11); + DUP2_ARG3(__lsx_vbitsel_v, diff_minus10, const1, cmp_minus10, + diff_minus11, const1, cmp_minus11, diff_minus10, diff_minus11); + + DUP2_ARG2(__lsx_vhaddw_hu_bu, diff_minus10, diff_minus10, diff_minus11, + diff_minus11, offset_mask0, offset_mask1); + DUP2_ARG2(__lsx_vaddi_hu, offset_mask0, 2, offset_mask1, 2, + offset_mask0, offset_mask1); + DUP2_ARG2(__lsx_vpickev_b, offset_mask1, offset_mask0, src_zero1, + src_zero0, offset, dst0); + DUP2_ARG3(__lsx_vshuf_b, edge_idx, edge_idx, offset, sao_offset, + sao_offset, offset, offset, offset); + + dst0 = __lsx_vxori_b(dst0, 128); + dst0 = __lsx_vsadd_b(dst0, offset); + dst0 = __lsx_vxori_b(dst0, 128); + src_minus10 = src10; + src_minus11 = src11; + + /* load in advance */ + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, + src10, src11); + + __lsx_vstelm_d(dst0, dst, 0, 0); + __lsx_vstelm_d(dst0, dst + dst_stride, 0, 1); + dst += dst_stride_2x; + } + + DUP4_ARG2(__lsx_vilvl_b, src10, src_minus10, src_minus11, src_minus11, + src11, src_minus11, src10, src10, src_minus10, src_zero0, + src_minus11, src_zero1); + DUP2_ARG2(__lsx_vseq_b, src_zero0, src_minus10, src_zero1, src_minus11, + cmp_minus10, cmp_minus11); + DUP2_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_minus11, cmp_minus11, + diff_minus10, diff_minus11); + DUP2_ARG2(__lsx_vsle_bu, src_zero0, src_minus10, src_zero1, src_minus11, + cmp_minus10, cmp_minus11); + DUP2_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_minus11, cmp_minus11, + cmp_minus10, cmp_minus11); + DUP2_ARG3(__lsx_vbitsel_v, diff_minus10, const1, cmp_minus10, diff_minus11, + const1, cmp_minus11, diff_minus10, diff_minus11); + + DUP2_ARG2(__lsx_vhaddw_hu_bu, diff_minus10, diff_minus10, diff_minus11, + diff_minus11, offset_mask0, offset_mask1); + DUP2_ARG2(__lsx_vaddi_hu, offset_mask0, 2, offset_mask1, 2, + offset_mask0, offset_mask1); + DUP2_ARG2(__lsx_vpickev_b, offset_mask1, offset_mask0, src_zero1, + src_zero0, offset, dst0); + DUP2_ARG3(__lsx_vshuf_b, edge_idx, edge_idx, offset, sao_offset, + sao_offset, offset, offset, offset); + dst0 = __lsx_vxori_b(dst0, 128); + dst0 = __lsx_vsadd_b(dst0, offset); + dst0 = __lsx_vxori_b(dst0, 128); + + __lsx_vstelm_d(dst0, dst, 0, 0); + __lsx_vstelm_d(dst0, dst + dst_stride, 0, 1); +} + +static void hevc_sao_edge_filter_90degree_16multiple_lsx(uint8_t *dst, + int32_t dst_stride, + uint8_t *src, + int32_t src_stride, + int16_t * + sao_offset_val, + int32_t width, + int32_t height) +{ + uint8_t *src_orig = src; + uint8_t *dst_orig = dst; + int32_t h_cnt, v_cnt; + const int32_t src_stride_2x = (src_stride << 1); + const int32_t dst_stride_2x = (dst_stride << 1); + const int32_t src_stride_4x = (src_stride << 2); + const int32_t dst_stride_4x = (dst_stride << 2); + const int32_t src_stride_3x = src_stride_2x + src_stride; + const int32_t dst_stride_3x = dst_stride_2x + dst_stride; + __m128i edge_idx = {0x403000201, 0x0}; + __m128i const1 = __lsx_vldi(1); + __m128i cmp_minus10, cmp_plus10, diff_minus10, diff_plus10, cmp_minus11; + __m128i cmp_plus11, diff_minus11, diff_plus11, cmp_minus12, cmp_plus12; + __m128i diff_minus12, diff_plus12, cmp_minus13, cmp_plus13, diff_minus13; + __m128i diff_plus13; + __m128i src10, src_minus10, dst0, src11, src_minus11, dst1; + __m128i src12, dst2, src13, dst3; + __m128i offset_mask0, offset_mask1, offset_mask2, offset_mask3, sao_offset; + + sao_offset = __lsx_vld(sao_offset_val, 0); + sao_offset = __lsx_vpickev_b(sao_offset, sao_offset); + + for (v_cnt = 0; v_cnt < width; v_cnt += 16) { + src = src_orig + v_cnt; + dst = dst_orig + v_cnt; + + DUP2_ARG2(__lsx_vld, src - src_stride, 0, src, 0, + src_minus10, src_minus11); + + for (h_cnt = (height >> 2); h_cnt--;) { + DUP4_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, + src, src_stride_3x, src, src_stride_4x, + src10, src11, src12, src13); + DUP4_ARG2(__lsx_vseq_b, src_minus11, src_minus10, src_minus11, + src10, src10, src_minus11, src10, src11, cmp_minus10, + cmp_plus10, cmp_minus11, cmp_plus11); + DUP4_ARG2(__lsx_vseq_b, src11, src10, src11, src12, src12, src11, + src12, src13, cmp_minus12, cmp_plus12, + cmp_minus13, cmp_plus13); + DUP4_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_plus10, + cmp_plus10, cmp_minus11, cmp_minus11, cmp_plus11, + cmp_plus11, diff_minus10, diff_plus10, diff_minus11, + diff_plus11); + DUP4_ARG2(__lsx_vnor_v, cmp_minus12, cmp_minus12, cmp_plus12, + cmp_plus12, cmp_minus13, cmp_minus13, cmp_plus13, + cmp_plus13, diff_minus12, diff_plus12, diff_minus13, + diff_plus13); + DUP4_ARG2(__lsx_vsle_bu, src_minus11, src_minus10, src_minus11, + src10, src10, src_minus11, src10, src11, cmp_minus10, + cmp_plus10, cmp_minus11, cmp_plus11); + DUP4_ARG2(__lsx_vsle_bu, src11, src10, src11, src12, src12, src11, + src12, src13, cmp_minus12, cmp_plus12, cmp_minus13, + cmp_plus13); + DUP4_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_plus10, + cmp_plus10, cmp_minus11, cmp_minus11, cmp_plus11, + cmp_plus11, cmp_minus10, cmp_plus10, cmp_minus11, + cmp_plus11); + DUP4_ARG2(__lsx_vnor_v, cmp_minus12, cmp_minus12, cmp_plus12, + cmp_plus12, cmp_minus13, cmp_minus13, cmp_plus13, + cmp_plus13, cmp_minus12, cmp_plus12, cmp_minus13, + cmp_plus13); + DUP4_ARG3(__lsx_vbitsel_v, diff_minus10, const1, cmp_minus10, + diff_plus10, const1, cmp_plus10, diff_minus11, const1, + cmp_minus11, diff_plus11, const1, cmp_plus11, + diff_minus10, diff_plus10, diff_minus11, diff_plus11); + DUP4_ARG3(__lsx_vbitsel_v, diff_minus12, const1, cmp_minus12, + diff_plus12, const1, cmp_plus12, diff_minus13, const1, + cmp_minus13, diff_plus13, const1, cmp_plus13, + diff_minus12, diff_plus12, diff_minus13, diff_plus13); + + DUP4_ARG2(__lsx_vadd_b, diff_minus10, diff_plus10, diff_minus11, + diff_plus11, diff_minus12, diff_plus12, diff_minus13, + diff_plus13, offset_mask0, offset_mask1, offset_mask2, + offset_mask3); + DUP4_ARG2(__lsx_vaddi_bu, offset_mask0, 2, offset_mask1, 2, + offset_mask2, 2, offset_mask3, 2, offset_mask0, + offset_mask1, offset_mask2, offset_mask3); + DUP2_ARG3(__lsx_vshuf_b, edge_idx, edge_idx, offset_mask0, + sao_offset, sao_offset, offset_mask0,\ + offset_mask0, offset_mask0); + DUP2_ARG3(__lsx_vshuf_b, edge_idx, edge_idx, offset_mask1, + sao_offset, sao_offset, offset_mask1, offset_mask1, + offset_mask1); + DUP2_ARG3(__lsx_vshuf_b, edge_idx, edge_idx, offset_mask2, + sao_offset, sao_offset, offset_mask2, offset_mask2, + offset_mask2); + DUP2_ARG3(__lsx_vshuf_b, edge_idx, edge_idx, offset_mask3, + sao_offset, sao_offset, offset_mask3, offset_mask3, + offset_mask3); + + src_minus10 = src12; + DUP4_ARG2(__lsx_vxori_b, src_minus11, 128, src10, 128, src11, 128, + src12, 128, src_minus11, src10, src11, src12); + DUP4_ARG2(__lsx_vsadd_b, src_minus11, offset_mask0, src10, + offset_mask1, src11, offset_mask2, src12, + offset_mask3, dst0, dst1, dst2, dst3); + DUP4_ARG2(__lsx_vxori_b, dst0, 128, dst1, 128, dst2, 128, dst3, + 128, dst0, dst1, dst2, dst3); + src_minus11 = src13; + + __lsx_vst(dst0, dst, 0); + __lsx_vstx(dst1, dst, dst_stride); + __lsx_vstx(dst2, dst, dst_stride_2x); + __lsx_vstx(dst3, dst, dst_stride_3x); + src += src_stride_4x; + dst += dst_stride_4x; + } + } +} + +static void hevc_sao_edge_filter_45degree_4width_lsx(uint8_t *dst, + int32_t dst_stride, + uint8_t *src, + int32_t src_stride, + int16_t *sao_offset_val, + int32_t height) +{ + uint8_t *src_orig; + const int32_t src_stride_2x = (src_stride << 1); + const int32_t dst_stride_2x = (dst_stride << 1); + __m128i shuf1 = {0x807060504030201, 0x100F0E0D0C0B0A09}; + __m128i shuf2 = {0x908070605040302, 0x11100F0E0D0C0B0A}; + __m128i edge_idx = {0x403000201, 0x0}; + __m128i const1 = __lsx_vldi(1); + __m128i offset, sao_offset = __lsx_vld(sao_offset_val, 0); + __m128i cmp_minus10, diff_minus10, src_minus10, cmp_minus11, diff_minus11; + __m128i src_minus11, src10, src11; + __m128i src_plus0, src_zero0, src_plus1, src_zero1, dst0; + __m128i offset_mask0, offset_mask1; + __m128i zeros = {0}; + + sao_offset = __lsx_vpickev_b(sao_offset, sao_offset); + src_orig = src - 1; + + /* load in advance */ + DUP2_ARG2(__lsx_vld, src_orig - src_stride, 0, src_orig, 0, + src_minus10, src_minus11); + DUP2_ARG2(__lsx_vldx, src_orig, src_stride, src_orig, src_stride_2x, + src10, src11); + + for (height -= 2; height; height -= 2) { + src_orig += src_stride_2x; + + DUP2_ARG3(__lsx_vshuf_b, zeros, src_minus11, shuf1, zeros, src10, + shuf1, src_zero0, src_zero1); + DUP2_ARG3(__lsx_vshuf_b, zeros, src10, shuf2, zeros, src11, shuf2, + src_plus0, src_plus1); + + DUP2_ARG2(__lsx_vilvl_b, src_plus0, src_minus10, src_plus1, + src_minus11, src_minus10, src_minus11); + DUP2_ARG2(__lsx_vilvl_b, src_zero0, src_zero0, src_zero1, + src_zero1, src_zero0, src_zero1); + DUP2_ARG2(__lsx_vseq_b, src_zero0, src_minus10, src_zero1, + src_minus11, cmp_minus10, cmp_minus11); + DUP2_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_minus11, + cmp_minus11, diff_minus10, diff_minus11); + DUP2_ARG2(__lsx_vsle_bu, src_zero0, src_minus10, src_zero1, + src_minus11, cmp_minus10, cmp_minus11); + DUP2_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_minus11, + cmp_minus11, cmp_minus10, cmp_minus11); + DUP2_ARG3(__lsx_vbitsel_v, diff_minus10, const1, cmp_minus10, + diff_minus11, const1, cmp_minus11, diff_minus10, diff_minus11); + + DUP2_ARG2(__lsx_vhaddw_hu_bu, diff_minus10, diff_minus10, diff_minus11, + diff_minus11, offset_mask0, offset_mask1); + DUP2_ARG2(__lsx_vaddi_hu, offset_mask0, 2, offset_mask1, 2, + offset_mask0, offset_mask1); + DUP2_ARG2(__lsx_vpickev_b, offset_mask1, offset_mask0, src_zero1, + src_zero0, offset, dst0); + DUP2_ARG3(__lsx_vshuf_b, edge_idx, edge_idx, offset, sao_offset, + sao_offset, offset, offset, offset); + dst0 = __lsx_vxori_b(dst0, 128); + dst0 = __lsx_vsadd_b(dst0, offset); + dst0 = __lsx_vxori_b(dst0, 128); + + src_minus10 = src10; + src_minus11 = src11; + + /* load in advance */ + DUP2_ARG2(__lsx_vldx, src_orig, src_stride, src_orig, src_stride_2x, + src10, src11); + + __lsx_vstelm_w(dst0, dst, 0, 0); + __lsx_vstelm_w(dst0, dst + dst_stride, 0, 2); + dst += dst_stride_2x; + } + + DUP2_ARG3(__lsx_vshuf_b, zeros, src_minus11, shuf1, zeros, src10, shuf1, + src_zero0, src_zero1); + DUP2_ARG3(__lsx_vshuf_b, zeros, src10, shuf2, zeros, src11, shuf2, + src_plus0, src_plus1); + + DUP2_ARG2(__lsx_vilvl_b, src_plus0, src_minus10, src_plus1, src_minus11, + src_minus10, src_minus11); + DUP2_ARG2(__lsx_vilvl_b, src_zero0, src_zero0, src_zero1, src_zero1, + src_zero0, src_zero1); + DUP2_ARG2(__lsx_vseq_b, src_zero0, src_minus10, src_zero1, src_minus11, + cmp_minus10, cmp_minus11); + DUP2_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_minus11, cmp_minus11, + diff_minus10, diff_minus11); + DUP2_ARG2(__lsx_vsle_bu, src_zero0, src_minus10, src_zero1, src_minus11, + cmp_minus10, cmp_minus11); + DUP2_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_minus11, cmp_minus11, + cmp_minus10, cmp_minus11); + DUP2_ARG3(__lsx_vbitsel_v, diff_minus10, const1, cmp_minus10, diff_minus11, + const1, cmp_minus11, diff_minus10, diff_minus11); + + DUP2_ARG2(__lsx_vhaddw_hu_bu, diff_minus10, diff_minus10, diff_minus11, + diff_minus11, offset_mask0, offset_mask1); + DUP2_ARG2(__lsx_vaddi_hu, offset_mask0, 2, offset_mask1, 2, offset_mask0, + offset_mask1); + DUP2_ARG2(__lsx_vpickev_b, offset_mask1, offset_mask0, src_zero1, + src_zero0, offset, dst0); + DUP2_ARG3(__lsx_vshuf_b, edge_idx, edge_idx, offset, sao_offset, + sao_offset, offset, offset, offset); + dst0 = __lsx_vxori_b(dst0, 128); + dst0 = __lsx_vsadd_b(dst0, offset); + dst0 = __lsx_vxori_b(dst0, 128); + + __lsx_vstelm_w(dst0, dst, 0, 0); + __lsx_vstelm_w(dst0, dst + dst_stride, 0, 2); +} + +static void hevc_sao_edge_filter_45degree_8width_lsx(uint8_t *dst, + int32_t dst_stride, + uint8_t *src, + int32_t src_stride, + int16_t *sao_offset_val, + int32_t height) +{ + uint8_t *src_orig; + const int32_t src_stride_2x = (src_stride << 1); + const int32_t dst_stride_2x = (dst_stride << 1); + __m128i shuf1 = {0x807060504030201, 0x100F0E0D0C0B0A09}; + __m128i shuf2 = {0x908070605040302, 0x11100F0E0D0C0B0A}; + __m128i edge_idx = {0x403000201, 0x0}; + __m128i const1 = __lsx_vldi(1); + __m128i offset, sao_offset = __lsx_vld(sao_offset_val, 0); + __m128i cmp_minus10, diff_minus10, cmp_minus11, diff_minus11; + __m128i src_minus10, src10, src_minus11, src11; + __m128i src_zero0, src_plus10, src_zero1, src_plus11, dst0; + __m128i offset_mask0, offset_mask1; + __m128i zeros = {0}; + + sao_offset = __lsx_vpickev_b(sao_offset, sao_offset); + src_orig = src - 1; + + /* load in advance */ + DUP2_ARG2(__lsx_vld, src_orig - src_stride, 0, src_orig, 0, src_minus10, + src_minus11); + DUP2_ARG2(__lsx_vldx, src_orig, src_stride, src_orig, src_stride_2x, + src10, src11); + + for (height -= 2; height; height -= 2) { + src_orig += src_stride_2x; + + DUP2_ARG3(__lsx_vshuf_b, zeros, src_minus11, shuf1, zeros, src10, + shuf1, src_zero0, src_zero1); + DUP2_ARG3(__lsx_vshuf_b, zeros, src10, shuf2, zeros, src11, shuf2, + src_plus10, src_plus11); + + DUP2_ARG2(__lsx_vilvl_b, src_plus10, src_minus10, src_plus11, + src_minus11, src_minus10, src_minus11); + DUP2_ARG2(__lsx_vilvl_b, src_zero0, src_zero0, src_zero1, src_zero1, + src_zero0, src_zero1); + DUP2_ARG2(__lsx_vseq_b, src_zero0, src_minus10, src_zero1, src_minus11, + cmp_minus10, cmp_minus11); + DUP2_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_minus11, + cmp_minus11, diff_minus10, diff_minus11); + DUP2_ARG2(__lsx_vsle_bu, src_zero0, src_minus10, src_zero1, + src_minus11, cmp_minus10, cmp_minus11); + DUP2_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_minus11, + cmp_minus11, cmp_minus10, cmp_minus11); + DUP2_ARG3(__lsx_vbitsel_v, diff_minus10, const1, cmp_minus10, + diff_minus11, const1, cmp_minus11, diff_minus10, diff_minus11); + + DUP2_ARG2(__lsx_vhaddw_hu_bu, diff_minus10, diff_minus10, diff_minus11, + diff_minus11, offset_mask0, offset_mask1); + DUP2_ARG2(__lsx_vaddi_hu, offset_mask0, 2, offset_mask1, 2, + offset_mask0, offset_mask1); + DUP2_ARG2(__lsx_vpickev_b, offset_mask1, offset_mask0, src_zero1, + src_zero0, offset, dst0); + DUP2_ARG3(__lsx_vshuf_b, edge_idx, edge_idx, offset, sao_offset, + sao_offset, offset, offset, offset); + dst0 = __lsx_vxori_b(dst0, 128); + dst0 = __lsx_vsadd_b(dst0, offset); + dst0 = __lsx_vxori_b(dst0, 128); + + src_minus10 = src10; + src_minus11 = src11; + + /* load in advance */ + DUP2_ARG2(__lsx_vldx, src_orig, src_stride, src_orig, src_stride_2x, + src10, src11) + __lsx_vstelm_d(dst0, dst, 0, 0); + __lsx_vstelm_d(dst0, dst + dst_stride, 0, 1); + dst += dst_stride_2x; + } + + DUP2_ARG3(__lsx_vshuf_b, zeros, src_minus11, shuf1, zeros, src10, shuf1, + src_zero0, src_zero1); + DUP2_ARG3(__lsx_vshuf_b, zeros, src10, shuf2, zeros, src11, shuf2, + src_plus10, src_plus11); + DUP2_ARG2(__lsx_vilvl_b, src_plus10, src_minus10, src_plus11, src_minus11, + src_minus10, src_minus11); + DUP2_ARG2(__lsx_vilvl_b, src_zero0, src_zero0, src_zero1, src_zero1, + src_zero0, src_zero1); + + DUP2_ARG2(__lsx_vseq_b, src_zero0, src_minus10, src_zero1, src_minus11, + cmp_minus10, cmp_minus11); + DUP2_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_minus11, + cmp_minus11, diff_minus10, diff_minus11); + DUP2_ARG2(__lsx_vsle_bu, src_zero0, src_minus10, src_zero1, src_minus11, + cmp_minus10, cmp_minus11); + DUP2_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_minus11, cmp_minus11, + cmp_minus10, cmp_minus11); + DUP2_ARG3(__lsx_vbitsel_v, diff_minus10, const1, cmp_minus10, diff_minus11, + const1, cmp_minus11, diff_minus10, diff_minus11); + + DUP2_ARG2(__lsx_vhaddw_hu_bu, diff_minus10, diff_minus10, diff_minus11, + diff_minus11, offset_mask0, offset_mask1); + DUP2_ARG2(__lsx_vaddi_hu, offset_mask0, 2, offset_mask1, 2, offset_mask0, + offset_mask1); + DUP2_ARG2(__lsx_vpickev_b, offset_mask1, offset_mask0, src_zero1, + src_zero0, offset, dst0); + DUP2_ARG3(__lsx_vshuf_b, edge_idx, edge_idx, offset, sao_offset, + sao_offset, offset, offset, offset); + dst0 = __lsx_vxori_b(dst0, 128); + dst0 = __lsx_vsadd_b(dst0, offset); + dst0 = __lsx_vxori_b(dst0, 128); + + src_minus10 = src10; + src_minus11 = src11; + + /* load in advance */ + DUP2_ARG2(__lsx_vldx, src_orig, src_stride, src_orig, src_stride_2x, + src10, src11); + + __lsx_vstelm_d(dst0, dst, 0, 0); + __lsx_vstelm_d(dst0, dst + dst_stride, 0, 1); +} + +static void hevc_sao_edge_filter_45degree_16multiple_lsx(uint8_t *dst, + int32_t dst_stride, + uint8_t *src, + int32_t src_stride, + int16_t * + sao_offset_val, + int32_t width, + int32_t height) +{ + uint8_t *src_orig = src; + uint8_t *dst_orig = dst; + int32_t v_cnt; + const int32_t src_stride_2x = (src_stride << 1); + const int32_t dst_stride_2x = (dst_stride << 1); + const int32_t src_stride_4x = (src_stride << 2); + const int32_t dst_stride_4x = (dst_stride << 2); + const int32_t src_stride_3x = src_stride_2x + src_stride; + const int32_t dst_stride_3x = dst_stride_2x + dst_stride; + + __m128i shuf1 = {0x807060504030201, 0x100F0E0D0C0B0A09}; + __m128i shuf2 = {0x908070605040302, 0x11100F0E0D0C0B0A}; + __m128i edge_idx = {0x403000201, 0x0}; + __m128i const1 = __lsx_vldi(1); + __m128i cmp_minus10, cmp_plus10, diff_minus10, diff_plus10, cmp_minus11; + __m128i cmp_plus11, diff_minus11, diff_plus11, cmp_minus12, cmp_plus12; + __m128i diff_minus12, diff_plus12, cmp_minus13, cmp_plus13, diff_minus13; + __m128i diff_plus13, src_minus14, src_plus13; + __m128i offset_mask0, offset_mask1, offset_mask2, offset_mask3; + __m128i src10, src_minus10, dst0, src11, src_minus11, dst1; + __m128i src12, src_minus12, dst2, src13, src_minus13, dst3; + __m128i src_zero0, src_plus10, src_zero1, src_plus11, src_zero2; + __m128i src_zero3, sao_offset, src_plus12; + + sao_offset = __lsx_vld(sao_offset_val, 0); + sao_offset = __lsx_vpickev_b(sao_offset, sao_offset); + + for (; height; height -= 4) { + src_orig = src - 1; + dst_orig = dst; + src_minus11 = __lsx_vld(src_orig, 0); + DUP2_ARG2(__lsx_vldx, src_orig, src_stride, src_orig, src_stride_2x, + src_minus12, src_minus13); + src_minus14 = __lsx_vldx(src_orig, src_stride_3x); + + for (v_cnt = 0; v_cnt < width; v_cnt += 16) { + src_minus10 = __lsx_vld(src_orig - src_stride, 0); + src_orig += 16; + src10 = __lsx_vld(src_orig, 0); + DUP2_ARG2(__lsx_vldx, src_orig, src_stride, src_orig, + src_stride_2x, src11, src12); + src13 = __lsx_vldx(src_orig, src_stride_3x); + src_plus13 = __lsx_vld(src + v_cnt + src_stride_4x, 1); + + DUP4_ARG3(__lsx_vshuf_b, src10, src_minus11, shuf1, src11, + src_minus12, shuf1, src12, src_minus13, shuf1, + src13, src_minus14, shuf1, src_zero0, src_zero1, + src_zero2, src_zero3); + DUP2_ARG3(__lsx_vshuf_b, src11, src_minus12, shuf2, src12, + src_minus13, shuf2, src_plus10, src_plus11); + src_plus12 = __lsx_vshuf_b(src13, src_minus14, shuf2); + + DUP4_ARG2(__lsx_vseq_b, src_zero0, src_minus10, src_zero0, + src_plus10, src_zero1, src_minus11, src_zero1, + src_plus11, cmp_minus10, cmp_plus10, + cmp_minus11, cmp_plus11); + DUP4_ARG2(__lsx_vseq_b, src_zero2, src_minus12, src_zero2, + src_plus12, src_zero3, src_minus13, src_zero3, + src_plus13, cmp_minus12, cmp_plus12, + cmp_minus13, cmp_plus13); + DUP4_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_plus10, + cmp_plus10, cmp_minus11, cmp_minus11, cmp_plus11, + cmp_plus11, diff_minus10, diff_plus10, diff_minus11, + diff_plus11); + DUP4_ARG2(__lsx_vnor_v, cmp_minus12, cmp_minus12, cmp_plus12, + cmp_plus12, cmp_minus13, cmp_minus13, cmp_plus13, + cmp_plus13, diff_minus12, diff_plus12, diff_minus13, + diff_plus13); + DUP4_ARG2(__lsx_vsle_bu, src_zero0, src_minus10, src_zero0, + src_plus10, src_zero1, src_minus11, src_zero1, + src_plus11, cmp_minus10, cmp_plus10, cmp_minus11, + cmp_plus11); + DUP4_ARG2(__lsx_vsle_bu, src_zero2, src_minus12, src_zero2, + src_plus12, src_zero3, src_minus13, src_zero3, + src_plus13, cmp_minus12, cmp_plus12, cmp_minus13, + cmp_plus13); + DUP4_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_plus10, + cmp_plus10, cmp_minus11, cmp_minus11, cmp_plus11, + cmp_plus11, cmp_minus10, cmp_plus10, cmp_minus11, + cmp_plus11); + DUP4_ARG2(__lsx_vnor_v, cmp_minus12, cmp_minus12, cmp_plus12, + cmp_plus12, cmp_minus13, cmp_minus13, cmp_plus13, + cmp_plus13, cmp_minus12, cmp_plus12, cmp_minus13, + cmp_plus13); + DUP4_ARG3(__lsx_vbitsel_v, diff_minus10, const1, cmp_minus10, + diff_plus10, const1, cmp_plus10, diff_minus11, const1, + cmp_minus11, diff_plus11, const1, cmp_plus11, + diff_minus10, diff_plus10, diff_minus11, diff_plus11); + DUP4_ARG3(__lsx_vbitsel_v, diff_minus12, const1, cmp_minus12, + diff_plus12, const1, cmp_plus12, diff_minus13, const1, + cmp_minus13, diff_plus13, const1, cmp_plus13, + diff_minus12, diff_plus12, diff_minus13, diff_plus13); + + DUP4_ARG2(__lsx_vadd_b, diff_minus10, diff_plus10, diff_minus11, + diff_plus11, diff_minus12, diff_plus12, diff_minus13, + diff_plus13, offset_mask0, offset_mask1, offset_mask2, + offset_mask3); + DUP4_ARG2(__lsx_vaddi_bu, offset_mask0, 2, offset_mask1, 2, + offset_mask2, 2, offset_mask3, 2, offset_mask0, + offset_mask1, offset_mask2, offset_mask3); + + DUP2_ARG3(__lsx_vshuf_b, edge_idx, edge_idx, offset_mask0, + sao_offset, sao_offset, offset_mask0, offset_mask0, + offset_mask0); + DUP2_ARG3(__lsx_vshuf_b, edge_idx, edge_idx, offset_mask1, + sao_offset, sao_offset, offset_mask1, offset_mask1, + offset_mask1); + DUP2_ARG3(__lsx_vshuf_b, edge_idx, edge_idx, offset_mask2, + sao_offset, sao_offset, offset_mask2, offset_mask2, + offset_mask2); + DUP2_ARG3(__lsx_vshuf_b, edge_idx, edge_idx, offset_mask3, + sao_offset, sao_offset, offset_mask3, offset_mask3, + offset_mask3); + + DUP4_ARG2(__lsx_vxori_b, src_zero0, 128, src_zero1, 128, src_zero2, + 128, src_zero3, 128, src_zero0, src_zero1, src_zero2, + src_zero3); + DUP4_ARG2(__lsx_vsadd_b, src_zero0, offset_mask0, src_zero1, + offset_mask1, src_zero2, offset_mask2, src_zero3, + offset_mask3, dst0, dst1, dst2, dst3); + DUP4_ARG2(__lsx_vxori_b, dst0, 128, dst1, 128, dst2, 128, dst3, + 128, dst0, dst1, dst2, dst3); + + src_minus11 = src10; + src_minus12 = src11; + src_minus13 = src12; + src_minus14 = src13; + + __lsx_vst(dst0, dst_orig, 0); + __lsx_vstx(dst1, dst_orig, dst_stride); + __lsx_vstx(dst2, dst_orig, dst_stride_2x); + __lsx_vstx(dst3, dst_orig, dst_stride_3x); + dst_orig += 16; + } + src += src_stride_4x; + dst += dst_stride_4x; + } +} + +static void hevc_sao_edge_filter_135degree_4width_lsx(uint8_t *dst, + int32_t dst_stride, + uint8_t *src, + int32_t src_stride, + int16_t *sao_offset_val, + int32_t height) +{ + uint8_t *src_orig; + const int32_t src_stride_2x = (src_stride << 1); + const int32_t dst_stride_2x = (dst_stride << 1); + + __m128i shuf1 = {0x807060504030201, 0x100F0E0D0C0B0A09}; + __m128i shuf2 = {0x908070605040302, 0x11100F0E0D0C0B0A}; + __m128i edge_idx = {0x403000201, 0x0}; + __m128i const1 = __lsx_vldi(1); + __m128i offset, sao_offset = __lsx_vld(sao_offset_val, 0); + __m128i src_zero0, src_zero1, dst0; + __m128i cmp_minus10, diff_minus10, cmp_minus11, diff_minus11; + __m128i src_minus10, src10, src_minus11, src11; + __m128i offset_mask0, offset_mask1; + __m128i zeros = {0}; + + sao_offset = __lsx_vpickev_b(sao_offset, sao_offset); + src_orig = src - 1; + + /* load in advance */ + DUP2_ARG2(__lsx_vld, src_orig - src_stride, 0, src_orig, 0, + src_minus10, src_minus11); + DUP2_ARG2(__lsx_vldx, src_orig, src_stride, src_orig, src_stride_2x, + src10, src11); + + for (height -= 2; height; height -= 2) { + src_orig += src_stride_2x; + + DUP2_ARG3(__lsx_vshuf_b, zeros, src_minus11, shuf1, zeros, src10, + shuf1, src_zero0, src_zero1); + DUP2_ARG3(__lsx_vshuf_b, zeros, src_minus10, shuf2, zeros, src_minus11, + shuf2, src_minus10, src_minus11); + + DUP2_ARG2(__lsx_vilvl_b, src10, src_minus10, src11, src_minus11, + src_minus10, src_minus11); + DUP2_ARG2(__lsx_vilvl_b, src_zero0, src_zero0, src_zero1, src_zero1, + src_zero0, src_zero1); + DUP2_ARG2(__lsx_vseq_b, src_zero0, src_minus10, src_zero1, src_minus11, + cmp_minus10, cmp_minus11); + DUP2_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_minus11, + cmp_minus11, diff_minus10, diff_minus11); + DUP2_ARG2(__lsx_vsle_bu, src_zero0, src_minus10, src_zero1, + src_minus11, cmp_minus10, cmp_minus11); + DUP2_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_minus11, + cmp_minus11, cmp_minus10, cmp_minus11); + DUP2_ARG3(__lsx_vbitsel_v, diff_minus10, const1, cmp_minus10, + diff_minus11, const1, cmp_minus11, diff_minus10, diff_minus11); + + DUP2_ARG2(__lsx_vhaddw_hu_bu, diff_minus10, diff_minus10, diff_minus11, + diff_minus11, offset_mask0, offset_mask1); + DUP2_ARG2(__lsx_vaddi_hu, offset_mask0, 2, offset_mask1, 2, + offset_mask0, offset_mask1); + DUP2_ARG2(__lsx_vpickev_b, offset_mask1, offset_mask0, src_zero1, + src_zero0, offset, dst0); + DUP2_ARG3(__lsx_vshuf_b, edge_idx, edge_idx, offset, sao_offset, + sao_offset, offset, offset, offset); + dst0 = __lsx_vxori_b(dst0, 128); + dst0 = __lsx_vsadd_b(dst0, offset); + dst0 = __lsx_vxori_b(dst0, 128); + + src_minus10 = src10; + src_minus11 = src11; + + /* load in advance */ + DUP2_ARG2(__lsx_vldx, src_orig, src_stride, src_orig, src_stride_2x, + src10, src11); + + __lsx_vstelm_w(dst0, dst, 0, 0); + __lsx_vstelm_w(dst0, dst + dst_stride, 0, 2); + dst += dst_stride_2x; + } + + DUP2_ARG3(__lsx_vshuf_b, zeros, src_minus11, shuf1, zeros, src10, shuf1, + src_zero0, src_zero1); + DUP2_ARG3(__lsx_vshuf_b, zeros, src_minus10, shuf2, zeros, src_minus11, + shuf2, src_minus10, src_minus11); + + DUP2_ARG2(__lsx_vilvl_b, src10, src_minus10, src11, src_minus11, + src_minus10, src_minus11); + DUP2_ARG2(__lsx_vilvl_b, src_zero0, src_zero0, src_zero1, src_zero1, + src_zero0, src_zero1); + DUP2_ARG2(__lsx_vseq_b, src_zero0, src_minus10, src_zero1, src_minus11, + cmp_minus10, cmp_minus11); + DUP2_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_minus11, + cmp_minus11, diff_minus10, diff_minus11); + DUP2_ARG2(__lsx_vsle_bu, src_zero0, src_minus10, src_zero1, src_minus11, + cmp_minus10, cmp_minus11); + DUP2_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_minus11, cmp_minus11, + cmp_minus10, cmp_minus11); + DUP2_ARG3(__lsx_vbitsel_v, diff_minus10, const1, cmp_minus10, diff_minus11, + const1, cmp_minus11, diff_minus10, diff_minus11); + + DUP2_ARG2(__lsx_vhaddw_hu_bu, diff_minus10, diff_minus10, diff_minus11, + diff_minus11, offset_mask0, offset_mask1); + DUP2_ARG2(__lsx_vaddi_hu, offset_mask0, 2, offset_mask1, 2, offset_mask0, + offset_mask1); + DUP2_ARG2(__lsx_vpickev_b, offset_mask1, offset_mask0, src_zero1, + src_zero0, offset, dst0); + DUP2_ARG3(__lsx_vshuf_b, edge_idx, edge_idx, offset, sao_offset, + sao_offset, offset, offset, offset); + dst0 = __lsx_vxori_b(dst0, 128); + dst0 = __lsx_vsadd_b(dst0, offset); + dst0 = __lsx_vxori_b(dst0, 128); + + __lsx_vstelm_w(dst0, dst, 0, 0); + __lsx_vstelm_w(dst0, dst + dst_stride, 0, 2); + dst += dst_stride_2x; +} + +static void hevc_sao_edge_filter_135degree_8width_lsx(uint8_t *dst, + int32_t dst_stride, + uint8_t *src, + int32_t src_stride, + int16_t *sao_offset_val, + int32_t height) +{ + uint8_t *src_orig; + const int32_t src_stride_2x = (src_stride << 1); + const int32_t dst_stride_2x = (dst_stride << 1); + + __m128i shuf1 = {0x807060504030201, 0x100F0E0D0C0B0A09}; + __m128i shuf2 = {0x908070605040302, 0x11100F0E0D0C0B0A}; + __m128i edge_idx = {0x403000201, 0x0}; + __m128i const1 = __lsx_vldi(1); + __m128i offset, sao_offset = __lsx_vld(sao_offset_val, 0); + __m128i cmp_minus10, diff_minus10, cmp_minus11, diff_minus11; + __m128i src_minus10, src10, src_minus11, src11; + __m128i src_zero0, src_zero1, dst0; + __m128i offset_mask0, offset_mask1; + __m128i zeros = {0}; + + sao_offset = __lsx_vpickev_b(sao_offset, sao_offset); + src_orig = src - 1; + + /* load in advance */ + DUP2_ARG2(__lsx_vld, src_orig - src_stride, 0, src_orig, 0, + src_minus10, src_minus11); + DUP2_ARG2(__lsx_vldx, src_orig, src_stride, src_orig, src_stride_2x, + src10, src11); + + for (height -= 2; height; height -= 2) { + src_orig += src_stride_2x; + + DUP2_ARG3(__lsx_vshuf_b, zeros, src_minus11, shuf1, zeros, src10, + shuf1, src_zero0, src_zero1); + DUP2_ARG3(__lsx_vshuf_b, zeros, src_minus10, shuf2, zeros, src_minus11, + shuf2, src_minus10, src_minus11); + + DUP2_ARG2(__lsx_vilvl_b, src10, src_minus10, src11, src_minus11, + src_minus10, src_minus11); + DUP2_ARG2(__lsx_vilvl_b, src_zero0, src_zero0, src_zero1, src_zero1, + src_zero0, src_zero1); + DUP2_ARG2(__lsx_vseq_b, src_zero0, src_minus10, src_zero1, src_minus11, + cmp_minus10, cmp_minus11); + DUP2_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_minus11, + cmp_minus11, diff_minus10, diff_minus11); + DUP2_ARG2(__lsx_vsle_bu, src_zero0, src_minus10, src_zero1, + src_minus11, cmp_minus10, cmp_minus11); + DUP2_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_minus11, + cmp_minus11, cmp_minus10, cmp_minus11); + DUP2_ARG3(__lsx_vbitsel_v, diff_minus10, const1, cmp_minus10, + diff_minus11, const1, cmp_minus11, diff_minus10, diff_minus11); + + DUP2_ARG2(__lsx_vhaddw_hu_bu, diff_minus10, diff_minus10, diff_minus11, + diff_minus11, offset_mask0, offset_mask1); + DUP2_ARG2(__lsx_vaddi_hu, offset_mask0, 2, offset_mask1, 2, + offset_mask0, offset_mask1); + DUP2_ARG2(__lsx_vpickev_b, offset_mask1, offset_mask0, src_zero1, + src_zero0, offset, dst0); + DUP2_ARG3(__lsx_vshuf_b, edge_idx, edge_idx, offset, sao_offset, + sao_offset, offset, offset, offset); + dst0 = __lsx_vxori_b(dst0, 128); + dst0 = __lsx_vsadd_b(dst0, offset); + dst0 = __lsx_vxori_b(dst0, 128); + + src_minus10 = src10; + src_minus11 = src11; + + /* load in advance */ + DUP2_ARG2(__lsx_vldx, src_orig, src_stride, src_orig, src_stride_2x, + src10, src11); + + __lsx_vstelm_d(dst0, dst, 0, 0); + __lsx_vstelm_d(dst0, dst + dst_stride, 0, 1); + dst += dst_stride_2x; + } + + DUP2_ARG3(__lsx_vshuf_b, zeros, src_minus11, shuf1, zeros, src10, shuf1, + src_zero0, src_zero1); + DUP2_ARG3(__lsx_vshuf_b, zeros, src_minus10, shuf2, zeros, src_minus11, + shuf2, src_minus10, src_minus11); + + DUP2_ARG2(__lsx_vilvl_b, src10, src_minus10, src11, src_minus11, + src_minus10, src_minus11); + DUP2_ARG2(__lsx_vilvl_b, src_zero0, src_zero0, src_zero1, src_zero1, + src_zero0, src_zero1); + DUP2_ARG2(__lsx_vseq_b, src_zero0, src_minus10, src_zero1, src_minus11, + cmp_minus10, cmp_minus11); + DUP2_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_minus11, cmp_minus11, + diff_minus10, diff_minus11); + DUP2_ARG2(__lsx_vsle_bu, src_zero0, src_minus10, src_zero1, src_minus11, + cmp_minus10, cmp_minus11); + DUP2_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_minus11, cmp_minus11, + cmp_minus10, cmp_minus11); + DUP2_ARG3(__lsx_vbitsel_v, diff_minus10, const1, cmp_minus10, diff_minus11, + const1, cmp_minus11, diff_minus10, diff_minus11); + + DUP2_ARG2(__lsx_vhaddw_hu_bu, diff_minus10, diff_minus10, diff_minus11, + diff_minus11, offset_mask0, offset_mask1); + DUP2_ARG2(__lsx_vaddi_hu, offset_mask0, 2, offset_mask1, 2, offset_mask0, + offset_mask1); + DUP2_ARG2(__lsx_vpickev_b, offset_mask1, offset_mask0, src_zero1, + src_zero0, offset, dst0); + DUP2_ARG3(__lsx_vshuf_b, edge_idx, edge_idx, offset, sao_offset, + sao_offset, offset, offset, offset); + dst0 = __lsx_vxori_b(dst0, 128); + dst0 = __lsx_vsadd_b(dst0, offset); + dst0 = __lsx_vxori_b(dst0, 128); + + __lsx_vstelm_d(dst0, dst, 0, 0); + __lsx_vstelm_d(dst0, dst + dst_stride, 0, 1); +} + +static void hevc_sao_edge_filter_135degree_16multiple_lsx(uint8_t *dst, + int32_t dst_stride, + uint8_t *src, + int32_t src_stride, + int16_t *sao_offset_val, + int32_t width, + int32_t height) +{ + uint8_t *src_orig, *dst_orig; + int32_t v_cnt; + const int32_t src_stride_2x = (src_stride << 1); + const int32_t dst_stride_2x = (dst_stride << 1); + const int32_t src_stride_4x = (src_stride << 2); + const int32_t dst_stride_4x = (dst_stride << 2); + const int32_t src_stride_3x = src_stride_2x + src_stride; + const int32_t dst_stride_3x = dst_stride_2x + dst_stride; + + __m128i shuf1 = {0x807060504030201, 0x100F0E0D0C0B0A09}; + __m128i shuf2 = {0x908070605040302, 0x11100F0E0D0C0B0A}; + __m128i edge_idx = {0x403000201, 0x0}; + __m128i const1 = __lsx_vldi(1); + __m128i dst0, dst1, dst2, dst3; + __m128i cmp_minus10, cmp_minus11, cmp_minus12, cmp_minus13, cmp_plus10; + __m128i cmp_plus11, cmp_plus12, cmp_plus13, diff_minus10, diff_minus11; + __m128i diff_minus12, diff_minus13, diff_plus10, diff_plus11, diff_plus12; + __m128i diff_plus13, src10, src11, src12, src13, src_minus10, src_minus11; + __m128i src_plus10, src_plus11, src_plus12, src_plus13; + __m128i src_minus12, src_minus13, src_zero0, src_zero1, src_zero2, src_zero3; + __m128i offset_mask0, offset_mask1, offset_mask2, offset_mask3, sao_offset; + + sao_offset = __lsx_vld(sao_offset_val, 0); + sao_offset = __lsx_vpickev_b(sao_offset, sao_offset); + + for (; height; height -= 4) { + src_orig = src - 1; + dst_orig = dst; + + src_minus11 = __lsx_vld(src_orig, 0); + DUP2_ARG2(__lsx_vldx, src_orig, src_stride, src_orig, src_stride_2x, + src_plus10, src_plus11); + src_plus12 = __lsx_vldx(src_orig, src_stride_3x); + + for (v_cnt = 0; v_cnt < width; v_cnt += 16) { + src_minus10 = __lsx_vld(src_orig - src_stride, 2); + src_plus13 = __lsx_vldx(src_orig, src_stride_4x); + src_orig += 16; + src10 = __lsx_vld(src_orig, 0); + DUP2_ARG2(__lsx_vldx, src_orig, src_stride, src_orig, src_stride_2x, + src11, src12); + src13 =__lsx_vldx(src_orig, src_stride_3x); + + DUP4_ARG3(__lsx_vshuf_b, src10, src_minus11, shuf1, src11, + src_plus10, shuf1, src12, src_plus11, shuf1, src13, + src_plus12, shuf1, src_zero0, src_zero1, src_zero2, + src_zero3); + src_minus11 = __lsx_vshuf_b(src10, src_minus11, shuf2); + DUP2_ARG3(__lsx_vshuf_b, src11, src_plus10, shuf2, src12, + src_plus11, shuf2, src_minus12, src_minus13); + + DUP4_ARG2(__lsx_vseq_b, src_zero0, src_minus10, src_zero0, + src_plus10, src_zero1, src_minus11, src_zero1, + src_plus11, cmp_minus10, cmp_plus10, cmp_minus11, + cmp_plus11); + DUP4_ARG2(__lsx_vseq_b, src_zero2, src_minus12, src_zero2, + src_plus12, src_zero3, src_minus13, src_zero3, + src_plus13, cmp_minus12, cmp_plus12, cmp_minus13, + cmp_plus13); + DUP4_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_plus10, + cmp_plus10, cmp_minus11, cmp_minus11, cmp_plus11, + cmp_plus11, diff_minus10, diff_plus10, diff_minus11, + diff_plus11); + DUP4_ARG2(__lsx_vnor_v, cmp_minus12, cmp_minus12, cmp_plus12, + cmp_plus12, cmp_minus13, cmp_minus13, cmp_plus13, + cmp_plus13, diff_minus12, diff_plus12, diff_minus13, + diff_plus13); + DUP4_ARG2(__lsx_vsle_bu, src_zero0, src_minus10, src_zero0, + src_plus10, src_zero1, src_minus11, src_zero1, src_plus11, + cmp_minus10, cmp_plus10, cmp_minus11, cmp_plus11); + DUP4_ARG2(__lsx_vsle_bu, src_zero2, src_minus12, src_zero2, + src_plus12, src_zero3, src_minus13, src_zero3, src_plus13, + cmp_minus12, cmp_plus12, cmp_minus13, cmp_plus13); + DUP4_ARG2(__lsx_vnor_v, cmp_minus10, cmp_minus10, cmp_plus10, + cmp_plus10, cmp_minus11, cmp_minus11, cmp_plus11, + cmp_plus11, cmp_minus10, cmp_plus10, cmp_minus11, + cmp_plus11); + DUP4_ARG2(__lsx_vnor_v, cmp_minus12, cmp_minus12, cmp_plus12, + cmp_plus12, cmp_minus13, cmp_minus13, cmp_plus13, + cmp_plus13, cmp_minus12, cmp_plus12, cmp_minus13, + cmp_plus13); + DUP4_ARG3(__lsx_vbitsel_v, diff_minus10, const1, cmp_minus10, + diff_plus10, const1, cmp_plus10, diff_minus11, const1, + cmp_minus11, diff_plus11, const1, cmp_plus11, + diff_minus10, diff_plus10, diff_minus11, diff_plus11); + DUP4_ARG3(__lsx_vbitsel_v, diff_minus12, const1, cmp_minus12, + diff_plus12, const1, cmp_plus12, diff_minus13, const1, + cmp_minus13, diff_plus13, const1, cmp_plus13, + diff_minus12, diff_plus12, diff_minus13, diff_plus13); + + DUP4_ARG2(__lsx_vadd_b, diff_minus10, diff_plus10, diff_minus11, + diff_plus11, diff_minus12, diff_plus12, diff_minus13, + diff_plus13, offset_mask0, offset_mask1, offset_mask2, + offset_mask3); + DUP4_ARG2(__lsx_vaddi_bu, offset_mask0, 2, offset_mask1, 2, + offset_mask2, 2, offset_mask3, 2, offset_mask0, + offset_mask1, offset_mask2, offset_mask3); + + DUP2_ARG3(__lsx_vshuf_b, edge_idx, edge_idx, offset_mask0, + sao_offset, sao_offset, offset_mask0, offset_mask0, + offset_mask0); + DUP2_ARG3(__lsx_vshuf_b, edge_idx, edge_idx, offset_mask1, + sao_offset, sao_offset, offset_mask1, offset_mask1, + offset_mask1); + DUP2_ARG3(__lsx_vshuf_b, edge_idx, edge_idx, offset_mask2, + sao_offset, sao_offset, offset_mask2, offset_mask2, + offset_mask2); + DUP2_ARG3(__lsx_vshuf_b, edge_idx, edge_idx, offset_mask3, + sao_offset, sao_offset, offset_mask3, offset_mask3, + offset_mask3); + + DUP4_ARG2(__lsx_vxori_b, src_zero0, 128, src_zero1, 128, + src_zero2, 128, src_zero3, 128, src_zero0, src_zero1, + src_zero2, src_zero3); + DUP4_ARG2(__lsx_vsadd_b, src_zero0, offset_mask0, src_zero1, + offset_mask1, src_zero2, offset_mask2, src_zero3, + offset_mask3, dst0, dst1, dst2, dst3); + DUP4_ARG2(__lsx_vxori_b, dst0, 128, dst1, 128, dst2, 128, dst3, + 128, dst0, dst1, dst2, dst3); + + src_minus11 = src10; + src_plus10 = src11; + src_plus11 = src12; + src_plus12 = src13; + + __lsx_vst(dst0, dst_orig, 0); + __lsx_vstx(dst1, dst_orig, dst_stride); + __lsx_vstx(dst2, dst_orig, dst_stride_2x); + __lsx_vstx(dst3, dst_orig, dst_stride_3x); + dst_orig += 16; + } + + src += src_stride_4x; + dst += dst_stride_4x; + } +} + +void ff_hevc_sao_edge_filter_8_lsx(uint8_t *dst, uint8_t *src, + ptrdiff_t stride_dst, + int16_t *sao_offset_val, + int eo, int width, int height) +{ + ptrdiff_t stride_src = (2 * MAX_PB_SIZE + AV_INPUT_BUFFER_PADDING_SIZE); + + switch (eo) { + case 0: + if (width >> 4) { + hevc_sao_edge_filter_0degree_16multiple_lsx(dst, stride_dst, + src, stride_src, + sao_offset_val, + width - (width & 0x0F), + height); + dst += width & 0xFFFFFFF0; + src += width & 0xFFFFFFF0; + width &= 0x0F; + } + + if (width >> 3) { + hevc_sao_edge_filter_0degree_8width_lsx(dst, stride_dst, + src, stride_src, + sao_offset_val, height); + dst += 8; + src += 8; + width &= 0x07; + } + + if (width) { + hevc_sao_edge_filter_0degree_4width_lsx(dst, stride_dst, + src, stride_src, + sao_offset_val, height); + } + break; + + case 1: + if (width >> 4) { + hevc_sao_edge_filter_90degree_16multiple_lsx(dst, stride_dst, + src, stride_src, + sao_offset_val, + width - (width & 0x0F), + height); + dst += width & 0xFFFFFFF0; + src += width & 0xFFFFFFF0; + width &= 0x0F; + } + + if (width >> 3) { + hevc_sao_edge_filter_90degree_8width_lsx(dst, stride_dst, + src, stride_src, + sao_offset_val, height); + dst += 8; + src += 8; + width &= 0x07; + } + + if (width) { + hevc_sao_edge_filter_90degree_4width_lsx(dst, stride_dst, + src, stride_src, + sao_offset_val, height); + } + break; + + case 2: + if (width >> 4) { + hevc_sao_edge_filter_45degree_16multiple_lsx(dst, stride_dst, + src, stride_src, + sao_offset_val, + width - (width & 0x0F), + height); + dst += width & 0xFFFFFFF0; + src += width & 0xFFFFFFF0; + width &= 0x0F; + } + + if (width >> 3) { + hevc_sao_edge_filter_45degree_8width_lsx(dst, stride_dst, + src, stride_src, + sao_offset_val, height); + dst += 8; + src += 8; + width &= 0x07; + } + + if (width) { + hevc_sao_edge_filter_45degree_4width_lsx(dst, stride_dst, + src, stride_src, + sao_offset_val, height); + } + break; + + case 3: + if (width >> 4) { + hevc_sao_edge_filter_135degree_16multiple_lsx(dst, stride_dst, + src, stride_src, + sao_offset_val, + width - (width & 0x0F), + height); + dst += width & 0xFFFFFFF0; + src += width & 0xFFFFFFF0; + width &= 0x0F; + } + + if (width >> 3) { + hevc_sao_edge_filter_135degree_8width_lsx(dst, stride_dst, + src, stride_src, + sao_offset_val, height); + dst += 8; + src += 8; + width &= 0x07; + } + + if (width) { + hevc_sao_edge_filter_135degree_4width_lsx(dst, stride_dst, + src, stride_src, + sao_offset_val, height); + } + break; + } +} diff --git a/libavcodec/loongarch/hevc_mc_bi_lsx.c b/libavcodec/loongarch/hevc_mc_bi_lsx.c new file mode 100644 index 000000000..9092fdccb --- /dev/null +++ b/libavcodec/loongarch/hevc_mc_bi_lsx.c @@ -0,0 +1,2289 @@ +/* + * Copyright (c) 2022 Loongson Technology Corporation Limited + * Contributed by Lu Wang + * Hao Chen + * + * 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/loongarch/loongson_intrinsics.h" +#include "hevcdsp_lsx.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 +}; + +static av_always_inline __m128i +hevc_bi_rnd_clip(__m128i in0, __m128i vec0, __m128i in1, __m128i vec1) +{ + __m128i out; + + vec0 = __lsx_vsadd_h(in0, vec0); + vec1 = __lsx_vsadd_h(in1, vec1); + out = __lsx_vssrarni_bu_h(vec1, vec0, 7); + return out; +} + +/* hevc_bi_copy: dst = av_clip_uint8((src0 << 6 + src1) >> 7) */ +static +void hevc_bi_copy_4w_lsx(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 loop_cnt = height >> 3; + int32_t res = (height & 0x07) >> 1; + int32_t src_stride_2x = (src_stride << 1); + int32_t dst_stride_2x = (dst_stride << 1); + int32_t src_stride_4x = (src_stride << 2); + int32_t dst_stride_4x = (dst_stride << 2); + int32_t src2_stride_2x = (src2_stride << 1); + int32_t src2_stride_4x = (src2_stride << 2); + int32_t src_stride_3x = src_stride_2x + src_stride; + int32_t dst_stride_3x = dst_stride_2x + dst_stride; + int32_t src2_stride_3x = src2_stride_2x + src2_stride; + __m128i src0, src1; + __m128i zero = __lsx_vldi(0); + __m128i in0, in1, in2, in3; + __m128i tmp0, tmp1, tmp2, tmp3; + __m128i reg0, reg1, reg2, reg3; + __m128i dst0, dst1, dst2, dst3; + + for (;loop_cnt--;) { + reg0 = __lsx_vldrepl_w(src0_ptr, 0); + reg1 = __lsx_vldrepl_w(src0_ptr + src_stride, 0); + reg2 = __lsx_vldrepl_w(src0_ptr + src_stride_2x, 0); + reg3 = __lsx_vldrepl_w(src0_ptr + src_stride_3x, 0); + src0_ptr += src_stride_4x; + DUP2_ARG2(__lsx_vilvl_w, reg1, reg0, reg3, reg2, tmp0, tmp1); + src0 = __lsx_vilvl_d(tmp1, tmp0); + reg0 = __lsx_vldrepl_w(src0_ptr, 0); + reg1 = __lsx_vldrepl_w(src0_ptr + src_stride, 0); + reg2 = __lsx_vldrepl_w(src0_ptr + src_stride_2x, 0); + reg3 = __lsx_vldrepl_w(src0_ptr + src_stride_3x, 0); + DUP2_ARG2(__lsx_vilvl_w, reg1, reg0, reg3, reg2, tmp0, tmp1); + src1 = __lsx_vilvl_d(tmp1, tmp0); + src0_ptr += src_stride_4x; + + tmp0 = __lsx_vldrepl_d(src1_ptr, 0); + tmp1 = __lsx_vldrepl_d(src1_ptr + src2_stride, 0); + tmp2 = __lsx_vldrepl_d(src1_ptr + src2_stride_2x, 0); + tmp3 = __lsx_vldrepl_d(src1_ptr + src2_stride_3x, 0); + src1_ptr += src2_stride_4x; + DUP2_ARG2(__lsx_vilvl_d, tmp1, tmp0, tmp3, tmp2, in0, in1); + tmp0 = __lsx_vldrepl_d(src1_ptr, 0); + tmp1 = __lsx_vldrepl_d(src1_ptr + src2_stride, 0); + tmp2 = __lsx_vldrepl_d(src1_ptr + src2_stride_2x, 0); + tmp3 = __lsx_vldrepl_d(src1_ptr + src2_stride_3x, 0); + src1_ptr += src2_stride_4x; + DUP2_ARG2(__lsx_vilvl_d, tmp1, tmp0, tmp3, tmp2, in2, in3); + DUP2_ARG2(__lsx_vsllwil_hu_bu, src0, 6, src1, 6, dst0, dst2); + DUP2_ARG2(__lsx_vilvh_b, zero, src0, zero, src1, dst1, dst3); + DUP2_ARG2(__lsx_vslli_h, dst1, 6, dst3, 6, dst1, dst3); + dst0 = hevc_bi_rnd_clip(in0, dst0, in1, dst1); + dst1 = hevc_bi_rnd_clip(in2, dst2, in3, dst3); + __lsx_vstelm_w(dst0, dst, 0, 0); + __lsx_vstelm_w(dst0, dst + dst_stride, 0, 1); + __lsx_vstelm_w(dst0, dst + dst_stride_2x, 0, 2); + __lsx_vstelm_w(dst0, dst + dst_stride_3x, 0, 3); + dst += dst_stride_4x; + __lsx_vstelm_w(dst1, dst, 0, 0); + __lsx_vstelm_w(dst1, dst + dst_stride, 0, 1); + __lsx_vstelm_w(dst1, dst + dst_stride_2x, 0, 2); + __lsx_vstelm_w(dst1, dst + dst_stride_3x, 0, 3); + dst += dst_stride_4x; + } + for(;res--;) { + reg0 = __lsx_vldrepl_w(src0_ptr, 0); + reg1 = __lsx_vldrepl_w(src0_ptr + src_stride, 0); + reg2 = __lsx_vldrepl_d(src1_ptr, 0); + reg3 = __lsx_vldrepl_d(src1_ptr + src2_stride, 0); + src0 = __lsx_vilvl_w(reg1, reg0); + in0 = __lsx_vilvl_d(reg3, reg2); + dst0 = __lsx_vsllwil_hu_bu(src0, 6); + dst0 = __lsx_vsadd_h(dst0, in0); + dst0 = __lsx_vssrarni_bu_h(dst0, dst0, 7); + __lsx_vstelm_w(dst0, dst, 0, 0); + __lsx_vstelm_w(dst0, dst + dst_stride, 0, 1); + src0_ptr += src_stride_2x; + src1_ptr += src2_stride_2x; + dst += dst_stride_2x; + } +} + +static +void hevc_bi_copy_6w_lsx(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 loop_cnt; + int32_t res = (height & 0x07) >> 1; + int32_t src_stride_2x = (src_stride << 1); + int32_t dst_stride_2x = (dst_stride << 1); + int32_t src_stride_4x = (src_stride << 2); + int32_t dst_stride_4x = (dst_stride << 2); + int32_t src2_stride_x = (src2_stride << 1); + int32_t src2_stride_2x = (src2_stride << 2); + int32_t src_stride_3x = src_stride_2x + src_stride; + int32_t dst_stride_3x = dst_stride_2x + dst_stride; + int32_t src2_stride_3x = src2_stride_2x + src2_stride_x; + __m128i out0, out1, out2, out3; + __m128i zero = __lsx_vldi(0); + __m128i src0, src1, src2, src3; + __m128i in0, in1, in2, in3, in4, in5, in6, in7; + __m128i dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + __m128i reg0, reg1, reg2, reg3; + + for (loop_cnt = (height >> 3); loop_cnt--;) { + reg0 = __lsx_vldrepl_d(src0_ptr, 0); + reg1 = __lsx_vldrepl_d(src0_ptr + src_stride, 0); + reg2 = __lsx_vldrepl_d(src0_ptr + src_stride_2x, 0); + reg3 = __lsx_vldrepl_d(src0_ptr + src_stride_3x, 0); + DUP2_ARG2(__lsx_vilvl_d, reg1, reg0, reg3, reg2, src0, src1); + src0_ptr += src_stride_4x; + reg0 = __lsx_vldrepl_d(src0_ptr, 0); + reg1 = __lsx_vldrepl_d(src0_ptr + src_stride, 0); + reg2 = __lsx_vldrepl_d(src0_ptr + src_stride_2x, 0); + reg3 = __lsx_vldrepl_d(src0_ptr + src_stride_3x, 0); + DUP2_ARG2(__lsx_vilvl_d, reg1, reg0, reg3, reg2, src2, src3); + src0_ptr += src_stride_4x; + in0 = __lsx_vld(src1_ptr, 0); + DUP2_ARG2(__lsx_vldx, src1_ptr, src2_stride_x, src1_ptr, + src2_stride_2x, in1, in2); + in3 = __lsx_vldx(src1_ptr, src2_stride_3x); + src1_ptr += src2_stride_2x; + in4 = __lsx_vld(src1_ptr, 0); + DUP2_ARG2(__lsx_vldx, src1_ptr, src2_stride_x, src1_ptr, + src2_stride_2x, in5, in6); + in7 = __lsx_vldx(src1_ptr, src2_stride_3x); + src1_ptr += src2_stride_2x; + DUP4_ARG2(__lsx_vsllwil_hu_bu, src0, 6, src1, 6, src2, 6, src3, 6, + dst0, dst2, dst4, dst6); + DUP4_ARG2(__lsx_vilvh_b, zero, src0, zero, src1, zero, src2, zero, src3, + dst1, dst3, dst5, dst7); + DUP4_ARG2(__lsx_vslli_h, dst1, 6, dst3, 6, dst5, 6, dst7, 6, dst1, dst3, + dst5, dst7); + out0 = hevc_bi_rnd_clip(in0, dst0, in1, dst1); + out1 = hevc_bi_rnd_clip(in2, dst2, in3, dst3); + out2 = hevc_bi_rnd_clip(in4, dst4, in5, dst5); + out3 = hevc_bi_rnd_clip(in6, dst6, in7, dst7); + __lsx_vstelm_w(out0, dst, 0, 0); + __lsx_vstelm_w(out0, dst + dst_stride, 0, 2); + __lsx_vstelm_h(out0, dst, 4, 2); + __lsx_vstelm_h(out0, dst + dst_stride, 4, 6); + __lsx_vstelm_w(out1, dst + dst_stride_2x, 0, 0); + __lsx_vstelm_w(out1, dst + dst_stride_3x, 0, 2); + __lsx_vstelm_h(out1, dst + dst_stride_2x, 4, 2); + __lsx_vstelm_h(out1, dst + dst_stride_3x, 4, 6); + dst += dst_stride_4x; + __lsx_vstelm_w(out2, dst, 0, 0); + __lsx_vstelm_w(out2, dst + dst_stride, 0, 2); + __lsx_vstelm_h(out2, dst, 4, 2); + __lsx_vstelm_h(out2, dst + dst_stride, 4, 6); + __lsx_vstelm_w(out3, dst + dst_stride_2x, 0, 0); + __lsx_vstelm_w(out3, dst + dst_stride_3x, 0, 2); + __lsx_vstelm_h(out3, dst + dst_stride_2x, 4, 2); + __lsx_vstelm_h(out3, dst + dst_stride_3x, 4, 6); + dst += dst_stride_4x; + } + for (;res--;) { + reg0 = __lsx_vldrepl_d(src0_ptr, 0); + reg1 = __lsx_vldrepl_d(src0_ptr + src_stride, 0); + src0 = __lsx_vilvl_d(reg1, reg0); + src0_ptr += src_stride_2x; + in0 = __lsx_vld(src1_ptr, 0); + in1 = __lsx_vldx(src1_ptr, src2_stride_x); + src1_ptr += src2_stride_x; + dst0 = __lsx_vsllwil_hu_bu(src0, 6); + dst1 = __lsx_vilvh_b(zero, src0); + dst1 = __lsx_vslli_h(dst1, 6); + out0 = hevc_bi_rnd_clip(in0, dst0, in1, dst1); + __lsx_vstelm_w(out0, dst, 0, 0); + __lsx_vstelm_h(out0, dst, 4, 2); + dst += dst_stride; + __lsx_vstelm_w(out0, dst, 0, 2); + __lsx_vstelm_h(out0, dst, 4, 6); + dst += dst_stride; + } +} + +static +void hevc_bi_copy_8w_lsx(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 loop_cnt = height >> 3; + int32_t res = (height & 7) >> 1; + int32_t src_stride_2x = (src_stride << 1); + int32_t dst_stride_2x = (dst_stride << 1); + int32_t src_stride_4x = (src_stride << 2); + int32_t dst_stride_4x = (dst_stride << 2); + int32_t src2_stride_x = (src2_stride << 1); + int32_t src2_stride_2x = (src2_stride << 2); + int32_t src_stride_3x = src_stride_2x + src_stride; + int32_t dst_stride_3x = dst_stride_2x + dst_stride; + int32_t src2_stride_3x = src2_stride_2x + src2_stride_x; + __m128i out0, out1, out2, out3; + __m128i src0, src1, src2, src3; + __m128i zero = __lsx_vldi(0); + __m128i in0, in1, in2, in3, in4, in5, in6, in7; + __m128i dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + __m128i reg0, reg1, reg2, reg3; + + for (loop_cnt = (height >> 3); loop_cnt--;) { + reg0 = __lsx_vldrepl_d(src0_ptr, 0); + reg1 = __lsx_vldrepl_d(src0_ptr + src_stride, 0); + reg2 = __lsx_vldrepl_d(src0_ptr + src_stride_2x, 0); + reg3 = __lsx_vldrepl_d(src0_ptr + src_stride_3x, 0); + DUP2_ARG2(__lsx_vilvl_d, reg1, reg0, reg3, reg2, src0, src1); + src0_ptr += src_stride_4x; + reg0 = __lsx_vldrepl_d(src0_ptr, 0); + reg1 = __lsx_vldrepl_d(src0_ptr + src_stride, 0); + reg2 = __lsx_vldrepl_d(src0_ptr + src_stride_2x, 0); + reg3 = __lsx_vldrepl_d(src0_ptr + src_stride_3x, 0); + DUP2_ARG2(__lsx_vilvl_d, reg1, reg0, reg3, reg2, src2, src3); + src0_ptr += src_stride_4x; + DUP4_ARG2(__lsx_vsllwil_hu_bu, src0, 6, src1, 6, src2, 6, src3, 6, + dst0, dst2, dst4, dst6); + DUP4_ARG2(__lsx_vilvh_b, zero, src0, zero, src1, zero, src2, zero, + src3, dst1, dst3, dst5, dst7); + DUP4_ARG2(__lsx_vslli_h, dst1, 6, dst3, 6, dst5, 6, dst7, 6, dst1, + dst3, dst5, dst7); + in0 = __lsx_vld(src1_ptr, 0); + DUP2_ARG2(__lsx_vldx, src1_ptr, src2_stride_x, src1_ptr, + src2_stride_2x, in1, in2); + in3 = __lsx_vldx(src1_ptr, src2_stride_3x); + src1_ptr += src2_stride_2x; + in4 = __lsx_vld(src1_ptr, 0); + DUP2_ARG2(__lsx_vldx, src1_ptr, src2_stride_x, src1_ptr, + src2_stride_2x, in5, in6); + in7 = __lsx_vldx(src1_ptr, src2_stride_3x); + src1_ptr += src2_stride_2x; + out0 = hevc_bi_rnd_clip(in0, dst0, in1, dst1); + out1 = hevc_bi_rnd_clip(in2, dst2, in3, dst3); + out2 = hevc_bi_rnd_clip(in4, dst4, in5, dst5); + out3 = hevc_bi_rnd_clip(in6, dst6, in7, dst7); + __lsx_vstelm_d(out0, dst, 0, 0); + __lsx_vstelm_d(out0, dst + dst_stride, 0, 1); + __lsx_vstelm_d(out1, dst + dst_stride_2x, 0, 0); + __lsx_vstelm_d(out1, dst + dst_stride_3x, 0, 1); + dst += dst_stride_4x; + __lsx_vstelm_d(out2, dst, 0, 0); + __lsx_vstelm_d(out2, dst + dst_stride, 0, 1); + __lsx_vstelm_d(out3, dst + dst_stride_2x, 0, 0); + __lsx_vstelm_d(out3, dst + dst_stride_3x, 0, 1); + dst += dst_stride_4x; + } + for (;res--;) { + reg0 = __lsx_vldrepl_d(src0_ptr, 0); + reg1 = __lsx_vldrepl_d(src0_ptr + src_stride, 0); + src0 = __lsx_vilvl_d(reg1, reg0); + in0 = __lsx_vld(src1_ptr, 0); + in1 = __lsx_vldx(src1_ptr, src2_stride_x); + dst0 = __lsx_vsllwil_hu_bu(src0, 6); + dst1 = __lsx_vilvh_b(zero, src0); + dst1 = __lsx_vslli_h(dst1, 6); + out0 = hevc_bi_rnd_clip(in0, dst0, in1, dst1); + __lsx_vstelm_d(out0, dst, 0, 0); + __lsx_vstelm_d(out0, dst + dst_stride, 0, 1); + src0_ptr += src_stride_2x; + src1_ptr += src2_stride_x; + dst += dst_stride_2x; + } +} + +static +void hevc_bi_copy_12w_lsx(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) +{ + uint32_t loop_cnt; + int32_t src_stride_2x = (src_stride << 1); + int32_t dst_stride_2x = (dst_stride << 1); + int32_t src_stride_4x = (src_stride << 2); + int32_t dst_stride_4x = (dst_stride << 2); + int32_t src2_stride_x = (src2_stride << 1); + int32_t src2_stride_2x = (src2_stride << 2); + int32_t src_stride_3x = src_stride_2x + src_stride; + int32_t dst_stride_3x = dst_stride_2x + dst_stride; + int32_t src2_stride_3x = src2_stride_2x + src2_stride_x; + int16_t* _src1 = src1_ptr + 8; + __m128i out0, out1, out2; + __m128i src0, src1, src2, src3; + __m128i in0, in1, in2, in3, in4, in5, in6, in7; + __m128i dst0, dst1, dst2, dst3, dst4, dst5; + + for (loop_cnt = 4; loop_cnt--;) { + src0 = __lsx_vld(src0_ptr, 0); + DUP2_ARG2(__lsx_vldx, src0_ptr, src_stride, src0_ptr, src_stride_2x, + src1, src2); + src3 = __lsx_vldx(src0_ptr, src_stride_3x); + src0_ptr += src_stride_4x; + in0 = __lsx_vld(src1_ptr, 0); + DUP2_ARG2(__lsx_vldx, src1_ptr, src2_stride_x, src1_ptr, + src2_stride_2x, in1, in2); + in3 = __lsx_vldx(src1_ptr, src2_stride_3x); + src1_ptr += src2_stride_2x; + in4 = __lsx_vld(_src1, 0); + DUP2_ARG2(__lsx_vldx, _src1, src2_stride_x, _src1, src2_stride_2x, + in5, in6); + in7 = __lsx_vldx(_src1, src2_stride_3x); + _src1 += src2_stride_2x; + + DUP2_ARG2(__lsx_vilvl_d, in5, in4, in7, in6, in4, in5); + DUP4_ARG2(__lsx_vsllwil_hu_bu, src0, 6, src1, 6, src2, 6, src3, 6, + dst0, dst1, dst2, dst3) + DUP2_ARG2(__lsx_vilvh_w, src1, src0, src3, src2, src0, src1); + DUP2_ARG2(__lsx_vsllwil_hu_bu, src0, 6, src1, 6, dst4, dst5) + out0 = hevc_bi_rnd_clip(in0, dst0, in1, dst1); + out1 = hevc_bi_rnd_clip(in2, dst2, in3, dst3); + out2 = hevc_bi_rnd_clip(in4, dst4, in5, dst5); + __lsx_vstelm_d(out0, dst, 0, 0); + __lsx_vstelm_d(out0, dst + dst_stride, 0, 1); + __lsx_vstelm_d(out1, dst + dst_stride_2x, 0, 0); + __lsx_vstelm_d(out1, dst + dst_stride_3x, 0, 1); + __lsx_vstelm_w(out2, dst, 8, 0); + __lsx_vstelm_w(out2, dst + dst_stride, 8, 1); + __lsx_vstelm_w(out2, dst + dst_stride_2x, 8, 2); + __lsx_vstelm_w(out2, dst + dst_stride_3x, 8, 3); + dst += dst_stride_4x; + } +} + +static +void hevc_bi_copy_16w_lsx(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) +{ + uint32_t loop_cnt; + int32_t src_stride_2x = (src_stride << 1); + int32_t dst_stride_2x = (dst_stride << 1); + int32_t src_stride_4x = (src_stride << 2); + int32_t dst_stride_4x = (dst_stride << 2); + int32_t src2_stride_x = (src2_stride << 1); + int32_t src2_stride_2x = (src2_stride << 2); + int32_t src_stride_3x = src_stride_2x + src_stride; + int32_t dst_stride_3x = dst_stride_2x + dst_stride; + int32_t src2_stride_3x = src2_stride_2x + src2_stride_x; + int16_t *_src1 = src1_ptr + 8; + __m128i out0, out1, out2, out3; + __m128i src0, src1, src2, src3; + __m128i in0, in1, in2, in3, in4, in5, in6, in7; + __m128i dst0_r, dst1_r, dst2_r, dst3_r, dst0_l, dst1_l, dst2_l, dst3_l; + __m128i zero = {0}; + + for (loop_cnt = (height >> 2); loop_cnt--;) { + src0 = __lsx_vld(src0_ptr, 0); + DUP2_ARG2(__lsx_vldx, src0_ptr, src_stride, src0_ptr, src_stride_2x, + src1, src2); + src3 = __lsx_vldx(src0_ptr, src_stride_3x); + src0_ptr += src_stride_4x; + in0 = __lsx_vld(src1_ptr, 0); + DUP2_ARG2(__lsx_vldx, src1_ptr, src2_stride_x, src1_ptr, + src2_stride_2x, in1, in2); + in3 = __lsx_vldx(src1_ptr, src2_stride_3x); + src1_ptr += src2_stride_2x; + in4 = __lsx_vld(_src1, 0); + DUP2_ARG2(__lsx_vldx, _src1, src2_stride_x, _src1, src2_stride_2x, + in5, in6); + in7 = __lsx_vldx(_src1, src2_stride_3x); + _src1 += src2_stride_2x; + DUP4_ARG2(__lsx_vsllwil_hu_bu, src0, 6, src1, 6, src2, 6, src3, 6, + dst0_r, dst1_r, dst2_r, dst3_r) + DUP4_ARG2(__lsx_vilvh_b, zero, src0, zero, src1, zero, src2, zero, src3, + dst0_l, dst1_l, dst2_l, dst3_l); + DUP4_ARG2(__lsx_vslli_h, dst0_l, 6, dst1_l, 6, dst2_l, 6, dst3_l, 6, + dst0_l, dst1_l, dst2_l, dst3_l); + + out0 = hevc_bi_rnd_clip(in0, dst0_r, in4, dst0_l); + out1 = hevc_bi_rnd_clip(in1, dst1_r, in5, dst1_l); + out2 = hevc_bi_rnd_clip(in2, dst2_r, in6, dst2_l); + out3 = hevc_bi_rnd_clip(in3, dst3_r, in7, dst3_l); + __lsx_vst(out0, dst, 0); + __lsx_vstx(out1, dst, dst_stride); + __lsx_vstx(out2, dst, dst_stride_2x); + __lsx_vstx(out3, dst, dst_stride_3x); + dst += dst_stride_4x; + } +} + +static +void hevc_bi_copy_24w_lsx(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) +{ + hevc_bi_copy_16w_lsx(src0_ptr, src_stride, src1_ptr, src2_stride, + dst, dst_stride, height); + hevc_bi_copy_8w_lsx(src0_ptr + 16, src_stride, src1_ptr + 16, src2_stride, + dst + 16, dst_stride, height); +} + +static +void hevc_bi_copy_32w_lsx(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) +{ + hevc_bi_copy_16w_lsx(src0_ptr, src_stride, src1_ptr, src2_stride, + dst, dst_stride, height); + hevc_bi_copy_16w_lsx(src0_ptr + 16, src_stride, src1_ptr + 16, src2_stride, + dst + 16, dst_stride, height); +} + +static +void hevc_bi_copy_48w_lsx(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) +{ + hevc_bi_copy_16w_lsx(src0_ptr, src_stride, src1_ptr, src2_stride, + dst, dst_stride, height); + hevc_bi_copy_32w_lsx(src0_ptr + 16, src_stride, src1_ptr + 16, src2_stride, + dst + 16, dst_stride, height); +} + +static +void hevc_bi_copy_64w_lsx(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) +{ + hevc_bi_copy_32w_lsx(src0_ptr, src_stride, src1_ptr, src2_stride, + dst, dst_stride, height); + hevc_bi_copy_32w_lsx(src0_ptr + 32, src_stride, src1_ptr + 32, src2_stride, + dst + 32, dst_stride, height); +} + +static void hevc_hz_8t_16w_lsx(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, int32_t height) +{ + uint32_t loop_cnt; + const int32_t dst_stride_2x = (dst_stride << 1); + __m128i src0, src1, src2, src3; + __m128i filt0, filt1, filt2, filt3; + __m128i mask1, mask2, mask3; + __m128i vec0, vec1, vec2, vec3; + __m128i dst0, dst1, dst2, dst3; + __m128i in0, in1, in2, in3; + __m128i mask0 = __lsx_vld(ff_hevc_mask_arr, 0); + + src0_ptr -= 3; + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filt0, filt1, filt2, filt3); + + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + + for (loop_cnt = (height >> 1); loop_cnt--;) { + DUP2_ARG2(__lsx_vld, src0_ptr, 0, src0_ptr, 8, src0, src1); + src0_ptr += src_stride; + DUP2_ARG2(__lsx_vld, src0_ptr, 0, src0_ptr, 8, src2, src3); + src0_ptr += src_stride; + DUP2_ARG2(__lsx_vld, src1_ptr, 0, src1_ptr, 16, in0, in1); + src1_ptr += src2_stride; + DUP2_ARG2(__lsx_vld, src1_ptr, 0, src1_ptr, 16, in2, in3); + src1_ptr += src2_stride; + + DUP2_ARG3(__lsx_vshuf_b, src0, src0, mask0, src1, src1, mask0, + vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src2, src2, mask0, src3, src3, mask0, + vec2, vec3); + DUP4_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec1, filt0, vec2, filt0, + vec3, filt0, dst0, dst1, dst2, dst3); + DUP2_ARG3(__lsx_vshuf_b, src0, src0, mask1, src1, src1, mask1, + vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src2, src2, mask1, src3, src3, mask1, + vec2, vec3); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec0, filt1, dst1, vec1, filt1, + dst2, vec2, filt1, dst3, vec3, filt1, dst0, dst1, dst2, dst3); + DUP2_ARG3(__lsx_vshuf_b, src0, src0, mask2, src1, src1, mask2, + vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src2, src2, mask2, src3, src3, mask2, + vec2, vec3); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec0, filt2, dst1, vec1, filt2, + dst2, vec2, filt2, dst3, vec3, filt2, dst0, dst1, dst2, dst3); + DUP2_ARG3(__lsx_vshuf_b, src0, src0, mask3, src1, src1, mask3, + vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src2, src2, mask3, src3, src3, mask3, + vec2, vec3); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec0, filt3, dst1, vec1, filt3, + dst2, vec2, filt3, dst3, vec3, filt3, dst0, dst1, dst2, dst3); + + dst0 = hevc_bi_rnd_clip(in0, dst0, in1, dst1); + dst1 = hevc_bi_rnd_clip(in2, dst2, in3, dst3); + __lsx_vst(dst0, dst, 0); + __lsx_vstx(dst1, dst, dst_stride); + dst += dst_stride_2x; + } +} + +static void hevc_hz_8t_24w_lsx(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, int32_t height) +{ + uint32_t loop_cnt; + __m128i src0, src1, tmp0, tmp1; + __m128i filt0, filt1, filt2, filt3; + __m128i mask1, mask2, mask3, mask4, mask5, mask6, mask7; + __m128i vec0, vec1, vec2, vec3; + __m128i dst0, dst1, dst2; + __m128i in0, in1, in2; + __m128i mask0 = __lsx_vld(ff_hevc_mask_arr, 0); + + src0_ptr -= 3; + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filt0, filt1, filt2, filt3); + + DUP4_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask0, 6, mask0, 8, mask1, + mask2, mask3, mask4); + DUP2_ARG2(__lsx_vaddi_bu, mask0, 10, mask0, 12, mask5, mask6); + mask7 = __lsx_vaddi_bu(mask0, 14); + + for (loop_cnt = height; loop_cnt--;) { + DUP2_ARG2(__lsx_vld, src0_ptr, 0, src0_ptr, 16, src0, src1); + src0_ptr += src_stride; + DUP2_ARG2(__lsx_vld, src1_ptr, 0, src1_ptr, 16, in0, in1); + in2 = __lsx_vld(src1_ptr, 32); + src1_ptr += src2_stride; + + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask0, src1, src0, mask4, src1, + src1, mask0, src0, src0, mask1, vec0, vec1, vec2, vec3); + DUP2_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec1, filt0, dst0, dst1); + dst2 = __lsx_vdp2_h_bu_b(vec2, filt0); + dst0 = __lsx_vdp2add_h_bu_b(dst0, vec3, filt1); + DUP4_ARG3(__lsx_vshuf_b, src1, src0, mask5, src1, src1, mask1, src0, + src0, mask2, src1, src0, mask6, vec0, vec1, vec2, vec3); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst1, vec0, filt1, dst2, vec1, filt1, + dst0, vec2, filt2, dst1, vec3, filt2, dst1, dst2, dst0, dst1); + DUP4_ARG3(__lsx_vshuf_b, src1, src1, mask2, src0, src0, mask3, src1, src0, + mask7, src1, src1, mask3, vec0, vec1, vec2, vec3); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst2, vec0, filt2, dst0, vec1, filt3, + dst1, vec2, filt3, dst2, vec3, filt3, dst2, dst0, dst1, dst2); + + tmp0 = hevc_bi_rnd_clip(in0, dst0, in1, dst1); + dst2 = __lsx_vsadd_h(dst2, in2); + tmp1 = __lsx_vssrarni_bu_h(dst2, dst2, 7); + + __lsx_vst(tmp0, dst, 0); + __lsx_vstelm_d(tmp1, dst, 16, 0); + dst += dst_stride; + } +} + +static void hevc_hz_8t_32w_lsx(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, int32_t height) +{ + hevc_hz_8t_16w_lsx(src0_ptr, src_stride, src1_ptr, src2_stride, + dst, dst_stride, filter, height); + hevc_hz_8t_16w_lsx(src0_ptr + 16, src_stride, src1_ptr + 16, src2_stride, + dst + 16, dst_stride, filter, height); +} + +static void hevc_hz_8t_48w_lsx(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, int32_t height) +{ + hevc_hz_8t_16w_lsx(src0_ptr, src_stride, src1_ptr, src2_stride, + dst, dst_stride, filter, height); + hevc_hz_8t_32w_lsx(src0_ptr + 16, src_stride, src1_ptr + 16, src2_stride, + dst + 16, dst_stride, filter, height); +} + +static void hevc_hz_8t_64w_lsx(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, int32_t height) +{ + hevc_hz_8t_32w_lsx(src0_ptr, src_stride, src1_ptr, src2_stride, + dst, dst_stride, filter, height); + hevc_hz_8t_32w_lsx(src0_ptr + 32, src_stride, src1_ptr + 32, src2_stride, + dst + 32, dst_stride, filter, height); +} + +static av_always_inline +void hevc_vt_8t_8w_lsx(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, int32_t height) +{ + int32_t loop_cnt; + int32_t src_stride_2x = (src_stride << 1); + int32_t dst_stride_2x = (dst_stride << 1); + int32_t src_stride_4x = (src_stride << 2); + int32_t dst_stride_4x = (dst_stride << 2); + int32_t src2_stride_x = (src2_stride << 1); + int32_t src2_stride_2x = (src2_stride << 2); + int32_t src_stride_3x = src_stride_2x + src_stride; + int32_t dst_stride_3x = dst_stride_2x + dst_stride; + int32_t src2_stride_3x = src2_stride_2x + src2_stride_x; + __m128i src0, src1, src2, src3, src4, src5; + __m128i src6, src7, src8, src9, src10; + __m128i in0, in1, in2, in3; + __m128i src10_r, src32_r, src54_r, src76_r, src98_r; + __m128i src21_r, src43_r, src65_r, src87_r, src109_r; + __m128i dst0_r, dst1_r, dst2_r, dst3_r; + __m128i filt0, filt1, filt2, filt3; + + src0_ptr -= src_stride_3x; + + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filt0, filt1, filt2, filt3); + + src0 = __lsx_vld(src0_ptr, 0); + DUP2_ARG2(__lsx_vldx, src0_ptr, src_stride, src0_ptr, src_stride_2x, + src1, src2); + src3 = __lsx_vldx(src0_ptr, src_stride_3x); + src0_ptr += src_stride_4x; + src4 = __lsx_vld(src0_ptr, 0); + DUP2_ARG2(__lsx_vldx, src0_ptr, src_stride, src0_ptr, src_stride_2x, + src5, src6); + src0_ptr += src_stride_3x; + DUP4_ARG2(__lsx_vilvl_b, src1, src0, src3, src2, src5, src4, src2, src1, + src10_r, src32_r, src54_r, src21_r); + DUP2_ARG2(__lsx_vilvl_b, src4, src3, src6, src5, src43_r, src65_r); + + for (loop_cnt = (height >> 2); loop_cnt--;) { + src7 = __lsx_vld(src0_ptr, 0); + DUP2_ARG2(__lsx_vldx, src0_ptr, src_stride, src0_ptr, src_stride_2x, + src8, src9); + src10 = __lsx_vldx(src0_ptr, src_stride_3x); + src0_ptr += src_stride_4x; + in0 = __lsx_vld(src1_ptr, 0); + DUP2_ARG2(__lsx_vldx, src1_ptr, src2_stride_x, src1_ptr, src2_stride_2x, + in1, in2); + in3 = __lsx_vldx(src1_ptr, src2_stride_3x); + src1_ptr += src2_stride_2x; + DUP4_ARG2(__lsx_vilvl_b, src7, src6, src8, src7, src9, src8, src10, src9, + src76_r, src87_r, src98_r, src109_r); + + DUP4_ARG2(__lsx_vdp2_h_bu_b, src10_r, filt0, src21_r, filt0, src32_r, + filt0, src43_r, filt0, dst0_r, dst1_r, dst2_r, dst3_r); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0_r, src32_r, filt1, dst1_r, src43_r, + filt1, dst2_r, src54_r, filt1, dst3_r, src65_r, filt1, + dst0_r, dst1_r, dst2_r, dst3_r); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0_r, src54_r, filt2, dst1_r, src65_r, + filt2, dst2_r, src76_r, filt2, dst3_r, src87_r, filt2, + dst0_r, dst1_r, dst2_r, dst3_r); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0_r, src76_r, filt3, dst1_r, src87_r, + filt3, dst2_r, src98_r, filt3, dst3_r, src109_r, filt3, + dst0_r, dst1_r, dst2_r, dst3_r); + + dst0_r = hevc_bi_rnd_clip(in0, dst0_r, in1, dst1_r); + dst1_r = hevc_bi_rnd_clip(in2, dst2_r, in3, dst3_r); + __lsx_vstelm_d(dst0_r, dst, 0, 0); + __lsx_vstelm_d(dst0_r, dst + dst_stride, 0, 1); + __lsx_vstelm_d(dst1_r, dst + dst_stride_2x, 0, 0); + __lsx_vstelm_d(dst1_r, dst + dst_stride_3x, 0, 1); + dst += dst_stride_4x; + + src10_r = src54_r; + src32_r = src76_r; + src54_r = src98_r; + src21_r = src65_r; + src43_r = src87_r; + src65_r = src109_r; + + src6 = src10; + } +} + +static av_always_inline +void hevc_vt_8t_16multx2mult_lsx(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, int32_t height, + int32_t width) +{ + uint8_t *src0_ptr_tmp; + int16_t *src1_ptr_tmp; + uint8_t *dst_tmp; + uint32_t loop_cnt; + uint32_t cnt; + int32_t src_stride_2x = (src_stride << 1); + int32_t dst_stride_2x = (dst_stride << 1); + int32_t src_stride_4x = (src_stride << 2); + int32_t src_stride_3x = src_stride_2x + src_stride; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8; + __m128i in0, in1, in2, in3; + __m128i src10_r, src32_r, src54_r, src76_r; + __m128i src21_r, src43_r, src65_r, src87_r; + __m128i dst0_r, dst1_r; + __m128i src10_l, src32_l, src54_l, src76_l; + __m128i src21_l, src43_l, src65_l, src87_l; + __m128i dst0_l, dst1_l; + __m128i filt0, filt1, filt2, filt3; + + src0_ptr -= src_stride_3x; + + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filt0, filt1, filt2, filt3); + + for (cnt = (width >> 4); cnt--;) { + src0_ptr_tmp = src0_ptr; + src1_ptr_tmp = src1_ptr; + dst_tmp = dst; + + src0 = __lsx_vld(src0_ptr_tmp, 0); + DUP2_ARG2(__lsx_vldx, src0_ptr_tmp, src_stride, src0_ptr_tmp, + src_stride_2x, src1, src2); + src3 = __lsx_vldx(src0_ptr_tmp, src_stride_3x); + src0_ptr_tmp += src_stride_4x; + src4 = __lsx_vld(src0_ptr_tmp, 0); + DUP2_ARG2(__lsx_vldx, src0_ptr_tmp, src_stride, src0_ptr_tmp, + src_stride_2x, src5, src6); + src0_ptr_tmp += src_stride_3x; + + DUP4_ARG2(__lsx_vilvl_b, src1, src0, src3, src2, src5, src4, src2, src1, + src10_r, src32_r, src54_r, src21_r); + DUP2_ARG2(__lsx_vilvl_b, src4, src3, src6, src5, src43_r, src65_r); + DUP4_ARG2(__lsx_vilvh_b, src1, src0, src3, src2, src5, src4, src2, src1, + src10_l, src32_l, src54_l, src21_l); + DUP2_ARG2(__lsx_vilvh_b, src4, src3, src6, src5, src43_l, src65_l); + + for (loop_cnt = (height >> 1); loop_cnt--;) { + src7 = __lsx_vld(src0_ptr_tmp, 0); + src8 = __lsx_vldx(src0_ptr_tmp, src_stride); + src0_ptr_tmp += src_stride_2x; + DUP2_ARG2(__lsx_vld, src1_ptr_tmp, 0, src1_ptr_tmp, 16, in0, in2); + src1_ptr_tmp += src2_stride; + DUP2_ARG2(__lsx_vld, src1_ptr_tmp, 0, src1_ptr_tmp, 16, in1, in3); + src1_ptr_tmp += src2_stride; + + DUP2_ARG2(__lsx_vilvl_b, src7, src6, src8, src7, src76_r, src87_r); + DUP2_ARG2(__lsx_vilvh_b, src7, src6, src8, src7, src76_l, src87_l); + + DUP4_ARG2(__lsx_vdp2_h_bu_b, src10_r, filt0, src21_r, filt0, src10_l, + filt0, src21_l, filt0, dst0_r, dst1_r, dst0_l, dst1_l); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0_r, src32_r, filt1, dst1_r, + src43_r, filt1, dst0_l, src32_l, filt1, dst1_l, src43_l, + filt1, dst0_r, dst1_r, dst0_l, dst1_l); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0_r, src54_r, filt2, dst1_r, + src65_r, filt2, dst0_l, src54_l, filt2, dst1_l, src65_l, + filt2, dst0_r, dst1_r, dst0_l, dst1_l); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0_r, src76_r, filt3, dst1_r, + src87_r, filt3, dst0_l, src76_l, filt3, dst1_l, src87_l, + filt3, dst0_r, dst1_r, dst0_l, dst1_l); + dst0_r = hevc_bi_rnd_clip(in0, dst0_r, in2, dst0_l); + dst1_r = hevc_bi_rnd_clip(in1, dst1_r, in3, dst1_l); + + __lsx_vst(dst0_r, dst_tmp, 0); + __lsx_vstx(dst1_r, dst_tmp, dst_stride); + dst_tmp += dst_stride_2x; + + 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; + } + + src0_ptr += 16; + src1_ptr += 16; + dst += 16; + } +} + +static void hevc_vt_8t_16w_lsx(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, int32_t height) +{ + hevc_vt_8t_16multx2mult_lsx(src0_ptr, src_stride, src1_ptr, src2_stride, + dst, dst_stride, filter, height, 16); +} + +static void hevc_vt_8t_24w_lsx(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, int32_t height) +{ + hevc_vt_8t_16multx2mult_lsx(src0_ptr, src_stride, src1_ptr, src2_stride, + dst, dst_stride, filter, height, 16); + hevc_vt_8t_8w_lsx(src0_ptr + 16, src_stride, src1_ptr + 16, src2_stride, + dst + 16, dst_stride, filter, height); +} + +static void hevc_vt_8t_32w_lsx(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, int32_t height) +{ + hevc_vt_8t_16multx2mult_lsx(src0_ptr, src_stride, src1_ptr, src2_stride, + dst, dst_stride, filter, height, 32); +} + +static void hevc_vt_8t_48w_lsx(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, int32_t height) +{ + hevc_vt_8t_16multx2mult_lsx(src0_ptr, src_stride, src1_ptr, src2_stride, + dst, dst_stride, filter, height, 48); +} + +static void hevc_vt_8t_64w_lsx(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, int32_t height) +{ + hevc_vt_8t_16multx2mult_lsx(src0_ptr, src_stride, src1_ptr, src2_stride, + dst, dst_stride, filter, height, 64); +} + +static av_always_inline +void hevc_hv_8t_8multx1mult_lsx(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 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; + int32_t src_stride_2x = (src_stride << 1); + int32_t src_stride_4x = (src_stride << 2); + int32_t src_stride_3x = src_stride_2x + src_stride; + __m128i out; + __m128i src0, src1, src2, src3, src4, src5, src6, src7; + __m128i in0, tmp; + __m128i filt0, filt1, filt2, filt3; + __m128i filt_h0, filt_h1, filt_h2, filt_h3; + __m128i mask0 = __lsx_vld(ff_hevc_mask_arr, 0); + __m128i mask1, mask2, mask3; + __m128i vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + __m128i vec8, vec9, vec10, vec11, vec12, vec13, vec14, vec15; + __m128i dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + __m128i dst0_r, dst0_l; + __m128i dst10_r, dst32_r, dst54_r, dst76_r; + __m128i dst10_l, dst32_l, dst54_l, dst76_l; + + src0_ptr -= src_stride_3x + 3; + + DUP4_ARG2(__lsx_vldrepl_h, filter_x, 0, filter_x, 2, filter_x, 4, filter_x, + 6, filt0, filt1, filt2, filt3); + filt_h3 = __lsx_vld(filter_y, 0); + filt_h3 = __lsx_vsllwil_h_b(filt_h3, 0); + + DUP4_ARG2(__lsx_vreplvei_w, filt_h3, 0, filt_h3, 1, filt_h3, 2, filt_h3, 3, + filt_h0, filt_h1, filt_h2, filt_h3); + + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + + for (cnt = width >> 3; cnt--;) { + src0_ptr_tmp = src0_ptr; + dst_tmp = dst; + src1_ptr_tmp = src1_ptr; + + src0 = __lsx_vld(src0_ptr_tmp, 0); + DUP2_ARG2(__lsx_vldx, src0_ptr_tmp, src_stride, src0_ptr_tmp, + src_stride_2x, src1, src2); + src3 = __lsx_vldx(src0_ptr_tmp, src_stride_3x); + src0_ptr_tmp += src_stride_4x; + src4 = __lsx_vld(src0_ptr_tmp, 0); + DUP2_ARG2(__lsx_vldx, src0_ptr_tmp, src_stride, src0_ptr_tmp, + src_stride_2x, src5, src6); + src0_ptr_tmp += src_stride_3x; + + /* row 0 row 1 row 2 row 3 */ + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask0, src0, src0, mask1, src0, + src0, mask2, src0, src0, mask3, vec0, vec1, vec2, vec3); + DUP4_ARG3(__lsx_vshuf_b, src1, src1, mask0, src1, src1, mask1, src1, + src1, mask2, src1, src1, mask3, vec4, vec5, vec6, vec7); + DUP4_ARG3(__lsx_vshuf_b, src2, src2, mask0, src2, src2, mask1, src2, + src2, mask2, src2, src2, mask3, vec8, vec9, vec10, vec11); + DUP4_ARG3(__lsx_vshuf_b, src3, src3, mask0, src3, src3, mask1, src3, + src3, mask2, src3, src3, mask3, vec12, vec13, vec14, vec15); + DUP4_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec4, filt0, vec8, filt0, + vec12, filt0, dst0, dst1, dst2, dst3); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec1, filt1, dst1, vec5, filt1, + dst2, vec9, filt1, dst3, vec13, filt1, dst0, dst1, dst2, dst3); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec2, filt2, dst1, vec6, filt2, + dst2, vec10, filt2, dst3, vec14, filt2, dst0, dst1, dst2, dst3); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec3, filt3, dst1, vec7, filt3, + dst2, vec11, filt3, dst3, vec15, filt3, dst0, dst1, dst2, dst3); + + DUP4_ARG3(__lsx_vshuf_b, src4, src4, mask0, src4, src4, mask1, src4, + src4, mask2, src4, src4, mask3, vec0, vec1, vec2, vec3); + DUP4_ARG3(__lsx_vshuf_b, src5, src5, mask0, src5, src5, mask1, src5, + src5, mask2, src5, src5, mask3, vec4, vec5, vec6, vec7); + DUP4_ARG3(__lsx_vshuf_b, src6, src6, mask0, src6, src6, mask1, src6, + src6, mask2, src6, src6, mask3, vec8, vec9, vec10, vec11); + DUP2_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec4, filt0, dst4, dst5); + dst6 = __lsx_vdp2_h_bu_b(vec8, filt0); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst4, vec1, filt1, dst5, vec5, filt1, + dst6, vec9, filt1, dst4, vec2, filt2, dst4, dst5, dst6, dst4); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst5, vec6, filt2, dst6, vec10, filt2, + dst4, vec3, filt3, dst5, vec7, filt3, dst5, dst6, dst4, dst5); + dst6 = __lsx_vdp2add_h_bu_b(dst6, vec11, filt3); + + for (loop_cnt = height; loop_cnt--;) { + src7 = __lsx_vld(src0_ptr_tmp, 0); + src0_ptr_tmp += src_stride; + + in0 = __lsx_vld(src1_ptr_tmp, 0); + src1_ptr_tmp += src2_stride; + + DUP4_ARG3(__lsx_vshuf_b, src7, src7, mask0, src7, src7, mask1, src7, + src7, mask2, src7, src7, mask3, vec0, vec1, vec2, vec3); + dst7 = __lsx_vdp2_h_bu_b(vec0, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst7, vec1, filt1, dst7, vec2, + filt2, dst7, dst7); + dst7 = __lsx_vdp2add_h_bu_b(dst7, vec3, filt3); + DUP4_ARG2(__lsx_vilvl_h, dst1, dst0, dst3, dst2, dst5, dst4, dst7, + dst6, dst10_r, dst32_r, dst54_r, dst76_r); + DUP4_ARG2(__lsx_vilvh_h, dst1, dst0, dst3, dst2, dst5, dst4, dst7, + dst6, dst10_l, dst32_l, dst54_l, dst76_l); + + DUP2_ARG2(__lsx_vdp2_w_h, dst10_r, filt_h0, dst10_l, filt_h0, + dst0_r, dst0_l); + DUP4_ARG3(__lsx_vdp2add_w_h, dst0_r, dst32_r, filt_h1, dst0_l, + dst32_l, filt_h1, dst0_r, dst54_r, filt_h2, dst0_l, + dst54_l, filt_h2, dst0_r, dst0_l, dst0_r, dst0_l); + DUP2_ARG3(__lsx_vdp2add_w_h, dst0_r, dst76_r, filt_h3, dst0_l, + dst76_l, filt_h3, dst0_r, dst0_l); + dst0_r = __lsx_vsrli_w(dst0_r, 6); + dst0_l = __lsx_vsrli_w(dst0_l, 6); + + tmp = __lsx_vpickev_h(dst0_l, dst0_r); + tmp = __lsx_vsadd_h(tmp, in0); + tmp = __lsx_vmaxi_h(tmp, 0); + out = __lsx_vssrlrni_bu_h(tmp, tmp, 7); + __lsx_vstelm_d(out, dst_tmp, 0, 0); + 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; + } +} + +static void hevc_hv_8t_8w_lsx(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 height) +{ + hevc_hv_8t_8multx1mult_lsx(src0_ptr, src_stride, src1_ptr, src2_stride, + dst, dst_stride, filter_x, filter_y, height, 8); +} + +static void hevc_hv_8t_16w_lsx(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 height) +{ + hevc_hv_8t_8multx1mult_lsx(src0_ptr, src_stride, src1_ptr, src2_stride, + dst, dst_stride, filter_x, filter_y, height, 16); +} + +static void hevc_hv_8t_24w_lsx(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 height) +{ + hevc_hv_8t_8multx1mult_lsx(src0_ptr, src_stride, src1_ptr, src2_stride, + dst, dst_stride, filter_x, filter_y, height, 24); +} + +static void hevc_hv_8t_32w_lsx(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 height) +{ + hevc_hv_8t_8multx1mult_lsx(src0_ptr, src_stride, src1_ptr, src2_stride, + dst, dst_stride, filter_x, filter_y, height, 32); +} + +static void hevc_hv_8t_48w_lsx(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 height) +{ + hevc_hv_8t_8multx1mult_lsx(src0_ptr, src_stride, src1_ptr, src2_stride, + dst, dst_stride, filter_x, filter_y, height, 48); +} + +static void hevc_hv_8t_64w_lsx(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 height) +{ + hevc_hv_8t_8multx1mult_lsx(src0_ptr, src_stride, src1_ptr, src2_stride, + dst, dst_stride, filter_x, filter_y, height, 64); +} + +static void hevc_hz_4t_24w_lsx(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, int32_t height) +{ + int16_t *src1_ptr_tmp; + uint8_t *dst_tmp; + uint32_t loop_cnt; + int32_t dst_stride_2x = (dst_stride << 1); + int32_t dst_stride_4x = (dst_stride << 2); + int32_t dst_stride_3x = dst_stride_2x + dst_stride; + int32_t src2_stride_x = src2_stride << 1; + int32_t src2_stride_2x = src2_stride << 2; + int32_t src2_stride_3x = src2_stride_2x + src2_stride_x; + + __m128i src0, src1, src2, src3, src4, src5, src6, src7; + __m128i in0, in1, in2, in3, in4, in5, in6, in7; + __m128i filt0, filt1; + __m128i mask0 = __lsx_vld(ff_hevc_mask_arr, 0); + __m128i mask1, mask2, mask3; + __m128i vec0, vec1, vec2, vec3; + __m128i dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + + src0_ptr -= 1; + DUP2_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filt0, filt1); + + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 8, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 10); + + dst_tmp = dst + 16; + src1_ptr_tmp = src1_ptr + 16; + + for (loop_cnt = (height >> 2); loop_cnt--;) { + DUP2_ARG2(__lsx_vld, src0_ptr, 0, src0_ptr, 16, src0, src1); + src0_ptr += src_stride; + DUP2_ARG2(__lsx_vld, src0_ptr, 0, src0_ptr, 16, src2, src3); + src0_ptr += src_stride; + DUP2_ARG2(__lsx_vld, src0_ptr, 0, src0_ptr, 16, src4, src5); + src0_ptr += src_stride; + DUP2_ARG2(__lsx_vld, src0_ptr, 0, src0_ptr, 16, src6, src7); + src0_ptr += src_stride; + + DUP2_ARG2(__lsx_vld, src1_ptr, 0, src1_ptr, 16, in0, in1); + src1_ptr += src2_stride; + DUP2_ARG2(__lsx_vld, src1_ptr, 0, src1_ptr, 16, in2, in3); + src1_ptr += src2_stride; + DUP2_ARG2(__lsx_vld, src1_ptr, 0, src1_ptr, 16, in4, in5); + src1_ptr += src2_stride; + DUP2_ARG2(__lsx_vld, src1_ptr, 0, src1_ptr, 16, in6, in7); + src1_ptr += src2_stride; + + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask0, src1, src0, mask2, src2, + src2, mask0, src3, src2, mask2, vec0, vec1, vec2, vec3); + DUP4_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec1, filt0, vec2, filt0, + vec3, filt0, dst0, dst1, dst2, dst3); + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask1, src1, src0, mask3, src2, + src2, mask1, src3, src2, mask3, vec0, vec1, vec2, vec3); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec0, filt1, dst1, vec1, filt1, + dst2, vec2, filt1, dst3, vec3, filt1, dst0, dst1, dst2, dst3); + + DUP4_ARG3(__lsx_vshuf_b, src4, src4, mask0, src5, src4, mask2, src6, + src6, mask0, src7, src6, mask2, vec0, vec1, vec2, vec3); + DUP4_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec1, filt0, vec2, filt0, + vec3, filt0, dst4, dst5, dst6, dst7); + DUP4_ARG3(__lsx_vshuf_b, src4, src4, mask1, src5, src4, mask3, src6, + src6, mask1, src7, src6, mask3, vec0, vec1, vec2, vec3); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst4, vec0, filt1, dst5, vec1, filt1, + dst6, vec2, filt1, dst7, vec3, filt1, dst4, dst5, dst6, dst7); + + dst0 = hevc_bi_rnd_clip(in0, dst0, in1, dst1); + dst1 = hevc_bi_rnd_clip(in2, dst2, in3, dst3); + dst2 = hevc_bi_rnd_clip(in4, dst4, in5, dst5); + dst3 = hevc_bi_rnd_clip(in6, dst6, in7, dst7); + __lsx_vst(dst0, dst, 0); + __lsx_vstx(dst1, dst, dst_stride); + __lsx_vstx(dst2, dst, dst_stride_2x); + __lsx_vstx(dst3, dst, dst_stride_3x); + dst += dst_stride_4x; + + in0 = __lsx_vld(src1_ptr_tmp, 0); + DUP2_ARG2(__lsx_vldx, src1_ptr_tmp, src2_stride_x, src1_ptr_tmp, + src2_stride_2x, in1, in2); + in3 = __lsx_vldx(src1_ptr_tmp, src2_stride_3x); + src1_ptr_tmp += src2_stride_2x; + + DUP4_ARG3(__lsx_vshuf_b, src1, src1, mask0, src3, src3, mask0, src5, + src5, mask0, src7, src7, mask0, vec0, vec1, vec2, vec3); + DUP4_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec1, filt0, vec2, filt0, + vec3, filt0, dst0, dst1, dst2, dst3); + DUP4_ARG3(__lsx_vshuf_b, src1, src1, mask1, src3, src3, mask1, src5, + src5, mask1, src7, src7, mask1, vec0, vec1, vec2, vec3); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec0, filt1, dst1, vec1, filt1, + dst2, vec2, filt1, dst3, vec3, filt1, dst0, dst1, dst2, dst3); + dst0 = hevc_bi_rnd_clip(in0, dst0, in1, dst1); + dst1 = hevc_bi_rnd_clip(in2, dst2, in3, dst3); + __lsx_vstelm_d(dst0, dst_tmp, 0, 0); + __lsx_vstelm_d(dst0, dst_tmp + dst_stride, 0, 1); + __lsx_vstelm_d(dst1, dst_tmp + dst_stride_2x, 0, 0); + __lsx_vstelm_d(dst1, dst_tmp + dst_stride_3x, 0, 1); + dst_tmp += dst_stride_4x; + } +} + +static void hevc_hz_4t_32w_lsx(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, int32_t height) +{ + uint32_t loop_cnt; + __m128i src0, src1, src2; + __m128i in0, in1, in2, in3; + __m128i filt0, filt1; + __m128i mask0 = __lsx_vld(ff_hevc_mask_arr, 0); + __m128i mask1, mask2, mask3; + __m128i dst0, dst1, dst2, dst3; + __m128i vec0, vec1, vec2, vec3; + + src0_ptr -= 1; + + DUP2_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filt0, filt1); + + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 8, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 10); + + for (loop_cnt = height; loop_cnt--;) { + DUP2_ARG2(__lsx_vld, src0_ptr, 0, src0_ptr, 16, src0, src1); + src2 = __lsx_vld(src0_ptr, 24); + src0_ptr += src_stride; + DUP4_ARG2(__lsx_vld, src1_ptr, 0, src1_ptr, 16, src1_ptr, 32, + src1_ptr, 48, in0, in1, in2, in3); + src1_ptr += src2_stride; + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask0, src1, src0, mask2, src1, + src1, mask0, src2, src2, mask0, vec0, vec1, vec2, vec3); + DUP4_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec1, filt0, vec2, filt0, + vec3, filt0, dst0, dst1, dst2, dst3); + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask1, src1, src0, mask3, src1, + src1, mask1, src2, src2, mask1, vec0, vec1, vec2, vec3); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec0, filt1, dst1, vec1, filt1, + dst2, vec2, filt1, dst3, vec3, filt1, dst0, dst1, dst2, dst3); + dst0 = hevc_bi_rnd_clip(in0, dst0, in1, dst1); + dst1 = hevc_bi_rnd_clip(in2, dst2, in3, dst3); + __lsx_vst(dst0, dst, 0); + __lsx_vst(dst1, dst, 16); + dst += dst_stride; + } +} + +static void hevc_vt_4t_12w_lsx(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, int32_t height) +{ + int32_t loop_cnt; + int32_t src_stride_2x = (src_stride << 1); + int32_t dst_stride_2x = (dst_stride << 1); + int32_t dst_stride_4x = (dst_stride << 2); + int32_t src_stride_4x = (src_stride << 2); + int32_t src2_stride_x = (src2_stride << 1); + int32_t src2_stride_2x = (src2_stride << 2); + int32_t src_stride_3x = src_stride_2x + src_stride; + int32_t dst_stride_3x = dst_stride_2x + dst_stride; + int32_t src2_stride_3x = src2_stride_2x + src2_stride_x; + int16_t *_src1 = src1_ptr + 8; + __m128i src0, src1, src2, src3, src4, src5, src6; + __m128i in0, in1, in2, in3, in4, in5, in6, in7; + __m128i src10_r, src32_r, src21_r, src43_r, src54_r, src65_r; + __m128i dst0_r, dst1_r, dst2_r, dst3_r; + __m128i src10_l, src32_l, src54_l, src21_l, src43_l, src65_l; + __m128i src2110, src4332, src6554; + __m128i dst0_l, dst1_l, filt0, filt1; + + src0_ptr -= src_stride; + DUP2_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filt0, filt1); + + src0 = __lsx_vld(src0_ptr, 0); + DUP2_ARG2(__lsx_vldx, src0_ptr, src_stride, src0_ptr, src_stride_2x, + src1, src2); + src0_ptr += src_stride_3x; + DUP2_ARG2(__lsx_vilvl_b, src1, src0, src2, src1, src10_r, src21_r); + DUP2_ARG2(__lsx_vilvh_b, src1, src0, src2, src1, src10_l, src21_l); + src2110 = __lsx_vilvl_d(src21_l, src10_l); + + for (loop_cnt = (height >> 2); loop_cnt--;) { + src3 = __lsx_vld(src0_ptr, 0); + DUP2_ARG2(__lsx_vldx, src0_ptr, src_stride, src0_ptr, src_stride_2x, + src4, src5); + src6 = __lsx_vldx(src0_ptr, src_stride_3x); + src0_ptr += src_stride_4x; + in0 = __lsx_vld(src1_ptr, 0); + DUP2_ARG2(__lsx_vldx, src1_ptr, src2_stride_x, src1_ptr, + src2_stride_2x, in1, in2); + in3 = __lsx_vldx(src1_ptr, src2_stride_3x); + src1_ptr += src2_stride_2x; + in4 = __lsx_vld(_src1, 0); + DUP2_ARG2(__lsx_vldx, _src1, src2_stride_x, _src1, src2_stride_2x, + in5, in6); + in7 = __lsx_vldx(_src1, src2_stride_3x); + _src1 += src2_stride_2x; + DUP2_ARG2(__lsx_vilvl_d, in5, in4, in7, in6, in4, in5); + + DUP2_ARG2(__lsx_vilvl_b, src3, src2, src4, src3, src32_r, src43_r); + DUP2_ARG2(__lsx_vilvh_b, src3, src2, src4, src3, src32_l, src43_l); + src4332 = __lsx_vilvl_d(src43_l, src32_l); + DUP2_ARG2(__lsx_vilvl_b, src5, src4, src6, src5, src54_r, src65_r); + DUP2_ARG2(__lsx_vilvh_b, src5, src4, src6, src5, src54_l, src65_l); + src6554 = __lsx_vilvl_d(src65_l, src54_l); + + DUP4_ARG2(__lsx_vdp2_h_bu_b, src10_r, filt0, src21_r, filt0, src2110, + filt0, src32_r, filt0, dst0_r, dst1_r, dst0_l, dst2_r); + DUP2_ARG2(__lsx_vdp2_h_bu_b, src43_r, filt0, src4332, filt0, + dst3_r, dst1_l); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0_r, src32_r, filt1, dst1_r, + src43_r, filt1, dst0_l, src4332, filt1, dst2_r, src54_r, + filt1, dst0_r, dst1_r, dst0_l, dst2_r); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst3_r, src65_r, filt1, dst1_l, + src6554, filt1, dst3_r, dst1_l); + dst0_r = hevc_bi_rnd_clip(in0, dst0_r, in1, dst1_r); + dst1_r = hevc_bi_rnd_clip(in2, dst2_r, in3, dst3_r); + dst0_l = hevc_bi_rnd_clip(in4, dst0_l, in5, dst1_l); + __lsx_vstelm_d(dst0_r, dst, 0, 0); + __lsx_vstelm_d(dst0_r, dst + dst_stride, 0, 1); + __lsx_vstelm_d(dst1_r, dst + dst_stride_2x, 0, 0); + __lsx_vstelm_d(dst1_r, dst + dst_stride_3x, 0, 1); + __lsx_vstelm_w(dst0_l, dst, 8, 0); + __lsx_vstelm_w(dst0_l, dst + dst_stride, 8, 1); + __lsx_vstelm_w(dst0_l, dst + dst_stride_2x, 8, 2); + __lsx_vstelm_w(dst0_l, dst + dst_stride_3x, 8, 3); + dst += dst_stride_4x; + + src2 = src6; + src10_r = src54_r; + src21_r = src65_r; + src2110 = src6554; + } +} + +static void hevc_vt_4t_16w_lsx(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, int32_t height) +{ + int32_t loop_cnt; + const int32_t src_stride_2x = (src_stride << 1); + const int32_t dst_stride_2x = (dst_stride << 1); + const int32_t src_stride_3x = src_stride_2x + src_stride; + __m128i src0, src1, src2, src3, src4, src5; + __m128i in0, in1, in2, in3; + __m128i src10_r, src32_r, src21_r, src43_r; + __m128i src10_l, src32_l, src21_l, src43_l; + __m128i dst0_r, dst1_r, dst0_l, dst1_l; + __m128i filt0, filt1; + + src0_ptr -= src_stride; + DUP2_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filt0, filt1); + + src0 = __lsx_vld(src0_ptr, 0); + DUP2_ARG2(__lsx_vldx, src0_ptr, src_stride, src0_ptr, src_stride_2x, + src1, src2); + src0_ptr += src_stride_3x; + DUP2_ARG2(__lsx_vilvl_b, src1, src0, src2, src1, src10_r, src21_r); + DUP2_ARG2(__lsx_vilvh_b, src1, src0, src2, src1, src10_l, src21_l); + + for (loop_cnt = (height >> 2); loop_cnt--;) { + src3 = __lsx_vld(src0_ptr, 0); + src4 = __lsx_vldx(src0_ptr, src_stride); + src0_ptr += src_stride_2x; + DUP2_ARG2(__lsx_vld, src1_ptr, 0, src1_ptr, 16, in0, in2); + src1_ptr += src2_stride; + DUP2_ARG2(__lsx_vld, src1_ptr, 0, src1_ptr, 16, in1, in3); + src1_ptr += src2_stride; + DUP2_ARG2(__lsx_vilvl_b, src3, src2, src4, src3, src32_r, src43_r); + DUP2_ARG2(__lsx_vilvh_b, src3, src2, src4, src3, src32_l, src43_l); + + DUP4_ARG2(__lsx_vdp2_h_bu_b, src10_r, filt0, src21_r, filt0, src10_l, + filt0, src21_l, filt0, dst0_r, dst1_r, dst0_l, dst1_l); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0_r, src32_r, filt1, dst1_r, src43_r, + filt1, dst0_l, src32_l, filt1, dst1_l, src43_l, filt1, + dst0_r, dst1_r, dst0_l, dst1_l); + + dst0_r = hevc_bi_rnd_clip(in0, dst0_r, in2, dst0_l); + dst1_r = hevc_bi_rnd_clip(in1, dst1_r, in3, dst1_l); + __lsx_vst(dst0_r, dst, 0); + __lsx_vstx(dst1_r, dst, dst_stride); + dst += dst_stride_2x; + + src5 = __lsx_vld(src0_ptr, 0); + src2 = __lsx_vldx(src0_ptr, src_stride); + src0_ptr += src_stride_2x; + DUP2_ARG2(__lsx_vld, src1_ptr, 0, src1_ptr, 16, in0, in2); + src1_ptr += src2_stride; + DUP2_ARG2(__lsx_vld, src1_ptr, 0, src1_ptr, 16, in1, in3); + src1_ptr += src2_stride; + DUP2_ARG2(__lsx_vilvl_b, src5, src4, src2, src5, src10_r, src21_r); + DUP2_ARG2(__lsx_vilvh_b, src5, src4, src2, src5, src10_l, src21_l); + + DUP4_ARG2(__lsx_vdp2_h_bu_b, src32_r, filt0, src32_l, filt0, src43_r, + filt0, src43_l, filt0, dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0_r, src10_r, filt1, dst0_l, + src10_l, filt1, dst1_r, src21_r, filt1, dst1_l, src21_l, + filt1, dst0_r, dst0_l, dst1_r, dst1_l); + dst0_r = hevc_bi_rnd_clip(in0, dst0_r, in2, dst0_l); + dst1_r = hevc_bi_rnd_clip(in1, dst1_r, in3, dst1_l); + __lsx_vst(dst0_r, dst, 0); + __lsx_vstx(dst1_r, dst, dst_stride); + dst += dst_stride_2x; + } +} + +static void hevc_vt_4t_24w_lsx(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, int32_t height) +{ + uint32_t loop_cnt; + int32_t dst_stride_2x = dst_stride << 1; + __m128i src0, src1, src2, src3, src4, src5; + __m128i src6, src7, src8, src9, src10, src11; + __m128i in0, in1, in2, in3, in4, in5; + __m128i src10_r, src32_r, src76_r, src98_r; + __m128i src21_r, src43_r, src87_r, src109_r; + __m128i src10_l, src32_l, src21_l, src43_l; + __m128i dst0_r, dst1_r, dst2_r, dst3_r; + __m128i dst0_l, dst1_l; + __m128i filt0, filt1; + + src0_ptr -= src_stride; + DUP2_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filt0, filt1); + + /* 16width */ + DUP2_ARG2(__lsx_vld, src0_ptr, 0, src0_ptr, 16, src0, src6); + src0_ptr += src_stride; + DUP2_ARG2(__lsx_vld, src0_ptr, 0, src0_ptr, 16, src1, src7); + src0_ptr += src_stride; + DUP2_ARG2(__lsx_vld, src0_ptr, 0, src0_ptr, 16, src2, src8); + src0_ptr += src_stride; + DUP2_ARG2(__lsx_vilvl_b, src1, src0, src2, src1, src10_r, src21_r); + DUP2_ARG2(__lsx_vilvh_b, src1, src0, src2, src1, src10_l, src21_l); + /* 8width */ + DUP2_ARG2(__lsx_vilvl_b, src7, src6, src8, src7, src76_r, src87_r); + + for (loop_cnt = (height >> 2); loop_cnt--;) { + /* 16width */ + DUP2_ARG2(__lsx_vld, src0_ptr, 0, src0_ptr, 16, src3, src9); + src0_ptr += src_stride; + DUP2_ARG2(__lsx_vld, src0_ptr, 0, src0_ptr, 16, src4, src10); + src0_ptr += src_stride; + DUP2_ARG2(__lsx_vld, src1_ptr, 0, src1_ptr, 16, in0, in2); + in4 = __lsx_vld(src1_ptr, 32); + src1_ptr += src2_stride; + DUP2_ARG2(__lsx_vld, src1_ptr, 0, src1_ptr, 16, in1, in3); + in5 = __lsx_vld(src1_ptr, 32); + src1_ptr += src2_stride; + DUP2_ARG2(__lsx_vilvl_b, src3, src2, src4, src3, src32_r, src43_r); + DUP2_ARG2(__lsx_vilvh_b, src3, src2, src4, src3, src32_l, src43_l); + /* 8width */ + DUP2_ARG2(__lsx_vilvl_b, src9, src8, src10, src9, src98_r, src109_r); + /* 16width */ + DUP4_ARG2(__lsx_vdp2_h_bu_b, src10_r, filt0, src10_l, filt0, src21_r, + filt0, src21_l, filt0, dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0_r, src32_r, filt1, dst0_l, + src32_l, filt1, dst1_r, src43_r, filt1, dst1_l, src43_l, filt1, + dst0_r, dst0_l, dst1_r, dst1_l); + /* 8width */ + DUP2_ARG2(__lsx_vdp2_h_bu_b, src76_r, filt0, src87_r, filt0, + dst2_r, dst3_r); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst2_r, src98_r, filt1, dst3_r, + src109_r, filt1, dst2_r, dst3_r); + /* 16width */ + dst0_r = hevc_bi_rnd_clip(in0, dst0_r, in2, dst0_l); + dst1_r = hevc_bi_rnd_clip(in1, dst1_r, in3, dst1_l); + dst2_r = hevc_bi_rnd_clip(in4, dst2_r, in5, dst3_r); + __lsx_vst(dst0_r, dst, 0); + __lsx_vstx(dst1_r, dst, dst_stride); + __lsx_vstelm_d(dst2_r, dst, 16, 0); + __lsx_vstelm_d(dst2_r, dst + dst_stride, 16, 1); + dst += dst_stride_2x; + + /* 16width */ + DUP4_ARG2(__lsx_vld, src0_ptr, 0, src1_ptr, 0, src1_ptr, 16, src1_ptr, + 32, src5, in0, in2, in4); + src1_ptr += src2_stride; + DUP4_ARG2(__lsx_vld, src0_ptr, 16, src1_ptr, 0, src1_ptr, 16, src1_ptr, + 32, src11, in1, in3, in5); + src1_ptr += src2_stride; + src0_ptr += src_stride; + DUP2_ARG2(__lsx_vld, src0_ptr, 0, src0_ptr, 16, src2, src8); + src0_ptr += src_stride; + DUP2_ARG2(__lsx_vilvl_b, src5, src4, src2, src5, src10_r, src21_r); + DUP2_ARG2(__lsx_vilvh_b, src5, src4, src2, src5, src10_l, src21_l); + /* 8width */ + DUP2_ARG2(__lsx_vilvl_b, src11, src10, src8, src11, src76_r, src87_r); + /* 16width */ + DUP4_ARG2(__lsx_vdp2_h_bu_b, src32_r, filt0, src32_l, filt0, src43_r, + filt0, src43_l, filt0, dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0_r, src10_r, filt1, dst0_l, + src10_l, filt1, dst1_r, src21_r, filt1, dst1_l, src21_l, + filt1, dst0_r, dst0_l, dst1_r, dst1_l); + + /* 8width */ + DUP2_ARG2(__lsx_vdp2_h_bu_b, src98_r, filt0, src109_r, filt0, + dst2_r, dst3_r); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst2_r, src76_r, filt1, dst3_r, + src87_r, filt1, dst2_r, dst3_r); + + dst0_r = hevc_bi_rnd_clip(in0, dst0_r, in2, dst0_l); + dst1_r = hevc_bi_rnd_clip(in1, dst1_r, in3, dst1_l); + dst2_r = hevc_bi_rnd_clip(in4, dst2_r, in5, dst3_r); + __lsx_vst(dst0_r, dst, 0); + __lsx_vstx(dst1_r, dst, dst_stride); + __lsx_vstelm_d(dst2_r, dst, 16, 0); + __lsx_vstelm_d(dst2_r, dst + dst_stride, 16, 1); + dst += dst_stride_2x; + } +} + +static void hevc_vt_4t_32w_lsx(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, int32_t height) +{ + hevc_vt_4t_16w_lsx(src0_ptr, src_stride, src1_ptr, src2_stride, + dst, dst_stride, filter, height); + hevc_vt_4t_16w_lsx(src0_ptr + 16, src_stride, src1_ptr + 16, src2_stride, + dst + 16, dst_stride, filter, height); +} + +static void hevc_hv_4t_6w_lsx(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 height) +{ + int32_t src_stride_2x = (src_stride << 1); + int32_t dst_stride_2x = (dst_stride << 1); + int32_t src_stride_4x = (src_stride << 2); + int32_t dst_stride_4x = (dst_stride << 2); + int32_t src2_stride_2x = (src2_stride << 1); + int32_t src2_stride_4x = (src2_stride << 2); + int32_t src_stride_3x = src_stride_2x + src_stride; + int32_t dst_stride_3x = dst_stride_2x + dst_stride; + int32_t src2_stride_3x = src2_stride_2x + src2_stride; + __m128i out0, out1; + __m128i src0, src1, src2, src3, src4, src5, src6; + __m128i vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7, mask1; + __m128i filt0, filt1, filt_h0, filt_h1; + __m128i dsth0, dsth1, dsth2, dsth3, dsth4, dsth5; + __m128i dsth6, dsth7, dsth8, dsth9, dsth10; + __m128i dst0_r, dst0_l, dst1_r, dst1_l, dst2_r, dst2_l, dst3_r, dst3_l; + __m128i dst4_r, dst5_r, dst6_r, dst7_r; + __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8; + __m128i reg0, reg1, reg2, reg3; + __m128i mask0 = __lsx_vld(ff_hevc_mask_arr, 0); + + src0_ptr -= (src_stride + 1); + DUP2_ARG2(__lsx_vldrepl_h, filter_x, 0, filter_x, 2, filt0, filt1); + + filt_h1 = __lsx_vld(filter_y, 0); + filt_h1 = __lsx_vsllwil_h_b(filt_h1, 0); + DUP2_ARG2(__lsx_vreplvei_w, filt_h1, 0, filt_h1, 1, filt_h0, filt_h1); + + mask1 = __lsx_vaddi_bu(mask0, 2); + + src0 = __lsx_vld(src0_ptr, 0); + DUP2_ARG2(__lsx_vldx, src0_ptr, src_stride, src0_ptr, src_stride_2x, + src1, src2); + src0_ptr += src_stride_3x; + + DUP2_ARG3(__lsx_vshuf_b, src0, src0, mask0, src0, src0, mask1, vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src1, src1, mask0, src1, src1, mask1, vec2, vec3); + DUP2_ARG3(__lsx_vshuf_b, src2, src2, mask0, src2, src2, mask1, vec4, vec5); + + DUP2_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec2, filt0, dsth0, dsth1); + dsth2 = __lsx_vdp2_h_bu_b(vec4, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dsth0, vec1, filt1, dsth1, vec3, filt1, + dsth0, dsth1); + dsth2 = __lsx_vdp2add_h_bu_b(dsth2, vec5, filt1); + + DUP2_ARG2(__lsx_vilvl_h, dsth1, dsth0, dsth2, dsth1, tmp0, tmp2); + DUP2_ARG2(__lsx_vilvh_h, dsth1, dsth0, dsth2, dsth1, tmp1, tmp3); + + src3 = __lsx_vld(src0_ptr, 0); + DUP2_ARG2(__lsx_vldx, src0_ptr, src_stride, src0_ptr, src_stride_2x, + src4, src5); + src6 = __lsx_vldx(src0_ptr, src_stride_3x); + src0_ptr += src_stride_4x; + DUP2_ARG3(__lsx_vshuf_b, src3, src3, mask0, src3, src3, mask1, vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src4, src4, mask0, src4, src4, mask1, vec2, vec3); + DUP2_ARG3(__lsx_vshuf_b, src5, src5, mask0, src5, src5, mask1, vec4, vec5); + DUP2_ARG3(__lsx_vshuf_b, src6, src6, mask0, src6, src6, mask1, vec6, vec7); + + DUP4_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec2, filt0, vec4, filt0, vec6, + filt0, dsth3, dsth4, dsth5, dsth6); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dsth3, vec1, filt1, dsth4, vec3, filt1, dsth5, + vec5, filt1, dsth6, vec7, filt1, dsth3, dsth4, dsth5, dsth6); + + src3 = __lsx_vld(src0_ptr, 0); + DUP2_ARG2(__lsx_vldx, src0_ptr, src_stride, src0_ptr, src_stride_2x, + src4, src5); + src6 = __lsx_vldx(src0_ptr, src_stride_3x); + + DUP2_ARG3(__lsx_vshuf_b, src3, src3, mask0, src3, src3, mask1, vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src4, src4, mask0, src4, src4, mask1, vec2, vec3); + DUP2_ARG3(__lsx_vshuf_b, src5, src5, mask0, src5, src5, mask1, vec4, vec5); + DUP2_ARG3(__lsx_vshuf_b, src6, src6, mask0, src6, src6, mask1, vec6, vec7); + + DUP4_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec2, filt0, vec4, filt0, vec6, + filt0, dsth7, dsth8, dsth9, dsth10); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dsth7, vec1, filt1, dsth8, vec3, filt1, dsth9, + vec5, filt1, dsth10, vec7, filt1, dsth7, dsth8, dsth9, dsth10); + + DUP2_ARG2(__lsx_vilvl_h, dsth3, dsth2, dsth4, dsth3, tmp4, tmp6); + DUP2_ARG2(__lsx_vilvh_h, dsth3, dsth2, dsth4, dsth3, tmp5, tmp7); + DUP2_ARG2(__lsx_vilvl_h, dsth5, dsth4, dsth6, dsth5, dsth0, dsth2); + DUP2_ARG2(__lsx_vilvh_h, dsth5, dsth4, dsth6, dsth5, dsth1, dsth3); + DUP4_ARG2(__lsx_vdp2_w_h, tmp0, filt_h0, tmp2, filt_h0, tmp4, filt_h0, + tmp6, filt_h0, dst0_r, dst1_r, dst2_r, dst3_r); + DUP4_ARG3(__lsx_vdp2add_w_h, dst0_r, tmp4, filt_h1, dst1_r, tmp6, + filt_h1, dst2_r, dsth0, filt_h1, dst3_r, dsth2, filt_h1, + dst0_r, dst1_r, dst2_r, dst3_r); + DUP2_ARG2(__lsx_vpickev_d, tmp3, tmp1, tmp7, tmp5, tmp0, tmp8); + dst0_l = __lsx_vdp2_w_h(tmp0, filt_h0); + dst0_l = __lsx_vdp2add_w_h(dst0_l, tmp8, filt_h1); + + DUP2_ARG2(__lsx_vilvl_h, dsth7, dsth6, dsth8, dsth7, tmp0, tmp2); + DUP2_ARG2(__lsx_vilvh_h, dsth7, dsth6, dsth8, dsth7, tmp1, tmp3); + DUP2_ARG2(__lsx_vilvl_h, dsth9, dsth8, dsth10, dsth9, tmp4, tmp6); + DUP2_ARG2(__lsx_vilvh_h, dsth9, dsth8, dsth10, dsth9, tmp5, tmp7); + DUP4_ARG2(__lsx_vdp2_w_h, dsth0, filt_h0, dsth2, filt_h0, tmp0, filt_h0, + tmp2, filt_h0, dst4_r, dst5_r, dst6_r, dst7_r); + DUP4_ARG3(__lsx_vdp2add_w_h, dst4_r, tmp0, filt_h1, dst5_r, tmp2, + filt_h1, dst6_r, tmp4, filt_h1, dst7_r, tmp6, filt_h1, + dst4_r, dst5_r, dst6_r, dst7_r); + DUP2_ARG2(__lsx_vpickev_d, dsth3, dsth1, tmp3, tmp1, tmp0, tmp1); + tmp2 = __lsx_vpickev_d(tmp7, tmp5); + + DUP2_ARG2(__lsx_vdp2_w_h, tmp8, filt_h0, tmp0, filt_h0, dst1_l, dst2_l); + dst3_l = __lsx_vdp2_w_h(tmp1, filt_h0); + DUP2_ARG3(__lsx_vdp2add_w_h, dst1_l, tmp0, filt_h1, dst2_l, tmp1, filt_h1, + dst1_l, dst2_l); + dst3_l = __lsx_vdp2add_w_h(dst3_l, tmp2, filt_h1); + + DUP4_ARG2(__lsx_vsrai_d, dst0_r, 6, dst1_r, 6, dst2_r, 6, dst3_r, 6, + dst0_r, dst1_r, dst2_r, dst3_r); + DUP4_ARG2(__lsx_vsrai_d, dst4_r, 6, dst5_r, 6, dst6_r, 6, dst7_r, 6, + dst4_r, dst5_r, dst6_r, dst7_r); + DUP4_ARG2(__lsx_vsrai_d, dst0_l, 6, dst1_l, 6, dst2_l, 6, dst3_l, 6, + dst0_l, dst1_l, dst2_l, dst3_l); + DUP2_ARG2(__lsx_vpickev_h, dst1_r, dst0_r, dst3_r, dst2_r, tmp0, tmp1); + DUP2_ARG2(__lsx_vpickev_h, dst5_r, dst4_r, dst7_r, dst6_r, tmp2, tmp3); + DUP2_ARG2(__lsx_vpickev_h, dst1_l, dst0_l, dst3_l, dst2_l, tmp4, tmp5); + + reg0 = __lsx_vldrepl_d(src1_ptr, 0); + reg1 = __lsx_vldrepl_d(src1_ptr + src2_stride, 0); + dsth0 = __lsx_vilvl_d(reg1, reg0); + reg0 = __lsx_vldrepl_d(src1_ptr + src2_stride_2x, 0); + reg1 = __lsx_vldrepl_d(src1_ptr + src2_stride_3x, 0); + dsth1 = __lsx_vilvl_d(reg1, reg0); + src1_ptr += src2_stride_4x; + reg0 = __lsx_vldrepl_d(src1_ptr, 0); + reg1 = __lsx_vldrepl_d(src1_ptr + src2_stride, 0); + dsth2 = __lsx_vilvl_d(reg1, reg0); + reg0 = __lsx_vldrepl_d(src1_ptr + src2_stride_2x, 0); + reg1 = __lsx_vldrepl_d(src1_ptr + src2_stride_3x, 0); + dsth3 = __lsx_vilvl_d(reg1, reg0); + + DUP4_ARG2(__lsx_vsadd_h, dsth0, tmp0, dsth1, tmp1, dsth2, tmp2, dsth3, + tmp3, tmp0, tmp1, tmp2, tmp3); + DUP4_ARG2(__lsx_vmaxi_h, tmp0, 0, tmp1, 0, tmp2, 0, tmp3, 0, + tmp0, tmp1, tmp2, tmp3); + DUP2_ARG3(__lsx_vssrlrni_bu_h, tmp1, tmp0, 7, tmp3, tmp2, 7, out0, out1); + + __lsx_vstelm_w(out0, dst, 0, 0); + __lsx_vstelm_w(out0, dst + dst_stride, 0, 1); + __lsx_vstelm_w(out0, dst + dst_stride_2x, 0, 2); + __lsx_vstelm_w(out0, dst + dst_stride_3x, 0, 3); + dst += dst_stride_4x; + __lsx_vstelm_w(out1, dst, 0, 0); + __lsx_vstelm_w(out1, dst + dst_stride, 0, 1); + __lsx_vstelm_w(out1, dst + dst_stride_2x, 0, 2); + __lsx_vstelm_w(out1, dst + dst_stride_3x, 0, 3); + dst -= dst_stride_4x; + + src1_ptr -= src2_stride_4x; + + reg0 = __lsx_vldrepl_w(src1_ptr, 8); + reg1 = __lsx_vldrepl_w(src1_ptr + src2_stride, 8); + reg2 = __lsx_vldrepl_w(src1_ptr + src2_stride_2x, 8); + reg3 = __lsx_vldrepl_w(src1_ptr + src2_stride_3x, 8); + DUP2_ARG2(__lsx_vilvl_w, reg1, reg0, reg3, reg2, tmp0, tmp1); + dsth4 = __lsx_vilvl_d(tmp1, tmp0); + src1_ptr += src2_stride_4x; + + reg0 = __lsx_vldrepl_w(src1_ptr, 8); + reg1 = __lsx_vldrepl_w(src1_ptr + src2_stride, 8); + reg2 = __lsx_vldrepl_w(src1_ptr + src2_stride_2x, 8); + reg3 = __lsx_vldrepl_w(src1_ptr + src2_stride_3x, 8); + DUP2_ARG2(__lsx_vilvl_w, reg1, reg0, reg3, reg2, tmp0, tmp1); + dsth5 = __lsx_vilvl_d(tmp1, tmp0); + DUP2_ARG2(__lsx_vsadd_h, dsth4, tmp4, dsth5, tmp5, tmp4, tmp5); + DUP2_ARG2(__lsx_vmaxi_h, tmp4, 0, tmp5, 7, tmp4, tmp5); + out0 = __lsx_vssrlrni_bu_h(tmp5, tmp4, 7); + + __lsx_vstelm_h(out0, dst, 4, 0); + __lsx_vstelm_h(out0, dst + dst_stride, 4, 1); + __lsx_vstelm_h(out0, dst + dst_stride_2x, 4, 2); + __lsx_vstelm_h(out0, dst + dst_stride_3x, 4, 3); + dst += dst_stride_4x; + __lsx_vstelm_h(out0, dst, 4, 4); + __lsx_vstelm_h(out0, dst + dst_stride, 4, 5); + __lsx_vstelm_h(out0, dst + dst_stride_2x, 4, 6); + __lsx_vstelm_h(out0, dst + dst_stride_3x, 4, 7); +} + +static av_always_inline +void hevc_hv_4t_8x2_lsx(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 src_stride_2x = (src_stride << 1); + int32_t src_stride_4x = (src_stride << 2); + int32_t src_stride_3x = src_stride_2x + src_stride; + + __m128i out; + __m128i src0, src1, src2, src3, src4; + __m128i filt0, filt1; + __m128i filt_h0, filt_h1; + __m128i mask0 = __lsx_vld(ff_hevc_mask_arr, 0); + __m128i mask1, filter_vec; + __m128i vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7, vec8, vec9; + __m128i dst0, dst1, dst2, dst3, dst4; + __m128i dst0_r, dst0_l, dst1_r, dst1_l; + __m128i dst10_r, dst32_r, dst21_r, dst43_r; + __m128i dst10_l, dst32_l, dst21_l, dst43_l; + __m128i tmp0, tmp1; + __m128i in0, in1; + + src0_ptr -= (src_stride + 1); + DUP2_ARG2(__lsx_vldrepl_h, filter_x, 0, filter_x, 2, filt0, filt1); + + filter_vec = __lsx_vld(filter_y, 0); + filter_vec = __lsx_vsllwil_h_b(filter_vec, 0); + DUP2_ARG2(__lsx_vreplvei_w, filter_vec, 0, filter_vec, 1, filt_h0, filt_h1); + + mask1 = __lsx_vaddi_bu(mask0, 2); + + src0 = __lsx_vld(src0_ptr, 0); + DUP4_ARG2(__lsx_vldx, src0_ptr, src_stride, src0_ptr, src_stride_2x, + src0_ptr, src_stride_3x, src0_ptr, src_stride_4x, + src1, src2, src3, src4); + + DUP2_ARG2(__lsx_vld, src1_ptr, 0, src1_ptr + src2_stride, 0, in0, in1); + + DUP2_ARG3(__lsx_vshuf_b, src0, src0, mask0, src0, src0, mask1, vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src1, src1, mask0, src1, src1, mask1, vec2, vec3); + DUP2_ARG3(__lsx_vshuf_b, src2, src2, mask0, src2, src2, mask1, vec4, vec5); + DUP2_ARG3(__lsx_vshuf_b, src3, src3, mask0, src3, src3, mask1, vec6, vec7); + DUP2_ARG3(__lsx_vshuf_b, src4, src4, mask0, src4, src4, mask1, vec8, vec9); + + DUP4_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec2, filt0, vec4, filt0, vec6, + filt0, dst0, dst1, dst2, dst3); + dst4 = __lsx_vdp2_h_bu_b(vec8, filt0); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec1, filt1, dst1, vec3, filt1, dst2, + vec5, filt1, dst3, vec7, filt1, dst0, dst1, dst2, dst3); + dst4 = __lsx_vdp2add_h_bu_b(dst4, vec9, filt1); + + DUP2_ARG2(__lsx_vilvl_h, dst1, dst0, dst2, dst1, dst10_r, dst21_r); + DUP2_ARG2(__lsx_vilvh_h, dst1, dst0, dst2, dst1, dst10_l, dst21_l); + DUP2_ARG2(__lsx_vilvl_h, dst3, dst2, dst4, dst3, dst32_r, dst43_r); + DUP2_ARG2(__lsx_vilvh_h, dst3, dst2, dst4, dst3, dst32_l, dst43_l); + DUP4_ARG2(__lsx_vdp2_w_h, dst10_r, filt_h0, dst10_l, filt_h0, dst21_r, + filt_h0, dst21_l, filt_h0, dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG3(__lsx_vdp2add_w_h, dst0_r, dst32_r, filt_h1, dst0_l, dst32_l, + filt_h1, dst1_r, dst43_r, filt_h1, dst1_l, dst43_l, filt_h1, + dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG2(__lsx_vsrai_w, dst0_r, 6, dst0_l, 6, dst1_r, 6, dst1_l, 6, + dst0_r, dst0_l, dst1_r, dst1_l); + DUP2_ARG2(__lsx_vpickev_h, dst0_l, dst0_r, dst1_l, dst1_r, tmp0, tmp1); + DUP2_ARG2(__lsx_vsadd_h, in0, tmp0, in1, tmp1, tmp0, tmp1); + DUP2_ARG2(__lsx_vmaxi_h, tmp0, 0, tmp1, 0, tmp0, tmp1); + out = __lsx_vssrlrni_bu_h(tmp1, tmp0, 7); + __lsx_vstelm_d(out, dst, 0, 0); + __lsx_vstelm_d(out, dst + dst_stride, 0, 1); +} + +static av_always_inline +void hevc_hv_4t_8multx4_lsx(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; + int32_t src_stride_2x = (src_stride << 1); + int32_t dst_stride_2x = (dst_stride << 1); + int32_t src_stride_4x = (src_stride << 2); + int32_t src2_stride_x = (src2_stride << 1); + int32_t src2_stride_2x = (src2_stride << 2); + int32_t src_stride_3x = src_stride_2x + src_stride; + int32_t dst_stride_3x = dst_stride_2x + dst_stride; + int32_t src2_stride_3x = src2_stride_2x + src2_stride_x; + + __m128i out0, out1; + __m128i src0, src1, src2, src3, src4, src5, src6, mask0, mask1; + __m128i vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + __m128i filt0, filt1, filt_h0, filt_h1, filter_vec; + __m128i dst0, dst1, dst2, dst3, dst4, dst5, dst6, tmp0, tmp1, tmp2, tmp3; + __m128i in0, in1, in2, in3; + __m128i dst0_r, dst0_l, dst1_r, dst1_l, dst2_r, dst2_l, dst3_r, dst3_l; + __m128i dst10_r, dst32_r, dst54_r, dst21_r, dst43_r, dst65_r; + __m128i dst10_l, dst32_l, dst54_l, dst21_l, dst43_l, dst65_l; + + src0_ptr -= (src_stride + 1); + DUP2_ARG2(__lsx_vldrepl_h, filter_x, 0, filter_x, 2, filt0, filt1); + + filter_vec = __lsx_vld(filter_y, 0); + filter_vec = __lsx_vsllwil_h_b(filter_vec, 0); + DUP2_ARG2(__lsx_vreplvei_w, filter_vec, 0, filter_vec, 1, filt_h0, filt_h1); + + mask0 = __lsx_vld(ff_hevc_mask_arr, 0); + mask1 = __lsx_vaddi_bu(mask0, 2); + + for (cnt = width8mult; cnt--;) { + src0 = __lsx_vld(src0_ptr, 0); + DUP2_ARG2(__lsx_vldx, src0_ptr, src_stride, src0_ptr, src_stride_2x, + src1, src2); + src3 = __lsx_vldx(src0_ptr, src_stride_3x); + src0_ptr += src_stride_4x; + src4 = __lsx_vld(src0_ptr, 0); + DUP2_ARG2(__lsx_vldx, src0_ptr, src_stride, src0_ptr, src_stride_2x, + src5, src6); + src0_ptr += (8 - src_stride_4x); + + in0 = __lsx_vld(src1_ptr, 0); + DUP2_ARG2(__lsx_vldx, src1_ptr, src2_stride_x, src1_ptr, + src2_stride_2x, in1, in2); + in3 = __lsx_vldx(src1_ptr, src2_stride_3x); + src1_ptr += 8; + + DUP2_ARG3(__lsx_vshuf_b, src0, src0, mask0, src0, src0, mask1, + vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src1, src1, mask0, src1, src1, mask1, + vec2, vec3); + DUP2_ARG3(__lsx_vshuf_b, src2, src2, mask0, src2, src2, mask1, + vec4, vec5); + + DUP2_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec2, filt0, dst0, dst1); + dst2 = __lsx_vdp2_h_bu_b(vec4, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec1, filt1, dst1, vec3, filt1, + dst0, dst1); + dst2 = __lsx_vdp2add_h_bu_b(dst2, vec5, filt1); + + DUP2_ARG2(__lsx_vilvl_h, dst1, dst0, dst2, dst1, dst10_r, dst21_r); + DUP2_ARG2(__lsx_vilvh_h, dst1, dst0, dst2, dst1, dst10_l, dst21_l); + + DUP2_ARG3(__lsx_vshuf_b, src3, src3, mask0, src3, src3, mask1, + vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src4, src4, mask0, src4, src4, mask1, + vec2, vec3); + DUP2_ARG3(__lsx_vshuf_b, src5, src5, mask0, src5, src5, mask1, + vec4, vec5); + DUP2_ARG3(__lsx_vshuf_b, src6, src6, mask0, src6, src6, mask1, + vec6, vec7); + + DUP4_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec2, filt0, vec4, filt0, + vec6, filt0, dst3, dst4, dst5, dst6); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst3, vec1, filt1, dst4, vec3, filt1, + dst5, vec5, filt1, dst6, vec7, filt1, dst3, dst4, dst5, dst6); + + DUP2_ARG2(__lsx_vilvl_h, dst3, dst2, dst4, dst3, dst32_r, dst43_r); + DUP2_ARG2(__lsx_vilvh_h, dst3, dst2, dst4, dst3, dst32_l, dst43_l); + DUP2_ARG2(__lsx_vilvl_h, dst5, dst4, dst6, dst5, dst54_r, dst65_r); + DUP2_ARG2(__lsx_vilvh_h, dst5, dst4, dst6, dst5, dst54_l, dst65_l); + + DUP4_ARG2(__lsx_vdp2_w_h, dst10_r, filt_h0, dst10_l, filt_h0, dst21_r, + filt_h0, dst21_l, filt_h0, dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG2(__lsx_vdp2_w_h, dst32_r, filt_h0, dst32_l, filt_h0, dst43_r, + filt_h0, dst43_l, filt_h0, dst2_r, dst2_l, dst3_r, dst3_l); + DUP4_ARG3(__lsx_vdp2add_w_h, dst0_r, dst32_r, filt_h1, dst0_l, dst32_l, + filt_h1, dst1_r, dst43_r, filt_h1, dst1_l, dst43_l, filt_h1, + dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG3(__lsx_vdp2add_w_h, dst2_r, dst54_r, filt_h1, dst2_l, dst54_l, + filt_h1, dst3_r, dst65_r, filt_h1, dst3_l, dst65_l, filt_h1, + dst2_r, dst2_l, dst3_r, dst3_l); + + DUP4_ARG2(__lsx_vsrai_w, dst0_r, 6, dst0_l, 6, dst1_r, 6, dst1_l, 6, + dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG2(__lsx_vsrai_w, dst2_r, 6, dst2_l, 6, dst3_r, 6, dst3_l, 6, + dst2_r, dst2_l, dst3_r, dst3_l); + DUP4_ARG2(__lsx_vpickev_h, dst0_l, dst0_r, dst1_l, dst1_r, dst2_l, + dst2_r, dst3_l, dst3_r, tmp0, tmp1, tmp2, tmp3); + DUP4_ARG2(__lsx_vsadd_h, in0, tmp0, in1, tmp1, in2, tmp2, in3, tmp3, + tmp0, tmp1, tmp2, tmp3); + DUP4_ARG2(__lsx_vmaxi_h, tmp0, 0, tmp1, 0, tmp2, 0, tmp3, 0, + tmp0, tmp1, tmp2, tmp3); + DUP2_ARG3(__lsx_vssrlrni_bu_h, tmp1, tmp0, 7, tmp3, tmp2, 7, out0, out1); + __lsx_vstelm_d(out0, dst, 0, 0); + __lsx_vstelm_d(out0, dst + dst_stride, 0, 1); + __lsx_vstelm_d(out1, dst + dst_stride_2x, 0, 0); + __lsx_vstelm_d(out1, dst + dst_stride_3x, 0, 1); + dst += 8; + } +} + +static av_always_inline +void hevc_hv_4t_8x6_lsx(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 src_stride_2x = (src_stride << 1); + int32_t dst_stride_2x = (dst_stride << 1); + int32_t src_stride_4x = (src_stride << 2); + int32_t dst_stride_4x = (dst_stride << 2); + int32_t src2_stride_x = (src2_stride << 1); + int32_t src2_stride_2x = (src2_stride << 2); + int32_t src_stride_3x = src_stride_2x + src_stride; + int32_t dst_stride_3x = dst_stride_2x + dst_stride; + int32_t src2_stride_3x = src2_stride_2x + src2_stride_x; + + __m128i out0, out1, out2; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8; + __m128i in0, in1, in2, in3, in4, in5; + __m128i filt0, filt1; + __m128i filt_h0, filt_h1; + __m128i mask0 = __lsx_vld(ff_hevc_mask_arr, 0); + __m128i mask1, filter_vec; + __m128i vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7, vec8, vec9; + __m128i vec10, vec11, vec12, vec13, vec14, vec15, vec16, vec17; + __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + __m128i dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7, dst8; + __m128i dst0_r, dst0_l, dst1_r, dst1_l, dst2_r, dst2_l, dst3_r, dst3_l; + __m128i dst4_r, dst4_l, dst5_r, dst5_l; + __m128i dst10_r, dst32_r, dst10_l, dst32_l; + __m128i dst21_r, dst43_r, dst21_l, dst43_l; + __m128i dst54_r, dst54_l, dst65_r, dst65_l; + __m128i dst76_r, dst76_l, dst87_r, dst87_l; + + src0_ptr -= (src_stride + 1); + DUP2_ARG2(__lsx_vldrepl_h, filter_x, 0, filter_x, 2, filt0, filt1); + + filter_vec = __lsx_vld(filter_y, 0); + filter_vec = __lsx_vsllwil_h_b(filter_vec, 0); + DUP2_ARG2(__lsx_vreplvei_w, filter_vec, 0, filter_vec, 1, filt_h0, filt_h1); + + mask1 = __lsx_vaddi_bu(mask0, 2); + + src0 = __lsx_vld(src0_ptr, 0); + DUP2_ARG2(__lsx_vldx, src0_ptr, src_stride, src0_ptr, src_stride_2x, + src1, src2); + src3 = __lsx_vldx(src0_ptr, src_stride_3x); + src0_ptr += src_stride_4x; + src4 = __lsx_vld(src0_ptr, 0); + DUP4_ARG2(__lsx_vldx, src0_ptr, src_stride, src0_ptr, src_stride_2x, + src0_ptr, src_stride_3x, src0_ptr, src_stride_4x, + src5, src6, src7, src8); + + in0 = __lsx_vld(src1_ptr, 0); + DUP2_ARG2(__lsx_vldx, src1_ptr, src2_stride_x, src1_ptr, src2_stride_2x, + in1, in2); + in3 = __lsx_vldx(src1_ptr, src2_stride_3x); + src1_ptr += src2_stride_2x; + in4 = __lsx_vld(src1_ptr, 0); + in5 = __lsx_vldx(src1_ptr, src2_stride_x); + + DUP2_ARG3(__lsx_vshuf_b, src0, src0, mask0, src0, src0, mask1, vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src1, src1, mask0, src1, src1, mask1, vec2, vec3); + DUP2_ARG3(__lsx_vshuf_b, src2, src2, mask0, src2, src2, mask1, vec4, vec5); + DUP2_ARG3(__lsx_vshuf_b, src3, src3, mask0, src3, src3, mask1, vec6, vec7); + DUP2_ARG3(__lsx_vshuf_b, src4, src4, mask0, src4, src4, mask1, vec8, vec9); + DUP2_ARG3(__lsx_vshuf_b, src5, src5, mask0, src5, src5, mask1, vec10, vec11); + DUP2_ARG3(__lsx_vshuf_b, src6, src6, mask0, src6, src6, mask1, vec12, vec13); + DUP2_ARG3(__lsx_vshuf_b, src7, src7, mask0, src7, src7, mask1, vec14, vec15); + DUP2_ARG3(__lsx_vshuf_b, src8, src8, mask0, src8, src8, mask1, vec16, vec17); + + DUP4_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec2, filt0, vec4, filt0, vec6, + filt0, dst0, dst1, dst2, dst3); + dst4 = __lsx_vdp2_h_bu_b(vec8, filt0); + DUP4_ARG2(__lsx_vdp2_h_bu_b, vec10, filt0, vec12, filt0, vec14, filt0, + vec16, filt0, dst5, dst6, dst7, dst8); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec1, filt1, dst1, vec3, filt1, dst2, + vec5, filt1, dst3, vec7, filt1, dst0, dst1, dst2, dst3); + dst4 = __lsx_vdp2add_h_bu_b(dst4, vec9, filt1); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst5, vec11, filt1, dst6, vec13, filt1, + dst7, vec15, filt1, dst8, vec17, filt1, dst5, dst6, dst7, dst8); + + DUP4_ARG2(__lsx_vilvl_h, dst1, dst0, dst2, dst1, dst3, dst2, dst4, dst3, + dst10_r, dst21_r, dst32_r, dst43_r); + DUP4_ARG2(__lsx_vilvh_h, dst1, dst0, dst2, dst1, dst3, dst2, dst4, dst3, + dst10_l, dst21_l, dst32_l, dst43_l); + DUP4_ARG2(__lsx_vilvl_h, dst5, dst4, dst6, dst5, dst7, dst6, dst8, dst7, + dst54_r, dst65_r, dst76_r, dst87_r); + DUP4_ARG2(__lsx_vilvh_h, dst5, dst4, dst6, dst5, dst7, dst6, dst8, dst7, + dst54_l, dst65_l, dst76_l, dst87_l); + + DUP4_ARG2(__lsx_vdp2_w_h, dst10_r, filt_h0, dst10_l, filt_h0, dst21_r, + filt_h0, dst21_l, filt_h0, dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG2(__lsx_vdp2_w_h, dst32_r, filt_h0, dst32_l, filt_h0, dst43_r, + filt_h0, dst43_l, filt_h0, dst2_r, dst2_l, dst3_r, dst3_l); + DUP4_ARG2(__lsx_vdp2_w_h, dst54_r, filt_h0, dst54_l, filt_h0, dst65_r, + filt_h0, dst65_l, filt_h0, dst4_r, dst4_l, dst5_r, dst5_l); + DUP4_ARG3(__lsx_vdp2add_w_h, dst0_r, dst32_r, filt_h1, dst0_l, dst32_l, + filt_h1, dst1_r, dst43_r, filt_h1, dst1_l, dst43_l, filt_h1, + dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG3(__lsx_vdp2add_w_h, dst2_r, dst54_r, filt_h1, dst2_l, dst54_l, + filt_h1, dst3_r, dst65_r, filt_h1, dst3_l, dst65_l, filt_h1, + dst2_r, dst2_l, dst3_r, dst3_l); + DUP4_ARG3(__lsx_vdp2add_w_h, dst4_r, dst76_r, filt_h1, dst4_l, dst76_l, + filt_h1, dst5_r, dst87_r, filt_h1, dst5_l, dst87_l, filt_h1, + dst4_r, dst4_l, dst5_r, dst5_l); + + DUP4_ARG2(__lsx_vsrai_w, dst0_r, 6, dst0_l, 6, dst1_r, 6, dst1_l, 6, + dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG2(__lsx_vsrai_w, dst2_r, 6, dst2_l, 6, dst3_r, 6, dst3_l, 6, + dst2_r, dst2_l, dst3_r, dst3_l); + DUP4_ARG2(__lsx_vsrai_w, dst4_r, 6, dst4_l, 6, dst5_r, 6, dst5_l, 6, + dst4_r, dst4_l, dst5_r, dst5_l); + DUP4_ARG2(__lsx_vpickev_h, dst0_l, dst0_r, dst1_l, dst1_r, dst2_l, dst2_r, + dst3_l, dst3_r, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lsx_vpickev_h, dst4_l, dst4_r, dst5_l, dst5_r, tmp4, tmp5); + DUP4_ARG2(__lsx_vsadd_h, in0, tmp0, in1, tmp1, in2, tmp2, in3, tmp3, + tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lsx_vsadd_h, in4, tmp4, in5, tmp5, tmp4, tmp5); + DUP4_ARG2(__lsx_vmaxi_h, tmp0, 0, tmp1, 0, tmp2, 0, tmp3, 0, + tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lsx_vmaxi_h, tmp4, 0, tmp5, 0, tmp4, tmp5); + DUP2_ARG3(__lsx_vssrlrni_bu_h, tmp1, tmp0, 7, tmp3, tmp2, 7, out0, out1); + out2 = __lsx_vssrlrni_bu_h(tmp5, tmp4, 7); + __lsx_vstelm_d(out0, dst, 0, 0); + __lsx_vstelm_d(out0, dst + dst_stride, 0, 1); + __lsx_vstelm_d(out1, dst + dst_stride_2x, 0, 0); + __lsx_vstelm_d(out1, dst + dst_stride_3x, 0, 1); + dst += dst_stride_4x; + __lsx_vstelm_d(out2, dst, 0, 0); + __lsx_vstelm_d(out2, dst + dst_stride, 0, 1); +} + +static av_always_inline +void hevc_hv_4t_8multx4mult_lsx(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 height, int32_t width) +{ + uint32_t loop_cnt, cnt; + uint8_t *src0_ptr_tmp; + int16_t *src1_ptr_tmp; + uint8_t *dst_tmp; + const int32_t src_stride_2x = (src_stride << 1); + const int32_t dst_stride_2x = (dst_stride << 1); + const int32_t src_stride_4x = (src_stride << 2); + const int32_t dst_stride_4x = (dst_stride << 2); + const int32_t src2_stride_x = (src2_stride << 1); + const int32_t src2_stride_2x = (src2_stride << 2); + const int32_t src_stride_3x = src_stride_2x + src_stride; + const int32_t dst_stride_3x = dst_stride_2x + dst_stride; + const int32_t src2_stride_3x = src2_stride_2x + src2_stride_x; + __m128i out0, out1; + __m128i src0, src1, src2, src3, src4, src5, src6; + __m128i in0, in1, in2, in3; + __m128i filt0, filt1; + __m128i filt_h0, filt_h1; + __m128i mask0 = __lsx_vld(ff_hevc_mask_arr, 0); + __m128i mask1, filter_vec; + __m128i vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + __m128i dst0, dst1, dst2, dst3, dst4, dst5; + __m128i dst0_r, dst0_l, dst1_r, dst1_l, dst2_r, dst2_l, dst3_r, dst3_l; + __m128i tmp0, tmp1, tmp2, tmp3; + __m128i dst10_r, dst32_r, dst21_r, dst43_r; + __m128i dst10_l, dst32_l, dst21_l, dst43_l; + __m128i dst54_r, dst54_l, dst65_r, dst65_l, dst6; + + src0_ptr -= (src_stride + 1); + + DUP2_ARG2(__lsx_vldrepl_h, filter_x, 0, filter_x, 2, filt0, filt1); + + filter_vec = __lsx_vld(filter_y, 0); + filter_vec = __lsx_vsllwil_h_b(filter_vec, 0); + + DUP2_ARG2(__lsx_vreplvei_w, filter_vec, 0, filter_vec, 1, filt_h0, filt_h1); + + mask1 = __lsx_vaddi_bu(mask0, 2); + + for (cnt = width >> 3; cnt--;) { + src0_ptr_tmp = src0_ptr; + dst_tmp = dst; + src1_ptr_tmp = src1_ptr; + + src0 = __lsx_vld(src0_ptr_tmp, 0); + DUP2_ARG2(__lsx_vldx, src0_ptr_tmp, src_stride, src0_ptr_tmp, + src_stride_2x, src1, src2); + src0_ptr_tmp += src_stride_3x; + + DUP2_ARG3(__lsx_vshuf_b, src0, src0, mask0, src0, src0, mask1, + vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src1, src1, mask0, src1, src1, mask1, + vec2, vec3); + DUP2_ARG3(__lsx_vshuf_b, src2, src2, mask0, src2, src2, mask1, + vec4, vec5); + + DUP2_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec2, filt0, dst0, dst1); + dst2 = __lsx_vdp2_h_bu_b(vec4, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec1, filt1, dst1, vec3, filt1, + dst0, dst1); + dst2 = __lsx_vdp2add_h_bu_b(dst2, vec5, filt1); + + DUP2_ARG2(__lsx_vilvl_h, dst1, dst0, dst2, dst1, dst10_r, dst21_r); + DUP2_ARG2(__lsx_vilvh_h, dst1, dst0, dst2, dst1, dst10_l, dst21_l); + + for (loop_cnt = height >> 2; loop_cnt--;) { + src3 = __lsx_vld(src0_ptr_tmp, 0); + DUP2_ARG2(__lsx_vldx, src0_ptr_tmp, src_stride, src0_ptr_tmp, + src_stride_2x, src4, src5); + src6 = __lsx_vldx(src0_ptr_tmp, src_stride_3x); + src0_ptr_tmp += src_stride_4x; + in0 = __lsx_vld(src1_ptr_tmp, 0); + DUP2_ARG2(__lsx_vldx, src1_ptr_tmp, src2_stride_x, src1_ptr_tmp, + src2_stride_2x, in1, in2); + in3 = __lsx_vldx(src1_ptr_tmp, src2_stride_3x); + src1_ptr_tmp += src2_stride_2x; + + DUP4_ARG3(__lsx_vshuf_b, src3, src3, mask0, src3, src3, mask1, src4, + src4, mask0, src4, src4, mask1, vec0, vec1, vec2, vec3); + DUP4_ARG3(__lsx_vshuf_b, src5, src5, mask0, src5, src5, mask1, src6, + src6, mask0, src6, src6, mask1, vec4, vec5, vec6, vec7); + + DUP4_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec2, filt0, vec4, filt0, + vec6, filt0, dst3, dst4, dst5, dst6); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst3, vec1, filt1, dst4, vec3, + filt1, dst5, vec5, filt1, dst6, vec7, filt1, + dst3, dst4, dst5, dst6); + + DUP2_ARG2(__lsx_vilvl_h, dst3, dst2, dst4, dst3, dst32_r, dst43_r); + DUP2_ARG2(__lsx_vilvh_h, dst3, dst2, dst4, dst3, dst32_l, dst43_l); + DUP2_ARG2(__lsx_vilvl_h, dst5, dst4, dst6, dst5, dst54_r, dst65_r); + DUP2_ARG2(__lsx_vilvh_h, dst5, dst4, dst6, dst5, dst54_l, dst65_l); + + DUP4_ARG2(__lsx_vdp2_w_h, dst10_r, filt_h0, dst10_l, filt_h0, dst21_r, + filt_h0, dst21_l, filt_h0, dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG2(__lsx_vdp2_w_h, dst32_r, filt_h0, dst32_l, filt_h0, dst43_r, + filt_h0, dst43_l, filt_h0, dst2_r, dst2_l, dst3_r, dst3_l); + DUP4_ARG3(__lsx_vdp2add_w_h, dst0_r, dst32_r, filt_h1, dst0_l, + dst32_l, filt_h1, dst1_r, dst43_r, filt_h1, dst1_l, + dst43_l, filt_h1, dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG3(__lsx_vdp2add_w_h, dst2_r, dst54_r, filt_h1, dst2_l, + dst54_l, filt_h1, dst3_r, dst65_r, filt_h1, dst3_l, + dst65_l, filt_h1, dst2_r, dst2_l, dst3_r, dst3_l); + + DUP4_ARG2(__lsx_vsrai_w, dst0_r, 6, dst0_l, 6, dst1_r, 6, dst1_l, 6, + dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG2(__lsx_vsrai_w, dst2_r, 6, dst2_l, 6, dst3_r, 6, dst3_l, 6, + dst2_r, dst2_l, dst3_r, dst3_l); + DUP4_ARG2(__lsx_vpickev_h, dst0_l, dst0_r, dst1_l, dst1_r, dst2_l, + dst2_r, dst3_l, dst3_r, tmp0, tmp1, tmp2, tmp3); + DUP4_ARG2(__lsx_vsadd_h, in0, tmp0, in1, tmp1, in2, tmp2, in3, tmp3, + tmp0, tmp1, tmp2, tmp3); + DUP4_ARG2(__lsx_vmaxi_h, tmp0, 0, tmp1, 0, tmp2, 0, tmp3, 0, tmp0, + tmp1, tmp2, tmp3); + DUP2_ARG3(__lsx_vssrlrni_bu_h, tmp1, tmp0, 7, tmp3, tmp2, 7, out0, out1); + __lsx_vstelm_d(out0, dst_tmp, 0, 0); + __lsx_vstelm_d(out0, dst_tmp + dst_stride, 0, 1); + __lsx_vstelm_d(out1, dst_tmp + dst_stride_2x, 0, 0); + __lsx_vstelm_d(out1, dst_tmp + dst_stride_3x, 0, 1); + dst_tmp += dst_stride_4x; + + dst10_r = dst54_r; + dst10_l = dst54_l; + dst21_r = dst65_r; + dst21_l = dst65_l; + dst2 = dst6; + } + + src0_ptr += 8; + dst += 8; + src1_ptr += 8; + } +} + +static void hevc_hv_4t_8w_lsx(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 height) +{ + if (2 == height) { + hevc_hv_4t_8x2_lsx(src0_ptr, src_stride, src1_ptr, src2_stride, + dst, dst_stride, filter_x, filter_y); + } else if (4 == height) { + hevc_hv_4t_8multx4_lsx(src0_ptr, src_stride, src1_ptr, src2_stride, + dst, dst_stride, filter_x, filter_y, 1); + } else if (6 == height) { + hevc_hv_4t_8x6_lsx(src0_ptr, src_stride, src1_ptr, src2_stride, + dst, dst_stride, filter_x, filter_y); + } else { + hevc_hv_4t_8multx4mult_lsx(src0_ptr, src_stride, src1_ptr, src2_stride, + dst, dst_stride, filter_x, filter_y, height, 8); + } +} + +static void hevc_hv_4t_16w_lsx(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 height) +{ + if (4 == height) { + hevc_hv_4t_8multx4_lsx(src0_ptr, src_stride, src1_ptr, src2_stride, + dst, dst_stride, filter_x, filter_y, 2); + } else { + hevc_hv_4t_8multx4mult_lsx(src0_ptr, src_stride, src1_ptr, src2_stride, + dst, dst_stride, filter_x, filter_y, height, 16); + } +} + +static void hevc_hv_4t_24w_lsx(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 height) +{ + hevc_hv_4t_8multx4mult_lsx(src0_ptr, src_stride, src1_ptr, src2_stride, + dst, dst_stride, filter_x, filter_y, height, 24); +} + +static void hevc_hv_4t_32w_lsx(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 height) +{ + hevc_hv_4t_8multx4mult_lsx(src0_ptr, src_stride, src1_ptr, src2_stride, + dst, dst_stride, filter_x, filter_y, height, 32); +} + +#define BI_MC_COPY(WIDTH) \ +void ff_hevc_put_hevc_bi_pel_pixels##WIDTH##_8_lsx(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) \ +{ \ + hevc_bi_copy_##WIDTH##w_lsx(src, src_stride, src_16bit, MAX_PB_SIZE, \ + dst, dst_stride, height); \ +} + +BI_MC_COPY(4); +BI_MC_COPY(6); +BI_MC_COPY(8); +BI_MC_COPY(12); +BI_MC_COPY(16); +BI_MC_COPY(24); +BI_MC_COPY(32); +BI_MC_COPY(48); +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_lsx(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##_##TAP##t_##WIDTH##w_lsx(src, src_stride, src_16bit, \ + MAX_PB_SIZE, dst, dst_stride, \ + filter, height); \ +} + +BI_MC(qpel, h, 16, 8, hz, mx); +BI_MC(qpel, h, 24, 8, hz, mx); +BI_MC(qpel, h, 32, 8, hz, mx); +BI_MC(qpel, h, 48, 8, hz, mx); +BI_MC(qpel, h, 64, 8, hz, mx); + +BI_MC(qpel, v, 8, 8, vt, my); +BI_MC(qpel, v, 16, 8, vt, my); +BI_MC(qpel, v, 24, 8, vt, my); +BI_MC(qpel, v, 32, 8, vt, my); +BI_MC(qpel, v, 48, 8, vt, my); +BI_MC(qpel, v, 64, 8, vt, my); + +BI_MC(epel, h, 24, 4, hz, mx); +BI_MC(epel, h, 32, 4, hz, mx); + +BI_MC(epel, v, 12, 4, vt, my); +BI_MC(epel, v, 16, 4, vt, my); +BI_MC(epel, v, 24, 4, vt, my); +BI_MC(epel, v, 32, 4, vt, my); + +#undef BI_MC + +#define BI_MC_HV(PEL, WIDTH, TAP) \ +void ff_hevc_put_hevc_bi_##PEL##_hv##WIDTH##_8_lsx(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_##TAP##t_##WIDTH##w_lsx(src, src_stride, src_16bit, \ + MAX_PB_SIZE, dst, dst_stride, \ + filter_x, filter_y, height); \ +} + +BI_MC_HV(qpel, 8, 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, 8, 4); +BI_MC_HV(epel, 6, 4); +BI_MC_HV(epel, 16, 4); +BI_MC_HV(epel, 24, 4); +BI_MC_HV(epel, 32, 4); + +#undef BI_MC_HV diff --git a/libavcodec/loongarch/hevc_mc_uni_lsx.c b/libavcodec/loongarch/hevc_mc_uni_lsx.c new file mode 100644 index 000000000..a15c86268 --- /dev/null +++ b/libavcodec/loongarch/hevc_mc_uni_lsx.c @@ -0,0 +1,1423 @@ +/* + * Copyright (c) 2022 Loongson Technology Corporation Limited + * Contributed by Lu Wang + * Hao Chen + * + * 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/loongarch/loongson_intrinsics.h" +#include "hevcdsp_lsx.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 +}; + +static av_always_inline +void common_hz_8t_64w_lsx(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; + __m128i mask0, mask1, mask2, mask3, out1, out2; + __m128i src0, src1, src2, src3, src4, src5, src6, src7; + __m128i vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + __m128i filt0, filt1, filt2, filt3; + __m128i res0, res1, res2, res3; + + mask0 = __lsx_vld(ff_hevc_mask_arr, 0); + src -= 3; + + /* rearranging filter */ + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filt0, filt1, filt2, filt3); + + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + + for (loop_cnt = height; loop_cnt--;) { + DUP4_ARG2(__lsx_vld, src, 0, src, 8, src, 16, src, 24, + src0, src1, src2, src3); + DUP4_ARG2(__lsx_vld, src, 32, src, 40, src, 48, src, 56, + src4, src5, src6, src7); + src += src_stride; + + DUP2_ARG3(__lsx_vshuf_b, src0, src0, mask0, src1, src1, mask0, + vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src2, src2, mask0, src3, src3, mask0, + vec2, vec3); + DUP4_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec1, filt0, vec2, filt0, + vec3, filt0, res0, res1, res2, res3); + DUP2_ARG3(__lsx_vshuf_b, src0, src0, mask2, src1, src1, mask2, + vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src2, src2, mask2, src3, src3, mask2, + vec2, vec3); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, res0, vec0, filt2, res1, vec1, filt2, + res2, vec2, filt2, res3, vec3, filt2, res0, res1, res2, res3); + DUP2_ARG3(__lsx_vshuf_b, src0, src0, mask1, src1, src1, mask1, + vec4, vec5); + DUP2_ARG3(__lsx_vshuf_b, src2, src2, mask1, src3, src3, mask1, + vec6, vec7); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, res0, vec4, filt1, res1, vec5, filt1, + res2, vec6, filt1, res3, vec7, filt1, res0, res1, res2, res3); + DUP2_ARG3(__lsx_vshuf_b, src0, src0, mask3, src1, src1, mask3, + vec4, vec5); + DUP2_ARG3(__lsx_vshuf_b, src2, src2, mask3, src3, src3, mask3, + vec6, vec7); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, res0, vec4, filt3, res1, vec5, filt3, + res2, vec6, filt3, res3, vec7, filt3, res0, res1, res2, res3); + + DUP2_ARG3(__lsx_vssrarni_bu_h, res1, res0, 6, res3, res2, 6, + out1, out2); + __lsx_vst(out1, dst, 0); + __lsx_vst(out2, dst, 16); + + DUP2_ARG3(__lsx_vshuf_b, src4, src4, mask0, src5, src5, mask0, + vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src6, src6, mask0, src7, src7, mask0, + vec2, vec3); + DUP4_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec1, filt0, vec2, filt0, + vec3, filt0, res0, res1, res2, res3); + DUP2_ARG3(__lsx_vshuf_b, src4, src4, mask2, src5, src5, mask2, + vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src6, src6, mask2, src7, src7, mask2, + vec2, vec3); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, res0, vec0, filt2, res1, vec1, filt2, + res2, vec2, filt2, res3, vec3, filt2, res0, res1, res2, res3); + DUP2_ARG3(__lsx_vshuf_b, src4, src4, mask1, src5, src5, mask1, + vec4, vec5); + DUP2_ARG3(__lsx_vshuf_b, src6, src6, mask1, src7, src7, mask1, + vec6, vec7); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, res0, vec4, filt1, res1, vec5, filt1, + res2, vec6, filt1, res3, vec7, filt1, res0, res1, res2, res3); + DUP2_ARG3(__lsx_vshuf_b, src4, src4, mask3, src5, src5, mask3, + vec4, vec5); + DUP2_ARG3(__lsx_vshuf_b, src6, src6, mask3, src7, src7, mask3, + vec6, vec7); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, res0, vec4, filt3, res1, vec5, filt3, + res2, vec6, filt3, res3, vec7, filt3, res0, res1, res2, res3); + + DUP2_ARG3(__lsx_vssrarni_bu_h, res1, res0, 6, res3, res2, 6, + out1, out2); + __lsx_vst(out1, dst, 32); + __lsx_vst(out2, dst, 48); + dst += dst_stride; + } +} + +static av_always_inline +void common_vt_8t_8w_lsx(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; + int32_t src_stride_2x = (src_stride << 1); + int32_t dst_stride_2x = (dst_stride << 1); + int32_t src_stride_4x = (src_stride << 2); + int32_t dst_stride_4x = (dst_stride << 2); + int32_t src_stride_3x = src_stride_2x + src_stride; + int32_t dst_stride_3x = dst_stride_2x + dst_stride; + + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + __m128i src10_r, src32_r, src54_r, src76_r, src98_r, src21_r, src43_r; + __m128i src65_r, src87_r, src109_r, filt0, filt1, filt2, filt3; + __m128i tmp0, tmp1; + __m128i out0_r, out1_r, out2_r, out3_r; + + src -= src_stride_3x; + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filt0, filt1, filt2, filt3); + + src0 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src1, src2); + src3 = __lsx_vldx(src, src_stride_3x); + src += src_stride_4x; + src4 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src5, src6); + src += src_stride_3x; + DUP4_ARG2(__lsx_vilvl_b, src1, src0, src3, src2, src5, src4, src2, src1, + src10_r, src32_r, src54_r, src21_r); + DUP2_ARG2(__lsx_vilvl_b, src4, src3, src6, src5, src43_r, src65_r); + + for (loop_cnt = (height >> 2); loop_cnt--;) { + src7 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src8, src9); + src10 = __lsx_vldx(src, src_stride_3x); + src += src_stride_4x; + + DUP4_ARG2(__lsx_vilvl_b, src7, src6, src8, src7, src9, src8, src10, + src9, src76_r, src87_r, src98_r, src109_r); + DUP4_ARG2(__lsx_vdp2_h_bu_b, src10_r, filt0, src21_r, filt0, src32_r, + filt0, src43_r, filt0, out0_r, out1_r, out2_r, out3_r); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, out0_r, src32_r, filt1, out1_r, + src43_r, filt1, out2_r, src54_r, filt1, out3_r, src65_r, + filt1, out0_r, out1_r, out2_r, out3_r); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, out0_r, src54_r, filt2, out1_r, + src65_r, filt2, out2_r, src76_r, filt2, out3_r, src87_r, + filt2, out0_r, out1_r, out2_r, out3_r); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, out0_r, src76_r, filt3, out1_r, + src87_r, filt3, out2_r, src98_r, filt3, out3_r, src109_r, + filt3, out0_r, out1_r, out2_r, out3_r); + + DUP2_ARG3(__lsx_vssrarni_bu_h, out1_r, out0_r, 6, out3_r, out2_r, 6, + tmp0, tmp1) + __lsx_vstelm_d(tmp0, dst, 0, 0); + __lsx_vstelm_d(tmp0, dst + dst_stride, 0, 1); + __lsx_vstelm_d(tmp1, dst + dst_stride_2x, 0, 0); + __lsx_vstelm_d(tmp1, dst + dst_stride_3x, 0, 1); + dst += dst_stride_4x; + + src10_r = src54_r; + src32_r = src76_r; + src54_r = src98_r; + src21_r = src65_r; + src43_r = src87_r; + src65_r = src109_r; + src6 = src10; + } +} + +static av_always_inline +void common_vt_8t_16w_lsx(uint8_t *src, int32_t src_stride, uint8_t *dst, + int32_t dst_stride, const int8_t *filter, + int32_t height, int32_t width) +{ + uint8_t *src_tmp; + uint8_t *dst_tmp; + uint32_t loop_cnt, cnt; + const int32_t src_stride_2x = (src_stride << 1); + const int32_t dst_stride_2x = (dst_stride << 1); + const int32_t src_stride_4x = (src_stride << 2); + const int32_t dst_stride_4x = (dst_stride << 2); + const int32_t src_stride_3x = src_stride_2x + src_stride; + const int32_t dst_stride_3x = dst_stride_2x + dst_stride; + + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + __m128i filt0, filt1, filt2, filt3; + __m128i src10_r, src32_r, src54_r, src76_r, src98_r, src21_r, src43_r; + __m128i src65_r, src87_r, src109_r, src10_l, src32_l, src54_l, src76_l; + __m128i src98_l, src21_l, src43_l, src65_l, src87_l, src109_l; + __m128i tmp0, tmp1, tmp2, tmp3; + __m128i out0_r, out1_r, out2_r, out3_r, out0_l, out1_l, out2_l, out3_l; + + src -= src_stride_3x; + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, filt0, + filt1, filt2, filt3); + + for (cnt = (width >> 4); cnt--;) { + src_tmp = src; + dst_tmp = dst; + + src0 = __lsx_vld(src_tmp, 0); + DUP2_ARG2(__lsx_vldx, src_tmp, src_stride, src_tmp, src_stride_2x, + src1, src2); + src3 = __lsx_vldx(src_tmp, src_stride_3x); + src_tmp += src_stride_4x; + src4 = __lsx_vld(src_tmp, 0); + DUP2_ARG2(__lsx_vldx, src_tmp, src_stride, src_tmp, src_stride_2x, + src5, src6); + src_tmp += src_stride_3x; + DUP4_ARG2(__lsx_vilvl_b, src1, src0, src3, src2, src5, src4, src2, src1, + src10_r, src32_r, src54_r, src21_r); + DUP2_ARG2(__lsx_vilvl_b, src4, src3, src6, src5, src43_r, src65_r); + DUP4_ARG2(__lsx_vilvh_b, src1, src0, src3, src2, src5, src4, src2, src1, + src10_l, src32_l, src54_l, src21_l); + DUP2_ARG2(__lsx_vilvh_b, src4, src3, src6, src5, src43_l, src65_l); + + for (loop_cnt = (height >> 2); loop_cnt--;) { + src7 = __lsx_vld(src_tmp, 0); + DUP2_ARG2(__lsx_vldx, src_tmp, src_stride, src_tmp, src_stride_2x, + src8, src9); + src10 = __lsx_vldx(src_tmp, src_stride_3x); + src_tmp += src_stride_4x; + DUP4_ARG2(__lsx_vilvl_b, src7, src6, src8, src7, src9, src8, src10, + src9, src76_r, src87_r, src98_r, src109_r); + DUP4_ARG2(__lsx_vilvh_b, src7, src6, src8, src7, src9, src8, src10, + src9, src76_l, src87_l, src98_l, src109_l); + DUP4_ARG2(__lsx_vdp2_h_bu_b, src10_r, filt0, src21_r, filt0, src32_r, + filt0, src43_r, filt0, out0_r, out1_r, out2_r, out3_r); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, out0_r, src32_r, filt1, out1_r, + src43_r, filt1, out2_r, src54_r, filt1, out3_r, src65_r, + filt1, out0_r, out1_r, out2_r, out3_r); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, out0_r, src54_r, filt2, out1_r, + src65_r, filt2, out2_r, src76_r, filt2, out3_r, src87_r, + filt2, out0_r, out1_r, out2_r, out3_r); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, out0_r, src76_r, filt3, out1_r, + src87_r, filt3, out2_r, src98_r, filt3, out3_r, src109_r, + filt3, out0_r, out1_r, out2_r, out3_r); + DUP4_ARG2(__lsx_vdp2_h_bu_b, src10_l, filt0, src21_l, filt0, src32_l, + filt0, src43_l, filt0, out0_l, out1_l, out2_l, out3_l); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, out0_l, src32_l, filt1, out1_l, + src43_l, filt1, out2_l, src54_l, filt1, out3_l, src65_l, + filt1, out0_l, out1_l, out2_l, out3_l); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, out0_l, src54_l, filt2, out1_l, + src65_l, filt2, out2_l, src76_l, filt2, out3_l, src87_l, + filt2, out0_l, out1_l, out2_l, out3_l); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, out0_l, src76_l, filt3, out1_l, + src87_l, filt3, out2_l, src98_l, filt3, out3_l, src109_l, + filt3, out0_l, out1_l, out2_l, out3_l); + DUP4_ARG3(__lsx_vssrarni_bu_h, out0_l, out0_r, 6, out1_l, out1_r, + 6, out2_l, out2_r, 6, out3_l, out3_r, 6, + tmp0, tmp1, tmp2, tmp3); + __lsx_vst(tmp0, dst_tmp, 0); + __lsx_vstx(tmp1, dst_tmp, dst_stride); + __lsx_vstx(tmp2, dst_tmp, dst_stride_2x); + __lsx_vstx(tmp3, dst_tmp, dst_stride_3x); + dst_tmp += dst_stride_4x; + + 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; + } + + src += 16; + dst += 16; + } +} + +static void common_vt_8t_24w_lsx(uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter, int32_t height) +{ + common_vt_8t_16w_lsx(src, src_stride, dst, dst_stride, filter, height, 16); + common_vt_8t_8w_lsx(src + 16, src_stride, dst + 16, dst_stride, filter, + height); +} + +static void common_vt_8t_32w_lsx(uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter, int32_t height) +{ + common_vt_8t_16w_lsx(src, src_stride, dst, dst_stride, filter, height, 32); +} + +static void common_vt_8t_48w_lsx(uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter, int32_t height) +{ + common_vt_8t_16w_lsx(src, src_stride, dst, dst_stride, filter, height, 48); +} + +static void common_vt_8t_64w_lsx(uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter, int32_t height) +{ + common_vt_8t_16w_lsx(src, src_stride, dst, dst_stride, filter, height, 64); +} + +static av_always_inline +void hevc_hv_8t_8x2_lsx(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) +{ + uint32_t loop_cnt, cnt; + uint8_t *src_tmp; + uint8_t *dst_tmp; + const int32_t src_stride_2x = (src_stride << 1); + const int32_t dst_stride_2x = (dst_stride << 1); + const int32_t src_stride_4x = (src_stride << 2); + const int32_t src_stride_3x = src_stride_2x + src_stride; + + __m128i out; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8; + __m128i filt0, filt1, filt2, filt3; + __m128i filt_h0, filt_h1, filt_h2, filt_h3; + __m128i mask1, mask2, mask3; + __m128i filter_vec; + __m128i vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + __m128i vec8, vec9, vec10, vec11, vec12, vec13, vec14, vec15; + __m128i dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7, dst8; + __m128i dst0_r, dst0_l, dst1_r, dst1_l; + __m128i dst10_r, dst32_r, dst54_r, dst76_r; + __m128i dst10_l, dst32_l, dst54_l, dst76_l; + __m128i dst21_r, dst43_r, dst65_r, dst87_r; + __m128i dst21_l, dst43_l, dst65_l, dst87_l; + __m128i mask0 = __lsx_vld(ff_hevc_mask_arr, 0); + + src -= (src_stride_3x + 3); + DUP4_ARG2(__lsx_vldrepl_h, filter_x, 0, filter_x, 2, filter_x, 4, + filter_x, 6, filt0, filt1, filt2, filt3); + + filter_vec = __lsx_vld(filter_y, 0); + filter_vec = __lsx_vsllwil_h_b(filter_vec, 0); + DUP4_ARG2(__lsx_vreplvei_w, filter_vec, 0, filter_vec, 1, filter_vec, 2, + filter_vec, 3, filt_h0, filt_h1, filt_h2, filt_h3); + + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + + for (cnt = width >> 3; cnt--;) { + src_tmp = src; + dst_tmp = dst; + + src0 = __lsx_vld(src_tmp, 0); + DUP2_ARG2(__lsx_vldx, src_tmp, src_stride, src_tmp, src_stride_2x, + src1, src2); + src3 = __lsx_vldx(src_tmp, src_stride_3x); + src_tmp += src_stride_4x; + src4 = __lsx_vld(src_tmp, 0); + DUP2_ARG2(__lsx_vldx, src_tmp, src_stride, src_tmp, src_stride_2x, + src5, src6); + src_tmp += src_stride_3x; + + /* row 0 row 1 row 2 row 3 */ + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask0, src0, src0, mask1, src0, + src0, mask2, src0, src0, mask3, vec0, vec1, vec2, vec3); + DUP4_ARG3(__lsx_vshuf_b, src1, src1, mask0, src1, src1, mask1, src1, + src1, mask2, src1, src1, mask3, vec4, vec5, vec6, vec7); + DUP4_ARG3(__lsx_vshuf_b, src2, src2, mask0, src2, src2, mask1, src2, + src2, mask2, src2, src2, mask3, vec8, vec9, vec10, vec11); + DUP4_ARG3(__lsx_vshuf_b, src3, src3, mask0, src3, src3, mask1, src3, + src3, mask2, src3, src3, mask3, vec12, vec13, vec14, vec15); + DUP4_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec4, filt0, vec8, filt0, + vec12, filt0, dst0, dst1, dst2, dst3); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec1, filt1, dst1, vec5, filt1, + dst2, vec9, filt1, dst3, vec13, filt1, dst0, dst1, dst2, dst3); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec2, filt2, dst1, vec6, filt2, + dst2, vec10, filt2, dst3, vec14, filt2, dst0, dst1, dst2, dst3); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec3, filt3, dst1, vec7, filt3, + dst2, vec11, filt3, dst3, vec15, filt3, dst0, dst1, dst2, dst3); + + DUP4_ARG3(__lsx_vshuf_b, src4, src4, mask0, src4, src4, mask1, src4, + src4, mask2, src4, src4, mask3, vec0, vec1, vec2, vec3); + DUP4_ARG3(__lsx_vshuf_b, src5, src5, mask0, src5, src5, mask1, src5, + src5, mask2, src5, src5, mask3, vec4, vec5, vec6, vec7); + DUP4_ARG3(__lsx_vshuf_b, src6, src6, mask0, src6, src6, mask1, src6, + src6, mask2, src6, src6, mask3, vec8, vec9, vec10, vec11); + DUP2_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec4, filt0, dst4, dst5); + dst6 = __lsx_vdp2_h_bu_b(vec8, filt0); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst4, vec1, filt1, dst5, vec5, filt1, + dst6, vec9, filt1, dst4, vec2, filt2, dst4, dst5, dst6, dst4); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst5, vec6, filt2, dst6, vec10, filt2, + dst4, vec3, filt3, dst5, vec7, filt3, dst5, dst6, dst4, dst5); + dst6 = __lsx_vdp2add_h_bu_b(dst6, vec11, filt3); + DUP4_ARG2(__lsx_vilvl_h, dst1, dst0, dst3, dst2, dst5, dst4, dst2, + dst1, dst10_r, dst32_r, dst54_r, dst21_r); + DUP4_ARG2(__lsx_vilvh_h, dst1, dst0, dst3, dst2, dst5, dst4, dst2, + dst1, dst10_l, dst32_l, dst54_l, dst21_l); + DUP2_ARG2(__lsx_vilvl_h, dst4, dst3, dst6, dst5, dst43_r, dst65_r); + DUP2_ARG2(__lsx_vilvh_h, dst4, dst3, dst6, dst5, dst43_l, dst65_l); + + for (loop_cnt = height >> 1; loop_cnt--;) { + src7 = __lsx_vld(src_tmp, 0); + src8 = __lsx_vldx(src_tmp, src_stride); + src_tmp += src_stride_2x; + + DUP4_ARG3(__lsx_vshuf_b, src7, src7, mask0, src7, src7, mask1, src7, + src7, mask2, src7, src7, mask3, vec0, vec1, vec2, vec3); + dst7 = __lsx_vdp2_h_bu_b(vec0, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst7, vec1, filt1, dst7, vec2, + filt2, dst7, dst7); + dst7 = __lsx_vdp2add_h_bu_b(dst7, vec3, filt3); + dst76_r = __lsx_vilvl_h(dst7, dst6); + dst76_l = __lsx_vilvh_h(dst7, dst6); + DUP2_ARG2(__lsx_vdp2_w_h, dst10_r, filt_h0, dst10_l, filt_h0, + dst0_r, dst0_l); + DUP4_ARG3(__lsx_vdp2add_w_h, dst0_r, dst32_r, filt_h1, dst0_l, + dst32_l, filt_h1, dst0_r, dst54_r, filt_h2, dst0_l, + dst54_l, filt_h2, dst0_r, dst0_l, dst0_r, dst0_l); + DUP2_ARG3(__lsx_vdp2add_w_h, dst0_r, dst76_r, filt_h3, dst0_l, + dst76_l, filt_h3, dst0_r, dst0_l); + DUP2_ARG2(__lsx_vsrai_w, dst0_r, 6, dst0_l, 6, dst0_r, dst0_l); + + DUP4_ARG3(__lsx_vshuf_b, src8, src8, mask0, src8, src8, mask1, src8, + src8, mask2, src8, src8, mask3, vec0, vec1, vec2, vec3); + dst8 = __lsx_vdp2_h_bu_b(vec0, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst8, vec1, filt1, dst8, vec2, + filt2, dst8, dst8); + dst8 = __lsx_vdp2add_h_bu_b(dst8, vec3, filt3); + + dst87_r = __lsx_vilvl_h(dst8, dst7); + dst87_l = __lsx_vilvh_h(dst8, dst7); + DUP2_ARG2(__lsx_vdp2_w_h, dst21_r, filt_h0, dst21_l, filt_h0, + dst1_r, dst1_l); + DUP4_ARG3(__lsx_vdp2add_w_h, dst1_r, dst43_r, filt_h1, dst1_l, + dst43_l, filt_h1, dst1_r, dst65_r, filt_h2, dst1_l, + dst65_l, filt_h2, dst1_r, dst1_l, dst1_r, dst1_l); + DUP2_ARG3(__lsx_vdp2add_w_h, dst1_r, dst87_r, filt_h3, dst1_l, + dst87_l, filt_h3, dst1_r, dst1_l); + DUP2_ARG2(__lsx_vsrai_w, dst1_r, 6, dst1_l, 6, dst1_r, dst1_l); + DUP4_ARG2(__lsx_vsrari_w, dst0_r, 6, dst0_l, 6,dst1_r, 6, dst1_l, + 6, dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG1(__lsx_vclip255_w, dst0_l, dst0_r, dst1_l, dst1_r, + dst0_l, dst0_r, dst1_l, dst1_r); + DUP2_ARG2(__lsx_vpickev_h, dst0_l, dst0_r, dst1_l, dst1_r, + dst0, dst1); + out = __lsx_vpickev_b(dst1, dst0); + __lsx_vstelm_d(out, dst_tmp, 0, 0); + __lsx_vstelm_d(out, dst_tmp + dst_stride, 0, 1); + dst_tmp += dst_stride_2x; + + 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; + } + src += 8; + dst += 8; + } +} + +static void hevc_hv_8t_8w_lsx(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) +{ + hevc_hv_8t_8x2_lsx(src, src_stride, dst, dst_stride, + filter_x, filter_y, height, 8); +} + +static void hevc_hv_8t_16w_lsx(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) +{ + hevc_hv_8t_8x2_lsx(src, src_stride, dst, dst_stride, + filter_x, filter_y, height, 16); +} + +static void hevc_hv_8t_24w_lsx(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) +{ + hevc_hv_8t_8x2_lsx(src, src_stride, dst, dst_stride, + filter_x, filter_y, height, 24); +} + +static void hevc_hv_8t_32w_lsx(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) +{ + hevc_hv_8t_8x2_lsx(src, src_stride, dst, dst_stride, + filter_x, filter_y, height, 32); +} + +static void hevc_hv_8t_48w_lsx(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) +{ + hevc_hv_8t_8x2_lsx(src, src_stride, dst, dst_stride, + filter_x, filter_y, height, 48); +} + +static void hevc_hv_8t_64w_lsx(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) +{ + hevc_hv_8t_8x2_lsx(src, src_stride, dst, dst_stride, + filter_x, filter_y, height, 64); +} + +static av_always_inline +void common_vt_4t_24w_lsx(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; + int32_t src_stride_2x = (src_stride << 1); + int32_t src_stride_3x = src_stride_2x + src_stride; + uint8_t *_src; + + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + __m128i src11, filt0, filt1; + __m128i src10_r, src32_r, src76_r, src98_r, src21_r, src43_r, src87_r; + __m128i src109_r, src10_l, src32_l, src21_l, src43_l; + __m128i out0_r, out1_r, out2_r, out3_r, out0_l, out1_l; + __m128i out1, out2, out3, out4; + + src -= src_stride; + DUP2_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filt0, filt1); + _src = src + 16; + + /* 16 width */ + src0 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src1, src2); + DUP2_ARG2(__lsx_vilvl_b, src1, src0, src2, src1, src10_r, src21_r); + DUP2_ARG2(__lsx_vilvh_b, src1, src0, src2, src1, src10_l, src21_l); + + /* 8 width */ + src6 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride_2x, src7, src8); + src += src_stride_3x; + _src += src_stride_3x; + DUP2_ARG2(__lsx_vilvl_b, src7, src6, src8, src7, src76_r, src87_r); + + for (loop_cnt = 8; loop_cnt--;) { + /* 16 width */ + DUP2_ARG2(__lsx_vld, src, 0, _src, 0, src3, src9); + DUP2_ARG2(__lsx_vldx, src, src_stride, _src, src_stride, src4, src10); + DUP2_ARG2(__lsx_vilvl_b, src3, src2, src4, src3, src32_r, src43_r); + DUP2_ARG2(__lsx_vilvh_b, src3, src2, src4, src3, src32_l, src43_l); + + /* 8 width */ + src += src_stride_2x; + _src += src_stride_2x; + DUP2_ARG2(__lsx_vilvl_b, src9, src8, src10, src9, src98_r, src109_r); + + /* 16 width */ + DUP4_ARG2(__lsx_vdp2_h_bu_b, src10_r, filt0, src10_l, filt0, src21_r, + filt0, src21_l, filt0, out0_r, out0_l, out1_r, out1_l); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, out0_r, src32_r, filt1, out0_l, src32_l, + filt1, out1_r, src43_r, filt1, out1_l, src43_l, filt1, + out0_r, out0_l, out1_r, out1_l); + + /* 8 width */ + DUP2_ARG2(__lsx_vdp2_h_bu_b, src76_r, filt0, src87_r, filt0, + out2_r, out3_r); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, out2_r, src98_r, filt1, out3_r, + src109_r, filt1, out2_r, out3_r); + + /* 16 + 8 width */ + DUP4_ARG3(__lsx_vssrarni_bu_h, out0_l, out0_r, 6, out2_r, out2_r, 6, + out3_r, out3_r, 6, out1_l, out1_r, 6, out1, out2, out3, out4); + __lsx_vst(out1, dst, 0); + __lsx_vstelm_d(out2, dst, 16, 0); + dst += dst_stride; + __lsx_vst(out4, dst, 0); + __lsx_vstelm_d(out3, dst, 16, 0); + dst += dst_stride; + + /* 16 width */ + DUP2_ARG2(__lsx_vld, src, 0, _src, 0, src5, src11); + DUP2_ARG2(__lsx_vldx, src, src_stride, _src, src_stride, src2, src8); + DUP2_ARG2(__lsx_vilvl_b, src5, src4, src2, src5, src10_r, src21_r); + DUP2_ARG2(__lsx_vilvh_b, src5, src4, src2, src5, src10_l, src21_l); + + /* 8 width */ + src += src_stride_2x; + _src += src_stride_2x; + DUP2_ARG2(__lsx_vilvl_b, src11, src10, src8, src11, src76_r, src87_r); + + /* 16 width */ + DUP4_ARG2(__lsx_vdp2_h_bu_b, src32_r, filt0, src32_l, filt0, src43_r, + filt0, src43_l, filt0, out0_r, out0_l, out1_r, out1_l); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, out0_r, src10_r, filt1, out0_l, src10_l, + filt1, out1_r, src21_r, filt1, out1_l, src21_l, filt1, + out0_r, out0_l, out1_r, out1_l); + + /* 8 width */ + DUP2_ARG2(__lsx_vdp2_h_bu_b, src98_r, filt0, src109_r, filt0, + out2_r, out3_r); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, out2_r, src76_r, filt1, out3_r, + src87_r, filt1, out2_r, out3_r); + + /* 16 + 8 width */ + DUP4_ARG3(__lsx_vssrarni_bu_h, out0_l, out0_r, 6, out2_r, out2_r, 6, + out1_l, out1_r, 6, out3_r, out3_r, 6, out1, out2, out3, out4); + + __lsx_vst(out1, dst, 0); + __lsx_vstelm_d(out2, dst, 16, 0); + dst += dst_stride; + __lsx_vst(out3, dst, 0); + __lsx_vstelm_d(out4, dst, 16, 0); + dst += dst_stride; + } +} + +static av_always_inline +void common_vt_4t_32w_lsx(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; + int32_t src_stride_2x = (src_stride << 1); + int32_t dst_stride_2x = (dst_stride << 1); + int32_t src_stride_3x = src_stride_2x + src_stride; + uint8_t *_src; + + __m128i src0, src1, src2, src3, src4, src6, src7, src8, src9, src10; + __m128i src10_r, src32_r, src76_r, src98_r; + __m128i src21_r, src43_r, src87_r, src109_r; + __m128i out0_r, out1_r, out2_r, out3_r, out0_l, out1_l, out2_l, out3_l; + __m128i src10_l, src32_l, src76_l, src98_l; + __m128i src21_l, src43_l, src87_l, src109_l; + __m128i filt0, filt1; + __m128i out1, out2; + + src -= src_stride; + DUP2_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filt0, filt1); + _src = src + 16; + + /* 16 width */ + src0 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src1, src2); + + DUP2_ARG2(__lsx_vilvl_b, src1, src0, src2, src1, src10_r, src21_r); + DUP2_ARG2(__lsx_vilvh_b, src1, src0, src2, src1, src10_l, src21_l); + + /* next 16 width */ + src6 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride_2x, src7, src8); + src += src_stride_3x; + _src += src_stride_3x; + + DUP2_ARG2(__lsx_vilvl_b, src7, src6, src8, src7, src76_r, src87_r); + DUP2_ARG2(__lsx_vilvh_b, src7, src6, src8, src7, src76_l, src87_l); + + for (loop_cnt = (height >> 1); loop_cnt--;) { + /* 16 width */ + DUP2_ARG2(__lsx_vld, src, 0, _src, 0, src3, src9); + DUP2_ARG2(__lsx_vldx, src, src_stride, _src, src_stride, src4, src10); + DUP2_ARG2(__lsx_vilvl_b, src3, src2, src4, src3, src32_r, src43_r); + DUP2_ARG2(__lsx_vilvh_b, src3, src2, src4, src3, src32_l, src43_l); + + /* 16 width */ + DUP4_ARG2(__lsx_vdp2_h_bu_b, src10_r, filt0, src10_l, filt0, src21_r, + filt0, src21_l, filt0, out0_r, out0_l, out1_r, out1_l); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, out0_r, src32_r, filt1, out0_l, src32_l, + filt1, out1_r, src43_r, filt1, out1_l, src43_l, filt1, + out0_r, out0_l, out1_r, out1_l); + + DUP2_ARG3(__lsx_vssrarni_bu_h, out0_l, out0_r, 6, out1_l, out1_r, 6, + out1, out2); + __lsx_vst(out1, dst, 0); + __lsx_vstx(out2, dst, dst_stride); + + src10_r = src32_r; + src21_r = src43_r; + src10_l = src32_l; + src21_l = src43_l; + src2 = src4; + + /* next 16 width */ + src += src_stride_2x; + _src += src_stride_2x; + DUP2_ARG2(__lsx_vilvl_b, src9, src8, src10, src9, src98_r, src109_r); + DUP2_ARG2(__lsx_vilvh_b, src9, src8, src10, src9, src98_l, src109_l); + + /* next 16 width */ + DUP4_ARG2(__lsx_vdp2_h_bu_b, src76_r, filt0, src76_l, filt0, src87_r, + filt0, src87_l, filt0, out2_r, out2_l, out3_r, out3_l); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, out2_r, src98_r, filt1, out2_l, src98_l, + filt1, out3_r, src109_r, filt1, out3_l, src109_l, filt1, + out2_r, out2_l, out3_r, out3_l); + + /* next 16 width */ + DUP2_ARG3(__lsx_vssrarni_bu_h, out2_l, out2_r, 6, out3_l, out3_r, 6, + out1, out2); + __lsx_vst(out1, dst, 16); + __lsx_vst(out2, dst + dst_stride, 16); + + dst += dst_stride_2x; + + src76_r = src98_r; + src87_r = src109_r; + src76_l = src98_l; + src87_l = src109_l; + src8 = src10; + } +} + +static av_always_inline +void hevc_hv_4t_8x2_lsx(uint8_t *src, int32_t src_stride, uint8_t *dst, + int32_t dst_stride, const int8_t *filter_x, + const int8_t *filter_y) +{ + const int32_t src_stride_2x = (src_stride << 1); + const int32_t src_stride_4x = (src_stride << 2); + const int32_t src_stride_3x = src_stride_2x + src_stride; + __m128i out; + __m128i src0, src1, src2, src3, src4; + __m128i filt0, filt1; + __m128i filt_h0, filt_h1, filter_vec; + __m128i mask0 = __lsx_vld(ff_hevc_mask_arr, 0); + __m128i mask1; + __m128i vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7, vec8, vec9; + __m128i dst0, dst1, dst2, dst3, dst4; + __m128i dst0_r, dst0_l, dst1_r, dst1_l; + __m128i dst10_r, dst32_r, dst21_r, dst43_r; + __m128i dst10_l, dst32_l, dst21_l, dst43_l; + __m128i out0_r, out1_r; + + src -= (src_stride + 1); + DUP2_ARG2(__lsx_vldrepl_h, filter_x, 0, filter_x, 2, filt0, filt1); + + filter_vec = __lsx_vld(filter_y, 0); + filter_vec = __lsx_vsllwil_h_b(filter_vec, 0); + DUP2_ARG2(__lsx_vreplvei_w, filter_vec, 0, filter_vec, 1, filt_h0, filt_h1); + + mask1 = __lsx_vaddi_bu(mask0, 2); + src0 = __lsx_vld(src, 0); + DUP4_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src, + src_stride_3x, src, src_stride_4x, src1, src2, src3, src4); + + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask0, src0, src0, mask1, src1, src1, + mask0, src1, src1, mask1, vec0, vec1, vec2, vec3); + DUP4_ARG3(__lsx_vshuf_b, src2, src2, mask0, src2, src2, mask1, src3, src3, + mask0, src3, src3, mask1, vec4, vec5, vec6, vec7); + DUP2_ARG3(__lsx_vshuf_b, src4, src4, mask0, src4, src4, mask1, vec8, vec9); + + DUP4_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec2, filt0, vec4, filt0, vec6, + filt0, dst0, dst1, dst2, dst3); + dst4 = __lsx_vdp2_h_bu_b(vec8, filt0); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec1, filt1, dst1, vec3, filt1, dst2, + vec5, filt1, dst3, vec7, filt1, dst0, dst1, dst2, dst3); + dst4 = __lsx_vdp2add_h_bu_b(dst4, vec9, filt1); + DUP4_ARG2(__lsx_vilvl_h, dst1, dst0, dst2, dst1, dst3, dst2, dst4, dst3, + dst10_r, dst21_r, dst32_r, dst43_r); + DUP4_ARG2(__lsx_vilvh_h, dst1, dst0, dst2, dst1, dst3, dst2, dst4, dst3, + dst10_l, dst21_l, dst32_l, dst43_l); + DUP4_ARG2(__lsx_vdp2_w_h, dst10_r, filt_h0, dst10_l, filt_h0, dst21_r, + filt_h0, dst21_l, filt_h0, dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG3(__lsx_vdp2add_w_h, dst0_r, dst32_r, filt_h1, dst0_l, dst32_l, + filt_h1, dst1_r, dst43_r, filt_h1, dst1_l, dst43_l, filt_h1, + dst0_r, dst0_l, dst1_r, dst1_l); + DUP2_ARG3(__lsx_vsrani_h_w, dst0_l, dst0_r, 6, dst1_l, dst1_r, 6, + out0_r, out1_r); + out = __lsx_vssrarni_bu_h(out1_r, out0_r, 6); + __lsx_vstelm_d(out, dst, 0, 0); + __lsx_vstelm_d(out, dst + dst_stride, 0, 1); +} + +static av_always_inline +void hevc_hv_4t_8multx4_lsx(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; + const int32_t src_stride_2x = (src_stride << 1); + const int32_t dst_stride_2x = (dst_stride << 1); + const int32_t src_stride_4x = (src_stride << 2); + const int32_t src_stride_3x = src_stride_2x + src_stride; + const int32_t dst_stride_3x = dst_stride_2x + dst_stride; + + __m128i out0, out1; + __m128i src0, src1, src2, src3, src4, src5, src6, mask0, mask1; + __m128i vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + __m128i filt0, filt1, filt_h0, filt_h1, filter_vec; + __m128i dst0, dst1, dst2, dst3, dst4, dst5, dst6, tmp0, tmp1, tmp2, tmp3; + __m128i dst0_r, dst0_l, dst1_r, dst1_l, dst2_r, dst2_l, dst3_r, dst3_l; + __m128i dst10_r, dst32_r, dst54_r, dst21_r, dst43_r, dst65_r; + __m128i dst10_l, dst32_l, dst54_l, dst21_l, dst43_l, dst65_l; + + src -= (src_stride + 1); + DUP2_ARG2(__lsx_vldrepl_h, filter_x, 0, filter_x, 2, filt0, filt1); + + filter_vec = __lsx_vld(filter_y, 0); + filter_vec = __lsx_vsllwil_h_b(filter_vec, 0); + DUP2_ARG2(__lsx_vreplvei_w, filter_vec, 0, filter_vec, 1, filt_h0, filt_h1); + + mask0 = __lsx_vld(ff_hevc_mask_arr, 0); + mask1 = __lsx_vaddi_bu(mask0, 2); + + for (cnt = width8mult; cnt--;) { + src0 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src1, src2); + src3 = __lsx_vldx(src, src_stride_3x); + src += src_stride_4x; + src4 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src5, src6); + src += (8 - src_stride_4x); + DUP2_ARG3(__lsx_vshuf_b, src0, src0, mask0, src0, src0, mask1, + vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src1, src1, mask0, src1, src1, mask1, + vec2, vec3); + DUP2_ARG3(__lsx_vshuf_b, src2, src2, mask0, src2, src2, mask1, + vec4, vec5); + + DUP2_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec2, filt0, dst0, dst1); + dst2 = __lsx_vdp2_h_bu_b(vec4, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec1, filt1, dst1, vec3, filt1, + dst0, dst1); + dst2 = __lsx_vdp2add_h_bu_b(dst2, vec5, filt1); + + DUP2_ARG2(__lsx_vilvl_h, dst1, dst0, dst2, dst1, dst10_r, dst21_r); + DUP2_ARG2(__lsx_vilvh_h, dst1, dst0, dst2, dst1, dst10_l, dst21_l); + + DUP2_ARG3(__lsx_vshuf_b, src3, src3, mask0, src3, src3, mask1, + vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src4, src4, mask0, src4, src4, mask1, + vec2, vec3); + DUP2_ARG3(__lsx_vshuf_b, src5, src5, mask0, src5, src5, mask1, + vec4, vec5); + DUP2_ARG3(__lsx_vshuf_b, src6, src6, mask0, src6, src6, mask1, + vec6, vec7); + + DUP4_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec2, filt0, vec4, filt0, + vec6, filt0, dst3, dst4, dst5, dst6); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst3, vec1, filt1, dst4, vec3, filt1, + dst5, vec5, filt1, dst6, vec7, filt1, dst3, dst4, dst5, dst6); + + DUP4_ARG2(__lsx_vilvl_h, dst3, dst2, dst4, dst3, dst5, dst4, dst6, + dst5, dst32_r, dst43_r, dst54_r, dst65_r); + DUP4_ARG2(__lsx_vilvh_h, dst3, dst2, dst4, dst3, dst5, dst4, dst6, + dst5, dst32_l, dst43_l, dst54_l, dst65_l); + + DUP4_ARG2(__lsx_vdp2_w_h, dst10_r, filt_h0, dst10_l, filt_h0, dst21_r, + filt_h0, dst21_l, filt_h0, dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG2(__lsx_vdp2_w_h, dst32_r, filt_h0, dst32_l, filt_h0, dst43_r, + filt_h0, dst43_l, filt_h0, dst2_r, dst2_l, dst3_r, dst3_l); + DUP4_ARG3(__lsx_vdp2add_w_h, dst0_r, dst32_r, filt_h1, dst0_l, dst32_l, + filt_h1, dst1_r, dst43_r, filt_h1, dst1_l, dst43_l, filt_h1, + dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG3(__lsx_vdp2add_w_h, dst2_r, dst54_r, filt_h1, dst2_l, dst54_l, + filt_h1, dst3_r, dst65_r, filt_h1, dst3_l, dst65_l, filt_h1, + dst2_r, dst2_l, dst3_r, dst3_l); + + DUP4_ARG3(__lsx_vsrani_h_w, dst0_l, dst0_r, 6, dst1_l, dst1_r, 6, + dst2_l, dst2_r, 6, dst3_l, dst3_r, 6, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG3(__lsx_vssrarni_bu_h, tmp1, tmp0, 6, tmp3, tmp2, 6, out0, out1); + __lsx_vstelm_d(out0, dst, 0, 0); + __lsx_vstelm_d(out0, dst + dst_stride, 0, 1); + __lsx_vstelm_d(out1, dst + dst_stride_2x, 0, 0); + __lsx_vstelm_d(out1, dst + dst_stride_3x, 0, 1); + dst += 8; + } +} + +static av_always_inline +void hevc_hv_4t_8x6_lsx(uint8_t *src, int32_t src_stride, uint8_t *dst, + int32_t dst_stride, const int8_t *filter_x, + const int8_t *filter_y) +{ + const int32_t src_stride_2x = (src_stride << 1); + const int32_t dst_stride_2x = (dst_stride << 1); + const int32_t src_stride_4x = (src_stride << 2); + const int32_t dst_stride_4x = (dst_stride << 2); + const int32_t src_stride_3x = src_stride_2x + src_stride; + const int32_t dst_stride_3x = dst_stride_2x + dst_stride; + __m128i out0, out1, out2; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8; + __m128i filt0, filt1; + __m128i filt_h0, filt_h1, filter_vec; + __m128i mask0 = __lsx_vld(ff_hevc_mask_arr, 0); + __m128i mask1; + __m128i vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7, vec8, vec9; + __m128i vec10, vec11, vec12, vec13, vec14, vec15, vec16, vec17; + __m128i dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7, dst8; + __m128i dst0_r, dst0_l, dst1_r, dst1_l, dst2_r, dst2_l, dst3_r, dst3_l; + __m128i dst4_r, dst4_l, dst5_r, dst5_l; + __m128i dst10_r, dst32_r, dst10_l, dst32_l; + __m128i dst21_r, dst43_r, dst21_l, dst43_l; + __m128i dst54_r, dst54_l, dst65_r, dst65_l; + __m128i dst76_r, dst76_l, dst87_r, dst87_l; + __m128i out0_r, out1_r, out2_r, out3_r, out4_r, out5_r; + + src -= (src_stride + 1); + DUP2_ARG2(__lsx_vldrepl_h, filter_x, 0, filter_x, 2, filt0, filt1); + + filter_vec = __lsx_vld(filter_y, 0); + filter_vec = __lsx_vsllwil_h_b(filter_vec, 0); + DUP2_ARG2(__lsx_vreplvei_w, filter_vec, 0, filter_vec, 1, filt_h0, filt_h1); + + mask1 = __lsx_vaddi_bu(mask0, 2); + + src0 = __lsx_vld(src, 0); + DUP4_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x,src, + src_stride_3x, src, src_stride_4x, src1, src2, src3, src4); + src += src_stride_4x; + DUP4_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x,src, + src_stride_3x, src, src_stride_4x, src5, src6, src7, src8); + + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask0, src0, src0, mask1, src1, src1, + mask0, src1, src1, mask1, vec0, vec1, vec2, vec3); + DUP4_ARG3(__lsx_vshuf_b, src2, src2, mask0, src2, src2, mask1, src3, src3, + mask0, src3, src3, mask1, vec4, vec5, vec6, vec7); + DUP4_ARG3(__lsx_vshuf_b, src4, src4, mask0, src4, src4, mask1, src5, src5, + mask0, src5, src5, mask1, vec8, vec9, vec10, vec11); + DUP4_ARG3(__lsx_vshuf_b, src6, src6, mask0, src6, src6, mask1, src7, src7, + mask0, src7, src7, mask1, vec12, vec13, vec14, vec15); + DUP2_ARG3(__lsx_vshuf_b, src8, src8, mask0, src8, src8, mask1, vec16, vec17); + + DUP4_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec2, filt0, vec4, filt0, vec6, + filt0, dst0, dst1, dst2, dst3); + DUP4_ARG2(__lsx_vdp2_h_bu_b, vec8, filt0, vec10, filt0, vec12, filt0, vec14, + filt0, dst4, dst5, dst6, dst7); + dst8 = __lsx_vdp2_h_bu_b(vec16, filt0); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec1, filt1, dst1, vec3, filt1, dst2, + vec5, filt1, dst3, vec7, filt1, dst0, dst1, dst2, dst3); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst4, vec9, filt1, dst5, vec11, filt1, dst6, + vec13, filt1, dst7, vec15, filt1, dst4, dst5, dst6, dst7); + dst8 = __lsx_vdp2add_h_bu_b(dst8, vec17, filt1); + + DUP4_ARG2(__lsx_vilvl_h, dst1, dst0, dst2, dst1, dst3, dst2, dst4, dst3, + dst10_r, dst21_r, dst32_r, dst43_r); + DUP4_ARG2(__lsx_vilvh_h, dst1, dst0, dst2, dst1, dst3, dst2, dst4, dst3, + dst10_l, dst21_l, dst32_l, dst43_l); + DUP4_ARG2(__lsx_vilvl_h, dst5, dst4, dst6, dst5, dst7, dst6, dst8, dst7, + dst54_r, dst65_r, dst76_r, dst87_r); + DUP4_ARG2(__lsx_vilvh_h, dst5, dst4, dst6, dst5, dst7, dst6, dst8, dst7, + dst54_l, dst65_l, dst76_l, dst87_l); + + DUP4_ARG2(__lsx_vdp2_w_h, dst10_r, filt_h0, dst10_l, filt_h0, dst21_r, + filt_h0, dst21_l, filt_h0, dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG2(__lsx_vdp2_w_h, dst32_r, filt_h0, dst32_l, filt_h0, dst43_r, + filt_h0, dst43_l, filt_h0, dst2_r, dst2_l, dst3_r, dst3_l); + DUP4_ARG2(__lsx_vdp2_w_h, dst54_r, filt_h0, dst54_l, filt_h0, dst65_r, + filt_h0, dst65_l, filt_h0, dst4_r, dst4_l, dst5_r, dst5_l); + DUP4_ARG3(__lsx_vdp2add_w_h, dst0_r, dst32_r, filt_h1, dst0_l, dst32_l, + filt_h1, dst1_r, dst43_r, filt_h1, dst1_l, dst43_l, filt_h1, + dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG3(__lsx_vdp2add_w_h, dst2_r, dst54_r, filt_h1, dst2_l, dst54_l, + filt_h1, dst3_r, dst65_r, filt_h1, dst3_l, dst65_l, filt_h1, + dst2_r, dst2_l, dst3_r, dst3_l); + DUP4_ARG3(__lsx_vdp2add_w_h, dst4_r, dst76_r, filt_h1, dst4_l, dst76_l, + filt_h1, dst5_r, dst87_r, filt_h1, dst5_l, dst87_l, filt_h1, + dst4_r, dst4_l, dst5_r, dst5_l); + + DUP4_ARG3(__lsx_vsrani_h_w, dst0_l, dst0_r, 6, dst1_l, dst1_r, 6, dst2_l, + dst2_r, 6, dst3_l, dst3_r, 6, out0_r, out1_r, out2_r, out3_r); + DUP2_ARG3(__lsx_vsrani_h_w, dst4_l, dst4_r, 6, dst5_l, dst5_r, 6, + out4_r, out5_r); + DUP2_ARG3(__lsx_vssrarni_bu_h, out1_r, out0_r, 6, out3_r, out2_r, 6, + out0, out1); + out2 = __lsx_vssrarni_bu_h(out5_r, out4_r, 6); + + __lsx_vstelm_d(out0, dst, 0, 0); + __lsx_vstelm_d(out0, dst + dst_stride, 0, 1); + __lsx_vstelm_d(out1, dst + dst_stride_2x, 0, 0); + __lsx_vstelm_d(out1, dst + dst_stride_3x, 0, 1); + dst += dst_stride_4x; + __lsx_vstelm_d(out2, dst, 0, 0); + __lsx_vstelm_d(out2, dst + dst_stride, 0, 1); +} + +static av_always_inline +void hevc_hv_4t_8multx4mult_lsx(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; + const int32_t src_stride_2x = (src_stride << 1); + const int32_t dst_stride_2x = (dst_stride << 1); + const int32_t src_stride_4x = (src_stride << 2); + const int32_t dst_stride_4x = (dst_stride << 2); + const int32_t src_stride_3x = src_stride_2x + src_stride; + const int32_t dst_stride_3x = dst_stride_2x + dst_stride; + + __m128i out0, out1; + __m128i src0, src1, src2, src3, src4, src5, src6; + __m128i filt0, filt1; + __m128i filt_h0, filt_h1, filter_vec; + __m128i mask0 = __lsx_vld(ff_hevc_mask_arr, 0); + __m128i mask1; + __m128i vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + __m128i dst0, dst1, dst2, dst3, dst4, dst5; + __m128i dst0_r, dst0_l, dst1_r, dst1_l, dst2_r, dst2_l, dst3_r, dst3_l; + __m128i dst10_r, dst32_r, dst21_r, dst43_r; + __m128i dst10_l, dst32_l, dst21_l, dst43_l; + __m128i dst54_r, dst54_l, dst65_r, dst65_l, dst6; + __m128i out0_r, out1_r, out2_r, out3_r; + + src -= (src_stride + 1); + DUP2_ARG2(__lsx_vldrepl_h, filter_x, 0, filter_x, 2, filt0, filt1); + + filter_vec = __lsx_vld(filter_y, 0); + filter_vec = __lsx_vsllwil_h_b(filter_vec, 0); + DUP2_ARG2(__lsx_vreplvei_w, filter_vec, 0, filter_vec, 1, filt_h0, filt_h1); + mask1 = __lsx_vaddi_bu(mask0, 2); + + for (cnt = width8mult; cnt--;) { + src_tmp = src; + dst_tmp = dst; + + src0 = __lsx_vld(src_tmp, 0); + DUP2_ARG2(__lsx_vldx, src_tmp, src_stride, src_tmp, src_stride_2x, + src1, src2); + src_tmp += src_stride_3x; + + DUP2_ARG3(__lsx_vshuf_b, src0, src0, mask0, src0, src0, mask1, + vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src1, src1, mask0, src1, src1, mask1, + vec2, vec3); + DUP2_ARG3(__lsx_vshuf_b, src2, src2, mask0, src2, src2, mask1, + vec4, vec5); + + DUP2_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec2, filt0, dst0, dst1); + dst2 = __lsx_vdp2_h_bu_b(vec4, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec1, filt1, dst1, vec3, filt1, + dst0, dst1); + dst2 = __lsx_vdp2add_h_bu_b(dst2, vec5, filt1); + + DUP2_ARG2(__lsx_vilvl_h, dst1, dst0, dst2, dst1, dst10_r, dst21_r); + DUP2_ARG2(__lsx_vilvh_h, dst1, dst0, dst2, dst1, dst10_l, dst21_l); + + for (loop_cnt = (height >> 2); loop_cnt--;) { + src3 = __lsx_vld(src_tmp, 0); + DUP2_ARG2(__lsx_vldx, src_tmp, src_stride, src_tmp, src_stride_2x, + src4, src5); + src6 = __lsx_vldx(src_tmp, src_stride_3x); + src_tmp += src_stride_4x; + + DUP4_ARG3(__lsx_vshuf_b, src3, src3, mask0, src3, src3, mask1, src4, + src4, mask0, src4, src4, mask1, vec0, vec1, vec2, vec3); + DUP4_ARG3(__lsx_vshuf_b, src5, src5, mask0, src5, src5, mask1, src6, + src6, mask0, src6, src6, mask1, vec4, vec5, vec6, vec7); + + DUP4_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec2, filt0, vec4, filt0, + vec6, filt0, dst3, dst4, dst5, dst6); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst3, vec1, filt1, dst4, vec3, + filt1, dst5, vec5, filt1, dst6, vec7, filt1, + dst3, dst4, dst5, dst6); + + DUP4_ARG2(__lsx_vilvl_h, dst3, dst2, dst4, dst3, dst5, dst4, + dst6, dst5, dst32_r, dst43_r, dst54_r, dst65_r); + DUP4_ARG2(__lsx_vilvh_h, dst3, dst2, dst4, dst3, dst5, dst4, + dst6, dst5, dst32_l, dst43_l, dst54_l, dst65_l); + + DUP4_ARG2(__lsx_vdp2_w_h, dst10_r, filt_h0, dst10_l, filt_h0, dst21_r, + filt_h0, dst21_l, filt_h0, dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG2(__lsx_vdp2_w_h, dst32_r, filt_h0, dst32_l, filt_h0, dst43_r, + filt_h0, dst43_l, filt_h0, dst2_r, dst2_l, dst3_r, dst3_l); + DUP4_ARG3(__lsx_vdp2add_w_h, dst0_r, dst32_r, filt_h1, dst0_l, + dst32_l, filt_h1, dst1_r, dst43_r, filt_h1, dst1_l, + dst43_l, filt_h1, dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG3(__lsx_vdp2add_w_h, dst2_r, dst54_r, filt_h1, dst2_l, + dst54_l, filt_h1, dst3_r, dst65_r, filt_h1, dst3_l, + dst65_l, filt_h1, dst2_r, dst2_l, dst3_r, dst3_l); + + DUP4_ARG3(__lsx_vsrani_h_w, dst0_l, dst0_r, 6, dst1_l, dst1_r, 6, + dst2_l, dst2_r, 6, dst3_l, dst3_r, 6, out0_r, out1_r, + out2_r, out3_r); + DUP2_ARG3(__lsx_vssrarni_bu_h, out1_r, out0_r, 6, out3_r, out2_r, + 6, out0, out1); + __lsx_vstelm_d(out0, dst_tmp, 0, 0); + __lsx_vstelm_d(out0, dst_tmp + dst_stride, 0, 1); + __lsx_vstelm_d(out1, dst_tmp + dst_stride_2x, 0, 0); + __lsx_vstelm_d(out1, dst_tmp + dst_stride_3x, 0, 1); + dst_tmp += dst_stride_4x; + + dst10_r = dst54_r; + dst10_l = dst54_l; + dst21_r = dst65_r; + dst21_l = dst65_l; + dst2 = dst6; + } + src += 8; + dst += 8; + } +} + +static +void hevc_hv_4t_8w_lsx(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) +{ + if (2 == height) { + hevc_hv_4t_8x2_lsx(src, src_stride, dst, dst_stride, filter_x, filter_y); + } else if (4 == height) { + hevc_hv_4t_8multx4_lsx(src, src_stride, dst, dst_stride, + filter_x, filter_y, 1); + } else if (6 == height) { + hevc_hv_4t_8x6_lsx(src, src_stride, dst, dst_stride, filter_x, filter_y); + } else if (0 == (height & 0x03)) { + hevc_hv_4t_8multx4mult_lsx(src, src_stride, dst, dst_stride, + filter_x, filter_y, height, 1); + } +} + +static av_always_inline +void hevc_hv_4t_12w_lsx(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) +{ + uint32_t loop_cnt; + uint8_t *src_tmp, *dst_tmp; + const int32_t src_stride_2x = (src_stride << 1); + const int32_t dst_stride_2x = (dst_stride << 1); + const int32_t src_stride_4x = (src_stride << 2); + const int32_t dst_stride_4x = (dst_stride << 2); + const int32_t src_stride_3x = src_stride_2x + src_stride; + const int32_t dst_stride_3x = dst_stride_2x + dst_stride; + __m128i out0, out1; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + __m128i vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + __m128i mask0, mask1, mask2, mask3; + __m128i filt0, filt1, filt_h0, filt_h1, filter_vec, tmp0, tmp1, tmp2, tmp3; + __m128i dsth0, dsth1, dsth2, dsth3, dsth4, dsth5, dsth6; + __m128i dst10, dst21, dst22, dst73, dst84, dst95, dst106; + __m128i dst76_r, dst98_r, dst87_r, dst109_r; + __m128i dst10_r, dst32_r, dst54_r, dst21_r, dst43_r, dst65_r; + __m128i dst10_l, dst32_l, dst54_l, dst21_l, dst43_l, dst65_l; + __m128i dst0_r, dst0_l, dst1_r, dst1_l, dst2_r, dst2_l, dst3_r, dst3_l; + __m128i dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + + src -= (src_stride + 1); + DUP2_ARG2(__lsx_vldrepl_h, filter_x, 0, filter_x, 2, filt0, filt1); + + filter_vec = __lsx_vld(filter_y, 0); + filter_vec = __lsx_vsllwil_h_b(filter_vec, 0); + DUP2_ARG2(__lsx_vreplvei_w, filter_vec, 0, filter_vec, 1, filt_h0, filt_h1); + + mask0 = __lsx_vld(ff_hevc_mask_arr, 0); + mask1 = __lsx_vaddi_bu(mask0, 2); + + src_tmp = src; + dst_tmp = dst; + + src0 = __lsx_vld(src_tmp, 0); + DUP2_ARG2(__lsx_vldx, src_tmp, src_stride, src_tmp, src_stride_2x, + src1, src2); + src_tmp += src_stride_3x; + + DUP2_ARG3(__lsx_vshuf_b, src0, src0, mask0, src0, src0, mask1, vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src1, src1, mask0, src1, src1, mask1, vec2, vec3); + DUP2_ARG3(__lsx_vshuf_b, src2, src2, mask0, src2, src2, mask1, vec4, vec5); + + DUP2_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec2, filt0, dsth0, dsth1); + dsth2 = __lsx_vdp2_h_bu_b(vec4, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dsth0, vec1, filt1, dsth1, vec3, filt1, + dsth0, dsth1); + dsth2 = __lsx_vdp2add_h_bu_b(dsth2, vec5, filt1); + + DUP2_ARG2(__lsx_vilvl_h, dsth1, dsth0, dsth2, dsth1, dst10_r, dst21_r); + DUP2_ARG2(__lsx_vilvh_h, dsth1, dsth0, dsth2, dsth1, dst10_l, dst21_l); + + for (loop_cnt = 4; loop_cnt--;) { + src3 = __lsx_vld(src_tmp, 0); + DUP2_ARG2(__lsx_vldx, src_tmp, src_stride, src_tmp, src_stride_2x, + src4, src5); + src6 = __lsx_vldx(src_tmp, src_stride_3x); + src_tmp += src_stride_4x; + + DUP4_ARG3(__lsx_vshuf_b, src3, src3, mask0, src3, src3, mask1, src4, + src4, mask0, src4, src4, mask1, vec0, vec1, vec2, vec3); + DUP4_ARG3(__lsx_vshuf_b, src5, src5, mask0, src5, src5, mask1, src6, + src6, mask0, src6, src6, mask1, vec4, vec5, vec6, vec7); + + DUP4_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec2, filt0, vec4, filt0, + vec6, filt0, dsth3, dsth4, dsth5, dsth6); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dsth3, vec1, filt1, dsth4, + vec3, filt1, dsth5, vec5, filt1, dsth6, vec7, filt1, + dsth3, dsth4, dsth5, dsth6); + + DUP4_ARG2(__lsx_vilvl_h, dsth3, dsth2, dsth4, dsth3, dsth5, dsth4, + dsth6, dsth5, dst32_r, dst43_r, dst54_r, dst65_r); + DUP4_ARG2(__lsx_vilvh_h, dsth3, dsth2, dsth4, dsth3, dsth5, dsth4, + dsth6, dsth5, dst32_l, dst43_l, dst54_l, dst65_l); + + DUP4_ARG2(__lsx_vdp2_w_h, dst10_r, filt_h0, dst10_l, filt_h0, dst21_r, + filt_h0, dst21_l, filt_h0, dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG2(__lsx_vdp2_w_h, dst32_r, filt_h0, dst32_l, filt_h0, dst43_r, + filt_h0, dst43_l, filt_h0, dst2_r, dst2_l, dst3_r, dst3_l); + DUP4_ARG3(__lsx_vdp2add_w_h, dst0_r, dst32_r, filt_h1, dst0_l, dst32_l, + filt_h1, dst1_r, dst43_r, filt_h1, dst1_l, dst43_l, filt_h1, + dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG3(__lsx_vdp2add_w_h, dst2_r, dst54_r, filt_h1, dst2_l, dst54_l, + filt_h1, dst3_r, dst65_r, filt_h1, dst3_l, dst65_l, filt_h1, + dst2_r, dst2_l, dst3_r, dst3_l); + + DUP4_ARG3(__lsx_vsrani_h_w, dst0_l, dst0_r, 6, dst1_l, dst1_r, 6, dst2_l, + dst2_r, 6, dst3_l, dst3_r, 6, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG3(__lsx_vssrarni_bu_h, tmp1, tmp0, 6, tmp3, tmp2, 6, out0, out1); + + __lsx_vstelm_d(out0, dst_tmp, 0, 0); + __lsx_vstelm_d(out0, dst_tmp + dst_stride, 0, 1); + __lsx_vstelm_d(out1, dst_tmp + dst_stride_2x, 0, 0); + __lsx_vstelm_d(out1, dst_tmp + dst_stride_3x, 0, 1); + dst_tmp += dst_stride_4x; + + dst10_r = dst54_r; + dst10_l = dst54_l; + dst21_r = dst65_r; + dst21_l = dst65_l; + dsth2 = dsth6; + } + + src += 8; + dst += 8; + + mask2 = __lsx_vld(ff_hevc_mask_arr, 16); + mask3 = __lsx_vaddi_bu(mask2, 2); + + src0 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src1, src2); + src += src_stride_3x; + DUP2_ARG3(__lsx_vshuf_b, src1, src0, mask2, src1, src0, mask3, vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src2, src1, mask2, src2, src1, mask3, vec2, vec3); + + DUP2_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec2, filt0, dst10, dst21); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst10, vec1, filt1, dst21, vec3, filt1, + dst10, dst21); + + dst10_r = __lsx_vilvl_h(dst21, dst10); + dst21_r = __lsx_vilvh_h(dst21, dst10); + dst22 = __lsx_vreplvei_d(dst21, 1); + + for (loop_cnt = 2; loop_cnt--;) { + src3 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src4, src5); + src6 = __lsx_vldx(src, src_stride_3x); + src += src_stride_4x; + src7 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src8, src9); + src10 = __lsx_vldx(src, src_stride_3x); + src += src_stride_4x; + DUP4_ARG3(__lsx_vshuf_b, src7, src3, mask2, src7, src3, mask3, src8, + src4, mask2, src8, src4, mask3, vec0, vec1, vec2, vec3); + DUP4_ARG3(__lsx_vshuf_b, src9, src5, mask2, src9, src5, mask3, src10, + src6, mask2, src10, src6, mask3, vec4, vec5, vec6, vec7); + + DUP4_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec2, filt0, vec4, filt0, + vec6, filt0, dst73, dst84, dst95, dst106); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst73, vec1, filt1, dst84, vec3, + filt1, dst95, vec5, filt1, dst106, vec7, filt1, + dst73, dst84, dst95, dst106); + + dst32_r = __lsx_vilvl_h(dst73, dst22); + DUP2_ARG2(__lsx_vilvl_h, dst84, dst73, dst95, dst84, dst43_r, dst54_r); + DUP2_ARG2(__lsx_vilvh_h, dst84, dst73, dst95, dst84, dst87_r, dst98_r); + dst65_r = __lsx_vilvl_h(dst106, dst95); + dst109_r = __lsx_vilvh_h(dst106, dst95); + dst22 = __lsx_vreplvei_d(dst73, 1); + dst76_r = __lsx_vilvl_h(dst22, dst106); + + DUP4_ARG2(__lsx_vdp2_w_h, dst10_r, filt_h0, dst21_r, filt_h0, dst32_r, + filt_h0, dst43_r, filt_h0, dst0, dst1, dst2, dst3); + DUP4_ARG2(__lsx_vdp2_w_h, dst54_r, filt_h0, dst65_r, filt_h0, dst76_r, + filt_h0, dst87_r, filt_h0, dst4, dst5, dst6, dst7); + DUP4_ARG3(__lsx_vdp2add_w_h, dst0, dst32_r, filt_h1, dst1, dst43_r, + filt_h1, dst2, dst54_r, filt_h1, dst3, dst65_r, filt_h1, + dst0, dst1, dst2, dst3); + DUP4_ARG3(__lsx_vdp2add_w_h, dst4, dst76_r, filt_h1, dst5, dst87_r, + filt_h1, dst6, dst98_r, filt_h1, dst7, dst109_r, filt_h1, + dst4, dst5, dst6, dst7); + + DUP4_ARG3(__lsx_vsrani_h_w, dst1, dst0, 6, dst3, dst2, 6, dst5, dst4, + 6, dst7, dst6, 6, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG3(__lsx_vssrarni_bu_h, tmp1, tmp0, 6, tmp3, tmp2, 6, out0, out1); + + __lsx_vstelm_w(out0, dst, 0, 0); + __lsx_vstelm_w(out0, dst + dst_stride, 0, 1); + __lsx_vstelm_w(out0, dst + dst_stride_2x, 0, 2); + __lsx_vstelm_w(out0, dst + dst_stride_3x, 0, 3); + dst += dst_stride_4x; + __lsx_vstelm_w(out1, dst, 0, 0); + __lsx_vstelm_w(out1, dst + dst_stride, 0, 1); + __lsx_vstelm_w(out1, dst + dst_stride_2x, 0, 2); + __lsx_vstelm_w(out1, dst + dst_stride_3x, 0, 3); + dst += dst_stride_4x; + + dst10_r = dst98_r; + dst21_r = dst109_r; + dst22 = __lsx_vreplvei_d(dst106, 1); + } +} + +static void hevc_hv_4t_16w_lsx(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) +{ + if (4 == height) { + hevc_hv_4t_8multx4_lsx(src, src_stride, dst, dst_stride, filter_x, + filter_y, 2); + } else { + hevc_hv_4t_8multx4mult_lsx(src, src_stride, dst, dst_stride, + filter_x, filter_y, height, 2); + } +} + +static void hevc_hv_4t_24w_lsx(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) +{ + hevc_hv_4t_8multx4mult_lsx(src, src_stride, dst, dst_stride, + filter_x, filter_y, height, 3); +} + +static void hevc_hv_4t_32w_lsx(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) +{ + hevc_hv_4t_8multx4mult_lsx(src, src_stride, dst, dst_stride, + filter_x, filter_y, height, 4); +} + +#define UNI_MC(PEL, DIR, WIDTH, TAP, DIR1, FILT_DIR) \ +void ff_hevc_put_hevc_uni_##PEL##_##DIR##WIDTH##_8_lsx(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 = ff_hevc_##PEL##_filters[FILT_DIR - 1]; \ + \ + common_##DIR1##_##TAP##t_##WIDTH##w_lsx(src, src_stride, dst, dst_stride, \ + filter, height); \ +} + +UNI_MC(qpel, h, 64, 8, hz, mx); + +UNI_MC(qpel, v, 24, 8, vt, my); +UNI_MC(qpel, v, 32, 8, vt, my); +UNI_MC(qpel, v, 48, 8, vt, my); +UNI_MC(qpel, v, 64, 8, vt, my); + +UNI_MC(epel, v, 24, 4, vt, my); +UNI_MC(epel, v, 32, 4, vt, my); + +#undef UNI_MC + +#define UNI_MC_HV(PEL, WIDTH, TAP) \ +void ff_hevc_put_hevc_uni_##PEL##_hv##WIDTH##_8_lsx(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_##TAP##t_##WIDTH##w_lsx(src, src_stride, dst, dst_stride, \ + filter_x, filter_y, height); \ +} + +UNI_MC_HV(qpel, 8, 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, 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 diff --git a/libavcodec/loongarch/hevc_mc_uniw_lsx.c b/libavcodec/loongarch/hevc_mc_uniw_lsx.c new file mode 100644 index 000000000..118f5b820 --- /dev/null +++ b/libavcodec/loongarch/hevc_mc_uniw_lsx.c @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2022 Loongson Technology Corporation Limited + * Contributed by Lu Wang + * Hao Chen + * + * 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/loongarch/loongson_intrinsics.h" +#include "hevcdsp_lsx.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 av_always_inline +void hevc_hv_8t_8x2_lsx(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 weight, + int32_t offset, int32_t rnd_val, int32_t width) +{ + uint32_t loop_cnt, cnt; + uint8_t *src_tmp; + uint8_t *dst_tmp; + const int32_t src_stride_2x = (src_stride << 1); + const int32_t dst_stride_2x = (dst_stride << 1); + const int32_t src_stride_4x = (src_stride << 2); + const int32_t src_stride_3x = src_stride_2x + src_stride; + + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8; + __m128i filt0, filt1, filt2, filt3; + __m128i filt_h0, filt_h1, filt_h2, filt_h3; + __m128i mask1, mask2, mask3; + __m128i filter_vec; + __m128i vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + __m128i vec8, vec9, vec10, vec11, vec12, vec13, vec14, vec15; + __m128i dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7, dst8; + __m128i dst0_r, dst0_l, dst1_r, dst1_l; + __m128i dst10_r, dst32_r, dst54_r, dst76_r; + __m128i dst10_l, dst32_l, dst54_l, dst76_l; + __m128i dst21_r, dst43_r, dst65_r, dst87_r; + __m128i dst21_l, dst43_l, dst65_l, dst87_l; + __m128i weight_vec, offset_vec, rnd_vec; + __m128i mask0 = __lsx_vld(ff_hevc_mask_arr, 0); + + src -= (src_stride_3x + 3); + weight_vec = __lsx_vreplgr2vr_w(weight); + offset_vec = __lsx_vreplgr2vr_w(offset); + rnd_vec = __lsx_vreplgr2vr_w(rnd_val); + + DUP4_ARG2(__lsx_vldrepl_h, filter_x, 0, filter_x, 2, filter_x, 4, + filter_x, 6, filt0, filt1, filt2, filt3); + filter_vec = __lsx_vld(filter_y, 0); + filter_vec = __lsx_vsllwil_h_b(filter_vec, 0); + DUP4_ARG2(__lsx_vreplvei_w, filter_vec, 0, filter_vec, 1, filter_vec, 2, + filter_vec, 3, filt_h0, filt_h1, filt_h2, filt_h3); + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + + for (cnt = width >> 3; cnt--;) { + src_tmp = src; + dst_tmp = dst; + + src0 = __lsx_vld(src_tmp, 0); + DUP2_ARG2(__lsx_vldx, src_tmp, src_stride, src_tmp, src_stride_2x, + src1, src2); + src3 = __lsx_vldx(src_tmp, src_stride_3x); + src_tmp += src_stride_4x; + src4 = __lsx_vld(src_tmp, 0); + DUP2_ARG2(__lsx_vldx, src_tmp, src_stride, src_tmp, src_stride_2x, + src5, src6); + src_tmp += src_stride_3x; + + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask0, src0, src0, mask1, src0, + src0, mask2, src0, src0, mask3, vec0, vec1, vec2, vec3); + DUP4_ARG3(__lsx_vshuf_b, src1, src1, mask0, src1, src1, mask1, src1, + src1, mask2, src1, src1, mask3, vec4, vec5, vec6, vec7); + DUP4_ARG3(__lsx_vshuf_b, src2, src2, mask0, src2, src2, mask1, src2, + src2, mask2, src2, src2, mask3, vec8, vec9, vec10, vec11); + DUP4_ARG3(__lsx_vshuf_b, src3, src3, mask0, src3, src3, mask1, src3, + src3, mask2, src3, src3, mask3, vec12, vec13, vec14, vec15); + DUP4_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec4, filt0, vec8, filt0, + vec12, filt0, dst0, dst1, dst2, dst3); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec1, filt1, dst1, vec5, filt1, + dst2, vec9, filt1, dst3, vec13, filt1, dst0, dst1, dst2, dst3); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec2, filt2, dst1, vec6, filt2, + dst2, vec10, filt2, dst3, vec14, filt2, dst0, dst1, dst2, dst3); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec3, filt3, dst1, vec7, filt3, + dst2, vec11, filt3, dst3, vec15, filt3, dst0, dst1, dst2, dst3); + DUP4_ARG3(__lsx_vshuf_b, src4, src4, mask0, src4, src4, mask1, src4, + src4, mask2, src4, src4, mask3, vec0, vec1, vec2, vec3); + DUP4_ARG3(__lsx_vshuf_b, src5, src5, mask0, src5, src5, mask1, src5, + src5, mask2, src5, src5, mask3, vec4, vec5, vec6, vec7); + DUP4_ARG3(__lsx_vshuf_b, src6, src6, mask0, src6, src6, mask1, src6, + src6, mask2, src6, src6, mask3, vec8, vec9, vec10, vec11); + DUP2_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec4, filt0, dst4, dst5); + dst6 = __lsx_vdp2_h_bu_b(vec8, filt0); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst4, vec1, filt1, dst5, vec5, filt1, + dst6, vec9, filt1, dst4, vec2, filt2, dst4, dst5, dst6, dst4); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst5, vec6, filt2, dst6, vec10, filt2, + dst4, vec3, filt3, dst5, vec7, filt3, dst5, dst6, dst4, dst5); + dst6 = __lsx_vdp2add_h_bu_b(dst6, vec11, filt3); + + DUP4_ARG2(__lsx_vilvl_h, dst1, dst0, dst3, dst2, dst5, dst4, dst2, + dst1, dst10_r, dst32_r, dst54_r, dst21_r); + DUP2_ARG2(__lsx_vilvl_h, dst4, dst3, dst6, dst5, dst43_r, dst65_r); + DUP4_ARG2(__lsx_vilvh_h, dst1, dst0, dst3, dst2, dst5, dst4, dst2, + dst1, dst10_l, dst32_l, dst54_l, dst21_l); + DUP2_ARG2(__lsx_vilvh_h, dst4, dst3, dst6, dst5, dst43_l, dst65_l); + + for (loop_cnt = height >> 1; loop_cnt--;) { + src7 = __lsx_vld(src_tmp, 0); + src8 = __lsx_vldx(src_tmp, src_stride); + src_tmp += src_stride_2x; + DUP4_ARG3(__lsx_vshuf_b, src7, src7, mask0, src7, src7, mask1, src7, + src7, mask2, src7, src7, mask3, vec0, vec1, vec2, vec3); + dst7 = __lsx_vdp2_h_bu_b(vec0, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst7, vec1, filt1, dst7, vec2, + filt2, dst7, dst7); + dst7 = __lsx_vdp2add_h_bu_b(dst7, vec3, filt3); + dst76_r = __lsx_vilvl_h(dst7, dst6); + dst76_l = __lsx_vilvh_h(dst7, dst6); + DUP2_ARG2(__lsx_vdp2_w_h, dst10_r, filt_h0, dst10_l, filt_h0, + dst0_r, dst0_l); + DUP4_ARG3(__lsx_vdp2add_w_h, dst0_r, dst32_r, filt_h1, dst0_l, + dst32_l, filt_h1, dst0_r, dst54_r, filt_h2, dst0_l, + dst54_l, filt_h2, dst0_r, dst0_l, dst0_r, dst0_l); + DUP2_ARG3(__lsx_vdp2add_w_h, dst0_r, dst76_r, filt_h3, dst0_l, + dst76_l, filt_h3, dst0_r, dst0_l); + DUP2_ARG2(__lsx_vsrai_w, dst0_r, 6, dst0_l, 6, dst0_r, dst0_l); + + /* row 8 */ + DUP4_ARG3(__lsx_vshuf_b, src8, src8, mask0, src8, src8, mask1, src8, + src8, mask2, src8, src8, mask3, vec0, vec1, vec2, vec3); + dst8 = __lsx_vdp2_h_bu_b(vec0, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst8, vec1, filt1, dst8, vec2, + filt2, dst8, dst8); + dst8 = __lsx_vdp2add_h_bu_b(dst8, vec3, filt3); + + dst87_r = __lsx_vilvl_h(dst8, dst7); + dst87_l = __lsx_vilvh_h(dst8, dst7); + DUP2_ARG2(__lsx_vdp2_w_h, dst21_r, filt_h0, dst21_l, filt_h0, + dst1_r, dst1_l); + DUP4_ARG3(__lsx_vdp2add_w_h, dst1_r, dst43_r, filt_h1, dst1_l, + dst43_l, filt_h1, dst1_r, dst65_r, filt_h2, dst1_l, + dst65_l, filt_h2, dst1_r, dst1_l, dst1_r, dst1_l); + DUP2_ARG3(__lsx_vdp2add_w_h, dst1_r, dst87_r, filt_h3, dst1_l, + dst87_l, filt_h3, dst1_r, dst1_l); + DUP2_ARG2(__lsx_vsrai_w, dst1_r, 6, dst1_l, 6, dst1_r, dst1_l); + + DUP2_ARG2(__lsx_vmul_w, dst0_r, weight_vec, dst0_l, weight_vec, + dst0_r, dst0_l); + DUP2_ARG2(__lsx_vmul_w, dst1_r, weight_vec, dst1_l, weight_vec, + dst1_r, dst1_l); + DUP4_ARG2(__lsx_vsrar_w, dst0_r, rnd_vec, dst1_r, rnd_vec, dst0_l, + rnd_vec, dst1_l, rnd_vec, dst0_r, dst1_r, dst0_l, dst1_l); + + DUP2_ARG2(__lsx_vadd_w, dst0_r, offset_vec, dst0_l, offset_vec, + dst0_r, dst0_l); + DUP2_ARG2(__lsx_vadd_w, dst1_r, offset_vec, dst1_l, offset_vec, + dst1_r, dst1_l); + DUP4_ARG1(__lsx_vclip255_w, dst0_r, dst1_r, dst0_l, dst1_l, dst0_r, + dst1_r, dst0_l, dst1_l); + DUP2_ARG2(__lsx_vpickev_h, dst0_l, dst0_r, dst1_l, dst1_r, + dst0_r, dst1_r); + dst0_r = __lsx_vpickev_b(dst1_r, dst0_r); + + __lsx_vstelm_d(dst0_r, dst_tmp, 0, 0); + __lsx_vstelm_d(dst0_r, dst_tmp + dst_stride, 0, 1); + dst_tmp += dst_stride_2x; + + 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; + } + + src += 8; + dst += 8; + } +} + +static +void hevc_hv_8t_8w_lsx(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 weight, + int32_t offset, int32_t rnd_val) +{ + hevc_hv_8t_8x2_lsx(src, src_stride, dst, dst_stride, filter_x, + filter_y, height, weight, offset, rnd_val, 8); +} + +static +void hevc_hv_8t_16w_lsx(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 weight, + int32_t offset, int32_t rnd_val) +{ + hevc_hv_8t_8x2_lsx(src, src_stride, dst, dst_stride, filter_x, + filter_y, height, weight, offset, rnd_val, 16); +} + +static +void hevc_hv_8t_24w_lsx(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 weight, + int32_t offset, int32_t rnd_val) +{ + hevc_hv_8t_8x2_lsx(src, src_stride, dst, dst_stride, filter_x, + filter_y, height, weight, offset, rnd_val, 24); +} + +static +void hevc_hv_8t_32w_lsx(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 weight, + int32_t offset, int32_t rnd_val) +{ + hevc_hv_8t_8x2_lsx(src, src_stride, dst, dst_stride, filter_x, + filter_y, height, weight, offset, rnd_val, 32); +} + +static +void hevc_hv_8t_48w_lsx(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 weight, + int32_t offset, int32_t rnd_val) +{ + hevc_hv_8t_8x2_lsx(src, src_stride, dst, dst_stride, filter_x, + filter_y, height, weight, offset, rnd_val, 48); +} + +static +void hevc_hv_8t_64w_lsx(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 weight, + int32_t offset, int32_t rnd_val) +{ + hevc_hv_8t_8x2_lsx(src, src_stride, dst, dst_stride, filter_x, + filter_y, height, weight, offset, rnd_val, 64); +} + + +#define UNI_W_MC_HV(PEL, WIDTH, TAP) \ +void ff_hevc_put_hevc_uni_w_##PEL##_hv##WIDTH##_8_lsx(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_##TAP##t_##WIDTH##w_lsx(src, src_stride, dst, dst_stride, filter_x,\ + filter_y, height, weight, offset, shift); \ +} + +UNI_W_MC_HV(qpel, 8, 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); + +#undef UNI_W_MC_HV diff --git a/libavcodec/loongarch/hevcdsp_init_loongarch.c b/libavcodec/loongarch/hevcdsp_init_loongarch.c new file mode 100644 index 000000000..22739c6f5 --- /dev/null +++ b/libavcodec/loongarch/hevcdsp_init_loongarch.c @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2022 Loongson Technology Corporation Limited + * Contributed by Lu Wang + * Hao Chen + * + * 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/loongarch/cpu.h" +#include "hevcdsp_lsx.h" + +void ff_hevc_dsp_init_loongarch(HEVCDSPContext *c, const int bit_depth) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_lsx(cpu_flags)) { + if (bit_depth == 8) { + c->put_hevc_qpel[1][0][0] = ff_hevc_put_hevc_pel_pixels4_8_lsx; + c->put_hevc_qpel[2][0][0] = ff_hevc_put_hevc_pel_pixels6_8_lsx; + c->put_hevc_qpel[3][0][0] = ff_hevc_put_hevc_pel_pixels8_8_lsx; + c->put_hevc_qpel[4][0][0] = ff_hevc_put_hevc_pel_pixels12_8_lsx; + c->put_hevc_qpel[5][0][0] = ff_hevc_put_hevc_pel_pixels16_8_lsx; + c->put_hevc_qpel[6][0][0] = ff_hevc_put_hevc_pel_pixels24_8_lsx; + c->put_hevc_qpel[7][0][0] = ff_hevc_put_hevc_pel_pixels32_8_lsx; + c->put_hevc_qpel[8][0][0] = ff_hevc_put_hevc_pel_pixels48_8_lsx; + c->put_hevc_qpel[9][0][0] = ff_hevc_put_hevc_pel_pixels64_8_lsx; + + c->put_hevc_epel[1][0][0] = ff_hevc_put_hevc_pel_pixels4_8_lsx; + c->put_hevc_epel[2][0][0] = ff_hevc_put_hevc_pel_pixels6_8_lsx; + c->put_hevc_epel[3][0][0] = ff_hevc_put_hevc_pel_pixels8_8_lsx; + c->put_hevc_epel[4][0][0] = ff_hevc_put_hevc_pel_pixels12_8_lsx; + c->put_hevc_epel[5][0][0] = ff_hevc_put_hevc_pel_pixels16_8_lsx; + c->put_hevc_epel[6][0][0] = ff_hevc_put_hevc_pel_pixels24_8_lsx; + c->put_hevc_epel[7][0][0] = ff_hevc_put_hevc_pel_pixels32_8_lsx; + + c->put_hevc_qpel[1][0][1] = ff_hevc_put_hevc_qpel_h4_8_lsx; + c->put_hevc_qpel[3][0][1] = ff_hevc_put_hevc_qpel_h8_8_lsx; + c->put_hevc_qpel[4][0][1] = ff_hevc_put_hevc_qpel_h12_8_lsx; + c->put_hevc_qpel[5][0][1] = ff_hevc_put_hevc_qpel_h16_8_lsx; + c->put_hevc_qpel[6][0][1] = ff_hevc_put_hevc_qpel_h24_8_lsx; + c->put_hevc_qpel[7][0][1] = ff_hevc_put_hevc_qpel_h32_8_lsx; + c->put_hevc_qpel[8][0][1] = ff_hevc_put_hevc_qpel_h48_8_lsx; + c->put_hevc_qpel[9][0][1] = ff_hevc_put_hevc_qpel_h64_8_lsx; + + c->put_hevc_qpel[1][1][0] = ff_hevc_put_hevc_qpel_v4_8_lsx; + c->put_hevc_qpel[3][1][0] = ff_hevc_put_hevc_qpel_v8_8_lsx; + c->put_hevc_qpel[4][1][0] = ff_hevc_put_hevc_qpel_v12_8_lsx; + c->put_hevc_qpel[5][1][0] = ff_hevc_put_hevc_qpel_v16_8_lsx; + c->put_hevc_qpel[6][1][0] = ff_hevc_put_hevc_qpel_v24_8_lsx; + c->put_hevc_qpel[7][1][0] = ff_hevc_put_hevc_qpel_v32_8_lsx; + c->put_hevc_qpel[8][1][0] = ff_hevc_put_hevc_qpel_v48_8_lsx; + c->put_hevc_qpel[9][1][0] = ff_hevc_put_hevc_qpel_v64_8_lsx; + + c->put_hevc_qpel[1][1][1] = ff_hevc_put_hevc_qpel_hv4_8_lsx; + c->put_hevc_qpel[3][1][1] = ff_hevc_put_hevc_qpel_hv8_8_lsx; + c->put_hevc_qpel[4][1][1] = ff_hevc_put_hevc_qpel_hv12_8_lsx; + c->put_hevc_qpel[5][1][1] = ff_hevc_put_hevc_qpel_hv16_8_lsx; + c->put_hevc_qpel[6][1][1] = ff_hevc_put_hevc_qpel_hv24_8_lsx; + c->put_hevc_qpel[7][1][1] = ff_hevc_put_hevc_qpel_hv32_8_lsx; + c->put_hevc_qpel[8][1][1] = ff_hevc_put_hevc_qpel_hv48_8_lsx; + c->put_hevc_qpel[9][1][1] = ff_hevc_put_hevc_qpel_hv64_8_lsx; + + c->put_hevc_epel[7][0][1] = ff_hevc_put_hevc_epel_h32_8_lsx; + + c->put_hevc_epel[5][1][0] = ff_hevc_put_hevc_epel_v16_8_lsx; + c->put_hevc_epel[6][1][0] = ff_hevc_put_hevc_epel_v24_8_lsx; + c->put_hevc_epel[7][1][0] = ff_hevc_put_hevc_epel_v32_8_lsx; + + c->put_hevc_epel[3][1][1] = ff_hevc_put_hevc_epel_hv8_8_lsx; + c->put_hevc_epel[4][1][1] = ff_hevc_put_hevc_epel_hv12_8_lsx; + c->put_hevc_epel[5][1][1] = ff_hevc_put_hevc_epel_hv16_8_lsx; + c->put_hevc_epel[6][1][1] = ff_hevc_put_hevc_epel_hv24_8_lsx; + c->put_hevc_epel[7][1][1] = ff_hevc_put_hevc_epel_hv32_8_lsx; + + c->put_hevc_qpel_bi[1][0][0] = ff_hevc_put_hevc_bi_pel_pixels4_8_lsx; + c->put_hevc_qpel_bi[3][0][0] = ff_hevc_put_hevc_bi_pel_pixels8_8_lsx; + c->put_hevc_qpel_bi[4][0][0] = ff_hevc_put_hevc_bi_pel_pixels12_8_lsx; + c->put_hevc_qpel_bi[5][0][0] = ff_hevc_put_hevc_bi_pel_pixels16_8_lsx; + c->put_hevc_qpel_bi[6][0][0] = ff_hevc_put_hevc_bi_pel_pixels24_8_lsx; + c->put_hevc_qpel_bi[7][0][0] = ff_hevc_put_hevc_bi_pel_pixels32_8_lsx; + c->put_hevc_qpel_bi[8][0][0] = ff_hevc_put_hevc_bi_pel_pixels48_8_lsx; + c->put_hevc_qpel_bi[9][0][0] = ff_hevc_put_hevc_bi_pel_pixels64_8_lsx; + + c->put_hevc_epel_bi[1][0][0] = ff_hevc_put_hevc_bi_pel_pixels4_8_lsx; + c->put_hevc_epel_bi[2][0][0] = ff_hevc_put_hevc_bi_pel_pixels6_8_lsx; + c->put_hevc_epel_bi[3][0][0] = ff_hevc_put_hevc_bi_pel_pixels8_8_lsx; + c->put_hevc_epel_bi[4][0][0] = ff_hevc_put_hevc_bi_pel_pixels12_8_lsx; + c->put_hevc_epel_bi[5][0][0] = ff_hevc_put_hevc_bi_pel_pixels16_8_lsx; + c->put_hevc_epel_bi[6][0][0] = ff_hevc_put_hevc_bi_pel_pixels24_8_lsx; + c->put_hevc_epel_bi[7][0][0] = ff_hevc_put_hevc_bi_pel_pixels32_8_lsx; + + c->put_hevc_qpel_bi[3][1][0] = ff_hevc_put_hevc_bi_qpel_v8_8_lsx; + c->put_hevc_qpel_bi[5][1][0] = ff_hevc_put_hevc_bi_qpel_v16_8_lsx; + c->put_hevc_qpel_bi[6][1][0] = ff_hevc_put_hevc_bi_qpel_v24_8_lsx; + c->put_hevc_qpel_bi[7][1][0] = ff_hevc_put_hevc_bi_qpel_v32_8_lsx; + c->put_hevc_qpel_bi[8][1][0] = ff_hevc_put_hevc_bi_qpel_v48_8_lsx; + c->put_hevc_qpel_bi[9][1][0] = ff_hevc_put_hevc_bi_qpel_v64_8_lsx; + + c->put_hevc_qpel_bi[3][1][1] = ff_hevc_put_hevc_bi_qpel_hv8_8_lsx; + c->put_hevc_qpel_bi[5][1][1] = ff_hevc_put_hevc_bi_qpel_hv16_8_lsx; + c->put_hevc_qpel_bi[6][1][1] = ff_hevc_put_hevc_bi_qpel_hv24_8_lsx; + c->put_hevc_qpel_bi[7][1][1] = ff_hevc_put_hevc_bi_qpel_hv32_8_lsx; + c->put_hevc_qpel_bi[8][1][1] = ff_hevc_put_hevc_bi_qpel_hv48_8_lsx; + c->put_hevc_qpel_bi[9][1][1] = ff_hevc_put_hevc_bi_qpel_hv64_8_lsx; + + c->put_hevc_qpel_bi[5][0][1] = ff_hevc_put_hevc_bi_qpel_h16_8_lsx; + c->put_hevc_qpel_bi[6][0][1] = ff_hevc_put_hevc_bi_qpel_h24_8_lsx; + c->put_hevc_qpel_bi[7][0][1] = ff_hevc_put_hevc_bi_qpel_h32_8_lsx; + c->put_hevc_qpel_bi[8][0][1] = ff_hevc_put_hevc_bi_qpel_h48_8_lsx; + c->put_hevc_qpel_bi[9][0][1] = ff_hevc_put_hevc_bi_qpel_h64_8_lsx; + + c->put_hevc_epel_bi[6][0][1] = ff_hevc_put_hevc_bi_epel_h24_8_lsx; + c->put_hevc_epel_bi[7][0][1] = ff_hevc_put_hevc_bi_epel_h32_8_lsx; + + c->put_hevc_epel_bi[4][1][0] = ff_hevc_put_hevc_bi_epel_v12_8_lsx; + c->put_hevc_epel_bi[5][1][0] = ff_hevc_put_hevc_bi_epel_v16_8_lsx; + c->put_hevc_epel_bi[6][1][0] = ff_hevc_put_hevc_bi_epel_v24_8_lsx; + c->put_hevc_epel_bi[7][1][0] = ff_hevc_put_hevc_bi_epel_v32_8_lsx; + + c->put_hevc_epel_bi[2][1][1] = ff_hevc_put_hevc_bi_epel_hv6_8_lsx; + c->put_hevc_epel_bi[3][1][1] = ff_hevc_put_hevc_bi_epel_hv8_8_lsx; + c->put_hevc_epel_bi[5][1][1] = ff_hevc_put_hevc_bi_epel_hv16_8_lsx; + c->put_hevc_epel_bi[6][1][1] = ff_hevc_put_hevc_bi_epel_hv24_8_lsx; + c->put_hevc_epel_bi[7][1][1] = ff_hevc_put_hevc_bi_epel_hv32_8_lsx; + + c->put_hevc_qpel_uni[9][0][1] = ff_hevc_put_hevc_uni_qpel_h64_8_lsx; + + c->put_hevc_qpel_uni[6][1][0] = ff_hevc_put_hevc_uni_qpel_v24_8_lsx; + c->put_hevc_qpel_uni[7][1][0] = ff_hevc_put_hevc_uni_qpel_v32_8_lsx; + c->put_hevc_qpel_uni[8][1][0] = ff_hevc_put_hevc_uni_qpel_v48_8_lsx; + c->put_hevc_qpel_uni[9][1][0] = ff_hevc_put_hevc_uni_qpel_v64_8_lsx; + + c->put_hevc_qpel_uni[3][1][1] = ff_hevc_put_hevc_uni_qpel_hv8_8_lsx; + c->put_hevc_qpel_uni[5][1][1] = ff_hevc_put_hevc_uni_qpel_hv16_8_lsx; + c->put_hevc_qpel_uni[6][1][1] = ff_hevc_put_hevc_uni_qpel_hv24_8_lsx; + c->put_hevc_qpel_uni[7][1][1] = ff_hevc_put_hevc_uni_qpel_hv32_8_lsx; + c->put_hevc_qpel_uni[8][1][1] = ff_hevc_put_hevc_uni_qpel_hv48_8_lsx; + c->put_hevc_qpel_uni[9][1][1] = ff_hevc_put_hevc_uni_qpel_hv64_8_lsx; + + c->put_hevc_epel_uni[6][1][0] = ff_hevc_put_hevc_uni_epel_v24_8_lsx; + c->put_hevc_epel_uni[7][1][0] = ff_hevc_put_hevc_uni_epel_v32_8_lsx; + + c->put_hevc_epel_uni[3][1][1] = ff_hevc_put_hevc_uni_epel_hv8_8_lsx; + c->put_hevc_epel_uni[4][1][1] = ff_hevc_put_hevc_uni_epel_hv12_8_lsx; + c->put_hevc_epel_uni[5][1][1] = ff_hevc_put_hevc_uni_epel_hv16_8_lsx; + c->put_hevc_epel_uni[6][1][1] = ff_hevc_put_hevc_uni_epel_hv24_8_lsx; + c->put_hevc_epel_uni[7][1][1] = ff_hevc_put_hevc_uni_epel_hv32_8_lsx; + + c->put_hevc_qpel_uni_w[3][1][1] = ff_hevc_put_hevc_uni_w_qpel_hv8_8_lsx; + c->put_hevc_qpel_uni_w[5][1][1] = ff_hevc_put_hevc_uni_w_qpel_hv16_8_lsx; + c->put_hevc_qpel_uni_w[6][1][1] = ff_hevc_put_hevc_uni_w_qpel_hv24_8_lsx; + c->put_hevc_qpel_uni_w[7][1][1] = ff_hevc_put_hevc_uni_w_qpel_hv32_8_lsx; + c->put_hevc_qpel_uni_w[8][1][1] = ff_hevc_put_hevc_uni_w_qpel_hv48_8_lsx; + c->put_hevc_qpel_uni_w[9][1][1] = ff_hevc_put_hevc_uni_w_qpel_hv64_8_lsx; + + c->sao_edge_filter[4] = ff_hevc_sao_edge_filter_8_lsx; + + c->hevc_h_loop_filter_luma = ff_hevc_loop_filter_luma_h_8_lsx; + c->hevc_v_loop_filter_luma = ff_hevc_loop_filter_luma_v_8_lsx; + + c->hevc_h_loop_filter_luma_c = ff_hevc_loop_filter_luma_h_8_lsx; + c->hevc_v_loop_filter_luma_c = ff_hevc_loop_filter_luma_v_8_lsx; + + c->hevc_h_loop_filter_chroma = ff_hevc_loop_filter_chroma_h_8_lsx; + c->hevc_v_loop_filter_chroma = ff_hevc_loop_filter_chroma_v_8_lsx; + + c->hevc_h_loop_filter_chroma_c = ff_hevc_loop_filter_chroma_h_8_lsx; + c->hevc_v_loop_filter_chroma_c = ff_hevc_loop_filter_chroma_v_8_lsx; + + c->idct[0] = ff_hevc_idct_4x4_lsx; + c->idct[1] = ff_hevc_idct_8x8_lsx; + c->idct[2] = ff_hevc_idct_16x16_lsx; + c->idct[3] = ff_hevc_idct_32x32_lsx; + } + } +} diff --git a/libavcodec/loongarch/hevcdsp_lsx.c b/libavcodec/loongarch/hevcdsp_lsx.c new file mode 100644 index 000000000..a520f02bd --- /dev/null +++ b/libavcodec/loongarch/hevcdsp_lsx.c @@ -0,0 +1,3299 @@ +/* + * Copyright (c) 2022 Loongson Technology Corporation Limited + * Contributed by Lu Wang + * Hao Chen + * + * 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/loongarch/loongson_intrinsics.h" +#include "hevcdsp_lsx.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 +}; + +/* hevc_copy: dst = src << 6 */ +static void hevc_copy_4w_lsx(uint8_t *src, int32_t src_stride, + int16_t *dst, int32_t dst_stride, + int32_t height) +{ + int32_t src_stride_2x = (src_stride << 1); + int32_t dst_stride_2x = (dst_stride << 1); + int32_t src_stride_4x = (src_stride << 2); + int32_t dst_stride_4x = (dst_stride << 2); + int32_t src_stride_3x = src_stride_2x + src_stride; + int32_t dst_stride_3x = dst_stride_2x + dst_stride; + int32_t loop_cnt = height >> 3; + int32_t res = height & 0x07; + + __m128i src0, src1, src2, src3, src4, src5, src6, src7; + __m128i in0, in1, in2, in3; + for (; loop_cnt--;) { + src0 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, + src1, src2); + src3 = __lsx_vldx(src, src_stride_3x); + src += src_stride_4x; + src4 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, + src5, src6); + src7 = __lsx_vldx(src, src_stride_3x); + src += src_stride_4x; + + DUP4_ARG2(__lsx_vilvl_w, src1, src0, src3, src2, src5, src4, src7, src6, + src0, src1, src2, src3); + DUP4_ARG2(__lsx_vsllwil_hu_bu, src0, 6, src1, 6, src2, 6, src3, 6, + in0, in1, in2, in3); + + __lsx_vstelm_d(in0, dst, 0, 0); + __lsx_vstelm_d(in0, dst + dst_stride, 0, 1); + __lsx_vstelm_d(in1, dst + dst_stride_2x, 0, 0); + __lsx_vstelm_d(in1, dst + dst_stride_3x, 0, 1); + dst += dst_stride_4x; + __lsx_vstelm_d(in2, dst, 0, 0); + __lsx_vstelm_d(in2, dst + dst_stride, 0, 1); + __lsx_vstelm_d(in3, dst + dst_stride_2x, 0, 0); + __lsx_vstelm_d(in3, dst + dst_stride_3x, 0, 1); + dst += dst_stride_4x; + } + for (;res--;) { + src0 = __lsx_vld(src, 0); + in0 = __lsx_vsllwil_hu_bu(src0, 6); + __lsx_vstelm_d(in0, dst, 0, 0); + src += src_stride; + dst += dst_stride; + } +} + +static void hevc_copy_6w_lsx(uint8_t *src, int32_t src_stride, + int16_t *dst, int32_t dst_stride, + int32_t height) +{ + int32_t loop_cnt = (height >> 3); + int32_t res = height & 0x07; + int32_t src_stride_2x = (src_stride << 1); + int32_t src_stride_4x = (src_stride << 2); + int32_t src_stride_3x = src_stride_2x + src_stride; + + __m128i src0, src1, src2, src3, src4, src5, src6, src7; + __m128i in0, in1, in2, in3, in4, in5, in6, in7; + + for (loop_cnt = (height >> 3); loop_cnt--;) { + src0 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src1, src2); + src3 = __lsx_vldx(src, src_stride_3x); + src += src_stride_4x; + src4 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src5, src6); + src7 = __lsx_vldx(src, src_stride_3x); + src += src_stride_4x; + + DUP4_ARG2(__lsx_vsllwil_hu_bu, src0, 6, src1, 6, src2, 6, src3, 6, + in0, in1, in2, in3); + DUP4_ARG2(__lsx_vsllwil_hu_bu, src4, 6, src5, 6, src6, 6, src7, 6, + in4, in5, in6, in7); + + __lsx_vstelm_d(in0, dst, 0, 0); + __lsx_vstelm_w(in0, dst, 8, 2); + dst += dst_stride; + __lsx_vstelm_d(in1, dst, 0, 0); + __lsx_vstelm_w(in1, dst, 8, 2); + dst += dst_stride; + __lsx_vstelm_d(in2, dst, 0, 0); + __lsx_vstelm_w(in2, dst, 8, 2); + dst += dst_stride; + __lsx_vstelm_d(in3, dst, 0, 0); + __lsx_vstelm_w(in3, dst, 8, 2); + dst += dst_stride; + __lsx_vstelm_d(in4, dst, 0, 0); + __lsx_vstelm_w(in4, dst, 8, 2); + dst += dst_stride; + __lsx_vstelm_d(in5, dst, 0, 0); + __lsx_vstelm_w(in5, dst, 8, 2); + dst += dst_stride; + __lsx_vstelm_d(in6, dst, 0, 0); + __lsx_vstelm_w(in6, dst, 8, 2); + dst += dst_stride; + __lsx_vstelm_d(in7, dst, 0, 0); + __lsx_vstelm_w(in7, dst, 8, 2); + dst += dst_stride; + } + for (;res--;) { + src0 = __lsx_vld(src, 0); + in0 = __lsx_vsllwil_hu_bu(src0, 6); + src += src_stride; + __lsx_vstelm_d(in0, dst, 0, 0); + __lsx_vstelm_w(in0, dst, 8, 2); + dst += dst_stride; + } +} + +static void hevc_copy_8w_lsx(uint8_t *src, int32_t src_stride, + int16_t *dst, int32_t dst_stride, + int32_t height) +{ + int32_t src_stride_2x = (src_stride << 1); + int32_t dst_stride_x = (dst_stride << 1); + int32_t src_stride_4x = (src_stride << 2); + int32_t dst_stride_2x = (dst_stride_x << 1); + int32_t src_stride_3x = src_stride_2x + src_stride; + int32_t dst_stride_3x = dst_stride_2x + dst_stride_x; + int32_t loop_cnt = height >> 3; + int32_t res = height & 0x07; + __m128i src0, src1, src2, src3, src4, src5, src6, src7; + __m128i in0, in1, in2, in3, in4, in5, in6, in7; + + for (loop_cnt = (height >> 3); loop_cnt--;) { + src0 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, + src1, src2); + src3 = __lsx_vldx(src, src_stride_3x); + src += src_stride_4x; + src4 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, + src5, src6); + src7 = __lsx_vldx(src, src_stride_3x); + src += src_stride_4x; + + DUP4_ARG2(__lsx_vsllwil_hu_bu, src0, 6, src1, 6, src2, 6, src3, 6, + in0, in1, in2, in3); + DUP4_ARG2(__lsx_vsllwil_hu_bu, src4, 6, src5, 6, src6, 6, src7, 6, + in4, in5, in6, in7); + __lsx_vst(in0, dst, 0); + __lsx_vstx(in1, dst, dst_stride_x); + __lsx_vstx(in2, dst, dst_stride_2x); + __lsx_vstx(in3, dst, dst_stride_3x); + dst += dst_stride_2x; + __lsx_vst(in4, dst, 0); + __lsx_vstx(in5, dst, dst_stride_x); + __lsx_vstx(in6, dst, dst_stride_2x); + __lsx_vstx(in7, dst, dst_stride_3x); + dst += dst_stride_2x; + } + for (;res--;) { + src0 = __lsx_vld(src, 0); + in0 = __lsx_vsllwil_hu_bu(src0, 6); + __lsx_vst(in0, dst, 0); + src += src_stride; + dst += dst_stride; + } +} + +static void hevc_copy_12w_lsx(uint8_t *src, int32_t src_stride, + int16_t *dst, int32_t dst_stride, + int32_t height) +{ + uint32_t loop_cnt; + uint32_t res = height & 0x07; + int32_t src_stride_2x = (src_stride << 1); + int32_t dst_stride_x = (dst_stride << 1); + int32_t src_stride_4x = (src_stride << 2); + int32_t dst_stride_2x = (dst_stride_x << 1); + int32_t src_stride_3x = src_stride_2x + src_stride; + int32_t dst_stride_3x = dst_stride_2x + dst_stride_x; + __m128i zero = __lsx_vldi(0); + __m128i src0, src1, src2, src3, src4, src5, src6, src7; + __m128i in0, in1, in0_r, in1_r, in2_r, in3_r; + + for (loop_cnt = (height >> 3); loop_cnt--;) { + src0 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src1, src2); + src3 = __lsx_vldx(src, src_stride_3x); + src += src_stride_4x; + src4 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src5, src6); + src7 = __lsx_vldx(src, src_stride_3x); + src += src_stride_4x; + + DUP4_ARG2(__lsx_vsllwil_hu_bu, src0, 6, src1, 6, src2, 6, src3, 6, + in0_r, in1_r, in2_r, in3_r); + DUP2_ARG2(__lsx_vilvh_w, src1, src0, src3, src2, src0, src1); + DUP2_ARG2(__lsx_vsllwil_hu_bu, src0, 6, src1, 6, in0, in1); + __lsx_vst(in0_r, dst, 0); + __lsx_vstx(in1_r, dst, dst_stride_x); + __lsx_vstx(in2_r, dst, dst_stride_2x); + __lsx_vstx(in3_r, dst, dst_stride_3x); + __lsx_vstelm_d(in0, dst, 16, 0); + dst += dst_stride; + __lsx_vstelm_d(in0, dst, 16, 1); + dst += dst_stride; + __lsx_vstelm_d(in1, dst, 16, 0); + dst += dst_stride; + __lsx_vstelm_d(in1, dst, 16, 1); + dst += dst_stride; + + DUP4_ARG2(__lsx_vsllwil_hu_bu, src4, 6, src5, 6, src6, 6, src7, 6, + in0_r, in1_r, in2_r, in3_r); + DUP2_ARG2(__lsx_vilvh_w, src5, src4, src7, src6, src0, src1); + DUP2_ARG2(__lsx_vsllwil_hu_bu, src0, 6, src1, 6, in0, in1); + __lsx_vst(in0_r, dst, 0); + __lsx_vstx(in1_r, dst, dst_stride_x); + __lsx_vstx(in2_r, dst, dst_stride_2x); + __lsx_vstx(in3_r, dst, dst_stride_3x); + __lsx_vstelm_d(in0, dst, 16, 0); + dst += dst_stride; + __lsx_vstelm_d(in0, dst, 16, 1); + dst += dst_stride; + __lsx_vstelm_d(in1, dst, 16, 0); + dst += dst_stride; + __lsx_vstelm_d(in1, dst, 16, 1); + dst += dst_stride; + } + for (;res--;) { + src0 = __lsx_vld(src, 0); + in0 = __lsx_vsllwil_hu_bu(src0, 6); + src1 = __lsx_vilvh_b(zero, src0); + in1 = __lsx_vslli_h(src1, 6); + __lsx_vst(in0, dst, 0); + __lsx_vstelm_d(in1, dst, 16, 0); + src += src_stride; + dst += dst_stride; + } +} + +static void hevc_copy_16w_lsx(uint8_t *src, int32_t src_stride, + int16_t *dst, int32_t dst_stride, + int32_t height) +{ + __m128i zero = __lsx_vldi(0); + int32_t src_stride_2x = (src_stride << 1); + int32_t dst_stride_x = (dst_stride << 1); + int32_t src_stride_4x = (src_stride << 2); + int32_t dst_stride_2x = (dst_stride << 2); + int32_t src_stride_3x = src_stride_2x + src_stride; + int32_t dst_stride_3x = dst_stride_2x + dst_stride_x; + int32_t loop_cnt = height >> 3; + int32_t res = height & 0x07; + int16_t* dst1 = dst + 8; + __m128i src0, src1, src2, src3, src4, src5, src6, src7; + __m128i in0_r, in1_r, in2_r, in3_r, in0_l, in1_l, in2_l, in3_l; + + for (loop_cnt = (height >> 3); loop_cnt--;) { + src0 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, + src1, src2); + src3 = __lsx_vldx(src, src_stride_3x); + src += src_stride_4x; + src4 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, + src5, src6); + src7 = __lsx_vldx(src, src_stride_3x); + src += src_stride_4x; + DUP4_ARG2(__lsx_vilvh_b, zero, src0, zero, src1, zero, src2, zero, src3, + in0_l, in1_l, in2_l, in3_l); + DUP4_ARG2(__lsx_vsllwil_hu_bu, src0, 6, src1, 6, src2, 6, src3, 6, + in0_r, in1_r, in2_r, in3_r); + DUP4_ARG2(__lsx_vslli_h, in0_l, 6, in1_l, 6, in2_l, 6, in3_l, 6, in0_l, + in1_l, in2_l, in3_l); + __lsx_vst(in0_r, dst, 0); + __lsx_vstx(in1_r, dst, dst_stride_x); + __lsx_vstx(in2_r, dst, dst_stride_2x); + __lsx_vstx(in3_r, dst, dst_stride_3x); + __lsx_vst(in0_l, dst1, 0); + __lsx_vstx(in1_l, dst1, dst_stride_x); + __lsx_vstx(in2_l, dst1, dst_stride_2x); + __lsx_vstx(in3_l, dst1, dst_stride_3x); + dst += dst_stride_2x; + dst1 += dst_stride_2x; + + DUP4_ARG2(__lsx_vilvh_b, zero, src4, zero, src5, zero, src6, zero, src7, + in0_l, in1_l, in2_l, in3_l); + DUP4_ARG2(__lsx_vsllwil_hu_bu, src4, 6, src5, 6, src6, 6, src7, 6, + in0_r, in1_r, in2_r, in3_r); + DUP4_ARG2(__lsx_vslli_h, in0_l, 6, in1_l, 6, in2_l, 6, in3_l, 6, in0_l, + in1_l, in2_l, in3_l); + __lsx_vst(in0_r, dst, 0); + __lsx_vstx(in1_r, dst, dst_stride_x); + __lsx_vstx(in2_r, dst, dst_stride_2x); + __lsx_vstx(in3_r, dst, dst_stride_3x); + __lsx_vst(in0_l, dst1, 0); + __lsx_vstx(in1_l, dst1, dst_stride_x); + __lsx_vstx(in2_l, dst1, dst_stride_2x); + __lsx_vstx(in3_l, dst1, dst_stride_3x); + dst += dst_stride_2x; + dst1 += dst_stride_2x; + } + if (res) { + src0 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src1, src2); + src3 = __lsx_vldx(src, src_stride_3x); + + DUP4_ARG2(__lsx_vilvh_b, zero, src0, zero, src1, zero, src2, zero, src3, + in0_l, in1_l, in2_l, in3_l); + DUP4_ARG2(__lsx_vsllwil_hu_bu, src0, 6, src1, 6, src2, 6, src3, 6, + in0_r, in1_r, in2_r, in3_r); + DUP4_ARG2(__lsx_vslli_h, in0_l, 6, in1_l, 6, in2_l, 6, in3_l, 6, in0_l, + in1_l, in2_l, in3_l); + __lsx_vst(in0_r, dst, 0); + __lsx_vstx(in1_r, dst, dst_stride_x); + __lsx_vstx(in2_r, dst, dst_stride_2x); + __lsx_vstx(in3_r, dst, dst_stride_3x); + dst += 8; + __lsx_vst(in0_l, dst, 0); + __lsx_vstx(in1_l, dst, dst_stride_x); + __lsx_vstx(in2_l, dst, dst_stride_2x); + __lsx_vstx(in3_l, dst, dst_stride_3x); + } +} + +static void hevc_copy_24w_lsx(uint8_t *src, int32_t src_stride, + int16_t *dst, int32_t dst_stride, + int32_t height) +{ + uint32_t loop_cnt; + int32_t src_stride_2x = (src_stride << 1); + int32_t dst_stride_x = (dst_stride << 1); + int32_t src_stride_4x = (src_stride << 2); + int32_t dst_stride_2x = (dst_stride << 2); + int32_t src_stride_3x = src_stride_2x + src_stride; + int32_t dst_stride_3x = dst_stride_2x + dst_stride_x; + uint8_t *_src = src + 16; + int16_t *dst1 = dst; + __m128i zero = __lsx_vldi(0); + __m128i src0, src1, src2, src3, src4, src5, src6, src7; + __m128i in0_r, in1_r, in2_r, in3_r, in0_l, in1_l, in2_l, in3_l; + + for (loop_cnt = (height >> 2); loop_cnt--;) { + src0 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src1, src2); + src3 = __lsx_vldx(src, src_stride_3x); + src += src_stride_4x; + src4 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride_2x, + src5, src6); + src7 = __lsx_vldx(_src, src_stride_3x); + _src += src_stride_4x; + + DUP4_ARG2(__lsx_vilvh_b, zero, src0, zero, src1, zero, src2, zero, + src3, in0_l, in1_l, in2_l, in3_l); + DUP4_ARG2(__lsx_vsllwil_hu_bu, src0, 6, src1, 6, src2, 6, src3, 6, + in0_r, in1_r, in2_r, in3_r); + DUP4_ARG2(__lsx_vslli_h, in0_l, 6, in1_l, 6, in2_l, 6, in3_l, 6, + in0_l, in1_l, in2_l, in3_l); + __lsx_vst(in0_r, dst, 0); + __lsx_vstx(in1_r, dst, dst_stride_x); + __lsx_vstx(in2_r, dst, dst_stride_2x); + __lsx_vstx(in3_r, dst, dst_stride_3x); + dst1 = dst + 8; + __lsx_vst(in0_l, dst1, 0); + __lsx_vstx(in1_l, dst1, dst_stride_x); + __lsx_vstx(in2_l, dst1, dst_stride_2x); + __lsx_vstx(in3_l, dst1, dst_stride_3x); + DUP4_ARG2(__lsx_vsllwil_hu_bu, src4, 6, src5, 6, src6, 6, src7, 6, + in0_r, in1_r, in2_r, in3_r); + dst1 = dst1 + 8; + __lsx_vst(in0_r, dst1, 0); + __lsx_vstx(in1_r, dst1, dst_stride_x); + __lsx_vstx(in2_r, dst1, dst_stride_2x); + __lsx_vstx(in3_r, dst1, dst_stride_3x); + dst += dst_stride_2x; + } +} + +static void hevc_copy_32w_lsx(uint8_t *src, int32_t src_stride, + int16_t *dst, int32_t dst_stride, + int32_t height) +{ + uint32_t loop_cnt; + int32_t src_stride_2x = (src_stride << 1); + int32_t src_stride_4x = (src_stride << 2); + int32_t src_stride_3x = src_stride_2x + src_stride; + uint8_t *_src = src + 16; + __m128i zero = {0}; + __m128i src0, src1, src2, src3, src4, src5, src6, src7; + __m128i in0_r, in1_r, in2_r, in3_r, in0_l, in1_l, in2_l, in3_l; + + for (loop_cnt = (height >> 2); loop_cnt--;) { + src0 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src2, src4); + src6 = __lsx_vldx(src, src_stride_3x); + src += src_stride_4x; + src1 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride_2x, + src3, src5); + src7 = __lsx_vldx(_src, src_stride_3x); + _src += src_stride_4x; + + DUP4_ARG2(__lsx_vilvh_b, zero, src0, zero, src1, zero, src2, zero, + src3, in0_l, in1_l, in2_l, in3_l); + DUP4_ARG2(__lsx_vsllwil_hu_bu, src0, 6, src1, 6, src2, 6, src3, 6, + in0_r, in1_r, in2_r, in3_r); + DUP4_ARG2(__lsx_vslli_h, in0_l, 6, in1_l, 6, in2_l, 6, in3_l, 6, + in0_l, in1_l, in2_l, in3_l); + __lsx_vst(in0_r, dst, 0); + __lsx_vst(in0_l, dst, 16); + __lsx_vst(in1_r, dst, 32); + __lsx_vst(in1_l, dst, 48); + dst += dst_stride; + __lsx_vst(in2_r, dst, 0); + __lsx_vst(in2_l, dst, 16); + __lsx_vst(in3_r, dst, 32); + __lsx_vst(in3_l, dst, 48); + dst += dst_stride; + + DUP4_ARG2(__lsx_vilvh_b, zero, src4, zero, src5, zero, src6, zero, src7, + in0_l, in1_l, in2_l, in3_l); + DUP4_ARG2(__lsx_vsllwil_hu_bu, src4, 6, src5, 6, src6, 6, src7, 6, + in0_r, in1_r, in2_r, in3_r); + DUP4_ARG2(__lsx_vslli_h, in0_l, 6, in1_l, 6, in2_l, 6, in3_l, 6, in0_l, + in1_l, in2_l, in3_l); + __lsx_vst(in0_r, dst, 0); + __lsx_vst(in0_l, dst, 16); + __lsx_vst(in1_r, dst, 32); + __lsx_vst(in1_l, dst, 48); + dst += dst_stride; + __lsx_vst(in2_r, dst, 0); + __lsx_vst(in2_l, dst, 16); + __lsx_vst(in3_r, dst, 32); + __lsx_vst(in3_l, dst, 48); + dst += dst_stride; + } +} + +static void hevc_copy_48w_lsx(uint8_t *src, int32_t src_stride, + int16_t *dst, int32_t dst_stride, + int32_t height) +{ + uint32_t loop_cnt; + __m128i zero = {0}; + __m128i src0, src1, src2, src3, src4, src5, src6, src7; + __m128i src8, src9, src10, src11; + __m128i in0_r, in1_r, in2_r, in3_r, in4_r, in5_r; + __m128i in0_l, in1_l, in2_l, in3_l, in4_l, in5_l; + + for (loop_cnt = (height >> 2); loop_cnt--;) { + DUP2_ARG2(__lsx_vld, src, 0, src, 16, src0, src1); + src2 = __lsx_vld(src, 32); + src += src_stride; + DUP2_ARG2(__lsx_vld, src, 0, src, 16, src3, src4); + src5 = __lsx_vld(src, 32); + src += src_stride; + DUP2_ARG2(__lsx_vld, src, 0, src, 16, src6, src7); + src8 = __lsx_vld(src, 32); + src += src_stride; + DUP2_ARG2(__lsx_vld, src, 0, src, 16, src9, src10); + src11 = __lsx_vld(src, 32); + src += src_stride; + + DUP4_ARG2(__lsx_vilvh_b, zero, src0, zero, src1, zero, src2, zero, + src3, in0_l, in1_l, in2_l, in3_l); + DUP2_ARG2(__lsx_vilvh_b, zero, src4, zero, src5, in4_l, in5_l); + DUP4_ARG2(__lsx_vsllwil_hu_bu, src0, 6, src1, 6, src2, 6, src3, 6, + in0_r, in1_r, in2_r, in3_r); + DUP4_ARG2(__lsx_vslli_h, in0_l, 6, in1_l, 6, in2_l, 6, in3_l, 6, in0_l, + in1_l, in2_l, in3_l); + DUP2_ARG2(__lsx_vsllwil_hu_bu, src4, 6, src5, 6, in4_r, in5_r); + DUP2_ARG2(__lsx_vslli_h, in4_l, 6, in5_l, 6, in4_l, in5_l); + __lsx_vst(in0_r, dst, 0); + __lsx_vst(in0_l, dst, 16); + __lsx_vst(in1_r, dst, 32); + __lsx_vst(in1_l, dst, 48); + __lsx_vst(in2_r, dst, 64); + __lsx_vst(in2_l, dst, 80); + dst += dst_stride; + __lsx_vst(in3_r, dst, 0); + __lsx_vst(in3_l, dst, 16); + __lsx_vst(in4_r, dst, 32); + __lsx_vst(in4_l, dst, 48); + __lsx_vst(in5_r, dst, 64); + __lsx_vst(in5_l, dst, 80); + dst += dst_stride; + + DUP4_ARG2(__lsx_vilvh_b, zero, src6, zero, src7, zero, src8, zero, src9, + in0_l, in1_l, in2_l, in3_l); + DUP2_ARG2(__lsx_vilvh_b, zero, src10, zero, src11, in4_l, in5_l); + DUP4_ARG2(__lsx_vsllwil_hu_bu, src6, 6, src7, 6, src8, 6, src9, 6, + in0_r, in1_r, in2_r, in3_r); + DUP4_ARG2(__lsx_vslli_h, in0_l, 6, in1_l, 6, in2_l, 6, in3_l, 6, in0_l, + in1_l, in2_l, in3_l); + DUP2_ARG2(__lsx_vsllwil_hu_bu, src10, 6, src11, 6, in4_r, in5_r); + DUP2_ARG2(__lsx_vslli_h, in4_l, 6, in5_l, 6, in4_l, in5_l); + __lsx_vst(in0_r, dst, 0); + __lsx_vst(in0_l, dst, 16); + __lsx_vst(in1_r, dst, 32); + __lsx_vst(in1_l, dst, 48); + __lsx_vst(in2_r, dst, 64); + __lsx_vst(in2_l, dst, 80); + dst += dst_stride; + __lsx_vst(in3_r, dst, 0); + __lsx_vst(in3_l, dst, 16); + __lsx_vst(in4_r, dst, 32); + __lsx_vst(in4_l, dst, 48); + __lsx_vst(in5_r, dst, 64); + __lsx_vst(in5_l, dst, 80); + dst += dst_stride; + } +} + +static void hevc_copy_64w_lsx(uint8_t *src, int32_t src_stride, + int16_t *dst, int32_t dst_stride, + int32_t height) +{ + uint32_t loop_cnt; + __m128i zero = {0}; + __m128i src0, src1, src2, src3, src4, src5, src6, src7; + __m128i in0_r, in1_r, in2_r, in3_r, in0_l, in1_l, in2_l, in3_l; + + + for (loop_cnt = (height >> 1); loop_cnt--;) { + DUP4_ARG2(__lsx_vld, src, 0, src, 16, src, 32, src, 48, + src0, src1, src2, src3); + src += src_stride; + DUP4_ARG2(__lsx_vld, src, 0, src, 16, src, 32, src, 48, + src4, src5, src6, src7); + src += src_stride; + + DUP4_ARG2(__lsx_vilvh_b, zero, src0, zero, src1, zero, src2, zero, + src3, in0_l, in1_l, in2_l, in3_l); + DUP4_ARG2(__lsx_vsllwil_hu_bu, src0, 6, src1, 6, src2, 6, src3, 6, + in0_r, in1_r, in2_r, in3_r); + DUP4_ARG2(__lsx_vslli_h, in0_l, 6, in1_l, 6, in2_l, 6, in3_l, 6, + in0_l, in1_l, in2_l, in3_l); + __lsx_vst(in0_r, dst, 0); + __lsx_vst(in0_l, dst, 16); + __lsx_vst(in1_r, dst, 32); + __lsx_vst(in1_l, dst, 48); + __lsx_vst(in2_r, dst, 64); + __lsx_vst(in2_l, dst, 80); + __lsx_vst(in3_r, dst, 96); + __lsx_vst(in3_l, dst, 112); + dst += dst_stride; + + DUP4_ARG2(__lsx_vilvh_b, zero, src4, zero, src5, zero, src6, zero, + src7, in0_l, in1_l, in2_l, in3_l); + DUP4_ARG2(__lsx_vsllwil_hu_bu, src4, 6, src5, 6, src6, 6, src7, 6, + in0_r, in1_r, in2_r, in3_r); + DUP4_ARG2(__lsx_vslli_h, in0_l, 6, in1_l, 6, in2_l, 6, in3_l, 6, in0_l, + in1_l, in2_l, in3_l); + __lsx_vst(in0_r, dst, 0); + __lsx_vst(in0_l, dst, 16); + __lsx_vst(in1_r, dst, 32); + __lsx_vst(in1_l, dst, 48); + __lsx_vst(in2_r, dst, 64); + __lsx_vst(in2_l, dst, 80); + __lsx_vst(in3_r, dst, 96); + __lsx_vst(in3_l, dst, 112); + dst += dst_stride; + } +} + +static void hevc_hz_8t_4w_lsx(uint8_t *src, int32_t src_stride, + int16_t *dst, int32_t dst_stride, + const int8_t *filter, int32_t height) +{ + uint32_t loop_cnt = height >> 3; + uint32_t res = (height & 0x7) >> 1; + int32_t src_stride_2x = (src_stride << 1); + int32_t dst_stride_2x = (dst_stride << 1); + int32_t src_stride_4x = (src_stride << 2); + int32_t dst_stride_4x = (dst_stride << 2); + int32_t src_stride_3x = src_stride_2x + src_stride; + int32_t dst_stride_3x = dst_stride_2x + dst_stride; + __m128i src0, src1, src2, src3, src4, src5, src6, src7; + __m128i filt0, filt1, filt2, filt3; + __m128i mask1, mask2, mask3; + __m128i vec0, vec1, vec2, vec3; + __m128i dst0, dst1, dst2, dst3; + __m128i mask0 = __lsx_vld(ff_hevc_mask_arr, 16); + + src -= 3; + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filt0, filt1, filt2, filt3); + + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + + for (;loop_cnt--;) { + src0 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src1, src2); + src3 = __lsx_vldx(src, src_stride_3x); + src += src_stride_4x; + src4 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src5, src6); + src7 = __lsx_vldx(src, src_stride_3x); + src += src_stride_4x; + DUP4_ARG3(__lsx_vshuf_b, src1, src0, mask0, src1, src0, mask1, src1, + src0, mask2, src1, src0, mask3, vec0, vec1, vec2, vec3); + dst0 = __lsx_vdp2_h_bu_b(vec0, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec1, filt1, dst0, vec2, filt2, + dst0, dst0); + dst0 = __lsx_vdp2add_h_bu_b(dst0, vec3, filt3); + DUP4_ARG3(__lsx_vshuf_b, src3, src2, mask0, src3, src2, mask1, src3, + src2, mask2, src3, src2, mask3, vec0, vec1, vec2, vec3); + dst1 = __lsx_vdp2_h_bu_b(vec0, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst1, vec1, filt1, dst1, vec2, filt2, + dst1, dst1); + dst1 = __lsx_vdp2add_h_bu_b(dst1, vec3, filt3); + DUP4_ARG3(__lsx_vshuf_b, src5, src4, mask0, src5, src4, mask1, src5, + src4, mask2, src5, src4, mask3, vec0, vec1, vec2, vec3); + dst2 = __lsx_vdp2_h_bu_b(vec0, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst2, vec1, filt1, dst2, vec2, filt2, + dst2, dst2); + dst2 = __lsx_vdp2add_h_bu_b(dst2, vec3, filt3); + DUP4_ARG3(__lsx_vshuf_b, src7, src6, mask0, src7, src6, mask1, src7, + src6, mask2, src7, src6, mask3, vec0, vec1, vec2, vec3); + dst3 = __lsx_vdp2_h_bu_b(vec0, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst3, vec1, filt1, dst3, vec2, filt2, + dst3, dst3); + dst3 = __lsx_vdp2add_h_bu_b(dst3, vec3, filt3); + + __lsx_vstelm_d(dst0, dst, 0, 0); + __lsx_vstelm_d(dst0, dst + dst_stride, 0, 1); + __lsx_vstelm_d(dst1, dst + dst_stride_2x, 0, 0); + __lsx_vstelm_d(dst1, dst + dst_stride_3x, 0, 1); + dst += dst_stride_4x; + __lsx_vstelm_d(dst2, dst, 0, 0); + __lsx_vstelm_d(dst2, dst + dst_stride, 0, 1); + __lsx_vstelm_d(dst3, dst + dst_stride_2x, 0, 0); + __lsx_vstelm_d(dst3, dst + dst_stride_3x, 0, 1); + dst += dst_stride_4x; + } + for (;res--;) { + src0 = __lsx_vld(src, 0); + src1 = __lsx_vldx(src, src_stride); + DUP4_ARG3(__lsx_vshuf_b, src1, src0, mask0, src1, src0, mask1, src1, + src0, mask2, src1, src0, mask3, vec0, vec1, vec2, vec3); + dst0 = __lsx_vdp2_h_bu_b(vec0, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec1, filt1, dst0, vec2, filt2, + dst0, dst0); + dst0 = __lsx_vdp2add_h_bu_b(dst0, vec3, filt3); + __lsx_vstelm_d(dst0, dst, 0, 0); + __lsx_vstelm_d(dst0, dst + dst_stride, 0, 1); + src += src_stride_2x; + dst += dst_stride_2x; + } +} + +static void hevc_hz_8t_8w_lsx(uint8_t *src, int32_t src_stride, + int16_t *dst, int32_t dst_stride, + const int8_t *filter, int32_t height) +{ + uint32_t loop_cnt; + int32_t src_stride_2x = (src_stride << 1); + int32_t dst_stride_x = (dst_stride << 1); + int32_t src_stride_4x = (src_stride << 2); + int32_t dst_stride_2x = (dst_stride << 2); + int32_t src_stride_3x = src_stride_2x + src_stride; + int32_t dst_stride_3x = dst_stride_2x + dst_stride_x; + __m128i src0, src1, src2, src3; + __m128i filt0, filt1, filt2, filt3; + __m128i mask1, mask2, mask3; + __m128i vec0, vec1, vec2, vec3; + __m128i dst0, dst1, dst2, dst3; + __m128i mask0 = __lsx_vld(ff_hevc_mask_arr, 0); + + src -= 3; + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filt0, filt1, filt2, filt3); + + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + + for (loop_cnt = (height >> 2); loop_cnt--;) { + src0 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src1, src2); + src3 = __lsx_vldx(src, src_stride_3x); + src += src_stride_4x; + + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask0, src0, src0, mask1, src0, + src0, mask2, src0, src0, mask3, vec0, vec1, vec2, vec3); + dst0 = __lsx_vdp2_h_bu_b(vec0, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec1, filt1, dst0, vec2, filt2, + dst0, dst0); + dst0 = __lsx_vdp2add_h_bu_b(dst0, vec3, filt3); + DUP4_ARG3(__lsx_vshuf_b, src1, src1, mask0, src1, src1, mask1, src1, + src1, mask2, src1, src1, mask3, vec0, vec1, vec2, vec3); + dst1 = __lsx_vdp2_h_bu_b(vec0, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst1, vec1, filt1, dst1, vec2, filt2, + dst1, dst1); + dst1 = __lsx_vdp2add_h_bu_b(dst1, vec3, filt3); + DUP4_ARG3(__lsx_vshuf_b, src2, src2, mask0, src2, src2, mask1, src2, + src2, mask2, src2, src2, mask3, vec0, vec1, vec2, vec3); + dst2 = __lsx_vdp2_h_bu_b(vec0, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst2, vec1, filt1, dst2, vec2, filt2, + dst2, dst2); + dst2 = __lsx_vdp2add_h_bu_b(dst2, vec3, filt3); + DUP4_ARG3(__lsx_vshuf_b, src3, src3, mask0, src3, src3, mask1, src3, + src3, mask2, src3, src3, mask3, vec0, vec1, vec2, vec3); + dst3 = __lsx_vdp2_h_bu_b(vec0, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst3, vec1, filt1, dst3, vec2, filt2, + dst3, dst3); + dst3 = __lsx_vdp2add_h_bu_b(dst3, vec3, filt3); + + __lsx_vst(dst0, dst, 0); + __lsx_vstx(dst1, dst, dst_stride_x); + __lsx_vstx(dst2, dst, dst_stride_2x); + __lsx_vstx(dst3, dst, dst_stride_3x); + dst += dst_stride_2x; + } +} + +static void hevc_hz_8t_12w_lsx(uint8_t *src, int32_t src_stride, + int16_t *dst, int32_t dst_stride, + const int8_t *filter, int32_t height) +{ + uint32_t loop_cnt; + int32_t src_stride_2x = (src_stride << 1); + int32_t src_stride_4x = (src_stride << 2); + int32_t src_stride_3x = src_stride_2x + src_stride; + uint8_t *_src; + __m128i src0, src1, src2, src3, src4, src5, src6, src7; + __m128i mask0, mask1, mask2, mask3, mask4, mask5, mask6, mask7; + __m128i vec0, vec1, vec2, vec3, vec4, vec5; + __m128i filt0, filt1, filt2, filt3, dst0, dst1, dst2, dst3, dst4, dst5; + + src -= 3; + _src = src + 8; + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filt0, filt1, filt2, filt3); + + mask0 = __lsx_vld(ff_hevc_mask_arr, 0); + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + mask4 = __lsx_vld(ff_hevc_mask_arr, 16); + DUP2_ARG2(__lsx_vaddi_bu, mask4, 2, mask4, 4, mask5, mask6); + mask7 = __lsx_vaddi_bu(mask4, 6); + + for (loop_cnt = 4; loop_cnt--;) { + src0 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src1, src2); + src3 = __lsx_vldx(src, src_stride_3x); + src4 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride_2x, + src5, src6); + src7 = __lsx_vldx(_src, src_stride_3x); + src += src_stride_4x; + _src += src_stride_4x; + + DUP2_ARG3(__lsx_vshuf_b, src0, src0, mask0, src1, src1, mask0, + vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src2, src2, mask0, src3, src3, mask0, + vec2, vec3); + DUP2_ARG3(__lsx_vshuf_b, src5, src4, mask4, src7, src6, mask4, + vec4, vec5); + DUP4_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec1, filt0, vec2, filt0, + vec3, filt0, dst0, dst1, dst2, dst3); + DUP2_ARG2(__lsx_vdp2_h_bu_b, vec4, filt0, vec5, filt0, dst4, dst5); + DUP2_ARG3(__lsx_vshuf_b, src0, src0, mask1, src1, src1, mask1, + vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src2, src2, mask1, src3, src3, mask1, + vec2, vec3); + DUP2_ARG3(__lsx_vshuf_b, src5, src4, mask5, src7, src6, mask5, + vec4, vec5); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec0, filt1, dst1, vec1, filt1, + dst2, vec2, filt1, dst3, vec3, filt1, dst0, dst1, dst2, dst3); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst4, vec4, filt1, dst5, vec5, filt1, + dst4, dst5); + DUP2_ARG3(__lsx_vshuf_b, src0, src0, mask2, src1, src1, mask2, + vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src2, src2, mask2, src3, src3, mask2, + vec2, vec3); + DUP2_ARG3(__lsx_vshuf_b, src5, src4, mask6, src7, src6, mask6, + vec4, vec5); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec0, filt2, dst1, vec1, filt2, + dst2, vec2, filt2, dst3, vec3, filt2, dst0, dst1, dst2, dst3); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst4, vec4, filt2, dst5, vec5, filt2, + dst4, dst5); + DUP2_ARG3(__lsx_vshuf_b, src0, src0, mask3, src1, src1, mask3, + vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src2, src2, mask3, src3, src3, mask3, + vec2, vec3); + DUP2_ARG3(__lsx_vshuf_b, src5, src4, mask7, src7, src6, mask7, + vec4, vec5); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec0, filt3, dst1, vec1, filt3, + dst2, vec2, filt3, dst3, vec3, filt3, dst0, dst1, dst2, dst3); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst4, vec4, filt3, dst5, vec5, filt3, + dst4, dst5); + + __lsx_vst(dst0, dst, 0); + __lsx_vstelm_d(dst4, dst, 16, 0); + dst += dst_stride; + __lsx_vst(dst1, dst, 0); + __lsx_vstelm_d(dst4, dst, 16, 1); + dst += dst_stride; + __lsx_vst(dst2, dst, 0); + __lsx_vstelm_d(dst5, dst, 16, 0); + dst += dst_stride; + __lsx_vst(dst3, dst, 0); + __lsx_vstelm_d(dst5, dst, 16, 1); + dst += dst_stride; + } +} + +static void hevc_hz_8t_16w_lsx(uint8_t *src, int32_t src_stride, + int16_t *dst, int32_t dst_stride, + const int8_t *filter, int32_t height) +{ + uint32_t loop_cnt; + __m128i src0, src1, src2, src3; + __m128i filt0, filt1, filt2, filt3; + __m128i mask1, mask2, mask3; + __m128i vec0, vec1, vec2, vec3; + __m128i dst0, dst1, dst2, dst3; + __m128i mask0; + + src -= 3; + mask0 = __lsx_vld(ff_hevc_mask_arr, 0); + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filt0, filt1, filt2, filt3); + + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + + for (loop_cnt = (height >> 1); loop_cnt--;) { + DUP2_ARG2(__lsx_vld, src, 0, src, 8, src0, src1); + src += src_stride; + DUP2_ARG2(__lsx_vld, src, 0, src, 8, src2, src3); + src += src_stride; + + DUP2_ARG3(__lsx_vshuf_b, src0, src0, mask0, src1, src1, mask0, + vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src2, src2, mask0, src3, src3, mask0, + vec2, vec3); + DUP4_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec1, filt0, vec2, filt0, + vec3, filt0, dst0, dst1, dst2, dst3); + DUP2_ARG3(__lsx_vshuf_b, src0, src0, mask1, src1, src1, mask1, + vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src2, src2, mask1, src3, src3, mask1, + vec2, vec3); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec0, filt1, dst1, vec1, filt1, + dst2, vec2, filt1, dst3, vec3, filt1, dst0, dst1, dst2, dst3); + DUP2_ARG3(__lsx_vshuf_b, src0, src0, mask2, src1, src1, mask2, + vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src2, src2, mask2, src3, src3, mask2, + vec2, vec3); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec0, filt2, dst1, vec1, filt2, + dst2, vec2, filt2, dst3, vec3, filt2, dst0, dst1, dst2, dst3); + DUP2_ARG3(__lsx_vshuf_b, src0, src0, mask3, src1, src1, mask3, + vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src2, src2, mask3, src3, src3, mask3, + vec2, vec3); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec0, filt3, dst1, vec1, filt3, + dst2, vec2, filt3, dst3, vec3, filt3, dst0, dst1, dst2, dst3); + + __lsx_vst(dst0, dst, 0); + __lsx_vst(dst1, dst, 16); + dst += dst_stride; + __lsx_vst(dst2, dst, 0); + __lsx_vst(dst3, dst, 16); + dst += dst_stride; + } +} + +static void hevc_hz_8t_24w_lsx(uint8_t *src, int32_t src_stride, + int16_t *dst, int32_t dst_stride, + const int8_t *filter, int32_t height) +{ + uint32_t loop_cnt; + __m128i src0, src1, src2, src3; + __m128i filt0, filt1, filt2, filt3; + __m128i mask1, mask2, mask3, mask4, mask5, mask6, mask7; + __m128i vec0, vec1, vec2, vec3, vec4, vec5; + __m128i dst0, dst1, dst2, dst3, dst4, dst5; + __m128i mask0 = __lsx_vld(ff_hevc_mask_arr, 0); + + src -= 3; + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filt0, filt1, filt2, filt3); + + DUP4_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask0, 6, mask0, 8, mask1, + mask2, mask3, mask4); + DUP2_ARG2(__lsx_vaddi_bu, mask0, 10, mask0, 12, mask5, mask6); + mask7 = __lsx_vaddi_bu(mask0, 14); + + for (loop_cnt = (height >> 1); loop_cnt--;) { + DUP2_ARG2(__lsx_vld, src, 0, src, 16, src0, src1); + src += src_stride; + DUP2_ARG2(__lsx_vld, src, 0, src, 16, src2, src3); + src += src_stride; + + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask0, src1, src0, mask4, src1, + src1, mask0, src2, src2, mask0, vec0, vec1, vec2, vec3); + DUP2_ARG3(__lsx_vshuf_b, src3, src2, mask4, src3, src3, mask0, + vec4, vec5); + DUP4_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec1, filt0, vec2, filt0, + vec3, filt0, dst0, dst1, dst2, dst3); + DUP2_ARG2(__lsx_vdp2_h_bu_b, vec4, filt0, vec5, filt0, dst4, dst5); + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask1, src1, src0, mask5, src1, + src1, mask1, src2, src2, mask1, vec0, vec1, vec2, vec3); + DUP2_ARG3(__lsx_vshuf_b, src3, src2, mask5, src3, src3, mask1, + vec4, vec5); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec0, filt1, dst1, vec1, filt1, + dst2, vec2, filt1, dst3, vec3, filt1, dst0, dst1, dst2, dst3); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst4, vec4, filt1, dst5, vec5, filt1, + dst4, dst5); + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask2, src1, src0, mask6, src1, + src1, mask2, src2, src2, mask2, vec0, vec1, vec2, vec3); + DUP2_ARG3(__lsx_vshuf_b, src3, src2, mask6, src3, src3, mask2, + vec4, vec5); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec0, filt2, dst1, vec1, filt2, + dst2, vec2, filt2, dst3, vec3, filt2, dst0, dst1, dst2, dst3); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst4, vec4, filt2, dst5, vec5, filt2, + dst4, dst5); + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask3, src1, src0, mask7, src1, + src1, mask3, src2, src2, mask3, vec0, vec1, vec2, vec3); + DUP2_ARG3(__lsx_vshuf_b, src3, src2, mask7, src3, src3, mask3, + vec4, vec5); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec0, filt3, dst1, vec1, filt3, + dst2, vec2, filt3, dst3, vec3, filt3, dst0, dst1, dst2, dst3); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst4, vec4, filt3, dst5, vec5, filt3, + dst4, dst5); + + __lsx_vst(dst0, dst, 0); + __lsx_vst(dst1, dst, 16); + __lsx_vst(dst2, dst, 32); + dst += dst_stride; + __lsx_vst(dst3, dst, 0); + __lsx_vst(dst4, dst, 16); + __lsx_vst(dst5, dst, 32); + dst += dst_stride; + } +} + +static void hevc_hz_8t_32w_lsx(uint8_t *src, int32_t src_stride, + int16_t *dst, int32_t dst_stride, + const int8_t *filter, int32_t height) +{ + uint32_t loop_cnt; + __m128i src0, src1, src2; + __m128i filt0, filt1, filt2, filt3; + __m128i mask1, mask2, mask3, mask4, mask5, mask6, mask7; + __m128i vec0, vec1, vec2, vec3; + __m128i dst0, dst1, dst2, dst3; + __m128i mask0 = __lsx_vld(ff_hevc_mask_arr, 0); + + src -= 3; + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filt0, filt1, filt2, filt3); + + DUP4_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask0, 6, mask0, 8, + mask1, mask2, mask3, mask4); + DUP2_ARG2(__lsx_vaddi_bu, mask0, 10, mask0, 12, mask5, mask6); + mask7 = __lsx_vaddi_bu(mask0, 14); + + for (loop_cnt = height; loop_cnt--;) { + DUP2_ARG2(__lsx_vld, src, 0, src, 16, src0, src1); + src2 = __lsx_vld(src, 24); + src += src_stride; + + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask0, src0, src0, mask1, src0, + src0, mask2, src0, src0, mask3, vec0, vec1, vec2, vec3); + dst0 = __lsx_vdp2_h_bu_b(vec0, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec1, filt1, dst0, vec2, filt2, + dst0, dst0); + dst0 = __lsx_vdp2add_h_bu_b(dst0, vec3, filt3); + + DUP4_ARG3(__lsx_vshuf_b, src1, src0, mask4, src1, src0, mask5, src1, + src0, mask6, src1, src0, mask7, vec0, vec1, vec2, vec3); + dst1 = __lsx_vdp2_h_bu_b(vec0, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst1, vec1, filt1, dst1, vec2, filt2, + dst1, dst1); + dst1 = __lsx_vdp2add_h_bu_b(dst1, vec3, filt3); + DUP4_ARG3(__lsx_vshuf_b, src1, src1, mask0, src1, src1, mask1, src1, src1, + mask2, src1, src1, mask3, vec0, vec1, vec2, vec3); + dst2 = __lsx_vdp2_h_bu_b(vec0, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst2, vec1, filt1, dst2, vec2, filt2, + dst2, dst2); + dst2 = __lsx_vdp2add_h_bu_b(dst2, vec3, filt3); + DUP4_ARG3(__lsx_vshuf_b, src2, src2, mask0, src2, src2, mask1, src2, src2, + mask2, src2, src2, mask3, vec0, vec1, vec2, vec3); + dst3 = __lsx_vdp2_h_bu_b(vec0, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst3, vec1, filt1, dst3, vec2, filt2, + dst3, dst3); + dst3 = __lsx_vdp2add_h_bu_b(dst3, vec3, filt3); + + __lsx_vst(dst0, dst, 0); + __lsx_vst(dst1, dst, 16); + __lsx_vst(dst2, dst, 32); + __lsx_vst(dst3, dst, 48); + dst += dst_stride; + } +} + +static void hevc_hz_8t_48w_lsx(uint8_t *src, int32_t src_stride, + int16_t *dst, int32_t dst_stride, + const int8_t *filter, int32_t height) +{ + uint32_t loop_cnt; + __m128i src0, src1, src2, src3; + __m128i filt0, filt1, filt2, filt3; + __m128i mask1, mask2, mask3, mask4, mask5, mask6, mask7; + __m128i vec0, vec1, vec2, vec3, vec4, vec5; + __m128i dst0, dst1, dst2, dst3, dst4, dst5; + __m128i mask0 = __lsx_vld(ff_hevc_mask_arr, 0); + + src -= 3; + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filt0, filt1, filt2, filt3); + + DUP4_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask0, 6, mask0, 8, mask1, + mask2, mask3, mask4); + DUP2_ARG2(__lsx_vaddi_bu, mask0, 10, mask0, 12, mask5, mask6); + mask7 = __lsx_vaddi_bu(mask0, 14); + + for (loop_cnt = height; loop_cnt--;) { + DUP2_ARG2(__lsx_vld, src, 0, src, 16, src0, src1); + src2 = __lsx_vld(src, 32); + src3 = __lsx_vld(src, 40); + src += src_stride; + + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask0, src1, src0, mask4, src1, src1, + mask0, src2, src1, mask4, vec0, vec1, vec2, vec3); + DUP4_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec1, filt0, vec2, filt0, + vec3, filt0, dst0, dst1, dst2, dst3); + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask1, src1, src0, mask5, src1, + src1, mask1, src2, src1, mask5, vec0, vec1, vec2, vec3); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec0, filt1, dst1, vec1, filt1, + dst2, vec2, filt1, dst3, vec3, filt1, dst0, dst1, dst2, dst3); + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask2, src1, src0, mask6, src1, + src1, mask2, src2, src1, mask6, vec0, vec1, vec2, vec3); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec0, filt2, dst1, vec1, filt2, + dst2, vec2, filt2, dst3, vec3, filt2, dst0, dst1, dst2, dst3); + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask3, src1, src0, mask7, src1, + src1, mask3, src2, src1, mask7, vec0, vec1, vec2, vec3); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec0, filt3, dst1, vec1, filt3, + dst2, vec2, filt3, dst3, vec3, filt3, dst0, dst1, dst2, dst3); + __lsx_vst(dst0, dst, 0); + __lsx_vst(dst1, dst, 16); + __lsx_vst(dst2, dst, 32); + __lsx_vst(dst3, dst, 48); + + DUP2_ARG3(__lsx_vshuf_b, src2, src2, mask0, src3, src3, mask0, + vec4, vec5); + DUP2_ARG2(__lsx_vdp2_h_bu_b, vec4, filt0, vec5, filt0, dst4, dst5); + DUP2_ARG3(__lsx_vshuf_b, src2, src2, mask1, src3, src3, mask1, + vec4, vec5); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst4, vec4, filt1, dst5, vec5, filt1, + dst4, dst5); + DUP2_ARG3(__lsx_vshuf_b, src2, src2, mask2, src3, src3, mask2, + vec4, vec5); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst4, vec4, filt2, dst5, vec5, filt2, + dst4, dst5); + DUP2_ARG3(__lsx_vshuf_b, src2, src2, mask3, src3, src3, mask3, + vec4, vec5); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst4, vec4, filt3, dst5, vec5, filt3, + dst4, dst5); + __lsx_vst(dst4, dst, 64); + __lsx_vst(dst5, dst, 80); + dst += dst_stride; + } +} + +static void hevc_hz_8t_64w_lsx(uint8_t *src, int32_t src_stride, + int16_t *dst, int32_t dst_stride, + const int8_t *filter, int32_t height) +{ + uint32_t loop_cnt; + __m128i src0, src1, src2, src3, src4; + __m128i filt0, filt1, filt2, filt3; + __m128i mask1, mask2, mask3, mask4, mask5, mask6, mask7; + __m128i vec0, vec1, vec2, vec3; + __m128i dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + __m128i mask0 = __lsx_vld(ff_hevc_mask_arr, 0); + + src -= 3; + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filt0, filt1, filt2, filt3); + + DUP4_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask0, 6, mask0, 8, mask1, + mask2, mask3, mask4); + DUP2_ARG2(__lsx_vaddi_bu, mask0, 10, mask0, 12, mask5, mask6) + mask7 = __lsx_vaddi_bu(mask0, 14); + + for (loop_cnt = height; loop_cnt--;) { + DUP4_ARG2(__lsx_vld, src, 0, src, 16, src, 32, src, 48, + src0, src1, src2, src3); + src4 = __lsx_vld(src, 56); + src += src_stride; + + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask0, src0, src0, mask1, src0, + src0, mask2, src0, src0, mask3, vec0, vec1, vec2, vec3); + dst0 = __lsx_vdp2_h_bu_b(vec0, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec1, filt1, dst0, vec2, filt2, + dst0, dst0); + dst0 = __lsx_vdp2add_h_bu_b(dst0, vec3, filt3); + __lsx_vst(dst0, dst, 0); + + DUP4_ARG3(__lsx_vshuf_b, src1, src0, mask4, src1, src0, mask5, src1, + src0, mask6, src1, src0, mask7, vec0, vec1, vec2, vec3); + dst1 = __lsx_vdp2_h_bu_b(vec0, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst1, vec1, filt1, dst1, vec2, filt2, + dst1, dst1); + dst1 = __lsx_vdp2add_h_bu_b(dst1, vec3, filt3); + __lsx_vst(dst1, dst, 16); + + DUP4_ARG3(__lsx_vshuf_b, src1, src1, mask0, src1, src1, mask1, src1, + src1, mask2, src1, src1, mask3, vec0, vec1, vec2, vec3); + dst2 = __lsx_vdp2_h_bu_b(vec0, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst2, vec1, filt1, dst2, vec2, filt2, + dst2, dst2); + dst2 = __lsx_vdp2add_h_bu_b(dst2, vec3, filt3); + __lsx_vst(dst2, dst, 32); + + DUP4_ARG3(__lsx_vshuf_b, src2, src1, mask4, src2, src1, mask5, src2, + src1, mask6, src2, src1, mask7, vec0, vec1, vec2, vec3); + dst3 = __lsx_vdp2_h_bu_b(vec0, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst3, vec1, filt1, dst3, vec2, filt2, + dst3, dst3); + dst3 = __lsx_vdp2add_h_bu_b(dst3, vec3, filt3); + __lsx_vst(dst3, dst, 48); + + DUP4_ARG3(__lsx_vshuf_b, src2, src2, mask0, src2, src2, mask1, src2, + src2, mask2, src2, src2, mask3, vec0, vec1, vec2, vec3); + dst4 = __lsx_vdp2_h_bu_b(vec0, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst4, vec1, filt1, dst4, vec2, filt2, + dst4, dst4); + dst4 = __lsx_vdp2add_h_bu_b(dst4, vec3, filt3); + __lsx_vst(dst4, dst, 64); + + DUP4_ARG3(__lsx_vshuf_b, src3, src2, mask4, src3, src2, mask5, src3, + src2, mask6, src3, src2, mask7, vec0, vec1, vec2, vec3); + dst5 = __lsx_vdp2_h_bu_b(vec0, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst5, vec1, filt1, dst5, vec2, filt2, + dst5, dst5); + dst5 = __lsx_vdp2add_h_bu_b(dst5, vec3, filt3); + __lsx_vst(dst5, dst, 80); + + DUP4_ARG3(__lsx_vshuf_b, src3, src3, mask0, src3, src3, mask1, src3, + src3, mask2, src3, src3, mask3, vec0, vec1, vec2, vec3); + dst6 = __lsx_vdp2_h_bu_b(vec0, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst6, vec1, filt1, dst6, vec2, filt2, + dst6, dst6); + dst6 = __lsx_vdp2add_h_bu_b(dst6, vec3, filt3); + __lsx_vst(dst6, dst, 96); + + DUP4_ARG3(__lsx_vshuf_b, src4, src4, mask0, src4, src4, mask1, src4, + src4, mask2, src4, src4, mask3, vec0, vec1, vec2, vec3); + dst7 = __lsx_vdp2_h_bu_b(vec0, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst7, vec1, filt1, dst7, vec2, filt2, + dst7, dst7); + dst7 = __lsx_vdp2add_h_bu_b(dst7, vec3, filt3); + __lsx_vst(dst7, dst, 112); + dst += dst_stride; + } +} + +static void hevc_vt_8t_4w_lsx(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; + int32_t res = (height & 0x07) >> 1; + int32_t src_stride_2x = (src_stride << 1); + int32_t src_stride_4x = (src_stride << 2); + int32_t src_stride_3x = src_stride_2x + src_stride; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8; + __m128i src9, src10, src11, src12, src13, src14; + __m128i src10_r, src32_r, src54_r, src76_r, src98_r; + __m128i src21_r, src43_r, src65_r, src87_r, src109_r; + __m128i src1110_r, src1211_r, src1312_r, src1413_r; + __m128i src2110, src4332, src6554, src8776, src10998; + __m128i src12111110, src14131312; + __m128i dst10, dst32, dst54, dst76; + __m128i filt0, filt1, filt2, filt3; + + src -= src_stride_3x; + + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filt0, filt1, filt2, filt3); + + src0 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src1, src2); + src3 = __lsx_vldx(src, src_stride_3x); + src += src_stride_4x; + src4 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src5, src6); + src += src_stride_3x; + DUP4_ARG2(__lsx_vilvl_b, src1, src0, src3, src2, src5, src4, src2, src1, + src10_r, src32_r, src54_r, src21_r); + DUP2_ARG2(__lsx_vilvl_b, src4, src3, src6, src5, src43_r, src65_r); + DUP2_ARG2(__lsx_vilvl_d, src21_r, src10_r, src43_r, src32_r, + src2110, src4332); + src6554 = __lsx_vilvl_d(src65_r, src54_r); + + for (loop_cnt = (height >> 3); loop_cnt--;) { + src7 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src8, src9); + src10 = __lsx_vldx(src, src_stride_3x); + src += src_stride_4x; + src11 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, + src12, src13); + src14 = __lsx_vldx(src, src_stride_3x); + src += src_stride_4x; + + DUP4_ARG2(__lsx_vilvl_b, src7, src6, src8, src7, src9, src8, src10, src9, + src76_r, src87_r, src98_r, src109_r); + DUP4_ARG2(__lsx_vilvl_b, src11, src10, src12, src11, src13, src12, src14, + src13, src1110_r, src1211_r, src1312_r, src1413_r); + DUP4_ARG2(__lsx_vilvl_d, src87_r, src76_r, src109_r, src98_r, src1211_r, + src1110_r, src1413_r, src1312_r, src8776, src10998, + src12111110, src14131312); + + dst10 = __lsx_vdp2_h_bu_b(src2110, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst10, src4332, filt1, dst10, src6554, + filt2, dst10, dst10); + dst10 = __lsx_vdp2add_h_bu_b(dst10, src8776, filt3); + dst32 = __lsx_vdp2_h_bu_b(src4332, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst32, src6554, filt1, dst32, src8776, + filt2, dst32, dst32); + dst32 = __lsx_vdp2add_h_bu_b(dst32, src10998, filt3); + dst54 = __lsx_vdp2_h_bu_b(src6554, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst54, src8776, filt1, + dst54, src10998, filt2, dst54, dst54); + dst54 = __lsx_vdp2add_h_bu_b(dst54, src12111110, filt3); + dst76 = __lsx_vdp2_h_bu_b(src8776, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst76, src10998, filt1, dst76, + src12111110, filt2, dst76, dst76); + dst76 = __lsx_vdp2add_h_bu_b(dst76, src14131312, filt3); + + __lsx_vstelm_d(dst10, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(dst10, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(dst32, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(dst32, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(dst54, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(dst54, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(dst76, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(dst76, dst, 0, 1); + dst += dst_stride; + + src2110 = src10998; + src4332 = src12111110; + src6554 = src14131312; + src6 = src14; + } + for (;res--;) { + src7 = __lsx_vld(src, 0); + src8 = __lsx_vldx(src, src_stride); + DUP2_ARG2(__lsx_vilvl_b, src7, src6, src8, src7, src76_r, src87_r); + src += src_stride_2x; + src8776 = __lsx_vilvl_d(src87_r, src76_r); + + dst10 = __lsx_vdp2_h_bu_b(src2110, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst10, src4332, filt1, dst10, src6554, + filt2, dst10, dst10); + dst10 = __lsx_vdp2add_h_bu_b(dst10, src8776, filt3); + + __lsx_vstelm_d(dst10, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(dst10, dst, 0, 1); + dst += dst_stride; + + src2110 = src4332; + src4332 = src6554; + src6554 = src8776; + src6 = src8; + } +} + +static void hevc_vt_8t_8w_lsx(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; + int32_t src_stride_2x = (src_stride << 1); + int32_t dst_stride_x = (dst_stride << 1); + int32_t src_stride_4x = (src_stride << 2); + int32_t dst_stride_2x = (dst_stride << 2); + int32_t src_stride_3x = src_stride_2x + src_stride; + int32_t dst_stride_3x = dst_stride_2x + dst_stride_x; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + __m128i src10_r, src32_r, src54_r, src76_r, src98_r; + __m128i src21_r, src43_r, src65_r, src87_r, src109_r; + __m128i dst0_r, dst1_r, dst2_r, dst3_r; + __m128i filt0, filt1, filt2, filt3; + + src -= src_stride_3x; + + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filt0, filt1, filt2, filt3); + + src0 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src1, src2); + src3 = __lsx_vldx(src, src_stride_3x); + src += src_stride_4x; + src4 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src5, src6); + src += src_stride_3x; + DUP4_ARG2(__lsx_vilvl_b, src1, src0, src3, src2, src5, src4, src2, src1, + src10_r, src32_r, src54_r, src21_r); + DUP2_ARG2(__lsx_vilvl_b, src4, src3, src6, src5, src43_r, src65_r); + + for (loop_cnt = (height >> 2); loop_cnt--;) { + src7 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src8, src9); + src10 = __lsx_vldx(src, src_stride_3x); + src += src_stride_4x; + DUP4_ARG2(__lsx_vilvl_b, src7, src6, src8, src7, src9, src8, src10, + src9, src76_r, src87_r, src98_r, src109_r); + + dst0_r = __lsx_vdp2_h_bu_b(src10_r, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst0_r, src32_r, filt1, dst0_r, + src54_r, filt2, dst0_r, dst0_r); + dst0_r = __lsx_vdp2add_h_bu_b(dst0_r, src76_r, filt3); + dst1_r = __lsx_vdp2_h_bu_b(src21_r, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst1_r, src43_r, filt1, dst1_r, + src65_r, filt2, dst1_r, dst1_r); + dst1_r = __lsx_vdp2add_h_bu_b(dst1_r, src87_r, filt3); + dst2_r = __lsx_vdp2_h_bu_b(src32_r, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst2_r, src54_r, filt1, dst2_r, + src76_r, filt2, dst2_r, dst2_r); + dst2_r = __lsx_vdp2add_h_bu_b(dst2_r, src98_r, filt3); + dst3_r = __lsx_vdp2_h_bu_b(src43_r, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst3_r, src65_r, filt1, dst3_r, + src87_r, filt2, dst3_r, dst3_r); + dst3_r = __lsx_vdp2add_h_bu_b(dst3_r, src109_r, filt3); + + __lsx_vst(dst0_r, dst, 0); + __lsx_vstx(dst1_r, dst, dst_stride_x); + __lsx_vstx(dst2_r, dst, dst_stride_2x); + __lsx_vstx(dst3_r, dst, dst_stride_3x); + dst += dst_stride_2x; + + src10_r = src54_r; + src32_r = src76_r; + src54_r = src98_r; + src21_r = src65_r; + src43_r = src87_r; + src65_r = src109_r; + src6 = src10; + } +} + +static void hevc_vt_8t_12w_lsx(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; + int32_t src_stride_2x = (src_stride << 1); + int32_t src_stride_4x = (src_stride << 2); + int32_t src_stride_3x = src_stride_2x + src_stride; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + __m128i src10_r, src32_r, src54_r, src76_r, src98_r; + __m128i src21_r, src43_r, src65_r, src87_r, src109_r; + __m128i dst0_r, dst1_r, dst2_r, dst3_r; + __m128i src10_l, src32_l, src54_l, src76_l, src98_l; + __m128i src21_l, src43_l, src65_l, src87_l, src109_l; + __m128i src2110, src4332, src6554, src8776, src10998; + __m128i dst0_l, dst1_l; + __m128i filt0, filt1, filt2, filt3; + + src -= src_stride_3x; + + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filt0, filt1, filt2, filt3); + src0 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src1, src2); + src3 = __lsx_vldx(src, src_stride_3x); + src += src_stride_4x; + src4 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src5, src6); + src += src_stride_3x; + DUP4_ARG2(__lsx_vilvl_b, src1, src0, src3, src2, src5, src4, src2, src1, + src10_r, src32_r, src54_r, src21_r); + DUP2_ARG2(__lsx_vilvl_b, src4, src3, src6, src5, src43_r, src65_r); + DUP4_ARG2(__lsx_vilvh_b, src1, src0, src3, src2, src5, src4, src2, src1, + src10_l, src32_l, src54_l, src21_l); + DUP2_ARG2(__lsx_vilvh_b, src4, src3, src6, src5, src43_l, src65_l); + DUP2_ARG2(__lsx_vilvl_d, src21_l, src10_l, src43_l, src32_l, + src2110, src4332); + src6554 = __lsx_vilvl_d(src65_l, src54_l); + + for (loop_cnt = (height >> 2); loop_cnt--;) { + src7 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src8, src9); + src10 = __lsx_vldx(src, src_stride_3x); + src += src_stride_4x; + DUP4_ARG2(__lsx_vilvl_b, src7, src6, src8, src7, src9, src8, src10, + src9, src76_r, src87_r, src98_r, src109_r); + DUP4_ARG2(__lsx_vilvh_b, src7, src6, src8, src7, src9, src8, src10, + src9, src76_l, src87_l, src98_l, src109_l); + DUP2_ARG2(__lsx_vilvl_d, src87_l, src76_l, src109_l, src98_l, + src8776, src10998); + + dst0_r = __lsx_vdp2_h_bu_b(src10_r, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst0_r, src32_r, filt1, dst0_r, + src54_r, filt2, dst0_r, dst0_r); + dst0_r = __lsx_vdp2add_h_bu_b(dst0_r, src76_r, filt3); + dst1_r = __lsx_vdp2_h_bu_b(src21_r, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst1_r, src43_r, filt1, dst1_r, + src65_r, filt2, dst1_r, dst1_r); + dst1_r = __lsx_vdp2add_h_bu_b(dst1_r, src87_r, filt3); + dst2_r = __lsx_vdp2_h_bu_b(src32_r, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst2_r, src54_r, filt1, dst2_r, + src76_r, filt2, dst2_r, dst2_r); + dst2_r = __lsx_vdp2add_h_bu_b(dst2_r, src98_r, filt3); + dst3_r = __lsx_vdp2_h_bu_b(src43_r, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst3_r, src65_r, filt1, dst3_r, + src87_r, filt2, dst3_r, dst3_r); + dst3_r = __lsx_vdp2add_h_bu_b(dst3_r, src109_r, filt3); + dst0_l = __lsx_vdp2_h_bu_b(src2110, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst0_l, src4332, filt1, dst0_l, + src6554, filt2, dst0_l, dst0_l); + dst0_l = __lsx_vdp2add_h_bu_b(dst0_l, src8776, filt3); + dst1_l = __lsx_vdp2_h_bu_b(src4332, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst1_l, src6554, filt1, dst1_l, + src8776, filt2, dst1_l, dst1_l); + dst1_l = __lsx_vdp2add_h_bu_b(dst1_l, src10998, filt3); + + __lsx_vst(dst0_r, dst, 0); + __lsx_vstelm_d(dst0_l, dst, 16, 0); + dst += dst_stride; + __lsx_vst(dst1_r, dst, 0); + __lsx_vstelm_d(dst0_l, dst, 16, 1); + dst += dst_stride; + __lsx_vst(dst2_r, dst, 0); + __lsx_vstelm_d(dst1_l, dst, 16, 0); + dst += dst_stride; + __lsx_vst(dst3_r, dst, 0); + __lsx_vstelm_d(dst1_l, dst, 16, 1); + dst += dst_stride; + + src10_r = src54_r; + src32_r = src76_r; + src54_r = src98_r; + src21_r = src65_r; + src43_r = src87_r; + src65_r = src109_r; + src2110 = src6554; + src4332 = src8776; + src6554 = src10998; + src6 = src10; + } +} + +static void hevc_vt_8t_16multx4mult_lsx(uint8_t *src, + int32_t src_stride, + int16_t *dst, + int32_t dst_stride, + const int8_t *filter, + int32_t height, + int32_t width) +{ + uint8_t *src_tmp; + int16_t *dst_tmp; + int32_t loop_cnt, cnt; + int32_t src_stride_2x = (src_stride << 1); + int32_t src_stride_4x = (src_stride << 2); + int32_t src_stride_3x = src_stride_2x + src_stride; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + __m128i src10_r, src32_r, src54_r, src76_r, src98_r; + __m128i src21_r, src43_r, src65_r, src87_r, src109_r; + __m128i dst0_r, dst1_r, dst2_r, dst3_r; + __m128i src10_l, src32_l, src54_l, src76_l, src98_l; + __m128i src21_l, src43_l, src65_l, src87_l, src109_l; + __m128i dst0_l, dst1_l, dst2_l, dst3_l; + __m128i filt0, filt1, filt2, filt3; + + src -= src_stride_3x; + + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filt0, filt1, filt2, filt3); + + for (cnt = width >> 4; cnt--;) { + src_tmp = src; + dst_tmp = dst; + + src0 = __lsx_vld(src_tmp, 0); + DUP2_ARG2(__lsx_vldx, src_tmp, src_stride, src_tmp, src_stride_2x, + src1, src2); + src3 = __lsx_vldx(src_tmp, src_stride_3x); + src_tmp += src_stride_4x; + src4 = __lsx_vld(src_tmp, 0); + DUP2_ARG2(__lsx_vldx, src_tmp, src_stride, src_tmp, src_stride_2x, + src5, src6); + src_tmp += src_stride_3x; + DUP4_ARG2(__lsx_vilvl_b, src1, src0, src3, src2, src5, src4, src2, src1, + src10_r, src32_r, src54_r, src21_r); + DUP2_ARG2(__lsx_vilvl_b, src4, src3, src6, src5, src43_r, src65_r); + DUP4_ARG2(__lsx_vilvh_b, src1, src0, src3, src2, src5, src4, src2, src1, + src10_l, src32_l, src54_l, src21_l); + DUP2_ARG2(__lsx_vilvh_b, src4, src3, src6, src5, src43_l, src65_l); + + for (loop_cnt = (height >> 2); loop_cnt--;) { + src7 = __lsx_vld(src_tmp, 0); + DUP2_ARG2(__lsx_vldx, src_tmp, src_stride, src_tmp, src_stride_2x, + src8, src9); + src10 = __lsx_vldx(src_tmp, src_stride_3x); + src_tmp += src_stride_4x; + DUP4_ARG2(__lsx_vilvl_b, src7, src6, src8, src7, src9, src8, + src10, src9, src76_r, src87_r, src98_r, src109_r); + DUP4_ARG2(__lsx_vilvh_b, src7, src6, src8, src7, src9, src8, + src10, src9, src76_l, src87_l, src98_l, src109_l); + + dst0_r = __lsx_vdp2_h_bu_b(src10_r, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst0_r, src32_r, filt1, dst0_r, + src54_r, filt2, dst0_r, dst0_r); + dst0_r = __lsx_vdp2add_h_bu_b(dst0_r, src76_r, filt3); + dst1_r = __lsx_vdp2_h_bu_b(src21_r, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst1_r, src43_r, filt1, dst1_r, + src65_r, filt2, dst1_r, dst1_r); + dst1_r = __lsx_vdp2add_h_bu_b(dst1_r, src87_r, filt3); + dst2_r = __lsx_vdp2_h_bu_b(src32_r, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst2_r, src54_r, filt1, dst2_r, + src76_r, filt2, dst2_r, dst2_r); + dst2_r = __lsx_vdp2add_h_bu_b(dst2_r, src98_r, filt3); + dst3_r = __lsx_vdp2_h_bu_b(src43_r, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst3_r, src65_r, filt1, dst3_r, + src87_r, filt2, dst3_r, dst3_r); + dst3_r = __lsx_vdp2add_h_bu_b(dst3_r, src109_r, filt3); + dst0_l = __lsx_vdp2_h_bu_b(src10_l, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst0_l, src32_l, filt1, dst0_l, + src54_l, filt2, dst0_l, dst0_l); + dst0_l = __lsx_vdp2add_h_bu_b(dst0_l, src76_l, filt3); + dst1_l = __lsx_vdp2_h_bu_b(src21_l, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst1_l, src43_l, filt1, dst1_l, + src65_l, filt2, dst1_l, dst1_l); + dst1_l = __lsx_vdp2add_h_bu_b(dst1_l, src87_l, filt3); + dst2_l = __lsx_vdp2_h_bu_b(src32_l, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst2_l, src54_l, filt1, dst2_l, + src76_l, filt2, dst2_l, dst2_l); + dst2_l = __lsx_vdp2add_h_bu_b(dst2_l, src98_l, filt3); + dst3_l = __lsx_vdp2_h_bu_b(src43_l, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst3_l, src65_l, filt1, dst3_l, + src87_l, filt2, dst3_l, dst3_l); + dst3_l = __lsx_vdp2add_h_bu_b(dst3_l, src109_l, filt3); + + __lsx_vst(dst0_r, dst_tmp, 0); + __lsx_vst(dst0_l, dst_tmp, 16); + dst_tmp += dst_stride; + __lsx_vst(dst1_r, dst_tmp, 0); + __lsx_vst(dst1_l, dst_tmp, 16); + dst_tmp += dst_stride; + __lsx_vst(dst2_r, dst_tmp, 0); + __lsx_vst(dst2_l, dst_tmp, 16); + dst_tmp += dst_stride; + __lsx_vst(dst3_r, dst_tmp, 0); + __lsx_vst(dst3_l, dst_tmp, 16); + dst_tmp += dst_stride; + + 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; + } + src += 16; + dst += 16; + } +} + +static void hevc_vt_8t_16w_lsx(uint8_t *src, int32_t src_stride, + int16_t *dst, int32_t dst_stride, + const int8_t *filter, int32_t height) +{ + hevc_vt_8t_16multx4mult_lsx(src, src_stride, dst, dst_stride, + filter, height, 16); +} + +static void hevc_vt_8t_24w_lsx(uint8_t *src, int32_t src_stride, + int16_t *dst, int32_t dst_stride, + const int8_t *filter, int32_t height) +{ + hevc_vt_8t_16multx4mult_lsx(src, src_stride, dst, dst_stride, + filter, height, 16); + hevc_vt_8t_8w_lsx(src + 16, src_stride, dst + 16, dst_stride, + filter, height); +} + +static void hevc_vt_8t_32w_lsx(uint8_t *src, int32_t src_stride, + int16_t *dst, int32_t dst_stride, + const int8_t *filter, int32_t height) +{ + hevc_vt_8t_16multx4mult_lsx(src, src_stride, dst, dst_stride, + filter, height, 32); +} + +static void hevc_vt_8t_48w_lsx(uint8_t *src, int32_t src_stride, + int16_t *dst, int32_t dst_stride, + const int8_t *filter, int32_t height) +{ + hevc_vt_8t_16multx4mult_lsx(src, src_stride, dst, dst_stride, + filter, height, 48); +} + +static void hevc_vt_8t_64w_lsx(uint8_t *src, int32_t src_stride, + int16_t *dst, int32_t dst_stride, + const int8_t *filter, int32_t height) +{ + hevc_vt_8t_16multx4mult_lsx(src, src_stride, dst, dst_stride, + filter, height, 64); +} + +static void hevc_hv_8t_4w_lsx(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) +{ + uint32_t loop_cnt; + int32_t src_stride_2x = (src_stride << 1); + int32_t src_stride_4x = (src_stride << 2); + int32_t src_stride_3x = src_stride_2x + src_stride; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + __m128i filt0, filt1, filt2, filt3; + __m128i filt_h0, filt_h1, filt_h2, filt_h3; + __m128i mask1, mask2, mask3; + __m128i filter_vec; + __m128i vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + __m128i vec8, vec9, vec10, vec11, vec12, vec13, vec14, vec15; + __m128i dst30, dst41, dst52, dst63, dst66, dst97, dst108; + __m128i dst0_r, dst1_r, dst2_r, dst3_r; + __m128i dst10_r, dst32_r, dst54_r, dst76_r, dst98_r; + __m128i dst21_r, dst43_r, dst65_r, dst87_r, dst109_r; + __m128i mask0; + + mask0 = __lsx_vld(ff_hevc_mask_arr, 16); + + src -= src_stride_3x + 3; + DUP4_ARG2(__lsx_vldrepl_h, filter_x, 0, filter_x, 2, filter_x, 4, + filter_x, 6, filt0, filt1, filt2, filt3); + filter_vec = __lsx_vld(filter_y, 0); + filter_vec = __lsx_vsllwil_h_b(filter_vec, 0); + + DUP4_ARG2(__lsx_vreplvei_w, filter_vec, 0, filter_vec, 1, filter_vec, 2, + filter_vec, 3, filt_h0, filt_h1, filt_h2, filt_h3); + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + + src0 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src1, src2); + src3 = __lsx_vldx(src, src_stride_3x); + src += src_stride_4x; + src4 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src5, src6); + src += src_stride_3x; + + DUP4_ARG3(__lsx_vshuf_b, src3, src0, mask0, src3, src0, mask1, src3, src0, + mask2, src3, src0, mask3, vec0, vec1, vec2, vec3); + DUP4_ARG3(__lsx_vshuf_b, src4, src1, mask0, src4, src1, mask1, src4, src1, + mask2, src4, src1, mask3, vec4, vec5, vec6, vec7); + DUP4_ARG3(__lsx_vshuf_b, src5, src2, mask0, src5, src2, mask1, src5, src2, + mask2, src5, src2, mask3, vec8, vec9, vec10, vec11); + DUP4_ARG3(__lsx_vshuf_b, src6, src3, mask0, src6, src3, mask1, src6, src3, + mask2, src6, src3, mask3, vec12, vec13, vec14, vec15); + dst30 = __lsx_vdp2_h_bu_b(vec0, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst30, vec1, filt1, dst30, vec2, filt2, + dst30, dst30); + dst30 = __lsx_vdp2add_h_bu_b(dst30, vec3, filt3); + dst41 = __lsx_vdp2_h_bu_b(vec4, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst41, vec5, filt1, dst41, vec6, filt2, + dst41, dst41); + dst41 = __lsx_vdp2add_h_bu_b(dst41, vec7, filt3); + dst52 = __lsx_vdp2_h_bu_b(vec8, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst52, vec9, filt1, dst52, vec10, filt2, + dst52, dst52); + dst52 = __lsx_vdp2add_h_bu_b(dst52, vec11, filt3); + dst63 = __lsx_vdp2_h_bu_b(vec12, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst63, vec13, filt1, dst63, vec14, filt2, + dst63, dst63); + dst63 = __lsx_vdp2add_h_bu_b(dst63, vec15, filt3); + + DUP2_ARG2(__lsx_vilvl_h, dst41, dst30, dst52, dst41, dst10_r, dst21_r); + DUP2_ARG2(__lsx_vilvh_h, dst41, dst30, dst52, dst41, dst43_r, dst54_r); + dst32_r = __lsx_vilvl_h(dst63, dst52); + dst65_r = __lsx_vilvh_h(dst63, dst52); + dst66 = __lsx_vreplvei_d(dst63, 1); + + for (loop_cnt = height >> 2; loop_cnt--;) { + src7 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src8, src9); + src10 = __lsx_vldx(src, src_stride_3x); + src += src_stride_4x; + + DUP4_ARG3(__lsx_vshuf_b, src9, src7, mask0, src9, src7, mask1, src9, src7, + mask2, src9, src7, mask3, vec0, vec1, vec2, vec3); + DUP4_ARG3(__lsx_vshuf_b, src10, src8, mask0, src10, src8, mask1, src10, src8, + mask2, src10, src8, mask3, vec4, vec5, vec6, vec7); + + dst97 = __lsx_vdp2_h_bu_b(vec0, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst97, vec1, filt1, dst97, vec2, filt2, + dst97, dst97); + dst97 = __lsx_vdp2add_h_bu_b(dst97, vec3, filt3); + dst108 = __lsx_vdp2_h_bu_b(vec4, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst108, vec5, filt1, dst108, vec6, + filt2, dst108, dst108); + dst108 = __lsx_vdp2add_h_bu_b(dst108, vec7, filt3); + + DUP2_ARG2(__lsx_vilvl_h, dst97, dst66, dst108, dst97, dst76_r, dst87_r); + dst109_r = __lsx_vilvh_h(dst108, dst97); + dst66 = __lsx_vreplvei_d(dst97, 1); + dst98_r = __lsx_vilvl_h(dst66, dst108); + + DUP4_ARG2(__lsx_vdp2_w_h, dst10_r, filt_h0, dst21_r, filt_h0, dst32_r, + filt_h0, dst43_r, filt_h0, dst0_r, dst1_r, dst2_r, dst3_r); + DUP4_ARG3(__lsx_vdp2add_w_h, dst0_r, dst32_r, filt_h1, dst1_r, dst43_r, + filt_h1, dst2_r, dst54_r, filt_h1, dst3_r, dst65_r, filt_h1, + dst0_r, dst1_r, dst2_r, dst3_r); + DUP4_ARG3(__lsx_vdp2add_w_h, dst0_r, dst54_r, filt_h2, dst1_r, dst65_r, + filt_h2, dst2_r, dst76_r, filt_h2, dst3_r, dst87_r, filt_h2, + dst0_r, dst1_r, dst2_r, dst3_r); + DUP4_ARG3(__lsx_vdp2add_w_h, dst0_r, dst76_r, filt_h3, dst1_r, dst87_r, + filt_h3, dst2_r, dst98_r, filt_h3, dst3_r, dst109_r, filt_h3, + dst0_r, dst1_r, dst2_r, dst3_r); + DUP4_ARG2(__lsx_vsrai_w, dst0_r, 6, dst1_r, 6, dst2_r, 6, dst3_r, 6, + dst0_r, dst1_r, dst2_r, dst3_r); + DUP2_ARG2(__lsx_vpickev_h, dst1_r, dst0_r, dst3_r, dst2_r, dst0_r, dst2_r); + __lsx_vstelm_d(dst0_r, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(dst0_r, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(dst2_r, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(dst2_r, dst, 0, 1); + dst += 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 = __lsx_vreplvei_d(dst108, 1); + } +} + +static void hevc_hv_8t_8multx1mult_lsx(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, + int32_t width) +{ + uint32_t loop_cnt, cnt; + uint8_t *src_tmp; + int16_t *dst_tmp; + int32_t src_stride_2x = (src_stride << 1); + int32_t src_stride_4x = (src_stride << 2); + int32_t src_stride_3x = src_stride_2x + src_stride; + __m128i src0, src1, src2, src3, src4, src5, src6, src7; + __m128i filt0, filt1, filt2, filt3; + __m128i filt_h0, filt_h1, filt_h2, filt_h3; + __m128i mask1, mask2, mask3; + __m128i filter_vec; + __m128i vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + __m128i vec8, vec9, vec10, vec11, vec12, vec13, vec14, vec15; + __m128i dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + __m128i dst0_r, dst0_l; + __m128i dst10_r, dst32_r, dst54_r, dst76_r; + __m128i dst10_l, dst32_l, dst54_l, dst76_l; + __m128i mask0 = {0x403030202010100, 0x807070606050504}; + + src -= src_stride_3x + 3; + DUP4_ARG2(__lsx_vldrepl_h, filter_x, 0, filter_x, 2, filter_x, 4, + filter_x, 6, filt0, filt1, filt2, filt3); + + filter_vec = __lsx_vld(filter_y, 0); + filter_vec = __lsx_vsllwil_h_b(filter_vec, 0); + + DUP4_ARG2(__lsx_vreplvei_w, filter_vec, 0, filter_vec, 1, filter_vec, 2, + filter_vec, 3, filt_h0, filt_h1, filt_h2, filt_h3); + + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + + for (cnt = width >> 3; cnt--;) { + src_tmp = src; + dst_tmp = dst; + src0 = __lsx_vld(src_tmp, 0); + DUP2_ARG2(__lsx_vldx, src_tmp, src_stride, src_tmp, src_stride_2x, + src1, src2); + src3 = __lsx_vldx(src_tmp, src_stride_3x); + src_tmp += src_stride_4x; + src4 = __lsx_vld(src_tmp, 0); + DUP2_ARG2(__lsx_vldx, src_tmp, src_stride, src_tmp, src_stride_2x, + src5, src6); + src_tmp += src_stride_3x; + + /* row 0 row 1 row 2 row 3 */ + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask0, src0, src0, mask1, src0, + src0, mask2, src0, src0, mask3, vec0, vec1, vec2, vec3); + DUP4_ARG3(__lsx_vshuf_b, src1, src1, mask0, src1, src1, mask1, src1, + src1, mask2, src1, src1, mask3, vec4, vec5, vec6, vec7); + DUP4_ARG3(__lsx_vshuf_b, src2, src2, mask0, src2, src2, mask1, src2, + src2, mask2, src2, src2, mask3, vec8, vec9, vec10, vec11); + DUP4_ARG3(__lsx_vshuf_b, src3, src3, mask0, src3, src3, mask1, src3, + src3, mask2, src3, src3, mask3, vec12, vec13, vec14, vec15); + dst0 = __lsx_vdp2_h_bu_b(vec0, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec1, filt1, dst0, vec2, filt2, + dst0, dst0); + dst0 = __lsx_vdp2add_h_bu_b(dst0, vec3, filt3); + dst1 = __lsx_vdp2_h_bu_b(vec4, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst1, vec5, filt1, dst1, vec6, filt2, + dst1, dst1); + dst1 = __lsx_vdp2add_h_bu_b(dst1, vec7, filt3); + dst2 = __lsx_vdp2_h_bu_b(vec8, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst2, vec9, filt1, dst2, vec10, filt2, + dst2, dst2); + dst2 = __lsx_vdp2add_h_bu_b(dst2, vec11, filt3); + dst3 = __lsx_vdp2_h_bu_b(vec12, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst3, vec13, filt1, dst3, vec14, filt2, + dst3, dst3); + dst3 = __lsx_vdp2add_h_bu_b(dst3, vec15, filt3); + + /* row 4 row 5 row 6 */ + DUP4_ARG3(__lsx_vshuf_b, src4, src4, mask0, src4, src4, mask1, src4, + src4, mask2, src4, src4, mask3, vec0, vec1, vec2, vec3); + DUP4_ARG3(__lsx_vshuf_b, src5, src5, mask0, src5, src5, mask1, src5, + src5, mask2, src5, src5, mask3, vec4, vec5, vec6, vec7); + DUP4_ARG3(__lsx_vshuf_b, src6, src6, mask0, src6, src6, mask1, src6, + src6, mask2, src6, src6, mask3, vec8, vec9, vec10, vec11); + dst4 = __lsx_vdp2_h_bu_b(vec0, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst4, vec1, filt1, dst4, vec2, filt2, + dst4, dst4); + dst4 = __lsx_vdp2add_h_bu_b(dst4, vec3, filt3); + dst5 = __lsx_vdp2_h_bu_b(vec4, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst5, vec5, filt1, dst5, vec6, filt2, + dst5, dst5); + dst5 = __lsx_vdp2add_h_bu_b(dst5, vec7, filt3); + dst6 = __lsx_vdp2_h_bu_b(vec8, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst6, vec9, filt1, dst6, vec10, filt2, + dst6, dst6); + dst6 = __lsx_vdp2add_h_bu_b(dst6, vec11, filt3); + + for (loop_cnt = height; loop_cnt--;) { + src7 = __lsx_vld(src_tmp, 0); + src_tmp += src_stride; + + DUP4_ARG3(__lsx_vshuf_b, src7, src7, mask0, src7, src7, mask1, src7, + src7, mask2, src7, src7, mask3, vec0, vec1, vec2, vec3); + dst7 = __lsx_vdp2_h_bu_b(vec0, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst7, vec1, filt1, dst7, vec2, + filt2, dst7, dst7); + dst7 = __lsx_vdp2add_h_bu_b(dst7, vec3, filt3); + + DUP4_ARG2(__lsx_vilvl_h, dst1, dst0, dst3, dst2, dst5, dst4, dst7, + dst6, dst10_r, dst32_r, dst54_r, dst76_r); + DUP4_ARG2(__lsx_vilvh_h, dst1, dst0, dst3, dst2, dst5, dst4, dst7, + dst6, dst10_l, dst32_l, dst54_l, dst76_l); + + DUP2_ARG2(__lsx_vdp2_w_h, dst10_r, filt_h0, dst10_l, filt_h0, + dst0_r, dst0_l); + DUP4_ARG3(__lsx_vdp2add_w_h, dst0_r, dst32_r, filt_h1, dst0_l, + dst32_l, filt_h1, dst0_r, dst54_r, filt_h2, dst0_l, + dst54_l, filt_h2, dst0_r, dst0_l, dst0_r, dst0_l); + DUP2_ARG3(__lsx_vdp2add_w_h, dst0_r, dst76_r, filt_h3, dst0_l, + dst76_l, filt_h3, dst0_r, dst0_l); + dst0_r = __lsx_vsrai_w(dst0_r, 6); + dst0_l = __lsx_vsrai_w(dst0_l, 6); + + dst0_r = __lsx_vpickev_h(dst0_l, dst0_r); + __lsx_vst(dst0_r, dst_tmp, 0); + dst_tmp += dst_stride; + + dst0 = dst1; + dst1 = dst2; + dst2 = dst3; + dst3 = dst4; + dst4 = dst5; + dst5 = dst6; + dst6 = dst7; + } + src += 8; + dst += 8; + } +} + +static void hevc_hv_8t_8w_lsx(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) +{ + hevc_hv_8t_8multx1mult_lsx(src, src_stride, dst, dst_stride, + filter_x, filter_y, height, 8); +} + +static void hevc_hv_8t_12w_lsx(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) +{ + uint32_t loop_cnt; + uint8_t *src_tmp; + int16_t *dst_tmp; + int32_t src_stride_2x = (src_stride << 1); + int32_t src_stride_4x = (src_stride << 2); + int32_t src_stride_3x = src_stride_2x + src_stride; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + __m128i mask0, mask1, mask2, mask3, mask4, mask5, mask6, mask7; + __m128i vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + __m128i vec8, vec9, vec10, vec11, vec12, vec13, vec14, vec15; + __m128i filt0, filt1, filt2, filt3, filt_h0, filt_h1, filt_h2, filt_h3; + __m128i filter_vec; + __m128i dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + __m128i dst30, dst41, dst52, dst63, dst66, dst97, dst108; + __m128i dst10_r, dst32_r, dst54_r, dst76_r, dst98_r, dst21_r, dst43_r; + __m128i dst65_r, dst87_r, dst109_r, dst10_l, dst32_l, dst54_l, dst76_l; + __m128i dst0_r, dst0_l, dst1_r, dst2_r, dst3_r; + + src -= src_stride_3x + 3; + DUP4_ARG2(__lsx_vldrepl_h, filter_x, 0, filter_x, 2, filter_x, 4, + filter_x, 6, filt0, filt1, filt2, filt3); + + filter_vec = __lsx_vld(filter_y, 0); + filter_vec = __lsx_vsllwil_h_b(filter_vec, 0); + + DUP4_ARG2(__lsx_vreplvei_w, filter_vec, 0, filter_vec, 1, filter_vec, 2, + filter_vec, 3, filt_h0, filt_h1, filt_h2, filt_h3); + + mask0 = __lsx_vld(ff_hevc_mask_arr, 0); + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + + src_tmp = src; + dst_tmp = dst; + + src0 = __lsx_vld(src_tmp, 0); + DUP2_ARG2(__lsx_vldx, src_tmp, src_stride, src_tmp, src_stride_2x, + src1, src2); + src3 = __lsx_vldx(src_tmp, src_stride_3x); + src_tmp += src_stride_4x; + src4 = __lsx_vld(src_tmp, 0); + DUP2_ARG2(__lsx_vldx, src_tmp, src_stride, src_tmp, src_stride_2x, + src5, src6); + src_tmp += src_stride_3x; + + /* row 0 row 1 row 2 row 3 */ + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask0, src0, src0, mask1, src0, src0, + mask2, src0, src0, mask3, vec0, vec1, vec2, vec3); + DUP4_ARG3(__lsx_vshuf_b, src1, src1, mask0, src1, src1, mask1, src1, src1, + mask2, src1, src1, mask3, vec4, vec5, vec6, vec7); + DUP4_ARG3(__lsx_vshuf_b, src2, src2, mask0, src2, src2, mask1, src2, src2, + mask2, src2, src2, mask3, vec8, vec9, vec10, vec11); + DUP4_ARG3(__lsx_vshuf_b, src3, src3, mask0, src3, src3, mask1, src3, src3, + mask2, src3, src3, mask3, vec12, vec13, vec14, vec15); + dst0 = __lsx_vdp2_h_bu_b(vec0, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec1, filt1, dst0, vec2, filt2, + dst0, dst0); + dst0 = __lsx_vdp2add_h_bu_b(dst0, vec3, filt3); + dst1 = __lsx_vdp2_h_bu_b(vec4, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst1, vec5, filt1, dst1, vec6, filt2, + dst1, dst1); + dst1 = __lsx_vdp2add_h_bu_b(dst1, vec7, filt3); + dst2 = __lsx_vdp2_h_bu_b(vec8, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst2, vec9, filt1, dst2, vec10, filt2, + dst2, dst2); + dst2 = __lsx_vdp2add_h_bu_b(dst2, vec11, filt3); + dst3 = __lsx_vdp2_h_bu_b(vec12, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst3, vec13, filt1, dst3, vec14, filt2, + dst3, dst3); + dst3 = __lsx_vdp2add_h_bu_b(dst3, vec15, filt3); + + /* row 4 row 5 row 6 */ + DUP4_ARG3(__lsx_vshuf_b, src4, src4, mask0, src4, src4, mask1, src4, src4, + mask2, src4, src4, mask3, vec0, vec1, vec2, vec3); + DUP4_ARG3(__lsx_vshuf_b, src5, src5, mask0, src5, src5, mask1, src5, src5, + mask2, src5, src5, mask3, vec4, vec5, vec6, vec7); + DUP4_ARG3(__lsx_vshuf_b, src6, src6, mask0, src6, src6, mask1, src6, src6, + mask2, src6, src6, mask3, vec8, vec9, vec10, vec11); + dst4 = __lsx_vdp2_h_bu_b(vec0, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst4, vec1, filt1, dst4, vec2, filt2, + dst4, dst4); + dst4 = __lsx_vdp2add_h_bu_b(dst4, vec3, filt3); + dst5 = __lsx_vdp2_h_bu_b(vec4, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst5, vec5, filt1, dst5, vec6, filt2, + dst5, dst5); + dst5 = __lsx_vdp2add_h_bu_b(dst5, vec7, filt3); + dst6 = __lsx_vdp2_h_bu_b(vec8, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst6, vec9, filt1, dst6, vec10, filt2, + dst6, dst6); + dst6 = __lsx_vdp2add_h_bu_b(dst6, vec11, filt3); + + for (loop_cnt = height; loop_cnt--;) { + src7 = __lsx_vld(src_tmp, 0); + src_tmp += src_stride; + + DUP4_ARG3(__lsx_vshuf_b, src7, src7, mask0, src7, src7, mask1, src7, + src7, mask2, src7, src7, mask3, vec0, vec1, vec2, vec3); + dst7 = __lsx_vdp2_h_bu_b(vec0, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst7, vec1, filt1, dst7, vec2, filt2, + dst7, dst7); + dst7 = __lsx_vdp2add_h_bu_b(dst7, vec3, filt3); + DUP4_ARG2(__lsx_vilvl_h, dst1, dst0, dst3, dst2, dst5, dst4, dst7, dst6, + dst10_r, dst32_r, dst54_r, dst76_r); + DUP4_ARG2(__lsx_vilvh_h, dst1, dst0, dst3, dst2, dst5, dst4, dst7, dst6, + dst10_l, dst32_l, dst54_l, dst76_l); + DUP2_ARG2(__lsx_vdp2_w_h, dst10_r, filt_h0, dst10_l, filt_h0, + dst0_r, dst0_l); + DUP4_ARG3(__lsx_vdp2add_w_h, dst0_r, dst32_r, filt_h1, dst0_l, dst32_l, + filt_h1, dst0_r, dst54_r, filt_h2, dst0_l, dst54_l, filt_h2, + dst0_r, dst0_l, dst0_r, dst0_l); + DUP2_ARG3(__lsx_vdp2add_w_h, dst0_r, dst76_r, filt_h3, dst0_l, dst76_l, + filt_h3, dst0_r, dst0_l) + dst0_r = __lsx_vsrai_w(dst0_r, 6); + dst0_l = __lsx_vsrai_w(dst0_l, 6); + + dst0_r = __lsx_vpickev_h(dst0_l, dst0_r); + __lsx_vst(dst0_r, dst_tmp, 0); + dst_tmp += dst_stride; + + dst0 = dst1; + dst1 = dst2; + dst2 = dst3; + dst3 = dst4; + dst4 = dst5; + dst5 = dst6; + dst6 = dst7; + } + src += 8; + dst += 8; + + mask4 = __lsx_vld(ff_hevc_mask_arr, 16); + DUP2_ARG2(__lsx_vaddi_bu, mask4, 2, mask4, 4, mask5, mask6); + mask7 = __lsx_vaddi_bu(mask4, 6); + + src0 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src1, src2); + src3 = __lsx_vldx(src, src_stride_3x); + src += src_stride_4x; + src4 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src5, src6); + src += src_stride_3x; + + DUP4_ARG3(__lsx_vshuf_b, src3, src0, mask4, src3, src0, mask5, src3, src0, + mask6, src3, src0, mask7, vec0, vec1, vec2, vec3); + DUP4_ARG3(__lsx_vshuf_b, src4, src1, mask4, src4, src1, mask5, src4, src1, + mask6, src4, src1, mask7, vec4, vec5, vec6, vec7); + DUP4_ARG3(__lsx_vshuf_b, src5, src2, mask4, src5, src2, mask5, src5, src2, + mask6, src5, src2, mask7, vec8, vec9, vec10, vec11); + DUP4_ARG3(__lsx_vshuf_b, src6, src3, mask4, src6, src3, mask5, src6, src3, + mask6, src6, src3, mask7, vec12, vec13, vec14, vec15); + dst30 = __lsx_vdp2_h_bu_b(vec0, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst30, vec1, filt1, dst30, vec2, filt2, + dst30, dst30); + dst30 = __lsx_vdp2add_h_bu_b(dst30, vec3, filt3); + dst41 = __lsx_vdp2_h_bu_b(vec4, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst41, vec5, filt1, dst41, vec6, filt2, + dst41, dst41); + dst41 = __lsx_vdp2add_h_bu_b(dst41, vec7, filt3); + dst52 = __lsx_vdp2_h_bu_b(vec8, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst52, vec9, filt1, dst52, vec10, filt2, + dst52, dst52); + dst52 = __lsx_vdp2add_h_bu_b(dst52, vec11, filt3); + dst63 = __lsx_vdp2_h_bu_b(vec12, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst63, vec13, filt1, dst63, vec14, filt2, + dst63, dst63); + dst63 = __lsx_vdp2add_h_bu_b(dst63, vec15, filt3); + + DUP2_ARG2(__lsx_vilvl_h, dst41, dst30, dst52, dst41, dst10_r, dst21_r); + DUP2_ARG2(__lsx_vilvh_h, dst41, dst30, dst52, dst41, dst43_r, dst54_r); + dst32_r = __lsx_vilvl_h(dst63, dst52); + dst65_r = __lsx_vilvh_h(dst63, dst52); + + dst66 = __lsx_vreplvei_d(dst63, 1); + + for (loop_cnt = height >> 2; loop_cnt--;) { + src7 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src8, src9); + src10 = __lsx_vldx(src, src_stride_3x); + src += src_stride_4x; + + DUP4_ARG3(__lsx_vshuf_b, src9, src7, mask4, src9, src7, mask5, src9, + src7, mask6, src9, src7, mask7, vec0, vec1, vec2, vec3); + DUP4_ARG3(__lsx_vshuf_b, src10, src8, mask4, src10, src8, mask5, src10, + src8, mask6, src10, src8, mask7, vec4, vec5, vec6, vec7); + dst97 = __lsx_vdp2_h_bu_b(vec0, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst97, vec1, filt1, dst97, vec2, filt2, + dst97, dst97); + dst97 = __lsx_vdp2add_h_bu_b(dst97, vec3, filt3); + dst108 = __lsx_vdp2_h_bu_b(vec4, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst108, vec5, filt1, dst108, vec6, + filt2, dst108, dst108); + dst108 = __lsx_vdp2add_h_bu_b(dst108, vec7, filt3); + + DUP2_ARG2(__lsx_vilvl_h, dst97, dst66, dst108, dst97, dst76_r, dst87_r); + dst109_r = __lsx_vilvh_h(dst108, dst97); + dst66 = __lsx_vreplvei_d(dst97, 1); + dst98_r = __lsx_vilvl_h(dst66, dst108); + + DUP4_ARG2(__lsx_vdp2_w_h, dst10_r, filt_h0, dst21_r, filt_h0, dst32_r, + filt_h0, dst43_r, filt_h0, dst0_r, dst1_r, dst2_r, dst3_r); + DUP4_ARG3(__lsx_vdp2add_w_h, dst0_r, dst32_r, filt_h1, dst1_r, dst43_r, + filt_h1, dst2_r, dst54_r, filt_h1, dst3_r, dst65_r, filt_h1, + dst0_r, dst1_r, dst2_r, dst3_r); + DUP4_ARG3(__lsx_vdp2add_w_h, dst0_r, dst54_r, filt_h2, dst1_r, dst65_r, + filt_h2, dst2_r, dst76_r, filt_h2, dst3_r, dst87_r, filt_h2, + dst0_r, dst1_r, dst2_r, dst3_r); + DUP4_ARG3(__lsx_vdp2add_w_h, dst0_r, dst76_r, filt_h3, dst1_r, dst87_r, + filt_h3, dst2_r, dst98_r, filt_h3, dst3_r, dst109_r, filt_h3, + dst0_r, dst1_r, dst2_r, dst3_r); + DUP4_ARG2(__lsx_vsrai_w, dst0_r, 6, dst1_r, 6, dst2_r, 6, dst3_r, 6, + dst0_r, dst1_r, dst2_r, dst3_r); + DUP2_ARG2(__lsx_vpickev_h, dst1_r, dst0_r, dst3_r, dst2_r, + dst0_r, dst2_r); + __lsx_vstelm_d(dst0_r, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(dst0_r, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(dst2_r, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(dst2_r, dst, 0, 1); + dst += 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 = __lsx_vreplvei_d(dst108, 1); + } +} + +static void hevc_hv_8t_16w_lsx(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) +{ + hevc_hv_8t_8multx1mult_lsx(src, src_stride, dst, dst_stride, + filter_x, filter_y, height, 16); +} + +static void hevc_hv_8t_24w_lsx(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) +{ + hevc_hv_8t_8multx1mult_lsx(src, src_stride, dst, dst_stride, + filter_x, filter_y, height, 24); +} + +static void hevc_hv_8t_32w_lsx(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) +{ + hevc_hv_8t_8multx1mult_lsx(src, src_stride, dst, dst_stride, + filter_x, filter_y, height, 32); +} + +static void hevc_hv_8t_48w_lsx(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) +{ + hevc_hv_8t_8multx1mult_lsx(src, src_stride, dst, dst_stride, + filter_x, filter_y, height, 48); +} + +static void hevc_hv_8t_64w_lsx(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) +{ + hevc_hv_8t_8multx1mult_lsx(src, src_stride, dst, dst_stride, + filter_x, filter_y, height, 64); +} + +static void hevc_hz_4t_32w_lsx(uint8_t *src, + int32_t src_stride, + int16_t *dst, + int32_t dst_stride, + const int8_t *filter, + int32_t height) +{ + uint32_t loop_cnt; + __m128i src0, src1, src2; + __m128i filt0, filt1; + __m128i mask0 = __lsx_vld(ff_hevc_mask_arr, 0); + __m128i mask1, mask2, mask3; + __m128i dst0, dst1, dst2, dst3; + __m128i vec0, vec1, vec2, vec3; + + src -= 1; + DUP2_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filt0, filt1); + + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 8, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 10); + + for (loop_cnt = height; loop_cnt--;) { + DUP2_ARG2(__lsx_vld, src, 0, src, 16, src0, src1); + src2 = __lsx_vld(src, 24); + src += src_stride; + + DUP2_ARG3(__lsx_vshuf_b, src0, src0, mask0, src1, src0, mask2, + vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src1, src1, mask0, src2, src2, mask0, + vec2, vec3); + DUP4_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec1, filt0, vec2, filt0, + vec3, filt0, dst0, dst1, dst2, dst3); + DUP2_ARG3(__lsx_vshuf_b, src0, src0, mask1, src1, src0, mask3, + vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src1, src1, mask1, src2, src2, mask1, + vec2, vec3); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec0, filt1, dst1, vec1, filt1, + dst2, vec2, filt1, dst3, vec3, filt1, dst0, dst1, dst2, dst3); + __lsx_vst(dst0, dst, 0); + __lsx_vst(dst1, dst, 16); + __lsx_vst(dst2, dst, 32); + __lsx_vst(dst3, dst, 48); + dst += dst_stride; + } +} + +static void hevc_vt_4t_16w_lsx(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; + int32_t src_stride_2x = (src_stride << 1); + int32_t src_stride_3x = src_stride_2x + src_stride; + __m128i src0, src1, src2, src3, src4, src5; + __m128i src10_r, src32_r, src21_r, src43_r; + __m128i src10_l, src32_l, src21_l, src43_l; + __m128i dst0_r, dst1_r, dst0_l, dst1_l; + __m128i filt0, filt1; + + src -= src_stride; + DUP2_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filt0, filt1); + + src0 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src1, src2); + src += src_stride_3x; + DUP2_ARG2(__lsx_vilvl_b, src1, src0, src2, src1, src10_r, src21_r); + DUP2_ARG2(__lsx_vilvh_b, src1, src0, src2, src1, src10_l, src21_l); + + for (loop_cnt = (height >> 2); loop_cnt--;) { + src3 = __lsx_vld(src, 0); + src4 = __lsx_vldx(src, src_stride); + src += src_stride_2x; + DUP2_ARG2(__lsx_vilvl_b, src3, src2, src4, src3, src32_r, src43_r); + DUP2_ARG2(__lsx_vilvh_b, src3, src2, src4, src3, src32_l, src43_l); + DUP4_ARG2(__lsx_vdp2_h_bu_b, src10_r, filt0, src10_l, filt0, src21_r, + filt0, src21_l, filt0, dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0_r, src32_r, filt1, dst0_l, + src32_l, filt1, dst1_r, src43_r, filt1, dst1_l, src43_l, + filt1, dst0_r, dst0_l, dst1_r, dst1_l); + __lsx_vst(dst0_r, dst, 0); + __lsx_vst(dst0_l, dst, 16); + dst += dst_stride; + __lsx_vst(dst1_r, dst, 0); + __lsx_vst(dst1_l, dst, 16); + dst += dst_stride; + + src5 = __lsx_vld(src, 0); + src2 = __lsx_vldx(src, src_stride); + src += src_stride_2x; + DUP2_ARG2(__lsx_vilvl_b, src5, src4, src2, src5, src10_r, src21_r); + DUP2_ARG2(__lsx_vilvh_b, src5, src4, src2, src5, src10_l, src21_l); + DUP4_ARG2(__lsx_vdp2_h_bu_b, src32_r, filt0, src32_l, filt0, src43_r, + filt0, src43_l, filt0, dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0_r, src10_r, filt1, dst0_l, + src10_l, filt1, dst1_r, src21_r, filt1, dst1_l, src21_l, + filt1, dst0_r, dst0_l, dst1_r, dst1_l); + __lsx_vst(dst0_r, dst, 0); + __lsx_vst(dst0_l, dst, 16); + dst += dst_stride; + __lsx_vst(dst1_r, dst, 0); + __lsx_vst(dst1_l, dst, 16); + dst += dst_stride; + } +} + +static void hevc_vt_4t_24w_lsx(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; + int32_t src_stride_2x = (src_stride << 1); + int32_t src_stride_3x = src_stride_2x + src_stride; + uint8_t *_src; + + __m128i src0, src1, src2, src3, src4, src5; + __m128i src6, src7, src8, src9, src10, src11; + __m128i src10_r, src32_r, src76_r, src98_r; + __m128i src21_r, src43_r, src87_r, src109_r; + __m128i dst0_r, dst1_r, dst2_r, dst3_r; + __m128i src10_l, src32_l, src21_l, src43_l; + __m128i dst0_l, dst1_l; + __m128i filt0, filt1; + + src -= src_stride; + _src = src + 16; + DUP2_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filt0, filt1); + + src0 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src1, src2); + DUP2_ARG2(__lsx_vilvl_b, src1, src0, src2, src1, src10_r, src21_r); + DUP2_ARG2(__lsx_vilvh_b, src1, src0, src2, src1, src10_l, src21_l); + + src6 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride_2x, src7, src8); + src += src_stride_3x; + _src += src_stride_3x; + DUP2_ARG2(__lsx_vilvl_b, src7, src6, src8, src7, src76_r, src87_r); + + for (loop_cnt = (height >> 2); loop_cnt--;) { + DUP2_ARG2(__lsx_vld, src, 0, _src, 0, src3, src9); + DUP2_ARG2(__lsx_vldx, src, src_stride, _src, src_stride, src4, src10); + src += src_stride_2x; + _src += src_stride_2x; + DUP2_ARG2(__lsx_vilvl_b, src3, src2, src4, src3, src32_r, src43_r); + DUP2_ARG2(__lsx_vilvh_b, src3, src2, src4, src3, src32_l, src43_l); + + DUP2_ARG2(__lsx_vilvl_b, src9, src8, src10, src9, src98_r, src109_r); + DUP4_ARG2(__lsx_vdp2_h_bu_b, src10_r, filt0, src10_l, filt0, src21_r, + filt0, src21_l, filt0, dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0_r, src32_r, filt1, dst0_l, + src32_l, filt1, dst1_r, src43_r, filt1, dst1_l, src43_l, + filt1, dst0_r, dst0_l, dst1_r, dst1_l); + DUP2_ARG2(__lsx_vdp2_h_bu_b, src76_r, filt0, src87_r, filt0, + dst2_r, dst3_r); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst2_r, src98_r, filt1, dst3_r, + src109_r, filt1, dst2_r, dst3_r); + + __lsx_vst(dst0_r, dst, 0); + __lsx_vst(dst0_l, dst, 16); + __lsx_vst(dst2_r, dst, 32); + dst += dst_stride; + __lsx_vst(dst1_r, dst, 0); + __lsx_vst(dst1_l, dst, 16); + __lsx_vst(dst3_r, dst, 32); + dst += dst_stride; + + DUP2_ARG2(__lsx_vld, src, 0, _src, 0, src5, src11); + DUP2_ARG2(__lsx_vldx, src, src_stride, _src, src_stride, src2, src8); + src += src_stride_2x; + _src += src_stride_2x; + DUP2_ARG2(__lsx_vilvl_b, src5, src4, src2, src5, src10_r, src21_r); + DUP2_ARG2(__lsx_vilvh_b, src5, src4, src2, src5, src10_l, src21_l); + + DUP2_ARG2(__lsx_vilvl_b, src11, src10, src8, src11, src76_r, src87_r); + + DUP4_ARG2(__lsx_vdp2_h_bu_b, src32_r, filt0, src32_l, filt0, src43_r, + filt0, src43_l, filt0, dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0_r, src10_r, filt1, dst0_l, src10_l, + filt1, dst1_r, src21_r, filt1, dst1_l, src21_l, filt1, + dst0_r, dst0_l, dst1_r, dst1_l); + DUP2_ARG2(__lsx_vdp2_h_bu_b, src98_r, filt0, src109_r, filt0, + dst2_r, dst3_r); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst2_r, src76_r, filt1, dst3_r, src87_r, + filt1, dst2_r, dst3_r); + + __lsx_vst(dst0_r, dst, 0); + __lsx_vst(dst0_l, dst, 16); + __lsx_vst(dst2_r, dst, 32); + dst += dst_stride; + __lsx_vst(dst1_r, dst, 0); + __lsx_vst(dst1_l, dst, 16); + __lsx_vst(dst3_r, dst, 32); + dst += dst_stride; + } +} + +static void hevc_vt_4t_32w_lsx(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; + int32_t src_stride_2x = (src_stride << 1); + int32_t src_stride_3x = src_stride_2x + src_stride; + uint8_t *_src; + + __m128i src0, src1, src2, src3, src4, src5; + __m128i src6, src7, src8, src9, src10, src11; + __m128i src10_r, src32_r, src76_r, src98_r; + __m128i src21_r, src43_r, src87_r, src109_r; + __m128i dst0_r, dst1_r, dst2_r, dst3_r; + __m128i src10_l, src32_l, src76_l, src98_l; + __m128i src21_l, src43_l, src87_l, src109_l; + __m128i dst0_l, dst1_l, dst2_l, dst3_l; + __m128i filt0, filt1; + + src -= src_stride; + _src = src + 16; + DUP2_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filt0, filt1); + + src0 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src1, src2); + DUP2_ARG2(__lsx_vilvl_b, src1, src0, src2, src1, src10_r, src21_r); + DUP2_ARG2(__lsx_vilvh_b, src1, src0, src2, src1, src10_l, src21_l); + + src6 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride_2x, src7, src8); + src += src_stride_3x; + _src += src_stride_3x; + DUP2_ARG2(__lsx_vilvl_b, src7, src6, src8, src7, src76_r, src87_r); + DUP2_ARG2(__lsx_vilvh_b, src7, src6, src8, src7, src76_l, src87_l); + + for (loop_cnt = (height >> 2); loop_cnt--;) { + DUP2_ARG2(__lsx_vld, src, 0, _src, 0, src3, src9); + DUP2_ARG2(__lsx_vldx, src, src_stride, _src, src_stride, src4, src10); + src += src_stride_2x; + _src += src_stride_2x; + DUP2_ARG2(__lsx_vilvl_b, src3, src2, src4, src3, src32_r, src43_r); + DUP2_ARG2(__lsx_vilvh_b, src3, src2, src4, src3, src32_l, src43_l); + + DUP2_ARG2(__lsx_vilvl_b, src9, src8, src10, src9, src98_r, src109_r); + DUP2_ARG2(__lsx_vilvh_b, src9, src8, src10, src9, src98_l, src109_l); + + DUP4_ARG2(__lsx_vdp2_h_bu_b, src10_r, filt0, src10_l, filt0, src21_r, + filt0, src21_l, filt0, dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0_r, src32_r, filt1, dst0_l, + src32_l, filt1, dst1_r, src43_r, filt1, dst1_l,src43_l, + filt1, dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG2(__lsx_vdp2_h_bu_b, src76_r, filt0, src76_l, filt0, src87_r, + filt0, src87_l, filt0, dst2_r, dst2_l, dst3_r, dst3_l); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst2_r, src98_r, filt1, dst2_l, src98_l, + filt1, dst3_r, src109_r, filt1, dst3_l, src109_l, filt1, + dst2_r, dst2_l, dst3_r, dst3_l); + + __lsx_vst(dst0_r, dst, 0); + __lsx_vst(dst0_l, dst, 16); + __lsx_vst(dst2_r, dst, 32); + __lsx_vst(dst2_l, dst, 48); + dst += dst_stride; + __lsx_vst(dst1_r, dst, 0); + __lsx_vst(dst1_l, dst, 16); + __lsx_vst(dst3_r, dst, 32); + __lsx_vst(dst3_l, dst, 48); + dst += dst_stride; + + DUP2_ARG2(__lsx_vld, src, 0, _src, 0, src5, src11); + DUP2_ARG2(__lsx_vldx, src, src_stride, _src, src_stride, src2, src8); + src += src_stride_2x; + _src += src_stride_2x; + DUP2_ARG2(__lsx_vilvl_b, src5, src4, src2, src5, src10_r, src21_r); + DUP2_ARG2(__lsx_vilvh_b, src5, src4, src2, src5, src10_l, src21_l); + + DUP2_ARG2(__lsx_vilvl_b, src11, src10, src8, src11, src76_r, src87_r); + DUP2_ARG2(__lsx_vilvh_b, src11, src10, src8, src11, src76_l, src87_l); + + DUP4_ARG2(__lsx_vdp2_h_bu_b, src32_r, filt0, src32_l, filt0, src43_r, + filt0, src43_l, filt0, dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0_r, src10_r, filt1, dst0_l, + src10_l, filt1, dst1_r, src21_r, filt1, dst1_l, src21_l, + filt1, dst0_r, dst0_l, dst1_r, dst1_l); + + DUP4_ARG2(__lsx_vdp2_h_bu_b, src98_r, filt0, src98_l, filt0, src109_r, + filt0, src109_l, filt0, dst2_r, dst2_l, dst3_r, dst3_l); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst2_r, src76_r, filt1, dst2_l, src76_l, + filt1, dst3_r, src87_r, filt1, dst3_l, src87_l, filt1, + dst2_r, dst2_l, dst3_r, dst3_l); + + __lsx_vst(dst0_r, dst, 0); + __lsx_vst(dst0_l, dst, 16); + __lsx_vst(dst2_r, dst, 32); + __lsx_vst(dst2_l, dst, 48); + dst += dst_stride; + __lsx_vst(dst1_r, dst, 0); + __lsx_vst(dst1_l, dst, 16); + __lsx_vst(dst3_r, dst, 32); + __lsx_vst(dst3_l, dst, 48); + dst += dst_stride; + } +} + +static void hevc_hv_4t_8x2_lsx(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 src_stride_2x = (src_stride << 1); + int32_t src_stride_4x = (src_stride << 2); + int32_t src_stride_3x = src_stride_2x + src_stride; + + __m128i src0, src1, src2, src3, src4; + __m128i filt0, filt1; + __m128i filt_h0, filt_h1; + __m128i mask0 = __lsx_vld(ff_hevc_mask_arr, 0); + __m128i mask1; + __m128i filter_vec; + __m128i vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7, vec8, vec9; + __m128i dst0, dst1, dst2, dst3, dst4; + __m128i dst0_r, dst0_l, dst1_r, dst1_l; + __m128i dst10_r, dst32_r, dst21_r, dst43_r; + __m128i dst10_l, dst32_l, dst21_l, dst43_l; + + src -= (src_stride + 1); + DUP2_ARG2(__lsx_vldrepl_h, filter_x, 0, filter_x, 2, filt0, filt1); + + filter_vec = __lsx_vld(filter_y, 0); + filter_vec = __lsx_vsllwil_h_b(filter_vec, 0); + DUP2_ARG2(__lsx_vreplvei_w, filter_vec, 0, filter_vec, 1, filt_h0, filt_h1); + + mask1 = __lsx_vaddi_bu(mask0, 2); + + src0 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src1, src2); + src3 = __lsx_vldx(src, src_stride_3x); + src4 = __lsx_vldx(src, src_stride_4x); + + DUP2_ARG3(__lsx_vshuf_b, src0, src0, mask0, src0, src0, mask1, vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src1, src1, mask0, src1, src1, mask1, vec2, vec3); + DUP2_ARG3(__lsx_vshuf_b, src2, src2, mask0, src2, src2, mask1, vec4, vec5); + DUP2_ARG3(__lsx_vshuf_b, src3, src3, mask0, src3, src3, mask1, vec6, vec7); + DUP2_ARG3(__lsx_vshuf_b, src4, src4, mask0, src4, src4, mask1, vec8, vec9); + + DUP4_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec2, filt0, vec4, filt0, + vec6, filt0, dst0, dst1, dst2, dst3); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec1, filt1, dst1, vec3, filt1, + dst2, vec5, filt1, dst3, vec7, filt1, dst0, dst1, dst2, dst3); + dst4 = __lsx_vdp2_h_bu_b(vec8, filt0); + dst4 = __lsx_vdp2add_h_bu_b(dst4, vec9, filt1); + + DUP2_ARG2(__lsx_vilvl_h, dst1, dst0, dst2, dst1, dst10_r, dst21_r); + DUP2_ARG2(__lsx_vilvh_h, dst1, dst0, dst2, dst1, dst10_l, dst21_l); + DUP2_ARG2(__lsx_vilvl_h, dst3, dst2, dst4, dst3, dst32_r, dst43_r); + DUP2_ARG2(__lsx_vilvh_h, dst3, dst2, dst4, dst3, dst32_l, dst43_l); + + DUP4_ARG2(__lsx_vdp2_w_h, dst10_r, filt_h0, dst10_l, filt_h0, dst21_r, + filt_h0, dst21_l, filt_h0, dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG3(__lsx_vdp2add_w_h, dst0_r, dst32_r, filt_h1, dst0_l, dst32_l, + filt_h1, dst1_r, dst43_r, filt_h1, dst1_l, dst43_l, filt_h1, + dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG2(__lsx_vsrai_w, dst0_r, 6, dst0_l, 6, dst1_r, 6, dst1_l, 6, + dst0_r, dst0_l, dst1_r, dst1_l); + DUP2_ARG2(__lsx_vpickev_h, dst0_l, dst0_r, dst1_l, dst1_r, dst0_r, dst1_r); + __lsx_vst(dst0_r, dst, 0); + __lsx_vst(dst1_r, dst + dst_stride, 0); +} + +static void hevc_hv_4t_8multx4_lsx(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; + int32_t src_stride_2x = (src_stride << 1); + int32_t dst_stride_x = (dst_stride << 1); + int32_t src_stride_4x = (src_stride << 2); + int32_t dst_stride_2x = (dst_stride << 2); + int32_t src_stride_3x = src_stride_2x + src_stride; + int32_t dst_stride_3x = dst_stride_2x + dst_stride_x; + + __m128i src0, src1, src2, src3, src4, src5, src6, mask0, mask1; + __m128i vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + __m128i filt0, filt1, filt_h0, filt_h1, filter_vec; + __m128i dst0, dst1, dst2, dst3, dst4, dst5, dst6; + __m128i dst10_r, dst32_r, dst54_r, dst21_r, dst43_r, dst65_r; + __m128i dst10_l, dst32_l, dst54_l, dst21_l, dst43_l, dst65_l; + __m128i dst0_r, dst0_l, dst1_r, dst1_l, dst2_r, dst2_l, dst3_r, dst3_l; + + src -= (src_stride + 1); + DUP2_ARG2(__lsx_vldrepl_h, filter_x, 0, filter_x, 2, filt0, filt1); + + filter_vec = __lsx_vld(filter_y, 0); + filter_vec = __lsx_vsllwil_h_b(filter_vec, 0); + DUP2_ARG2(__lsx_vreplvei_w, filter_vec, 0, filter_vec, 1, filt_h0, filt_h1); + + mask0 = __lsx_vld(ff_hevc_mask_arr, 0); + mask1 = __lsx_vaddi_bu(mask0, 2); + + for (cnt = width8mult; cnt--;) { + src0 = __lsx_vld(src, 0); + DUP4_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src, + src_stride_3x, src, src_stride_4x, src1, src2, src3, src4); + src += src_stride_4x; + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src5, src6); + src += (8 - src_stride_4x); + + DUP2_ARG3(__lsx_vshuf_b, src0, src0, mask0, src0, src0, mask1, + vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src1, src1, mask0, src1, src1, mask1, + vec2, vec3); + DUP2_ARG3(__lsx_vshuf_b, src2, src2, mask0, src2, src2, mask1, + vec4, vec5); + + DUP2_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec2, filt0, dst0, dst1); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec1, filt1, dst1, vec3, filt1, + dst0, dst1); + dst2 = __lsx_vdp2_h_bu_b(vec4, filt0); + dst2 = __lsx_vdp2add_h_bu_b(dst2, vec5, filt1); + + DUP2_ARG2(__lsx_vilvl_h, dst1, dst0, dst2, dst1, dst10_r, dst21_r); + DUP2_ARG2(__lsx_vilvh_h, dst1, dst0, dst2, dst1, dst10_l, dst21_l); + + DUP2_ARG3(__lsx_vshuf_b, src3, src3, mask0, src3, src3, mask1, + vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src4, src4, mask0, src4, src4, mask1, + vec2, vec3); + DUP2_ARG3(__lsx_vshuf_b, src5, src5, mask0, src5, src5, mask1, + vec4, vec5); + DUP2_ARG3(__lsx_vshuf_b, src6, src6, mask0, src6, src6, mask1, + vec6, vec7); + DUP4_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec2, filt0, vec4, filt0, + vec6, filt0, dst3, dst4, dst5, dst6); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst3, vec1, filt1, dst4, vec3, filt1, + dst5, vec5, filt1, dst6, vec7, filt1, dst3, dst4, dst5, dst6); + DUP2_ARG2(__lsx_vilvl_h, dst3, dst2, dst4, dst3, dst32_r, dst43_r); + DUP2_ARG2(__lsx_vilvh_h, dst3, dst2, dst4, dst3, dst32_l, dst43_l); + DUP2_ARG2(__lsx_vilvl_h, dst5, dst4, dst6, dst5, dst54_r, dst65_r); + DUP2_ARG2(__lsx_vilvh_h, dst5, dst4, dst6, dst5, dst54_l, dst65_l); + + DUP4_ARG2(__lsx_vdp2_w_h, dst10_r, filt_h0, dst10_l, filt_h0, dst21_r, + filt_h0, dst21_l, filt_h0, dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG3(__lsx_vdp2add_w_h, dst0_r, dst32_r, filt_h1, dst0_l, dst32_l, + filt_h1, dst1_r, dst43_r, filt_h1, dst1_l, dst43_l, filt_h1, + dst0_r, dst0_l, dst1_r, dst1_l); + + DUP4_ARG2(__lsx_vdp2_w_h, dst32_r, filt_h0, dst32_l, filt_h0, dst43_r, + filt_h0, dst43_l, filt_h0, dst2_r, dst2_l, dst3_r, dst3_l); + DUP4_ARG3(__lsx_vdp2add_w_h, dst2_r, dst54_r, filt_h1, dst2_l, dst54_l, + filt_h1, dst3_r, dst65_r, filt_h1, dst3_l, dst65_l, filt_h1, + dst2_r, dst2_l, dst3_r, dst3_l); + DUP4_ARG2(__lsx_vsrai_w, dst0_r, 6, dst0_l, 6, dst1_r, 6, dst1_l, 6, + dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG2(__lsx_vsrai_w, dst2_r, 6, dst2_l, 6, dst3_r, 6, dst3_l, 6, + dst2_r, dst2_l, dst3_r, dst3_l); + DUP2_ARG2(__lsx_vpickev_h, dst0_l, dst0_r, dst1_l, dst1_r, + dst0_r, dst1_r); + DUP2_ARG2(__lsx_vpickev_h, dst2_l, dst2_r, dst3_l, dst3_r, + dst2_r, dst3_r); + + __lsx_vst(dst0_r, dst, 0); + __lsx_vstx(dst1_r, dst, dst_stride_x); + __lsx_vstx(dst2_r, dst, dst_stride_2x); + __lsx_vstx(dst3_r, dst, dst_stride_3x); + dst += 8; + } +} + +static void hevc_hv_4t_8x6_lsx(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 src_stride_2x = (src_stride << 1); + int32_t dst_stride_2x = (dst_stride << 1); + int32_t src_stride_4x = (src_stride << 2); + int32_t src_stride_3x = src_stride_2x + src_stride; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8; + __m128i filt0, filt1; + __m128i filt_h0, filt_h1; + __m128i mask0 = __lsx_vld(ff_hevc_mask_arr, 0); + __m128i mask1, filter_vec; + __m128i vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7, vec8, vec9; + __m128i vec10, vec11, vec12, vec13, vec14, vec15, vec16, vec17; + __m128i dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7, dst8; + __m128i dst0_r, dst0_l, dst1_r, dst1_l, dst2_r, dst2_l, dst3_r, dst3_l; + __m128i dst4_r, dst4_l, dst5_r, dst5_l; + __m128i dst10_r, dst32_r, dst10_l, dst32_l; + __m128i dst21_r, dst43_r, dst21_l, dst43_l; + __m128i dst54_r, dst54_l, dst65_r, dst65_l; + __m128i dst76_r, dst76_l, dst87_r, dst87_l; + + src -= (src_stride + 1); + DUP2_ARG2(__lsx_vldrepl_h, filter_x, 0, filter_x, 2, filt0, filt1); + + filter_vec = __lsx_vld(filter_y, 0); + filter_vec = __lsx_vsllwil_h_b(filter_vec, 0); + DUP2_ARG2(__lsx_vreplvei_w, filter_vec, 0, filter_vec, 1, filt_h0, filt_h1); + + mask1 = __lsx_vaddi_bu(mask0, 2); + + src0 = __lsx_vld(src, 0); + DUP4_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src, + src_stride_3x, src, src_stride_4x, src1, src2, src3, src4); + src += src_stride_4x; + DUP4_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src, + src_stride_3x, src, src_stride_4x, src5, src6, src7, src8); + + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask0, src0, src0, mask1, src1, src1, + mask0, src1, src1, mask1, vec0, vec1, vec2, vec3); + DUP4_ARG3(__lsx_vshuf_b, src2, src2, mask0, src2, src2, mask1,src3, src3, + mask0, src3, src3, mask1, vec4, vec5, vec6, vec7); + DUP4_ARG3(__lsx_vshuf_b, src4, src4, mask0, src4, src4, mask1, src5, src5, + mask0, src5, src5, mask1, vec8, vec9, vec10, vec11); + DUP4_ARG3(__lsx_vshuf_b, src6, src6, mask0, src6, src6, mask1, src7, src7, + mask0, src7, src7, mask1, vec12, vec13, vec14, vec15); + DUP2_ARG3(__lsx_vshuf_b, src8, src8, mask0, src8, src8, mask1, + vec16, vec17); + + DUP4_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec2, filt0, vec4, filt0, vec6, + filt0, dst0, dst1, dst2, dst3); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec1, filt1, dst1, vec3, filt1, + dst2, vec5, filt1, dst3, vec7, filt1, dst0, dst1, dst2, dst3); + DUP4_ARG2(__lsx_vdp2_h_bu_b, vec8, filt0, vec10, filt0, vec12, filt0, + vec14, filt0, dst4, dst5, dst6, dst7); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst4, vec9, filt1, dst5, vec11, filt1, dst6, + vec13, filt1, dst7, vec15, filt1, dst4, dst5, dst6, dst7); + dst8 = __lsx_vdp2_h_bu_b(vec16, filt0); + dst8 = __lsx_vdp2add_h_bu_b(dst8, vec17, filt1); + + DUP4_ARG2(__lsx_vilvl_h, dst1, dst0, dst2, dst1, dst3, dst2, dst4, dst3, + dst10_r, dst21_r, dst32_r, dst43_r); + DUP4_ARG2(__lsx_vilvh_h, dst1, dst0, dst2, dst1, dst3, dst2, dst4, dst3, + dst10_l, dst21_l, dst32_l, dst43_l); + DUP4_ARG2(__lsx_vilvl_h, dst5, dst4, dst6, dst5, dst7, dst6, dst8, dst7, + dst54_r, dst65_r, dst76_r, dst87_r); + DUP4_ARG2(__lsx_vilvh_h, dst5, dst4, dst6, dst5, dst7, dst6, dst8, dst7, + dst54_l, dst65_l, dst76_l, dst87_l); + + DUP4_ARG2(__lsx_vdp2_w_h, dst10_r, filt_h0, dst10_l, filt_h0, dst21_r, + filt_h0, dst21_l, filt_h0, dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG2(__lsx_vdp2_w_h, dst32_r, filt_h0, dst32_l, filt_h0, dst43_r, + filt_h0, dst43_l, filt_h0, dst2_r, dst2_l, dst3_r, dst3_l); + DUP4_ARG2(__lsx_vdp2_w_h, dst54_r, filt_h0, dst54_l, filt_h0, dst65_r, + filt_h0, dst65_l, filt_h0, dst4_r, dst4_l, dst5_r, dst5_l); + DUP4_ARG3(__lsx_vdp2add_w_h, dst0_r, dst32_r, filt_h1, dst0_l, dst32_l, + filt_h1, dst1_r, dst43_r, filt_h1, dst1_l, dst43_l, filt_h1, + dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG3(__lsx_vdp2add_w_h, dst2_r, dst54_r, filt_h1, dst2_l, dst54_l, + filt_h1, dst3_r, dst65_r, filt_h1, dst3_l, dst65_l, filt_h1, + dst2_r, dst2_l, dst3_r, dst3_l); + DUP4_ARG3(__lsx_vdp2add_w_h, dst4_r, dst76_r, filt_h1, dst4_l, dst76_l, + filt_h1, dst5_r, dst87_r, filt_h1, dst5_l, dst87_l, filt_h1, + dst4_r, dst4_l, dst5_r, dst5_l); + DUP4_ARG2(__lsx_vsrai_w, dst0_r, 6, dst0_l, 6, dst1_r, 6, dst1_l, 6, dst0_r, + dst0_l, dst1_r, dst1_l); + DUP4_ARG2(__lsx_vsrai_w, dst2_r, 6, dst2_l, 6, dst3_r, 6, dst3_l, 6, dst2_r, + dst2_l, dst3_r, dst3_l); + DUP4_ARG2(__lsx_vsrai_w, dst4_r, 6, dst4_l, 6, dst5_r, 6, dst5_l, 6, dst4_r, + dst4_l, dst5_r, dst5_l); + + DUP4_ARG2(__lsx_vpickev_h,dst0_l, dst0_r, dst1_l, dst1_r, dst2_l, dst2_r, + dst3_l, dst3_r, dst0_r, dst1_r, dst2_r, dst3_r); + DUP2_ARG2(__lsx_vpickev_h, dst4_l, dst4_r, dst5_l, dst5_r, dst4_r, dst5_r); + + __lsx_vst(dst0_r, dst, 0); + __lsx_vstx(dst1_r, dst, dst_stride_2x); + dst += dst_stride_2x; + __lsx_vst(dst2_r, dst, 0); + __lsx_vstx(dst3_r, dst, dst_stride_2x); + dst += dst_stride_2x; + __lsx_vst(dst4_r, dst, 0); + __lsx_vstx(dst5_r, dst, dst_stride_2x); +} + +static void hevc_hv_4t_8multx4mult_lsx(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, + int32_t width8mult) +{ + uint32_t loop_cnt, cnt; + uint8_t *src_tmp; + int16_t *dst_tmp; + int32_t src_stride_2x = (src_stride << 1); + int32_t dst_stride_x = (dst_stride << 1); + int32_t src_stride_4x = (src_stride << 2); + int32_t dst_stride_2x = (dst_stride << 2); + int32_t src_stride_3x = src_stride_2x + src_stride; + int32_t dst_stride_3x = dst_stride_2x + dst_stride_x; + + __m128i src0, src1, src2, src3, src4, src5, src6; + __m128i filt0, filt1; + __m128i filt_h0, filt_h1; + __m128i mask0 = __lsx_vld(ff_hevc_mask_arr, 0); + __m128i mask1, filter_vec; + __m128i vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + __m128i dst0, dst1, dst2, dst3, dst4, dst5, dst6; + __m128i dst0_r, dst0_l, dst1_r, dst1_l, dst2_r, dst2_l, dst3_r, dst3_l; + __m128i dst10_r, dst32_r, dst54_r, dst21_r, dst43_r, dst65_r; + __m128i dst10_l, dst32_l, dst54_l, dst21_l, dst43_l, dst65_l; + + src -= (src_stride + 1); + DUP2_ARG2(__lsx_vldrepl_h, filter_x, 0, filter_x, 2, filt0, filt1); + + filter_vec = __lsx_vld(filter_y, 0); + filter_vec = __lsx_vsllwil_h_b(filter_vec, 0); + DUP2_ARG2(__lsx_vreplvei_w, filter_vec, 0, filter_vec, 1, filt_h0, filt_h1); + + mask1 = __lsx_vaddi_bu(mask0, 2); + + for (cnt = width8mult; cnt--;) { + src_tmp = src; + dst_tmp = dst; + + src0 = __lsx_vld(src_tmp, 0); + DUP2_ARG2(__lsx_vldx, src_tmp, src_stride, src_tmp, src_stride_2x, + src1, src2); + src_tmp += src_stride_3x; + + DUP2_ARG3(__lsx_vshuf_b, src0, src0, mask0, src0, src0, mask1, + vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src1, src1, mask0, src1, src1, mask1, + vec2, vec3); + DUP2_ARG3(__lsx_vshuf_b, src2, src2, mask0, src2, src2, mask1, + vec4, vec5); + + DUP2_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec2, filt0, dst0, dst1); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec1, filt1, dst1, vec3, filt1, + dst0, dst1); + dst2 = __lsx_vdp2_h_bu_b(vec4, filt0); + dst2 = __lsx_vdp2add_h_bu_b(dst2, vec5, filt1); + + DUP2_ARG2(__lsx_vilvl_h, dst1, dst0, dst2, dst1, dst10_r, dst21_r); + DUP2_ARG2(__lsx_vilvh_h, dst1, dst0, dst2, dst1, dst10_l, dst21_l); + + for (loop_cnt = height >> 2; loop_cnt--;) { + src3 = __lsx_vld(src_tmp, 0); + DUP2_ARG2(__lsx_vldx, src_tmp, src_stride, src_tmp, src_stride_2x, + src4, src5); + src6 = __lsx_vldx(src_tmp, src_stride_3x); + src_tmp += src_stride_4x; + + DUP2_ARG3(__lsx_vshuf_b, src3, src3, mask0, src3, src3, mask1, + vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src4, src4, mask0, src4, src4, mask1, + vec2, vec3); + DUP2_ARG3(__lsx_vshuf_b, src5, src5, mask0, src5, src5, mask1, + vec4, vec5); + DUP2_ARG3(__lsx_vshuf_b, src6, src6, mask0, src6, src6, mask1, + vec6, vec7); + + DUP4_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec2, filt0, vec4, filt0, + vec6, filt0, dst3, dst4, dst5, dst6); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst3, vec1, filt1, dst4, vec3, + filt1, dst5, vec5, filt1, dst6, vec7, filt1, dst3, + dst4, dst5, dst6); + + DUP2_ARG2(__lsx_vilvl_h, dst3, dst2, dst4, dst3, dst32_r, dst43_r); + DUP2_ARG2(__lsx_vilvh_h, dst3, dst2, dst4, dst3, dst32_l, dst43_l); + DUP2_ARG2(__lsx_vilvl_h, dst5, dst4, dst6, dst5, dst54_r, dst65_r); + DUP2_ARG2(__lsx_vilvh_h, dst5, dst4, dst6, dst5, dst54_l, dst65_l); + + DUP4_ARG2(__lsx_vdp2_w_h, dst10_r, filt_h0, dst10_l, filt_h0, dst21_r, + filt_h0, dst21_l, filt_h0, dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG2(__lsx_vdp2_w_h, dst32_r, filt_h0, dst32_l, filt_h0, dst43_r, + filt_h0, dst43_l, filt_h0, dst2_r, dst2_l, dst3_r, dst3_l); + DUP4_ARG3(__lsx_vdp2add_w_h, dst0_r, dst32_r, filt_h1, dst0_l, + dst32_l, filt_h1, dst1_r, dst43_r, filt_h1, dst1_l, + dst43_l, filt_h1, dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG3(__lsx_vdp2add_w_h, dst2_r, dst54_r, filt_h1, dst2_l, + dst54_l, filt_h1, dst3_r, dst65_r, filt_h1, dst3_l, + dst65_l, filt_h1, dst2_r, dst2_l, dst3_r, dst3_l); + + DUP4_ARG2(__lsx_vsrai_w, dst0_r, 6, dst0_l, 6, dst1_r, 6, dst1_l, 6, + dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG2(__lsx_vsrai_w, dst2_r, 6, dst2_l, 6, dst3_r, 6, dst3_l, 6, + dst2_r, dst2_l, dst3_r, dst3_l); + + DUP4_ARG2(__lsx_vpickev_h, dst0_l, dst0_r, dst1_l, dst1_r, dst2_l, + dst2_r, dst3_l, dst3_r, dst0_r, dst1_r, dst2_r, dst3_r); + + __lsx_vst(dst0_r, dst_tmp, 0); + __lsx_vstx(dst1_r, dst_tmp, dst_stride_x); + __lsx_vstx(dst2_r, dst_tmp, dst_stride_2x); + __lsx_vstx(dst3_r, dst_tmp, dst_stride_3x); + dst_tmp += dst_stride_2x; + + dst10_r = dst54_r; + dst10_l = dst54_l; + dst21_r = dst65_r; + dst21_l = dst65_l; + dst2 = dst6; + } + src += 8; + dst += 8; + } +} + +static void hevc_hv_4t_8w_lsx(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) +{ + + if (2 == height) { + hevc_hv_4t_8x2_lsx(src, src_stride, dst, dst_stride, + filter_x, filter_y); + } else if (4 == height) { + hevc_hv_4t_8multx4_lsx(src, src_stride, dst, dst_stride, + filter_x, filter_y, 1); + } else if (6 == height) { + hevc_hv_4t_8x6_lsx(src, src_stride, dst, dst_stride, + filter_x, filter_y); + } else if (0 == (height & 0x03)) { + hevc_hv_4t_8multx4mult_lsx(src, src_stride, dst, dst_stride, + filter_x, filter_y, height, 1); + } +} + +static void hevc_hv_4t_12w_lsx(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) +{ + uint32_t loop_cnt; + uint8_t *src_tmp; + int16_t *dst_tmp; + int32_t src_stride_2x = (src_stride << 1); + int32_t dst_stride_x = (dst_stride << 1); + int32_t src_stride_4x = (src_stride << 2); + int32_t dst_stride_2x = (dst_stride << 2); + int32_t src_stride_3x = src_stride_2x + src_stride; + int32_t dst_stride_3x = dst_stride_2x + dst_stride_x; + + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + __m128i vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + __m128i mask0, mask1, mask2, mask3; + __m128i filt0, filt1, filt_h0, filt_h1, filter_vec, dst0; + __m128i dst1, dst2, dst3, dst4, dst5, dst6, dst10, dst21, dst22, dst73; + __m128i dst84, dst95, dst106, dst76_r, dst98_r, dst87_r, dst109_r; + __m128i dst10_r, dst32_r, dst54_r, dst21_r, dst43_r, dst65_r; + __m128i dst10_l, dst32_l, dst54_l, dst21_l, dst43_l, dst65_l; + __m128i dst0_r, dst0_l, dst1_r, dst1_l, dst2_r, dst2_l, dst3_r, dst3_l; + __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + + src -= (src_stride + 1); + DUP2_ARG2(__lsx_vldrepl_h, filter_x, 0, filter_x, 2, filt0, filt1); + + filter_vec = __lsx_vld(filter_y, 0); + filter_vec = __lsx_vsllwil_h_b(filter_vec, 0); + DUP2_ARG2(__lsx_vreplvei_w, filter_vec, 0, filter_vec, 1, filt_h0, filt_h1); + + mask0 = __lsx_vld(ff_hevc_mask_arr, 0); + mask1 = __lsx_vaddi_bu(mask0, 2); + + src_tmp = src; + dst_tmp = dst; + + src0 = __lsx_vld(src_tmp, 0); + DUP2_ARG2(__lsx_vldx, src_tmp, src_stride, src_tmp, src_stride_2x, + src1, src2); + src_tmp += src_stride_3x; + + DUP2_ARG3(__lsx_vshuf_b, src0, src0, mask0, src0, src0, mask1, vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src1, src1, mask0, src1, src1, mask1, vec2, vec3); + DUP2_ARG3(__lsx_vshuf_b, src2, src2, mask0, src2, src2, mask1, vec4, vec5); + + DUP2_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec2, filt0, dst0, dst1); + dst2 = __lsx_vdp2_h_bu_b(vec4, filt0); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst0, vec1, filt1, dst1, vec3, filt1, + dst0, dst1); + dst2 = __lsx_vdp2add_h_bu_b(dst2, vec5, filt1); + + DUP2_ARG2(__lsx_vilvl_h, dst1, dst0, dst2, dst1, dst10_r, dst21_r); + DUP2_ARG2(__lsx_vilvh_h, dst1, dst0, dst2, dst1, dst10_l, dst21_l); + + for (loop_cnt = 4; loop_cnt--;) { + src3 = __lsx_vld(src_tmp, 0); + DUP2_ARG2(__lsx_vldx, src_tmp, src_stride, src_tmp, src_stride_2x, + src4, src5); + src6 = __lsx_vldx(src_tmp, src_stride_3x); + src_tmp += src_stride_4x; + + DUP2_ARG3(__lsx_vshuf_b, src3, src3, mask0, src3, src3, mask1, + vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src4, src4, mask0, src4, src4, mask1, + vec2, vec3); + DUP2_ARG3(__lsx_vshuf_b, src5, src5, mask0, src5, src5, mask1, + vec4, vec5); + DUP2_ARG3(__lsx_vshuf_b, src6, src6, mask0, src6, src6, mask1, + vec6, vec7); + + DUP4_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec2, filt0, vec4, filt0, + vec6, filt0, dst3, dst4, dst5, dst6); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst3, vec1, filt1, dst4, vec3, + filt1, dst5, vec5, filt1, dst6, vec7, filt1, dst3, + dst4, dst5, dst6); + + DUP2_ARG2(__lsx_vilvl_h, dst3, dst2, dst4, dst3, dst32_r, dst43_r); + DUP2_ARG2(__lsx_vilvh_h, dst3, dst2, dst4, dst3, dst32_l, dst43_l); + DUP2_ARG2(__lsx_vilvl_h, dst5, dst4, dst6, dst5, dst54_r, dst65_r); + DUP2_ARG2(__lsx_vilvh_h, dst5, dst4, dst6, dst5, dst54_l, dst65_l); + + DUP4_ARG2(__lsx_vdp2_w_h, dst10_r, filt_h0, dst10_l, filt_h0, dst21_r, + filt_h0, dst21_l, filt_h0, dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG2(__lsx_vdp2_w_h, dst32_r, filt_h0, dst32_l, filt_h0, dst43_r, + filt_h0, dst43_l, filt_h0, dst2_r, dst2_l, dst3_r, dst3_l); + DUP4_ARG3(__lsx_vdp2add_w_h, dst0_r, dst32_r, filt_h1, dst0_l, dst32_l, + filt_h1, dst1_r, dst43_r, filt_h1, dst1_l, dst43_l, filt_h1, + dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG3(__lsx_vdp2add_w_h, dst2_r, dst54_r, filt_h1, dst2_l, dst54_l, + filt_h1, dst3_r, dst65_r, filt_h1, dst3_l, dst65_l, filt_h1, + dst2_r, dst2_l, dst3_r, dst3_l); + DUP4_ARG2(__lsx_vsrai_w, dst0_r, 6, dst0_l, 6, dst1_r, 6, dst1_l, 6, + dst0_r, dst0_l, dst1_r, dst1_l); + DUP4_ARG2(__lsx_vsrai_w, dst2_r, 6, dst2_l, 6, dst3_r, 6, dst3_l, 6, + dst2_r, dst2_l, dst3_r, dst3_l); + DUP4_ARG2(__lsx_vpickev_h, dst0_l, dst0_r, dst1_l, dst1_r, dst2_l, dst2_r, + dst3_l, dst3_r, dst0_r, dst1_r, dst2_r, dst3_r); + __lsx_vst(dst0_r, dst_tmp, 0); + __lsx_vstx(dst1_r, dst_tmp, dst_stride_x); + __lsx_vstx(dst2_r, dst_tmp, dst_stride_2x); + __lsx_vstx(dst3_r, dst_tmp, dst_stride_3x); + dst_tmp += dst_stride_2x; + + dst10_r = dst54_r; + dst10_l = dst54_l; + dst21_r = dst65_r; + dst21_l = dst65_l; + dst2 = dst6; + } + + src += 8; + dst += 8; + + mask2 = __lsx_vld(ff_hevc_mask_arr, 16); + mask3 = __lsx_vaddi_bu(mask2, 2); + + src0 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src1, src2); + src += src_stride_3x; + DUP2_ARG3(__lsx_vshuf_b, src1, src0, mask2, src1, src0, mask3, vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src2, src1, mask2, src2, src1, mask3, vec2, vec3); + DUP2_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec2, filt0, dst10, dst21); + DUP2_ARG3(__lsx_vdp2add_h_bu_b, dst10, vec1, filt1, dst21, vec3, filt1, + dst10, dst21); + dst10_r = __lsx_vilvl_h(dst21, dst10); + dst21_r = __lsx_vilvh_h(dst21, dst10); + dst22 = __lsx_vreplvei_d(dst21, 1); + + for (loop_cnt = 2; loop_cnt--;) { + src3 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src4, src5); + src6 = __lsx_vldx(src, src_stride_3x); + src += src_stride_4x; + src7 = __lsx_vld(src, 0); + DUP2_ARG2(__lsx_vldx, src, src_stride, src, src_stride_2x, src8, src9); + src10 = __lsx_vldx(src, src_stride_3x); + src += src_stride_4x; + DUP2_ARG3(__lsx_vshuf_b, src7, src3, mask2, src7, src3, mask3, + vec0, vec1); + DUP2_ARG3(__lsx_vshuf_b, src8, src4, mask2, src8, src4, mask3, + vec2, vec3); + DUP2_ARG3(__lsx_vshuf_b, src9, src5, mask2, src9, src5, mask3, + vec4, vec5); + DUP2_ARG3(__lsx_vshuf_b, src10, src6, mask2, src10, src6, mask3, + vec6, vec7); + + DUP4_ARG2(__lsx_vdp2_h_bu_b, vec0, filt0, vec2, filt0, vec4, filt0, + vec6, filt0, dst73, dst84, dst95, dst106); + DUP4_ARG3(__lsx_vdp2add_h_bu_b, dst73, vec1, filt1, dst84, vec3, + filt1, dst95, vec5, filt1, dst106, vec7, filt1, dst73, + dst84, dst95, dst106); + + DUP2_ARG2(__lsx_vilvl_h, dst73, dst22, dst84, dst73, dst32_r, dst43_r); + DUP2_ARG2(__lsx_vilvh_h, dst84, dst73, dst95, dst84, dst87_r, dst98_r); + DUP2_ARG2(__lsx_vilvl_h, dst95, dst84, dst106, dst95, dst54_r, dst65_r); + dst109_r = __lsx_vilvh_h(dst106, dst95); + dst22 = __lsx_vreplvei_d(dst73, 1); + dst76_r = __lsx_vilvl_h(dst22, dst106); + + DUP4_ARG2(__lsx_vdp2_w_h, dst10_r, filt_h0, dst21_r, filt_h0, dst32_r, + filt_h0, dst43_r, filt_h0, tmp0, tmp1, tmp2, tmp3); + DUP4_ARG2(__lsx_vdp2_w_h, dst54_r, filt_h0, dst65_r, filt_h0, dst76_r, + filt_h0, dst87_r, filt_h0, tmp4, tmp5, tmp6, tmp7); + DUP4_ARG3(__lsx_vdp2add_w_h, tmp0, dst32_r, filt_h1, tmp1, dst43_r, + filt_h1, tmp2, dst54_r, filt_h1, tmp3, dst65_r, filt_h1, + tmp0, tmp1, tmp2, tmp3); + DUP4_ARG3(__lsx_vdp2add_w_h, tmp4, dst76_r, filt_h1, tmp5, dst87_r, + filt_h1, tmp6, dst98_r, filt_h1, tmp7, dst109_r, filt_h1, + tmp4, tmp5, tmp6, tmp7); + DUP4_ARG2(__lsx_vsrai_w, tmp0, 6, tmp1, 6, tmp2, 6, tmp3, 6, + tmp0, tmp1, tmp2, tmp3); + DUP4_ARG2(__lsx_vsrai_w, tmp4, 6, tmp5, 6, tmp6, 6, tmp7, 6, + tmp4, tmp5, tmp6, tmp7); + DUP4_ARG2(__lsx_vpickev_h, tmp1, tmp0, tmp3, tmp2, tmp5, tmp4, + tmp7, tmp6, tmp0, tmp1, tmp2, tmp3); + + __lsx_vstelm_d(tmp0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(tmp0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(tmp1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(tmp1, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(tmp2, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(tmp2, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(tmp3, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(tmp3, dst, 0, 1); + dst += dst_stride; + + dst10_r = dst98_r; + dst21_r = dst109_r; + dst22 = __lsx_vreplvei_d(dst106, 1); + } +} + +static void hevc_hv_4t_16w_lsx(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) +{ + if (4 == height) { + hevc_hv_4t_8multx4_lsx(src, src_stride, dst, dst_stride, + filter_x, filter_y, 2); + } else { + hevc_hv_4t_8multx4mult_lsx(src, src_stride, dst, dst_stride, + filter_x, filter_y, height, 2); + } +} + +static void hevc_hv_4t_24w_lsx(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) +{ + hevc_hv_4t_8multx4mult_lsx(src, src_stride, dst, dst_stride, + filter_x, filter_y, height, 3); +} + +static void hevc_hv_4t_32w_lsx(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) +{ + hevc_hv_4t_8multx4mult_lsx(src, src_stride, dst, dst_stride, + filter_x, filter_y, height, 4); +} + +#define MC_COPY(WIDTH) \ +void ff_hevc_put_hevc_pel_pixels##WIDTH##_8_lsx(int16_t *dst, \ + uint8_t *src, \ + ptrdiff_t src_stride, \ + int height, \ + intptr_t mx, \ + intptr_t my, \ + int width) \ +{ \ + hevc_copy_##WIDTH##w_lsx(src, src_stride, dst, MAX_PB_SIZE, height); \ +} + +MC_COPY(4); +MC_COPY(6); +MC_COPY(8); +MC_COPY(12); +MC_COPY(16); +MC_COPY(24); +MC_COPY(32); +MC_COPY(48); +MC_COPY(64); + +#undef MC_COPY + +#define MC(PEL, DIR, WIDTH, TAP, DIR1, FILT_DIR) \ +void ff_hevc_put_hevc_##PEL##_##DIR##WIDTH##_8_lsx(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_lsx(src, src_stride, dst, \ + MAX_PB_SIZE, filter, height); \ +} + +MC(qpel, h, 4, 8, hz, mx); +MC(qpel, h, 8, 8, hz, mx); +MC(qpel, h, 12, 8, hz, mx); +MC(qpel, h, 16, 8, hz, mx); +MC(qpel, h, 24, 8, hz, mx); +MC(qpel, h, 32, 8, hz, mx); +MC(qpel, h, 48, 8, hz, mx); +MC(qpel, h, 64, 8, hz, mx); + +MC(qpel, v, 4, 8, vt, my); +MC(qpel, v, 8, 8, vt, my); +MC(qpel, v, 12, 8, vt, my); +MC(qpel, v, 16, 8, vt, my); +MC(qpel, v, 24, 8, vt, my); +MC(qpel, v, 32, 8, vt, my); +MC(qpel, v, 48, 8, vt, my); +MC(qpel, v, 64, 8, vt, my); + +MC(epel, h, 32, 4, hz, mx); + +MC(epel, v, 16, 4, vt, my); +MC(epel, v, 24, 4, vt, my); +MC(epel, v, 32, 4, vt, my); + +#undef MC + +#define MC_HV(PEL, WIDTH, TAP) \ +void ff_hevc_put_hevc_##PEL##_hv##WIDTH##_8_lsx(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_lsx(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, 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 diff --git a/libavcodec/loongarch/hevcdsp_lsx.h b/libavcodec/loongarch/hevcdsp_lsx.h new file mode 100644 index 000000000..0c517af88 --- /dev/null +++ b/libavcodec/loongarch/hevcdsp_lsx.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2022 Loongson Technology Corporation Limited + * Contributed by Lu Wang + * Hao Chen + * + * 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_LOONGARCH_HEVCDSP_LSX_H +#define AVCODEC_LOONGARCH_HEVCDSP_LSX_H + +#include "libavcodec/hevcdsp.h" + +#define MC(PEL, DIR, WIDTH) \ +void ff_hevc_put_hevc_##PEL##_##DIR##WIDTH##_8_lsx(int16_t *dst, \ + uint8_t *src, \ + ptrdiff_t src_stride, \ + int height, \ + intptr_t mx, \ + intptr_t my, \ + int width) + +MC(pel, pixels, 4); +MC(pel, pixels, 6); +MC(pel, pixels, 8); +MC(pel, pixels, 12); +MC(pel, pixels, 16); +MC(pel, pixels, 24); +MC(pel, pixels, 32); +MC(pel, pixels, 48); +MC(pel, pixels, 64); + +MC(qpel, h, 4); +MC(qpel, h, 8); +MC(qpel, h, 12); +MC(qpel, h, 16); +MC(qpel, h, 24); +MC(qpel, h, 32); +MC(qpel, h, 48); +MC(qpel, h, 64); + +MC(qpel, v, 4); +MC(qpel, v, 8); +MC(qpel, v, 12); +MC(qpel, v, 16); +MC(qpel, v, 24); +MC(qpel, v, 32); +MC(qpel, v, 48); +MC(qpel, v, 64); + +MC(qpel, hv, 4); +MC(qpel, hv, 8); +MC(qpel, hv, 12); +MC(qpel, hv, 16); +MC(qpel, hv, 24); +MC(qpel, hv, 32); +MC(qpel, hv, 48); +MC(qpel, hv, 64); + +MC(epel, h, 32); + +MC(epel, v, 16); +MC(epel, v, 24); +MC(epel, v, 32); + +MC(epel, hv, 8); +MC(epel, hv, 12); +MC(epel, hv, 16); +MC(epel, hv, 24); +MC(epel, hv, 32); + +#undef MC + +#define BI_MC(PEL, DIR, WIDTH) \ +void ff_hevc_put_hevc_bi_##PEL##_##DIR##WIDTH##_8_lsx(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) + +BI_MC(pel, pixels, 4); +BI_MC(pel, pixels, 6); +BI_MC(pel, pixels, 8); +BI_MC(pel, pixels, 12); +BI_MC(pel, pixels, 16); +BI_MC(pel, pixels, 24); +BI_MC(pel, pixels, 32); +BI_MC(pel, pixels, 48); +BI_MC(pel, pixels, 64); + +BI_MC(qpel, h, 16); +BI_MC(qpel, h, 24); +BI_MC(qpel, h, 32); +BI_MC(qpel, h, 48); +BI_MC(qpel, h, 64); + +BI_MC(qpel, v, 8); +BI_MC(qpel, v, 16); +BI_MC(qpel, v, 24); +BI_MC(qpel, v, 32); +BI_MC(qpel, v, 48); +BI_MC(qpel, v, 64); + +BI_MC(qpel, hv, 8); +BI_MC(qpel, hv, 16); +BI_MC(qpel, hv, 24); +BI_MC(qpel, hv, 32); +BI_MC(qpel, hv, 48); +BI_MC(qpel, hv, 64); + +BI_MC(epel, h, 24); +BI_MC(epel, h, 32); + +BI_MC(epel, v, 12); +BI_MC(epel, v, 16); +BI_MC(epel, v, 24); +BI_MC(epel, v, 32); + +BI_MC(epel, hv, 6); +BI_MC(epel, hv, 8); +BI_MC(epel, hv, 16); +BI_MC(epel, hv, 24); +BI_MC(epel, hv, 32); + +#undef BI_MC + +#define UNI_MC(PEL, DIR, WIDTH) \ +void ff_hevc_put_hevc_uni_##PEL##_##DIR##WIDTH##_8_lsx(uint8_t *dst, \ + ptrdiff_t dst_stride, \ + uint8_t *src, \ + ptrdiff_t src_stride, \ + int height, \ + intptr_t mx, \ + intptr_t my, \ + int width) + +UNI_MC(qpel, h, 64); + +UNI_MC(qpel, v, 24); +UNI_MC(qpel, v, 32); +UNI_MC(qpel, v, 48); +UNI_MC(qpel, v, 64); + +UNI_MC(qpel, hv, 8); +UNI_MC(qpel, hv, 16); +UNI_MC(qpel, hv, 24); +UNI_MC(qpel, hv, 32); +UNI_MC(qpel, hv, 48); +UNI_MC(qpel, hv, 64); + +UNI_MC(epel, v, 24); +UNI_MC(epel, v, 32); + +UNI_MC(epel, hv, 8); +UNI_MC(epel, hv, 12); +UNI_MC(epel, hv, 16); +UNI_MC(epel, hv, 24); +UNI_MC(epel, hv, 32); + +#undef UNI_MC + +#define UNI_W_MC(PEL, DIR, WIDTH) \ +void ff_hevc_put_hevc_uni_w_##PEL##_##DIR##WIDTH##_8_lsx(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) + +UNI_W_MC(qpel, hv, 8); +UNI_W_MC(qpel, hv, 16); +UNI_W_MC(qpel, hv, 24); +UNI_W_MC(qpel, hv, 32); +UNI_W_MC(qpel, hv, 48); +UNI_W_MC(qpel, hv, 64); + +#undef UNI_W_MC + +void ff_hevc_loop_filter_luma_h_8_lsx(uint8_t *src, ptrdiff_t stride, + int32_t beta, int32_t *tc, + uint8_t *p_is_pcm, uint8_t *q_is_pcm); + +void ff_hevc_loop_filter_luma_v_8_lsx(uint8_t *src, ptrdiff_t stride, + int32_t beta, int32_t *tc, + uint8_t *p_is_pcm, uint8_t *q_is_pcm); + +void ff_hevc_loop_filter_chroma_h_8_lsx(uint8_t *src, ptrdiff_t stride, + int32_t *tc, uint8_t *p_is_pcm, + uint8_t *q_is_pcm); + +void ff_hevc_loop_filter_chroma_v_8_lsx(uint8_t *src, ptrdiff_t stride, + int32_t *tc, uint8_t *p_is_pcm, + uint8_t *q_is_pcm); + +void ff_hevc_sao_edge_filter_8_lsx(uint8_t *dst, uint8_t *src, + ptrdiff_t stride_dst, + int16_t *sao_offset_val, + int eo, int width, int height); + +void ff_hevc_idct_4x4_lsx(int16_t *coeffs, int col_limit); +void ff_hevc_idct_8x8_lsx(int16_t *coeffs, int col_limit); +void ff_hevc_idct_16x16_lsx(int16_t *coeffs, int col_limit); +void ff_hevc_idct_32x32_lsx(int16_t *coeffs, int col_limit); + +#endif // #ifndef AVCODEC_LOONGARCH_HEVCDSP_LSX_H diff --git a/libavcodec/loongarch/hpeldsp_init_loongarch.c b/libavcodec/loongarch/hpeldsp_init_loongarch.c new file mode 100644 index 000000000..1690be543 --- /dev/null +++ b/libavcodec/loongarch/hpeldsp_init_loongarch.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Shiyou Yin + * + * 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/loongarch/cpu.h" +#include "libavcodec/hpeldsp.h" +#include "libavcodec/loongarch/hpeldsp_lasx.h" + +void ff_hpeldsp_init_loongarch(HpelDSPContext *c, int flags) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_lasx(cpu_flags)) { + c->put_pixels_tab[0][0] = ff_put_pixels16_8_lsx; + c->put_pixels_tab[0][1] = ff_put_pixels16_x2_8_lasx; + c->put_pixels_tab[0][2] = ff_put_pixels16_y2_8_lasx; + c->put_pixels_tab[0][3] = ff_put_pixels16_xy2_8_lasx; + + c->put_pixels_tab[1][0] = ff_put_pixels8_8_lasx; + c->put_pixels_tab[1][1] = ff_put_pixels8_x2_8_lasx; + c->put_pixels_tab[1][2] = ff_put_pixels8_y2_8_lasx; + c->put_pixels_tab[1][3] = ff_put_pixels8_xy2_8_lasx; + c->put_no_rnd_pixels_tab[0][0] = ff_put_pixels16_8_lsx; + c->put_no_rnd_pixels_tab[0][1] = ff_put_no_rnd_pixels16_x2_8_lasx; + c->put_no_rnd_pixels_tab[0][2] = ff_put_no_rnd_pixels16_y2_8_lasx; + c->put_no_rnd_pixels_tab[0][3] = ff_put_no_rnd_pixels16_xy2_8_lasx; + + c->put_no_rnd_pixels_tab[1][0] = ff_put_pixels8_8_lasx; + c->put_no_rnd_pixels_tab[1][1] = ff_put_no_rnd_pixels8_x2_8_lasx; + c->put_no_rnd_pixels_tab[1][2] = ff_put_no_rnd_pixels8_y2_8_lasx; + c->put_no_rnd_pixels_tab[1][3] = ff_put_no_rnd_pixels8_xy2_8_lasx; + } +} diff --git a/libavcodec/loongarch/hpeldsp_lasx.c b/libavcodec/loongarch/hpeldsp_lasx.c new file mode 100644 index 000000000..dd2ae173d --- /dev/null +++ b/libavcodec/loongarch/hpeldsp_lasx.c @@ -0,0 +1,1287 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Shiyou Yin + * + * 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/loongarch/loongson_intrinsics.h" +#include "hpeldsp_lasx.h" + +static av_always_inline void +put_pixels8_l2_8_lsx(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, + int dst_stride, int src_stride1, int src_stride2, int h) +{ + int stride1_2, stride1_3, stride1_4; + int stride2_2, stride2_3, stride2_4; + __asm__ volatile ( + "slli.d %[stride1_2], %[srcStride1], 1 \n\t" + "slli.d %[stride2_2], %[srcStride2], 1 \n\t" + "add.d %[stride1_3], %[stride1_2], %[srcStride1] \n\t" + "add.d %[stride2_3], %[stride2_2], %[srcStride2] \n\t" + "slli.d %[stride1_4], %[stride1_2], 1 \n\t" + "slli.d %[stride2_4], %[stride2_2], 1 \n\t" + "1: \n\t" + "vld $vr0, %[src1], 0 \n\t" + "vldx $vr1, %[src1], %[srcStride1] \n\t" + "vldx $vr2, %[src1], %[stride1_2] \n\t" + "vldx $vr3, %[src1], %[stride1_3] \n\t" + "add.d %[src1], %[src1], %[stride1_4] \n\t" + + "vld $vr4, %[src2], 0 \n\t" + "vldx $vr5, %[src2], %[srcStride2] \n\t" + "vldx $vr6, %[src2], %[stride2_2] \n\t" + "vldx $vr7, %[src2], %[stride2_3] \n\t" + "add.d %[src2], %[src2], %[stride2_4] \n\t" + + "addi.d %[h], %[h], -4 \n\t" + + "vavgr.bu $vr0, $vr4, $vr0 \n\t" + "vavgr.bu $vr1, $vr5, $vr1 \n\t" + "vavgr.bu $vr2, $vr6, $vr2 \n\t" + "vavgr.bu $vr3, $vr7, $vr3 \n\t" + "vstelm.d $vr0, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[dstStride] \n\t" + "vstelm.d $vr1, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[dstStride] \n\t" + "vstelm.d $vr2, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[dstStride] \n\t" + "vstelm.d $vr3, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[dstStride] \n\t" + "bnez %[h], 1b \n\t" + + : [dst]"+&r"(dst), [src2]"+&r"(src2), [src1]"+&r"(src1), + [h]"+&r"(h), [stride1_2]"=&r"(stride1_2), + [stride1_3]"=&r"(stride1_3), [stride1_4]"=&r"(stride1_4), + [stride2_2]"=&r"(stride2_2), [stride2_3]"=&r"(stride2_3), + [stride2_4]"=&r"(stride2_4) + : [dstStride]"r"(dst_stride), [srcStride1]"r"(src_stride1), + [srcStride2]"r"(src_stride2) + : "memory" + ); +} + +static av_always_inline void +put_pixels16_l2_8_lsx(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, + int dst_stride, int src_stride1, int src_stride2, int h) +{ + int stride1_2, stride1_3, stride1_4; + int stride2_2, stride2_3, stride2_4; + int dststride2, dststride3, dststride4; + __asm__ volatile ( + "slli.d %[stride1_2], %[srcStride1], 1 \n\t" + "slli.d %[stride2_2], %[srcStride2], 1 \n\t" + "slli.d %[dststride2], %[dstStride], 1 \n\t" + "add.d %[stride1_3], %[stride1_2], %[srcStride1] \n\t" + "add.d %[stride2_3], %[stride2_2], %[srcStride2] \n\t" + "add.d %[dststride3], %[dststride2], %[dstStride] \n\t" + "slli.d %[stride1_4], %[stride1_2], 1 \n\t" + "slli.d %[stride2_4], %[stride2_2], 1 \n\t" + "slli.d %[dststride4], %[dststride2], 1 \n\t" + "1: \n\t" + "vld $vr0, %[src1], 0 \n\t" + "vldx $vr1, %[src1], %[srcStride1] \n\t" + "vldx $vr2, %[src1], %[stride1_2] \n\t" + "vldx $vr3, %[src1], %[stride1_3] \n\t" + "add.d %[src1], %[src1], %[stride1_4] \n\t" + + "vld $vr4, %[src2], 0 \n\t" + "vldx $vr5, %[src2], %[srcStride2] \n\t" + "vldx $vr6, %[src2], %[stride2_2] \n\t" + "vldx $vr7, %[src2], %[stride2_3] \n\t" + "add.d %[src2], %[src2], %[stride2_4] \n\t" + + "addi.d %[h], %[h], -4 \n\t" + + "vavgr.bu $vr0, $vr4, $vr0 \n\t" + "vavgr.bu $vr1, $vr5, $vr1 \n\t" + "vavgr.bu $vr2, $vr6, $vr2 \n\t" + "vavgr.bu $vr3, $vr7, $vr3 \n\t" + "vst $vr0, %[dst], 0 \n\t" + "vstx $vr1, %[dst], %[dstStride] \n\t" + "vstx $vr2, %[dst], %[dststride2] \n\t" + "vstx $vr3, %[dst], %[dststride3] \n\t" + "add.d %[dst], %[dst], %[dststride4] \n\t" + "bnez %[h], 1b \n\t" + + : [dst]"+&r"(dst), [src2]"+&r"(src2), [src1]"+&r"(src1), + [h]"+&r"(h), [stride1_2]"=&r"(stride1_2), + [stride1_3]"=&r"(stride1_3), [stride1_4]"=&r"(stride1_4), + [stride2_2]"=&r"(stride2_2), [stride2_3]"=&r"(stride2_3), + [stride2_4]"=&r"(stride2_4), [dststride2]"=&r"(dststride2), + [dststride3]"=&r"(dststride3), [dststride4]"=&r"(dststride4) + : [dstStride]"r"(dst_stride), [srcStride1]"r"(src_stride1), + [srcStride2]"r"(src_stride2) + : "memory" + ); +} + +void ff_put_pixels8_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + uint64_t tmp[8]; + int h_8 = h >> 3; + int res = h & 7; + ptrdiff_t stride2, stride3, stride4; + + __asm__ volatile ( + "beqz %[h_8], 2f \n\t" + "slli.d %[stride2], %[stride], 1 \n\t" + "add.d %[stride3], %[stride2], %[stride] \n\t" + "slli.d %[stride4], %[stride2], 1 \n\t" + "1: \n\t" + "ld.d %[tmp0], %[src], 0x0 \n\t" + "ldx.d %[tmp1], %[src], %[stride] \n\t" + "ldx.d %[tmp2], %[src], %[stride2] \n\t" + "ldx.d %[tmp3], %[src], %[stride3] \n\t" + "add.d %[src], %[src], %[stride4] \n\t" + "ld.d %[tmp4], %[src], 0x0 \n\t" + "ldx.d %[tmp5], %[src], %[stride] \n\t" + "ldx.d %[tmp6], %[src], %[stride2] \n\t" + "ldx.d %[tmp7], %[src], %[stride3] \n\t" + "add.d %[src], %[src], %[stride4] \n\t" + + "addi.d %[h_8], %[h_8], -1 \n\t" + + "st.d %[tmp0], %[dst], 0x0 \n\t" + "stx.d %[tmp1], %[dst], %[stride] \n\t" + "stx.d %[tmp2], %[dst], %[stride2] \n\t" + "stx.d %[tmp3], %[dst], %[stride3] \n\t" + "add.d %[dst], %[dst], %[stride4] \n\t" + "st.d %[tmp4], %[dst], 0x0 \n\t" + "stx.d %[tmp5], %[dst], %[stride] \n\t" + "stx.d %[tmp6], %[dst], %[stride2] \n\t" + "stx.d %[tmp7], %[dst], %[stride3] \n\t" + "add.d %[dst], %[dst], %[stride4] \n\t" + "bnez %[h_8], 1b \n\t" + + "2: \n\t" + "beqz %[res], 4f \n\t" + "3: \n\t" + "ld.d %[tmp0], %[src], 0x0 \n\t" + "add.d %[src], %[src], %[stride] \n\t" + "addi.d %[res], %[res], -1 \n\t" + "st.d %[tmp0], %[dst], 0x0 \n\t" + "add.d %[dst], %[dst], %[stride] \n\t" + "bnez %[res], 3b \n\t" + "4: \n\t" + : [tmp0]"=&r"(tmp[0]), [tmp1]"=&r"(tmp[1]), + [tmp2]"=&r"(tmp[2]), [tmp3]"=&r"(tmp[3]), + [tmp4]"=&r"(tmp[4]), [tmp5]"=&r"(tmp[5]), + [tmp6]"=&r"(tmp[6]), [tmp7]"=&r"(tmp[7]), + [dst]"+&r"(block), [src]"+&r"(pixels), + [h_8]"+&r"(h_8), [res]"+&r"(res), + [stride2]"=&r"(stride2), [stride3]"=&r"(stride3), + [stride4]"=&r"(stride4) + : [stride]"r"(line_size) + : "memory" + ); +} + +void ff_put_pixels16_8_lsx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + int h_8 = h >> 3; + int res = h & 7; + ptrdiff_t stride2, stride3, stride4; + + __asm__ volatile ( + "beqz %[h_8], 2f \n\t" + "slli.d %[stride2], %[stride], 1 \n\t" + "add.d %[stride3], %[stride2], %[stride] \n\t" + "slli.d %[stride4], %[stride2], 1 \n\t" + "1: \n\t" + "vld $vr0, %[src], 0x0 \n\t" + "vldx $vr1, %[src], %[stride] \n\t" + "vldx $vr2, %[src], %[stride2] \n\t" + "vldx $vr3, %[src], %[stride3] \n\t" + "add.d %[src], %[src], %[stride4] \n\t" + "vld $vr4, %[src], 0x0 \n\t" + "vldx $vr5, %[src], %[stride] \n\t" + "vldx $vr6, %[src], %[stride2] \n\t" + "vldx $vr7, %[src], %[stride3] \n\t" + "add.d %[src], %[src], %[stride4] \n\t" + + "addi.d %[h_8], %[h_8], -1 \n\t" + + "vst $vr0, %[dst], 0x0 \n\t" + "vstx $vr1, %[dst], %[stride] \n\t" + "vstx $vr2, %[dst], %[stride2] \n\t" + "vstx $vr3, %[dst], %[stride3] \n\t" + "add.d %[dst], %[dst], %[stride4] \n\t" + "vst $vr4, %[dst], 0x0 \n\t" + "vstx $vr5, %[dst], %[stride] \n\t" + "vstx $vr6, %[dst], %[stride2] \n\t" + "vstx $vr7, %[dst], %[stride3] \n\t" + "add.d %[dst], %[dst], %[stride4] \n\t" + "bnez %[h_8], 1b \n\t" + + "2: \n\t" + "beqz %[res], 4f \n\t" + "3: \n\t" + "vld $vr0, %[src], 0x0 \n\t" + "add.d %[src], %[src], %[stride] \n\t" + "addi.d %[res], %[res], -1 \n\t" + "vst $vr0, %[dst], 0x0 \n\t" + "add.d %[dst], %[dst], %[stride] \n\t" + "bnez %[res], 3b \n\t" + "4: \n\t" + : [dst]"+&r"(block), [src]"+&r"(pixels), + [h_8]"+&r"(h_8), [res]"+&r"(res), + [stride2]"=&r"(stride2), [stride3]"=&r"(stride3), + [stride4]"=&r"(stride4) + : [stride]"r"(line_size) + : "memory" + ); +} + +void ff_put_pixels8_x2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + put_pixels8_l2_8_lsx(block, pixels, pixels + 1, line_size, line_size, + line_size, h); +} + +void ff_put_pixels8_y2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + put_pixels8_l2_8_lsx(block, pixels, pixels + line_size, line_size, + line_size, line_size, h); +} + +void ff_put_pixels16_x2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + put_pixels16_l2_8_lsx(block, pixels, pixels + 1, line_size, line_size, + line_size, h); +} + +void ff_put_pixels16_y2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + put_pixels16_l2_8_lsx(block, pixels, pixels + line_size, line_size, + line_size, line_size, h); +} + +static void common_hz_bil_no_rnd_16x16_lasx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, int32_t dst_stride) +{ + __m256i src0, src1, src2, src3, src4, src5, src6, src7; + int32_t src_stride_2x = src_stride << 1; + int32_t src_stride_4x = src_stride << 2; + int32_t src_stride_3x = src_stride_2x + src_stride; + uint8_t *_src = (uint8_t*)src; + + src0 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src1, src2); + src3 = __lasx_xvldx(_src, src_stride_3x); + _src += 1; + src4 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src5, src6); + src7 = __lasx_xvldx(_src, src_stride_3x); + _src += (src_stride_4x -1); + DUP4_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src3, src2, 0x20, src5, + src4, 0x20, src7, src6, 0x20, src0, src1, src2, src3); + src0 = __lasx_xvavg_bu(src0, src2); + src1 = __lasx_xvavg_bu(src1, src3); + __lasx_xvstelm_d(src0, dst, 0, 0); + __lasx_xvstelm_d(src0, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src0, dst, 0, 2); + __lasx_xvstelm_d(src0, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(src1, dst, 0, 0); + __lasx_xvstelm_d(src1, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src1, dst, 0, 2); + __lasx_xvstelm_d(src1, dst, 8, 3); + dst += dst_stride; + + src0 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src1, src2); + src3 = __lasx_xvldx(_src, src_stride_3x); + _src += 1; + src4 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src5, src6); + src7 = __lasx_xvldx(_src, src_stride_3x); + _src += (src_stride_4x - 1); + DUP4_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src3, src2, 0x20, src5, src4, + 0x20, src7, src6, 0x20, src0, src1, src2, src3); + src0 = __lasx_xvavg_bu(src0, src2); + src1 = __lasx_xvavg_bu(src1, src3); + __lasx_xvstelm_d(src0, dst, 0, 0); + __lasx_xvstelm_d(src0, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src0, dst, 0, 2); + __lasx_xvstelm_d(src0, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(src1, dst, 0, 0); + __lasx_xvstelm_d(src1, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src1, dst, 0, 2); + __lasx_xvstelm_d(src1, dst, 8, 3); + dst += dst_stride; + + src0 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src1, src2); + src3 = __lasx_xvldx(_src, src_stride_3x); + _src += 1; + src4 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src5, src6); + src7 = __lasx_xvldx(_src, src_stride_3x); + _src += (src_stride_4x - 1); + DUP4_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src3, src2, 0x20, src5, src4, + 0x20, src7, src6, 0x20, src0, src1, src2, src3); + src0 = __lasx_xvavg_bu(src0, src2); + src1 = __lasx_xvavg_bu(src1, src3); + __lasx_xvstelm_d(src0, dst, 0, 0); + __lasx_xvstelm_d(src0, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src0, dst, 0, 2); + __lasx_xvstelm_d(src0, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(src1, dst, 0, 0); + __lasx_xvstelm_d(src1, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src1, dst, 0, 2); + __lasx_xvstelm_d(src1, dst, 8, 3); + dst += dst_stride; + + src0 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src1, src2); + src3 = __lasx_xvldx(_src, src_stride_3x); + _src += 1; + src4 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src5, src6); + src7 = __lasx_xvldx(_src, src_stride_3x); + DUP4_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src3, src2, 0x20, src5, src4, + 0x20, src7, src6, 0x20, src0, src1, src2, src3); + src0 = __lasx_xvavg_bu(src0, src2); + src1 = __lasx_xvavg_bu(src1, src3); + __lasx_xvstelm_d(src0, dst, 0, 0); + __lasx_xvstelm_d(src0, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src0, dst, 0, 2); + __lasx_xvstelm_d(src0, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(src1, dst, 0, 0); + __lasx_xvstelm_d(src1, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src1, dst, 0, 2); + __lasx_xvstelm_d(src1, dst, 8, 3); +} + +static void common_hz_bil_no_rnd_8x16_lasx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, int32_t dst_stride) +{ + __m256i src0, src1, src2, src3, src4, src5, src6, src7; + int32_t src_stride_2x = src_stride << 1; + int32_t src_stride_4x = src_stride << 2; + int32_t src_stride_3x = src_stride_2x + src_stride; + uint8_t* _src = (uint8_t*)src; + + src0 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src1, src2); + src3 = __lasx_xvldx(_src, src_stride_3x); + _src += 1; + src4 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src5, src6); + src7 = __lasx_xvldx(_src, src_stride_3x); + _src += (src_stride_4x - 1); + DUP4_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src3, src2, 0x20, src5, src4, + 0x20, src7, src6, 0x20, src0, src1, src2, src3); + src0 = __lasx_xvavg_bu(src0, src2); + src1 = __lasx_xvavg_bu(src1, src3); + __lasx_xvstelm_d(src0, dst, 0, 0); + __lasx_xvstelm_d(src0, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src0, dst, 0, 2); + __lasx_xvstelm_d(src0, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(src1, dst, 0, 0); + __lasx_xvstelm_d(src1, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src1, dst, 0, 2); + __lasx_xvstelm_d(src1, dst, 8, 3); + dst += dst_stride; + + src0 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src1, src2); + src3 = __lasx_xvldx(_src, src_stride_3x); + _src += 1; + src4 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src5, src6); + src7 = __lasx_xvldx(_src, src_stride_3x); + DUP4_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src3, src2, 0x20, src5, src4, + 0x20, src7, src6, 0x20, src0, src1, src2, src3); + src0 = __lasx_xvavg_bu(src0, src2); + src1 = __lasx_xvavg_bu(src1, src3); + __lasx_xvstelm_d(src0, dst, 0, 0); + __lasx_xvstelm_d(src0, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src0, dst, 0, 2); + __lasx_xvstelm_d(src0, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(src1, dst, 0, 0); + __lasx_xvstelm_d(src1, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src1, dst, 0, 2); + __lasx_xvstelm_d(src1, dst, 8, 3); +} + +void ff_put_no_rnd_pixels16_x2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + if (h == 16) { + common_hz_bil_no_rnd_16x16_lasx(pixels, line_size, block, line_size); + } else if (h == 8) { + common_hz_bil_no_rnd_8x16_lasx(pixels, line_size, block, line_size); + } +} + +static void common_vt_bil_no_rnd_16x16_lasx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, int32_t dst_stride) +{ + __m256i src0, src1, src2, src3, src4, src5, src6, src7, src8; + __m256i src9, src10, src11, src12, src13, src14, src15, src16; + int32_t src_stride_2x = src_stride << 1; + int32_t src_stride_4x = src_stride << 2; + int32_t src_stride_3x = src_stride_2x + src_stride; + uint8_t* _src = (uint8_t*)src; + + src0 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src1, src2); + src3 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src4 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src5, src6); + src7 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src8 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src9, src10); + src11 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src12 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, + src13, src14); + src15 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src16 = __lasx_xvld(_src, 0); + + DUP4_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src2, src1, 0x20, src3, src2, + 0x20, src4, src3, 0x20, src0, src1, src2, src3); + DUP4_ARG3(__lasx_xvpermi_q, src5, src4, 0x20, src6, src5, 0x20, src7, src6, + 0x20, src8, src7, 0x20, src4, src5, src6, src7); + DUP4_ARG3(__lasx_xvpermi_q, src9, src8, 0x20, src10, src9, 0x20, src11, + src10, 0x20, src12, src11, 0x20, src8, src9, src10, src11); + DUP4_ARG3(__lasx_xvpermi_q, src13, src12, 0x20, src14, src13, 0x20, src15, + src14, 0x20, src16, src15, 0x20, src12, src13, src14, src15); + DUP4_ARG2(__lasx_xvavg_bu, src0, src1, src2, src3, src4, src5, src6, src7, + src0, src2, src4, src6); + DUP4_ARG2(__lasx_xvavg_bu, src8, src9, src10, src11, src12, src13, src14, + src15, src8, src10, src12, src14); + + __lasx_xvstelm_d(src0, dst, 0, 0); + __lasx_xvstelm_d(src0, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src0, dst, 0, 2); + __lasx_xvstelm_d(src0, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(src2, dst, 0, 0); + __lasx_xvstelm_d(src2, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src2, dst, 0, 2); + __lasx_xvstelm_d(src2, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(src4, dst, 0, 0); + __lasx_xvstelm_d(src4, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src4, dst, 0, 2); + __lasx_xvstelm_d(src4, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(src6, dst, 0, 0); + __lasx_xvstelm_d(src6, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src6, dst, 0, 2); + __lasx_xvstelm_d(src6, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(src8, dst, 0, 0); + __lasx_xvstelm_d(src8, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src8, dst, 0, 2); + __lasx_xvstelm_d(src8, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(src10, dst, 0, 0); + __lasx_xvstelm_d(src10, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src10, dst, 0, 2); + __lasx_xvstelm_d(src10, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(src12, dst, 0, 0); + __lasx_xvstelm_d(src12, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src12, dst, 0, 2); + __lasx_xvstelm_d(src12, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(src14, dst, 0, 0); + __lasx_xvstelm_d(src14, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src14, dst, 0, 2); + __lasx_xvstelm_d(src14, dst, 8, 3); +} + +static void common_vt_bil_no_rnd_8x16_lasx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, int32_t dst_stride) +{ + __m256i src0, src1, src2, src3, src4, src5, src6, src7, src8; + int32_t src_stride_2x = src_stride << 1; + int32_t src_stride_4x = src_stride << 2; + int32_t src_stride_3x = src_stride_2x + src_stride; + uint8_t* _src = (uint8_t*)src; + + src0 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src1, src2); + src3 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src4 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src5, src6); + src7 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src8 = __lasx_xvld(_src, 0); + + DUP4_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src2, src1, 0x20, src3, src2, + 0x20, src4, src3, 0x20, src0, src1, src2, src3); + DUP4_ARG3(__lasx_xvpermi_q, src5, src4, 0x20, src6, src5, 0x20, src7, src6, + 0x20, src8, src7, 0x20, src4, src5, src6, src7); + DUP4_ARG2(__lasx_xvavg_bu, src0, src1, src2, src3, src4, src5, src6, src7, + src0, src2, src4, src6); + + __lasx_xvstelm_d(src0, dst, 0, 0); + __lasx_xvstelm_d(src0, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src0, dst, 0, 2); + __lasx_xvstelm_d(src0, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(src2, dst, 0, 0); + __lasx_xvstelm_d(src2, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src2, dst, 0, 2); + __lasx_xvstelm_d(src2, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(src4, dst, 0, 0); + __lasx_xvstelm_d(src4, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src4, dst, 0, 2); + __lasx_xvstelm_d(src4, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(src6, dst, 0, 0); + __lasx_xvstelm_d(src6, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(src6, dst, 0, 2); + __lasx_xvstelm_d(src6, dst, 8, 3); +} + +void ff_put_no_rnd_pixels16_y2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + if (h == 16) { + common_vt_bil_no_rnd_16x16_lasx(pixels, line_size, block, line_size); + } else if (h == 8) { + common_vt_bil_no_rnd_8x16_lasx(pixels, line_size, block, line_size); + } +} + +static void common_hv_bil_no_rnd_16x16_lasx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, int32_t dst_stride) +{ + __m256i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9; + __m256i src10, src11, src12, src13, src14, src15, src16, src17; + __m256i sum0, sum1, sum2, sum3, sum4, sum5, sum6, sum7; + int32_t src_stride_2x = src_stride << 1; + int32_t src_stride_4x = src_stride << 2; + int32_t src_stride_3x = src_stride_2x + src_stride; + uint8_t* _src = (uint8_t*)src; + + src0 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src1, src2); + src3 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src4 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src5, src6); + src7 = __lasx_xvldx(_src, src_stride_3x); + _src += (1 - src_stride_4x); + src9 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, + src10, src11); + src12 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src13 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, + src14, src15); + src16 = __lasx_xvldx(_src, src_stride_3x); + _src += (src_stride_4x - 1); + DUP2_ARG2(__lasx_xvld, _src, 0, _src, 1, src8, src17); + + DUP4_ARG3(__lasx_xvpermi_q, src0, src4, 0x02, src1, src5, 0x02, src2, + src6, 0x02, src3, src7, 0x02, src0, src1, src2, src3); + DUP4_ARG3(__lasx_xvpermi_q, src4, src8, 0x02, src9, src13, 0x02, src10, + src14, 0x02, src11, src15, 0x02, src4, src5, src6, src7); + DUP2_ARG3(__lasx_xvpermi_q, src12, src16, 0x02, src13, src17, 0x02, + src8, src9); + DUP4_ARG2(__lasx_xvilvl_h, src5, src0, src6, src1, src7, src2, src8, src3, + sum0, sum2, sum4, sum6); + DUP4_ARG2(__lasx_xvilvh_h, src5, src0, src6, src1, src7, src2, src8, src3, + sum1, sum3, sum5, sum7); + src8 = __lasx_xvilvl_h(src9, src4); + src9 = __lasx_xvilvh_h(src9, src4); + + DUP4_ARG2(__lasx_xvhaddw_hu_bu, sum0, sum0, sum1, sum1, sum2, sum2, + sum3, sum3, src0, src1, src2, src3); + DUP4_ARG2(__lasx_xvhaddw_hu_bu, sum4, sum4, sum5, sum5, sum6, sum6, + sum7, sum7, src4, src5, src6, src7); + DUP2_ARG2(__lasx_xvhaddw_hu_bu, src8, src8, src9, src9, src8, src9); + + DUP4_ARG2(__lasx_xvadd_h, src0, src2, src1, src3, src2, src4, src3, src5, + sum0, sum1, sum2, sum3); + DUP4_ARG2(__lasx_xvadd_h, src4, src6, src5, src7, src6, src8, src7, src9, + sum4, sum5, sum6, sum7); + DUP4_ARG2(__lasx_xvaddi_hu, sum0, 1, sum1, 1, sum2, 1, sum3, 1, + sum0, sum1, sum2, sum3); + DUP4_ARG2(__lasx_xvaddi_hu, sum4, 1, sum5, 1, sum6, 1, sum7, 1, + sum4, sum5, sum6, sum7); + DUP4_ARG3(__lasx_xvsrani_b_h, sum1, sum0, 2, sum3, sum2, 2, sum5, sum4, 2, + sum7, sum6, 2, sum0, sum1, sum2, sum3); + __lasx_xvstelm_d(sum0, dst, 0, 0); + __lasx_xvstelm_d(sum0, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(sum1, dst, 0, 0); + __lasx_xvstelm_d(sum1, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(sum2, dst, 0, 0); + __lasx_xvstelm_d(sum2, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(sum3, dst, 0, 0); + __lasx_xvstelm_d(sum3, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(sum0, dst, 0, 2); + __lasx_xvstelm_d(sum0, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(sum1, dst, 0, 2); + __lasx_xvstelm_d(sum1, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(sum2, dst, 0, 2); + __lasx_xvstelm_d(sum2, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(sum3, dst, 0, 2); + __lasx_xvstelm_d(sum3, dst, 8, 3); + dst += dst_stride; + + src0 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src1, src2); + src3 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src4 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src5, src6); + src7 = __lasx_xvldx(_src, src_stride_3x); + _src += (1 - src_stride_4x); + src9 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, + src10, src11); + src12 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src13 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, + src14, src15); + src16 = __lasx_xvldx(_src, src_stride_3x); + _src += (src_stride_4x - 1); + DUP2_ARG2(__lasx_xvld, _src, 0, _src, 1, src8, src17); + + DUP4_ARG3(__lasx_xvpermi_q, src0, src4, 0x02, src1, src5, 0x02, src2, src6, 0x02, + src3, src7, 0x02, src0, src1, src2, src3); + DUP4_ARG3(__lasx_xvpermi_q, src4, src8, 0x02, src9, src13, 0x02, src10, src14, 0x02, + src11, src15, 0x02, src4, src5, src6, src7); + DUP2_ARG3(__lasx_xvpermi_q, src12, src16, 0x02, src13, src17, 0x02, src8, src9); + + DUP4_ARG2(__lasx_xvilvl_h, src5, src0, src6, src1, src7, src2, src8, src3, + sum0, sum2, sum4, sum6); + DUP4_ARG2(__lasx_xvilvh_h, src5, src0, src6, src1, src7, src2, src8, src3, + sum1, sum3, sum5, sum7); + src8 = __lasx_xvilvl_h(src9, src4); + src9 = __lasx_xvilvh_h(src9, src4); + + DUP4_ARG2(__lasx_xvhaddw_hu_bu, sum0, sum0, sum1, sum1, sum2, sum2, + sum3, sum3, src0, src1, src2, src3); + DUP4_ARG2(__lasx_xvhaddw_hu_bu, sum4, sum4, sum5, sum5, sum6, sum6, + sum7, sum7, src4, src5, src6, src7); + DUP2_ARG2(__lasx_xvhaddw_hu_bu, src8, src8, src9, src9, src8, src9); + + DUP4_ARG2(__lasx_xvadd_h, src0, src2, src1, src3, src2, src4, src3, src5, + sum0, sum1, sum2, sum3); + DUP4_ARG2(__lasx_xvadd_h, src4, src6, src5, src7, src6, src8, src7, src9, + sum4, sum5, sum6, sum7); + DUP4_ARG2(__lasx_xvaddi_hu, sum0, 1, sum1, 1, sum2, 1, sum3, 1, + sum0, sum1, sum2, sum3); + DUP4_ARG2(__lasx_xvaddi_hu, sum4, 1, sum5, 1, sum6, 1, sum7, 1, + sum4, sum5, sum6, sum7); + DUP4_ARG3(__lasx_xvsrani_b_h, sum1, sum0, 2, sum3, sum2, 2, sum5, sum4, 2, + sum7, sum6, 2, sum0, sum1, sum2, sum3); + __lasx_xvstelm_d(sum0, dst, 0, 0); + __lasx_xvstelm_d(sum0, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(sum1, dst, 0, 0); + __lasx_xvstelm_d(sum1, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(sum2, dst, 0, 0); + __lasx_xvstelm_d(sum2, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(sum3, dst, 0, 0); + __lasx_xvstelm_d(sum3, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(sum0, dst, 0, 2); + __lasx_xvstelm_d(sum0, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(sum1, dst, 0, 2); + __lasx_xvstelm_d(sum1, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(sum2, dst, 0, 2); + __lasx_xvstelm_d(sum2, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(sum3, dst, 0, 2); + __lasx_xvstelm_d(sum3, dst, 8, 3); +} + +static void common_hv_bil_no_rnd_8x16_lasx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, int32_t dst_stride) +{ + __m256i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9; + __m256i src10, src11, src12, src13, src14, src15, src16, src17; + __m256i sum0, sum1, sum2, sum3, sum4, sum5, sum6, sum7; + int32_t src_stride_2x = src_stride << 1; + int32_t src_stride_4x = src_stride << 2; + int32_t src_stride_3x = src_stride_2x + src_stride; + uint8_t* _src = (uint8_t*)src; + + src0 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src1, src2); + src3 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src4 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src5, src6); + src7 = __lasx_xvldx(_src, src_stride_3x); + _src += (1 - src_stride_4x); + src9 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, + src10, src11); + src12 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src13 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, + src14, src15); + src16 = __lasx_xvldx(_src, src_stride_3x); + _src += (src_stride_4x - 1); + DUP2_ARG2(__lasx_xvld, _src, 0, _src, 1, src8, src17); + + DUP4_ARG3(__lasx_xvpermi_q, src0, src4, 0x02, src1, src5, 0x02, src2, + src6, 0x02, src3, src7, 0x02, src0, src1, src2, src3); + DUP4_ARG3(__lasx_xvpermi_q, src4, src8, 0x02, src9, src13, 0x02, src10, + src14, 0x02, src11, src15, 0x02, src4, src5, src6, src7); + DUP2_ARG3(__lasx_xvpermi_q, src12, src16, 0x02, src13, src17, 0x02, src8, src9); + + DUP4_ARG2(__lasx_xvilvl_h, src5, src0, src6, src1, src7, src2, src8, src3, + sum0, sum2, sum4, sum6); + DUP4_ARG2(__lasx_xvilvh_h, src5, src0, src6, src1, src7, src2, src8, src3, + sum1, sum3, sum5, sum7); + src8 = __lasx_xvilvl_h(src9, src4); + src9 = __lasx_xvilvh_h(src9, src4); + + DUP4_ARG2(__lasx_xvhaddw_hu_bu, sum0, sum0, sum1, sum1, sum2, sum2, + sum3, sum3, src0, src1, src2, src3); + DUP4_ARG2(__lasx_xvhaddw_hu_bu, sum4, sum4, sum5, sum5, sum6, sum6, + sum7, sum7, src4, src5, src6, src7); + DUP2_ARG2(__lasx_xvhaddw_hu_bu, src8, src8, src9, src9, src8, src9); + + DUP4_ARG2(__lasx_xvadd_h, src0, src2, src1, src3, src2, src4, src3, src5, + sum0, sum1, sum2, sum3); + DUP4_ARG2(__lasx_xvadd_h, src4, src6, src5, src7, src6, src8, src7, src9, + sum4, sum5, sum6, sum7); + DUP4_ARG2(__lasx_xvaddi_hu, sum0, 1, sum1, 1, sum2, 1, sum3, 1, + sum0, sum1, sum2, sum3); + DUP4_ARG2(__lasx_xvaddi_hu, sum4, 1, sum5, 1, sum6, 1, sum7, 1, + sum4, sum5, sum6, sum7); + DUP4_ARG3(__lasx_xvsrani_b_h, sum1, sum0, 2, sum3, sum2, 2, sum5, sum4, 2, + sum7, sum6, 2, sum0, sum1, sum2, sum3); + __lasx_xvstelm_d(sum0, dst, 0, 0); + __lasx_xvstelm_d(sum0, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(sum1, dst, 0, 0); + __lasx_xvstelm_d(sum1, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(sum2, dst, 0, 0); + __lasx_xvstelm_d(sum2, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(sum3, dst, 0, 0); + __lasx_xvstelm_d(sum3, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(sum0, dst, 0, 2); + __lasx_xvstelm_d(sum0, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(sum1, dst, 0, 2); + __lasx_xvstelm_d(sum1, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(sum2, dst, 0, 2); + __lasx_xvstelm_d(sum2, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(sum3, dst, 0, 2); + __lasx_xvstelm_d(sum3, dst, 8, 3); +} + +void ff_put_no_rnd_pixels16_xy2_8_lasx(uint8_t *block, + const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + if (h == 16) { + common_hv_bil_no_rnd_16x16_lasx(pixels, line_size, block, line_size); + } else if (h == 8) { + common_hv_bil_no_rnd_8x16_lasx(pixels, line_size, block, line_size); + } +} + +static void common_hz_bil_no_rnd_8x8_lasx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, int32_t dst_stride) +{ + __m256i src0, src1, src2, src3, src4, src5, src6, src7; + __m256i src8, src9, src10, src11, src12, src13, src14, src15; + int32_t src_stride_2x = src_stride << 1; + int32_t src_stride_4x = src_stride << 2; + int32_t dst_stride_2x = dst_stride << 1; + int32_t dst_stride_4x = dst_stride << 2; + int32_t dst_stride_3x = dst_stride_2x + dst_stride; + int32_t src_stride_3x = src_stride_2x + src_stride; + uint8_t* _src = (uint8_t*)src; + + src0 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src1, src2); + src3 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src4 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src5, src6); + src7 = __lasx_xvldx(_src, src_stride_3x); + _src += (1 - src_stride_4x); + src8 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src9, src10); + src11 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src12 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, + src13, src14); + src15 = __lasx_xvldx(_src, src_stride_3x); + + DUP4_ARG2(__lasx_xvpickev_d, src1, src0, src3, src2, src5, src4, src7, + src6, src0, src1, src2, src3); + DUP4_ARG2(__lasx_xvpickev_d, src9, src8, src11, src10, src13, src12, src15, + src14, src4, src5, src6, src7); + DUP4_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src3, src2, 0x20, src5, src4, + 0x20, src7, src6, 0x20, src0, src1, src2, src3); + src0 = __lasx_xvavg_bu(src0, src2); + src1 = __lasx_xvavg_bu(src1, src3); + __lasx_xvstelm_d(src0, dst, 0, 0); + __lasx_xvstelm_d(src0, dst + dst_stride, 0, 1); + __lasx_xvstelm_d(src0, dst + dst_stride_2x, 0, 2); + __lasx_xvstelm_d(src0, dst + dst_stride_3x, 0, 3); + dst += dst_stride_4x; + __lasx_xvstelm_d(src1, dst, 0, 0); + __lasx_xvstelm_d(src1, dst + dst_stride, 0, 1); + __lasx_xvstelm_d(src1, dst + dst_stride_2x, 0, 2); + __lasx_xvstelm_d(src1, dst + dst_stride_3x, 0, 3); +} + +static void common_hz_bil_no_rnd_4x8_lasx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, int32_t dst_stride) +{ + __m256i src0, src1, src2, src3, src4, src5, src6, src7; + int32_t src_stride_2x = src_stride << 1; + int32_t src_stride_3x = src_stride_2x + src_stride; + int32_t dst_stride_2x = dst_stride << 1; + int32_t dst_stride_3x = dst_stride_2x + dst_stride; + uint8_t *_src = (uint8_t*)src; + + src0 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src1, src2); + src3 = __lasx_xvldx(_src, src_stride_3x); + _src += 1; + src4 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src5, src6); + src7 = __lasx_xvldx(_src, src_stride_3x); + DUP4_ARG2(__lasx_xvpickev_d, src1, src0, src3, src2, src5, src4, src7, src6, + src0, src1, src2, src3); + DUP2_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src3, src2, 0x20, src0, src1); + src0 = __lasx_xvavg_bu(src0, src1); + __lasx_xvstelm_d(src0, dst, 0, 0); + __lasx_xvstelm_d(src0, dst + dst_stride, 0, 1); + __lasx_xvstelm_d(src0, dst + dst_stride_2x, 0, 2); + __lasx_xvstelm_d(src0, dst + dst_stride_3x, 0, 3); +} + +void ff_put_no_rnd_pixels8_x2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + if (h == 8) { + common_hz_bil_no_rnd_8x8_lasx(pixels, line_size, block, line_size); + } else if (h == 4) { + common_hz_bil_no_rnd_4x8_lasx(pixels, line_size, block, line_size); + } +} + +static void common_vt_bil_no_rnd_8x8_lasx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride) +{ + __m256i src0, src1, src2, src3, src4, src5, src6, src7, src8; + int32_t src_stride_2x = src_stride << 1; + int32_t src_stride_4x = src_stride << 2; + int32_t dst_stride_2x = dst_stride << 1; + int32_t dst_stride_4x = dst_stride << 2; + int32_t dst_stride_3x = dst_stride_2x + dst_stride; + int32_t src_stride_3x = src_stride_2x + src_stride; + uint8_t* _src = (uint8_t*)src; + + src0 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src1, src2); + src3 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src4 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src5, src6); + src7 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src8 = __lasx_xvld(_src, 0); + + DUP4_ARG2(__lasx_xvpickev_d, src1, src0, src2, src1, src3, src2, src4, src3, + src0, src1, src2, src3); + DUP4_ARG2(__lasx_xvpickev_d, src5, src4, src6, src5, src7, src6, src8, src7, + src4, src5, src6, src7); + DUP4_ARG3(__lasx_xvpermi_q, src2, src0, 0x20, src3, src1, 0x20, src6, src4, + 0x20, src7, src5, 0x20, src0, src1, src2, src3); + src0 = __lasx_xvavg_bu(src0, src1); + src1 = __lasx_xvavg_bu(src2, src3); + __lasx_xvstelm_d(src0, dst, 0, 0); + __lasx_xvstelm_d(src0, dst + dst_stride, 0, 1); + __lasx_xvstelm_d(src0, dst + dst_stride_2x, 0, 2); + __lasx_xvstelm_d(src0, dst + dst_stride_3x, 0, 3); + dst += dst_stride_4x; + __lasx_xvstelm_d(src1, dst, 0, 0); + __lasx_xvstelm_d(src1, dst + dst_stride, 0, 1); + __lasx_xvstelm_d(src1, dst + dst_stride_2x, 0, 2); + __lasx_xvstelm_d(src1, dst + dst_stride_3x, 0, 3); +} + +static void common_vt_bil_no_rnd_4x8_lasx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride) +{ + __m256i src0, src1, src2, src3, src4; + int32_t src_stride_2x = src_stride << 1; + int32_t src_stride_4x = src_stride << 2; + int32_t dst_stride_2x = dst_stride << 1; + int32_t dst_stride_3x = dst_stride_2x + dst_stride; + int32_t src_stride_3x = src_stride_2x + src_stride; + uint8_t* _src = (uint8_t*)src; + + src0 = __lasx_xvld(_src, 0); + DUP4_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, _src, + src_stride_3x, _src, src_stride_4x, src1, src2, src3, src4); + DUP4_ARG2(__lasx_xvpickev_d, src1, src0, src2, src1, src3, src2, src4, src3, + src0, src1, src2, src3); + DUP2_ARG3(__lasx_xvpermi_q, src2, src0, 0x20, src3, src1, 0x20, src0, src1); + src0 = __lasx_xvavg_bu(src0, src1); + __lasx_xvstelm_d(src0, dst, 0, 0); + __lasx_xvstelm_d(src0, dst + dst_stride, 0, 1); + __lasx_xvstelm_d(src0, dst + dst_stride_2x, 0, 2); + __lasx_xvstelm_d(src0, dst + dst_stride_3x, 0, 3); +} + +void ff_put_no_rnd_pixels8_y2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + if (h == 8) { + common_vt_bil_no_rnd_8x8_lasx(pixels, line_size, block, line_size); + } else if (h == 4) { + common_vt_bil_no_rnd_4x8_lasx(pixels, line_size, block, line_size); + } +} + +static void common_hv_bil_no_rnd_8x8_lasx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride) +{ + __m256i src0, src1, src2, src3, src4, src5, src6, src7; + __m256i src8, src9, src10, src11, src12, src13, src14, src15, src16, src17; + __m256i sum0, sum1, sum2, sum3; + int32_t src_stride_2x = src_stride << 1; + int32_t src_stride_4x = src_stride << 2; + int32_t dst_stride_2x = dst_stride << 1; + int32_t dst_stride_4x = dst_stride << 2; + int32_t dst_stride_3x = dst_stride_2x + dst_stride; + int32_t src_stride_3x = src_stride_2x + src_stride; + uint8_t* _src = (uint8_t*)src; + + src0 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src1, src2); + src3 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src4 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src5, src6); + src7 = __lasx_xvldx(_src, src_stride_3x); + _src += (1 - src_stride_4x); + src9 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, + src10, src11); + src12 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src13 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, + src14, src15); + src16 = __lasx_xvldx(_src, src_stride_3x); + _src += (src_stride_4x - 1); + DUP2_ARG2(__lasx_xvld, _src, 0, _src, 1, src8, src17); + + DUP4_ARG2(__lasx_xvilvl_b, src9, src0, src10, src1, src11, src2, src12, src3, + src0, src1, src2, src3); + DUP4_ARG2(__lasx_xvilvl_b, src13, src4, src14, src5, src15, src6, src16, src7, + src4, src5, src6, src7); + src8 = __lasx_xvilvl_b(src17, src8); + DUP4_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src2, src1, 0x20, src3, src2, + 0x20, src4, src3, 0x20, src0, src1, src2, src3); + DUP4_ARG3(__lasx_xvpermi_q, src5, src4, 0x20, src6, src5, 0x20, src7, src6, + 0x20, src8, src7, 0x20, src4, src5, src6, src7); + DUP4_ARG2(__lasx_xvhaddw_hu_bu, src0, src0, src1, src1, src2, src2, + src3, src3, src0, src1, src2, src3); + DUP4_ARG2(__lasx_xvhaddw_hu_bu, src4, src4, src5, src5, src6, src6, + src7, src7, src4, src5, src6, src7); + DUP4_ARG2(__lasx_xvadd_h, src0, src1, src2, src3, src4, src5, src6, src7, + sum0, sum1, sum2, sum3); + DUP4_ARG2(__lasx_xvaddi_hu, sum0, 1, sum1, 1, sum2, 1, sum3, 1, + sum0, sum1, sum2, sum3); + DUP2_ARG3(__lasx_xvsrani_b_h, sum1, sum0, 2, sum3, sum2, 2, sum0, sum1); + __lasx_xvstelm_d(sum0, dst, 0, 0); + __lasx_xvstelm_d(sum0, dst + dst_stride, 0, 2); + __lasx_xvstelm_d(sum0, dst + dst_stride_2x, 0, 1); + __lasx_xvstelm_d(sum0, dst + dst_stride_3x, 0, 3); + dst += dst_stride_4x; + __lasx_xvstelm_d(sum1, dst, 0, 0); + __lasx_xvstelm_d(sum1, dst + dst_stride, 0, 2); + __lasx_xvstelm_d(sum1, dst + dst_stride_2x, 0, 1); + __lasx_xvstelm_d(sum1, dst + dst_stride_3x, 0, 3); +} + +static void common_hv_bil_no_rnd_4x8_lasx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride) +{ + __m256i src0, src1, src2, src3, src4, src5, src6, src7; + __m256i src8, src9, sum0, sum1; + int32_t src_stride_2x = src_stride << 1; + int32_t src_stride_4x = src_stride << 2; + int32_t dst_stride_2x = dst_stride << 1; + int32_t dst_stride_3x = dst_stride_2x + dst_stride; + int32_t src_stride_3x = src_stride_2x + src_stride; + uint8_t *_src = (uint8_t*)src; + + src0 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src1, src2); + src3 = __lasx_xvldx(_src, src_stride_3x); + _src += 1; + src5 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src6, src7); + src8 = __lasx_xvldx(_src, src_stride_3x); + _src += (src_stride_4x - 1); + DUP2_ARG2(__lasx_xvld, _src, 0, _src, 1, src4, src9); + + DUP4_ARG2(__lasx_xvilvl_b, src5, src0, src6, src1, src7, src2, src8, src3, + src0, src1, src2, src3); + src4 = __lasx_xvilvl_b(src9, src4); + DUP4_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src2, src1, 0x20, src3, src2, + 0x20, src4, src3, 0x20, src0, src1, src2, src3); + DUP4_ARG2(__lasx_xvhaddw_hu_bu, src0, src0, src1, src1, src2, src2, + src3, src3, src0, src1, src2, src3); + DUP2_ARG2(__lasx_xvadd_h, src0, src1, src2, src3, sum0, sum1); + sum0 = __lasx_xvaddi_hu(sum0, 1); + sum1 = __lasx_xvaddi_hu(sum1, 1); + sum0 = __lasx_xvsrani_b_h(sum1, sum0, 2); + __lasx_xvstelm_d(sum0, dst, 0, 0); + __lasx_xvstelm_d(sum0, dst + dst_stride, 0, 2); + __lasx_xvstelm_d(sum0, dst + dst_stride_2x, 0, 1); + __lasx_xvstelm_d(sum0, dst + dst_stride_3x, 0, 3); +} + +void ff_put_no_rnd_pixels8_xy2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + if (h == 8) { + common_hv_bil_no_rnd_8x8_lasx(pixels, line_size, block, line_size); + } else if (h == 4) { + common_hv_bil_no_rnd_4x8_lasx(pixels, line_size, block, line_size); + } +} + +static void common_hv_bil_16w_lasx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + uint8_t height) +{ + __m256i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9; + __m256i src10, src11, src12, src13, src14, src15, src16, src17; + __m256i sum0, sum1, sum2, sum3, sum4, sum5, sum6, sum7; + uint8_t loop_cnt; + int32_t src_stride_2x = src_stride << 1; + int32_t src_stride_4x = src_stride << 2; + int32_t src_stride_3x = src_stride_2x + src_stride; + uint8_t* _src = (uint8_t*)src; + + for (loop_cnt = (height >> 3); loop_cnt--;) { + src0 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src1, src2); + src3 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src4 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src5, src6); + src7 = __lasx_xvldx(_src, src_stride_3x); + _src += (1 - src_stride_4x); + src9 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, + src10, src11); + src12 = __lasx_xvldx(_src, src_stride_3x); + _src += src_stride_4x; + src13 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, + src14, src15); + src16 = __lasx_xvldx(_src, src_stride_3x); + _src += (src_stride_4x - 1); + DUP2_ARG2(__lasx_xvld, _src, 0, _src, 1, src8, src17); + + DUP4_ARG3(__lasx_xvpermi_q, src0, src4, 0x02, src1, src5, 0x02, src2, + src6, 0x02, src3, src7, 0x02, src0, src1, src2, src3); + DUP4_ARG3(__lasx_xvpermi_q, src4, src8, 0x02, src9, src13, 0x02, src10, + src14, 0x02, src11, src15, 0x02, src4, src5, src6, src7); + DUP2_ARG3(__lasx_xvpermi_q, src12, src16, 0x02, src13, src17, 0x02, + src8, src9); + + DUP4_ARG2(__lasx_xvilvl_h, src5, src0, src6, src1, src7, src2, src8, + src3, sum0, sum2, sum4, sum6); + DUP4_ARG2(__lasx_xvilvh_h, src5, src0, src6, src1, src7, src2, src8, + src3, sum1, sum3, sum5, sum7); + src8 = __lasx_xvilvl_h(src9, src4); + src9 = __lasx_xvilvh_h(src9, src4); + + DUP4_ARG2(__lasx_xvhaddw_hu_bu, sum0, sum0, sum1, sum1, sum2, sum2, + sum3, sum3, src0, src1, src2, src3); + DUP4_ARG2(__lasx_xvhaddw_hu_bu, sum4, sum4, sum5, sum5, sum6, sum6, + sum7, sum7, src4, src5, src6, src7); + DUP2_ARG2(__lasx_xvhaddw_hu_bu, src8, src8, src9, src9, src8, src9); + + DUP4_ARG2(__lasx_xvadd_h, src0, src2, src1, src3, src2, src4, src3, + src5, sum0, sum1, sum2, sum3); + DUP4_ARG2(__lasx_xvadd_h, src4, src6, src5, src7, src6, src8, src7, + src9, sum4, sum5, sum6, sum7); + DUP4_ARG3(__lasx_xvsrarni_b_h, sum1, sum0, 2, sum3, sum2, 2, sum5, + sum4, 2, sum7, sum6, 2, sum0, sum1, sum2, sum3); + __lasx_xvstelm_d(sum0, dst, 0, 0); + __lasx_xvstelm_d(sum0, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(sum1, dst, 0, 0); + __lasx_xvstelm_d(sum1, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(sum2, dst, 0, 0); + __lasx_xvstelm_d(sum2, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(sum3, dst, 0, 0); + __lasx_xvstelm_d(sum3, dst, 8, 1); + dst += dst_stride; + __lasx_xvstelm_d(sum0, dst, 0, 2); + __lasx_xvstelm_d(sum0, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(sum1, dst, 0, 2); + __lasx_xvstelm_d(sum1, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(sum2, dst, 0, 2); + __lasx_xvstelm_d(sum2, dst, 8, 3); + dst += dst_stride; + __lasx_xvstelm_d(sum3, dst, 0, 2); + __lasx_xvstelm_d(sum3, dst, 8, 3); + dst += dst_stride; + } +} + +void ff_put_pixels16_xy2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + common_hv_bil_16w_lasx(pixels, line_size, block, line_size, h); +} + +static void common_hv_bil_8w_lasx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + uint8_t height) +{ + __m256i src0, src1, src2, src3, src4, src5, src6, src7; + __m256i src8, src9, sum0, sum1; + uint8_t loop_cnt; + int32_t src_stride_2x = src_stride << 1; + int32_t src_stride_4x = src_stride << 2; + int32_t dst_stride_2x = dst_stride << 1; + int32_t dst_stride_4x = dst_stride << 2; + int32_t dst_stride_3x = dst_stride_2x + dst_stride; + int32_t src_stride_3x = src_stride_2x + src_stride; + uint8_t* _src = (uint8_t*)src; + + DUP2_ARG2(__lasx_xvld, _src, 0, _src, 1, src0, src5); + _src += src_stride; + + for (loop_cnt = (height >> 2); loop_cnt--;) { + src1 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src2, src3); + src4 = __lasx_xvldx(_src, src_stride_3x); + _src += 1; + src6 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, src_stride, _src, src_stride_2x, src7, src8); + src9 = __lasx_xvldx(_src, src_stride_3x); + _src += (src_stride_4x - 1); + DUP4_ARG2(__lasx_xvilvl_b, src5, src0, src6, src1, src7, src2, src8, src3, + src0, src1, src2, src3); + src5 = __lasx_xvilvl_b(src9, src4); + DUP4_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src2, src1, 0x20, src3, src2, + 0x20, src5, src3, 0x20, src0, src1, src2, src3); + DUP4_ARG2(__lasx_xvhaddw_hu_bu, src0, src0, src1, src1, src2, src2, + src3, src3, src0, src1, src2, src3); + DUP2_ARG2(__lasx_xvadd_h, src0, src1, src2, src3, sum0, sum1); + sum0 = __lasx_xvsrarni_b_h(sum1, sum0, 2); + __lasx_xvstelm_d(sum0, dst, 0, 0); + __lasx_xvstelm_d(sum0, dst + dst_stride, 0, 2); + __lasx_xvstelm_d(sum0, dst + dst_stride_2x, 0, 1); + __lasx_xvstelm_d(sum0, dst + dst_stride_3x, 0, 3); + dst += dst_stride_4x; + src0 = src4; + src5 = src9; + } +} + +void ff_put_pixels8_xy2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h) +{ + common_hv_bil_8w_lasx(pixels, line_size, block, line_size, h); +} diff --git a/libavcodec/loongarch/hpeldsp_lasx.h b/libavcodec/loongarch/hpeldsp_lasx.h new file mode 100644 index 000000000..2e035eade --- /dev/null +++ b/libavcodec/loongarch/hpeldsp_lasx.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Shiyou Yin + * + * 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_LOONGARCH_HPELDSP_LASX_H +#define AVCODEC_LOONGARCH_HPELDSP_LASX_H + +#include +#include +#include "libavutil/attributes.h" + +void ff_put_pixels8_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_pixels8_x2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int32_t h); +void ff_put_pixels8_y2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int32_t h); +void ff_put_pixels16_8_lsx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_pixels16_x2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int32_t h); +void ff_put_pixels16_y2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int32_t h); +void ff_put_no_rnd_pixels16_x2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_no_rnd_pixels16_y2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_no_rnd_pixels16_xy2_8_lasx(uint8_t *block, + const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_no_rnd_pixels8_x2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_no_rnd_pixels8_y2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_no_rnd_pixels8_xy2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_pixels8_xy2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +void ff_put_pixels16_xy2_8_lasx(uint8_t *block, const uint8_t *pixels, + ptrdiff_t line_size, int h); +#endif diff --git a/libavcodec/loongarch/idctdsp_init_loongarch.c b/libavcodec/loongarch/idctdsp_init_loongarch.c new file mode 100644 index 000000000..9d1d21cc1 --- /dev/null +++ b/libavcodec/loongarch/idctdsp_init_loongarch.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Hao Chen + * + * 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/loongarch/cpu.h" +#include "idctdsp_loongarch.h" +#include "libavcodec/xvididct.h" + +av_cold void ff_idctdsp_init_loongarch(IDCTDSPContext *c, AVCodecContext *avctx, + unsigned high_bit_depth) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_lasx(cpu_flags)) { + if ((avctx->lowres != 1) && (avctx->lowres != 2) && (avctx->lowres != 3) && + (avctx->bits_per_raw_sample != 10) && + (avctx->bits_per_raw_sample != 12) && + (avctx->idct_algo == FF_IDCT_AUTO)) { + c->idct_put = ff_simple_idct_put_lasx; + c->idct_add = ff_simple_idct_add_lasx; + c->idct = ff_simple_idct_lasx; + c->perm_type = FF_IDCT_PERM_NONE; + } + c->put_pixels_clamped = ff_put_pixels_clamped_lasx; + c->put_signed_pixels_clamped = ff_put_signed_pixels_clamped_lasx; + c->add_pixels_clamped = ff_add_pixels_clamped_lasx; + } +} diff --git a/libavcodec/loongarch/idctdsp_lasx.c b/libavcodec/loongarch/idctdsp_lasx.c new file mode 100644 index 000000000..1cfab0e02 --- /dev/null +++ b/libavcodec/loongarch/idctdsp_lasx.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Hao Chen + * + * 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 "idctdsp_loongarch.h" +#include "libavutil/loongarch/loongson_intrinsics.h" + +void ff_put_pixels_clamped_lasx(const int16_t *block, + uint8_t *av_restrict pixels, + ptrdiff_t stride) +{ + __m256i b0, b1, b2, b3; + __m256i temp0, temp1; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_4x = stride << 2; + ptrdiff_t stride_3x = stride_2x + stride; + + DUP4_ARG2(__lasx_xvld, block, 0, block, 32, block, 64, block, 96, + b0, b1, b2, b3); + DUP4_ARG1(__lasx_xvclip255_h, b0, b1, b2, b3, b0, b1, b2, b3); + DUP2_ARG2(__lasx_xvpickev_b, b1, b0, b3, b2, temp0, temp1); + __lasx_xvstelm_d(temp0, pixels, 0, 0); + __lasx_xvstelm_d(temp0, pixels + stride, 0, 2); + __lasx_xvstelm_d(temp0, pixels + stride_2x, 0, 1); + __lasx_xvstelm_d(temp0, pixels + stride_3x, 0, 3); + pixels += stride_4x; + __lasx_xvstelm_d(temp1, pixels, 0, 0); + __lasx_xvstelm_d(temp1, pixels + stride, 0, 2); + __lasx_xvstelm_d(temp1, pixels + stride_2x, 0, 1); + __lasx_xvstelm_d(temp1, pixels + stride_3x, 0, 3); +} + +void ff_put_signed_pixels_clamped_lasx(const int16_t *block, + uint8_t *av_restrict pixels, + ptrdiff_t stride) +{ + __m256i b0, b1, b2, b3; + __m256i temp0, temp1; + __m256i const_128 = {0x0080008000800080, 0x0080008000800080, + 0x0080008000800080, 0x0080008000800080}; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_4x = stride << 2; + ptrdiff_t stride_3x = stride_2x + stride; + + DUP4_ARG2(__lasx_xvld, block, 0, block, 32, block, 64, block, 96, + b0, b1, b2, b3); + DUP4_ARG2(__lasx_xvadd_h, b0, const_128, b1, const_128, b2, const_128, + b3, const_128, b0, b1, b2, b3); + DUP4_ARG1(__lasx_xvclip255_h, b0, b1, b2, b3, b0, b1, b2, b3); + DUP2_ARG2(__lasx_xvpickev_b, b1, b0, b3, b2, temp0, temp1); + __lasx_xvstelm_d(temp0, pixels, 0, 0); + __lasx_xvstelm_d(temp0, pixels + stride, 0, 2); + __lasx_xvstelm_d(temp0, pixels + stride_2x, 0, 1); + __lasx_xvstelm_d(temp0, pixels + stride_3x, 0, 3); + pixels += stride_4x; + __lasx_xvstelm_d(temp1, pixels, 0, 0); + __lasx_xvstelm_d(temp1, pixels + stride, 0, 2); + __lasx_xvstelm_d(temp1, pixels + stride_2x, 0, 1); + __lasx_xvstelm_d(temp1, pixels + stride_3x, 0, 3); +} + +void ff_add_pixels_clamped_lasx(const int16_t *block, + uint8_t *av_restrict pixels, + ptrdiff_t stride) +{ + __m256i b0, b1, b2, b3; + __m256i p0, p1, p2, p3, p4, p5, p6, p7; + __m256i temp0, temp1, temp2, temp3; + uint8_t *pix = pixels; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_4x = stride << 2; + ptrdiff_t stride_3x = stride_2x + stride; + + DUP4_ARG2(__lasx_xvld, block, 0, block, 32, block, 64, block, 96, + b0, b1, b2, b3); + p0 = __lasx_xvldrepl_d(pix, 0); + pix += stride; + p1 = __lasx_xvldrepl_d(pix, 0); + pix += stride; + p2 = __lasx_xvldrepl_d(pix, 0); + pix += stride; + p3 = __lasx_xvldrepl_d(pix, 0); + pix += stride; + p4 = __lasx_xvldrepl_d(pix, 0); + pix += stride; + p5 = __lasx_xvldrepl_d(pix, 0); + pix += stride; + p6 = __lasx_xvldrepl_d(pix, 0); + pix += stride; + p7 = __lasx_xvldrepl_d(pix, 0); + DUP4_ARG3(__lasx_xvpermi_q, p1, p0, 0x20, p3, p2, 0x20, p5, p4, 0x20, + p7, p6, 0x20, temp0, temp1, temp2, temp3); + DUP4_ARG2(__lasx_xvaddw_h_h_bu, b0, temp0, b1, temp1, b2, temp2, b3, temp3, + temp0, temp1, temp2, temp3); + DUP4_ARG1(__lasx_xvclip255_h, temp0, temp1, temp2, temp3, + temp0, temp1, temp2, temp3); + DUP2_ARG2(__lasx_xvpickev_b, temp1, temp0, temp3, temp2, temp0, temp1); + __lasx_xvstelm_d(temp0, pixels, 0, 0); + __lasx_xvstelm_d(temp0, pixels + stride, 0, 2); + __lasx_xvstelm_d(temp0, pixels + stride_2x, 0, 1); + __lasx_xvstelm_d(temp0, pixels + stride_3x, 0, 3); + pixels += stride_4x; + __lasx_xvstelm_d(temp1, pixels, 0, 0); + __lasx_xvstelm_d(temp1, pixels + stride, 0, 2); + __lasx_xvstelm_d(temp1, pixels + stride_2x, 0, 1); + __lasx_xvstelm_d(temp1, pixels + stride_3x, 0, 3); +} diff --git a/libavcodec/loongarch/idctdsp_loongarch.h b/libavcodec/loongarch/idctdsp_loongarch.h new file mode 100644 index 000000000..cae8e7af5 --- /dev/null +++ b/libavcodec/loongarch/idctdsp_loongarch.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Hao Chen + * + * 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_LOONGARCH_IDCTDSP_LOONGARCH_H +#define AVCODEC_LOONGARCH_IDCTDSP_LOONGARCH_H + +#include +#include "libavcodec/mpegvideo.h" + +void ff_simple_idct_lasx(int16_t *block); +void ff_simple_idct_put_lasx(uint8_t *dest, ptrdiff_t stride_dst, int16_t *block); +void ff_simple_idct_add_lasx(uint8_t *dest, ptrdiff_t stride_dst, int16_t *block); +void ff_put_pixels_clamped_lasx(const int16_t *block, + uint8_t *av_restrict pixels, + ptrdiff_t line_size); +void ff_put_signed_pixels_clamped_lasx(const int16_t *block, + uint8_t *av_restrict pixels, + ptrdiff_t line_size); +void ff_add_pixels_clamped_lasx(const int16_t *block, + uint8_t *av_restrict pixels, + ptrdiff_t line_size); + +#endif /* AVCODEC_LOONGARCH_IDCTDSP_LOONGARCH_H */ diff --git a/libavcodec/loongarch/simple_idct_lasx.c b/libavcodec/loongarch/simple_idct_lasx.c new file mode 100644 index 000000000..a0d936b66 --- /dev/null +++ b/libavcodec/loongarch/simple_idct_lasx.c @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Hao Chen + * + * 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/loongarch/loongson_intrinsics.h" +#include "idctdsp_loongarch.h" + +#define LASX_TRANSPOSE4x16(in_0, in_1, in_2, in_3, out_0, out_1, out_2, out_3) \ +{ \ + __m256i temp_0, temp_1, temp_2, temp_3; \ + __m256i temp_4, temp_5, temp_6, temp_7; \ + DUP4_ARG3(__lasx_xvpermi_q, in_2, in_0, 0x20, in_2, in_0, 0x31, in_3, in_1,\ + 0x20, in_3, in_1, 0x31, temp_0, temp_1, temp_2, temp_3); \ + DUP2_ARG2(__lasx_xvilvl_h, temp_1, temp_0, temp_3, temp_2, temp_4, temp_6);\ + DUP2_ARG2(__lasx_xvilvh_h, temp_1, temp_0, temp_3, temp_2, temp_5, temp_7);\ + DUP2_ARG2(__lasx_xvilvl_w, temp_6, temp_4, temp_7, temp_5, out_0, out_2); \ + DUP2_ARG2(__lasx_xvilvh_w, temp_6, temp_4, temp_7, temp_5, out_1, out_3); \ +} + +#define LASX_IDCTROWCONDDC \ + const_val = 16383 * ((1 << 19) / 16383); \ + const_val1 = __lasx_xvreplgr2vr_w(const_val); \ + DUP4_ARG2(__lasx_xvld, block, 0, block, 32, block, 64, block, 96, \ + in0, in1, in2, in3); \ + LASX_TRANSPOSE4x16(in0, in1, in2, in3, in0, in1, in2, in3); \ + a0 = __lasx_xvpermi_d(in0, 0xD8); \ + a0 = __lasx_vext2xv_w_h(a0); \ + temp = __lasx_xvslli_w(a0, 3); \ + a1 = __lasx_xvpermi_d(in0, 0x8D); \ + a1 = __lasx_vext2xv_w_h(a1); \ + a2 = __lasx_xvpermi_d(in1, 0xD8); \ + a2 = __lasx_vext2xv_w_h(a2); \ + a3 = __lasx_xvpermi_d(in1, 0x8D); \ + a3 = __lasx_vext2xv_w_h(a3); \ + b0 = __lasx_xvpermi_d(in2, 0xD8); \ + b0 = __lasx_vext2xv_w_h(b0); \ + b1 = __lasx_xvpermi_d(in2, 0x8D); \ + b1 = __lasx_vext2xv_w_h(b1); \ + b2 = __lasx_xvpermi_d(in3, 0xD8); \ + b2 = __lasx_vext2xv_w_h(b2); \ + b3 = __lasx_xvpermi_d(in3, 0x8D); \ + b3 = __lasx_vext2xv_w_h(b3); \ + select_vec = a0 | a1 | a2 | a3 | b0 | b1 | b2 | b3; \ + select_vec = __lasx_xvslti_wu(select_vec, 1); \ + \ + DUP4_ARG2(__lasx_xvrepl128vei_h, w1, 2, w1, 3, w1, 4, w1, 5, \ + w2, w3, w4, w5); \ + DUP2_ARG2(__lasx_xvrepl128vei_h, w1, 6, w1, 7, w6, w7); \ + w1 = __lasx_xvrepl128vei_h(w1, 1); \ + \ + /* part of FUNC6(idctRowCondDC) */ \ + temp0 = __lasx_xvmaddwl_w_h(const_val0, in0, w4); \ + DUP2_ARG2(__lasx_xvmulwl_w_h, in1, w2, in1, w6, temp1, temp2); \ + a0 = __lasx_xvadd_w(temp0, temp1); \ + a1 = __lasx_xvadd_w(temp0, temp2); \ + a2 = __lasx_xvsub_w(temp0, temp2); \ + a3 = __lasx_xvsub_w(temp0, temp1); \ + \ + DUP2_ARG2(__lasx_xvilvh_h, in1, in0, w3, w1, temp0, temp1); \ + b0 = __lasx_xvdp2_w_h(temp0, temp1); \ + temp1 = __lasx_xvneg_h(w7); \ + temp2 = __lasx_xvilvl_h(temp1, w3); \ + b1 = __lasx_xvdp2_w_h(temp0, temp2); \ + temp1 = __lasx_xvneg_h(w1); \ + temp2 = __lasx_xvilvl_h(temp1, w5); \ + b2 = __lasx_xvdp2_w_h(temp0, temp2); \ + temp1 = __lasx_xvneg_h(w5); \ + temp2 = __lasx_xvilvl_h(temp1, w7); \ + b3 = __lasx_xvdp2_w_h(temp0, temp2); \ + \ + /* if (AV_RAN64A(row + 4)) */ \ + DUP2_ARG2(__lasx_xvilvl_h, in3, in2, w6, w4, temp0, temp1); \ + a0 = __lasx_xvdp2add_w_h(a0, temp0, temp1); \ + temp1 = __lasx_xvilvl_h(w2, w4); \ + a1 = __lasx_xvdp2sub_w_h(a1, temp0, temp1); \ + temp1 = __lasx_xvneg_h(w4); \ + temp2 = __lasx_xvilvl_h(w2, temp1); \ + a2 = __lasx_xvdp2add_w_h(a2, temp0, temp2); \ + temp1 = __lasx_xvneg_h(w6); \ + temp2 = __lasx_xvilvl_h(temp1, w4); \ + a3 = __lasx_xvdp2add_w_h(a3, temp0, temp2); \ + \ + DUP2_ARG2(__lasx_xvilvh_h, in3, in2, w7, w5, temp0, temp1); \ + b0 = __lasx_xvdp2add_w_h(b0, temp0, temp1); \ + DUP2_ARG2(__lasx_xvilvl_h, w5, w1, w3, w7, temp1, temp2); \ + b1 = __lasx_xvdp2sub_w_h(b1, temp0, temp1); \ + b2 = __lasx_xvdp2add_w_h(b2, temp0, temp2); \ + temp1 = __lasx_xvneg_h(w1); \ + temp2 = __lasx_xvilvl_h(temp1, w3); \ + b3 = __lasx_xvdp2add_w_h(b3, temp0, temp2); \ + \ + DUP4_ARG2(__lasx_xvadd_w, a0, b0, a1, b1, a2, b2, a3, b3, \ + temp0, temp1, temp2, temp3); \ + DUP4_ARG2(__lasx_xvsub_w, a0, b0, a1, b1, a2, b2, a3, b3, \ + a0, a1, a2, a3); \ + DUP4_ARG2(__lasx_xvsrai_w, temp0, 11, temp1, 11, temp2, 11, temp3, 11, \ + temp0, temp1, temp2, temp3); \ + DUP4_ARG2(__lasx_xvsrai_w, a0, 11, a1, 11, a2, 11, a3, 11, a0, a1, a2, a3);\ + DUP4_ARG3(__lasx_xvbitsel_v, temp0, temp, select_vec, temp1, temp, \ + select_vec, temp2, temp, select_vec, temp3, temp, select_vec, \ + in0, in1, in2, in3); \ + DUP4_ARG3(__lasx_xvbitsel_v, a0, temp, select_vec, a1, temp, \ + select_vec, a2, temp, select_vec, a3, temp, select_vec, \ + a0, a1, a2, a3); \ + DUP4_ARG2(__lasx_xvpickev_h, in1, in0, in3, in2, a2, a3, a0, a1, \ + in0, in1, in2, in3); \ + DUP4_ARG2(__lasx_xvpermi_d, in0, 0xD8, in1, 0xD8, in2, 0xD8, in3, 0xD8, \ + in0, in1, in2, in3); \ + +#define LASX_IDCTCOLS \ + /* part of FUNC6(idctSparaseCol) */ \ + LASX_TRANSPOSE4x16(in0, in1, in2, in3, in0, in1, in2, in3); \ + temp0 = __lasx_xvmaddwl_w_h(const_val1, in0, w4); \ + DUP2_ARG2(__lasx_xvmulwl_w_h, in1, w2, in1, w6, temp1, temp2); \ + a0 = __lasx_xvadd_w(temp0, temp1); \ + a1 = __lasx_xvadd_w(temp0, temp2); \ + a2 = __lasx_xvsub_w(temp0, temp2); \ + a3 = __lasx_xvsub_w(temp0, temp1); \ + \ + DUP2_ARG2(__lasx_xvilvh_h, in1, in0, w3, w1, temp0, temp1); \ + b0 = __lasx_xvdp2_w_h(temp0, temp1); \ + temp1 = __lasx_xvneg_h(w7); \ + temp2 = __lasx_xvilvl_h(temp1, w3); \ + b1 = __lasx_xvdp2_w_h(temp0, temp2); \ + temp1 = __lasx_xvneg_h(w1); \ + temp2 = __lasx_xvilvl_h(temp1, w5); \ + b2 = __lasx_xvdp2_w_h(temp0, temp2); \ + temp1 = __lasx_xvneg_h(w5); \ + temp2 = __lasx_xvilvl_h(temp1, w7); \ + b3 = __lasx_xvdp2_w_h(temp0, temp2); \ + \ + /* if (AV_RAN64A(row + 4)) */ \ + DUP2_ARG2(__lasx_xvilvl_h, in3, in2, w6, w4, temp0, temp1); \ + a0 = __lasx_xvdp2add_w_h(a0, temp0, temp1); \ + temp1 = __lasx_xvilvl_h(w2, w4); \ + a1 = __lasx_xvdp2sub_w_h(a1, temp0, temp1); \ + temp1 = __lasx_xvneg_h(w4); \ + temp2 = __lasx_xvilvl_h(w2, temp1); \ + a2 = __lasx_xvdp2add_w_h(a2, temp0, temp2); \ + temp1 = __lasx_xvneg_h(w6); \ + temp2 = __lasx_xvilvl_h(temp1, w4); \ + a3 = __lasx_xvdp2add_w_h(a3, temp0, temp2); \ + \ + DUP2_ARG2(__lasx_xvilvh_h, in3, in2, w7, w5, temp0, temp1); \ + b0 = __lasx_xvdp2add_w_h(b0, temp0, temp1); \ + DUP2_ARG2(__lasx_xvilvl_h, w5, w1, w3, w7, temp1, temp2); \ + b1 = __lasx_xvdp2sub_w_h(b1, temp0, temp1); \ + b2 = __lasx_xvdp2add_w_h(b2, temp0, temp2); \ + temp1 = __lasx_xvneg_h(w1); \ + temp2 = __lasx_xvilvl_h(temp1, w3); \ + b3 = __lasx_xvdp2add_w_h(b3, temp0, temp2); \ + \ + DUP4_ARG2(__lasx_xvadd_w, a0, b0, a1, b1, a2, b2, a3, b3, \ + temp0, temp1, temp2, temp3); \ + DUP4_ARG2(__lasx_xvsub_w, a3, b3, a2, b2, a1, b1, a0, b0, \ + a3, a2, a1, a0); \ + DUP4_ARG3(__lasx_xvsrani_h_w, temp1, temp0, 20, temp3, temp2, 20, a2, a3, \ + 20, a0, a1, 20, in0, in1, in2, in3); \ + +void ff_simple_idct_lasx(int16_t *block) +{ + int32_t const_val = 1 << 10; + __m256i w1 = {0x4B42539F58C50000, 0x11A822A332493FFF, + 0x4B42539F58C50000, 0x11A822A332493FFF}; + __m256i in0, in1, in2, in3; + __m256i w2, w3, w4, w5, w6, w7; + __m256i a0, a1, a2, a3; + __m256i b0, b1, b2, b3; + __m256i temp0, temp1, temp2, temp3; + __m256i const_val0 = __lasx_xvreplgr2vr_w(const_val); + __m256i const_val1, select_vec, temp; + + LASX_IDCTROWCONDDC + LASX_IDCTCOLS + DUP4_ARG2(__lasx_xvpermi_d, in0, 0xD8, in1, 0xD8, in2, 0xD8, in3, 0xD8, + in0, in1, in2, in3); + __lasx_xvst(in0, block, 0); + __lasx_xvst(in1, block, 32); + __lasx_xvst(in2, block, 64); + __lasx_xvst(in3, block, 96); +} + +void ff_simple_idct_put_lasx(uint8_t *dst, ptrdiff_t dst_stride, + int16_t *block) +{ + int32_t const_val = 1 << 10; + ptrdiff_t dst_stride_2x = dst_stride << 1; + ptrdiff_t dst_stride_4x = dst_stride << 2; + ptrdiff_t dst_stride_3x = dst_stride_2x + dst_stride; + __m256i w1 = {0x4B42539F58C50000, 0x11A822A332493FFF, + 0x4B42539F58C50000, 0x11A822A332493FFF}; + __m256i in0, in1, in2, in3; + __m256i w2, w3, w4, w5, w6, w7; + __m256i a0, a1, a2, a3; + __m256i b0, b1, b2, b3; + __m256i temp0, temp1, temp2, temp3; + __m256i const_val0 = __lasx_xvreplgr2vr_w(const_val); + __m256i const_val1, select_vec, temp; + + LASX_IDCTROWCONDDC + LASX_IDCTCOLS + DUP4_ARG2(__lasx_xvpermi_d, in0, 0xD8, in1, 0xD8, in2, 0xD8, in3, 0xD8, + in0, in1, in2, in3); + DUP4_ARG1(__lasx_xvclip255_h, in0, in1, in2, in3, in0, in1, in2, in3); + DUP2_ARG2(__lasx_xvpickev_b, in1, in0, in3, in2, in0, in1); + __lasx_xvstelm_d(in0, dst, 0, 0); + __lasx_xvstelm_d(in0, dst + dst_stride, 0, 2); + __lasx_xvstelm_d(in0, dst + dst_stride_2x, 0, 1); + __lasx_xvstelm_d(in0, dst + dst_stride_3x, 0, 3); + dst += dst_stride_4x; + __lasx_xvstelm_d(in1, dst, 0, 0); + __lasx_xvstelm_d(in1, dst + dst_stride, 0, 2); + __lasx_xvstelm_d(in1, dst + dst_stride_2x, 0, 1); + __lasx_xvstelm_d(in1, dst + dst_stride_3x, 0, 3); +} + +void ff_simple_idct_add_lasx(uint8_t *dst, ptrdiff_t dst_stride, + int16_t *block) +{ + int32_t const_val = 1 << 10; + uint8_t *dst1 = dst; + ptrdiff_t dst_stride_2x = dst_stride << 1; + ptrdiff_t dst_stride_4x = dst_stride << 2; + ptrdiff_t dst_stride_3x = dst_stride_2x + dst_stride; + + __m256i w1 = {0x4B42539F58C50000, 0x11A822A332493FFF, + 0x4B42539F58C50000, 0x11A822A332493FFF}; + __m256i sh = {0x0003000200010000, 0x000B000A00090008, + 0x0007000600050004, 0x000F000E000D000C}; + __m256i in0, in1, in2, in3; + __m256i w2, w3, w4, w5, w6, w7; + __m256i a0, a1, a2, a3; + __m256i b0, b1, b2, b3; + __m256i temp0, temp1, temp2, temp3; + __m256i const_val0 = __lasx_xvreplgr2vr_w(const_val); + __m256i const_val1, select_vec, temp; + + LASX_IDCTROWCONDDC + LASX_IDCTCOLS + a0 = __lasx_xvldrepl_d(dst1, 0); + a0 = __lasx_vext2xv_hu_bu(a0); + dst1 += dst_stride; + a1 = __lasx_xvldrepl_d(dst1, 0); + a1 = __lasx_vext2xv_hu_bu(a1); + dst1 += dst_stride; + a2 = __lasx_xvldrepl_d(dst1, 0); + a2 = __lasx_vext2xv_hu_bu(a2); + dst1 += dst_stride; + a3 = __lasx_xvldrepl_d(dst1, 0); + a3 = __lasx_vext2xv_hu_bu(a3); + dst1 += dst_stride; + b0 = __lasx_xvldrepl_d(dst1, 0); + b0 = __lasx_vext2xv_hu_bu(b0); + dst1 += dst_stride; + b1 = __lasx_xvldrepl_d(dst1, 0); + b1 = __lasx_vext2xv_hu_bu(b1); + dst1 += dst_stride; + b2 = __lasx_xvldrepl_d(dst1, 0); + b2 = __lasx_vext2xv_hu_bu(b2); + dst1 += dst_stride; + b3 = __lasx_xvldrepl_d(dst1, 0); + b3 = __lasx_vext2xv_hu_bu(b3); + DUP4_ARG3(__lasx_xvshuf_h, sh, a1, a0, sh, a3, a2, sh, b1, b0, sh, b3, b2, + temp0, temp1, temp2, temp3); + DUP4_ARG2(__lasx_xvadd_h, temp0, in0, temp1, in1, temp2, in2, temp3, in3, + in0, in1, in2, in3); + DUP4_ARG2(__lasx_xvpermi_d, in0, 0xD8, in1, 0xD8, in2, 0xD8, in3, 0xD8, + in0, in1, in2, in3); + DUP4_ARG1(__lasx_xvclip255_h, in0, in1, in2, in3, in0, in1, in2, in3); + DUP2_ARG2(__lasx_xvpickev_b, in1, in0, in3, in2, in0, in1); + __lasx_xvstelm_d(in0, dst, 0, 0); + __lasx_xvstelm_d(in0, dst + dst_stride, 0, 2); + __lasx_xvstelm_d(in0, dst + dst_stride_2x, 0, 1); + __lasx_xvstelm_d(in0, dst + dst_stride_3x, 0, 3); + dst += dst_stride_4x; + __lasx_xvstelm_d(in1, dst, 0, 0); + __lasx_xvstelm_d(in1, dst + dst_stride, 0, 2); + __lasx_xvstelm_d(in1, dst + dst_stride_2x, 0, 1); + __lasx_xvstelm_d(in1, dst + dst_stride_3x, 0, 3); +} diff --git a/libavcodec/loongarch/videodsp_init.c b/libavcodec/loongarch/videodsp_init.c new file mode 100644 index 000000000..6cbb7763f --- /dev/null +++ b/libavcodec/loongarch/videodsp_init.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Xiwei Gu + * + * 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/videodsp.h" +#include "libavutil/attributes.h" + +static void prefetch_loongarch(uint8_t *mem, ptrdiff_t stride, int h) +{ + register const uint8_t *p = mem; + + __asm__ volatile ( + "1: \n\t" + "preld 0, %[p], 0 \n\t" + "preld 0, %[p], 32 \n\t" + "addi.d %[h], %[h], -1 \n\t" + "add.d %[p], %[p], %[stride] \n\t" + + "blt $r0, %[h], 1b \n\t" + : [p] "+r" (p), [h] "+r" (h) + : [stride] "r" (stride) + ); +} + +av_cold void ff_videodsp_init_loongarch(VideoDSPContext *ctx, int bpc) +{ + ctx->prefetch = prefetch_loongarch; +} diff --git a/libavcodec/lossless_audiodsp.c b/libavcodec/lossless_audiodsp.c index 274ab5a85..1daf2e4c1 100644 --- a/libavcodec/lossless_audiodsp.c +++ b/libavcodec/lossless_audiodsp.c @@ -59,10 +59,11 @@ av_cold void ff_llauddsp_init(LLAudDSPContext *c) c->scalarproduct_and_madd_int16 = scalarproduct_and_madd_int16_c; c->scalarproduct_and_madd_int32 = scalarproduct_and_madd_int32_c; - if (ARCH_ARM) - ff_llauddsp_init_arm(c); - if (ARCH_PPC) - ff_llauddsp_init_ppc(c); - if (ARCH_X86) - ff_llauddsp_init_x86(c); +#if ARCH_ARM + ff_llauddsp_init_arm(c); +#elif ARCH_PPC + ff_llauddsp_init_ppc(c); +#elif ARCH_X86 + ff_llauddsp_init_x86(c); +#endif } diff --git a/libavcodec/lossless_videodsp.c b/libavcodec/lossless_videodsp.c index fa0869eef..359606981 100644 --- a/libavcodec/lossless_videodsp.c +++ b/libavcodec/lossless_videodsp.c @@ -119,8 +119,9 @@ void ff_llviddsp_init(LLVidDSPContext *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); - if (ARCH_X86) - ff_llviddsp_init_x86(c); +#if ARCH_PPC + ff_llviddsp_init_ppc(c); +#elif ARCH_X86 + ff_llviddsp_init_x86(c); +#endif } diff --git a/libavcodec/lossless_videoencdsp.c b/libavcodec/lossless_videoencdsp.c index ed7032962..e0b78bb3d 100644 --- a/libavcodec/lossless_videoencdsp.c +++ b/libavcodec/lossless_videoencdsp.c @@ -94,6 +94,7 @@ av_cold void ff_llvidencdsp_init(LLVidEncDSPContext *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); +#if ARCH_X86 + ff_llvidencdsp_init_x86(c); +#endif } diff --git a/libavcodec/lpc.c b/libavcodec/lpc.c index 3ed61563e..3238ad5fc 100644 --- a/libavcodec/lpc.c +++ b/libavcodec/lpc.c @@ -314,8 +314,9 @@ av_cold int ff_lpc_init(LPCContext *s, int blocksize, int max_order, s->lpc_apply_welch_window = lpc_apply_welch_window_c; s->lpc_compute_autocorr = lpc_compute_autocorr_c; - if (ARCH_X86) - ff_lpc_init_x86(s); +#if ARCH_X86 + ff_lpc_init_x86(s); +#endif return 0; } diff --git a/libavcodec/lscrdec.c b/libavcodec/lscrdec.c index 18f46bd27..9e7010c28 100644 --- a/libavcodec/lscrdec.c +++ b/libavcodec/lscrdec.c @@ -28,10 +28,12 @@ #include "avcodec.h" #include "bytestream.h" #include "codec.h" +#include "codec_internal.h" #include "internal.h" #include "packet.h" #include "png.h" #include "pngdsp.h" +#include "zlib_wrapper.h" typedef struct LSCRContext { PNGDSPContext dsp; @@ -52,7 +54,7 @@ typedef struct LSCRContext { int cur_h; int y; - z_stream zstream; + FFZStream zstream; } LSCRContext; static void handle_row(LSCRContext *s) @@ -71,11 +73,11 @@ static void handle_row(LSCRContext *s) s->y++; } -static int decode_idat(LSCRContext *s, int length) +static int decode_idat(LSCRContext *s, z_stream *zstream, int length) { int ret; - s->zstream.avail_in = FFMIN(length, bytestream2_get_bytes_left(&s->gb)); - s->zstream.next_in = s->gb.buffer; + zstream->avail_in = FFMIN(length, bytestream2_get_bytes_left(&s->gb)); + zstream->next_in = s->gb.buffer; if (length <= 0) return AVERROR_INVALIDDATA; @@ -83,31 +85,30 @@ static int decode_idat(LSCRContext *s, int length) bytestream2_skip(&s->gb, length); /* decode one line if possible */ - while (s->zstream.avail_in > 0) { - ret = inflate(&s->zstream, Z_PARTIAL_FLUSH); + while (zstream->avail_in > 0) { + ret = inflate(zstream, Z_PARTIAL_FLUSH); if (ret != Z_OK && ret != Z_STREAM_END) { av_log(s->avctx, AV_LOG_ERROR, "inflate returned error %d\n", ret); return AVERROR_EXTERNAL; } - if (s->zstream.avail_out == 0) { + if (zstream->avail_out == 0) { if (s->y < s->cur_h) { handle_row(s); } - s->zstream.avail_out = s->crow_size; - s->zstream.next_out = s->crow_buf; + zstream->avail_out = s->crow_size; + zstream->next_out = s->crow_buf; } - if (ret == Z_STREAM_END && s->zstream.avail_in > 0) { + if (ret == Z_STREAM_END && zstream->avail_in > 0) { av_log(s->avctx, AV_LOG_WARNING, - "%d undecompressed bytes left in buffer\n", s->zstream.avail_in); + "%d undecompressed bytes left in buffer\n", zstream->avail_in); return 0; } } return 0; } -static int decode_frame_lscr(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame_lscr(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *avpkt) { LSCRContext *const s = avctx->priv_data; GetByteContext *gb = &s->gb; @@ -131,18 +132,12 @@ static int decode_frame_lscr(AVCodecContext *avctx, return ret; for (int b = 0; b < nb_blocks; b++) { + z_stream *const zstream = &s->zstream.zstream; int x, y, x2, y2, w, h, left; uint32_t csize, size; - s->zstream.zalloc = ff_png_zalloc; - s->zstream.zfree = ff_png_zfree; - s->zstream.opaque = NULL; - - if ((ret = inflateInit(&s->zstream)) != Z_OK) { - av_log(avctx, AV_LOG_ERROR, "inflateInit returned error %d\n", ret); - ret = AVERROR_EXTERNAL; - goto end; - } + if (inflateReset(zstream) != Z_OK) + return AVERROR_EXTERNAL; bytestream2_seek(gb, 2 + b * 12, SEEK_SET); @@ -154,10 +149,8 @@ static int decode_frame_lscr(AVCodecContext *avctx, s->cur_h = h = y2-y; if (w <= 0 || x < 0 || x >= avctx->width || w + x > avctx->width || - h <= 0 || y < 0 || y >= avctx->height || h + y > avctx->height) { - ret = AVERROR_INVALIDDATA; - goto end; - } + h <= 0 || y < 0 || y >= avctx->height || h + y > avctx->height) + return AVERROR_INVALIDDATA; size = bytestream2_get_le32(gb); @@ -168,10 +161,8 @@ static int decode_frame_lscr(AVCodecContext *avctx, bytestream2_seek(gb, 2 + nb_blocks * 12 + offset, SEEK_SET); csize = bytestream2_get_be32(gb); - if (bytestream2_get_le32(gb) != MKTAG('I', 'D', 'A', 'T')) { - ret = AVERROR_INVALIDDATA; - goto end; - } + if (bytestream2_get_le32(gb) != MKTAG('I', 'D', 'A', 'T')) + return AVERROR_INVALIDDATA; offset += size; left = size; @@ -180,53 +171,41 @@ static int decode_frame_lscr(AVCodecContext *avctx, s->row_size = w * 3; av_fast_padded_malloc(&s->buffer, &s->buffer_size, s->row_size + 16); - if (!s->buffer) { - ret = AVERROR(ENOMEM); - goto end; - } + if (!s->buffer) + return AVERROR(ENOMEM); av_fast_padded_malloc(&s->last_row, &s->last_row_size, s->row_size); - if (!s->last_row) { - ret = AVERROR(ENOMEM); - goto end; - } + if (!s->last_row) + return AVERROR(ENOMEM); s->crow_size = w * 3 + 1; s->crow_buf = s->buffer + 15; - s->zstream.avail_out = s->crow_size; - s->zstream.next_out = s->crow_buf; + zstream->avail_out = s->crow_size; + zstream->next_out = s->crow_buf; s->image_buf = frame->data[0] + (avctx->height - y - 1) * frame->linesize[0] + x * 3; s->image_linesize =-frame->linesize[0]; while (left > 16) { - ret = decode_idat(s, csize); + ret = decode_idat(s, zstream, csize); if (ret < 0) - goto end; + return ret; left -= csize + 16; if (left > 16) { bytestream2_skip(gb, 4); csize = bytestream2_get_be32(gb); - if (bytestream2_get_le32(gb) != MKTAG('I', 'D', 'A', 'T')) { - ret = AVERROR_INVALIDDATA; - goto end; - } + if (bytestream2_get_le32(gb) != MKTAG('I', 'D', 'A', 'T')) + return AVERROR_INVALIDDATA; } } - - inflateEnd(&s->zstream); } frame->pict_type = frame->key_frame ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; - if ((ret = av_frame_ref(data, frame)) < 0) + if ((ret = av_frame_ref(rframe, frame)) < 0) return ret; *got_frame = 1; -end: - inflateEnd(&s->zstream); - if (ret < 0) - return ret; return avpkt->size; } @@ -237,6 +216,7 @@ static int lscr_decode_close(AVCodecContext *avctx) av_frame_free(&s->last_picture); av_freep(&s->buffer); av_freep(&s->last_row); + ff_inflate_end(&s->zstream); return 0; } @@ -255,7 +235,7 @@ static int lscr_decode_init(AVCodecContext *avctx) ff_pngdsp_init(&s->dsp); - return 0; + return ff_inflate_init(&s->zstream, avctx); } static void lscr_decode_flush(AVCodecContext *avctx) @@ -264,16 +244,16 @@ static void lscr_decode_flush(AVCodecContext *avctx) av_frame_unref(s->last_picture); } -const AVCodec ff_lscr_decoder = { - .name = "lscr", - .long_name = NULL_IF_CONFIG_SMALL("LEAD Screen Capture"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_LSCR, +const FFCodec ff_lscr_decoder = { + .p.name = "lscr", + .p.long_name = NULL_IF_CONFIG_SMALL("LEAD Screen Capture"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_LSCR, + .p.capabilities = AV_CODEC_CAP_DR1, .priv_data_size = sizeof(LSCRContext), .init = lscr_decode_init, .close = lscr_decode_close, - .decode = decode_frame_lscr, + FF_CODEC_DECODE_CB(decode_frame_lscr), .flush = lscr_decode_flush, - .capabilities = AV_CODEC_CAP_DR1, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/lsp.c b/libavcodec/lsp.c index 29055fd47..90f2efaaf 100644 --- a/libavcodec/lsp.c +++ b/libavcodec/lsp.c @@ -21,10 +21,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include +#include #define FRAC_BITS 14 -#include "libavutil/common.h" +#include "libavutil/macros.h" #include "mathops.h" #include "lsp.h" #include "libavcodec/mips/lsp_mips.h" diff --git a/libavcodec/lzwenc.c b/libavcodec/lzwenc.c index bb8eb2e1d..ae1816a03 100644 --- a/libavcodec/lzwenc.c +++ b/libavcodec/lzwenc.c @@ -27,7 +27,7 @@ #include #include "libavutil/avassert.h" -#include "libavutil/common.h" +#include "libavutil/macros.h" #include "lzw.h" #include "put_bits.h" diff --git a/libavcodec/m101.c b/libavcodec/m101.c index dd0ace76f..fce31956c 100644 --- a/libavcodec/m101.c +++ b/libavcodec/m101.c @@ -21,6 +21,7 @@ #include "libavutil/intreadwrite.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" @@ -43,15 +44,14 @@ static av_cold int m101_decode_init(AVCodecContext *avctx) return 0; } -static int m101_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int m101_decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int stride, ret; int x, y; int min_stride = 2 * avctx->width; int bits = avctx->extradata[2*4]; - AVFrame *frame = data; if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; @@ -105,13 +105,13 @@ static int m101_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, return avpkt->size; } -const AVCodec ff_m101_decoder = { - .name = "m101", - .long_name = NULL_IF_CONFIG_SMALL("Matrox Uncompressed SD"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_M101, +const FFCodec ff_m101_decoder = { + .p.name = "m101", + .p.long_name = NULL_IF_CONFIG_SMALL("Matrox Uncompressed SD"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_M101, .init = m101_decode_init, - .decode = m101_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(m101_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/mace.c b/libavcodec/mace.c index 506a0ddec..110b32003 100644 --- a/libavcodec/mace.c +++ b/libavcodec/mace.c @@ -25,6 +25,7 @@ */ #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "libavutil/common.h" @@ -182,14 +183,13 @@ static int16_t read_table(ChannelData *chd, uint8_t val, int tab_idx) current = - 1 - tabs[tab_idx].tab2[((chd->index & 0x7f0) >> 4)*tabs[tab_idx].stride + 2*tabs[tab_idx].stride-val-1]; if (( chd->index += tabs[tab_idx].tab1[val]-(chd->index >> 5) ) < 0) - chd->index = 0; + chd->index = 0; return current; } static void chomp3(ChannelData *chd, int16_t *output, uint8_t val, int tab_idx) { - int16_t current = read_table(chd, val, tab_idx); current = mace_broken_clip_int16(current + chd->level); @@ -226,44 +226,44 @@ static void chomp6(ChannelData *chd, int16_t *output, uint8_t val, int tab_idx) static av_cold int mace_decode_init(AVCodecContext * avctx) { - if (avctx->channels > 2 || avctx->channels < 1) + if (avctx->ch_layout.nb_channels > 2 || avctx->ch_layout.nb_channels < 1) return AVERROR(EINVAL); avctx->sample_fmt = AV_SAMPLE_FMT_S16P; return 0; } -static int mace_decode_frame(AVCodecContext *avctx, void *data, +static int mace_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; + int channels = avctx->ch_layout.nb_channels; int16_t **samples; MACEContext *ctx = avctx->priv_data; int i, j, k, l, ret; int is_mace3 = (avctx->codec_id == AV_CODEC_ID_MACE3); - if (buf_size % (avctx->channels << is_mace3)) { + if (buf_size % (channels << is_mace3)) { av_log(avctx, AV_LOG_ERROR, "buffer size %d is odd\n", buf_size); - buf_size -= buf_size % (avctx->channels << is_mace3); + buf_size -= buf_size % (channels << is_mace3); if (!buf_size) return AVERROR_INVALIDDATA; } /* get output buffer */ - frame->nb_samples = 3 * (buf_size << (1 - is_mace3)) / avctx->channels; + frame->nb_samples = 3 * (buf_size << (1 - is_mace3)) / channels; if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; samples = (int16_t **)frame->extended_data; - for(i = 0; i < avctx->channels; i++) { + for(i = 0; i < channels; i++) { int16_t *output = samples[i]; - for (j=0; j < buf_size / (avctx->channels << is_mace3); j++) + for (j=0; j < buf_size / (channels << is_mace3); j++) for (k=0; k < (1 << is_mace3); k++) { uint8_t pkt = buf[(i << is_mace3) + - (j*avctx->channels << is_mace3) + k]; + (j * channels << is_mace3) + k]; uint8_t val[2][3] = {{pkt >> 5, (pkt >> 3) & 3, pkt & 7 }, {pkt & 7 , (pkt >> 3) & 3, pkt >> 5}}; @@ -284,30 +284,30 @@ static int mace_decode_frame(AVCodecContext *avctx, void *data, return buf_size; } -const AVCodec ff_mace3_decoder = { - .name = "mace3", - .long_name = NULL_IF_CONFIG_SMALL("MACE (Macintosh Audio Compression/Expansion) 3:1"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_MACE3, +const FFCodec ff_mace3_decoder = { + .p.name = "mace3", + .p.long_name = NULL_IF_CONFIG_SMALL("MACE (Macintosh Audio Compression/Expansion) 3:1"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_MACE3, .priv_data_size = sizeof(MACEContext), .init = mace_decode_init, - .decode = mace_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, + FF_CODEC_DECODE_CB(mace_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; -const AVCodec ff_mace6_decoder = { - .name = "mace6", - .long_name = NULL_IF_CONFIG_SMALL("MACE (Macintosh Audio Compression/Expansion) 6:1"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_MACE6, +const FFCodec ff_mace6_decoder = { + .p.name = "mace6", + .p.long_name = NULL_IF_CONFIG_SMALL("MACE (Macintosh Audio Compression/Expansion) 6:1"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_MACE6, .priv_data_size = sizeof(MACEContext), .init = mace_decode_init, - .decode = mace_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, + FF_CODEC_DECODE_CB(mace_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/magicyuv.c b/libavcodec/magicyuv.c index 594196063..634d45ca4 100644 --- a/libavcodec/magicyuv.c +++ b/libavcodec/magicyuv.c @@ -28,6 +28,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "get_bits.h" #include "huffyuvdsp.h" #include "internal.h" @@ -427,12 +428,10 @@ static int build_huffman(AVCodecContext *avctx, const uint8_t *table, return 0; } -static int magy_decode_frame(AVCodecContext *avctx, void *data, +static int magy_decode_frame(AVCodecContext *avctx, AVFrame *p, int *got_frame, AVPacket *avpkt) { MagicYUVContext *s = avctx->priv_data; - ThreadFrame frame = { .f = data }; - AVFrame *p = data; GetByteContext gb; uint32_t first_offset, offset, next_offset, header_size, slice_width; int width, height, format, version, table_size; @@ -641,7 +640,7 @@ static int magy_decode_frame(AVCodecContext *avctx, void *data, p->pict_type = AV_PICTURE_TYPE_I; p->key_frame = 1; - if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, p, 0)) < 0) return ret; s->buf = avpkt->data; @@ -694,16 +693,16 @@ static av_cold int magy_decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_magicyuv_decoder = { - .name = "magicyuv", - .long_name = NULL_IF_CONFIG_SMALL("MagicYUV video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MAGICYUV, +const FFCodec ff_magicyuv_decoder = { + .p.name = "magicyuv", + .p.long_name = NULL_IF_CONFIG_SMALL("MagicYUV video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MAGICYUV, .priv_data_size = sizeof(MagicYUVContext), .init = magy_decode_init, .close = magy_decode_end, - .decode = magy_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | + FF_CODEC_DECODE_CB(magy_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_SLICE_THREADS, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, diff --git a/libavcodec/magicyuvenc.c b/libavcodec/magicyuvenc.c index ab32d4cee..ce492368e 100644 --- a/libavcodec/magicyuvenc.c +++ b/libavcodec/magicyuvenc.c @@ -28,9 +28,9 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "encode.h" #include "put_bits.h" -#include "internal.h" #include "thread.h" #include "lossless_videoencdsp.h" @@ -58,7 +58,6 @@ typedef struct MagicYUVContext { PutBitContext pb; int planes; uint8_t format; - AVFrame *p; int slice_height; int nb_slices; int correlate; @@ -67,14 +66,15 @@ typedef struct MagicYUVContext { uint8_t *slices[4]; unsigned slice_pos[4]; unsigned tables_size; + uint8_t *decorrelate_buf[2]; HuffEntry he[4][256]; LLVidEncDSPContext llvidencdsp; - void (*predict)(struct MagicYUVContext *s, uint8_t *src, uint8_t *dst, + void (*predict)(struct MagicYUVContext *s, const 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, + const uint8_t *src, uint8_t *dst, ptrdiff_t stride, int width, int height) { uint8_t prev = 0; @@ -98,7 +98,7 @@ static void left_predict(MagicYUVContext *s, } static void gradient_predict(MagicYUVContext *s, - uint8_t *src, uint8_t *dst, ptrdiff_t stride, + const uint8_t *src, uint8_t *dst, ptrdiff_t stride, int width, int height) { int left = 0, top, lefttop; @@ -126,7 +126,7 @@ static void gradient_predict(MagicYUVContext *s, } static void median_predict(MagicYUVContext *s, - uint8_t *src, uint8_t *dst, ptrdiff_t stride, + const uint8_t *src, uint8_t *dst, ptrdiff_t stride, int width, int height) { int left = 0, lefttop; @@ -190,6 +190,12 @@ static av_cold int magy_encode_init(AVCodecContext *avctx) s->format = 0x6b; break; } + if (s->correlate) { + s->decorrelate_buf[0] = av_calloc(2U * avctx->height, FFALIGN(avctx->width, 16)); + if (!s->decorrelate_buf[0]) + return AVERROR(ENOMEM); + s->decorrelate_buf[1] = s->decorrelate_buf[0] + avctx->height * FFALIGN(avctx->width, 16); + } ff_llvidencdsp_init(&s->llvidencdsp); @@ -452,32 +458,34 @@ static int magy_encode_frame(AVCodecContext *avctx, AVPacket *pkt, } if (s->correlate) { - uint8_t *r, *g, *b; - AVFrame *p = av_frame_clone(frame); + uint8_t *r, *g, *b, *decorrelated[2] = { s->decorrelate_buf[0], + s->decorrelate_buf[1] }; + const int decorrelate_linesize = FFALIGN(width, 16); + const uint8_t *const data[4] = { decorrelated[0], frame->data[0], + decorrelated[1], frame->data[3] }; + const int linesize[4] = { decorrelate_linesize, frame->linesize[0], + decorrelate_linesize, frame->linesize[3] }; - g = p->data[0]; - b = p->data[1]; - r = p->data[2]; + g = frame->data[0]; + b = frame->data[1]; + r = frame->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]; + s->llvidencdsp.diff_bytes(decorrelated[0], b, g, width); + s->llvidencdsp.diff_bytes(decorrelated[1], r, g, width); + g += frame->linesize[0]; + b += frame->linesize[1]; + r += frame->linesize[2]; + decorrelated[0] += decorrelate_linesize; + decorrelated[1] += decorrelate_linesize; } - 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); + s->predict(s, data[i], s->slices[i], linesize[i], + frame->width, frame->height); } } - - av_frame_free(&p); } else { for (i = 0; i < s->planes; i++) { for (slice = 0; slice < s->nb_slices; slice++) { @@ -533,6 +541,7 @@ static av_cold int magy_encode_close(AVCodecContext *avctx) for (i = 0; i < s->planes; i++) av_freep(&s->slices[i]); + av_freep(&s->decorrelate_buf); return 0; } @@ -554,18 +563,18 @@ static const AVClass magicyuv_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_magicyuv_encoder = { - .name = "magicyuv", - .long_name = NULL_IF_CONFIG_SMALL("MagicYUV video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MAGICYUV, +const FFCodec ff_magicyuv_encoder = { + .p.name = "magicyuv", + .p.long_name = NULL_IF_CONFIG_SMALL("MagicYUV video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MAGICYUV, .priv_data_size = sizeof(MagicYUVContext), - .priv_class = &magicyuv_class, + .p.priv_class = &magicyuv_class, .init = magy_encode_init, .close = magy_encode_close, - .encode2 = magy_encode_frame, - .capabilities = AV_CODEC_CAP_FRAME_THREADS, - .pix_fmts = (const enum AVPixelFormat[]) { + FF_CODEC_ENCODE_CB(magy_encode_frame), + .p.capabilities = AV_CODEC_CAP_FRAME_THREADS, + .p.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 diff --git a/libavcodec/mathops.h b/libavcodec/mathops.h index 1c3566431..f81d21f9c 100644 --- a/libavcodec/mathops.h +++ b/libavcodec/mathops.h @@ -25,12 +25,12 @@ #include #include "libavutil/common.h" -#include "libavutil/reverse.h" #include "config.h" #define MAX_NEG_CROP 1024 extern const uint32_t ff_inverse[257]; +extern const uint8_t ff_log2_run[41]; extern const uint8_t ff_sqrt_tab[256]; extern const uint8_t ff_crop_tab[256 + 2 * MAX_NEG_CROP]; extern const uint8_t ff_zigzag_direct[64]; @@ -126,6 +126,8 @@ static inline av_const int median4(int a, int b, int c, int d) } #endif +#define FF_SIGNBIT(x) ((x) >> CHAR_BIT * sizeof(x) - 1) + #ifndef sign_extend static inline av_const int sign_extend(int val, unsigned bits) { @@ -240,12 +242,4 @@ static inline int8_t ff_u8_to_s8(uint8_t a) return b.s8; } -static av_always_inline uint32_t bitswap_32(uint32_t x) -{ - return (uint32_t)ff_reverse[ x & 0xFF] << 24 | - (uint32_t)ff_reverse[(x >> 8) & 0xFF] << 16 | - (uint32_t)ff_reverse[(x >> 16) & 0xFF] << 8 | - (uint32_t)ff_reverse[ x >> 24]; -} - #endif /* AVCODEC_MATHOPS_H */ diff --git a/libavcodec/mathtables.c b/libavcodec/mathtables.c index 81eabc7a6..8b0031eb0 100644 --- a/libavcodec/mathtables.c +++ b/libavcodec/mathtables.c @@ -112,3 +112,12 @@ const uint8_t ff_zigzag_scan[16+1] = { 1 + 2 * 4, 0 + 3 * 4, 1 + 3 * 4, 2 + 2 * 4, 3 + 1 * 4, 3 + 2 * 4, 2 + 3 * 4, 3 + 3 * 4, }; + +const uint8_t ff_log2_run[41] = { + 0, 0, 0, 0, 1, 1, 1, 1, + 2, 2, 2, 2, 3, 3, 3, 3, + 4, 4, 5, 5, 6, 6, 7, 7, + 8, 9, 10, 11, 12, 13, 14, 15, +16, 17, 18, 19, 20, 21, 22, 23, +24, +}; diff --git a/libavcodec/mdct15.c b/libavcodec/mdct15.c index 6f35059bf..f8ed74d15 100644 --- a/libavcodec/mdct15.c +++ b/libavcodec/mdct15.c @@ -27,11 +27,12 @@ #include #include #include +#include #include "config.h" #include "libavutil/attributes.h" -#include "libavutil/common.h" +#include "libavutil/error.h" #include "mdct15.h" @@ -316,8 +317,9 @@ av_cold int ff_mdct15_init(MDCT15Context **ps, int inverse, int N, double scale) s->exptab[20].im *= -1; } - if (ARCH_X86) - ff_mdct15_init_x86(s); +#if ARCH_X86 + ff_mdct15_init_x86(s); +#endif *ps = s; diff --git a/libavcodec/mdec.c b/libavcodec/mdec.c index 39efed69b..deabebda6 100644 --- a/libavcodec/mdec.c +++ b/libavcodec/mdec.c @@ -32,8 +32,10 @@ #include "avcodec.h" #include "blockdsp.h" #include "bswapdsp.h" +#include "codec_internal.h" #include "idctdsp.h" -#include "mpeg12.h" +#include "mpeg12data.h" +#include "mpeg12dec.h" #include "thread.h" typedef struct MDECContext { @@ -41,7 +43,6 @@ typedef struct MDECContext { BlockDSPContext bdsp; BswapDSPContext bbdsp; IDCTDSPContext idsp; - ThreadFrame frame; GetBitContext gb; ScanTable scantable; int version; @@ -166,20 +167,18 @@ static inline void idct_put(MDECContext *a, AVFrame *frame, int mb_x, int mb_y) } } -static int decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { MDECContext * const a = avctx->priv_data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; - ThreadFrame frame = { .f = data }; int ret; - if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, frame, 0)) < 0) return ret; - frame.f->pict_type = AV_PICTURE_TYPE_I; - frame.f->key_frame = 1; + frame->pict_type = AV_PICTURE_TYPE_I; + frame->key_frame = 1; av_fast_padded_malloc(&a->bitstream_buffer, &a->bitstream_buffer_size, buf_size); if (!a->bitstream_buffer) @@ -201,7 +200,7 @@ static int decode_frame(AVCodecContext *avctx, if ((ret = decode_mb(a, a->block)) < 0) return ret; - idct_put(a, frame.f, a->mb_x, a->mb_y); + idct_put(a, frame, a->mb_x, a->mb_y); } } @@ -250,15 +249,15 @@ static av_cold int decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_mdec_decoder = { - .name = "mdec", - .long_name = NULL_IF_CONFIG_SMALL("Sony PlayStation MDEC (Motion DECoder)"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MDEC, +const FFCodec ff_mdec_decoder = { + .p.name = "mdec", + .p.long_name = NULL_IF_CONFIG_SMALL("Sony PlayStation MDEC (Motion DECoder)"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MDEC, .priv_data_size = sizeof(MDECContext), .init = decode_init, .close = decode_end, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/me_cmp.c b/libavcodec/me_cmp.c index 60545248b..d0cd14ad3 100644 --- a/libavcodec/me_cmp.c +++ b/libavcodec/me_cmp.c @@ -27,8 +27,9 @@ #include "copy_block.h" #include "simple_idct.h" #include "me_cmp.h" -#include "mpegvideo.h" +#include "mpegvideoenc.h" #include "config.h" +#include "config_components.h" /* (i - 256) * (i - 256) */ const uint32_t ff_square_tab[512] = { @@ -1060,16 +1061,19 @@ av_cold void ff_me_cmp_init(MECmpContext *c, AVCodecContext *avctx) ff_dsputil_init_dwt(c); #endif - if (ARCH_ALPHA) - ff_me_cmp_init_alpha(c, avctx); - if (ARCH_ARM) - ff_me_cmp_init_arm(c, avctx); - if (ARCH_PPC) - ff_me_cmp_init_ppc(c, avctx); - if (ARCH_X86) - ff_me_cmp_init_x86(c, avctx); - if (ARCH_MIPS) - ff_me_cmp_init_mips(c, avctx); +#if ARCH_AARCH64 + ff_me_cmp_init_aarch64(c, avctx); +#elif ARCH_ALPHA + ff_me_cmp_init_alpha(c, avctx); +#elif ARCH_ARM + ff_me_cmp_init_arm(c, avctx); +#elif ARCH_PPC + ff_me_cmp_init_ppc(c, avctx); +#elif ARCH_X86 + ff_me_cmp_init_x86(c, avctx); +#elif ARCH_MIPS + ff_me_cmp_init_mips(c, avctx); +#endif c->median_sad[0] = pix_median_abs16_c; c->median_sad[1] = pix_median_abs8_c; diff --git a/libavcodec/me_cmp.h b/libavcodec/me_cmp.h index e9b5161c9..7b057a923 100644 --- a/libavcodec/me_cmp.h +++ b/libavcodec/me_cmp.h @@ -80,6 +80,7 @@ typedef struct MECmpContext { } MECmpContext; void ff_me_cmp_init(MECmpContext *c, AVCodecContext *avctx); +void ff_me_cmp_init_aarch64(MECmpContext *c, AVCodecContext *avctx); void ff_me_cmp_init_alpha(MECmpContext *c, AVCodecContext *avctx); void ff_me_cmp_init_arm(MECmpContext *c, AVCodecContext *avctx); void ff_me_cmp_init_ppc(MECmpContext *c, AVCodecContext *avctx); diff --git a/libavcodec/mediacodec.c b/libavcodec/mediacodec.c index aa14624fd..33bde8112 100644 --- a/libavcodec/mediacodec.c +++ b/libavcodec/mediacodec.c @@ -35,7 +35,6 @@ #include "ffjni.h" #include "mediacodecdec_common.h" -#include "version.h" AVMediaCodecContext *av_mediacodec_alloc_context(void) { diff --git a/libavcodec/mediacodec_wrapper.c b/libavcodec/mediacodec_wrapper.c index c829941d6..8ffc58e1d 100644 --- a/libavcodec/mediacodec_wrapper.c +++ b/libavcodec/mediacodec_wrapper.c @@ -28,7 +28,6 @@ #include "avcodec.h" #include "ffjni.h" -#include "version.h" #include "mediacodec_wrapper.h" struct JNIAMediaCodecListFields { diff --git a/libavcodec/mediacodecdec.c b/libavcodec/mediacodecdec.c index 04d5026e6..6b4c39b4e 100644 --- a/libavcodec/mediacodecdec.c +++ b/libavcodec/mediacodecdec.c @@ -20,6 +20,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include #include @@ -31,8 +33,10 @@ #include "libavutil/internal.h" #include "avcodec.h" +#include "codec_internal.h" #include "decode.h" #include "h264_parse.h" +#include "h264_ps.h" #include "hevc_parse.h" #include "hwconfig.h" #include "internal.h" @@ -528,22 +532,22 @@ static const AVClass ff_##short_name##_mediacodec_dec_class = { \ #define DECLARE_MEDIACODEC_VDEC(short_name, full_name, codec_id, bsf) \ DECLARE_MEDIACODEC_VCLASS(short_name) \ -const 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, \ +const FFCodec ff_ ## short_name ## _mediacodec_decoder = { \ + .p.name = #short_name "_mediacodec", \ + .p.long_name = NULL_IF_CONFIG_SMALL(full_name " Android MediaCodec decoder"), \ + .p.type = AVMEDIA_TYPE_VIDEO, \ + .p.id = codec_id, \ + .p.priv_class = &ff_##short_name##_mediacodec_dec_class, \ .priv_data_size = sizeof(MediaCodecH264DecContext), \ .init = mediacodec_decode_init, \ - .receive_frame = mediacodec_receive_frame, \ + FF_CODEC_RECEIVE_FRAME_CB(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, \ + .p.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", \ + .p.wrapper_name = "mediacodec", \ }; \ #if CONFIG_H264_MEDIACODEC_DECODER diff --git a/libavcodec/metasound.c b/libavcodec/metasound.c index 57851a43c..9c5d0369c 100644 --- a/libavcodec/metasound.c +++ b/libavcodec/metasound.c @@ -30,9 +30,9 @@ #define BITSTREAM_READER_LE #include "avcodec.h" +#include "codec_internal.h" #include "fft.h" #include "get_bits.h" -#include "internal.h" #include "lsp.h" #include "sinewin.h" @@ -65,8 +65,9 @@ static void decode_ppc(TwinVQContext *tctx, int period_coef, int g_coef, const float *shape, float *speech) { const TwinVQModeTab *mtab = tctx->mtab; + int channels = tctx->avctx->ch_layout.nb_channels; int isampf = tctx->avctx->sample_rate / 1000; - int ibps = tctx->avctx->bit_rate / (1000 * tctx->avctx->channels); + int ibps = tctx->avctx->bit_rate / (1000 * channels); int width; float ratio = (float)mtab->size / isampf; @@ -75,7 +76,7 @@ static void decode_ppc(TwinVQContext *tctx, int period_coef, int g_coef, float pgain_base, pgain_step, ppc_gain; - if (tctx->avctx->channels == 1) { + if (channels == 1) { min_period = log2(ratio * 0.2); max_period = min_period + log2(6); } else { @@ -85,7 +86,7 @@ static void decode_ppc(TwinVQContext *tctx, int period_coef, int g_coef, period_range = max_period - min_period; period = min_period + period_coef * period_range / ((1 << mtab->ppc_period_bit) - 1); - if (tctx->avctx->channels == 1) + if (channels == 1) period = powf(2.0, period); else period = (int)(period * 400 + 0.5) / 400.0; @@ -103,7 +104,7 @@ static void decode_ppc(TwinVQContext *tctx, int period_coef, int g_coef, if (isampf == 22 && ibps == 32) width = (int)((2.0 / period + 1) * width + 0.5); - pgain_base = tctx->avctx->channels == 2 ? 25000.0 : 20000.0; + pgain_base = channels == 2 ? 25000.0 : 20000.0; pgain_step = pgain_base / ((1 << mtab->pgain_bit) - 1); ppc_gain = 1.0 / 8192 * twinvq_mulawinv(pgain_step * g_coef + pgain_step / 2, @@ -123,8 +124,9 @@ static void dec_bark_env(TwinVQContext *tctx, const uint8_t *in, int use_hist, int bark_n_coef = mtab->fmode[ftype].bark_n_coef; int fw_cb_len = mtab->fmode[ftype].bark_env_size / bark_n_coef; int idx = 0; + int channels = tctx->avctx->ch_layout.nb_channels; - if (tctx->avctx->channels == 1) + if (channels == 1) val = 0.5; for (i = 0; i < fw_cb_len; i++) for (j = 0; j < bark_n_coef; j++, idx++) { @@ -132,7 +134,7 @@ static void dec_bark_env(TwinVQContext *tctx, const uint8_t *in, int use_hist, (1.0 / 2048); float st; - if (tctx->avctx->channels == 1) + if (channels == 1) st = use_hist ? tmp2 + val * hist[idx] + 1.0 : tmp2 + 1.0; else @@ -167,7 +169,7 @@ static int metasound_read_bitstream(AVCodecContext *avctx, TwinVQContext *tctx, { TwinVQFrameData *bits; const TwinVQModeTab *mtab = tctx->mtab; - int channels = tctx->avctx->channels; + int channels = tctx->avctx->ch_layout.nb_channels; int sub; GetBitContext gb; int i, j, k, ret; @@ -276,6 +278,7 @@ static av_cold int metasound_decode_init(AVCodecContext *avctx) TwinVQContext *tctx = avctx->priv_data; uint32_t tag; const MetasoundProps *props = codec_props; + int channels; if (!avctx->extradata || avctx->extradata_size < 16) { av_log(avctx, AV_LOG_ERROR, "Missing or incomplete extradata\n"); @@ -291,7 +294,7 @@ static av_cold int metasound_decode_init(AVCodecContext *avctx) } if (props->tag == tag) { avctx->sample_rate = props->sample_rate; - avctx->channels = props->channels; + channels = props->channels; avctx->bit_rate = props->bit_rate * 1000; isampf = avctx->sample_rate / 1000; break; @@ -299,17 +302,17 @@ static av_cold int metasound_decode_init(AVCodecContext *avctx) props++; } - if (avctx->channels <= 0 || avctx->channels > TWINVQ_CHANNELS_MAX) { + if (channels <= 0 || channels > TWINVQ_CHANNELS_MAX) { av_log(avctx, AV_LOG_ERROR, "Unsupported number of channels: %i\n", - avctx->channels); + channels); return AVERROR_INVALIDDATA; } - avctx->channel_layout = avctx->channels == 1 ? AV_CH_LAYOUT_MONO - : AV_CH_LAYOUT_STEREO; + av_channel_layout_uninit(&avctx->ch_layout); + av_channel_layout_default(&avctx->ch_layout, channels); - ibps = avctx->bit_rate / (1000 * avctx->channels); + ibps = avctx->bit_rate / (1000 * channels); - switch ((avctx->channels << 16) + (isampf << 8) + ibps) { + switch ((channels << 16) + (isampf << 8) + ibps) { case (1 << 16) + ( 8 << 8) + 6: tctx->mtab = &ff_metasound_mode0806; break; @@ -370,17 +373,17 @@ static av_cold int metasound_decode_init(AVCodecContext *avctx) return ff_twinvq_decode_init(avctx); } -const AVCodec ff_metasound_decoder = { - .name = "metasound", - .long_name = NULL_IF_CONFIG_SMALL("Voxware MetaSound"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_METASOUND, +const FFCodec ff_metasound_decoder = { + .p.name = "metasound", + .p.long_name = NULL_IF_CONFIG_SMALL("Voxware MetaSound"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_METASOUND, .priv_data_size = sizeof(TwinVQContext), .init = metasound_decode_init, .close = ff_twinvq_decode_close, - .decode = ff_twinvq_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + FF_CODEC_DECODE_CB(ff_twinvq_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/metasound_data.c b/libavcodec/metasound_data.c index 22b2730dd..b2044364f 100644 --- a/libavcodec/metasound_data.c +++ b/libavcodec/metasound_data.c @@ -20,6 +20,7 @@ */ #include "config.h" +#include "config_components.h" #include "metasound_data.h" #if CONFIG_METASOUND_DECODER diff --git a/libavcodec/mf_utils.c b/libavcodec/mf_utils.c index eeabd0ce0..48e3a63ef 100644 --- a/libavcodec/mf_utils.c +++ b/libavcodec/mf_utils.c @@ -47,39 +47,6 @@ HRESULT ff_MFSetAttributeSize(IMFAttributes *pattr, REFGUID guid, #define ff_MFSetAttributeRatio ff_MFSetAttributeSize #define ff_MFGetAttributeRatio ff_MFGetAttributeSize -// MFTEnumEx was missing from mingw-w64's mfplat import library until -// mingw-w64 v6.0.0, thus wrap it and load it using GetProcAddress. -// It's also missing in Windows Vista's mfplat.dll. -HRESULT ff_MFTEnumEx(GUID guidCategory, UINT32 Flags, - const MFT_REGISTER_TYPE_INFO *pInputType, - const MFT_REGISTER_TYPE_INFO *pOutputType, - IMFActivate ***pppMFTActivate, UINT32 *pnumMFTActivate) -{ - HRESULT (WINAPI *MFTEnumEx_ptr)(GUID guidCategory, UINT32 Flags, - const MFT_REGISTER_TYPE_INFO *pInputType, - const MFT_REGISTER_TYPE_INFO *pOutputType, - IMFActivate ***pppMFTActivate, - UINT32 *pnumMFTActivate) = NULL; -#if !HAVE_UWP - HANDLE lib = GetModuleHandleW(L"mfplat.dll"); - if (lib) - MFTEnumEx_ptr = (void *)GetProcAddress(lib, "MFTEnumEx"); -#else - // In UWP (which lacks GetModuleHandle), just link directly against - // the functions - this requires building with new/complete enough - // import libraries. - MFTEnumEx_ptr = MFTEnumEx; -#endif - if (!MFTEnumEx_ptr) - return E_FAIL; - return MFTEnumEx_ptr(guidCategory, - Flags, - pInputType, - pOutputType, - pppMFTActivate, - pnumMFTActivate); -} - char *ff_hr_str_buf(char *buf, size_t size, HRESULT hr) { #define HR(x) case x: return (char *) # x; @@ -106,19 +73,20 @@ char *ff_hr_str_buf(char *buf, size_t size, HRESULT hr) // If fill_data!=NULL, initialize the buffer and set the length. (This is a // subtle but important difference: some decoders want CurrentLength==0 on // provided output buffers.) -IMFSample *ff_create_memory_sample(void *fill_data, size_t size, size_t align) +IMFSample *ff_create_memory_sample(MFFunctions *f,void *fill_data, size_t size, + size_t align) { HRESULT hr; IMFSample *sample; IMFMediaBuffer *buffer; - hr = MFCreateSample(&sample); + hr = f->MFCreateSample(&sample); if (FAILED(hr)) return NULL; align = FFMAX(align, 16); // 16 is "recommended", even if not required - hr = MFCreateAlignedMemoryBuffer(size, align - 1, &buffer); + hr = f->MFCreateAlignedMemoryBuffer(size, align - 1, &buffer); if (FAILED(hr)) return NULL; @@ -548,7 +516,7 @@ const CLSID *ff_codec_to_mf_subtype(enum AVCodecID codec) } } -static int init_com_mf(void *log) +static int init_com_mf(void *log, MFFunctions *f) { HRESULT hr; @@ -561,7 +529,7 @@ static int init_com_mf(void *log) return AVERROR(ENOSYS); } - hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); + hr = f->MFStartup(MF_VERSION, MFSTARTUP_FULL); if (FAILED(hr)) { av_log(log, AV_LOG_ERROR, "could not initialize MediaFoundation\n"); CoUninitialize(); @@ -571,15 +539,16 @@ static int init_com_mf(void *log) return 0; } -static void uninit_com_mf(void) +static void uninit_com_mf(MFFunctions *f) { - MFShutdown(); + f->MFShutdown(); CoUninitialize(); } // Find and create a IMFTransform with the given input/output types. When done, // you should use ff_free_mf() to destroy it, which will also uninit COM. int ff_instantiate_mf(void *log, + MFFunctions *f, GUID category, MFT_REGISTER_TYPE_INFO *in_type, MFT_REGISTER_TYPE_INFO *out_type, @@ -594,7 +563,7 @@ int ff_instantiate_mf(void *log, IMFActivate *winner = 0; UINT32 flags; - ret = init_com_mf(log); + ret = init_com_mf(log, f); if (ret < 0) return ret; @@ -606,7 +575,7 @@ int ff_instantiate_mf(void *log, flags |= MFT_ENUM_FLAG_SYNCMFT; } - hr = ff_MFTEnumEx(category, flags, in_type, out_type, &activate, + hr = f->MFTEnumEx(category, flags, in_type, out_type, &activate, &num_activate); if (FAILED(hr)) goto error_uninit_mf; @@ -667,14 +636,14 @@ int ff_instantiate_mf(void *log, return 0; error_uninit_mf: - uninit_com_mf(); + uninit_com_mf(f); return AVERROR(ENOSYS); } -void ff_free_mf(IMFTransform **mft) +void ff_free_mf(MFFunctions *f, IMFTransform **mft) { if (*mft) IMFTransform_Release(*mft); *mft = NULL; - uninit_com_mf(); + uninit_com_mf(f); } diff --git a/libavcodec/mf_utils.h b/libavcodec/mf_utils.h index d514723c3..aebfb9ad2 100644 --- a/libavcodec/mf_utils.h +++ b/libavcodec/mf_utils.h @@ -29,6 +29,7 @@ // mf*.h headers below indirectly include strmif.h.) #include #else +#define NO_DSHOW_STRSAFE #include // Older versions of mingw-w64 need codecapi.h explicitly included, while newer // ones include it implicitly from dshow.h (via uuids.h). @@ -41,6 +42,25 @@ #include "avcodec.h" +// Windows N editions does not provide MediaFoundation by default. +// So to avoid DLL loading error, MediaFoundation will be dynamically loaded +// except on UWP build since LoadLibrary is not available on it. +typedef struct MFFunctions { + HRESULT (WINAPI *MFStartup) (ULONG Version, DWORD dwFlags); + HRESULT (WINAPI *MFShutdown) (void); + HRESULT (WINAPI *MFCreateAlignedMemoryBuffer) (DWORD cbMaxLength, + DWORD cbAligment, + IMFMediaBuffer **ppBuffer); + HRESULT (WINAPI *MFCreateSample) (IMFSample **ppIMFSample); + HRESULT (WINAPI *MFCreateMediaType) (IMFMediaType **ppMFType); + // MFTEnumEx is missing in Windows Vista's mfplat.dll. + HRESULT (WINAPI *MFTEnumEx)(GUID guidCategory, UINT32 Flags, + const MFT_REGISTER_TYPE_INFO *pInputType, + const MFT_REGISTER_TYPE_INFO *pOutputType, + IMFActivate ***pppMFTActivate, + UINT32 *pnumMFTActivate); +} MFFunctions; + // These functions do exist in mfapi.h, but are only available within // __cplusplus ifdefs. HRESULT ff_MFGetAttributeSize(IMFAttributes *pattr, REFGUID guid, @@ -50,15 +70,6 @@ HRESULT ff_MFSetAttributeSize(IMFAttributes *pattr, REFGUID guid, #define ff_MFSetAttributeRatio ff_MFSetAttributeSize #define ff_MFGetAttributeRatio ff_MFGetAttributeSize -// MFTEnumEx was missing from mingw-w64's mfplat import library until -// mingw-w64 v6.0.0, thus wrap it and load it using GetProcAddress. -// It's also missing in Windows Vista's mfplat.dll. -HRESULT ff_MFTEnumEx(GUID guidCategory, UINT32 Flags, - const MFT_REGISTER_TYPE_INFO *pInputType, - const MFT_REGISTER_TYPE_INFO *pOutputType, - IMFActivate ***pppMFTActivate, UINT32 *pnumMFTActivate); - - // These do exist in mingw-w64's codecapi.h, but they aren't properly defined // by the header until after mingw-w64 v7.0.0. DEFINE_GUID(ff_CODECAPI_AVDecVideoThumbnailGenerationMode, 0x2efd8eee,0x1150,0x4328,0x9c,0xf5,0x66,0xdc,0xe9,0x33,0xfc,0xf4); @@ -150,7 +161,8 @@ char *ff_hr_str_buf(char *buf, size_t size, HRESULT hr); #define FF_VAL_VT_UI4(v) FF_VARIANT_VALUE(VT_UI4, .ulVal = (v)) #define FF_VAL_VT_BOOL(v) FF_VARIANT_VALUE(VT_BOOL, .boolVal = (v)) -IMFSample *ff_create_memory_sample(void *fill_data, size_t size, size_t align); +IMFSample *ff_create_memory_sample(MFFunctions *f, void *fill_data, + size_t size, size_t align); enum AVSampleFormat ff_media_type_to_sample_fmt(IMFAttributes *type); enum AVPixelFormat ff_media_type_to_pix_fmt(IMFAttributes *type); const GUID *ff_pix_fmt_to_guid(enum AVPixelFormat pix_fmt); @@ -160,10 +172,10 @@ char *ff_guid_str_buf(char *buf, size_t buf_size, const GUID *guid); void ff_attributes_dump(void *log, IMFAttributes *attrs); void ff_media_type_dump(void *log, IMFMediaType *type); const CLSID *ff_codec_to_mf_subtype(enum AVCodecID codec); -int ff_instantiate_mf(void *log, GUID category, +int ff_instantiate_mf(void *log, MFFunctions *f, GUID category, MFT_REGISTER_TYPE_INFO *in_type, MFT_REGISTER_TYPE_INFO *out_type, int use_hw, IMFTransform **res); -void ff_free_mf(IMFTransform **mft); +void ff_free_mf(MFFunctions *f, IMFTransform **mft); #endif diff --git a/libavcodec/mfenc.c b/libavcodec/mfenc.c index 410ad64d8..bbe78605a 100644 --- a/libavcodec/mfenc.c +++ b/libavcodec/mfenc.c @@ -27,10 +27,14 @@ #include "libavutil/imgutils.h" #include "libavutil/opt.h" #include "libavutil/time.h" +#include "codec_internal.h" #include "internal.h" +#include "compat/w32dlfcn.h" typedef struct MFContext { AVClass *av_class; + HMODULE library; + MFFunctions functions; AVFrame *frame; int is_video, is_audio; GUID main_subtype; @@ -288,10 +292,11 @@ static IMFSample *mf_a_avframe_to_sample(AVCodecContext *avctx, const AVFrame *f size_t bps; IMFSample *sample; - bps = av_get_bytes_per_sample(avctx->sample_fmt) * avctx->channels; + bps = av_get_bytes_per_sample(avctx->sample_fmt) * avctx->ch_layout.nb_channels; len = frame->nb_samples * bps; - sample = ff_create_memory_sample(frame->data[0], len, c->in_info.cbAlignment); + sample = ff_create_memory_sample(&c->functions, frame->data[0], len, + c->in_info.cbAlignment); if (sample) IMFSample_SetSampleDuration(sample, mf_to_mf_time(avctx, frame->nb_samples)); return sample; @@ -311,7 +316,8 @@ static IMFSample *mf_v_avframe_to_sample(AVCodecContext *avctx, const AVFrame *f if (size < 0) return NULL; - sample = ff_create_memory_sample(NULL, size, c->in_info.cbAlignment); + sample = ff_create_memory_sample(&c->functions, NULL, size, + c->in_info.cbAlignment); if (!sample) return NULL; @@ -421,7 +427,9 @@ static int mf_receive_sample(AVCodecContext *avctx, IMFSample **out_sample) } if (!c->out_stream_provides_samples) { - sample = ff_create_memory_sample(NULL, c->out_info.cbSize, c->out_info.cbAlignment); + sample = ff_create_memory_sample(&c->functions, NULL, + c->out_info.cbSize, + c->out_info.cbAlignment); if (!sample) return AVERROR(ENOMEM); } @@ -536,7 +544,7 @@ static int64_t mf_enca_output_score(AVCodecContext *avctx, IMFMediaType *type) score |= 1LL << 32; hr = IMFAttributes_GetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, &t); - if (!FAILED(hr) && t == avctx->channels) + if (!FAILED(hr) && t == avctx->ch_layout.nb_channels) score |= 2LL << 32; hr = IMFAttributes_GetGUID(type, &MF_MT_SUBTYPE, &tg); @@ -591,7 +599,7 @@ static int64_t mf_enca_input_score(AVCodecContext *avctx, IMFMediaType *type) score |= 2; hr = IMFAttributes_GetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, &t); - if (!FAILED(hr) && t == avctx->channels) + if (!FAILED(hr) && t == avctx->ch_layout.nb_channels) score |= 4; return score; @@ -615,7 +623,7 @@ static int mf_enca_input_adjust(AVCodecContext *avctx, IMFMediaType *type) } hr = IMFAttributes_GetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, &t); - if (FAILED(hr) || t != avctx->channels) { + if (FAILED(hr) || t != avctx->ch_layout.nb_channels) { av_log(avctx, AV_LOG_ERROR, "unsupported input channel number set\n"); return AVERROR(EINVAL); } @@ -776,7 +784,7 @@ static int mf_choose_output_type(AVCodecContext *avctx) if (out_type) { av_log(avctx, AV_LOG_VERBOSE, "picking output type %d.\n", out_type_index); } else { - hr = MFCreateMediaType(&out_type); + hr = c->functions.MFCreateMediaType(&out_type); if (FAILED(hr)) { ret = AVERROR(ENOMEM); goto done; @@ -1004,7 +1012,8 @@ err: return res; } -static int mf_create(void *log, IMFTransform **mft, const AVCodec *codec, int use_hw) +static int mf_create(void *log, MFFunctions *f, IMFTransform **mft, + const AVCodec *codec, int use_hw) { int is_audio = codec->type == AVMEDIA_TYPE_AUDIO; const CLSID *subtype = ff_codec_to_mf_subtype(codec->id); @@ -1027,13 +1036,13 @@ static int mf_create(void *log, IMFTransform **mft, const AVCodec *codec, int us category = MFT_CATEGORY_VIDEO_ENCODER; } - if ((ret = ff_instantiate_mf(log, category, NULL, ®, use_hw, mft)) < 0) + if ((ret = ff_instantiate_mf(log, f, category, NULL, ®, use_hw, mft)) < 0) return ret; return 0; } -static int mf_init(AVCodecContext *avctx) +static int mf_init_encoder(AVCodecContext *avctx) { MFContext *c = avctx->priv_data; HRESULT hr; @@ -1057,7 +1066,7 @@ static int mf_init(AVCodecContext *avctx) c->main_subtype = *subtype; - if ((ret = mf_create(avctx, &c->mft, avctx->codec, use_hw)) < 0) + if ((ret = mf_create(avctx, &c->functions, &c->mft, avctx->codec, use_hw)) < 0) return ret; if ((ret = mf_unlock_async(avctx)) < 0) @@ -1121,6 +1130,54 @@ static int mf_init(AVCodecContext *avctx) return 0; } +#if !HAVE_UWP +#define LOAD_MF_FUNCTION(context, func_name) \ + context->functions.func_name = (void *)dlsym(context->library, #func_name); \ + if (!context->functions.func_name) { \ + av_log(context, AV_LOG_ERROR, "DLL mfplat.dll failed to find function "\ + #func_name "\n"); \ + return AVERROR_UNKNOWN; \ + } +#else +// In UWP (which lacks LoadLibrary), just link directly against +// the functions - this requires building with new/complete enough +// import libraries. +#define LOAD_MF_FUNCTION(context, func_name) \ + context->functions.func_name = func_name; \ + if (!context->functions.func_name) { \ + av_log(context, AV_LOG_ERROR, "Failed to find function " #func_name \ + "\n"); \ + return AVERROR_UNKNOWN; \ + } +#endif + +// Windows N editions does not provide MediaFoundation by default. +// So to avoid DLL loading error, MediaFoundation is dynamically loaded except +// on UWP build since LoadLibrary is not available on it. +static int mf_load_library(AVCodecContext *avctx) +{ + MFContext *c = avctx->priv_data; + +#if !HAVE_UWP + c->library = dlopen("mfplat.dll", 0); + + if (!c->library) { + av_log(c, AV_LOG_ERROR, "DLL mfplat.dll failed to open\n"); + return AVERROR_UNKNOWN; + } +#endif + + LOAD_MF_FUNCTION(c, MFStartup); + LOAD_MF_FUNCTION(c, MFShutdown); + LOAD_MF_FUNCTION(c, MFCreateAlignedMemoryBuffer); + LOAD_MF_FUNCTION(c, MFCreateSample); + LOAD_MF_FUNCTION(c, MFCreateMediaType); + // MFTEnumEx is missing in Windows Vista's mfplat.dll. + LOAD_MF_FUNCTION(c, MFTEnumEx); + + return 0; +} + static int mf_close(AVCodecContext *avctx) { MFContext *c = avctx->priv_data; @@ -1131,7 +1188,15 @@ static int mf_close(AVCodecContext *avctx) if (c->async_events) IMFMediaEventGenerator_Release(c->async_events); - ff_free_mf(&c->mft); +#if !HAVE_UWP + if (c->library) + ff_free_mf(&c->functions, &c->mft); + + dlclose(c->library); + c->library = NULL; +#else + ff_free_mf(&c->functions, &c->mft); +#endif av_frame_free(&c->frame); @@ -1141,39 +1206,53 @@ static int mf_close(AVCodecContext *avctx) return 0; } +static int mf_init(AVCodecContext *avctx) +{ + int ret; + if ((ret = mf_load_library(avctx)) == 0) { + if ((ret = mf_init_encoder(avctx)) == 0) { + return 0; + } + } + mf_close(avctx); + return ret; +} + #define OFFSET(x) offsetof(MFContext, x) -#define MF_ENCODER(MEDIATYPE, NAME, ID, OPTS, EXTRA) \ +#define MF_ENCODER(MEDIATYPE, NAME, ID, OPTS, FMTS, CAPS) \ static const AVClass ff_ ## NAME ## _mf_encoder_class = { \ .class_name = #NAME "_mf", \ .item_name = av_default_item_name, \ .option = OPTS, \ .version = LIBAVUTIL_VERSION_INT, \ }; \ - const AVCodec ff_ ## NAME ## _mf_encoder = { \ - .priv_class = &ff_ ## NAME ## _mf_encoder_class, \ - .name = #NAME "_mf", \ - .long_name = NULL_IF_CONFIG_SMALL(#ID " via MediaFoundation"), \ - .type = AVMEDIA_TYPE_ ## MEDIATYPE, \ - .id = AV_CODEC_ID_ ## ID, \ + const FFCodec ff_ ## NAME ## _mf_encoder = { \ + .p.priv_class = &ff_ ## NAME ## _mf_encoder_class, \ + .p.name = #NAME "_mf", \ + .p.long_name = NULL_IF_CONFIG_SMALL(#ID " via MediaFoundation"), \ + .p.type = AVMEDIA_TYPE_ ## MEDIATYPE, \ + .p.id = AV_CODEC_ID_ ## ID, \ .priv_data_size = sizeof(MFContext), \ .init = mf_init, \ .close = mf_close, \ - .receive_packet = mf_receive_packet, \ - EXTRA \ - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID | \ - AV_CODEC_CAP_DR1, \ + FF_CODEC_RECEIVE_PACKET_CB(mf_receive_packet), \ + FMTS \ + CAPS \ .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | \ FF_CODEC_CAP_INIT_CLEANUP, \ }; #define AFMTS \ - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, \ + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, \ AV_SAMPLE_FMT_NONE }, +#define ACAPS \ + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID | \ + AV_CODEC_CAP_DR1 | AV_CODEC_CAP_VARIABLE_FRAME_SIZE, -MF_ENCODER(AUDIO, aac, AAC, NULL, AFMTS); -MF_ENCODER(AUDIO, ac3, AC3, NULL, AFMTS); -MF_ENCODER(AUDIO, mp3, MP3, NULL, AFMTS); +MF_ENCODER(AUDIO, aac, AAC, NULL, AFMTS, ACAPS); +MF_ENCODER(AUDIO, ac3, AC3, NULL, AFMTS, ACAPS); +MF_ENCODER(AUDIO, mp3, MP3, NULL, AFMTS, ACAPS); #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM static const AVOption venc_opts[] = { @@ -1203,9 +1282,12 @@ static const AVOption venc_opts[] = { }; #define VFMTS \ - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, \ + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, \ AV_PIX_FMT_YUV420P, \ AV_PIX_FMT_NONE }, +#define VCAPS \ + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID | \ + AV_CODEC_CAP_DR1, -MF_ENCODER(VIDEO, h264, H264, venc_opts, VFMTS); -MF_ENCODER(VIDEO, hevc, HEVC, venc_opts, VFMTS); +MF_ENCODER(VIDEO, h264, H264, venc_opts, VFMTS, VCAPS); +MF_ENCODER(VIDEO, hevc, HEVC, venc_opts, VFMTS, VCAPS); diff --git a/libavcodec/microdvddec.c b/libavcodec/microdvddec.c index c45fe043b..f36ad5146 100644 --- a/libavcodec/microdvddec.c +++ b/libavcodec/microdvddec.c @@ -31,7 +31,7 @@ #include "libavutil/bprint.h" #include "avcodec.h" #include "ass.h" -#include "internal.h" +#include "codec_internal.h" static int indexof(const char *s, int c) { @@ -274,10 +274,9 @@ static void microdvd_close_no_persistent_tags(AVBPrint *new_line, } } -static int microdvd_decode_frame(AVCodecContext *avctx, - void *data, int *got_sub_ptr, AVPacket *avpkt) +static int microdvd_decode_frame(AVCodecContext *avctx, AVSubtitle *sub, + int *got_sub_ptr, const AVPacket *avpkt) { - AVSubtitle *sub = data; AVBPrint new_line; char *line = avpkt->data; char *end = avpkt->data + avpkt->size; @@ -369,13 +368,13 @@ static int microdvd_init(AVCodecContext *avctx) alignment); } -const AVCodec ff_microdvd_decoder = { - .name = "microdvd", - .long_name = NULL_IF_CONFIG_SMALL("MicroDVD subtitle"), - .type = AVMEDIA_TYPE_SUBTITLE, - .id = AV_CODEC_ID_MICRODVD, +const FFCodec ff_microdvd_decoder = { + .p.name = "microdvd", + .p.long_name = NULL_IF_CONFIG_SMALL("MicroDVD subtitle"), + .p.type = AVMEDIA_TYPE_SUBTITLE, + .p.id = AV_CODEC_ID_MICRODVD, .init = microdvd_init, - .decode = microdvd_decode_frame, + FF_CODEC_DECODE_SUB_CB(microdvd_decode_frame), .flush = ff_ass_decoder_flush, .priv_data_size = sizeof(FFASSDecoderContext), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, diff --git a/libavcodec/midivid.c b/libavcodec/midivid.c index 4a3ba33f1..a21303ab6 100644 --- a/libavcodec/midivid.c +++ b/libavcodec/midivid.c @@ -32,6 +32,7 @@ #include "avcodec.h" #include "get_bits.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" typedef struct MidiVidContext { @@ -187,7 +188,7 @@ static ptrdiff_t lzss_uncompress(MidiVidContext *s, GetByteContext *gb, uint8_t return dst - dst_start; } -static int decode_frame(AVCodecContext *avctx, void *data, +static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, int *got_frame, AVPacket *avpkt) { MidiVidContext *s = avctx->priv_data; @@ -223,7 +224,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, return ret; key = ret; - if ((ret = av_frame_ref(data, s->frame)) < 0) + if ((ret = av_frame_ref(rframe, s->frame)) < 0) return ret; frame->pict_type = key ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; @@ -277,16 +278,16 @@ static av_cold int decode_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_mvdv_decoder = { - .name = "mvdv", - .long_name = NULL_IF_CONFIG_SMALL("MidiVid VQ"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MVDV, +const FFCodec ff_mvdv_decoder = { + .p.name = "mvdv", + .p.long_name = NULL_IF_CONFIG_SMALL("MidiVid VQ"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MVDV, .priv_data_size = sizeof(MidiVidContext), .init = decode_init, - .decode = decode_frame, + FF_CODEC_DECODE_CB(decode_frame), .flush = decode_flush, .close = decode_close, - .capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/mimic.c b/libavcodec/mimic.c index ade973d86..74dd947f8 100644 --- a/libavcodec/mimic.c +++ b/libavcodec/mimic.c @@ -28,6 +28,7 @@ #include "avcodec.h" #include "blockdsp.h" +#include "codec_internal.h" #include "internal.h" #include "get_bits.h" #include "bytestream.h" @@ -35,6 +36,7 @@ #include "hpeldsp.h" #include "idctdsp.h" #include "thread.h" +#include "threadframe.h" #define MIMIC_HEADER_SIZE 20 #define MIMIC_VLC_BITS 11 @@ -111,7 +113,7 @@ static av_cold int mimic_decode_end(AVCodecContext *avctx) for (i = 0; i < FF_ARRAY_ELEMS(ctx->frames); i++) { if (ctx->frames[i].f) - ff_thread_release_buffer(avctx, &ctx->frames[i]); + ff_thread_release_ext_buffer(avctx, &ctx->frames[i]); av_frame_free(&ctx->frames[i].f); } @@ -163,7 +165,7 @@ static int mimic_decode_update_thread_context(AVCodecContext *avctx, const AVCod dst->prev_index = src->next_prev_index; for (i = 0; i < FF_ARRAY_ELEMS(dst->frames); i++) { - ff_thread_release_buffer(avctx, &dst->frames[i]); + ff_thread_release_ext_buffer(avctx, &dst->frames[i]); if (i != src->next_cur_index && src->frames[i].f->data[0]) { ret = ff_thread_ref_frame(&dst->frames[i], &src->frames[i]); if (ret < 0) @@ -337,7 +339,7 @@ static void flip_swap_frame(AVFrame *f) f->linesize[i] *= -1; } -static int mimic_decode_frame(AVCodecContext *avctx, void *data, +static int mimic_decode_frame(AVCodecContext *avctx, AVFrame *rframe, int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; @@ -394,11 +396,11 @@ static int mimic_decode_frame(AVCodecContext *avctx, void *data, return AVERROR_INVALIDDATA; } - ff_thread_release_buffer(avctx, &ctx->frames[ctx->cur_index]); + ff_thread_release_ext_buffer(avctx, &ctx->frames[ctx->cur_index]); ctx->frames[ctx->cur_index].f->pict_type = is_pframe ? AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_I; - if ((res = ff_thread_get_buffer(avctx, &ctx->frames[ctx->cur_index], - AV_GET_BUFFER_FLAG_REF)) < 0) + if ((res = ff_thread_get_ext_buffer(avctx, &ctx->frames[ctx->cur_index], + AV_GET_BUFFER_FLAG_REF)) < 0) return res; ctx->next_prev_index = ctx->cur_index; @@ -419,15 +421,15 @@ static int mimic_decode_frame(AVCodecContext *avctx, void *data, ff_thread_report_progress(&ctx->frames[ctx->cur_index], INT_MAX, 0); if (res < 0) { if (!(avctx->active_thread_type & FF_THREAD_FRAME)) - ff_thread_release_buffer(avctx, &ctx->frames[ctx->cur_index]); + ff_thread_release_ext_buffer(avctx, &ctx->frames[ctx->cur_index]); return res; } - if ((res = av_frame_ref(data, ctx->frames[ctx->cur_index].f)) < 0) + if ((res = av_frame_ref(rframe, ctx->frames[ctx->cur_index].f)) < 0) return res; *got_frame = 1; - flip_swap_frame(data); + flip_swap_frame(rframe); ctx->prev_index = ctx->next_prev_index; ctx->cur_index = ctx->next_cur_index; @@ -435,16 +437,16 @@ static int mimic_decode_frame(AVCodecContext *avctx, void *data, return buf_size; } -const AVCodec ff_mimic_decoder = { - .name = "mimic", - .long_name = NULL_IF_CONFIG_SMALL("Mimic"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MIMIC, +const FFCodec ff_mimic_decoder = { + .p.name = "mimic", + .p.long_name = NULL_IF_CONFIG_SMALL("Mimic"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MIMIC, .priv_data_size = sizeof(MimicContext), .init = mimic_decode_init, .close = mimic_decode_end, - .decode = mimic_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + FF_CODEC_DECODE_CB(mimic_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, .update_thread_context = ONLY_IF_THREADS_ENABLED(mimic_decode_update_thread_context), .caps_internal = FF_CODEC_CAP_ALLOCATE_PROGRESS | FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE, diff --git a/libavcodec/mips/Makefile b/libavcodec/mips/Makefile index 81a73a4d0..05ed63bf3 100644 --- a/libavcodec/mips/Makefile +++ b/libavcodec/mips/Makefile @@ -1,3 +1,7 @@ +ARCH_HEADERS = aacsbr_mips.h aacpsy_mips.h \ + cabac.h compute_antialias_fixed.h \ + compute_antialias_float.h \ + MIPSFPU-OBJS-$(CONFIG_AMRNB_DECODER) += mips/acelp_filters_mips.o \ mips/celp_filters_mips.o \ mips/celp_math_mips.o \ diff --git a/libavcodec/mips/ac3dsp_mips.c b/libavcodec/mips/ac3dsp_mips.c index e5cee1608..8f62c03aa 100644 --- a/libavcodec/mips/ac3dsp_mips.c +++ b/libavcodec/mips/ac3dsp_mips.c @@ -56,6 +56,7 @@ #include "config.h" #include "libavcodec/ac3dsp.h" #include "libavcodec/ac3.h" +#include "libavcodec/ac3tab.h" #include "libavutil/mips/asmdefs.h" #if HAVE_INLINE_ASM diff --git a/libavcodec/mips/lsp_mips.h b/libavcodec/mips/lsp_mips.h index 23b2b6bfd..c69f8b770 100644 --- a/libavcodec/mips/lsp_mips.h +++ b/libavcodec/mips/lsp_mips.h @@ -54,6 +54,8 @@ #ifndef AVCODEC_MIPS_LSP_MIPS_H #define AVCODEC_MIPS_LSP_MIPS_H +#include "config.h" + #if HAVE_MIPSFPU && HAVE_INLINE_ASM #if !HAVE_MIPS32R6 && !HAVE_MIPS64R6 #include "libavutil/attributes.h" diff --git a/libavcodec/mips/mpegaudiodsp_mips_fixed.c b/libavcodec/mips/mpegaudiodsp_mips_fixed.c index 1c9c68d23..ef9750a44 100644 --- a/libavcodec/mips/mpegaudiodsp_mips_fixed.c +++ b/libavcodec/mips/mpegaudiodsp_mips_fixed.c @@ -54,6 +54,7 @@ #include +#include "config.h" #include "libavutil/mips/asmdefs.h" #include "libavcodec/mpegaudiodsp.h" diff --git a/libavcodec/mips/mpegaudiodsp_mips_float.c b/libavcodec/mips/mpegaudiodsp_mips_float.c index ae130c752..53b77619c 100644 --- a/libavcodec/mips/mpegaudiodsp_mips_float.c +++ b/libavcodec/mips/mpegaudiodsp_mips_float.c @@ -55,6 +55,7 @@ #include +#include "config.h" #include "libavutil/mips/asmdefs.h" #include "libavcodec/mpegaudiodsp.h" diff --git a/libavcodec/mips/vc1dsp_mips.h b/libavcodec/mips/vc1dsp_mips.h index 5897daea8..356153cab 100644 --- a/libavcodec/mips/vc1dsp_mips.h +++ b/libavcodec/mips/vc1dsp_mips.h @@ -166,17 +166,17 @@ void ff_vc1_inv_trans_4x8_dc_mmi(uint8_t *dest, ptrdiff_t linesize, int16_t *blo void ff_vc1_inv_trans_8x4_dc_mmi(uint8_t *dest, ptrdiff_t linesize, int16_t *block); void ff_vc1_inv_trans_8x8_dc_mmi(uint8_t *dest, ptrdiff_t linesize, int16_t *block); -void ff_vc1_v_overlap_mmi(uint8_t *src, int stride); -void ff_vc1_h_overlap_mmi(uint8_t *src, int stride); +void ff_vc1_v_overlap_mmi(uint8_t *src, ptrdiff_t stride); +void ff_vc1_h_overlap_mmi(uint8_t *src, ptrdiff_t stride); void ff_vc1_v_s_overlap_mmi(int16_t *top, int16_t *bottom); -void ff_vc1_h_s_overlap_mmi(int16_t *left, int16_t *right, int left_stride, int right_stride, int flags); +void ff_vc1_h_s_overlap_mmi(int16_t *left, int16_t *right, ptrdiff_t left_stride, ptrdiff_t right_stride, int flags); -void ff_vc1_v_loop_filter4_mmi(uint8_t *src, int stride, int pq); -void ff_vc1_h_loop_filter4_mmi(uint8_t *src, int stride, int pq); -void ff_vc1_v_loop_filter8_mmi(uint8_t *src, int stride, int pq); -void ff_vc1_h_loop_filter8_mmi(uint8_t *src, int stride, int pq); -void ff_vc1_v_loop_filter16_mmi(uint8_t *src, int stride, int pq); -void ff_vc1_h_loop_filter16_mmi(uint8_t *src, int stride, int pq); +void ff_vc1_v_loop_filter4_mmi(uint8_t *src, ptrdiff_t stride, int pq); +void ff_vc1_h_loop_filter4_mmi(uint8_t *src, ptrdiff_t stride, int pq); +void ff_vc1_v_loop_filter8_mmi(uint8_t *src, ptrdiff_t stride, int pq); +void ff_vc1_h_loop_filter8_mmi(uint8_t *src, ptrdiff_t stride, int pq); +void ff_vc1_v_loop_filter16_mmi(uint8_t *src, ptrdiff_t stride, int pq); +void ff_vc1_h_loop_filter16_mmi(uint8_t *src, ptrdiff_t stride, int pq); void ff_put_no_rnd_vc1_chroma_mc8_mmi(uint8_t *dst /* align 8 */, uint8_t *src /* align 1 */, diff --git a/libavcodec/mips/vc1dsp_mmi.c b/libavcodec/mips/vc1dsp_mmi.c index 27a3c813d..278aa566b 100644 --- a/libavcodec/mips/vc1dsp_mmi.c +++ b/libavcodec/mips/vc1dsp_mmi.c @@ -1375,7 +1375,7 @@ void ff_vc1_inv_trans_4x4_mmi(uint8_t *dest, ptrdiff_t linesize, int16_t *block) } /* Apply overlap transform to horizontal edge */ -void ff_vc1_h_overlap_mmi(uint8_t *src, int stride) +void ff_vc1_h_overlap_mmi(uint8_t *src, ptrdiff_t stride) { int i; int a, b, c, d; @@ -1398,7 +1398,7 @@ void ff_vc1_h_overlap_mmi(uint8_t *src, int stride) } } -void ff_vc1_h_s_overlap_mmi(int16_t *left, int16_t *right, int left_stride, int right_stride, int flags) +void ff_vc1_h_s_overlap_mmi(int16_t *left, int16_t *right, ptrdiff_t left_stride, ptrdiff_t right_stride, int flags) { int i; int a, b, c, d; @@ -1428,7 +1428,7 @@ void ff_vc1_h_s_overlap_mmi(int16_t *left, int16_t *right, int left_stride, int } /* Apply overlap transform to vertical edge */ -void ff_vc1_v_overlap_mmi(uint8_t *src, int stride) +void ff_vc1_v_overlap_mmi(uint8_t *src, ptrdiff_t stride) { int i; int a, b, c, d; @@ -1551,32 +1551,32 @@ static inline void vc1_loop_filter(uint8_t *src, int step, int stride, } } -void ff_vc1_v_loop_filter4_mmi(uint8_t *src, int stride, int pq) +void ff_vc1_v_loop_filter4_mmi(uint8_t *src, ptrdiff_t stride, int pq) { vc1_loop_filter(src, 1, stride, 4, pq); } -void ff_vc1_h_loop_filter4_mmi(uint8_t *src, int stride, int pq) +void ff_vc1_h_loop_filter4_mmi(uint8_t *src, ptrdiff_t stride, int pq) { vc1_loop_filter(src, stride, 1, 4, pq); } -void ff_vc1_v_loop_filter8_mmi(uint8_t *src, int stride, int pq) +void ff_vc1_v_loop_filter8_mmi(uint8_t *src, ptrdiff_t stride, int pq) { vc1_loop_filter(src, 1, stride, 8, pq); } -void ff_vc1_h_loop_filter8_mmi(uint8_t *src, int stride, int pq) +void ff_vc1_h_loop_filter8_mmi(uint8_t *src, ptrdiff_t stride, int pq) { vc1_loop_filter(src, stride, 1, 8, pq); } -void ff_vc1_v_loop_filter16_mmi(uint8_t *src, int stride, int pq) +void ff_vc1_v_loop_filter16_mmi(uint8_t *src, ptrdiff_t stride, int pq) { vc1_loop_filter(src, 1, stride, 16, pq); } -void ff_vc1_h_loop_filter16_mmi(uint8_t *src, int stride, int pq) +void ff_vc1_h_loop_filter16_mmi(uint8_t *src, ptrdiff_t stride, int pq) { vc1_loop_filter(src, stride, 1, 16, pq); } diff --git a/libavcodec/mips/vp9dsp_mips.h b/libavcodec/mips/vp9dsp_mips.h index 0b6ce7cd7..021ae9e59 100644 --- a/libavcodec/mips/vp9dsp_mips.h +++ b/libavcodec/mips/vp9dsp_mips.h @@ -21,6 +21,9 @@ #ifndef AVCODEC_MIPS_VP9DSP_MIPS_H #define AVCODEC_MIPS_VP9DSP_MIPS_H +#include +#include + #define VP9_8TAP_MIPS_MSA_FUNC(SIZE, type, type_idx) \ void ff_put_8tap_##type##_##SIZE##h_msa(uint8_t *dst, ptrdiff_t dststride, \ const uint8_t *src, \ diff --git a/libavcodec/mjpeg2jpeg_bsf.c b/libavcodec/mjpeg2jpeg_bsf.c index 2a972a7c3..f545e9438 100644 --- a/libavcodec/mjpeg2jpeg_bsf.c +++ b/libavcodec/mjpeg2jpeg_bsf.c @@ -135,8 +135,8 @@ static const enum AVCodecID codec_ids[] = { AV_CODEC_ID_MJPEG, AV_CODEC_ID_NONE, }; -const AVBitStreamFilter ff_mjpeg2jpeg_bsf = { - .name = "mjpeg2jpeg", +const FFBitStreamFilter ff_mjpeg2jpeg_bsf = { + .p.name = "mjpeg2jpeg", + .p.codec_ids = codec_ids, .filter = mjpeg2jpeg_filter, - .codec_ids = codec_ids, }; diff --git a/libavcodec/mjpega_dump_header_bsf.c b/libavcodec/mjpega_dump_header_bsf.c index ab68f9c3e..d541084e7 100644 --- a/libavcodec/mjpega_dump_header_bsf.c +++ b/libavcodec/mjpega_dump_header_bsf.c @@ -101,8 +101,8 @@ static const enum AVCodecID codec_ids[] = { AV_CODEC_ID_MJPEG, AV_CODEC_ID_NONE, }; -const AVBitStreamFilter ff_mjpega_dump_header_bsf = { - .name = "mjpegadump", - .filter = mjpega_dump_header, - .codec_ids = codec_ids, +const FFBitStreamFilter ff_mjpega_dump_header_bsf = { + .p.name = "mjpegadump", + .p.codec_ids = codec_ids, + .filter = mjpega_dump_header, }; diff --git a/libavcodec/mjpegbdec.c b/libavcodec/mjpegbdec.c index c3d312514..8c1809e5f 100644 --- a/libavcodec/mjpegbdec.c +++ b/libavcodec/mjpegbdec.c @@ -27,7 +27,7 @@ #include #include "avcodec.h" -#include "internal.h" +#include "codec_internal.h" #include "mjpeg.h" #include "mjpegdec.h" @@ -40,9 +40,8 @@ static uint32_t read_offs(AVCodecContext *avctx, GetBitContext *gb, uint32_t siz return offs; } -static int mjpegb_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int mjpegb_decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; @@ -145,7 +144,7 @@ read_header: return buf_size; } - if ((ret = av_frame_ref(data, s->picture_ptr)) < 0) + if ((ret = av_frame_ref(rframe, s->picture_ptr)) < 0) return ret; *got_frame = 1; @@ -157,16 +156,16 @@ read_header: return buf_size; } -const AVCodec ff_mjpegb_decoder = { - .name = "mjpegb", - .long_name = NULL_IF_CONFIG_SMALL("Apple MJPEG-B"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MJPEGB, +const FFCodec ff_mjpegb_decoder = { + .p.name = "mjpegb", + .p.long_name = NULL_IF_CONFIG_SMALL("Apple MJPEG-B"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MJPEGB, .priv_data_size = sizeof(MJpegDecodeContext), .init = ff_mjpeg_decode_init, .close = ff_mjpeg_decode_end, - .decode = mjpegb_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, - .max_lowres = 3, + FF_CODEC_DECODE_CB(mjpegb_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, + .p.max_lowres = 3, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index a735d2337..32874a5a1 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -30,12 +30,15 @@ * MJPEG decoder. */ +#include "config_components.h" + #include "libavutil/display.h" #include "libavutil/imgutils.h" #include "libavutil/avassert.h" #include "libavutil/opt.h" #include "avcodec.h" #include "blockdsp.h" +#include "codec_internal.h" #include "copy_block.h" #include "decode.h" #include "hwconfig.h" @@ -50,6 +53,7 @@ #include "tiff.h" #include "exif.h" #include "bytestream.h" +#include "tiff_common.h" static int init_default_huffman_tables(MJpegDecodeContext *s) @@ -3008,20 +3012,20 @@ static const AVClass mjpegdec_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_mjpeg_decoder = { - .name = "mjpeg", - .long_name = NULL_IF_CONFIG_SMALL("MJPEG (Motion JPEG)"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MJPEG, +const FFCodec ff_mjpeg_decoder = { + .p.name = "mjpeg", + .p.long_name = NULL_IF_CONFIG_SMALL("MJPEG (Motion JPEG)"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MJPEG, .priv_data_size = sizeof(MJpegDecodeContext), .init = ff_mjpeg_decode_init, .close = ff_mjpeg_decode_end, - .receive_frame = ff_mjpeg_receive_frame, + FF_CODEC_RECEIVE_FRAME_CB(ff_mjpeg_receive_frame), .flush = decode_flush, - .capabilities = AV_CODEC_CAP_DR1, - .max_lowres = 3, - .priv_class = &mjpegdec_class, - .profiles = NULL_IF_CONFIG_SMALL(ff_mjpeg_profiles), + .p.capabilities = AV_CODEC_CAP_DR1, + .p.max_lowres = 3, + .p.priv_class = &mjpegdec_class, + .p.profiles = NULL_IF_CONFIG_SMALL(ff_mjpeg_profiles), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM | FF_CODEC_CAP_SETS_PKT_DTS, .hw_configs = (const AVCodecHWConfigInternal *const []) { @@ -3036,35 +3040,35 @@ const AVCodec ff_mjpeg_decoder = { }; #endif #if CONFIG_THP_DECODER -const AVCodec ff_thp_decoder = { - .name = "thp", - .long_name = NULL_IF_CONFIG_SMALL("Nintendo Gamecube THP video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_THP, +const FFCodec ff_thp_decoder = { + .p.name = "thp", + .p.long_name = NULL_IF_CONFIG_SMALL("Nintendo Gamecube THP video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_THP, .priv_data_size = sizeof(MJpegDecodeContext), .init = ff_mjpeg_decode_init, .close = ff_mjpeg_decode_end, - .receive_frame = ff_mjpeg_receive_frame, + FF_CODEC_RECEIVE_FRAME_CB(ff_mjpeg_receive_frame), .flush = decode_flush, - .capabilities = AV_CODEC_CAP_DR1, - .max_lowres = 3, + .p.capabilities = AV_CODEC_CAP_DR1, + .p.max_lowres = 3, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_SETS_PKT_DTS, }; #endif #if CONFIG_SMVJPEG_DECODER -const AVCodec ff_smvjpeg_decoder = { - .name = "smvjpeg", - .long_name = NULL_IF_CONFIG_SMALL("SMV JPEG"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_SMVJPEG, +const FFCodec ff_smvjpeg_decoder = { + .p.name = "smvjpeg", + .p.long_name = NULL_IF_CONFIG_SMALL("SMV JPEG"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_SMVJPEG, .priv_data_size = sizeof(MJpegDecodeContext), .init = ff_mjpeg_decode_init, .close = ff_mjpeg_decode_end, - .receive_frame = ff_mjpeg_receive_frame, + FF_CODEC_RECEIVE_FRAME_CB(ff_mjpeg_receive_frame), .flush = decode_flush, - .capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_EXPORTS_CROPPING | FF_CODEC_CAP_SETS_PKT_DTS | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/mjpegenc.c b/libavcodec/mjpegenc.c index 30cbbddb5..27217441a 100644 --- a/libavcodec/mjpegenc.c +++ b/libavcodec/mjpegenc.c @@ -30,17 +30,30 @@ * MJPEG encoder. */ +#include "config_components.h" + #include "libavutil/pixdesc.h" #include "avcodec.h" +#include "codec_internal.h" #include "jpegtables.h" #include "mjpegenc_common.h" #include "mjpegenc_huffman.h" #include "mpegvideo.h" #include "mjpeg.h" #include "mjpegenc.h" +#include "mpegvideoenc.h" #include "profiles.h" +/* The following is the private context of MJPEG/AMV decoder. + * Note that when using slice threading only the main thread's + * MpegEncContext is followed by a MjpegContext; the other threads + * can access this shared context via MpegEncContext.mjpeg. */ +typedef struct MJPEGEncContext { + MpegEncContext mpeg; + MJpegContext mjpeg; +} MJPEGEncContext; + static av_cold void init_uni_ac_vlc(const uint8_t huff_size_ac[256], uint8_t *uni_ac_vlc_len) { @@ -65,6 +78,27 @@ static av_cold void init_uni_ac_vlc(const uint8_t huff_size_ac[256], } } +static void mjpeg_encode_picture_header(MpegEncContext *s) +{ + ff_mjpeg_encode_picture_header(s->avctx, &s->pb, s->picture->f, s->mjpeg_ctx, + &s->intra_scantable, 0, + s->intra_matrix, s->chroma_intra_matrix, + s->slice_context_count > 1); + + s->esc_pos = put_bytes_count(&s->pb, 0); + for (int i = 1; i < s->slice_context_count; i++) + s->thread_context[i]->esc_pos = 0; +} + +void ff_mjpeg_amv_encode_picture_header(MpegEncContext *s) +{ + MJPEGEncContext *const m = (MJPEGEncContext*)s; + av_assert2(s->mjpeg_ctx == &m->mjpeg); + /* s->huffman == HUFFMAN_TABLE_OPTIMAL can only be true for MJPEG. */ + if (!CONFIG_MJPEG_ENCODER || m->mjpeg.huffman != HUFFMAN_TABLE_OPTIMAL) + mjpeg_encode_picture_header(s); +} + #if CONFIG_MJPEG_ENCODER /** * Encodes and outputs the entire frame in the JPEG format. @@ -185,13 +219,13 @@ static void mjpeg_build_optimal_huffman(MJpegContext *m) */ int ff_mjpeg_encode_stuffing(MpegEncContext *s) { + MJpegContext *const m = s->mjpeg_ctx; PutBitContext *pbc = &s->pb; int mb_y = s->mb_y - !s->mb_x; int ret; #if CONFIG_MJPEG_ENCODER - if (s->huffman == HUFFMAN_TABLE_OPTIMAL) { - MJpegContext *m = s->mjpeg_ctx; + if (m->huffman == HUFFMAN_TABLE_OPTIMAL) { mjpeg_build_optimal_huffman(m); @@ -204,8 +238,7 @@ int ff_mjpeg_encode_stuffing(MpegEncContext *s) s->intra_chroma_ac_vlc_length = s->intra_chroma_ac_vlc_last_length = m->uni_chroma_ac_vlc_len; - ff_mjpeg_encode_picture_header(s->avctx, &s->pb, &s->intra_scantable, - s->pred, s->intra_matrix, s->chroma_intra_matrix); + mjpeg_encode_picture_header(s); mjpeg_encode_picture_frame(s); } #endif @@ -219,7 +252,7 @@ int ff_mjpeg_encode_stuffing(MpegEncContext *s) ff_mjpeg_escape_FF(pbc, s->esc_pos); - if ((s->avctx->active_thread_type & FF_THREAD_SLICE) && mb_y < s->mb_height - 1) + if (s->slice_context_count > 1 && mb_y < s->mb_height - 1) put_marker(pbc, RST0 + (mb_y&7)); s->esc_pos = put_bytes_count(pbc, 0); @@ -260,10 +293,23 @@ static int alloc_huffman(MpegEncContext *s) av_cold int ff_mjpeg_encode_init(MpegEncContext *s) { - MJpegContext *m; - int ret; + MJpegContext *const m = &((MJPEGEncContext*)s)->mjpeg; + int ret, use_slices; - av_assert0(s->slice_context_count == 1); + s->mjpeg_ctx = m; + use_slices = s->avctx->slices > 0 ? s->avctx->slices > 1 : + (s->avctx->active_thread_type & FF_THREAD_SLICE) && + s->avctx->thread_count > 1; + + if (s->codec_id == AV_CODEC_ID_AMV || use_slices) + m->huffman = HUFFMAN_TABLE_DEFAULT; + + if (s->mpv_flags & FF_MPV_FLAG_QP_RD) { + // Used to produce garbage with MJPEG. + av_log(s->avctx, AV_LOG_ERROR, + "QP RD is no longer compatible with MJPEG or AMV\n"); + return AVERROR(EINVAL); + } /* The following check is automatically true for AMV, * but it doesn't hurt either. */ @@ -276,10 +322,6 @@ av_cold int ff_mjpeg_encode_init(MpegEncContext *s) return AVERROR(EINVAL); } - m = av_mallocz(sizeof(MJpegContext)); - if (!m) - return AVERROR(ENOMEM); - s->min_qcoeff=-1023; s->max_qcoeff= 1023; @@ -312,20 +354,19 @@ av_cold int ff_mjpeg_encode_init(MpegEncContext *s) // Buffers start out empty. m->huff_ncode = 0; - s->mjpeg_ctx = m; - if(s->huffman == HUFFMAN_TABLE_OPTIMAL) + if (m->huffman == HUFFMAN_TABLE_OPTIMAL) return alloc_huffman(s); return 0; } -av_cold void ff_mjpeg_encode_close(MpegEncContext *s) +static av_cold int mjpeg_encode_close(AVCodecContext *avctx) { - if (s->mjpeg_ctx) { - av_freep(&s->mjpeg_ctx->huff_buffer); - av_freep(&s->mjpeg_ctx); - } + MJPEGEncContext *const mjpeg = avctx->priv_data; + av_freep(&mjpeg->mjpeg.huff_buffer); + ff_mpv_encode_end(avctx); + return 0; } /** @@ -374,7 +415,7 @@ static void ff_mjpeg_encode_coef(MJpegContext *s, uint8_t table_id, int val, int /** * Add the block's data into the JPEG buffer. * - * @param s The MJpegEncContext that contains the JPEG buffer. + * @param s The MpegEncContext that contains the JPEG buffer. * @param block The block. * @param n The block's index or number. */ @@ -482,7 +523,7 @@ static void encode_block(MpegEncContext *s, int16_t *block, int n) void ff_mjpeg_encode_mb(MpegEncContext *s, int16_t block[12][64]) { int i; - if (s->huffman == HUFFMAN_TABLE_OPTIMAL) { + if (s->mjpeg_ctx->huffman == HUFFMAN_TABLE_OPTIMAL) { if (s->chroma_format == CHROMA_444) { record_block(s, block[0], 0); record_block(s, block[2], 2); @@ -582,23 +623,14 @@ static int amv_encode_picture(AVCodecContext *avctx, AVPacket *pkt, } #endif -#define OFFSET(x) offsetof(MpegEncContext, x) +#define OFFSET(x) offsetof(MJPEGEncContext, mjpeg.x) #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { FF_MPV_COMMON_OPTS -{ "pred", "Prediction method", OFFSET(pred), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, 3, VE, "pred" }, - { "left", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, VE, "pred" }, - { "plane", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, INT_MIN, INT_MAX, VE, "pred" }, - { "median", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 3 }, INT_MIN, INT_MAX, VE, "pred" }, { "huffman", "Huffman table strategy", OFFSET(huffman), AV_OPT_TYPE_INT, { .i64 = HUFFMAN_TABLE_OPTIMAL }, 0, NB_HUFFMAN_TABLE_OPTION - 1, VE, "huffman" }, { "default", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = HUFFMAN_TABLE_DEFAULT }, INT_MIN, INT_MAX, VE, "huffman" }, { "optimal", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = HUFFMAN_TABLE_OPTIMAL }, INT_MIN, INT_MAX, VE, "huffman" }, { "force_duplicated_matrix", "Always write luma and chroma matrix for mjpeg, useful for rtp streaming.", OFFSET(force_duplicated_matrix), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, VE }, -#if FF_API_MPEGVIDEO_OPTS -FF_MPV_DEPRECATED_MPEG_QUANT_OPT -FF_MPV_DEPRECATED_A53_CC_OPT -FF_MPV_DEPRECATED_BFRAME_OPTS -#endif { NULL}, }; @@ -610,24 +642,24 @@ static const AVClass mjpeg_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_mjpeg_encoder = { - .name = "mjpeg", - .long_name = NULL_IF_CONFIG_SMALL("MJPEG (Motion JPEG)"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MJPEG, - .priv_data_size = sizeof(MpegEncContext), +const FFCodec ff_mjpeg_encoder = { + .p.name = "mjpeg", + .p.long_name = NULL_IF_CONFIG_SMALL("MJPEG (Motion JPEG)"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MJPEG, + .priv_data_size = sizeof(MJPEGEncContext), .init = ff_mpv_encode_init, - .encode2 = ff_mpv_encode_picture, - .close = ff_mpv_encode_end, - .capabilities = AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS, + FF_CODEC_ENCODE_CB(ff_mpv_encode_picture), + .close = mjpeg_encode_close, + .p.capabilities = AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .pix_fmts = (const enum AVPixelFormat[]) { + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_NONE }, - .priv_class = &mjpeg_class, - .profiles = NULL_IF_CONFIG_SMALL(ff_mjpeg_profiles), + .p.priv_class = &mjpeg_class, + .p.profiles = NULL_IF_CONFIG_SMALL(ff_mjpeg_profiles), }; #endif @@ -639,19 +671,19 @@ static const AVClass amv_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_amv_encoder = { - .name = "amv", - .long_name = NULL_IF_CONFIG_SMALL("AMV Video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_AMV, - .priv_data_size = sizeof(MpegEncContext), +const FFCodec ff_amv_encoder = { + .p.name = "amv", + .p.long_name = NULL_IF_CONFIG_SMALL("AMV Video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_AMV, + .priv_data_size = sizeof(MJPEGEncContext), .init = ff_mpv_encode_init, - .encode2 = amv_encode_picture, - .close = ff_mpv_encode_end, + FF_CODEC_ENCODE_CB(amv_encode_picture), + .close = mjpeg_encode_close, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .pix_fmts = (const enum AVPixelFormat[]) { + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_NONE }, - .priv_class = &amv_class, + .p.priv_class = &amv_class, }; #endif diff --git a/libavcodec/mjpegenc.h b/libavcodec/mjpegenc.h index 2e9251127..a593b67e9 100644 --- a/libavcodec/mjpegenc.h +++ b/libavcodec/mjpegenc.h @@ -57,6 +57,9 @@ typedef struct MJpegHuffmanCode { * Holds JPEG frame data and Huffman table data. */ typedef struct MJpegContext { + int huffman; + /* Force duplication of mjpeg matrices, useful for rtp streaming */ + int force_duplicated_matrix; //FIXME use array [3] instead of lumi / chroma, for easier addressing uint8_t huff_size_dc_luminance[12]; ///< DC luminance Huffman table size. uint16_t huff_code_dc_luminance[12]; ///< DC luminance Huffman table codes. @@ -105,7 +108,7 @@ static inline void put_marker(PutBitContext *p, enum JpegMarker code) } int ff_mjpeg_encode_init(MpegEncContext *s); -void ff_mjpeg_encode_close(MpegEncContext *s); +void ff_mjpeg_amv_encode_picture_header(MpegEncContext *s); void ff_mjpeg_encode_mb(MpegEncContext *s, int16_t block[12][64]); int ff_mjpeg_encode_stuffing(MpegEncContext *s); diff --git a/libavcodec/mjpegenc_common.c b/libavcodec/mjpegenc_common.c index 368e87128..98c464fc6 100644 --- a/libavcodec/mjpegenc_common.c +++ b/libavcodec/mjpegenc_common.c @@ -33,6 +33,7 @@ #include "mjpegenc.h" #include "mjpegenc_common.h" #include "mjpeg.h" +#include "version.h" /* table_class: 0 = DC coef, 1 = AC coefs */ static int put_huffman_table(PutBitContext *p, int table_class, int table_id, @@ -56,34 +57,30 @@ static int put_huffman_table(PutBitContext *p, int table_class, int table_id, } static void jpeg_table_header(AVCodecContext *avctx, PutBitContext *p, + MJpegContext *m, ScanTable *intra_scantable, uint16_t luma_intra_matrix[64], uint16_t chroma_intra_matrix[64], - int hsample[3]) + int hsample[3], int use_slices) { int i, j, size; uint8_t *ptr; - MpegEncContext *s = NULL; - /* Since avctx->priv_data will point to LJpegEncContext in this case */ - if (avctx->codec_id != AV_CODEC_ID_LJPEG) - s = avctx->priv_data; - - if (avctx->codec_id != AV_CODEC_ID_LJPEG) { + if (m) { int matrix_count = 1 + !!memcmp(luma_intra_matrix, chroma_intra_matrix, sizeof(luma_intra_matrix[0]) * 64); - if (s && s->force_duplicated_matrix) - matrix_count = 2; - /* quant matrixes */ - put_marker(p, DQT); - put_bits(p, 16, 2 + matrix_count * (1 + 64)); - put_bits(p, 4, 0); /* 8 bit precision */ - put_bits(p, 4, 0); /* table 0 */ - for(i=0;i<64;i++) { - j = intra_scantable->permutated[i]; - put_bits(p, 8, luma_intra_matrix[j]); - } + if (m->force_duplicated_matrix) + matrix_count = 2; + /* quant matrixes */ + put_marker(p, DQT); + put_bits(p, 16, 2 + matrix_count * (1 + 64)); + put_bits(p, 4, 0); /* 8 bit precision */ + put_bits(p, 4, 0); /* table 0 */ + for (int i = 0; i < 64; i++) { + uint8_t j = intra_scantable->permutated[i]; + put_bits(p, 8, luma_intra_matrix[j]); + } if (matrix_count > 1) { put_bits(p, 4, 0); /* 8 bit precision */ @@ -95,7 +92,7 @@ static void jpeg_table_header(AVCodecContext *avctx, PutBitContext *p, } } - if(avctx->active_thread_type & FF_THREAD_SLICE){ + if (use_slices) { put_marker(p, DRI); put_bits(p, 16, 4); put_bits(p, 16, (avctx->width-1)/(8*hsample[0]) + 1); @@ -110,16 +107,16 @@ static void jpeg_table_header(AVCodecContext *avctx, PutBitContext *p, // Only MJPEG can have a variable Huffman variable. All other // formats use the default Huffman table. - if (s && s->huffman == HUFFMAN_TABLE_OPTIMAL) { - size += put_huffman_table(p, 0, 0, s->mjpeg_ctx->bits_dc_luminance, - s->mjpeg_ctx->val_dc_luminance); - size += put_huffman_table(p, 0, 1, s->mjpeg_ctx->bits_dc_chrominance, - s->mjpeg_ctx->val_dc_chrominance); + if (m && m->huffman == HUFFMAN_TABLE_OPTIMAL) { + size += put_huffman_table(p, 0, 0, m->bits_dc_luminance, + m->val_dc_luminance); + size += put_huffman_table(p, 0, 1, m->bits_dc_chrominance, + m->val_dc_chrominance); - size += put_huffman_table(p, 1, 0, s->mjpeg_ctx->bits_ac_luminance, - s->mjpeg_ctx->val_ac_luminance); - size += put_huffman_table(p, 1, 1, s->mjpeg_ctx->bits_ac_chrominance, - s->mjpeg_ctx->val_ac_chrominance); + size += put_huffman_table(p, 1, 0, m->bits_ac_luminance, + m->val_ac_luminance); + size += put_huffman_table(p, 1, 1, m->bits_ac_chrominance, + m->val_ac_chrominance); } else { size += put_huffman_table(p, 0, 0, ff_mjpeg_bits_dc_luminance, ff_mjpeg_val_dc); @@ -134,8 +131,41 @@ static void jpeg_table_header(AVCodecContext *avctx, PutBitContext *p, AV_WB16(ptr, size); } -static void jpeg_put_comments(AVCodecContext *avctx, PutBitContext *p) +enum { + ICC_HDR_SIZE = 16, /* ICC_PROFILE\0 tag + 4 bytes */ + ICC_CHUNK_SIZE = UINT16_MAX - ICC_HDR_SIZE, + ICC_MAX_CHUNKS = UINT8_MAX, +}; + +int ff_mjpeg_add_icc_profile_size(AVCodecContext *avctx, const AVFrame *frame, + size_t *max_pkt_size) { + const AVFrameSideData *sd; + size_t new_pkt_size; + int nb_chunks; + sd = av_frame_get_side_data(frame, AV_FRAME_DATA_ICC_PROFILE); + if (!sd || !sd->size) + return 0; + + if (sd->size > ICC_MAX_CHUNKS * ICC_CHUNK_SIZE) { + av_log(avctx, AV_LOG_ERROR, "Cannot store %"SIZE_SPECIFIER" byte ICC " + "profile: too large for JPEG\n", + sd->size); + return AVERROR_INVALIDDATA; + } + + nb_chunks = (sd->size + ICC_CHUNK_SIZE - 1) / ICC_CHUNK_SIZE; + new_pkt_size = *max_pkt_size + nb_chunks * (UINT16_MAX + 2 /* APP2 marker */); + if (new_pkt_size < *max_pkt_size) /* overflow */ + return AVERROR_INVALIDDATA; + *max_pkt_size = new_pkt_size; + return 0; +} + +static void jpeg_put_comments(AVCodecContext *avctx, PutBitContext *p, + const AVFrame *frame) +{ + const AVFrameSideData *sd = NULL; int size; uint8_t *ptr; @@ -165,6 +195,35 @@ static void jpeg_put_comments(AVCodecContext *avctx, PutBitContext *p) put_bits(p, 8, 0); /* thumbnail height */ } + /* ICC profile */ + sd = av_frame_get_side_data(frame, AV_FRAME_DATA_ICC_PROFILE); + if (sd && sd->size) { + const int nb_chunks = (sd->size + ICC_CHUNK_SIZE - 1) / ICC_CHUNK_SIZE; + const uint8_t *data = sd->data; + size_t remaining = sd->size; + /* must already be checked by the packat allocation code */ + av_assert0(remaining <= ICC_MAX_CHUNKS * ICC_CHUNK_SIZE); + flush_put_bits(p); + for (int i = 0; i < nb_chunks; i++) { + size = FFMIN(remaining, ICC_CHUNK_SIZE); + av_assert1(size > 0); + ptr = put_bits_ptr(p); + ptr[0] = 0xff; /* chunk marker, not part of ICC_HDR_SIZE */ + ptr[1] = APP2; + AV_WB16(ptr+2, size + ICC_HDR_SIZE); + AV_WL32(ptr+4, MKTAG('I','C','C','_')); + AV_WL32(ptr+8, MKTAG('P','R','O','F')); + AV_WL32(ptr+12, MKTAG('I','L','E','\0')); + ptr[16] = i+1; + ptr[17] = nb_chunks; + memcpy(&ptr[18], data, size); + skip_put_bytes(p, size + ICC_HDR_SIZE + 2); + remaining -= size; + data += size; + } + av_assert1(!remaining); + } + /* comment */ if (!(avctx->flags & AV_CODEC_FLAG_BITEXACT)) { put_marker(p, COM); @@ -192,11 +251,7 @@ static void jpeg_put_comments(AVCodecContext *avctx, PutBitContext *p) void ff_mjpeg_init_hvsample(AVCodecContext *avctx, int hsample[4], int vsample[4]) { - int chroma_h_shift, chroma_v_shift; - - av_pix_fmt_get_chroma_sub_sample(avctx->pix_fmt, &chroma_h_shift, - &chroma_v_shift); - if (avctx->codec->id == AV_CODEC_ID_LJPEG && + if (avctx->codec_id == AV_CODEC_ID_LJPEG && ( avctx->pix_fmt == AV_PIX_FMT_BGR0 || avctx->pix_fmt == AV_PIX_FMT_BGRA || avctx->pix_fmt == AV_PIX_FMT_BGR24)) { @@ -208,6 +263,9 @@ void ff_mjpeg_init_hvsample(AVCodecContext *avctx, int hsample[4], int vsample[4 vsample[0] = vsample[1] = vsample[2] = 2; hsample[0] = hsample[1] = hsample[2] = 1; } else { + int chroma_h_shift, chroma_v_shift; + av_pix_fmt_get_chroma_sub_sample(avctx->pix_fmt, &chroma_h_shift, + &chroma_v_shift); vsample[0] = 2; vsample[1] = 2 >> chroma_v_shift; vsample[2] = 2 >> chroma_v_shift; @@ -218,13 +276,14 @@ void ff_mjpeg_init_hvsample(AVCodecContext *avctx, int hsample[4], int vsample[4 } void ff_mjpeg_encode_picture_header(AVCodecContext *avctx, PutBitContext *pb, + const AVFrame *frame, struct MJpegContext *m, ScanTable *intra_scantable, int pred, uint16_t luma_intra_matrix[64], - uint16_t chroma_intra_matrix[64]) + uint16_t chroma_intra_matrix[64], + int use_slices) { - const int lossless = avctx->codec_id != AV_CODEC_ID_MJPEG && avctx->codec_id != AV_CODEC_ID_AMV; + const int lossless = !m; int hsample[4], vsample[4]; - int i; int components = 3 + (avctx->pix_fmt == AV_PIX_FMT_BGRA); int chroma_matrix = !!memcmp(luma_intra_matrix, chroma_intra_matrix, @@ -235,11 +294,14 @@ void ff_mjpeg_encode_picture_header(AVCodecContext *avctx, PutBitContext *pb, put_marker(pb, SOI); // hack for AMV mjpeg format - if(avctx->codec_id == AV_CODEC_ID_AMV) goto end; + if (avctx->codec_id == AV_CODEC_ID_AMV) + return; - jpeg_put_comments(avctx, pb); + jpeg_put_comments(avctx, pb, frame); - jpeg_table_header(avctx, pb, intra_scantable, luma_intra_matrix, chroma_intra_matrix, hsample); + jpeg_table_header(avctx, pb, m, intra_scantable, + luma_intra_matrix, chroma_intra_matrix, hsample, + use_slices); switch (avctx->codec_id) { case AV_CODEC_ID_MJPEG: put_marker(pb, SOF0 ); break; @@ -310,7 +372,7 @@ void ff_mjpeg_encode_picture_header(AVCodecContext *avctx, PutBitContext *pb, put_bits(pb, 4, 0); /* AC huffman table index */ } - put_bits(pb, 8, lossless ? pred : 0); /* Ss (not used) */ + put_bits(pb, 8, pred); /* Ss (not used); pred only nonzero for LJPEG */ switch (avctx->codec_id) { case AV_CODEC_ID_MJPEG: put_bits(pb, 8, 63); break; /* Se (not used) */ @@ -319,16 +381,6 @@ void ff_mjpeg_encode_picture_header(AVCodecContext *avctx, PutBitContext *pb, } put_bits(pb, 8, 0); /* Ah/Al (not used) */ - -end: - if (!lossless) { - MpegEncContext *s = avctx->priv_data; - av_assert0(avctx->codec->priv_data_size == sizeof(MpegEncContext)); - - s->esc_pos = put_bytes_count(pb, 0); - for(i=1; islice_context_count; i++) - s->thread_context[i]->esc_pos = 0; - } } void ff_mjpeg_escape_FF(PutBitContext *pb, int start) diff --git a/libavcodec/mjpegenc_common.h b/libavcodec/mjpegenc_common.h index 76c236d83..5b13faae2 100644 --- a/libavcodec/mjpegenc_common.h +++ b/libavcodec/mjpegenc_common.h @@ -27,10 +27,16 @@ #include "idctdsp.h" #include "put_bits.h" +struct MJpegContext; + +int ff_mjpeg_add_icc_profile_size(AVCodecContext *avctx, const AVFrame *frame, + size_t *max_pkt_size); void ff_mjpeg_encode_picture_header(AVCodecContext *avctx, PutBitContext *pb, + const AVFrame *frame, struct MJpegContext *m, ScanTable *intra_scantable, int pred, uint16_t luma_intra_matrix[64], - uint16_t chroma_intra_matrix[64]); + uint16_t chroma_intra_matrix[64], + int use_slices); void ff_mjpeg_encode_picture_trailer(PutBitContext *pb, int header_bits); void ff_mjpeg_escape_FF(PutBitContext *pb, int start); void ff_mjpeg_build_huffman_codes(uint8_t *huff_size, uint16_t *huff_code, diff --git a/libavcodec/mjpegenc_huffman.c b/libavcodec/mjpegenc_huffman.c index 0e63f8066..9bfcb7e78 100644 --- a/libavcodec/mjpegenc_huffman.c +++ b/libavcodec/mjpegenc_huffman.c @@ -21,10 +21,7 @@ #include #include -#include #include "libavutil/avassert.h" -#include "libavutil/common.h" -#include "libavutil/error.h" #include "libavutil/qsort.h" #include "mjpegenc_huffman.h" diff --git a/libavcodec/mlp.c b/libavcodec/mlp.c index dcec145eb..3f54b2e44 100644 --- a/libavcodec/mlp.c +++ b/libavcodec/mlp.c @@ -57,12 +57,21 @@ const ChannelInformation ff_mlp_ch_info[21] = { { 0x3F, 0x04, 0x02, 0x00 }, }; +#if FF_API_OLD_CHANNEL_LAYOUT const uint64_t ff_mlp_channel_layouts[12] = { AV_CH_LAYOUT_MONO, AV_CH_LAYOUT_STEREO, AV_CH_LAYOUT_2_1, AV_CH_LAYOUT_QUAD, AV_CH_LAYOUT_2POINT1, AV_CH_LAYOUT_SURROUND, AV_CH_LAYOUT_4POINT0, AV_CH_LAYOUT_5POINT0_BACK, AV_CH_LAYOUT_3POINT1, AV_CH_LAYOUT_4POINT1, AV_CH_LAYOUT_5POINT1_BACK, 0, }; +#endif + +const AVChannelLayout ff_mlp_ch_layouts[12] = { + AV_CHANNEL_LAYOUT_MONO, AV_CHANNEL_LAYOUT_STEREO, AV_CHANNEL_LAYOUT_2_1, + AV_CHANNEL_LAYOUT_QUAD, AV_CHANNEL_LAYOUT_2POINT1, AV_CHANNEL_LAYOUT_SURROUND, + AV_CHANNEL_LAYOUT_4POINT0, AV_CHANNEL_LAYOUT_5POINT0_BACK, AV_CHANNEL_LAYOUT_3POINT1, + AV_CHANNEL_LAYOUT_4POINT1, AV_CHANNEL_LAYOUT_5POINT1_BACK, { 0 }, +}; #if CONFIG_SMALL #define CRC_TABLE_SIZE 257 diff --git a/libavcodec/mlp.h b/libavcodec/mlp.h index e45eba55a..8a3e4566a 100644 --- a/libavcodec/mlp.h +++ b/libavcodec/mlp.h @@ -24,6 +24,8 @@ #include +#include "libavutil/channel_layout.h" + #define SYNC_MLP 0xbb #define SYNC_TRUEHD 0xba @@ -135,7 +137,10 @@ typedef struct { */ extern const ChannelInformation ff_mlp_ch_info[21]; +#if FF_API_OLD_CHANNEL_LAYOUT extern const uint64_t ff_mlp_channel_layouts[12]; +#endif +extern const AVChannelLayout ff_mlp_ch_layouts[12]; /** MLP uses checksums that seem to be based on the standard CRC algorithm, but * are not (in implementation terms, the table lookup and XOR are reversed). diff --git a/libavcodec/mlp_parser.c b/libavcodec/mlp_parser.c index 9fea7db95..d391390dd 100644 --- a/libavcodec/mlp_parser.c +++ b/libavcodec/mlp_parser.c @@ -175,22 +175,18 @@ static int mlp_parse(AVCodecParserContext *s, avctx->frame_size = s->duration = mh.access_unit_size; - if(!avctx->channels || !avctx->channel_layout) { + av_channel_layout_uninit(&avctx->ch_layout); if (mh.stream_type == 0xbb) { /* MLP stream */ - avctx->channels = mh.channels_mlp; - avctx->channel_layout = mh.channel_layout_mlp; + av_channel_layout_from_mask(&avctx->ch_layout, mh.channel_layout_mlp); } else { /* mh.stream_type == 0xba */ /* TrueHD stream */ if (!mh.channels_thd_stream2) { - avctx->channels = mh.channels_thd_stream1; - avctx->channel_layout = mh.channel_layout_thd_stream1; + av_channel_layout_from_mask(&avctx->ch_layout, mh.channel_layout_thd_stream1); } else { - avctx->channels = mh.channels_thd_stream2; - avctx->channel_layout = mh.channel_layout_thd_stream2; + av_channel_layout_from_mask(&avctx->ch_layout, mh.channel_layout_thd_stream2); } } - } if (!mh.is_vbr) /* Stream is CBR */ avctx->bit_rate = mh.peak_bitrate; diff --git a/libavcodec/mlpdec.c b/libavcodec/mlpdec.c index 29fac5454..caf35dca0 100644 --- a/libavcodec/mlpdec.c +++ b/libavcodec/mlpdec.c @@ -24,6 +24,8 @@ * MLP decoder */ +#include "config_components.h" + #include #include "avcodec.h" @@ -32,6 +34,8 @@ #include "libavutil/channel_layout.h" #include "libavutil/mem_internal.h" #include "libavutil/thread.h" +#include "libavutil/opt.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" #include "libavutil/crc.h" @@ -132,8 +136,11 @@ typedef struct SubStream { } SubStream; typedef struct MLPDecodeContext { + const AVClass *class; AVCodecContext *avctx; + AVChannelLayout downmix_layout; + /// Current access unit being read has a major sync. int is_major_sync_unit; @@ -169,39 +176,41 @@ typedef struct MLPDecodeContext { MLPDSPContext dsp; } MLPDecodeContext; -static const uint64_t thd_channel_order[] = { - AV_CH_FRONT_LEFT, AV_CH_FRONT_RIGHT, // LR - AV_CH_FRONT_CENTER, // C - AV_CH_LOW_FREQUENCY, // LFE - AV_CH_SIDE_LEFT, AV_CH_SIDE_RIGHT, // LRs - AV_CH_TOP_FRONT_LEFT, AV_CH_TOP_FRONT_RIGHT, // LRvh - AV_CH_FRONT_LEFT_OF_CENTER, AV_CH_FRONT_RIGHT_OF_CENTER, // LRc - AV_CH_BACK_LEFT, AV_CH_BACK_RIGHT, // LRrs - AV_CH_BACK_CENTER, // Cs - AV_CH_TOP_CENTER, // Ts - AV_CH_SURROUND_DIRECT_LEFT, AV_CH_SURROUND_DIRECT_RIGHT, // LRsd - AV_CH_WIDE_LEFT, AV_CH_WIDE_RIGHT, // LRw - AV_CH_TOP_FRONT_CENTER, // Cvh - AV_CH_LOW_FREQUENCY_2, // LFE2 +static const enum AVChannel thd_channel_order[] = { + AV_CHAN_FRONT_LEFT, AV_CHAN_FRONT_RIGHT, // LR + AV_CHAN_FRONT_CENTER, // C + AV_CHAN_LOW_FREQUENCY, // LFE + AV_CHAN_SIDE_LEFT, AV_CHAN_SIDE_RIGHT, // LRs + AV_CHAN_TOP_FRONT_LEFT, AV_CHAN_TOP_FRONT_RIGHT, // LRvh + AV_CHAN_FRONT_LEFT_OF_CENTER, AV_CHAN_FRONT_RIGHT_OF_CENTER, // LRc + AV_CHAN_BACK_LEFT, AV_CHAN_BACK_RIGHT, // LRrs + AV_CHAN_BACK_CENTER, // Cs + AV_CHAN_TOP_CENTER, // Ts + AV_CHAN_SURROUND_DIRECT_LEFT, AV_CHAN_SURROUND_DIRECT_RIGHT, // LRsd + AV_CHAN_WIDE_LEFT, AV_CHAN_WIDE_RIGHT, // LRw + AV_CHAN_TOP_FRONT_CENTER, // Cvh + AV_CHAN_LOW_FREQUENCY_2, // LFE2 }; -static int mlp_channel_layout_subset(uint64_t channel_layout, uint64_t mask) +static int mlp_channel_layout_subset(AVChannelLayout *layout, uint64_t mask) { - return channel_layout && ((channel_layout & mask) == channel_layout); + return av_channel_layout_check(layout) && + av_channel_layout_subset(layout, mask) == + av_channel_layout_subset(layout, UINT64_MAX); } -static uint64_t thd_channel_layout_extract_channel(uint64_t channel_layout, - int index) +static enum AVChannel thd_channel_layout_extract_channel(uint64_t channel_layout, + int index) { int i; - if (av_get_channel_layout_nb_channels(channel_layout) <= index) - return 0; + if (av_popcount64(channel_layout) <= index) + return AV_CHAN_NONE; for (i = 0; i < FF_ARRAY_ELEMS(thd_channel_order); i++) - if (channel_layout & thd_channel_order[i] && !index--) + if (channel_layout & (1ULL << thd_channel_order[i]) && !index--) return thd_channel_order[i]; - return 0; + return AV_CHAN_NONE; } static VLC huff_vlc[3]; @@ -211,7 +220,7 @@ static VLC huff_vlc[3]; static av_cold void init_static(void) { for (int i = 0; i < 3; i++) { - static VLC_TYPE vlc_buf[3 * VLC_STATIC_SIZE][2]; + static VLCElem vlc_buf[3 * VLC_STATIC_SIZE]; huff_vlc[i].table = &vlc_buf[i * VLC_STATIC_SIZE]; huff_vlc[i].table_allocated = VLC_STATIC_SIZE; init_vlc(&huff_vlc[i], VLC_BITS, 18, @@ -290,6 +299,14 @@ static av_cold int mlp_decode_init(AVCodecContext *avctx) m->substream[substr].lossless_check_data = 0xffffffff; ff_mlpdsp_init(&m->dsp); +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->request_channel_layout) { + av_channel_layout_uninit(&m->downmix_layout); + av_channel_layout_from_mask(&m->downmix_layout, avctx->request_channel_layout); + } +FF_ENABLE_DEPRECATION_WARNINGS +#endif ff_thread_once(&init_static_once, init_static); return 0; @@ -410,7 +427,7 @@ static int read_major_sync(MLPDecodeContext *m, GetBitContext *gb) } if (mh.channels_thd_stream1 == 2 && mh.channels_thd_stream2 == 2 && - m->avctx->channels == 2) + m->avctx->ch_layout.nb_channels == 2) m->substream[0].mask = AV_CH_LAYOUT_STEREO; if ((substr = (mh.num_substreams > 1))) m->substream[0].mask = AV_CH_LAYOUT_STEREO; @@ -419,14 +436,17 @@ static int read_major_sync(MLPDecodeContext *m, GetBitContext *gb) m->substream[2].mask = mh.channel_layout_thd_stream2; else m->substream[2].mask = mh.channel_layout_thd_stream1; - if (m->avctx->channels > 2) + if (m->avctx->ch_layout.nb_channels > 2) m->substream[mh.num_substreams > 1].mask = mh.channel_layout_thd_stream1; - if (m->avctx->channels<=2 && m->substream[substr].mask == AV_CH_LAYOUT_MONO && m->max_decoded_substream == 1) { + if (m->avctx->ch_layout.nb_channels <= 2 && + m->substream[substr].mask == AV_CH_LAYOUT_MONO && m->max_decoded_substream == 1) { av_log(m->avctx, AV_LOG_DEBUG, "Mono stream with 2 substreams, ignoring 2nd\n"); m->max_decoded_substream = 0; - if (m->avctx->channels==2) - m->avctx->channel_layout = AV_CH_LAYOUT_STEREO; + if (m->avctx->ch_layout.nb_channels == 2) { + av_channel_layout_uninit(&m->avctx->ch_layout); + m->avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; + } } } @@ -548,7 +568,7 @@ static int read_restart_header(MLPDecodeContext *m, GetBitContext *gbp, s->max_matrix_channel = max_matrix_channel; s->noise_type = noise_type; - if (mlp_channel_layout_subset(m->avctx->request_channel_layout, s->mask) && + if (mlp_channel_layout_subset(&m->downmix_layout, s->mask) && m->max_decoded_substream > substr) { av_log(m->avctx, AV_LOG_DEBUG, "Extracting %d-channel downmix (0x%"PRIx64") from substream %d. " @@ -580,10 +600,11 @@ static int read_restart_header(MLPDecodeContext *m, GetBitContext *gbp, for (ch = 0; ch <= s->max_matrix_channel; ch++) { int ch_assign = get_bits(gbp, 6); if (m->avctx->codec_id == AV_CODEC_ID_TRUEHD) { - uint64_t channel = thd_channel_layout_extract_channel(s->mask, - ch_assign); - ch_assign = av_get_channel_layout_channel_index(s->mask, - channel); + AVChannelLayout l; + enum AVChannel channel = thd_channel_layout_extract_channel(s->mask, ch_assign); + + av_channel_layout_from_mask(&l, s->mask); + ch_assign = av_channel_layout_index_from_channel(&l, channel); } if (ch_assign < 0 || ch_assign > s->max_matrix_channel) { avpriv_request_sample(m->avctx, @@ -623,21 +644,21 @@ static int read_restart_header(MLPDecodeContext *m, GetBitContext *gbp, } if (substr == m->max_decoded_substream) { - m->avctx->channels = s->max_matrix_channel + 1; - m->avctx->channel_layout = s->mask; + av_channel_layout_uninit(&m->avctx->ch_layout); + av_channel_layout_from_mask(&m->avctx->ch_layout, s->mask); m->dsp.mlp_pack_output = m->dsp.mlp_select_pack_output(s->ch_assign, s->output_shift, s->max_matrix_channel, m->avctx->sample_fmt == AV_SAMPLE_FMT_S32); if (m->avctx->codec_id == AV_CODEC_ID_MLP && m->needs_reordering) { - if (m->avctx->channel_layout == (AV_CH_LAYOUT_QUAD|AV_CH_LOW_FREQUENCY) || - m->avctx->channel_layout == AV_CH_LAYOUT_5POINT0_BACK) { + if (s->mask == (AV_CH_LAYOUT_QUAD|AV_CH_LOW_FREQUENCY) || + s->mask == AV_CH_LAYOUT_5POINT0_BACK) { int i = s->ch_assign[4]; s->ch_assign[4] = s->ch_assign[3]; s->ch_assign[3] = s->ch_assign[2]; s->ch_assign[2] = i; - } else if (m->avctx->channel_layout == AV_CH_LAYOUT_5POINT1_BACK) { + } else if (s->mask == AV_CH_LAYOUT_5POINT1_BACK) { FFSWAP(int, s->ch_assign[2], s->ch_assign[4]); FFSWAP(int, s->ch_assign[3], s->ch_assign[5]); } @@ -1078,7 +1099,7 @@ static int output_data(MLPDecodeContext *m, unsigned int substr, int ret; int is32 = (m->avctx->sample_fmt == AV_SAMPLE_FMT_S32); - if (m->avctx->channels != s->max_matrix_channel + 1) { + if (m->avctx->ch_layout.nb_channels != s->max_matrix_channel + 1) { av_log(m->avctx, AV_LOG_ERROR, "channel count mismatch\n"); return AVERROR_INVALIDDATA; } @@ -1143,7 +1164,7 @@ static int output_data(MLPDecodeContext *m, unsigned int substr, * @return negative on error, 0 if not enough data is present in the input stream, * otherwise the number of bytes consumed. */ -static int read_access_unit(AVCodecContext *avctx, void* data, +static int read_access_unit(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; @@ -1255,7 +1276,7 @@ static int read_access_unit(AVCodecContext *avctx, void* data, if (substr != m->max_decoded_substream && m->substream[m->max_decoded_substream].min_channel == 0 && - m->substream[m->max_decoded_substream].max_channel == avctx->channels - 1) + m->substream[m->max_decoded_substream].max_channel == avctx->ch_layout.nb_channels - 1) goto skip_substr; init_get_bits(&gb, buf, substream_data_len[substr] * 8); @@ -1335,7 +1356,7 @@ skip_substr: buf += substream_data_len[substr]; } - if ((ret = output_data(m, m->max_decoded_substream, data, got_frame_ptr)) < 0) + if ((ret = output_data(m, m->max_decoded_substream, frame, got_frame_ptr)) < 0) return ret; for (substr = 0; substr <= m->max_decoded_substream; substr++){ @@ -1372,31 +1393,55 @@ static void mlp_decode_flush(AVCodecContext *avctx) } } +#define OFFSET(x) offsetof(MLPDecodeContext, x) +#define FLAGS (AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM) +static const AVOption options[] = { + { "downmix", "Request a specific channel layout from the decoder", OFFSET(downmix_layout), + AV_OPT_TYPE_CHLAYOUT, {.str = NULL}, .flags = FLAGS }, + { NULL }, +}; + +static const AVClass mlp_decoder_class = { + .class_name = "MLP decoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const AVClass truehd_decoder_class = { + .class_name = "TrueHD decoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + #if CONFIG_MLP_DECODER -const AVCodec ff_mlp_decoder = { - .name = "mlp", - .long_name = NULL_IF_CONFIG_SMALL("MLP (Meridian Lossless Packing)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_MLP, +const FFCodec ff_mlp_decoder = { + .p.name = "mlp", + .p.long_name = NULL_IF_CONFIG_SMALL("MLP (Meridian Lossless Packing)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_MLP, .priv_data_size = sizeof(MLPDecodeContext), + .p.priv_class = &mlp_decoder_class, .init = mlp_decode_init, - .decode = read_access_unit, + FF_CODEC_DECODE_CB(read_access_unit), .flush = mlp_decode_flush, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_TRUEHD_DECODER -const AVCodec ff_truehd_decoder = { - .name = "truehd", - .long_name = NULL_IF_CONFIG_SMALL("TrueHD"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_TRUEHD, +const FFCodec ff_truehd_decoder = { + .p.name = "truehd", + .p.long_name = NULL_IF_CONFIG_SMALL("TrueHD"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_TRUEHD, .priv_data_size = sizeof(MLPDecodeContext), + .p.priv_class = &truehd_decoder_class, .init = mlp_decode_init, - .decode = read_access_unit, + FF_CODEC_DECODE_CB(read_access_unit), .flush = mlp_decode_flush, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif /* CONFIG_TRUEHD_DECODER */ diff --git a/libavcodec/mlpdsp.c b/libavcodec/mlpdsp.c index 12bef3a72..eaf5de8e1 100644 --- a/libavcodec/mlpdsp.c +++ b/libavcodec/mlpdsp.c @@ -131,8 +131,9 @@ av_cold void ff_mlpdsp_init(MLPDSPContext *c) c->mlp_rematrix_channel = ff_mlp_rematrix_channel; c->mlp_select_pack_output = mlp_select_pack_output; c->mlp_pack_output = ff_mlp_pack_output; - if (ARCH_ARM) - ff_mlpdsp_init_arm(c); - if (ARCH_X86) - ff_mlpdsp_init_x86(c); +#if ARCH_ARM + ff_mlpdsp_init_arm(c); +#elif ARCH_X86 + ff_mlpdsp_init_x86(c); +#endif } diff --git a/libavcodec/mlpenc.c b/libavcodec/mlpenc.c index d8783b6f5..52ddec3a2 100644 --- a/libavcodec/mlpenc.c +++ b/libavcodec/mlpenc.c @@ -20,9 +20,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "put_bits.h" #include "audio_frame_queue.h" #include "libavutil/channel_layout.h" @@ -381,8 +383,8 @@ static void copy_restart_frame_params(MLPEncodeContext *ctx) copy_matrix_params(&dp->matrix_params, &ctx->cur_decoding_params->matrix_params); - for (unsigned int channel = 0; channel < ctx->avctx->channels; channel++) { - ChannelParams *cp = ctx->seq_channel_params + index*(ctx->avctx->channels) + channel; + for (unsigned int channel = 0; channel < ctx->avctx->ch_layout.nb_channels; channel++) { + ChannelParams *cp = ctx->seq_channel_params + index*(ctx->avctx->ch_layout.nb_channels) + channel; dp->quant_step_size[channel] = ctx->cur_decoding_params->quant_step_size[channel]; dp->matrix_params.shift[channel] = ctx->cur_decoding_params->matrix_params.shift[channel]; @@ -528,13 +530,13 @@ static av_cold int mlp_encode_init(AVCodecContext *avctx) ctx->coded_peak_bitrate = mlp_peak_bitrate(9600000, avctx->sample_rate); /* TODO support more channels. */ - if (avctx->channels > 2) { + if (avctx->ch_layout.nb_channels > 2) { av_log(avctx, AV_LOG_WARNING, "Only mono and stereo are supported at the moment.\n"); } ctx->substream_info |= SUBSTREAM_INFO_ALWAYS_SET; - if (avctx->channels <= 2) { + if (avctx->ch_layout.nb_channels <= 2) { ctx->substream_info |= SUBSTREAM_INFO_MAX_2_CHAN; } @@ -559,7 +561,7 @@ static av_cold int mlp_encode_init(AVCodecContext *avctx) ctx->dts = -avctx->frame_size; - ctx->num_channels = avctx->channels + 2; /* +2 noise channels */ + ctx->num_channels = avctx->ch_layout.nb_channels + 2; /* +2 noise channels */ ctx->one_sample_buffer_size = avctx->frame_size * ctx->num_channels; /* TODO Let user pass major header interval as parameter. */ @@ -588,59 +590,48 @@ static av_cold int mlp_encode_init(AVCodecContext *avctx) ctx->num_substreams = 1; // TODO: change this after adding multi-channel support for TrueHD if (ctx->avctx->codec_id == AV_CODEC_ID_MLP) { - /* MLP */ - switch(avctx->channel_layout) { - case AV_CH_LAYOUT_MONO: - ctx->channel_arrangement = 0; break; - case AV_CH_LAYOUT_STEREO: - ctx->channel_arrangement = 1; break; - case AV_CH_LAYOUT_2_1: - ctx->channel_arrangement = 2; break; - case AV_CH_LAYOUT_QUAD: - ctx->channel_arrangement = 3; break; - case AV_CH_LAYOUT_2POINT1: - ctx->channel_arrangement = 4; break; - case AV_CH_LAYOUT_SURROUND: - ctx->channel_arrangement = 7; break; - case AV_CH_LAYOUT_4POINT0: - ctx->channel_arrangement = 8; break; - case AV_CH_LAYOUT_5POINT0_BACK: - ctx->channel_arrangement = 9; break; - case AV_CH_LAYOUT_3POINT1: - ctx->channel_arrangement = 10; break; - case AV_CH_LAYOUT_4POINT1: - ctx->channel_arrangement = 11; break; - case AV_CH_LAYOUT_5POINT1_BACK: - ctx->channel_arrangement = 12; break; - default: + static const AVChannelLayout layout_arrangement[] = { + AV_CHANNEL_LAYOUT_MONO, AV_CHANNEL_LAYOUT_STEREO, + AV_CHANNEL_LAYOUT_2_1, AV_CHANNEL_LAYOUT_QUAD, + AV_CHANNEL_LAYOUT_2POINT1, { 0 }, { 0 }, + AV_CHANNEL_LAYOUT_SURROUND, AV_CHANNEL_LAYOUT_4POINT0, + AV_CHANNEL_LAYOUT_5POINT0_BACK, AV_CHANNEL_LAYOUT_3POINT1, + AV_CHANNEL_LAYOUT_4POINT1, AV_CHANNEL_LAYOUT_5POINT1_BACK, + }; + int i; + + for (i = 0; i < FF_ARRAY_ELEMS(layout_arrangement); i++) + if (!av_channel_layout_compare(&avctx->ch_layout, &layout_arrangement[i])) + break; + if (i == FF_ARRAY_ELEMS(layout_arrangement)) { av_log(avctx, AV_LOG_ERROR, "Unsupported channel arrangement\n"); return AVERROR(EINVAL); } + ctx->channel_arrangement = i; ctx->flags = FLAGS_DVDA; ctx->channel_occupancy = ff_mlp_ch_info[ctx->channel_arrangement].channel_occupancy; ctx->summary_info = ff_mlp_ch_info[ctx->channel_arrangement].summary_info ; } else { /* TrueHD */ - switch(avctx->channel_layout) { - case AV_CH_LAYOUT_STEREO: + if (!av_channel_layout_compare(&avctx->ch_layout, + &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO)) { ctx->ch_modifier_thd0 = 0; ctx->ch_modifier_thd1 = 0; ctx->ch_modifier_thd2 = 0; ctx->channel_arrangement = 1; - break; - case AV_CH_LAYOUT_5POINT0_BACK: + } else if (!av_channel_layout_compare(&avctx->ch_layout, + &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT0_BACK)) { ctx->ch_modifier_thd0 = 1; ctx->ch_modifier_thd1 = 1; ctx->ch_modifier_thd2 = 1; ctx->channel_arrangement = 11; - break; - case AV_CH_LAYOUT_5POINT1_BACK: + } else if (!av_channel_layout_compare(&avctx->ch_layout, + &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1_BACK)) { ctx->ch_modifier_thd0 = 2; ctx->ch_modifier_thd1 = 1; ctx->ch_modifier_thd2 = 2; ctx->channel_arrangement = 15; - break; - default: + } else { av_log(avctx, AV_LOG_ERROR, "Unsupported channel arrangement\n"); return AVERROR(EINVAL); } @@ -665,7 +656,7 @@ static av_cold int mlp_encode_init(AVCodecContext *avctx) sum += ctx->seq_size[index]; } ctx->sequence_size = sum; - size = ctx->restart_intervals * ctx->sequence_size * ctx->avctx->channels; + size = ctx->restart_intervals * ctx->sequence_size * ctx->avctx->ch_layout.nb_channels; ctx->channel_params = av_calloc(size, sizeof(*ctx->channel_params)); if (!ctx->channel_params) return AVERROR(ENOMEM); @@ -679,7 +670,7 @@ static av_cold int mlp_encode_init(AVCodecContext *avctx) rh->noisegen_seed = 0; rh->min_channel = 0; - rh->max_channel = avctx->channels - 1; + rh->max_channel = avctx->ch_layout.nb_channels - 1; /* FIXME: this works for 1 and 2 channels, but check for more */ rh->max_matrix_channel = rh->max_channel; @@ -1174,6 +1165,7 @@ static int write_access_unit(MLPEncodeContext *ctx, uint8_t *buf, * lossless_check_data that will be written to the restart header. */ static void input_data_internal(MLPEncodeContext *ctx, const uint8_t *samples, + int nb_samples, int is24) { int32_t *lossless_check_data = ctx->lossless_check_data; @@ -1186,7 +1178,7 @@ static void input_data_internal(MLPEncodeContext *ctx, const uint8_t *samples, lossless_check_data += ctx->frame_index; - for (int i = 0; i < ctx->avctx->frame_size; i++) { + for (int i = 0; i < nb_samples; i++) { for (unsigned int channel = 0; channel <= rh->max_channel; channel++) { uint32_t abs_sample; int32_t sample; @@ -1195,8 +1187,7 @@ static void input_data_internal(MLPEncodeContext *ctx, const uint8_t *samples, /* TODO Find out if number_sbits can be used for negative values. */ abs_sample = FFABS(sample); - if (greatest < abs_sample) - greatest = abs_sample; + greatest = FFMAX(greatest, abs_sample); temp_lossless_check_data ^= (sample & 0x00ffffff) << channel; *sample_buffer++ = sample; @@ -1211,12 +1202,9 @@ static void input_data_internal(MLPEncodeContext *ctx, const uint8_t *samples, } /** Wrapper function for inputting data in two different bit-depths. */ -static void input_data(MLPEncodeContext *ctx, void *samples) +static void input_data(MLPEncodeContext *ctx, void *samples, int nb_samples) { - if (ctx->avctx->sample_fmt == AV_SAMPLE_FMT_S32) - input_data_internal(ctx, samples, 1); - else - input_data_internal(ctx, samples, 0); + input_data_internal(ctx, samples, nb_samples, ctx->avctx->sample_fmt == AV_SAMPLE_FMT_S32); } static void input_to_sample_buffer(MLPEncodeContext *ctx) @@ -1228,7 +1216,7 @@ static void input_to_sample_buffer(MLPEncodeContext *ctx) int32_t *input_buffer = ctx->inout_buffer + cur_index * ctx->one_sample_buffer_size; for (unsigned int i = 0; i < ctx->avctx->frame_size; i++) { - for (unsigned int channel = 0; channel < ctx->avctx->channels; channel++) + for (unsigned int channel = 0; channel < ctx->avctx->ch_layout.nb_channels; channel++) *sample_buffer++ = *input_buffer++; sample_buffer += 2; /* noise_channels */ input_buffer += 2; /* noise_channels */ @@ -1947,7 +1935,7 @@ static void set_best_codebook(MLPEncodeContext *ctx) /* Update context. */ for (unsigned int index = 0; index < ctx->number_of_subblocks; index++) { - ChannelParams *cp = ctx->seq_channel_params + index*(ctx->avctx->channels) + channel; + ChannelParams *cp = ctx->seq_channel_params + index*(ctx->avctx->ch_layout.nb_channels) + channel; best_codebook = *best_path++; cur_bo = &ctx->best_offset[index][channel][best_codebook]; @@ -1968,17 +1956,18 @@ static void set_major_params(MLPEncodeContext *ctx) RestartHeader *rh = ctx->cur_restart_header; uint8_t max_huff_lsbs = 0; uint8_t max_output_bits = 0; - DecodingParams *seq_dp = ctx->decoding_params + ctx->seq_offset[0] * ctx->avctx->channels; - ChannelParams *seq_cp = ctx->channel_params + ctx->seq_offset[0] * ctx->avctx->channels; + int channels = ctx->avctx->ch_layout.nb_channels; + DecodingParams *seq_dp = ctx->decoding_params + ctx->seq_offset[0] * channels; + ChannelParams *seq_cp = ctx->channel_params + ctx->seq_offset[0] * channels; for (unsigned int index = 0; index < ctx->seq_size[ctx->restart_intervals-1]; index++) { memcpy(&ctx->major_decoding_params[index], seq_dp + index, sizeof(DecodingParams)); - for (unsigned int channel = 0; channel < ctx->avctx->channels; channel++) { - uint8_t huff_lsbs = (seq_cp + index*(ctx->avctx->channels) + channel)->huff_lsbs; + for (unsigned int channel = 0; channel < channels; channel++) { + uint8_t huff_lsbs = (seq_cp + index*(channels) + channel)->huff_lsbs; if (max_huff_lsbs < huff_lsbs) max_huff_lsbs = huff_lsbs; memcpy(&ctx->major_channel_params[index][channel], - (seq_cp + index*(ctx->avctx->channels) + channel), + (seq_cp + index*(channels) + channel), sizeof(ChannelParams)); } } @@ -2017,7 +2006,7 @@ static void analyze_sample_buffer(MLPEncodeContext *ctx) ctx->cur_restart_header = &ctx->restart_header; ctx->cur_decoding_params = seq_dp + 1; - ctx->cur_channel_params = seq_cp + ctx->avctx->channels; + ctx->cur_channel_params = seq_cp + ctx->avctx->ch_layout.nb_channels; determine_quant_step_size(ctx); generate_2_noise_channels(ctx); @@ -2044,7 +2033,7 @@ static void analyze_sample_buffer(MLPEncodeContext *ctx) for (unsigned int index = 0; index < ctx->number_of_subblocks; index++) { ctx->cur_decoding_params = seq_dp + index; - ctx->cur_channel_params = seq_cp + index*(ctx->avctx->channels); + ctx->cur_channel_params = seq_cp + index*(ctx->avctx->ch_layout.nb_channels); ctx->cur_best_offset = ctx->best_offset[index]; determine_bits(ctx); ctx->sample_buffer += ctx->cur_decoding_params->blocksize * ctx->num_channels; @@ -2078,20 +2067,23 @@ static int mlp_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, { MLPEncodeContext *ctx = avctx->priv_data; int bytes_written = 0; + int channels = avctx->ch_layout.nb_channels; int restart_frame, ret; uint8_t *data; + if (!frame && !ctx->last_frames) + ctx->last_frames = (ctx->afq.remaining_samples + avctx->frame_size - 1) / avctx->frame_size; + if (!frame && !ctx->last_frames--) return 0; - if ((ret = ff_alloc_packet(avctx, avpkt, 87500 * avctx->channels)) < 0) + if ((ret = ff_alloc_packet(avctx, avpkt, 87500 * channels)) < 0) return ret; if (frame) { /* add current frame to queue */ if ((ret = ff_af_queue_add(&ctx->afq, frame)) < 0) return ret; - ctx->last_frames = ctx->max_restart_interval; } data = frame ? frame->data[0] : NULL; @@ -2130,12 +2122,13 @@ static int mlp_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, input_and_return: - if (frame) + if (frame) { ctx->shorten_by = avctx->frame_size - frame->nb_samples; - ctx->next_major_frame_size += avctx->frame_size; - ctx->next_major_number_of_frames++; + ctx->next_major_frame_size += avctx->frame_size; + ctx->next_major_number_of_frames++; + } if (data) - input_data(ctx, data); + input_data(ctx, data, frame->nb_samples); restart_frame = (ctx->frame_index + 1) % ctx->min_restart_interval; @@ -2149,7 +2142,7 @@ input_and_return: ctx->number_of_frames = ctx->next_major_number_of_frames; ctx->number_of_subblocks = ctx->next_major_number_of_frames + 1; - ctx->seq_channel_params = ctx->channel_params + ctx->seq_offset[seq_index] * ctx->avctx->channels; + ctx->seq_channel_params = ctx->channel_params + ctx->seq_offset[seq_index] * channels; ctx->seq_decoding_params = ctx->decoding_params + ctx->seq_offset[seq_index]; @@ -2157,7 +2150,7 @@ input_and_return: ctx->number_of_samples = number_of_samples; for (unsigned int index = 0; index < ctx->seq_size[seq_index]; index++) { - clear_channel_params(ctx->seq_channel_params + index * ctx->avctx->channels, ctx->avctx->channels); + clear_channel_params(ctx->seq_channel_params + index * channels, channels); default_decoding_params(ctx, ctx->seq_decoding_params + index); } @@ -2174,11 +2167,13 @@ input_and_return: } } - if (!frame) + if (!frame && ctx->last_frames < ctx->max_restart_interval - 1) avctx->frame_number++; if (bytes_written > 0) { - ff_af_queue_remove(&ctx->afq, avctx->frame_size, &avpkt->pts, + ff_af_queue_remove(&ctx->afq, + FFMIN(avctx->frame_size, ctx->afq.remaining_samples), + &avpkt->pts, &avpkt->duration); av_shrink_packet(avpkt, bytes_written); @@ -2213,36 +2208,47 @@ static av_cold int mlp_encode_close(AVCodecContext *avctx) } #if CONFIG_MLP_ENCODER -const AVCodec ff_mlp_encoder = { - .name ="mlp", - .long_name = NULL_IF_CONFIG_SMALL("MLP (Meridian Lossless Packing)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_MLP, +const FFCodec ff_mlp_encoder = { + .p.name ="mlp", + .p.long_name = NULL_IF_CONFIG_SMALL("MLP (Meridian Lossless Packing)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_MLP, .priv_data_size = sizeof(MLPEncodeContext), .init = mlp_encode_init, - .encode2 = mlp_encode_frame, + FF_CODEC_ENCODE_CB(mlp_encode_frame), .close = mlp_encode_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_EXPERIMENTAL, - .sample_fmts = (const enum AVSampleFormat[]) {AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE}, - .supported_samplerates = (const int[]) {44100, 48000, 88200, 96000, 176400, 192000, 0}, - .channel_layouts = ff_mlp_channel_layouts, + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_EXPERIMENTAL, + .p.sample_fmts = (const enum AVSampleFormat[]) {AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE}, + .p.supported_samplerates = (const int[]) {44100, 48000, 88200, 96000, 176400, 192000, 0}, +#if FF_API_OLD_CHANNEL_LAYOUT + .p.channel_layouts = ff_mlp_channel_layouts, +#endif + .p.ch_layouts = ff_mlp_ch_layouts, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; #endif #if CONFIG_TRUEHD_ENCODER -const AVCodec ff_truehd_encoder = { - .name ="truehd", - .long_name = NULL_IF_CONFIG_SMALL("TrueHD"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_TRUEHD, +const FFCodec ff_truehd_encoder = { + .p.name ="truehd", + .p.long_name = NULL_IF_CONFIG_SMALL("TrueHD"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_TRUEHD, .priv_data_size = sizeof(MLPEncodeContext), .init = mlp_encode_init, - .encode2 = mlp_encode_frame, + FF_CODEC_ENCODE_CB(mlp_encode_frame), .close = mlp_encode_close, - .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_EXPERIMENTAL, - .sample_fmts = (const enum AVSampleFormat[]) {AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE}, - .supported_samplerates = (const int[]) {44100, 48000, 88200, 96000, 176400, 192000, 0}, - .channel_layouts = (const uint64_t[]) {AV_CH_LAYOUT_STEREO, AV_CH_LAYOUT_5POINT0_BACK, AV_CH_LAYOUT_5POINT1_BACK, 0}, + .p.capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_EXPERIMENTAL, + .p.sample_fmts = (const enum AVSampleFormat[]) {AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE}, + .p.supported_samplerates = (const int[]) {44100, 48000, 88200, 96000, 176400, 192000, 0}, +#if FF_API_OLD_CHANNEL_LAYOUT + .p.channel_layouts = (const uint64_t[]) {AV_CH_LAYOUT_STEREO, AV_CH_LAYOUT_5POINT0_BACK, AV_CH_LAYOUT_5POINT1_BACK, 0}, +#endif + .p.ch_layouts = (const AVChannelLayout[]) { + AV_CHANNEL_LAYOUT_STEREO, + AV_CHANNEL_LAYOUT_5POINT0_BACK, + AV_CHANNEL_LAYOUT_5POINT1_BACK, + { 0 } + }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; #endif diff --git a/libavcodec/mlz.c b/libavcodec/mlz.c index dbeb7dcad..9087ffd8f 100644 --- a/libavcodec/mlz.c +++ b/libavcodec/mlz.c @@ -20,8 +20,11 @@ #include "mlz.h" -av_cold void ff_mlz_init_dict(void* context, MLZ *mlz) { +av_cold int ff_mlz_init_dict(void *context, MLZ *mlz) +{ mlz->dict = av_mallocz(TABLE_SIZE * sizeof(*mlz->dict)); + if (!mlz->dict) + return AVERROR(ENOMEM); mlz->flush_code = FLUSH_CODE; mlz->current_dic_index_max = DIC_INDEX_INIT; @@ -30,6 +33,8 @@ av_cold void ff_mlz_init_dict(void* context, MLZ *mlz) { mlz->next_code = FIRST_CODE; mlz->freeze_flag = 0; mlz->context = context; + + return 0; } av_cold void ff_mlz_flush_dict(MLZ *mlz) { diff --git a/libavcodec/mlz.h b/libavcodec/mlz.h index c3df52c9b..24993126c 100644 --- a/libavcodec/mlz.h +++ b/libavcodec/mlz.h @@ -57,7 +57,7 @@ typedef struct MLZ { /** Initialize the dictionary */ -void ff_mlz_init_dict(void* context, MLZ *mlz); +int ff_mlz_init_dict(void *context, MLZ *mlz); /** Flush the dictionary */ diff --git a/libavcodec/mmaldec.c b/libavcodec/mmaldec.c index cd645189d..7fd24ad3b 100644 --- a/libavcodec/mmaldec.c +++ b/libavcodec/mmaldec.c @@ -34,6 +34,7 @@ #include #include "avcodec.h" +#include "codec_internal.h" #include "decode.h" #include "hwconfig.h" #include "internal.h" @@ -828,24 +829,24 @@ static const AVClass ffmmal_dec_class = { }; #define FFMMAL_DEC(NAME, ID) \ - const AVCodec ff_##NAME##_mmal_decoder = { \ - .name = #NAME "_mmal", \ - .long_name = NULL_IF_CONFIG_SMALL(#NAME " (mmal)"), \ - .type = AVMEDIA_TYPE_VIDEO, \ - .id = ID, \ + const FFCodec ff_##NAME##_mmal_decoder = { \ + .p.name = #NAME "_mmal", \ + .p.long_name = NULL_IF_CONFIG_SMALL(#NAME " (mmal)"), \ + .p.type = AVMEDIA_TYPE_VIDEO, \ + .p.id = ID, \ .priv_data_size = sizeof(MMALDecodeContext), \ .init = ffmmal_init_decoder, \ .close = ffmmal_close_decoder, \ - .receive_frame = ffmmal_receive_frame, \ + FF_CODEC_RECEIVE_FRAME_CB(ffmmal_receive_frame), \ .flush = ffmmal_flush, \ - .priv_class = &ffmmal_dec_class, \ - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, \ + .p.priv_class = &ffmmal_dec_class, \ + .p.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, \ + .p.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", \ + .p.wrapper_name = "mmal", \ }; FFMMAL_DEC(h264, AV_CODEC_ID_H264) diff --git a/libavcodec/mmvideo.c b/libavcodec/mmvideo.c index 8dfcc7193..fc80ec476 100644 --- a/libavcodec/mmvideo.c +++ b/libavcodec/mmvideo.c @@ -34,6 +34,7 @@ #include "libavutil/intreadwrite.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" #define MM_PREAMBLE_SIZE 6 @@ -185,9 +186,8 @@ static int mm_decode_inter(MmContext * s, int half_horiz, int half_vert) return 0; } -static int mm_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int mm_decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; @@ -221,7 +221,7 @@ static int mm_decode_frame(AVCodecContext *avctx, memcpy(s->frame->data[1], s->palette, AVPALETTE_SIZE); - if ((res = av_frame_ref(data, s->frame)) < 0) + if ((res = av_frame_ref(rframe, s->frame)) < 0) return res; *got_frame = 1; @@ -238,15 +238,15 @@ static av_cold int mm_decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_mmvideo_decoder = { - .name = "mmvideo", - .long_name = NULL_IF_CONFIG_SMALL("American Laser Games MM Video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MMVIDEO, +const FFCodec ff_mmvideo_decoder = { + .p.name = "mmvideo", + .p.long_name = NULL_IF_CONFIG_SMALL("American Laser Games MM Video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MMVIDEO, .priv_data_size = sizeof(MmContext), .init = mm_decode_init, .close = mm_decode_end, - .decode = mm_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(mm_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/mobiclip.c b/libavcodec/mobiclip.c index 23d64f76f..dcf788c63 100644 --- a/libavcodec/mobiclip.c +++ b/libavcodec/mobiclip.c @@ -29,6 +29,7 @@ #include "avcodec.h" #include "bytestream.h" #include "bswapdsp.h" +#include "codec_internal.h" #include "get_bits.h" #include "golomb.h" #include "internal.h" @@ -287,7 +288,7 @@ static av_cold void mobiclip_init_static(void) syms1, sizeof(*syms1), sizeof(*syms1), 0, 0, 1 << MOBI_RL_VLC_BITS); for (int i = 0; i < 2; i++) { - static VLC_TYPE vlc_buf[2 * 16 << MOBI_MV_VLC_BITS][2]; + static VLCElem vlc_buf[2 * 16 << MOBI_MV_VLC_BITS]; for (int j = 0; j < 16; j++) { mv_vlc[i][j].table = &vlc_buf[(16 * i + j) << MOBI_MV_VLC_BITS]; mv_vlc[i][j].table_allocated = 1 << MOBI_MV_VLC_BITS; @@ -1207,8 +1208,8 @@ static int predict_motion(AVCodecContext *avctx, return 0; } -static int mobiclip_decode(AVCodecContext *avctx, void *data, - int *got_frame, AVPacket *pkt) +static int mobiclip_decode(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *pkt) { MobiClipContext *s = avctx->priv_data; GetBitContext *gb = &s->gb; @@ -1307,7 +1308,7 @@ static int mobiclip_decode(AVCodecContext *avctx, void *data, avctx->colorspace = AVCOL_SPC_YCGCO; s->current_pic = (s->current_pic + 1) % 6; - ret = av_frame_ref(data, frame); + ret = av_frame_ref(rframe, frame); if (ret < 0) return ret; *got_frame = 1; @@ -1339,16 +1340,16 @@ static av_cold int mobiclip_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_mobiclip_decoder = { - .name = "mobiclip", - .long_name = NULL_IF_CONFIG_SMALL("MobiClip Video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MOBICLIP, +const FFCodec ff_mobiclip_decoder = { + .p.name = "mobiclip", + .p.long_name = NULL_IF_CONFIG_SMALL("MobiClip Video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MOBICLIP, .priv_data_size = sizeof(MobiClipContext), .init = mobiclip_init, - .decode = mobiclip_decode, + FF_CODEC_DECODE_CB(mobiclip_decode), .flush = mobiclip_flush, .close = mobiclip_close, - .capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/motion_est.c b/libavcodec/motion_est.c index b79e22c42..62c5b2836 100644 --- a/libavcodec/motion_est.c +++ b/libavcodec/motion_est.c @@ -32,11 +32,10 @@ #include #include "avcodec.h" -#include "internal.h" #include "mathops.h" #include "motion_est.h" #include "mpegutils.h" -#include "mpegvideo.h" +#include "mpegvideoenc.h" #define P_LEFT P[1] #define P_TOP P[2] @@ -681,7 +680,7 @@ static inline int h263_mv4_search(MpegEncContext *s, int mx, int my, int shift) if (s->mecc.me_sub_cmp[0] != s->mecc.mb_cmp[0]) { dmin_sum += s->mecc.mb_cmp[0](s, - s->new_picture.f->data[0] + + s->new_picture->data[0] + s->mb_x * 16 + s->mb_y * 16 * stride, c->scratchpad, stride, 16); } @@ -705,8 +704,8 @@ static inline int h263_mv4_search(MpegEncContext *s, int mx, int my, int shift) s->hdsp.put_pixels_tab [1][dxy](c->scratchpad + 8, s->last_picture.f->data[2] + offset, s->uvlinesize, 8); } - dmin_sum += s->mecc.mb_cmp[1](s, s->new_picture.f->data[1] + s->mb_x * 8 + s->mb_y * 8 * s->uvlinesize, c->scratchpad, s->uvlinesize, 8); - dmin_sum += s->mecc.mb_cmp[1](s, s->new_picture.f->data[2] + s->mb_x * 8 + s->mb_y * 8 * s->uvlinesize, c->scratchpad + 8, s->uvlinesize, 8); + dmin_sum += s->mecc.mb_cmp[1](s, s->new_picture->data[1] + s->mb_x * 8 + s->mb_y * 8 * s->uvlinesize, c->scratchpad, s->uvlinesize, 8); + dmin_sum += s->mecc.mb_cmp[1](s, s->new_picture->data[2] + s->mb_x * 8 + s->mb_y * 8 * s->uvlinesize, c->scratchpad + 8, s->uvlinesize, 8); } c->pred_x= mx; @@ -895,7 +894,7 @@ void ff_estimate_p_frame_motion(MpegEncContext * s, int mb_type=0; Picture * const pic= &s->current_picture; - init_ref(c, s->new_picture.f->data, s->last_picture.f->data, NULL, 16*mb_x, 16*mb_y, 0); + init_ref(c, s->new_picture->data, s->last_picture.f->data, NULL, 16*mb_x, 16*mb_y, 0); av_assert0(s->quarter_sample==0 || s->quarter_sample==1); av_assert0(s->linesize == c->stride); @@ -1066,7 +1065,7 @@ int ff_pre_estimate_p_frame_motion(MpegEncContext * s, int P[10][2]; const int shift= 1+s->quarter_sample; const int xy= mb_x + mb_y*s->mb_stride; - init_ref(c, s->new_picture.f->data, s->last_picture.f->data, NULL, 16*mb_x, 16*mb_y, 0); + init_ref(c, s->new_picture->data, s->last_picture.f->data, NULL, 16*mb_x, 16*mb_y, 0); av_assert0(s->quarter_sample==0 || s->quarter_sample==1); @@ -1495,7 +1494,7 @@ void ff_estimate_b_frame_motion(MpegEncContext * s, int fmin, bmin, dmin, fbmin, bimin, fimin; int type=0; const int xy = mb_y*s->mb_stride + mb_x; - init_ref(c, s->new_picture.f->data, s->last_picture.f->data, + init_ref(c, s->new_picture->data, s->last_picture.f->data, s->next_picture.f->data, 16 * mb_x, 16 * mb_y, 2); get_limits(s, 16*mb_x, 16*mb_y); @@ -1595,7 +1594,7 @@ void ff_estimate_b_frame_motion(MpegEncContext * s, } /* find best f_code for ME which do unlimited searches */ -int ff_get_best_fcode(MpegEncContext * s, int16_t (*mv_table)[2], int type) +int ff_get_best_fcode(MpegEncContext * s, const int16_t (*mv_table)[2], int type) { if (s->motion_est != FF_ME_ZERO) { int score[8]; diff --git a/libavcodec/motion_est.h b/libavcodec/motion_est.h index 5742e5148..d0950bf7e 100644 --- a/libavcodec/motion_est.h +++ b/libavcodec/motion_est.h @@ -118,14 +118,14 @@ int ff_pre_estimate_p_frame_motion(struct MpegEncContext *s, int ff_epzs_motion_search(struct MpegEncContext *s, int *mx_ptr, int *my_ptr, int P[10][2], int src_index, int ref_index, - int16_t (*last_mv)[2], int ref_mv_scale, int size, - int h); + const int16_t (*last_mv)[2], int ref_mv_scale, + int size, int h); int ff_get_mb_score(struct MpegEncContext *s, int mx, int my, int src_index, int ref_index, int size, int h, int add_rate); int ff_get_best_fcode(struct MpegEncContext *s, - int16_t (*mv_table)[2], int type); + const int16_t (*mv_table)[2], int type); void ff_fix_long_p_mvs(struct MpegEncContext *s, int type); void ff_fix_long_mvs(struct MpegEncContext *s, uint8_t *field_select_table, diff --git a/libavcodec/motion_est_template.c b/libavcodec/motion_est_template.c index 6ab0ea13d..f3e94b7eb 100644 --- a/libavcodec/motion_est_template.c +++ b/libavcodec/motion_est_template.c @@ -858,7 +858,7 @@ static av_always_inline int diamond_search(MpegEncContext * s, int *best, int dm optimal mv. */ static av_always_inline int epzs_motion_search_internal(MpegEncContext * s, int *mx_ptr, int *my_ptr, - int P[10][2], int src_index, int ref_index, int16_t (*last_mv)[2], + int P[10][2], int src_index, int ref_index, const int16_t (*last_mv)[2], int ref_mv_scale, int flags, int size, int h) { MotionEstContext * const c= &s->me; @@ -976,7 +976,7 @@ static av_always_inline int epzs_motion_search_internal(MpegEncContext * s, int //this function is dedicated to the brain damaged gcc int ff_epzs_motion_search(MpegEncContext *s, int *mx_ptr, int *my_ptr, int P[10][2], int src_index, int ref_index, - int16_t (*last_mv)[2], int ref_mv_scale, + const int16_t (*last_mv)[2], int ref_mv_scale, int size, int h) { MotionEstContext * const c= &s->me; @@ -992,7 +992,7 @@ int ff_epzs_motion_search(MpegEncContext *s, int *mx_ptr, int *my_ptr, static int epzs_motion_search2(MpegEncContext * s, int *mx_ptr, int *my_ptr, int P[10][2], - int src_index, int ref_index, int16_t (*last_mv)[2], + int src_index, int ref_index, const int16_t (*last_mv)[2], int ref_mv_scale, const int size) { MotionEstContext * const c= &s->me; diff --git a/libavcodec/motionpixels.c b/libavcodec/motionpixels.c index 7ac963453..29454fd24 100644 --- a/libavcodec/motionpixels.c +++ b/libavcodec/motionpixels.c @@ -26,6 +26,7 @@ #include "avcodec.h" #include "get_bits.h" #include "bswapdsp.h" +#include "codec_internal.h" #include "internal.h" #define MAX_HUFF_CODES 16 @@ -277,9 +278,8 @@ static void mp_decode_frame_helper(MotionPixelsContext *mp, GetBitContext *gb) mp_decode_line(mp, gb, y); } -static int mp_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int mp_decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; @@ -339,21 +339,21 @@ static int mp_decode_frame(AVCodecContext *avctx, ff_free_vlc(&mp->vlc); end: - if ((ret = av_frame_ref(data, mp->frame)) < 0) + if ((ret = av_frame_ref(rframe, mp->frame)) < 0) return ret; *got_frame = 1; return buf_size; } -const AVCodec ff_motionpixels_decoder = { - .name = "motionpixels", - .long_name = NULL_IF_CONFIG_SMALL("Motion Pixels video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MOTIONPIXELS, +const FFCodec ff_motionpixels_decoder = { + .p.name = "motionpixels", + .p.long_name = NULL_IF_CONFIG_SMALL("Motion Pixels video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MOTIONPIXELS, .priv_data_size = sizeof(MotionPixelsContext), .init = mp_decode_init, .close = mp_decode_end, - .decode = mp_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(mp_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/movsub_bsf.c b/libavcodec/movsub_bsf.c index 6e29fa8e5..a5125c7af 100644 --- a/libavcodec/movsub_bsf.c +++ b/libavcodec/movsub_bsf.c @@ -57,8 +57,8 @@ fail: return ret; } -const AVBitStreamFilter ff_text2movsub_bsf = { - .name = "text2movsub", +const FFBitStreamFilter ff_text2movsub_bsf = { + .p.name = "text2movsub", .filter = text2movsub, }; @@ -81,7 +81,7 @@ static int mov2textsub(AVBSFContext *ctx, AVPacket *pkt) return 0; } -const AVBitStreamFilter ff_mov2textsub_bsf = { - .name = "mov2textsub", +const FFBitStreamFilter ff_mov2textsub_bsf = { + .p.name = "mov2textsub", .filter = mov2textsub, }; diff --git a/libavcodec/movtextdec.c b/libavcodec/movtextdec.c index dc30fdc69..70162b488 100644 --- a/libavcodec/movtextdec.c +++ b/libavcodec/movtextdec.c @@ -28,7 +28,7 @@ #include "libavutil/intreadwrite.h" #include "libavutil/mem.h" #include "bytestream.h" -#include "internal.h" +#include "codec_internal.h" #define STYLE_FLAG_BOLD (1<<0) #define STYLE_FLAG_ITALIC (1<<1) @@ -472,10 +472,9 @@ static int mov_text_init(AVCodecContext *avctx) { return ff_ass_subtitle_header_default(avctx); } -static int mov_text_decode_frame(AVCodecContext *avctx, - void *data, int *got_sub_ptr, AVPacket *avpkt) +static int mov_text_decode_frame(AVCodecContext *avctx, AVSubtitle *sub, + int *got_sub_ptr, const AVPacket *avpkt) { - AVSubtitle *sub = data; MovTextContext *m = avctx->priv_data; int ret; AVBPrint buf; @@ -592,15 +591,15 @@ static const AVClass mov_text_decoder_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_movtext_decoder = { - .name = "mov_text", - .long_name = NULL_IF_CONFIG_SMALL("3GPP Timed Text subtitle"), - .type = AVMEDIA_TYPE_SUBTITLE, - .id = AV_CODEC_ID_MOV_TEXT, +const FFCodec ff_movtext_decoder = { + .p.name = "mov_text", + .p.long_name = NULL_IF_CONFIG_SMALL("3GPP Timed Text subtitle"), + .p.type = AVMEDIA_TYPE_SUBTITLE, + .p.id = AV_CODEC_ID_MOV_TEXT, .priv_data_size = sizeof(MovTextContext), - .priv_class = &mov_text_decoder_class, + .p.priv_class = &mov_text_decoder_class, .init = mov_text_init, - .decode = mov_text_decode_frame, + FF_CODEC_DECODE_SUB_CB(mov_text_decode_frame), .close = mov_text_decode_close, .flush = mov_text_flush, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, diff --git a/libavcodec/movtextenc.c b/libavcodec/movtextenc.c index 221cd76fe..728338f2c 100644 --- a/libavcodec/movtextenc.c +++ b/libavcodec/movtextenc.c @@ -29,7 +29,7 @@ #include "ass_split.h" #include "ass.h" #include "bytestream.h" -#include "internal.h" +#include "codec_internal.h" #define STYLE_FLAG_BOLD (1<<0) #define STYLE_FLAG_ITALIC (1<<1) @@ -699,15 +699,15 @@ static const AVClass mov_text_encoder_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_movtext_encoder = { - .name = "mov_text", - .long_name = NULL_IF_CONFIG_SMALL("3GPP Timed Text subtitle"), - .type = AVMEDIA_TYPE_SUBTITLE, - .id = AV_CODEC_ID_MOV_TEXT, +const FFCodec ff_movtext_encoder = { + .p.name = "mov_text", + .p.long_name = NULL_IF_CONFIG_SMALL("3GPP Timed Text subtitle"), + .p.type = AVMEDIA_TYPE_SUBTITLE, + .p.id = AV_CODEC_ID_MOV_TEXT, .priv_data_size = sizeof(MovTextContext), - .priv_class = &mov_text_encoder_class, + .p.priv_class = &mov_text_encoder_class, .init = mov_text_encode_init, - .encode_sub = mov_text_encode_frame, + FF_CODEC_ENCODE_SUB_CB(mov_text_encode_frame), .close = mov_text_encode_close, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/mp3_header_decompress_bsf.c b/libavcodec/mp3_header_decompress_bsf.c index ebf6bde1c..a177029fe 100644 --- a/libavcodec/mp3_header_decompress_bsf.c +++ b/libavcodec/mp3_header_decompress_bsf.c @@ -98,7 +98,7 @@ static int mp3_header_decompress(AVBSFContext *ctx, AVPacket *out) } memcpy(out->data + frame_size - buf_size, buf, buf_size + AV_INPUT_BUFFER_PADDING_SIZE); - if(ctx->par_in->channels==2){ + if (ctx->par_in->ch_layout.nb_channels == 2){ uint8_t *p= out->data + frame_size - buf_size; if(lsf){ FFSWAP(int, p[1], p[2]); @@ -123,8 +123,8 @@ static const enum AVCodecID codec_ids[] = { AV_CODEC_ID_MP3, AV_CODEC_ID_NONE, }; -const AVBitStreamFilter ff_mp3_header_decompress_bsf = { - .name = "mp3decomp", - .filter = mp3_header_decompress, - .codec_ids = codec_ids, +const FFBitStreamFilter ff_mp3_header_decompress_bsf = { + .p.name = "mp3decomp", + .p.codec_ids = codec_ids, + .filter = mp3_header_decompress, }; diff --git a/libavcodec/mpc7.c b/libavcodec/mpc7.c index c1a63203d..837507ba5 100644 --- a/libavcodec/mpc7.c +++ b/libavcodec/mpc7.c @@ -32,6 +32,7 @@ #include "libavutil/thread.h" #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" #include "mpegaudiodsp.h" @@ -43,7 +44,7 @@ static VLC scfi_vlc, dscf_vlc, hdr_vlc, quant_vlc[MPC7_QUANT_VLC_TABLES][2]; static av_cold void mpc7_init_static(void) { - static VLC_TYPE quant_tables[7224][2]; + static VLCElem quant_tables[7224]; const uint8_t *raw_quant_table = mpc7_quant_vlcs; INIT_VLC_STATIC_FROM_LENGTHS(&scfi_vlc, MPC7_SCFI_BITS, MPC7_SCFI_SIZE, @@ -79,8 +80,8 @@ static av_cold int mpc7_decode_init(AVCodecContext * avctx) LOCAL_ALIGNED_16(uint8_t, buf, [16]); /* Musepack SV7 is always stereo */ - if (avctx->channels != 2) { - avpriv_request_sample(avctx, "%d channels", avctx->channels); + if (avctx->ch_layout.nb_channels != 2) { + avpriv_request_sample(avctx, "%d channels", avctx->ch_layout.nb_channels); return AVERROR_PATCHWELCOME; } @@ -110,7 +111,8 @@ static av_cold int mpc7_decode_init(AVCodecContext * avctx) c->frames_to_skip = 0; avctx->sample_fmt = AV_SAMPLE_FMT_S16P; - avctx->channel_layout = AV_CH_LAYOUT_STEREO; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; ff_thread_once(&init_static_once, mpc7_init_static); @@ -170,10 +172,9 @@ static int get_scale_idx(GetBitContext *gb, int ref) return ref + t; } -static int mpc7_decode_frame(AVCodecContext * avctx, void *data, +static int mpc7_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size; MPCContext *c = avctx->priv_data; @@ -308,18 +309,18 @@ static av_cold int mpc7_decode_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_mpc7_decoder = { - .name = "mpc7", - .long_name = NULL_IF_CONFIG_SMALL("Musepack SV7"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_MUSEPACK7, +const FFCodec ff_mpc7_decoder = { + .p.name = "mpc7", + .p.long_name = NULL_IF_CONFIG_SMALL("Musepack SV7"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_MUSEPACK7, .priv_data_size = sizeof(MPCContext), .init = mpc7_decode_init, .close = mpc7_decode_close, - .decode = mpc7_decode_frame, + FF_CODEC_DECODE_CB(mpc7_decode_frame), .flush = mpc7_decode_flush, - .capabilities = AV_CODEC_CAP_DR1, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, + .p.capabilities = AV_CODEC_CAP_DR1, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/mpc8.c b/libavcodec/mpc8.c index ae0709333..9d084e166 100644 --- a/libavcodec/mpc8.c +++ b/libavcodec/mpc8.c @@ -29,6 +29,7 @@ #include "libavutil/lfg.h" #include "libavutil/thread.h" #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" #include "mpegaudiodsp.h" @@ -91,7 +92,7 @@ static av_cold void build_vlc(VLC *vlc, unsigned *buf_offset, const uint8_t codes_counts[16], const uint8_t **syms, int offset) { - static VLC_TYPE vlc_buf[9296][2]; + static VLCElem vlc_buf[9296]; uint8_t len[MPC8_MAX_VLC_SIZE]; unsigned num = 0; @@ -169,18 +170,17 @@ static av_cold int mpc8_decode_init(AVCodecContext * avctx) c->frames = 1 << (get_bits(&gb, 3) * 2); avctx->sample_fmt = AV_SAMPLE_FMT_S16P; - avctx->channel_layout = (channels==2) ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO; - avctx->channels = channels; + av_channel_layout_uninit(&avctx->ch_layout); + av_channel_layout_default(&avctx->ch_layout, channels); ff_thread_once(&init_static_once, mpc8_init_static); return 0; } -static int mpc8_decode_frame(AVCodecContext * avctx, void *data, +static int mpc8_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; MPCContext *c = avctx->priv_data; @@ -358,7 +358,7 @@ static int mpc8_decode_frame(AVCodecContext * avctx, void *data, ff_mpc_dequantize_and_synth(c, maxband - 1, (int16_t **)frame->extended_data, - avctx->channels); + avctx->ch_layout.nb_channels); c->cur_frame++; @@ -383,17 +383,17 @@ static av_cold void mpc8_decode_flush(AVCodecContext *avctx) c->cur_frame = 0; } -const AVCodec ff_mpc8_decoder = { - .name = "mpc8", - .long_name = NULL_IF_CONFIG_SMALL("Musepack SV8"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_MUSEPACK8, +const FFCodec ff_mpc8_decoder = { + .p.name = "mpc8", + .p.long_name = NULL_IF_CONFIG_SMALL("Musepack SV8"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_MUSEPACK8, .priv_data_size = sizeof(MPCContext), .init = mpc8_decode_init, - .decode = mpc8_decode_frame, + FF_CODEC_DECODE_CB(mpc8_decode_frame), .flush = mpc8_decode_flush, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/mpeg12.c b/libavcodec/mpeg12.c index 58e03c05d..d78e25a77 100644 --- a/libavcodec/mpeg12.c +++ b/libavcodec/mpeg12.c @@ -29,18 +29,15 @@ #include "libavutil/attributes.h" #include "libavutil/avassert.h" -#include "libavutil/timecode.h" #include "libavutil/thread.h" -#include "internal.h" #include "avcodec.h" #include "mpegvideo.h" -#include "error_resilience.h" #include "mpeg12.h" #include "mpeg12data.h" +#include "mpeg12dec.h" #include "mpegvideodata.h" -#include "bytestream.h" -#include "thread.h" +#include "startcode.h" static const uint8_t table_mb_ptype[7][2] = { { 3, 5 }, // 0x01 MB_INTRA @@ -69,14 +66,14 @@ static const uint8_t table_mb_btype[11][2] = { av_cold void ff_init_2d_vlc_rl(RLTable *rl, unsigned static_size, int flags) { int i; - VLC_TYPE table[680][2] = {{0}}; + VLCElem table[680] = { 0 }; VLC vlc = { .table = table, .table_allocated = static_size }; av_assert0(static_size <= FF_ARRAY_ELEMS(table)); init_vlc(&vlc, TEX_VLC_BITS, rl->n + 2, &rl->table_vlc[0][1], 4, 2, &rl->table_vlc[0][0], 4, 2, INIT_VLC_USE_NEW_STATIC | flags); for (i = 0; i < vlc.table_size; i++) { - int code = vlc.table[i][0]; - int len = vlc.table[i][1]; + int code = vlc.table[i].sym; + int len = vlc.table[i].len; int level, run; if (len == 0) { // illegal code @@ -238,7 +235,7 @@ int ff_mpeg1_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size, int ff_mpeg1_decode_block_intra(GetBitContext *gb, const uint16_t *quant_matrix, - uint8_t *const scantable, int last_dc[3], + const uint8_t *scantable, int last_dc[3], int16_t *block, int index, int qscale) { int dc, diff, i = 0, component; diff --git a/libavcodec/mpeg12.h b/libavcodec/mpeg12.h index fb2b37e7c..e0406b32d 100644 --- a/libavcodec/mpeg12.h +++ b/libavcodec/mpeg12.h @@ -22,7 +22,6 @@ #ifndef AVCODEC_MPEG12_H #define AVCODEC_MPEG12_H -#include "mpeg12vlc.h" #include "mpegvideo.h" /* Start codes. */ @@ -37,49 +36,11 @@ void ff_mpeg12_common_init(MpegEncContext *s); -#define INIT_2D_VLC_RL(rl, static_size, flags)\ -{\ - static RL_VLC_ELEM rl_vlc_table[static_size];\ - rl.rl_vlc[0] = rl_vlc_table;\ - ff_init_2d_vlc_rl(&rl, static_size, flags);\ -} - -void ff_init_2d_vlc_rl(RLTable *rl, unsigned static_size, int flags); -void ff_mpeg1_init_uni_ac_vlc(const RLTable *rl, uint8_t *uni_ac_vlc_len); - -static inline int decode_dc(GetBitContext *gb, int component) -{ - int code, diff; - - if (component == 0) { - code = get_vlc2(gb, ff_dc_lum_vlc.table, DC_VLC_BITS, 2); - } else { - code = get_vlc2(gb, ff_dc_chroma_vlc.table, DC_VLC_BITS, 2); - } - if (code == 0) { - diff = 0; - } else { - diff = get_xbits(gb, code); - } - return diff; -} - -int ff_mpeg1_decode_block_intra(GetBitContext *gb, - const uint16_t *quant_matrix, - uint8_t *const scantable, int last_dc[3], - int16_t *block, int index, int qscale); - void ff_mpeg1_clean_buffers(MpegEncContext *s); #if FF_API_FLAG_TRUNCATED int ff_mpeg1_find_frame_end(ParseContext *pc, const uint8_t *buf, int buf_size, AVCodecParserContext *s); #endif -void ff_mpeg1_encode_picture_header(MpegEncContext *s, int picture_number); -void ff_mpeg1_encode_mb(MpegEncContext *s, int16_t block[8][64], - int motion_x, int motion_y); -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); diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c index cf06af0a7..e9bde48f7 100644 --- a/libavcodec/mpeg12dec.c +++ b/libavcodec/mpeg12dec.c @@ -25,6 +25,8 @@ * MPEG-1/2 decoder */ +#include "config_components.h" + #define UNCHECKED_BITSTREAM_READER 1 #include @@ -32,11 +34,12 @@ #include "libavutil/imgutils.h" #include "libavutil/internal.h" #include "libavutil/mem_internal.h" +#include "libavutil/reverse.h" #include "libavutil/stereo3d.h" -#include "libavutil/video_enc_params.h" +#include "libavutil/timecode.h" #include "avcodec.h" -#include "bytestream.h" +#include "codec_internal.h" #include "error_resilience.h" #include "hwconfig.h" #include "idctdsp.h" @@ -44,12 +47,14 @@ #include "mpeg_er.h" #include "mpeg12.h" #include "mpeg12data.h" +#include "mpeg12dec.h" #include "mpegutils.h" #include "mpegvideo.h" #include "mpegvideodata.h" +#include "mpegvideodec.h" #include "profiles.h" +#include "startcode.h" #include "thread.h" -#include "xvmc_internal.h" #define A53_MAX_CC_COUNT 2000 @@ -64,15 +69,18 @@ typedef struct Mpeg1Context { uint8_t afd; int has_afd; int slice_count; + unsigned aspect_ratio_info; AVRational save_aspect; int save_width, save_height, save_progressive_seq; int rc_buffer_size; AVRational frame_rate_ext; /* MPEG-2 specific framerate modificator */ + unsigned frame_rate_index; int sync; /* Did we reach a sync point like a GOP/SEQ/KEYFrame? */ int closed_gop; int tmpgexs; int first_slice; int extradata_decoded; + int64_t timecode_frame_start; /*< GOP timecode frame start number, in non drop frame format */ } Mpeg1Context; #define MB_TYPE_ZERO_MV 0x20000000 @@ -758,9 +766,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 1, we memcpy blocks in xvmcvideo - if ((CONFIG_MPEG1_XVMC_HWACCEL || CONFIG_MPEG2_XVMC_HWACCEL) && s->pack_pblocks) - ff_xvmc_pack_pblocks(s, -1); // inter are always full blocks if (s->codec_id == AV_CODEC_ID_MPEG2VIDEO) { if (s->avctx->flags2 & AV_CODEC_FLAG2_FAST) { @@ -989,10 +994,6 @@ static int mpeg_decode_mb(MpegEncContext *s, int16_t block[12][64]) return AVERROR_INVALIDDATA; } - // if 1, we memcpy blocks in xvmcvideo - if ((CONFIG_MPEG1_XVMC_HWACCEL || CONFIG_MPEG2_XVMC_HWACCEL) && s->pack_pblocks) - ff_xvmc_pack_pblocks(s, cbp); - if (s->codec_id == AV_CODEC_ID_MPEG2VIDEO) { if (s->avctx->flags2 & AV_CODEC_FLAG2_FAST) { for (i = 0; i < 6; i++) { @@ -1065,7 +1066,6 @@ static av_cold int mpeg_decode_init(AVCodecContext *avctx) s2->chroma_format = 1; s->mpeg_enc_ctx_allocated = 0; - s->mpeg_enc_ctx.picture_number = 0; s->repeat_field = 0; avctx->color_range = AVCOL_RANGE_MPEG; return 0; @@ -1091,9 +1091,6 @@ static int mpeg_decode_update_thread_context(AVCodecContext *avctx, if (!ctx->mpeg_enc_ctx_allocated) memcpy(s + 1, s1 + 1, sizeof(Mpeg1Context) - sizeof(MpegEncContext)); - if (!(s->pict_type == AV_PICTURE_TYPE_B || s->low_delay)) - s->picture_number++; - return 0; } #endif @@ -1114,9 +1111,6 @@ 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 #if CONFIG_MPEG1_VDPAU_HWACCEL AV_PIX_FMT_VDPAU, #endif @@ -1128,9 +1122,6 @@ 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 #if CONFIG_MPEG2_VDPAU_HWACCEL AV_PIX_FMT_VDPAU, #endif @@ -1182,21 +1173,6 @@ static enum AVPixelFormat mpeg_get_pixelformat(AVCodecContext *avctx) return ff_thread_get_format(avctx, pix_fmts); } -static void setup_hwaccel_for_pixfmt(AVCodecContext *avctx) -{ - // until then pix_fmt may be changed right after codec init - if (avctx->hwaccel) - if (avctx->idct_algo == FF_IDCT_AUTO) - avctx->idct_algo = FF_IDCT_NONE; - - if (avctx->hwaccel && avctx->pix_fmt == AV_PIX_FMT_XVMC) { - Mpeg1Context *s1 = avctx->priv_data; - MpegEncContext *s = &s1->mpeg_enc_ctx; - - s->pack_pblocks = 1; - } -} - /* Call this function when we know all parameters. * It may be called in different places for MPEG-1 and MPEG-2. */ static int mpeg_decode_postinit(AVCodecContext *avctx) @@ -1208,13 +1184,13 @@ static int mpeg_decode_postinit(AVCodecContext *avctx) if (avctx->codec_id == AV_CODEC_ID_MPEG1VIDEO) { // MPEG-1 aspect - AVRational aspect_inv = av_d2q(ff_mpeg1_aspect[s->aspect_ratio_info], 255); + AVRational aspect_inv = av_d2q(ff_mpeg1_aspect[s1->aspect_ratio_info], 255); avctx->sample_aspect_ratio = (AVRational) { aspect_inv.den, aspect_inv.num }; } else { // MPEG-2 // MPEG-2 aspect - if (s->aspect_ratio_info > 1) { + if (s1->aspect_ratio_info > 1) { AVRational dar = - av_mul_q(av_div_q(ff_mpeg2_aspect[s->aspect_ratio_info], + av_mul_q(av_div_q(ff_mpeg2_aspect[s1->aspect_ratio_info], (AVRational) { s1->pan_scan.width, s1->pan_scan.height }), (AVRational) { s->width, s->height }); @@ -1227,25 +1203,25 @@ static int mpeg_decode_postinit(AVCodecContext *avctx) (av_cmp_q(dar, (AVRational) { 4, 3 }) && av_cmp_q(dar, (AVRational) { 16, 9 }))) { s->avctx->sample_aspect_ratio = - av_div_q(ff_mpeg2_aspect[s->aspect_ratio_info], + av_div_q(ff_mpeg2_aspect[s1->aspect_ratio_info], (AVRational) { s->width, s->height }); } else { s->avctx->sample_aspect_ratio = - av_div_q(ff_mpeg2_aspect[s->aspect_ratio_info], + av_div_q(ff_mpeg2_aspect[s1->aspect_ratio_info], (AVRational) { s1->pan_scan.width, s1->pan_scan.height }); // issue1613 4/3 16/9 -> 16/9 // res_change_ffmpeg_aspect.ts 4/3 225/44 ->4/3 // widescreen-issue562.mpg 4/3 16/9 -> 16/9 // s->avctx->sample_aspect_ratio = av_mul_q(s->avctx->sample_aspect_ratio, (AVRational) {s->width, s->height}); ff_dlog(avctx, "aspect A %d/%d\n", - ff_mpeg2_aspect[s->aspect_ratio_info].num, - ff_mpeg2_aspect[s->aspect_ratio_info].den); + ff_mpeg2_aspect[s1->aspect_ratio_info].num, + ff_mpeg2_aspect[s1->aspect_ratio_info].den); ff_dlog(avctx, "aspect B %d/%d\n", s->avctx->sample_aspect_ratio.num, s->avctx->sample_aspect_ratio.den); } } else { s->avctx->sample_aspect_ratio = - ff_mpeg2_aspect[s->aspect_ratio_info]; + ff_mpeg2_aspect[s1->aspect_ratio_info]; } } // MPEG-2 @@ -1298,7 +1274,7 @@ static int mpeg_decode_postinit(AVCodecContext *avctx) if (avctx->codec_id == AV_CODEC_ID_MPEG1VIDEO) { // MPEG-1 fps - avctx->framerate = ff_mpeg12_frame_rate_tab[s->frame_rate_index]; + avctx->framerate = ff_mpeg12_frame_rate_tab[s1->frame_rate_index]; avctx->ticks_per_frame = 1; avctx->chroma_sample_location = AVCHROMA_LOC_CENTER; @@ -1306,8 +1282,8 @@ static int mpeg_decode_postinit(AVCodecContext *avctx) // MPEG-2 fps av_reduce(&s->avctx->framerate.num, &s->avctx->framerate.den, - ff_mpeg12_frame_rate_tab[s->frame_rate_index].num * s1->frame_rate_ext.num, - ff_mpeg12_frame_rate_tab[s->frame_rate_index].den * s1->frame_rate_ext.den, + ff_mpeg12_frame_rate_tab[s1->frame_rate_index].num * s1->frame_rate_ext.num, + ff_mpeg12_frame_rate_tab[s1->frame_rate_index].den * s1->frame_rate_ext.den, 1 << 30); avctx->ticks_per_frame = 2; @@ -1320,7 +1296,6 @@ static int mpeg_decode_postinit(AVCodecContext *avctx) } // MPEG-2 avctx->pix_fmt = mpeg_get_pixelformat(avctx); - setup_hwaccel_for_pixfmt(avctx); /* Quantization matrices may need reordering * if DCT permutation is changed. */ @@ -1789,13 +1764,13 @@ static int mpeg_decode_slice(MpegEncContext *s, int mb_y, if (s->mb_y == 0 && s->mb_x == 0 && (s->first_field || s->picture_structure == PICT_FRAME)) { if (s->avctx->debug & FF_DEBUG_PICT_INFO) { av_log(s->avctx, AV_LOG_DEBUG, - "qp:%d fc:%2d%2d%2d%2d %s %s %s %s %s dc:%d pstruct:%d fdct:%d cmv:%d qtype:%d ivlc:%d rff:%d %s\n", + "qp:%d fc:%2d%2d%2d%2d %c %s %s %s %s dc:%d pstruct:%d fdct:%d cmv:%d qtype:%d ivlc:%d rff:%d %s\n", s->qscale, s->mpeg_f_code[0][0], s->mpeg_f_code[0][1], s->mpeg_f_code[1][0], s->mpeg_f_code[1][1], - s->pict_type == AV_PICTURE_TYPE_I ? "I" : - (s->pict_type == AV_PICTURE_TYPE_P ? "P" : - (s->pict_type == AV_PICTURE_TYPE_B ? "B" : "S")), + s->pict_type == AV_PICTURE_TYPE_I ? 'I' : + (s->pict_type == AV_PICTURE_TYPE_P ? 'P' : + (s->pict_type == AV_PICTURE_TYPE_B ? 'B' : 'S')), s->progressive_sequence ? "ps" : "", s->progressive_frame ? "pf" : "", s->alternate_scan ? "alt" : "", @@ -1808,10 +1783,6 @@ static int mpeg_decode_slice(MpegEncContext *s, int mb_y, } for (;;) { - // If 1, we memcpy blocks in xvmcvideo. - if ((CONFIG_MPEG1_XVMC_HWACCEL || CONFIG_MPEG2_XVMC_HWACCEL) && s->pack_pblocks) - ff_xvmc_init_block(s); // set s->block - if ((ret = mpeg_decode_mb(s, s->block)) < 0) return ret; @@ -2069,18 +2040,15 @@ static int slice_end(AVCodecContext *avctx, AVFrame *pict) if (ret < 0) return ret; ff_print_debug_info(s, s->current_picture_ptr, pict); - ff_mpv_export_qp_table(s, pict, s->current_picture_ptr, FF_QSCALE_TYPE_MPEG2); + ff_mpv_export_qp_table(s, pict, s->current_picture_ptr, FF_MPV_QSCALE_TYPE_MPEG2); } else { - if (avctx->active_thread_type & FF_THREAD_FRAME) - s->picture_number++; /* latency of 1 frame for I- and P-frames */ - /* XXX: use another variable than picture_number */ if (s->last_picture_ptr) { int ret = av_frame_ref(pict, s->last_picture_ptr->f); if (ret < 0) return ret; ff_print_debug_info(s, s->last_picture_ptr, pict); - ff_mpv_export_qp_table(s, pict, s->last_picture_ptr, FF_QSCALE_TYPE_MPEG2); + ff_mpv_export_qp_table(s, pict, s->last_picture_ptr, FF_MPV_QSCALE_TYPE_MPEG2); } } @@ -2108,17 +2076,17 @@ static int mpeg1_decode_sequence(AVCodecContext *avctx, if (avctx->err_recognition & (AV_EF_BITSTREAM | AV_EF_COMPLIANT)) return AVERROR_INVALIDDATA; } - s->aspect_ratio_info = get_bits(&s->gb, 4); - if (s->aspect_ratio_info == 0) { + s1->aspect_ratio_info = get_bits(&s->gb, 4); + if (s1->aspect_ratio_info == 0) { av_log(avctx, AV_LOG_ERROR, "aspect ratio has forbidden 0 value\n"); if (avctx->err_recognition & (AV_EF_BITSTREAM | AV_EF_COMPLIANT)) return AVERROR_INVALIDDATA; } - s->frame_rate_index = get_bits(&s->gb, 4); - if (s->frame_rate_index == 0 || s->frame_rate_index > 13) { + s1->frame_rate_index = get_bits(&s->gb, 4); + if (s1->frame_rate_index == 0 || s1->frame_rate_index > 13) { av_log(avctx, AV_LOG_WARNING, - "frame_rate_index %d is invalid\n", s->frame_rate_index); - s->frame_rate_index = 1; + "frame_rate_index %d is invalid\n", s1->frame_rate_index); + s1->frame_rate_index = 1; } s->bit_rate = get_bits(&s->gb, 18) * 400LL; if (check_marker(s->avctx, &s->gb, "in sequence header") == 0) { @@ -2168,13 +2136,12 @@ static int mpeg1_decode_sequence(AVCodecContext *avctx, s->codec_id = s->avctx->codec_id = AV_CODEC_ID_MPEG1VIDEO; s->out_format = FMT_MPEG1; - s->swap_uv = 0; // AFAIK VCR2 does not have SEQ_HEADER if (s->avctx->flags & AV_CODEC_FLAG_LOW_DELAY) s->low_delay = 1; if (s->avctx->debug & FF_DEBUG_PICT_INFO) av_log(s->avctx, AV_LOG_DEBUG, "vbv buffer: %d, bitrate:%"PRId64", aspect_ratio_info: %d \n", - s1->rc_buffer_size, s->bit_rate, s->aspect_ratio_info); + s1->rc_buffer_size, s->bit_rate, s1->aspect_ratio_info); return 0; } @@ -2197,7 +2164,6 @@ static int vcr2_init_sequence(AVCodecContext *avctx) s->low_delay = 1; avctx->pix_fmt = mpeg_get_pixelformat(avctx); - setup_hwaccel_for_pixfmt(avctx); ff_mpv_idct_init(s); if ((ret = ff_mpv_common_init(s)) < 0) @@ -2224,7 +2190,6 @@ static int vcr2_init_sequence(AVCodecContext *avctx) if (s->codec_tag == AV_RL32("BW10")) { s->codec_id = s->avctx->codec_id = AV_CODEC_ID_MPEG1VIDEO; } else { - s->swap_uv = 1; // in case of xvmc we need to swap uv for each MB s->codec_id = s->avctx->codec_id = AV_CODEC_ID_MPEG2VIDEO; } s1->save_width = s->width; @@ -2448,7 +2413,7 @@ static void mpeg_decode_gop(AVCodecContext *avctx, init_get_bits(&s->gb, buf, buf_size * 8); - tc = s-> timecode_frame_start = get_bits(&s->gb, 25); + tc = s1->timecode_frame_start = get_bits(&s->gb, 25); s1->closed_gop = get_bits1(&s->gb); /* broken_link indicates that after editing the @@ -2797,14 +2762,13 @@ static int decode_chunks(AVCodecContext *avctx, AVFrame *picture, } } -static int mpeg_decode_frame(AVCodecContext *avctx, void *data, +static int mpeg_decode_frame(AVCodecContext *avctx, AVFrame *picture, int *got_output, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int ret; int buf_size = avpkt->size; Mpeg1Context *s = avctx->priv_data; - AVFrame *picture = data; MpegEncContext *s2 = &s->mpeg_enc_ctx; if (buf_size == 0 || (buf_size == 4 && AV_RB32(buf) == SEQ_END_CODE)) { @@ -2859,19 +2823,19 @@ static int mpeg_decode_frame(AVCodecContext *avctx, void *data, if (ret<0 || *got_output) { s2->current_picture_ptr = NULL; - if (s2->timecode_frame_start != -1 && *got_output) { + if (s->timecode_frame_start != -1 && *got_output) { char tcbuf[AV_TIMECODE_STR_SIZE]; AVFrameSideData *tcside = av_frame_new_side_data(picture, AV_FRAME_DATA_GOP_TIMECODE, sizeof(int64_t)); if (!tcside) return AVERROR(ENOMEM); - memcpy(tcside->data, &s2->timecode_frame_start, sizeof(int64_t)); + memcpy(tcside->data, &s->timecode_frame_start, sizeof(int64_t)); - av_timecode_make_mpeg_tc_string(tcbuf, s2->timecode_frame_start); + av_timecode_make_mpeg_tc_string(tcbuf, s->timecode_frame_start); av_dict_set(&picture->metadata, "timecode", tcbuf, 0); - s2->timecode_frame_start = -1; + s->timecode_frame_start = -1; } } @@ -2898,16 +2862,16 @@ static av_cold int mpeg_decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_mpeg1video_decoder = { - .name = "mpeg1video", - .long_name = NULL_IF_CONFIG_SMALL("MPEG-1 video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MPEG1VIDEO, +const FFCodec ff_mpeg1video_decoder = { + .p.name = "mpeg1video", + .p.long_name = NULL_IF_CONFIG_SMALL("MPEG-1 video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MPEG1VIDEO, .priv_data_size = sizeof(Mpeg1Context), .init = mpeg_decode_init, .close = mpeg_decode_end, - .decode = mpeg_decode_frame, - .capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 | + FF_CODEC_DECODE_CB(mpeg_decode_frame), + .p.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 | #if FF_API_FLAG_TRUNCATED AV_CODEC_CAP_TRUNCATED | #endif @@ -2915,7 +2879,7 @@ const AVCodec ff_mpeg1video_decoder = { .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, .flush = flush, - .max_lowres = 3, + .p.max_lowres = 3, .update_thread_context = ONLY_IF_THREADS_ENABLED(mpeg_decode_update_thread_context), .hw_configs = (const AVCodecHWConfigInternal *const []) { #if CONFIG_MPEG1_NVDEC_HWACCEL @@ -2926,24 +2890,21 @@ const AVCodec ff_mpeg1video_decoder = { #endif #if CONFIG_MPEG1_VIDEOTOOLBOX_HWACCEL HWACCEL_VIDEOTOOLBOX(mpeg1), -#endif -#if CONFIG_MPEG1_XVMC_HWACCEL - HWACCEL_XVMC(mpeg1), #endif NULL }, }; -const AVCodec ff_mpeg2video_decoder = { - .name = "mpeg2video", - .long_name = NULL_IF_CONFIG_SMALL("MPEG-2 video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MPEG2VIDEO, +const FFCodec ff_mpeg2video_decoder = { + .p.name = "mpeg2video", + .p.long_name = NULL_IF_CONFIG_SMALL("MPEG-2 video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MPEG2VIDEO, .priv_data_size = sizeof(Mpeg1Context), .init = mpeg_decode_init, .close = mpeg_decode_end, - .decode = mpeg_decode_frame, - .capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 | + FF_CODEC_DECODE_CB(mpeg_decode_frame), + .p.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 | #if FF_API_FLAG_TRUNCATED AV_CODEC_CAP_TRUNCATED | #endif @@ -2951,8 +2912,8 @@ const AVCodec ff_mpeg2video_decoder = { .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, .flush = flush, - .max_lowres = 3, - .profiles = NULL_IF_CONFIG_SMALL(ff_mpeg2_video_profiles), + .p.max_lowres = 3, + .p.profiles = NULL_IF_CONFIG_SMALL(ff_mpeg2_video_profiles), .hw_configs = (const AVCodecHWConfigInternal *const []) { #if CONFIG_MPEG2_DXVA2_HWACCEL HWACCEL_DXVA2(mpeg2), @@ -2974,25 +2935,22 @@ const AVCodec ff_mpeg2video_decoder = { #endif #if CONFIG_MPEG2_VIDEOTOOLBOX_HWACCEL HWACCEL_VIDEOTOOLBOX(mpeg2), -#endif -#if CONFIG_MPEG2_XVMC_HWACCEL - HWACCEL_XVMC(mpeg2), #endif NULL }, }; //legacy decoder -const AVCodec ff_mpegvideo_decoder = { - .name = "mpegvideo", - .long_name = NULL_IF_CONFIG_SMALL("MPEG-1 video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MPEG2VIDEO, +const FFCodec ff_mpegvideo_decoder = { + .p.name = "mpegvideo", + .p.long_name = NULL_IF_CONFIG_SMALL("MPEG-1 video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MPEG2VIDEO, .priv_data_size = sizeof(Mpeg1Context), .init = mpeg_decode_init, .close = mpeg_decode_end, - .decode = mpeg_decode_frame, - .capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 | + FF_CODEC_DECODE_CB(mpeg_decode_frame), + .p.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 | #if FF_API_FLAG_TRUNCATED AV_CODEC_CAP_TRUNCATED | #endif @@ -3000,7 +2958,7 @@ const AVCodec ff_mpegvideo_decoder = { .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, .flush = flush, - .max_lowres = 3, + .p.max_lowres = 3, }; typedef struct IPUContext { @@ -3010,13 +2968,12 @@ typedef struct IPUContext { DECLARE_ALIGNED(32, int16_t, block)[6][64]; } IPUContext; -static int ipu_decode_frame(AVCodecContext *avctx, void *data, +static int ipu_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt) { IPUContext *s = avctx->priv_data; MpegEncContext *m = &s->m; GetBitContext *gb = &m->gb; - AVFrame * const frame = data; int ret; ret = ff_get_buffer(avctx, frame, 0); @@ -3149,15 +3106,15 @@ static av_cold int ipu_decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_ipu_decoder = { - .name = "ipu", - .long_name = NULL_IF_CONFIG_SMALL("IPU Video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_IPU, +const FFCodec ff_ipu_decoder = { + .p.name = "ipu", + .p.long_name = NULL_IF_CONFIG_SMALL("IPU Video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_IPU, .priv_data_size = sizeof(IPUContext), .init = ipu_decode_init, - .decode = ipu_decode_frame, + FF_CODEC_DECODE_CB(ipu_decode_frame), .close = ipu_decode_end, - .capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/mpeg12dec.h b/libavcodec/mpeg12dec.h new file mode 100644 index 000000000..b4e94a92c --- /dev/null +++ b/libavcodec/mpeg12dec.h @@ -0,0 +1,60 @@ +/* + * MPEG-1/2 decoder header + * Copyright (c) 2007 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 + */ + +#ifndef AVCODEC_MPEG12DEC_H +#define AVCODEC_MPEG12DEC_H + +#include "get_bits.h" +#include "mpeg12vlc.h" +#include "rl.h" + +#define INIT_2D_VLC_RL(rl, static_size, flags)\ +{\ + static RL_VLC_ELEM rl_vlc_table[static_size];\ + rl.rl_vlc[0] = rl_vlc_table;\ + ff_init_2d_vlc_rl(&rl, static_size, flags);\ +} + +void ff_init_2d_vlc_rl(RLTable *rl, unsigned static_size, int flags); + +static inline int decode_dc(GetBitContext *gb, int component) +{ + int code, diff; + + if (component == 0) { + code = get_vlc2(gb, ff_dc_lum_vlc.table, DC_VLC_BITS, 2); + } else { + code = get_vlc2(gb, ff_dc_chroma_vlc.table, DC_VLC_BITS, 2); + } + if (code == 0) { + diff = 0; + } else { + diff = get_xbits(gb, code); + } + return diff; +} + +int ff_mpeg1_decode_block_intra(GetBitContext *gb, + const uint16_t *quant_matrix, + const uint8_t *scantable, int last_dc[3], + int16_t *block, int index, int qscale); + +#endif /* AVCODEC_MPEG12DEC_H */ diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c index 2fb2232f3..09d63ff7d 100644 --- a/libavcodec/mpeg12enc.c +++ b/libavcodec/mpeg12enc.c @@ -28,6 +28,7 @@ #include #include "config.h" +#include "config_components.h" #include "libavutil/attributes.h" #include "libavutil/avassert.h" #include "libavutil/log.h" @@ -37,12 +38,14 @@ #include "libavutil/stereo3d.h" #include "avcodec.h" -#include "bytestream.h" +#include "codec_internal.h" #include "mathops.h" #include "mpeg12.h" #include "mpeg12data.h" +#include "mpeg12enc.h" #include "mpegutils.h" #include "mpegvideo.h" +#include "mpegvideoenc.h" #include "profiles.h" #if CONFIG_MPEG1VIDEO_ENCODER || CONFIG_MPEG2VIDEO_ENCODER @@ -62,6 +65,24 @@ static uint8_t uni_mpeg2_ac_vlc_len[64 * 64 * 2]; static uint32_t mpeg1_lum_dc_uni[512]; static uint32_t mpeg1_chr_dc_uni[512]; +typedef struct MPEG12EncContext { + MpegEncContext mpeg; + AVRational frame_rate_ext; + unsigned frame_rate_index; + + int gop_picture_number; ///< index of the first picture of a GOP based on fake_pic_num + + int64_t timecode_frame_start; ///< GOP timecode frame start number, in non drop frame format + AVTimecode tc; ///< timecode context + char *tc_opt_str; ///< timecode option string + int drop_frame_timecode; ///< timecode is in drop frame format. + int scan_offset; ///< reserve space for SVCD scan offset user data. + + int a53_cc; + int seq_disp_ext; + int video_format; +} MPEG12EncContext; + #define A53_MAX_CC_COUNT 0x1f #endif /* CONFIG_MPEG1VIDEO_ENCODER || CONFIG_MPEG2VIDEO_ENCODER */ @@ -101,8 +122,9 @@ av_cold void ff_mpeg1_init_uni_ac_vlc(const RLTable *rl, uint8_t *uni_ac_vlc_len } #if CONFIG_MPEG1VIDEO_ENCODER || CONFIG_MPEG2VIDEO_ENCODER -static int find_frame_rate_index(MpegEncContext *s) +static int find_frame_rate_index(MPEG12EncContext *mpeg12) { + MpegEncContext *const s = &mpeg12->mpeg; int i; AVRational bestq = (AVRational) {0, 0}; AVRational ext; @@ -126,9 +148,9 @@ static int find_frame_rate_index(MpegEncContext *s) || av_nearer_q(target, bestq, q) < 0 || ext.num==1 && ext.den==1 && av_nearer_q(target, bestq, q) == 0) { bestq = q; - s->frame_rate_index = i; - s->mpeg2_frame_rate_ext.num = ext.num; - s->mpeg2_frame_rate_ext.den = ext.den; + mpeg12->frame_rate_index = i; + mpeg12->frame_rate_ext.num = ext.num; + mpeg12->frame_rate_ext.den = ext.den; } } } @@ -142,8 +164,9 @@ static int find_frame_rate_index(MpegEncContext *s) static av_cold int encode_init(AVCodecContext *avctx) { + MPEG12EncContext *const mpeg12 = avctx->priv_data; + MpegEncContext *const s = &mpeg12->mpeg; int ret; - MpegEncContext *s = avctx->priv_data; int max_size = avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO ? 16383 : 4095; if (avctx->width > max_size || avctx->height > max_size) { @@ -199,8 +222,8 @@ static av_cold int encode_init(AVCodecContext *avctx) if ((ret = ff_mpv_encode_init(avctx)) < 0) return ret; - if (find_frame_rate_index(s) < 0) { - if (s->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) { + if (find_frame_rate_index(mpeg12) < 0) { + if (avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) { av_log(avctx, AV_LOG_ERROR, "MPEG-1/2 does not support %d/%d fps\n", avctx->time_base.den, avctx->time_base.num); return AVERROR(EINVAL); @@ -211,24 +234,24 @@ static av_cold int encode_init(AVCodecContext *avctx) } } - s->drop_frame_timecode = s->drop_frame_timecode || !!(avctx->flags2 & AV_CODEC_FLAG2_DROP_FRAME_TIMECODE); - if (s->drop_frame_timecode) - s->tc.flags |= AV_TIMECODE_FLAG_DROPFRAME; - if (s->drop_frame_timecode && s->frame_rate_index != 4) { + mpeg12->drop_frame_timecode = mpeg12->drop_frame_timecode || !!(avctx->flags2 & AV_CODEC_FLAG2_DROP_FRAME_TIMECODE); + if (mpeg12->drop_frame_timecode) + mpeg12->tc.flags |= AV_TIMECODE_FLAG_DROPFRAME; + if (mpeg12->drop_frame_timecode && mpeg12->frame_rate_index != 4) { av_log(avctx, AV_LOG_ERROR, "Drop frame time code only allowed with 1001/30000 fps\n"); return AVERROR(EINVAL); } - if (s->tc_opt_str) { - AVRational rate = ff_mpeg12_frame_rate_tab[s->frame_rate_index]; - int ret = av_timecode_init_from_string(&s->tc, rate, s->tc_opt_str, s); + if (mpeg12->tc_opt_str) { + AVRational rate = ff_mpeg12_frame_rate_tab[mpeg12->frame_rate_index]; + int ret = av_timecode_init_from_string(&mpeg12->tc, rate, mpeg12->tc_opt_str, s); if (ret < 0) return ret; - s->drop_frame_timecode = !!(s->tc.flags & AV_TIMECODE_FLAG_DROPFRAME); - s->timecode_frame_start = s->tc.start; + mpeg12->drop_frame_timecode = !!(mpeg12->tc.flags & AV_TIMECODE_FLAG_DROPFRAME); + mpeg12->timecode_frame_start = mpeg12->tc.start; } else { - s->timecode_frame_start = 0; // default is -1 + mpeg12->timecode_frame_start = 0; // default is -1 } return 0; @@ -244,157 +267,161 @@ static void put_header(MpegEncContext *s, int header) /* put sequence header if needed */ static void mpeg1_encode_sequence_header(MpegEncContext *s) { + MPEG12EncContext *const mpeg12 = (MPEG12EncContext*)s; unsigned int vbv_buffer_size, fps, v; - int i, constraint_parameter_flag; + int constraint_parameter_flag; + AVRational framerate = ff_mpeg12_frame_rate_tab[mpeg12->frame_rate_index]; uint64_t time_code; int64_t best_aspect_error = INT64_MAX; AVRational aspect_ratio = s->avctx->sample_aspect_ratio; + int aspect_ratio_info; + + if (!s->current_picture.f->key_frame) + return; if (aspect_ratio.num == 0 || aspect_ratio.den == 0) aspect_ratio = (AVRational){1,1}; // pixel aspect 1.1 (VGA) - if (s->current_picture.f->key_frame) { - AVRational framerate = ff_mpeg12_frame_rate_tab[s->frame_rate_index]; + /* MPEG-1 header repeated every GOP */ + put_header(s, SEQ_START_CODE); - /* MPEG-1 header repeated every GOP */ - put_header(s, SEQ_START_CODE); + put_sbits(&s->pb, 12, s->width & 0xFFF); + put_sbits(&s->pb, 12, s->height & 0xFFF); - put_sbits(&s->pb, 12, s->width & 0xFFF); - put_sbits(&s->pb, 12, s->height & 0xFFF); - - for (i = 1; i < 15; i++) { - int64_t error = aspect_ratio.num * (1LL<<32) / aspect_ratio.den; - if (s->codec_id == AV_CODEC_ID_MPEG1VIDEO || i <= 1) - error -= (1LL<<32) / ff_mpeg1_aspect[i]; - else - error -= (1LL<<32)*ff_mpeg2_aspect[i].num * s->height / s->width / ff_mpeg2_aspect[i].den; - - error = FFABS(error); - - if (error - 2 <= best_aspect_error) { - best_aspect_error = error; - s->aspect_ratio_info = i; - } - } - - put_bits(&s->pb, 4, s->aspect_ratio_info); - put_bits(&s->pb, 4, s->frame_rate_index); - - if (s->avctx->rc_max_rate) { - v = (s->avctx->rc_max_rate + 399) / 400; - if (v > 0x3ffff && s->codec_id == AV_CODEC_ID_MPEG1VIDEO) - v = 0x3ffff; - } else { - v = 0x3FFFF; - } - - if (s->avctx->rc_buffer_size) - vbv_buffer_size = s->avctx->rc_buffer_size; + for (int i = 1; i < 15; i++) { + int64_t error = aspect_ratio.num * (1LL<<32) / aspect_ratio.den; + if (s->codec_id == AV_CODEC_ID_MPEG1VIDEO || i <= 1) + error -= (1LL<<32) / ff_mpeg1_aspect[i]; else - /* VBV calculation: Scaled so that a VCD has the proper - * VBV size of 40 kilobytes */ - vbv_buffer_size = ((20 * s->bit_rate) / (1151929 / 2)) * 8 * 1024; - vbv_buffer_size = (vbv_buffer_size + 16383) / 16384; + error -= (1LL<<32)*ff_mpeg2_aspect[i].num * s->height / s->width / ff_mpeg2_aspect[i].den; - put_sbits(&s->pb, 18, v); - put_bits(&s->pb, 1, 1); // marker - put_sbits(&s->pb, 10, vbv_buffer_size); + error = FFABS(error); - constraint_parameter_flag = - s->width <= 768 && - s->height <= 576 && - s->mb_width * s->mb_height <= 396 && - s->mb_width * s->mb_height * framerate.num <= 396 * 25 * framerate.den && - framerate.num <= framerate.den * 30 && - s->avctx->me_range && - s->avctx->me_range < 128 && - vbv_buffer_size <= 20 && - v <= 1856000 / 400 && - s->codec_id == AV_CODEC_ID_MPEG1VIDEO; + if (error - 2 <= best_aspect_error) { + best_aspect_error = error; + aspect_ratio_info = i; + } + } - put_bits(&s->pb, 1, constraint_parameter_flag); + put_bits(&s->pb, 4, aspect_ratio_info); + put_bits(&s->pb, 4, mpeg12->frame_rate_index); - ff_write_quant_matrix(&s->pb, s->avctx->intra_matrix); - ff_write_quant_matrix(&s->pb, s->avctx->inter_matrix); + if (s->avctx->rc_max_rate) { + v = (s->avctx->rc_max_rate + 399) / 400; + if (v > 0x3ffff && s->codec_id == AV_CODEC_ID_MPEG1VIDEO) + v = 0x3ffff; + } else { + v = 0x3FFFF; + } - if (s->codec_id == AV_CODEC_ID_MPEG2VIDEO) { - AVFrameSideData *side_data; - int width = s->width; - int height = s->height; - int use_seq_disp_ext; + if (s->avctx->rc_buffer_size) + vbv_buffer_size = s->avctx->rc_buffer_size; + else + /* VBV calculation: Scaled so that a VCD has the proper + * VBV size of 40 kilobytes */ + vbv_buffer_size = ((20 * s->bit_rate) / (1151929 / 2)) * 8 * 1024; + vbv_buffer_size = (vbv_buffer_size + 16383) / 16384; - put_header(s, EXT_START_CODE); - put_bits(&s->pb, 4, 1); // seq ext + put_sbits(&s->pb, 18, v); + put_bits(&s->pb, 1, 1); // marker + put_sbits(&s->pb, 10, vbv_buffer_size); - put_bits(&s->pb, 1, s->avctx->profile == FF_PROFILE_MPEG2_422); // escx 1 for 4:2:2 profile + constraint_parameter_flag = + s->width <= 768 && + s->height <= 576 && + s->mb_width * s->mb_height <= 396 && + s->mb_width * s->mb_height * framerate.num <= 396 * 25 * framerate.den && + framerate.num <= framerate.den * 30 && + s->avctx->me_range && + s->avctx->me_range < 128 && + vbv_buffer_size <= 20 && + v <= 1856000 / 400 && + s->codec_id == AV_CODEC_ID_MPEG1VIDEO; - put_bits(&s->pb, 3, s->avctx->profile); // profile - put_bits(&s->pb, 4, s->avctx->level); // level + put_bits(&s->pb, 1, constraint_parameter_flag); - put_bits(&s->pb, 1, s->progressive_sequence); - put_bits(&s->pb, 2, s->chroma_format); - put_bits(&s->pb, 2, s->width >> 12); - put_bits(&s->pb, 2, s->height >> 12); - put_bits(&s->pb, 12, v >> 18); // bitrate ext - put_bits(&s->pb, 1, 1); // marker - put_bits(&s->pb, 8, vbv_buffer_size >> 10); // vbv buffer ext - put_bits(&s->pb, 1, s->low_delay); - put_bits(&s->pb, 2, s->mpeg2_frame_rate_ext.num-1); // frame_rate_ext_n - put_bits(&s->pb, 5, s->mpeg2_frame_rate_ext.den-1); // frame_rate_ext_d + ff_write_quant_matrix(&s->pb, s->avctx->intra_matrix); + ff_write_quant_matrix(&s->pb, s->avctx->inter_matrix); - side_data = av_frame_get_side_data(s->current_picture_ptr->f, AV_FRAME_DATA_PANSCAN); - if (side_data) { - AVPanScan *pan_scan = (AVPanScan *)side_data->data; - if (pan_scan->width && pan_scan->height) { - width = pan_scan->width >> 4; - height = pan_scan->height >> 4; - } - } + if (s->codec_id == AV_CODEC_ID_MPEG2VIDEO) { + const AVFrameSideData *side_data; + int width = s->width; + int height = s->height; + int use_seq_disp_ext; - use_seq_disp_ext = (width != s->width || - height != s->height || - s->avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || - s->avctx->color_trc != AVCOL_TRC_UNSPECIFIED || - s->avctx->colorspace != AVCOL_SPC_UNSPECIFIED || - s->video_format != VIDEO_FORMAT_UNSPECIFIED); + put_header(s, EXT_START_CODE); + put_bits(&s->pb, 4, 1); // seq ext - 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, 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 - put_bits(&s->pb, 8, s->avctx->colorspace); // matrix_coefficients - put_bits(&s->pb, 14, width); // display_horizontal_size - put_bits(&s->pb, 1, 1); // marker_bit - put_bits(&s->pb, 14, height); // display_vertical_size - put_bits(&s->pb, 3, 0); // remaining 3 bits are zero padding + put_bits(&s->pb, 1, s->avctx->profile == FF_PROFILE_MPEG2_422); // escx 1 for 4:2:2 profile + + put_bits(&s->pb, 3, s->avctx->profile); // profile + put_bits(&s->pb, 4, s->avctx->level); // level + + put_bits(&s->pb, 1, s->progressive_sequence); + put_bits(&s->pb, 2, s->chroma_format); + put_bits(&s->pb, 2, s->width >> 12); + put_bits(&s->pb, 2, s->height >> 12); + put_bits(&s->pb, 12, v >> 18); // bitrate ext + put_bits(&s->pb, 1, 1); // marker + put_bits(&s->pb, 8, vbv_buffer_size >> 10); // vbv buffer ext + put_bits(&s->pb, 1, s->low_delay); + put_bits(&s->pb, 2, mpeg12->frame_rate_ext.num-1); // frame_rate_ext_n + put_bits(&s->pb, 5, mpeg12->frame_rate_ext.den-1); // frame_rate_ext_d + + side_data = av_frame_get_side_data(s->current_picture_ptr->f, AV_FRAME_DATA_PANSCAN); + if (side_data) { + const AVPanScan *pan_scan = (AVPanScan *)side_data->data; + if (pan_scan->width && pan_scan->height) { + width = pan_scan->width >> 4; + height = pan_scan->height >> 4; } } - put_header(s, GOP_START_CODE); - put_bits(&s->pb, 1, s->drop_frame_timecode); // drop frame flag - /* time code: we must convert from the real frame rate to a - * fake MPEG frame rate in case of low frame rate */ - fps = (framerate.num + framerate.den / 2) / framerate.den; - time_code = s->current_picture_ptr->f->coded_picture_number + - s->timecode_frame_start; + use_seq_disp_ext = (width != s->width || + height != s->height || + s->avctx->color_primaries != AVCOL_PRI_UNSPECIFIED || + s->avctx->color_trc != AVCOL_TRC_UNSPECIFIED || + s->avctx->colorspace != AVCOL_SPC_UNSPECIFIED || + mpeg12->video_format != VIDEO_FORMAT_UNSPECIFIED); - s->gop_picture_number = s->current_picture_ptr->f->coded_picture_number; - - av_assert0(s->drop_frame_timecode == !!(s->tc.flags & AV_TIMECODE_FLAG_DROPFRAME)); - if (s->drop_frame_timecode) - time_code = av_timecode_adjust_ntsc_framenum2(time_code, fps); - - put_bits(&s->pb, 5, (uint32_t)((time_code / (fps * 3600)) % 24)); - put_bits(&s->pb, 6, (uint32_t)((time_code / (fps * 60)) % 60)); - put_bits(&s->pb, 1, 1); - put_bits(&s->pb, 6, (uint32_t)((time_code / fps) % 60)); - put_bits(&s->pb, 6, (uint32_t)((time_code % fps))); - put_bits(&s->pb, 1, !!(s->avctx->flags & AV_CODEC_FLAG_CLOSED_GOP) || s->intra_only || !s->gop_picture_number); - put_bits(&s->pb, 1, 0); // broken link + if (mpeg12->seq_disp_ext == 1 || + (mpeg12->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, mpeg12->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 + put_bits(&s->pb, 8, s->avctx->colorspace); // matrix_coefficients + put_bits(&s->pb, 14, width); // display_horizontal_size + put_bits(&s->pb, 1, 1); // marker_bit + put_bits(&s->pb, 14, height); // display_vertical_size + put_bits(&s->pb, 3, 0); // remaining 3 bits are zero padding + } } + + put_header(s, GOP_START_CODE); + put_bits(&s->pb, 1, mpeg12->drop_frame_timecode); // drop frame flag + /* time code: we must convert from the real frame rate to a + * fake MPEG frame rate in case of low frame rate */ + fps = (framerate.num + framerate.den / 2) / framerate.den; + time_code = s->current_picture_ptr->f->coded_picture_number + + mpeg12->timecode_frame_start; + + mpeg12->gop_picture_number = s->current_picture_ptr->f->coded_picture_number; + + av_assert0(mpeg12->drop_frame_timecode == !!(mpeg12->tc.flags & AV_TIMECODE_FLAG_DROPFRAME)); + if (mpeg12->drop_frame_timecode) + time_code = av_timecode_adjust_ntsc_framenum2(time_code, fps); + + put_bits(&s->pb, 5, (uint32_t)((time_code / (fps * 3600)) % 24)); + put_bits(&s->pb, 6, (uint32_t)((time_code / (fps * 60)) % 60)); + put_bits(&s->pb, 1, 1); + put_bits(&s->pb, 6, (uint32_t)((time_code / fps) % 60)); + put_bits(&s->pb, 6, (uint32_t)((time_code % fps))); + put_bits(&s->pb, 1, !!(s->avctx->flags & AV_CODEC_FLAG_CLOSED_GOP) || + s->intra_only || !mpeg12->gop_picture_number); + put_bits(&s->pb, 1, 0); // broken link } static inline void encode_mb_skip_run(MpegEncContext *s, int run) @@ -428,6 +455,7 @@ void ff_mpeg1_encode_slice_header(MpegEncContext *s) void ff_mpeg1_encode_picture_header(MpegEncContext *s, int picture_number) { + MPEG12EncContext *const mpeg12 = (MPEG12EncContext*)s; AVFrameSideData *side_data; mpeg1_encode_sequence_header(s); @@ -437,10 +465,10 @@ void ff_mpeg1_encode_picture_header(MpegEncContext *s, int picture_number) // RAL: s->picture_number instead of s->fake_picture_number put_bits(&s->pb, 10, - (s->picture_number - s->gop_picture_number) & 0x3ff); + (s->picture_number - mpeg12->gop_picture_number) & 0x3ff); put_bits(&s->pb, 3, s->pict_type); - s->vbv_delay_ptr = s->pb.buf + put_bytes_count(&s->pb, 0); + s->vbv_delay_pos = put_bytes_count(&s->pb, 0); put_bits(&s->pb, 16, 0xFFFF); /* vbv_delay */ // RAL: Forward f_code also needed for B-frames @@ -505,7 +533,7 @@ void ff_mpeg1_encode_picture_header(MpegEncContext *s, int picture_number) put_bits(&s->pb, 1, s->progressive_frame); put_bits(&s->pb, 1, 0); /* composite_display_flag */ } - if (s->scan_offset) { + if (mpeg12->scan_offset) { int i; put_header(s, USER_START_CODE); @@ -551,7 +579,7 @@ void ff_mpeg1_encode_picture_header(MpegEncContext *s, int picture_number) } } - if (s->codec_id == AV_CODEC_ID_MPEG2VIDEO && s->a53_cc) { + if (CONFIG_MPEG2VIDEO_ENCODER && mpeg12->a53_cc) { side_data = av_frame_get_side_data(s->current_picture_ptr->f, AV_FRAME_DATA_A53_CC); if (side_data) { @@ -601,10 +629,8 @@ static inline void put_mb_modes(MpegEncContext *s, int n, int bits, static void mpeg1_encode_motion(MpegEncContext *s, int val, int f_or_b_code) { if (val == 0) { - /* zero vector */ - put_bits(&s->pb, - ff_mpeg12_mbMotionVectorTable[0][1], - ff_mpeg12_mbMotionVectorTable[0][0]); + /* zero vector, corresponds to ff_mpeg12_mbMotionVectorTable[0] */ + put_bits(&s->pb, 1, 0x01); } else { int code, sign, bits; int bit_size = f_or_b_code - 1; @@ -726,8 +752,10 @@ next_coef: put_bits(&s->pb, table_vlc[code][1] + 1, (table_vlc[code][0] << 1) + sign); } else { - /* escape seems to be pretty rare <5% so I do not optimize it */ - put_bits(&s->pb, table_vlc[111][1], table_vlc[111][0]); + /* Escape seems to be pretty rare <5% so I do not optimize it; + * the following value is the common escape value for both + * possible tables (i.e. table_vlc[111]). */ + put_bits(&s->pb, 6, 0x01); /* escape: only clip in this case */ put_bits(&s->pb, 6, run); if (s->codec_id == AV_CODEC_ID_MPEG1VIDEO) { @@ -753,8 +781,11 @@ next_coef: static av_always_inline void mpeg1_encode_mb_internal(MpegEncContext *s, int16_t block[8][64], int motion_x, int motion_y, - int mb_block_count) + int mb_block_count, + int chroma_y_shift) { +/* MPEG-1 is always 420. */ +#define IS_MPEG1(s) (chroma_y_shift == 1 && (s)->codec_id == AV_CODEC_ID_MPEG1VIDEO) int i, cbp; const int mb_x = s->mb_x; const int mb_y = s->mb_y; @@ -768,7 +799,7 @@ static av_always_inline void mpeg1_encode_mb_internal(MpegEncContext *s, if (cbp == 0 && !first_mb && s->mv_type == MV_TYPE_16X16 && (mb_x != s->mb_width - 1 || - (mb_y != s->end_mb_y - 1 && s->codec_id == AV_CODEC_ID_MPEG1VIDEO)) && + (mb_y != s->end_mb_y - 1 && IS_MPEG1(s))) && ((s->pict_type == AV_PICTURE_TYPE_P && (motion_x | motion_y) == 0) || (s->pict_type == AV_PICTURE_TYPE_B && s->mv_dir == s->last_mv_dir && (((s->mv_dir & MV_DIR_FORWARD) @@ -898,7 +929,7 @@ static av_always_inline void mpeg1_encode_mb_internal(MpegEncContext *s, s->mv_bits += get_bits_diff(s); } if (cbp) { - if (s->chroma_y_shift) { + if (chroma_y_shift) { put_bits(&s->pb, ff_mpeg12_mbPatTable[cbp][1], ff_mpeg12_mbPatTable[cbp][0]); @@ -909,7 +940,6 @@ static av_always_inline void mpeg1_encode_mb_internal(MpegEncContext *s, put_sbits(&s->pb, 2, cbp); } } - s->f_count++; } else { if (s->mv_type == MV_TYPE_16X16) { if (cbp) { // With coded bloc pattern @@ -940,7 +970,6 @@ static av_always_inline void mpeg1_encode_mb_internal(MpegEncContext *s, s->last_mv[0][1][0] = s->mv[0][0][0]; s->last_mv[0][0][1] = s->last_mv[0][1][1] = s->mv[0][0][1]; - s->f_count++; } if (s->mv_dir & MV_DIR_BACKWARD) { mpeg1_encode_motion(s, @@ -953,7 +982,6 @@ static av_always_inline void mpeg1_encode_mb_internal(MpegEncContext *s, s->last_mv[1][1][0] = s->mv[1][0][0]; s->last_mv[1][0][1] = s->last_mv[1][1][1] = s->mv[1][0][1]; - s->b_count++; } } else { av_assert2(s->mv_type == MV_TYPE_FIELD); @@ -986,7 +1014,6 @@ static av_always_inline void mpeg1_encode_mb_internal(MpegEncContext *s, s->last_mv[0][i][0] = s->mv[0][i][0]; s->last_mv[0][i][1] = s->mv[0][i][1] * 2; } - s->f_count++; } if (s->mv_dir & MV_DIR_BACKWARD) { for (i = 0; i < 2; i++) { @@ -1000,12 +1027,11 @@ static av_always_inline void mpeg1_encode_mb_internal(MpegEncContext *s, s->last_mv[1][i][0] = s->mv[1][i][0]; s->last_mv[1][i][1] = s->mv[1][i][1] * 2; } - s->b_count++; } } s->mv_bits += get_bits_diff(s); if (cbp) { - if (s->chroma_y_shift) { + if (chroma_y_shift) { put_bits(&s->pb, ff_mpeg12_mbPatTable[cbp][1], ff_mpeg12_mbPatTable[cbp][0]); @@ -1032,9 +1058,9 @@ void ff_mpeg1_encode_mb(MpegEncContext *s, int16_t block[8][64], int motion_x, int motion_y) { if (s->chroma_format == CHROMA_420) - mpeg1_encode_mb_internal(s, block, motion_x, motion_y, 6); + mpeg1_encode_mb_internal(s, block, motion_x, motion_y, 6, 1); else - mpeg1_encode_mb_internal(s, block, motion_x, motion_y, 8); + mpeg1_encode_mb_internal(s, block, motion_x, motion_y, 8, 0); } static av_cold void mpeg12_encode_init_static(void) @@ -1074,7 +1100,7 @@ static av_cold void mpeg12_encode_init_static(void) int len; if (mv == 0) { - len = ff_mpeg12_mbMotionVectorTable[0][1]; + len = 1; /* ff_mpeg12_mbMotionVectorTable[0][1] */ } else { int val, bit_size, code; @@ -1089,7 +1115,7 @@ static av_cold void mpeg12_encode_init_static(void) len = ff_mpeg12_mbMotionVectorTable[code][1] + 1 + bit_size; else - len = ff_mpeg12_mbMotionVectorTable[16][1] + + len = 10 /* ff_mpeg12_mbMotionVectorTable[16][1] */ + 2 + bit_size; } @@ -1116,6 +1142,7 @@ av_cold void ff_mpeg1_encode_init(MpegEncContext *s) } else { s->min_qcoeff = -2047; s->max_qcoeff = 2047; + s->mpeg_quant = 1; } if (s->intra_vlc_format) { s->intra_ac_vlc_length = @@ -1130,7 +1157,7 @@ av_cold void ff_mpeg1_encode_init(MpegEncContext *s) ff_thread_once(&init_static_once, mpeg12_encode_init_static); } -#define OFFSET(x) offsetof(MpegEncContext, x) +#define OFFSET(x) offsetof(MPEG12EncContext, x) #define VE AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM #define COMMON_OPTS \ { "gop_timecode", "MPEG GOP Timecode in hh:mm:ss[:;.]ff format. Overrides timecode_frame_start.", \ @@ -1146,20 +1173,16 @@ av_cold void ff_mpeg1_encode_init(MpegEncContext *s) static const AVOption mpeg1_options[] = { COMMON_OPTS FF_MPV_COMMON_OPTS -#if FF_API_MPEGVIDEO_OPTS - FF_MPV_DEPRECATED_MPEG_QUANT_OPT - FF_MPV_DEPRECATED_A53_CC_OPT - FF_MPV_DEPRECATED_MATRIX_OPT -#endif + FF_MPV_COMMON_MOTION_EST_OPTS { NULL }, }; static const AVOption mpeg2_options[] = { COMMON_OPTS { "intra_vlc", "Use MPEG-2 intra VLC table.", - OFFSET(intra_vlc_format), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, - { "non_linear_quant", "Use nonlinear quantizer.", OFFSET(q_scale_type), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, - { "alternate_scan", "Enable alternate scantable.", OFFSET(alternate_scan), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, + FF_MPV_OFFSET(intra_vlc_format), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, + { "non_linear_quant", "Use nonlinear quantizer.", FF_MPV_OFFSET(q_scale_type), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, + { "alternate_scan", "Enable alternate scantable.", FF_MPV_OFFSET(alternate_scan), 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 }, { "seq_disp_ext", "Write sequence_display_extension blocks.", OFFSET(seq_disp_ext), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE, "seq_disp_ext" }, { "auto", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, VE, "seq_disp_ext" }, @@ -1179,11 +1202,7 @@ static const AVOption mpeg2_options[] = { { LEVEL("low", 10) }, #undef LEVEL FF_MPV_COMMON_OPTS -#if FF_API_MPEGVIDEO_OPTS - { "mpeg_quant", "Deprecated, does nothing", OFFSET(mpeg_quant), - AV_OPT_TYPE_INT, {.i64 = 1 }, 0, 1, VE | AV_OPT_FLAG_DEPRECATED }, - FF_MPV_DEPRECATED_MATRIX_OPT -#endif + FF_MPV_COMMON_MOTION_EST_OPTS FF_MPEG2_PROFILE_OPTS { NULL }, }; @@ -1199,38 +1218,38 @@ static const AVClass mpeg ## x ## _class = { \ mpeg12_class(1) mpeg12_class(2) -const AVCodec ff_mpeg1video_encoder = { - .name = "mpeg1video", - .long_name = NULL_IF_CONFIG_SMALL("MPEG-1 video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MPEG1VIDEO, - .priv_data_size = sizeof(MpegEncContext), +const FFCodec ff_mpeg1video_encoder = { + .p.name = "mpeg1video", + .p.long_name = NULL_IF_CONFIG_SMALL("MPEG-1 video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MPEG1VIDEO, + .priv_data_size = sizeof(MPEG12EncContext), .init = encode_init, - .encode2 = ff_mpv_encode_picture, + FF_CODEC_ENCODE_CB(ff_mpv_encode_picture), .close = ff_mpv_encode_end, - .supported_framerates = ff_mpeg12_frame_rate_tab + 1, - .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, + .p.supported_framerates = ff_mpeg12_frame_rate_tab + 1, + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS, + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .priv_class = &mpeg1_class, + .p.priv_class = &mpeg1_class, }; -const AVCodec ff_mpeg2video_encoder = { - .name = "mpeg2video", - .long_name = NULL_IF_CONFIG_SMALL("MPEG-2 video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MPEG2VIDEO, - .priv_data_size = sizeof(MpegEncContext), +const FFCodec ff_mpeg2video_encoder = { + .p.name = "mpeg2video", + .p.long_name = NULL_IF_CONFIG_SMALL("MPEG-2 video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MPEG2VIDEO, + .priv_data_size = sizeof(MPEG12EncContext), .init = encode_init, - .encode2 = ff_mpv_encode_picture, + FF_CODEC_ENCODE_CB(ff_mpv_encode_picture), .close = ff_mpv_encode_end, - .supported_framerates = ff_mpeg2_frame_rate_tab, - .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, + .p.supported_framerates = ff_mpeg2_frame_rate_tab, + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_NONE }, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS, + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .priv_class = &mpeg2_class, + .p.priv_class = &mpeg2_class, }; #endif /* CONFIG_MPEG1VIDEO_ENCODER || CONFIG_MPEG2VIDEO_ENCODER */ diff --git a/libavcodec/mpeg12enc.h b/libavcodec/mpeg12enc.h new file mode 100644 index 000000000..fbbc43f89 --- /dev/null +++ b/libavcodec/mpeg12enc.h @@ -0,0 +1,38 @@ +/* + * MPEG-1/2 encoder header + * Copyright (c) 2007 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 + */ + +#ifndef AVCODEC_MPEG12ENC_H +#define AVCODEC_MPEG12ENC_H + +#include + +#include "mpegvideo.h" +#include "rl.h" + +void ff_mpeg1_init_uni_ac_vlc(const RLTable *rl, uint8_t *uni_ac_vlc_len); + +void ff_mpeg1_encode_picture_header(MpegEncContext *s, int picture_number); +void ff_mpeg1_encode_mb(MpegEncContext *s, int16_t block[8][64], + int motion_x, int motion_y); +void ff_mpeg1_encode_init(MpegEncContext *s); +void ff_mpeg1_encode_slice_header(MpegEncContext *s); + +#endif /* AVCODEC_MPEG12ENC_H */ diff --git a/libavcodec/mpeg2_metadata_bsf.c b/libavcodec/mpeg2_metadata_bsf.c index 11b46c0ae..1aa6e0279 100644 --- a/libavcodec/mpeg2_metadata_bsf.c +++ b/libavcodec/mpeg2_metadata_bsf.c @@ -16,11 +16,11 @@ * 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 "bsf_internal.h" #include "cbs.h" #include "cbs_bsf.h" #include "cbs_mpeg2.h" @@ -232,12 +232,12 @@ 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", +const FFBitStreamFilter ff_mpeg2_metadata_bsf = { + .p.name = "mpeg2_metadata", + .p.codec_ids = mpeg2_metadata_codec_ids, + .p.priv_class = &mpeg2_metadata_class, .priv_data_size = sizeof(MPEG2MetadataContext), - .priv_class = &mpeg2_metadata_class, .init = &mpeg2_metadata_init, .close = &ff_cbs_bsf_generic_close, .filter = &ff_cbs_bsf_generic_filter, - .codec_ids = mpeg2_metadata_codec_ids, }; diff --git a/libavcodec/mpeg4_unpack_bframes_bsf.c b/libavcodec/mpeg4_unpack_bframes_bsf.c index 6f8595713..5493dafa9 100644 --- a/libavcodec/mpeg4_unpack_bframes_bsf.c +++ b/libavcodec/mpeg4_unpack_bframes_bsf.c @@ -21,8 +21,8 @@ #include "bsf.h" #include "bsf_internal.h" -#include "internal.h" #include "mpeg4video.h" +#include "startcode.h" typedef struct UnpackBFramesBSFContext { AVBufferRef *b_frame_ref; @@ -155,12 +155,12 @@ static const enum AVCodecID codec_ids[] = { AV_CODEC_ID_MPEG4, AV_CODEC_ID_NONE, }; -const AVBitStreamFilter ff_mpeg4_unpack_bframes_bsf = { - .name = "mpeg4_unpack_bframes", +const FFBitStreamFilter ff_mpeg4_unpack_bframes_bsf = { + .p.name = "mpeg4_unpack_bframes", + .p.codec_ids = codec_ids, .priv_data_size = sizeof(UnpackBFramesBSFContext), .init = mpeg4_unpack_bframes_init, .filter = mpeg4_unpack_bframes_filter, .flush = mpeg4_unpack_bframes_close_flush, .close = mpeg4_unpack_bframes_close_flush, - .codec_ids = codec_ids, }; diff --git a/libavcodec/mpeg4data.h b/libavcodec/mpeg4data.h index 30179d980..c5a2b1472 100644 --- a/libavcodec/mpeg4data.h +++ b/libavcodec/mpeg4data.h @@ -28,8 +28,7 @@ #ifndef AVCODEC_MPEG4DATA_H #define AVCODEC_MPEG4DATA_H -#include -#include "mpegvideo.h" +#include "mpeg4videodata.h" /* dc encoding for MPEG-4 */ const uint8_t ff_mpeg4_DCtab_lum[13][2] = diff --git a/libavcodec/mpeg4video.h b/libavcodec/mpeg4video.h index 3db6f8515..ab6528075 100644 --- a/libavcodec/mpeg4video.h +++ b/libavcodec/mpeg4video.h @@ -25,9 +25,7 @@ #include -#include "get_bits.h" #include "mpegvideo.h" -#include "rl.h" // shapes #define RECT_SHAPE 0 @@ -71,110 +69,9 @@ /* smaller packets likely don't contain a real frame */ #define MAX_NVOP_SIZE 19 -typedef struct Mpeg4DecContext { - MpegEncContext m; - - /// number of bits to represent the fractional part of time - int time_increment_bits; - int shape; - int vol_sprite_usage; - int sprite_brightness_change; - int num_sprite_warping_points; - /// sprite trajectory points - uint16_t sprite_traj[4][2]; - /// sprite shift [isChroma] - int sprite_shift[2]; - - // reversible vlc - int rvlc; - /// could this stream contain resync markers - int resync_marker; - /// time distance of first I -> B, used for interlaced B-frames - int t_frame; - - int new_pred; - int enhancement_type; - int scalability; - int use_intra_dc_vlc; - - /// QP above which the ac VLC should be used for intra dc - int intra_dc_threshold; - - /* bug workarounds */ - int divx_version; - int divx_build; - int xvid_build; - int lavc_build; - - /// flag for having shown the warning about invalid Divx B-frames - int showed_packed_warning; - /** does the stream contain the low_delay flag, - * used to work around buggy encoders. */ - int vol_control_parameters; - int cplx_estimation_trash_i; - int cplx_estimation_trash_p; - int cplx_estimation_trash_b; - - 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]; - -extern const uint16_t ff_mpeg4_intra_vlc[103][2]; -extern const int8_t ff_mpeg4_intra_level[102]; -extern const int8_t ff_mpeg4_intra_run[102]; - -extern RLTable ff_mpeg4_rl_intra; -void ff_mpeg4_init_rl_intra(void); - -/* Note this is identical to the intra rvlc except that it is reordered. */ -extern RLTable ff_rvlc_rl_inter; -extern RLTable ff_rvlc_rl_intra; - -extern const uint8_t ff_sprite_trajectory_lens[15]; -extern const uint8_t ff_mb_type_b_tab[4][2]; - -/* these matrixes will be permuted for the idct */ -extern const int16_t ff_mpeg4_default_intra_matrix[64]; -extern const int16_t ff_mpeg4_default_non_intra_matrix[64]; - -extern const uint8_t ff_mpeg4_y_dc_scale_table[32]; -extern const uint8_t ff_mpeg4_c_dc_scale_table[32]; -extern const uint16_t ff_mpeg4_resync_prefix[8]; - -extern const uint8_t ff_mpeg4_dc_threshold[8]; - -extern const uint8_t ff_mpeg4_studio_dc_luma[19][2]; -extern const uint8_t ff_mpeg4_studio_dc_chroma[19][2]; -extern const uint8_t ff_mpeg4_studio_intra[12][24][2]; - -void ff_mpeg4_encode_mb(MpegEncContext *s, - int16_t block[6][64], - int motion_x, int motion_y); -void ff_mpeg4_pred_ac(MpegEncContext *s, int16_t *block, int n, - int dir); -void ff_set_mpeg4_time(MpegEncContext *s); -int ff_mpeg4_encode_picture_header(MpegEncContext *s, int picture_number); - -int ff_mpeg4_decode_picture_header(Mpeg4DecContext *ctx, GetBitContext *gb, int header); -void ff_mpeg4_encode_video_packet_header(MpegEncContext *s); void ff_mpeg4_clean_buffers(MpegEncContext *s); -void ff_mpeg4_stuffing(PutBitContext *pbc); -void ff_mpeg4_init_partitions(MpegEncContext *s); -void ff_mpeg4_merge_partitions(MpegEncContext *s); -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); -int ff_mpeg4_frame_end(AVCodecContext *avctx, const uint8_t *buf, int buf_size); /** * @return the mb_type diff --git a/libavcodec/mpeg4video_parser.c b/libavcodec/mpeg4video_parser.c index c68c96625..3d0d0e471 100644 --- a/libavcodec/mpeg4video_parser.c +++ b/libavcodec/mpeg4video_parser.c @@ -26,6 +26,7 @@ #include "parser.h" #include "mpegvideo.h" #include "mpeg4video.h" +#include "mpeg4videodec.h" #if FF_API_FLAG_TRUNCATED /* Nuke this header when removing FF_API_FLAG_TRUNCATED */ #include "mpeg4video_parser.h" @@ -100,13 +101,13 @@ static int mpeg4_decode_header(AVCodecParserContext *s1, AVCodecContext *avctx, if (avctx->extradata_size && pc->first_picture) { init_get_bits(gb, avctx->extradata, avctx->extradata_size * 8); - ret = ff_mpeg4_decode_picture_header(dec_ctx, gb, 1); + ret = ff_mpeg4_decode_picture_header(dec_ctx, gb, 1, 1); if (ret < 0) av_log(avctx, AV_LOG_WARNING, "Failed to parse extradata\n"); } init_get_bits(gb, buf, 8 * buf_size); - ret = ff_mpeg4_decode_picture_header(dec_ctx, gb, 0); + ret = ff_mpeg4_decode_picture_header(dec_ctx, gb, 0, 1); if (s->width && (!avctx->width || !avctx->height || !avctx->coded_width || !avctx->coded_height)) { ret = ff_set_dimensions(avctx, s->width, s->height); @@ -129,8 +130,6 @@ static av_cold int mpeg4video_parse_init(AVCodecParserContext *s) { struct Mp4vParseContext *pc = s->priv_data; - ff_mpeg4videodec_static_init(); - pc->first_picture = 1; pc->dec_ctx.m.quant_precision = 5; pc->dec_ctx.m.slice_context_count = 1; diff --git a/libavcodec/mpeg4videodata.h b/libavcodec/mpeg4videodata.h new file mode 100644 index 000000000..b20096067 --- /dev/null +++ b/libavcodec/mpeg4videodata.h @@ -0,0 +1,61 @@ +/* + * MPEG-4 encoder/decoder data. + * Copyright (c) 2000,2001 Fabrice Bellard + * Copyright (c) 2002-2010 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 + */ + +#ifndef AVCODEC_MPEG4VIDEODATA_H +#define AVCODEC_MPEG4VIDEODATA_H + +#include +#include "rl.h" + +/* 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]; + +extern const uint16_t ff_mpeg4_intra_vlc[103][2]; +extern const int8_t ff_mpeg4_intra_level[102]; +extern const int8_t ff_mpeg4_intra_run[102]; + +extern RLTable ff_mpeg4_rl_intra; +void ff_mpeg4_init_rl_intra(void); + +/* Note this is identical to the intra rvlc except that it is reordered. */ +extern RLTable ff_rvlc_rl_inter; +extern RLTable ff_rvlc_rl_intra; + +extern const uint8_t ff_sprite_trajectory_lens[15]; +extern const uint8_t ff_mb_type_b_tab[4][2]; + +/* these matrixes will be permuted for the idct */ +extern const int16_t ff_mpeg4_default_intra_matrix[64]; +extern const int16_t ff_mpeg4_default_non_intra_matrix[64]; + +extern const uint8_t ff_mpeg4_y_dc_scale_table[32]; +extern const uint8_t ff_mpeg4_c_dc_scale_table[32]; +extern const uint16_t ff_mpeg4_resync_prefix[8]; + +extern const uint8_t ff_mpeg4_dc_threshold[8]; + +extern const uint8_t ff_mpeg4_studio_dc_luma[19][2]; +extern const uint8_t ff_mpeg4_studio_dc_chroma[19][2]; +extern const uint8_t ff_mpeg4_studio_intra[12][24][2]; + +#endif /* AVCODEC_MPEG4VIDEO_H */ diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index 34b050db2..220d415c6 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -22,21 +22,27 @@ #define UNCHECKED_BITSTREAM_READER 1 +#include "config_components.h" + #include "libavutil/internal.h" #include "libavutil/opt.h" -#include "libavutil/pixdesc.h" #include "libavutil/thread.h" +#include "codec_internal.h" #include "error_resilience.h" #include "hwconfig.h" #include "idctdsp.h" -#include "internal.h" #include "mpegutils.h" #include "mpegvideo.h" #include "mpegvideodata.h" +#include "mpegvideodec.h" #include "mpeg4video.h" +#include "mpeg4videodata.h" +#include "mpeg4videodec.h" #include "h263.h" +#include "h263data.h" +#include "h263dec.h" #include "profiles.h" -#include "thread.h" +#include "threadframe.h" #include "xvididct.h" #include "unary.h" @@ -56,6 +62,8 @@ static VLC studio_intra_tab[12]; static VLC studio_luma_dc; static VLC studio_chroma_dc; +static const uint8_t mpeg4_block_count[4] = { 0, 6, 8, 12 }; + static const int mb_type_b_map[4] = { MB_TYPE_DIRECT2 | MB_TYPE_L0L1, MB_TYPE_L0L1 | MB_TYPE_16x16, @@ -63,6 +71,69 @@ static const int mb_type_b_map[4] = { MB_TYPE_L0 | MB_TYPE_16x16, }; +void ff_mpeg4_decode_studio(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb, + uint8_t *dest_cr, int block_size, int uvlinesize, + int dct_linesize, int dct_offset) +{ + Mpeg4DecContext *const ctx = (Mpeg4DecContext*)s; + const int act_block_size = block_size * 2; + + if (ctx->dpcm_direction == 0) { + s->idsp.idct_put(dest_y, dct_linesize, (int16_t*)ctx->block32[0]); + s->idsp.idct_put(dest_y + act_block_size, dct_linesize, (int16_t*)ctx->block32[1]); + s->idsp.idct_put(dest_y + dct_offset, dct_linesize, (int16_t*)ctx->block32[2]); + s->idsp.idct_put(dest_y + dct_offset + act_block_size, dct_linesize, (int16_t*)ctx->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*)ctx->block32[4]); + s->idsp.idct_put(dest_cr, dct_linesize, (int16_t*)ctx->block32[5]); + s->idsp.idct_put(dest_cb + dct_offset, dct_linesize, (int16_t*)ctx->block32[6]); + s->idsp.idct_put(dest_cr + dct_offset, dct_linesize, (int16_t*)ctx->block32[7]); + if (!s->chroma_x_shift){ //Chroma444 + s->idsp.idct_put(dest_cb + act_block_size, dct_linesize, (int16_t*)ctx->block32[8]); + s->idsp.idct_put(dest_cr + act_block_size, dct_linesize, (int16_t*)ctx->block32[9]); + s->idsp.idct_put(dest_cb + act_block_size + dct_offset, dct_linesize, (int16_t*)ctx->block32[10]); + s->idsp.idct_put(dest_cr + act_block_size + dct_offset, dct_linesize, (int16_t*)ctx->block32[11]); + } + } else if (ctx->dpcm_direction == 1) { + uint16_t *dest_pcm[3] = {(uint16_t*)dest_y, (uint16_t*)dest_cb, (uint16_t*)dest_cr}; + int linesize[3] = {dct_linesize, uvlinesize, uvlinesize}; + for (int i = 0; i < 3; i++) { + const uint16_t *src = ctx->dpcm_macroblock[i]; + int vsub = i ? s->chroma_y_shift : 0; + int hsub = i ? s->chroma_x_shift : 0; + int lowres = s->avctx->lowres; + int step = 1 << lowres; + for (int h = 0; h < (16 >> (vsub + lowres)); h++){ + for (int w = 0, idx = 0; w < (16 >> (hsub + lowres)); w++, idx += step) + dest_pcm[i][w] = src[idx]; + dest_pcm[i] += linesize[i] / 2; + src += (16 >> hsub) * step; + } + } + } else { + uint16_t *dest_pcm[3] = {(uint16_t*)dest_y, (uint16_t*)dest_cb, (uint16_t*)dest_cr}; + int linesize[3] = {dct_linesize, uvlinesize, uvlinesize}; + av_assert2(ctx->dpcm_direction == -1); + for (int i = 0; i < 3; i++) { + const uint16_t *src = ctx->dpcm_macroblock[i]; + int vsub = i ? s->chroma_y_shift : 0; + int hsub = i ? s->chroma_x_shift : 0; + int lowres = s->avctx->lowres; + int step = 1 << lowres; + dest_pcm[i] += (linesize[i] / 2) * ((16 >> vsub) - 1); + for (int h = (16 >> (vsub + lowres)) - 1; h >= 0; h--){ + for (int w = (16 >> (hsub + lowres)) - 1, idx = 0; w >= 0; w--, idx += step) + dest_pcm[i][w] = src[idx]; + src += step * (16 >> hsub); + dest_pcm[i] -= linesize[i] / 2; + } + } + } +} + /** * Predict the ac. * @param n block index (0-3 are luma, 4-5 are chroma) @@ -1038,7 +1109,8 @@ int ff_mpeg4_decode_partitions(Mpeg4DecContext *ctx) * @return <0 if an error occurred */ static inline int mpeg4_decode_block(Mpeg4DecContext *ctx, int16_t *block, - int n, int coded, int intra, int rvlc) + int n, int coded, int intra, + int use_intra_dc_vlc, int rvlc) { MpegEncContext *s = &ctx->m; int level, i, last, run, qmul, qadd; @@ -1050,7 +1122,7 @@ static inline int mpeg4_decode_block(Mpeg4DecContext *ctx, int16_t *block, // Note intra & rvlc should be optimized away if this is inlined if (intra) { - if (ctx->use_intra_dc_vlc) { + if (use_intra_dc_vlc) { /* DC coef */ if (s->partitioned_frame) { level = s->dc_val[0][s->block_index[n]]; @@ -1290,7 +1362,7 @@ static inline int mpeg4_decode_block(Mpeg4DecContext *ctx, int16_t *block, not_coded: if (intra) { - if (!ctx->use_intra_dc_vlc) { + if (!use_intra_dc_vlc) { block[0] = ff_mpeg4_pred_dc(s, n, block[0], &dc_pred_dir, 0); i -= i >> 31; // if (i == -1) i = 0; @@ -1311,7 +1383,7 @@ not_coded: static int mpeg4_decode_partitioned_mb(MpegEncContext *s, int16_t block[6][64]) { Mpeg4DecContext *ctx = s->avctx->priv_data; - int cbp, mb_type; + int cbp, mb_type, use_intra_dc_vlc; const int xy = s->mb_x + s->mb_y * s->mb_stride; av_assert2(s == (void*)ctx); @@ -1319,7 +1391,7 @@ static int mpeg4_decode_partitioned_mb(MpegEncContext *s, int16_t block[6][64]) mb_type = s->current_picture.mb_type[xy]; cbp = s->cbp_table[xy]; - ctx->use_intra_dc_vlc = s->qscale < ctx->intra_dc_threshold; + use_intra_dc_vlc = s->qscale < ctx->intra_dc_threshold; if (s->current_picture.qscale_table[xy] != s->qscale) ff_set_qscale(s, s->current_picture.qscale_table[xy]); @@ -1369,7 +1441,8 @@ static int mpeg4_decode_partitioned_mb(MpegEncContext *s, int16_t block[6][64]) s->bdsp.clear_blocks(s->block[0]); /* decode each block */ for (i = 0; i < 6; i++) { - if (mpeg4_decode_block(ctx, block[i], i, cbp & 32, s->mb_intra, ctx->rvlc) < 0) { + if (mpeg4_decode_block(ctx, block[i], i, cbp & 32, s->mb_intra, + use_intra_dc_vlc, ctx->rvlc) < 0) { av_log(s->avctx, AV_LOG_ERROR, "texture corrupted at %d %d %d\n", s->mb_x, s->mb_y, s->mb_intra); @@ -1696,6 +1769,8 @@ static int mpeg4_decode_mb(MpegEncContext *s, int16_t block[6][64]) } s->current_picture.mb_type[xy] = mb_type; } else { /* I-Frame */ + int use_intra_dc_vlc; + do { cbpc = get_vlc2(&s->gb, ff_h263_intra_MCBPC_vlc.table, INTRA_MCBPC_VLC_BITS, 2); if (cbpc < 0) { @@ -1723,7 +1798,7 @@ intra: } cbp = (cbpc & 3) | (cbpy << 2); - ctx->use_intra_dc_vlc = s->qscale < ctx->intra_dc_threshold; + use_intra_dc_vlc = s->qscale < ctx->intra_dc_threshold; if (dquant) ff_set_qscale(s, s->qscale + quant_tab[get_bits(&s->gb, 2)]); @@ -1734,7 +1809,8 @@ intra: s->bdsp.clear_blocks(s->block[0]); /* decode each block */ for (i = 0; i < 6; i++) { - if (mpeg4_decode_block(ctx, block[i], i, cbp & 32, 1, 0) < 0) + if (mpeg4_decode_block(ctx, block[i], i, cbp & 32, + 1, use_intra_dc_vlc, 0) < 0) return AVERROR_INVALIDDATA; cbp += cbp; } @@ -1743,7 +1819,7 @@ intra: /* decode each block */ for (i = 0; i < 6; i++) { - if (mpeg4_decode_block(ctx, block[i], i, cbp & 32, 0, 0) < 0) + if (mpeg4_decode_block(ctx, block[i], i, cbp & 32, 0, 0, 0) < 0) return AVERROR_INVALIDDATA; cbp += cbp; } @@ -2012,9 +2088,10 @@ static int mpeg4_decode_dpcm_macroblock(MpegEncContext *s, int16_t macroblock[25 static int mpeg4_decode_studio_mb(MpegEncContext *s, int16_t block_[12][64]) { + Mpeg4DecContext *const ctx = (Mpeg4DecContext*)s; int i; - s->dpcm_direction = 0; + ctx->dpcm_direction = 0; /* StudioMacroblock */ /* Assumes I-VOP */ @@ -2028,15 +2105,15 @@ static int mpeg4_decode_studio_mb(MpegEncContext *s, int16_t block_[12][64]) } for (i = 0; i < mpeg4_block_count[s->chroma_format]; i++) { - if (mpeg4_decode_studio_block(s, (*s->block32)[i], i) < 0) + if (mpeg4_decode_studio_block(s, ctx->block32[i], i) < 0) return AVERROR_INVALIDDATA; } } else { /* DPCM */ check_marker(s->avctx, &s->gb, "DPCM block start"); - s->dpcm_direction = get_bits1(&s->gb) ? -1 : 1; + ctx->dpcm_direction = get_bits1(&s->gb) ? -1 : 1; for (i = 0; i < 3; i++) { - if (mpeg4_decode_dpcm_macroblock(s, (*s->dpcm_macroblock)[i], i) < 0) + if (mpeg4_decode_dpcm_macroblock(s, ctx->dpcm_macroblock[i], i) < 0) return AVERROR_INVALIDDATA; } } @@ -2211,7 +2288,7 @@ static void extension_and_user_data(MpegEncContext *s, GetBitContext *gb, int id static int decode_studio_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb) { MpegEncContext *s = &ctx->m; - int width, height; + int width, height, aspect_ratio_info; int bits_per_raw_sample; int rgb, chroma_format; @@ -2266,12 +2343,12 @@ static int decode_studio_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb) s->height = height; } } - s->aspect_ratio_info = get_bits(gb, 4); - if (s->aspect_ratio_info == FF_ASPECT_EXTENDED) { + aspect_ratio_info = get_bits(gb, 4); + if (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]; + s->avctx->sample_aspect_ratio = ff_h263_pixel_aspect[aspect_ratio_info]; } skip_bits(gb, 4); /* frame_rate_code */ skip_bits(gb, 15); /* first_half_bit_rate */ @@ -2297,19 +2374,19 @@ static int decode_studio_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb) static int decode_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb) { MpegEncContext *s = &ctx->m; - int width, height, vo_ver_id; + int width, height, vo_ver_id, aspect_ratio_info; /* vol header */ skip_bits(gb, 1); /* random access */ - s->vo_type = get_bits(gb, 8); + ctx->vo_type = get_bits(gb, 8); /* If we are in studio profile (per vo_type), check if its all consistent * and if so continue pass control to decode_studio_vol_header(). * elIf something is inconsistent, error out * else continue with (non studio) vol header decpoding. */ - if (s->vo_type == CORE_STUDIO_VO_TYPE || - s->vo_type == SIMPLE_STUDIO_VO_TYPE) { + if (ctx->vo_type == CORE_STUDIO_VO_TYPE || + ctx->vo_type == SIMPLE_STUDIO_VO_TYPE) { if (s->avctx->profile != FF_PROFILE_UNKNOWN && s->avctx->profile != FF_PROFILE_MPEG4_SIMPLE_STUDIO) return AVERROR_INVALIDDATA; s->studio_profile = 1; @@ -2325,12 +2402,12 @@ static int decode_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb) } else { vo_ver_id = 1; } - s->aspect_ratio_info = get_bits(gb, 4); - if (s->aspect_ratio_info == FF_ASPECT_EXTENDED) { + aspect_ratio_info = get_bits(gb, 4); + if (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]; + s->avctx->sample_aspect_ratio = ff_h263_pixel_aspect[aspect_ratio_info]; } if ((ctx->vol_control_parameters = get_bits1(gb))) { /* vol control parameter */ @@ -2356,7 +2433,7 @@ static int decode_vol_header(Mpeg4DecContext *ctx, GetBitContext *gb) /* is setting low delay flag only once the smartest thing to do? * low delay detection will not be overridden. */ if (s->picture_number == 0) { - switch(s->vo_type) { + switch (ctx->vo_type) { case SIMPLE_VO_TYPE: case ADV_SIMPLE_VO_TYPE: s->low_delay = 1; @@ -2741,7 +2818,7 @@ int ff_mpeg4_workaround_bugs(AVCodecContext *avctx) } if (ctx->xvid_build == -1 && ctx->divx_version == -1 && ctx->lavc_build == -1) - if (s->codec_tag == AV_RL32("DIVX") && s->vo_type == 0 && + if (s->codec_tag == AV_RL32("DIVX") && ctx->vo_type == 0 && ctx->vol_control_parameters == 0) ctx->divx_version = 400; // divx 4 @@ -2844,7 +2921,8 @@ int ff_mpeg4_workaround_bugs(AVCodecContext *avctx) return 0; } -static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb) +static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb, + int parse_only) { MpegEncContext *s = &ctx->m; int time_incr, time_increment; @@ -3018,6 +3096,12 @@ static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb) ff_init_scantable(s->idsp.idct_permutation, &s->intra_v_scantable, ff_alternate_vertical_scan); } + /* Skip at this point when only parsing since the remaining + * data is not useful for a parser and requires the + * sprite_trajectory VLC to be initialized. */ + if (parse_only) + goto end; + if (s->pict_type == AV_PICTURE_TYPE_S) { if((ctx->vol_sprite_usage == STATIC_SPRITE || ctx->vol_sprite_usage == GMC_SPRITE)) { @@ -3066,14 +3150,14 @@ static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb) if (s->avctx->debug & FF_DEBUG_PICT_INFO) { av_log(s->avctx, AV_LOG_DEBUG, - "qp:%d fc:%d,%d %s size:%d pro:%d alt:%d top:%d %spel part:%d resync:%d w:%d a:%d rnd:%d vot:%d%s dc:%d ce:%d/%d/%d time:%"PRId64" tincr:%d\n", + "qp:%d fc:%d,%d %c size:%d pro:%d alt:%d top:%d %cpel part:%d resync:%d w:%d a:%d rnd:%d vot:%d%s dc:%d ce:%d/%d/%d time:%"PRId64" tincr:%d\n", s->qscale, s->f_code, s->b_code, - s->pict_type == AV_PICTURE_TYPE_I ? "I" : (s->pict_type == AV_PICTURE_TYPE_P ? "P" : (s->pict_type == AV_PICTURE_TYPE_B ? "B" : "S")), + s->pict_type == AV_PICTURE_TYPE_I ? 'I' : (s->pict_type == AV_PICTURE_TYPE_P ? 'P' : (s->pict_type == AV_PICTURE_TYPE_B ? 'B' : 'S')), gb->size_in_bits,s->progressive_sequence, s->alternate_scan, - s->top_field_first, s->quarter_sample ? "q" : "h", + s->top_field_first, s->quarter_sample ? 'q' : 'h', s->data_partitioning, ctx->resync_marker, ctx->num_sprite_warping_points, s->sprite_warping_accuracy, - 1 - s->no_rounding, s->vo_type, + 1 - s->no_rounding, ctx->vo_type, ctx->vol_control_parameters ? " VOLC" : " ", ctx->intra_dc_threshold, ctx->cplx_estimation_trash_i, ctx->cplx_estimation_trash_p, ctx->cplx_estimation_trash_b, @@ -3095,10 +3179,12 @@ static int decode_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb) skip_bits(gb, 2); // ref_select_code } } + +end: /* detect buggy encoders which don't set the low_delay flag * (divx4/xvid/opendivx). Note we cannot detect divx5 without B-frames * easily (although it's buggy too) */ - if (s->vo_type == 0 && ctx->vol_control_parameters == 0 && + if (ctx->vo_type == 0 && ctx->vol_control_parameters == 0 && ctx->divx_version == -1 && s->picture_number == 0) { av_log(s->avctx, AV_LOG_WARNING, "looks like this file was encoded with (divx4/(old)xvid/opendivx) -> forcing low_delay flag\n"); @@ -3214,11 +3300,14 @@ static int decode_studiovisualobject(Mpeg4DecContext *ctx, GetBitContext *gb) * Decode MPEG-4 headers. * * @param header If set the absence of a VOP is not treated as error; otherwise, it is treated as such. + * @param parse_only If set, things only relevant to a decoder may be skipped; + * furthermore, the VLC tables may be uninitialized. * @return <0 if an error occurred * FRAME_SKIPPED if a not coded VOP is found * 0 else */ -int ff_mpeg4_decode_picture_header(Mpeg4DecContext *ctx, GetBitContext *gb, int header) +int ff_mpeg4_decode_picture_header(Mpeg4DecContext *ctx, GetBitContext *gb, + int header, int parse_only) { MpegEncContext *s = &ctx->m; unsigned startcode, v; @@ -3261,62 +3350,63 @@ int ff_mpeg4_decode_picture_header(Mpeg4DecContext *ctx, GetBitContext *gb, int continue; // no startcode if (s->avctx->debug & FF_DEBUG_STARTCODE) { - av_log(s->avctx, AV_LOG_DEBUG, "startcode: %3X ", startcode); + const char *name; if (startcode <= 0x11F) - av_log(s->avctx, AV_LOG_DEBUG, "Video Object Start"); + name = "Video Object Start"; else if (startcode <= 0x12F) - av_log(s->avctx, AV_LOG_DEBUG, "Video Object Layer Start"); + name = "Video Object Layer Start"; else if (startcode <= 0x13F) - av_log(s->avctx, AV_LOG_DEBUG, "Reserved"); + name = "Reserved"; else if (startcode <= 0x15F) - av_log(s->avctx, AV_LOG_DEBUG, "FGS bp start"); + name = "FGS bp start"; else if (startcode <= 0x1AF) - av_log(s->avctx, AV_LOG_DEBUG, "Reserved"); + name = "Reserved"; else if (startcode == 0x1B0) - av_log(s->avctx, AV_LOG_DEBUG, "Visual Object Seq Start"); + name = "Visual Object Seq Start"; else if (startcode == 0x1B1) - av_log(s->avctx, AV_LOG_DEBUG, "Visual Object Seq End"); + name = "Visual Object Seq End"; else if (startcode == 0x1B2) - av_log(s->avctx, AV_LOG_DEBUG, "User Data"); + name = "User Data"; else if (startcode == 0x1B3) - av_log(s->avctx, AV_LOG_DEBUG, "Group of VOP start"); + name = "Group of VOP start"; else if (startcode == 0x1B4) - av_log(s->avctx, AV_LOG_DEBUG, "Video Session Error"); + name = "Video Session Error"; else if (startcode == 0x1B5) - av_log(s->avctx, AV_LOG_DEBUG, "Visual Object Start"); + name = "Visual Object Start"; else if (startcode == 0x1B6) - av_log(s->avctx, AV_LOG_DEBUG, "Video Object Plane start"); + name = "Video Object Plane start"; else if (startcode == 0x1B7) - av_log(s->avctx, AV_LOG_DEBUG, "slice start"); + name = "slice start"; else if (startcode == 0x1B8) - av_log(s->avctx, AV_LOG_DEBUG, "extension start"); + name = "extension start"; else if (startcode == 0x1B9) - av_log(s->avctx, AV_LOG_DEBUG, "fgs start"); + name = "fgs start"; else if (startcode == 0x1BA) - av_log(s->avctx, AV_LOG_DEBUG, "FBA Object start"); + name = "FBA Object start"; else if (startcode == 0x1BB) - av_log(s->avctx, AV_LOG_DEBUG, "FBA Object Plane start"); + name = "FBA Object Plane start"; else if (startcode == 0x1BC) - av_log(s->avctx, AV_LOG_DEBUG, "Mesh Object start"); + name = "Mesh Object start"; else if (startcode == 0x1BD) - av_log(s->avctx, AV_LOG_DEBUG, "Mesh Object Plane start"); + name = "Mesh Object Plane start"; else if (startcode == 0x1BE) - av_log(s->avctx, AV_LOG_DEBUG, "Still Texture Object start"); + name = "Still Texture Object start"; else if (startcode == 0x1BF) - av_log(s->avctx, AV_LOG_DEBUG, "Texture Spatial Layer start"); + name = "Texture Spatial Layer start"; else if (startcode == 0x1C0) - av_log(s->avctx, AV_LOG_DEBUG, "Texture SNR Layer start"); + name = "Texture SNR Layer start"; else if (startcode == 0x1C1) - av_log(s->avctx, AV_LOG_DEBUG, "Texture Tile start"); + name = "Texture Tile start"; else if (startcode == 0x1C2) - av_log(s->avctx, AV_LOG_DEBUG, "Texture Shape Layer start"); + name = "Texture Shape Layer start"; else if (startcode == 0x1C3) - av_log(s->avctx, AV_LOG_DEBUG, "stuffing start"); + name = "stuffing start"; else if (startcode <= 0x1C5) - av_log(s->avctx, AV_LOG_DEBUG, "reserved"); + name = "Reserved"; else if (startcode <= 0x1FF) - av_log(s->avctx, AV_LOG_DEBUG, "System start"); - av_log(s->avctx, AV_LOG_DEBUG, " at %d\n", get_bits_count(gb)); + name = "System start"; + av_log(s->avctx, AV_LOG_DEBUG, "startcode: %3X %s at %d\n", + startcode, name, get_bits_count(gb)); } if (startcode >= 0x120 && startcode <= 0x12F) { @@ -3371,35 +3461,7 @@ end: } return decode_studio_vop_header(ctx, gb); } else - return decode_vop_header(ctx, gb); -} - -av_cold void ff_mpeg4videodec_static_init(void) { - static int done = 0; - - if (!done) { - static uint8_t mpeg4_rvlc_rl_tables[2][2][2 * MAX_RUN + MAX_LEVEL + 3]; - - ff_mpeg4_init_rl_intra(); - ff_rl_init(&ff_rvlc_rl_inter, mpeg4_rvlc_rl_tables[0]); - ff_rl_init(&ff_rvlc_rl_intra, mpeg4_rvlc_rl_tables[1]); - INIT_FIRST_VLC_RL(ff_mpeg4_rl_intra, 554); - INIT_VLC_RL(ff_rvlc_rl_inter, 1072); - INIT_FIRST_VLC_RL(ff_rvlc_rl_intra, 1072); - INIT_VLC_STATIC(&dc_lum, DC_VLC_BITS, 10 /* 13 */, - &ff_mpeg4_DCtab_lum[0][1], 2, 1, - &ff_mpeg4_DCtab_lum[0][0], 2, 1, 512); - INIT_VLC_STATIC(&dc_chrom, DC_VLC_BITS, 10 /* 13 */, - &ff_mpeg4_DCtab_chrom[0][1], 2, 1, - &ff_mpeg4_DCtab_chrom[0][0], 2, 1, 512); - INIT_VLC_STATIC_FROM_LENGTHS(&sprite_trajectory, SPRITE_TRAJ_VLC_BITS, 15, - ff_sprite_trajectory_lens, 1, - NULL, 0, 0, 0, 0, 128); - INIT_VLC_STATIC(&mb_type_b_vlc, MB_TYPE_B_VLC_BITS, 4, - &ff_mb_type_b_tab[0][1], 2, 1, - &ff_mb_type_b_tab[0][0], 2, 1, 16); - done = 1; - } + return decode_vop_header(ctx, gb, parse_only); } int ff_mpeg4_frame_end(AVCodecContext *avctx, const uint8_t *buf, int buf_size) @@ -3476,12 +3538,12 @@ static int mpeg4_update_thread_context(AVCodecContext *dst, s->new_pred = s1->new_pred; s->enhancement_type = s1->enhancement_type; s->scalability = s1->scalability; - s->use_intra_dc_vlc = s1->use_intra_dc_vlc; s->intra_dc_threshold = s1->intra_dc_threshold; s->divx_version = s1->divx_version; s->divx_build = s1->divx_build; s->xvid_build = s1->xvid_build; s->lavc_build = s1->lavc_build; + s->vo_type = s1->vo_type; s->showed_packed_warning = s1->showed_packed_warning; s->vol_control_parameters = s1->vol_control_parameters; s->cplx_estimation_trash_i = s1->cplx_estimation_trash_i; @@ -3513,6 +3575,8 @@ static int mpeg4_update_thread_context_for_user(AVCodecContext *dst, static av_cold void mpeg4_init_static(void) { + static uint8_t mpeg4_rvlc_rl_tables[2][2][2 * MAX_RUN + MAX_LEVEL + 3]; + INIT_VLC_STATIC_FROM_LENGTHS(&studio_luma_dc, STUDIO_INTRA_BITS, 19, &ff_mpeg4_studio_dc_luma[0][1], 2, &ff_mpeg4_studio_dc_luma[0][0], 2, 1, @@ -3524,7 +3588,7 @@ static av_cold void mpeg4_init_static(void) 0, 0, 528); for (unsigned i = 0, offset = 0; i < 12; i++) { - static VLC_TYPE vlc_buf[6498][2]; + static VLCElem vlc_buf[6498]; studio_intra_tab[i].table = &vlc_buf[offset]; studio_intra_tab[i].table_allocated = FF_ARRAY_ELEMS(vlc_buf) - offset; @@ -3535,7 +3599,25 @@ static av_cold void mpeg4_init_static(void) 0, INIT_VLC_STATIC_OVERLONG, NULL); offset += studio_intra_tab[i].table_size; } - ff_mpeg4videodec_static_init(); + + ff_mpeg4_init_rl_intra(); + ff_rl_init(&ff_rvlc_rl_inter, mpeg4_rvlc_rl_tables[0]); + ff_rl_init(&ff_rvlc_rl_intra, mpeg4_rvlc_rl_tables[1]); + INIT_FIRST_VLC_RL(ff_mpeg4_rl_intra, 554); + INIT_VLC_RL(ff_rvlc_rl_inter, 1072); + INIT_FIRST_VLC_RL(ff_rvlc_rl_intra, 1072); + INIT_VLC_STATIC(&dc_lum, DC_VLC_BITS, 10 /* 13 */, + &ff_mpeg4_DCtab_lum[0][1], 2, 1, + &ff_mpeg4_DCtab_lum[0][0], 2, 1, 512); + INIT_VLC_STATIC(&dc_chrom, DC_VLC_BITS, 10 /* 13 */, + &ff_mpeg4_DCtab_chrom[0][1], 2, 1, + &ff_mpeg4_DCtab_chrom[0][0], 2, 1, 512); + INIT_VLC_STATIC_FROM_LENGTHS(&sprite_trajectory, SPRITE_TRAJ_VLC_BITS, 15, + ff_sprite_trajectory_lens, 1, + NULL, 0, 0, 0, 0, 128); + INIT_VLC_STATIC(&mb_type_b_vlc, MB_TYPE_B_VLC_BITS, 4, + &ff_mb_type_b_tab[0][1], 2, 1, + &ff_mb_type_b_tab[0][0], 2, 1, 16); } static av_cold int decode_init(AVCodecContext *avctx) @@ -3580,29 +3662,30 @@ static const AVClass mpeg4_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_mpeg4_decoder = { - .name = "mpeg4", - .long_name = NULL_IF_CONFIG_SMALL("MPEG-4 part 2"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MPEG4, +const FFCodec ff_mpeg4_decoder = { + .p.name = "mpeg4", + .p.long_name = NULL_IF_CONFIG_SMALL("MPEG-4 part 2"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MPEG4, .priv_data_size = sizeof(Mpeg4DecContext), .init = decode_init, .close = ff_h263_decode_end, - .decode = ff_h263_decode_frame, - .capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 | + FF_CODEC_DECODE_CB(ff_h263_decode_frame), + .p.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 | #if FF_API_FLAG_TRUNCATED AV_CODEC_CAP_TRUNCATED | #endif AV_CODEC_CAP_DELAY | AV_CODEC_CAP_FRAME_THREADS, - .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM | + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM | FF_CODEC_CAP_ALLOCATE_PROGRESS, .flush = ff_mpeg_flush, - .max_lowres = 3, - .pix_fmts = ff_h263_hwaccel_pixfmt_list_420, - .profiles = NULL_IF_CONFIG_SMALL(ff_mpeg4_video_profiles), + .p.max_lowres = 3, + .p.pix_fmts = ff_h263_hwaccel_pixfmt_list_420, + .p.profiles = NULL_IF_CONFIG_SMALL(ff_mpeg4_video_profiles), .update_thread_context = ONLY_IF_THREADS_ENABLED(mpeg4_update_thread_context), .update_thread_context_for_user = ONLY_IF_THREADS_ENABLED(mpeg4_update_thread_context_for_user), - .priv_class = &mpeg4_class, + .p.priv_class = &mpeg4_class, .hw_configs = (const AVCodecHWConfigInternal *const []) { #if CONFIG_MPEG4_NVDEC_HWACCEL HWACCEL_NVDEC(mpeg4), diff --git a/libavcodec/mpeg4videodec.h b/libavcodec/mpeg4videodec.h new file mode 100644 index 000000000..65d846aed --- /dev/null +++ b/libavcodec/mpeg4videodec.h @@ -0,0 +1,99 @@ +/* + * MPEG-4 decoder internal header. + * Copyright (c) 2000,2001 Fabrice Bellard + * Copyright (c) 2002-2010 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 + */ + +#ifndef AVCODEC_MPEG4VIDEODEC_H +#define AVCODEC_MPEG4VIDEODEC_H + +#include + +#include "get_bits.h" +#include "mpegvideo.h" + + +typedef struct Mpeg4DecContext { + MpegEncContext m; + + /// number of bits to represent the fractional part of time + int time_increment_bits; + int shape; + int vol_sprite_usage; + int sprite_brightness_change; + int num_sprite_warping_points; + /// sprite trajectory points + uint16_t sprite_traj[4][2]; + /// sprite shift [isChroma] + int sprite_shift[2]; + + // reversible vlc + int rvlc; + /// could this stream contain resync markers + int resync_marker; + /// time distance of first I -> B, used for interlaced B-frames + int t_frame; + + int new_pred; + int enhancement_type; + int scalability; + + /// QP above which the ac VLC should be used for intra dc + int intra_dc_threshold; + + /* bug workarounds */ + int divx_version; + int divx_build; + int xvid_build; + int lavc_build; + + int vo_type; + + /// flag for having shown the warning about invalid Divx B-frames + int showed_packed_warning; + /** does the stream contain the low_delay flag, + * used to work around buggy encoders. */ + int vol_control_parameters; + int cplx_estimation_trash_i; + int cplx_estimation_trash_p; + int cplx_estimation_trash_b; + + int rgb; + + int32_t block32[12][64]; + // 0 = DCT, 1 = DPCM top to bottom scan, -1 = DPCM bottom to top scan + int dpcm_direction; + int16_t dpcm_macroblock[3][256]; +} Mpeg4DecContext; + +int ff_mpeg4_decode_picture_header(Mpeg4DecContext *ctx, GetBitContext *gb, + int header, int parse_only); +void ff_mpeg4_decode_studio(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb, + uint8_t *dest_cr, int block_size, int uvlinesize, + int dct_linesize, int dct_offset); +int ff_mpeg4_decode_partitions(Mpeg4DecContext *ctx); +int ff_mpeg4_decode_video_packet_header(Mpeg4DecContext *ctx); +int ff_mpeg4_decode_studio_slice_header(Mpeg4DecContext *ctx); +int ff_mpeg4_workaround_bugs(AVCodecContext *avctx); +void ff_mpeg4_pred_ac(MpegEncContext *s, int16_t *block, int n, + int dir); +int ff_mpeg4_frame_end(AVCodecContext *avctx, const uint8_t *buf, int buf_size); + + +#endif diff --git a/libavcodec/mpeg4videoenc.c b/libavcodec/mpeg4videoenc.c index b77653d45..8f0452de3 100644 --- a/libavcodec/mpeg4videoenc.c +++ b/libavcodec/mpeg4videoenc.c @@ -24,11 +24,17 @@ #include "libavutil/log.h" #include "libavutil/opt.h" #include "libavutil/thread.h" +#include "codec_internal.h" #include "mpegutils.h" #include "mpegvideo.h" #include "h263.h" +#include "h263enc.h" #include "mpeg4video.h" +#include "mpeg4videodata.h" +#include "mpeg4videoenc.h" +#include "mpegvideoenc.h" #include "profiles.h" +#include "version.h" /* The uni_DCtab_* tables below contain unified bits+length tables to encode DC * differences in MPEG-4. Unified in the sense that the specification specifies @@ -560,8 +566,6 @@ void ff_mpeg4_encode_mb(MpegEncContext *s, int16_t block[6][64], if (!mb_type) { av_assert2(s->mv_dir & MV_DIRECT); ff_h263_encode_motion_vector(s, motion_x, motion_y, 1); - s->b_count++; - s->f_count++; } else { av_assert2(mb_type > 0 && mb_type < 4); if (s->mv_type != MV_TYPE_FIELD) { @@ -574,7 +578,6 @@ void ff_mpeg4_encode_mb(MpegEncContext *s, int16_t block[6][64], s->last_mv[0][1][0] = s->mv[0][0][0]; s->last_mv[0][0][1] = s->last_mv[0][1][1] = s->mv[0][0][1]; - s->f_count++; } if (s->mv_dir & MV_DIR_BACKWARD) { ff_h263_encode_motion_vector(s, @@ -585,7 +588,6 @@ void ff_mpeg4_encode_mb(MpegEncContext *s, int16_t block[6][64], s->last_mv[1][1][0] = s->mv[1][0][0]; s->last_mv[1][0][1] = s->last_mv[1][1][1] = s->mv[1][0][1]; - s->b_count++; } } else { if (s->mv_dir & MV_DIR_FORWARD) { @@ -605,7 +607,6 @@ void ff_mpeg4_encode_mb(MpegEncContext *s, int16_t block[6][64], s->last_mv[0][i][0] = s->mv[0][i][0]; s->last_mv[0][i][1] = s->mv[0][i][1] * 2; } - s->f_count++; } if (s->mv_dir & MV_DIR_BACKWARD) { for (i = 0; i < 2; i++) { @@ -616,7 +617,6 @@ void ff_mpeg4_encode_mb(MpegEncContext *s, int16_t block[6][64], s->last_mv[1][i][0] = s->mv[1][i][0]; s->last_mv[1][i][1] = s->mv[1][i][1] * 2; } - s->b_count++; } } } @@ -645,7 +645,7 @@ void ff_mpeg4_encode_mb(MpegEncContext *s, int16_t block[6][64], y = s->mb_y * 16; offset = x + y * s->linesize; - p_pic = s->new_picture.f->data[0] + offset; + p_pic = s->new_picture->data[0] + offset; s->mb_skipped = 1; for (i = 0; i < s->max_b_frames; i++) { @@ -792,8 +792,6 @@ void ff_mpeg4_encode_mb(MpegEncContext *s, int16_t block[6][64], if (interleaved_stats) s->p_tex_bits += get_bits_diff(s); - - s->f_count++; } } else { int cbp; @@ -960,14 +958,14 @@ static void mpeg4_encode_vol_header(MpegEncContext *s, int vo_number, int vol_number) { - int vo_ver_id; + int vo_ver_id, vo_type, aspect_ratio_info; if (s->max_b_frames || s->quarter_sample) { vo_ver_id = 5; - s->vo_type = ADV_SIMPLE_VO_TYPE; + vo_type = ADV_SIMPLE_VO_TYPE; } else { vo_ver_id = 1; - s->vo_type = SIMPLE_VO_TYPE; + vo_type = SIMPLE_VO_TYPE; } put_bits(&s->pb, 16, 0); @@ -976,7 +974,7 @@ static void mpeg4_encode_vol_header(MpegEncContext *s, put_bits(&s->pb, 16, 0x120 + vol_number); /* video obj layer */ put_bits(&s->pb, 1, 0); /* random access vol */ - put_bits(&s->pb, 8, s->vo_type); /* video obj type indication */ + put_bits(&s->pb, 8, vo_type); /* video obj type indication */ if (s->workaround_bugs & FF_BUG_MS) { put_bits(&s->pb, 1, 0); /* is obj layer id= no */ } else { @@ -985,10 +983,10 @@ static void mpeg4_encode_vol_header(MpegEncContext *s, put_bits(&s->pb, 3, 1); /* is obj layer priority */ } - s->aspect_ratio_info = ff_h263_aspect_to_info(s->avctx->sample_aspect_ratio); + aspect_ratio_info = ff_h263_aspect_to_info(s->avctx->sample_aspect_ratio); - put_bits(&s->pb, 4, s->aspect_ratio_info); /* aspect ratio info */ - if (s->aspect_ratio_info == FF_ASPECT_EXTENDED) { + put_bits(&s->pb, 4, aspect_ratio_info); /* aspect ratio info */ + if (aspect_ratio_info == FF_ASPECT_EXTENDED) { av_reduce(&s->avctx->sample_aspect_ratio.num, &s->avctx->sample_aspect_ratio.den, s->avctx->sample_aspect_ratio.num, s->avctx->sample_aspect_ratio.den, 255); put_bits(&s->pb, 8, s->avctx->sample_aspect_ratio.num); @@ -1064,9 +1062,9 @@ int ff_mpeg4_encode_picture_header(MpegEncContext *s, int picture_number) if (s->pict_type == AV_PICTURE_TYPE_I) { if (!(s->avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER)) { - if (s->strict_std_compliance < FF_COMPLIANCE_VERY_STRICT) // HACK, the reference sw is buggy + if (s->avctx->strict_std_compliance < FF_COMPLIANCE_VERY_STRICT) // HACK, the reference sw is buggy mpeg4_encode_visual_object_header(s); - if (s->strict_std_compliance < FF_COMPLIANCE_VERY_STRICT || picture_number == 0) // HACK, the reference sw is buggy + if (s->avctx->strict_std_compliance < FF_COMPLIANCE_VERY_STRICT || picture_number == 0) // HACK, the reference sw is buggy mpeg4_encode_vol_header(s, 0, 0); } if (!(s->workaround_bugs & FF_BUG_MS)) @@ -1381,10 +1379,7 @@ static const AVOption options[] = { OFFSET(mpeg_quant), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 1, VE }, FF_MPV_COMMON_BFRAME_OPTS FF_MPV_COMMON_OPTS -#if FF_API_MPEGVIDEO_OPTS - FF_MPV_DEPRECATED_A53_CC_OPT - FF_MPV_DEPRECATED_MATRIX_OPT -#endif + FF_MPV_COMMON_MOTION_EST_OPTS FF_MPEG4_PROFILE_OPTS { NULL }, }; @@ -1396,17 +1391,17 @@ static const AVClass mpeg4enc_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_mpeg4_encoder = { - .name = "mpeg4", - .long_name = NULL_IF_CONFIG_SMALL("MPEG-4 part 2"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MPEG4, +const FFCodec ff_mpeg4_encoder = { + .p.name = "mpeg4", + .p.long_name = NULL_IF_CONFIG_SMALL("MPEG-4 part 2"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MPEG4, .priv_data_size = sizeof(MpegEncContext), .init = encode_init, - .encode2 = ff_mpv_encode_picture, + FF_CODEC_ENCODE_CB(ff_mpv_encode_picture), .close = ff_mpv_encode_end, - .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS, + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .priv_class = &mpeg4enc_class, + .p.priv_class = &mpeg4enc_class, }; diff --git a/libavcodec/mpeg4videoenc.h b/libavcodec/mpeg4videoenc.h new file mode 100644 index 000000000..243cd297a --- /dev/null +++ b/libavcodec/mpeg4videoenc.h @@ -0,0 +1,43 @@ +/* + * MPEG-4 encoder internal header. + * Copyright (c) 2000,2001 Fabrice Bellard + * Copyright (c) 2002-2010 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 + */ + +#ifndef AVCODEC_MPEG4VIDEOENC_H +#define AVCODEC_MPEG4VIDEOENC_H + +#include + +#include "mpegvideo.h" +#include "put_bits.h" + +void ff_mpeg4_encode_mb(MpegEncContext *s, + int16_t block[6][64], + int motion_x, int motion_y); +void ff_set_mpeg4_time(MpegEncContext *s); +int ff_mpeg4_encode_picture_header(MpegEncContext *s, int picture_number); + +void ff_mpeg4_encode_video_packet_header(MpegEncContext *s); +void ff_mpeg4_stuffing(PutBitContext *pbc); +void ff_mpeg4_init_partitions(MpegEncContext *s); +void ff_mpeg4_merge_partitions(MpegEncContext *s); +void ff_clean_mpeg4_qscales(MpegEncContext *s); + +#endif diff --git a/libavcodec/mpegaudio_parser.c b/libavcodec/mpegaudio_parser.c index 2549503d3..d54366f10 100644 --- a/libavcodec/mpegaudio_parser.c +++ b/libavcodec/mpegaudio_parser.c @@ -84,7 +84,8 @@ static int mpegaudio_parse(AVCodecParserContext *s1, if (s->header_count > header_threshold) { avctx->sample_rate= sr; - avctx->channels = channels; + av_channel_layout_uninit(&avctx->ch_layout); + av_channel_layout_default(&avctx->ch_layout, channels); s1->duration = frame_size; avctx->codec_id = codec_id; if (s->no_bitrate || !avctx->bit_rate) { diff --git a/libavcodec/mpegaudiodec_common.c b/libavcodec/mpegaudiodec_common.c index a963f6683..71fc2e7c8 100644 --- a/libavcodec/mpegaudiodec_common.c +++ b/libavcodec/mpegaudiodec_common.c @@ -28,6 +28,7 @@ #include #include "libavutil/avassert.h" +#include "libavutil/libm.h" #include "libavutil/thread.h" #include "mpegaudiodata.h" @@ -64,10 +65,10 @@ const uint8_t ff_lsf_nsf_table[6][3][4] = { /* mpegaudio layer 3 huffman tables */ VLC ff_huff_vlc[16]; -static VLC_TYPE huff_vlc_tables[128 + 128 + 128 + 130 + 128 + 154 + 166 + 142 + - 204 + 190 + 170 + 542 + 460 + 662 + 414][2]; +static VLCElem huff_vlc_tables[128 + 128 + 128 + 130 + 128 + 154 + 166 + 142 + + 204 + 190 + 170 + 542 + 460 + 662 + 414]; VLC ff_huff_quad_vlc[2]; -static VLC_TYPE huff_quad_vlc_tables[64 + 16][2]; +static VLCElem huff_quad_vlc_tables[64 + 16]; static const uint8_t mpa_hufflens[] = { /* Huffman table 1 - 4 entries */ diff --git a/libavcodec/mpegaudiodec_fixed.c b/libavcodec/mpegaudiodec_fixed.c index f9f24330f..8a5721d38 100644 --- a/libavcodec/mpegaudiodec_fixed.c +++ b/libavcodec/mpegaudiodec_fixed.c @@ -19,10 +19,12 @@ */ #include "config.h" +#include "config_components.h" #include "libavutil/samplefmt.h" #define USE_FLOATS 0 +#include "codec_internal.h" #include "mpegaudio.h" #define SHR(a,b) (((int)(a))>>(b)) @@ -59,91 +61,91 @@ static const int32_t csa_table[8][4] = { #include "mpegaudiodec_template.c" #if CONFIG_MP1_DECODER -const AVCodec ff_mp1_decoder = { - .name = "mp1", - .long_name = NULL_IF_CONFIG_SMALL("MP1 (MPEG audio layer 1)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_MP1, +const FFCodec ff_mp1_decoder = { + .p.name = "mp1", + .p.long_name = NULL_IF_CONFIG_SMALL("MP1 (MPEG audio layer 1)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_MP1, .priv_data_size = sizeof(MPADecodeContext), .init = decode_init, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1, .flush = flush, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_MP2_DECODER -const AVCodec ff_mp2_decoder = { - .name = "mp2", - .long_name = NULL_IF_CONFIG_SMALL("MP2 (MPEG audio layer 2)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_MP2, +const FFCodec ff_mp2_decoder = { + .p.name = "mp2", + .p.long_name = NULL_IF_CONFIG_SMALL("MP2 (MPEG audio layer 2)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_MP2, .priv_data_size = sizeof(MPADecodeContext), .init = decode_init, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1, .flush = flush, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_MP3_DECODER -const AVCodec ff_mp3_decoder = { - .name = "mp3", - .long_name = NULL_IF_CONFIG_SMALL("MP3 (MPEG audio layer 3)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_MP3, +const FFCodec ff_mp3_decoder = { + .p.name = "mp3", + .p.long_name = NULL_IF_CONFIG_SMALL("MP3 (MPEG audio layer 3)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_MP3, .priv_data_size = sizeof(MPADecodeContext), .init = decode_init, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1, .flush = flush, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_MP3ADU_DECODER -const AVCodec ff_mp3adu_decoder = { - .name = "mp3adu", - .long_name = NULL_IF_CONFIG_SMALL("ADU (Application Data Unit) MP3 (MPEG audio layer 3)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_MP3ADU, +const FFCodec ff_mp3adu_decoder = { + .p.name = "mp3adu", + .p.long_name = NULL_IF_CONFIG_SMALL("ADU (Application Data Unit) MP3 (MPEG audio layer 3)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_MP3ADU, .priv_data_size = sizeof(MPADecodeContext), .init = decode_init, - .decode = decode_frame_adu, - .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + FF_CODEC_DECODE_CB(decode_frame_adu), + .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1, .flush = flush, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_MP3ON4_DECODER -const AVCodec ff_mp3on4_decoder = { - .name = "mp3on4", - .long_name = NULL_IF_CONFIG_SMALL("MP3onMP4"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_MP3ON4, +const FFCodec ff_mp3on4_decoder = { + .p.name = "mp3on4", + .p.long_name = NULL_IF_CONFIG_SMALL("MP3onMP4"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_MP3ON4, .priv_data_size = sizeof(MP3On4DecodeContext), .init = decode_init_mp3on4, .close = decode_close_mp3on4, - .decode = decode_frame_mp3on4, - .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + FF_CODEC_DECODE_CB(decode_frame_mp3on4), + .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1, .flush = flush_mp3on4, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/mpegaudiodec_float.c b/libavcodec/mpegaudiodec_float.c index c7b783999..bcd55069a 100644 --- a/libavcodec/mpegaudiodec_float.c +++ b/libavcodec/mpegaudiodec_float.c @@ -20,10 +20,12 @@ */ #include "config.h" +#include "config_components.h" #include "libavutil/samplefmt.h" #define USE_FLOATS 1 +#include "codec_internal.h" #include "mpegaudio.h" #define SHR(a,b) ((a)*(1.0f/(1<<(b)))) @@ -72,91 +74,91 @@ static const float csa_table[8][4] = { #include "mpegaudiodec_template.c" #if CONFIG_MP1FLOAT_DECODER -const AVCodec ff_mp1float_decoder = { - .name = "mp1float", - .long_name = NULL_IF_CONFIG_SMALL("MP1 (MPEG audio layer 1)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_MP1, +const FFCodec ff_mp1float_decoder = { + .p.name = "mp1float", + .p.long_name = NULL_IF_CONFIG_SMALL("MP1 (MPEG audio layer 1)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_MP1, .priv_data_size = sizeof(MPADecodeContext), .init = decode_init, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1, .flush = flush, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_MP2FLOAT_DECODER -const AVCodec ff_mp2float_decoder = { - .name = "mp2float", - .long_name = NULL_IF_CONFIG_SMALL("MP2 (MPEG audio layer 2)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_MP2, +const FFCodec ff_mp2float_decoder = { + .p.name = "mp2float", + .p.long_name = NULL_IF_CONFIG_SMALL("MP2 (MPEG audio layer 2)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_MP2, .priv_data_size = sizeof(MPADecodeContext), .init = decode_init, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1, .flush = flush, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_MP3FLOAT_DECODER -const AVCodec ff_mp3float_decoder = { - .name = "mp3float", - .long_name = NULL_IF_CONFIG_SMALL("MP3 (MPEG audio layer 3)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_MP3, +const FFCodec ff_mp3float_decoder = { + .p.name = "mp3float", + .p.long_name = NULL_IF_CONFIG_SMALL("MP3 (MPEG audio layer 3)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_MP3, .priv_data_size = sizeof(MPADecodeContext), .init = decode_init, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1, .flush = flush, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_MP3ADUFLOAT_DECODER -const AVCodec ff_mp3adufloat_decoder = { - .name = "mp3adufloat", - .long_name = NULL_IF_CONFIG_SMALL("ADU (Application Data Unit) MP3 (MPEG audio layer 3)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_MP3ADU, +const FFCodec ff_mp3adufloat_decoder = { + .p.name = "mp3adufloat", + .p.long_name = NULL_IF_CONFIG_SMALL("ADU (Application Data Unit) MP3 (MPEG audio layer 3)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_MP3ADU, .priv_data_size = sizeof(MPADecodeContext), .init = decode_init, - .decode = decode_frame_adu, - .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + FF_CODEC_DECODE_CB(decode_frame_adu), + .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1, .flush = flush, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_MP3ON4FLOAT_DECODER -const AVCodec ff_mp3on4float_decoder = { - .name = "mp3on4float", - .long_name = NULL_IF_CONFIG_SMALL("MP3onMP4"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_MP3ON4, +const FFCodec ff_mp3on4float_decoder = { + .p.name = "mp3on4float", + .p.long_name = NULL_IF_CONFIG_SMALL("MP3onMP4"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_MP3ON4, .priv_data_size = sizeof(MP3On4DecodeContext), .init = decode_init_mp3on4, .close = decode_close_mp3on4, - .decode = decode_frame_mp3on4, - .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + FF_CODEC_DECODE_CB(decode_frame_mp3on4), + .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1, .flush = flush_mp3on4, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/mpegaudiodec_template.c b/libavcodec/mpegaudiodec_template.c index bbb6ff112..a28cac986 100644 --- a/libavcodec/mpegaudiodec_template.c +++ b/libavcodec/mpegaudiodec_template.c @@ -24,6 +24,8 @@ * MPEG Audio decoder */ +#include "config_components.h" + #include "libavutil/attributes.h" #include "libavutil/avassert.h" #include "libavutil/channel_layout.h" @@ -1546,8 +1548,8 @@ static int mp_decode_frame(MPADecodeContext *s, OUT_INT **samples, return nb_frames * 32 * sizeof(OUT_INT) * s->nb_channels; } -static int decode_frame(AVCodecContext * avctx, void *data, int *got_frame_ptr, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame_ptr, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; @@ -1580,8 +1582,9 @@ static int decode_frame(AVCodecContext * avctx, void *data, int *got_frame_ptr, return AVERROR_INVALIDDATA; } /* update codec info */ - avctx->channels = s->nb_channels; - avctx->channel_layout = s->nb_channels == 1 ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = s->nb_channels == 1 ? (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO : + (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; if (!avctx->bit_rate) avctx->bit_rate = s->bit_rate; @@ -1593,7 +1596,7 @@ static int decode_frame(AVCodecContext * avctx, void *data, int *got_frame_ptr, buf_size= s->frame_size; } - s->frame = data; + s->frame = frame; ret = mp_decode_frame(s, NULL, buf, buf_size); if (ret >= 0) { @@ -1630,7 +1633,7 @@ static void flush(AVCodecContext *avctx) } #if CONFIG_MP3ADU_DECODER || CONFIG_MP3ADUFLOAT_DECODER -static int decode_frame_adu(AVCodecContext *avctx, void *data, +static int decode_frame_adu(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; @@ -1661,14 +1664,15 @@ static int decode_frame_adu(AVCodecContext *avctx, void *data, } /* update codec info */ avctx->sample_rate = s->sample_rate; - avctx->channels = s->nb_channels; - avctx->channel_layout = s->nb_channels == 1 ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = s->nb_channels == 1 ? (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO : + (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; if (!avctx->bit_rate) avctx->bit_rate = s->bit_rate; s->frame_size = len; - s->frame = data; + s->frame = frame; ret = mp_decode_frame(s, NULL, buf, buf_size); if (ret < 0) { @@ -1756,8 +1760,8 @@ static av_cold int decode_init_mp3on4(AVCodecContext * avctx) } s->frames = mp3Frames[cfg.chan_config]; s->coff = chan_offset[cfg.chan_config]; - avctx->channels = ff_mpeg4audio_channels[cfg.chan_config]; - avctx->channel_layout = chan_layout[cfg.chan_config]; + av_channel_layout_uninit(&avctx->ch_layout); + av_channel_layout_from_mask(&avctx->ch_layout, chan_layout[cfg.chan_config]); if (cfg.sample_rate < 16000) s->syncword = 0xffe00000; @@ -1809,10 +1813,9 @@ static void flush_mp3on4(AVCodecContext *avctx) } -static int decode_frame_mp3on4(AVCodecContext *avctx, void *data, +static int decode_frame_mp3on4(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; MP3On4DecodeContext *s = avctx->priv_data; @@ -1854,8 +1857,8 @@ static int decode_frame_mp3on4(AVCodecContext *avctx, void *data, return AVERROR_INVALIDDATA; } - if (ch + m->nb_channels > avctx->channels || - s->coff[fr] + m->nb_channels > avctx->channels) { + if (ch + m->nb_channels > avctx->ch_layout.nb_channels || + s->coff[fr] + m->nb_channels > avctx->ch_layout.nb_channels) { av_log(avctx, AV_LOG_ERROR, "frame channel count exceeds codec " "channel count\n"); return AVERROR_INVALIDDATA; @@ -1880,7 +1883,7 @@ static int decode_frame_mp3on4(AVCodecContext *avctx, void *data, avctx->bit_rate += m->bit_rate; } - if (ch != avctx->channels) { + if (ch != avctx->ch_layout.nb_channels) { av_log(avctx, AV_LOG_ERROR, "failed to decode all channels\n"); return AVERROR_INVALIDDATA; } @@ -1888,7 +1891,7 @@ static int decode_frame_mp3on4(AVCodecContext *avctx, void *data, /* update codec info */ avctx->sample_rate = s->mp3decctx[0]->sample_rate; - frame->nb_samples = out_size / (avctx->channels * sizeof(OUT_INT)); + frame->nb_samples = out_size / (avctx->ch_layout.nb_channels * sizeof(OUT_INT)); *got_frame_ptr = 1; return buf_size; diff --git a/libavcodec/mpegaudiodecheader.c b/libavcodec/mpegaudiodecheader.c index 446a6e29d..ef63befbf 100644 --- a/libavcodec/mpegaudiodecheader.c +++ b/libavcodec/mpegaudiodecheader.c @@ -24,7 +24,7 @@ * MPEG Audio header decoder. */ -#include "libavutil/common.h" +#include "libavutil/macros.h" #include "mpegaudio.h" #include "mpegaudiodata.h" diff --git a/libavcodec/mpegaudiodsp.c b/libavcodec/mpegaudiodsp.c index f03e24464..5a5a679d9 100644 --- a/libavcodec/mpegaudiodsp.c +++ b/libavcodec/mpegaudiodsp.c @@ -74,8 +74,9 @@ static av_cold void mpadsp_init_tabs(void) } } - if (ARCH_X86) - ff_mpadsp_init_x86_tabs(); +#if ARCH_X86 + ff_mpadsp_init_x86_tabs(); +#endif } av_cold void ff_mpadsp_init(MPADSPContext *s) @@ -94,10 +95,19 @@ av_cold void ff_mpadsp_init(MPADSPContext *s) s->imdct36_blocks_float = ff_imdct36_blocks_float; s->imdct36_blocks_fixed = ff_imdct36_blocks_fixed; - if (ARCH_AARCH64) ff_mpadsp_init_aarch64(s); - if (ARCH_ARM) ff_mpadsp_init_arm(s); - if (ARCH_PPC) ff_mpadsp_init_ppc(s); - if (ARCH_X86) ff_mpadsp_init_x86(s); - if (HAVE_MIPSFPU) ff_mpadsp_init_mipsfpu(s); - if (HAVE_MIPSDSP) ff_mpadsp_init_mipsdsp(s); +#if ARCH_AARCH64 + ff_mpadsp_init_aarch64(s); +#elif ARCH_ARM + ff_mpadsp_init_arm(s); +#elif ARCH_PPC + ff_mpadsp_init_ppc(s); +#elif ARCH_X86 + ff_mpadsp_init_x86(s); +#endif +#if HAVE_MIPSFPU + ff_mpadsp_init_mipsfpu(s); +#endif +#if HAVE_MIPSDSP + ff_mpadsp_init_mipsdsp(s); +#endif } diff --git a/libavcodec/mpegaudiodsp.h b/libavcodec/mpegaudiodsp.h index 4577d515d..7bc635191 100644 --- a/libavcodec/mpegaudiodsp.h +++ b/libavcodec/mpegaudiodsp.h @@ -22,7 +22,7 @@ #include #include -#include "libavutil/common.h" +#include "libavutil/macros.h" typedef struct MPADSPContext { void (*apply_window_float)(float *synth_buf, float *window, diff --git a/libavcodec/mpegaudioenc_fixed.c b/libavcodec/mpegaudioenc_fixed.c index fb1ba4e1b..74cb4b8d5 100644 --- a/libavcodec/mpegaudioenc_fixed.c +++ b/libavcodec/mpegaudioenc_fixed.c @@ -20,24 +20,30 @@ */ #include "libavutil/channel_layout.h" +#include "codec_internal.h" #include "mpegaudioenc_template.c" -const AVCodec ff_mp2fixed_encoder = { - .name = "mp2fixed", - .long_name = NULL_IF_CONFIG_SMALL("MP2 fixed point (MPEG audio layer 2)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_MP2, +const FFCodec ff_mp2fixed_encoder = { + .p.name = "mp2fixed", + .p.long_name = NULL_IF_CONFIG_SMALL("MP2 fixed point (MPEG audio layer 2)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_MP2, .priv_data_size = sizeof(MpegAudioContext), .init = MPA_encode_init, - .encode2 = MPA_encode_frame, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + FF_CODEC_ENCODE_CB(MPA_encode_frame), + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, - .supported_samplerates = (const int[]){ + .p.supported_samplerates = (const int[]){ 44100, 48000, 32000, 22050, 24000, 16000, 0 }, - .channel_layouts = (const uint64_t[]){ AV_CH_LAYOUT_MONO, +#if FF_API_OLD_CHANNEL_LAYOUT + .p.channel_layouts = (const uint64_t[]){ AV_CH_LAYOUT_MONO, AV_CH_LAYOUT_STEREO, 0 }, +#endif + .p.ch_layouts = (const AVChannelLayout[]){ AV_CHANNEL_LAYOUT_MONO, + AV_CHANNEL_LAYOUT_STEREO, + { 0 } }, .defaults = mp2_defaults, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/mpegaudioenc_float.c b/libavcodec/mpegaudioenc_float.c index accb909a6..0a597b7e0 100644 --- a/libavcodec/mpegaudioenc_float.c +++ b/libavcodec/mpegaudioenc_float.c @@ -21,24 +21,30 @@ #include "libavutil/channel_layout.h" #define USE_FLOATS 1 +#include "codec_internal.h" #include "mpegaudioenc_template.c" -const AVCodec ff_mp2_encoder = { - .name = "mp2", - .long_name = NULL_IF_CONFIG_SMALL("MP2 (MPEG audio layer 2)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_MP2, +const FFCodec ff_mp2_encoder = { + .p.name = "mp2", + .p.long_name = NULL_IF_CONFIG_SMALL("MP2 (MPEG audio layer 2)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_MP2, .priv_data_size = sizeof(MpegAudioContext), .init = MPA_encode_init, - .encode2 = MPA_encode_frame, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + FF_CODEC_ENCODE_CB(MPA_encode_frame), + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, - .supported_samplerates = (const int[]){ + .p.supported_samplerates = (const int[]){ 44100, 48000, 32000, 22050, 24000, 16000, 0 }, - .channel_layouts = (const uint64_t[]){ AV_CH_LAYOUT_MONO, +#if FF_API_OLD_CHANNEL_LAYOUT + .p.channel_layouts = (const uint64_t[]){ AV_CH_LAYOUT_MONO, AV_CH_LAYOUT_STEREO, 0 }, +#endif + .p.ch_layouts = (const AVChannelLayout[]){ AV_CHANNEL_LAYOUT_MONO, + AV_CHANNEL_LAYOUT_STEREO, + { 0 } }, .defaults = mp2_defaults, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/mpegaudioenc_template.c b/libavcodec/mpegaudioenc_template.c index 1ffd31f7c..839bd98dd 100644 --- a/libavcodec/mpegaudioenc_template.c +++ b/libavcodec/mpegaudioenc_template.c @@ -79,7 +79,7 @@ static av_cold int MPA_encode_init(AVCodecContext *avctx) MpegAudioContext *s = avctx->priv_data; int freq = avctx->sample_rate; int bitrate = avctx->bit_rate; - int channels = avctx->channels; + int channels = avctx->ch_layout.nb_channels; int i, v, table; float a; @@ -779,7 +779,7 @@ static int MPA_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, return 0; } -static const AVCodecDefault mp2_defaults[] = { +static const FFCodecDefault mp2_defaults[] = { { "b", "0" }, { NULL }, }; diff --git a/libavcodec/mpegpicture.c b/libavcodec/mpegpicture.c index 0652b7c87..aaa1df0bd 100644 --- a/libavcodec/mpegpicture.c +++ b/libavcodec/mpegpicture.c @@ -26,9 +26,29 @@ #include "libavutil/imgutils.h" #include "avcodec.h" +#include "encode.h" #include "motion_est.h" #include "mpegpicture.h" #include "mpegutils.h" +#include "threadframe.h" + +static void av_noinline free_picture_tables(Picture *pic) +{ + pic->alloc_mb_width = + pic->alloc_mb_height = 0; + + av_buffer_unref(&pic->mb_var_buf); + av_buffer_unref(&pic->mc_mb_var_buf); + av_buffer_unref(&pic->mb_mean_buf); + av_buffer_unref(&pic->mbskip_table_buf); + av_buffer_unref(&pic->qscale_table_buf); + av_buffer_unref(&pic->mb_type_buf); + + for (int i = 0; i < 2; i++) { + av_buffer_unref(&pic->motion_val_buf[i]); + av_buffer_unref(&pic->ref_index_buf[i]); + } +} static int make_tables_writable(Picture *pic) { @@ -104,16 +124,17 @@ static int alloc_frame_buffer(AVCodecContext *avctx, Picture *pic, int r, ret; pic->tf.f = pic->f; - if (avctx->codec_id != AV_CODEC_ID_WMV3IMAGE && - avctx->codec_id != AV_CODEC_ID_VC1IMAGE && - avctx->codec_id != AV_CODEC_ID_MSS2) { - if (edges_needed) { - pic->f->width = avctx->width + 2 * EDGE_WIDTH; - pic->f->height = avctx->height + 2 * EDGE_WIDTH; - } - r = ff_thread_get_buffer(avctx, &pic->tf, - pic->reference ? AV_GET_BUFFER_FLAG_REF : 0); + if (edges_needed) { + pic->f->width = avctx->width + 2 * EDGE_WIDTH; + pic->f->height = avctx->height + 2 * EDGE_WIDTH; + + r = ff_encode_alloc_frame(avctx, pic->f); + } else if (avctx->codec_id != AV_CODEC_ID_WMV3IMAGE && + avctx->codec_id != AV_CODEC_ID_VC1IMAGE && + avctx->codec_id != AV_CODEC_ID_MSS2) { + r = ff_thread_get_ext_buffer(avctx, &pic->tf, + pic->reference ? AV_GET_BUFFER_FLAG_REF : 0); } else { pic->f->width = avctx->width; pic->f->height = avctx->height; @@ -240,7 +261,7 @@ int ff_alloc_picture(AVCodecContext *avctx, Picture *pic, MotionEstContext *me, if (pic->qscale_table_buf) if ( pic->alloc_mb_width != mb_width || pic->alloc_mb_height != mb_height) - ff_free_picture_tables(pic); + free_picture_tables(pic); if (shared) { av_assert0(pic->f->data[0]); @@ -285,12 +306,13 @@ int ff_alloc_picture(AVCodecContext *avctx, Picture *pic, MotionEstContext *me, fail: av_log(avctx, AV_LOG_ERROR, "Error allocating a picture.\n"); ff_mpeg_unref_picture(avctx, pic); - ff_free_picture_tables(pic); + free_picture_tables(pic); return AVERROR(ENOMEM); } /** - * Deallocate a picture. + * Deallocate a picture; frees the picture tables in case they + * need to be reallocated anyway. */ void ff_mpeg_unref_picture(AVCodecContext *avctx, Picture *pic) { @@ -302,19 +324,19 @@ void ff_mpeg_unref_picture(AVCodecContext *avctx, Picture *pic) if (avctx->codec_id != AV_CODEC_ID_WMV3IMAGE && avctx->codec_id != AV_CODEC_ID_VC1IMAGE && avctx->codec_id != AV_CODEC_ID_MSS2) - ff_thread_release_buffer(avctx, &pic->tf); + ff_thread_release_ext_buffer(avctx, &pic->tf); else if (pic->f) av_frame_unref(pic->f); av_buffer_unref(&pic->hwaccel_priv_buf); if (pic->needs_realloc) - ff_free_picture_tables(pic); + free_picture_tables(pic); memset((uint8_t*)pic + off, 0, sizeof(*pic) - off); } -int ff_update_picture_tables(Picture *dst, Picture *src) +int ff_update_picture_tables(Picture *dst, const Picture *src) { int i, ret; @@ -330,7 +352,7 @@ int ff_update_picture_tables(Picture *dst, Picture *src) } if (ret < 0) { - ff_free_picture_tables(dst); + free_picture_tables(dst); return ret; } @@ -399,7 +421,7 @@ static inline int pic_is_unused(Picture *pic) { if (!pic->f->buf[0]) return 1; - if (pic->needs_realloc && !(pic->reference & DELAYED_PIC_REF)) + if (pic->needs_realloc) return 1; return 0; } @@ -443,30 +465,15 @@ int ff_find_unused_picture(AVCodecContext *avctx, Picture *picture, int shared) if (ret >= 0 && ret < MAX_PICTURE_COUNT) { if (picture[ret].needs_realloc) { - picture[ret].needs_realloc = 0; - ff_free_picture_tables(&picture[ret]); ff_mpeg_unref_picture(avctx, &picture[ret]); } } return ret; } -void ff_free_picture_tables(Picture *pic) +void av_cold ff_mpv_picture_free(AVCodecContext *avctx, Picture *pic) { - int i; - - pic->alloc_mb_width = - pic->alloc_mb_height = 0; - - av_buffer_unref(&pic->mb_var_buf); - av_buffer_unref(&pic->mc_mb_var_buf); - av_buffer_unref(&pic->mb_mean_buf); - av_buffer_unref(&pic->mbskip_table_buf); - av_buffer_unref(&pic->qscale_table_buf); - av_buffer_unref(&pic->mb_type_buf); - - for (i = 0; i < 2; i++) { - av_buffer_unref(&pic->motion_val_buf[i]); - av_buffer_unref(&pic->ref_index_buf[i]); - } + free_picture_tables(pic); + ff_mpeg_unref_picture(avctx, pic); + av_frame_free(&pic->f); } diff --git a/libavcodec/mpegpicture.h b/libavcodec/mpegpicture.h index 4bcd66679..0671bbae8 100644 --- a/libavcodec/mpegpicture.h +++ b/libavcodec/mpegpicture.h @@ -27,8 +27,9 @@ #include "avcodec.h" #include "motion_est.h" -#include "thread.h" +#include "threadframe.h" +#define MPEGVIDEO_MAX_PLANES 4 #define MAX_PICTURE_COUNT 36 #define EDGE_WIDTH 16 @@ -88,7 +89,7 @@ typedef struct Picture { int reference; int shared; - uint64_t encoding_error[AV_NUM_DATA_POINTERS]; + uint64_t encoding_error[MPEGVIDEO_MAX_PLANES]; } Picture; /** @@ -107,8 +108,8 @@ int ff_mpeg_framesize_alloc(AVCodecContext *avctx, MotionEstContext *me, int ff_mpeg_ref_picture(AVCodecContext *avctx, Picture *dst, Picture *src); void ff_mpeg_unref_picture(AVCodecContext *avctx, Picture *picture); -void ff_free_picture_tables(Picture *pic); -int ff_update_picture_tables(Picture *dst, Picture *src); +void ff_mpv_picture_free(AVCodecContext *avctx, Picture *pic); +int ff_update_picture_tables(Picture *dst, const Picture *src); int ff_find_unused_picture(AVCodecContext *avctx, Picture *picture, int shared); diff --git a/libavcodec/mpegutils.h b/libavcodec/mpegutils.h index 07705854b..c92f9192d 100644 --- a/libavcodec/mpegutils.h +++ b/libavcodec/mpegutils.h @@ -37,12 +37,6 @@ #define PICT_BOTTOM_FIELD 2 #define PICT_FRAME 3 -/** - * Value of Picture.reference when Picture is not a reference picture, but - * is held for delayed output. - */ -#define DELAYED_PIC_REF 4 - #define MAX_MB_BYTES (30 * 16 * 16 * 3 / 8 + 120) #define MAX_FCODE 7 diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index a97465013..319934a11 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -27,28 +27,26 @@ * The simplest mpeg encoder (well, it was the simplest!). */ +#include "config_components.h" + #include "libavutil/attributes.h" #include "libavutil/avassert.h" #include "libavutil/imgutils.h" #include "libavutil/internal.h" -#include "libavutil/motion_vector.h" -#include "libavutil/video_enc_params.h" #include "avcodec.h" #include "blockdsp.h" #include "h264chroma.h" #include "idctdsp.h" -#include "internal.h" #include "mathops.h" #include "mpeg_er.h" #include "mpegutils.h" #include "mpegvideo.h" +#include "mpeg4videodec.h" #include "mpegvideodata.h" -#include "mjpegenc.h" -#include "msmpeg4.h" #include "qpeldsp.h" -#include "thread.h" -#include "wmv2.h" +#include "threadframe.h" +#include "wmv2dec.h" #include static void dct_unquantize_mpeg1_intra_c(MpegEncContext *s, @@ -311,19 +309,21 @@ static av_cold int dct_init(MpegEncContext *s) s->dct_unquantize_mpeg2_intra = dct_unquantize_mpeg2_intra_bitexact; s->dct_unquantize_mpeg2_inter = dct_unquantize_mpeg2_inter_c; - if (HAVE_INTRINSICS_NEON) - ff_mpv_common_init_neon(s); +#if HAVE_INTRINSICS_NEON + ff_mpv_common_init_neon(s); +#endif - if (ARCH_ALPHA) - ff_mpv_common_init_axp(s); - if (ARCH_ARM) - ff_mpv_common_init_arm(s); - if (ARCH_PPC) - ff_mpv_common_init_ppc(s); - if (ARCH_X86) - ff_mpv_common_init_x86(s); - if (ARCH_MIPS) - ff_mpv_common_init_mips(s); +#if ARCH_ALPHA + ff_mpv_common_init_axp(s); +#elif ARCH_ARM + ff_mpv_common_init_arm(s); +#elif ARCH_PPC + ff_mpv_common_init_ppc(s); +#elif ARCH_X86 + ff_mpv_common_init_x86(s); +#elif ARCH_MIPS + ff_mpv_common_init_mips(s); +#endif return 0; } @@ -348,14 +348,6 @@ av_cold void ff_mpv_idct_init(MpegEncContext *s) ff_init_scantable(s->idsp.idct_permutation, &s->intra_v_scantable, ff_alternate_vertical_scan); } -static int alloc_picture(MpegEncContext *s, Picture *pic) -{ - return ff_alloc_picture(s->avctx, pic, &s->me, &s->sc, 0, 0, - s->chroma_x_shift, s->chroma_y_shift, s->out_format, - s->mb_stride, s->mb_width, s->mb_height, s->b8_stride, - &s->linesize, &s->uvlinesize); -} - static int init_duplicate_context(MpegEncContext *s) { int y_size = s->b8_stride * (2 * s->mb_height + 1); @@ -384,11 +376,6 @@ static int init_duplicate_context(MpegEncContext *s) s->pblocks[i] = &s->block[i]; } - if (!(s->block32 = av_mallocz(sizeof(*s->block32))) || - !(s->dpcm_macroblock = av_mallocz(sizeof(*s->dpcm_macroblock)))) - return AVERROR(ENOMEM); - s->dpcm_direction = 0; - if (s->avctx->codec_tag == AV_RL32("VCR2")) { // exchange uv FFSWAP(void *, s->pblocks[4], s->pblocks[5]); @@ -406,12 +393,7 @@ static int init_duplicate_context(MpegEncContext *s) return 0; } -/** - * Initialize an MpegEncContext's thread contexts. Presumes that - * slice_context_count is already set and that all the fields - * that are freed/reset in free_duplicate_context() are NULL. - */ -static int init_duplicate_contexts(MpegEncContext *s) +int ff_mpv_init_duplicate_contexts(MpegEncContext *s) { int nb_slices = s->slice_context_count, ret; @@ -451,8 +433,6 @@ 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->dpcm_macroblock); av_freep(&s->ac_val_base); s->block = NULL; } @@ -479,9 +459,6 @@ static void backup_duplicate_context(MpegEncContext *bak, MpegEncContext *src) COPY(me.score_map); COPY(blocks); COPY(block); - COPY(block32); - COPY(dpcm_macroblock); - COPY(dpcm_direction); COPY(start_mb_y); COPY(end_mb_y); COPY(me.map_generation); @@ -496,7 +473,7 @@ static void backup_duplicate_context(MpegEncContext *bak, MpegEncContext *src) #undef COPY } -int ff_update_duplicate_context(MpegEncContext *dst, MpegEncContext *src) +int ff_update_duplicate_context(MpegEncContext *dst, const MpegEncContext *src) { MpegEncContext bak; int i, ret; @@ -521,146 +498,6 @@ int ff_update_duplicate_context(MpegEncContext *dst, MpegEncContext *src) return 0; } -int ff_mpeg_update_thread_context(AVCodecContext *dst, - const AVCodecContext *src) -{ - int i, ret; - MpegEncContext *s = dst->priv_data, *s1 = src->priv_data; - - if (dst == src) - return 0; - - av_assert0(s != s1); - - // FIXME can parameters change on I-frames? - // in that case dst may need a reinit - if (!s->context_initialized) { - int err; - memcpy(s, s1, sizeof(MpegEncContext)); - - s->avctx = dst; - s->bitstream_buffer = NULL; - s->bitstream_buffer_size = s->allocated_bitstream_buffer_size = 0; - - if (s1->context_initialized){ -// s->picture_range_start += MAX_PICTURE_COUNT; -// s->picture_range_end += MAX_PICTURE_COUNT; - ff_mpv_idct_init(s); - if((err = ff_mpv_common_init(s)) < 0){ - memset(s, 0, sizeof(MpegEncContext)); - s->avctx = dst; - return err; - } - } - } - - if (s->height != s1->height || s->width != s1->width || s->context_reinit) { - s->height = s1->height; - s->width = s1->width; - if ((ret = ff_mpv_common_frame_size_change(s)) < 0) - return ret; - } - - s->avctx->coded_height = s1->avctx->coded_height; - s->avctx->coded_width = s1->avctx->coded_width; - s->avctx->width = s1->avctx->width; - s->avctx->height = s1->avctx->height; - - s->quarter_sample = s1->quarter_sample; - - s->coded_picture_number = s1->coded_picture_number; - s->picture_number = s1->picture_number; - - av_assert0(!s->picture || s->picture != s1->picture); - if(s->picture) - for (i = 0; i < MAX_PICTURE_COUNT; i++) { - ff_mpeg_unref_picture(s->avctx, &s->picture[i]); - if (s1->picture && s1->picture[i].f->buf[0] && - (ret = ff_mpeg_ref_picture(s->avctx, &s->picture[i], &s1->picture[i])) < 0) - return ret; - } - -#define UPDATE_PICTURE(pic)\ -do {\ - ff_mpeg_unref_picture(s->avctx, &s->pic);\ - if (s1->pic.f && s1->pic.f->buf[0])\ - ret = ff_mpeg_ref_picture(s->avctx, &s->pic, &s1->pic);\ - else\ - ret = ff_update_picture_tables(&s->pic, &s1->pic);\ - if (ret < 0)\ - return ret;\ -} while (0) - - UPDATE_PICTURE(current_picture); - UPDATE_PICTURE(last_picture); - UPDATE_PICTURE(next_picture); - -#define REBASE_PICTURE(pic, new_ctx, old_ctx) \ - ((pic && pic >= old_ctx->picture && \ - pic < old_ctx->picture + MAX_PICTURE_COUNT) ? \ - &new_ctx->picture[pic - old_ctx->picture] : NULL) - - s->last_picture_ptr = REBASE_PICTURE(s1->last_picture_ptr, s, s1); - s->current_picture_ptr = REBASE_PICTURE(s1->current_picture_ptr, s, s1); - s->next_picture_ptr = REBASE_PICTURE(s1->next_picture_ptr, s, s1); - - // Error/bug resilience - s->next_p_frame_damaged = s1->next_p_frame_damaged; - s->workaround_bugs = s1->workaround_bugs; - s->padding_bug_score = s1->padding_bug_score; - - // MPEG-4 timing info - memcpy(&s->last_time_base, &s1->last_time_base, - (char *) &s1->pb_field_time + sizeof(s1->pb_field_time) - - (char *) &s1->last_time_base); - - // B-frame info - s->max_b_frames = s1->max_b_frames; - s->low_delay = s1->low_delay; - s->droppable = s1->droppable; - - // DivX handling (doesn't work) - s->divx_packed = s1->divx_packed; - - if (s1->bitstream_buffer) { - if (s1->bitstream_buffer_size + - AV_INPUT_BUFFER_PADDING_SIZE > s->allocated_bitstream_buffer_size) { - av_fast_malloc(&s->bitstream_buffer, - &s->allocated_bitstream_buffer_size, - s1->allocated_bitstream_buffer_size); - if (!s->bitstream_buffer) { - s->bitstream_buffer_size = 0; - return AVERROR(ENOMEM); - } - } - s->bitstream_buffer_size = s1->bitstream_buffer_size; - memcpy(s->bitstream_buffer, s1->bitstream_buffer, - s1->bitstream_buffer_size); - memset(s->bitstream_buffer + s->bitstream_buffer_size, 0, - AV_INPUT_BUFFER_PADDING_SIZE); - } - - // linesize-dependent scratch buffer allocation - if (!s->sc.edge_emu_buffer) - if (s1->linesize) { - if (ff_mpeg_framesize_alloc(s->avctx, &s->me, - &s->sc, s1->linesize) < 0) { - av_log(s->avctx, AV_LOG_ERROR, "Failed to allocate context " - "scratch buffers.\n"); - return AVERROR(ENOMEM); - } - } else { - av_log(s->avctx, AV_LOG_ERROR, "Context scratch buffers could not " - "be allocated due to unknown size.\n"); - } - - // MPEG-2/interlacing info - memcpy(&s->progressive_sequence, &s1->progressive_sequence, - (char *) &s1->rtp_mode - (char *) &s1->progressive_sequence); - - return 0; -} - /** * Set the given MpegEncContext to common defaults * (same for encoding and decoding). @@ -685,29 +522,7 @@ void ff_mpv_common_defaults(MpegEncContext *s) s->slice_context_count = 1; } -/** - * Initialize the given MpegEncContext for decoding. - * the changed fields will not depend upon - * the prior state of the MpegEncContext. - */ -void ff_mpv_decode_init(MpegEncContext *s, AVCodecContext *avctx) -{ - ff_mpv_common_defaults(s); - - s->avctx = avctx; - s->width = avctx->coded_width; - s->height = avctx->coded_height; - s->codec_id = avctx->codec->id; - s->workaround_bugs = avctx->workaround_bugs; - - /* convert fourcc to upper case */ - s->codec_tag = ff_toupper4(avctx->codec_tag); -} - -/** - * Initialize and allocates MpegEncContext fields dependent on the resolution. - */ -static int init_context_frame(MpegEncContext *s) +int ff_mpv_init_context_frame(MpegEncContext *s) { int y_size, c_size, yc_size, i, mb_array_size, mv_table_size, x, y; @@ -812,9 +627,9 @@ static int init_context_frame(MpegEncContext *s) if (s->out_format == FMT_H263) { /* cbp values, cbp, ac_pred, pred_dir */ - if (!FF_ALLOCZ_TYPED_ARRAY(s->coded_block_base, y_size + (s->mb_height&1)*2*s->b8_stride) || - !FF_ALLOCZ_TYPED_ARRAY(s->cbp_table, mb_array_size) || - !FF_ALLOCZ_TYPED_ARRAY(s->pred_dir_table, mb_array_size)) + if (!(s->coded_block_base = av_mallocz(y_size + (s->mb_height&1)*2*s->b8_stride)) || + !(s->cbp_table = av_mallocz(mb_array_size)) || + !(s->pred_dir_table = av_mallocz(mb_array_size))) return AVERROR(ENOMEM); s->coded_block = s->coded_block_base + s->b8_stride + 1; } @@ -832,13 +647,13 @@ static int init_context_frame(MpegEncContext *s) } /* which mb is an intra block, init macroblock skip table */ - if (!FF_ALLOC_TYPED_ARRAY(s->mbintra_table, mb_array_size) || + if (!(s->mbintra_table = av_mallocz(mb_array_size)) || // Note the + 1 is for a quicker MPEG-4 slice_end detection - !FF_ALLOCZ_TYPED_ARRAY(s->mbskip_table, mb_array_size + 2)) + !(s->mbskip_table = av_mallocz(mb_array_size + 2))) return AVERROR(ENOMEM); memset(s->mbintra_table, 1, mb_array_size); - return ff_mpeg_er_init(s); + return !CONFIG_MPEGVIDEODEC || s->encoding ? 0 : ff_mpeg_er_init(s); } static void clear_context(MpegEncContext *s) @@ -857,10 +672,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->dpcm_direction = 0; - s->dpcm_macroblock = NULL; s->ac_val_base = NULL; s->ac_val[0] = s->ac_val[1] = @@ -981,10 +793,10 @@ av_cold int ff_mpv_common_init(MpegEncContext *s) if (!(s->next_picture.f = av_frame_alloc()) || !(s->last_picture.f = av_frame_alloc()) || !(s->current_picture.f = av_frame_alloc()) || - !(s->new_picture.f = av_frame_alloc())) + !(s->new_picture = av_frame_alloc())) goto fail_nomem; - if ((ret = init_context_frame(s))) + if ((ret = ff_mpv_init_context_frame(s))) goto fail; #if FF_API_FLAG_TRUNCATED @@ -997,7 +809,7 @@ av_cold int ff_mpv_common_init(MpegEncContext *s) s->slice_context_count = nb_slices; // if (s->width && s->height) { - ret = init_duplicate_contexts(s); + ret = ff_mpv_init_duplicate_contexts(s); if (ret < 0) goto fail; // } @@ -1010,13 +822,7 @@ av_cold int ff_mpv_common_init(MpegEncContext *s) return ret; } -/** - * Frees and resets MpegEncContext fields depending on the resolution - * as well as the slice thread contexts. - * Is used during resolution changes to avoid a full reinitialization of the - * codec. - */ -static void free_context_frame(MpegEncContext *s) +void ff_mpv_free_context_frame(MpegEncContext *s) { int i, j, k; @@ -1069,70 +875,13 @@ static void free_context_frame(MpegEncContext *s) s->linesize = s->uvlinesize = 0; } -int ff_mpv_common_frame_size_change(MpegEncContext *s) -{ - int i, err = 0; - - if (!s->context_initialized) - return AVERROR(EINVAL); - - free_context_frame(s); - - if (s->picture) - for (i = 0; i < MAX_PICTURE_COUNT; i++) { - s->picture[i].needs_realloc = 1; - } - - s->last_picture_ptr = - s->next_picture_ptr = - s->current_picture_ptr = NULL; - - // init - if (s->codec_id == AV_CODEC_ID_MPEG2VIDEO && !s->progressive_sequence) - s->mb_height = (s->height + 31) / 32 * 2; - else - s->mb_height = (s->height + 15) / 16; - - if ((s->width || s->height) && - (err = av_image_check_size(s->width, s->height, 0, s->avctx)) < 0) - goto fail; - - /* set chroma shifts */ - err = av_pix_fmt_get_chroma_sub_sample(s->avctx->pix_fmt, - &s->chroma_x_shift, - &s->chroma_y_shift); - if (err < 0) - goto fail; - - if ((err = init_context_frame(s))) - goto fail; - - memset(s->thread_context, 0, sizeof(s->thread_context)); - s->thread_context[0] = s; - - if (s->width && s->height) { - err = init_duplicate_contexts(s); - if (err < 0) - goto fail; - } - s->context_reinit = 0; - - return 0; - fail: - free_context_frame(s); - s->context_reinit = 1; - return err; -} - /* init common structure for both encoder and decoder */ void ff_mpv_common_end(MpegEncContext *s) { - int i; - if (!s) return; - free_context_frame(s); + ff_mpv_free_context_frame(s); if (s->slice_context_count > 1) s->slice_context_count = 1; @@ -1148,25 +897,14 @@ void ff_mpv_common_end(MpegEncContext *s) return; if (s->picture) { - for (i = 0; i < MAX_PICTURE_COUNT; i++) { - ff_free_picture_tables(&s->picture[i]); - ff_mpeg_unref_picture(s->avctx, &s->picture[i]); - av_frame_free(&s->picture[i].f); - } + for (int i = 0; i < MAX_PICTURE_COUNT; i++) + ff_mpv_picture_free(s->avctx, &s->picture[i]); } av_freep(&s->picture); - ff_free_picture_tables(&s->last_picture); - ff_mpeg_unref_picture(s->avctx, &s->last_picture); - av_frame_free(&s->last_picture.f); - ff_free_picture_tables(&s->current_picture); - ff_mpeg_unref_picture(s->avctx, &s->current_picture); - av_frame_free(&s->current_picture.f); - ff_free_picture_tables(&s->next_picture); - ff_mpeg_unref_picture(s->avctx, &s->next_picture); - av_frame_free(&s->next_picture.f); - ff_free_picture_tables(&s->new_picture); - ff_mpeg_unref_picture(s->avctx, &s->new_picture); - av_frame_free(&s->new_picture.f); + ff_mpv_picture_free(s->avctx, &s->last_picture); + ff_mpv_picture_free(s->avctx, &s->current_picture); + ff_mpv_picture_free(s->avctx, &s->next_picture); + av_frame_free(&s->new_picture); s->context_initialized = 0; s->context_reinit = 0; @@ -1177,296 +915,6 @@ void ff_mpv_common_end(MpegEncContext *s) } -static void gray_frame(AVFrame *frame) -{ - int i, h_chroma_shift, v_chroma_shift; - - av_pix_fmt_get_chroma_sub_sample(frame->format, &h_chroma_shift, &v_chroma_shift); - - for(i=0; iheight; i++) - memset(frame->data[0] + frame->linesize[0]*i, 0x80, frame->width); - for(i=0; iheight, v_chroma_shift); i++) { - memset(frame->data[1] + frame->linesize[1]*i, - 0x80, AV_CEIL_RSHIFT(frame->width, h_chroma_shift)); - memset(frame->data[2] + frame->linesize[2]*i, - 0x80, AV_CEIL_RSHIFT(frame->width, h_chroma_shift)); - } -} - -/** - * generic function called after decoding - * the header and before a frame is decoded. - */ -int ff_mpv_frame_start(MpegEncContext *s, AVCodecContext *avctx) -{ - int i, ret; - Picture *pic; - s->mb_skipped = 0; - - if (!ff_thread_can_start_frame(avctx)) { - av_log(avctx, AV_LOG_ERROR, "Attempt to start a frame outside SETUP state\n"); - return -1; - } - - /* mark & release old frames */ - if (s->pict_type != AV_PICTURE_TYPE_B && s->last_picture_ptr && - s->last_picture_ptr != s->next_picture_ptr && - s->last_picture_ptr->f->buf[0]) { - ff_mpeg_unref_picture(s->avctx, s->last_picture_ptr); - } - - /* release forgotten pictures */ - /* if (MPEG-124 / H.263) */ - for (i = 0; i < MAX_PICTURE_COUNT; i++) { - if (&s->picture[i] != s->last_picture_ptr && - &s->picture[i] != s->next_picture_ptr && - s->picture[i].reference && !s->picture[i].needs_realloc) { - ff_mpeg_unref_picture(s->avctx, &s->picture[i]); - } - } - - ff_mpeg_unref_picture(s->avctx, &s->current_picture); - ff_mpeg_unref_picture(s->avctx, &s->last_picture); - ff_mpeg_unref_picture(s->avctx, &s->next_picture); - - /* release non reference frames */ - for (i = 0; i < MAX_PICTURE_COUNT; i++) { - if (!s->picture[i].reference) - ff_mpeg_unref_picture(s->avctx, &s->picture[i]); - } - - if (s->current_picture_ptr && !s->current_picture_ptr->f->buf[0]) { - // we already have an unused image - // (maybe it was set before reading the header) - pic = s->current_picture_ptr; - } else { - i = ff_find_unused_picture(s->avctx, s->picture, 0); - if (i < 0) { - av_log(s->avctx, AV_LOG_ERROR, "no frame buffer available\n"); - return i; - } - pic = &s->picture[i]; - } - - pic->reference = 0; - if (!s->droppable) { - if (s->pict_type != AV_PICTURE_TYPE_B) - pic->reference = 3; - } - - pic->f->coded_picture_number = s->coded_picture_number++; - - if (alloc_picture(s, pic) < 0) - return -1; - - s->current_picture_ptr = pic; - // FIXME use only the vars from current_pic - s->current_picture_ptr->f->top_field_first = s->top_field_first; - if (s->codec_id == AV_CODEC_ID_MPEG1VIDEO || - s->codec_id == AV_CODEC_ID_MPEG2VIDEO) { - if (s->picture_structure != PICT_FRAME) - s->current_picture_ptr->f->top_field_first = - (s->picture_structure == PICT_TOP_FIELD) == s->first_field; - } - s->current_picture_ptr->f->interlaced_frame = !s->progressive_frame && - !s->progressive_sequence; - s->current_picture_ptr->field_picture = s->picture_structure != PICT_FRAME; - - s->current_picture_ptr->f->pict_type = s->pict_type; - // if (s->avctx->flags && AV_CODEC_FLAG_QSCALE) - // s->current_picture_ptr->quality = s->new_picture_ptr->quality; - s->current_picture_ptr->f->key_frame = s->pict_type == AV_PICTURE_TYPE_I; - - if ((ret = ff_mpeg_ref_picture(s->avctx, &s->current_picture, - s->current_picture_ptr)) < 0) - return ret; - - if (s->pict_type != AV_PICTURE_TYPE_B) { - s->last_picture_ptr = s->next_picture_ptr; - if (!s->droppable) - s->next_picture_ptr = s->current_picture_ptr; - } - ff_dlog(s->avctx, "L%p N%p C%p L%p N%p C%p type:%d drop:%d\n", - s->last_picture_ptr, s->next_picture_ptr,s->current_picture_ptr, - s->last_picture_ptr ? s->last_picture_ptr->f->data[0] : NULL, - s->next_picture_ptr ? s->next_picture_ptr->f->data[0] : NULL, - s->current_picture_ptr ? s->current_picture_ptr->f->data[0] : NULL, - s->pict_type, s->droppable); - - if ((!s->last_picture_ptr || !s->last_picture_ptr->f->buf[0]) && - (s->pict_type != AV_PICTURE_TYPE_I)) { - int h_chroma_shift, v_chroma_shift; - av_pix_fmt_get_chroma_sub_sample(s->avctx->pix_fmt, - &h_chroma_shift, &v_chroma_shift); - if (s->pict_type == AV_PICTURE_TYPE_B && s->next_picture_ptr && s->next_picture_ptr->f->buf[0]) - av_log(avctx, AV_LOG_DEBUG, - "allocating dummy last picture for B frame\n"); - else if (s->pict_type != AV_PICTURE_TYPE_I) - av_log(avctx, AV_LOG_ERROR, - "warning: first frame is no keyframe\n"); - - /* Allocate a dummy frame */ - i = ff_find_unused_picture(s->avctx, s->picture, 0); - if (i < 0) { - av_log(s->avctx, AV_LOG_ERROR, "no frame buffer available\n"); - return i; - } - s->last_picture_ptr = &s->picture[i]; - - s->last_picture_ptr->reference = 3; - s->last_picture_ptr->f->key_frame = 0; - s->last_picture_ptr->f->pict_type = AV_PICTURE_TYPE_P; - - if (alloc_picture(s, s->last_picture_ptr) < 0) { - s->last_picture_ptr = NULL; - return -1; - } - - if (!avctx->hwaccel) { - for(i=0; iheight; i++) - memset(s->last_picture_ptr->f->data[0] + s->last_picture_ptr->f->linesize[0]*i, - 0x80, avctx->width); - if (s->last_picture_ptr->f->data[2]) { - for(i=0; iheight, v_chroma_shift); i++) { - memset(s->last_picture_ptr->f->data[1] + s->last_picture_ptr->f->linesize[1]*i, - 0x80, AV_CEIL_RSHIFT(avctx->width, h_chroma_shift)); - memset(s->last_picture_ptr->f->data[2] + s->last_picture_ptr->f->linesize[2]*i, - 0x80, AV_CEIL_RSHIFT(avctx->width, h_chroma_shift)); - } - } - - if(s->codec_id == AV_CODEC_ID_FLV1 || s->codec_id == AV_CODEC_ID_H263){ - for(i=0; iheight; i++) - memset(s->last_picture_ptr->f->data[0] + s->last_picture_ptr->f->linesize[0]*i, 16, avctx->width); - } - } - - ff_thread_report_progress(&s->last_picture_ptr->tf, INT_MAX, 0); - ff_thread_report_progress(&s->last_picture_ptr->tf, INT_MAX, 1); - } - if ((!s->next_picture_ptr || !s->next_picture_ptr->f->buf[0]) && - s->pict_type == AV_PICTURE_TYPE_B) { - /* Allocate a dummy frame */ - i = ff_find_unused_picture(s->avctx, s->picture, 0); - if (i < 0) { - av_log(s->avctx, AV_LOG_ERROR, "no frame buffer available\n"); - return i; - } - s->next_picture_ptr = &s->picture[i]; - - s->next_picture_ptr->reference = 3; - s->next_picture_ptr->f->key_frame = 0; - s->next_picture_ptr->f->pict_type = AV_PICTURE_TYPE_P; - - if (alloc_picture(s, s->next_picture_ptr) < 0) { - s->next_picture_ptr = NULL; - return -1; - } - ff_thread_report_progress(&s->next_picture_ptr->tf, INT_MAX, 0); - ff_thread_report_progress(&s->next_picture_ptr->tf, INT_MAX, 1); - } - -#if 0 // BUFREF-FIXME - memset(s->last_picture.f->data, 0, sizeof(s->last_picture.f->data)); - memset(s->next_picture.f->data, 0, sizeof(s->next_picture.f->data)); -#endif - if (s->last_picture_ptr) { - if (s->last_picture_ptr->f->buf[0] && - (ret = ff_mpeg_ref_picture(s->avctx, &s->last_picture, - s->last_picture_ptr)) < 0) - return ret; - } - if (s->next_picture_ptr) { - if (s->next_picture_ptr->f->buf[0] && - (ret = ff_mpeg_ref_picture(s->avctx, &s->next_picture, - s->next_picture_ptr)) < 0) - return ret; - } - - av_assert0(s->pict_type == AV_PICTURE_TYPE_I || (s->last_picture_ptr && - s->last_picture_ptr->f->buf[0])); - - if (s->picture_structure!= PICT_FRAME) { - int i; - for (i = 0; i < 4; i++) { - if (s->picture_structure == PICT_BOTTOM_FIELD) { - s->current_picture.f->data[i] += - s->current_picture.f->linesize[i]; - } - s->current_picture.f->linesize[i] *= 2; - s->last_picture.f->linesize[i] *= 2; - s->next_picture.f->linesize[i] *= 2; - } - } - - /* set dequantizer, we can't do it during init as - * it might change for MPEG-4 and we can't do it in the header - * decode as init is not called for MPEG-4 there yet */ - if (s->mpeg_quant || s->codec_id == AV_CODEC_ID_MPEG2VIDEO) { - s->dct_unquantize_intra = s->dct_unquantize_mpeg2_intra; - s->dct_unquantize_inter = s->dct_unquantize_mpeg2_inter; - } else if (s->out_format == FMT_H263 || s->out_format == FMT_H261) { - s->dct_unquantize_intra = s->dct_unquantize_h263_intra; - s->dct_unquantize_inter = s->dct_unquantize_h263_inter; - } else { - s->dct_unquantize_intra = s->dct_unquantize_mpeg1_intra; - s->dct_unquantize_inter = s->dct_unquantize_mpeg1_inter; - } - - if (s->avctx->debug & FF_DEBUG_NOMC) { - gray_frame(s->current_picture_ptr->f); - } - - return 0; -} - -/* called after a frame has been decoded. */ -void ff_mpv_frame_end(MpegEncContext *s) -{ - emms_c(); - - if (s->current_picture.reference) - ff_thread_report_progress(&s->current_picture_ptr->tf, INT_MAX, 0); -} - -void ff_print_debug_info(MpegEncContext *s, Picture *p, AVFrame *pict) -{ - ff_print_debug_info2(s->avctx, pict, s->mbskip_table, p->mb_type, - p->qscale_table, p->motion_val, - s->mb_width, s->mb_height, s->mb_stride, s->quarter_sample); -} - -int ff_mpv_export_qp_table(MpegEncContext *s, AVFrame *f, Picture *p, int qp_type) -{ - AVVideoEncParams *par; - int mult = (qp_type == FF_QSCALE_TYPE_MPEG1) ? 2 : 1; - unsigned int nb_mb = p->alloc_mb_height * p->alloc_mb_width; - unsigned int x, y; - - if (!(s->avctx->export_side_data & AV_CODEC_EXPORT_DATA_VIDEO_ENC_PARAMS)) - return 0; - - par = av_video_enc_params_create_side_data(f, AV_VIDEO_ENC_PARAMS_MPEG2, nb_mb); - if (!par) - return AVERROR(ENOMEM); - - for (y = 0; y < p->alloc_mb_height; y++) - for (x = 0; x < p->alloc_mb_width; x++) { - const unsigned int block_idx = y * p->alloc_mb_width + x; - const unsigned int mb_xy = y * p->alloc_mb_stride + x; - AVVideoBlockParams *b = av_video_enc_params_block(par, block_idx); - - b->src_x = x * 16; - b->src_y = y * 16; - b->w = 16; - b->h = 16; - - b->delta_qp = p->qscale_table[mb_xy] * mult; - } - - return 0; -} - static inline int hpel_motion_lowres(MpegEncContext *s, uint8_t *dest, uint8_t *src, int field_based, int field_select, @@ -1964,27 +1412,10 @@ static av_always_inline void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64], int lowres_flag, int is_mpeg12) { +#define IS_ENCODER(s) (CONFIG_MPEGVIDEOENC && !lowres_flag && (s)->encoding) +#define IS_MPEG12(s) (CONFIG_SMALL ? ((s)->out_format == FMT_MPEG1) : is_mpeg12) const int mb_xy = s->mb_y * s->mb_stride + s->mb_x; - if (CONFIG_XVMC && - s->avctx->hwaccel && s->avctx->hwaccel->decode_mb) { - s->avctx->hwaccel->decode_mb(s);//xvmc uses pblocks - return; - } - - if(s->avctx->debug&FF_DEBUG_DCT_COEFF) { - /* print DCT coefficients */ - int i,j; - av_log(s->avctx, AV_LOG_DEBUG, "DCT coeffs of MB at %dx%d:\n", s->mb_x, s->mb_y); - for(i=0; i<6; i++){ - for(j=0; j<64; j++){ - av_log(s->avctx, AV_LOG_DEBUG, "%5d", - block[i][s->idsp.idct_permutation[j]]); - } - av_log(s->avctx, AV_LOG_DEBUG, "\n"); - } - } - s->current_picture.qscale_table[mb_xy] = s->qscale; /* update DC predictors for P macroblocks */ @@ -2001,8 +1432,8 @@ void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64], else if (!is_mpeg12 && (s->h263_pred || s->h263_aic)) s->mbintra_table[mb_xy]=1; - if ((s->avctx->flags & AV_CODEC_FLAG_PSNR) || s->frame_skip_threshold || s->frame_skip_factor || - !(s->encoding && (s->intra_only || s->pict_type == AV_PICTURE_TYPE_B) && + if (!IS_ENCODER(s) || (s->avctx->flags & AV_CODEC_FLAG_PSNR) || s->frame_skip_threshold || s->frame_skip_factor || + !((s->intra_only || s->pict_type == AV_PICTURE_TYPE_B) && s->avctx->mb_decision != FF_MB_DECISION_RD)) { // FIXME precalc uint8_t *dest_y, *dest_cb, *dest_cr; int dct_linesize, dct_offset; @@ -2010,12 +1441,12 @@ void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64], qpel_mc_func (*op_qpix)[16]; 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 readable= s->pict_type != AV_PICTURE_TYPE_B || s->encoding || s->avctx->draw_horiz_band || lowres_flag; + const int readable = s->pict_type != AV_PICTURE_TYPE_B || IS_ENCODER(s) || s->avctx->draw_horiz_band || lowres_flag; const int block_size= lowres_flag ? 8>>s->avctx->lowres : 8; /* avoid copy if macroblock skipped in last frame too */ /* skip only during decoding as we might trash the buffers during encoding a bit */ - if(!s->encoding){ + if (!IS_ENCODER(s)) { uint8_t *mbskip_ptr = &s->mbskip_table[mb_xy]; if (s->mb_skipped) { @@ -2045,7 +1476,7 @@ void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64], if (!s->mb_intra) { /* motion handling */ /* decoding or more than one mb_type (MC was already done otherwise) */ - if(!s->encoding){ + if (!IS_ENCODER(s)) { if(HAVE_THREADS && s->avctx->active_thread_type&FF_THREAD_FRAME) { if (s->mv_dir & MV_DIR_FORWARD) { @@ -2072,7 +1503,7 @@ void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64], } }else{ op_qpix = s->me.qpel_put; - if ((!s->no_rounding) || s->pict_type==AV_PICTURE_TYPE_B){ + if ((is_mpeg12 || !s->no_rounding) || s->pict_type == AV_PICTURE_TYPE_B) { op_pix = s->hdsp.put_pixels_tab; }else{ op_pix = s->hdsp.put_no_rnd_pixels_tab; @@ -2097,7 +1528,7 @@ void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64], } /* add dct residue */ - if(s->encoding || !( s->msmpeg4_version || s->codec_id==AV_CODEC_ID_MPEG1VIDEO || s->codec_id==AV_CODEC_ID_MPEG2VIDEO + if (IS_ENCODER(s) || !(IS_MPEG12(s) || s->msmpeg4_version || (s->codec_id==AV_CODEC_ID_MPEG4 && !s->mpeg_quant))){ add_dequant_dct(s, block[0], 0, dest_y , dct_linesize, s->qscale); add_dequant_dct(s, block[1], 1, dest_y + block_size, dct_linesize, s->qscale); @@ -2144,68 +1575,19 @@ void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64], } } }//fi gray - } - else if (CONFIG_WMV2_DECODER || CONFIG_WMV2_ENCODER) { + } else if (CONFIG_WMV2_DECODER) { 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; - - if(s->dpcm_direction == 0) { - 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]); - } - } else if(s->dpcm_direction == 1) { - int i, w, h; - uint16_t *dest_pcm[3] = {(uint16_t*)dest_y, (uint16_t*)dest_cb, (uint16_t*)dest_cr}; - int linesize[3] = {dct_linesize, uvlinesize, uvlinesize}; - for(i = 0; i < 3; i++) { - int idx = 0; - int vsub = i ? s->chroma_y_shift : 0; - int hsub = i ? s->chroma_x_shift : 0; - for(h = 0; h < (16 >> vsub); h++){ - for(w = 0; w < (16 >> hsub); w++) - dest_pcm[i][w] = (*s->dpcm_macroblock)[i][idx++]; - dest_pcm[i] += linesize[i] / 2; - } - } - } else if(s->dpcm_direction == -1) { - int i, w, h; - uint16_t *dest_pcm[3] = {(uint16_t*)dest_y, (uint16_t*)dest_cb, (uint16_t*)dest_cr}; - int linesize[3] = {dct_linesize, uvlinesize, uvlinesize}; - for(i = 0; i < 3; i++) { - int idx = 0; - int vsub = i ? s->chroma_y_shift : 0; - int hsub = i ? s->chroma_x_shift : 0; - dest_pcm[i] += (linesize[i] / 2) * ((16 >> vsub) - 1); - for(h = (16 >> vsub)-1; h >= 1; h--){ - for(w = (16 >> hsub)-1; w >= 1; w--) - dest_pcm[i][w] = (*s->dpcm_macroblock)[i][idx++]; - dest_pcm[i] -= linesize[i] / 2; - } - } - } + if (!is_mpeg12 && CONFIG_MPEG4_DECODER && /* s->codec_id == AV_CODEC_ID_MPEG4 && */ + s->avctx->bits_per_raw_sample > 8) { + ff_mpeg4_decode_studio(s, dest_y, dest_cb, dest_cr, block_size, + uvlinesize, dct_linesize, dct_offset); } /* dct only in intra block */ - else if(s->encoding || !(s->codec_id==AV_CODEC_ID_MPEG1VIDEO || s->codec_id==AV_CODEC_ID_MPEG2VIDEO)){ + else if (IS_ENCODER(s) || !IS_MPEG12(s)) { 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); @@ -2266,6 +1648,18 @@ skip_idct: void ff_mpv_reconstruct_mb(MpegEncContext *s, int16_t block[12][64]) { + if (s->avctx->debug & FF_DEBUG_DCT_COEFF) { + /* print DCT coefficients */ + av_log(s->avctx, AV_LOG_DEBUG, "DCT coeffs of MB at %dx%d:\n", s->mb_x, s->mb_y); + for (int i = 0; i < 6; i++) { + for (int j = 0; j < 64; j++) { + av_log(s->avctx, AV_LOG_DEBUG, "%5d", + block[i][s->idsp.idct_permutation[j]]); + } + av_log(s->avctx, AV_LOG_DEBUG, "\n"); + } + } + #if !CONFIG_SMALL if(s->out_format == FMT_MPEG1) { if(s->avctx->lowres) mpv_reconstruct_mb_internal(s, block, 1, 1); @@ -2276,13 +1670,6 @@ void ff_mpv_reconstruct_mb(MpegEncContext *s, int16_t block[12][64]) else mpv_reconstruct_mb_internal(s, block, 0, 0); } -void ff_mpeg_draw_horiz_band(MpegEncContext *s, int y, int h) -{ - ff_draw_horiz_band(s->avctx, s->current_picture_ptr->f, - s->last_picture_ptr ? s->last_picture_ptr->f : NULL, y, h, s->picture_structure, - s->first_field, s->low_delay); -} - 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]; @@ -2316,35 +1703,6 @@ void ff_init_block_index(MpegEncContext *s){ //FIXME maybe rename } } -void ff_mpeg_flush(AVCodecContext *avctx){ - int i; - MpegEncContext *s = avctx->priv_data; - - if (!s || !s->picture) - return; - - for (i = 0; i < MAX_PICTURE_COUNT; i++) - ff_mpeg_unref_picture(s->avctx, &s->picture[i]); - s->current_picture_ptr = s->last_picture_ptr = s->next_picture_ptr = NULL; - - ff_mpeg_unref_picture(s->avctx, &s->current_picture); - ff_mpeg_unref_picture(s->avctx, &s->last_picture); - ff_mpeg_unref_picture(s->avctx, &s->next_picture); - - s->mb_x= s->mb_y= 0; - -#if FF_API_FLAG_TRUNCATED - s->parse_context.state= -1; - s->parse_context.frame_start_found= 0; - s->parse_context.overread= 0; - s->parse_context.overread_index= 0; - s->parse_context.index= 0; - s->parse_context.last_index= 0; -#endif - s->bitstream_buffer_size=0; - s->pp_time=0; -} - /** * set qscale and update qscale dependent variables. */ @@ -2361,9 +1719,3 @@ void ff_set_qscale(MpegEncContext * s, int qscale) s->y_dc_scale= s->y_dc_scale_table[ qscale ]; s->c_dc_scale= s->c_dc_scale_table[ s->chroma_qscale ]; } - -void ff_mpv_report_decode_progress(MpegEncContext *s) -{ - if (s->pict_type != AV_PICTURE_TYPE_B && !s->partitioned_frame && !s->er.error_occurred) - ff_thread_report_progress(&s->current_picture_ptr->tf, s->mb_y, 0); -} diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 879b019ff..82889a0ed 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -28,8 +28,6 @@ #ifndef AVCODEC_MPEGVIDEO_H #define AVCODEC_MPEGVIDEO_H -#include - #include "avcodec.h" #include "blockdsp.h" #include "error_resilience.h" @@ -39,13 +37,11 @@ #include "h263dsp.h" #include "hpeldsp.h" #include "idctdsp.h" -#include "internal.h" #include "me_cmp.h" #include "motion_est.h" #include "mpegpicture.h" #include "mpegvideodsp.h" #include "mpegvideoencdsp.h" -#include "mpegvideodata.h" #include "pixblockdsp.h" #include "put_bits.h" #include "ratecontrol.h" @@ -53,14 +49,9 @@ #include "parser.h" #endif #include "mpegutils.h" -#include "mpeg12data.h" #include "qpeldsp.h" -#include "thread.h" #include "videodsp.h" -#include "libavutil/opt.h" -#include "libavutil/timecode.h" - #define MAX_THREADS 32 #define MAX_B_FRAMES 16 @@ -86,6 +77,9 @@ typedef struct MpegEncContext { * offsets used in ASM. */ struct AVCodecContext *avctx; + /* The following pointer is intended for codecs sharing code + * between decoder and encoder and in need of a common context to do so. */ + void *private_ctx; /* the following parameters must be initialized before encoding */ int width, height;///< picture size. must be a multiple of 16 int gop_size; @@ -105,7 +99,6 @@ typedef struct MpegEncContext { int max_b_frames; ///< max number of B-frames for encoding int luma_elim_threshold; int chroma_elim_threshold; - int strict_std_compliance; ///< strictly follow the std (MPEG-4, ...) int workaround_bugs; ///< workaround bugs in encoders which cannot be detected automatically int codec_tag; ///< internal codec_tag upper case converted from avctx codec_tag /* the following fields are managed internally by the encoder */ @@ -158,10 +151,10 @@ typedef struct MpegEncContext { Picture next_picture; /** - * copy of the source picture structure for encoding. + * Reference to the source picture for encoding. * note, linesize & data, might not match the source picture (for field pictures) */ - Picture new_picture; + AVFrame *new_picture; /** * copy of the current picture structure. @@ -203,8 +196,6 @@ typedef struct MpegEncContext { int last_pict_type; //FIXME removes int last_non_b_pict_type; ///< used for MPEG-4 gmc B-frames & ratecontrol int droppable; - int frame_rate_index; - AVRational mpeg2_frame_rate_ext; int last_lambda_for[5]; ///< last lambda for a specific pict type int skipdct; ///< skip dct and code zero residual @@ -290,7 +281,6 @@ typedef struct MpegEncContext { uint16_t chroma_intra_matrix[64]; uint16_t inter_matrix[64]; uint16_t chroma_inter_matrix[64]; - int force_duplicated_matrix; ///< Force duplication of mjpeg matrices, useful for rtp streaming int intra_quant_bias; ///< bias for the quantizer int inter_quant_bias; ///< bias for the quantizer @@ -304,7 +294,6 @@ typedef struct MpegEncContext { uint8_t *inter_ac_vlc_length; uint8_t *inter_ac_vlc_last_length; uint8_t *luma_dc_vlc_length; -#define UNI_AC_ENC_INDEX(run,level) ((run)*128 + (level)) int coded_score[12]; @@ -335,8 +324,6 @@ typedef struct MpegEncContext { int i_tex_bits; int p_tex_bits; int i_count; - int f_count; - int b_count; int skip_count; int misc_bits; ///< cbp, mb_type int last_bits; ///< temp var used for calculating the above vars @@ -346,7 +333,6 @@ typedef struct MpegEncContext { int resync_mb_y; ///< y position of last resync marker GetBitContext last_resync_gb; ///< used to search for the next resync marker int mb_num_left; ///< number of MBs left in this video packet (for partitioned Slices only) - int next_p_frame_damaged; ///< set if the next p frame is damaged, to avoid showing trashed B-frames #if FF_API_FLAG_TRUNCATED ParseContext parse_context; @@ -389,12 +375,10 @@ typedef struct MpegEncContext { int mcsel; int quant_precision; int quarter_sample; ///< 1->qpel, 0->half pel ME/MC - int aspect_ratio_info; //FIXME remove int sprite_warping_accuracy; int data_partitioning; ///< data partitioning flag from header int partitioned_frame; ///< is current frame partitioned int low_delay; ///< no reordering needed / has no B-frames - int vo_type; PutBitContext tex_pb; ///< used for data partitioned VOPs PutBitContext pb2; ///< used for data partitioned VOPs int mpeg_quant; @@ -413,8 +397,6 @@ typedef struct MpegEncContext { /* MJPEG specific */ struct MJpegContext *mjpeg_ctx; int esc_pos; - int pred; - int huffman; /* MSMPEG4 specific */ int mv_table_index; @@ -429,31 +411,23 @@ typedef struct MpegEncContext { int per_mb_rl_table; int esc3_level_length; int esc3_run_length; - /** [mb_intra][isChroma][level][run][last] */ - int (*ac_stats)[2][MAX_LEVEL+1][MAX_RUN+1][2]; int inter_intra_pred; int mspel; - /* SpeedHQ specific */ - int slice_start; - /* decompression specific */ GetBitContext gb; /* MPEG-1 specific */ - int gop_picture_number; ///< index of the first picture of a GOP based on fake_pic_num & MPEG-1 specific int last_mv_dir; ///< last mv_dir, used for B-frame encoding - uint8_t *vbv_delay_ptr; ///< pointer to vbv_delay in the bitstream + int vbv_delay_pos; ///< offset of vbv_delay in the bitstream /* MPEG-2-specific - I wished not to have to support this mess. */ int progressive_sequence; int mpeg_f_code[2][2]; - int a53_cc; // picture structure defines are loaded from mpegutils.h int picture_structure; - int64_t timecode_frame_start; ///< GOP timecode frame start number, in non drop frame format int intra_dc_precision; int frame_pred_frame_dct; int top_field_first; @@ -462,8 +436,6 @@ typedef struct MpegEncContext { int brd_scale; 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 @@ -483,29 +455,18 @@ typedef struct MpegEncContext { int full_pel[2]; int interlaced_dct; int first_field; ///< is 1 for the first field of a field picture 0 otherwise - int drop_frame_timecode; ///< timecode is in drop frame format. - int scan_offset; ///< reserve space for SVCD scan offset user data. /* RTP specific */ int rtp_mode; int rtp_payload_size; - char *tc_opt_str; ///< timecode option string - AVTimecode tc; ///< timecode context - uint8_t *ptr_lastgob; - int swap_uv; //vcr2 codec is an MPEG-2 variant with U and V swapped - int pack_pblocks; //xvmc needs to keep blocks without gaps. int16_t (*pblocks[12])[64]; 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[12][64]); // used by some codecs to avoid a switch() - int32_t (*block32)[12][64]; - int dpcm_direction; // 0 = DCT, 1 = DPCM top to bottom scan, -1 = DPCM bottom to top scan - int16_t (*dpcm_macroblock)[3][256]; - #define SLICE_OK 0 #define SLICE_ERROR -1 #define SLICE_END -2 ///", 0, AV_OPT_TYPE_CONST, { .i64 = FF_MPV_FLAG_MV0 }, 0, 0, FF_MPV_OPT_FLAGS, "mpv_flags" },\ -{ "luma_elim_threshold", "single coefficient elimination threshold for luminance (negative values also consider dc coefficient)",\ - FF_MPV_OFFSET(luma_elim_threshold), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS },\ -{ "chroma_elim_threshold", "single coefficient elimination threshold for chrominance (negative values also consider dc coefficient)",\ - FF_MPV_OFFSET(chroma_elim_threshold), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS },\ -{ "quantizer_noise_shaping", NULL, FF_MPV_OFFSET(quantizer_noise_shaping), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FF_MPV_OPT_FLAGS },\ -{ "error_rate", "Simulate errors in the bitstream to test error concealment.", \ - FF_MPV_OFFSET(error_rate), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FF_MPV_OPT_FLAGS },\ -{"qsquish", "how to keep quantizer between qmin and qmax (0 = clip, 1 = use differentiable function)", \ - FF_MPV_OFFSET(rc_qsquish), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, 0, 99, FF_MPV_OPT_FLAGS}, \ -{"rc_qmod_amp", "experimental quantizer modulation", FF_MPV_OFFSET(rc_qmod_amp), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, -FLT_MAX, FLT_MAX, FF_MPV_OPT_FLAGS}, \ -{"rc_qmod_freq", "experimental quantizer modulation", FF_MPV_OFFSET(rc_qmod_freq), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS}, \ -{"rc_eq", "Set rate control equation. When computing the expression, besides the standard functions " \ - "defined in the section 'Expression Evaluation', the following functions are available: " \ - "bits2qp(bits), qp2bits(qp). Also the following constants are available: iTex pTex tex mv " \ - "fCode iCount mcVar var isI isP isB avgQP qComp avgIITex avgPITex avgPPTex avgBPTex avgTex.", \ - FF_MPV_OFFSET(rc_eq), AV_OPT_TYPE_STRING, .flags = FF_MPV_OPT_FLAGS }, \ -{"rc_init_cplx", "initial complexity for 1-pass encoding", FF_MPV_OFFSET(rc_initial_cplx), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, -FLT_MAX, FLT_MAX, FF_MPV_OPT_FLAGS}, \ -{"rc_buf_aggressivity", "currently useless", FF_MPV_OFFSET(rc_buffer_aggressivity), AV_OPT_TYPE_FLOAT, {.dbl = 1.0 }, -FLT_MAX, FLT_MAX, FF_MPV_OPT_FLAGS}, \ -{"border_mask", "increase the quantizer for macroblocks close to borders", FF_MPV_OFFSET(border_masking), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, -FLT_MAX, FLT_MAX, FF_MPV_OPT_FLAGS}, \ -{"lmin", "minimum Lagrange factor (VBR)", FF_MPV_OFFSET(lmin), AV_OPT_TYPE_INT, {.i64 = 2*FF_QP2LAMBDA }, 0, INT_MAX, FF_MPV_OPT_FLAGS }, \ -{"lmax", "maximum Lagrange factor (VBR)", FF_MPV_OFFSET(lmax), AV_OPT_TYPE_INT, {.i64 = 31*FF_QP2LAMBDA }, 0, INT_MAX, FF_MPV_OPT_FLAGS }, \ -{"ibias", "intra quant bias", FF_MPV_OFFSET(intra_quant_bias), AV_OPT_TYPE_INT, {.i64 = FF_DEFAULT_QUANT_BIAS }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ -{"pbias", "inter quant bias", FF_MPV_OFFSET(inter_quant_bias), AV_OPT_TYPE_INT, {.i64 = FF_DEFAULT_QUANT_BIAS }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ -{"motion_est", "motion estimation algorithm", FF_MPV_OFFSET(motion_est), AV_OPT_TYPE_INT, {.i64 = FF_ME_EPZS }, FF_ME_ZERO, FF_ME_XONE, FF_MPV_OPT_FLAGS, "motion_est" }, \ -{ "zero", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_ME_ZERO }, 0, 0, FF_MPV_OPT_FLAGS, "motion_est" }, \ -{ "epzs", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_ME_EPZS }, 0, 0, FF_MPV_OPT_FLAGS, "motion_est" }, \ -{ "xone", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_ME_XONE }, 0, 0, FF_MPV_OPT_FLAGS, "motion_est" }, \ -{"skip_threshold", "Frame skip threshold", FF_MPV_OFFSET(frame_skip_threshold), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ -{"skip_factor", "Frame skip factor", FF_MPV_OFFSET(frame_skip_factor), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ -{"skip_exp", "Frame skip exponent", FF_MPV_OFFSET(frame_skip_exp), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ -{"skip_cmp", "Frame skip compare function", FF_MPV_OFFSET(frame_skip_cmp), AV_OPT_TYPE_INT, {.i64 = FF_CMP_DCTMAX }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" }, \ -{"sc_threshold", "Scene change threshold", FF_MPV_OFFSET(scenechange_threshold), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ -{"noise_reduction", "Noise reduction", FF_MPV_OFFSET(noise_reduction), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ -{"ps", "RTP payload size in bytes", FF_MPV_OFFSET(rtp_payload_size), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ -{"mepc", "Motion estimation bitrate penalty compensation (1.0 = 256)", FF_MPV_OFFSET(me_penalty_compensation), AV_OPT_TYPE_INT, {.i64 = 256 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ -{"mepre", "pre motion estimation", FF_MPV_OFFSET(me_pre), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ -{"intra_penalty", "Penalty for intra blocks in block decision", FF_MPV_OFFSET(intra_penalty), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX/2, FF_MPV_OPT_FLAGS }, \ - -#define FF_MPV_COMMON_BFRAME_OPTS \ -{"b_strategy", "Strategy to choose between I/P/B-frames", FF_MPV_OFFSET(b_frame_strategy), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 2, FF_MPV_OPT_FLAGS }, \ -{"b_sensitivity", "Adjust sensitivity of b_frame_strategy 1", FF_MPV_OFFSET(b_sensitivity), AV_OPT_TYPE_INT, {.i64 = 40 }, 1, INT_MAX, FF_MPV_OPT_FLAGS }, \ -{"brd_scale", "Downscale frames for dynamic B-frame decision", FF_MPV_OFFSET(brd_scale), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 3, FF_MPV_OPT_FLAGS }, - -#if FF_API_MPEGVIDEO_OPTS -#define FF_MPV_DEPRECATED_MPEG_QUANT_OPT \ - { "mpeg_quant", "Deprecated, does nothing", FF_MPV_OFFSET(mpeg_quant), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 0, FF_MPV_OPT_FLAGS | AV_OPT_FLAG_DEPRECATED }, -#define FF_MPV_DEPRECATED_A53_CC_OPT \ - { "a53cc", "Deprecated, does nothing", FF_MPV_OFFSET(a53_cc), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, FF_MPV_OPT_FLAGS | AV_OPT_FLAG_DEPRECATED }, -#define FF_MPV_DEPRECATED_MATRIX_OPT \ - { "force_duplicated_matrix", "Deprecated, does nothing", FF_MPV_OFFSET(force_duplicated_matrix), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, FF_MPV_OPT_FLAGS | AV_OPT_FLAG_DEPRECATED }, -#define FF_MPV_DEPRECATED_BFRAME_OPTS \ - { "b_strategy", "Deprecated, does nothing", FF_MPV_OFFSET(b_frame_strategy), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, FF_MPV_OPT_FLAGS | AV_OPT_FLAG_DEPRECATED }, \ - { "b_sensitivity", "Deprecated, does nothing", FF_MPV_OFFSET(b_sensitivity), AV_OPT_TYPE_INT, { .i64 = 40 }, 1, INT_MAX, FF_MPV_OPT_FLAGS | AV_OPT_FLAG_DEPRECATED }, \ - { "brd_scale", "Deprecated, does nothing", FF_MPV_OFFSET(brd_scale), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 3, FF_MPV_OPT_FLAGS | AV_OPT_FLAG_DEPRECATED }, -#endif - -extern const AVClass ff_mpv_enc_class; /** * Set the given MpegEncContext to common defaults (same for encoding @@ -680,8 +546,6 @@ extern const AVClass ff_mpv_enc_class; */ void ff_mpv_common_defaults(MpegEncContext *s); -void ff_dct_encode_init_x86(MpegEncContext *s); - int ff_mpv_common_init(MpegEncContext *s); void ff_mpv_common_init_arm(MpegEncContext *s); void ff_mpv_common_init_axp(MpegEncContext *s); @@ -689,46 +553,34 @@ void ff_mpv_common_init_neon(MpegEncContext *s); void ff_mpv_common_init_ppc(MpegEncContext *s); void ff_mpv_common_init_x86(MpegEncContext *s); void ff_mpv_common_init_mips(MpegEncContext *s); +/** + * Initialize an MpegEncContext's thread contexts. Presumes that + * slice_context_count is already set and that all the fields + * that are freed/reset in free_duplicate_context() are NULL. + */ +int ff_mpv_init_duplicate_contexts(MpegEncContext *s); +/** + * Initialize and allocates MpegEncContext fields dependent on the resolution. + */ +int ff_mpv_init_context_frame(MpegEncContext *s); +/** + * Frees and resets MpegEncContext fields depending on the resolution + * as well as the slice thread contexts. + * Is used during resolution changes to avoid a full reinitialization of the + * codec. + */ +void ff_mpv_free_context_frame(MpegEncContext *s); -int ff_mpv_common_frame_size_change(MpegEncContext *s); void ff_mpv_common_end(MpegEncContext *s); -void ff_mpv_decode_init(MpegEncContext *s, AVCodecContext *avctx); void ff_mpv_reconstruct_mb(MpegEncContext *s, int16_t block[12][64]); -void ff_mpv_report_decode_progress(MpegEncContext *s); - -int ff_mpv_frame_start(MpegEncContext *s, AVCodecContext *avctx); -void ff_mpv_frame_end(MpegEncContext *s); - -int ff_mpv_encode_init(AVCodecContext *avctx); -void ff_mpv_encode_init_x86(MpegEncContext *s); - -int ff_mpv_encode_end(AVCodecContext *avctx); -int ff_mpv_encode_picture(AVCodecContext *avctx, AVPacket *pkt, - const AVFrame *frame, int *got_packet); -int ff_mpv_reallocate_putbitbuffer(MpegEncContext *s, size_t threshold, size_t size_increase); void ff_clean_intra_table_entries(MpegEncContext *s); -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); - -int ff_mpv_export_qp_table(MpegEncContext *s, AVFrame *f, Picture *p, int qp_type); - -void ff_write_quant_matrix(PutBitContext *pb, uint16_t *matrix); - -int ff_update_duplicate_context(MpegEncContext *dst, MpegEncContext *src); -int ff_mpeg_update_thread_context(AVCodecContext *dst, const AVCodecContext *src); +int ff_update_duplicate_context(MpegEncContext *dst, const MpegEncContext *src); void ff_set_qscale(MpegEncContext * s, int qscale); void ff_mpv_idct_init(MpegEncContext *s); -int ff_dct_encode_init(MpegEncContext *s); -void ff_convert_matrix(MpegEncContext *s, int (*qmat)[64], uint16_t (*qmat16)[2][64], - const uint16_t *quant_matrix, int bias, int qmin, int qmax, int intra); -int ff_dct_quantize_c(MpegEncContext *s, int16_t *block, int n, int qscale, int *overflow); -void ff_block_permute(int16_t *block, uint8_t *permutation, - const uint8_t *scantable, int last); void ff_init_block_index(MpegEncContext *s); void ff_mpv_motion(MpegEncContext *s, @@ -753,22 +605,4 @@ static inline void ff_update_block_index(MpegEncContext *s){ s->dest[2]+= (2 >> s->chroma_x_shift) * block_size; } -static inline int get_bits_diff(MpegEncContext *s){ - const int bits= put_bits_count(&s->pb); - const int last= s->last_bits; - - s->last_bits = bits; - - 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/mpegvideo_dec.c b/libavcodec/mpegvideo_dec.c new file mode 100644 index 000000000..7caaf0596 --- /dev/null +++ b/libavcodec/mpegvideo_dec.c @@ -0,0 +1,584 @@ +/* + * Common mpeg video decoding code + * Copyright (c) 2000,2001 Fabrice Bellard + * Copyright (c) 2002-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/imgutils.h" +#include "libavutil/internal.h" +#include "libavutil/video_enc_params.h" + +#include "avcodec.h" +#include "internal.h" +#include "mpegutils.h" +#include "mpegvideo.h" +#include "mpegvideodec.h" +#include "threadframe.h" + +void ff_mpv_decode_init(MpegEncContext *s, AVCodecContext *avctx) +{ + ff_mpv_common_defaults(s); + + s->avctx = avctx; + s->width = avctx->coded_width; + s->height = avctx->coded_height; + s->codec_id = avctx->codec->id; + s->workaround_bugs = avctx->workaround_bugs; + + /* convert fourcc to upper case */ + s->codec_tag = ff_toupper4(avctx->codec_tag); +} + +int ff_mpeg_update_thread_context(AVCodecContext *dst, + const AVCodecContext *src) +{ + MpegEncContext *const s1 = src->priv_data; + MpegEncContext *const s = dst->priv_data; + int ret; + + if (dst == src) + return 0; + + av_assert0(s != s1); + + // FIXME can parameters change on I-frames? + // in that case dst may need a reinit + if (!s->context_initialized) { + void *private_ctx = s->private_ctx; + int err; + memcpy(s, s1, sizeof(*s)); + + s->avctx = dst; + s->private_ctx = private_ctx; + s->bitstream_buffer = NULL; + s->bitstream_buffer_size = s->allocated_bitstream_buffer_size = 0; + + if (s1->context_initialized) { +// s->picture_range_start += MAX_PICTURE_COUNT; +// s->picture_range_end += MAX_PICTURE_COUNT; + ff_mpv_idct_init(s); + if ((err = ff_mpv_common_init(s)) < 0) { + memset(s, 0, sizeof(*s)); + s->avctx = dst; + s->private_ctx = private_ctx; + return err; + } + } + } + + if (s->height != s1->height || s->width != s1->width || s->context_reinit) { + s->height = s1->height; + s->width = s1->width; + if ((ret = ff_mpv_common_frame_size_change(s)) < 0) + return ret; + } + + s->avctx->coded_height = s1->avctx->coded_height; + s->avctx->coded_width = s1->avctx->coded_width; + s->avctx->width = s1->avctx->width; + s->avctx->height = s1->avctx->height; + + s->quarter_sample = s1->quarter_sample; + + s->coded_picture_number = s1->coded_picture_number; + s->picture_number = s1->picture_number; + + av_assert0(!s->picture || s->picture != s1->picture); + if (s->picture) + for (int i = 0; i < MAX_PICTURE_COUNT; i++) { + ff_mpeg_unref_picture(s->avctx, &s->picture[i]); + if (s1->picture && s1->picture[i].f->buf[0] && + (ret = ff_mpeg_ref_picture(s->avctx, &s->picture[i], &s1->picture[i])) < 0) + return ret; + } + +#define UPDATE_PICTURE(pic)\ +do {\ + ff_mpeg_unref_picture(s->avctx, &s->pic);\ + if (s1->pic.f && s1->pic.f->buf[0])\ + ret = ff_mpeg_ref_picture(s->avctx, &s->pic, &s1->pic);\ + else\ + ret = ff_update_picture_tables(&s->pic, &s1->pic);\ + if (ret < 0)\ + return ret;\ +} while (0) + + UPDATE_PICTURE(current_picture); + UPDATE_PICTURE(last_picture); + UPDATE_PICTURE(next_picture); + +#define REBASE_PICTURE(pic, new_ctx, old_ctx) \ + ((pic && pic >= old_ctx->picture && \ + pic < old_ctx->picture + MAX_PICTURE_COUNT) ? \ + &new_ctx->picture[pic - old_ctx->picture] : NULL) + + s->last_picture_ptr = REBASE_PICTURE(s1->last_picture_ptr, s, s1); + s->current_picture_ptr = REBASE_PICTURE(s1->current_picture_ptr, s, s1); + s->next_picture_ptr = REBASE_PICTURE(s1->next_picture_ptr, s, s1); + + // Error/bug resilience + s->workaround_bugs = s1->workaround_bugs; + s->padding_bug_score = s1->padding_bug_score; + + // MPEG-4 timing info + memcpy(&s->last_time_base, &s1->last_time_base, + (char *) &s1->pb_field_time + sizeof(s1->pb_field_time) - + (char *) &s1->last_time_base); + + // B-frame info + s->max_b_frames = s1->max_b_frames; + s->low_delay = s1->low_delay; + s->droppable = s1->droppable; + + // DivX handling (doesn't work) + s->divx_packed = s1->divx_packed; + + if (s1->bitstream_buffer) { + if (s1->bitstream_buffer_size + + AV_INPUT_BUFFER_PADDING_SIZE > s->allocated_bitstream_buffer_size) { + av_fast_malloc(&s->bitstream_buffer, + &s->allocated_bitstream_buffer_size, + s1->allocated_bitstream_buffer_size); + if (!s->bitstream_buffer) { + s->bitstream_buffer_size = 0; + return AVERROR(ENOMEM); + } + } + s->bitstream_buffer_size = s1->bitstream_buffer_size; + memcpy(s->bitstream_buffer, s1->bitstream_buffer, + s1->bitstream_buffer_size); + memset(s->bitstream_buffer + s->bitstream_buffer_size, 0, + AV_INPUT_BUFFER_PADDING_SIZE); + } + + // linesize-dependent scratch buffer allocation + if (!s->sc.edge_emu_buffer) + if (s1->linesize) { + if (ff_mpeg_framesize_alloc(s->avctx, &s->me, + &s->sc, s1->linesize) < 0) { + av_log(s->avctx, AV_LOG_ERROR, "Failed to allocate context " + "scratch buffers.\n"); + return AVERROR(ENOMEM); + } + } else { + av_log(s->avctx, AV_LOG_ERROR, "Context scratch buffers could not " + "be allocated due to unknown size.\n"); + } + + // MPEG-2/interlacing info + memcpy(&s->progressive_sequence, &s1->progressive_sequence, + (char *) &s1->rtp_mode - (char *) &s1->progressive_sequence); + + return 0; +} + +int ff_mpv_common_frame_size_change(MpegEncContext *s) +{ + int err = 0; + + if (!s->context_initialized) + return AVERROR(EINVAL); + + ff_mpv_free_context_frame(s); + + if (s->picture) + for (int i = 0; i < MAX_PICTURE_COUNT; i++) + s->picture[i].needs_realloc = 1; + + s->last_picture_ptr = + s->next_picture_ptr = + s->current_picture_ptr = NULL; + + // init + if (s->codec_id == AV_CODEC_ID_MPEG2VIDEO && !s->progressive_sequence) + s->mb_height = (s->height + 31) / 32 * 2; + else + s->mb_height = (s->height + 15) / 16; + + if ((s->width || s->height) && + (err = av_image_check_size(s->width, s->height, 0, s->avctx)) < 0) + goto fail; + + /* set chroma shifts */ + err = av_pix_fmt_get_chroma_sub_sample(s->avctx->pix_fmt, + &s->chroma_x_shift, + &s->chroma_y_shift); + if (err < 0) + goto fail; + + if ((err = ff_mpv_init_context_frame(s))) + goto fail; + + memset(s->thread_context, 0, sizeof(s->thread_context)); + s->thread_context[0] = s; + + if (s->width && s->height) { + err = ff_mpv_init_duplicate_contexts(s); + if (err < 0) + goto fail; + } + s->context_reinit = 0; + + return 0; + fail: + ff_mpv_free_context_frame(s); + s->context_reinit = 1; + return err; +} + +static int alloc_picture(MpegEncContext *s, Picture *pic) +{ + return ff_alloc_picture(s->avctx, pic, &s->me, &s->sc, 0, 0, + s->chroma_x_shift, s->chroma_y_shift, s->out_format, + s->mb_stride, s->mb_width, s->mb_height, s->b8_stride, + &s->linesize, &s->uvlinesize); +} + +static void gray_frame(AVFrame *frame) +{ + int h_chroma_shift, v_chroma_shift; + + av_pix_fmt_get_chroma_sub_sample(frame->format, &h_chroma_shift, &v_chroma_shift); + + for (int i = 0; i < frame->height; i++) + memset(frame->data[0] + frame->linesize[0] * i, 0x80, frame->width); + for (int i = 0; i < AV_CEIL_RSHIFT(frame->height, v_chroma_shift); i++) { + memset(frame->data[1] + frame->linesize[1] * i, + 0x80, AV_CEIL_RSHIFT(frame->width, h_chroma_shift)); + memset(frame->data[2] + frame->linesize[2] * i, + 0x80, AV_CEIL_RSHIFT(frame->width, h_chroma_shift)); + } +} + +/** + * generic function called after decoding + * the header and before a frame is decoded. + */ +int ff_mpv_frame_start(MpegEncContext *s, AVCodecContext *avctx) +{ + Picture *pic; + int idx, ret; + + s->mb_skipped = 0; + + if (!ff_thread_can_start_frame(avctx)) { + av_log(avctx, AV_LOG_ERROR, "Attempt to start a frame outside SETUP state\n"); + return -1; + } + + /* mark & release old frames */ + if (s->pict_type != AV_PICTURE_TYPE_B && s->last_picture_ptr && + s->last_picture_ptr != s->next_picture_ptr && + s->last_picture_ptr->f->buf[0]) { + ff_mpeg_unref_picture(s->avctx, s->last_picture_ptr); + } + + /* release forgotten pictures */ + /* if (MPEG-124 / H.263) */ + for (int i = 0; i < MAX_PICTURE_COUNT; i++) { + if (&s->picture[i] != s->last_picture_ptr && + &s->picture[i] != s->next_picture_ptr && + s->picture[i].reference && !s->picture[i].needs_realloc) { + ff_mpeg_unref_picture(s->avctx, &s->picture[i]); + } + } + + ff_mpeg_unref_picture(s->avctx, &s->current_picture); + ff_mpeg_unref_picture(s->avctx, &s->last_picture); + ff_mpeg_unref_picture(s->avctx, &s->next_picture); + + /* release non reference frames */ + for (int i = 0; i < MAX_PICTURE_COUNT; i++) { + if (!s->picture[i].reference) + ff_mpeg_unref_picture(s->avctx, &s->picture[i]); + } + + if (s->current_picture_ptr && !s->current_picture_ptr->f->buf[0]) { + // we already have an unused image + // (maybe it was set before reading the header) + pic = s->current_picture_ptr; + } else { + idx = ff_find_unused_picture(s->avctx, s->picture, 0); + if (idx < 0) { + av_log(s->avctx, AV_LOG_ERROR, "no frame buffer available\n"); + return idx; + } + pic = &s->picture[idx]; + } + + pic->reference = 0; + if (!s->droppable) { + if (s->pict_type != AV_PICTURE_TYPE_B) + pic->reference = 3; + } + + pic->f->coded_picture_number = s->coded_picture_number++; + + if (alloc_picture(s, pic) < 0) + return -1; + + s->current_picture_ptr = pic; + // FIXME use only the vars from current_pic + s->current_picture_ptr->f->top_field_first = s->top_field_first; + if (s->codec_id == AV_CODEC_ID_MPEG1VIDEO || + s->codec_id == AV_CODEC_ID_MPEG2VIDEO) { + if (s->picture_structure != PICT_FRAME) + s->current_picture_ptr->f->top_field_first = + (s->picture_structure == PICT_TOP_FIELD) == s->first_field; + } + s->current_picture_ptr->f->interlaced_frame = !s->progressive_frame && + !s->progressive_sequence; + s->current_picture_ptr->field_picture = s->picture_structure != PICT_FRAME; + + s->current_picture_ptr->f->pict_type = s->pict_type; + s->current_picture_ptr->f->key_frame = s->pict_type == AV_PICTURE_TYPE_I; + + if ((ret = ff_mpeg_ref_picture(s->avctx, &s->current_picture, + s->current_picture_ptr)) < 0) + return ret; + + if (s->pict_type != AV_PICTURE_TYPE_B) { + s->last_picture_ptr = s->next_picture_ptr; + if (!s->droppable) + s->next_picture_ptr = s->current_picture_ptr; + } + ff_dlog(s->avctx, "L%p N%p C%p L%p N%p C%p type:%d drop:%d\n", + s->last_picture_ptr, s->next_picture_ptr,s->current_picture_ptr, + s->last_picture_ptr ? s->last_picture_ptr->f->data[0] : NULL, + s->next_picture_ptr ? s->next_picture_ptr->f->data[0] : NULL, + s->current_picture_ptr ? s->current_picture_ptr->f->data[0] : NULL, + s->pict_type, s->droppable); + + if ((!s->last_picture_ptr || !s->last_picture_ptr->f->buf[0]) && + (s->pict_type != AV_PICTURE_TYPE_I)) { + int h_chroma_shift, v_chroma_shift; + av_pix_fmt_get_chroma_sub_sample(s->avctx->pix_fmt, + &h_chroma_shift, &v_chroma_shift); + if (s->pict_type == AV_PICTURE_TYPE_B && s->next_picture_ptr && s->next_picture_ptr->f->buf[0]) + av_log(avctx, AV_LOG_DEBUG, + "allocating dummy last picture for B frame\n"); + else if (s->pict_type != AV_PICTURE_TYPE_I) + av_log(avctx, AV_LOG_ERROR, + "warning: first frame is no keyframe\n"); + + /* Allocate a dummy frame */ + idx = ff_find_unused_picture(s->avctx, s->picture, 0); + if (idx < 0) { + av_log(s->avctx, AV_LOG_ERROR, "no frame buffer available\n"); + return idx; + } + s->last_picture_ptr = &s->picture[idx]; + + s->last_picture_ptr->reference = 3; + s->last_picture_ptr->f->key_frame = 0; + s->last_picture_ptr->f->pict_type = AV_PICTURE_TYPE_P; + + if (alloc_picture(s, s->last_picture_ptr) < 0) { + s->last_picture_ptr = NULL; + return -1; + } + + if (!avctx->hwaccel) { + for (int i = 0; i < avctx->height; i++) + memset(s->last_picture_ptr->f->data[0] + s->last_picture_ptr->f->linesize[0]*i, + 0x80, avctx->width); + if (s->last_picture_ptr->f->data[2]) { + for (int i = 0; i < AV_CEIL_RSHIFT(avctx->height, v_chroma_shift); i++) { + memset(s->last_picture_ptr->f->data[1] + s->last_picture_ptr->f->linesize[1]*i, + 0x80, AV_CEIL_RSHIFT(avctx->width, h_chroma_shift)); + memset(s->last_picture_ptr->f->data[2] + s->last_picture_ptr->f->linesize[2]*i, + 0x80, AV_CEIL_RSHIFT(avctx->width, h_chroma_shift)); + } + } + + if (s->codec_id == AV_CODEC_ID_FLV1 || s->codec_id == AV_CODEC_ID_H263) { + for (int i = 0; i < avctx->height; i++) + memset(s->last_picture_ptr->f->data[0] + s->last_picture_ptr->f->linesize[0] * i, + 16, avctx->width); + } + } + + ff_thread_report_progress(&s->last_picture_ptr->tf, INT_MAX, 0); + ff_thread_report_progress(&s->last_picture_ptr->tf, INT_MAX, 1); + } + if ((!s->next_picture_ptr || !s->next_picture_ptr->f->buf[0]) && + s->pict_type == AV_PICTURE_TYPE_B) { + /* Allocate a dummy frame */ + idx = ff_find_unused_picture(s->avctx, s->picture, 0); + if (idx < 0) { + av_log(s->avctx, AV_LOG_ERROR, "no frame buffer available\n"); + return idx; + } + s->next_picture_ptr = &s->picture[idx]; + + s->next_picture_ptr->reference = 3; + s->next_picture_ptr->f->key_frame = 0; + s->next_picture_ptr->f->pict_type = AV_PICTURE_TYPE_P; + + if (alloc_picture(s, s->next_picture_ptr) < 0) { + s->next_picture_ptr = NULL; + return -1; + } + ff_thread_report_progress(&s->next_picture_ptr->tf, INT_MAX, 0); + ff_thread_report_progress(&s->next_picture_ptr->tf, INT_MAX, 1); + } + +#if 0 // BUFREF-FIXME + memset(s->last_picture.f->data, 0, sizeof(s->last_picture.f->data)); + memset(s->next_picture.f->data, 0, sizeof(s->next_picture.f->data)); +#endif + if (s->last_picture_ptr) { + if (s->last_picture_ptr->f->buf[0] && + (ret = ff_mpeg_ref_picture(s->avctx, &s->last_picture, + s->last_picture_ptr)) < 0) + return ret; + } + if (s->next_picture_ptr) { + if (s->next_picture_ptr->f->buf[0] && + (ret = ff_mpeg_ref_picture(s->avctx, &s->next_picture, + s->next_picture_ptr)) < 0) + return ret; + } + + av_assert0(s->pict_type == AV_PICTURE_TYPE_I || (s->last_picture_ptr && + s->last_picture_ptr->f->buf[0])); + + if (s->picture_structure != PICT_FRAME) { + for (int i = 0; i < 4; i++) { + if (s->picture_structure == PICT_BOTTOM_FIELD) { + s->current_picture.f->data[i] += + s->current_picture.f->linesize[i]; + } + s->current_picture.f->linesize[i] *= 2; + s->last_picture.f->linesize[i] *= 2; + s->next_picture.f->linesize[i] *= 2; + } + } + + /* set dequantizer, we can't do it during init as + * it might change for MPEG-4 and we can't do it in the header + * decode as init is not called for MPEG-4 there yet */ + if (s->mpeg_quant || s->codec_id == AV_CODEC_ID_MPEG2VIDEO) { + s->dct_unquantize_intra = s->dct_unquantize_mpeg2_intra; + s->dct_unquantize_inter = s->dct_unquantize_mpeg2_inter; + } else if (s->out_format == FMT_H263 || s->out_format == FMT_H261) { + s->dct_unquantize_intra = s->dct_unquantize_h263_intra; + s->dct_unquantize_inter = s->dct_unquantize_h263_inter; + } else { + s->dct_unquantize_intra = s->dct_unquantize_mpeg1_intra; + s->dct_unquantize_inter = s->dct_unquantize_mpeg1_inter; + } + + if (s->avctx->debug & FF_DEBUG_NOMC) + gray_frame(s->current_picture_ptr->f); + + return 0; +} + +/* called after a frame has been decoded. */ +void ff_mpv_frame_end(MpegEncContext *s) +{ + emms_c(); + + if (s->current_picture.reference) + ff_thread_report_progress(&s->current_picture_ptr->tf, INT_MAX, 0); +} + +void ff_print_debug_info(MpegEncContext *s, Picture *p, AVFrame *pict) +{ + ff_print_debug_info2(s->avctx, pict, s->mbskip_table, p->mb_type, + p->qscale_table, p->motion_val, + s->mb_width, s->mb_height, s->mb_stride, s->quarter_sample); +} + +int ff_mpv_export_qp_table(MpegEncContext *s, AVFrame *f, Picture *p, int qp_type) +{ + AVVideoEncParams *par; + int mult = (qp_type == FF_MPV_QSCALE_TYPE_MPEG1) ? 2 : 1; + unsigned int nb_mb = p->alloc_mb_height * p->alloc_mb_width; + + if (!(s->avctx->export_side_data & AV_CODEC_EXPORT_DATA_VIDEO_ENC_PARAMS)) + return 0; + + par = av_video_enc_params_create_side_data(f, AV_VIDEO_ENC_PARAMS_MPEG2, nb_mb); + if (!par) + return AVERROR(ENOMEM); + + for (unsigned y = 0; y < p->alloc_mb_height; y++) + for (unsigned x = 0; x < p->alloc_mb_width; x++) { + const unsigned int block_idx = y * p->alloc_mb_width + x; + const unsigned int mb_xy = y * p->alloc_mb_stride + x; + AVVideoBlockParams *const b = av_video_enc_params_block(par, block_idx); + + b->src_x = x * 16; + b->src_y = y * 16; + b->w = 16; + b->h = 16; + + b->delta_qp = p->qscale_table[mb_xy] * mult; + } + + return 0; +} + +void ff_mpeg_draw_horiz_band(MpegEncContext *s, int y, int h) +{ + ff_draw_horiz_band(s->avctx, s->current_picture_ptr->f, + s->last_picture_ptr ? s->last_picture_ptr->f : NULL, + y, h, s->picture_structure, + s->first_field, s->low_delay); +} + +void ff_mpeg_flush(AVCodecContext *avctx) +{ + MpegEncContext *const s = avctx->priv_data; + + if (!s->picture) + return; + + for (int i = 0; i < MAX_PICTURE_COUNT; i++) + ff_mpeg_unref_picture(s->avctx, &s->picture[i]); + s->current_picture_ptr = s->last_picture_ptr = s->next_picture_ptr = NULL; + + ff_mpeg_unref_picture(s->avctx, &s->current_picture); + ff_mpeg_unref_picture(s->avctx, &s->last_picture); + ff_mpeg_unref_picture(s->avctx, &s->next_picture); + + s->mb_x = s->mb_y = 0; + +#if FF_API_FLAG_TRUNCATED + s->parse_context.state = -1; + s->parse_context.frame_start_found = 0; + s->parse_context.overread = 0; + s->parse_context.overread_index = 0; + s->parse_context.index = 0; + s->parse_context.last_index = 0; +#endif + s->bitstream_buffer_size = 0; + s->pp_time = 0; +} + +void ff_mpv_report_decode_progress(MpegEncContext *s) +{ + if (s->pict_type != AV_PICTURE_TYPE_B && !s->partitioned_frame && !s->er.error_occurred) + ff_thread_report_progress(&s->current_picture_ptr->tf, s->mb_y, 0); +} diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c index 128d1a327..c9d9e2a76 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -31,6 +31,8 @@ * The simplest mpeg encoder (well, it was the simplest!). */ +#include "config_components.h" + #include #include "libavutil/internal.h" @@ -45,28 +47,33 @@ #include "encode.h" #include "idctdsp.h" #include "mpeg12.h" +#include "mpeg12data.h" +#include "mpeg12enc.h" #include "mpegvideo.h" #include "mpegvideodata.h" -#include "h261.h" +#include "mpegvideoenc.h" +#include "h261enc.h" #include "h263.h" #include "h263data.h" +#include "h263enc.h" #include "mjpegenc_common.h" #include "mathops.h" #include "mpegutils.h" #include "mjpegenc.h" #include "speedhqenc.h" -#include "msmpeg4.h" +#include "msmpeg4enc.h" #include "pixblockdsp.h" #include "qpeldsp.h" #include "faandct.h" -#include "thread.h" #include "aandcttab.h" -#include "flv.h" +#include "flvenc.h" #include "mpeg4video.h" +#include "mpeg4videodata.h" +#include "mpeg4videoenc.h" #include "internal.h" #include "bytestream.h" -#include "wmv2.h" -#include "rv10.h" +#include "wmv2enc.h" +#include "rv10enc.h" #include "packet_internal.h" #include #include "sp5x.h" @@ -87,12 +94,7 @@ static uint8_t default_fcode_tab[MAX_MV * 2 + 1]; static const AVOption mpv_generic_options[] = { FF_MPV_COMMON_OPTS -#if FF_API_MPEGVIDEO_OPTS - FF_MPV_DEPRECATED_MPEG_QUANT_OPT - FF_MPV_DEPRECATED_A53_CC_OPT - FF_MPV_DEPRECATED_MATRIX_OPT - FF_MPV_DEPRECATED_BFRAME_OPTS -#endif + FF_MPV_COMMON_MOTION_EST_OPTS { NULL }, }; @@ -245,7 +247,7 @@ void ff_init_qscale_tab(MpegEncContext *s) } static void update_duplicate_context_after_me(MpegEncContext *dst, - MpegEncContext *src) + const MpegEncContext *src) { #define COPY(a) dst->a= src->a COPY(pict_type); @@ -255,8 +257,6 @@ static void update_duplicate_context_after_me(MpegEncContext *dst, COPY(qscale); COPY(lambda); COPY(lambda2); - COPY(picture_in_gop_number); - COPY(gop_picture_number); COPY(frame_pred_frame_dct); // FIXME don't set in encode_header COPY(progressive_frame); // FIXME don't set in encode_header COPY(partitioned_frame); // FIXME don't set in encode_header @@ -290,8 +290,9 @@ static void mpv_encode_defaults(MpegEncContext *s) av_cold int ff_dct_encode_init(MpegEncContext *s) { - if (ARCH_X86) - ff_dct_encode_init_x86(s); +#if ARCH_X86 + ff_dct_encode_init_x86(s); +#endif if (CONFIG_H263_ENCODER) ff_h263dsp_init(&s->h263dsp); @@ -349,10 +350,18 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) av_log(avctx, AV_LOG_ERROR, "Too many B-frames requested, maximum " "is %d.\n", MAX_B_FRAMES); avctx->max_b_frames = MAX_B_FRAMES; + } else if (avctx->max_b_frames < 0) { + av_log(avctx, AV_LOG_ERROR, + "max b frames must be 0 or positive for mpegvideo based encoders\n"); + return AVERROR(EINVAL); } s->max_b_frames = avctx->max_b_frames; s->codec_id = avctx->codec->id; - s->strict_std_compliance = avctx->strict_std_compliance; + if (s->max_b_frames && !(avctx->codec->capabilities & AV_CODEC_CAP_DELAY)) { + av_log(avctx, AV_LOG_ERROR, "B-frames not supported by codec\n"); + return AVERROR(EINVAL); + } + s->quarter_sample = (avctx->flags & AV_CODEC_FLAG_QPEL) != 0; s->rtp_mode = !!s->rtp_payload_size; s->intra_dc_precision = avctx->intra_dc_precision; @@ -370,9 +379,6 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) return AVERROR(EINVAL); } - if (avctx->codec_id == AV_CODEC_ID_AMV || (avctx->active_thread_type & FF_THREAD_SLICE)) - s->huffman = 0; - if (s->intra_dc_precision > (avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO ? 3 : 0)) { av_log(avctx, AV_LOG_ERROR, "intra dc precision too large\n"); return AVERROR(EINVAL); @@ -501,19 +507,6 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) return AVERROR(EINVAL); } - if (s->max_b_frames && - s->codec_id != AV_CODEC_ID_MPEG4 && - s->codec_id != AV_CODEC_ID_MPEG1VIDEO && - s->codec_id != AV_CODEC_ID_MPEG2VIDEO) { - av_log(avctx, AV_LOG_ERROR, "B-frames not supported by codec\n"); - return AVERROR(EINVAL); - } - if (s->max_b_frames < 0) { - av_log(avctx, AV_LOG_ERROR, - "max b frames must be 0 or positive for mpegvideo based encoders\n"); - return AVERROR(EINVAL); - } - if ((s->codec_id == AV_CODEC_ID_MPEG4 || s->codec_id == AV_CODEC_ID_H263 || s->codec_id == AV_CODEC_ID_H263P) && @@ -573,15 +566,6 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) return AVERROR(EINVAL); } - if ((s->mpv_flags & FF_MPV_FLAG_QP_RD) && - (s->codec_id == AV_CODEC_ID_AMV || - s->codec_id == AV_CODEC_ID_MJPEG)) { - // Used to produce garbage with MJPEG. - av_log(avctx, AV_LOG_ERROR, - "QP RD is no longer compatible with MJPEG or AMV\n"); - return AVERROR(EINVAL); - } - if (s->scenechange_threshold < 1000000000 && (avctx->flags & AV_CODEC_FLAG_CLOSED_GOP)) { av_log(avctx, AV_LOG_ERROR, @@ -592,7 +576,7 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) if (avctx->flags & AV_CODEC_FLAG_LOW_DELAY) { if (s->codec_id != AV_CODEC_ID_MPEG2VIDEO && - s->strict_std_compliance >= FF_COMPLIANCE_NORMAL) { + avctx->strict_std_compliance >= FF_COMPLIANCE_NORMAL) { av_log(avctx, AV_LOG_ERROR, "low delay forcing is only available for mpeg2, " "set strict_std_compliance to 'unofficial' or lower in order to allow it\n"); @@ -614,29 +598,11 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) } if (avctx->slices > 1 && - (avctx->codec_id == AV_CODEC_ID_FLV1 || avctx->codec_id == AV_CODEC_ID_H261)) { + !(avctx->codec->capabilities & AV_CODEC_CAP_SLICE_THREADS)) { av_log(avctx, AV_LOG_ERROR, "Multiple slices are not supported by this codec\n"); return AVERROR(EINVAL); } - if (avctx->thread_count > 1 && - s->codec_id != AV_CODEC_ID_MPEG4 && - s->codec_id != AV_CODEC_ID_MPEG1VIDEO && - s->codec_id != AV_CODEC_ID_MPEG2VIDEO && - s->codec_id != AV_CODEC_ID_MJPEG && - (s->codec_id != AV_CODEC_ID_H263P)) { - av_log(avctx, AV_LOG_ERROR, - "multi threaded encoding not supported by codec\n"); - return AVERROR_PATCHWELCOME; - } - - if (avctx->thread_count < 1) { - av_log(avctx, AV_LOG_ERROR, - "automatic thread number detection not supported by codec, " - "patch welcome\n"); - return AVERROR_PATCHWELCOME; - } - if (s->b_frame_strategy && (avctx->flags & AV_CODEC_FLAG_PASS2)) { av_log(avctx, AV_LOG_INFO, "notice: b_frame_strategy only affects the first pass\n"); @@ -846,12 +812,6 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) ff_pixblockdsp_init(&s->pdsp, avctx); ff_qpeldsp_init(&s->qdsp); - if (s->msmpeg4_version) { - int ac_stats_size = 2 * 2 * (MAX_LEVEL + 1) * (MAX_RUN + 1) * 2 * sizeof(int); - if (!(s->ac_stats = av_mallocz(ac_stats_size))) - return AVERROR(ENOMEM); - } - if (!(avctx->stats_out = av_mallocz(256)) || !FF_ALLOCZ_TYPED_ARRAY(s->q_intra_matrix, 32) || !FF_ALLOCZ_TYPED_ARRAY(s->q_chroma_intra_matrix, 32) || @@ -970,18 +930,13 @@ av_cold int ff_mpv_encode_end(AVCodecContext *avctx) ff_rate_control_uninit(s); ff_mpv_common_end(s); - if ((CONFIG_MJPEG_ENCODER || CONFIG_AMV_ENCODER) && - s->out_format == FMT_MJPEG) - ff_mjpeg_encode_close(s); for (i = 0; i < FF_ARRAY_ELEMS(s->tmp_frames); i++) av_frame_free(&s->tmp_frames[i]); - ff_free_picture_tables(&s->new_picture); - ff_mpeg_unref_picture(avctx, &s->new_picture); + av_frame_free(&s->new_picture); av_freep(&avctx->stats_out); - av_freep(&s->ac_stats); if(s->q_chroma_intra_matrix != s->q_intra_matrix ) av_freep(&s->q_chroma_intra_matrix); if(s->q_chroma_intra_matrix16 != s->q_intra_matrix16) av_freep(&s->q_chroma_intra_matrix16); @@ -1258,7 +1213,6 @@ static int encode_frame(AVCodecContext *c, AVFrame *frame, AVPacket *pkt) static int estimate_best_b_count(MpegEncContext *s) { - const AVCodec *codec = avcodec_find_encoder(s->avctx->codec_id); AVPacket *pkt; const int scale = s->brd_scale; int width = s->width >> scale; @@ -1342,7 +1296,7 @@ static int estimate_best_b_count(MpegEncContext *s) c->time_base = s->avctx->time_base; c->max_b_frames = s->max_b_frames; - ret = avcodec_open2(c, codec, NULL); + ret = avcodec_open2(c, s->avctx->codec, NULL); if (ret < 0) goto fail; @@ -1528,14 +1482,15 @@ static int select_input_picture(MpegEncContext *s) } } no_output_pic: - ff_mpeg_unref_picture(s->avctx, &s->new_picture); + av_frame_unref(s->new_picture); if (s->reordered_input_picture[0]) { s->reordered_input_picture[0]->reference = s->reordered_input_picture[0]->f->pict_type != AV_PICTURE_TYPE_B ? 3 : 0; - if ((ret = ff_mpeg_ref_picture(s->avctx, &s->new_picture, s->reordered_input_picture[0]))) + if ((ret = av_frame_ref(s->new_picture, + s->reordered_input_picture[0]->f))) return ret; if (s->reordered_input_picture[0]->shared || s->avctx->rc_buffer_size) { @@ -1566,16 +1521,11 @@ no_output_pic: // input is not a shared pix -> reuse buffer for current_pix s->current_picture_ptr = s->reordered_input_picture[0]; for (i = 0; i < 4; i++) { - if (s->new_picture.f->data[i]) - s->new_picture.f->data[i] += INPLACE_OFFSET; + if (s->new_picture->data[i]) + s->new_picture->data[i] += INPLACE_OFFSET; } } - ff_mpeg_unref_picture(s->avctx, &s->current_picture); - if ((ret = ff_mpeg_ref_picture(s->avctx, &s->current_picture, - s->current_picture_ptr)) < 0) - return ret; - - s->picture_number = s->new_picture.f->display_picture_number; + s->picture_number = s->new_picture->display_picture_number; } return 0; } @@ -1728,13 +1678,18 @@ int ff_mpv_encode_picture(AVCodecContext *avctx, AVPacket *pkt, } /* output? */ - if (s->new_picture.f->data[0]) { - int growing_buffer = context_count == 1 && !pkt->data && !s->data_partitioning; - int pkt_size = growing_buffer ? FFMAX(s->mb_width*s->mb_height*64+10000, avctx->internal->byte_buffer_size) - AV_INPUT_BUFFER_PADDING_SIZE - : - s->mb_width*s->mb_height*(MAX_MB_BYTES+100)+10000; + if (s->new_picture->data[0]) { + int growing_buffer = context_count == 1 && !s->data_partitioning; + size_t pkt_size = 10000 + s->mb_width * s->mb_height * + (growing_buffer ? 64 : (MAX_MB_BYTES + 100)); + if (CONFIG_MJPEG_ENCODER && avctx->codec_id == AV_CODEC_ID_MJPEG) { + ret = ff_mjpeg_add_icc_profile_size(avctx, s->new_picture, &pkt_size); + if (ret < 0) + return ret; + } if ((ret = ff_alloc_packet(avctx, pkt, pkt_size)) < 0) return ret; + pkt->size = avctx->internal->byte_buffer_size - AV_INPUT_BUFFER_PADDING_SIZE; if (s->mb_info) { s->mb_info_ptr = av_packet_new_side_data(pkt, AV_PKT_DATA_H263_MB_INFO, @@ -1752,7 +1707,7 @@ int ff_mpv_encode_picture(AVCodecContext *avctx, AVPacket *pkt, init_put_bits(&s->thread_context[i]->pb, start, end - start); } - s->pict_type = s->new_picture.f->pict_type; + s->pict_type = s->new_picture->pict_type; //emms_c(); ret = frame_start(s); if (ret < 0) @@ -1823,7 +1778,7 @@ vbv_retry: } ff_side_data_set_encoder_stats(pkt, s->current_picture.f->quality, s->current_picture_ptr->encoding_error, - (avctx->flags&AV_CODEC_FLAG_PSNR) ? 4 : 0, + (avctx->flags&AV_CODEC_FLAG_PSNR) ? MPEGVIDEO_MAX_PLANES : 0, s->pict_type); if (avctx->flags & AV_CODEC_FLAG_PASS1) @@ -1877,8 +1832,9 @@ vbv_retry: double inbits = avctx->rc_max_rate * av_q2d(avctx->time_base); int minbits = s->frame_bits - 8 * - (s->vbv_delay_ptr - s->pb.buf - 1); + (s->vbv_delay_pos - 1); double bits = s->rc_context.buffer_index + minbits - inbits; + uint8_t *const vbv_delay_ptr = s->pb.buf + s->vbv_delay_pos; if (bits < 0) av_log(avctx, AV_LOG_ERROR, @@ -1894,11 +1850,11 @@ vbv_retry: av_assert0(vbv_delay < 0xFFFF); - s->vbv_delay_ptr[0] &= 0xF8; - s->vbv_delay_ptr[0] |= vbv_delay >> 13; - s->vbv_delay_ptr[1] = vbv_delay >> 5; - s->vbv_delay_ptr[2] &= 0x07; - s->vbv_delay_ptr[2] |= vbv_delay << 3; + vbv_delay_ptr[0] &= 0xF8; + vbv_delay_ptr[0] |= vbv_delay >> 13; + vbv_delay_ptr[1] = vbv_delay >> 5; + vbv_delay_ptr[2] &= 0x07; + vbv_delay_ptr[2] |= vbv_delay << 3; props = av_cpb_properties_alloc(&props_size); if (!props) @@ -2062,8 +2018,15 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, int motion_x, int motion_y, int mb_block_height, int mb_block_width, - int mb_block_count) + int mb_block_count, + int chroma_x_shift, + int chroma_y_shift, + int chroma_format) { +/* Interlaced DCT is only possible with MPEG-2 and MPEG-4 + * and neither of these encoders currently supports 444. */ +#define INTERLACED_DCT(s) ((chroma_format == CHROMA_420 || chroma_format == CHROMA_422) && \ + (s)->avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) int16_t weight[12][64]; int16_t orig[12][64]; const int mb_x = s->mb_x; @@ -2110,17 +2073,17 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, wrap_y = s->linesize; wrap_c = s->uvlinesize; - ptr_y = s->new_picture.f->data[0] + + ptr_y = s->new_picture->data[0] + (mb_y * 16 * wrap_y) + mb_x * 16; - ptr_cb = s->new_picture.f->data[1] + + ptr_cb = s->new_picture->data[1] + (mb_y * mb_block_height * wrap_c) + mb_x * mb_block_width; - ptr_cr = s->new_picture.f->data[2] + + ptr_cr = s->new_picture->data[2] + (mb_y * mb_block_height * wrap_c) + mb_x * mb_block_width; if((mb_x * 16 + 16 > s->width || mb_y * 16 + 16 > s->height) && s->codec_id != AV_CODEC_ID_AMV){ uint8_t *ebuf = s->sc.edge_emu_buffer + 38 * wrap_y; - int cw = (s->width + s->chroma_x_shift) >> s->chroma_x_shift; - int ch = (s->height + s->chroma_y_shift) >> s->chroma_y_shift; + int cw = (s->width + chroma_x_shift) >> chroma_x_shift; + int ch = (s->height + chroma_y_shift) >> chroma_y_shift; s->vdsp.emulated_edge_mc(ebuf, ptr_y, wrap_y, wrap_y, 16, 16, mb_x * 16, mb_y * 16, @@ -2141,7 +2104,7 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, } if (s->mb_intra) { - if (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) { + if (INTERLACED_DCT(s)) { int progressive_score, interlaced_score; s->interlaced_dct = 0; @@ -2160,8 +2123,8 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, dct_offset = wrap_y; uv_dct_offset = wrap_c; wrap_y <<= 1; - if (s->chroma_format == CHROMA_422 || - s->chroma_format == CHROMA_444) + if (chroma_format == CHROMA_422 || + chroma_format == CHROMA_444) wrap_c <<= 1; } } @@ -2178,10 +2141,10 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, } else { s->pdsp.get_pixels(s->block[4], ptr_cb, wrap_c); s->pdsp.get_pixels(s->block[5], ptr_cr, wrap_c); - if (!s->chroma_y_shift && s->chroma_x_shift) { /* 422 */ + if (chroma_format == CHROMA_422) { s->pdsp.get_pixels(s->block[6], ptr_cb + uv_dct_offset, wrap_c); s->pdsp.get_pixels(s->block[7], ptr_cr + uv_dct_offset, wrap_c); - } else if (!s->chroma_y_shift && !s->chroma_x_shift) { /* 444 */ + } else if (chroma_format == CHROMA_444) { s->pdsp.get_pixels(s->block[ 6], ptr_cb + 8, wrap_c); s->pdsp.get_pixels(s->block[ 7], ptr_cr + 8, wrap_c); s->pdsp.get_pixels(s->block[ 8], ptr_cb + uv_dct_offset, wrap_c); @@ -2220,7 +2183,7 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, op_pix, op_qpix); } - if (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) { + if (INTERLACED_DCT(s)) { int progressive_score, interlaced_score; s->interlaced_dct = 0; @@ -2245,7 +2208,7 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, dct_offset = wrap_y; uv_dct_offset = wrap_c; wrap_y <<= 1; - if (s->chroma_format == CHROMA_422) + if (chroma_format == CHROMA_422) wrap_c <<= 1; } } @@ -2264,7 +2227,7 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, } else { s->pdsp.diff_pixels(s->block[4], ptr_cb, dest_cb, wrap_c); s->pdsp.diff_pixels(s->block[5], ptr_cr, dest_cr, wrap_c); - if (!s->chroma_y_shift) { /* 422 */ + if (!chroma_y_shift) { /* 422 */ s->pdsp.diff_pixels(s->block[6], ptr_cb + uv_dct_offset, dest_cb + uv_dct_offset, wrap_c); s->pdsp.diff_pixels(s->block[7], ptr_cr + uv_dct_offset, @@ -2289,7 +2252,7 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, skip_dct[4] = 1; if (s->mecc.sad[1](NULL, ptr_cr, dest_cr, wrap_c, 8) < 20 * s->qscale) skip_dct[5] = 1; - if (!s->chroma_y_shift) { /* 422 */ + if (!chroma_y_shift) { /* 422 */ if (s->mecc.sad[1](NULL, ptr_cb + uv_dct_offset, dest_cb + uv_dct_offset, wrap_c, 8) < 20 * s->qscale) @@ -2315,7 +2278,7 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, get_visual_weight(weight[4], ptr_cb , wrap_c); if (!skip_dct[5]) get_visual_weight(weight[5], ptr_cr , wrap_c); - if (!s->chroma_y_shift) { /* 422 */ + if (!chroma_y_shift) { /* 422 */ if (!skip_dct[6]) get_visual_weight(weight[6], ptr_cb + uv_dct_offset, wrap_c); @@ -2373,7 +2336,7 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, s->block_last_index[5] = 0; s->block[4][0] = s->block[5][0] = (1024 + s->c_dc_scale / 2) / s->c_dc_scale; - if (!s->chroma_y_shift) { /* 422 / 444 */ + if (!chroma_y_shift) { /* 422 / 444 */ for (i=6; i<12; i++) { s->block_last_index[i] = 0; s->block[i][0] = s->block[4][0]; @@ -2445,12 +2408,17 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, static av_always_inline void encode_mb(MpegEncContext *s, int motion_x, int motion_y) { - if (s->chroma_format == CHROMA_420) encode_mb_internal(s, motion_x, motion_y, 8, 8, 6); - else if (s->chroma_format == CHROMA_422) encode_mb_internal(s, motion_x, motion_y, 16, 8, 8); - else encode_mb_internal(s, motion_x, motion_y, 16, 16, 12); + if (s->chroma_format == CHROMA_420) + encode_mb_internal(s, motion_x, motion_y, 8, 8, 6, 1, 1, CHROMA_420); + else if (s->chroma_format == CHROMA_422) + encode_mb_internal(s, motion_x, motion_y, 16, 8, 8, 1, 0, CHROMA_422); + else + encode_mb_internal(s, motion_x, motion_y, 16, 16, 12, 0, 0, CHROMA_444); } -static inline void copy_context_before_encode(MpegEncContext *d, MpegEncContext *s, int type){ +static inline void copy_context_before_encode(MpegEncContext *d, + const MpegEncContext *s) +{ int i; memcpy(d->last_mv, s->last_mv, 2*2*2*sizeof(int)); //FIXME is memcpy faster than a loop? @@ -2465,8 +2433,6 @@ static inline void copy_context_before_encode(MpegEncContext *d, MpegEncContext d->i_tex_bits= s->i_tex_bits; d->p_tex_bits= s->p_tex_bits; d->i_count= s->i_count; - d->f_count= s->f_count; - d->b_count= s->b_count; d->skip_count= s->skip_count; d->misc_bits= s->misc_bits; d->last_bits= 0; @@ -2478,7 +2444,9 @@ static inline void copy_context_before_encode(MpegEncContext *d, MpegEncContext d->esc3_level_length= s->esc3_level_length; } -static inline void copy_context_after_encode(MpegEncContext *d, MpegEncContext *s, int type){ +static inline void copy_context_after_encode(MpegEncContext *d, + const MpegEncContext *s) +{ int i; memcpy(d->mv, s->mv, 2*4*2*sizeof(int)); @@ -2494,8 +2462,6 @@ static inline void copy_context_after_encode(MpegEncContext *d, MpegEncContext * d->i_tex_bits= s->i_tex_bits; d->p_tex_bits= s->p_tex_bits; d->i_count= s->i_count; - d->f_count= s->f_count; - d->b_count= s->b_count; d->skip_count= s->skip_count; d->misc_bits= s->misc_bits; @@ -2517,14 +2483,14 @@ static inline void copy_context_after_encode(MpegEncContext *d, MpegEncContext * d->esc3_level_length= s->esc3_level_length; } -static inline void encode_mb_hq(MpegEncContext *s, MpegEncContext *backup, MpegEncContext *best, int type, +static inline void encode_mb_hq(MpegEncContext *s, MpegEncContext *backup, MpegEncContext *best, PutBitContext pb[2], PutBitContext pb2[2], PutBitContext tex_pb[2], int *dmin, int *next_block, int motion_x, int motion_y) { int score; uint8_t *dest_backup[3]; - copy_context_before_encode(s, backup, type); + copy_context_before_encode(s, backup); s->block= s->blocks[*next_block]; s->pb= pb[*next_block]; @@ -2564,7 +2530,7 @@ static inline void encode_mb_hq(MpegEncContext *s, MpegEncContext *backup, MpegE *dmin= score; *next_block^=1; - copy_context_after_encode(best, s, type); + copy_context_after_encode(best, s); } } @@ -2592,24 +2558,35 @@ static int sse(MpegEncContext *s, uint8_t *src1, uint8_t *src2, int w, int h, in static int sse_mb(MpegEncContext *s){ int w= 16; int h= 16; + int chroma_mb_w = w >> s->chroma_x_shift; + int chroma_mb_h = h >> s->chroma_y_shift; if(s->mb_x*16 + 16 > s->width ) w= s->width - s->mb_x*16; if(s->mb_y*16 + 16 > s->height) h= s->height- s->mb_y*16; if(w==16 && h==16) if(s->avctx->mb_cmp == FF_CMP_NSSE){ - return s->mecc.nsse[0](s, s->new_picture.f->data[0] + s->mb_x * 16 + s->mb_y * s->linesize * 16, s->dest[0], s->linesize, 16) + - s->mecc.nsse[1](s, s->new_picture.f->data[1] + s->mb_x * 8 + s->mb_y * s->uvlinesize * 8, s->dest[1], s->uvlinesize, 8) + - s->mecc.nsse[1](s, s->new_picture.f->data[2] + s->mb_x * 8 + s->mb_y * s->uvlinesize * 8, s->dest[2], s->uvlinesize, 8); + return s->mecc.nsse[0](s, s->new_picture->data[0] + s->mb_x * 16 + s->mb_y * s->linesize * 16, + s->dest[0], s->linesize, 16) + + s->mecc.nsse[1](s, s->new_picture->data[1] + s->mb_x * chroma_mb_w + s->mb_y * s->uvlinesize * chroma_mb_h, + s->dest[1], s->uvlinesize, chroma_mb_h) + + s->mecc.nsse[1](s, s->new_picture->data[2] + s->mb_x * chroma_mb_w + s->mb_y * s->uvlinesize * chroma_mb_h, + s->dest[2], s->uvlinesize, chroma_mb_h); }else{ - return s->mecc.sse[0](NULL, s->new_picture.f->data[0] + s->mb_x * 16 + s->mb_y * s->linesize * 16, s->dest[0], s->linesize, 16) + - s->mecc.sse[1](NULL, s->new_picture.f->data[1] + s->mb_x * 8 + s->mb_y * s->uvlinesize * 8, s->dest[1], s->uvlinesize, 8) + - s->mecc.sse[1](NULL, s->new_picture.f->data[2] + s->mb_x * 8 + s->mb_y * s->uvlinesize * 8, s->dest[2], s->uvlinesize, 8); + return s->mecc.sse[0](NULL, s->new_picture->data[0] + s->mb_x * 16 + s->mb_y * s->linesize * 16, + s->dest[0], s->linesize, 16) + + s->mecc.sse[1](NULL, s->new_picture->data[1] + s->mb_x * chroma_mb_w + s->mb_y * s->uvlinesize * chroma_mb_h, + s->dest[1], s->uvlinesize, chroma_mb_h) + + s->mecc.sse[1](NULL, s->new_picture->data[2] + s->mb_x * chroma_mb_w + s->mb_y * s->uvlinesize * chroma_mb_h, + s->dest[2], s->uvlinesize, chroma_mb_h); } else - return sse(s, s->new_picture.f->data[0] + s->mb_x*16 + s->mb_y*s->linesize*16, s->dest[0], w, h, s->linesize) - +sse(s, s->new_picture.f->data[1] + s->mb_x*8 + s->mb_y*s->uvlinesize*8,s->dest[1], w>>1, h>>1, s->uvlinesize) - +sse(s, s->new_picture.f->data[2] + s->mb_x*8 + s->mb_y*s->uvlinesize*8,s->dest[2], w>>1, h>>1, s->uvlinesize); + return sse(s, s->new_picture->data[0] + s->mb_x * 16 + s->mb_y * s->linesize * 16, + s->dest[0], w, h, s->linesize) + + sse(s, s->new_picture->data[1] + s->mb_x * chroma_mb_w + s->mb_y * s->uvlinesize * chroma_mb_h, + s->dest[1], w >> s->chroma_x_shift, h >> s->chroma_y_shift, s->uvlinesize) + + sse(s, s->new_picture->data[2] + s->mb_x * chroma_mb_w + s->mb_y * s->uvlinesize * chroma_mb_h, + s->dest[2], w >> s->chroma_x_shift, h >> s->chroma_y_shift, s->uvlinesize); } static int pre_estimate_motion_thread(AVCodecContext *c, void *arg){ @@ -2664,7 +2641,7 @@ static int mb_var_thread(AVCodecContext *c, void *arg){ for(mb_x=0; mb_x < s->mb_width; mb_x++) { int xx = mb_x * 16; int yy = mb_y * 16; - uint8_t *pix = s->new_picture.f->data[0] + (yy * s->linesize) + xx; + uint8_t *pix = s->new_picture->data[0] + (yy * s->linesize) + xx; int varc; int sum = s->mpvencdsp.pix_sum(pix, s->linesize); @@ -2748,7 +2725,6 @@ int ff_mpv_reallocate_putbitbuffer(MpegEncContext *s, size_t threshold, size_t s && s->slice_context_count == 1 && s->pb.buf == s->avctx->internal->byte_buffer) { int lastgob_pos = s->ptr_lastgob - s->pb.buf; - int vbv_pos = s->vbv_delay_ptr - s->pb.buf; uint8_t *new_buffer = NULL; int new_buffer_size = 0; @@ -2771,7 +2747,6 @@ int ff_mpv_reallocate_putbitbuffer(MpegEncContext *s, size_t threshold, size_t s s->avctx->internal->byte_buffer_size = new_buffer_size; rebase_put_bits(&s->pb, new_buffer, new_buffer_size); s->ptr_lastgob = s->pb.buf + lastgob_pos; - s->vbv_delay_ptr = s->pb.buf + vbv_pos; } if (put_bytes_left(&s->pb, 0) < threshold) return AVERROR(EINVAL); @@ -2801,8 +2776,6 @@ static int encode_thread(AVCodecContext *c, void *arg){ s->i_tex_bits=0; s->p_tex_bits=0; s->i_count=0; - s->f_count=0; - s->b_count=0; s->skip_count=0; for(i=0; i<3; i++){ @@ -2938,8 +2911,6 @@ static int encode_thread(AVCodecContext *c, void *arg){ } } - update_mb_info(s, 1); - switch(s->codec_id){ case AV_CODEC_ID_MPEG4: if (CONFIG_MPEG4_ENCODER) { @@ -2956,8 +2927,10 @@ static int encode_thread(AVCodecContext *c, void *arg){ break; case AV_CODEC_ID_H263: case AV_CODEC_ID_H263P: - if (CONFIG_H263_ENCODER) + if (CONFIG_H263_ENCODER) { + update_mb_info(s, 1); ff_h263_encode_gob_header(s, mb_y); + } break; } @@ -2988,7 +2961,7 @@ static int encode_thread(AVCodecContext *c, void *arg){ int next_block=0; int pb_bits_count, pb2_bits_count, tex_pb_bits_count; - copy_context_before_encode(&backup_s, s, -1); + copy_context_before_encode(&backup_s, s); backup_s.pb= s->pb; best_s.data_partitioning= s->data_partitioning; best_s.partitioned_frame= s->partitioned_frame; @@ -3003,7 +2976,7 @@ static int encode_thread(AVCodecContext *c, void *arg){ s->mb_intra= 0; s->mv[0][0][0] = s->p_mv_table[xy][0]; s->mv[0][0][1] = s->p_mv_table[xy][1]; - encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_INTER, pb, pb2, tex_pb, + encode_mb_hq(s, &backup_s, &best_s, pb, pb2, tex_pb, &dmin, &next_block, s->mv[0][0][0], s->mv[0][0][1]); } if(mb_type&CANDIDATE_MB_TYPE_INTER_I){ @@ -3015,7 +2988,7 @@ static int encode_thread(AVCodecContext *c, void *arg){ s->mv[0][i][0] = s->p_field_mv_table[i][j][xy][0]; s->mv[0][i][1] = s->p_field_mv_table[i][j][xy][1]; } - encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_INTER_I, pb, pb2, tex_pb, + encode_mb_hq(s, &backup_s, &best_s, pb, pb2, tex_pb, &dmin, &next_block, 0, 0); } if(mb_type&CANDIDATE_MB_TYPE_SKIPPED){ @@ -3024,7 +2997,7 @@ static int encode_thread(AVCodecContext *c, void *arg){ s->mb_intra= 0; s->mv[0][0][0] = 0; s->mv[0][0][1] = 0; - encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_SKIPPED, pb, pb2, tex_pb, + encode_mb_hq(s, &backup_s, &best_s, pb, pb2, tex_pb, &dmin, &next_block, s->mv[0][0][0], s->mv[0][0][1]); } if(mb_type&CANDIDATE_MB_TYPE_INTER4V){ @@ -3035,7 +3008,7 @@ static int encode_thread(AVCodecContext *c, void *arg){ s->mv[0][i][0] = s->current_picture.motion_val[0][s->block_index[i]][0]; s->mv[0][i][1] = s->current_picture.motion_val[0][s->block_index[i]][1]; } - encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_INTER4V, pb, pb2, tex_pb, + encode_mb_hq(s, &backup_s, &best_s, pb, pb2, tex_pb, &dmin, &next_block, 0, 0); } if(mb_type&CANDIDATE_MB_TYPE_FORWARD){ @@ -3044,7 +3017,7 @@ static int encode_thread(AVCodecContext *c, void *arg){ s->mb_intra= 0; s->mv[0][0][0] = s->b_forw_mv_table[xy][0]; s->mv[0][0][1] = s->b_forw_mv_table[xy][1]; - encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_FORWARD, pb, pb2, tex_pb, + encode_mb_hq(s, &backup_s, &best_s, pb, pb2, tex_pb, &dmin, &next_block, s->mv[0][0][0], s->mv[0][0][1]); } if(mb_type&CANDIDATE_MB_TYPE_BACKWARD){ @@ -3053,7 +3026,7 @@ static int encode_thread(AVCodecContext *c, void *arg){ s->mb_intra= 0; s->mv[1][0][0] = s->b_back_mv_table[xy][0]; s->mv[1][0][1] = s->b_back_mv_table[xy][1]; - encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_BACKWARD, pb, pb2, tex_pb, + encode_mb_hq(s, &backup_s, &best_s, pb, pb2, tex_pb, &dmin, &next_block, s->mv[1][0][0], s->mv[1][0][1]); } if(mb_type&CANDIDATE_MB_TYPE_BIDIR){ @@ -3064,7 +3037,7 @@ static int encode_thread(AVCodecContext *c, void *arg){ s->mv[0][0][1] = s->b_bidir_forw_mv_table[xy][1]; s->mv[1][0][0] = s->b_bidir_back_mv_table[xy][0]; s->mv[1][0][1] = s->b_bidir_back_mv_table[xy][1]; - encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_BIDIR, pb, pb2, tex_pb, + encode_mb_hq(s, &backup_s, &best_s, pb, pb2, tex_pb, &dmin, &next_block, 0, 0); } if(mb_type&CANDIDATE_MB_TYPE_FORWARD_I){ @@ -3076,7 +3049,7 @@ static int encode_thread(AVCodecContext *c, void *arg){ s->mv[0][i][0] = s->b_field_mv_table[0][i][j][xy][0]; s->mv[0][i][1] = s->b_field_mv_table[0][i][j][xy][1]; } - encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_FORWARD_I, pb, pb2, tex_pb, + encode_mb_hq(s, &backup_s, &best_s, pb, pb2, tex_pb, &dmin, &next_block, 0, 0); } if(mb_type&CANDIDATE_MB_TYPE_BACKWARD_I){ @@ -3088,7 +3061,7 @@ static int encode_thread(AVCodecContext *c, void *arg){ s->mv[1][i][0] = s->b_field_mv_table[1][i][j][xy][0]; s->mv[1][i][1] = s->b_field_mv_table[1][i][j][xy][1]; } - encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_BACKWARD_I, pb, pb2, tex_pb, + encode_mb_hq(s, &backup_s, &best_s, pb, pb2, tex_pb, &dmin, &next_block, 0, 0); } if(mb_type&CANDIDATE_MB_TYPE_BIDIR_I){ @@ -3102,7 +3075,7 @@ static int encode_thread(AVCodecContext *c, void *arg){ s->mv[dir][i][1] = s->b_field_mv_table[dir][i][j][xy][1]; } } - encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_BIDIR_I, pb, pb2, tex_pb, + encode_mb_hq(s, &backup_s, &best_s, pb, pb2, tex_pb, &dmin, &next_block, 0, 0); } if(mb_type&CANDIDATE_MB_TYPE_INTRA){ @@ -3111,7 +3084,7 @@ static int encode_thread(AVCodecContext *c, void *arg){ s->mb_intra= 1; s->mv[0][0][0] = 0; s->mv[0][0][1] = 0; - encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_INTRA, pb, pb2, tex_pb, + encode_mb_hq(s, &backup_s, &best_s, pb, pb2, tex_pb, &dmin, &next_block, 0, 0); if(s->h263_pred || s->h263_aic){ if(best_s.mb_intra) @@ -3155,7 +3128,7 @@ static int encode_thread(AVCodecContext *c, void *arg){ } } - encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_INTER /* wrong but unused */, pb, pb2, tex_pb, + encode_mb_hq(s, &backup_s, &best_s, pb, pb2, tex_pb, &dmin, &next_block, s->mv[mvdir][0][0], s->mv[mvdir][0][1]); if(best_s.qscale != qp){ if(storecoefs){ @@ -3176,7 +3149,7 @@ static int encode_thread(AVCodecContext *c, void *arg){ s->mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD | MV_DIRECT; s->mb_intra= 0; ff_mpeg4_set_direct_mv(s, mx, my); - encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_DIRECT, pb, pb2, tex_pb, + encode_mb_hq(s, &backup_s, &best_s, pb, pb2, tex_pb, &dmin, &next_block, mx, my); } if(CONFIG_MPEG4_ENCODER && mb_type&CANDIDATE_MB_TYPE_DIRECT0){ @@ -3184,7 +3157,7 @@ static int encode_thread(AVCodecContext *c, void *arg){ s->mv_dir = MV_DIR_FORWARD | MV_DIR_BACKWARD | MV_DIRECT; s->mb_intra= 0; ff_mpeg4_set_direct_mv(s, 0, 0); - encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_DIRECT, pb, pb2, tex_pb, + encode_mb_hq(s, &backup_s, &best_s, pb, pb2, tex_pb, &dmin, &next_block, 0, 0); } if (!best_s.mb_intra && s->mpv_flags & FF_MPV_FLAG_SKIP_RD) { @@ -3214,7 +3187,7 @@ static int encode_thread(AVCodecContext *c, void *arg){ s->mv[1][0][1] = best_s.mv[1][0][1];*/ backup_s.dquant= 0; s->skipdct=1; - encode_mb_hq(s, &backup_s, &best_s, CANDIDATE_MB_TYPE_INTER /* wrong but unused */, pb, pb2, tex_pb, + encode_mb_hq(s, &backup_s, &best_s, pb, pb2, tex_pb, &dmin, &next_block, mx, my); s->skipdct=0; } @@ -3222,7 +3195,7 @@ static int encode_thread(AVCodecContext *c, void *arg){ s->current_picture.qscale_table[xy] = best_s.qscale; - copy_context_after_encode(s, &best_s, -1); + copy_context_after_encode(s, &best_s); pb_bits_count= put_bits_count(&s->pb); flush_put_bits(&s->pb); @@ -3389,13 +3362,13 @@ static int encode_thread(AVCodecContext *c, void *arg){ if(s->mb_y*16 + 16 > s->height) h= s->height- s->mb_y*16; s->current_picture.encoding_error[0] += sse( - s, s->new_picture.f->data[0] + s->mb_x*16 + s->mb_y*s->linesize*16, + s, s->new_picture->data[0] + s->mb_x*16 + s->mb_y*s->linesize*16, s->dest[0], w, h, s->linesize); s->current_picture.encoding_error[1] += sse( - s, s->new_picture.f->data[1] + s->mb_x*8 + s->mb_y*s->uvlinesize*chr_h, + s, s->new_picture->data[1] + s->mb_x*8 + s->mb_y*s->uvlinesize*chr_h, s->dest[1], w>>1, h>>s->chroma_y_shift, s->uvlinesize); s->current_picture.encoding_error[2] += sse( - s, s->new_picture.f->data[2] + s->mb_x*8 + s->mb_y*s->uvlinesize*chr_h, + s, s->new_picture->data[2] + s->mb_x*8 + s->mb_y*s->uvlinesize*chr_h, s->dest[2], w>>1, h>>s->chroma_y_shift, s->uvlinesize); } if(s->loop_filter){ @@ -3432,12 +3405,8 @@ static void merge_context_after_encode(MpegEncContext *dst, MpegEncContext *src) MERGE(i_tex_bits); MERGE(p_tex_bits); MERGE(i_count); - MERGE(f_count); - MERGE(b_count); MERGE(skip_count); MERGE(misc_bits); - MERGE(er.error_count); - MERGE(padding_bug_score); MERGE(current_picture.encoding_error[0]); MERGE(current_picture.encoding_error[1]); MERGE(current_picture.encoding_error[2]); @@ -3628,9 +3597,7 @@ static int encode_picture(MpegEncContext *s, int picture_number) s->p_field_mv_table[i][j], s->f_code, CANDIDATE_MB_TYPE_INTER_I, !!s->intra_penalty); } } - } - - if(s->pict_type==AV_PICTURE_TYPE_B){ + } else if (s->pict_type == AV_PICTURE_TYPE_B) { int a, b; a = ff_get_best_fcode(s, s->b_forw_mv_table, CANDIDATE_MB_TYPE_FORWARD); @@ -3735,10 +3702,7 @@ static int encode_picture(MpegEncContext *s, int picture_number) switch(s->out_format) { #if CONFIG_MJPEG_ENCODER || CONFIG_AMV_ENCODER case FMT_MJPEG: - /* s->huffman == HUFFMAN_TABLE_OPTIMAL can only be true for MJPEG. */ - if (!CONFIG_MJPEG_ENCODER || s->huffman != HUFFMAN_TABLE_OPTIMAL) - ff_mjpeg_encode_picture_header(s->avctx, &s->pb, &s->intra_scantable, - s->pred, s->intra_matrix, s->chroma_intra_matrix); + ff_mjpeg_amv_encode_picture_header(s); break; #endif case FMT_SPEEDHQ: @@ -4585,117 +4549,3 @@ int ff_dct_quantize_c(MpegEncContext *s, return last_non_zero; } - -#define OFFSET(x) offsetof(MpegEncContext, x) -#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM -static const AVOption h263_options[] = { - { "obmc", "use overlapped block motion compensation.", OFFSET(obmc), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, - { "mb_info", "emit macroblock info for RFC 2190 packetization, the parameter value is the maximum payload size", OFFSET(mb_info), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, - FF_MPV_COMMON_OPTS -#if FF_API_MPEGVIDEO_OPTS - FF_MPV_DEPRECATED_MPEG_QUANT_OPT - FF_MPV_DEPRECATED_A53_CC_OPT - FF_MPV_DEPRECATED_MATRIX_OPT - FF_MPV_DEPRECATED_BFRAME_OPTS -#endif - { NULL }, -}; - -static const AVClass h263_class = { - .class_name = "H.263 encoder", - .item_name = av_default_item_name, - .option = h263_options, - .version = LIBAVUTIL_VERSION_INT, -}; - -const AVCodec ff_h263_encoder = { - .name = "h263", - .long_name = NULL_IF_CONFIG_SMALL("H.263 / H.263-1996"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_H263, - .priv_data_size = sizeof(MpegEncContext), - .init = ff_mpv_encode_init, - .encode2 = ff_mpv_encode_picture, - .close = ff_mpv_encode_end, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .pix_fmts= (const enum AVPixelFormat[]){AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE}, - .priv_class = &h263_class, -}; - -static const AVOption h263p_options[] = { - { "umv", "Use unlimited motion vectors.", OFFSET(umvplus), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, - { "aiv", "Use alternative inter VLC.", OFFSET(alt_inter_vlc), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, - { "obmc", "use overlapped block motion compensation.", OFFSET(obmc), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, - { "structured_slices", "Write slice start position at every GOB header instead of just GOB number.", OFFSET(h263_slice_structured), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE}, - FF_MPV_COMMON_OPTS -#if FF_API_MPEGVIDEO_OPTS - FF_MPV_DEPRECATED_MPEG_QUANT_OPT - FF_MPV_DEPRECATED_A53_CC_OPT - FF_MPV_DEPRECATED_MATRIX_OPT - FF_MPV_DEPRECATED_BFRAME_OPTS -#endif - { NULL }, -}; -static const AVClass h263p_class = { - .class_name = "H.263p encoder", - .item_name = av_default_item_name, - .option = h263p_options, - .version = LIBAVUTIL_VERSION_INT, -}; - -const AVCodec ff_h263p_encoder = { - .name = "h263p", - .long_name = NULL_IF_CONFIG_SMALL("H.263+ / H.263-1998 / H.263 version 2"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_H263P, - .priv_data_size = sizeof(MpegEncContext), - .init = ff_mpv_encode_init, - .encode2 = ff_mpv_encode_picture, - .close = ff_mpv_encode_end, - .capabilities = AV_CODEC_CAP_SLICE_THREADS, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, - .priv_class = &h263p_class, -}; - -const AVCodec ff_msmpeg4v2_encoder = { - .name = "msmpeg4v2", - .long_name = NULL_IF_CONFIG_SMALL("MPEG-4 part 2 Microsoft variant version 2"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MSMPEG4V2, - .priv_class = &ff_mpv_enc_class, - .priv_data_size = sizeof(MpegEncContext), - .init = ff_mpv_encode_init, - .encode2 = ff_mpv_encode_picture, - .close = ff_mpv_encode_end, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, -}; - -const AVCodec ff_msmpeg4v3_encoder = { - .name = "msmpeg4", - .long_name = NULL_IF_CONFIG_SMALL("MPEG-4 part 2 Microsoft variant version 3"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MSMPEG4V3, - .priv_class = &ff_mpv_enc_class, - .priv_data_size = sizeof(MpegEncContext), - .init = ff_mpv_encode_init, - .encode2 = ff_mpv_encode_picture, - .close = ff_mpv_encode_end, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, -}; - -const AVCodec ff_wmv1_encoder = { - .name = "wmv1", - .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 7"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_WMV1, - .priv_class = &ff_mpv_enc_class, - .priv_data_size = sizeof(MpegEncContext), - .init = ff_mpv_encode_init, - .encode2 = ff_mpv_encode_picture, - .close = ff_mpv_encode_end, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, -}; diff --git a/libavcodec/mpegvideo_motion.c b/libavcodec/mpegvideo_motion.c index 427bc9688..9a450b7c8 100644 --- a/libavcodec/mpegvideo_motion.c +++ b/libavcodec/mpegvideo_motion.c @@ -21,6 +21,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/avassert.h" #include "libavutil/internal.h" #include "libavutil/mem_internal.h" @@ -839,8 +841,6 @@ static av_always_inline void mpv_motion_internal(MpegEncContext *s, int i; int mb_y = s->mb_y; - prefetch_motion(s, ref_picture, dir); - if (!is_mpeg12 && s->obmc && s->pict_type != AV_PICTURE_TYPE_B) { apply_obmc(s, dest_y, dest_cb, dest_cr, ref_picture, pix_op); return; @@ -978,6 +978,8 @@ void ff_mpv_motion(MpegEncContext *s, op_pixels_func (*pix_op)[4], qpel_mc_func (*qpix_op)[16]) { + prefetch_motion(s, ref_picture, dir); + #if !CONFIG_SMALL if (s->out_format == FMT_MPEG1) mpv_motion_internal(s, dest_y, dest_cb, dest_cr, dir, diff --git a/libavcodec/mpegvideo_parser.c b/libavcodec/mpegvideo_parser.c index 39b9f2e43..97da5bfe1 100644 --- a/libavcodec/mpegvideo_parser.c +++ b/libavcodec/mpegvideo_parser.c @@ -20,9 +20,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "internal.h" #include "parser.h" #include "mpeg12.h" -#include "internal.h" +#include "mpeg12data.h" +#include "startcode.h" struct MpvParseContext { ParseContext pc; diff --git a/libavcodec/mpegvideodec.h b/libavcodec/mpegvideodec.h new file mode 100644 index 000000000..fabc1b220 --- /dev/null +++ b/libavcodec/mpegvideodec.h @@ -0,0 +1,82 @@ +/* + * MPEGVideo decoders header + * Copyright (c) 2000, 2001, 2002 Fabrice Bellard + * Copyright (c) 2002-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 + * mpegvideo decoder header. + */ + +#ifndef AVCODEC_MPEGVIDEODEC_H +#define AVCODEC_MPEGVIDEODEC_H + +#include "libavutil/frame.h" +#include "libavutil/log.h" + +#include "avcodec.h" +#include "get_bits.h" +#include "mpegpicture.h" +#include "mpegvideo.h" +#include "mpegvideodata.h" + +#define FF_MPV_QSCALE_TYPE_MPEG1 0 +#define FF_MPV_QSCALE_TYPE_MPEG2 1 + +/** + * Initialize the given MpegEncContext for decoding. + * the changed fields will not depend upon + * the prior state of the MpegEncContext. + */ +void ff_mpv_decode_init(MpegEncContext *s, AVCodecContext *avctx); + +int ff_mpv_common_frame_size_change(MpegEncContext *s); + +int ff_mpv_frame_start(MpegEncContext *s, AVCodecContext *avctx); +void ff_mpv_report_decode_progress(MpegEncContext *s); +void ff_mpv_frame_end(MpegEncContext *s); + +int ff_mpv_export_qp_table(MpegEncContext *s, AVFrame *f, Picture *p, int qp_type); +int ff_mpeg_update_thread_context(AVCodecContext *dst, const AVCodecContext *src); +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); + +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; +} + +static inline int check_marker(void *logctx, GetBitContext *s, const char *msg) +{ + int bit = get_bits1(s); + if (!bit) + av_log(logctx, AV_LOG_INFO, "Marker bit missing at %d of %d %s\n", + get_bits_count(s) - 1, s->size_in_bits, msg); + + return bit; +} + +#endif /* AVCODEC_MPEGVIDEODEC_H */ diff --git a/libavcodec/mpegvideodsp.c b/libavcodec/mpegvideodsp.c index a58e45ad4..a8cf7fbe3 100644 --- a/libavcodec/mpegvideodsp.c +++ b/libavcodec/mpegvideodsp.c @@ -112,8 +112,9 @@ av_cold void ff_mpegvideodsp_init(MpegVideoDSPContext *c) c->gmc1 = gmc1_c; c->gmc = ff_gmc_c; - if (ARCH_PPC) - ff_mpegvideodsp_init_ppc(c); - if (ARCH_X86) - ff_mpegvideodsp_init_x86(c); +#if ARCH_PPC + ff_mpegvideodsp_init_ppc(c); +#elif ARCH_X86 + ff_mpegvideodsp_init_x86(c); +#endif } diff --git a/libavcodec/mpegvideoenc.h b/libavcodec/mpegvideoenc.h new file mode 100644 index 000000000..0e93124cc --- /dev/null +++ b/libavcodec/mpegvideoenc.h @@ -0,0 +1,149 @@ +/* + * Generic DCT based hybrid video encoder + * Copyright (c) 2000, 2001, 2002 Fabrice Bellard + * Copyright (c) 2002-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 + * mpegvideo header. + */ + +#ifndef AVCODEC_MPEGVIDEOENC_H +#define AVCODEC_MPEGVIDEOENC_H + +#include + +#include "libavutil/opt.h" +#include "mpegvideo.h" + +#define UNI_AC_ENC_INDEX(run,level) ((run)*128 + (level)) + +/* mpegvideo_enc common options */ +#define FF_MPV_FLAG_SKIP_RD 0x0001 +#define FF_MPV_FLAG_STRICT_GOP 0x0002 +#define FF_MPV_FLAG_QP_RD 0x0004 +#define FF_MPV_FLAG_CBP_RD 0x0008 +#define FF_MPV_FLAG_NAQ 0x0010 +#define FF_MPV_FLAG_MV0 0x0020 + +#define FF_MPV_OPT_CMP_FUNC \ +{ "sad", "Sum of absolute differences, fast", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_SAD }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" }, \ +{ "sse", "Sum of squared errors", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_SSE }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" }, \ +{ "satd", "Sum of absolute Hadamard transformed differences", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_SATD }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" }, \ +{ "dct", "Sum of absolute DCT transformed differences", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_DCT }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" }, \ +{ "psnr", "Sum of squared quantization errors, low quality", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_PSNR }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" }, \ +{ "bit", "Number of bits needed for the block", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_BIT }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" }, \ +{ "rd", "Rate distortion optimal, slow", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_RD }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" }, \ +{ "zero", "Zero", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_ZERO }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" }, \ +{ "vsad", "Sum of absolute vertical differences", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_VSAD }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" }, \ +{ "vsse", "Sum of squared vertical differences", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_VSSE }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" }, \ +{ "nsse", "Noise preserving sum of squared differences", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_NSSE }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" }, \ +{ "dct264", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_DCT264 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" }, \ +{ "dctmax", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_DCTMAX }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" }, \ +{ "chroma", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_CHROMA }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" }, \ +{ "msad", "Sum of absolute differences, median predicted", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_MEDIAN_SAD }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" } + +#define FF_MPV_OFFSET(x) offsetof(MpegEncContext, x) +#define FF_MPV_OPT_FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM) +#define FF_MPV_COMMON_OPTS \ +FF_MPV_OPT_CMP_FUNC, \ +{ "mpv_flags", "Flags common for all mpegvideo-based encoders.", FF_MPV_OFFSET(mpv_flags), AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "mpv_flags" },\ +{ "skip_rd", "RD optimal MB level residual skipping", 0, AV_OPT_TYPE_CONST, { .i64 = FF_MPV_FLAG_SKIP_RD }, 0, 0, FF_MPV_OPT_FLAGS, "mpv_flags" },\ +{ "strict_gop", "Strictly enforce gop size", 0, AV_OPT_TYPE_CONST, { .i64 = FF_MPV_FLAG_STRICT_GOP }, 0, 0, FF_MPV_OPT_FLAGS, "mpv_flags" },\ +{ "qp_rd", "Use rate distortion optimization for qp selection", 0, AV_OPT_TYPE_CONST, { .i64 = FF_MPV_FLAG_QP_RD }, 0, 0, FF_MPV_OPT_FLAGS, "mpv_flags" },\ +{ "cbp_rd", "use rate distortion optimization for CBP", 0, AV_OPT_TYPE_CONST, { .i64 = FF_MPV_FLAG_CBP_RD }, 0, 0, FF_MPV_OPT_FLAGS, "mpv_flags" },\ +{ "naq", "normalize adaptive quantization", 0, AV_OPT_TYPE_CONST, { .i64 = FF_MPV_FLAG_NAQ }, 0, 0, FF_MPV_OPT_FLAGS, "mpv_flags" },\ +{ "mv0", "always try a mb with mv=<0,0>", 0, AV_OPT_TYPE_CONST, { .i64 = FF_MPV_FLAG_MV0 }, 0, 0, FF_MPV_OPT_FLAGS, "mpv_flags" },\ +{ "luma_elim_threshold", "single coefficient elimination threshold for luminance (negative values also consider dc coefficient)",\ + FF_MPV_OFFSET(luma_elim_threshold), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS },\ +{ "chroma_elim_threshold", "single coefficient elimination threshold for chrominance (negative values also consider dc coefficient)",\ + FF_MPV_OFFSET(chroma_elim_threshold), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS },\ +{ "quantizer_noise_shaping", NULL, FF_MPV_OFFSET(quantizer_noise_shaping), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FF_MPV_OPT_FLAGS },\ +{ "error_rate", "Simulate errors in the bitstream to test error concealment.", \ + FF_MPV_OFFSET(error_rate), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FF_MPV_OPT_FLAGS },\ +{"qsquish", "how to keep quantizer between qmin and qmax (0 = clip, 1 = use differentiable function)", \ + FF_MPV_OFFSET(rc_qsquish), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, 0, 99, FF_MPV_OPT_FLAGS}, \ +{"rc_qmod_amp", "experimental quantizer modulation", FF_MPV_OFFSET(rc_qmod_amp), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, -FLT_MAX, FLT_MAX, FF_MPV_OPT_FLAGS}, \ +{"rc_qmod_freq", "experimental quantizer modulation", FF_MPV_OFFSET(rc_qmod_freq), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS}, \ +{"rc_eq", "Set rate control equation. When computing the expression, besides the standard functions " \ + "defined in the section 'Expression Evaluation', the following functions are available: " \ + "bits2qp(bits), qp2bits(qp). Also the following constants are available: iTex pTex tex mv " \ + "fCode iCount mcVar var isI isP isB avgQP qComp avgIITex avgPITex avgPPTex avgBPTex avgTex.", \ + FF_MPV_OFFSET(rc_eq), AV_OPT_TYPE_STRING, .flags = FF_MPV_OPT_FLAGS }, \ +{"rc_init_cplx", "initial complexity for 1-pass encoding", FF_MPV_OFFSET(rc_initial_cplx), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, -FLT_MAX, FLT_MAX, FF_MPV_OPT_FLAGS}, \ +{"rc_buf_aggressivity", "currently useless", FF_MPV_OFFSET(rc_buffer_aggressivity), AV_OPT_TYPE_FLOAT, {.dbl = 1.0 }, -FLT_MAX, FLT_MAX, FF_MPV_OPT_FLAGS}, \ +{"border_mask", "increase the quantizer for macroblocks close to borders", FF_MPV_OFFSET(border_masking), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, -FLT_MAX, FLT_MAX, FF_MPV_OPT_FLAGS}, \ +{"lmin", "minimum Lagrange factor (VBR)", FF_MPV_OFFSET(lmin), AV_OPT_TYPE_INT, {.i64 = 2*FF_QP2LAMBDA }, 0, INT_MAX, FF_MPV_OPT_FLAGS }, \ +{"lmax", "maximum Lagrange factor (VBR)", FF_MPV_OFFSET(lmax), AV_OPT_TYPE_INT, {.i64 = 31*FF_QP2LAMBDA }, 0, INT_MAX, FF_MPV_OPT_FLAGS }, \ +{"skip_threshold", "Frame skip threshold", FF_MPV_OFFSET(frame_skip_threshold), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ +{"skip_factor", "Frame skip factor", FF_MPV_OFFSET(frame_skip_factor), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ +{"skip_exp", "Frame skip exponent", FF_MPV_OFFSET(frame_skip_exp), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ +{"skip_cmp", "Frame skip compare function", FF_MPV_OFFSET(frame_skip_cmp), AV_OPT_TYPE_INT, {.i64 = FF_CMP_DCTMAX }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" }, \ +{"sc_threshold", "Scene change threshold", FF_MPV_OFFSET(scenechange_threshold), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ +{"noise_reduction", "Noise reduction", FF_MPV_OFFSET(noise_reduction), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ +{"ps", "RTP payload size in bytes", FF_MPV_OFFSET(rtp_payload_size), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ + +#define FF_MPV_COMMON_BFRAME_OPTS \ +{"b_strategy", "Strategy to choose between I/P/B-frames", FF_MPV_OFFSET(b_frame_strategy), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 2, FF_MPV_OPT_FLAGS }, \ +{"b_sensitivity", "Adjust sensitivity of b_frame_strategy 1", FF_MPV_OFFSET(b_sensitivity), AV_OPT_TYPE_INT, {.i64 = 40 }, 1, INT_MAX, FF_MPV_OPT_FLAGS }, \ +{"brd_scale", "Downscale frames for dynamic B-frame decision", FF_MPV_OFFSET(brd_scale), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 3, FF_MPV_OPT_FLAGS }, + +#define FF_MPV_COMMON_MOTION_EST_OPTS \ +{"motion_est", "motion estimation algorithm", FF_MPV_OFFSET(motion_est), AV_OPT_TYPE_INT, {.i64 = FF_ME_EPZS }, FF_ME_ZERO, FF_ME_XONE, FF_MPV_OPT_FLAGS, "motion_est" }, \ +{ "zero", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_ME_ZERO }, 0, 0, FF_MPV_OPT_FLAGS, "motion_est" }, \ +{ "epzs", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_ME_EPZS }, 0, 0, FF_MPV_OPT_FLAGS, "motion_est" }, \ +{ "xone", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = FF_ME_XONE }, 0, 0, FF_MPV_OPT_FLAGS, "motion_est" }, \ +{"mepc", "Motion estimation bitrate penalty compensation (1.0 = 256)", FF_MPV_OFFSET(me_penalty_compensation), AV_OPT_TYPE_INT, {.i64 = 256 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ +{"mepre", "pre motion estimation", FF_MPV_OFFSET(me_pre), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS }, \ +{"intra_penalty", "Penalty for intra blocks in block decision", FF_MPV_OFFSET(intra_penalty), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX/2, FF_MPV_OPT_FLAGS }, \ + +extern const AVClass ff_mpv_enc_class; + +int ff_mpv_encode_init(AVCodecContext *avctx); +void ff_mpv_encode_init_x86(MpegEncContext *s); + +int ff_mpv_encode_end(AVCodecContext *avctx); +int ff_mpv_encode_picture(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet); +int ff_mpv_reallocate_putbitbuffer(MpegEncContext *s, size_t threshold, size_t size_increase); + +void ff_write_quant_matrix(PutBitContext *pb, uint16_t *matrix); + +int ff_dct_encode_init(MpegEncContext *s); +void ff_dct_encode_init_x86(MpegEncContext *s); + +int ff_dct_quantize_c(MpegEncContext *s, int16_t *block, int n, int qscale, int *overflow); +void ff_convert_matrix(MpegEncContext *s, int (*qmat)[64], uint16_t (*qmat16)[2][64], + const uint16_t *quant_matrix, int bias, int qmin, int qmax, int intra); + +void ff_block_permute(int16_t *block, uint8_t *permutation, + const uint8_t *scantable, int last); + +static inline int get_bits_diff(MpegEncContext *s) +{ + const int bits = put_bits_count(&s->pb); + const int last = s->last_bits; + + s->last_bits = bits; + + return bits - last; +} + +#endif diff --git a/libavcodec/mpegvideoencdsp.c b/libavcodec/mpegvideoencdsp.c index a34ab3553..adf19e69f 100644 --- a/libavcodec/mpegvideoencdsp.c +++ b/libavcodec/mpegvideoencdsp.c @@ -245,12 +245,13 @@ av_cold void ff_mpegvideoencdsp_init(MpegvideoEncDSPContext *c, c->draw_edges = draw_edges_8_c; - if (ARCH_ARM) - ff_mpegvideoencdsp_init_arm(c, avctx); - if (ARCH_PPC) - ff_mpegvideoencdsp_init_ppc(c, avctx); - if (ARCH_X86) - ff_mpegvideoencdsp_init_x86(c, avctx); - if (ARCH_MIPS) - ff_mpegvideoencdsp_init_mips(c, avctx); +#if ARCH_ARM + ff_mpegvideoencdsp_init_arm(c, avctx); +#elif ARCH_PPC + ff_mpegvideoencdsp_init_ppc(c, avctx); +#elif ARCH_X86 + ff_mpegvideoencdsp_init_x86(c, avctx); +#elif ARCH_MIPS + ff_mpegvideoencdsp_init_mips(c, avctx); +#endif } diff --git a/libavcodec/mpl2dec.c b/libavcodec/mpl2dec.c index 61e47050e..56f008b65 100644 --- a/libavcodec/mpl2dec.c +++ b/libavcodec/mpl2dec.c @@ -27,7 +27,7 @@ #include "avcodec.h" #include "ass.h" -#include "internal.h" +#include "codec_internal.h" #include "libavutil/bprint.h" static int mpl2_event_to_ass(AVBPrint *buf, const char *p) @@ -63,12 +63,11 @@ static int mpl2_event_to_ass(AVBPrint *buf, const char *p) return 0; } -static int mpl2_decode_frame(AVCodecContext *avctx, void *data, - int *got_sub_ptr, AVPacket *avpkt) +static int mpl2_decode_frame(AVCodecContext *avctx, AVSubtitle *sub, + int *got_sub_ptr, const AVPacket *avpkt) { int ret = 0; AVBPrint buf; - AVSubtitle *sub = data; const char *ptr = avpkt->data; FFASSDecoderContext *s = avctx->priv_data; @@ -82,12 +81,12 @@ static int mpl2_decode_frame(AVCodecContext *avctx, void *data, return avpkt->size; } -const AVCodec ff_mpl2_decoder = { - .name = "mpl2", - .long_name = NULL_IF_CONFIG_SMALL("MPL2 subtitle"), - .type = AVMEDIA_TYPE_SUBTITLE, - .id = AV_CODEC_ID_MPL2, - .decode = mpl2_decode_frame, +const FFCodec ff_mpl2_decoder = { + .p.name = "mpl2", + .p.long_name = NULL_IF_CONFIG_SMALL("MPL2 subtitle"), + .p.type = AVMEDIA_TYPE_SUBTITLE, + .p.id = AV_CODEC_ID_MPL2, + FF_CODEC_DECODE_SUB_CB(mpl2_decode_frame), .init = ff_ass_subtitle_header_default, .flush = ff_ass_decoder_flush, .priv_data_size = sizeof(FFASSDecoderContext), diff --git a/libavcodec/mqcenc.c b/libavcodec/mqcenc.c index 6d0368f82..a8c35c8db 100644 --- a/libavcodec/mqcenc.c +++ b/libavcodec/mqcenc.c @@ -25,6 +25,8 @@ * @author Kamil Nowosad */ +#include + #include "libavutil/avassert.h" #include "mqc.h" diff --git a/libavcodec/mscc.c b/libavcodec/mscc.c index d9a6de094..3666b881a 100644 --- a/libavcodec/mscc.c +++ b/libavcodec/mscc.c @@ -26,7 +26,9 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" +#include "zlib_wrapper.h" #include @@ -36,7 +38,7 @@ typedef struct MSCCContext { uint8_t *decomp_buf; unsigned int uncomp_size; uint8_t *uncomp_buf; - z_stream zstream; + FFZStream zstream; uint32_t pal[256]; } MSCCContext; @@ -127,13 +129,12 @@ static int rle_uncompress(AVCodecContext *avctx, GetByteContext *gb, PutByteCont return AVERROR_INVALIDDATA; } -static int decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { MSCCContext *s = avctx->priv_data; - AVFrame *frame = data; - uint8_t *buf = avpkt->data; + z_stream *const zstream = &s->zstream.zstream; + const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; GetByteContext gb; PutByteContext pb; @@ -145,12 +146,6 @@ static int decode_frame(AVCodecContext *avctx, if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; - if (avctx->codec_id == AV_CODEC_ID_MSCC) { - avpkt->data[2] ^= avpkt->data[0]; - buf += 2; - buf_size -= 2; - } - if (avctx->pix_fmt == AV_PIX_FMT_PAL8) { size_t size; const uint8_t *pal = av_packet_get_side_data(avpkt, AV_PKT_DATA_PALETTE, &size); @@ -166,22 +161,35 @@ static int decode_frame(AVCodecContext *avctx, memcpy(frame->data[1], s->pal, AVPALETTE_SIZE); } - ret = inflateReset(&s->zstream); + ret = inflateReset(zstream); if (ret != Z_OK) { av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", ret); return AVERROR_UNKNOWN; } - s->zstream.next_in = buf; - s->zstream.avail_in = buf_size; - s->zstream.next_out = s->decomp_buf; - s->zstream.avail_out = s->decomp_size; - ret = inflate(&s->zstream, Z_FINISH); + zstream->next_out = s->decomp_buf; + zstream->avail_out = s->decomp_size; + if (avctx->codec_id == AV_CODEC_ID_MSCC) { + const uint8_t start = avpkt->data[2] ^ avpkt->data[0]; + + zstream->next_in = &start; + zstream->avail_in = 1; + ret = inflate(zstream, Z_NO_FLUSH); + if (ret != Z_OK || zstream->avail_in != 0) + goto inflate_error; + + buf += 3; + buf_size -= 3; + } + zstream->next_in = buf; + zstream->avail_in = buf_size; + ret = inflate(zstream, Z_FINISH); if (ret != Z_STREAM_END) { +inflate_error: av_log(avctx, AV_LOG_ERROR, "Inflate error: %d\n", ret); return AVERROR_UNKNOWN; } - bytestream2_init(&gb, s->decomp_buf, s->zstream.total_out); + bytestream2_init(&gb, s->decomp_buf, zstream->total_out); bytestream2_init_writer(&pb, s->uncomp_buf, s->uncomp_size); ret = rle_uncompress(avctx, &gb, &pb); @@ -204,7 +212,7 @@ static int decode_frame(AVCodecContext *avctx, static av_cold int decode_init(AVCodecContext *avctx) { MSCCContext *s = avctx->priv_data; - int stride, zret; + int stride; switch (avctx->bits_per_coded_sample) { case 8: avctx->pix_fmt = AV_PIX_FMT_PAL8; break; @@ -227,16 +235,7 @@ static av_cold int decode_init(AVCodecContext *avctx) if (!(s->uncomp_buf = av_malloc(s->uncomp_size))) return AVERROR(ENOMEM); - s->zstream.zalloc = Z_NULL; - s->zstream.zfree = Z_NULL; - s->zstream.opaque = Z_NULL; - zret = inflateInit(&s->zstream); - if (zret != Z_OK) { - av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret); - return AVERROR_UNKNOWN; - } - - return 0; + return ff_inflate_init(&s->zstream, avctx); } static av_cold int decode_close(AVCodecContext *avctx) @@ -247,33 +246,33 @@ static av_cold int decode_close(AVCodecContext *avctx) s->decomp_size = 0; av_freep(&s->uncomp_buf); s->uncomp_size = 0; - inflateEnd(&s->zstream); + ff_inflate_end(&s->zstream); return 0; } -const AVCodec ff_mscc_decoder = { - .name = "mscc", - .long_name = NULL_IF_CONFIG_SMALL("Mandsoft Screen Capture Codec"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MSCC, +const FFCodec ff_mscc_decoder = { + .p.name = "mscc", + .p.long_name = NULL_IF_CONFIG_SMALL("Mandsoft Screen Capture Codec"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MSCC, .priv_data_size = sizeof(MSCCContext), .init = decode_init, .close = decode_close, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; -const AVCodec ff_srgc_decoder = { - .name = "srgc", - .long_name = NULL_IF_CONFIG_SMALL("Screen Recorder Gold Codec"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_SRGC, +const FFCodec ff_srgc_decoder = { + .p.name = "srgc", + .p.long_name = NULL_IF_CONFIG_SMALL("Screen Recorder Gold Codec"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_SRGC, .priv_data_size = sizeof(MSCCContext), .init = decode_init, .close = decode_close, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/msmpeg4.c b/libavcodec/msmpeg4.c index 16b6f1895..455436e9c 100644 --- a/libavcodec/msmpeg4.c +++ b/libavcodec/msmpeg4.c @@ -27,6 +27,8 @@ * MSMPEG4 backend for encoder and decoder */ +#include "config_components.h" + #include "libavutil/thread.h" #include "avcodec.h" @@ -34,8 +36,7 @@ #include "mpegvideo.h" #include "msmpeg4.h" #include "libavutil/x86/asm.h" -#include "h263.h" -#include "mpeg4video.h" +#include "mpeg4videodata.h" #include "msmpeg4data.h" #include "mpegvideodata.h" #include "vc1data.h" diff --git a/libavcodec/msmpeg4.h b/libavcodec/msmpeg4.h index 483c965b9..b918028fe 100644 --- a/libavcodec/msmpeg4.h +++ b/libavcodec/msmpeg4.h @@ -24,57 +24,18 @@ #include -#include "config.h" -#include "avcodec.h" #include "mpegvideo.h" -#include "msmpeg4data.h" -#include "put_bits.h" - -#define INTER_INTRA_VLC_BITS 3 -#define MB_NON_INTRA_VLC_BITS 9 -#define MB_INTRA_VLC_BITS 9 #define II_BITRATE 128*1024 #define MBAC_BITRATE 50*1024 #define DC_MAX 119 -extern VLC ff_mb_non_intra_vlc[4]; -extern VLC ff_inter_intra_vlc; - -void ff_msmpeg4_code012(PutBitContext *pb, int n); void ff_msmpeg4_common_init(MpegEncContext *s); -void ff_msmpeg4_encode_block(MpegEncContext * s, int16_t * block, int n); -void ff_msmpeg4_handle_slices(MpegEncContext *s); -void ff_msmpeg4_encode_motion(MpegEncContext * s, int mx, int my); int ff_msmpeg4_coded_block_pred(MpegEncContext * s, int n, uint8_t **coded_block_ptr); -void ff_msmpeg4_encode_init(MpegEncContext *s); -void ff_msmpeg4_encode_picture_header(MpegEncContext *s, int picture_number); -void ff_msmpeg4_encode_ext_header(MpegEncContext *s); -void ff_msmpeg4_encode_mb(MpegEncContext *s, int16_t block[6][64], - int motion_x, int motion_y); - -int ff_msmpeg4_decode_init(AVCodecContext *avctx); -int ff_msmpeg4_decode_picture_header(MpegEncContext *s); -int ff_msmpeg4_decode_ext_header(MpegEncContext *s, int buf_size); -void ff_msmpeg4_decode_motion(MpegEncContext * s, int *mx_ptr, int *my_ptr); -int ff_msmpeg4_decode_block(MpegEncContext * s, int16_t * block, - int n, int coded, const uint8_t *scan_table); int ff_msmpeg4_pred_dc(MpegEncContext *s, int n, int16_t **dc_val_ptr, int *dir_ptr); - -#define CONFIG_MSMPEG4_DECODER (CONFIG_MSMPEG4V1_DECODER || \ - CONFIG_MSMPEG4V2_DECODER || \ - CONFIG_MSMPEG4V3_DECODER || \ - CONFIG_WMV1_DECODER || \ - CONFIG_WMV2_DECODER || \ - CONFIG_VC1_DECODER) -#define CONFIG_MSMPEG4_ENCODER (CONFIG_MSMPEG4V2_ENCODER || \ - CONFIG_MSMPEG4V3_ENCODER || \ - CONFIG_WMV1_ENCODER || \ - CONFIG_WMV2_ENCODER) - #endif /* AVCODEC_MSMPEG4_H */ diff --git a/libavcodec/msmpeg4data.c b/libavcodec/msmpeg4data.c index 890aeb567..63f30ac54 100644 --- a/libavcodec/msmpeg4data.c +++ b/libavcodec/msmpeg4data.c @@ -27,8 +27,8 @@ * MSMPEG4 data tables. */ -#include "h263.h" -#include "mpeg4video.h" +#include "h263data.h" +#include "mpeg4videodata.h" #include "msmpeg4data.h" uint32_t ff_v2_dc_lum_table[512][2]; diff --git a/libavcodec/msmpeg4data.h b/libavcodec/msmpeg4data.h index 87b4057d9..ec7957c12 100644 --- a/libavcodec/msmpeg4data.h +++ b/libavcodec/msmpeg4data.h @@ -30,7 +30,7 @@ #ifndef AVCODEC_MSMPEG4DATA_H #define AVCODEC_MSMPEG4DATA_H -#include "libavutil/common.h" +#include #include "rl.h" #include "vlc.h" diff --git a/libavcodec/msmpeg4dec.c b/libavcodec/msmpeg4dec.c index f30250958..abebeffc7 100644 --- a/libavcodec/msmpeg4dec.c +++ b/libavcodec/msmpeg4dec.c @@ -22,17 +22,23 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + +#include "libavutil/thread.h" + #include "avcodec.h" -#include "internal.h" +#include "codec_internal.h" #include "mpegutils.h" #include "mpegvideo.h" #include "msmpeg4.h" +#include "msmpeg4dec.h" #include "libavutil/imgutils.h" #include "h263.h" -#include "mpeg4video.h" +#include "h263data.h" +#include "h263dec.h" +#include "mpeg4videodec.h" #include "msmpeg4data.h" -#include "vc1data.h" -#include "wmv2.h" +#include "wmv2dec.h" #define DC_VLC_BITS 9 #define V2_INTRA_CBPC_VLC_BITS 3 @@ -291,12 +297,81 @@ static int msmpeg4v34_decode_mb(MpegEncContext *s, int16_t block[6][64]) } /* init all vlc decoding tables */ +static av_cold void msmpeg4_decode_init_static(void) +{ + MVTable *mv; + + INIT_FIRST_VLC_RL(ff_rl_table[0], 642); + INIT_FIRST_VLC_RL(ff_rl_table[1], 1104); + INIT_FIRST_VLC_RL(ff_rl_table[2], 554); + INIT_VLC_RL(ff_rl_table[3], 940); + INIT_VLC_RL(ff_rl_table[4], 962); + /* ff_rl_table[5] coincides with ff_h263_rl_inter which has just been + * initialized in ff_h263_decode_init() earlier. So just copy the VLCs. */ + av_assert1(ff_h263_rl_inter.rl_vlc[0]); + memcpy(ff_rl_table[5].rl_vlc, ff_h263_rl_inter.rl_vlc, sizeof(ff_rl_table[5].rl_vlc)); + + mv = &ff_mv_tables[0]; + INIT_VLC_STATIC(&mv->vlc, MV_VLC_BITS, MSMPEG4_MV_TABLES_NB_ELEMS + 1, + mv->table_mv_bits, 1, 1, + mv->table_mv_code, 2, 2, 3714); + mv = &ff_mv_tables[1]; + INIT_VLC_STATIC(&mv->vlc, MV_VLC_BITS, MSMPEG4_MV_TABLES_NB_ELEMS + 1, + mv->table_mv_bits, 1, 1, + mv->table_mv_code, 2, 2, 2694); + + INIT_VLC_STATIC(&ff_msmp4_dc_luma_vlc[0], DC_VLC_BITS, 120, + &ff_table0_dc_lum[0][1], 8, 4, + &ff_table0_dc_lum[0][0], 8, 4, 1158); + INIT_VLC_STATIC(&ff_msmp4_dc_chroma_vlc[0], DC_VLC_BITS, 120, + &ff_table0_dc_chroma[0][1], 8, 4, + &ff_table0_dc_chroma[0][0], 8, 4, 1118); + INIT_VLC_STATIC(&ff_msmp4_dc_luma_vlc[1], DC_VLC_BITS, 120, + &ff_table1_dc_lum[0][1], 8, 4, + &ff_table1_dc_lum[0][0], 8, 4, 1476); + INIT_VLC_STATIC(&ff_msmp4_dc_chroma_vlc[1], DC_VLC_BITS, 120, + &ff_table1_dc_chroma[0][1], 8, 4, + &ff_table1_dc_chroma[0][0], 8, 4, 1216); + + INIT_VLC_STATIC(&v2_dc_lum_vlc, DC_VLC_BITS, 512, + &ff_v2_dc_lum_table[0][1], 8, 4, + &ff_v2_dc_lum_table[0][0], 8, 4, 1472); + INIT_VLC_STATIC(&v2_dc_chroma_vlc, DC_VLC_BITS, 512, + &ff_v2_dc_chroma_table[0][1], 8, 4, + &ff_v2_dc_chroma_table[0][0], 8, 4, 1506); + + INIT_VLC_STATIC(&v2_intra_cbpc_vlc, V2_INTRA_CBPC_VLC_BITS, 4, + &ff_v2_intra_cbpc[0][1], 2, 1, + &ff_v2_intra_cbpc[0][0], 2, 1, 8); + INIT_VLC_STATIC(&v2_mb_type_vlc, V2_MB_TYPE_VLC_BITS, 8, + &ff_v2_mb_type[0][1], 2, 1, + &ff_v2_mb_type[0][0], 2, 1, 128); + + for (unsigned i = 0, offset = 0; i < 4; i++) { + static VLCElem vlc_buf[1636 + 2648 + 1532 + 2488]; + ff_mb_non_intra_vlc[i].table = &vlc_buf[offset]; + ff_mb_non_intra_vlc[i].table_allocated = FF_ARRAY_ELEMS(vlc_buf) - offset; + init_vlc(&ff_mb_non_intra_vlc[i], MB_NON_INTRA_VLC_BITS, 128, + &ff_wmv2_inter_table[i][0][1], 8, 4, + &ff_wmv2_inter_table[i][0][0], 8, 4, + INIT_VLC_STATIC_OVERLONG); + offset += ff_mb_non_intra_vlc[i].table_size; + } + + INIT_VLC_STATIC(&ff_msmp4_mb_i_vlc, MB_INTRA_VLC_BITS, 64, + &ff_msmp4_mb_i_table[0][1], 4, 2, + &ff_msmp4_mb_i_table[0][0], 4, 2, 536); + + INIT_VLC_STATIC(&ff_inter_intra_vlc, INTER_INTRA_VLC_BITS, 4, + &ff_table_inter_intra[0][1], 2, 1, + &ff_table_inter_intra[0][0], 2, 1, 8); +} + av_cold int ff_msmpeg4_decode_init(AVCodecContext *avctx) { + static AVOnce init_static_once = AV_ONCE_INIT; MpegEncContext *s = avctx->priv_data; - static volatile int done = 0; int ret; - MVTable *mv; if ((ret = av_image_check_size(avctx->width, avctx->height, 0, avctx)) < 0) return ret; @@ -306,74 +381,6 @@ av_cold int ff_msmpeg4_decode_init(AVCodecContext *avctx) ff_msmpeg4_common_init(s); - if (!done) { - INIT_FIRST_VLC_RL(ff_rl_table[0], 642); - INIT_FIRST_VLC_RL(ff_rl_table[1], 1104); - INIT_FIRST_VLC_RL(ff_rl_table[2], 554); - INIT_VLC_RL(ff_rl_table[3], 940); - INIT_VLC_RL(ff_rl_table[4], 962); - /* ff_rl_table[5] coincides with ff_h263_rl_inter which has just been - * initialized in ff_h263_decode_init() above. So just copy the VLCs. */ - av_assert1(ff_h263_rl_inter.rl_vlc[0]); - memcpy(ff_rl_table[5].rl_vlc, ff_h263_rl_inter.rl_vlc, sizeof(ff_rl_table[5].rl_vlc)); - - mv = &ff_mv_tables[0]; - INIT_VLC_STATIC(&mv->vlc, MV_VLC_BITS, MSMPEG4_MV_TABLES_NB_ELEMS + 1, - mv->table_mv_bits, 1, 1, - mv->table_mv_code, 2, 2, 3714); - mv = &ff_mv_tables[1]; - INIT_VLC_STATIC(&mv->vlc, MV_VLC_BITS, MSMPEG4_MV_TABLES_NB_ELEMS + 1, - mv->table_mv_bits, 1, 1, - mv->table_mv_code, 2, 2, 2694); - - INIT_VLC_STATIC(&ff_msmp4_dc_luma_vlc[0], DC_VLC_BITS, 120, - &ff_table0_dc_lum[0][1], 8, 4, - &ff_table0_dc_lum[0][0], 8, 4, 1158); - INIT_VLC_STATIC(&ff_msmp4_dc_chroma_vlc[0], DC_VLC_BITS, 120, - &ff_table0_dc_chroma[0][1], 8, 4, - &ff_table0_dc_chroma[0][0], 8, 4, 1118); - INIT_VLC_STATIC(&ff_msmp4_dc_luma_vlc[1], DC_VLC_BITS, 120, - &ff_table1_dc_lum[0][1], 8, 4, - &ff_table1_dc_lum[0][0], 8, 4, 1476); - INIT_VLC_STATIC(&ff_msmp4_dc_chroma_vlc[1], DC_VLC_BITS, 120, - &ff_table1_dc_chroma[0][1], 8, 4, - &ff_table1_dc_chroma[0][0], 8, 4, 1216); - - INIT_VLC_STATIC(&v2_dc_lum_vlc, DC_VLC_BITS, 512, - &ff_v2_dc_lum_table[0][1], 8, 4, - &ff_v2_dc_lum_table[0][0], 8, 4, 1472); - INIT_VLC_STATIC(&v2_dc_chroma_vlc, DC_VLC_BITS, 512, - &ff_v2_dc_chroma_table[0][1], 8, 4, - &ff_v2_dc_chroma_table[0][0], 8, 4, 1506); - - INIT_VLC_STATIC(&v2_intra_cbpc_vlc, V2_INTRA_CBPC_VLC_BITS, 4, - &ff_v2_intra_cbpc[0][1], 2, 1, - &ff_v2_intra_cbpc[0][0], 2, 1, 8); - INIT_VLC_STATIC(&v2_mb_type_vlc, V2_MB_TYPE_VLC_BITS, 8, - &ff_v2_mb_type[0][1], 2, 1, - &ff_v2_mb_type[0][0], 2, 1, 128); - - for (unsigned i = 0, offset = 0; i < 4; i++) { - static VLC_TYPE vlc_buf[1636 + 2648 + 1532 + 2488][2]; - ff_mb_non_intra_vlc[i].table = &vlc_buf[offset]; - ff_mb_non_intra_vlc[i].table_allocated = FF_ARRAY_ELEMS(vlc_buf) - offset; - init_vlc(&ff_mb_non_intra_vlc[i], MB_NON_INTRA_VLC_BITS, 128, - &ff_wmv2_inter_table[i][0][1], 8, 4, - &ff_wmv2_inter_table[i][0][0], 8, 4, - INIT_VLC_STATIC_OVERLONG); - offset += ff_mb_non_intra_vlc[i].table_size; - } - - INIT_VLC_STATIC(&ff_msmp4_mb_i_vlc, MB_INTRA_VLC_BITS, 64, - &ff_msmp4_mb_i_table[0][1], 4, 2, - &ff_msmp4_mb_i_table[0][0], 4, 2, 536); - - INIT_VLC_STATIC(&ff_inter_intra_vlc, INTER_INTRA_VLC_BITS, 4, - &ff_table_inter_intra[0][1], 2, 1, - &ff_table_inter_intra[0][0], 2, 1, 8); - done = 1; - } - switch(s->msmpeg4_version){ case 1: case 2: @@ -393,6 +400,8 @@ av_cold int ff_msmpeg4_decode_init(AVCodecContext *avctx) s->slice_height= s->mb_height; //to avoid 1/0 if the first frame is not a keyframe + ff_thread_once(&init_static_once, msmpeg4_decode_init_static); + return 0; } @@ -855,73 +864,77 @@ void ff_msmpeg4_decode_motion(MpegEncContext *s, int *mx_ptr, int *my_ptr) *my_ptr = my; } -const AVCodec ff_msmpeg4v1_decoder = { - .name = "msmpeg4v1", - .long_name = NULL_IF_CONFIG_SMALL("MPEG-4 part 2 Microsoft variant version 1"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MSMPEG4V1, +const FFCodec ff_msmpeg4v1_decoder = { + .p.name = "msmpeg4v1", + .p.long_name = NULL_IF_CONFIG_SMALL("MPEG-4 part 2 Microsoft variant version 1"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MSMPEG4V1, .priv_data_size = sizeof(MpegEncContext), .init = ff_msmpeg4_decode_init, .close = ff_h263_decode_end, - .decode = ff_h263_decode_frame, - .capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1, - .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, - .max_lowres = 3, - .pix_fmts = (const enum AVPixelFormat[]) { + FF_CODEC_DECODE_CB(ff_h263_decode_frame), + .p.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, + .p.max_lowres = 3, + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, }; -const AVCodec ff_msmpeg4v2_decoder = { - .name = "msmpeg4v2", - .long_name = NULL_IF_CONFIG_SMALL("MPEG-4 part 2 Microsoft variant version 2"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MSMPEG4V2, +const FFCodec ff_msmpeg4v2_decoder = { + .p.name = "msmpeg4v2", + .p.long_name = NULL_IF_CONFIG_SMALL("MPEG-4 part 2 Microsoft variant version 2"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MSMPEG4V2, .priv_data_size = sizeof(MpegEncContext), .init = ff_msmpeg4_decode_init, .close = ff_h263_decode_end, - .decode = ff_h263_decode_frame, - .capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1, - .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, - .max_lowres = 3, - .pix_fmts = (const enum AVPixelFormat[]) { + FF_CODEC_DECODE_CB(ff_h263_decode_frame), + .p.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, + .p.max_lowres = 3, + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, }; -const AVCodec ff_msmpeg4v3_decoder = { - .name = "msmpeg4", - .long_name = NULL_IF_CONFIG_SMALL("MPEG-4 part 2 Microsoft variant version 3"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MSMPEG4V3, +const FFCodec ff_msmpeg4v3_decoder = { + .p.name = "msmpeg4", + .p.long_name = NULL_IF_CONFIG_SMALL("MPEG-4 part 2 Microsoft variant version 3"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MSMPEG4V3, .priv_data_size = sizeof(MpegEncContext), .init = ff_msmpeg4_decode_init, .close = ff_h263_decode_end, - .decode = ff_h263_decode_frame, - .capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1, - .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, - .max_lowres = 3, - .pix_fmts = (const enum AVPixelFormat[]) { + FF_CODEC_DECODE_CB(ff_h263_decode_frame), + .p.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, + .p.max_lowres = 3, + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, }; -const AVCodec ff_wmv1_decoder = { - .name = "wmv1", - .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 7"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_WMV1, +const FFCodec ff_wmv1_decoder = { + .p.name = "wmv1", + .p.long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 7"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_WMV1, .priv_data_size = sizeof(MpegEncContext), .init = ff_msmpeg4_decode_init, .close = ff_h263_decode_end, - .decode = ff_h263_decode_frame, - .capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1, - .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, - .max_lowres = 3, - .pix_fmts = (const enum AVPixelFormat[]) { + FF_CODEC_DECODE_CB(ff_h263_decode_frame), + .p.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM, + .p.max_lowres = 3, + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, diff --git a/libavcodec/msmpeg4dec.h b/libavcodec/msmpeg4dec.h new file mode 100644 index 000000000..af2591caf --- /dev/null +++ b/libavcodec/msmpeg4dec.h @@ -0,0 +1,50 @@ +/* + * MSMPEG4 decoder header + * copyright (c) 2007 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 + */ + +#ifndef AVCODEC_MSMPEG4DEC_H +#define AVCODEC_MSMPEG4DEC_H + +#include "config.h" +#include "avcodec.h" +#include "mpegvideo.h" + +#define INTER_INTRA_VLC_BITS 3 +#define MB_NON_INTRA_VLC_BITS 9 +#define MB_INTRA_VLC_BITS 9 + +extern VLC ff_mb_non_intra_vlc[4]; +extern VLC ff_inter_intra_vlc; + +int ff_msmpeg4_decode_init(AVCodecContext *avctx); +int ff_msmpeg4_decode_picture_header(MpegEncContext *s); +int ff_msmpeg4_decode_ext_header(MpegEncContext *s, int buf_size); +void ff_msmpeg4_decode_motion(MpegEncContext * s, int *mx_ptr, int *my_ptr); +int ff_msmpeg4_decode_block(MpegEncContext * s, int16_t * block, + int n, int coded, const uint8_t *scan_table); + +#define CONFIG_MSMPEG4_DECODER (CONFIG_MSMPEG4V1_DECODER || \ + CONFIG_MSMPEG4V2_DECODER || \ + CONFIG_MSMPEG4V3_DECODER || \ + CONFIG_WMV1_DECODER || \ + CONFIG_WMV2_DECODER || \ + CONFIG_VC1_DECODER) + +#endif diff --git a/libavcodec/msmpeg4enc.c b/libavcodec/msmpeg4enc.c index a4efbd34e..e597dbbb4 100644 --- a/libavcodec/msmpeg4enc.c +++ b/libavcodec/msmpeg4enc.c @@ -33,15 +33,17 @@ #include "libavutil/attributes.h" #include "libavutil/avutil.h" #include "libavutil/thread.h" +#include "codec_internal.h" #include "mpegvideo.h" +#include "mpegvideoenc.h" #include "h263.h" -#include "internal.h" +#include "h263data.h" #include "mpeg4video.h" #include "msmpeg4.h" #include "msmpeg4data.h" +#include "msmpeg4enc.h" #include "put_bits.h" #include "rl.h" -#include "vc1data.h" static uint8_t rl_length[NB_RL_TABLES][MAX_LEVEL+1][MAX_RUN+1][2]; @@ -147,8 +149,9 @@ av_cold void ff_msmpeg4_encode_init(MpegEncContext *s) ff_thread_once(&init_static_once, msmpeg4_encode_init_static); } -static void find_best_tables(MpegEncContext * s) +static void find_best_tables(MSMPEG4EncContext *ms) { + MpegEncContext *const s = &ms->s; int i; int best = 0, best_size = INT_MAX; int chroma_best = 0, best_chroma_size = INT_MAX; @@ -168,9 +171,9 @@ static void find_best_tables(MpegEncContext * s) int last; const int last_size= size + chroma_size; for(last=0; last<2; last++){ - int inter_count = s->ac_stats[0][0][level][run][last] + s->ac_stats[0][1][level][run][last]; - int intra_luma_count = s->ac_stats[1][0][level][run][last]; - int intra_chroma_count= s->ac_stats[1][1][level][run][last]; + int inter_count = ms->ac_stats[0][0][level][run][last] + ms->ac_stats[0][1][level][run][last]; + int intra_luma_count = ms->ac_stats[1][0][level][run][last]; + int intra_chroma_count= ms->ac_stats[1][1][level][run][last]; if(s->pict_type==AV_PICTURE_TYPE_I){ size += intra_luma_count *rl_length[i ][level][run][last]; @@ -196,7 +199,7 @@ static void find_best_tables(MpegEncContext * s) if(s->pict_type==AV_PICTURE_TYPE_P) chroma_best= best; - memset(s->ac_stats, 0, sizeof(int)*(MAX_LEVEL+1)*(MAX_RUN+1)*2*2*2); + memset(ms->ac_stats, 0, sizeof(ms->ac_stats)); s->rl_table_index = best; s->rl_chroma_table_index= chroma_best; @@ -214,7 +217,9 @@ static void find_best_tables(MpegEncContext * s) /* write MSMPEG4 compatible frame header */ void ff_msmpeg4_encode_picture_header(MpegEncContext * s, int picture_number) { - find_best_tables(s); + MSMPEG4EncContext *const ms = (MSMPEG4EncContext*)s; + + find_best_tables(ms); align_put_bits(&s->pb); put_bits(&s->pb, 2, s->pict_type - 1); @@ -552,6 +557,7 @@ static void msmpeg4_encode_dc(MpegEncContext * s, int level, int n, int *dir_ptr * escape coding (same as H.263) and more VLC tables. */ void ff_msmpeg4_encode_block(MpegEncContext * s, int16_t * block, int n) { + MSMPEG4EncContext *const ms = (MSMPEG4EncContext*)s; int level, run, last, i, j, last_index; int last_non_zero, sign, slevel; int code, run_diff, dc_pred_dir; @@ -602,10 +608,10 @@ void ff_msmpeg4_encode_block(MpegEncContext * s, int16_t * block, int n) } if(level<=MAX_LEVEL && run<=MAX_RUN){ - s->ac_stats[s->mb_intra][n>3][level][run][last]++; + ms->ac_stats[s->mb_intra][n>3][level][run][last]++; } - s->ac_stats[s->mb_intra][n > 3][40][63][0]++; //esc3 like + ms->ac_stats[s->mb_intra][n > 3][40][63][0]++; //esc3 like code = get_rl_index(rl, last, run, level); put_bits(&s->pb, rl->table_vlc[code][1], rl->table_vlc[code][0]); @@ -669,3 +675,45 @@ void ff_msmpeg4_encode_block(MpegEncContext * s, int16_t * block, int n) } } } + +const FFCodec ff_msmpeg4v2_encoder = { + .p.name = "msmpeg4v2", + .p.long_name = NULL_IF_CONFIG_SMALL("MPEG-4 part 2 Microsoft variant version 2"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MSMPEG4V2, + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, + .p.priv_class = &ff_mpv_enc_class, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, + .priv_data_size = sizeof(MSMPEG4EncContext), + .init = ff_mpv_encode_init, + FF_CODEC_ENCODE_CB(ff_mpv_encode_picture), + .close = ff_mpv_encode_end, +}; + +const FFCodec ff_msmpeg4v3_encoder = { + .p.name = "msmpeg4", + .p.long_name = NULL_IF_CONFIG_SMALL("MPEG-4 part 2 Microsoft variant version 3"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MSMPEG4V3, + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, + .p.priv_class = &ff_mpv_enc_class, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, + .priv_data_size = sizeof(MSMPEG4EncContext), + .init = ff_mpv_encode_init, + FF_CODEC_ENCODE_CB(ff_mpv_encode_picture), + .close = ff_mpv_encode_end, +}; + +const FFCodec ff_wmv1_encoder = { + .p.name = "wmv1", + .p.long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 7"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_WMV1, + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, + .p.priv_class = &ff_mpv_enc_class, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, + .priv_data_size = sizeof(MSMPEG4EncContext), + .init = ff_mpv_encode_init, + FF_CODEC_ENCODE_CB(ff_mpv_encode_picture), + .close = ff_mpv_encode_end, +}; diff --git a/libavcodec/msmpeg4enc.h b/libavcodec/msmpeg4enc.h new file mode 100644 index 000000000..98044913b --- /dev/null +++ b/libavcodec/msmpeg4enc.h @@ -0,0 +1,53 @@ +/* + * MSMPEG4 encoder header + * copyright (c) 2007 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 + */ + +#ifndef AVCODEC_MSMPEG4ENC_H +#define AVCODEC_MSMPEG4ENC_H + +#include "config.h" +#include "mpegvideo.h" +#include "put_bits.h" +#include "rl.h" + +typedef struct MSMPEG4EncContext { + MpegEncContext s; + + /** [mb_intra][isChroma][level][run][last] */ + unsigned ac_stats[2][2][MAX_LEVEL + 1][MAX_RUN + 1][2]; +} MSMPEG4EncContext; + +void ff_msmpeg4_encode_init(MpegEncContext *s); +void ff_msmpeg4_encode_picture_header(MpegEncContext *s, int picture_number); +void ff_msmpeg4_encode_ext_header(MpegEncContext *s); +void ff_msmpeg4_encode_mb(MpegEncContext *s, int16_t block[6][64], + int motion_x, int motion_y); +void ff_msmpeg4_encode_block(MpegEncContext * s, int16_t * block, int n); +void ff_msmpeg4_handle_slices(MpegEncContext *s); +void ff_msmpeg4_encode_motion(MpegEncContext * s, int mx, int my); + +void ff_msmpeg4_code012(PutBitContext *pb, int n); + +#define CONFIG_MSMPEG4_ENCODER (CONFIG_MSMPEG4V2_ENCODER || \ + CONFIG_MSMPEG4V3_ENCODER || \ + CONFIG_WMV1_ENCODER || \ + CONFIG_WMV2_ENCODER) + +#endif diff --git a/libavcodec/msp2dec.c b/libavcodec/msp2dec.c index 8772bff6b..5374c4be8 100644 --- a/libavcodec/msp2dec.c +++ b/libavcodec/msp2dec.c @@ -26,15 +26,14 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" -static int msp2_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int msp2_decode_frame(AVCodecContext *avctx, AVFrame *p, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; - AVFrame *p = data; int ret; unsigned int x, y, width = (avctx->width + 7) / 8; GetByteContext idx, gb; @@ -93,11 +92,11 @@ static int msp2_decode_frame(AVCodecContext *avctx, return buf_size; } -const AVCodec ff_msp2_decoder = { - .name = "msp2", - .long_name = NULL_IF_CONFIG_SMALL("Microsoft Paint (MSP) version 2"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MSP2, - .decode = msp2_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, +const FFCodec ff_msp2_decoder = { + .p.name = "msp2", + .p.long_name = NULL_IF_CONFIG_SMALL("Microsoft Paint (MSP) version 2"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MSP2, + .p.capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(msp2_decode_frame), }; diff --git a/libavcodec/msrle.c b/libavcodec/msrle.c index b6f80653c..f9d7141c0 100644 --- a/libavcodec/msrle.c +++ b/libavcodec/msrle.c @@ -33,6 +33,7 @@ #include #include "avcodec.h" +#include "codec_internal.h" #include "decode.h" #include "internal.h" #include "msrledec.h" @@ -81,9 +82,8 @@ static av_cold int msrle_decode_init(AVCodecContext *avctx) return 0; } -static int msrle_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int msrle_decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; @@ -108,7 +108,7 @@ static int msrle_decode_frame(AVCodecContext *avctx, if (avctx->height * istride == avpkt->size) { /* assume uncompressed */ int linesize = av_image_get_linesize(avctx->pix_fmt, avctx->width, 0); uint8_t *ptr = s->frame->data[0]; - uint8_t *buf = avpkt->data + (avctx->height-1)*istride; + const uint8_t *buf = avpkt->data + (avctx->height-1)*istride; int i, j; if (linesize < 0) @@ -133,7 +133,7 @@ static int msrle_decode_frame(AVCodecContext *avctx, ff_msrle_decode(avctx, s->frame, avctx->bits_per_coded_sample, &s->gb); } - if ((ret = av_frame_ref(data, s->frame)) < 0) + if ((ret = av_frame_ref(rframe, s->frame)) < 0) return ret; *got_frame = 1; @@ -159,16 +159,16 @@ static av_cold int msrle_decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_msrle_decoder = { - .name = "msrle", - .long_name = NULL_IF_CONFIG_SMALL("Microsoft RLE"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MSRLE, +const FFCodec ff_msrle_decoder = { + .p.name = "msrle", + .p.long_name = NULL_IF_CONFIG_SMALL("Microsoft RLE"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MSRLE, .priv_data_size = sizeof(MsrleContext), .init = msrle_decode_init, .close = msrle_decode_end, - .decode = msrle_decode_frame, + FF_CODEC_DECODE_CB(msrle_decode_frame), .flush = msrle_decode_flush, - .capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/mss1.c b/libavcodec/mss1.c index a9a7a81d2..bc00a11ab 100644 --- a/libavcodec/mss1.c +++ b/libavcodec/mss1.c @@ -25,6 +25,7 @@ */ #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "mss12.h" @@ -139,8 +140,8 @@ static int decode_pal(MSS12Context *ctx, ArithCoder *acoder) return !!ncol; } -static int mss1_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int mss1_decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *avpkt) { MSS1Context *ctx = avctx->priv_data; MSS12Context *c = &ctx->ctx; @@ -179,7 +180,7 @@ static int mss1_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, memcpy(ctx->pic->data[1], c->pal, AVPALETTE_SIZE); ctx->pic->palette_has_changed = pal_changed; - if ((ret = av_frame_ref(data, ctx->pic)) < 0) + if ((ret = av_frame_ref(rframe, ctx->pic)) < 0) return ret; *got_frame = 1; @@ -218,15 +219,15 @@ static av_cold int mss1_decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_mss1_decoder = { - .name = "mss1", - .long_name = NULL_IF_CONFIG_SMALL("MS Screen 1"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MSS1, +const FFCodec ff_mss1_decoder = { + .p.name = "mss1", + .p.long_name = NULL_IF_CONFIG_SMALL("MS Screen 1"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MSS1, .priv_data_size = sizeof(MSS1Context), .init = mss1_decode_init, .close = mss1_decode_end, - .decode = mss1_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(mss1_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/mss12.h b/libavcodec/mss12.h index 6f68fc3db..27aa2d56b 100644 --- a/libavcodec/mss12.h +++ b/libavcodec/mss12.h @@ -68,7 +68,7 @@ typedef struct PixContext { struct MSS12Context; typedef struct SliceContext { - struct MSS12Context *c; + const struct MSS12Context *c; Model intra_region, inter_region; Model pivot, edge_mode, split_mode; PixContext intra_pix_ctx, inter_pix_ctx; diff --git a/libavcodec/mss2.c b/libavcodec/mss2.c index d7a19f6ad..228f66afc 100644 --- a/libavcodec/mss2.c +++ b/libavcodec/mss2.c @@ -24,10 +24,12 @@ */ #include "libavutil/avassert.h" +#include "codec_internal.h" #include "error_resilience.h" #include "internal.h" #include "mpeg_er.h" -#include "msmpeg4.h" +#include "mpegvideodec.h" +#include "msmpeg4dec.h" #include "qpeldsp.h" #include "vc1.h" #include "wmv2data.h" @@ -40,7 +42,6 @@ typedef struct MSS2Context { AVFrame *last_pic; MSS12Context c; MSS2DSPContext dsp; - QpelDSPContext qdsp; SliceContext sc[2]; } MSS2Context; @@ -470,14 +471,13 @@ struct Rectangle { #define MAX_WMV9_RECTANGLES 20 #define ARITH2_PADDING 2 -static int mss2_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int mss2_decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; MSS2Context *ctx = avctx->priv_data; MSS12Context *c = &ctx->c; - AVFrame *frame = data; GetBitContext gb; GetByteContext gB; ArithCoder acoder; @@ -836,7 +836,6 @@ static av_cold int mss2_decode_init(AVCodecContext *avctx) return ret; } ff_mss2dsp_init(&ctx->dsp); - ff_qpeldsp_init(&ctx->qdsp); avctx->pix_fmt = c->free_colours == 127 ? AV_PIX_FMT_RGB555 : AV_PIX_FMT_RGB24; @@ -845,14 +844,15 @@ static av_cold int mss2_decode_init(AVCodecContext *avctx) return 0; } -const AVCodec ff_mss2_decoder = { - .name = "mss2", - .long_name = NULL_IF_CONFIG_SMALL("MS Windows Media Video V9 Screen"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MSS2, +const FFCodec ff_mss2_decoder = { + .p.name = "mss2", + .p.long_name = NULL_IF_CONFIG_SMALL("MS Windows Media Video V9 Screen"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MSS2, .priv_data_size = sizeof(MSS2Context), .init = mss2_decode_init, .close = mss2_decode_end, - .decode = mss2_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(mss2_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/mss3.c b/libavcodec/mss3.c index 8ac2c23d3..55d2d10bd 100644 --- a/libavcodec/mss3.c +++ b/libavcodec/mss3.c @@ -26,6 +26,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" #include "mathops.h" #include "mss34dsp.h" @@ -681,8 +682,8 @@ static av_cold void init_coders(MSS3Context *ctx) } } -static int mss3_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int mss3_decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; @@ -742,7 +743,7 @@ static int mss3_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, c->pic->key_frame = keyframe; c->pic->pict_type = keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; if (!bytestream2_get_bytes_left(&gb)) { - if ((ret = av_frame_ref(data, c->pic)) < 0) + if ((ret = av_frame_ref(rframe, c->pic)) < 0) return ret; *got_frame = 1; @@ -801,7 +802,7 @@ static int mss3_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, dst[2] += c->pic->linesize[2] * 8; } - if ((ret = av_frame_ref(data, c->pic)) < 0) + if ((ret = av_frame_ref(rframe, c->pic)) < 0) return ret; *got_frame = 1; @@ -859,15 +860,15 @@ static av_cold int mss3_decode_init(AVCodecContext *avctx) return 0; } -const AVCodec ff_msa1_decoder = { - .name = "msa1", - .long_name = NULL_IF_CONFIG_SMALL("MS ATC Screen"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MSA1, +const FFCodec ff_msa1_decoder = { + .p.name = "msa1", + .p.long_name = NULL_IF_CONFIG_SMALL("MS ATC Screen"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MSA1, .priv_data_size = sizeof(MSS3Context), .init = mss3_decode_init, .close = mss3_decode_end, - .decode = mss3_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(mss3_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/mss4.c b/libavcodec/mss4.c index 216df2852..43eb1025a 100644 --- a/libavcodec/mss4.c +++ b/libavcodec/mss4.c @@ -26,9 +26,11 @@ */ #include "libavutil/thread.h" +#include "libavutil/imgutils.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" #include "jpegtables.h" @@ -99,7 +101,7 @@ static VLC vec_entry_vlc[2]; static av_cold void mss4_init_vlc(VLC *vlc, unsigned *offset, const uint8_t *lens, const uint8_t *syms) { - static VLC_TYPE vlc_buf[2146][2]; + static VLCElem vlc_buf[2146]; uint8_t bits[MAX_ENTRIES]; int i, j; int idx = 0; @@ -443,8 +445,8 @@ static inline void mss4_update_dc_cache(MSS4Context *c, int mb_x) } } -static int mss4_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int mss4_decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; @@ -476,6 +478,9 @@ static int mss4_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, width, height); return AVERROR_INVALIDDATA; } + if (av_image_check_size2(width, height, avctx->max_pixels, AV_PIX_FMT_NONE, 0, avctx) < 0) + return AVERROR_INVALIDDATA; + if (quality < 1 || quality > 100) { av_log(avctx, AV_LOG_ERROR, "Invalid quality setting %d\n", quality); return AVERROR_INVALIDDATA; @@ -503,7 +508,7 @@ static int mss4_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, : AV_PICTURE_TYPE_P; if (frame_type == SKIP_FRAME) { *got_frame = 1; - if ((ret = av_frame_ref(data, c->pic)) < 0) + if ((ret = av_frame_ref(rframe, c->pic)) < 0) return ret; return buf_size; @@ -558,7 +563,7 @@ static int mss4_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, dst[2] += c->pic->linesize[2] * 16; } - if ((ret = av_frame_ref(data, c->pic)) < 0) + if ((ret = av_frame_ref(rframe, c->pic)) < 0) return ret; *got_frame = 1; @@ -604,15 +609,15 @@ static av_cold int mss4_decode_init(AVCodecContext *avctx) return 0; } -const AVCodec ff_mts2_decoder = { - .name = "mts2", - .long_name = NULL_IF_CONFIG_SMALL("MS Expression Encoder Screen"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MTS2, +const FFCodec ff_mts2_decoder = { + .p.name = "mts2", + .p.long_name = NULL_IF_CONFIG_SMALL("MS Expression Encoder Screen"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MTS2, .priv_data_size = sizeof(MSS4Context), .init = mss4_decode_init, .close = mss4_decode_end, - .decode = mss4_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(mss4_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/msvideo1.c b/libavcodec/msvideo1.c index 182b3c38a..a39f684b5 100644 --- a/libavcodec/msvideo1.c +++ b/libavcodec/msvideo1.c @@ -33,6 +33,7 @@ #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" #include "avcodec.h" +#include "codec_internal.h" #include "decode.h" #include "internal.h" @@ -293,9 +294,8 @@ static void msvideo1_decode_16bit(Msvideo1Context *s) } } -static int msvideo1_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int msvideo1_decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; @@ -323,7 +323,7 @@ static int msvideo1_decode_frame(AVCodecContext *avctx, else msvideo1_decode_16bit(s); - if ((ret = av_frame_ref(data, s->frame)) < 0) + if ((ret = av_frame_ref(rframe, s->frame)) < 0) return ret; *got_frame = 1; @@ -341,15 +341,15 @@ static av_cold int msvideo1_decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_msvideo1_decoder = { - .name = "msvideo1", - .long_name = NULL_IF_CONFIG_SMALL("Microsoft Video 1"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MSVIDEO1, +const FFCodec ff_msvideo1_decoder = { + .p.name = "msvideo1", + .p.long_name = NULL_IF_CONFIG_SMALL("Microsoft Video 1"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MSVIDEO1, .priv_data_size = sizeof(Msvideo1Context), .init = msvideo1_decode_init, .close = msvideo1_decode_end, - .decode = msvideo1_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(msvideo1_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/msvideo1enc.c b/libavcodec/msvideo1enc.c index a8761bdd2..53f4a4b36 100644 --- a/libavcodec/msvideo1enc.c +++ b/libavcodec/msvideo1enc.c @@ -25,8 +25,8 @@ */ #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "bytestream.h" #include "libavutil/lfg.h" #include "elbg.h" @@ -302,15 +302,15 @@ static av_cold int encode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_msvideo1_encoder = { - .name = "msvideo1", - .long_name = NULL_IF_CONFIG_SMALL("Microsoft Video-1"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MSVIDEO1, +const FFCodec ff_msvideo1_encoder = { + .p.name = "msvideo1", + .p.long_name = NULL_IF_CONFIG_SMALL("Microsoft Video-1"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MSVIDEO1, .priv_data_size = sizeof(Msvideo1EncContext), .init = encode_init, - .encode2 = encode_frame, + FF_CODEC_ENCODE_CB(encode_frame), .close = encode_end, - .pix_fmts = (const enum AVPixelFormat[]){AV_PIX_FMT_RGB555, AV_PIX_FMT_NONE}, + .p.pix_fmts = (const enum AVPixelFormat[]){AV_PIX_FMT_RGB555, AV_PIX_FMT_NONE}, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/mv30.c b/libavcodec/mv30.c index 21f52679c..a32fab2b9 100644 --- a/libavcodec/mv30.c +++ b/libavcodec/mv30.c @@ -28,6 +28,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "copy_block.h" #include "mathops.h" #include "blockdsp.h" @@ -600,12 +601,11 @@ fail: return ret; } -static int decode_frame(AVCodecContext *avctx, void *data, +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt) { MV30Context *s = avctx->priv_data; GetBitContext *gb = &s->gb; - AVFrame *frame = data; int ret; if ((ret = init_get_bits8(gb, avpkt->data, avpkt->size)) < 0) @@ -702,17 +702,17 @@ static av_cold int decode_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_mv30_decoder = { - .name = "mv30", - .long_name = NULL_IF_CONFIG_SMALL("MidiVid 3.0"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MV30, +const FFCodec ff_mv30_decoder = { + .p.name = "mv30", + .p.long_name = NULL_IF_CONFIG_SMALL("MidiVid 3.0"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MV30, .priv_data_size = sizeof(MV30Context), .init = decode_init, .close = decode_close, - .decode = decode_frame, + FF_CODEC_DECODE_CB(decode_frame), .flush = decode_flush, - .capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/mvcdec.c b/libavcodec/mvcdec.c index ae5ce4c0d..4ee8d10ca 100644 --- a/libavcodec/mvcdec.c +++ b/libavcodec/mvcdec.c @@ -24,10 +24,13 @@ * Silicon Graphics Motion Video Compressor 1 & 2 decoder */ +#include "config_components.h" + #include "libavutil/intreadwrite.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" typedef struct MvcContext { @@ -222,11 +225,10 @@ static int decode_mvc2(AVCodecContext *avctx, GetByteContext *gb, return 0; } -static int mvc_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int mvc_decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { MvcContext *s = avctx->priv_data; - AVFrame *frame = data; GetByteContext gb; int ret; @@ -253,29 +255,29 @@ static int mvc_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, } #if CONFIG_MVC1_DECODER -const AVCodec ff_mvc1_decoder = { - .name = "mvc1", - .long_name = NULL_IF_CONFIG_SMALL("Silicon Graphics Motion Video Compressor 1"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MVC1, +const FFCodec ff_mvc1_decoder = { + .p.name = "mvc1", + .p.long_name = NULL_IF_CONFIG_SMALL("Silicon Graphics Motion Video Compressor 1"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MVC1, .priv_data_size = sizeof(MvcContext), .init = mvc_decode_init, - .decode = mvc_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(mvc_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_MVC2_DECODER -const AVCodec ff_mvc2_decoder = { - .name = "mvc2", - .long_name = NULL_IF_CONFIG_SMALL("Silicon Graphics Motion Video Compressor 2"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MVC2, +const FFCodec ff_mvc2_decoder = { + .p.name = "mvc2", + .p.long_name = NULL_IF_CONFIG_SMALL("Silicon Graphics Motion Video Compressor 2"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MVC2, .priv_data_size = sizeof(MvcContext), .init = mvc_decode_init, - .decode = mvc_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(mvc_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif diff --git a/libavcodec/mvha.c b/libavcodec/mvha.c index 4048e4625..8a65c4258 100644 --- a/libavcodec/mvha.c +++ b/libavcodec/mvha.c @@ -29,9 +29,11 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" #include "lossless_videodsp.h" +#include "zlib_wrapper.h" #include @@ -43,7 +45,7 @@ typedef struct MVHAContext { uint32_t prob[256]; VLC vlc; - z_stream zstream; + FFZStream zstream; LLVidDSPContext llviddsp; } MVHAContext; @@ -146,12 +148,10 @@ static int build_vlc(AVCodecContext *avctx, VLC *vlc) return ff_init_vlc_sparse(vlc, 12, pos, lens, 2, 2, bits, 4, 4, xlat, 1, 1, 0); } -static int decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { MVHAContext *s = avctx->priv_data; - AVFrame *frame = data; uint32_t type, size; int ret; @@ -168,21 +168,22 @@ static int decode_frame(AVCodecContext *avctx, return ret; if (type == MKTAG('L','Z','Y','V')) { - ret = inflateReset(&s->zstream); + z_stream *const zstream = &s->zstream.zstream; + ret = inflateReset(zstream); if (ret != Z_OK) { av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", ret); return AVERROR_EXTERNAL; } - s->zstream.next_in = avpkt->data + 8; - s->zstream.avail_in = avpkt->size - 8; + zstream->next_in = avpkt->data + 8; + zstream->avail_in = avpkt->size - 8; for (int p = 0; p < 3; p++) { for (int y = 0; y < avctx->height; y++) { - s->zstream.next_out = frame->data[p] + (avctx->height - y - 1) * frame->linesize[p]; - s->zstream.avail_out = avctx->width >> (p > 0); + zstream->next_out = frame->data[p] + (avctx->height - y - 1) * frame->linesize[p]; + zstream->avail_out = avctx->width >> (p > 0); - ret = inflate(&s->zstream, Z_SYNC_FLUSH); + ret = inflate(zstream, Z_SYNC_FLUSH); if (ret != Z_OK && ret != Z_STREAM_END) { av_log(avctx, AV_LOG_ERROR, "Inflate error: %d\n", ret); return AVERROR_EXTERNAL; @@ -279,44 +280,34 @@ static int decode_frame(AVCodecContext *avctx, static av_cold int decode_init(AVCodecContext *avctx) { MVHAContext *s = avctx->priv_data; - int zret; avctx->pix_fmt = AV_PIX_FMT_YUV422P; - s->zstream.zalloc = Z_NULL; - s->zstream.zfree = Z_NULL; - s->zstream.opaque = Z_NULL; - zret = inflateInit(&s->zstream); - if (zret != Z_OK) { - av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret); - return AVERROR_EXTERNAL; - } - ff_llviddsp_init(&s->llviddsp); - return 0; + return ff_inflate_init(&s->zstream, avctx); } static av_cold int decode_close(AVCodecContext *avctx) { MVHAContext *s = avctx->priv_data; - inflateEnd(&s->zstream); + ff_inflate_end(&s->zstream); ff_free_vlc(&s->vlc); return 0; } -const AVCodec ff_mvha_decoder = { - .name = "mvha", - .long_name = NULL_IF_CONFIG_SMALL("MidiVid Archive Codec"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MVHA, +const FFCodec ff_mvha_decoder = { + .p.name = "mvha", + .p.long_name = NULL_IF_CONFIG_SMALL("MidiVid Archive Codec"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MVHA, .priv_data_size = sizeof(MVHAContext), .init = decode_init, .close = decode_close, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/mwsc.c b/libavcodec/mwsc.c index b62db67ff..499b220a0 100644 --- a/libavcodec/mwsc.c +++ b/libavcodec/mwsc.c @@ -26,15 +26,17 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" +#include "zlib_wrapper.h" #include typedef struct MWSCContext { unsigned int decomp_size; uint8_t *decomp_buf; - z_stream zstream; AVFrame *prev_frame; + FFZStream zstream; } MWSCContext; static int rle_uncompress(GetByteContext *gb, PutByteContext *pb, GetByteContext *gbp, @@ -85,29 +87,28 @@ static int rle_uncompress(GetByteContext *gb, PutByteContext *pb, GetByteContext return intra; } -static int decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { MWSCContext *s = avctx->priv_data; - AVFrame *frame = data; - uint8_t *buf = avpkt->data; + z_stream *const zstream = &s->zstream.zstream; + const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; GetByteContext gb; GetByteContext gbp; PutByteContext pb; int ret; - ret = inflateReset(&s->zstream); + ret = inflateReset(zstream); if (ret != Z_OK) { av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", ret); return AVERROR_EXTERNAL; } - s->zstream.next_in = buf; - s->zstream.avail_in = buf_size; - s->zstream.next_out = s->decomp_buf; - s->zstream.avail_out = s->decomp_size; - ret = inflate(&s->zstream, Z_FINISH); + zstream->next_in = buf; + zstream->avail_in = buf_size; + zstream->next_out = s->decomp_buf; + zstream->avail_out = s->decomp_size; + ret = inflate(zstream, Z_FINISH); if (ret != Z_STREAM_END) { av_log(avctx, AV_LOG_ERROR, "Inflate error: %d\n", ret); return AVERROR_EXTERNAL; @@ -116,7 +117,7 @@ static int decode_frame(AVCodecContext *avctx, if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) return ret; - bytestream2_init(&gb, s->decomp_buf, s->zstream.total_out); + bytestream2_init(&gb, s->decomp_buf, zstream->total_out); bytestream2_init(&gbp, s->prev_frame->data[0], avctx->height * s->prev_frame->linesize[0]); bytestream2_init_writer(&pb, frame->data[0], avctx->height * frame->linesize[0]); @@ -138,7 +139,6 @@ static av_cold int decode_init(AVCodecContext *avctx) { MWSCContext *s = avctx->priv_data; int64_t size; - int zret; avctx->pix_fmt = AV_PIX_FMT_BGR24; @@ -149,20 +149,11 @@ static av_cold int decode_init(AVCodecContext *avctx) if (!(s->decomp_buf = av_malloc(s->decomp_size))) return AVERROR(ENOMEM); - s->zstream.zalloc = Z_NULL; - s->zstream.zfree = Z_NULL; - s->zstream.opaque = Z_NULL; - zret = inflateInit(&s->zstream); - if (zret != Z_OK) { - av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret); - return AVERROR_EXTERNAL; - } - s->prev_frame = av_frame_alloc(); if (!s->prev_frame) return AVERROR(ENOMEM); - return 0; + return ff_inflate_init(&s->zstream, avctx); } static av_cold int decode_close(AVCodecContext *avctx) @@ -172,21 +163,21 @@ static av_cold int decode_close(AVCodecContext *avctx) av_frame_free(&s->prev_frame); av_freep(&s->decomp_buf); s->decomp_size = 0; - inflateEnd(&s->zstream); + ff_inflate_end(&s->zstream); return 0; } -const AVCodec ff_mwsc_decoder = { - .name = "mwsc", - .long_name = NULL_IF_CONFIG_SMALL("MatchWare Screen Capture Codec"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MWSC, +const FFCodec ff_mwsc_decoder = { + .p.name = "mwsc", + .p.long_name = NULL_IF_CONFIG_SMALL("MatchWare Screen Capture Codec"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MWSC, .priv_data_size = sizeof(MWSCContext), .init = decode_init, .close = decode_close, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/mxpegdec.c b/libavcodec/mxpegdec.c index 16e586c1e..e5cdd44fd 100644 --- a/libavcodec/mxpegdec.c +++ b/libavcodec/mxpegdec.c @@ -25,6 +25,7 @@ * MxPEG decoder */ +#include "codec_internal.h" #include "internal.h" #include "mjpeg.h" #include "mjpegdec.h" @@ -179,9 +180,8 @@ static int mxpeg_check_dimensions(MXpegDecodeContext *s, MJpegDecodeContext *jpg return 0; } -static int mxpeg_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int mxpeg_decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; @@ -323,7 +323,7 @@ static int mxpeg_decode_frame(AVCodecContext *avctx, the_end: if (jpg->got_picture) { - int ret = av_frame_ref(data, jpg->picture_ptr); + int ret = av_frame_ref(rframe, jpg->picture_ptr); if (ret < 0) return ret; *got_frame = 1; @@ -342,16 +342,16 @@ the_end: return buf_ptr - buf; } -const AVCodec ff_mxpeg_decoder = { - .name = "mxpeg", - .long_name = NULL_IF_CONFIG_SMALL("Mobotix MxPEG video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MXPEG, +const FFCodec ff_mxpeg_decoder = { + .p.name = "mxpeg", + .p.long_name = NULL_IF_CONFIG_SMALL("Mobotix MxPEG video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MXPEG, .priv_data_size = sizeof(MXpegDecodeContext), .init = mxpeg_decode_init, .close = mxpeg_decode_end, - .decode = mxpeg_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, - .max_lowres = 3, + FF_CODEC_DECODE_CB(mxpeg_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, + .p.max_lowres = 3, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/nellymoserdec.c b/libavcodec/nellymoserdec.c index ccfe88179..63b60f202 100644 --- a/libavcodec/nellymoserdec.c +++ b/libavcodec/nellymoserdec.c @@ -39,6 +39,7 @@ #define BITSTREAM_READER_LE #include "avcodec.h" +#include "codec_internal.h" #include "fft.h" #include "get_bits.h" #include "internal.h" @@ -129,8 +130,8 @@ static av_cold int decode_init(AVCodecContext * avctx) { s->scale_bias = 1.0/(32768*8); avctx->sample_fmt = AV_SAMPLE_FMT_FLT; - avctx->channels = 1; - avctx->channel_layout = AV_CH_LAYOUT_MONO; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; /* Generate overlap window */ ff_init_ff_sine_windows(7); @@ -138,10 +139,9 @@ static av_cold int decode_init(AVCodecContext * avctx) { return 0; } -static int decode_tag(AVCodecContext *avctx, void *data, +static int decode_tag(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; NellyMoserDecodeContext *s = avctx->priv_data; @@ -186,17 +186,17 @@ static av_cold int decode_end(AVCodecContext * avctx) { return 0; } -const AVCodec ff_nellymoser_decoder = { - .name = "nellymoser", - .long_name = NULL_IF_CONFIG_SMALL("Nellymoser Asao"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_NELLYMOSER, +const FFCodec ff_nellymoser_decoder = { + .p.name = "nellymoser", + .p.long_name = NULL_IF_CONFIG_SMALL("Nellymoser Asao"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_NELLYMOSER, .priv_data_size = sizeof(NellyMoserDecodeContext), .init = decode_init, .close = decode_end, - .decode = decode_tag, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_PARAM_CHANGE | AV_CODEC_CAP_CHANNEL_CONF, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLT, + FF_CODEC_DECODE_CB(decode_tag), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_PARAM_CHANGE | AV_CODEC_CAP_CHANNEL_CONF, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/nellymoserenc.c b/libavcodec/nellymoserenc.c index 41d911706..c11dfe504 100644 --- a/libavcodec/nellymoserenc.c +++ b/libavcodec/nellymoserenc.c @@ -42,9 +42,9 @@ #include "audio_frame_queue.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" #include "fft.h" -#include "internal.h" #include "nellymoser.h" #include "sinewin.h" @@ -171,11 +171,6 @@ static av_cold int encode_init(AVCodecContext *avctx) NellyMoserEncodeContext *s = avctx->priv_data; int ret; - if (avctx->channels != 1) { - av_log(avctx, AV_LOG_ERROR, "Nellymoser supports only 1 channel\n"); - return AVERROR(EINVAL); - } - if (avctx->sample_rate != 8000 && avctx->sample_rate != 16000 && avctx->sample_rate != 11025 && avctx->sample_rate != 22050 && avctx->sample_rate != 44100 && @@ -418,18 +413,19 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *avpkt, return 0; } -const AVCodec ff_nellymoser_encoder = { - .name = "nellymoser", - .long_name = NULL_IF_CONFIG_SMALL("Nellymoser Asao"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_NELLYMOSER, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | +const FFCodec ff_nellymoser_encoder = { + .p.name = "nellymoser", + .p.long_name = NULL_IF_CONFIG_SMALL("Nellymoser Asao"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_NELLYMOSER, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SMALL_LAST_FRAME, .priv_data_size = sizeof(NellyMoserEncodeContext), .init = encode_init, - .encode2 = encode_frame, + FF_CODEC_ENCODE_CB(encode_frame), .close = encode_end, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLT, + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_NONE }, + .p.ch_layouts = (const AVChannelLayout[]){ AV_CHANNEL_LAYOUT_MONO, { 0 } }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/noise_bsf.c b/libavcodec/noise_bsf.c index 05b5d5f32..168f3aa37 100644 --- a/libavcodec/noise_bsf.c +++ b/libavcodec/noise_bsf.c @@ -23,7 +23,6 @@ #include "bsf.h" #include "bsf_internal.h" -#include "libavutil/avstring.h" #include "libavutil/log.h" #include "libavutil/opt.h" #include "libavutil/eval.h" @@ -220,10 +219,10 @@ static const AVClass noise_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVBitStreamFilter ff_noise_bsf = { - .name = "noise", +const FFBitStreamFilter ff_noise_bsf = { + .p.name = "noise", + .p.priv_class = &noise_class, .priv_data_size = sizeof(NoiseContext), - .priv_class = &noise_class, .init = noise_init, .close = noise_close, .filter = noise, diff --git a/libavcodec/notchlc.c b/libavcodec/notchlc.c index be2816199..f6d62b8a4 100644 --- a/libavcodec/notchlc.c +++ b/libavcodec/notchlc.c @@ -27,6 +27,7 @@ #include "libavutil/intreadwrite.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" #include "lzf.h" @@ -146,7 +147,7 @@ static int lz4_decompress(AVCodecContext *avctx, return bytestream2_tell_p(pb); } -static int decode_blocks(AVCodecContext *avctx, AVFrame *p, ThreadFrame *frame, +static int decode_blocks(AVCodecContext *avctx, AVFrame *p, unsigned uncompressed_size) { NotchLCContext *s = avctx->priv_data; @@ -221,7 +222,7 @@ static int decode_blocks(AVCodecContext *avctx, AVFrame *p, ThreadFrame *frame, return AVERROR_INVALIDDATA; s->uv_count_offset = s->y_data_offset - s->a_data_offset; - if ((ret = ff_thread_get_buffer(avctx, frame, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, p, 0)) < 0) return ret; rgb = *gb; @@ -459,16 +460,13 @@ static int decode_blocks(AVCodecContext *avctx, AVFrame *p, ThreadFrame *frame, return 0; } -static int decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *p, + int *got_frame, AVPacket *avpkt) { NotchLCContext *s = avctx->priv_data; - ThreadFrame frame = { .f = data }; GetByteContext *gb = &s->gb; PutByteContext *pb = &s->pb; unsigned uncompressed_size; - AVFrame *p = data; int ret; if (avpkt->size <= 40) @@ -513,7 +511,7 @@ static int decode_frame(AVCodecContext *avctx, bytestream2_init(gb, s->uncompressed_buffer, uncompressed_size); } - ret = decode_blocks(avctx, p, &frame, uncompressed_size); + ret = decode_blocks(avctx, p, uncompressed_size); if (ret < 0) return ret; @@ -537,15 +535,15 @@ static av_cold int decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_notchlc_decoder = { - .name = "notchlc", - .long_name = NULL_IF_CONFIG_SMALL("NotchLC"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_NOTCHLC, +const FFCodec ff_notchlc_decoder = { + .p.name = "notchlc", + .p.long_name = NULL_IF_CONFIG_SMALL("NotchLC"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_NOTCHLC, .priv_data_size = sizeof(NotchLCContext), .init = decode_init, .close = decode_end, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/null_bsf.c b/libavcodec/null_bsf.c index 595945027..28237076f 100644 --- a/libavcodec/null_bsf.c +++ b/libavcodec/null_bsf.c @@ -21,10 +21,9 @@ * Null bitstream filter -- pass the input through unchanged. */ -#include "bsf.h" #include "bsf_internal.h" -const AVBitStreamFilter ff_null_bsf = { - .name = "null", +const FFBitStreamFilter ff_null_bsf = { + .p.name = "null", .filter = ff_bsf_get_packet_ref, }; diff --git a/libavcodec/nuv.c b/libavcodec/nuv.c index 089ce6833..71420a62f 100644 --- a/libavcodec/nuv.c +++ b/libavcodec/nuv.c @@ -29,6 +29,7 @@ #include "libavutil/lzo.h" #include "libavutil/imgutils.h" #include "avcodec.h" +#include "codec_internal.h" #include "idctdsp.h" #include "internal.h" #include "rtjpeg.h" @@ -151,13 +152,12 @@ static int codec_reinit(AVCodecContext *avctx, int width, int height, return 0; } -static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *picture, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; NuvContext *c = avctx->priv_data; - AVFrame *picture = data; int orig_size = buf_size; int keyframe, ret; int size_change = 0; @@ -362,15 +362,15 @@ static av_cold int decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_nuv_decoder = { - .name = "nuv", - .long_name = NULL_IF_CONFIG_SMALL("NuppelVideo/RTJPEG"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_NUV, +const FFCodec ff_nuv_decoder = { + .p.name = "nuv", + .p.long_name = NULL_IF_CONFIG_SMALL("NuppelVideo/RTJPEG"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_NUV, .priv_data_size = sizeof(NuvContext), .init = decode_init, .close = decode_end, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/nvdec.c b/libavcodec/nvdec.c index 251be039a..edff46d31 100644 --- a/libavcodec/nvdec.c +++ b/libavcodec/nvdec.c @@ -21,6 +21,7 @@ */ #include "config.h" +#include "config_components.h" #include "libavutil/common.h" #include "libavutil/error.h" diff --git a/libavcodec/nvdec_av1.c b/libavcodec/nvdec_av1.c index 1ce846a60..3bbcd7612 100644 --- a/libavcodec/nvdec_av1.c +++ b/libavcodec/nvdec_av1.c @@ -49,7 +49,7 @@ static int nvdec_av1_start_frame(AVCodecContext *avctx, const uint8_t *buffer, u CUVIDAV1PICPARAMS *ppc = &pp->CodecSpecific.av1; FrameDecodeData *fdd; NVDECFrame *cf; - AVFrame *cur_frame = s->cur_frame.tf.f; + AVFrame *cur_frame = s->cur_frame.f; unsigned char remap_lr_type[4] = { AV1_RESTORE_NONE, AV1_RESTORE_SWITCHABLE, AV1_RESTORE_WIENER, AV1_RESTORE_SGRPROJ }; @@ -233,7 +233,7 @@ static int nvdec_av1_start_frame(AVCodecContext *avctx, const uint8_t *buffer, u ppc->loop_filter_ref_deltas[i] = frame_header->loop_filter_ref_deltas[i]; /* Reference Frames */ - ppc->ref_frame_map[i] = ff_nvdec_get_ref_idx(s->ref[i].tf.f); + ppc->ref_frame_map[i] = ff_nvdec_get_ref_idx(s->ref[i].f); } if (frame_header->primary_ref_frame == AV1_PRIMARY_REF_NONE) { @@ -246,7 +246,7 @@ static int nvdec_av1_start_frame(AVCodecContext *avctx, const uint8_t *buffer, u for (i = 0; i < AV1_REFS_PER_FRAME; ++i) { /* Ref Frame List */ int8_t ref_idx = frame_header->ref_frame_idx[i]; - AVFrame *ref_frame = s->ref[ref_idx].tf.f; + AVFrame *ref_frame = s->ref[ref_idx].f; ppc->ref_frame[i].index = ppc->ref_frame_map[ref_idx]; ppc->ref_frame[i].width = ref_frame->width; diff --git a/libavcodec/nvdec_mjpeg.c b/libavcodec/nvdec_mjpeg.c index be39d23ba..87f7a99a4 100644 --- a/libavcodec/nvdec_mjpeg.c +++ b/libavcodec/nvdec_mjpeg.c @@ -20,6 +20,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "avcodec.h" #include "internal.h" #include "mjpegdec.h" diff --git a/libavcodec/nvdec_mpeg12.c b/libavcodec/nvdec_mpeg12.c index 9a9030d8d..e10735587 100644 --- a/libavcodec/nvdec_mpeg12.c +++ b/libavcodec/nvdec_mpeg12.c @@ -20,7 +20,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "avcodec.h" +#include "internal.h" #include "mpegvideo.h" #include "nvdec.h" #include "decode.h" diff --git a/libavcodec/nvdec_mpeg4.c b/libavcodec/nvdec_mpeg4.c index 739b04993..b7e182175 100644 --- a/libavcodec/nvdec_mpeg4.c +++ b/libavcodec/nvdec_mpeg4.c @@ -21,7 +21,9 @@ */ #include "avcodec.h" +#include "internal.h" #include "mpeg4video.h" +#include "mpeg4videodec.h" #include "nvdec.h" #include "decode.h" diff --git a/libavcodec/nvdec_vc1.c b/libavcodec/nvdec_vc1.c index 10e7b5ab0..fae1cb0ab 100644 --- a/libavcodec/nvdec_vc1.c +++ b/libavcodec/nvdec_vc1.c @@ -20,7 +20,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "avcodec.h" +#include "internal.h" #include "nvdec.h" #include "decode.h" #include "vc1.h" diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index 850c46022..e19378736 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -20,6 +20,7 @@ */ #include "config.h" +#include "config_components.h" #include "nvenc.h" #include "hevc_sei.h" @@ -50,7 +51,11 @@ const enum AVPixelFormat ff_nvenc_pix_fmts[] = { AV_PIX_FMT_P016, // Truncated to 10bits AV_PIX_FMT_YUV444P16, // Truncated to 10bits AV_PIX_FMT_0RGB32, + AV_PIX_FMT_RGB32, AV_PIX_FMT_0BGR32, + AV_PIX_FMT_BGR32, + AV_PIX_FMT_X2RGB10, + AV_PIX_FMT_X2BGR10, AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP16, // Truncated to 10bits AV_PIX_FMT_CUDA, @@ -1509,9 +1514,15 @@ static NV_ENC_BUFFER_FORMAT nvenc_map_buffer_format(enum AVPixelFormat pix_fmt) case AV_PIX_FMT_YUV444P16: return NV_ENC_BUFFER_FORMAT_YUV444_10BIT; case AV_PIX_FMT_0RGB32: + case AV_PIX_FMT_RGB32: return NV_ENC_BUFFER_FORMAT_ARGB; case AV_PIX_FMT_0BGR32: + case AV_PIX_FMT_BGR32: return NV_ENC_BUFFER_FORMAT_ABGR; + case AV_PIX_FMT_X2RGB10: + return NV_ENC_BUFFER_FORMAT_ARGB10; + case AV_PIX_FMT_X2BGR10: + return NV_ENC_BUFFER_FORMAT_ABGR10; default: return NV_ENC_BUFFER_FORMAT_UNDEFINED; } @@ -1568,7 +1579,7 @@ static av_cold int nvenc_alloc_surface(AVCodecContext *avctx, int idx) ctx->surfaces[idx].output_surface = allocOut.bitstreamBuffer; - av_fifo_generic_write(ctx->unused_surface_queue, &tmp_surface, sizeof(tmp_surface), NULL); + av_fifo_write(ctx->unused_surface_queue, &tmp_surface, 1); return 0; } @@ -1582,18 +1593,18 @@ static av_cold int nvenc_setup_surfaces(AVCodecContext *avctx) if (!ctx->surfaces) return AVERROR(ENOMEM); - ctx->timestamp_list = av_fifo_alloc(ctx->nb_surfaces * sizeof(int64_t)); + ctx->timestamp_list = av_fifo_alloc2(ctx->nb_surfaces, sizeof(int64_t), 0); if (!ctx->timestamp_list) return AVERROR(ENOMEM); - ctx->unused_surface_queue = av_fifo_alloc(ctx->nb_surfaces * sizeof(NvencSurface*)); + ctx->unused_surface_queue = av_fifo_alloc2(ctx->nb_surfaces, sizeof(NvencSurface*), 0); if (!ctx->unused_surface_queue) return AVERROR(ENOMEM); - ctx->output_surface_queue = av_fifo_alloc(ctx->nb_surfaces * sizeof(NvencSurface*)); + ctx->output_surface_queue = av_fifo_alloc2(ctx->nb_surfaces, sizeof(NvencSurface*), 0); if (!ctx->output_surface_queue) return AVERROR(ENOMEM); - ctx->output_surface_ready_queue = av_fifo_alloc(ctx->nb_surfaces * sizeof(NvencSurface*)); + ctx->output_surface_ready_queue = av_fifo_alloc2(ctx->nb_surfaces, sizeof(NvencSurface*), 0); if (!ctx->output_surface_ready_queue) return AVERROR(ENOMEM); @@ -1666,10 +1677,10 @@ av_cold int ff_nvenc_encode_close(AVCodecContext *avctx) p_nvenc->nvEncEncodePicture(ctx->nvencoder, ¶ms); } - av_fifo_freep(&ctx->timestamp_list); - av_fifo_freep(&ctx->output_surface_ready_queue); - av_fifo_freep(&ctx->output_surface_queue); - av_fifo_freep(&ctx->unused_surface_queue); + av_fifo_freep2(&ctx->timestamp_list); + av_fifo_freep2(&ctx->output_surface_ready_queue); + av_fifo_freep2(&ctx->output_surface_queue); + av_fifo_freep2(&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_registered_frames; i++) { @@ -1777,11 +1788,10 @@ static NvencSurface *get_free_frame(NvencContext *ctx) { NvencSurface *tmp_surf; - if (!(av_fifo_size(ctx->unused_surface_queue) > 0)) + if (av_fifo_read(ctx->unused_surface_queue, &tmp_surf, 1) < 0) // queue empty return NULL; - av_fifo_generic_read(ctx->unused_surface_queue, &tmp_surf, sizeof(tmp_surf), NULL); return tmp_surf; } @@ -1998,16 +2008,16 @@ static void nvenc_codec_specific_pic_params(AVCodecContext *avctx, } } -static inline void timestamp_queue_enqueue(AVFifoBuffer* queue, int64_t timestamp) +static inline void timestamp_queue_enqueue(AVFifo *queue, int64_t timestamp) { - av_fifo_generic_write(queue, ×tamp, sizeof(timestamp), NULL); + av_fifo_write(queue, ×tamp, 1); } -static inline int64_t timestamp_queue_dequeue(AVFifoBuffer* queue) +static inline int64_t timestamp_queue_dequeue(AVFifo *queue) { int64_t timestamp = AV_NOPTS_VALUE; - if (av_fifo_size(queue) > 0) - av_fifo_generic_read(queue, ×tamp, sizeof(timestamp), NULL); + // The following call might fail if the queue is empty. + av_fifo_read(queue, ×tamp, 1); return timestamp; } @@ -2152,8 +2162,8 @@ static int output_ready(AVCodecContext *avctx, int flush) NvencContext *ctx = avctx->priv_data; int nb_ready, nb_pending; - nb_ready = av_fifo_size(ctx->output_surface_ready_queue) / sizeof(NvencSurface*); - nb_pending = av_fifo_size(ctx->output_surface_queue) / sizeof(NvencSurface*); + nb_ready = av_fifo_can_read(ctx->output_surface_ready_queue); + nb_pending = av_fifo_can_read(ctx->output_surface_queue); if (flush) return nb_ready > 0; return (nb_ready > 0) && (nb_ready + nb_pending >= ctx->async_depth); @@ -2442,16 +2452,14 @@ static int nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame) return nvenc_print_error(avctx, nv_status, "EncodePicture failed!"); if (frame && frame->buf[0]) { - av_fifo_generic_write(ctx->output_surface_queue, &in_surf, sizeof(in_surf), NULL); + av_fifo_write(ctx->output_surface_queue, &in_surf, 1); timestamp_queue_enqueue(ctx->timestamp_list, frame->pts); } /* all the pending buffers are now ready for output */ if (nv_status == NV_ENC_SUCCESS) { - while (av_fifo_size(ctx->output_surface_queue) > 0) { - av_fifo_generic_read(ctx->output_surface_queue, &tmp_out_surf, sizeof(tmp_out_surf), NULL); - av_fifo_generic_write(ctx->output_surface_ready_queue, &tmp_out_surf, sizeof(tmp_out_surf), NULL); - } + while (av_fifo_read(ctx->output_surface_queue, &tmp_out_surf, 1) >= 0) + av_fifo_write(ctx->output_surface_ready_queue, &tmp_out_surf, 1); } return 0; @@ -2483,7 +2491,7 @@ int ff_nvenc_receive_packet(AVCodecContext *avctx, AVPacket *pkt) av_frame_unref(frame); if (output_ready(avctx, avctx->internal->draining)) { - av_fifo_generic_read(ctx->output_surface_ready_queue, &tmp_out_surf, sizeof(tmp_out_surf), NULL); + av_fifo_read(ctx->output_surface_ready_queue, &tmp_out_surf, 1); res = nvenc_push_context(avctx); if (res < 0) @@ -2498,7 +2506,7 @@ int ff_nvenc_receive_packet(AVCodecContext *avctx, AVPacket *pkt) if (res) return res; - av_fifo_generic_write(ctx->unused_surface_queue, &tmp_out_surf, sizeof(tmp_out_surf), NULL); + av_fifo_write(ctx->unused_surface_queue, &tmp_out_surf, 1); } else if (avctx->internal->draining) { return AVERROR_EOF; } else { @@ -2513,5 +2521,5 @@ av_cold void ff_nvenc_encode_flush(AVCodecContext *avctx) NvencContext *ctx = avctx->priv_data; nvenc_send_frame(avctx, NULL); - av_fifo_reset(ctx->timestamp_list); + av_fifo_reset2(ctx->timestamp_list); } diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h index b42a156c5..9eb129952 100644 --- a/libavcodec/nvenc.h +++ b/libavcodec/nvenc.h @@ -168,10 +168,10 @@ typedef struct NvencContext int nb_surfaces; NvencSurface *surfaces; - AVFifoBuffer *unused_surface_queue; - AVFifoBuffer *output_surface_queue; - AVFifoBuffer *output_surface_ready_queue; - AVFifoBuffer *timestamp_list; + AVFifo *unused_surface_queue; + AVFifo *output_surface_queue; + AVFifo *output_surface_ready_queue; + AVFifo *timestamp_list; NV_ENC_SEI_PAYLOAD *sei_data; int sei_data_size; diff --git a/libavcodec/nvenc_h264.c b/libavcodec/nvenc_h264.c index 89e9a043f..1860c60a2 100644 --- a/libavcodec/nvenc_h264.c +++ b/libavcodec/nvenc_h264.c @@ -19,7 +19,7 @@ #include "libavutil/internal.h" #include "avcodec.h" -#include "internal.h" +#include "codec_internal.h" #include "nvenc.h" @@ -199,7 +199,7 @@ static const AVOption options[] = { { NULL } }; -static const AVCodecDefault defaults[] = { +static const FFCodecDefault defaults[] = { { "b", "2M" }, { "qmin", "-1" }, { "qmax", "-1" }, @@ -219,22 +219,22 @@ static const AVClass h264_nvenc_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_h264_nvenc_encoder = { - .name = "h264_nvenc", - .long_name = NULL_IF_CONFIG_SMALL("NVIDIA NVENC H.264 encoder"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_H264, +const FFCodec ff_h264_nvenc_encoder = { + .p.name = "h264_nvenc", + .p.long_name = NULL_IF_CONFIG_SMALL("NVIDIA NVENC H.264 encoder"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_H264, .init = ff_nvenc_encode_init, - .receive_packet = ff_nvenc_receive_packet, + FF_CODEC_RECEIVE_PACKET_CB(ff_nvenc_receive_packet), .close = ff_nvenc_encode_close, .flush = ff_nvenc_encode_flush, .priv_data_size = sizeof(NvencContext), - .priv_class = &h264_nvenc_class, + .p.priv_class = &h264_nvenc_class, .defaults = defaults, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, - .pix_fmts = ff_nvenc_pix_fmts, - .wrapper_name = "nvenc", + .p.pix_fmts = ff_nvenc_pix_fmts, + .p.wrapper_name = "nvenc", .hw_configs = ff_nvenc_hw_configs, }; diff --git a/libavcodec/nvenc_hevc.c b/libavcodec/nvenc_hevc.c index c2c13bb21..2c64cce59 100644 --- a/libavcodec/nvenc_hevc.c +++ b/libavcodec/nvenc_hevc.c @@ -19,7 +19,7 @@ #include "libavutil/internal.h" #include "avcodec.h" -#include "internal.h" +#include "codec_internal.h" #include "nvenc.h" @@ -180,7 +180,7 @@ static const AVOption options[] = { { NULL } }; -static const AVCodecDefault defaults[] = { +static const FFCodecDefault defaults[] = { { "b", "2M" }, { "qmin", "-1" }, { "qmax", "-1" }, @@ -200,22 +200,22 @@ static const AVClass hevc_nvenc_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_hevc_nvenc_encoder = { - .name = "hevc_nvenc", - .long_name = NULL_IF_CONFIG_SMALL("NVIDIA NVENC hevc encoder"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_HEVC, +const FFCodec ff_hevc_nvenc_encoder = { + .p.name = "hevc_nvenc", + .p.long_name = NULL_IF_CONFIG_SMALL("NVIDIA NVENC hevc encoder"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_HEVC, .init = ff_nvenc_encode_init, - .receive_packet = ff_nvenc_receive_packet, + FF_CODEC_RECEIVE_PACKET_CB(ff_nvenc_receive_packet), .close = ff_nvenc_encode_close, .flush = ff_nvenc_encode_flush, .priv_data_size = sizeof(NvencContext), - .priv_class = &hevc_nvenc_class, + .p.priv_class = &hevc_nvenc_class, .defaults = defaults, - .pix_fmts = ff_nvenc_pix_fmts, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | + .p.pix_fmts = ff_nvenc_pix_fmts, + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, - .wrapper_name = "nvenc", + .p.wrapper_name = "nvenc", .hw_configs = ff_nvenc_hw_configs, }; diff --git a/libavcodec/omx.c b/libavcodec/omx.c index cec0d04b8..d481c0678 100644 --- a/libavcodec/omx.c +++ b/libavcodec/omx.c @@ -41,8 +41,8 @@ #include "libavutil/opt.h" #include "avcodec.h" +#include "codec_internal.h" #include "h264.h" -#include "internal.h" #include "pthread_internal.h" #ifdef OMX_SKIP64BIT @@ -936,19 +936,19 @@ static const AVClass omx_mpeg4enc_class = { .option = options, .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_mpeg4_omx_encoder = { - .name = "mpeg4_omx", - .long_name = NULL_IF_CONFIG_SMALL("OpenMAX IL MPEG-4 video encoder"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MPEG4, +const FFCodec ff_mpeg4_omx_encoder = { + .p.name = "mpeg4_omx", + .p.long_name = NULL_IF_CONFIG_SMALL("OpenMAX IL MPEG-4 video encoder"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MPEG4, .priv_data_size = sizeof(OMXCodecContext), .init = omx_encode_init, - .encode2 = omx_encode_frame, + FF_CODEC_ENCODE_CB(omx_encode_frame), .close = omx_encode_end, - .pix_fmts = omx_encoder_pix_fmts, - .capabilities = AV_CODEC_CAP_DELAY, + .p.pix_fmts = omx_encoder_pix_fmts, + .p.capabilities = AV_CODEC_CAP_DELAY, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .priv_class = &omx_mpeg4enc_class, + .p.priv_class = &omx_mpeg4enc_class, }; static const AVClass omx_h264enc_class = { @@ -957,17 +957,17 @@ static const AVClass omx_h264enc_class = { .option = options, .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_h264_omx_encoder = { - .name = "h264_omx", - .long_name = NULL_IF_CONFIG_SMALL("OpenMAX IL H.264 video encoder"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_H264, +const FFCodec ff_h264_omx_encoder = { + .p.name = "h264_omx", + .p.long_name = NULL_IF_CONFIG_SMALL("OpenMAX IL H.264 video encoder"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_H264, .priv_data_size = sizeof(OMXCodecContext), .init = omx_encode_init, - .encode2 = omx_encode_frame, + FF_CODEC_ENCODE_CB(omx_encode_frame), .close = omx_encode_end, - .pix_fmts = omx_encoder_pix_fmts, - .capabilities = AV_CODEC_CAP_DELAY, + .p.pix_fmts = omx_encoder_pix_fmts, + .p.capabilities = AV_CODEC_CAP_DELAY, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .priv_class = &omx_h264enc_class, + .p.priv_class = &omx_h264enc_class, }; diff --git a/libavcodec/on2avc.c b/libavcodec/on2avc.c index fa3eb4b21..5477f6f87 100644 --- a/libavcodec/on2avc.c +++ b/libavcodec/on2avc.c @@ -27,6 +27,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "fft.h" #include "get_bits.h" #include "internal.h" @@ -691,7 +692,7 @@ static int on2avc_reconstruct_channel_ext(On2AVCContext *c, AVFrame *dst, int of { int ch, i; - for (ch = 0; ch < c->avctx->channels; ch++) { + for (ch = 0; ch < c->avctx->ch_layout.nb_channels; ch++) { float *out = (float*)dst->extended_data[ch] + offset; float *in = c->coeffs[ch]; float *saved = c->delay[ch]; @@ -823,13 +824,13 @@ static int on2avc_decode_subframe(On2AVCContext *c, const uint8_t *buf, c->grouping[i] = !get_bits1(&gb); on2avc_read_ms_info(c, &gb); - for (i = 0; i < c->avctx->channels; i++) + for (i = 0; i < c->avctx->ch_layout.nb_channels; i++) if ((ret = on2avc_read_channel_data(c, &gb, i)) < 0) return AVERROR_INVALIDDATA; - if (c->avctx->channels == 2 && c->ms_present) + if (c->avctx->ch_layout.nb_channels == 2 && c->ms_present) on2avc_apply_ms(c); if (c->window_type < WINDOW_TYPE_EXT4) { - for (i = 0; i < c->avctx->channels; i++) + for (i = 0; i < c->avctx->ch_layout.nb_channels; i++) on2avc_reconstruct_channel(c, i, dst, offset); } else { on2avc_reconstruct_channel_ext(c, dst, offset); @@ -838,10 +839,9 @@ static int on2avc_decode_subframe(On2AVCContext *c, const uint8_t *buf, return 0; } -static int on2avc_decode_frame(AVCodecContext * avctx, void *data, +static int on2avc_decode_frame(AVCodecContext * avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; On2AVCContext *c = avctx->priv_data; @@ -910,21 +910,23 @@ static av_cold int on2avc_decode_init(AVCodecContext *avctx) On2AVCContext *c = avctx->priv_data; const uint8_t *lens = ff_on2avc_cb_lens; const uint16_t *syms = ff_on2avc_cb_syms; + int channels = avctx->ch_layout.nb_channels; int i, ret; - if (avctx->channels > 2U) { + if (channels > 2U) { avpriv_request_sample(avctx, "Decoding more than 2 channels"); return AVERROR_PATCHWELCOME; } c->avctx = avctx; avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; - avctx->channel_layout = (avctx->channels == 2) ? AV_CH_LAYOUT_STEREO - : AV_CH_LAYOUT_MONO; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = (channels == 2) ? (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO : + (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; c->is_av500 = (avctx->codec_tag == 0x500); - if (avctx->channels == 2) + if (channels == 2) av_log(avctx, AV_LOG_WARNING, "Stereo mode support is not good, patch is welcome\n"); @@ -936,7 +938,7 @@ static av_cold int on2avc_decode_init(AVCodecContext *avctx) for (; i < 128; i++) c->scale_tab[i] = ceil(ff_exp10(i * 0.1) * 0.5 - 0.01); - if (avctx->sample_rate < 32000 || avctx->channels == 1) + if (avctx->sample_rate < 32000 || channels == 1) memcpy(c->long_win, ff_on2avc_window_long_24000, 1024 * sizeof(*c->long_win)); else @@ -1002,17 +1004,17 @@ static av_cold int on2avc_decode_close(AVCodecContext *avctx) } -const AVCodec ff_on2avc_decoder = { - .name = "on2avc", - .long_name = NULL_IF_CONFIG_SMALL("On2 Audio for Video Codec"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_ON2AVC, +const FFCodec ff_on2avc_decoder = { + .p.name = "on2avc", + .p.long_name = NULL_IF_CONFIG_SMALL("On2 Audio for Video Codec"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_ON2AVC, .priv_data_size = sizeof(On2AVCContext), .init = on2avc_decode_init, - .decode = on2avc_decode_frame, + FF_CODEC_DECODE_CB(on2avc_decode_frame), .close = on2avc_decode_close, - .capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, }; diff --git a/libavcodec/options.c b/libavcodec/options.c index bba6078b6..2e05d29e1 100644 --- a/libavcodec/options.c +++ b/libavcodec/options.c @@ -24,8 +24,10 @@ * Options definition for AVCodecContext. */ +#include "config_components.h" + #include "avcodec.h" -#include "internal.h" +#include "codec_internal.h" #include "libavutil/avassert.h" #include "libavutil/internal.h" #include "libavutil/mem.h" @@ -66,8 +68,10 @@ static const AVClass *codec_child_class_iterate(void **iter) static AVClassCategory get_category(void *ptr) { AVCodecContext* avctx = ptr; - if(avctx->codec && avctx->codec->decode) return AV_CLASS_CATEGORY_DECODER; - else return AV_CLASS_CATEGORY_ENCODER; + if (avctx->codec && av_codec_is_decoder(avctx->codec)) + return AV_CLASS_CATEGORY_DECODER; + else + return AV_CLASS_CATEGORY_ENCODER; } static const AVClass av_codec_context_class = { @@ -84,6 +88,7 @@ static const AVClass av_codec_context_class = { static int init_context_defaults(AVCodecContext *s, const AVCodec *codec) { + const FFCodec *const codec2 = ffcodec(codec); int flags=0; memset(s, 0, sizeof(AVCodecContext)); @@ -103,6 +108,8 @@ static int init_context_defaults(AVCodecContext *s, const AVCodec *codec) flags= AV_OPT_FLAG_SUBTITLE_PARAM; av_opt_set_defaults2(s, flags, flags); + av_channel_layout_uninit(&s->ch_layout); + s->time_base = (AVRational){0,1}; s->framerate = (AVRational){ 0, 1 }; s->pkt_timebase = (AVRational){ 0, 1 }; @@ -112,13 +119,14 @@ static int init_context_defaults(AVCodecContext *s, const AVCodec *codec) s->execute = avcodec_default_execute; s->execute2 = avcodec_default_execute2; s->sample_aspect_ratio = (AVRational){0,1}; + s->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; s->pix_fmt = AV_PIX_FMT_NONE; s->sw_pix_fmt = AV_PIX_FMT_NONE; s->sample_fmt = AV_SAMPLE_FMT_NONE; s->reordered_opaque = AV_NOPTS_VALUE; - if(codec && codec->priv_data_size){ - s->priv_data = av_mallocz(codec->priv_data_size); + if(codec && codec2->priv_data_size){ + s->priv_data = av_mallocz(codec2->priv_data_size); if (!s->priv_data) return AVERROR(ENOMEM); if(codec->priv_class){ @@ -126,9 +134,9 @@ static int init_context_defaults(AVCodecContext *s, const AVCodec *codec) av_opt_set_defaults(s->priv_data); } } - if (codec && codec->defaults) { + if (codec && codec2->defaults) { int ret; - const AVCodecDefault *d = codec->defaults; + const FFCodecDefault *d = codec2->defaults; while (d->key) { ret = av_opt_set(s, d->key, d->value, 0); av_assert0(ret >= 0); @@ -167,6 +175,7 @@ void avcodec_free_context(AVCodecContext **pavctx) av_freep(&avctx->intra_matrix); av_freep(&avctx->inter_matrix); av_freep(&avctx->rc_override); + av_channel_layout_uninit(&avctx->ch_layout); av_freep(pavctx); } @@ -177,6 +186,7 @@ const AVClass *avcodec_get_class(void) } #if FF_API_GET_FRAME_CLASS +FF_DISABLE_DEPRECATION_WARNINGS #define FOFFSET(x) offsetof(AVFrame,x) static const AVOption frame_options[]={ @@ -187,7 +197,9 @@ static const AVOption frame_options[]={ {"width", "", FOFFSET(width), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, 0}, {"height", "", FOFFSET(height), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, 0}, {"format", "", FOFFSET(format), AV_OPT_TYPE_INT, {.i64 = -1 }, 0, INT_MAX, 0}, +#if FF_API_OLD_CHANNEL_LAYOUT {"channel_layout", "", FOFFSET(channel_layout), AV_OPT_TYPE_INT64, {.i64 = 0 }, 0, INT64_MAX, 0}, +#endif {"sample_rate", "", FOFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, 0}, {NULL}, }; @@ -203,6 +215,7 @@ const AVClass *avcodec_get_frame_class(void) { return &av_frame_class; } +FF_ENABLE_DEPRECATION_WARNINGS #endif #define SROFFSET(x) offsetof(AVSubtitleRect,x) diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h index 130341a2e..e72b4d12b 100644 --- a/libavcodec/options_table.h +++ b/libavcodec/options_table.h @@ -22,13 +22,15 @@ #ifndef AVCODEC_OPTIONS_TABLE_H #define AVCODEC_OPTIONS_TABLE_H +#include "config_components.h" + #include #include #include #include "libavutil/opt.h" #include "avcodec.h" -#include "version.h" +#include "version_major.h" #define OFFSET(x) offsetof(AVCodecContext,x) #define DEFAULT 0 //should be NAN but it does not work as it is not a constant in glibc as required by ANSI/ISO C @@ -89,7 +91,9 @@ static const AVOption avcodec_options[] = { {"time_base", NULL, OFFSET(time_base), AV_OPT_TYPE_RATIONAL, {.dbl = 0}, 0, 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}, {"ar", "set audio sampling rate (in Hz)", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, 0, INT_MAX, A|D|E}, +#if FF_API_OLD_CHANNEL_LAYOUT {"ac", "set number of audio channels", OFFSET(channels), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, 0, INT_MAX, A|D|E}, +#endif {"cutoff", "set cutoff bandwidth", OFFSET(cutoff), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, A|E}, {"frame_size", NULL, OFFSET(frame_size), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, 0, INT_MAX, A|E}, {"frame_number", NULL, OFFSET(frame_number), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX}, @@ -262,8 +266,11 @@ static const AVOption avcodec_options[] = { {"mv0_threshold", NULL, OFFSET(mv0_threshold), AV_OPT_TYPE_INT, {.i64 = 256 }, 0, INT_MAX, V|E}, {"compression_level", NULL, OFFSET(compression_level), AV_OPT_TYPE_INT, {.i64 = FF_COMPRESSION_DEFAULT }, INT_MIN, INT_MAX, V|A|E}, {"bits_per_raw_sample", NULL, OFFSET(bits_per_raw_sample), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, 0, INT_MAX}, +{"ch_layout", NULL, OFFSET(ch_layout), AV_OPT_TYPE_CHLAYOUT, {.str = NULL }, 0, 0, A|E|D, "ch_layout"}, +#if FF_API_OLD_CHANNEL_LAYOUT {"channel_layout", NULL, OFFSET(channel_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64 = DEFAULT }, 0, UINT64_MAX, A|E|D, "channel_layout"}, {"request_channel_layout", NULL, OFFSET(request_channel_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64 = DEFAULT }, 0, UINT64_MAX, A|D, "request_channel_layout"}, +#endif {"rc_max_vbv_use", NULL, OFFSET(rc_max_available_vbv_use), AV_OPT_TYPE_FLOAT, {.dbl = 0 }, 0.0, FLT_MAX, V|E}, {"rc_min_vbv_use", NULL, OFFSET(rc_min_vbv_overflow_use), AV_OPT_TYPE_FLOAT, {.dbl = 3 }, 0.0, FLT_MAX, V|E}, {"ticks_per_frame", NULL, OFFSET(ticks_per_frame), AV_OPT_TYPE_INT, {.i64 = 1 }, 1, INT_MAX, A|V|E|D}, diff --git a/libavcodec/opus.c b/libavcodec/opus.c index df8ba93fa..354020634 100644 --- a/libavcodec/opus.c +++ b/libavcodec/opus.c @@ -296,14 +296,15 @@ av_cold int ff_opus_parse_extradata(AVCodecContext *avctx, static const uint8_t default_channel_map[2] = { 0, 1 }; int (*channel_reorder)(int, int) = channel_reorder_unknown; + int channels = avctx->ch_layout.nb_channels; const uint8_t *extradata, *channel_map; int extradata_size; - int version, channels, map_type, streams, stereo_streams, i, j; - uint64_t layout; + int version, map_type, streams, stereo_streams, i, j, ret; + AVChannelLayout layout = { 0 }; if (!avctx->extradata) { - if (avctx->channels > 2) { + if (channels > 2) { av_log(avctx, AV_LOG_ERROR, "Multichannel configuration without extradata.\n"); return AVERROR(EINVAL); @@ -331,7 +332,7 @@ av_cold int ff_opus_parse_extradata(AVCodecContext *avctx, if (avctx->internal) avctx->internal->skip_samples = avctx->delay; - channels = avctx->extradata ? extradata[9] : (avctx->channels == 1) ? 1 : 2; + channels = avctx->extradata ? extradata[9] : (channels == 1) ? 1 : 2; if (!channels) { av_log(avctx, AV_LOG_ERROR, "Zero channel count specified in the extradata\n"); return AVERROR_INVALIDDATA; @@ -346,9 +347,11 @@ av_cold int ff_opus_parse_extradata(AVCodecContext *avctx, if (channels > 2) { av_log(avctx, AV_LOG_ERROR, "Channel mapping 0 is only specified for up to 2 channels\n"); - return AVERROR_INVALIDDATA; + ret = AVERROR_INVALIDDATA; + goto fail; } - layout = (channels == 1) ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO; + layout = (channels == 1) ? (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO : + (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; streams = 1; stereo_streams = channels - 1; channel_map = default_channel_map; @@ -356,7 +359,8 @@ av_cold int ff_opus_parse_extradata(AVCodecContext *avctx, if (extradata_size < 21 + channels) { av_log(avctx, AV_LOG_ERROR, "Invalid extradata size: %d\n", extradata_size); - return AVERROR_INVALIDDATA; + ret = AVERROR_INVALIDDATA; + goto fail; } streams = extradata[19]; @@ -365,16 +369,18 @@ av_cold int ff_opus_parse_extradata(AVCodecContext *avctx, streams + stereo_streams > 255) { av_log(avctx, AV_LOG_ERROR, "Invalid stream/stereo stream count: %d/%d\n", streams, stereo_streams); - return AVERROR_INVALIDDATA; + ret = AVERROR_INVALIDDATA; + goto fail; } if (map_type == 1) { if (channels > 8) { av_log(avctx, AV_LOG_ERROR, "Channel mapping 1 is only specified for up to 8 channels\n"); - return AVERROR_INVALIDDATA; + ret = AVERROR_INVALIDDATA; + goto fail; } - layout = ff_vorbis_channel_layouts[channels - 1]; + av_channel_layout_copy(&layout, &ff_vorbis_ch_layouts[channels - 1]); channel_reorder = channel_reorder_vorbis; } else if (map_type == 2) { int ambisonic_order = ff_sqrt(channels) - 1; @@ -384,15 +390,23 @@ av_cold int ff_opus_parse_extradata(AVCodecContext *avctx, "Channel mapping 2 is only specified for channel counts" " which can be written as (n + 1)^2 or (n + 1)^2 + 2" " for nonnegative integer n\n"); - return AVERROR_INVALIDDATA; + ret = AVERROR_INVALIDDATA; + goto fail; } if (channels > 227) { av_log(avctx, AV_LOG_ERROR, "Too many channels\n"); - return AVERROR_INVALIDDATA; + ret = AVERROR_INVALIDDATA; + goto fail; } - layout = 0; - } else - layout = 0; + + layout.order = AV_CHANNEL_ORDER_AMBISONIC; + layout.nb_channels = channels; + if (channels != ((ambisonic_order + 1) * (ambisonic_order + 1))) + layout.u.mask = AV_CH_LAYOUT_STEREO; + } else { + layout.order = AV_CHANNEL_ORDER_UNSPEC; + layout.nb_channels = channels; + } channel_map = extradata + 21; } else { @@ -401,8 +415,10 @@ av_cold int ff_opus_parse_extradata(AVCodecContext *avctx, } s->channel_maps = av_calloc(channels, sizeof(*s->channel_maps)); - if (!s->channel_maps) - return AVERROR(ENOMEM); + if (!s->channel_maps) { + ret = AVERROR(ENOMEM); + goto fail; + } for (i = 0; i < channels; i++) { ChannelMap *map = &s->channel_maps[i]; @@ -415,7 +431,8 @@ av_cold int ff_opus_parse_extradata(AVCodecContext *avctx, av_log(avctx, AV_LOG_ERROR, "Invalid channel map for output channel %d: %d\n", i, idx); av_freep(&s->channel_maps); - return AVERROR_INVALIDDATA; + ret = AVERROR_INVALIDDATA; + goto fail; } /* check that we did not see this index yet */ @@ -436,12 +453,17 @@ av_cold int ff_opus_parse_extradata(AVCodecContext *avctx, } } - avctx->channels = channels; - avctx->channel_layout = layout; + ret = av_channel_layout_copy(&avctx->ch_layout, &layout); + if (ret < 0) + goto fail; + s->nb_streams = streams; s->nb_stereo_streams = stereo_streams; return 0; +fail: + av_channel_layout_uninit(&layout); + return ret; } void ff_celt_quant_bands(CeltFrame *f, OpusRangeCoder *rc) diff --git a/libavcodec/opus_metadata_bsf.c b/libavcodec/opus_metadata_bsf.c index e73852d61..2a0f86cec 100644 --- a/libavcodec/opus_metadata_bsf.c +++ b/libavcodec/opus_metadata_bsf.c @@ -58,11 +58,11 @@ static const enum AVCodecID codec_ids[] = { AV_CODEC_ID_OPUS, AV_CODEC_ID_NONE, }; -const AVBitStreamFilter ff_opus_metadata_bsf = { - .name = "opus_metadata", +const FFBitStreamFilter ff_opus_metadata_bsf = { + .p.name = "opus_metadata", + .p.codec_ids = codec_ids, + .p.priv_class = &opus_metadata_class, .priv_data_size = sizeof(OpusBSFContext), - .priv_class = &opus_metadata_class, .init = &opus_metadata_init, .filter = &ff_bsf_get_packet_ref, - .codec_ids = codec_ids, }; diff --git a/libavcodec/opus_pvq.c b/libavcodec/opus_pvq.c index a4ab7c46e..a4e44b7a1 100644 --- a/libavcodec/opus_pvq.c +++ b/libavcodec/opus_pvq.c @@ -23,6 +23,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "opustab.h" #include "opus_pvq.h" @@ -903,8 +905,9 @@ 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; - if (CONFIG_OPUS_ENCODER && ARCH_X86) - ff_celt_pvq_init_x86(s); +#if CONFIG_OPUS_ENCODER && ARCH_X86 + ff_celt_pvq_init_x86(s); +#endif *pvq = s; diff --git a/libavcodec/opusdec.c b/libavcodec/opusdec.c index b063e0efe..8ca99369c 100644 --- a/libavcodec/opusdec.c +++ b/libavcodec/opusdec.c @@ -43,6 +43,7 @@ #include "libswresample/swresample.h" #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" #include "mathops.h" @@ -411,11 +412,10 @@ finish: return output_samples; } -static int opus_decode_packet(AVCodecContext *avctx, void *data, +static int opus_decode_packet(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { OpusContext *c = avctx->priv_data; - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; int coded_samples = 0; @@ -458,7 +458,7 @@ static int opus_decode_packet(AVCodecContext *avctx, void *data, return ret; frame->nb_samples = 0; - for (i = 0; i < avctx->channels; i++) { + for (i = 0; i < avctx->ch_layout.nb_channels; i++) { ChannelMap *map = &c->channel_maps[i]; if (!map->copy) c->streams[map->stream_idx].out[map->channel_idx] = (float*)frame->extended_data[i]; @@ -541,7 +541,7 @@ static int opus_decode_packet(AVCodecContext *avctx, void *data, } } - for (i = 0; i < avctx->channels; i++) { + for (i = 0; i < avctx->ch_layout.nb_channels; i++) { ChannelMap *map = &c->channel_maps[i]; /* handle copied channels */ @@ -704,17 +704,17 @@ static const AVClass opus_class = { .version = LIBAVUTIL_VERSION_INT, }; -const 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, +const FFCodec ff_opus_decoder = { + .p.name = "opus", + .p.long_name = NULL_IF_CONFIG_SMALL("Opus"), + .p.priv_class = &opus_class, + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_OPUS, .priv_data_size = sizeof(OpusContext), .init = opus_decode_init, .close = opus_decode_close, - .decode = opus_decode_packet, + FF_CODEC_DECODE_CB(opus_decode_packet), .flush = opus_decode_flush, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_CHANNEL_CONF, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_CHANNEL_CONF, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/opusdsp.c b/libavcodec/opusdsp.c index 08df87ffb..badcfcc88 100644 --- a/libavcodec/opusdsp.c +++ b/libavcodec/opusdsp.c @@ -16,6 +16,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config.h" +#include "libavutil/attributes.h" #include "opusdsp.h" static void postfilter_c(float *data, int period, float *gains, int len) @@ -54,9 +56,9 @@ av_cold void ff_opus_dsp_init(OpusDSP *ctx) ctx->postfilter = postfilter_c; ctx->deemphasis = deemphasis_c; - if (ARCH_X86) - ff_opus_dsp_init_x86(ctx); - - if (ARCH_AARCH64) - ff_opus_dsp_init_aarch64(ctx); +#if ARCH_AARCH64 + ff_opus_dsp_init_aarch64(ctx); +#elif ARCH_X86 + ff_opus_dsp_init_x86(ctx); +#endif } diff --git a/libavcodec/opusdsp.h b/libavcodec/opusdsp.h index ee3186dd4..3ea3d14bf 100644 --- a/libavcodec/opusdsp.h +++ b/libavcodec/opusdsp.h @@ -19,8 +19,6 @@ #ifndef AVCODEC_OPUSDSP_H #define AVCODEC_OPUSDSP_H -#include "libavutil/common.h" - #define CELT_EMPH_COEFF 0.8500061035f typedef struct OpusDSP { diff --git a/libavcodec/opusenc.c b/libavcodec/opusenc.c index b7f4760a2..b4b7c472a 100644 --- a/libavcodec/opusenc.c +++ b/libavcodec/opusenc.c @@ -29,9 +29,9 @@ #include "libavutil/float_dsp.h" #include "libavutil/mem_internal.h" #include "libavutil/opt.h" -#include "internal.h" #include "bytestream.h" #include "audio_frame_queue.h" +#include "codec_internal.h" typedef struct OpusEncContext { AVClass *av_class; @@ -66,7 +66,7 @@ static void opus_write_extradata(AVCodecContext *avctx) bytestream_put_buffer(&bs, "OpusHead", 8); bytestream_put_byte (&bs, 0x1); - bytestream_put_byte (&bs, avctx->channels); + bytestream_put_byte (&bs, avctx->ch_layout.nb_channels); bytestream_put_le16 (&bs, avctx->initial_padding); bytestream_put_le32 (&bs, avctx->sample_rate); bytestream_put_le16 (&bs, 0x0); @@ -518,11 +518,16 @@ static void opus_packet_assembler(OpusEncContext *s, AVPacket *avpkt) static AVFrame *spawn_empty_frame(OpusEncContext *s) { AVFrame *f = av_frame_alloc(); + int ret; if (!f) return NULL; f->format = s->avctx->sample_fmt; f->nb_samples = s->avctx->frame_size; - f->channel_layout = s->avctx->channel_layout; + ret = av_channel_layout_copy(&f->ch_layout, &s->avctx->ch_layout); + if (ret < 0) { + av_frame_free(&f); + return NULL; + } if (av_frame_get_buffer(f, 4)) { av_frame_free(&f); return NULL; @@ -626,7 +631,7 @@ static av_cold int opus_encode_init(AVCodecContext *avctx) OpusEncContext *s = avctx->priv_data; s->avctx = avctx; - s->channels = avctx->channels; + s->channels = avctx->ch_layout.nb_channels; /* Opus allows us to change the framesize on each packet (and each packet may * have multiple frames in it) but we can't change the codec's frame size on @@ -714,28 +719,32 @@ static const AVClass opusenc_class = { .version = LIBAVUTIL_VERSION_INT, }; -static const AVCodecDefault opusenc_defaults[] = { +static const FFCodecDefault opusenc_defaults[] = { { "b", "0" }, { "compression_level", "10" }, { NULL }, }; -const AVCodec ff_opus_encoder = { - .name = "opus", - .long_name = NULL_IF_CONFIG_SMALL("Opus"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_OPUS, +const FFCodec ff_opus_encoder = { + .p.name = "opus", + .p.long_name = NULL_IF_CONFIG_SMALL("Opus"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_OPUS, .defaults = opusenc_defaults, - .priv_class = &opusenc_class, + .p.priv_class = &opusenc_class, .priv_data_size = sizeof(OpusEncContext), .init = opus_encode_init, - .encode2 = opus_encode_frame, + FF_CODEC_ENCODE_CB(opus_encode_frame), .close = opus_encode_end, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .capabilities = AV_CODEC_CAP_EXPERIMENTAL | AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY, - .supported_samplerates = (const int []){ 48000, 0 }, - .channel_layouts = (const uint64_t []){ AV_CH_LAYOUT_MONO, + .p.capabilities = AV_CODEC_CAP_EXPERIMENTAL | AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY, + .p.supported_samplerates = (const int []){ 48000, 0 }, +#if FF_API_OLD_CHANNEL_LAYOUT + .p.channel_layouts = (const uint64_t []){ AV_CH_LAYOUT_MONO, AV_CH_LAYOUT_STEREO, 0 }, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP, +#endif + .p.ch_layouts = (const AVChannelLayout []){ AV_CHANNEL_LAYOUT_MONO, + AV_CHANNEL_LAYOUT_STEREO, { 0 } }, + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, }; diff --git a/libavcodec/opusenc.h b/libavcodec/opusenc.h index b623b3e94..32d23deea 100644 --- a/libavcodec/opusenc.h +++ b/libavcodec/opusenc.h @@ -22,7 +22,6 @@ #ifndef AVCODEC_OPUSENC_H #define AVCODEC_OPUSENC_H -#include "internal.h" #include "opus_celt.h" /* Determines the maximum delay the psychoacoustic system will use for lookahead */ diff --git a/libavcodec/opusenc_psy.c b/libavcodec/opusenc_psy.c index 5a50db942..1c8f69269 100644 --- a/libavcodec/opusenc_psy.c +++ b/libavcodec/opusenc_psy.c @@ -83,7 +83,7 @@ static void step_collect_psy_metrics(OpusPsyContext *s, int index) st->index = index; - for (ch = 0; ch < s->avctx->channels; ch++) { + for (ch = 0; ch < s->avctx->ch_layout.nb_channels; ch++) { const int lap_size = (1 << s->bsize_analysis); for (i = 1; i <= FFMIN(lap_size, index); i++) { const int offset = i*120; @@ -105,7 +105,7 @@ static void step_collect_psy_metrics(OpusPsyContext *s, int index) st->bands[ch][i] = &st->coeffs[ch][ff_celt_freq_bands[i] << s->bsize_analysis]; } - for (ch = 0; ch < s->avctx->channels; ch++) { + for (ch = 0; ch < s->avctx->ch_layout.nb_channels; ch++) { for (i = 0; i < CELT_MAX_BANDS; i++) { float avg_c_s, energy = 0.0f, dist_dev = 0.0f; const int range = ff_celt_freq_range[i] << s->bsize_analysis; @@ -128,7 +128,7 @@ static void step_collect_psy_metrics(OpusPsyContext *s, int index) st->silence = !silence; - if (s->avctx->channels > 1) { + if (s->avctx->ch_layout.nb_channels > 1) { for (i = 0; i < CELT_MAX_BANDS; i++) { float incompat = 0.0f; const float *coeffs1 = st->bands[0][i]; @@ -140,7 +140,7 @@ static void step_collect_psy_metrics(OpusPsyContext *s, int index) } } - for (ch = 0; ch < s->avctx->channels; ch++) { + for (ch = 0; ch < s->avctx->ch_layout.nb_channels; ch++) { for (i = 0; i < CELT_MAX_BANDS; i++) { OpusBandExcitation *ex = &s->ex[ch][i]; float bp_e = bessel_filter(&s->bfilter_lo[ch][i], st->energy[ch][i]); @@ -259,7 +259,7 @@ void ff_opus_psy_celt_frame_init(OpusPsyContext *s, CeltFrame *f, int index) f->start_band = (s->p.mode == OPUS_MODE_HYBRID) ? 17 : 0; f->end_band = ff_celt_band_end[s->p.bandwidth]; - f->channels = s->avctx->channels; + f->channels = s->avctx->ch_layout.nb_channels; f->size = s->p.framesize; for (i = 0; i < (1 << f->size); i++) @@ -327,7 +327,7 @@ static void celt_gauge_psy_weight(OpusPsyContext *s, OpusPsyStep **start, float tonal_contrib = 0.0f; for (f = 0; f < (1 << s->p.framesize); f++) { weight = start[f]->stereo[i]; - for (ch = 0; ch < s->avctx->channels; ch++) { + for (ch = 0; ch < s->avctx->ch_layout.nb_channels; ch++) { weight += start[f]->change_amp[ch][i] + start[f]->tone[ch][i] + start[f]->energy[ch][i]; tonal_contrib += start[f]->tone[ch][i]; } @@ -384,7 +384,7 @@ static void celt_search_for_dual_stereo(OpusPsyContext *s, CeltFrame *f) float td1, td2; f->dual_stereo = 0; - if (s->avctx->channels < 2) + if (s->avctx->ch_layout.nb_channels < 2) return; bands_dist(s, f, &td1); @@ -402,7 +402,7 @@ static void celt_search_for_intensity(OpusPsyContext *s, CeltFrame *f) /* TODO: fix, make some heuristic up here using the lambda value */ float end_band = 0; - if (s->avctx->channels < 2) + if (s->avctx->ch_layout.nb_channels < 2) return; for (i = f->end_band; i >= end_band; i--) { @@ -436,7 +436,7 @@ static int celt_search_for_tf(OpusPsyContext *s, OpusPsyStep **start, CeltFrame float iscore0 = 0.0f; float iscore1 = 0.0f; for (j = 0; j < (1 << f->size); j++) { - for (k = 0; k < s->avctx->channels; k++) { + for (k = 0; k < s->avctx->ch_layout.nb_channels; k++) { iscore0 += start[j]->tone[k][i]*start[j]->change_amp[k][i]/mag[0]; iscore1 += start[j]->tone[k][i]*start[j]->change_amp[k][i]/mag[1]; } @@ -540,7 +540,7 @@ av_cold int ff_opus_psy_init(OpusPsyContext *s, AVCodecContext *avctx, goto fail; } - for (ch = 0; ch < s->avctx->channels; ch++) { + for (ch = 0; ch < s->avctx->ch_layout.nb_channels; ch++) { for (i = 0; i < CELT_MAX_BANDS; i++) { bessel_init(&s->bfilter_hi[ch][i], 1.0f, 19.0f, 100.0f, 1); bessel_init(&s->bfilter_lo[ch][i], 1.0f, 20.0f, 100.0f, 0); diff --git a/libavcodec/packet.h b/libavcodec/packet.h index 4a349fe05..404d52007 100644 --- a/libavcodec/packet.h +++ b/libavcodec/packet.h @@ -28,8 +28,9 @@ #include "libavutil/buffer.h" #include "libavutil/dict.h" #include "libavutil/rational.h" +#include "libavutil/version.h" -#include "libavcodec/version.h" +#include "libavcodec/version_major.h" /** * @defgroup lavc_packet AVPacket @@ -447,8 +448,13 @@ typedef struct AVPacketList { #define AV_PKT_FLAG_DISPOSABLE 0x0010 enum AVSideDataParamChangeFlags { +#if FF_API_OLD_CHANNEL_LAYOUT + /** + * @deprecated those are not used by any decoder + */ AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT = 0x0001, AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT = 0x0002, +#endif AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE = 0x0004, AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS = 0x0008, }; diff --git a/libavcodec/pafaudio.c b/libavcodec/pafaudio.c index 969eb7fa9..9f694d2dc 100644 --- a/libavcodec/pafaudio.c +++ b/libavcodec/pafaudio.c @@ -23,27 +23,28 @@ #include "libavutil/intreadwrite.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "mathops.h" #include "paf.h" static av_cold int paf_audio_init(AVCodecContext *avctx) { - if (avctx->channels != 2) { + if (avctx->ch_layout.nb_channels != 2) { av_log(avctx, AV_LOG_ERROR, "invalid number of channels\n"); return AVERROR_INVALIDDATA; } - avctx->channel_layout = AV_CH_LAYOUT_STEREO; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; avctx->sample_fmt = AV_SAMPLE_FMT_S16; return 0; } -static int paf_audio_decode(AVCodecContext *avctx, void *data, +static int paf_audio_decode(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *pkt) { - AVFrame *frame = data; int16_t *output_samples; const uint8_t *src = pkt->data; int frames, ret, i, j; @@ -72,13 +73,13 @@ static int paf_audio_decode(AVCodecContext *avctx, void *data, return pkt->size; } -const AVCodec ff_paf_audio_decoder = { - .name = "paf_audio", - .long_name = NULL_IF_CONFIG_SMALL("Amazing Studio Packed Animation File Audio"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_PAF_AUDIO, +const FFCodec ff_paf_audio_decoder = { + .p.name = "paf_audio", + .p.long_name = NULL_IF_CONFIG_SMALL("Amazing Studio Packed Animation File Audio"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_PAF_AUDIO, .init = paf_audio_init, - .decode = paf_audio_decode, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(paf_audio_decode), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/pafvideo.c b/libavcodec/pafvideo.c index bb5c17b6a..60cdd34ad 100644 --- a/libavcodec/pafvideo.c +++ b/libavcodec/pafvideo.c @@ -24,6 +24,7 @@ #include "avcodec.h" #include "bytestream.h" #include "copy_block.h" +#include "codec_internal.h" #include "internal.h" @@ -158,7 +159,7 @@ static void set_src_position(PAFVideoDecContext *c, *pend = c->frame[page] + c->frame_size; } -static int decode_0(PAFVideoDecContext *c, uint8_t *pkt, uint8_t code) +static int decode_0(PAFVideoDecContext *c, const uint8_t *pkt, uint8_t code) { uint32_t opcode_size, offset; uint8_t *dst, *dend, mask = 0, color = 0; @@ -267,7 +268,7 @@ static int decode_0(PAFVideoDecContext *c, uint8_t *pkt, uint8_t code) return 0; } -static int paf_video_decode(AVCodecContext *avctx, void *data, +static int paf_video_decode(AVCodecContext *avctx, AVFrame *rframe, int *got_frame, AVPacket *pkt) { PAFVideoDecContext *c = avctx->priv_data; @@ -399,7 +400,7 @@ static int paf_video_decode(AVCodecContext *avctx, void *data, c->width, c->height); c->current_frame = (c->current_frame + 1) & 3; - if ((ret = av_frame_ref(data, c->pic)) < 0) + if ((ret = av_frame_ref(rframe, c->pic)) < 0) return ret; *got_frame = 1; @@ -407,15 +408,15 @@ static int paf_video_decode(AVCodecContext *avctx, void *data, return pkt->size; } -const AVCodec ff_paf_video_decoder = { - .name = "paf_video", - .long_name = NULL_IF_CONFIG_SMALL("Amazing Studio Packed Animation File Video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_PAF_VIDEO, +const FFCodec ff_paf_video_decoder = { + .p.name = "paf_video", + .p.long_name = NULL_IF_CONFIG_SMALL("Amazing Studio Packed Animation File Video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_PAF_VIDEO, .priv_data_size = sizeof(PAFVideoDecContext), .init = paf_video_init, .close = paf_video_close, - .decode = paf_video_decode, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(paf_video_decode), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/pamenc.c b/libavcodec/pamenc.c index d2ceb3355..8a94f8a53 100644 --- a/libavcodec/pamenc.c +++ b/libavcodec/pamenc.c @@ -21,8 +21,8 @@ #include "libavutil/avassert.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" static int pam_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *p, int *got_packet) @@ -127,14 +127,14 @@ static int pam_encode_frame(AVCodecContext *avctx, AVPacket *pkt, return 0; } -const AVCodec ff_pam_encoder = { - .name = "pam", - .long_name = NULL_IF_CONFIG_SMALL("PAM (Portable AnyMap) image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_PAM, - .capabilities = AV_CODEC_CAP_DR1, - .encode2 = pam_encode_frame, - .pix_fmts = (const enum AVPixelFormat[]){ +const FFCodec ff_pam_encoder = { + .p.name = "pam", + .p.long_name = NULL_IF_CONFIG_SMALL("PAM (Portable AnyMap) image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_PAM, + .p.capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_ENCODE_CB(pam_encode_frame), + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, AV_PIX_FMT_RGB48BE, AV_PIX_FMT_RGBA64BE, AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY8A, diff --git a/libavcodec/parser.c b/libavcodec/parser.c index 3b459cc12..49de7e6a5 100644 --- a/libavcodec/parser.c +++ b/libavcodec/parser.c @@ -25,10 +25,8 @@ #include #include "libavutil/avassert.h" -#include "libavutil/internal.h" #include "libavutil/mem.h" -#include "internal.h" #include "parser.h" AVCodecParserContext *av_parser_init(int codec_id) diff --git a/libavcodec/parsers.c b/libavcodec/parsers.c index 6b40c18d8..b59388835 100644 --- a/libavcodec/parsers.c +++ b/libavcodec/parsers.c @@ -60,6 +60,7 @@ extern const AVCodecParser ff_mpegvideo_parser; extern const AVCodecParser ff_opus_parser; extern const AVCodecParser ff_png_parser; extern const AVCodecParser ff_pnm_parser; +extern const AVCodecParser ff_qoi_parser; extern const AVCodecParser ff_rv30_parser; extern const AVCodecParser ff_rv40_parser; extern const AVCodecParser ff_sbc_parser; diff --git a/libavcodec/pcm-bluray.c b/libavcodec/pcm-bluray.c index c2a6e82b1..54338e679 100644 --- a/libavcodec/pcm-bluray.c +++ b/libavcodec/pcm-bluray.c @@ -27,6 +27,7 @@ #include "libavutil/channel_layout.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" /* @@ -54,14 +55,12 @@ static int pcm_bluray_parse_header(AVCodecContext *avctx, const uint8_t *header) { static const uint8_t bits_per_samples[4] = { 0, 16, 20, 24 }; - static const uint32_t channel_layouts[16] = { - 0, AV_CH_LAYOUT_MONO, 0, AV_CH_LAYOUT_STEREO, AV_CH_LAYOUT_SURROUND, - AV_CH_LAYOUT_2_1, AV_CH_LAYOUT_4POINT0, AV_CH_LAYOUT_2_2, - AV_CH_LAYOUT_5POINT0, AV_CH_LAYOUT_5POINT1, AV_CH_LAYOUT_7POINT0, - AV_CH_LAYOUT_7POINT1, 0, 0, 0, 0 - }; - static const uint8_t channels[16] = { - 0, 1, 0, 2, 3, 3, 4, 4, 5, 6, 7, 8, 0, 0, 0, 0 + static const AVChannelLayout channel_layouts[16] = { + { 0 }, AV_CHANNEL_LAYOUT_MONO, { 0 }, + AV_CHANNEL_LAYOUT_STEREO, AV_CHANNEL_LAYOUT_SURROUND, AV_CHANNEL_LAYOUT_2_1, + AV_CHANNEL_LAYOUT_4POINT0, AV_CHANNEL_LAYOUT_2_2, AV_CHANNEL_LAYOUT_5POINT0, + AV_CHANNEL_LAYOUT_5POINT1, AV_CHANNEL_LAYOUT_7POINT0, AV_CHANNEL_LAYOUT_7POINT1, + { 0 }, { 0 }, { 0 }, { 0 }, }; uint8_t channel_layout = header[2] >> 4; @@ -104,29 +103,28 @@ static int pcm_bluray_parse_header(AVCodecContext *avctx, * differ from the actual meaningful number, e.g. mono audio still has two * channels, one being empty. */ - avctx->channel_layout = channel_layouts[channel_layout]; - avctx->channels = channels[channel_layout]; - if (!avctx->channels) { + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = channel_layouts[channel_layout]; + if (!avctx->ch_layout.nb_channels) { av_log(avctx, AV_LOG_ERROR, "reserved channel configuration (%d)\n", channel_layout); return AVERROR_INVALIDDATA; } - avctx->bit_rate = FFALIGN(avctx->channels, 2) * avctx->sample_rate * + avctx->bit_rate = FFALIGN(avctx->ch_layout.nb_channels, 2) * avctx->sample_rate * avctx->bits_per_coded_sample; if (avctx->debug & FF_DEBUG_PICT_INFO) ff_dlog(avctx, "pcm_bluray_parse_header: %d channels, %d bits per sample, %d Hz, %"PRId64" bit/s\n", - avctx->channels, avctx->bits_per_coded_sample, + avctx->ch_layout.nb_channels, avctx->bits_per_coded_sample, avctx->sample_rate, avctx->bit_rate); return 0; } -static int pcm_bluray_decode_frame(AVCodecContext *avctx, void *data, +static int pcm_bluray_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; const uint8_t *src = avpkt->data; int buf_size = avpkt->size; GetByteContext gb; @@ -148,7 +146,7 @@ static int pcm_bluray_decode_frame(AVCodecContext *avctx, void *data, bytestream2_init(&gb, src, buf_size); /* There's always an even number of channels in the source */ - num_source_channels = FFALIGN(avctx->channels, 2); + num_source_channels = FFALIGN(avctx->ch_layout.nb_channels, 2); sample_size = (num_source_channels * (avctx->sample_fmt == AV_SAMPLE_FMT_S16 ? 16 : 24)) >> 3; samples = buf_size / sample_size; @@ -161,7 +159,7 @@ static int pcm_bluray_decode_frame(AVCodecContext *avctx, void *data, dst32 = (int32_t *)frame->data[0]; if (samples) { - switch (avctx->channel_layout) { + switch (avctx->ch_layout.u.mask) { /* cases with same number of source and coded channels */ case AV_CH_LAYOUT_STEREO: case AV_CH_LAYOUT_4POINT0: @@ -189,10 +187,10 @@ static int pcm_bluray_decode_frame(AVCodecContext *avctx, void *data, if (AV_SAMPLE_FMT_S16 == avctx->sample_fmt) { do { #if HAVE_BIGENDIAN - bytestream2_get_buffer(&gb, dst16, avctx->channels * 2); - dst16 += avctx->channels; + bytestream2_get_buffer(&gb, dst16, avctx->ch_layout.nb_channels * 2); + dst16 += avctx->ch_layout.nb_channels; #else - channel = avctx->channels; + channel = avctx->ch_layout.nb_channels; do { *dst16++ = bytestream2_get_be16u(&gb); } while (--channel); @@ -201,7 +199,7 @@ static int pcm_bluray_decode_frame(AVCodecContext *avctx, void *data, } while (--samples); } else { do { - channel = avctx->channels; + channel = avctx->ch_layout.nb_channels; do { *dst32++ = bytestream2_get_be24u(&gb) << 8; } while (--channel); @@ -301,14 +299,14 @@ static int pcm_bluray_decode_frame(AVCodecContext *avctx, void *data, return retval + 4; } -const AVCodec ff_pcm_bluray_decoder = { - .name = "pcm_bluray", - .long_name = NULL_IF_CONFIG_SMALL("PCM signed 16|20|24-bit big-endian for Blu-ray media"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_PCM_BLURAY, - .decode = pcm_bluray_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, - .sample_fmts = (const enum AVSampleFormat[]){ +const FFCodec ff_pcm_bluray_decoder = { + .p.name = "pcm_bluray", + .p.long_name = NULL_IF_CONFIG_SMALL("PCM signed 16|20|24-bit big-endian for Blu-ray media"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_PCM_BLURAY, + FF_CODEC_DECODE_CB(pcm_bluray_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE }, }; diff --git a/libavcodec/pcm-blurayenc.c b/libavcodec/pcm-blurayenc.c new file mode 100644 index 000000000..a139b54fe --- /dev/null +++ b/libavcodec/pcm-blurayenc.c @@ -0,0 +1,315 @@ +/* + * LPCM codecs for PCM formats found in Blu-ray m2ts streams + * + * 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 "avcodec.h" +#include "bytestream.h" +#include "codec_internal.h" +#include "encode.h" +#include "internal.h" + +typedef struct BlurayPCMEncContext { + uint16_t header; // Header added to every frame +} BlurayPCMEncContext; + +static av_cold int pcm_bluray_encode_init(AVCodecContext *avctx) +{ + BlurayPCMEncContext *s = avctx->priv_data; + uint8_t ch_layout; + int quant, freq, frame_size; + + switch (avctx->sample_fmt) { + case AV_SAMPLE_FMT_S16: + avctx->bits_per_coded_sample = 16; + frame_size = 240; + quant = 1; + break; + case AV_SAMPLE_FMT_S32: + frame_size = 360; + avctx->bits_per_coded_sample = 24; + quant = 3; + break; + default: + return AVERROR_BUG; + } + + switch (avctx->sample_rate) { + case 48000: + freq = 1; + break; + case 96000: + freq = 4; + break; + case 192000: + freq = 5; + break; + default: + return AVERROR_BUG; + } + + switch (avctx->ch_layout.u.mask) { + case AV_CH_LAYOUT_MONO: + ch_layout = 1; + break; + case AV_CH_LAYOUT_STEREO: + ch_layout = 3; + break; + case AV_CH_LAYOUT_SURROUND: + ch_layout = 4; + break; + case AV_CH_LAYOUT_2_1: + ch_layout = 5; + break; + case AV_CH_LAYOUT_4POINT0: + ch_layout = 6; + break; + case AV_CH_LAYOUT_2_2: + ch_layout = 7; + break; + case AV_CH_LAYOUT_5POINT0: + ch_layout = 8; + break; + case AV_CH_LAYOUT_5POINT1: + ch_layout = 9; + break; + case AV_CH_LAYOUT_7POINT0: + ch_layout = 10; + break; + case AV_CH_LAYOUT_7POINT1: + ch_layout = 11; + break; + default: + return AVERROR_BUG; + } + + s->header = (((ch_layout << 4) | freq) << 8) | (quant << 6); + avctx->frame_size = frame_size; + + return 0; +} + +static int pcm_bluray_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, + const AVFrame *frame, int *got_packet_ptr) +{ + BlurayPCMEncContext *s = avctx->priv_data; + int sample_size, samples, channel, num_dest_channels; + const int16_t *src16; + const int32_t *src32; + unsigned pkt_size; + PutByteContext pb; + int ret; + + num_dest_channels = FFALIGN(avctx->ch_layout.nb_channels, 2); + sample_size = (num_dest_channels * + (avctx->sample_fmt == AV_SAMPLE_FMT_S16 ? 16 : 24)) >> 3; + samples = frame->nb_samples; + + pkt_size = sample_size * samples + 4; + + if ((ret = ff_get_encode_buffer(avctx, avpkt, pkt_size, 0)) < 0) + return ret; + + AV_WB16(avpkt->data, pkt_size - 4); + AV_WB16(avpkt->data + 2, s->header); + + src16 = (const int16_t *)frame->data[0]; + src32 = (const int32_t *)frame->data[0]; + + bytestream2_init_writer(&pb, avpkt->data + 4, avpkt->size - 4); + + switch (avctx->ch_layout.u.mask) { + /* cases with same number of source and coded channels */ + case AV_CH_LAYOUT_STEREO: + case AV_CH_LAYOUT_4POINT0: + case AV_CH_LAYOUT_2_2: + samples *= num_dest_channels; + if (AV_SAMPLE_FMT_S16 == avctx->sample_fmt) { +#if HAVE_BIGENDIAN + bytestream2_put_bufferu(&pb, frame->data[0], samples * 2); +#else + do { + bytestream2_put_be16u(&pb, *src16++); + } while (--samples); +#endif + } else { + do { + bytestream2_put_be24u(&pb, (*src32++) >> 8); + } while (--samples); + } + break; + /* cases where number of source channels = coded channels + 1 */ + case AV_CH_LAYOUT_MONO: + case AV_CH_LAYOUT_SURROUND: + case AV_CH_LAYOUT_2_1: + case AV_CH_LAYOUT_5POINT0: + if (AV_SAMPLE_FMT_S16 == avctx->sample_fmt) { + do { +#if HAVE_BIGENDIAN + bytestream2_put_bufferu(&pb, (const uint8_t *)src16, avctx->ch_layout.nb_channels * 2); + src16 += avctx->ch_layout.nb_channels; +#else + channel = avctx->ch_layout.nb_channels; + do { + bytestream2_put_be16u(&pb, *src16++); + } while (--channel); +#endif + bytestream2_put_ne16(&pb, 0); + } while (--samples); + } else { + do { + channel = avctx->ch_layout.nb_channels; + do { + bytestream2_put_be24u(&pb, (*src32++) >> 8); + } while (--channel); + bytestream2_put_ne24(&pb, 0); + } while (--samples); + } + break; + /* remapping: L, R, C, LBack, RBack, LF */ + case AV_CH_LAYOUT_5POINT1: + if (AV_SAMPLE_FMT_S16 == avctx->sample_fmt) { + do { + bytestream2_put_be16u(&pb, src16[0]); + bytestream2_put_be16u(&pb, src16[1]); + bytestream2_put_be16u(&pb, src16[2]); + bytestream2_put_be16u(&pb, src16[4]); + bytestream2_put_be16u(&pb, src16[5]); + bytestream2_put_be16u(&pb, src16[3]); + src16 += 6; + } while (--samples); + } else { + do { + bytestream2_put_be24u(&pb, src32[0] >> 8); + bytestream2_put_be24u(&pb, src32[1] >> 8); + bytestream2_put_be24u(&pb, src32[2] >> 8); + bytestream2_put_be24u(&pb, src32[4] >> 8); + bytestream2_put_be24u(&pb, src32[5] >> 8); + bytestream2_put_be24u(&pb, src32[3] >> 8); + src32 += 6; + } while (--samples); + } + break; + /* remapping: L, R, C, LSide, LBack, RBack, RSide, */ + case AV_CH_LAYOUT_7POINT0: + if (AV_SAMPLE_FMT_S16 == avctx->sample_fmt) { + do { + bytestream2_put_be16u(&pb, src16[0]); + bytestream2_put_be16u(&pb, src16[1]); + bytestream2_put_be16u(&pb, src16[2]); + bytestream2_put_be16u(&pb, src16[5]); + bytestream2_put_be16u(&pb, src16[3]); + bytestream2_put_be16u(&pb, src16[4]); + bytestream2_put_be16u(&pb, src16[6]); + src16 += 7; + bytestream2_put_ne16(&pb, 0); + } while (--samples); + } else { + do { + bytestream2_put_be24u(&pb, src32[0] >> 8); + bytestream2_put_be24u(&pb, src32[1] >> 8); + bytestream2_put_be24u(&pb, src32[2] >> 8); + bytestream2_put_be24u(&pb, src32[5] >> 8); + bytestream2_put_be24u(&pb, src32[3] >> 8); + bytestream2_put_be24u(&pb, src32[4] >> 8); + bytestream2_put_be24u(&pb, src32[6] >> 8); + src32 += 7; + bytestream2_put_ne24(&pb, 0); + } while (--samples); + } + break; + /* remapping: L, R, C, LSide, LBack, RBack, RSide, LF */ + case AV_CH_LAYOUT_7POINT1: + if (AV_SAMPLE_FMT_S16 == avctx->sample_fmt) { + do { + bytestream2_put_be16u(&pb, src16[0]); + bytestream2_put_be16u(&pb, src16[1]); + bytestream2_put_be16u(&pb, src16[2]); + bytestream2_put_be16u(&pb, src16[6]); + bytestream2_put_be16u(&pb, src16[4]); + bytestream2_put_be16u(&pb, src16[5]); + bytestream2_put_be16u(&pb, src16[7]); + bytestream2_put_be16u(&pb, src16[3]); + src16 += 8; + } while (--samples); + } else { + do { + bytestream2_put_be24u(&pb, src32[0]); + bytestream2_put_be24u(&pb, src32[1]); + bytestream2_put_be24u(&pb, src32[2]); + bytestream2_put_be24u(&pb, src32[6]); + bytestream2_put_be24u(&pb, src32[4]); + bytestream2_put_be24u(&pb, src32[5]); + bytestream2_put_be24u(&pb, src32[7]); + bytestream2_put_be24u(&pb, src32[3]); + src32 += 8; + } while (--samples); + } + break; + default: + return AVERROR_BUG; + } + + avpkt->pts = frame->pts; + avpkt->duration = ff_samples_to_time_base(avctx, frame->nb_samples); + *got_packet_ptr = 1; + + return 0; +} + +const FFCodec ff_pcm_bluray_encoder = { + .p.name = "pcm_bluray", + .p.long_name = NULL_IF_CONFIG_SMALL("PCM signed 16|20|24-bit big-endian for Blu-ray media"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_PCM_BLURAY, + .priv_data_size = sizeof(BlurayPCMEncContext), + .init = pcm_bluray_encode_init, + FF_CODEC_ENCODE_CB(pcm_bluray_encode_frame), + .p.supported_samplerates = (const int[]) { 48000, 96000, 192000, 0 }, +#if FF_API_OLD_CHANNEL_LAYOUT + .p.channel_layouts = (const uint64_t[]) { + AV_CH_LAYOUT_MONO, + AV_CH_LAYOUT_STEREO, + AV_CH_LAYOUT_SURROUND, + AV_CH_LAYOUT_2_1, + AV_CH_LAYOUT_4POINT0, + AV_CH_LAYOUT_2_2, + AV_CH_LAYOUT_5POINT0, + AV_CH_LAYOUT_5POINT1, + AV_CH_LAYOUT_7POINT0, + AV_CH_LAYOUT_7POINT1, + 0 }, +#endif + .p.ch_layouts = (const AVChannelLayout[]) { + AV_CHANNEL_LAYOUT_MONO, + AV_CHANNEL_LAYOUT_STEREO, + AV_CHANNEL_LAYOUT_SURROUND, + AV_CHANNEL_LAYOUT_2_1, + AV_CHANNEL_LAYOUT_4POINT0, + AV_CHANNEL_LAYOUT_2_2, + AV_CHANNEL_LAYOUT_5POINT0, + AV_CHANNEL_LAYOUT_5POINT1, + AV_CHANNEL_LAYOUT_7POINT0, + AV_CHANNEL_LAYOUT_7POINT1, + { 0 } }, + .p.sample_fmts = (const enum AVSampleFormat[]) { + AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + .p.capabilities = AV_CODEC_CAP_DR1, +}; diff --git a/libavcodec/pcm-dvd.c b/libavcodec/pcm-dvd.c index 775d342ea..57d0ff81d 100644 --- a/libavcodec/pcm-dvd.c +++ b/libavcodec/pcm-dvd.c @@ -26,6 +26,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" typedef struct PCMDVDContext { @@ -55,6 +56,7 @@ static int pcm_dvd_parse_header(AVCodecContext *avctx, const uint8_t *header) static const uint32_t frequencies[4] = { 48000, 96000, 44100, 32000 }; PCMDVDContext *s = avctx->priv_data; int header_int = (header[0] & 0xe0) | (header[1] << 8) | (header[2] << 16); + int channels; /* early exit if the header didn't change apart from the frame number */ if (s->last_header == header_int) @@ -89,9 +91,12 @@ static int pcm_dvd_parse_header(AVCodecContext *avctx, const uint8_t *header) avctx->sample_rate = frequencies[header[1] >> 4 & 3]; /* get the number of channels */ - avctx->channels = 1 + (header[1] & 7); + channels = 1 + (header[1] & 7); + + av_channel_layout_uninit(&avctx->ch_layout); + av_channel_layout_default(&avctx->ch_layout, channels); /* calculate the bitrate */ - avctx->bit_rate = avctx->channels * + avctx->bit_rate = channels * avctx->sample_rate * avctx->bits_per_coded_sample; @@ -100,15 +105,15 @@ static int pcm_dvd_parse_header(AVCodecContext *avctx, const uint8_t *header) * needed to complete a set of samples for each channel. */ if (avctx->bits_per_coded_sample == 16) { s->samples_per_block = 1; - s->block_size = avctx->channels * 2; + s->block_size = channels * 2; } else { - switch (avctx->channels) { + switch (channels) { case 1: case 2: case 4: /* one group has all the samples needed */ s->block_size = 4 * avctx->bits_per_coded_sample / 8; - s->samples_per_block = 4 / avctx->channels; + s->samples_per_block = 4 / channels; s->groups_per_block = 1; break; case 8: @@ -118,11 +123,11 @@ static int pcm_dvd_parse_header(AVCodecContext *avctx, const uint8_t *header) s->groups_per_block = 2; break; default: - /* need avctx->channels groups */ - s->block_size = 4 * avctx->channels * + /* need channels groups */ + s->block_size = 4 * channels * avctx->bits_per_coded_sample / 8; s->samples_per_block = 4; - s->groups_per_block = avctx->channels; + s->groups_per_block = channels; break; } } @@ -130,7 +135,7 @@ static int pcm_dvd_parse_header(AVCodecContext *avctx, const uint8_t *header) if (avctx->debug & FF_DEBUG_PICT_INFO) ff_dlog(avctx, "pcm_dvd_parse_header: %d channels, %d bits per sample, %d Hz, %"PRId64" bit/s\n", - avctx->channels, avctx->bits_per_coded_sample, + avctx->ch_layout.nb_channels, avctx->bits_per_coded_sample, avctx->sample_rate, avctx->bit_rate); s->last_header = header_int; @@ -155,7 +160,7 @@ static void *pcm_dvd_decode_samples(AVCodecContext *avctx, const uint8_t *src, bytestream2_get_buffer(&gb, dst16, blocks * s->block_size); dst16 += blocks * s->block_size / 2; #else - int samples = blocks * avctx->channels; + int samples = blocks * avctx->ch_layout.nb_channels; do { *dst16++ = bytestream2_get_be16u(&gb); } while (--samples); @@ -163,7 +168,7 @@ static void *pcm_dvd_decode_samples(AVCodecContext *avctx, const uint8_t *src, return dst16; } case 20: - if (avctx->channels == 1) { + if (avctx->ch_layout.nb_channels == 1) { do { for (i = 2; i; i--) { dst32[0] = bytestream2_get_be16u(&gb) << 16; @@ -191,7 +196,7 @@ static void *pcm_dvd_decode_samples(AVCodecContext *avctx, const uint8_t *src, } return dst32; case 24: - if (avctx->channels == 1) { + if (avctx->ch_layout.nb_channels == 1) { do { for (i = 2; i; i--) { dst32[0] = bytestream2_get_be16u(&gb) << 16; @@ -220,10 +225,9 @@ static void *pcm_dvd_decode_samples(AVCodecContext *avctx, const uint8_t *src, } } -static int pcm_dvd_decode_frame(AVCodecContext *avctx, void *data, +static int pcm_dvd_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; const uint8_t *src = avpkt->data; int buf_size = avpkt->size; PCMDVDContext *s = avctx->priv_data; @@ -291,17 +295,17 @@ static int pcm_dvd_decode_frame(AVCodecContext *avctx, void *data, return avpkt->size; } -const AVCodec ff_pcm_dvd_decoder = { - .name = "pcm_dvd", - .long_name = NULL_IF_CONFIG_SMALL("PCM signed 16|20|24-bit big-endian for DVD media"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_PCM_DVD, +const FFCodec ff_pcm_dvd_decoder = { + .p.name = "pcm_dvd", + .p.long_name = NULL_IF_CONFIG_SMALL("PCM signed 16|20|24-bit big-endian for DVD media"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_PCM_DVD, .priv_data_size = sizeof(PCMDVDContext), .init = pcm_dvd_decode_init, - .decode = pcm_dvd_decode_frame, - .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + FF_CODEC_DECODE_CB(pcm_dvd_decode_frame), + .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1, - .sample_fmts = (const enum AVSampleFormat[]) { + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, diff --git a/libavcodec/pcm-dvdenc.c b/libavcodec/pcm-dvdenc.c index c9afac69d..0881697c1 100644 --- a/libavcodec/pcm-dvdenc.c +++ b/libavcodec/pcm-dvdenc.c @@ -22,6 +22,7 @@ #include "libavutil/channel_layout.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "encode.h" #include "internal.h" @@ -30,8 +31,6 @@ typedef struct PCMDVDContext { int block_size; // Size of a block of samples in bytes int samples_per_block; // Number of samples per channel per block int groups_per_block; // Number of 20/24-bit sample groups per block - uint8_t *extra_samples; // Pointer to leftover samples from a frame - int extra_sample_count; // Number of leftover samples in the buffer } PCMDVDContext; static av_cold int pcm_dvd_encode_init(AVCodecContext *avctx) @@ -46,6 +45,8 @@ static av_cold int pcm_dvd_encode_init(AVCodecContext *avctx) case 96000: freq = 1; break; + default: + av_assert1(0); } switch (avctx->sample_fmt) { @@ -57,10 +58,12 @@ static av_cold int pcm_dvd_encode_init(AVCodecContext *avctx) avctx->bits_per_coded_sample = 24; quant = 2; break; + default: + av_assert1(0); } avctx->bits_per_coded_sample = 16 + quant * 4; - avctx->block_align = avctx->channels * avctx->bits_per_coded_sample / 8; + avctx->block_align = avctx->ch_layout.nb_channels * avctx->bits_per_coded_sample / 8; avctx->bit_rate = avctx->block_align * 8LL * avctx->sample_rate; if (avctx->bit_rate > 9800000) { av_log(avctx, AV_LOG_ERROR, "Too big bitrate: reduce sample rate, bitdepth or channels.\n"); @@ -69,16 +72,16 @@ static av_cold int pcm_dvd_encode_init(AVCodecContext *avctx) if (avctx->sample_fmt == AV_SAMPLE_FMT_S16) { s->samples_per_block = 1; - s->block_size = avctx->channels * 2; + s->block_size = avctx->ch_layout.nb_channels * 2; frame_size = 2008 / s->block_size; } else { - switch (avctx->channels) { + switch (avctx->ch_layout.nb_channels) { case 1: case 2: case 4: /* one group has all the samples needed */ s->block_size = 4 * avctx->bits_per_coded_sample / 8; - s->samples_per_block = 4 / avctx->channels; + s->samples_per_block = 4 / avctx->ch_layout.nb_channels; s->groups_per_block = 1; break; case 8: @@ -88,11 +91,11 @@ static av_cold int pcm_dvd_encode_init(AVCodecContext *avctx) s->groups_per_block = 2; break; default: - /* need avctx->channels groups */ - s->block_size = 4 * avctx->channels * + /* need avctx->ch_layout.nb_channels groups */ + s->block_size = 4 * avctx->ch_layout.nb_channels * avctx->bits_per_coded_sample / 8; s->samples_per_block = 4; - s->groups_per_block = avctx->channels; + s->groups_per_block = avctx->ch_layout.nb_channels; break; } @@ -100,7 +103,7 @@ static av_cold int pcm_dvd_encode_init(AVCodecContext *avctx) } s->header[0] = 0x0c; - s->header[1] = (quant << 6) | (freq << 4) | (avctx->channels - 1); + s->header[1] = (quant << 6) | (freq << 4) | (avctx->ch_layout.nb_channels - 1); s->header[2] = 0x80; if (!avctx->frame_size) @@ -113,7 +116,7 @@ static int pcm_dvd_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet_ptr) { PCMDVDContext *s = avctx->priv_data; - int samples = frame->nb_samples * avctx->channels; + int samples = frame->nb_samples * avctx->ch_layout.nb_channels; int64_t pkt_size = (frame->nb_samples / s->samples_per_block) * s->block_size + 3; int blocks = (pkt_size - 3) / s->block_size; const int16_t *src16; @@ -138,13 +141,13 @@ static int pcm_dvd_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, } while (--samples); break; case AV_SAMPLE_FMT_S32: - if (avctx->channels == 1) { + if (avctx->ch_layout.nb_channels == 1) { do { for (int i = 2; i; i--) { bytestream2_put_be16(&pb, src32[0] >> 16); bytestream2_put_be16(&pb, src32[1] >> 16); - bytestream2_put_byte(&pb, (*src32++) >> 24); - bytestream2_put_byte(&pb, (*src32++) >> 24); + bytestream2_put_byte(&pb, (uint8_t)((*src32++) >> 8)); + bytestream2_put_byte(&pb, (uint8_t)((*src32++) >> 8)); } } while (--blocks); } else { @@ -154,10 +157,10 @@ static int pcm_dvd_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, bytestream2_put_be16(&pb, src32[1] >> 16); bytestream2_put_be16(&pb, src32[2] >> 16); bytestream2_put_be16(&pb, src32[3] >> 16); - bytestream2_put_byte(&pb, (*src32++) >> 24); - bytestream2_put_byte(&pb, (*src32++) >> 24); - bytestream2_put_byte(&pb, (*src32++) >> 24); - bytestream2_put_byte(&pb, (*src32++) >> 24); + bytestream2_put_byte(&pb, (uint8_t)((*src32++) >> 8)); + bytestream2_put_byte(&pb, (uint8_t)((*src32++) >> 8)); + bytestream2_put_byte(&pb, (uint8_t)((*src32++) >> 8)); + bytestream2_put_byte(&pb, (uint8_t)((*src32++) >> 8)); } } while (--blocks); } @@ -171,22 +174,29 @@ static int pcm_dvd_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, return 0; } -const AVCodec ff_pcm_dvd_encoder = { - .name = "pcm_dvd", - .long_name = NULL_IF_CONFIG_SMALL("PCM signed 16|20|24-bit big-endian for DVD media"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_PCM_DVD, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME, +const FFCodec ff_pcm_dvd_encoder = { + .p.name = "pcm_dvd", + .p.long_name = NULL_IF_CONFIG_SMALL("PCM signed 16|20|24-bit big-endian for DVD media"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_PCM_DVD, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME, .priv_data_size = sizeof(PCMDVDContext), .init = pcm_dvd_encode_init, - .encode2 = pcm_dvd_encode_frame, - .supported_samplerates = (const int[]) { 48000, 96000, 0}, - .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO, + FF_CODEC_ENCODE_CB(pcm_dvd_encode_frame), + .p.supported_samplerates = (const int[]) { 48000, 96000, 0}, +#if FF_API_OLD_CHANNEL_LAYOUT + .p.channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO, AV_CH_LAYOUT_STEREO, AV_CH_LAYOUT_5POINT1, AV_CH_LAYOUT_7POINT1, 0 }, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, +#endif + .p.ch_layouts = (const AVChannelLayout[]) { AV_CHANNEL_LAYOUT_MONO, + AV_CHANNEL_LAYOUT_STEREO, + AV_CHANNEL_LAYOUT_5POINT1, + AV_CHANNEL_LAYOUT_7POINT1, + { 0 } }, + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, diff --git a/libavcodec/pcm.c b/libavcodec/pcm.c index e9b8eab48..471075ad7 100644 --- a/libavcodec/pcm.c +++ b/libavcodec/pcm.c @@ -25,11 +25,14 @@ */ #include "config.h" +#include "config_components.h" #include "libavutil/attributes.h" #include "libavutil/float_dsp.h" +#include "libavutil/reverse.h" #include "libavutil/thread.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "encode.h" #include "internal.h" #include "mathops.h" @@ -56,7 +59,7 @@ static av_cold int pcm_encode_init(AVCodecContext *avctx) #endif avctx->bits_per_coded_sample = av_get_bits_per_sample(avctx->codec->id); - avctx->block_align = avctx->channels * avctx->bits_per_coded_sample / 8; + avctx->block_align = avctx->ch_layout.nb_channels * avctx->bits_per_coded_sample / 8; avctx->bit_rate = avctx->block_align * 8LL * avctx->sample_rate; return 0; @@ -80,8 +83,8 @@ static av_cold int pcm_encode_init(AVCodecContext *avctx) } #define ENCODE_PLANAR(type, endian, dst, n, shift, offset) \ - n /= avctx->channels; \ - for (c = 0; c < avctx->channels; c++) { \ + n /= avctx->ch_layout.nb_channels; \ + for (c = 0; c < avctx->ch_layout.nb_channels; c++) { \ int i; \ samples_ ## type = (const type *) frame->extended_data[c]; \ for (i = n; i > 0; i--) { \ @@ -104,7 +107,7 @@ static int pcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, const uint32_t *samples_uint32_t; sample_size = av_get_bits_per_sample(avctx->codec->id) / 8; - n = frame->nb_samples * avctx->channels; + n = frame->nb_samples * avctx->ch_layout.nb_channels; samples = (const short *)frame->data[0]; if ((ret = ff_get_encode_buffer(avctx, avpkt, n * sample_size, 0)) < 0) @@ -207,8 +210,8 @@ static int pcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, case AV_CODEC_ID_PCM_S16LE_PLANAR: case AV_CODEC_ID_PCM_S32LE_PLANAR: #endif /* HAVE_BIGENDIAN */ - n /= avctx->channels; - for (c = 0; c < avctx->channels; c++) { + n /= avctx->ch_layout.nb_channels; + for (c = 0; c < avctx->ch_layout.nb_channels; c++) { const uint8_t *src = frame->extended_data[c]; bytestream_put_buffer(&dst, src, n * sample_size); } @@ -252,7 +255,7 @@ static av_cold int pcm_decode_init(AVCodecContext *avctx) AVFloatDSPContext *fdsp; int i; - if (avctx->channels <= 0) { + if (avctx->ch_layout.nb_channels <= 0) { av_log(avctx, AV_LOG_ERROR, "PCM channels out of bounds\n"); return AVERROR(EINVAL); } @@ -312,8 +315,8 @@ static av_cold int pcm_decode_init(AVCodecContext *avctx) } #define DECODE_PLANAR(size, endian, src, dst, n, shift, offset) \ - n /= avctx->channels; \ - for (c = 0; c < avctx->channels; c++) { \ + n /= channels; \ + for (c = 0; c < avctx->ch_layout.nb_channels; c++) { \ int i; \ dst = frame->extended_data[c]; \ for (i = n; i > 0; i--) { \ @@ -323,13 +326,13 @@ static av_cold int pcm_decode_init(AVCodecContext *avctx) } \ } -static int pcm_decode_frame(AVCodecContext *avctx, void *data, - int *got_frame_ptr, AVPacket *avpkt) +static int pcm_decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame_ptr, AVPacket *avpkt) { const uint8_t *src = avpkt->data; int buf_size = avpkt->size; PCMDecode *s = avctx->priv_data; - AVFrame *frame = data; + int channels = avctx->ch_layout.nb_channels; int sample_size, c, n, ret, samples_per_block; uint8_t *samples; int32_t *dst_int32_t; @@ -349,7 +352,7 @@ static int pcm_decode_frame(AVCodecContext *avctx, void *data, return AVERROR(EINVAL); } - if (avctx->channels == 0) { + if (channels == 0) { av_log(avctx, AV_LOG_ERROR, "Invalid number of channels\n"); return AVERROR(EINVAL); } @@ -359,7 +362,7 @@ static int pcm_decode_frame(AVCodecContext *avctx, void *data, return AVERROR(EINVAL); } - n = avctx->channels * sample_size; + n = channels * sample_size; if (n && buf_size % n) { if (buf_size < n) { @@ -374,7 +377,7 @@ static int pcm_decode_frame(AVCodecContext *avctx, void *data, n = buf_size / sample_size; /* get output buffer */ - frame->nb_samples = n * samples_per_block / avctx->channels; + frame->nb_samples = n * samples_per_block / channels; if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; samples = frame->data[0]; @@ -429,8 +432,8 @@ static int pcm_decode_frame(AVCodecContext *avctx, void *data, } break; case AV_CODEC_ID_PCM_S8_PLANAR: - n /= avctx->channels; - for (c = 0; c < avctx->channels; c++) { + n /= avctx->ch_layout.nb_channels; + for (c = 0; c < avctx->ch_layout.nb_channels; c++) { int i; samples = frame->extended_data[c]; for (i = n; i > 0; i--) @@ -494,8 +497,8 @@ static int pcm_decode_frame(AVCodecContext *avctx, void *data, case AV_CODEC_ID_PCM_S16LE_PLANAR: case AV_CODEC_ID_PCM_S32LE_PLANAR: #endif /* HAVE_BIGENDIAN */ - n /= avctx->channels; - for (c = 0; c < avctx->channels; c++) { + n /= avctx->ch_layout.nb_channels; + for (c = 0; c < avctx->ch_layout.nb_channels; c++) { samples = frame->extended_data[c]; bytestream_get_buffer(&src, samples, n * sample_size); } @@ -511,8 +514,8 @@ static int pcm_decode_frame(AVCodecContext *avctx, void *data, case AV_CODEC_ID_PCM_LXF: { int i; - n /= avctx->channels; - for (c = 0; c < avctx->channels; c++) { + n /= channels; + for (c = 0; c < channels; c++) { dst_int32_t = (int32_t *)frame->extended_data[c]; for (i = 0; i < n; i++) { // extract low 20 bits and expand to 32 bits @@ -540,7 +543,7 @@ static int pcm_decode_frame(AVCodecContext *avctx, void *data, avctx->codec_id == AV_CODEC_ID_PCM_F24LE) { s->vector_fmul_scalar((float *)frame->extended_data[0], (const float *)frame->extended_data[0], - s->scale, FFALIGN(frame->nb_samples * avctx->channels, 4)); + s->scale, FFALIGN(frame->nb_samples * avctx->ch_layout.nb_channels, 4)); emms_c(); } @@ -551,15 +554,15 @@ static int pcm_decode_frame(AVCodecContext *avctx, void *data, #define PCM_ENCODER_0(id_, sample_fmt_, name_, long_name_) #define PCM_ENCODER_1(id_, sample_fmt_, name_, long_name_) \ -const AVCodec ff_ ## name_ ## _encoder = { \ - .name = #name_, \ - .long_name = NULL_IF_CONFIG_SMALL(long_name_), \ - .type = AVMEDIA_TYPE_AUDIO, \ - .id = AV_CODEC_ID_ ## id_, \ - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_VARIABLE_FRAME_SIZE, \ +const FFCodec ff_ ## name_ ## _encoder = { \ + .p.name = #name_, \ + .p.long_name = NULL_IF_CONFIG_SMALL(long_name_), \ + .p.type = AVMEDIA_TYPE_AUDIO, \ + .p.id = AV_CODEC_ID_ ## id_, \ + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_VARIABLE_FRAME_SIZE, \ .init = pcm_encode_init, \ - .encode2 = pcm_encode_frame, \ - .sample_fmts = (const enum AVSampleFormat[]){ sample_fmt_, \ + FF_CODEC_ENCODE_CB(pcm_encode_frame), \ + .p.sample_fmts = (const enum AVSampleFormat[]){ sample_fmt_, \ AV_SAMPLE_FMT_NONE }, \ .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, \ } @@ -573,16 +576,16 @@ const AVCodec ff_ ## name_ ## _encoder = { \ #define PCM_DECODER_0(id, sample_fmt, name, long_name) #define PCM_DECODER_1(id_, sample_fmt_, name_, long_name_) \ -const AVCodec ff_ ## name_ ## _decoder = { \ - .name = #name_, \ - .long_name = NULL_IF_CONFIG_SMALL(long_name_), \ - .type = AVMEDIA_TYPE_AUDIO, \ - .id = AV_CODEC_ID_ ## id_, \ +const FFCodec ff_ ## name_ ## _decoder = { \ + .p.name = #name_, \ + .p.long_name = NULL_IF_CONFIG_SMALL(long_name_), \ + .p.type = AVMEDIA_TYPE_AUDIO, \ + .p.id = AV_CODEC_ID_ ## id_, \ .priv_data_size = sizeof(PCMDecode), \ .init = pcm_decode_init, \ - .decode = pcm_decode_frame, \ - .capabilities = AV_CODEC_CAP_DR1, \ - .sample_fmts = (const enum AVSampleFormat[]){ sample_fmt_, \ + FF_CODEC_DECODE_CB(pcm_decode_frame), \ + .p.capabilities = AV_CODEC_CAP_DR1, \ + .p.sample_fmts = (const enum AVSampleFormat[]){ sample_fmt_, \ AV_SAMPLE_FMT_NONE }, \ .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, \ } diff --git a/libavcodec/pcm_rechunk_bsf.c b/libavcodec/pcm_rechunk_bsf.c index 7cf763359..108d9e90b 100644 --- a/libavcodec/pcm_rechunk_bsf.c +++ b/libavcodec/pcm_rechunk_bsf.c @@ -42,11 +42,12 @@ static int init(AVBSFContext *ctx) AVRational sr = av_make_q(ctx->par_in->sample_rate, 1); int64_t min_samples; - if (ctx->par_in->channels <= 0 || ctx->par_in->sample_rate <= 0) + if (ctx->par_in->ch_layout.nb_channels <= 0 || ctx->par_in->sample_rate <= 0) return AVERROR(EINVAL); ctx->time_base_out = av_inv_q(sr); - s->sample_size = ctx->par_in->channels * av_get_bits_per_sample(ctx->par_in->codec_id) / 8; + s->sample_size = ctx->par_in->ch_layout.nb_channels * + av_get_bits_per_sample(ctx->par_in->codec_id) / 8; if (s->frame_rate.num) { min_samples = av_rescale_q_rnd(1, sr, s->frame_rate, AV_ROUND_DOWN); @@ -208,13 +209,13 @@ static const enum AVCodecID codec_ids[] = { AV_CODEC_ID_NONE, }; -const AVBitStreamFilter ff_pcm_rechunk_bsf = { - .name = "pcm_rechunk", +const FFBitStreamFilter ff_pcm_rechunk_bsf = { + .p.name = "pcm_rechunk", + .p.codec_ids = codec_ids, + .p.priv_class = &pcm_rechunk_class, .priv_data_size = sizeof(PCMContext), - .priv_class = &pcm_rechunk_class, .filter = rechunk_filter, .init = init, .flush = flush, .close = uninit, - .codec_ids = codec_ids, }; diff --git a/libavcodec/pcx.c b/libavcodec/pcx.c index b8d911be6..b21bdce5c 100644 --- a/libavcodec/pcx.c +++ b/libavcodec/pcx.c @@ -25,6 +25,7 @@ #include "libavutil/imgutils.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" @@ -69,11 +70,10 @@ static void pcx_palette(GetByteContext *gb, uint32_t *dst, int pallen) memset(dst, 0, (256 - pallen) * sizeof(*dst)); } -static int pcx_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int pcx_decode_frame(AVCodecContext *avctx, AVFrame *p, + int *got_frame, AVPacket *avpkt) { GetByteContext gb; - AVFrame * const p = data; int compressed, xmin, ymin, xmax, ymax; int ret; unsigned int w, h, bits_per_pixel, bytes_per_line, nplanes, stride, y, x, @@ -249,11 +249,11 @@ end: return ret; } -const AVCodec ff_pcx_decoder = { - .name = "pcx", - .long_name = NULL_IF_CONFIG_SMALL("PC Paintbrush PCX image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_PCX, - .decode = pcx_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, +const FFCodec ff_pcx_decoder = { + .p.name = "pcx", + .p.long_name = NULL_IF_CONFIG_SMALL("PC Paintbrush PCX image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_PCX, + FF_CODEC_DECODE_CB(pcx_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, }; diff --git a/libavcodec/pcxenc.c b/libavcodec/pcxenc.c index 27ebc1b2f..e6eb387f0 100644 --- a/libavcodec/pcxenc.c +++ b/libavcodec/pcxenc.c @@ -29,8 +29,8 @@ #include "avcodec.h" #include "bytestream.h" #include "libavutil/imgutils.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" static const uint32_t monoblack_pal[16] = { 0x000000, 0xFFFFFF }; @@ -192,13 +192,13 @@ static int pcx_encode_frame(AVCodecContext *avctx, AVPacket *pkt, return 0; } -const AVCodec ff_pcx_encoder = { - .name = "pcx", - .long_name = NULL_IF_CONFIG_SMALL("PC Paintbrush PCX image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_PCX, - .encode2 = pcx_encode_frame, - .pix_fmts = (const enum AVPixelFormat[]){ +const FFCodec ff_pcx_encoder = { + .p.name = "pcx", + .p.long_name = NULL_IF_CONFIG_SMALL("PC Paintbrush PCX image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_PCX, + FF_CODEC_ENCODE_CB(pcx_encode_frame), + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_RGB24, AV_PIX_FMT_RGB8, AV_PIX_FMT_BGR8, AV_PIX_FMT_RGB4_BYTE, AV_PIX_FMT_BGR4_BYTE, AV_PIX_FMT_GRAY8, AV_PIX_FMT_PAL8, diff --git a/libavcodec/pgs_frame_merge_bsf.c b/libavcodec/pgs_frame_merge_bsf.c new file mode 100644 index 000000000..bcd894533 --- /dev/null +++ b/libavcodec/pgs_frame_merge_bsf.c @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2020 John Stebbins + * + * 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 + * This bitstream filter merges PGS subtitle packets containing incomplete + * set of segments into a single packet + * + * Packets already containing a complete set of segments will be passed through + * unchanged. + */ + +#include "libavutil/attributes.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/log.h" +#include "bsf.h" +#include "bsf_internal.h" + +enum PGSSegmentType { + PALETTE_SEGMENT = 0x14, + OBJECT_SEGMENT = 0x15, + PRESENTATION_SEGMENT = 0x16, + WINDOW_SEGMENT = 0x17, + END_DISPLAY_SET_SEGMENT = 0x80, +}; + +typedef struct PGSMergeContext { + AVPacket *buffer_pkt, *in; + int presentation_found; + int pkt_flags; +} PGSMergeContext; + +static av_cold void frame_merge_flush(AVBSFContext *bsf) +{ + PGSMergeContext *ctx = bsf->priv_data; + + ctx->presentation_found = ctx->pkt_flags = 0; + av_packet_unref(ctx->in); + av_packet_unref(ctx->buffer_pkt); +} + +static int frame_merge_output(PGSMergeContext *ctx, AVPacket *dst, AVPacket *src) +{ + if (!ctx->presentation_found) + ctx->pkt_flags |= AV_PKT_FLAG_CORRUPT; + ctx->presentation_found = 0; + src->flags |= ctx->pkt_flags; + ctx->pkt_flags = 0; + av_packet_move_ref(dst, src); + return 0; +} + +static int frame_merge_filter(AVBSFContext *bsf, AVPacket *out) +{ + PGSMergeContext *ctx = bsf->priv_data; + AVPacket *in = ctx->in, *pkt = ctx->buffer_pkt; + int ret, size, pos, display = 0, presentation = 0; + unsigned int i; + + if (!in->data) { + ret = ff_bsf_get_packet_ref(bsf, in); + if (ret == AVERROR_EOF && pkt->data) { + // Output remaining data + ctx->pkt_flags |= AV_PKT_FLAG_CORRUPT; + return frame_merge_output(ctx, out, pkt); + } + if (ret < 0) + return ret; + } + if (!in->size) { + av_packet_unref(in); + return AVERROR(EAGAIN); + } + in->flags &= ~AV_PKT_FLAG_KEY; // Will be detected in the stream + + // Validate packet data and find display_end segment + size = in->size; + i = 0; + while (i + 3 <= in->size) { + uint8_t segment_type = in->data[i]; + int segment_len = AV_RB16(in->data + i + 1) + 3; + + if (i + segment_len > in->size) + break; // Invalid, segments can't span packets + if (segment_type == PRESENTATION_SEGMENT && ctx->presentation_found) + break; // Invalid, there can be only one + if (segment_type == PRESENTATION_SEGMENT) { + uint8_t state; + if (segment_len < 11) + break; // Invalid presentation segment length + ctx->presentation_found = presentation = 1; + state = in->data[i + 10] & 0xc0; + if (state) + ctx->pkt_flags |= AV_PKT_FLAG_KEY; + else + ctx->pkt_flags &= ~AV_PKT_FLAG_KEY; + } + i += segment_len; + if (segment_type == END_DISPLAY_SET_SEGMENT) { + size = i; + display = 1; + break; + } + } + if (display && pkt->size == 0 && size == in->size) // passthrough + return frame_merge_output(ctx, out, in); + if (!display && i != in->size) { + av_log(bsf, AV_LOG_WARNING, "Failed to parse PGS segments.\n"); + // force output what we have + size = in->size; + display = 1; + ctx->pkt_flags |= AV_PKT_FLAG_CORRUPT; + } + + if (presentation) { + ret = av_packet_copy_props(pkt, in); + if (ret < 0) + goto fail; + } + pos = pkt->size; + ret = av_grow_packet(pkt, size); + if (ret < 0) + goto fail; + memcpy(pkt->data + pos, in->data, size); + + if (size == in->size) + av_packet_unref(in); + else { + in->data += size; + in->size -= size; + } + + if (display) + return frame_merge_output(ctx, out, pkt); + return AVERROR(EAGAIN); + +fail: + frame_merge_flush(bsf); + return ret; +} + +static av_cold int frame_merge_init(AVBSFContext *bsf) +{ + PGSMergeContext *ctx = bsf->priv_data; + + ctx->in = av_packet_alloc(); + ctx->buffer_pkt = av_packet_alloc(); + if (!ctx->in || !ctx->buffer_pkt) + return AVERROR(ENOMEM); + + return 0; +} + +static av_cold void frame_merge_close(AVBSFContext *bsf) +{ + PGSMergeContext *ctx = bsf->priv_data; + + av_packet_free(&ctx->in); + av_packet_free(&ctx->buffer_pkt); +} + +static const enum AVCodecID frame_merge_codec_ids[] = { + AV_CODEC_ID_HDMV_PGS_SUBTITLE, AV_CODEC_ID_NONE, +}; + +const FFBitStreamFilter ff_pgs_frame_merge_bsf = { + .p.name = "pgs_frame_merge", + .p.codec_ids = frame_merge_codec_ids, + .priv_data_size = sizeof(PGSMergeContext), + .init = frame_merge_init, + .flush = frame_merge_flush, + .close = frame_merge_close, + .filter = frame_merge_filter, +}; diff --git a/libavcodec/pgssubdec.c b/libavcodec/pgssubdec.c index bdd20c914..e50c6766c 100644 --- a/libavcodec/pgssubdec.c +++ b/libavcodec/pgssubdec.c @@ -26,6 +26,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" #include "mathops.h" @@ -493,10 +494,9 @@ static int parse_presentation_segment(AVCodecContext *avctx, * @param buf pointer to the packet to process * @param buf_size size of packet to process */ -static int display_end_segment(AVCodecContext *avctx, void *data, +static int display_end_segment(AVCodecContext *avctx, AVSubtitle *sub, const uint8_t *buf, int buf_size) { - AVSubtitle *sub = data; PGSSubContext *ctx = avctx->priv_data; int64_t pts; PGSSubPalette *palette; @@ -589,8 +589,8 @@ static int display_end_segment(AVCodecContext *avctx, void *data, return 1; } -static int decode(AVCodecContext *avctx, void *data, int *got_sub_ptr, - AVPacket *avpkt) +static int decode(AVCodecContext *avctx, AVSubtitle *sub, + int *got_sub_ptr, const AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; @@ -638,7 +638,7 @@ static int decode(AVCodecContext *avctx, void *data, int *got_sub_ptr, ret = parse_object_segment(avctx, buf, segment_length); break; case PRESENTATION_SEGMENT: - ret = parse_presentation_segment(avctx, buf, segment_length, ((AVSubtitle*)(data))->pts); + ret = parse_presentation_segment(avctx, buf, segment_length, sub->pts); break; case WINDOW_SEGMENT: /* @@ -656,7 +656,7 @@ static int decode(AVCodecContext *avctx, void *data, int *got_sub_ptr, ret = AVERROR_INVALIDDATA; break; } - ret = display_end_segment(avctx, data, buf, segment_length); + ret = display_end_segment(avctx, sub, buf, segment_length); if (ret >= 0) *got_sub_ptr = ret; break; @@ -690,15 +690,15 @@ static const AVClass pgsdec_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_pgssub_decoder = { - .name = "pgssub", - .long_name = NULL_IF_CONFIG_SMALL("HDMV Presentation Graphic Stream subtitles"), - .type = AVMEDIA_TYPE_SUBTITLE, - .id = AV_CODEC_ID_HDMV_PGS_SUBTITLE, +const FFCodec ff_pgssub_decoder = { + .p.name = "pgssub", + .p.long_name = NULL_IF_CONFIG_SMALL("HDMV Presentation Graphic Stream subtitles"), + .p.type = AVMEDIA_TYPE_SUBTITLE, + .p.id = AV_CODEC_ID_HDMV_PGS_SUBTITLE, .priv_data_size = sizeof(PGSSubContext), .init = init_decoder, .close = close_decoder, - .decode = decode, - .priv_class = &pgsdec_class, + FF_CODEC_DECODE_SUB_CB(decode), + .p.priv_class = &pgsdec_class, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/pgxdec.c b/libavcodec/pgxdec.c index 1d659e82c..52e2c2a36 100644 --- a/libavcodec/pgxdec.c +++ b/libavcodec/pgxdec.c @@ -22,6 +22,7 @@ #include "avcodec.h" #include "internal.h" #include "bytestream.h" +#include "codec_internal.h" #include "libavutil/imgutils.h" static int pgx_get_number(AVCodecContext *avctx, GetByteContext *g, int *number) { @@ -31,9 +32,9 @@ static int pgx_get_number(AVCodecContext *avctx, GetByteContext *g, int *number) *number = 0; while (1) { uint64_t temp; - if (!bytestream2_get_bytes_left(g)) + if (bytestream2_get_bytes_left(g) <= 0) return AVERROR_INVALIDDATA; - digit = bytestream2_get_byte(g); + digit = bytestream2_get_byteu(g); if (digit == ' ' || digit == 0xA || digit == 0xD) break; else if (digit < '0' || digit > '9') @@ -55,28 +56,24 @@ static int pgx_decode_header(AVCodecContext *avctx, GetByteContext *g, { int byte; - if (bytestream2_get_bytes_left(g) < 6) { + if (bytestream2_get_bytes_left(g) < 12) return AVERROR_INVALIDDATA; - } - bytestream2_skip(g, 6); + bytestream2_skipu(g, 6); // Is the component signed? - byte = bytestream2_peek_byte(g); + byte = bytestream2_peek_byteu(g); if (byte == '+') { *sign = 0; - bytestream2_skip(g, 1); + bytestream2_skipu(g, 1); } else if (byte == '-') { *sign = 1; - bytestream2_skip(g, 1); - } else if (byte == 0) - goto error; + bytestream2_skipu(g, 1); + } - byte = bytestream2_peek_byte(g); + byte = bytestream2_peek_byteu(g); if (byte == ' ') - bytestream2_skip(g, 1); - else if (byte == 0) - goto error; + bytestream2_skipu(g, 1); if (pgx_get_number(avctx, g, depth)) goto error; @@ -98,28 +95,24 @@ error: static inline void write_frame_ ##D(AVFrame *frame, GetByteContext *g, \ int width, int height, int sign, int depth) \ { \ + const unsigned offset = sign ? (1 << (D - 1)) : 0; \ int i, j; \ for (i = 0; i < height; i++) { \ - PIXEL *line = (PIXEL*)frame->data[0] + i*frame->linesize[0]/sizeof(PIXEL); \ + PIXEL *line = (PIXEL*)(frame->data[0] + i * frame->linesize[0]); \ for (j = 0; j < width; j++) { \ - unsigned val; \ - if (sign) \ - val = (PIXEL)bytestream2_get_ ##suffix(g) + (1 << (depth - 1)); \ - else \ - val = bytestream2_get_ ##suffix(g); \ - val <<= (D - depth); \ + unsigned val = bytestream2_get_ ##suffix##u(g) << (D - depth); \ + val ^= offset; \ *(line + j) = val; \ } \ } \ } \ -WRITE_FRAME(8, int8_t, byte) -WRITE_FRAME(16, int16_t, be16) +WRITE_FRAME(8, uint8_t, byte) +WRITE_FRAME(16, uint16_t, be16) -static int pgx_decode_frame(AVCodecContext *avctx, void *data, +static int pgx_decode_frame(AVCodecContext *avctx, AVFrame *p, int *got_frame, AVPacket *avpkt) { - AVFrame *p = data; int ret; int bpp; int width, height, depth; @@ -158,11 +151,11 @@ static int pgx_decode_frame(AVCodecContext *avctx, void *data, return 0; } -const AVCodec ff_pgx_decoder = { - .name = "pgx", - .long_name = NULL_IF_CONFIG_SMALL("PGX (JPEG2000 Test Format)"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_PGX, - .decode = pgx_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, +const FFCodec ff_pgx_decoder = { + .p.name = "pgx", + .p.long_name = NULL_IF_CONFIG_SMALL("PGX (JPEG2000 Test Format)"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_PGX, + .p.capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(pgx_decode_frame), }; diff --git a/libavcodec/photocd.c b/libavcodec/photocd.c index 50b465c1c..0f3001f2e 100644 --- a/libavcodec/photocd.c +++ b/libavcodec/photocd.c @@ -35,6 +35,7 @@ #include "libavutil/opt.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" #include "thread.h" @@ -289,14 +290,12 @@ static av_noinline int decode_huff(AVCodecContext *avctx, AVFrame *frame, return 0; } -static int photocd_decode_frame(AVCodecContext *avctx, void *data, +static int photocd_decode_frame(AVCodecContext *avctx, AVFrame *p, int *got_frame, AVPacket *avpkt) { PhotoCDContext *s = avctx->priv_data; - ThreadFrame frame = { .f = data }; const uint8_t *buf = avpkt->data; GetByteContext *gb = &s->gb; - AVFrame *p = data; uint8_t *ptr, *ptr1, *ptr2; int ret; @@ -326,7 +325,7 @@ static int photocd_decode_frame(AVCodecContext *avctx, void *data, if (ret < 0) return ret; - if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, p, 0)) < 0) return ret; p->pict_type = AV_PICTURE_TYPE_I; @@ -457,16 +456,16 @@ static const AVClass photocd_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_photocd_decoder = { - .name = "photocd", - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_PHOTOCD, +const FFCodec ff_photocd_decoder = { + .p.name = "photocd", + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_PHOTOCD, .priv_data_size = sizeof(PhotoCDContext), - .priv_class = &photocd_class, + .p.priv_class = &photocd_class, .init = photocd_decode_init, .close = photocd_decode_close, - .decode = photocd_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, - .long_name = NULL_IF_CONFIG_SMALL("Kodak Photo CD"), + FF_CODEC_DECODE_CB(photocd_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .p.long_name = NULL_IF_CONFIG_SMALL("Kodak Photo CD"), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/pictordec.c b/libavcodec/pictordec.c index c7b3a335d..ed0292c79 100644 --- a/libavcodec/pictordec.c +++ b/libavcodec/pictordec.c @@ -28,6 +28,7 @@ #include "avcodec.h" #include "bytestream.h" #include "cga_data.h" +#include "codec_internal.h" #include "internal.h" typedef struct PicContext { @@ -118,12 +119,10 @@ static const uint8_t cga_mode45_index[6][4] = { [5] = { 0, 11, 12, 15 }, // mode5, high intensity }; -static int decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { PicContext *s = avctx->priv_data; - AVFrame *frame = data; uint32_t *palette; int bits_per_plane, bpp, etype, esize, npal, pos_after_pal; int i, x, y, plane, tmp, ret, val; @@ -280,12 +279,12 @@ finish: return avpkt->size; } -const AVCodec ff_pictor_decoder = { - .name = "pictor", - .long_name = NULL_IF_CONFIG_SMALL("Pictor/PC Paint"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_PICTOR, +const FFCodec ff_pictor_decoder = { + .p.name = "pictor", + .p.long_name = NULL_IF_CONFIG_SMALL("Pictor/PC Paint"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_PICTOR, + .p.capabilities = AV_CODEC_CAP_DR1, .priv_data_size = sizeof(PicContext), - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), }; diff --git a/libavcodec/pixblockdsp.c b/libavcodec/pixblockdsp.c index 67393b959..17c487da1 100644 --- a/libavcodec/pixblockdsp.c +++ b/libavcodec/pixblockdsp.c @@ -80,7 +80,7 @@ static void diff_pixels_c(int16_t *av_restrict block, const uint8_t *s1, av_cold void ff_pixblockdsp_init(PixblockDSPContext *c, AVCodecContext *avctx) { - const unsigned high_bit_depth = avctx->bits_per_raw_sample > 8; + av_unused const unsigned high_bit_depth = avctx->bits_per_raw_sample > 8; c->diff_pixels_unaligned = c->diff_pixels = diff_pixels_c; @@ -101,16 +101,17 @@ av_cold void ff_pixblockdsp_init(PixblockDSPContext *c, AVCodecContext *avctx) break; } - if (ARCH_AARCH64) - ff_pixblockdsp_init_aarch64(c, avctx, high_bit_depth); - if (ARCH_ALPHA) - ff_pixblockdsp_init_alpha(c, avctx, high_bit_depth); - if (ARCH_ARM) - ff_pixblockdsp_init_arm(c, avctx, high_bit_depth); - if (ARCH_PPC) - ff_pixblockdsp_init_ppc(c, avctx, high_bit_depth); - if (ARCH_X86) - ff_pixblockdsp_init_x86(c, avctx, high_bit_depth); - if (ARCH_MIPS) - ff_pixblockdsp_init_mips(c, avctx, high_bit_depth); +#if ARCH_AARCH64 + ff_pixblockdsp_init_aarch64(c, avctx, high_bit_depth); +#elif ARCH_ALPHA + ff_pixblockdsp_init_alpha(c, avctx, high_bit_depth); +#elif ARCH_ARM + ff_pixblockdsp_init_arm(c, avctx, high_bit_depth); +#elif ARCH_PPC + ff_pixblockdsp_init_ppc(c, avctx, high_bit_depth); +#elif ARCH_X86 + ff_pixblockdsp_init_x86(c, avctx, high_bit_depth); +#elif ARCH_MIPS + ff_pixblockdsp_init_mips(c, avctx, high_bit_depth); +#endif } diff --git a/libavcodec/pixlet.c b/libavcodec/pixlet.c index 83949a2ce..4f9282bb9 100644 --- a/libavcodec/pixlet.c +++ b/libavcodec/pixlet.c @@ -27,6 +27,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" #include "thread.h" @@ -197,7 +198,7 @@ static int read_low_coeffs(AVCodecContext *avctx, int16_t *dst, int size, return get_bits_count(bc) >> 3; } -static int read_high_coeffs(AVCodecContext *avctx, uint8_t *src, int16_t *dst, +static int read_high_coeffs(AVCodecContext *avctx, const uint8_t *src, int16_t *dst, int size, int c, int a, int d, int width, ptrdiff_t stride) { @@ -312,7 +313,7 @@ static int read_high_coeffs(AVCodecContext *avctx, uint8_t *src, int16_t *dst, return get_bits_count(bc) >> 3; } -static int read_highpass(AVCodecContext *avctx, uint8_t *ptr, +static int read_highpass(AVCodecContext *avctx, const uint8_t *ptr, int plane, AVFrame *frame) { PixletContext *ctx = avctx->priv_data; @@ -600,19 +601,17 @@ static int decode_plane(AVCodecContext *avctx, int plane, return 0; } -static int pixlet_decode_frame(AVCodecContext *avctx, void *data, +static int pixlet_decode_frame(AVCodecContext *avctx, AVFrame *p, 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, depth; 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)) { + if (pktsize <= 44 + (NB_LEVELS * 8 + 6) * 3 || pktsize - 4 > bytestream2_get_bytes_left(&ctx->gb)) { av_log(avctx, AV_LOG_ERROR, "Invalid packet size %"PRIu32"\n", pktsize); return AVERROR_INVALIDDATA; } @@ -673,36 +672,36 @@ static int pixlet_decode_frame(AVCodecContext *avctx, void *data, p->key_frame = 1; p->color_range = AVCOL_RANGE_JPEG; - ret = ff_thread_get_buffer(avctx, &frame, 0); + ret = ff_thread_get_buffer(avctx, p, 0); if (ret < 0) return ret; for (i = 0; i < 3; i++) { - ret = decode_plane(avctx, i, avpkt, frame.f); + ret = decode_plane(avctx, i, avpkt, p); if (ret < 0) return ret; if (avctx->flags & AV_CODEC_FLAG_GRAY) break; } - postprocess_luma(avctx, frame.f, ctx->w, ctx->h, ctx->depth); - postprocess_chroma(frame.f, ctx->w >> 1, ctx->h >> 1, ctx->depth); + postprocess_luma(avctx, p, ctx->w, ctx->h, ctx->depth); + postprocess_chroma(p, ctx->w >> 1, ctx->h >> 1, ctx->depth); *got_frame = 1; return pktsize; } -const AVCodec ff_pixlet_decoder = { - .name = "pixlet", - .long_name = NULL_IF_CONFIG_SMALL("Apple Pixlet"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_PIXLET, +const FFCodec ff_pixlet_decoder = { + .p.name = "pixlet", + .p.long_name = NULL_IF_CONFIG_SMALL("Apple Pixlet"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_PIXLET, .init = pixlet_init, .close = pixlet_close, - .decode = pixlet_decode_frame, + FF_CODEC_DECODE_CB(pixlet_decode_frame), .priv_data_size = sizeof(PixletContext), - .capabilities = AV_CODEC_CAP_DR1 | + .p.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/png.c b/libavcodec/png.c index e772eaad2..34f649815 100644 --- a/libavcodec/png.c +++ b/libavcodec/png.c @@ -38,16 +38,6 @@ static const uint8_t ff_png_pass_xshift[NB_PASSES] = { 3, 3, 2, 2, 1, 1, 0 }; -void *ff_png_zalloc(void *opaque, unsigned int items, unsigned int size) -{ - return av_calloc(items, size); -} - -void ff_png_zfree(void *opaque, void *ptr) -{ - av_free(ptr); -} - int ff_png_get_nb_channels(int color_type) { int channels; diff --git a/libavcodec/png.h b/libavcodec/png.h index a15560131..01171e682 100644 --- a/libavcodec/png.h +++ b/libavcodec/png.h @@ -52,10 +52,6 @@ /* Mask to determine which y pixels are valid in a pass */ extern const uint8_t ff_png_pass_ymask[NB_PASSES]; -void *ff_png_zalloc(void *opaque, unsigned int items, unsigned int size); - -void ff_png_zfree(void *opaque, void *ptr); - int ff_png_get_nb_channels(int color_type); /* compute the row size of an interleaved pass */ diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c index 3c0000790..87b0c639e 100644 --- a/libavcodec/pngdec.c +++ b/libavcodec/pngdec.c @@ -21,6 +21,8 @@ //#define DEBUG +#include "config_components.h" + #include "libavutil/avassert.h" #include "libavutil/bprint.h" #include "libavutil/crc.h" @@ -31,11 +33,14 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" #include "apng.h" #include "png.h" #include "pngdsp.h" #include "thread.h" +#include "threadframe.h" +#include "zlib_wrapper.h" #include @@ -104,7 +109,7 @@ typedef struct PNGDecContext { int row_size; /* decompressed row size */ int pass_row_size; /* decompress row size of the current pass */ int y; - z_stream zstream; + FFZStream zstream; } PNGDecContext; /* Mask to determine which pixels are valid in a pass */ @@ -426,27 +431,28 @@ the_end:; static int png_decode_idat(PNGDecContext *s, GetByteContext *gb, uint8_t *dst, ptrdiff_t dst_stride) { + z_stream *const zstream = &s->zstream.zstream; int ret; - s->zstream.avail_in = bytestream2_get_bytes_left(gb); - s->zstream.next_in = gb->buffer; + zstream->avail_in = bytestream2_get_bytes_left(gb); + zstream->next_in = gb->buffer; /* decode one line if possible */ - while (s->zstream.avail_in > 0) { - ret = inflate(&s->zstream, Z_PARTIAL_FLUSH); + while (zstream->avail_in > 0) { + ret = inflate(zstream, Z_PARTIAL_FLUSH); if (ret != Z_OK && ret != Z_STREAM_END) { av_log(s->avctx, AV_LOG_ERROR, "inflate returned error %d\n", ret); return AVERROR_EXTERNAL; } - if (s->zstream.avail_out == 0) { + if (zstream->avail_out == 0) { if (!(s->pic_state & PNG_ALLIMAGE)) { png_handle_row(s, dst, dst_stride); } - s->zstream.avail_out = s->crow_size; - s->zstream.next_out = s->crow_buf; + zstream->avail_out = s->crow_size; + zstream->next_out = s->crow_buf; } - if (ret == Z_STREAM_END && s->zstream.avail_in > 0) { + if (ret == Z_STREAM_END && zstream->avail_in > 0) { av_log(s->avctx, AV_LOG_WARNING, - "%d undecompressed bytes left in buffer\n", s->zstream.avail_in); + "%d undecompressed bytes left in buffer\n", zstream->avail_in); return 0; } } @@ -454,45 +460,43 @@ static int png_decode_idat(PNGDecContext *s, GetByteContext *gb, } static int decode_zbuf(AVBPrint *bp, const uint8_t *data, - const uint8_t *data_end) + const uint8_t *data_end, void *logctx) { - z_stream zstream; + FFZStream z; + z_stream *const zstream = &z.zstream; unsigned char *buf; unsigned buf_size; - int ret; + int ret = ff_inflate_init(&z, logctx); + if (ret < 0) + return ret; - zstream.zalloc = ff_png_zalloc; - zstream.zfree = ff_png_zfree; - zstream.opaque = NULL; - if (inflateInit(&zstream) != Z_OK) - return AVERROR_EXTERNAL; - zstream.next_in = data; - zstream.avail_in = data_end - data; + zstream->next_in = data; + zstream->avail_in = data_end - data; av_bprint_init(bp, 0, AV_BPRINT_SIZE_UNLIMITED); - while (zstream.avail_in > 0) { + while (zstream->avail_in > 0) { av_bprint_get_buffer(bp, 2, &buf, &buf_size); if (buf_size < 2) { ret = AVERROR(ENOMEM); goto fail; } - zstream.next_out = buf; - zstream.avail_out = buf_size - 1; - ret = inflate(&zstream, Z_PARTIAL_FLUSH); + zstream->next_out = buf; + zstream->avail_out = buf_size - 1; + ret = inflate(zstream, Z_PARTIAL_FLUSH); if (ret != Z_OK && ret != Z_STREAM_END) { ret = AVERROR_EXTERNAL; goto fail; } - bp->len += zstream.next_out - buf; + bp->len += zstream->next_out - buf; if (ret == Z_STREAM_END) break; } - inflateEnd(&zstream); + ff_inflate_end(&z); bp->str[bp->len] = 0; return 0; fail: - inflateEnd(&zstream); + ff_inflate_end(&z); av_bprint_finalize(bp, NULL); return ret; } @@ -542,7 +546,7 @@ static int decode_text_chunk(PNGDecContext *s, GetByteContext *gb, int compresse method = *(data++); if (method) return AVERROR_INVALIDDATA; - if ((ret = decode_zbuf(&bp, data, data_end)) < 0) + if ((ret = decode_zbuf(&bp, data, data_end, s->avctx)) < 0) return ret; text_len = bp.len; ret = av_bprint_finalize(&bp, (char **)&text); @@ -676,7 +680,7 @@ static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s, avctx->pix_fmt = AV_PIX_FMT_RGBA64BE; } else if ((s->bits_per_pixel == 1 || s->bits_per_pixel == 2 || s->bits_per_pixel == 4 || s->bits_per_pixel == 8) && s->color_type == PNG_COLOR_TYPE_PALETTE) { - avctx->pix_fmt = AV_PIX_FMT_PAL8; + avctx->pix_fmt = avctx->codec_id == AV_CODEC_ID_APNG ? AV_PIX_FMT_RGBA : AV_PIX_FMT_PAL8; } else if (s->bit_depth == 1 && s->bits_per_pixel == 1 && avctx->codec_id != AV_CODEC_ID_APNG) { avctx->pix_fmt = AV_PIX_FMT_MONOBLACK; } else if (s->bit_depth == 8 && @@ -720,8 +724,9 @@ static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s, s->bpp += byte_depth; } - ff_thread_release_buffer(avctx, &s->picture); - if ((ret = ff_thread_get_buffer(avctx, &s->picture, AV_GET_BUFFER_FLAG_REF)) < 0) + ff_thread_release_ext_buffer(avctx, &s->picture); + if ((ret = ff_thread_get_ext_buffer(avctx, &s->picture, + AV_GET_BUFFER_FLAG_REF)) < 0) return ret; p->pict_type = AV_PICTURE_TYPE_I; @@ -763,8 +768,8 @@ static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s, /* we want crow_buf+1 to be 16-byte aligned */ s->crow_buf = s->buffer + 15; - s->zstream.avail_out = s->crow_size; - s->zstream.next_out = s->crow_buf; + s->zstream.zstream.avail_out = s->crow_size; + s->zstream.zstream.next_out = s->crow_buf; } s->pic_state |= PNG_IDAT; @@ -873,7 +878,7 @@ static int decode_iccp_chunk(PNGDecContext *s, GetByteContext *gb, AVFrame *f) goto fail; } - if ((ret = decode_zbuf(&bp, gb->buffer, gb->buffer_end)) < 0) + if ((ret = decode_zbuf(&bp, gb->buffer, gb->buffer_end, s->avctx)) < 0) return ret; av_freep(&s->iccp_data); @@ -967,7 +972,7 @@ static int decode_fctl_chunk(AVCodecContext *avctx, PNGDecContext *s, uint32_t sequence_number; int cur_w, cur_h, x_offset, y_offset, dispose_op, blend_op; - if (bytestream2_get_bytes_left(gb) != 26) + if (bytestream2_get_bytes_left(gb) != APNG_FCTL_CHUNK_SIZE) return AVERROR_INVALIDDATA; if (!(s->hdr_state & PNG_IHDR)) { @@ -1020,7 +1025,6 @@ static int decode_fctl_chunk(AVCodecContext *avctx, PNGDecContext *s, if (blend_op == APNG_BLEND_OP_OVER && !s->has_trns && ( avctx->pix_fmt == AV_PIX_FMT_RGB24 || avctx->pix_fmt == AV_PIX_FMT_RGB48BE || - avctx->pix_fmt == AV_PIX_FMT_PAL8 || avctx->pix_fmt == AV_PIX_FMT_GRAY8 || avctx->pix_fmt == AV_PIX_FMT_GRAY16BE || avctx->pix_fmt == AV_PIX_FMT_MONOBLACK @@ -1068,13 +1072,13 @@ static int handle_p_frame_apng(AVCodecContext *avctx, PNGDecContext *s, ptrdiff_t dst_stride = p->linesize[0]; const uint8_t *src = s->last_picture.f->data[0]; ptrdiff_t src_stride = s->last_picture.f->linesize[0]; + const int bpp = s->color_type == PNG_COLOR_TYPE_PALETTE ? 4 : s->bpp; size_t x, y; if (s->blend_op == APNG_BLEND_OP_OVER && avctx->pix_fmt != AV_PIX_FMT_RGBA && - avctx->pix_fmt != AV_PIX_FMT_GRAY8A && - avctx->pix_fmt != AV_PIX_FMT_PAL8) { + avctx->pix_fmt != AV_PIX_FMT_GRAY8A) { avpriv_request_sample(avctx, "Blending with pixel format %s", av_get_pix_fmt_name(avctx->pix_fmt)); return AVERROR_PATCHWELCOME; @@ -1093,7 +1097,7 @@ static int handle_p_frame_apng(AVCodecContext *avctx, PNGDecContext *s, for (y = s->last_y_offset; y < s->last_y_offset + s->last_h; y++) { memset(s->background_buf + src_stride * y + - s->bpp * s->last_x_offset, 0, s->bpp * s->last_w); + bpp * s->last_x_offset, 0, bpp * s->last_w); } src = s->background_buf; @@ -1101,22 +1105,22 @@ static int handle_p_frame_apng(AVCodecContext *avctx, PNGDecContext *s, // copy unchanged rectangles from the last frame for (y = 0; y < s->y_offset; y++) - memcpy(dst + y * dst_stride, src + y * src_stride, p->width * s->bpp); + memcpy(dst + y * dst_stride, src + y * src_stride, p->width * bpp); for (y = s->y_offset; y < s->y_offset + s->cur_h; y++) { - memcpy(dst + y * dst_stride, src + y * src_stride, s->x_offset * s->bpp); - memcpy(dst + y * dst_stride + (s->x_offset + s->cur_w) * s->bpp, - src + y * src_stride + (s->x_offset + s->cur_w) * s->bpp, - (p->width - s->cur_w - s->x_offset) * s->bpp); + memcpy(dst + y * dst_stride, src + y * src_stride, s->x_offset * bpp); + memcpy(dst + y * dst_stride + (s->x_offset + s->cur_w) * bpp, + src + y * src_stride + (s->x_offset + s->cur_w) * bpp, + (p->width - s->cur_w - s->x_offset) * bpp); } for (y = s->y_offset + s->cur_h; y < p->height; y++) - memcpy(dst + y * dst_stride, src + y * src_stride, p->width * s->bpp); + memcpy(dst + y * dst_stride, src + y * src_stride, p->width * bpp); if (s->blend_op == APNG_BLEND_OP_OVER) { // Perform blending for (y = s->y_offset; y < s->y_offset + s->cur_h; ++y) { - uint8_t *foreground = dst + dst_stride * y + s->bpp * s->x_offset; - const uint8_t *background = src + src_stride * y + s->bpp * s->x_offset; - for (x = s->x_offset; x < s->x_offset + s->cur_w; ++x, foreground += s->bpp, background += s->bpp) { + uint8_t *foreground = dst + dst_stride * y + bpp * s->x_offset; + const uint8_t *background = src + src_stride * y + bpp * s->x_offset; + for (x = s->x_offset; x < s->x_offset + s->cur_w; ++x, foreground += bpp, background += bpp) { size_t b; uint8_t foreground_alpha, background_alpha, output_alpha; uint8_t output[10]; @@ -1135,32 +1139,21 @@ static int handle_p_frame_apng(AVCodecContext *avctx, PNGDecContext *s, foreground_alpha = foreground[1]; background_alpha = background[1]; break; - - case AV_PIX_FMT_PAL8: - foreground_alpha = s->palette[foreground[0]] >> 24; - background_alpha = s->palette[background[0]] >> 24; - break; } if (foreground_alpha == 255) continue; if (foreground_alpha == 0) { - memcpy(foreground, background, s->bpp); - continue; - } - - if (avctx->pix_fmt == AV_PIX_FMT_PAL8) { - // TODO: Alpha blending with PAL8 will likely need the entire image converted over to RGBA first - avpriv_request_sample(avctx, "Alpha blending palette samples"); + memcpy(foreground, background, bpp); continue; } output_alpha = foreground_alpha + FAST_DIV255((255 - foreground_alpha) * background_alpha); - av_assert0(s->bpp <= 10); + av_assert0(bpp <= 10); - for (b = 0; b < s->bpp - 1; ++b) { + for (b = 0; b < bpp - 1; ++b) { if (output_alpha == 0) { output[b] = 0; } else if (background_alpha == 255) { @@ -1170,7 +1163,7 @@ static int handle_p_frame_apng(AVCodecContext *avctx, PNGDecContext *s, } } output[b] = output_alpha; - memcpy(foreground, output, s->bpp); + memcpy(foreground, output, bpp); } } } @@ -1366,6 +1359,21 @@ exit_loop: if (s->bits_per_pixel <= 4) handle_small_bpp(s, p); + if (s->color_type == PNG_COLOR_TYPE_PALETTE && avctx->codec_id == AV_CODEC_ID_APNG) { + for (int y = 0; y < s->height; y++) { + uint8_t *row = &p->data[0][p->linesize[0] * y]; + + for (int x = s->width - 1; x >= 0; x--) { + const uint8_t idx = row[x]; + + row[4*x+2] = s->palette[idx] & 0xFF; + row[4*x+1] = (s->palette[idx] >> 8 ) & 0xFF; + row[4*x+0] = (s->palette[idx] >> 16) & 0xFF; + row[4*x+3] = s->palette[idx] >> 24; + } + } + } + /* apply transparency if needed */ if (s->has_trns && s->color_type != PNG_COLOR_TYPE_PALETTE) { size_t byte_depth = s->bit_depth > 8 ? 2 : 1; @@ -1507,14 +1515,12 @@ fail: } #if CONFIG_PNG_DECODER -static int decode_frame_png(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame_png(AVCodecContext *avctx, AVFrame *dst_frame, + int *got_frame, AVPacket *avpkt) { PNGDecContext *const s = avctx->priv_data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; - AVFrame *dst_frame = data; AVFrame *p = s->picture.f; int64_t sig; int ret; @@ -1535,15 +1541,10 @@ static int decode_frame_png(AVCodecContext *avctx, s->hdr_state = 0; s->pic_state = 0; - /* init the zlib */ - s->zstream.zalloc = ff_png_zalloc; - s->zstream.zfree = ff_png_zfree; - s->zstream.opaque = NULL; - ret = inflateInit(&s->zstream); - if (ret != Z_OK) { - av_log(avctx, AV_LOG_ERROR, "inflateInit returned error %d\n", ret); + /* Reset z_stream */ + ret = inflateReset(&s->zstream.zstream); + if (ret != Z_OK) return AVERROR_EXTERNAL; - } if ((ret = decode_frame_common(avctx, s, p, avpkt)) < 0) goto the_end; @@ -1559,7 +1560,7 @@ static int decode_frame_png(AVCodecContext *avctx, goto the_end; if (!(avctx->active_thread_type & FF_THREAD_FRAME)) { - ff_thread_release_buffer(avctx, &s->last_picture); + ff_thread_release_ext_buffer(avctx, &s->last_picture); FFSWAP(ThreadFrame, s->picture, s->last_picture); } @@ -1567,19 +1568,16 @@ static int decode_frame_png(AVCodecContext *avctx, ret = bytestream2_tell(&s->gb); the_end: - inflateEnd(&s->zstream); s->crow_buf = NULL; return ret; } #endif #if CONFIG_APNG_DECODER -static int decode_frame_apng(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame_apng(AVCodecContext *avctx, AVFrame *dst_frame, + int *got_frame, AVPacket *avpkt) { PNGDecContext *const s = avctx->priv_data; - AVFrame *dst_frame = data; int ret; AVFrame *p = s->picture.f; @@ -1589,53 +1587,42 @@ static int decode_frame_apng(AVCodecContext *avctx, if (!avctx->extradata_size) return AVERROR_INVALIDDATA; - /* only init fields, there is no zlib use in extradata */ - s->zstream.zalloc = ff_png_zalloc; - s->zstream.zfree = ff_png_zfree; - + if ((ret = inflateReset(&s->zstream.zstream)) != Z_OK) + return AVERROR_EXTERNAL; bytestream2_init(&s->gb, avctx->extradata, avctx->extradata_size); if ((ret = decode_frame_common(avctx, s, p, avpkt)) < 0) - goto end; + return ret; } /* reset state for a new frame */ - if ((ret = inflateInit(&s->zstream)) != Z_OK) { - av_log(avctx, AV_LOG_ERROR, "inflateInit returned error %d\n", ret); - ret = AVERROR_EXTERNAL; - goto end; - } + if ((ret = inflateReset(&s->zstream.zstream)) != Z_OK) + return AVERROR_EXTERNAL; s->y = 0; s->pic_state = 0; bytestream2_init(&s->gb, avpkt->data, avpkt->size); if ((ret = decode_frame_common(avctx, s, p, avpkt)) < 0) - goto end; + return ret; if (!(s->pic_state & PNG_ALLIMAGE)) av_log(avctx, AV_LOG_WARNING, "Frame did not contain a complete image\n"); - if (!(s->pic_state & (PNG_ALLIMAGE|PNG_IDAT))) { - ret = AVERROR_INVALIDDATA; - goto end; - } + if (!(s->pic_state & (PNG_ALLIMAGE|PNG_IDAT))) + return AVERROR_INVALIDDATA; ret = output_frame(s, dst_frame, s->picture.f); if (ret < 0) - goto end; + return ret; if (!(avctx->active_thread_type & FF_THREAD_FRAME)) { if (s->dispose_op == APNG_DISPOSE_OP_PREVIOUS) { - ff_thread_release_buffer(avctx, &s->picture); + ff_thread_release_ext_buffer(avctx, &s->picture); } else { - ff_thread_release_buffer(avctx, &s->last_picture); + ff_thread_release_ext_buffer(avctx, &s->last_picture); FFSWAP(ThreadFrame, s->picture, s->last_picture); } } *got_frame = 1; - ret = bytestream2_tell(&s->gb); - -end: - inflateEnd(&s->zstream); - return ret; + return bytestream2_tell(&s->gb); } #endif @@ -1676,7 +1663,7 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src) src_frame = psrc->dispose_op == APNG_DISPOSE_OP_PREVIOUS ? &psrc->last_picture : &psrc->picture; - ff_thread_release_buffer(dst, &pdst->last_picture); + ff_thread_release_ext_buffer(dst, &pdst->last_picture); if (src_frame && src_frame->f->data[0]) { ret = ff_thread_ref_frame(&pdst->last_picture, src_frame); if (ret < 0) @@ -1696,24 +1683,21 @@ static av_cold int png_dec_init(AVCodecContext *avctx) s->avctx = avctx; s->last_picture.f = av_frame_alloc(); s->picture.f = av_frame_alloc(); - if (!s->last_picture.f || !s->picture.f) { - av_frame_free(&s->last_picture.f); - av_frame_free(&s->picture.f); + if (!s->last_picture.f || !s->picture.f) return AVERROR(ENOMEM); - } ff_pngdsp_init(&s->dsp); - return 0; + return ff_inflate_init(&s->zstream, avctx); } static av_cold int png_dec_end(AVCodecContext *avctx) { PNGDecContext *s = avctx->priv_data; - ff_thread_release_buffer(avctx, &s->last_picture); + ff_thread_release_ext_buffer(avctx, &s->last_picture); av_frame_free(&s->last_picture.f); - ff_thread_release_buffer(avctx, &s->picture); + ff_thread_release_ext_buffer(avctx, &s->picture); av_frame_free(&s->picture.f); av_freep(&s->buffer); s->buffer_size = 0; @@ -1725,40 +1709,41 @@ static av_cold int png_dec_end(AVCodecContext *avctx) av_freep(&s->iccp_data); av_dict_free(&s->frame_metadata); + ff_inflate_end(&s->zstream); return 0; } #if CONFIG_APNG_DECODER -const AVCodec ff_apng_decoder = { - .name = "apng", - .long_name = NULL_IF_CONFIG_SMALL("APNG (Animated Portable Network Graphics) image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_APNG, +const FFCodec ff_apng_decoder = { + .p.name = "apng", + .p.long_name = NULL_IF_CONFIG_SMALL("APNG (Animated Portable Network Graphics) image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_APNG, .priv_data_size = sizeof(PNGDecContext), .init = png_dec_init, .close = png_dec_end, - .decode = decode_frame_apng, + FF_CODEC_DECODE_CB(decode_frame_apng), .update_thread_context = ONLY_IF_THREADS_ENABLED(update_thread_context), - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS /*| AV_CODEC_CAP_DRAW_HORIZ_BAND*/, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS /*| AV_CODEC_CAP_DRAW_HORIZ_BAND*/, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_ALLOCATE_PROGRESS, }; #endif #if CONFIG_PNG_DECODER -const AVCodec ff_png_decoder = { - .name = "png", - .long_name = NULL_IF_CONFIG_SMALL("PNG (Portable Network Graphics) image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_PNG, +const FFCodec ff_png_decoder = { + .p.name = "png", + .p.long_name = NULL_IF_CONFIG_SMALL("PNG (Portable Network Graphics) image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_PNG, .priv_data_size = sizeof(PNGDecContext), .init = png_dec_init, .close = png_dec_end, - .decode = decode_frame_png, + FF_CODEC_DECODE_CB(decode_frame_png), .update_thread_context = ONLY_IF_THREADS_ENABLED(update_thread_context), - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS /*| AV_CODEC_CAP_DRAW_HORIZ_BAND*/, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS /*| AV_CODEC_CAP_DRAW_HORIZ_BAND*/, .caps_internal = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM | FF_CODEC_CAP_INIT_THREADSAFE | - FF_CODEC_CAP_ALLOCATE_PROGRESS, + FF_CODEC_CAP_ALLOCATE_PROGRESS | FF_CODEC_CAP_INIT_CLEANUP, }; #endif diff --git a/libavcodec/pngdsp.c b/libavcodec/pngdsp.c index d2753163d..65916b138 100644 --- a/libavcodec/pngdsp.c +++ b/libavcodec/pngdsp.c @@ -19,8 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config.h" #include "libavutil/attributes.h" -#include "libavutil/common.h" #include "png.h" #include "pngdsp.h" @@ -45,6 +45,7 @@ av_cold void ff_pngdsp_init(PNGDSPContext *dsp) dsp->add_bytes_l2 = add_bytes_l2_c; dsp->add_paeth_prediction = ff_add_png_paeth_prediction; - if (ARCH_X86) - ff_pngdsp_init_x86(dsp); +#if ARCH_X86 + ff_pngdsp_init_x86(dsp); +#endif } diff --git a/libavcodec/pngenc.c b/libavcodec/pngenc.c index 3ebcc1e57..93463dd34 100644 --- a/libavcodec/pngenc.c +++ b/libavcodec/pngenc.c @@ -20,12 +20,13 @@ */ #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "bytestream.h" #include "lossless_videoencdsp.h" #include "png.h" #include "apng.h" +#include "zlib_wrapper.h" #include "libavutil/avassert.h" #include "libavutil/crc.h" @@ -56,7 +57,7 @@ typedef struct PNGEncContext { int filter_type; - z_stream zstream; + FFZStream zstream; uint8_t buf[IOBUF_SIZE]; int dpi; ///< Physical pixel density, in dots per inch, if set int dpm; ///< Physical pixel density, in dots per meter, if set @@ -235,7 +236,8 @@ static void png_write_chunk(uint8_t **f, uint32_t tag, bytestream_put_be32(f, av_bswap32(tag)); if (length > 0) { crc = av_crc(crc_table, crc, buf, length); - memcpy(*f, buf, length); + if (*f != buf) + memcpy(*f, buf, length); *f += length; } bytestream_put_be32(f, ~crc); @@ -272,19 +274,20 @@ static void png_write_image_data(AVCodecContext *avctx, static int png_write_row(AVCodecContext *avctx, const uint8_t *data, int size) { PNGEncContext *s = avctx->priv_data; + z_stream *const zstream = &s->zstream.zstream; int ret; - s->zstream.avail_in = size; - s->zstream.next_in = data; - while (s->zstream.avail_in > 0) { - ret = deflate(&s->zstream, Z_NO_FLUSH); + zstream->avail_in = size; + zstream->next_in = data; + while (zstream->avail_in > 0) { + ret = deflate(zstream, Z_NO_FLUSH); if (ret != Z_OK) return -1; - if (s->zstream.avail_out == 0) { + if (zstream->avail_out == 0) { if (s->bytestream_end - s->bytestream > IOBUF_SIZE + 100) png_write_image_data(avctx, s->buf, IOBUF_SIZE); - s->zstream.avail_out = IOBUF_SIZE; - s->zstream.next_out = s->buf; + zstream->avail_out = IOBUF_SIZE; + zstream->next_out = s->buf; } } return 0; @@ -343,10 +346,53 @@ static int png_get_gama(enum AVColorTransferCharacteristic trc, uint8_t *buf) return 1; } +static int png_write_iccp(PNGEncContext *s, const AVFrameSideData *sd) +{ + z_stream *const zstream = &s->zstream.zstream; + const AVDictionaryEntry *entry; + const char *name; + uint8_t *start, *buf; + int ret; + + if (!sd || !sd->size) + return 0; + zstream->next_in = sd->data; + zstream->avail_in = sd->size; + + /* write the chunk contents first */ + start = s->bytestream + 8; /* make room for iCCP tag + length */ + buf = start; + + /* profile description */ + entry = av_dict_get(sd->metadata, "name", NULL, 0); + name = (entry && entry->value[0]) ? entry->value : "icc"; + for (int i = 0;; i++) { + char c = (i == 79) ? 0 : name[i]; + bytestream_put_byte(&buf, c); + if (!c) + break; + } + + /* compression method and profile data */ + bytestream_put_byte(&buf, 0); + zstream->next_out = buf; + zstream->avail_out = s->bytestream_end - buf; + ret = deflate(zstream, Z_FINISH); + deflateReset(zstream); + if (ret != Z_STREAM_END) + return AVERROR_EXTERNAL; + + /* rewind to the start and write the chunk header/crc */ + png_write_chunk(&s->bytestream, MKTAG('i', 'C', 'C', 'P'), start, + zstream->next_out - start); + return 0; +} + static int encode_headers(AVCodecContext *avctx, const AVFrame *pict) { AVFrameSideData *side_data; PNGEncContext *s = avctx->priv_data; + int ret; /* write png header */ AV_WB32(s->buf, avctx->width); @@ -399,7 +445,11 @@ static int encode_headers(AVCodecContext *avctx, const AVFrame *pict) if (png_get_gama(pict->color_trc, s->buf)) png_write_chunk(&s->bytestream, MKTAG('g', 'A', 'M', 'A'), s->buf, 4); - /* put the palette if needed */ + side_data = av_frame_get_side_data(pict, AV_FRAME_DATA_ICC_PROFILE); + if ((ret = png_write_iccp(s, side_data))) + return ret; + + /* put the palette if needed, must be after colorspace information */ if (s->color_type == PNG_COLOR_TYPE_PALETTE) { int has_alpha, alpha, i; unsigned int v; @@ -432,6 +482,7 @@ static int encode_headers(AVCodecContext *avctx, const AVFrame *pict) static int encode_frame(AVCodecContext *avctx, const AVFrame *pict) { PNGEncContext *s = avctx->priv_data; + z_stream *const zstream = &s->zstream.zstream; const AVFrame *const p = pict; int y, len, ret; int row_size, pass_row_size; @@ -459,8 +510,8 @@ static int encode_frame(AVCodecContext *avctx, const AVFrame *pict) } /* put each row */ - s->zstream.avail_out = IOBUF_SIZE; - s->zstream.next_out = s->buf; + zstream->avail_out = IOBUF_SIZE; + zstream->next_out = s->buf; if (s->is_progressive) { int pass; @@ -496,14 +547,14 @@ static int encode_frame(AVCodecContext *avctx, const AVFrame *pict) } /* compress last bytes */ for (;;) { - ret = deflate(&s->zstream, Z_FINISH); + ret = deflate(zstream, Z_FINISH); if (ret == Z_OK || ret == Z_STREAM_END) { - len = IOBUF_SIZE - s->zstream.avail_out; + len = IOBUF_SIZE - zstream->avail_out; if (len > 0 && s->bytestream_end - s->bytestream > len + 100) { png_write_image_data(avctx, s->buf, len); } - s->zstream.avail_out = IOBUF_SIZE; - s->zstream.next_out = s->buf; + zstream->avail_out = IOBUF_SIZE; + zstream->next_out = s->buf; if (ret == Z_STREAM_END) break; } else { @@ -518,27 +569,56 @@ the_end: av_freep(&crow_base); av_freep(&progressive_buf); av_freep(&top_buf); - deflateReset(&s->zstream); + deflateReset(zstream); return ret; } +static int add_icc_profile_size(AVCodecContext *avctx, const AVFrame *pict, + uint64_t *max_packet_size) +{ + PNGEncContext *s = avctx->priv_data; + const AVFrameSideData *sd; + const int hdr_size = 128; + uint64_t new_pkt_size; + uLong bound; + + if (!pict) + return 0; + sd = av_frame_get_side_data(pict, AV_FRAME_DATA_ICC_PROFILE); + if (!sd || !sd->size) + return 0; + if (sd->size != (uLong) sd->size) + return AVERROR_INVALIDDATA; + + bound = deflateBound(&s->zstream.zstream, sd->size); + if (bound > INT32_MAX - hdr_size) + return AVERROR_INVALIDDATA; + + new_pkt_size = *max_packet_size + bound + hdr_size; + if (new_pkt_size < *max_packet_size) + return AVERROR_INVALIDDATA; + *max_packet_size = new_pkt_size; + return 0; +} + static int encode_png(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pict, int *got_packet) { PNGEncContext *s = avctx->priv_data; int ret; int enc_row_size; - size_t max_packet_size; + uint64_t max_packet_size; - enc_row_size = deflateBound(&s->zstream, (avctx->width * s->bits_per_pixel + 7) >> 3); + enc_row_size = deflateBound(&s->zstream.zstream, + (avctx->width * s->bits_per_pixel + 7) >> 3); max_packet_size = AV_INPUT_BUFFER_MIN_SIZE + // headers avctx->height * ( enc_row_size + 12 * (((int64_t)enc_row_size + IOBUF_SIZE - 1) / IOBUF_SIZE) // IDAT * ceil(enc_row_size / IOBUF_SIZE) ); - if (max_packet_size > INT_MAX) - return AVERROR(ENOMEM); + if ((ret = add_icc_profile_size(avctx, pict, &max_packet_size))) + return ret; ret = ff_alloc_packet(avctx, pkt, max_packet_size); if (ret < 0) return ret; @@ -845,7 +925,7 @@ static int encode_apng(AVCodecContext *avctx, AVPacket *pkt, PNGEncContext *s = avctx->priv_data; int ret; int enc_row_size; - size_t max_packet_size; + uint64_t max_packet_size; APNGFctlChunk fctl_chunk = {0}; if (pict && s->color_type == PNG_COLOR_TYPE_PALETTE) { @@ -860,13 +940,16 @@ static int encode_apng(AVCodecContext *avctx, AVPacket *pkt, } } - enc_row_size = deflateBound(&s->zstream, (avctx->width * s->bits_per_pixel + 7) >> 3); + enc_row_size = deflateBound(&s->zstream.zstream, + (avctx->width * s->bits_per_pixel + 7) >> 3); max_packet_size = AV_INPUT_BUFFER_MIN_SIZE + // headers avctx->height * ( enc_row_size + (4 + 12) * (((int64_t)enc_row_size + IOBUF_SIZE - 1) / IOBUF_SIZE) // fdAT * ceil(enc_row_size / IOBUF_SIZE) ); + if ((ret = add_icc_profile_size(avctx, pict, &max_packet_size))) + return ret; if (max_packet_size > INT_MAX) return AVERROR(ENOMEM); @@ -905,7 +988,7 @@ static int encode_apng(AVCodecContext *avctx, AVPacket *pkt, // to have the image data write to the correct place in the buffer fctl_chunk.sequence_number = s->sequence_number; ++s->sequence_number; - s->bytestream += 26 + 12; + s->bytestream += APNG_FCTL_CHUNK_SIZE + 12; ret = apng_encode_frame(avctx, pict, &fctl_chunk, &s->last_frame_fctl); if (ret < 0) @@ -919,7 +1002,7 @@ static int encode_apng(AVCodecContext *avctx, AVPacket *pkt, if (s->last_frame) { uint8_t* last_fctl_chunk_start = pkt->data; - uint8_t buf[26]; + uint8_t buf[APNG_FCTL_CHUNK_SIZE]; if (!s->extra_data_updated) { uint8_t *side_data = av_packet_new_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, s->extra_data_size); if (!side_data) @@ -937,7 +1020,7 @@ static int encode_apng(AVCodecContext *avctx, AVPacket *pkt, AV_WB16(buf + 22, s->last_frame_fctl.delay_den); buf[24] = s->last_frame_fctl.dispose_op; buf[25] = s->last_frame_fctl.blend_op; - png_write_chunk(&last_fctl_chunk_start, MKTAG('f', 'c', 'T', 'L'), buf, 26); + png_write_chunk(&last_fctl_chunk_start, MKTAG('f', 'c', 'T', 'L'), buf, sizeof(buf)); *got_packet = 1; } @@ -1067,23 +1150,17 @@ static av_cold int png_enc_init(AVCodecContext *avctx) } s->bits_per_pixel = ff_png_get_nb_channels(s->color_type) * s->bit_depth; - s->zstream.zalloc = ff_png_zalloc; - s->zstream.zfree = ff_png_zfree; - s->zstream.opaque = NULL; compression_level = avctx->compression_level == FF_COMPRESSION_DEFAULT ? Z_DEFAULT_COMPRESSION : av_clip(avctx->compression_level, 0, 9); - if (deflateInit2(&s->zstream, compression_level, Z_DEFLATED, 15, 8, Z_DEFAULT_STRATEGY) != Z_OK) - return -1; - - return 0; + return ff_deflate_init(&s->zstream, compression_level, avctx); } static av_cold int png_enc_close(AVCodecContext *avctx) { PNGEncContext *s = avctx->priv_data; - deflateEnd(&s->zstream); + ff_deflate_end(&s->zstream); av_frame_free(&s->last_frame); av_frame_free(&s->prev_frame); av_freep(&s->last_frame_packet); @@ -1114,17 +1191,17 @@ static const AVClass pngenc_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_png_encoder = { - .name = "png", - .long_name = NULL_IF_CONFIG_SMALL("PNG (Portable Network Graphics) image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_PNG, +const FFCodec ff_png_encoder = { + .p.name = "png", + .p.long_name = NULL_IF_CONFIG_SMALL("PNG (Portable Network Graphics) image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_PNG, .priv_data_size = sizeof(PNGEncContext), .init = png_enc_init, .close = png_enc_close, - .encode2 = encode_png, - .capabilities = AV_CODEC_CAP_FRAME_THREADS, - .pix_fmts = (const enum AVPixelFormat[]) { + FF_CODEC_ENCODE_CB(encode_png), + .p.capabilities = AV_CODEC_CAP_FRAME_THREADS, + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, AV_PIX_FMT_RGB48BE, AV_PIX_FMT_RGBA64BE, AV_PIX_FMT_PAL8, @@ -1132,21 +1209,21 @@ const AVCodec ff_png_encoder = { AV_PIX_FMT_GRAY16BE, AV_PIX_FMT_YA16BE, AV_PIX_FMT_MONOBLACK, AV_PIX_FMT_NONE }, - .priv_class = &pngenc_class, + .p.priv_class = &pngenc_class, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; -const AVCodec ff_apng_encoder = { - .name = "apng", - .long_name = NULL_IF_CONFIG_SMALL("APNG (Animated Portable Network Graphics) image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_APNG, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, +const FFCodec ff_apng_encoder = { + .p.name = "apng", + .p.long_name = NULL_IF_CONFIG_SMALL("APNG (Animated Portable Network Graphics) image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_APNG, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, .priv_data_size = sizeof(PNGEncContext), .init = png_enc_init, .close = png_enc_close, - .encode2 = encode_apng, - .pix_fmts = (const enum AVPixelFormat[]) { + FF_CODEC_ENCODE_CB(encode_apng), + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, AV_PIX_FMT_RGB48BE, AV_PIX_FMT_RGBA64BE, AV_PIX_FMT_PAL8, @@ -1154,6 +1231,6 @@ const AVCodec ff_apng_encoder = { AV_PIX_FMT_GRAY16BE, AV_PIX_FMT_YA16BE, AV_PIX_FMT_NONE }, - .priv_class = &pngenc_class, + .p.priv_class = &pngenc_class, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/pnm.c b/libavcodec/pnm.c index 958f2a342..605a52962 100644 --- a/libavcodec/pnm.c +++ b/libavcodec/pnm.c @@ -73,18 +73,27 @@ int ff_pnm_decode_header(AVCodecContext *avctx, PNMContext * const s) (s->bytestream[1] < '1' || s->bytestream[1] > '7' && s->bytestream[1] != 'f' && - s->bytestream[1] != 'F')) { + s->bytestream[1] != 'F' && + s->bytestream[1] != 'H' && + s->bytestream[1] != 'h')) { s->bytestream += s->bytestream_end > s->bytestream; s->bytestream += s->bytestream_end > s->bytestream; return AVERROR_INVALIDDATA; } pnm_get(s, buf1, sizeof(buf1)); s->type= buf1[1]-'0'; + s->half = 0; if (buf1[1] == 'F') { avctx->pix_fmt = AV_PIX_FMT_GBRPF32; } else if (buf1[1] == 'f') { avctx->pix_fmt = AV_PIX_FMT_GRAYF32; + } else if (buf1[1] == 'H') { + avctx->pix_fmt = AV_PIX_FMT_GBRPF32; + s->half = 1; + } else if (buf1[1] == 'h') { + avctx->pix_fmt = AV_PIX_FMT_GRAYF32; + s->half = 1; } else if (s->type==1 || s->type==4) { avctx->pix_fmt = AV_PIX_FMT_MONOWHITE; } else if (s->type==2 || s->type==5) { diff --git a/libavcodec/pnm.h b/libavcodec/pnm.h index 89c3b5a2d..f109d1623 100644 --- a/libavcodec/pnm.h +++ b/libavcodec/pnm.h @@ -31,7 +31,12 @@ typedef struct PNMContext { int maxval; ///< maximum value of a pixel int type; int endian; + int half; float scale; + + uint32_t mantissatable[2048]; + uint32_t exponenttable[64]; + uint16_t offsettable[64]; } PNMContext; int ff_pnm_decode_header(AVCodecContext *avctx, PNMContext * const s); diff --git a/libavcodec/pnm_parser.c b/libavcodec/pnm_parser.c index 309bc76a2..6607ac7e7 100644 --- a/libavcodec/pnm_parser.c +++ b/libavcodec/pnm_parser.c @@ -111,6 +111,8 @@ retry: } else { int ret = av_image_get_buffer_size(avctx->pix_fmt, avctx->width, avctx->height, 1); next = pnmctx.bytestream - pnmctx.bytestream_start + skip; + if (ret > 0 && pnmctx.half) + ret >>= 1; if (ret >= 0 && next + (uint64_t)ret <= INT_MAX) next += ret; } @@ -133,7 +135,8 @@ end: const AVCodecParser ff_pnm_parser = { .codec_ids = { AV_CODEC_ID_PGM, AV_CODEC_ID_PGMYUV, AV_CODEC_ID_PPM, - AV_CODEC_ID_PBM, AV_CODEC_ID_PAM, AV_CODEC_ID_PFM }, + AV_CODEC_ID_PBM, AV_CODEC_ID_PAM, AV_CODEC_ID_PFM, + AV_CODEC_ID_PHM }, .priv_data_size = sizeof(PNMParseContext), .parser_parse = pnm_parse, .parser_close = ff_parse_close, diff --git a/libavcodec/pnmdec.c b/libavcodec/pnmdec.c index 01f9dade1..bb2ce5349 100644 --- a/libavcodec/pnmdec.c +++ b/libavcodec/pnmdec.c @@ -19,10 +19,14 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "put_bits.h" #include "pnm.h" +#include "half2float.h" static void samplecpy(uint8_t *dst, const uint8_t *src, int n, int maxval) { @@ -36,13 +40,12 @@ static void samplecpy(uint8_t *dst, const uint8_t *src, int n, int maxval) } } -static int pnm_decode_frame(AVCodecContext *avctx, void *data, +static int pnm_decode_frame(AVCodecContext *avctx, AVFrame *p, int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; PNMContext * const s = avctx->priv_data; - AVFrame * const p = data; int i, j, k, n, linesize, h, upgrade = 0, is_mono = 0; unsigned char *ptr; int components, sample_len, ret; @@ -256,6 +259,7 @@ static int pnm_decode_frame(AVCodecContext *avctx, void *data, } break; case AV_PIX_FMT_GBRPF32: + if (!s->half) { if (avctx->width * avctx->height * 12 > s->bytestream_end - s->bytestream) return AVERROR_INVALIDDATA; scale = 1.f / s->scale; @@ -296,8 +300,68 @@ static int pnm_decode_frame(AVCodecContext *avctx, void *data, b += p->linesize[1] / 4; } } + } else { + if (avctx->width * avctx->height * 6 > s->bytestream_end - s->bytestream) + return AVERROR_INVALIDDATA; + scale = 1.f / s->scale; + if (s->endian) { + float *r, *g, *b; + + r = (float *)p->data[2]; + g = (float *)p->data[0]; + b = (float *)p->data[1]; + for (int i = 0; i < avctx->height; i++) { + for (int j = 0; j < avctx->width; j++) { + r[j] = av_int2float(half2float(AV_RL16(s->bytestream+0), + s->mantissatable, + s->exponenttable, + s->offsettable)) * scale; + g[j] = av_int2float(half2float(AV_RL16(s->bytestream+2), + s->mantissatable, + s->exponenttable, + s->offsettable)) * scale; + b[j] = av_int2float(half2float(AV_RL16(s->bytestream+4), + s->mantissatable, + s->exponenttable, + s->offsettable)) * scale; + s->bytestream += 6; + } + + r += p->linesize[2] / 4; + g += p->linesize[0] / 4; + b += p->linesize[1] / 4; + } + } else { + float *r, *g, *b; + + r = (float *)p->data[2]; + g = (float *)p->data[0]; + b = (float *)p->data[1]; + for (int i = 0; i < avctx->height; i++) { + for (int j = 0; j < avctx->width; j++) { + r[j] = av_int2float(half2float(AV_RB16(s->bytestream+0), + s->mantissatable, + s->exponenttable, + s->offsettable)) * scale; + g[j] = av_int2float(half2float(AV_RB16(s->bytestream+2), + s->mantissatable, + s->exponenttable, + s->offsettable)) * scale; + b[j] = av_int2float(half2float(AV_RB16(s->bytestream+4), + s->mantissatable, + s->exponenttable, + s->offsettable)) * scale; + s->bytestream += 6; + } + + r += p->linesize[2] / 4; + g += p->linesize[0] / 4; + b += p->linesize[1] / 4; + } + } } break; case AV_PIX_FMT_GRAYF32: + if (!s->half) { if (avctx->width * avctx->height * 4 > s->bytestream_end - s->bytestream) return AVERROR_INVALIDDATA; scale = 1.f / s->scale; @@ -320,6 +384,36 @@ static int pnm_decode_frame(AVCodecContext *avctx, void *data, g += p->linesize[0] / 4; } } + } else { + if (avctx->width * avctx->height * 2 > s->bytestream_end - s->bytestream) + return AVERROR_INVALIDDATA; + scale = 1.f / s->scale; + if (s->endian) { + float *g = (float *)p->data[0]; + for (int i = 0; i < avctx->height; i++) { + for (int j = 0; j < avctx->width; j++) { + g[j] = av_int2float(half2float(AV_RL16(s->bytestream), + s->mantissatable, + s->exponenttable, + s->offsettable)) * scale; + s->bytestream += 2; + } + g += p->linesize[0] / 4; + } + } else { + float *g = (float *)p->data[0]; + for (int i = 0; i < avctx->height; i++) { + for (int j = 0; j < avctx->width; j++) { + g[j] = av_int2float(half2float(AV_RB16(s->bytestream), + s->mantissatable, + s->exponenttable, + s->offsettable)) * scale; + s->bytestream += 2; + } + g += p->linesize[0] / 4; + } + } + } break; } *got_frame = 1; @@ -329,73 +423,95 @@ static int pnm_decode_frame(AVCodecContext *avctx, void *data, #if CONFIG_PGM_DECODER -const AVCodec ff_pgm_decoder = { - .name = "pgm", - .long_name = NULL_IF_CONFIG_SMALL("PGM (Portable GrayMap) image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_PGM, +const FFCodec ff_pgm_decoder = { + .p.name = "pgm", + .p.long_name = NULL_IF_CONFIG_SMALL("PGM (Portable GrayMap) image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_PGM, + .p.capabilities = AV_CODEC_CAP_DR1, .priv_data_size = sizeof(PNMContext), - .decode = pnm_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(pnm_decode_frame), }; #endif #if CONFIG_PGMYUV_DECODER -const AVCodec ff_pgmyuv_decoder = { - .name = "pgmyuv", - .long_name = NULL_IF_CONFIG_SMALL("PGMYUV (Portable GrayMap YUV) image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_PGMYUV, +const FFCodec ff_pgmyuv_decoder = { + .p.name = "pgmyuv", + .p.long_name = NULL_IF_CONFIG_SMALL("PGMYUV (Portable GrayMap YUV) image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_PGMYUV, + .p.capabilities = AV_CODEC_CAP_DR1, .priv_data_size = sizeof(PNMContext), - .decode = pnm_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(pnm_decode_frame), }; #endif #if CONFIG_PPM_DECODER -const AVCodec ff_ppm_decoder = { - .name = "ppm", - .long_name = NULL_IF_CONFIG_SMALL("PPM (Portable PixelMap) image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_PPM, +const FFCodec ff_ppm_decoder = { + .p.name = "ppm", + .p.long_name = NULL_IF_CONFIG_SMALL("PPM (Portable PixelMap) image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_PPM, + .p.capabilities = AV_CODEC_CAP_DR1, .priv_data_size = sizeof(PNMContext), - .decode = pnm_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(pnm_decode_frame), }; #endif #if CONFIG_PBM_DECODER -const AVCodec ff_pbm_decoder = { - .name = "pbm", - .long_name = NULL_IF_CONFIG_SMALL("PBM (Portable BitMap) image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_PBM, +const FFCodec ff_pbm_decoder = { + .p.name = "pbm", + .p.long_name = NULL_IF_CONFIG_SMALL("PBM (Portable BitMap) image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_PBM, + .p.capabilities = AV_CODEC_CAP_DR1, .priv_data_size = sizeof(PNMContext), - .decode = pnm_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(pnm_decode_frame), }; #endif #if CONFIG_PAM_DECODER -const AVCodec ff_pam_decoder = { - .name = "pam", - .long_name = NULL_IF_CONFIG_SMALL("PAM (Portable AnyMap) image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_PAM, +const FFCodec ff_pam_decoder = { + .p.name = "pam", + .p.long_name = NULL_IF_CONFIG_SMALL("PAM (Portable AnyMap) image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_PAM, + .p.capabilities = AV_CODEC_CAP_DR1, .priv_data_size = sizeof(PNMContext), - .decode = pnm_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(pnm_decode_frame), }; #endif #if CONFIG_PFM_DECODER -const AVCodec ff_pfm_decoder = { - .name = "pfm", - .long_name = NULL_IF_CONFIG_SMALL("PFM (Portable FloatMap) image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_PFM, +const FFCodec ff_pfm_decoder = { + .p.name = "pfm", + .p.long_name = NULL_IF_CONFIG_SMALL("PFM (Portable FloatMap) image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_PFM, + .p.capabilities = AV_CODEC_CAP_DR1, .priv_data_size = sizeof(PNMContext), - .decode = pnm_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(pnm_decode_frame), +}; +#endif + +#if CONFIG_PHM_DECODER +static av_cold int phm_dec_init(AVCodecContext *avctx) +{ + PNMContext *s = avctx->priv_data; + + half2float_table(s->mantissatable, s->exponenttable, s->offsettable); + + return 0; +} + +const FFCodec ff_phm_decoder = { + .p.name = "phm", + .p.long_name = NULL_IF_CONFIG_SMALL("PHM (Portable HalfFloatMap) image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_PHM, + .p.capabilities = AV_CODEC_CAP_DR1, + .priv_data_size = sizeof(PNMContext), + .init = phm_dec_init, + FF_CODEC_DECODE_CB(pnm_decode_frame), }; #endif diff --git a/libavcodec/pnmenc.c b/libavcodec/pnmenc.c index 8378f90d0..db40f4b8e 100644 --- a/libavcodec/pnmenc.c +++ b/libavcodec/pnmenc.c @@ -19,16 +19,25 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/intreadwrite.h" #include "libavutil/imgutils.h" #include "libavutil/pixdesc.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" +#include "float2half.h" + +typedef struct PHMEncContext { + uint16_t basetable[512]; + uint8_t shifttable[512]; +} PHMEncContext; static int pnm_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *p, int *got_packet) { + PHMEncContext *s = avctx->priv_data; uint8_t *bytestream, *bytestream_start, *bytestream_end; int i, h, h1, c, n, linesize, ret; uint8_t *ptr, *ptr1, *ptr2; @@ -79,9 +88,25 @@ static int pnm_encode_frame(AVCodecContext *avctx, AVPacket *pkt, n = avctx->width * 2; h1 = (h * 3) / 2; break; - case AV_PIX_FMT_GBRPF32: + case AV_PIX_FMT_GBRPF32BE: + case AV_PIX_FMT_GBRPF32LE: + if (avctx->codec_id == AV_CODEC_ID_PFM) { c = 'F'; n = avctx->width * 4; + } else { + c = 'H'; + n = avctx->width * 2; + } + break; + case AV_PIX_FMT_GRAYF32BE: + case AV_PIX_FMT_GRAYF32LE: + if (avctx->codec_id == AV_CODEC_ID_PFM) { + c = 'f'; + n = avctx->width * 4; + } else { + c = 'h'; + n = avctx->width * 2; + } break; default: return -1; @@ -89,19 +114,27 @@ static int pnm_encode_frame(AVCodecContext *avctx, AVPacket *pkt, snprintf(bytestream, bytestream_end - bytestream, "P%c\n%d %d\n", c, avctx->width, h1); bytestream += strlen(bytestream); - if (avctx->pix_fmt == AV_PIX_FMT_GBRPF32) + if (avctx->pix_fmt == AV_PIX_FMT_GBRPF32LE || + avctx->pix_fmt == AV_PIX_FMT_GRAYF32LE || + avctx->pix_fmt == AV_PIX_FMT_GBRPF32BE || + avctx->pix_fmt == AV_PIX_FMT_GRAYF32BE) snprintf(bytestream, bytestream_end - bytestream, - "%f\n", avctx->pix_fmt == AV_PIX_FMT_GBRPF32BE ? 1.f: -1.f); + "%f\n", (avctx->pix_fmt == AV_PIX_FMT_GBRPF32BE || + avctx->pix_fmt == AV_PIX_FMT_GRAYF32BE) ? 1.f: -1.f); bytestream += strlen(bytestream); if (avctx->pix_fmt != AV_PIX_FMT_MONOWHITE && - avctx->pix_fmt != AV_PIX_FMT_GBRPF32) { + avctx->pix_fmt != AV_PIX_FMT_GBRPF32LE && + avctx->pix_fmt != AV_PIX_FMT_GRAYF32LE && + avctx->pix_fmt != AV_PIX_FMT_GBRPF32BE && + avctx->pix_fmt != AV_PIX_FMT_GRAYF32BE) { int maxdepth = (1 << av_pix_fmt_desc_get(avctx->pix_fmt)->comp[0].depth) - 1; snprintf(bytestream, bytestream_end - bytestream, "%d\n", maxdepth); bytestream += strlen(bytestream); } - if (avctx->pix_fmt == AV_PIX_FMT_GBRPF32) { + if ((avctx->pix_fmt == AV_PIX_FMT_GBRPF32LE || + avctx->pix_fmt == AV_PIX_FMT_GBRPF32BE) && c == 'F') { float *r = (float *)p->data[2]; float *g = (float *)p->data[0]; float *b = (float *)p->data[1]; @@ -118,14 +151,54 @@ static int pnm_encode_frame(AVCodecContext *avctx, AVPacket *pkt, g += p->linesize[0] / 4; b += p->linesize[1] / 4; } + } else if ((avctx->pix_fmt == AV_PIX_FMT_GRAYF32LE || + avctx->pix_fmt == AV_PIX_FMT_GRAYF32BE) && c == 'f') { + const float *g = (const float *)p->data[0]; + + for (int i = 0; i < avctx->height; i++) { + for (int j = 0; j < avctx->width; j++) { + AV_WN32(bytestream, av_float2int(g[j])); + bytestream += 4; + } + + g += p->linesize[0] / 4; + } + } else if (avctx->pix_fmt == AV_PIX_FMT_GBRPF32 && c == 'H') { + float *r = (float *)p->data[2]; + float *g = (float *)p->data[0]; + float *b = (float *)p->data[1]; + + for (int i = 0; i < avctx->height; i++) { + for (int j = 0; j < avctx->width; j++) { + AV_WN16(bytestream + 0, float2half(av_float2int(r[j]), s->basetable, s->shifttable)); + AV_WN16(bytestream + 2, float2half(av_float2int(g[j]), s->basetable, s->shifttable)); + AV_WN16(bytestream + 4, float2half(av_float2int(b[j]), s->basetable, s->shifttable)); + bytestream += 6; + } + + r += p->linesize[2] / 4; + g += p->linesize[0] / 4; + b += p->linesize[1] / 4; + } + } else if (avctx->pix_fmt == AV_PIX_FMT_GRAYF32 && c == 'h') { + const float *g = (const float *)p->data[0]; + + for (int i = 0; i < avctx->height; i++) { + for (int j = 0; j < avctx->width; j++) { + AV_WN16(bytestream, float2half(av_float2int(g[j]), s->basetable, s->shifttable)); + bytestream += 2; + } + + g += p->linesize[0] / 4; + } } else { - ptr = p->data[0]; - linesize = p->linesize[0]; - for (i = 0; i < h; i++) { - memcpy(bytestream, ptr, n); - bytestream += n; - ptr += linesize; - } + ptr = p->data[0]; + linesize = p->linesize[0]; + for (i = 0; i < h; i++) { + memcpy(bytestream, ptr, n); + bytestream += n; + ptr += linesize; + } } if (avctx->pix_fmt == AV_PIX_FMT_YUV420P || avctx->pix_fmt == AV_PIX_FMT_YUV420P16BE) { @@ -149,14 +222,14 @@ static int pnm_encode_frame(AVCodecContext *avctx, AVPacket *pkt, } #if CONFIG_PGM_ENCODER -const AVCodec ff_pgm_encoder = { - .name = "pgm", - .long_name = NULL_IF_CONFIG_SMALL("PGM (Portable GrayMap) image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_PGM, - .capabilities = AV_CODEC_CAP_DR1, - .encode2 = pnm_encode_frame, - .pix_fmts = (const enum AVPixelFormat[]){ +const FFCodec ff_pgm_encoder = { + .p.name = "pgm", + .p.long_name = NULL_IF_CONFIG_SMALL("PGM (Portable GrayMap) image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_PGM, + .p.capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_ENCODE_CB(pnm_encode_frame), + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY16BE, AV_PIX_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, @@ -164,14 +237,14 @@ const AVCodec ff_pgm_encoder = { #endif #if CONFIG_PGMYUV_ENCODER -const AVCodec ff_pgmyuv_encoder = { - .name = "pgmyuv", - .long_name = NULL_IF_CONFIG_SMALL("PGMYUV (Portable GrayMap YUV) image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_PGMYUV, - .capabilities = AV_CODEC_CAP_DR1, - .encode2 = pnm_encode_frame, - .pix_fmts = (const enum AVPixelFormat[]){ +const FFCodec ff_pgmyuv_encoder = { + .p.name = "pgmyuv", + .p.long_name = NULL_IF_CONFIG_SMALL("PGMYUV (Portable GrayMap YUV) image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_PGMYUV, + .p.capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_ENCODE_CB(pnm_encode_frame), + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P16BE, AV_PIX_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, @@ -179,14 +252,14 @@ const AVCodec ff_pgmyuv_encoder = { #endif #if CONFIG_PPM_ENCODER -const AVCodec ff_ppm_encoder = { - .name = "ppm", - .long_name = NULL_IF_CONFIG_SMALL("PPM (Portable PixelMap) image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_PPM, - .capabilities = AV_CODEC_CAP_DR1, - .encode2 = pnm_encode_frame, - .pix_fmts = (const enum AVPixelFormat[]){ +const FFCodec ff_ppm_encoder = { + .p.name = "ppm", + .p.long_name = NULL_IF_CONFIG_SMALL("PPM (Portable PixelMap) image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_PPM, + .p.capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_ENCODE_CB(pnm_encode_frame), + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_RGB24, AV_PIX_FMT_RGB48BE, AV_PIX_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, @@ -194,28 +267,57 @@ const AVCodec ff_ppm_encoder = { #endif #if CONFIG_PBM_ENCODER -const AVCodec ff_pbm_encoder = { - .name = "pbm", - .long_name = NULL_IF_CONFIG_SMALL("PBM (Portable BitMap) image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_PBM, - .capabilities = AV_CODEC_CAP_DR1, - .encode2 = pnm_encode_frame, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_MONOWHITE, +const FFCodec ff_pbm_encoder = { + .p.name = "pbm", + .p.long_name = NULL_IF_CONFIG_SMALL("PBM (Portable BitMap) image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_PBM, + .p.capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_ENCODE_CB(pnm_encode_frame), + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_MONOWHITE, AV_PIX_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_PFM_ENCODER -const AVCodec ff_pfm_encoder = { - .name = "pfm", - .long_name = NULL_IF_CONFIG_SMALL("PFM (Portable FloatMap) image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_PFM, - .capabilities = AV_CODEC_CAP_DR1, - .encode2 = pnm_encode_frame, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_GBRPF32, +const FFCodec ff_pfm_encoder = { + .p.name = "pfm", + .p.long_name = NULL_IF_CONFIG_SMALL("PFM (Portable FloatMap) image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_PFM, + .p.capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_ENCODE_CB(pnm_encode_frame), + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_GBRPF32LE, + AV_PIX_FMT_GRAYF32LE, + AV_PIX_FMT_GBRPF32BE, + AV_PIX_FMT_GRAYF32BE, + AV_PIX_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, +}; +#endif + +#if CONFIG_PHM_ENCODER +static av_cold int phm_enc_init(AVCodecContext *avctx) +{ + PHMEncContext *s = avctx->priv_data; + + float2half_tables(s->basetable, s->shifttable); + + return 0; +} + +const FFCodec ff_phm_encoder = { + .p.name = "phm", + .p.long_name = NULL_IF_CONFIG_SMALL("PHM (Portable HalfFloatMap) image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_PHM, + .p.capabilities = AV_CODEC_CAP_DR1, + .priv_data_size = sizeof(PHMEncContext), + .init = phm_enc_init, + FF_CODEC_ENCODE_CB(pnm_encode_frame), + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_GBRPF32, + AV_PIX_FMT_GRAYF32, AV_PIX_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/prores_metadata_bsf.c b/libavcodec/prores_metadata_bsf.c index d971243a8..fb001b38d 100644 --- a/libavcodec/prores_metadata_bsf.c +++ b/libavcodec/prores_metadata_bsf.c @@ -166,11 +166,11 @@ static const AVClass prores_metadata_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVBitStreamFilter ff_prores_metadata_bsf = { - .name = "prores_metadata", - .init = prores_metadata_init, - .filter = prores_metadata, +const FFBitStreamFilter ff_prores_metadata_bsf = { + .p.name = "prores_metadata", + .p.codec_ids = codec_ids, + .p.priv_class = &prores_metadata_class, .priv_data_size = sizeof(ProresMetadataContext), - .priv_class = &prores_metadata_class, - .codec_ids = codec_ids, + .init = prores_metadata_init, + .filter = prores_metadata, }; diff --git a/libavcodec/proresdec2.c b/libavcodec/proresdec2.c index d2d881a3d..385ca2fb1 100644 --- a/libavcodec/proresdec2.c +++ b/libavcodec/proresdec2.c @@ -21,17 +21,20 @@ /** * @file - * Known FOURCCs: 'apch' (HQ), 'apcn' (SD), 'apcs' (LT), 'acpo' (Proxy), 'ap4h' (4444) + * Known FOURCCs: 'apch' (HQ), 'apcn' (SD), 'apcs' (LT), 'apco' (Proxy), 'ap4h' (4444), 'ap4x' (4444 XQ) */ //#define DEBUG #define LONG_BITSTREAM_READER +#include "config_components.h" + #include "libavutil/internal.h" #include "libavutil/mem_internal.h" #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" #include "hwconfig.h" #include "idctdsp.h" @@ -775,12 +778,10 @@ static int decode_picture(AVCodecContext *avctx) return ctx->slices[0].ret; } -static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { ProresContext *ctx = avctx->priv_data; - ThreadFrame tframe = { .f = data }; - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; int frame_hdr_size, pic_size, ret; @@ -805,7 +806,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, buf += frame_hdr_size; buf_size -= frame_hdr_size; - if ((ret = ff_thread_get_buffer(avctx, &tframe, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, frame, 0)) < 0) return ret; ff_thread_finish_setup(avctx); @@ -869,18 +870,18 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src) } #endif -const AVCodec ff_prores_decoder = { - .name = "prores", - .long_name = NULL_IF_CONFIG_SMALL("Apple ProRes (iCodec Pro)"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_PRORES, +const FFCodec ff_prores_decoder = { + .p.name = "prores", + .p.long_name = NULL_IF_CONFIG_SMALL("Apple ProRes (iCodec Pro)"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_PRORES, .priv_data_size = sizeof(ProresContext), .init = decode_init, .close = decode_close, - .decode = decode_frame, + FF_CODEC_DECODE_CB(decode_frame), .update_thread_context = ONLY_IF_THREADS_ENABLED(update_thread_context), - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS, - .profiles = NULL_IF_CONFIG_SMALL(ff_prores_profiles), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS, + .p.profiles = NULL_IF_CONFIG_SMALL(ff_prores_profiles), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, .hw_configs = (const AVCodecHWConfigInternal *const []) { #if CONFIG_PRORES_VIDEOTOOLBOX_HWACCEL diff --git a/libavcodec/proresdsp.c b/libavcodec/proresdsp.c index a3c618cdd..6ed01179f 100644 --- a/libavcodec/proresdsp.c +++ b/libavcodec/proresdsp.c @@ -88,8 +88,9 @@ av_cold int ff_proresdsp_init(ProresDSPContext *dsp, AVCodecContext *avctx) return AVERROR_BUG; } - if (ARCH_X86) - ff_proresdsp_init_x86(dsp, avctx); +#if ARCH_X86 + ff_proresdsp_init_x86(dsp, avctx); +#endif ff_init_scantable_permutation(dsp->idct_permutation, dsp->idct_permutation_type); diff --git a/libavcodec/proresenc_anatoliy.c b/libavcodec/proresenc_anatoliy.c index b7e00f208..914c3fb2c 100644 --- a/libavcodec/proresenc_anatoliy.c +++ b/libavcodec/proresenc_anatoliy.c @@ -30,6 +30,7 @@ #include "libavutil/mem_internal.h" #include "libavutil/opt.h" #include "avcodec.h" +#include "codec_internal.h" #include "dct.h" #include "encode.h" #include "internal.h" @@ -939,34 +940,34 @@ static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_NONE }; -const AVCodec ff_prores_aw_encoder = { - .name = "prores_aw", - .long_name = NULL_IF_CONFIG_SMALL("Apple ProRes"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_PRORES, - .pix_fmts = pix_fmts, +const FFCodec ff_prores_aw_encoder = { + .p.name = "prores_aw", + .p.long_name = NULL_IF_CONFIG_SMALL("Apple ProRes"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_PRORES, + .p.pix_fmts = pix_fmts, .priv_data_size = sizeof(ProresContext), .init = prores_encode_init, .close = prores_encode_close, - .encode2 = prores_encode_frame, - .capabilities = AV_CODEC_CAP_FRAME_THREADS, - .priv_class = &prores_enc_class, - .profiles = NULL_IF_CONFIG_SMALL(ff_prores_profiles), + FF_CODEC_ENCODE_CB(prores_encode_frame), + .p.capabilities = AV_CODEC_CAP_FRAME_THREADS, + .p.priv_class = &prores_enc_class, + .p.profiles = NULL_IF_CONFIG_SMALL(ff_prores_profiles), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; -const AVCodec ff_prores_encoder = { - .name = "prores", - .long_name = NULL_IF_CONFIG_SMALL("Apple ProRes"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_PRORES, - .pix_fmts = pix_fmts, +const FFCodec ff_prores_encoder = { + .p.name = "prores", + .p.long_name = NULL_IF_CONFIG_SMALL("Apple ProRes"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_PRORES, + .p.pix_fmts = pix_fmts, .priv_data_size = sizeof(ProresContext), .init = prores_encode_init, .close = prores_encode_close, - .encode2 = prores_encode_frame, - .capabilities = AV_CODEC_CAP_FRAME_THREADS, - .priv_class = &prores_enc_class, - .profiles = NULL_IF_CONFIG_SMALL(ff_prores_profiles), + FF_CODEC_ENCODE_CB(prores_encode_frame), + .p.capabilities = AV_CODEC_CAP_FRAME_THREADS, + .p.priv_class = &prores_enc_class, + .p.profiles = NULL_IF_CONFIG_SMALL(ff_prores_profiles), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/proresenc_kostya.c b/libavcodec/proresenc_kostya.c index 85651fce2..1062ca144 100644 --- a/libavcodec/proresenc_kostya.c +++ b/libavcodec/proresenc_kostya.c @@ -27,12 +27,12 @@ #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" #include "fdctdsp.h" #include "put_bits.h" #include "profiles.h" #include "bytestream.h" -#include "internal.h" #include "proresdata.h" #define CFACTOR_Y422 2 @@ -1273,26 +1273,20 @@ static av_cold int encode_init(AVCodecContext *avctx) } } - ctx->slice_q = av_malloc(ctx->slices_per_picture * sizeof(*ctx->slice_q)); - if (!ctx->slice_q) { - encode_close(avctx); + ctx->slice_q = av_malloc_array(ctx->slices_per_picture, sizeof(*ctx->slice_q)); + if (!ctx->slice_q) return AVERROR(ENOMEM); - } - ctx->tdata = av_mallocz(avctx->thread_count * sizeof(*ctx->tdata)); - if (!ctx->tdata) { - encode_close(avctx); + ctx->tdata = av_calloc(avctx->thread_count, sizeof(*ctx->tdata)); + if (!ctx->tdata) return AVERROR(ENOMEM); - } for (j = 0; j < avctx->thread_count; j++) { - ctx->tdata[j].nodes = av_malloc((ctx->slices_width + 1) - * TRELLIS_WIDTH - * sizeof(*ctx->tdata->nodes)); - if (!ctx->tdata[j].nodes) { - encode_close(avctx); + ctx->tdata[j].nodes = av_malloc_array(ctx->slices_width + 1, + TRELLIS_WIDTH + * sizeof(*ctx->tdata->nodes)); + if (!ctx->tdata[j].nodes) return AVERROR(ENOMEM); - } for (i = min_quant; i < max_quant + 2; i++) { ctx->tdata[j].nodes[i].prev_node = -1; ctx->tdata[j].nodes[i].bits = 0; @@ -1399,21 +1393,21 @@ static const AVClass proresenc_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_prores_ks_encoder = { - .name = "prores_ks", - .long_name = NULL_IF_CONFIG_SMALL("Apple ProRes (iCodec Pro)"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_PRORES, +const FFCodec ff_prores_ks_encoder = { + .p.name = "prores_ks", + .p.long_name = NULL_IF_CONFIG_SMALL("Apple ProRes (iCodec Pro)"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_PRORES, .priv_data_size = sizeof(ProresContext), .init = encode_init, .close = encode_close, - .encode2 = encode_frame, - .capabilities = AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS, - .pix_fmts = (const enum AVPixelFormat[]) { + FF_CODEC_ENCODE_CB(encode_frame), + .p.capabilities = AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS, + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_NONE }, - .priv_class = &proresenc_class, - .profiles = NULL_IF_CONFIG_SMALL(ff_prores_profiles), - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + .p.priv_class = &proresenc_class, + .p.profiles = NULL_IF_CONFIG_SMALL(ff_prores_profiles), + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/prosumer.c b/libavcodec/prosumer.c index f57d8dda4..8a91d5e11 100644 --- a/libavcodec/prosumer.c +++ b/libavcodec/prosumer.c @@ -30,6 +30,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" typedef struct ProSumerContext { @@ -143,11 +144,10 @@ static void vertical_predict(uint32_t *dst, int offset, const uint32_t *src, int } } -static int decode_frame(AVCodecContext *avctx, void *data, +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt) { ProSumerContext *s = avctx->priv_data; - AVFrame * const frame = data; int ret; if (avpkt->size <= 32) @@ -365,16 +365,16 @@ static av_cold int decode_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_prosumer_decoder = { - .name = "prosumer", - .long_name = NULL_IF_CONFIG_SMALL("Brooktree ProSumer Video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_PROSUMER, +const FFCodec ff_prosumer_decoder = { + .p.name = "prosumer", + .p.long_name = NULL_IF_CONFIG_SMALL("Brooktree ProSumer Video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_PROSUMER, .priv_data_size = sizeof(ProSumerContext), .init = decode_init, - .decode = decode_frame, + FF_CODEC_DECODE_CB(decode_frame), .close = decode_close, - .capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/psd.c b/libavcodec/psd.c index 681d8a83c..1d9216340 100644 --- a/libavcodec/psd.c +++ b/libavcodec/psd.c @@ -20,6 +20,7 @@ */ #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" enum PsdCompr { @@ -288,7 +289,7 @@ static int decode_rle(PSDContext * s){ return 0; } -static int decode_frame(AVCodecContext *avctx, void *data, +static int decode_frame(AVCodecContext *avctx, AVFrame *picture, int *got_frame, AVPacket *avpkt) { int ret; @@ -298,8 +299,6 @@ static int decode_frame(AVCodecContext *avctx, void *data, uint8_t eq_channel[4] = {2,0,1,3};/* RGBA -> GBRA channel order */ uint8_t plane_number; - AVFrame *picture = data; - PSDContext *s = avctx->priv_data; s->avctx = avctx; s->channel_count = 0; @@ -545,12 +544,12 @@ static int decode_frame(AVCodecContext *avctx, void *data, return avpkt->size; } -const AVCodec ff_psd_decoder = { - .name = "psd", - .long_name = NULL_IF_CONFIG_SMALL("Photoshop PSD file"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_PSD, +const FFCodec ff_psd_decoder = { + .p.name = "psd", + .p.long_name = NULL_IF_CONFIG_SMALL("Photoshop PSD file"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_PSD, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, .priv_data_size = sizeof(PSDContext), - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + FF_CODEC_DECODE_CB(decode_frame), }; diff --git a/libavcodec/psymodel.c b/libavcodec/psymodel.c index 93c840829..890b13e1c 100644 --- a/libavcodec/psymodel.c +++ b/libavcodec/psymodel.c @@ -35,7 +35,7 @@ av_cold int ff_psy_init(FFPsyContext *ctx, AVCodecContext *avctx, int num_lens, int i, j, k = 0; ctx->avctx = avctx; - ctx->ch = av_calloc(avctx->channels, 2 * sizeof(ctx->ch[0])); + ctx->ch = av_calloc(avctx->ch_layout.nb_channels, 2 * sizeof(ctx->ch[0])); ctx->group = av_calloc(num_groups, sizeof(ctx->group[0])); ctx->bands = av_malloc_array (sizeof(ctx->bands[0]), num_lens); ctx->num_bands = av_malloc_array (sizeof(ctx->num_bands[0]), num_lens); @@ -120,13 +120,13 @@ av_cold struct FFPsyPreprocessContext* ff_psy_preprocess_init(AVCodecContext *av FF_FILTER_MODE_LOWPASS, FILT_ORDER, cutoff_coeff, 0.0, 0.0); if (ctx->fcoeffs) { - ctx->fstate = av_calloc(avctx->channels, sizeof(ctx->fstate[0])); + ctx->fstate = av_calloc(avctx->ch_layout.nb_channels, sizeof(ctx->fstate[0])); if (!ctx->fstate) { av_free(ctx->fcoeffs); av_free(ctx); return NULL; } - for (i = 0; i < avctx->channels; i++) + for (i = 0; i < avctx->ch_layout.nb_channels; i++) ctx->fstate[i] = ff_iir_filter_init_state(FILT_ORDER); } } @@ -154,7 +154,7 @@ av_cold void ff_psy_preprocess_end(struct FFPsyPreprocessContext *ctx) int i; ff_iir_filter_free_coeffsp(&ctx->fcoeffs); if (ctx->fstate) - for (i = 0; i < ctx->avctx->channels; i++) + for (i = 0; i < ctx->avctx->ch_layout.nb_channels; i++) ff_iir_filter_free_statep(&ctx->fstate[i]); av_freep(&ctx->fstate); av_free(ctx); diff --git a/libavcodec/psymodel.h b/libavcodec/psymodel.h index e5f917d49..22899a38d 100644 --- a/libavcodec/psymodel.h +++ b/libavcodec/psymodel.h @@ -41,7 +41,7 @@ #define AAC_CUTOFF(s) ( \ (s->flags & AV_CODEC_FLAG_QSCALE) \ ? s->sample_rate / 2 \ - : AAC_CUTOFF_FROM_BITRATE(s->bit_rate, s->channels, s->sample_rate) \ + : AAC_CUTOFF_FROM_BITRATE(s->bit_rate, s->ch_layout.nb_channels, s->sample_rate) \ ) /** diff --git a/libavcodec/pthread.c b/libavcodec/pthread.c index 5adc3c43a..60ba87dac 100644 --- a/libavcodec/pthread.c +++ b/libavcodec/pthread.c @@ -32,7 +32,7 @@ #include "libavutil/thread.h" #include "avcodec.h" -#include "internal.h" +#include "codec_internal.h" #include "pthread_internal.h" #include "thread.h" @@ -60,7 +60,7 @@ static void validate_thread_parameters(AVCodecContext *avctx) } else if (avctx->codec->capabilities & AV_CODEC_CAP_SLICE_THREADS && avctx->thread_type & FF_THREAD_SLICE) { avctx->active_thread_type = FF_THREAD_SLICE; - } else if (!(avctx->codec->caps_internal & FF_CODEC_CAP_AUTO_THREADS)) { + } else if (!(ffcodec(avctx->codec)->caps_internal & FF_CODEC_CAP_AUTO_THREADS)) { avctx->thread_count = 1; avctx->active_thread_type = 0; } diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c index 85a6bc98c..8faea75a4 100644 --- a/libavcodec/pthread_frame.c +++ b/libavcodec/pthread_frame.c @@ -28,11 +28,13 @@ #include #include "avcodec.h" +#include "codec_internal.h" #include "hwconfig.h" #include "internal.h" #include "pthread_internal.h" #include "thread.h" -#include "version.h" +#include "threadframe.h" +#include "version_major.h" #include "libavutil/avassert.h" #include "libavutil/buffer.h" @@ -66,7 +68,7 @@ enum { enum { UNINITIALIZED, ///< Thread has not been created, AVCodec->close mustn't be called - NEEDS_CLOSE, ///< AVCodec->close needs to be called + NEEDS_CLOSE, ///< FFCodec->close needs to be called INITIALIZED, ///< Thread has been properly set up }; @@ -181,7 +183,7 @@ static attribute_align_arg void *frame_worker_thread(void *arg) { PerThreadContext *p = arg; AVCodecContext *avctx = p->avctx; - const AVCodec *codec = avctx->codec; + const FFCodec *codec = ffcodec(avctx->codec); pthread_mutex_lock(&p->mutex); while (1) { @@ -216,14 +218,10 @@ FF_ENABLE_DEPRECATION_WARNINGS av_frame_unref(p->frame); p->got_frame = 0; - p->result = codec->decode(avctx, p->frame, &p->got_frame, p->avpkt); + p->result = codec->cb.decode(avctx, p->frame, &p->got_frame, p->avpkt); - if ((p->result < 0 || !p->got_frame) && p->frame->buf[0]) { - if (avctx->codec->caps_internal & FF_CODEC_CAP_ALLOCATE_PROGRESS) - av_log(avctx, AV_LOG_ERROR, "A frame threaded decoder did not " - "free the frame on failure. This is a bug, please report it.\n"); - av_frame_unref(p->frame); - } + if ((p->result < 0 || !p->got_frame) && p->frame->buf[0]) + ff_thread_release_buffer(avctx, p->frame); if (atomic_load(&p->state) == STATE_SETTING_UP) ff_thread_finish_setup(avctx); @@ -262,9 +260,10 @@ FF_ENABLE_DEPRECATION_WARNINGS */ static int update_context_from_thread(AVCodecContext *dst, AVCodecContext *src, int for_user) { + const FFCodec *const codec = ffcodec(dst->codec); int err = 0; - if (dst != src && (for_user || src->codec->update_thread_context)) { + if (dst != src && (for_user || codec->update_thread_context)) { dst->time_base = src->time_base; dst->framerate = src->framerate; dst->width = src->width; @@ -297,10 +296,18 @@ static int update_context_from_thread(AVCodecContext *dst, AVCodecContext *src, dst->hwaccel = src->hwaccel; dst->hwaccel_context = src->hwaccel_context; - dst->channels = src->channels; dst->sample_rate = src->sample_rate; dst->sample_fmt = src->sample_fmt; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + dst->channels = src->channels; dst->channel_layout = src->channel_layout; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + err = av_channel_layout_copy(&dst->ch_layout, &src->ch_layout); + if (err < 0) + return err; + dst->internal->hwaccel_priv_data = src->internal->hwaccel_priv_data; if (!!dst->hw_frames_ctx != !!src->hw_frames_ctx || @@ -322,11 +329,11 @@ static int update_context_from_thread(AVCodecContext *dst, AVCodecContext *src, } if (for_user) { - if (dst->codec->update_thread_context_for_user) - err = dst->codec->update_thread_context_for_user(dst, src); + if (codec->update_thread_context_for_user) + err = codec->update_thread_context_for_user(dst, src); } else { - if (dst->codec->update_thread_context) - err = dst->codec->update_thread_context(dst, src); + if (codec->update_thread_context) + err = codec->update_thread_context(dst, src); } return err; @@ -695,7 +702,7 @@ DEFINE_OFFSET_ARRAY(PerThreadContext, per_thread, pthread_init_cnt, void ff_frame_thread_free(AVCodecContext *avctx, int thread_count) { FrameThreadContext *fctx = avctx->internal->thread_ctx; - const AVCodec *codec = avctx->codec; + const FFCodec *codec = ffcodec(avctx->codec); int i; park_frame_worker_threads(fctx, thread_count); @@ -707,13 +714,6 @@ void ff_frame_thread_free(AVCodecContext *avctx, int thread_count) } } - if (fctx->prev_thread && fctx->prev_thread != fctx->threads) - if (update_context_from_thread(fctx->threads->avctx, fctx->prev_thread->avctx, 0) < 0) { - av_log(avctx, AV_LOG_ERROR, "Final thread update failed\n"); - fctx->prev_thread->avctx->internal->is_copy = fctx->threads->avctx->internal->is_copy; - fctx->threads->avctx->internal->is_copy = 1; - } - for (i = 0; i < thread_count; i++) { PerThreadContext *p = &fctx->threads[i]; AVCodecContext *ctx = p->avctx; @@ -737,7 +737,7 @@ void ff_frame_thread_free(AVCodecContext *avctx, int thread_count) av_freep(&p->released_buffers); #endif if (ctx->priv_data) { - if (codec->priv_class) + if (codec->p.priv_class) av_opt_free(ctx->priv_data); av_freep(&ctx->priv_data); } @@ -765,7 +765,7 @@ void ff_frame_thread_free(AVCodecContext *avctx, int thread_count) static av_cold int init_thread(PerThreadContext *p, int *threads_to_free, FrameThreadContext *fctx, AVCodecContext *avctx, - const AVCodec *codec, int first) + const FFCodec *codec, int first) { AVCodecContext *copy; int err; @@ -784,7 +784,7 @@ static av_cold int init_thread(PerThreadContext *p, int *threads_to_free, p->parent = fctx; p->avctx = copy; - copy->internal = av_memdup(avctx->internal, sizeof(*avctx->internal)); + copy->internal = av_mallocz(sizeof(*copy->internal)); if (!copy->internal) return AVERROR(ENOMEM); copy->internal->thread_ctx = p; @@ -796,8 +796,8 @@ static av_cold int init_thread(PerThreadContext *p, int *threads_to_free, if (!copy->priv_data) return AVERROR(ENOMEM); - if (codec->priv_class) { - *(const AVClass **)copy->priv_data = codec->priv_class; + if (codec->p.priv_class) { + *(const AVClass **)copy->priv_data = codec->p.priv_class; err = av_opt_copy(copy->priv_data, avctx->priv_data); if (err < 0) return err; @@ -842,7 +842,7 @@ static av_cold int init_thread(PerThreadContext *p, int *threads_to_free, int ff_frame_thread_init(AVCodecContext *avctx) { int thread_count = avctx->thread_count; - const AVCodec *codec = avctx->codec; + const FFCodec *codec = ffcodec(avctx->codec); FrameThreadContext *fctx; int err, i = 0; @@ -874,7 +874,7 @@ int ff_frame_thread_init(AVCodecContext *avctx) fctx->async_lock = 1; fctx->delaying = 1; - if (codec->type == AVMEDIA_TYPE_VIDEO) + if (codec->p.type == AVMEDIA_TYPE_VIDEO) avctx->delay = avctx->thread_count - 1; fctx->threads = av_calloc(thread_count, sizeof(*fctx->threads)); @@ -926,8 +926,8 @@ void ff_thread_flush(AVCodecContext *avctx) release_delayed_buffers(p); #endif - if (avctx->codec->flush) - avctx->codec->flush(p->avctx); + if (ffcodec(avctx->codec)->flush) + ffcodec(avctx->codec)->flush(p->avctx); } } @@ -936,7 +936,7 @@ int ff_thread_can_start_frame(AVCodecContext *avctx) PerThreadContext *p = avctx->internal->thread_ctx; FF_DISABLE_DEPRECATION_WARNINGS if ((avctx->active_thread_type&FF_THREAD_FRAME) && atomic_load(&p->state) != STATE_SETTING_UP && - (avctx->codec->update_thread_context + (ffcodec(avctx->codec)->update_thread_context #if FF_API_THREAD_SAFE_CALLBACKS || !THREAD_SAFE_CALLBACKS(avctx) #endif @@ -947,19 +947,18 @@ FF_ENABLE_DEPRECATION_WARNINGS return 1; } -static int thread_get_buffer_internal(AVCodecContext *avctx, ThreadFrame *f, int flags) +static int thread_get_buffer_internal(AVCodecContext *avctx, AVFrame *f, int flags) { - PerThreadContext *p = avctx->internal->thread_ctx; + PerThreadContext *p; int err; - f->owner[0] = f->owner[1] = avctx; - if (!(avctx->active_thread_type & FF_THREAD_FRAME)) - return ff_get_buffer(avctx, f->f, flags); + return ff_get_buffer(avctx, f, flags); + p = avctx->internal->thread_ctx; FF_DISABLE_DEPRECATION_WARNINGS if (atomic_load(&p->state) != STATE_SETTING_UP && - (avctx->codec->update_thread_context + (ffcodec(avctx->codec)->update_thread_context #if FF_API_THREAD_SAFE_CALLBACKS || !THREAD_SAFE_CALLBACKS(avctx) #endif @@ -969,28 +968,16 @@ FF_ENABLE_DEPRECATION_WARNINGS return -1; } - if (avctx->codec->caps_internal & FF_CODEC_CAP_ALLOCATE_PROGRESS) { - atomic_int *progress; - f->progress = av_buffer_alloc(2 * sizeof(*progress)); - if (!f->progress) { - return AVERROR(ENOMEM); - } - progress = (atomic_int*)f->progress->data; - - atomic_init(&progress[0], -1); - atomic_init(&progress[1], -1); - } - pthread_mutex_lock(&p->parent->buffer_mutex); #if !FF_API_THREAD_SAFE_CALLBACKS err = ff_get_buffer(avctx, f->f, flags); #else FF_DISABLE_DEPRECATION_WARNINGS if (THREAD_SAFE_CALLBACKS(avctx)) { - err = ff_get_buffer(avctx, f->f, flags); + err = ff_get_buffer(avctx, f, flags); } else { pthread_mutex_lock(&p->progress_mutex); - p->requested_frame = f->f; + p->requested_frame = f; p->requested_flags = flags; atomic_store_explicit(&p->state, STATE_GET_BUFFER, memory_order_release); pthread_cond_broadcast(&p->progress_cond); @@ -1003,12 +990,10 @@ FF_DISABLE_DEPRECATION_WARNINGS pthread_mutex_unlock(&p->progress_mutex); } - if (!THREAD_SAFE_CALLBACKS(avctx) && !avctx->codec->update_thread_context) + if (!THREAD_SAFE_CALLBACKS(avctx) && !ffcodec(avctx->codec)->update_thread_context) ff_thread_finish_setup(avctx); FF_ENABLE_DEPRECATION_WARNINGS #endif - if (err) - av_buffer_unref(&f->progress); pthread_mutex_unlock(&p->parent->buffer_mutex); @@ -1020,10 +1005,12 @@ FF_DISABLE_DEPRECATION_WARNINGS enum AVPixelFormat ff_thread_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt) { enum AVPixelFormat res; - PerThreadContext *p = avctx->internal->thread_ctx; + PerThreadContext *p; if (!(avctx->active_thread_type & FF_THREAD_FRAME) || avctx->thread_safe_callbacks || avctx->get_format == avcodec_default_get_format) return ff_get_format(avctx, fmt); + + p = avctx->internal->thread_ctx; if (atomic_load(&p->state) != STATE_SETTING_UP) { av_log(avctx, AV_LOG_ERROR, "get_format() cannot be called after ff_thread_finish_setup()\n"); return -1; @@ -1045,7 +1032,7 @@ enum AVPixelFormat ff_thread_get_format(AVCodecContext *avctx, const enum AVPixe FF_ENABLE_DEPRECATION_WARNINGS #endif -int ff_thread_get_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags) +int ff_thread_get_buffer(AVCodecContext *avctx, AVFrame *f, int flags) { int ret = thread_get_buffer_internal(avctx, f, flags); if (ret < 0) @@ -1053,11 +1040,42 @@ int ff_thread_get_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags) return ret; } -void ff_thread_release_buffer(AVCodecContext *avctx, ThreadFrame *f) +int ff_thread_get_ext_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags) +{ + int ret; + + f->owner[0] = f->owner[1] = avctx; + /* Hint: It is possible for this function to be called with codecs + * that don't support frame threading at all, namely in case + * a frame-threaded decoder shares code with codecs that are not. + * This currently affects non-MPEG-4 mpegvideo codecs and and VP7. + * The following check will always be true for them. */ + if (!(avctx->active_thread_type & FF_THREAD_FRAME)) + return ff_get_buffer(avctx, f->f, flags); + + if (ffcodec(avctx->codec)->caps_internal & FF_CODEC_CAP_ALLOCATE_PROGRESS) { + atomic_int *progress; + f->progress = av_buffer_alloc(2 * sizeof(*progress)); + if (!f->progress) { + return AVERROR(ENOMEM); + } + progress = (atomic_int*)f->progress->data; + + atomic_init(&progress[0], -1); + atomic_init(&progress[1], -1); + } + + ret = ff_thread_get_buffer(avctx, f->f, flags); + if (ret) + av_buffer_unref(&f->progress); + return ret; +} + +void ff_thread_release_buffer(AVCodecContext *avctx, AVFrame *f) { #if FF_API_THREAD_SAFE_CALLBACKS FF_DISABLE_DEPRECATION_WARNINGS - PerThreadContext *p = avctx->internal->thread_ctx; + PerThreadContext *p; FrameThreadContext *fctx; AVFrame *dst; int ret = 0; @@ -1066,24 +1084,22 @@ FF_DISABLE_DEPRECATION_WARNINGS FF_ENABLE_DEPRECATION_WARNINGS #endif - if (!f->f) + if (!f) return; if (avctx->debug & FF_DEBUG_BUFFERS) av_log(avctx, AV_LOG_DEBUG, "thread_release_buffer called on pic %p\n", f); - av_buffer_unref(&f->progress); - f->owner[0] = f->owner[1] = NULL; - #if !FF_API_THREAD_SAFE_CALLBACKS av_frame_unref(f->f); #else // when the frame buffers are not allocated, just reset it to clean state - if (can_direct_free || !f->f->buf[0]) { - av_frame_unref(f->f); + if (can_direct_free || !f->buf[0]) { + av_frame_unref(f); return; } + p = avctx->internal->thread_ctx; fctx = p->parent; pthread_mutex_lock(&fctx->buffer_mutex); @@ -1103,7 +1119,7 @@ FF_ENABLE_DEPRECATION_WARNINGS } dst = p->released_buffers[p->num_released_buffers]; - av_frame_move_ref(dst, f->f); + av_frame_move_ref(dst, f); p->num_released_buffers++; @@ -1114,10 +1130,17 @@ fail: // this leaks, but it is better than crashing if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Could not queue a frame for freeing, this will leak\n"); - memset(f->f->buf, 0, sizeof(f->f->buf)); - if (f->f->extended_buf) - memset(f->f->extended_buf, 0, f->f->nb_extended_buf * sizeof(*f->f->extended_buf)); - av_frame_unref(f->f); + memset(f->buf, 0, sizeof(f->buf)); + if (f->extended_buf) + memset(f->extended_buf, 0, f->nb_extended_buf * sizeof(*f->extended_buf)); + av_frame_unref(f); } #endif } + +void ff_thread_release_ext_buffer(AVCodecContext *avctx, ThreadFrame *f) +{ + av_buffer_unref(&f->progress); + f->owner[0] = f->owner[1] = NULL; + ff_thread_release_buffer(avctx, f->f); +} diff --git a/libavcodec/pthread_slice.c b/libavcodec/pthread_slice.c index 86411b21b..e34116116 100644 --- a/libavcodec/pthread_slice.c +++ b/libavcodec/pthread_slice.c @@ -25,6 +25,7 @@ #include "config.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "pthread_internal.h" #include "thread.h" @@ -40,6 +41,11 @@ typedef int (action_func)(AVCodecContext *c, void *arg); typedef int (action_func2)(AVCodecContext *c, void *arg, int jobnr, int threadnr); typedef int (main_func)(AVCodecContext *c); +typedef struct Progress { + pthread_cond_t cond; + pthread_mutex_t mutex; +} Progress; + typedef struct SliceThreadContext { AVSliceThread *thread; action_func *func; @@ -52,8 +58,7 @@ typedef struct SliceThreadContext { int *entries; int entries_count; int thread_count; - pthread_cond_t *progress_cond; - pthread_mutex_t *progress_mutex; + Progress *progress; } SliceThreadContext; static void main_function(void *priv) { @@ -82,13 +87,13 @@ void ff_slice_thread_free(AVCodecContext *avctx) avpriv_slicethread_free(&c->thread); for (i = 0; i < c->thread_count; i++) { - pthread_mutex_destroy(&c->progress_mutex[i]); - pthread_cond_destroy(&c->progress_cond[i]); + Progress *const progress = &c->progress[i]; + pthread_mutex_destroy(&progress->mutex); + pthread_cond_destroy(&progress->cond); } av_freep(&c->entries); - av_freep(&c->progress_mutex); - av_freep(&c->progress_cond); + av_freep(&c->progress); av_freep(&avctx->internal->thread_ctx); } @@ -155,7 +160,7 @@ int ff_slice_thread_init(AVCodecContext *avctx) } avctx->internal->thread_ctx = c = av_mallocz(sizeof(*c)); - mainfunc = avctx->codec->caps_internal & FF_CODEC_CAP_SLICE_THREAD_HAS_MF ? &main_function : NULL; + mainfunc = ffcodec(avctx->codec)->caps_internal & FF_CODEC_CAP_SLICE_THREAD_HAS_MF ? &main_function : NULL; if (!c || (thread_count = avpriv_slicethread_create(&c->thread, avctx, worker_func, mainfunc, thread_count)) <= 1) { if (c) avpriv_slicethread_free(&c->thread); @@ -171,65 +176,82 @@ int ff_slice_thread_init(AVCodecContext *avctx) return 0; } +int av_cold ff_slice_thread_init_progress(AVCodecContext *avctx) +{ + SliceThreadContext *const p = avctx->internal->thread_ctx; + int err, i = 0, thread_count = avctx->thread_count; + + p->progress = av_calloc(thread_count, sizeof(*p->progress)); + if (!p->progress) { + err = AVERROR(ENOMEM); + goto fail; + } + + for (; i < thread_count; i++) { + Progress *const progress = &p->progress[i]; + err = pthread_mutex_init(&progress->mutex, NULL); + if (err) { + err = AVERROR(err); + goto fail; + } + err = pthread_cond_init (&progress->cond, NULL); + if (err) { + err = AVERROR(err); + pthread_mutex_destroy(&progress->mutex); + goto fail; + } + } + err = 0; +fail: + p->thread_count = i; + return err; +} + void ff_thread_report_progress2(AVCodecContext *avctx, int field, int thread, int n) { SliceThreadContext *p = avctx->internal->thread_ctx; + Progress *const progress = &p->progress[thread]; int *entries = p->entries; - pthread_mutex_lock(&p->progress_mutex[thread]); + pthread_mutex_lock(&progress->mutex); entries[field] +=n; - pthread_cond_signal(&p->progress_cond[thread]); - pthread_mutex_unlock(&p->progress_mutex[thread]); + pthread_cond_signal(&progress->cond); + pthread_mutex_unlock(&progress->mutex); } void ff_thread_await_progress2(AVCodecContext *avctx, int field, int thread, int shift) { SliceThreadContext *p = avctx->internal->thread_ctx; + Progress *progress; int *entries = p->entries; if (!entries || !field) return; thread = thread ? thread - 1 : p->thread_count - 1; + progress = &p->progress[thread]; - pthread_mutex_lock(&p->progress_mutex[thread]); + pthread_mutex_lock(&progress->mutex); while ((entries[field - 1] - entries[field]) < shift){ - pthread_cond_wait(&p->progress_cond[thread], &p->progress_mutex[thread]); + pthread_cond_wait(&progress->cond, &progress->mutex); } - pthread_mutex_unlock(&p->progress_mutex[thread]); + pthread_mutex_unlock(&progress->mutex); } int ff_alloc_entries(AVCodecContext *avctx, int count) { - int i; - if (avctx->active_thread_type & FF_THREAD_SLICE) { SliceThreadContext *p = avctx->internal->thread_ctx; if (p->entries) { - av_assert0(p->thread_count == avctx->thread_count); av_freep(&p->entries); } - p->thread_count = avctx->thread_count; p->entries = av_calloc(count, sizeof(*p->entries)); - - if (!p->progress_mutex) { - p->progress_mutex = av_malloc_array(p->thread_count, sizeof(pthread_mutex_t)); - p->progress_cond = av_malloc_array(p->thread_count, sizeof(pthread_cond_t)); - } - - if (!p->entries || !p->progress_mutex || !p->progress_cond) { - av_freep(&p->entries); - av_freep(&p->progress_mutex); - av_freep(&p->progress_cond); + if (!p->entries) { + p->entries_count = 0; return AVERROR(ENOMEM); } p->entries_count = count; - - for (i = 0; i < p->thread_count; i++) { - pthread_mutex_init(&p->progress_mutex[i], NULL); - pthread_cond_init(&p->progress_cond[i], NULL); - } } return 0; diff --git a/libavcodec/ptx.c b/libavcodec/ptx.c index 47b8926f7..110204934 100644 --- a/libavcodec/ptx.c +++ b/libavcodec/ptx.c @@ -23,13 +23,14 @@ #include "libavutil/intreadwrite.h" #include "libavutil/imgutils.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" -static int ptx_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) { +static int ptx_decode_frame(AVCodecContext *avctx, AVFrame *p, + int *got_frame, AVPacket *avpkt) +{ const uint8_t *buf = avpkt->data; const uint8_t *buf_end = avpkt->data + avpkt->size; - AVFrame * const p = data; unsigned int offset, w, h, y, stride, bytes_per_pixel; int ret; uint8_t *ptr; @@ -85,11 +86,11 @@ static int ptx_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, return offset + w*h*bytes_per_pixel; } -const AVCodec ff_ptx_decoder = { - .name = "ptx", - .long_name = NULL_IF_CONFIG_SMALL("V.Flash PTX image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_PTX, - .decode = ptx_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, +const FFCodec ff_ptx_decoder = { + .p.name = "ptx", + .p.long_name = NULL_IF_CONFIG_SMALL("V.Flash PTX image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_PTX, + .p.capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(ptx_decode_frame), }; diff --git a/libavcodec/put_bits.h b/libavcodec/put_bits.h index 689c6b282..4b4f977ad 100644 --- a/libavcodec/put_bits.h +++ b/libavcodec/put_bits.h @@ -32,6 +32,7 @@ #include "config.h" #include "libavutil/intreadwrite.h" #include "libavutil/avassert.h" +#include "libavutil/common.h" #if ARCH_X86_64 // TODO: Benchmark and optionally enable on other 64-bit architectures. diff --git a/libavcodec/put_golomb.h b/libavcodec/put_golomb.h new file mode 100644 index 000000000..9ca911fc3 --- /dev/null +++ b/libavcodec/put_golomb.h @@ -0,0 +1,168 @@ +/* + * exp golomb vlc writing stuff + * Copyright (c) 2003 Michael Niedermayer + * Copyright (c) 2004 Alex Beregszaszi + * + * 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 + * @brief + * exp golomb vlc writing stuff + * @author Michael Niedermayer and Alex Beregszaszi + */ + +#ifndef AVCODEC_PUT_GOLOMB_H +#define AVCODEC_PUT_GOLOMB_H + +#include +#include "put_bits.h" + +extern const uint8_t ff_ue_golomb_len[256]; + +/** + * write unsigned exp golomb code. 2^16 - 2 at most + */ +static inline void set_ue_golomb(PutBitContext *pb, int i) +{ + av_assert2(i >= 0); + av_assert2(i <= 0xFFFE); + + if (i < 256) + put_bits(pb, ff_ue_golomb_len[i], i + 1); + else { + int e = av_log2(i + 1); + put_bits(pb, 2 * e + 1, i + 1); + } +} + +/** + * write unsigned exp golomb code. 2^32-2 at most. + */ +static inline void set_ue_golomb_long(PutBitContext *pb, uint32_t i) +{ + av_assert2(i <= (UINT32_MAX - 1)); + + if (i < 256) + put_bits(pb, ff_ue_golomb_len[i], i + 1); + else { + int e = av_log2(i + 1); + put_bits64(pb, 2 * e + 1, i + 1); + } +} + +/** + * write truncated unsigned exp golomb code. + */ +static inline void set_te_golomb(PutBitContext *pb, int i, int range) +{ + av_assert2(range >= 1); + av_assert2(i <= range); + + if (range == 2) + put_bits(pb, 1, i ^ 1); + else + set_ue_golomb(pb, i); +} + +/** + * write signed exp golomb code. 16 bits at most. + */ +static inline void set_se_golomb(PutBitContext *pb, int i) +{ + i = 2 * i - 1; + if (i < 0) + i ^= -1; //FIXME check if gcc does the right thing + set_ue_golomb(pb, i); +} + +/** + * write unsigned golomb rice code (ffv1). + */ +static inline void set_ur_golomb(PutBitContext *pb, int i, int k, int limit, + int esc_len) +{ + int e; + + av_assert2(i >= 0); + + e = i >> k; + if (e < limit) + put_bits(pb, e + k + 1, (1 << k) + av_mod_uintp2(i, k)); + else + put_bits(pb, limit + esc_len, i - limit + 1); +} + +/** + * write unsigned golomb rice code (jpegls). + */ +static inline void set_ur_golomb_jpegls(PutBitContext *pb, int i, int k, + int limit, int esc_len) +{ + int e; + + av_assert2(i >= 0); + + e = (i >> k) + 1; + if (e < limit) { + while (e > 31) { + put_bits(pb, 31, 0); + e -= 31; + } + put_bits(pb, e, 1); + if (k) + put_sbits(pb, k, i); + } else { + while (limit > 31) { + put_bits(pb, 31, 0); + limit -= 31; + } + put_bits(pb, limit, 1); + put_bits(pb, esc_len, i - 1); + } +} + +/** + * write signed golomb rice code (ffv1). + */ +static inline void set_sr_golomb(PutBitContext *pb, int i, int k, int limit, + int esc_len) +{ + int v; + + v = -2 * i - 1; + v ^= (v >> 31); + + set_ur_golomb(pb, v, k, limit, esc_len); +} + +/** + * write signed golomb rice code (flac). + */ +static inline void set_sr_golomb_flac(PutBitContext *pb, int i, int k, + int limit, int esc_len) +{ + int v; + + v = -2 * i - 1; + v ^= (v >> 31); + + set_ur_golomb_jpegls(pb, v, k, limit, esc_len); +} + +#endif /* AVCODEC_PUT_GOLOMB_H */ diff --git a/libavcodec/qcelpdec.c b/libavcodec/qcelpdec.c index b23013816..1a4d308ac 100644 --- a/libavcodec/qcelpdec.c +++ b/libavcodec/qcelpdec.c @@ -33,6 +33,7 @@ #include "libavutil/channel_layout.h" #include "libavutil/float_dsp.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "get_bits.h" #include "qcelpdata.h" @@ -87,8 +88,8 @@ static av_cold int qcelp_decode_init(AVCodecContext *avctx) QCELPContext *q = avctx->priv_data; int i; - avctx->channels = 1; - avctx->channel_layout = AV_CH_LAYOUT_MONO; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; avctx->sample_fmt = AV_SAMPLE_FMT_FLT; for (i = 0; i < 10; i++) @@ -683,13 +684,12 @@ static void postfilter(QCELPContext *q, float *samples, float *lpc) 160, 0.9375, &q->postfilter_agc_mem); } -static int qcelp_decode_frame(AVCodecContext *avctx, void *data, +static int qcelp_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; QCELPContext *q = avctx->priv_data; - AVFrame *frame = data; float *outbuffer; int i, ret; float quantized_lspf[10], lpc[10]; @@ -790,14 +790,14 @@ erasure: return buf_size; } -const AVCodec ff_qcelp_decoder = { - .name = "qcelp", - .long_name = NULL_IF_CONFIG_SMALL("QCELP / PureVoice"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_QCELP, +const FFCodec ff_qcelp_decoder = { + .p.name = "qcelp", + .p.long_name = NULL_IF_CONFIG_SMALL("QCELP / PureVoice"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_QCELP, .init = qcelp_decode_init, - .decode = qcelp_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + FF_CODEC_DECODE_CB(qcelp_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .priv_data_size = sizeof(QCELPContext), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/qdm2.c b/libavcodec/qdm2.c index 5e4e741e5..427e8e844 100644 --- a/libavcodec/qdm2.c +++ b/libavcodec/qdm2.c @@ -43,6 +43,7 @@ #include "avcodec.h" #include "get_bits.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" #include "mpegaudio.h" #include "mpegaudiodsp.h" @@ -1687,13 +1688,13 @@ static av_cold int qdm2_decode_init(AVCodecContext *avctx) bytestream2_skip(&gb, 4); - avctx->channels = s->nb_channels = s->channels = bytestream2_get_be32(&gb); + s->nb_channels = s->channels = bytestream2_get_be32(&gb); if (s->channels <= 0 || s->channels > MPA_MAX_CHANNELS) { av_log(avctx, AV_LOG_ERROR, "Invalid number of channels\n"); return AVERROR_INVALIDDATA; } - avctx->channel_layout = avctx->channels == 2 ? AV_CH_LAYOUT_STEREO : - AV_CH_LAYOUT_MONO; + av_channel_layout_uninit(&avctx->ch_layout); + av_channel_layout_default(&avctx->ch_layout, s->channels); avctx->sample_rate = bytestream2_get_be32(&gb); avctx->bit_rate = bytestream2_get_be32(&gb); @@ -1837,10 +1838,9 @@ static int qdm2_decode(QDM2Context *q, const uint8_t *in, int16_t *out) return 0; } -static int qdm2_decode_frame(AVCodecContext *avctx, void *data, +static int qdm2_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; QDM2Context *s = avctx->priv_data; @@ -1869,15 +1869,15 @@ static int qdm2_decode_frame(AVCodecContext *avctx, void *data, return s->checksum_size; } -const AVCodec ff_qdm2_decoder = { - .name = "qdm2", - .long_name = NULL_IF_CONFIG_SMALL("QDesign Music Codec 2"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_QDM2, +const FFCodec ff_qdm2_decoder = { + .p.name = "qdm2", + .p.long_name = NULL_IF_CONFIG_SMALL("QDesign Music Codec 2"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_QDM2, .priv_data_size = sizeof(QDM2Context), .init = qdm2_decode_init, .close = qdm2_decode_close, - .decode = qdm2_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + FF_CODEC_DECODE_CB(qdm2_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/qdm2_tablegen.c b/libavcodec/qdm2_tablegen.c index e19b49b23..932da0c50 100644 --- a/libavcodec/qdm2_tablegen.c +++ b/libavcodec/qdm2_tablegen.c @@ -42,7 +42,7 @@ int main(void) qdm2_init_vlc(); - WRITE_2D_ARRAY("static const", VLC_TYPE, qdm2_table); + WRITE_VLC_TABLE("static const", qdm2_table); WRITE_VLC_TYPE("static const", vlc_tab_level, qdm2_table); WRITE_VLC_TYPE("static const", vlc_tab_diff, qdm2_table); WRITE_VLC_TYPE("static const", vlc_tab_run, qdm2_table); diff --git a/libavcodec/qdm2_tablegen.h b/libavcodec/qdm2_tablegen.h index ca47fea2d..a68ea8599 100644 --- a/libavcodec/qdm2_tablegen.h +++ b/libavcodec/qdm2_tablegen.h @@ -109,7 +109,7 @@ static VLC vlc_tab_type30; static VLC vlc_tab_type34; static VLC vlc_tab_fft_tone_offset[5]; -static VLC_TYPE qdm2_table[3838][2]; +static VLCElem qdm2_table[3838]; static av_cold void build_vlc(VLC *vlc, int nb_bits, int nb_codes, unsigned *offset, const uint8_t tab[][2]) diff --git a/libavcodec/qdmc.c b/libavcodec/qdmc.c index ae75ca524..f24e94b18 100644 --- a/libavcodec/qdmc.c +++ b/libavcodec/qdmc.c @@ -27,12 +27,13 @@ #include "libavutil/channel_layout.h" #include "libavutil/thread.h" +#include "libavutil/tx.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" -#include "fft.h" typedef struct QDMCTone { uint8_t mode; @@ -66,8 +67,10 @@ typedef struct QDMCContext { float *buffer_ptr; int rndval; - DECLARE_ALIGNED(32, FFTComplex, cmplx)[2][512]; - FFTContext fft_ctx; + DECLARE_ALIGNED(32, AVComplexFloat, cmplx_in)[2][512]; + DECLARE_ALIGNED(32, AVComplexFloat, cmplx_out)[2][512]; + AVTXContext *fft_ctx; + av_tx_fn itx_fn; } QDMCContext; static float sin_table[512]; @@ -166,7 +169,7 @@ static av_cold void qdmc_init_static_data(void) int i; for (unsigned i = 0, offset = 0; i < FF_ARRAY_ELEMS(vtable); i++) { - static VLC_TYPE vlc_buffer[13698][2]; + static VLCElem vlc_buffer[13698]; vtable[i].table = &vlc_buffer[offset]; vtable[i].table_allocated = FF_ARRAY_ELEMS(vlc_buffer) - offset; ff_init_vlc_from_lengths(&vtable[i], huff_bits[i], huff_sizes[i], @@ -207,6 +210,7 @@ static av_cold int qdmc_decode_init(AVCodecContext *avctx) static AVOnce init_static_once = AV_ONCE_INIT; QDMCContext *s = avctx->priv_data; int ret, fft_size, fft_order, size, g, j, x; + float scale = 1.f; GetByteContext b; ff_thread_once(&init_static_once, qdmc_init_static_data); @@ -245,13 +249,14 @@ static av_cold int qdmc_decode_init(AVCodecContext *avctx) } bytestream2_skipu(&b, 4); - avctx->channels = s->nb_channels = bytestream2_get_be32u(&b); + s->nb_channels = bytestream2_get_be32u(&b); if (s->nb_channels <= 0 || s->nb_channels > 2) { av_log(avctx, AV_LOG_ERROR, "invalid number of channels\n"); return AVERROR_INVALIDDATA; } - avctx->channel_layout = avctx->channels == 2 ? AV_CH_LAYOUT_STEREO : - AV_CH_LAYOUT_MONO; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = s->nb_channels == 2 ? (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO : + (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; avctx->sample_rate = bytestream2_get_be32u(&b); avctx->bit_rate = bytestream2_get_be32u(&b); @@ -277,7 +282,7 @@ static av_cold int qdmc_decode_init(AVCodecContext *avctx) s->frame_size = 1 << s->frame_bits; s->subframe_size = s->frame_size >> 5; - if (avctx->channels == 2) + if (avctx->ch_layout.nb_channels == 2) x = 3 * x / 2; s->band_index = noise_bands_selector[FFMIN(6, llrint(floor(avctx->bit_rate * 3.0 / (double)x + 0.5)))]; @@ -291,7 +296,7 @@ static av_cold int qdmc_decode_init(AVCodecContext *avctx) return AVERROR_INVALIDDATA; } - ret = ff_fft_init(&s->fft_ctx, fft_order, 1); + ret = av_tx_init(&s->fft_ctx, &s->itx_fn, AV_TX_FLOAT_FFT, 1, 1 << fft_order, &scale, 0); if (ret < 0) return ret; @@ -311,7 +316,7 @@ static av_cold int qdmc_decode_close(AVCodecContext *avctx) { QDMCContext *s = avctx->priv_data; - ff_fft_end(&s->fft_ctx); + av_tx_uninit(&s->fft_ctx); return 0; } @@ -641,22 +646,21 @@ static int decode_frame(QDMCContext *s, GetBitContext *gb, int16_t *out) for (ch = 0; ch < s->nb_channels; ch++) { for (i = 0; i < s->subframe_size; i++) { - s->cmplx[ch][i].re = s->fft_buffer[ch + 2][s->fft_offset + n * s->subframe_size + i]; - s->cmplx[ch][i].im = s->fft_buffer[ch + 0][s->fft_offset + n * s->subframe_size + i]; - s->cmplx[ch][s->subframe_size + i].re = 0; - s->cmplx[ch][s->subframe_size + i].im = 0; + s->cmplx_in[ch][i].re = s->fft_buffer[ch + 2][s->fft_offset + n * s->subframe_size + i]; + s->cmplx_in[ch][i].im = s->fft_buffer[ch + 0][s->fft_offset + n * s->subframe_size + i]; + s->cmplx_in[ch][s->subframe_size + i].re = 0; + s->cmplx_in[ch][s->subframe_size + i].im = 0; } } for (ch = 0; ch < s->nb_channels; ch++) { - s->fft_ctx.fft_permute(&s->fft_ctx, s->cmplx[ch]); - s->fft_ctx.fft_calc(&s->fft_ctx, s->cmplx[ch]); + s->itx_fn(s->fft_ctx, s->cmplx_out[ch], s->cmplx_in[ch], sizeof(float)); } r = &s->buffer_ptr[s->nb_channels * n * s->subframe_size]; for (i = 0; i < 2 * s->subframe_size; i++) { for (ch = 0; ch < s->nb_channels; ch++) { - *r++ += s->cmplx[ch][i].re; + *r++ += s->cmplx_out[ch][i].re; } } @@ -692,11 +696,10 @@ static av_cold void qdmc_flush(AVCodecContext *avctx) s->buffer_offset = 0; } -static int qdmc_decode_frame(AVCodecContext *avctx, void *data, +static int qdmc_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { QDMCContext *s = avctx->priv_data; - AVFrame *frame = data; GetBitContext gb; int ret; @@ -725,16 +728,16 @@ static int qdmc_decode_frame(AVCodecContext *avctx, void *data, return ret; } -const AVCodec ff_qdmc_decoder = { - .name = "qdmc", - .long_name = NULL_IF_CONFIG_SMALL("QDesign Music Codec 1"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_QDMC, +const FFCodec ff_qdmc_decoder = { + .p.name = "qdmc", + .p.long_name = NULL_IF_CONFIG_SMALL("QDesign Music Codec 1"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_QDMC, .priv_data_size = sizeof(QDMCContext), .init = qdmc_decode_init, .close = qdmc_decode_close, - .decode = qdmc_decode_frame, + FF_CODEC_DECODE_CB(qdmc_decode_frame), .flush = qdmc_flush, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/qdrw.c b/libavcodec/qdrw.c index fcc1de0c6..ff8f97713 100644 --- a/libavcodec/qdrw.c +++ b/libavcodec/qdrw.c @@ -30,6 +30,7 @@ #include "libavutil/intreadwrite.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" enum QuickdrawOpcodes { @@ -287,11 +288,9 @@ static int check_header(const char *buf, int buf_size) } -static int decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *p, + int *got_frame, AVPacket *avpkt) { - AVFrame * const p = data; GetByteContext gbc; int colors; int w, h, ret; @@ -369,7 +368,7 @@ static int decode_frame(AVCodecContext *avctx, bytestream2_skip(&gbc, 18); colors = bytestream2_get_be16(&gbc); - if (colors < 0 || colors > 256) { + if (colors < 0 || colors > 255) { av_log(avctx, AV_LOG_ERROR, "Error color count - %i(0x%X)\n", colors, colors); return AVERROR_INVALIDDATA; @@ -514,11 +513,11 @@ static int decode_frame(AVCodecContext *avctx, } } -const AVCodec ff_qdraw_decoder = { - .name = "qdraw", - .long_name = NULL_IF_CONFIG_SMALL("Apple QuickDraw"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_QDRAW, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, +const FFCodec ff_qdraw_decoder = { + .p.name = "qdraw", + .p.long_name = NULL_IF_CONFIG_SMALL("Apple QuickDraw"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_QDRAW, + .p.capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), }; diff --git a/libavcodec/qoi.h b/libavcodec/qoi.h new file mode 100644 index 000000000..3efab1e55 --- /dev/null +++ b/libavcodec/qoi.h @@ -0,0 +1,35 @@ +/* + * QOI image format + * + * 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_QOI_H +#define AVCODEC_QOI_H + +#define QOI_OP_INDEX 0x00 /* 00xxxxxx */ +#define QOI_OP_DIFF 0x40 /* 01xxxxxx */ +#define QOI_OP_LUMA 0x80 /* 10xxxxxx */ +#define QOI_OP_RUN 0xc0 /* 11xxxxxx */ +#define QOI_OP_RGB 0xfe /* 11111110 */ +#define QOI_OP_RGBA 0xff /* 11111111 */ + +#define QOI_MASK_2 0xc0 /* 11000000 */ + +#define QOI_COLOR_HASH(px) (px[0]*3 + px[1]*5 + px[2]*7 + px[3]*11) + +#endif /* AVCODEC_QOI_H */ diff --git a/libavcodec/qoi_parser.c b/libavcodec/qoi_parser.c new file mode 100644 index 000000000..e5af11e94 --- /dev/null +++ b/libavcodec/qoi_parser.c @@ -0,0 +1,77 @@ +/* + * QOI parser + * Copyright (c) 2022 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 + */ + +/** + * @file + * QOI parser + */ + +#include "parser.h" + +typedef struct QOIParseContext { + ParseContext pc; +} QOIParseContext; + +static int qoi_parse(AVCodecParserContext *s, AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + QOIParseContext *ipc = s->priv_data; + uint64_t state = ipc->pc.state64; + int next = END_NOT_FOUND, i = 0; + + s->pict_type = AV_PICTURE_TYPE_NONE; + s->duration = 1; + + *poutbuf_size = 0; + *poutbuf = NULL; + + if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { + next = buf_size; + } else { + for (; i < buf_size; i++) { + state = (state << 8) | buf[i]; + if (state == 0x01LL) { + next = i + 1; + break; + } + } + + ipc->pc.state64 = state; + if (ff_combine_frame(&ipc->pc, next, &buf, &buf_size) < 0) { + *poutbuf = NULL; + *poutbuf_size = 0; + return buf_size; + } + } + + *poutbuf = buf; + *poutbuf_size = buf_size; + + return next; +} + +const AVCodecParser ff_qoi_parser = { + .codec_ids = { AV_CODEC_ID_QOI }, + .priv_data_size = sizeof(QOIParseContext), + .parser_parse = qoi_parse, + .parser_close = ff_parse_close, +}; diff --git a/libavcodec/qoidec.c b/libavcodec/qoidec.c new file mode 100644 index 000000000..1e052f659 --- /dev/null +++ b/libavcodec/qoidec.c @@ -0,0 +1,125 @@ +/* + * QOI image format + * + * 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 "avcodec.h" +#include "internal.h" +#include "bytestream.h" +#include "codec_internal.h" +#include "thread.h" +#include "qoi.h" + +static int qoi_decode_frame(AVCodecContext *avctx, AVFrame *p, + int *got_frame, AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int ret, buf_size = avpkt->size; + int width, height, channels, space, run = 0; + uint8_t index[64][4] = { 0 }; + uint8_t px[4] = { 0, 0, 0, 255 }; + GetByteContext gb; + uint8_t *dst; + uint64_t len; + + if (buf_size < 20) + return AVERROR_INVALIDDATA; + + bytestream2_init(&gb, buf, buf_size); + bytestream2_skip(&gb, 4); + width = bytestream2_get_be32(&gb); + height = bytestream2_get_be32(&gb); + channels = bytestream2_get_byte(&gb); + space = bytestream2_get_byte(&gb); + switch (space) { + case 0: break; + case 1: avctx->color_trc = AVCOL_TRC_LINEAR; break; + default: return AVERROR_INVALIDDATA; + } + + if ((ret = ff_set_dimensions(avctx, width, height)) < 0) + return ret; + + switch (channels) { + case 3: avctx->pix_fmt = AV_PIX_FMT_RGB24; break; + case 4: avctx->pix_fmt = AV_PIX_FMT_RGBA; break; + default: return AVERROR_INVALIDDATA; + } + + if ((ret = ff_thread_get_buffer(avctx, p, 0)) < 0) + return ret; + + dst = p->data[0]; + len = width * height * channels; + for (int n = 0, off_x = 0; n < len; n += channels, off_x++) { + if (off_x >= width) { + off_x = 0; + dst += p->linesize[0]; + } + if (run > 0) { + run--; + } else if (bytestream2_get_bytes_left(&gb) > 4) { + int chunk = bytestream2_get_byteu(&gb); + + if (chunk == QOI_OP_RGB) { + bytestream2_get_bufferu(&gb, px, 3); + } else if (chunk == QOI_OP_RGBA) { + bytestream2_get_bufferu(&gb, px, 4); + } else if ((chunk & QOI_MASK_2) == QOI_OP_INDEX) { + memcpy(px, index[chunk], 4); + } else if ((chunk & QOI_MASK_2) == QOI_OP_DIFF) { + px[0] += ((chunk >> 4) & 0x03) - 2; + px[1] += ((chunk >> 2) & 0x03) - 2; + px[2] += ( chunk & 0x03) - 2; + } else if ((chunk & QOI_MASK_2) == QOI_OP_LUMA) { + int b2 = bytestream2_get_byteu(&gb); + int vg = (chunk & 0x3f) - 32; + px[0] += vg - 8 + ((b2 >> 4) & 0x0f); + px[1] += vg; + px[2] += vg - 8 + (b2 & 0x0f); + } else if ((chunk & QOI_MASK_2) == QOI_OP_RUN) { + run = chunk & 0x3f; + } + + memcpy(index[QOI_COLOR_HASH(px) & 63], px, 4); + } else { + break; + } + + memcpy(&dst[off_x * channels], px, channels); + } + + p->key_frame = 1; + p->pict_type = AV_PICTURE_TYPE_I; + + *got_frame = 1; + + return buf_size; +} + +const FFCodec ff_qoi_decoder = { + .p.name = "qoi", + .p.long_name = NULL_IF_CONFIG_SMALL("QOI (Quite OK Image format) image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_QOI, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + FF_CODEC_DECODE_CB(qoi_decode_frame), +}; diff --git a/libavcodec/qoienc.c b/libavcodec/qoienc.c new file mode 100644 index 000000000..bd137674a --- /dev/null +++ b/libavcodec/qoienc.c @@ -0,0 +1,140 @@ +/* + * QOI image format encoder + * + * 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 "avcodec.h" +#include "bytestream.h" +#include "codec_internal.h" +#include "encode.h" +#include "qoi.h" + +static int qoi_encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *pict, int *got_packet) +{ + const int channels = 3 + (avctx->pix_fmt == AV_PIX_FMT_RGBA); + uint8_t px_prev[4] = { 0, 0, 0, 255 }; + uint8_t px[4] = { 0, 0, 0, 255 }; + uint8_t index[64][4] = { 0 }; + int64_t packet_size; + uint8_t *buf, *src; + int ret, run = 0; + + packet_size = avctx->width * avctx->height * (channels + 1LL) + 14LL + 8LL; + if ((ret = ff_alloc_packet(avctx, pkt, packet_size)) < 0) + return ret; + + buf = pkt->data; + src = pict->data[0]; + + bytestream_put_buffer(&buf, "qoif", 4); + bytestream_put_be32(&buf, avctx->width); + bytestream_put_be32(&buf, avctx->height); + bytestream_put_byte(&buf, channels); + bytestream_put_byte(&buf, avctx->color_trc == AVCOL_TRC_LINEAR); + + for (int y = 0; y < avctx->height; y++) { + for (int x = 0; x < avctx->width; x++) { + memcpy(px, src + x * channels, channels); + + if (!memcmp(px, px_prev, 4)) { + run++; + if (run == 62) { + bytestream_put_byte(&buf, QOI_OP_RUN | (run - 1)); + run = 0; + } + } else { + int index_pos; + + if (run > 0) { + bytestream_put_byte(&buf, QOI_OP_RUN | (run - 1)); + run = 0; + } + + index_pos = QOI_COLOR_HASH(px) & 63; + + if (!memcmp(index[index_pos], px, 4)) { + bytestream_put_byte(&buf, QOI_OP_INDEX | index_pos); + } else { + memcpy(index[index_pos], px, 4); + + if (px[3] == px_prev[3]) { + int8_t vr = px[0] - px_prev[0]; + int8_t vg = px[1] - px_prev[1]; + int8_t vb = px[2] - px_prev[2]; + + int8_t vg_r = vr - vg; + int8_t vg_b = vb - vg; + + if (vr > -3 && vr < 2 && + vg > -3 && vg < 2 && + vb > -3 && vb < 2) { + bytestream_put_byte(&buf, QOI_OP_DIFF | (vr + 2) << 4 | (vg + 2) << 2 | (vb + 2)); + } else if (vg_r > -9 && vg_r < 8 && + vg > -33 && vg < 32 && + vg_b > -9 && vg_b < 8) { + bytestream_put_byte(&buf, QOI_OP_LUMA | (vg + 32)); + bytestream_put_byte(&buf, (vg_r + 8) << 4 | (vg_b + 8)); + } else { + bytestream_put_byte(&buf, QOI_OP_RGB); + bytestream_put_byte(&buf, px[0]); + bytestream_put_byte(&buf, px[1]); + bytestream_put_byte(&buf, px[2]); + } + } else { + bytestream_put_byte(&buf, QOI_OP_RGBA); + bytestream_put_byte(&buf, px[0]); + bytestream_put_byte(&buf, px[1]); + bytestream_put_byte(&buf, px[2]); + bytestream_put_byte(&buf, px[3]); + } + } + } + + memcpy(px_prev, px, 4); + } + + src += pict->linesize[0]; + } + + if (run) + bytestream_put_byte(&buf, QOI_OP_RUN | (run - 1)); + + bytestream_put_be64(&buf, 0x01); + + pkt->size = buf - pkt->data; + + *got_packet = 1; + + return 0; +} + +const FFCodec ff_qoi_encoder = { + .p.name = "qoi", + .p.long_name = NULL_IF_CONFIG_SMALL("QOI (Quite OK Image format) image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_QOI, + .p.capabilities = AV_CODEC_CAP_FRAME_THREADS, + FF_CODEC_ENCODE_CB(qoi_encode_frame), + .p.pix_fmts = (const enum AVPixelFormat[]){ + AV_PIX_FMT_RGBA, AV_PIX_FMT_RGB24, + AV_PIX_FMT_NONE + }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, +}; diff --git a/libavcodec/qpeg.c b/libavcodec/qpeg.c index 829e08aba..9e787cb43 100644 --- a/libavcodec/qpeg.c +++ b/libavcodec/qpeg.c @@ -26,6 +26,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "decode.h" #include "internal.h" @@ -265,13 +266,11 @@ static void av_noinline qpeg_decode_inter(QpegContext *qctx, uint8_t *dst, } } -static int decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *p, + int *got_frame, AVPacket *avpkt) { uint8_t ctable[128]; QpegContext * const a = avctx->priv_data; - AVFrame * const p = data; AVFrame * const ref = a->ref; uint8_t* outdata; int delta, intra, ret; @@ -352,17 +351,17 @@ static av_cold int decode_init(AVCodecContext *avctx){ return 0; } -const AVCodec ff_qpeg_decoder = { - .name = "qpeg", - .long_name = NULL_IF_CONFIG_SMALL("Q-team QPEG"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_QPEG, +const FFCodec ff_qpeg_decoder = { + .p.name = "qpeg", + .p.long_name = NULL_IF_CONFIG_SMALL("Q-team QPEG"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_QPEG, .priv_data_size = sizeof(QpegContext), .init = decode_init, .close = decode_end, - .decode = decode_frame, + FF_CODEC_DECODE_CB(decode_frame), .flush = decode_flush, - .capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/qpeldsp.c b/libavcodec/qpeldsp.c index 6e52b3365..5f937f9d9 100644 --- a/libavcodec/qpeldsp.c +++ b/libavcodec/qpeldsp.c @@ -29,6 +29,7 @@ #include #include "config.h" +#include "config_components.h" #include "libavutil/attributes.h" #include "copy_block.h" #include "qpeldsp.h" @@ -198,7 +199,7 @@ static void OPNAME ## qpel8_mc01_c(uint8_t *dst, const uint8_t *src, \ uint8_t full[16 * 9]; \ uint8_t half[64]; \ \ - copy_block9(full, src, 16, stride, 9); \ + copy_block8(full, src, 16, stride, 9); \ put ## RND ## mpeg4_qpel8_v_lowpass(half, full, 8, 16); \ OPNAME ## pixels8_l2_8(dst, full, half, stride, 16, 8, 8); \ } \ @@ -208,7 +209,7 @@ static void OPNAME ## qpel8_mc02_c(uint8_t *dst, const uint8_t *src, \ { \ uint8_t full[16 * 9]; \ \ - copy_block9(full, src, 16, stride, 9); \ + copy_block8(full, src, 16, stride, 9); \ OPNAME ## mpeg4_qpel8_v_lowpass(dst, full, stride, 16); \ } \ \ @@ -218,7 +219,7 @@ static void OPNAME ## qpel8_mc03_c(uint8_t *dst, const uint8_t *src, \ uint8_t full[16 * 9]; \ uint8_t half[64]; \ \ - copy_block9(full, src, 16, stride, 9); \ + copy_block8(full, src, 16, stride, 9); \ put ## RND ## mpeg4_qpel8_v_lowpass(half, full, 8, 16); \ OPNAME ## pixels8_l2_8(dst, full + 16, half, stride, 16, 8, 8); \ } \ @@ -458,7 +459,7 @@ static void OPNAME ## qpel16_mc01_c(uint8_t *dst, const uint8_t *src, \ uint8_t full[24 * 17]; \ uint8_t half[256]; \ \ - copy_block17(full, src, 24, stride, 17); \ + copy_block16(full, src, 24, stride, 17); \ put ## RND ## mpeg4_qpel16_v_lowpass(half, full, 16, 24); \ OPNAME ## pixels16_l2_8(dst, full, half, stride, 24, 16, 16); \ } \ @@ -468,7 +469,7 @@ static void OPNAME ## qpel16_mc02_c(uint8_t *dst, const uint8_t *src, \ { \ uint8_t full[24 * 17]; \ \ - copy_block17(full, src, 24, stride, 17); \ + copy_block16(full, src, 24, stride, 17); \ OPNAME ## mpeg4_qpel16_v_lowpass(dst, full, stride, 24); \ } \ \ @@ -478,7 +479,7 @@ static void OPNAME ## qpel16_mc03_c(uint8_t *dst, const uint8_t *src, \ uint8_t full[24 * 17]; \ uint8_t half[256]; \ \ - copy_block17(full, src, 24, stride, 17); \ + copy_block16(full, src, 24, stride, 17); \ put ## RND ## mpeg4_qpel16_v_lowpass(half, full, 16, 24); \ OPNAME ## pixels16_l2_8(dst, full + 24, half, stride, 24, 16, 16); \ } \ @@ -809,8 +810,9 @@ av_cold void ff_qpeldsp_init(QpelDSPContext *c) dspfunc(avg_qpel, 0, 16); dspfunc(avg_qpel, 1, 8); - if (ARCH_X86) - ff_qpeldsp_init_x86(c); - if (ARCH_MIPS) - ff_qpeldsp_init_mips(c); +#if ARCH_X86 + ff_qpeldsp_init_x86(c); +#elif ARCH_MIPS + ff_qpeldsp_init_mips(c); +#endif } diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c index 9d08485c9..385b43bb6 100644 --- a/libavcodec/qsv.c +++ b/libavcodec/qsv.c @@ -38,34 +38,26 @@ #define MFX_IMPL_VIA_MASK(impl) (0x0f00 & (impl)) -#if QSV_VERSION_ATLEAST(1, 12) #include "mfx/mfxvp8.h" -#endif int ff_qsv_codec_id_to_mfx(enum AVCodecID codec_id) { switch (codec_id) { case AV_CODEC_ID_H264: return MFX_CODEC_AVC; -#if QSV_VERSION_ATLEAST(1, 8) case AV_CODEC_ID_HEVC: return MFX_CODEC_HEVC; -#endif case AV_CODEC_ID_MPEG1VIDEO: case AV_CODEC_ID_MPEG2VIDEO: return MFX_CODEC_MPEG2; case AV_CODEC_ID_VC1: return MFX_CODEC_VC1; -#if QSV_VERSION_ATLEAST(1, 12) case AV_CODEC_ID_VP8: return MFX_CODEC_VP8; -#endif case AV_CODEC_ID_MJPEG: return MFX_CODEC_JPEG; -#if QSV_VERSION_ATLEAST(1, 19) case AV_CODEC_ID_VP9: return MFX_CODEC_VP9; -#endif #if QSV_VERSION_ATLEAST(1, 34) case AV_CODEC_ID_AV1: return MFX_CODEC_AV1; @@ -189,11 +181,11 @@ enum AVPixelFormat ff_qsv_map_fourcc(uint32_t fourcc) case MFX_FOURCC_NV12: return AV_PIX_FMT_NV12; case MFX_FOURCC_P010: return AV_PIX_FMT_P010; case MFX_FOURCC_P8: return AV_PIX_FMT_PAL8; + case MFX_FOURCC_A2RGB10: return AV_PIX_FMT_X2RGB10; + case MFX_FOURCC_RGB4: return AV_PIX_FMT_BGRA; #if CONFIG_VAAPI case MFX_FOURCC_YUY2: return AV_PIX_FMT_YUYV422; -#if QSV_VERSION_ATLEAST(1, 27) case MFX_FOURCC_Y210: return AV_PIX_FMT_Y210; -#endif #endif } return AV_PIX_FMT_NONE; @@ -211,23 +203,63 @@ int ff_qsv_map_pixfmt(enum AVPixelFormat format, uint32_t *fourcc) case AV_PIX_FMT_P010: *fourcc = MFX_FOURCC_P010; return AV_PIX_FMT_P010; + case AV_PIX_FMT_X2RGB10: + *fourcc = MFX_FOURCC_A2RGB10; + return AV_PIX_FMT_X2RGB10; + case AV_PIX_FMT_BGRA: + *fourcc = MFX_FOURCC_RGB4; + return AV_PIX_FMT_BGRA; #if CONFIG_VAAPI case AV_PIX_FMT_YUV422P: case AV_PIX_FMT_YUYV422: *fourcc = MFX_FOURCC_YUY2; return AV_PIX_FMT_YUYV422; -#if QSV_VERSION_ATLEAST(1, 27) case AV_PIX_FMT_YUV422P10: case AV_PIX_FMT_Y210: *fourcc = MFX_FOURCC_Y210; return AV_PIX_FMT_Y210; -#endif #endif default: return AVERROR(ENOSYS); } } +int ff_qsv_map_frame_to_surface(const AVFrame *frame, mfxFrameSurface1 *surface) +{ + switch (frame->format) { + case AV_PIX_FMT_NV12: + case AV_PIX_FMT_P010: + surface->Data.Y = frame->data[0]; + surface->Data.UV = frame->data[1]; + /* The SDK checks Data.V when using system memory for VP9 encoding */ + surface->Data.V = surface->Data.UV + 1; + break; + case AV_PIX_FMT_X2RGB10LE: + case AV_PIX_FMT_BGRA: + 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; + 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_Y210: + surface->Data.Y16 = (mfxU16 *)frame->data[0]; + surface->Data.U16 = (mfxU16 *)frame->data[0] + 1; + surface->Data.V16 = (mfxU16 *)frame->data[0] + 3; + break; + default: + return AVERROR(ENOSYS); + } + surface->Data.PitchLow = frame->linesize[0]; + + return 0; +} + int ff_qsv_find_surface_idx(QSVFramesContext *ctx, QSVFrame *frame) { int i; @@ -386,9 +418,7 @@ int ff_qsv_init_internal_session(AVCodecContext *avctx, QSVSession *qs, const char *desc; int ret; -#if QSV_VERSION_ATLEAST(1, 16) init_par.GPUCopy = gpu_copy; -#endif init_par.Implementation = impl; init_par.Version = ver; ret = MFXInitEx(init_par, &qs->session); @@ -408,7 +438,10 @@ int ff_qsv_init_internal_session(AVCodecContext *avctx, QSVSession *qs, return ret; } - MFXQueryIMPL(qs->session, &impl); + ret = MFXQueryIMPL(qs->session, &impl); + if (ret != MFX_ERR_NONE) + return ff_qsv_print_error(avctx, ret, + "Error querying the session attributes"); switch (MFX_IMPL_BASETYPE(impl)) { case MFX_IMPL_SOFTWARE: @@ -736,9 +769,7 @@ int ff_qsv_init_session_device(AVCodecContext *avctx, mfxSession *psession, "from the session\n"); } -#if QSV_VERSION_ATLEAST(1, 16) init_par.GPUCopy = gpu_copy; -#endif init_par.Implementation = impl; init_par.Version = ver; err = MFXInitEx(init_par, &session); @@ -828,3 +859,30 @@ int ff_qsv_close_internal_session(QSVSession *qs) #endif return 0; } + +void ff_qsv_frame_add_ext_param (AVCodecContext *avctx, QSVFrame *frame, + mfxExtBuffer * param) +{ + int i; + + for (i = 0; i < frame->num_ext_params; i++) { + mfxExtBuffer *ext_buffer = frame->ext_param[i]; + + if (ext_buffer->BufferId == param->BufferId) { + av_log(avctx, AV_LOG_WARNING, "A buffer with the same type has been " + "added\n"); + return; + } + } + + if (frame->num_ext_params < QSV_MAX_FRAME_EXT_PARAMS) { + frame->ext_param[frame->num_ext_params] = param; + frame->num_ext_params++; + frame->surface.Data.NumExtParam = frame->num_ext_params; + } else { + av_log(avctx, AV_LOG_WARNING, "Ignore this extra buffer because do not " + "have enough space\n"); + } + + +} diff --git a/libavcodec/qsv_internal.h b/libavcodec/qsv_internal.h index fe9d5319c..8131acdae 100644 --- a/libavcodec/qsv_internal.h +++ b/libavcodec/qsv_internal.h @@ -51,6 +51,11 @@ #define ASYNC_DEPTH_DEFAULT 4 // internal parallelism #define QSV_MAX_ENC_PAYLOAD 2 // # of mfxEncodeCtrl payloads supported +#define QSV_MAX_ENC_EXTPARAM 2 + +#define QSV_MAX_ROI_NUM 256 + +#define QSV_MAX_FRAME_EXT_PARAMS 4 #define QSV_VERSION_ATLEAST(MAJOR, MINOR) \ (MFX_VERSION_MAJOR > (MAJOR) || \ @@ -74,9 +79,14 @@ typedef struct QSVFrame { mfxFrameSurface1 surface; mfxEncodeCtrl enc_ctrl; mfxExtDecodedFrameInfo dec_info; - mfxExtBuffer *ext_param; +#if QSV_VERSION_ATLEAST(1, 34) + mfxExtAV1FilmGrainParam av1_film_grain_param; +#endif + mfxExtBuffer *ext_param[QSV_MAX_FRAME_EXT_PARAMS]; + int num_ext_params; mfxPayload *payloads[QSV_MAX_ENC_PAYLOAD]; ///< used for enc_ctrl.Payload + mfxExtBuffer *extparam[QSV_MAX_ENC_EXTPARAM]; ///< used for enc_ctrl.ExtParam int queued; int used; @@ -138,4 +148,10 @@ int ff_qsv_init_session_frames(AVCodecContext *avctx, mfxSession *session, int ff_qsv_find_surface_idx(QSVFramesContext *ctx, QSVFrame *frame); +void ff_qsv_frame_add_ext_param(AVCodecContext *avctx, QSVFrame *frame, + mfxExtBuffer *param); + +int ff_qsv_map_frame_to_surface(const AVFrame *frame, mfxFrameSurface1 *surface); + + #endif /* AVCODEC_QSV_INTERNAL_H */ diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c index 8bce9f2cf..5fc5bed4c 100644 --- a/libavcodec/qsvdec.c +++ b/libavcodec/qsvdec.c @@ -21,6 +21,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include #include #include @@ -38,8 +40,10 @@ #include "libavutil/pixfmt.h" #include "libavutil/time.h" #include "libavutil/imgutils.h" +#include "libavutil/film_grain_params.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "decode.h" #include "hwconfig.h" @@ -56,9 +60,15 @@ static const AVRational mfx_tb = { 1, 90000 }; AV_NOPTS_VALUE : pts_tb.num ? \ av_rescale_q(mfx_pts, mfx_tb, pts_tb) : mfx_pts) +typedef struct QSVAsyncFrame { + mfxSyncPoint *sync; + QSVFrame *frame; +} QSVAsyncFrame; + typedef struct QSVContext { // the session used for decoding mfxSession session; + mfxVersion ver; // the session we allocated internally, in case the caller did not provide // one @@ -71,16 +81,15 @@ typedef struct QSVContext { */ QSVFrame *work_frames; - AVFifoBuffer *async_fifo; + AVFifo *async_fifo; int zero_consume_run; - int buffered_count; int reinit_flag; enum AVPixelFormat orig_pix_fmt; uint32_t fourcc; mfxFrameInfo frame_info; AVBufferPool *pool; - + int suggest_pool_size; int initialized; // options set by the caller @@ -122,21 +131,28 @@ static int qsv_get_continuous_buffer(AVCodecContext *avctx, AVFrame *frame, frame->linesize[0] = FFALIGN(avctx->width, 128); break; case AV_PIX_FMT_P010: + case AV_PIX_FMT_YUYV422: frame->linesize[0] = 2 * FFALIGN(avctx->width, 128); break; + case AV_PIX_FMT_Y210: + frame->linesize[0] = 4 * FFALIGN(avctx->width, 128); + break; default: av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format.\n"); return AVERROR(EINVAL); } - frame->linesize[1] = frame->linesize[0]; frame->buf[0] = av_buffer_pool_get(pool); if (!frame->buf[0]) return AVERROR(ENOMEM); frame->data[0] = frame->buf[0]->data; - frame->data[1] = frame->data[0] + - frame->linesize[0] * FFALIGN(avctx->height, 64); + if (avctx->pix_fmt == AV_PIX_FMT_NV12 || + avctx->pix_fmt == AV_PIX_FMT_P010) { + frame->linesize[1] = frame->linesize[0]; + frame->data[1] = frame->data[0] + + frame->linesize[0] * FFALIGN(avctx->height, 64); + } ret = ff_attach_decode_data(frame); if (ret < 0) @@ -202,22 +218,24 @@ static int qsv_init_session(AVCodecContext *avctx, QSVContext *q, mfxSession ses q->session = q->internal_qs.session; } + if (MFXQueryVersion(q->session, &q->ver) != MFX_ERR_NONE) { + av_log(avctx, AV_LOG_ERROR, "Error querying the session version. \n"); + q->session = NULL; + + if (q->internal_qs.session) { + MFXClose(q->internal_qs.session); + q->internal_qs.session = NULL; + } + + return AVERROR_EXTERNAL; + } + /* make sure the decoder is uninitialized */ MFXVideoDECODE_Close(q->session); return 0; } -static inline unsigned int qsv_fifo_item_size(void) -{ - return sizeof(mfxSyncPoint*) + sizeof(QSVFrame*); -} - -static inline unsigned int qsv_fifo_size(const AVFifoBuffer* fifo) -{ - return av_fifo_size(fifo) / qsv_fifo_item_size(); -} - static int qsv_decode_preinit(AVCodecContext *avctx, QSVContext *q, enum AVPixelFormat pix_fmt, mfxVideoParam *param) { mfxSession session = NULL; @@ -235,7 +253,7 @@ static int qsv_decode_preinit(AVCodecContext *avctx, QSVContext *q, enum AVPixel } if (!q->async_fifo) { - q->async_fifo = av_fifo_alloc(q->async_depth * qsv_fifo_item_size()); + q->async_fifo = av_fifo_alloc2(q->async_depth, sizeof(QSVAsyncFrame), 0); if (!q->async_fifo) return AVERROR(ENOMEM); } @@ -265,7 +283,7 @@ static int qsv_decode_preinit(AVCodecContext *avctx, QSVContext *q, enum AVPixel hwframes_ctx->height = FFALIGN(avctx->coded_height, 32); hwframes_ctx->format = AV_PIX_FMT_QSV; hwframes_ctx->sw_format = avctx->sw_pix_fmt; - hwframes_ctx->initial_pool_size = 64 + avctx->extra_hw_frames; + hwframes_ctx->initial_pool_size = q->suggest_pool_size + 16 + avctx->extra_hw_frames; frames_hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET; ret = av_hwframe_ctx_init(avctx->hw_frames_ctx); @@ -391,6 +409,11 @@ static int qsv_decode_header(AVCodecContext *avctx, QSVContext *q, param->ExtParam = q->ext_buffers; param->NumExtParam = q->nb_ext_buffers; +#if QSV_VERSION_ATLEAST(1, 34) + if (QSV_RUNTIME_VERSION_ATLEAST(q->ver, 1, 34) && avctx->codec_id == AV_CODEC_ID_AV1) + param->mfx.FilmGrain = (avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN) ? 0 : param->mfx.FilmGrain; +#endif + return 0; } @@ -409,13 +432,15 @@ static int alloc_frame(AVCodecContext *avctx, QSVContext *q, QSVFrame *frame) if (frame->frame->format == AV_PIX_FMT_QSV) { frame->surface = *(mfxFrameSurface1*)frame->frame->data[3]; } else { - frame->surface.Info = q->frame_info; - - frame->surface.Data.PitchLow = frame->frame->linesize[0]; - frame->surface.Data.Y = frame->frame->data[0]; - frame->surface.Data.UV = frame->frame->data[1]; + ret = ff_qsv_map_frame_to_surface(frame->frame, &frame->surface); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "map frame to surface failed.\n"); + return ret; + } } + frame->surface.Info = q->frame_info; + if (q->frames_ctx.mids) { ret = ff_qsv_find_surface_idx(&q->frames_ctx, frame); if (ret < 0) @@ -423,11 +448,21 @@ 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->surface.Data.ExtParam = frame->ext_param; + frame->surface.Data.NumExtParam = 0; + frame->num_ext_params = 0; frame->dec_info.Header.BufferId = MFX_EXTBUFF_DECODED_FRAME_INFO; frame->dec_info.Header.BufferSz = sizeof(frame->dec_info); + ff_qsv_frame_add_ext_param(avctx, frame, (mfxExtBuffer *)&frame->dec_info); +#if QSV_VERSION_ATLEAST(1, 34) + if (QSV_RUNTIME_VERSION_ATLEAST(q->ver, 1, 34) && avctx->codec_id == AV_CODEC_ID_AV1) { + frame->av1_film_grain_param.Header.BufferId = MFX_EXTBUFF_AV1_FILM_GRAIN_PARAM; + frame->av1_film_grain_param.Header.BufferSz = sizeof(frame->av1_film_grain_param); + frame->av1_film_grain_param.FilmGrainFlags = 0; + ff_qsv_frame_add_ext_param(avctx, frame, (mfxExtBuffer *)&frame->av1_film_grain_param); + } +#endif frame->used = 1; @@ -498,11 +533,77 @@ static QSVFrame *find_frame(QSVContext *q, mfxFrameSurface1 *surf) return NULL; } +#if QSV_VERSION_ATLEAST(1, 34) +static int qsv_export_film_grain(AVCodecContext *avctx, mfxExtAV1FilmGrainParam *ext_param, AVFrame *frame) +{ + AVFilmGrainParams *fgp; + AVFilmGrainAOMParams *aom; + int i; + + if (!(ext_param->FilmGrainFlags & MFX_FILM_GRAIN_APPLY)) + return 0; + + fgp = av_film_grain_params_create_side_data(frame); + + if (!fgp) + return AVERROR(ENOMEM); + + fgp->type = AV_FILM_GRAIN_PARAMS_AV1; + fgp->seed = ext_param->GrainSeed; + aom = &fgp->codec.aom; + + aom->chroma_scaling_from_luma = !!(ext_param->FilmGrainFlags & MFX_FILM_GRAIN_CHROMA_SCALING_FROM_LUMA); + aom->scaling_shift = ext_param->GrainScalingMinus8 + 8; + aom->ar_coeff_lag = ext_param->ArCoeffLag; + aom->ar_coeff_shift = ext_param->ArCoeffShiftMinus6 + 6; + aom->grain_scale_shift = ext_param->GrainScaleShift; + aom->overlap_flag = !!(ext_param->FilmGrainFlags & MFX_FILM_GRAIN_OVERLAP); + aom->limit_output_range = !!(ext_param->FilmGrainFlags & MFX_FILM_GRAIN_CLIP_TO_RESTRICTED_RANGE); + + aom->num_y_points = ext_param->NumYPoints; + + for (i = 0; i < aom->num_y_points; i++) { + aom->y_points[i][0] = ext_param->PointY[i].Value; + aom->y_points[i][1] = ext_param->PointY[i].Scaling; + } + + aom->num_uv_points[0] = ext_param->NumCbPoints; + + for (i = 0; i < aom->num_uv_points[0]; i++) { + aom->uv_points[0][i][0] = ext_param->PointCb[i].Value; + aom->uv_points[0][i][1] = ext_param->PointCb[i].Scaling; + } + + aom->num_uv_points[1] = ext_param->NumCrPoints; + + for (i = 0; i < aom->num_uv_points[1]; i++) { + aom->uv_points[1][i][0] = ext_param->PointCr[i].Value; + aom->uv_points[1][i][1] = ext_param->PointCr[i].Scaling; + } + + for (i = 0; i < 24; i++) + aom->ar_coeffs_y[i] = ext_param->ArCoeffsYPlus128[i] - 128; + + for (i = 0; i < 25; i++) { + aom->ar_coeffs_uv[0][i] = ext_param->ArCoeffsCbPlus128[i] - 128; + aom->ar_coeffs_uv[1][i] = ext_param->ArCoeffsCrPlus128[i] - 128; + } + + aom->uv_mult[0] = ext_param->CbMult; + aom->uv_mult[1] = ext_param->CrMult; + aom->uv_mult_luma[0] = ext_param->CbLumaMult; + aom->uv_mult_luma[1] = ext_param->CrLumaMult; + aom->uv_offset[0] = ext_param->CbOffset; + aom->uv_offset[1] = ext_param->CrOffset; + + return 0; +} +#endif + static int qsv_decode(AVCodecContext *avctx, QSVContext *q, AVFrame *frame, int *got_frame, const AVPacket *avpkt) { - QSVFrame *out_frame; mfxFrameSurface1 *insurf; mfxFrameSurface1 *outsurf; mfxSyncPoint *sync; @@ -538,6 +639,13 @@ static int qsv_decode(AVCodecContext *avctx, QSVContext *q, } while (ret == MFX_WRN_DEVICE_BUSY || ret == MFX_ERR_MORE_SURFACE); + if (ret == MFX_ERR_INCOMPATIBLE_VIDEO_PARAM) { + q->reinit_flag = 1; + av_log(avctx, AV_LOG_DEBUG, "Video parameter change\n"); + av_freep(&sync); + return 0; + } + if (ret != MFX_ERR_NONE && ret != MFX_ERR_MORE_DATA && ret != MFX_WRN_VIDEO_PARAM_CHANGED && @@ -554,13 +662,12 @@ static int qsv_decode(AVCodecContext *avctx, QSVContext *q, ++q->zero_consume_run; if (q->zero_consume_run > 1) ff_qsv_print_warning(avctx, ret, "A decode call did not consume any data"); - } else if (!*sync && bs.DataOffset) { - ++q->buffered_count; } else { q->zero_consume_run = 0; } if (*sync) { + QSVAsyncFrame aframe; QSVFrame *out_frame = find_frame(q, outsurf); if (!out_frame) { @@ -570,38 +677,49 @@ static int qsv_decode(AVCodecContext *avctx, QSVContext *q, return AVERROR_BUG; } - out_frame->queued = 1; - av_fifo_generic_write(q->async_fifo, &out_frame, sizeof(out_frame), NULL); - av_fifo_generic_write(q->async_fifo, &sync, sizeof(sync), NULL); + out_frame->queued += 1; + + aframe = (QSVAsyncFrame){ sync, out_frame }; + av_fifo_write(q->async_fifo, &aframe, 1); } else { av_freep(&sync); } - if ((qsv_fifo_size(q->async_fifo) >= q->async_depth) || - (!avpkt->size && av_fifo_size(q->async_fifo))) { + if ((av_fifo_can_read(q->async_fifo) >= q->async_depth) || + (!avpkt->size && av_fifo_can_read(q->async_fifo))) { + QSVAsyncFrame aframe; AVFrame *src_frame; - av_fifo_generic_read(q->async_fifo, &out_frame, sizeof(out_frame), NULL); - av_fifo_generic_read(q->async_fifo, &sync, sizeof(sync), NULL); - out_frame->queued = 0; + av_fifo_read(q->async_fifo, &aframe, 1); + aframe.frame->queued -= 1; if (avctx->pix_fmt != AV_PIX_FMT_QSV) { do { - ret = MFXVideoCORE_SyncOperation(q->session, *sync, 1000); + ret = MFXVideoCORE_SyncOperation(q->session, *aframe.sync, 1000); } while (ret == MFX_WRN_IN_EXECUTION); } - av_freep(&sync); + av_freep(&aframe.sync); - src_frame = out_frame->frame; + src_frame = aframe.frame->frame; ret = av_frame_ref(frame, src_frame); if (ret < 0) return ret; - outsurf = &out_frame->surface; + outsurf = &aframe.frame->surface; frame->pts = MFX_PTS_TO_PTS(outsurf->Data.TimeStamp, avctx->pkt_timebase); +#if QSV_VERSION_ATLEAST(1, 34) + if ((avctx->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN) && + QSV_RUNTIME_VERSION_ATLEAST(q->ver, 1, 34) && + avctx->codec_id == AV_CODEC_ID_AV1) { + ret = qsv_export_film_grain(avctx, &aframe.frame->av1_film_grain_param, frame); + + if (ret < 0) + return ret; + } +#endif frame->repeat_pict = outsurf->Info.PicStruct & MFX_PICSTRUCT_FRAME_TRIPLING ? 4 : @@ -611,10 +729,10 @@ static int qsv_decode(AVCodecContext *avctx, QSVContext *q, 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); + frame->pict_type = ff_qsv_map_pictype(aframe.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); + frame->key_frame = !!(aframe.frame->dec_info.FrameType & MFX_FRAMETYPE_IDR); /* update the surface properties */ if (avctx->pix_fmt == AV_PIX_FMT_QSV) @@ -633,14 +751,11 @@ static void qsv_decode_close_qsvcontext(QSVContext *q) if (q->session) MFXVideoDECODE_Close(q->session); - while (q->async_fifo && av_fifo_size(q->async_fifo)) { - QSVFrame *out_frame; - mfxSyncPoint *sync; - - av_fifo_generic_read(q->async_fifo, &out_frame, sizeof(out_frame), NULL); - av_fifo_generic_read(q->async_fifo, &sync, sizeof(sync), NULL); - - av_freep(&sync); + if (q->async_fifo) { + QSVAsyncFrame aframe; + while (av_fifo_read(q->async_fifo, &aframe, 1) >= 0) + av_freep(&aframe.sync); + av_fifo_freep2(&q->async_fifo); } while (cur) { @@ -650,9 +765,6 @@ static void qsv_decode_close_qsvcontext(QSVContext *q) cur = q->work_frames; } - av_fifo_free(q->async_fifo); - q->async_fifo = NULL; - ff_qsv_close_internal_session(&q->internal_qs); av_buffer_unref(&q->frames_ctx.hw_frames_ctx); @@ -682,26 +794,40 @@ static int qsv_process_data(AVCodecContext *avctx, QSVContext *q, if (!avctx->coded_height) avctx->coded_height = 720; - ret = qsv_decode_header(avctx, q, pkt, pix_fmt, ¶m); - - if (ret >= 0 && (q->orig_pix_fmt != ff_qsv_map_fourcc(param.mfx.FrameInfo.FourCC) || - avctx->coded_width != param.mfx.FrameInfo.Width || - avctx->coded_height != param.mfx.FrameInfo.Height)) { + /* decode zero-size pkt to flush the buffered pkt before reinit */ + if (q->reinit_flag) { AVPacket zero_pkt = {0}; + ret = qsv_decode(avctx, q, frame, got_frame, &zero_pkt); + if (ret < 0 || *got_frame) + return ret; + } + + if (q->reinit_flag || !q->session || !q->initialized) { + mfxFrameAllocRequest request; + memset(&request, 0, sizeof(request)); - if (q->buffered_count) { - q->reinit_flag = 1; - /* decode zero-size pkt to flush the buffered pkt before reinit */ - q->buffered_count--; - return qsv_decode(avctx, q, frame, got_frame, &zero_pkt); - } q->reinit_flag = 0; + ret = qsv_decode_header(avctx, q, pkt, pix_fmt, ¶m); + if (ret < 0) { + if (ret == AVERROR(EAGAIN)) + av_log(avctx, AV_LOG_INFO, "More data is required to decode header\n"); + else + av_log(avctx, AV_LOG_ERROR, "Error decoding header\n"); + goto reinit_fail; + } + param.IOPattern = q->iopattern; q->orig_pix_fmt = avctx->pix_fmt = pix_fmt = ff_qsv_map_fourcc(param.mfx.FrameInfo.FourCC); avctx->coded_width = param.mfx.FrameInfo.Width; avctx->coded_height = param.mfx.FrameInfo.Height; + ret = MFXVideoDECODE_QueryIOSurf(q->session, ¶m, &request); + if (ret < 0) + return ff_qsv_print_error(avctx, ret, "Error querying IO surface"); + + q->suggest_pool_size = request.NumFrameSuggested; + ret = qsv_decode_preinit(avctx, q, pix_fmt, ¶m); if (ret < 0) goto reinit_fail; @@ -734,7 +860,7 @@ typedef struct QSVDecContext { int load_plugin; - AVFifoBuffer *packet_fifo; + AVFifo *packet_fifo; AVPacket buffer_pkt; } QSVDecContext; @@ -742,10 +868,8 @@ typedef struct QSVDecContext { static void qsv_clear_buffers(QSVDecContext *s) { AVPacket pkt; - while (av_fifo_size(s->packet_fifo) >= sizeof(pkt)) { - av_fifo_generic_read(s->packet_fifo, &pkt, sizeof(pkt), NULL); + while (av_fifo_read(s->packet_fifo, &pkt, 1) >= 0) av_packet_unref(&pkt); - } av_packet_unref(&s->buffer_pkt); } @@ -754,13 +878,11 @@ static av_cold int qsv_decode_close(AVCodecContext *avctx) { QSVDecContext *s = avctx->priv_data; - av_freep(&s->qsv.load_plugins); - qsv_decode_close_qsvcontext(&s->qsv); qsv_clear_buffers(s); - av_fifo_free(s->packet_fifo); + av_fifo_freep2(&s->packet_fifo); return 0; } @@ -799,7 +921,8 @@ static av_cold int qsv_decode_init(AVCodecContext *avctx) } s->qsv.orig_pix_fmt = AV_PIX_FMT_NV12; - s->packet_fifo = av_fifo_alloc(sizeof(AVPacket)); + s->packet_fifo = av_fifo_alloc2(1, sizeof(AVPacket), + AV_FIFO_FLAG_AUTO_GROW); if (!s->packet_fifo) { ret = AVERROR(ENOMEM); goto fail; @@ -814,28 +937,20 @@ fail: return ret; } -static int qsv_decode_frame(AVCodecContext *avctx, void *data, +static int qsv_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt) { QSVDecContext *s = avctx->priv_data; - AVFrame *frame = data; int ret; /* buffer the input packet */ if (avpkt->size) { AVPacket input_ref; - if (av_fifo_space(s->packet_fifo) < sizeof(input_ref)) { - ret = av_fifo_realloc2(s->packet_fifo, - av_fifo_size(s->packet_fifo) + sizeof(input_ref)); - if (ret < 0) - return ret; - } - ret = av_packet_ref(&input_ref, avpkt); if (ret < 0) return ret; - av_fifo_generic_write(s->packet_fifo, &input_ref, sizeof(input_ref), NULL); + av_fifo_write(s->packet_fifo, &input_ref, 1); } /* process buffered data */ @@ -843,12 +958,12 @@ static int qsv_decode_frame(AVCodecContext *avctx, void *data, /* prepare the input data */ if (s->buffer_pkt.size <= 0) { /* no more data */ - if (av_fifo_size(s->packet_fifo) < sizeof(AVPacket)) + if (!av_fifo_can_read(s->packet_fifo)) return avpkt->size ? avpkt->size : qsv_process_data(avctx, &s->qsv, frame, got_frame, avpkt); /* in progress of reinit, no read from fifo and keep the buffer_pkt */ if (!s->qsv.reinit_flag) { av_packet_unref(&s->buffer_pkt); - av_fifo_generic_read(s->packet_fifo, &s->buffer_pkt, sizeof(s->buffer_pkt), NULL); + av_fifo_read(s->packet_fifo, &s->buffer_pkt, 1); } } @@ -889,25 +1004,27 @@ static const AVClass x##_qsv_class = { \ .option = opt, \ .version = LIBAVUTIL_VERSION_INT, \ }; \ -const AVCodec ff_##x##_qsv_decoder = { \ - .name = #x "_qsv", \ - .long_name = NULL_IF_CONFIG_SMALL(#X " video (Intel Quick Sync Video acceleration)"), \ +const FFCodec ff_##x##_qsv_decoder = { \ + .p.name = #x "_qsv", \ + .p.long_name = NULL_IF_CONFIG_SMALL(#X " video (Intel Quick Sync Video acceleration)"), \ .priv_data_size = sizeof(QSVDecContext), \ - .type = AVMEDIA_TYPE_VIDEO, \ - .id = AV_CODEC_ID_##X, \ + .p.type = AVMEDIA_TYPE_VIDEO, \ + .p.id = AV_CODEC_ID_##X, \ .init = qsv_decode_init, \ - .decode = qsv_decode_frame, \ + FF_CODEC_DECODE_CB(qsv_decode_frame), \ .flush = qsv_decode_flush, \ .close = qsv_decode_close, \ .bsfs = bsf_name, \ - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HYBRID, \ - .priv_class = &x##_qsv_class, \ - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, \ + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HYBRID, \ + .p.priv_class = &x##_qsv_class, \ + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, \ AV_PIX_FMT_P010, \ + AV_PIX_FMT_YUYV422, \ + AV_PIX_FMT_Y210, \ AV_PIX_FMT_QSV, \ AV_PIX_FMT_NONE }, \ .hw_configs = qsv_hw_configs, \ - .wrapper_name = "qsv", \ + .p.wrapper_name = "qsv", \ }; \ #define DEFINE_QSV_DECODER(x, X, bsf_name) DEFINE_QSV_DECODER_WITH_OPTION(x, X, bsf_name, options) diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index db6d39706..2382c2f5f 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -21,6 +21,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include #include #include @@ -51,14 +53,10 @@ static const struct profile_names avc_profiles[] = { { MFX_PROFILE_AVC_MAIN, "avc main" }, { MFX_PROFILE_AVC_EXTENDED, "avc extended" }, { MFX_PROFILE_AVC_HIGH, "avc high" }, -#if QSV_VERSION_ATLEAST(1, 15) { MFX_PROFILE_AVC_HIGH_422, "avc high 422" }, -#endif -#if QSV_VERSION_ATLEAST(1, 4) { MFX_PROFILE_AVC_CONSTRAINED_BASELINE, "avc constrained baseline" }, { MFX_PROFILE_AVC_CONSTRAINED_HIGH, "avc constrained high" }, { MFX_PROFILE_AVC_PROGRESSIVE_HIGH, "avc progressive high" }, -#endif }; static const struct profile_names mpeg2_profiles[] = { @@ -68,23 +66,28 @@ static const struct profile_names mpeg2_profiles[] = { }; static const struct profile_names hevc_profiles[] = { -#if QSV_VERSION_ATLEAST(1, 8) { MFX_PROFILE_HEVC_MAIN, "hevc main" }, { MFX_PROFILE_HEVC_MAIN10, "hevc main10" }, { MFX_PROFILE_HEVC_MAINSP, "hevc mainsp" }, { MFX_PROFILE_HEVC_REXT, "hevc rext" }, +#if QSV_VERSION_ATLEAST(1, 32) + { MFX_PROFILE_HEVC_SCC, "hevc scc" }, #endif }; static const struct profile_names vp9_profiles[] = { -#if QSV_VERSION_ATLEAST(1, 19) { MFX_PROFILE_VP9_0, "vp9 0" }, { MFX_PROFILE_VP9_1, "vp9 1" }, { MFX_PROFILE_VP9_2, "vp9 2" }, { MFX_PROFILE_VP9_3, "vp9 3" }, -#endif }; +typedef struct QSVPacket { + AVPacket pkt; + mfxSyncPoint *sync; + mfxBitstream *bs; +} QSVPacket; + static const char *print_profile(enum AVCodecID codec_id, mfxU16 profile) { const struct profile_names *profiles; @@ -132,27 +135,25 @@ static const struct { #if QSV_HAVE_AVBR { MFX_RATECONTROL_AVBR, "AVBR" }, #endif -#if QSV_HAVE_LA { MFX_RATECONTROL_LA, "LA" }, -#endif -#if QSV_HAVE_ICQ { MFX_RATECONTROL_ICQ, "ICQ" }, { MFX_RATECONTROL_LA_ICQ, "LA_ICQ" }, -#endif #if QSV_HAVE_VCM { MFX_RATECONTROL_VCM, "VCM" }, #endif -#if QSV_VERSION_ATLEAST(1, 10) { MFX_RATECONTROL_LA_EXT, "LA_EXT" }, -#endif -#if QSV_HAVE_LA_HRD { MFX_RATECONTROL_LA_HRD, "LA_HRD" }, -#endif -#if QSV_HAVE_QVBR { MFX_RATECONTROL_QVBR, "QVBR" }, -#endif }; +#define UPDATE_PARAM(a, b) \ +do { \ + if ((a) != (b)) { \ + a = b; \ + updated = 1; \ + } \ +} while (0) \ + static const char *print_ratecontrol(mfxU16 rc_mode) { int i; @@ -176,16 +177,20 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q, { mfxInfoMFX *info = &q->param.mfx; - mfxExtCodingOption *co = (mfxExtCodingOption*)coding_opts[0]; -#if QSV_HAVE_CO2 - mfxExtCodingOption2 *co2 = (mfxExtCodingOption2*)coding_opts[1]; -#endif -#if QSV_HAVE_CO3 - mfxExtCodingOption3 *co3 = (mfxExtCodingOption3*)coding_opts[2]; -#endif -#if QSV_HAVE_EXT_HEVC_TILES - mfxExtHEVCTiles *exthevctiles = (mfxExtHEVCTiles *)coding_opts[3 + QSV_HAVE_CO_VPS]; -#endif + // co is always at index 1 + mfxExtCodingOption *co = (mfxExtCodingOption*)coding_opts[1]; + mfxExtCodingOption2 *co2 = NULL; + mfxExtCodingOption3 *co3 = NULL; + mfxExtHEVCTiles *exthevctiles = NULL; + + if (q->co2_idx > 0) + co2 = (mfxExtCodingOption2*)coding_opts[q->co2_idx]; + + if (q->co3_idx > 0) + co3 = (mfxExtCodingOption3*)coding_opts[q->co3_idx]; + + if (q->exthevctiles_idx > 0) + exthevctiles = (mfxExtHEVCTiles *)coding_opts[q->exthevctiles_idx]; av_log(avctx, AV_LOG_VERBOSE, "profile: %s; level: %"PRIu16"\n", print_profile(avctx->codec_id, info->CodecProfile), info->CodecLevel); @@ -210,11 +215,6 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q, av_log(avctx, AV_LOG_VERBOSE, "BufferSizeInKB: %"PRIu16"; InitialDelayInKB: %"PRIu16"; TargetKbps: %"PRIu16"; MaxKbps: %"PRIu16"; BRCParamMultiplier: %"PRIu16"\n", info->BufferSizeInKB, info->InitialDelayInKB, info->TargetKbps, info->MaxKbps, info->BRCParamMultiplier); -#if QSV_HAVE_LA - if (info->RateControlMethod == MFX_RATECONTROL_VBR && q->extbrc && q->look_ahead_depth > 0 ) { - av_log(avctx, AV_LOG_VERBOSE, "LookAheadDepth: %"PRIu16"\n",co2->LookAheadDepth); - } -#endif } 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); @@ -226,109 +226,22 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q, info->TargetKbps, info->Accuracy, info->Convergence, info->BRCParamMultiplier); } #endif -#if QSV_HAVE_LA else if (info->RateControlMethod == MFX_RATECONTROL_LA -#if QSV_HAVE_LA_HRD || info->RateControlMethod == MFX_RATECONTROL_LA_HRD -#endif ) { av_log(avctx, AV_LOG_VERBOSE, - "TargetKbps: %"PRIu16"; LookAheadDepth: %"PRIu16"; BRCParamMultiplier: %"PRIu16"\n", - info->TargetKbps, co2->LookAheadDepth, info->BRCParamMultiplier); - } -#endif -#if QSV_HAVE_ICQ - else if (info->RateControlMethod == MFX_RATECONTROL_ICQ) { + "TargetKbps: %"PRIu16"; BRCParamMultiplier: %"PRIu16"\n", + info->TargetKbps, info->BRCParamMultiplier); + } else if (info->RateControlMethod == MFX_RATECONTROL_ICQ || + info->RateControlMethod == MFX_RATECONTROL_LA_ICQ) av_log(avctx, AV_LOG_VERBOSE, "ICQQuality: %"PRIu16"\n", info->ICQQuality); - } else if (info->RateControlMethod == MFX_RATECONTROL_LA_ICQ) { - av_log(avctx, AV_LOG_VERBOSE, "ICQQuality: %"PRIu16"; LookAheadDepth: %"PRIu16"\n", - info->ICQQuality, co2->LookAheadDepth); - } -#endif -#if QSV_HAVE_QVBR - else if (info->RateControlMethod == MFX_RATECONTROL_QVBR) { - av_log(avctx, AV_LOG_VERBOSE, "QVBRQuality: %"PRIu16"\n", - co3->QVBRQuality); - } -#endif av_log(avctx, AV_LOG_VERBOSE, "NumSlice: %"PRIu16"; NumRefFrame: %"PRIu16"\n", info->NumSlice, info->NumRefFrame); av_log(avctx, AV_LOG_VERBOSE, "RateDistortionOpt: %s\n", print_threestate(co->RateDistortionOpt)); -#if QSV_HAVE_EXT_HEVC_TILES - if (avctx->codec_id == AV_CODEC_ID_HEVC) - av_log(avctx, AV_LOG_VERBOSE, "NumTileColumns: %"PRIu16"; NumTileRows: %"PRIu16"\n", - exthevctiles->NumTileColumns, exthevctiles->NumTileRows); -#endif - -#if QSV_HAVE_CO2 - av_log(avctx, AV_LOG_VERBOSE, - "RecoveryPointSEI: %s IntRefType: %"PRIu16"; IntRefCycleSize: %"PRIu16"; IntRefQPDelta: %"PRId16"\n", - print_threestate(co->RecoveryPointSEI), co2->IntRefType, co2->IntRefCycleSize, co2->IntRefQPDelta); - - av_log(avctx, AV_LOG_VERBOSE, "MaxFrameSize: %d; ", co2->MaxFrameSize); -#if QSV_HAVE_MAX_SLICE_SIZE - av_log(avctx, AV_LOG_VERBOSE, "MaxSliceSize: %d; ", co2->MaxSliceSize); -#endif - av_log(avctx, AV_LOG_VERBOSE, "\n"); - - av_log(avctx, AV_LOG_VERBOSE, - "BitrateLimit: %s; MBBRC: %s; ExtBRC: %s\n", - print_threestate(co2->BitrateLimit), print_threestate(co2->MBBRC), - print_threestate(co2->ExtBRC)); - -#if QSV_HAVE_TRELLIS - av_log(avctx, AV_LOG_VERBOSE, "Trellis: "); - if (co2->Trellis & MFX_TRELLIS_OFF) { - av_log(avctx, AV_LOG_VERBOSE, "off"); - } else if (!co2->Trellis) { - av_log(avctx, AV_LOG_VERBOSE, "auto"); - } else { - if (co2->Trellis & MFX_TRELLIS_I) av_log(avctx, AV_LOG_VERBOSE, "I"); - if (co2->Trellis & MFX_TRELLIS_P) av_log(avctx, AV_LOG_VERBOSE, "P"); - if (co2->Trellis & MFX_TRELLIS_B) av_log(avctx, AV_LOG_VERBOSE, "B"); - } - av_log(avctx, AV_LOG_VERBOSE, "\n"); -#endif - -#if QSV_HAVE_VDENC + av_log(avctx, AV_LOG_VERBOSE, "RecoveryPointSEI: %s\n", print_threestate(co->RecoveryPointSEI)); av_log(avctx, AV_LOG_VERBOSE, "VDENC: %s\n", print_threestate(info->LowPower)); -#endif - -#if QSV_VERSION_ATLEAST(1, 8) - av_log(avctx, AV_LOG_VERBOSE, - "RepeatPPS: %s; NumMbPerSlice: %"PRIu16"; LookAheadDS: ", - print_threestate(co2->RepeatPPS), co2->NumMbPerSlice); - switch (co2->LookAheadDS) { - case MFX_LOOKAHEAD_DS_OFF: av_log(avctx, AV_LOG_VERBOSE, "off"); break; - case MFX_LOOKAHEAD_DS_2x: av_log(avctx, AV_LOG_VERBOSE, "2x"); break; - case MFX_LOOKAHEAD_DS_4x: av_log(avctx, AV_LOG_VERBOSE, "4x"); break; - default: av_log(avctx, AV_LOG_VERBOSE, "unknown"); break; - } - av_log(avctx, AV_LOG_VERBOSE, "\n"); - - av_log(avctx, AV_LOG_VERBOSE, "AdaptiveI: %s; AdaptiveB: %s; BRefType: ", - print_threestate(co2->AdaptiveI), print_threestate(co2->AdaptiveB)); - switch (co2->BRefType) { - case MFX_B_REF_OFF: av_log(avctx, AV_LOG_VERBOSE, "off"); break; - case MFX_B_REF_PYRAMID: av_log(avctx, AV_LOG_VERBOSE, "pyramid"); break; - default: av_log(avctx, AV_LOG_VERBOSE, "auto"); break; - } - av_log(avctx, AV_LOG_VERBOSE, "\n"); -#endif - -#if QSV_VERSION_ATLEAST(1, 9) - av_log(avctx, AV_LOG_VERBOSE, - "MinQPI: %"PRIu8"; MaxQPI: %"PRIu8"; MinQPP: %"PRIu8"; MaxQPP: %"PRIu8"; MinQPB: %"PRIu8"; MaxQPB: %"PRIu8"\n", - co2->MinQPI, co2->MaxQPI, co2->MinQPP, co2->MaxQPP, co2->MinQPB, co2->MaxQPB); -#endif -#endif - -#if QSV_HAVE_GPB - if (avctx->codec_id == AV_CODEC_ID_HEVC) - av_log(avctx, AV_LOG_VERBOSE,"GPB: %s\n", print_threestate(co3->GPB)); -#endif if (avctx->codec_id == AV_CODEC_ID_H264) { av_log(avctx, AV_LOG_VERBOSE, "Entropy coding: %s; MaxDecFrameBuffering: %"PRIu16"\n", @@ -346,18 +259,103 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q, av_log(avctx, AV_LOG_VERBOSE, "FrameRateExtD: %"PRIu32"; FrameRateExtN: %"PRIu32" \n", info->FrameInfo.FrameRateExtD, info->FrameInfo.FrameRateExtN); + if (co2) { + if ((info->RateControlMethod == MFX_RATECONTROL_VBR && q->extbrc && q->look_ahead_depth > 0) || + (info->RateControlMethod == MFX_RATECONTROL_LA) || + (info->RateControlMethod == MFX_RATECONTROL_LA_HRD) || + (info->RateControlMethod == MFX_RATECONTROL_LA_ICQ)) + av_log(avctx, AV_LOG_VERBOSE, "LookAheadDepth: %"PRIu16"\n", co2->LookAheadDepth); + + av_log(avctx, AV_LOG_VERBOSE, "IntRefType: %"PRIu16"; IntRefCycleSize: %"PRIu16"; IntRefQPDelta: %"PRId16"\n", + co2->IntRefType, co2->IntRefCycleSize, co2->IntRefQPDelta); + + av_log(avctx, AV_LOG_VERBOSE, "MaxFrameSize: %d; ", co2->MaxFrameSize); + av_log(avctx, AV_LOG_VERBOSE, "MaxSliceSize: %d; ", co2->MaxSliceSize); + av_log(avctx, AV_LOG_VERBOSE, "\n"); + + av_log(avctx, AV_LOG_VERBOSE, + "BitrateLimit: %s; MBBRC: %s; ExtBRC: %s\n", + print_threestate(co2->BitrateLimit), print_threestate(co2->MBBRC), + print_threestate(co2->ExtBRC)); + + av_log(avctx, AV_LOG_VERBOSE, "Trellis: "); + if (co2->Trellis & MFX_TRELLIS_OFF) { + av_log(avctx, AV_LOG_VERBOSE, "off"); + } else if (!co2->Trellis) { + av_log(avctx, AV_LOG_VERBOSE, "auto"); + } else { + if (co2->Trellis & MFX_TRELLIS_I) av_log(avctx, AV_LOG_VERBOSE, "I"); + if (co2->Trellis & MFX_TRELLIS_P) av_log(avctx, AV_LOG_VERBOSE, "P"); + if (co2->Trellis & MFX_TRELLIS_B) av_log(avctx, AV_LOG_VERBOSE, "B"); + } + av_log(avctx, AV_LOG_VERBOSE, "\n"); + + av_log(avctx, AV_LOG_VERBOSE, + "RepeatPPS: %s; NumMbPerSlice: %"PRIu16"; LookAheadDS: ", + print_threestate(co2->RepeatPPS), co2->NumMbPerSlice); + switch (co2->LookAheadDS) { + case MFX_LOOKAHEAD_DS_OFF: av_log(avctx, AV_LOG_VERBOSE, "off"); break; + case MFX_LOOKAHEAD_DS_2x: av_log(avctx, AV_LOG_VERBOSE, "2x"); break; + case MFX_LOOKAHEAD_DS_4x: av_log(avctx, AV_LOG_VERBOSE, "4x"); break; + default: av_log(avctx, AV_LOG_VERBOSE, "unknown"); break; + } + av_log(avctx, AV_LOG_VERBOSE, "\n"); + + av_log(avctx, AV_LOG_VERBOSE, "AdaptiveI: %s; AdaptiveB: %s; BRefType: ", + print_threestate(co2->AdaptiveI), print_threestate(co2->AdaptiveB)); + switch (co2->BRefType) { + case MFX_B_REF_OFF: av_log(avctx, AV_LOG_VERBOSE, "off"); break; + case MFX_B_REF_PYRAMID: av_log(avctx, AV_LOG_VERBOSE, "pyramid"); break; + default: av_log(avctx, AV_LOG_VERBOSE, "auto"); break; + } + + av_log(avctx, AV_LOG_VERBOSE, + "MinQPI: %"PRIu8"; MaxQPI: %"PRIu8"; MinQPP: %"PRIu8"; MaxQPP: %"PRIu8"; MinQPB: %"PRIu8"; MaxQPB: %"PRIu8"\n", + co2->MinQPI, co2->MaxQPI, co2->MinQPP, co2->MaxQPP, co2->MinQPB, co2->MaxQPB); + av_log(avctx, AV_LOG_VERBOSE, "DisableDeblockingIdc: %"PRIu32" \n", co2->DisableDeblockingIdc); + } + + if (co3) { + if (info->RateControlMethod == MFX_RATECONTROL_QVBR) + av_log(avctx, AV_LOG_VERBOSE, "QVBRQuality: %"PRIu16"\n", co3->QVBRQuality); + + av_log(avctx, AV_LOG_VERBOSE, "PRefType: "); + switch (co3->PRefType) { + case MFX_P_REF_DEFAULT: av_log(avctx, AV_LOG_VERBOSE, "default"); break; + case MFX_P_REF_SIMPLE: av_log(avctx, AV_LOG_VERBOSE, "simple"); break; + case MFX_P_REF_PYRAMID: av_log(avctx, AV_LOG_VERBOSE, "pyramid"); break; + default: av_log(avctx, AV_LOG_VERBOSE, "unknown"); break; + } + av_log(avctx, AV_LOG_VERBOSE, "\n"); + + if (avctx->codec_id == AV_CODEC_ID_HEVC) + av_log(avctx, AV_LOG_VERBOSE,"GPB: %s\n", print_threestate(co3->GPB)); + + av_log(avctx, AV_LOG_VERBOSE, "TransformSkip: %s \n", print_threestate(co3->TransformSkip)); + av_log(avctx, AV_LOG_VERBOSE, "IntRefCycleDist: %"PRId16"\n", co3->IntRefCycleDist); + av_log(avctx, AV_LOG_VERBOSE, "LowDelayBRC: %s\n", print_threestate(co3->LowDelayBRC)); + av_log(avctx, AV_LOG_VERBOSE, "MaxFrameSizeI: %d; ", co3->MaxFrameSizeI); + av_log(avctx, AV_LOG_VERBOSE, "MaxFrameSizeP: %d\n", co3->MaxFrameSizeP); + } + + if (exthevctiles) { + av_log(avctx, AV_LOG_VERBOSE, "NumTileColumns: %"PRIu16"; NumTileRows: %"PRIu16"\n", + exthevctiles->NumTileColumns, exthevctiles->NumTileRows); + } } static void dump_video_vp9_param(AVCodecContext *avctx, QSVEncContext *q, mfxExtBuffer **coding_opts) { mfxInfoMFX *info = &q->param.mfx; -#if QSV_HAVE_EXT_VP9_PARAM - mfxExtVP9Param *vp9_param = (mfxExtVP9Param *)coding_opts[0]; -#endif -#if QSV_HAVE_CO2 - mfxExtCodingOption2 *co2 = (mfxExtCodingOption2*)coding_opts[1]; -#endif + mfxExtVP9Param *vp9_param = NULL; + mfxExtCodingOption2 *co2 = NULL; + + if (q->vp9_idx >= 0) + vp9_param = (mfxExtVP9Param *)coding_opts[q->vp9_idx]; + + if (q->co2_idx >= 0) + co2 = (mfxExtCodingOption2*)coding_opts[q->co2_idx]; av_log(avctx, AV_LOG_VERBOSE, "profile: %s \n", print_profile(avctx->codec_id, info->CodecProfile)); @@ -382,48 +380,41 @@ static void dump_video_vp9_param(AVCodecContext *avctx, QSVEncContext *q, av_log(avctx, AV_LOG_VERBOSE, "QPI: %"PRIu16"; QPP: %"PRIu16"; QPB: %"PRIu16"\n", info->QPI, info->QPP, info->QPB); } -#if QSV_HAVE_ICQ else if (info->RateControlMethod == MFX_RATECONTROL_ICQ) { av_log(avctx, AV_LOG_VERBOSE, "ICQQuality: %"PRIu16"\n", info->ICQQuality); } -#endif else { av_log(avctx, AV_LOG_VERBOSE, "Unsupported ratecontrol method: %d \n", info->RateControlMethod); } av_log(avctx, AV_LOG_VERBOSE, "NumRefFrame: %"PRIu16"\n", info->NumRefFrame); - -#if QSV_HAVE_CO2 - av_log(avctx, AV_LOG_VERBOSE, - "IntRefType: %"PRIu16"; IntRefCycleSize: %"PRIu16"; IntRefQPDelta: %"PRId16"\n", - co2->IntRefType, co2->IntRefCycleSize, co2->IntRefQPDelta); - - av_log(avctx, AV_LOG_VERBOSE, "MaxFrameSize: %d; ", co2->MaxFrameSize); - av_log(avctx, AV_LOG_VERBOSE, "\n"); - - av_log(avctx, AV_LOG_VERBOSE, - "BitrateLimit: %s; MBBRC: %s; ExtBRC: %s\n", - print_threestate(co2->BitrateLimit), print_threestate(co2->MBBRC), - print_threestate(co2->ExtBRC)); - -#if QSV_HAVE_VDENC - av_log(avctx, AV_LOG_VERBOSE, "VDENC: %s\n", print_threestate(info->LowPower)); -#endif - -#if QSV_VERSION_ATLEAST(1, 9) - av_log(avctx, AV_LOG_VERBOSE, - "MinQPI: %"PRIu8"; MaxQPI: %"PRIu8"; MinQPP: %"PRIu8"; MaxQPP: %"PRIu8"; MinQPB: %"PRIu8"; MaxQPB: %"PRIu8"\n", - co2->MinQPI, co2->MaxQPI, co2->MinQPP, co2->MaxQPP, co2->MinQPB, co2->MaxQPB); -#endif -#endif - av_log(avctx, AV_LOG_VERBOSE, "FrameRateExtD: %"PRIu32"; FrameRateExtN: %"PRIu32" \n", info->FrameInfo.FrameRateExtD, info->FrameInfo.FrameRateExtN); -#if QSV_HAVE_EXT_VP9_PARAM - av_log(avctx, AV_LOG_VERBOSE, "WriteIVFHeaders: %s \n", - print_threestate(vp9_param->WriteIVFHeaders)); -#endif + if (co2) { + av_log(avctx, AV_LOG_VERBOSE, + "IntRefType: %"PRIu16"; IntRefCycleSize: %"PRIu16"; IntRefQPDelta: %"PRId16"\n", + co2->IntRefType, co2->IntRefCycleSize, co2->IntRefQPDelta); + + av_log(avctx, AV_LOG_VERBOSE, "MaxFrameSize: %d; ", co2->MaxFrameSize); + av_log(avctx, AV_LOG_VERBOSE, "\n"); + + av_log(avctx, AV_LOG_VERBOSE, + "BitrateLimit: %s; MBBRC: %s; ExtBRC: %s\n", + print_threestate(co2->BitrateLimit), print_threestate(co2->MBBRC), + print_threestate(co2->ExtBRC)); + + av_log(avctx, AV_LOG_VERBOSE, "VDENC: %s\n", print_threestate(info->LowPower)); + + av_log(avctx, AV_LOG_VERBOSE, + "MinQPI: %"PRIu8"; MaxQPI: %"PRIu8"; MinQPP: %"PRIu8"; MaxQPP: %"PRIu8"; MinQPB: %"PRIu8"; MaxQPB: %"PRIu8"\n", + co2->MinQPI, co2->MaxQPI, co2->MinQPP, co2->MaxQPP, co2->MinQPB, co2->MaxQPB); + } + + if (vp9_param) { + av_log(avctx, AV_LOG_VERBOSE, "WriteIVFHeaders: %s \n", + print_threestate(vp9_param->WriteIVFHeaders)); + } } static void dump_video_mjpeg_param(AVCodecContext *avctx, QSVEncContext *q) @@ -447,11 +438,6 @@ static int select_rc_mode(AVCodecContext *avctx, QSVEncContext *q) int want_qscale = !!(avctx->flags & AV_CODEC_FLAG_QSCALE); int want_vcm = q->vcm; - if (want_la && !QSV_HAVE_LA) { - av_log(avctx, AV_LOG_ERROR, - "Lookahead ratecontrol mode requested, but is not supported by this SDK version\n"); - return AVERROR(ENOSYS); - } if (want_vcm && !QSV_HAVE_VCM) { av_log(avctx, AV_LOG_ERROR, "VCM ratecontrol mode requested, but is not supported by this SDK version\n"); @@ -465,12 +451,6 @@ 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)"; @@ -481,25 +461,19 @@ static int select_rc_mode(AVCodecContext *avctx, QSVEncContext *q) rc_desc = "video conferencing mode (VCM)"; } #endif -#if QSV_HAVE_LA else if (want_la) { rc_mode = MFX_RATECONTROL_LA; rc_desc = "VBR with lookahead (LA)"; -#if QSV_HAVE_ICQ if (avctx->global_quality > 0) { rc_mode = MFX_RATECONTROL_LA_ICQ; rc_desc = "intelligent constant quality with lookahead (LA_ICQ)"; } -#endif } -#endif -#if QSV_HAVE_ICQ else if (avctx->global_quality > 0 && !avctx->rc_max_rate) { rc_mode = MFX_RATECONTROL_ICQ; rc_desc = "intelligent constant quality (ICQ)"; } -#endif else if (avctx->rc_max_rate == avctx->bit_rate) { rc_mode = MFX_RATECONTROL_CBR; rc_desc = "constant bitrate (CBR)"; @@ -510,12 +484,10 @@ static int select_rc_mode(AVCodecContext *avctx, QSVEncContext *q) rc_desc = "average variable bitrate (AVBR)"; } #endif -#if QSV_HAVE_QVBR else if (avctx->global_quality > 0) { rc_mode = MFX_RATECONTROL_QVBR; rc_desc = "constant quality with VBR algorithm (QVBR)"; } -#endif else { rc_mode = MFX_RATECONTROL_VBR; rc_desc = "variable bitrate (VBR)"; @@ -578,7 +550,9 @@ static int init_video_param_jpeg(AVCodecContext *avctx, QSVEncContext *q) if (!desc) return AVERROR_BUG; - ff_qsv_map_pixfmt(sw_format, &q->param.mfx.FrameInfo.FourCC); + ret = ff_qsv_map_pixfmt(sw_format, &q->param.mfx.FrameInfo.FourCC); + if (ret < 0) + return AVERROR_BUG; q->param.mfx.FrameInfo.CropX = 0; q->param.mfx.FrameInfo.CropY = 0; @@ -586,7 +560,8 @@ static int init_video_param_jpeg(AVCodecContext *avctx, QSVEncContext *q) 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.ChromaFormat = MFX_CHROMAFORMAT_YUV420 + + !desc->log2_chroma_w + !desc->log2_chroma_h; 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; @@ -652,14 +627,7 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) } if (q->low_power == 1) { -#if QSV_HAVE_VDENC q->param.mfx.LowPower = MFX_CODINGOPTION_ON; -#else - av_log(avctx, AV_LOG_WARNING, "The low_power option is " - "not supported with this MSDK version.\n"); - q->low_power = 0; - q->param.mfx.LowPower = MFX_CODINGOPTION_OFF; -#endif } else if (q->low_power == -1) q->param.mfx.LowPower = MFX_CODINGOPTION_UNKNOWN; else @@ -681,7 +649,9 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) if (!desc) return AVERROR_BUG; - ff_qsv_map_pixfmt(sw_format, &q->param.mfx.FrameInfo.FourCC); + ret = ff_qsv_map_pixfmt(sw_format, &q->param.mfx.FrameInfo.FourCC); + if (ret < 0) + return AVERROR_BUG; q->param.mfx.FrameInfo.CropX = 0; q->param.mfx.FrameInfo.CropY = 0; @@ -747,26 +717,20 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) switch (q->param.mfx.RateControlMethod) { case MFX_RATECONTROL_CBR: case MFX_RATECONTROL_VBR: -#if QSV_HAVE_LA if (q->extbrc) { q->extco2.LookAheadDepth = q->look_ahead_depth; } -#endif #if QSV_HAVE_VCM case MFX_RATECONTROL_VCM: #endif -#if QSV_HAVE_QVBR case MFX_RATECONTROL_QVBR: -#endif q->param.mfx.BufferSizeInKB = buffer_size_in_kilobytes / brc_param_multiplier; q->param.mfx.InitialDelayInKB = initial_delay_in_kilobytes / brc_param_multiplier; q->param.mfx.TargetKbps = target_bitrate_kbps / brc_param_multiplier; q->param.mfx.MaxKbps = max_bitrate_kbps / brc_param_multiplier; q->param.mfx.BRCParamMultiplier = brc_param_multiplier; -#if QSV_HAVE_QVBR if (q->param.mfx.RateControlMethod == MFX_RATECONTROL_QVBR) q->extco3.QVBRQuality = av_clip(avctx->global_quality, 0, 51); -#endif break; case MFX_RATECONTROL_CQP: quant = avctx->global_quality / FF_QP2LAMBDA; @@ -784,20 +748,16 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) q->param.mfx.BRCParamMultiplier = brc_param_multiplier; break; #endif -#if QSV_HAVE_LA case MFX_RATECONTROL_LA: q->param.mfx.TargetKbps = target_bitrate_kbps / brc_param_multiplier; q->extco2.LookAheadDepth = q->look_ahead_depth; q->param.mfx.BRCParamMultiplier = brc_param_multiplier; break; -#if QSV_HAVE_ICQ case MFX_RATECONTROL_LA_ICQ: q->extco2.LookAheadDepth = q->look_ahead_depth; case MFX_RATECONTROL_ICQ: q->param.mfx.ICQQuality = av_clip(avctx->global_quality, 1, 51); break; -#endif -#endif } // The HEVC encoder plugin currently fails with some old libmfx version if coding options @@ -841,54 +801,48 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extco; -#if QSV_HAVE_CO2 if (avctx->codec_id == AV_CODEC_ID_H264) { + if (q->bitrate_limit >= 0) + q->extco2.BitrateLimit = q->bitrate_limit ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; + + if (avctx->trellis >= 0) + q->extco2.Trellis = (avctx->trellis == 0) ? MFX_TRELLIS_OFF : (MFX_TRELLIS_I | MFX_TRELLIS_P | MFX_TRELLIS_B); + else + q->extco2.Trellis = MFX_TRELLIS_UNKNOWN; + + q->extco2.LookAheadDS = q->look_ahead_downsampling; + q->extco2.RepeatPPS = q->repeat_pps ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; + + if (q->adaptive_i >= 0) + q->extco2.AdaptiveI = q->adaptive_i ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; + if (q->adaptive_b >= 0) + q->extco2.AdaptiveB = q->adaptive_b ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; + } + + if (avctx->codec_id == AV_CODEC_ID_H264 || avctx->codec_id == AV_CODEC_ID_HEVC) { + if (q->extbrc >= 0) + q->extco2.ExtBRC = q->extbrc ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; + if (q->max_frame_size >= 0) + q->extco2.MaxFrameSize = q->max_frame_size; if (q->int_ref_type >= 0) q->extco2.IntRefType = q->int_ref_type; if (q->int_ref_cycle_size >= 0) q->extco2.IntRefCycleSize = q->int_ref_cycle_size; if (q->int_ref_qp_delta != INT16_MIN) q->extco2.IntRefQPDelta = q->int_ref_qp_delta; - - if (q->bitrate_limit >= 0) - q->extco2.BitrateLimit = q->bitrate_limit ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; - if (q->mbbrc >= 0) - q->extco2.MBBRC = q->mbbrc ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; - - if (q->max_frame_size >= 0) - q->extco2.MaxFrameSize = q->max_frame_size; -#if QSV_HAVE_MAX_SLICE_SIZE if (q->max_slice_size >= 0) q->extco2.MaxSliceSize = q->max_slice_size; -#endif - -#if QSV_HAVE_TRELLIS - if (avctx->trellis >= 0) - q->extco2.Trellis = (avctx->trellis == 0) ? MFX_TRELLIS_OFF : (MFX_TRELLIS_I | MFX_TRELLIS_P | MFX_TRELLIS_B); - else - q->extco2.Trellis = MFX_TRELLIS_UNKNOWN; -#endif - -#if QSV_VERSION_ATLEAST(1, 8) - q->extco2.LookAheadDS = q->look_ahead_downsampling; - q->extco2.RepeatPPS = q->repeat_pps ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; + q->extco2.DisableDeblockingIdc = q->dblk_idc; if (q->b_strategy >= 0) q->extco2.BRefType = q->b_strategy ? MFX_B_REF_PYRAMID : MFX_B_REF_OFF; - if (q->adaptive_i >= 0) - q->extco2.AdaptiveI = q->adaptive_i ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; - if (q->adaptive_b >= 0) - q->extco2.AdaptiveB = q->adaptive_b ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; -#endif - } - - if (avctx->codec_id == AV_CODEC_ID_H264 || avctx->codec_id == AV_CODEC_ID_HEVC) { - if (q->extbrc >= 0) - q->extco2.ExtBRC = q->extbrc ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; - -#if QSV_VERSION_ATLEAST(1, 9) - if (avctx->qmin >= 0 && avctx->qmax >= 0 && avctx->qmin > avctx->qmax) { - av_log(avctx, AV_LOG_ERROR, "qmin and or qmax are set but invalid, please make sure min <= max\n"); + if ((avctx->qmin >= 0 && avctx->qmax >= 0 && avctx->qmin > avctx->qmax) || + (q->max_qp_i >= 0 && q->min_qp_i >= 0 && q->min_qp_i > q->max_qp_i) || + (q->max_qp_p >= 0 && q->min_qp_p >= 0 && q->min_qp_p > q->max_qp_p) || + (q->max_qp_b >= 0 && q->min_qp_b >= 0 && q->min_qp_b > q->max_qp_b)) { + av_log(avctx, AV_LOG_ERROR, + "qmin and or qmax are set but invalid," + " please make sure min <= max\n"); return AVERROR(EINVAL); } if (avctx->qmin >= 0) { @@ -899,13 +853,26 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) q->extco2.MaxQPI = avctx->qmax > 51 ? 51 : avctx->qmax; q->extco2.MaxQPP = q->extco2.MaxQPB = q->extco2.MaxQPI; } -#endif + if (q->min_qp_i >= 0) + q->extco2.MinQPI = q->min_qp_i > 51 ? 51 : q->min_qp_i; + if (q->max_qp_i >= 0) + q->extco2.MaxQPI = q->max_qp_i > 51 ? 51 : q->max_qp_i; + if (q->min_qp_p >= 0) + q->extco2.MinQPP = q->min_qp_p > 51 ? 51 : q->min_qp_p; + if (q->max_qp_p >= 0) + q->extco2.MaxQPP = q->max_qp_p > 51 ? 51 : q->max_qp_p; + if (q->min_qp_b >= 0) + q->extco2.MinQPB = q->min_qp_b > 51 ? 51 : q->min_qp_b; + if (q->max_qp_b >= 0) + q->extco2.MaxQPB = q->max_qp_b > 51 ? 51 : q->max_qp_b; + if (q->mbbrc >= 0) + q->extco2.MBBRC = q->mbbrc ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; + q->extco2.Header.BufferId = MFX_EXTBUFF_CODING_OPTION2; q->extco2.Header.BufferSz = sizeof(q->extco2); q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extco2; } -#endif if (avctx->codec_id == AV_CODEC_ID_H264) { #if QSV_HAVE_MF @@ -919,27 +886,64 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) } #endif } -#if QSV_HAVE_CO3 q->extco3.Header.BufferId = MFX_EXTBUFF_CODING_OPTION3; q->extco3.Header.BufferSz = sizeof(q->extco3); -#if QSV_HAVE_GPB - if (avctx->codec_id == AV_CODEC_ID_HEVC) + + if (avctx->codec_id == AV_CODEC_ID_HEVC || + avctx->codec_id == AV_CODEC_ID_H264) { + switch (q->p_strategy) { + case 0: + q->extco3.PRefType = MFX_P_REF_DEFAULT; + break; + case 1: + q->extco3.PRefType = MFX_P_REF_SIMPLE; + break; + case 2: + q->extco3.PRefType = MFX_P_REF_PYRAMID; + break; + default: + q->extco3.PRefType = MFX_P_REF_DEFAULT; + av_log(avctx, AV_LOG_WARNING, + "invalid p_strategy, set to default\n"); + break; + } + if (q->extco3.PRefType == MFX_P_REF_PYRAMID && + avctx->max_b_frames != 0) { + av_log(avctx, AV_LOG_WARNING, + "Please set max_b_frames(-bf) to 0 to enable P-pyramid\n"); + } + if (q->int_ref_cycle_dist >= 0) + q->extco3.IntRefCycleDist = q->int_ref_cycle_dist; + if (q->low_delay_brc >= 0) + q->extco3.LowDelayBRC = q->low_delay_brc ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; + if (q->max_frame_size_i >= 0) + q->extco3.MaxFrameSizeI = q->max_frame_size_i; + if (q->max_frame_size_p >= 0) + q->extco3.MaxFrameSizeP = q->max_frame_size_p; + } + + if (avctx->codec_id == AV_CODEC_ID_HEVC) { + if (q->transform_skip >= 0) + q->extco3.TransformSkip = q->transform_skip ? MFX_CODINGOPTION_ON : + MFX_CODINGOPTION_OFF; + else + q->extco3.TransformSkip = MFX_CODINGOPTION_UNKNOWN; q->extco3.GPB = q->gpb ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF; -#endif + } q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extco3; -#endif } -#if QSV_HAVE_EXT_VP9_PARAM if (avctx->codec_id == AV_CODEC_ID_VP9) { q->extvp9param.Header.BufferId = MFX_EXTBUFF_VP9_PARAM; q->extvp9param.Header.BufferSz = sizeof(q->extvp9param); q->extvp9param.WriteIVFHeaders = MFX_CODINGOPTION_OFF; +#if QSV_HAVE_EXT_VP9_TILES + q->extvp9param.NumTileColumns = q->tile_cols; + q->extvp9param.NumTileRows = q->tile_rows; +#endif q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->extvp9param; } -#endif -#if QSV_HAVE_EXT_HEVC_TILES if (avctx->codec_id == AV_CODEC_ID_HEVC) { q->exthevctiles.Header.BufferId = MFX_EXTBUFF_HEVC_TILES; q->exthevctiles.Header.BufferSz = sizeof(q->exthevctiles); @@ -947,7 +951,6 @@ static int init_video_param(AVCodecContext *avctx, QSVEncContext *q) q->exthevctiles.NumTileRows = q->tile_rows; q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->exthevctiles; } -#endif q->extvsi.VideoFullRange = (avctx->color_range == AVCOL_RANGE_JPEG); q->extvsi.ColourDescriptionPresent = 0; @@ -1000,41 +1003,44 @@ static int qsv_retrieve_enc_jpeg_params(AVCodecContext *avctx, QSVEncContext *q) static int qsv_retrieve_enc_vp9_params(AVCodecContext *avctx, QSVEncContext *q) { int ret = 0; -#if QSV_HAVE_EXT_VP9_PARAM mfxExtVP9Param vp9_extend_buf = { .Header.BufferId = MFX_EXTBUFF_VP9_PARAM, .Header.BufferSz = sizeof(vp9_extend_buf), }; -#endif -#if QSV_HAVE_CO2 mfxExtCodingOption2 co2 = { .Header.BufferId = MFX_EXTBUFF_CODING_OPTION2, .Header.BufferSz = sizeof(co2), }; -#endif -#if QSV_HAVE_CO3 mfxExtCodingOption3 co3 = { .Header.BufferId = MFX_EXTBUFF_CODING_OPTION3, .Header.BufferSz = sizeof(co3), }; -#endif - mfxExtBuffer *ext_buffers[] = { -#if QSV_HAVE_EXT_VP9_PARAM - (mfxExtBuffer*)&vp9_extend_buf, -#endif -#if QSV_HAVE_CO2 - (mfxExtBuffer*)&co2, -#endif -#if QSV_HAVE_CO3 - (mfxExtBuffer*)&co3, -#endif - }; + mfxExtBuffer *ext_buffers[3]; + int ext_buf_num = 0; + + q->co2_idx = q->co3_idx = q->vp9_idx = -1; + + // It is possible the runtime doesn't support the given ext buffer + if (QSV_RUNTIME_VERSION_ATLEAST(q->ver, 1, 6)) { + q->co2_idx = ext_buf_num; + ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&co2; + } + + if (QSV_RUNTIME_VERSION_ATLEAST(q->ver, 1, 11)) { + q->co3_idx = ext_buf_num; + ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&co3; + } + + if (QSV_RUNTIME_VERSION_ATLEAST(q->ver, 1, 26)) { + q->vp9_idx = ext_buf_num; + ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&vp9_extend_buf; + } q->param.ExtParam = ext_buffers; - q->param.NumExtParam = FF_ARRAY_ELEMS(ext_buffers); + q->param.NumExtParam = ext_buf_num; ret = MFXVideoENCODE_GetVideoParam(q->session, &q->param); if (ret < 0) @@ -1066,20 +1072,15 @@ static int qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q) .Header.BufferId = MFX_EXTBUFF_CODING_OPTION, .Header.BufferSz = sizeof(co), }; -#if QSV_HAVE_CO2 mfxExtCodingOption2 co2 = { .Header.BufferId = MFX_EXTBUFF_CODING_OPTION2, .Header.BufferSz = sizeof(co2), }; -#endif -#if QSV_HAVE_CO3 mfxExtCodingOption3 co3 = { .Header.BufferId = MFX_EXTBUFF_CODING_OPTION3, .Header.BufferSz = sizeof(co3), }; -#endif -#if QSV_HAVE_CO_VPS uint8_t vps_buf[128]; mfxExtCodingOptionVPS extradata_vps = { .Header.BufferId = MFX_EXTBUFF_CODING_OPTION_VPS, @@ -1087,37 +1088,39 @@ static int qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q) .VPSBuffer = vps_buf, .VPSBufSize = sizeof(vps_buf), }; -#endif -#if QSV_HAVE_EXT_HEVC_TILES mfxExtHEVCTiles hevc_tile_buf = { .Header.BufferId = MFX_EXTBUFF_HEVC_TILES, .Header.BufferSz = sizeof(hevc_tile_buf), }; -#endif - mfxExtBuffer *ext_buffers[2 + QSV_HAVE_CO2 + QSV_HAVE_CO3 + QSV_HAVE_CO_VPS + QSV_HAVE_EXT_HEVC_TILES]; + mfxExtBuffer *ext_buffers[6]; int need_pps = avctx->codec_id != AV_CODEC_ID_MPEG2VIDEO; int ret, ext_buf_num = 0, extradata_offset = 0; + q->co2_idx = q->co3_idx = q->exthevctiles_idx = -1; ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&extradata; ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&co; -#if QSV_HAVE_CO2 - ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&co2; -#endif -#if QSV_HAVE_CO3 - ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&co3; -#endif -#if QSV_HAVE_CO_VPS + + // It is possible the runtime doesn't support the given ext buffer + if (QSV_RUNTIME_VERSION_ATLEAST(q->ver, 1, 6)) { + q->co2_idx = ext_buf_num; + ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&co2; + } + + if (QSV_RUNTIME_VERSION_ATLEAST(q->ver, 1, 11)) { + q->co3_idx = ext_buf_num; + ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&co3; + } + q->hevc_vps = ((avctx->codec_id == AV_CODEC_ID_HEVC) && QSV_RUNTIME_VERSION_ATLEAST(q->ver, 1, 17)); if (q->hevc_vps) ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&extradata_vps; -#endif -#if QSV_HAVE_EXT_HEVC_TILES - if (avctx->codec_id == AV_CODEC_ID_HEVC) + if (avctx->codec_id == AV_CODEC_ID_HEVC && QSV_RUNTIME_VERSION_ATLEAST(q->ver, 1, 13)) { + q->exthevctiles_idx = ext_buf_num; ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&hevc_tile_buf; -#endif + } q->param.ExtParam = ext_buffers; q->param.NumExtParam = ext_buf_num; @@ -1130,29 +1133,23 @@ static int qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q) q->packet_size = q->param.mfx.BufferSizeInKB * q->param.mfx.BRCParamMultiplier * 1000; if (!extradata.SPSBufSize || (need_pps && !extradata.PPSBufSize) -#if QSV_HAVE_CO_VPS || (q->hevc_vps && !extradata_vps.VPSBufSize) -#endif ) { av_log(avctx, AV_LOG_ERROR, "No extradata returned from libmfx.\n"); return AVERROR_UNKNOWN; } avctx->extradata_size = extradata.SPSBufSize + need_pps * extradata.PPSBufSize; -#if QSV_HAVE_CO_VPS avctx->extradata_size += q->hevc_vps * extradata_vps.VPSBufSize; -#endif avctx->extradata = av_malloc(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!avctx->extradata) return AVERROR(ENOMEM); -#if QSV_HAVE_CO_VPS if (q->hevc_vps) { memcpy(avctx->extradata, vps_buf, extradata_vps.VPSBufSize); extradata_offset += extradata_vps.VPSBufSize; } -#endif memcpy(avctx->extradata + extradata_offset, sps_buf, extradata.SPSBufSize); extradata_offset += extradata.SPSBufSize; @@ -1170,7 +1167,7 @@ static int qsv_retrieve_enc_params(AVCodecContext *avctx, QSVEncContext *q) cpb_props->avg_bitrate = avctx->bit_rate; cpb_props->buffer_size = avctx->rc_buffer_size; - dump_video_param(avctx, q, ext_buffers + 1); + dump_video_param(avctx, q, ext_buffers); return 0; } @@ -1254,16 +1251,6 @@ static int qsvenc_init_session(AVCodecContext *avctx, QSVEncContext *q) return 0; } -static inline unsigned int qsv_fifo_item_size(void) -{ - return sizeof(AVPacket) + sizeof(mfxSyncPoint*) + sizeof(mfxBitstream*); -} - -static inline unsigned int qsv_fifo_size(const AVFifoBuffer* fifo) -{ - return av_fifo_size(fifo)/qsv_fifo_item_size(); -} - int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q) { int iopattern = 0; @@ -1272,7 +1259,7 @@ int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q) q->param.AsyncDepth = q->async_depth; - q->async_fifo = av_fifo_alloc(q->async_depth * qsv_fifo_item_size()); + q->async_fifo = av_fifo_alloc2(q->async_depth, sizeof(QSVPacket), 0); if (!q->async_fifo) return AVERROR(ENOMEM); @@ -1411,15 +1398,29 @@ static void free_encoder_ctrl_payloads(mfxEncodeCtrl* enc_ctrl) } } +static void free_encoder_ctrl_extparam(mfxEncodeCtrl* enc_ctrl) +{ + if (enc_ctrl) { + int i; + for (i = 0; i < enc_ctrl->NumExtParam && i < QSV_MAX_ENC_EXTPARAM; i++) { + if (enc_ctrl->ExtParam[i]) + av_freep(&(enc_ctrl->ExtParam[i])); + } + enc_ctrl->NumExtParam = 0; + } +} + static void clear_unused_frames(QSVEncContext *q) { QSVFrame *cur = q->work_frames; while (cur) { if (cur->used && !cur->surface.Data.Locked) { free_encoder_ctrl_payloads(&cur->enc_ctrl); + free_encoder_ctrl_extparam(&cur->enc_ctrl); //do not reuse enc_ctrl from previous frame memset(&cur->enc_ctrl, 0, sizeof(cur->enc_ctrl)); cur->enc_ctrl.Payload = cur->payloads; + cur->enc_ctrl.ExtParam = cur->extparam; if (cur->frame->format == AV_PIX_FMT_QSV) { av_frame_unref(cur->frame); } @@ -1457,6 +1458,7 @@ static int get_free_frame(QSVEncContext *q, QSVFrame **f) return AVERROR(ENOMEM); } frame->enc_ctrl.Payload = frame->payloads; + frame->enc_ctrl.ExtParam = frame->extparam; *last = frame; *f = frame; @@ -1514,6 +1516,7 @@ static int submit_frame(QSVEncContext *q, const AVFrame *frame, return ret; } } else { + av_frame_unref(qf->frame); ret = av_frame_ref(qf->frame, frame); if (ret < 0) return ret; @@ -1532,11 +1535,12 @@ static int submit_frame(QSVEncContext *q, const AVFrame *frame, else if (frame->repeat_pict == 4) qf->surface.Info.PicStruct |= MFX_PICSTRUCT_FRAME_TRIPLING; - qf->surface.Data.PitchLow = qf->frame->linesize[0]; - qf->surface.Data.Y = qf->frame->data[0]; - qf->surface.Data.UV = qf->frame->data[1]; + ret = ff_qsv_map_frame_to_surface(qf->frame, &qf->surface); + if (ret < 0) { + av_log(q->avctx, AV_LOG_ERROR, "map frame to surface failed.\n"); + return ret; + } } - qf->surface.Data.TimeStamp = av_rescale_q(frame->pts, q->avctx->time_base, (AVRational){1, 90000}); *new_frame = qf; @@ -1556,18 +1560,152 @@ static void print_interlace_msg(AVCodecContext *avctx, QSVEncContext *q) } } +static int set_roi_encode_ctrl(AVCodecContext *avctx, const AVFrame *frame, + mfxEncodeCtrl *enc_ctrl) +{ + AVFrameSideData *sd = NULL; + int mb_size; + + if (avctx->codec_id == AV_CODEC_ID_H264) + mb_size = 16; + else if (avctx->codec_id == AV_CODEC_ID_H265) + mb_size = 32; + else + return 0; + + if (frame) + sd = av_frame_get_side_data(frame, AV_FRAME_DATA_REGIONS_OF_INTEREST); + + if (sd) { + mfxExtEncoderROI *enc_roi = NULL; + AVRegionOfInterest *roi; + uint32_t roi_size; + int nb_roi, i; + + roi = (AVRegionOfInterest *)sd->data; + roi_size = roi->self_size; + if (!roi_size || sd->size % roi_size) { + av_log(avctx, AV_LOG_ERROR, "Invalid ROI Data.\n"); + return AVERROR(EINVAL); + } + nb_roi = sd->size / roi_size; + if (nb_roi > QSV_MAX_ROI_NUM) { + av_log(avctx, AV_LOG_WARNING, "More ROIs set than " + "supported by driver (%d > %d).\n", + nb_roi, QSV_MAX_ROI_NUM); + nb_roi = QSV_MAX_ROI_NUM; + } + + enc_roi = av_mallocz(sizeof(*enc_roi)); + if (!enc_roi) + return AVERROR(ENOMEM); + enc_roi->Header.BufferId = MFX_EXTBUFF_ENCODER_ROI; + enc_roi->Header.BufferSz = sizeof(*enc_roi); + enc_roi->NumROI = nb_roi; + enc_roi->ROIMode = MFX_ROI_MODE_QP_DELTA; + for (i = 0; i < nb_roi; i++) { + roi = (AVRegionOfInterest *)(sd->data + roi_size * i); + enc_roi->ROI[i].Top = FFALIGN(roi->top, mb_size); + enc_roi->ROI[i].Bottom = FFALIGN(roi->bottom, mb_size); + enc_roi->ROI[i].Left = FFALIGN(roi->left, mb_size); + enc_roi->ROI[i].Right = FFALIGN(roi->right, mb_size); + enc_roi->ROI[i].DeltaQP = + roi->qoffset.num * 51 / roi->qoffset.den; + av_log(avctx, AV_LOG_DEBUG, "ROI: (%d,%d)-(%d,%d) -> %+d.\n", + roi->top, roi->left, roi->bottom, roi->right, + enc_roi->ROI[i].DeltaQP); + } + enc_ctrl->ExtParam[enc_ctrl->NumExtParam] = (mfxExtBuffer *)enc_roi; + enc_ctrl->NumExtParam++; + } + return 0; +} + +static int update_qp(AVCodecContext *avctx, QSVEncContext *q, + const AVFrame *frame) +{ + int updated = 0, qp = 0, new_qp; + char *tail; + AVDictionaryEntry *entry = NULL; + + if (avctx->codec_id != AV_CODEC_ID_H264 && avctx->codec_id != AV_CODEC_ID_HEVC) + return 0; + + entry = av_dict_get(frame->metadata, "qsv_config_qp", NULL, 0); + if (entry && q->param.mfx.RateControlMethod == MFX_RATECONTROL_CQP) { + qp = strtol(entry->value, &tail, 10); + if (*tail) { + av_log(avctx, AV_LOG_WARNING, "Invalid qsv_config_qp string. Ignore this metadata\n"); + return 0; + } + if (qp < 0 || qp > 51) { + av_log(avctx, AV_LOG_WARNING, "Invalid qp, clip to 0 ~ 51\n"); + qp = av_clip(qp, 0, 51); + } + av_log(avctx, AV_LOG_DEBUG, "Configure qp: %d\n",qp); + UPDATE_PARAM(q->param.mfx.QPP, qp); + new_qp = av_clip(qp * fabs(avctx->i_quant_factor) + + avctx->i_quant_offset, 0, 51); + UPDATE_PARAM(q->param.mfx.QPI, new_qp); + new_qp = av_clip(qp * fabs(avctx->b_quant_factor) + + avctx->b_quant_offset, 0, 51); + UPDATE_PARAM(q->param.mfx.QPB, new_qp); + av_log(avctx, AV_LOG_DEBUG, + "using fixed qp = %d/%d/%d for idr/p/b frames\n", + q->param.mfx.QPI, q->param.mfx.QPP, q->param.mfx.QPB); + } + return updated; +} + +static int update_parameters(AVCodecContext *avctx, QSVEncContext *q, + const AVFrame *frame) +{ + int needReset = 0, ret = 0; + + if (!frame) + return 0; + + needReset = update_qp(avctx, q, frame); + if (!needReset) + return 0; + + if (avctx->hwaccel_context) { + AVQSVContext *qsv = avctx->hwaccel_context; + int i, j; + q->param.ExtParam = q->extparam; + for (i = 0; i < qsv->nb_ext_buffers; i++) + q->param.ExtParam[i] = qsv->ext_buffers[i]; + q->param.NumExtParam = qsv->nb_ext_buffers; + + for (i = 0; i < q->nb_extparam_internal; i++) { + for (j = 0; j < qsv->nb_ext_buffers; j++) { + if (qsv->ext_buffers[j]->BufferId == q->extparam_internal[i]->BufferId) + break; + } + if (j < qsv->nb_ext_buffers) + continue; + q->param.ExtParam[q->param.NumExtParam++] = q->extparam_internal[i]; + } + } else { + q->param.ExtParam = q->extparam_internal; + q->param.NumExtParam = q->nb_extparam_internal; + } + av_log(avctx, AV_LOG_DEBUG, "Parameter change, call msdk reset.\n"); + ret = MFXVideoENCODE_Reset(q->session, &q->param); + if (ret < 0) + return ff_qsv_print_error(avctx, ret, "Error during resetting"); + + return 0; +} + static int encode_frame(AVCodecContext *avctx, QSVEncContext *q, const AVFrame *frame) { - AVPacket new_pkt = { 0 }; - mfxBitstream *bs = NULL; -#if QSV_VERSION_ATLEAST(1, 26) + QSVPacket pkt = { { 0 } }; mfxExtAVCEncodedFrameInfo *enc_info = NULL; mfxExtBuffer **enc_buf = NULL; -#endif mfxFrameSurface1 *surf = NULL; - mfxSyncPoint *sync = NULL; QSVFrame *qsv_frame = NULL; mfxEncodeCtrl* enc_ctrl = NULL; int ret; @@ -1590,19 +1728,18 @@ static int encode_frame(AVCodecContext *avctx, QSVEncContext *q, } } - ret = av_new_packet(&new_pkt, q->packet_size); + ret = av_new_packet(&pkt.pkt, q->packet_size); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Error allocating the output packet\n"); return ret; } - bs = av_mallocz(sizeof(*bs)); - if (!bs) + pkt.bs = av_mallocz(sizeof(*pkt.bs)); + if (!pkt.bs) goto nomem; - bs->Data = new_pkt.data; - bs->MaxLength = new_pkt.size; + pkt.bs->Data = pkt.pkt.data; + pkt.bs->MaxLength = pkt.pkt.size; -#if QSV_VERSION_ATLEAST(1, 26) if (avctx->codec_id == AV_CODEC_ID_H264) { enc_info = av_mallocz(sizeof(*enc_info)); if (!enc_info) @@ -1610,26 +1747,33 @@ static int encode_frame(AVCodecContext *avctx, QSVEncContext *q, enc_info->Header.BufferId = MFX_EXTBUFF_ENCODED_FRAME_INFO; enc_info->Header.BufferSz = sizeof (*enc_info); - bs->NumExtParam = 1; + pkt.bs->NumExtParam = 1; enc_buf = av_mallocz(sizeof(mfxExtBuffer *)); if (!enc_buf) goto nomem; enc_buf[0] = (mfxExtBuffer *)enc_info; - bs->ExtParam = enc_buf; + pkt.bs->ExtParam = enc_buf; } -#endif if (q->set_encode_ctrl_cb) { q->set_encode_ctrl_cb(avctx, frame, &qsv_frame->enc_ctrl); } - sync = av_mallocz(sizeof(*sync)); - if (!sync) + if ((avctx->codec_id == AV_CODEC_ID_H264 || + avctx->codec_id == AV_CODEC_ID_H265) && + enc_ctrl && QSV_RUNTIME_VERSION_ATLEAST(q->ver, 1, 8)) { + ret = set_roi_encode_ctrl(avctx, frame, enc_ctrl); + if (ret < 0) + goto free; + } + + pkt.sync = av_mallocz(sizeof(*pkt.sync)); + if (!pkt.sync) goto nomem; do { - ret = MFXVideoENCODE_EncodeFrameAsync(q->session, enc_ctrl, surf, bs, sync); + ret = MFXVideoENCODE_EncodeFrameAsync(q->session, enc_ctrl, surf, pkt.bs, pkt.sync); if (ret == MFX_WRN_DEVICE_BUSY) av_usleep(500); } while (ret == MFX_WRN_DEVICE_BUSY || ret == MFX_WRN_IN_EXECUTION); @@ -1643,26 +1787,22 @@ static int encode_frame(AVCodecContext *avctx, QSVEncContext *q, goto free; } - if (ret == MFX_WRN_INCOMPATIBLE_VIDEO_PARAM && frame->interlaced_frame) + if (ret == MFX_WRN_INCOMPATIBLE_VIDEO_PARAM && frame && frame->interlaced_frame) print_interlace_msg(avctx, q); ret = 0; - if (*sync) { - av_fifo_generic_write(q->async_fifo, &new_pkt, sizeof(new_pkt), NULL); - av_fifo_generic_write(q->async_fifo, &sync, sizeof(sync), NULL); - av_fifo_generic_write(q->async_fifo, &bs, sizeof(bs), NULL); + if (*pkt.sync) { + av_fifo_write(q->async_fifo, &pkt, 1); } else { free: - av_freep(&sync); - av_packet_unref(&new_pkt); - av_freep(&bs); -#if QSV_VERSION_ATLEAST(1, 26) + av_freep(&pkt.sync); + av_packet_unref(&pkt.pkt); + av_freep(&pkt.bs); if (avctx->codec_id == AV_CODEC_ID_H264) { av_freep(&enc_info); av_freep(&enc_buf); } -#endif } return ret; @@ -1676,64 +1816,60 @@ int ff_qsv_encode(AVCodecContext *avctx, QSVEncContext *q, { int ret; + ret = update_parameters(avctx, q, frame); + if (ret < 0) + return ret; + ret = encode_frame(avctx, q, frame); if (ret < 0) return ret; - if ((qsv_fifo_size(q->async_fifo) >= q->async_depth) || - (!frame && av_fifo_size(q->async_fifo))) { - AVPacket new_pkt; - mfxBitstream *bs; - mfxSyncPoint *sync; -#if QSV_VERSION_ATLEAST(1, 26) + if ((av_fifo_can_read(q->async_fifo) >= q->async_depth) || + (!frame && av_fifo_can_read(q->async_fifo))) { + QSVPacket qpkt; mfxExtAVCEncodedFrameInfo *enc_info; mfxExtBuffer **enc_buf; -#endif enum AVPictureType pict_type; - av_fifo_generic_read(q->async_fifo, &new_pkt, sizeof(new_pkt), NULL); - av_fifo_generic_read(q->async_fifo, &sync, sizeof(sync), NULL); - av_fifo_generic_read(q->async_fifo, &bs, sizeof(bs), NULL); + av_fifo_read(q->async_fifo, &qpkt, 1); do { - ret = MFXVideoCORE_SyncOperation(q->session, *sync, 1000); + ret = MFXVideoCORE_SyncOperation(q->session, *qpkt.sync, 1000); } while (ret == MFX_WRN_IN_EXECUTION); - new_pkt.dts = av_rescale_q(bs->DecodeTimeStamp, (AVRational){1, 90000}, avctx->time_base); - new_pkt.pts = av_rescale_q(bs->TimeStamp, (AVRational){1, 90000}, avctx->time_base); - new_pkt.size = bs->DataLength; + qpkt.pkt.dts = av_rescale_q(qpkt.bs->DecodeTimeStamp, (AVRational){1, 90000}, avctx->time_base); + qpkt.pkt.pts = av_rescale_q(qpkt.bs->TimeStamp, (AVRational){1, 90000}, avctx->time_base); + qpkt.pkt.size = qpkt.bs->DataLength; - if (bs->FrameType & MFX_FRAMETYPE_IDR || bs->FrameType & MFX_FRAMETYPE_xIDR) { - new_pkt.flags |= AV_PKT_FLAG_KEY; + if (qpkt.bs->FrameType & MFX_FRAMETYPE_IDR || qpkt.bs->FrameType & MFX_FRAMETYPE_xIDR) { + qpkt.pkt.flags |= AV_PKT_FLAG_KEY; pict_type = AV_PICTURE_TYPE_I; - } else if (bs->FrameType & MFX_FRAMETYPE_I || bs->FrameType & MFX_FRAMETYPE_xI) + } else if (qpkt.bs->FrameType & MFX_FRAMETYPE_I || qpkt.bs->FrameType & MFX_FRAMETYPE_xI) pict_type = AV_PICTURE_TYPE_I; - else if (bs->FrameType & MFX_FRAMETYPE_P || bs->FrameType & MFX_FRAMETYPE_xP) + else if (qpkt.bs->FrameType & MFX_FRAMETYPE_P || qpkt.bs->FrameType & MFX_FRAMETYPE_xP) pict_type = AV_PICTURE_TYPE_P; - else if (bs->FrameType & MFX_FRAMETYPE_B || bs->FrameType & MFX_FRAMETYPE_xB) + else if (qpkt.bs->FrameType & MFX_FRAMETYPE_B || qpkt.bs->FrameType & MFX_FRAMETYPE_xB) pict_type = AV_PICTURE_TYPE_B; - else if (bs->FrameType == MFX_FRAMETYPE_UNKNOWN) { + else if (qpkt.bs->FrameType == MFX_FRAMETYPE_UNKNOWN) { pict_type = AV_PICTURE_TYPE_NONE; av_log(avctx, AV_LOG_WARNING, "Unknown FrameType, set pict_type to AV_PICTURE_TYPE_NONE.\n"); } else { - av_log(avctx, AV_LOG_ERROR, "Invalid FrameType:%d.\n", bs->FrameType); + av_log(avctx, AV_LOG_ERROR, "Invalid FrameType:%d.\n", qpkt.bs->FrameType); return AVERROR_INVALIDDATA; } -#if QSV_VERSION_ATLEAST(1, 26) if (avctx->codec_id == AV_CODEC_ID_H264) { - enc_buf = bs->ExtParam; - enc_info = (mfxExtAVCEncodedFrameInfo *)(*bs->ExtParam); - ff_side_data_set_encoder_stats(&new_pkt, + enc_buf = qpkt.bs->ExtParam; + enc_info = (mfxExtAVCEncodedFrameInfo *)(*enc_buf); + ff_side_data_set_encoder_stats(&qpkt.pkt, enc_info->QP * FF_QP2LAMBDA, NULL, 0, pict_type); av_freep(&enc_info); av_freep(&enc_buf); } -#endif - av_freep(&bs); - av_freep(&sync); + av_freep(&qpkt.bs); + av_freep(&qpkt.sync); - av_packet_move_ref(pkt, &new_pkt); + av_packet_move_ref(pkt, &qpkt.pkt); *got_packet = 1; } @@ -1758,34 +1894,27 @@ int ff_qsv_enc_close(AVCodecContext *avctx, QSVEncContext *q) while (cur) { q->work_frames = cur->next; av_frame_free(&cur->frame); + free_encoder_ctrl_extparam(&cur->enc_ctrl); free_encoder_ctrl_payloads(&cur->enc_ctrl); av_freep(&cur); cur = q->work_frames; } - while (q->async_fifo && av_fifo_size(q->async_fifo)) { - AVPacket pkt; - mfxSyncPoint *sync; - mfxBitstream *bs; - - av_fifo_generic_read(q->async_fifo, &pkt, sizeof(pkt), NULL); - av_fifo_generic_read(q->async_fifo, &sync, sizeof(sync), NULL); - av_fifo_generic_read(q->async_fifo, &bs, sizeof(bs), NULL); - -#if QSV_VERSION_ATLEAST(1, 26) - if (avctx->codec_id == AV_CODEC_ID_H264) { - mfxExtBuffer **enc_buf = bs->ExtParam; - mfxExtAVCEncodedFrameInfo *enc_info = (mfxExtAVCEncodedFrameInfo *)(*bs->ExtParam); - av_freep(&enc_info); - av_freep(&enc_buf); + if (q->async_fifo) { + QSVPacket pkt; + while (av_fifo_read(q->async_fifo, &pkt, 1) >= 0) { + if (avctx->codec_id == AV_CODEC_ID_H264) { + mfxExtBuffer **enc_buf = pkt.bs->ExtParam; + mfxExtAVCEncodedFrameInfo *enc_info = (mfxExtAVCEncodedFrameInfo *)(*enc_buf); + av_freep(&enc_info); + av_freep(&enc_buf); + } + av_freep(&pkt.sync); + av_freep(&pkt.bs); + av_packet_unref(&pkt.pkt); } -#endif - av_freep(&sync); - av_freep(&bs); - av_packet_unref(&pkt); + av_fifo_freep2(&q->async_fifo); } - av_fifo_free(q->async_fifo); - q->async_fifo = NULL; av_freep(&q->opaque_surfaces); av_buffer_unref(&q->opaque_alloc_buf); diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h index 31516b8e5..b754ac4b5 100644 --- a/libavcodec/qsvenc.h +++ b/libavcodec/qsvenc.h @@ -35,43 +35,16 @@ #include "hwconfig.h" #include "qsv_internal.h" -#define QSV_HAVE_CO2 QSV_VERSION_ATLEAST(1, 6) -#define QSV_HAVE_CO3 QSV_VERSION_ATLEAST(1, 11) -#define QSV_HAVE_CO_VPS QSV_VERSION_ATLEAST(1, 17) - -#define QSV_HAVE_EXT_HEVC_TILES QSV_VERSION_ATLEAST(1, 13) -#define QSV_HAVE_EXT_VP9_PARAM QSV_VERSION_ATLEAST(1, 26) - -#define QSV_HAVE_TRELLIS QSV_VERSION_ATLEAST(1, 8) -#define QSV_HAVE_MAX_SLICE_SIZE QSV_VERSION_ATLEAST(1, 9) -#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) -#define QSV_HAVE_VDENC QSV_VERSION_ATLEAST(1, 15) - -#define QSV_HAVE_GPB QSV_VERSION_ATLEAST(1, 18) +#define QSV_HAVE_EXT_VP9_TILES QSV_VERSION_ATLEAST(1, 29) #if defined(_WIN32) || defined(__CYGWIN__) -#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) +#define QSV_HAVE_AVBR 1 +#define QSV_HAVE_VCM 1 #define QSV_HAVE_MF 0 #else #define QSV_HAVE_AVBR 0 -#define QSV_HAVE_ICQ QSV_VERSION_ATLEAST(1, 28) #define QSV_HAVE_VCM 0 -#define QSV_HAVE_QVBR QSV_VERSION_ATLEAST(1, 28) -#define QSV_HAVE_MF QSV_VERSION_ATLEAST(1, 25) -#endif - -#if !QSV_HAVE_LA_DS -#define MFX_LOOKAHEAD_DS_UNKNOWN 0 -#define MFX_LOOKAHEAD_DS_OFF 0 -#define MFX_LOOKAHEAD_DS_2x 0 -#define MFX_LOOKAHEAD_DS_4x 0 +#define QSV_HAVE_MF 1 #endif #define QSV_COMMON_OPTS \ @@ -86,17 +59,54 @@ { "slow", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_3 }, INT_MIN, INT_MAX, VE, "preset" }, \ { "slower", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_2 }, INT_MIN, INT_MAX, VE, "preset" }, \ { "veryslow", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_TARGETUSAGE_BEST_QUALITY }, INT_MIN, INT_MAX, VE, "preset" }, \ -{ "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 }, \ -{ "max_slice_size", "Maximum encoded slice size in bytes", OFFSET(qsv.max_slice_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, UINT16_MAX, VE }, \ -{ "bitrate_limit", "Toggle bitrate limitations", OFFSET(qsv.bitrate_limit), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ -{ "mbbrc", "MB level bitrate control", OFFSET(qsv.mbbrc), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, \ -{ "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 }, \ { "forced_idr", "Forcing I frames as IDR frames", OFFSET(qsv.forced_idr), AV_OPT_TYPE_BOOL,{ .i64 = 0 }, 0, 1, VE }, \ -{ "low_power", "enable low power mode(experimental: many limitations by mfx version, BRC modes, etc.)", OFFSET(qsv.low_power), AV_OPT_TYPE_BOOL, { .i64 = -1}, -1, 1, VE},\ +{ "low_power", "enable low power mode(experimental: many limitations by mfx version, BRC modes, etc.)", OFFSET(qsv.low_power), AV_OPT_TYPE_BOOL, { .i64 = -1}, -1, 1, VE}, + +#define QSV_OPTION_RDO \ +{ "rdo", "Enable rate distortion optimization", OFFSET(qsv.rdo), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, + +#define QSV_OPTION_MAX_FRAME_SIZE \ +{ "max_frame_size", "Maximum encoded frame size in bytes", OFFSET(qsv.max_frame_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, VE }, \ +{ "max_frame_size_i", "Maximum encoded I frame size in bytes",OFFSET(qsv.max_frame_size_i), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, VE }, \ +{ "max_frame_size_p", "Maximum encoded P frame size in bytes",OFFSET(qsv.max_frame_size_p), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, VE }, + +#define QSV_OPTION_MAX_SLICE_SIZE \ +{ "max_slice_size", "Maximum encoded slice size in bytes", OFFSET(qsv.max_slice_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, VE }, + +#define QSV_OPTION_BITRATE_LIMIT \ +{ "bitrate_limit", "Toggle bitrate limitations", OFFSET(qsv.bitrate_limit), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, + +#define QSV_OPTION_MBBRC \ +{ "mbbrc", "MB level bitrate control", OFFSET(qsv.mbbrc), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, + +#define QSV_OPTION_EXTBRC \ +{ "extbrc", "Extended bitrate control", OFFSET(qsv.extbrc), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, + +#define QSV_OPTION_ADAPTIVE_I \ +{ "adaptive_i", "Adaptive I-frame placement", OFFSET(qsv.adaptive_i), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, + +#define QSV_OPTION_ADAPTIVE_B \ +{ "adaptive_b", "Adaptive B-frame placement", OFFSET(qsv.adaptive_b), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, + +#define QSV_OPTION_P_STRATEGY \ +{ "p_strategy", "Enable P-pyramid: 0-default 1-simple 2-pyramid(bf need to be set to 0).", OFFSET(qsv.p_strategy), AV_OPT_TYPE_INT, { .i64 = 0}, 0, 2, VE }, + +#define QSV_OPTION_B_STRATEGY \ +{ "b_strategy", "Strategy to choose between I/P/B-frames", OFFSET(qsv.b_strategy), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, + +#define QSV_OPTION_DBLK_IDC \ +{ "dblk_idc", "This option disable deblocking. It has value in range 0~2.", OFFSET(qsv.dblk_idc), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, VE}, + +#define QSV_OPTION_LOW_DELAY_BRC \ +{ "low_delay_brc", "Allow to strictly obey avg frame size", OFFSET(qsv.low_delay_brc), AV_OPT_TYPE_BOOL,{ .i64 = -1 }, -1, 1, VE }, + +#define QSV_OPTION_MAX_MIN_QP \ +{ "max_qp_i", "Maximum video quantizer scale for I frame", OFFSET(qsv.max_qp_i), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE}, \ +{ "min_qp_i", "Minimum video quantizer scale for I frame", OFFSET(qsv.min_qp_i), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE}, \ +{ "max_qp_p", "Maximum video quantizer scale for P frame", OFFSET(qsv.max_qp_p), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE}, \ +{ "min_qp_p", "Minimum video quantizer scale for P frame", OFFSET(qsv.min_qp_p), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE}, \ +{ "max_qp_b", "Maximum video quantizer scale for B frame", OFFSET(qsv.max_qp_b), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE}, \ +{ "min_qp_b", "Minimum video quantizer scale for B frame", OFFSET(qsv.min_qp_b), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE}, extern const AVCodecHWConfigInternal *const ff_qsv_enc_hw_configs[]; @@ -118,22 +128,14 @@ typedef struct QSVEncContext { mfxFrameAllocRequest req; mfxExtCodingOption extco; -#if QSV_HAVE_CO2 mfxExtCodingOption2 extco2; -#endif -#if QSV_HAVE_CO3 mfxExtCodingOption3 extco3; -#endif #if QSV_HAVE_MF mfxExtMultiFrameParam extmfp; mfxExtMultiFrameControl extmfc; #endif -#if QSV_HAVE_EXT_HEVC_TILES mfxExtHEVCTiles exthevctiles; -#endif -#if QSV_HAVE_EXT_VP9_PARAM mfxExtVP9Param extvp9param; -#endif mfxExtOpaqueSurfaceAlloc opaque_alloc; mfxFrameSurface1 **opaque_surfaces; @@ -141,12 +143,12 @@ typedef struct QSVEncContext { mfxExtVideoSignalInfo extvsi; - mfxExtBuffer *extparam_internal[3 + QSV_HAVE_CO2 + QSV_HAVE_CO3 + (QSV_HAVE_MF * 2)]; + mfxExtBuffer *extparam_internal[5 + (QSV_HAVE_MF * 2)]; int nb_extparam_internal; mfxExtBuffer **extparam; - AVFifoBuffer *async_fifo; + AVFifo *async_fifo; QSVFramesContext frames_ctx; @@ -168,7 +170,10 @@ typedef struct QSVEncContext { int vcm; int rdo; int max_frame_size; + int max_frame_size_i; + int max_frame_size_p; int max_slice_size; + int dblk_idc; int tile_cols; int tile_rows; @@ -184,16 +189,19 @@ typedef struct QSVEncContext { int adaptive_i; int adaptive_b; int b_strategy; + int p_strategy; int cavlc; int int_ref_type; int int_ref_cycle_size; int int_ref_qp_delta; + int int_ref_cycle_dist; int recovery_point_sei; int repeat_pps; int low_power; int gpb; + int transform_skip; int a53_cc; @@ -203,6 +211,19 @@ typedef struct QSVEncContext { char *load_plugins; SetEncodeCtrlCB *set_encode_ctrl_cb; int forced_idr; + int low_delay_brc; + + int co2_idx; + int co3_idx; + int exthevctiles_idx; + int vp9_idx; + + int max_qp_i; + int min_qp_i; + int max_qp_p; + int min_qp_p; + int max_qp_b; + int min_qp_b; } QSVEncContext; int ff_qsv_enc_init(AVCodecContext *avctx, QSVEncContext *q); diff --git a/libavcodec/qsvenc_h264.c b/libavcodec/qsvenc_h264.c index 9f127607b..87b09360c 100644 --- a/libavcodec/qsvenc_h264.c +++ b/libavcodec/qsvenc_h264.c @@ -30,7 +30,7 @@ #include "libavutil/opt.h" #include "avcodec.h" -#include "internal.h" +#include "codec_internal.h" #include "qsv.h" #include "qsv_internal.h" #include "qsvenc.h" @@ -102,6 +102,19 @@ static av_cold int qsv_enc_close(AVCodecContext *avctx) #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { QSV_COMMON_OPTS + QSV_OPTION_RDO + QSV_OPTION_MAX_FRAME_SIZE + QSV_OPTION_MAX_SLICE_SIZE + QSV_OPTION_BITRATE_LIMIT + QSV_OPTION_MBBRC + QSV_OPTION_EXTBRC + QSV_OPTION_ADAPTIVE_I + QSV_OPTION_ADAPTIVE_B + QSV_OPTION_P_STRATEGY + QSV_OPTION_B_STRATEGY + QSV_OPTION_DBLK_IDC + QSV_OPTION_LOW_DELAY_BRC + QSV_OPTION_MAX_MIN_QP { "cavlc", "Enable CAVLC", OFFSET(qsv.cavlc), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, #if QSV_HAVE_VCM @@ -112,11 +125,8 @@ static const AVOption options[] = { { "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 }, -#if QSV_HAVE_LA { "look_ahead", "Use VBR algorithm with look ahead", OFFSET(qsv.look_ahead), AV_OPT_TYPE_BOOL, { .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 { "look_ahead_downsampling", "Downscaling factor for the frames saved for the lookahead analysis", OFFSET(qsv.look_ahead_downsampling), AV_OPT_TYPE_INT, { .i64 = MFX_LOOKAHEAD_DS_UNKNOWN }, MFX_LOOKAHEAD_DS_UNKNOWN, MFX_LOOKAHEAD_DS_4x, VE, "look_ahead_downsampling" }, { "unknown" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LOOKAHEAD_DS_UNKNOWN }, INT_MIN, INT_MAX, VE, "look_ahead_downsampling" }, @@ -124,15 +134,15 @@ static const AVOption options[] = { { "off" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LOOKAHEAD_DS_OFF }, INT_MIN, INT_MAX, VE, "look_ahead_downsampling" }, { "2x" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LOOKAHEAD_DS_2x }, INT_MIN, INT_MAX, VE, "look_ahead_downsampling" }, { "4x" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_LOOKAHEAD_DS_4x }, INT_MIN, INT_MAX, VE, "look_ahead_downsampling" }, -#endif - { "int_ref_type", "Intra refresh type", OFFSET(qsv.int_ref_type), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, UINT16_MAX, VE, "int_ref_type" }, + { "int_ref_type", "Intra refresh type. B frames should be set to 0.", OFFSET(qsv.int_ref_type), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, UINT16_MAX, VE, "int_ref_type" }, { "none", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, .flags = VE, "int_ref_type" }, { "vertical", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, .flags = VE, "int_ref_type" }, + { "horizontal", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, .flags = VE, "int_ref_type" }, { "int_ref_cycle_size", "Number of frames in the intra refresh cycle", OFFSET(qsv.int_ref_cycle_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, UINT16_MAX, VE }, { "int_ref_qp_delta", "QP difference for the refresh MBs", OFFSET(qsv.int_ref_qp_delta), AV_OPT_TYPE_INT, { .i64 = INT16_MIN }, INT16_MIN, INT16_MAX, VE }, { "recovery_point_sei", "Insert recovery point SEI messages", OFFSET(qsv.recovery_point_sei), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, - + { "int_ref_cycle_dist", "Distance between the beginnings of the intra-refresh cycles in frames", OFFSET(qsv.int_ref_cycle_dist), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT16_MAX, VE }, { "profile", NULL, OFFSET(qsv.profile), AV_OPT_TYPE_INT, { .i64 = MFX_PROFILE_UNKNOWN }, 0, INT_MAX, VE, "profile" }, { "unknown" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_UNKNOWN }, INT_MIN, INT_MAX, VE, "profile" }, { "baseline", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_AVC_BASELINE }, INT_MIN, INT_MAX, VE, "profile" }, @@ -161,7 +171,7 @@ static const AVClass class = { .version = LIBAVUTIL_VERSION_INT, }; -static const AVCodecDefault qsv_enc_defaults[] = { +static const FFCodecDefault qsv_enc_defaults[] = { { "b", "1M" }, { "refs", "0" }, // same as the x264 default @@ -174,23 +184,23 @@ static const AVCodecDefault qsv_enc_defaults[] = { { NULL }, }; -const AVCodec ff_h264_qsv_encoder = { - .name = "h264_qsv", - .long_name = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (Intel Quick Sync Video acceleration)"), +const FFCodec ff_h264_qsv_encoder = { + .p.name = "h264_qsv", + .p.long_name = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (Intel Quick Sync Video acceleration)"), .priv_data_size = sizeof(QSVH264EncContext), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_H264, + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_H264, .init = qsv_enc_init, - .encode2 = qsv_enc_frame, + FF_CODEC_ENCODE_CB(qsv_enc_frame), .close = qsv_enc_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID, + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, AV_PIX_FMT_P010, AV_PIX_FMT_QSV, AV_PIX_FMT_NONE }, - .priv_class = &class, + .p.priv_class = &class, .defaults = qsv_enc_defaults, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, - .wrapper_name = "qsv", + .p.wrapper_name = "qsv", .hw_configs = ff_qsv_enc_hw_configs, }; diff --git a/libavcodec/qsvenc_hevc.c b/libavcodec/qsvenc_hevc.c index 08aba3011..f6027f600 100644 --- a/libavcodec/qsvenc_hevc.c +++ b/libavcodec/qsvenc_hevc.c @@ -29,11 +29,11 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "get_bits.h" #include "hevc.h" #include "hevcdec.h" #include "h2645_parse.h" -#include "internal.h" #include "qsv.h" #include "qsv_internal.h" #include "qsvenc.h" @@ -224,6 +224,16 @@ static av_cold int qsv_enc_close(AVCodecContext *avctx) #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { QSV_COMMON_OPTS + QSV_OPTION_RDO + QSV_OPTION_MAX_FRAME_SIZE + QSV_OPTION_MAX_SLICE_SIZE + QSV_OPTION_MBBRC + QSV_OPTION_EXTBRC + QSV_OPTION_P_STRATEGY + QSV_OPTION_B_STRATEGY + QSV_OPTION_DBLK_IDC + QSV_OPTION_LOW_DELAY_BRC + QSV_OPTION_MAX_MIN_QP { "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" }, @@ -235,15 +245,16 @@ static const AVOption options[] = { { "load_plugins", "A :-separate list of hexadecimal plugin UIDs to load in an internal session", OFFSET(qsv.load_plugins), AV_OPT_TYPE_STRING, { .str = "" }, 0, 0, VE }, -#if QSV_HAVE_LA { "look_ahead_depth", "Depth of look ahead in number frames, available when extbrc option is enabled", OFFSET(qsv.look_ahead_depth), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 100, VE }, -#endif { "profile", NULL, OFFSET(qsv.profile), AV_OPT_TYPE_INT, { .i64 = MFX_PROFILE_UNKNOWN }, 0, INT_MAX, VE, "profile" }, { "unknown", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_UNKNOWN }, INT_MIN, INT_MAX, VE, "profile" }, { "main", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_HEVC_MAIN }, INT_MIN, INT_MAX, VE, "profile" }, { "main10", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_HEVC_MAIN10 }, INT_MIN, INT_MAX, VE, "profile" }, { "mainsp", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_HEVC_MAINSP }, INT_MIN, INT_MAX, VE, "profile" }, { "rext", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_HEVC_REXT }, INT_MIN, INT_MAX, VE, "profile" }, +#if QSV_VERSION_ATLEAST(1, 32) + { "scc", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_HEVC_SCC }, INT_MIN, INT_MAX, VE, "profile" }, +#endif { "gpb", "1: GPB (generalized P/B frame); 0: regular P frame", OFFSET(qsv.gpb), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE}, @@ -251,6 +262,15 @@ static const AVOption options[] = { { "tile_rows", "Number of rows for tiled encoding", OFFSET(qsv.tile_rows), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UINT16_MAX, VE }, { "recovery_point_sei", "Insert recovery point SEI messages", OFFSET(qsv.recovery_point_sei), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, { "aud", "Insert the Access Unit Delimiter NAL", OFFSET(qsv.aud), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE}, + { "pic_timing_sei", "Insert picture timing SEI with pic_struct_syntax element", OFFSET(qsv.pic_timing_sei), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE }, + { "transform_skip", "Turn this option ON to enable transformskip", OFFSET(qsv.transform_skip), AV_OPT_TYPE_INT, { .i64 = -1}, -1, 1, VE}, + { "int_ref_type", "Intra refresh type. B frames should be set to 0", OFFSET(qsv.int_ref_type), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, UINT16_MAX, VE, "int_ref_type" }, + { "none", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, .flags = VE, "int_ref_type" }, + { "vertical", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, .flags = VE, "int_ref_type" }, + { "horizontal", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, .flags = VE, "int_ref_type" }, + { "int_ref_cycle_size", "Number of frames in the intra refresh cycle", OFFSET(qsv.int_ref_cycle_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, UINT16_MAX, VE }, + { "int_ref_qp_delta", "QP difference for the refresh MBs", OFFSET(qsv.int_ref_qp_delta), AV_OPT_TYPE_INT, { .i64 = INT16_MIN }, INT16_MIN, INT16_MAX, VE }, + { "int_ref_cycle_dist", "Distance between the beginnings of the intra-refresh cycles in frames", OFFSET(qsv.int_ref_cycle_dist), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT16_MAX, VE }, { NULL }, }; @@ -262,12 +282,12 @@ static const AVClass class = { .version = LIBAVUTIL_VERSION_INT, }; -static const AVCodecDefault qsv_enc_defaults[] = { +static const FFCodecDefault qsv_enc_defaults[] = { { "b", "1M" }, { "refs", "0" }, // same as the x264 default { "g", "248" }, - { "bf", "8" }, + { "bf", "-1" }, { "qmin", "-1" }, { "qmax", "-1" }, { "trellis", "-1" }, @@ -275,23 +295,27 @@ static const AVCodecDefault qsv_enc_defaults[] = { { NULL }, }; -const AVCodec ff_hevc_qsv_encoder = { - .name = "hevc_qsv", - .long_name = NULL_IF_CONFIG_SMALL("HEVC (Intel Quick Sync Video acceleration)"), +const FFCodec ff_hevc_qsv_encoder = { + .p.name = "hevc_qsv", + .p.long_name = NULL_IF_CONFIG_SMALL("HEVC (Intel Quick Sync Video acceleration)"), .priv_data_size = sizeof(QSVHEVCEncContext), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_HEVC, + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_HEVC, .init = qsv_enc_init, - .encode2 = qsv_enc_frame, + FF_CODEC_ENCODE_CB(qsv_enc_frame), .close = qsv_enc_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID, + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, AV_PIX_FMT_P010, + AV_PIX_FMT_YUYV422, + AV_PIX_FMT_Y210, AV_PIX_FMT_QSV, + AV_PIX_FMT_BGRA, + AV_PIX_FMT_X2RGB10, AV_PIX_FMT_NONE }, - .priv_class = &class, + .p.priv_class = &class, .defaults = qsv_enc_defaults, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, - .wrapper_name = "qsv", + .p.wrapper_name = "qsv", .hw_configs = ff_qsv_enc_hw_configs, }; diff --git a/libavcodec/qsvenc_jpeg.c b/libavcodec/qsvenc_jpeg.c index dd082692b..825eb8dc0 100644 --- a/libavcodec/qsvenc_jpeg.c +++ b/libavcodec/qsvenc_jpeg.c @@ -28,7 +28,7 @@ #include "libavutil/opt.h" #include "avcodec.h" -#include "internal.h" +#include "codec_internal.h" #include "qsv.h" #include "qsv_internal.h" #include "qsvenc.h" @@ -74,26 +74,26 @@ static const AVClass class = { .version = LIBAVUTIL_VERSION_INT, }; -static const AVCodecDefault qsv_enc_defaults[] = { +static const FFCodecDefault qsv_enc_defaults[] = { { "global_quality", "80" }, { NULL }, }; -const AVCodec ff_mjpeg_qsv_encoder = { - .name = "mjpeg_qsv", - .long_name = NULL_IF_CONFIG_SMALL("MJPEG (Intel Quick Sync Video acceleration)"), +const FFCodec ff_mjpeg_qsv_encoder = { + .p.name = "mjpeg_qsv", + .p.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, + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MJPEG, .init = qsv_enc_init, - .encode2 = qsv_enc_frame, + FF_CODEC_ENCODE_CB(qsv_enc_frame), .close = qsv_enc_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID, + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, AV_PIX_FMT_QSV, AV_PIX_FMT_NONE }, - .priv_class = &class, + .p.priv_class = &class, .defaults = qsv_enc_defaults, - .wrapper_name = "qsv", + .p.wrapper_name = "qsv", .hw_configs = ff_qsv_enc_hw_configs, }; diff --git a/libavcodec/qsvenc_mpeg2.c b/libavcodec/qsvenc_mpeg2.c index 525df99e5..5cb12a258 100644 --- a/libavcodec/qsvenc_mpeg2.c +++ b/libavcodec/qsvenc_mpeg2.c @@ -28,7 +28,7 @@ #include "libavutil/opt.h" #include "avcodec.h" -#include "internal.h" +#include "codec_internal.h" #include "qsv.h" #include "qsv_internal.h" #include "qsvenc.h" @@ -64,6 +64,7 @@ static av_cold int qsv_enc_close(AVCodecContext *avctx) #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { QSV_COMMON_OPTS + QSV_OPTION_RDO { "profile", NULL, OFFSET(qsv.profile), AV_OPT_TYPE_INT, { .i64 = MFX_PROFILE_UNKNOWN }, 0, INT_MAX, VE, "profile" }, { "unknown", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_UNKNOWN }, INT_MIN, INT_MAX, VE, "profile" }, @@ -81,7 +82,7 @@ static const AVClass class = { .version = LIBAVUTIL_VERSION_INT, }; -static const AVCodecDefault qsv_enc_defaults[] = { +static const FFCodecDefault qsv_enc_defaults[] = { { "b", "1M" }, { "refs", "0" }, // same as the x264 default @@ -92,22 +93,22 @@ static const AVCodecDefault qsv_enc_defaults[] = { { NULL }, }; -const AVCodec ff_mpeg2_qsv_encoder = { - .name = "mpeg2_qsv", - .long_name = NULL_IF_CONFIG_SMALL("MPEG-2 video (Intel Quick Sync Video acceleration)"), +const FFCodec ff_mpeg2_qsv_encoder = { + .p.name = "mpeg2_qsv", + .p.long_name = NULL_IF_CONFIG_SMALL("MPEG-2 video (Intel Quick Sync Video acceleration)"), .priv_data_size = sizeof(QSVMpeg2EncContext), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MPEG2VIDEO, + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MPEG2VIDEO, .init = qsv_enc_init, - .encode2 = qsv_enc_frame, + FF_CODEC_ENCODE_CB(qsv_enc_frame), .close = qsv_enc_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID, + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, AV_PIX_FMT_QSV, AV_PIX_FMT_NONE }, - .priv_class = &class, + .p.priv_class = &class, .defaults = qsv_enc_defaults, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, - .wrapper_name = "qsv", + .p.wrapper_name = "qsv", .hw_configs = ff_qsv_enc_hw_configs, }; diff --git a/libavcodec/qsvenc_vp9.c b/libavcodec/qsvenc_vp9.c index 9329990d1..4b2a6ce77 100644 --- a/libavcodec/qsvenc_vp9.c +++ b/libavcodec/qsvenc_vp9.c @@ -28,7 +28,7 @@ #include "libavutil/opt.h" #include "avcodec.h" -#include "internal.h" +#include "codec_internal.h" #include "qsv.h" #include "qsv_internal.h" #include "qsvenc.h" @@ -73,6 +73,16 @@ static const AVOption options[] = { { "profile2", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_VP9_2 }, INT_MIN, INT_MAX, VE, "profile" }, { "profile3", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_VP9_3 }, INT_MIN, INT_MAX, VE, "profile" }, +#if QSV_HAVE_EXT_VP9_TILES + /* The minimum tile width in luma pixels is 256, set maximum tile_cols to 32 for 8K video */ + { "tile_cols", "Number of columns for tiled encoding", OFFSET(qsv.tile_cols), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 32, VE }, + /* Set maximum tile_rows to 4 per VP9 spec */ + { "tile_rows", "Number of rows for tiled encoding", OFFSET(qsv.tile_rows), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 4, VE }, +#else + { "tile_cols", "(not supported)", OFFSET(qsv.tile_cols), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 0, VE }, + { "tile_rows", "(not supported)", OFFSET(qsv.tile_rows), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 0, VE }, +#endif + { NULL }, }; @@ -83,7 +93,7 @@ static const AVClass class = { .version = LIBAVUTIL_VERSION_INT, }; -static const AVCodecDefault qsv_enc_defaults[] = { +static const FFCodecDefault qsv_enc_defaults[] = { { "b", "1M" }, { "refs", "0" }, { "g", "250" }, @@ -92,23 +102,23 @@ static const AVCodecDefault qsv_enc_defaults[] = { { NULL }, }; -const AVCodec ff_vp9_qsv_encoder = { - .name = "vp9_qsv", - .long_name = NULL_IF_CONFIG_SMALL("VP9 video (Intel Quick Sync Video acceleration)"), +const FFCodec ff_vp9_qsv_encoder = { + .p.name = "vp9_qsv", + .p.long_name = NULL_IF_CONFIG_SMALL("VP9 video (Intel Quick Sync Video acceleration)"), .priv_data_size = sizeof(QSVVP9EncContext), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_VP9, + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_VP9, .init = qsv_enc_init, - .encode2 = qsv_enc_frame, + FF_CODEC_ENCODE_CB(qsv_enc_frame), .close = qsv_enc_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HYBRID, + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12, AV_PIX_FMT_P010, AV_PIX_FMT_QSV, AV_PIX_FMT_NONE }, - .priv_class = &class, + .p.priv_class = &class, .defaults = qsv_enc_defaults, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, - .wrapper_name = "qsv", + .p.wrapper_name = "qsv", .hw_configs = ff_qsv_enc_hw_configs, }; diff --git a/libavcodec/qtrle.c b/libavcodec/qtrle.c index d6c5eaec1..5e2139cce 100644 --- a/libavcodec/qtrle.c +++ b/libavcodec/qtrle.c @@ -38,6 +38,7 @@ #include "avcodec.h" #include "decode.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" typedef struct QtrleContext { @@ -445,9 +446,8 @@ static av_cold int qtrle_decode_init(AVCodecContext *avctx) return 0; } -static int qtrle_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int qtrle_decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *avpkt) { QtrleContext *s = avctx->priv_data; int header, start_line; @@ -557,7 +557,7 @@ done: return ret; } - if ((ret = av_frame_ref(data, s->frame)) < 0) + if ((ret = av_frame_ref(rframe, s->frame)) < 0) return ret; *got_frame = 1; @@ -581,16 +581,16 @@ static av_cold int qtrle_decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_qtrle_decoder = { - .name = "qtrle", - .long_name = NULL_IF_CONFIG_SMALL("QuickTime Animation (RLE) video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_QTRLE, +const FFCodec ff_qtrle_decoder = { + .p.name = "qtrle", + .p.long_name = NULL_IF_CONFIG_SMALL("QuickTime Animation (RLE) video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_QTRLE, .priv_data_size = sizeof(QtrleContext), .init = qtrle_decode_init, .close = qtrle_decode_end, - .decode = qtrle_decode_frame, + FF_CODEC_DECODE_CB(qtrle_decode_frame), .flush = qtrle_decode_flush, - .capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/qtrleenc.c b/libavcodec/qtrleenc.c index fd131995b..21c19eda2 100644 --- a/libavcodec/qtrleenc.c +++ b/libavcodec/qtrleenc.c @@ -25,8 +25,8 @@ #include "libavutil/imgutils.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" /** Maximum RLE code for bulk copy */ #define MAX_RLE_BULK 127 @@ -399,16 +399,16 @@ static int qtrle_encode_frame(AVCodecContext *avctx, AVPacket *pkt, return 0; } -const AVCodec ff_qtrle_encoder = { - .name = "qtrle", - .long_name = NULL_IF_CONFIG_SMALL("QuickTime Animation (RLE) video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_QTRLE, +const FFCodec ff_qtrle_encoder = { + .p.name = "qtrle", + .p.long_name = NULL_IF_CONFIG_SMALL("QuickTime Animation (RLE) video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_QTRLE, .priv_data_size = sizeof(QtrleEncContext), .init = qtrle_encode_init, - .encode2 = qtrle_encode_frame, + FF_CODEC_ENCODE_CB(qtrle_encode_frame), .close = qtrle_encode_end, - .pix_fmts = (const enum AVPixelFormat[]){ + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_RGB24, AV_PIX_FMT_RGB555BE, AV_PIX_FMT_ARGB, AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, diff --git a/libavcodec/r210dec.c b/libavcodec/r210dec.c index 476f1c068..b95f663aa 100644 --- a/libavcodec/r210dec.c +++ b/libavcodec/r210dec.c @@ -21,6 +21,8 @@ */ #include "avcodec.h" +#include "codec_internal.h" +#include "config_components.h" #include "internal.h" #include "libavutil/bswap.h" #include "libavutil/common.h" @@ -33,11 +35,10 @@ static av_cold int decode_init(AVCodecContext *avctx) return 0; } -static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *pic, + int *got_frame, AVPacket *avpkt) { int h, w, ret; - AVFrame *pic = data; const uint32_t *src = (const uint32_t *)avpkt->data; int aligned_width = FFALIGN(avctx->width, avctx->codec_id == AV_CODEC_ID_R10K ? 1 : 64); @@ -102,38 +103,38 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, } #if CONFIG_R210_DECODER -const AVCodec ff_r210_decoder = { - .name = "r210", - .long_name = NULL_IF_CONFIG_SMALL("Uncompressed RGB 10-bit"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_R210, +const FFCodec ff_r210_decoder = { + .p.name = "r210", + .p.long_name = NULL_IF_CONFIG_SMALL("Uncompressed RGB 10-bit"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_R210, .init = decode_init, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_R10K_DECODER -const AVCodec ff_r10k_decoder = { - .name = "r10k", - .long_name = NULL_IF_CONFIG_SMALL("AJA Kona 10-bit RGB Codec"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_R10K, +const FFCodec ff_r10k_decoder = { + .p.name = "r10k", + .p.long_name = NULL_IF_CONFIG_SMALL("AJA Kona 10-bit RGB Codec"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_R10K, .init = decode_init, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_AVRP_DECODER -const AVCodec ff_avrp_decoder = { - .name = "avrp", - .long_name = NULL_IF_CONFIG_SMALL("Avid 1:1 10-bit RGB Packer"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_AVRP, +const FFCodec ff_avrp_decoder = { + .p.name = "avrp", + .p.long_name = NULL_IF_CONFIG_SMALL("Avid 1:1 10-bit RGB Packer"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_AVRP, .init = decode_init, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif diff --git a/libavcodec/r210enc.c b/libavcodec/r210enc.c index 7a72ba469..cfff21cb2 100644 --- a/libavcodec/r210enc.c +++ b/libavcodec/r210enc.c @@ -20,7 +20,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" #include "internal.h" #include "bytestream.h" @@ -88,41 +91,41 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, static const enum AVPixelFormat pix_fmt[] = { AV_PIX_FMT_GBRP10, AV_PIX_FMT_NONE }; #if CONFIG_R210_ENCODER -const AVCodec ff_r210_encoder = { - .name = "r210", - .long_name = NULL_IF_CONFIG_SMALL("Uncompressed RGB 10-bit"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_R210, - .capabilities = AV_CODEC_CAP_DR1, +const FFCodec ff_r210_encoder = { + .p.name = "r210", + .p.long_name = NULL_IF_CONFIG_SMALL("Uncompressed RGB 10-bit"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_R210, + .p.capabilities = AV_CODEC_CAP_DR1, .init = encode_init, - .encode2 = encode_frame, - .pix_fmts = pix_fmt, + FF_CODEC_ENCODE_CB(encode_frame), + .p.pix_fmts = pix_fmt, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_R10K_ENCODER -const AVCodec ff_r10k_encoder = { - .name = "r10k", - .long_name = NULL_IF_CONFIG_SMALL("AJA Kona 10-bit RGB Codec"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_R10K, - .capabilities = AV_CODEC_CAP_DR1, +const FFCodec ff_r10k_encoder = { + .p.name = "r10k", + .p.long_name = NULL_IF_CONFIG_SMALL("AJA Kona 10-bit RGB Codec"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_R10K, + .p.capabilities = AV_CODEC_CAP_DR1, .init = encode_init, - .encode2 = encode_frame, - .pix_fmts = pix_fmt, + FF_CODEC_ENCODE_CB(encode_frame), + .p.pix_fmts = pix_fmt, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_AVRP_ENCODER -const AVCodec ff_avrp_encoder = { - .name = "avrp", - .long_name = NULL_IF_CONFIG_SMALL("Avid 1:1 10-bit RGB Packer"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_AVRP, - .capabilities = AV_CODEC_CAP_DR1, +const FFCodec ff_avrp_encoder = { + .p.name = "avrp", + .p.long_name = NULL_IF_CONFIG_SMALL("Avid 1:1 10-bit RGB Packer"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_AVRP, + .p.capabilities = AV_CODEC_CAP_DR1, .init = encode_init, - .encode2 = encode_frame, - .pix_fmts = pix_fmt, + FF_CODEC_ENCODE_CB(encode_frame), + .p.pix_fmts = pix_fmt, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif diff --git a/libavcodec/ra144dec.c b/libavcodec/ra144dec.c index b6272b343..bef6389bc 100644 --- a/libavcodec/ra144dec.c +++ b/libavcodec/ra144dec.c @@ -24,6 +24,7 @@ #include "libavutil/channel_layout.h" #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" #include "ra144.h" @@ -39,8 +40,8 @@ static av_cold int ra144_decode_init(AVCodecContext * avctx) ractx->lpc_coef[0] = ractx->lpc_tables[0]; ractx->lpc_coef[1] = ractx->lpc_tables[1]; - avctx->channels = 1; - avctx->channel_layout = AV_CH_LAYOUT_MONO; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; avctx->sample_fmt = AV_SAMPLE_FMT_S16; return 0; @@ -59,10 +60,9 @@ static void do_output_subblock(RA144Context *ractx, const int16_t *lpc_coefs, } /** Uncompress one block (20 bytes -> 160*2 bytes). */ -static int ra144_decode_frame(AVCodecContext * avctx, void *data, +static int ra144_decode_frame(AVCodecContext * avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; static const uint8_t sizes[LPC_ORDER] = {6, 5, 5, 4, 4, 3, 3, 3, 3, 2}; @@ -126,14 +126,14 @@ static int ra144_decode_frame(AVCodecContext * avctx, void *data, return FRAME_SIZE; } -const AVCodec ff_ra_144_decoder = { - .name = "real_144", - .long_name = NULL_IF_CONFIG_SMALL("RealAudio 1.0 (14.4K)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_RA_144, +const FFCodec ff_ra_144_decoder = { + .p.name = "real_144", + .p.long_name = NULL_IF_CONFIG_SMALL("RealAudio 1.0 (14.4K)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_RA_144, .priv_data_size = sizeof(RA144Context), .init = ra144_decode_init, - .decode = ra144_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + FF_CODEC_DECODE_CB(ra144_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/ra144enc.c b/libavcodec/ra144enc.c index 7a9635463..66ac381e6 100644 --- a/libavcodec/ra144enc.c +++ b/libavcodec/ra144enc.c @@ -31,8 +31,8 @@ #include "avcodec.h" #include "audio_frame_queue.h" #include "celp_filters.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "mathops.h" #include "put_bits.h" #include "ra144.h" @@ -51,11 +51,6 @@ static av_cold int ra144_encode_init(AVCodecContext * avctx) RA144Context *ractx; int ret; - if (avctx->channels != 1) { - av_log(avctx, AV_LOG_ERROR, "invalid number of channels: %d\n", - avctx->channels); - return -1; - } avctx->frame_size = NBLOCKS * BLOCKSIZE; avctx->initial_padding = avctx->frame_size; avctx->bit_rate = 8000; @@ -540,20 +535,23 @@ static int ra144_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, } -const AVCodec ff_ra_144_encoder = { - .name = "real_144", - .long_name = NULL_IF_CONFIG_SMALL("RealAudio 1.0 (14.4K)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_RA_144, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | +const FFCodec ff_ra_144_encoder = { + .p.name = "real_144", + .p.long_name = NULL_IF_CONFIG_SMALL("RealAudio 1.0 (14.4K)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_RA_144, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SMALL_LAST_FRAME, .priv_data_size = sizeof(RA144Context), .init = ra144_encode_init, - .encode2 = ra144_encode_frame, + FF_CODEC_ENCODE_CB(ra144_encode_frame), .close = ra144_encode_close, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, - .supported_samplerates = (const int[]){ 8000, 0 }, - .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO, 0 }, + .p.supported_samplerates = (const int[]){ 8000, 0 }, +#if FF_API_OLD_CHANNEL_LAYOUT + .p.channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO, 0 }, +#endif + .p.ch_layouts = (const AVChannelLayout[]){ AV_CHANNEL_LAYOUT_MONO, { 0 } }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/ra288.c b/libavcodec/ra288.c index 4310ccdf2..24d976fd9 100644 --- a/libavcodec/ra288.c +++ b/libavcodec/ra288.c @@ -27,6 +27,7 @@ #define BITSTREAM_READER_LE #include "avcodec.h" #include "celp_filters.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" #include "lpc.h" @@ -67,8 +68,8 @@ static av_cold int ra288_decode_init(AVCodecContext *avctx) RA288Context *ractx = avctx->priv_data; AVFloatDSPContext *fdsp; - avctx->channels = 1; - avctx->channel_layout = AV_CH_LAYOUT_MONO; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; avctx->sample_fmt = AV_SAMPLE_FMT_FLT; if (avctx->block_align != 38) { @@ -186,10 +187,9 @@ static void backward_filter(RA288Context *ractx, memmove(hist, hist + n, move_size*sizeof(*hist)); } -static int ra288_decode_frame(AVCodecContext * avctx, void *data, +static int ra288_decode_frame(AVCodecContext * avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; float *out; @@ -237,14 +237,14 @@ static int ra288_decode_frame(AVCodecContext * avctx, void *data, return avctx->block_align; } -const AVCodec ff_ra_288_decoder = { - .name = "real_288", - .long_name = NULL_IF_CONFIG_SMALL("RealAudio 2.0 (28.8K)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_RA_288, +const FFCodec ff_ra_288_decoder = { + .p.name = "real_288", + .p.long_name = NULL_IF_CONFIG_SMALL("RealAudio 2.0 (28.8K)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_RA_288, .priv_data_size = sizeof(RA288Context), .init = ra288_decode_init, - .decode = ra288_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + FF_CODEC_DECODE_CB(ra288_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/ra288.h b/libavcodec/ra288.h index 96b074bff..e7b12c5fa 100644 --- a/libavcodec/ra288.h +++ b/libavcodec/ra288.h @@ -23,7 +23,7 @@ #define AVCODEC_RA288_H #include -#include "libavutil/common.h" +#include "libavutil/macros.h" #include "libavutil/mem_internal.h" static const float amptable[8]={ diff --git a/libavcodec/ralf.c b/libavcodec/ralf.c index bb80119b0..16cb524a4 100644 --- a/libavcodec/ralf.c +++ b/libavcodec/ralf.c @@ -29,6 +29,7 @@ #include "libavutil/attributes.h" #include "libavutil/channel_layout.h" #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" #include "golomb.h" #include "internal.h" @@ -128,7 +129,7 @@ static av_cold int decode_init(AVCodecContext *avctx) { RALFContext *ctx = avctx->priv_data; int i, j, k; - int ret; + int ret, channels; if (avctx->extradata_size < 24 || memcmp(avctx->extradata, "LSD:", 4)) { av_log(avctx, AV_LOG_ERROR, "Extradata is not groovy, dude\n"); @@ -141,17 +142,17 @@ static av_cold int decode_init(AVCodecContext *avctx) return AVERROR_PATCHWELCOME; } - avctx->channels = AV_RB16(avctx->extradata + 8); + channels = AV_RB16(avctx->extradata + 8); avctx->sample_rate = AV_RB32(avctx->extradata + 12); - if (avctx->channels < 1 || avctx->channels > 2 + if (channels < 1 || channels > 2 || avctx->sample_rate < 8000 || avctx->sample_rate > 96000) { av_log(avctx, AV_LOG_ERROR, "Invalid coding parameters %d Hz %d ch\n", - avctx->sample_rate, avctx->channels); + avctx->sample_rate, channels); return AVERROR_INVALIDDATA; } avctx->sample_fmt = AV_SAMPLE_FMT_S16P; - avctx->channel_layout = (avctx->channels == 2) ? AV_CH_LAYOUT_STEREO - : AV_CH_LAYOUT_MONO; + av_channel_layout_uninit(&avctx->ch_layout); + av_channel_layout_default(&avctx->ch_layout, channels); ctx->max_frame_size = AV_RB32(avctx->extradata + 16); if (ctx->max_frame_size > (1 << 20) || !ctx->max_frame_size) { @@ -163,47 +164,35 @@ static av_cold int decode_init(AVCodecContext *avctx) for (i = 0; i < 3; i++) { ret = init_ralf_vlc(&ctx->sets[i].filter_params, filter_param_def[i], FILTERPARAM_ELEMENTS); - if (ret < 0) { - decode_close(avctx); + if (ret < 0) return ret; - } ret = init_ralf_vlc(&ctx->sets[i].bias, bias_def[i], BIAS_ELEMENTS); - if (ret < 0) { - decode_close(avctx); + if (ret < 0) return ret; - } ret = init_ralf_vlc(&ctx->sets[i].coding_mode, coding_mode_def[i], CODING_MODE_ELEMENTS); - if (ret < 0) { - decode_close(avctx); + if (ret < 0) return ret; - } for (j = 0; j < 10; j++) { for (k = 0; k < 11; k++) { ret = init_ralf_vlc(&ctx->sets[i].filter_coeffs[j][k], filter_coeffs_def[i][j][k], FILTER_COEFFS_ELEMENTS); - if (ret < 0) { - decode_close(avctx); + if (ret < 0) return ret; - } } } for (j = 0; j < 15; j++) { ret = init_ralf_vlc(&ctx->sets[i].short_codes[j], short_codes_def[i][j], SHORT_CODES_ELEMENTS); - if (ret < 0) { - decode_close(avctx); + if (ret < 0) return ret; - } } for (j = 0; j < 125; j++) { ret = init_ralf_vlc(&ctx->sets[i].long_codes[j], long_codes_def[i][j], LONG_CODES_ELEMENTS); - if (ret < 0) { - decode_close(avctx); + if (ret < 0) return ret; - } } } @@ -358,7 +347,7 @@ static int decode_block(AVCodecContext *avctx, GetBitContext *gb, return AVERROR_INVALIDDATA; } - if (avctx->channels > 1) + if (avctx->ch_layout.nb_channels > 1) dmode = get_bits(gb, 2) + 1; else dmode = 0; @@ -368,7 +357,7 @@ static int decode_block(AVCodecContext *avctx, GetBitContext *gb, bits[0] = 16; bits[1] = (mode[1] == 2) ? 17 : 16; - for (ch = 0; ch < avctx->channels; ch++) { + for (ch = 0; ch < avctx->ch_layout.nb_channels; ch++) { if ((ret = decode_channel(ctx, gb, ch, len, mode[ch], bits[ch])) < 0) return ret; if (ctx->filter_params > 1 && ctx->filter_params != FILTER_RAW) { @@ -421,11 +410,10 @@ static int decode_block(AVCodecContext *avctx, GetBitContext *gb, return 0; } -static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame_ptr, AVPacket *avpkt) { RALFContext *ctx = avctx->priv_data; - AVFrame *frame = data; int16_t *samples0; int16_t *samples1; int ret; @@ -484,7 +472,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, while (get_bits_left(&gb) > 0) { if (ctx->num_blocks >= FF_ARRAY_ELEMS(ctx->block_size)) return AVERROR_INVALIDDATA; - ctx->block_size[ctx->num_blocks] = get_bits(&gb, 13 + avctx->channels); + ctx->block_size[ctx->num_blocks] = get_bits(&gb, 13 + avctx->ch_layout.nb_channels); if (get_bits1(&gb)) { ctx->block_pts[ctx->num_blocks] = get_bits(&gb, 9); } else { @@ -525,19 +513,19 @@ static void decode_flush(AVCodecContext *avctx) } -const AVCodec ff_ralf_decoder = { - .name = "ralf", - .long_name = NULL_IF_CONFIG_SMALL("RealAudio Lossless"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_RALF, +const FFCodec ff_ralf_decoder = { + .p.name = "ralf", + .p.long_name = NULL_IF_CONFIG_SMALL("RealAudio Lossless"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_RALF, .priv_data_size = sizeof(RALFContext), .init = decode_init, .close = decode_close, - .decode = decode_frame, + FF_CODEC_DECODE_CB(decode_frame), .flush = decode_flush, - .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE }, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/rangecoder.h b/libavcodec/rangecoder.h index 4495f6df1..89d178ac3 100644 --- a/libavcodec/rangecoder.h +++ b/libavcodec/rangecoder.h @@ -29,8 +29,8 @@ #include -#include "libavutil/common.h" #include "libavutil/avassert.h" +#include "libavutil/intmath.h" typedef struct RangeCoder { int low; diff --git a/libavcodec/rasc.c b/libavcodec/rasc.c index b328e219b..bcb619f11 100644 --- a/libavcodec/rasc.c +++ b/libavcodec/rasc.c @@ -29,7 +29,9 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" +#include "zlib_wrapper.h" #include @@ -58,10 +60,10 @@ typedef struct RASCContext { unsigned cursor_y; int stride; int bpp; - z_stream zstream; AVFrame *frame; AVFrame *frame1; AVFrame *frame2; + FFZStream zstream; } RASCContext; static void clear_plane(AVCodecContext *avctx, AVFrame *frame) @@ -174,10 +176,11 @@ static int decode_zlib(AVCodecContext *avctx, const AVPacket *avpkt, unsigned size, unsigned uncompressed_size) { RASCContext *s = avctx->priv_data; + z_stream *const zstream = &s->zstream.zstream; GetByteContext *gb = &s->gb; int zret; - zret = inflateReset(&s->zstream); + zret = inflateReset(zstream); if (zret != Z_OK) { av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", zret); return AVERROR_EXTERNAL; @@ -187,13 +190,13 @@ static int decode_zlib(AVCodecContext *avctx, const AVPacket *avpkt, if (!s->delta) return AVERROR(ENOMEM); - s->zstream.next_in = avpkt->data + bytestream2_tell(gb); - s->zstream.avail_in = FFMIN(size, bytestream2_get_bytes_left(gb)); + zstream->next_in = avpkt->data + bytestream2_tell(gb); + zstream->avail_in = FFMIN(size, bytestream2_get_bytes_left(gb)); - s->zstream.next_out = s->delta; - s->zstream.avail_out = s->delta_size; + zstream->next_out = s->delta; + zstream->avail_out = s->delta_size; - zret = inflate(&s->zstream, Z_FINISH); + zret = inflate(zstream, Z_FINISH); if (zret != Z_STREAM_END) { av_log(avctx, AV_LOG_ERROR, "Inflate failed with return code: %d.\n", zret); @@ -473,6 +476,7 @@ static int decode_kfrm(AVCodecContext *avctx, const AVPacket *avpkt, unsigned size) { RASCContext *s = avctx->priv_data; + z_stream *const zstream = &s->zstream.zstream; GetByteContext *gb = &s->gb; uint8_t *dst; unsigned pos; @@ -488,21 +492,21 @@ static int decode_kfrm(AVCodecContext *avctx, if (!s->frame2->data[0]) return AVERROR_INVALIDDATA; - zret = inflateReset(&s->zstream); + zret = inflateReset(zstream); if (zret != Z_OK) { av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", zret); return AVERROR_EXTERNAL; } - s->zstream.next_in = avpkt->data + bytestream2_tell(gb); - s->zstream.avail_in = bytestream2_get_bytes_left(gb); + zstream->next_in = avpkt->data + bytestream2_tell(gb); + zstream->avail_in = bytestream2_get_bytes_left(gb); dst = s->frame2->data[0] + (avctx->height - 1) * s->frame2->linesize[0]; for (int i = 0; i < avctx->height; i++) { - s->zstream.next_out = dst; - s->zstream.avail_out = s->stride; + zstream->next_out = dst; + zstream->avail_out = s->stride; - zret = inflate(&s->zstream, Z_SYNC_FLUSH); + zret = inflate(zstream, Z_SYNC_FLUSH); if (zret != Z_OK && zret != Z_STREAM_END) { av_log(avctx, AV_LOG_ERROR, "Inflate failed with return code: %d.\n", zret); @@ -514,10 +518,10 @@ static int decode_kfrm(AVCodecContext *avctx, dst = s->frame1->data[0] + (avctx->height - 1) * s->frame1->linesize[0]; for (int i = 0; i < avctx->height; i++) { - s->zstream.next_out = dst; - s->zstream.avail_out = s->stride; + zstream->next_out = dst; + zstream->avail_out = s->stride; - zret = inflate(&s->zstream, Z_SYNC_FLUSH); + zret = inflate(zstream, Z_SYNC_FLUSH); if (zret != Z_OK && zret != Z_STREAM_END) { av_log(avctx, AV_LOG_ERROR, "Inflate failed with return code: %d.\n", zret); @@ -667,14 +671,12 @@ static void draw_cursor(AVCodecContext *avctx) } } -static int decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { RASCContext *s = avctx->priv_data; GetByteContext *gb = &s->gb; int ret, intra = 0; - AVFrame *frame = data; bytestream2_init(gb, avpkt->data, avpkt->size); @@ -751,23 +753,13 @@ static int decode_frame(AVCodecContext *avctx, static av_cold int decode_init(AVCodecContext *avctx) { RASCContext *s = avctx->priv_data; - int zret; - - s->zstream.zalloc = Z_NULL; - s->zstream.zfree = Z_NULL; - s->zstream.opaque = Z_NULL; - zret = inflateInit(&s->zstream); - if (zret != Z_OK) { - av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret); - return AVERROR_EXTERNAL; - } s->frame1 = av_frame_alloc(); s->frame2 = av_frame_alloc(); if (!s->frame1 || !s->frame2) return AVERROR(ENOMEM); - return 0; + return ff_inflate_init(&s->zstream, avctx); } static av_cold int decode_close(AVCodecContext *avctx) @@ -780,7 +772,7 @@ static av_cold int decode_close(AVCodecContext *avctx) s->delta_size = 0; av_frame_free(&s->frame1); av_frame_free(&s->frame2); - inflateEnd(&s->zstream); + ff_inflate_end(&s->zstream); return 0; } @@ -805,18 +797,18 @@ static const AVClass rasc_decoder_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_rasc_decoder = { - .name = "rasc", - .long_name = NULL_IF_CONFIG_SMALL("RemotelyAnywhere Screen Capture"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_RASC, +const FFCodec ff_rasc_decoder = { + .p.name = "rasc", + .p.long_name = NULL_IF_CONFIG_SMALL("RemotelyAnywhere Screen Capture"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_RASC, .priv_data_size = sizeof(RASCContext), .init = decode_init, .close = decode_close, - .decode = decode_frame, + FF_CODEC_DECODE_CB(decode_frame), .flush = decode_flush, - .capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .priv_class = &rasc_decoder_class, + .p.priv_class = &rasc_decoder_class, }; diff --git a/libavcodec/ratecontrol.c b/libavcodec/ratecontrol.c index 6b77ccd00..a7614d75e 100644 --- a/libavcodec/ratecontrol.c +++ b/libavcodec/ratecontrol.c @@ -29,10 +29,9 @@ #include "libavutil/internal.h" #include "avcodec.h" -#include "internal.h" #include "ratecontrol.h" #include "mpegutils.h" -#include "mpegvideo.h" +#include "mpegvideoenc.h" #include "libavutil/eval.h" void ff_write_pass1_stats(MpegEncContext *s) diff --git a/libavcodec/raw.c b/libavcodec/raw.c index 5efc1eb46..a371bb36c 100644 --- a/libavcodec/raw.c +++ b/libavcodec/raw.c @@ -24,9 +24,9 @@ * Raw Video Codec */ +#include "libavutil/macros.h" #include "avcodec.h" #include "raw.h" -#include "libavutil/common.h" static const PixelFormatTag raw_pix_fmt_tags[] = { { AV_PIX_FMT_YUV420P, MKTAG('I', '4', '2', '0') }, /* Planar formats */ diff --git a/libavcodec/rawdec.c b/libavcodec/rawdec.c index 9724cce13..c10b20d4f 100644 --- a/libavcodec/rawdec.c +++ b/libavcodec/rawdec.c @@ -26,6 +26,7 @@ #include "avcodec.h" #include "bswapdsp.h" +#include "codec_internal.h" #include "decode.h" #include "get_bits.h" #include "internal.h" @@ -162,8 +163,8 @@ static void name(AVCodecContext *avctx, uint8_t * dst, const uint8_t *buf, int b MKSCALE16(scale16be, AV_RB16, AV_WB16) MKSCALE16(scale16le, AV_RL16, AV_WL16) -static int raw_decode(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int raw_decode(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { const AVPixFmtDescriptor *desc; RawVideoContext *context = avctx->priv_data; @@ -174,8 +175,6 @@ static int raw_decode(AVCodecContext *avctx, void *data, int *got_frame, int res, len; int need_copy; - AVFrame *frame = data; - if (avctx->width <= 0) { av_log(avctx, AV_LOG_ERROR, "width is not set\n"); return AVERROR_INVALIDDATA; @@ -481,16 +480,16 @@ static av_cold int raw_close_decoder(AVCodecContext *avctx) return 0; } -const AVCodec ff_rawvideo_decoder = { - .name = "rawvideo", - .long_name = NULL_IF_CONFIG_SMALL("raw video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_RAWVIDEO, +const FFCodec ff_rawvideo_decoder = { + .p.name = "rawvideo", + .p.long_name = NULL_IF_CONFIG_SMALL("raw video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_RAWVIDEO, .priv_data_size = sizeof(RawVideoContext), .init = raw_init_decoder, .close = raw_close_decoder, - .decode = raw_decode, - .priv_class = &rawdec_class, - .capabilities = AV_CODEC_CAP_PARAM_CHANGE, + FF_CODEC_DECODE_CB(raw_decode), + .p.priv_class = &rawdec_class, + .p.capabilities = AV_CODEC_CAP_PARAM_CHANGE, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/rawenc.c b/libavcodec/rawenc.c index 561d992a4..34d7a1bef 100644 --- a/libavcodec/rawenc.c +++ b/libavcodec/rawenc.c @@ -25,6 +25,7 @@ */ #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" #include "raw.h" #include "internal.h" @@ -80,13 +81,13 @@ static int raw_encode(AVCodecContext *avctx, AVPacket *pkt, return 0; } -const AVCodec ff_rawvideo_encoder = { - .name = "rawvideo", - .long_name = NULL_IF_CONFIG_SMALL("raw video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_RAWVIDEO, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, +const FFCodec ff_rawvideo_encoder = { + .p.name = "rawvideo", + .p.long_name = NULL_IF_CONFIG_SMALL("raw video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_RAWVIDEO, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, .init = raw_encode_init, - .encode2 = raw_encode, + FF_CODEC_ENCODE_CB(raw_encode), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/rdft.c b/libavcodec/rdft.c index 6ba748423..ac6f5d678 100644 --- a/libavcodec/rdft.c +++ b/libavcodec/rdft.c @@ -20,6 +20,7 @@ */ #include #include +#include "libavutil/error.h" #include "libavutil/mathematics.h" #include "rdft.h" @@ -106,7 +107,9 @@ av_cold int ff_rdft_init(RDFTContext *s, int nbits, enum RDFTransformType trans) s->tsin = ff_cos_tabs[nbits] + (n >> 2); s->rdft_calc = rdft_calc_c; - if (ARCH_ARM) ff_rdft_init_arm(s); +#if ARCH_ARM + ff_rdft_init_arm(s); +#endif return 0; } diff --git a/libavcodec/realtextdec.c b/libavcodec/realtextdec.c index 11b586d49..c3e138a7b 100644 --- a/libavcodec/realtextdec.c +++ b/libavcodec/realtextdec.c @@ -26,7 +26,7 @@ #include "avcodec.h" #include "ass.h" -#include "internal.h" +#include "codec_internal.h" #include "libavutil/avstring.h" #include "libavutil/bprint.h" @@ -56,11 +56,10 @@ static int rt_event_to_ass(AVBPrint *buf, const char *p) return 0; } -static int realtext_decode_frame(AVCodecContext *avctx, - void *data, int *got_sub_ptr, AVPacket *avpkt) +static int realtext_decode_frame(AVCodecContext *avctx, AVSubtitle *sub, + int *got_sub_ptr, const AVPacket *avpkt) { int ret = 0; - AVSubtitle *sub = data; const char *ptr = avpkt->data; FFASSDecoderContext *s = avctx->priv_data; AVBPrint buf; @@ -75,12 +74,12 @@ static int realtext_decode_frame(AVCodecContext *avctx, return avpkt->size; } -const AVCodec ff_realtext_decoder = { - .name = "realtext", - .long_name = NULL_IF_CONFIG_SMALL("RealText subtitle"), - .type = AVMEDIA_TYPE_SUBTITLE, - .id = AV_CODEC_ID_REALTEXT, - .decode = realtext_decode_frame, +const FFCodec ff_realtext_decoder = { + .p.name = "realtext", + .p.long_name = NULL_IF_CONFIG_SMALL("RealText subtitle"), + .p.type = AVMEDIA_TYPE_SUBTITLE, + .p.id = AV_CODEC_ID_REALTEXT, + FF_CODEC_DECODE_SUB_CB(realtext_decode_frame), .init = ff_ass_subtitle_header_default, .flush = ff_ass_decoder_flush, .priv_data_size = sizeof(FFASSDecoderContext), diff --git a/libavcodec/remove_extradata_bsf.c b/libavcodec/remove_extradata_bsf.c index 1d5f193f8..66b7d00bd 100644 --- a/libavcodec/remove_extradata_bsf.c +++ b/libavcodec/remove_extradata_bsf.c @@ -26,7 +26,7 @@ #include "bsf_internal.h" #include "h264.h" #include "hevc.h" -#include "internal.h" +#include "startcode.h" #include "vc1_common.h" enum RemoveFreq { @@ -245,9 +245,9 @@ static const AVClass remove_extradata_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVBitStreamFilter ff_remove_extradata_bsf = { - .name = "remove_extra", +const FFBitStreamFilter ff_remove_extradata_bsf = { + .p.name = "remove_extra", + .p.priv_class = &remove_extradata_class, .priv_data_size = sizeof(RemoveExtradataContext), - .priv_class = &remove_extradata_class, .filter = remove_extradata, }; diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c index 19ef10883..d4f09f456 100644 --- a/libavcodec/rkmppdec.c +++ b/libavcodec/rkmppdec.c @@ -27,9 +27,9 @@ #include #include "avcodec.h" +#include "codec_internal.h" #include "decode.h" #include "hwconfig.h" -#include "internal.h" #include "libavutil/buffer.h" #include "libavutil/common.h" #include "libavutil/frame.h" @@ -561,23 +561,23 @@ static const AVCodecHWConfigInternal *const rkmpp_hw_configs[] = { #define RKMPP_DEC(NAME, ID, BSFS) \ RKMPP_DEC_CLASS(NAME) \ - const AVCodec ff_##NAME##_rkmpp_decoder = { \ - .name = #NAME "_rkmpp", \ - .long_name = NULL_IF_CONFIG_SMALL(#NAME " (rkmpp)"), \ - .type = AVMEDIA_TYPE_VIDEO, \ - .id = ID, \ + const FFCodec ff_##NAME##_rkmpp_decoder = { \ + .p.name = #NAME "_rkmpp", \ + .p.long_name = NULL_IF_CONFIG_SMALL(#NAME " (rkmpp)"), \ + .p.type = AVMEDIA_TYPE_VIDEO, \ + .p.id = ID, \ .priv_data_size = sizeof(RKMPPDecodeContext), \ .init = rkmpp_init_decoder, \ .close = rkmpp_close_decoder, \ - .receive_frame = rkmpp_receive_frame, \ + FF_CODEC_RECEIVE_FRAME_CB(rkmpp_receive_frame), \ .flush = rkmpp_flush, \ - .priv_class = &rkmpp_##NAME##_dec_class, \ - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, \ - .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_DRM_PRIME, \ + .p.priv_class = &rkmpp_##NAME##_dec_class, \ + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, \ + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_DRM_PRIME, \ AV_PIX_FMT_NONE}, \ .hw_configs = rkmpp_hw_configs, \ .bsfs = BSFS, \ - .wrapper_name = "rkmpp", \ + .p.wrapper_name = "rkmpp", \ }; RKMPP_DEC(h264, AV_CODEC_ID_H264, "h264_mp4toannexb") diff --git a/libavcodec/rl.c b/libavcodec/rl.c index fab96d63a..645a5362f 100644 --- a/libavcodec/rl.c +++ b/libavcodec/rl.c @@ -27,16 +27,13 @@ av_cold void ff_rl_init(RLTable *rl, uint8_t static_store[2][2 * MAX_RUN + MAX_LEVEL + 3]) { - int8_t max_level[MAX_RUN + 1], max_run[MAX_LEVEL + 1]; - uint8_t index_run[MAX_RUN + 1]; int last, run, level, start, end, i; - /* If rl->max_level[0] is set, this RLTable has already been initialized */ - if (rl->max_level[0]) - return; - /* compute max_level[], max_run[] and index_run[] */ for (last = 0; last < 2; last++) { + int8_t *max_level = static_store[last]; + int8_t *max_run = static_store[last] + MAX_RUN + 1; + uint8_t *index_run = static_store[last] + MAX_RUN + 1 + MAX_LEVEL + 1; if (last == 0) { start = 0; end = rl->last; @@ -45,8 +42,6 @@ av_cold void ff_rl_init(RLTable *rl, end = rl->n; } - memset(max_level, 0, MAX_RUN + 1); - memset(max_run, 0, MAX_LEVEL + 1); memset(index_run, rl->n, MAX_RUN + 1); for (i = start; i < end; i++) { run = rl->table_run[i]; @@ -58,19 +53,16 @@ av_cold void ff_rl_init(RLTable *rl, if (run > max_run[level]) max_run[level] = run; } - rl->max_level[last] = static_store[last]; - memcpy(rl->max_level[last], max_level, MAX_RUN + 1); - rl->max_run[last] = static_store[last] + MAX_RUN + 1; - memcpy(rl->max_run[last], max_run, MAX_LEVEL + 1); - rl->index_run[last] = static_store[last] + MAX_RUN + MAX_LEVEL + 2; - memcpy(rl->index_run[last], index_run, MAX_RUN + 1); + rl->max_level[last] = max_level; + rl->max_run[last] = max_run; + rl->index_run[last] = index_run; } } av_cold void ff_rl_init_vlc(RLTable *rl, unsigned static_size) { int i, q; - VLC_TYPE table[1500][2] = {{0}}; + VLCElem table[1500] = { 0 }; VLC vlc = { .table = table, .table_allocated = static_size }; av_assert0(static_size <= FF_ARRAY_ELEMS(table)); init_vlc(&vlc, 9, rl->n + 1, &rl->table_vlc[0][1], 4, 2, &rl->table_vlc[0][0], 4, 2, INIT_VLC_USE_NEW_STATIC); @@ -87,8 +79,8 @@ av_cold void ff_rl_init_vlc(RLTable *rl, unsigned static_size) qadd = 0; } for (i = 0; i < vlc.table_size; i++) { - int code = vlc.table[i][0]; - int len = vlc.table[i][1]; + int code = vlc.table[i].sym; + int len = vlc.table[i].len; int level, run; if (len == 0) { // illegal code diff --git a/libavcodec/rl.h b/libavcodec/rl.h index 5aae698e3..07e3da500 100644 --- a/libavcodec/rl.h +++ b/libavcodec/rl.h @@ -72,15 +72,12 @@ void ff_rl_init_vlc(RLTable *rl, unsigned static_size); #define INIT_VLC_RL(rl, static_size)\ {\ - int q;\ static RL_VLC_ELEM rl_vlc_table[32][static_size];\ \ - if(!rl.rl_vlc[0]){\ - for(q=0; q<32; q++)\ - rl.rl_vlc[q]= rl_vlc_table[q];\ + for (int q = 0; q < 32; q++) \ + rl.rl_vlc[q] = rl_vlc_table[q]; \ \ - ff_rl_init_vlc(&rl, static_size);\ - }\ + ff_rl_init_vlc(&rl, static_size); \ } #define INIT_FIRST_VLC_RL(rl, static_size) \ diff --git a/libavcodec/rl2.c b/libavcodec/rl2.c index 4d13aec0c..e76b06897 100644 --- a/libavcodec/rl2.c +++ b/libavcodec/rl2.c @@ -34,6 +34,7 @@ #include "libavutil/intreadwrite.h" #include "libavutil/mem.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" @@ -177,11 +178,9 @@ static av_cold int rl2_decode_init(AVCodecContext *avctx) } -static int rl2_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int rl2_decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int ret, buf_size = avpkt->size; Rl2Context *s = avctx->priv_data; @@ -218,15 +217,15 @@ static av_cold int rl2_decode_end(AVCodecContext *avctx) } -const AVCodec ff_rl2_decoder = { - .name = "rl2", - .long_name = NULL_IF_CONFIG_SMALL("RL2 video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_RL2, +const FFCodec ff_rl2_decoder = { + .p.name = "rl2", + .p.long_name = NULL_IF_CONFIG_SMALL("RL2 video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_RL2, .priv_data_size = sizeof(Rl2Context), .init = rl2_decode_init, .close = rl2_decode_end, - .decode = rl2_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(rl2_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/rle.c b/libavcodec/rle.c index 1ef6077a6..cebd23826 100644 --- a/libavcodec/rle.c +++ b/libavcodec/rle.c @@ -21,7 +21,7 @@ #include -#include "libavutil/common.h" +#include "libavutil/macros.h" #include "rle.h" diff --git a/libavcodec/roqaudioenc.c b/libavcodec/roqaudioenc.c index 530e6b68d..18a5f23df 100644 --- a/libavcodec/roqaudioenc.c +++ b/libavcodec/roqaudioenc.c @@ -23,8 +23,8 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "mathops.h" #define ROQ_FRAME_SIZE 735 @@ -54,8 +54,9 @@ static av_cold int roq_dpcm_encode_close(AVCodecContext *avctx) static av_cold int roq_dpcm_encode_init(AVCodecContext *avctx) { ROQDPCMContext *context = avctx->priv_data; + int channels = avctx->ch_layout.nb_channels; - if (avctx->channels > 2) { + if (channels > 2) { av_log(avctx, AV_LOG_ERROR, "Audio must be mono or stereo\n"); return AVERROR(EINVAL); } @@ -65,10 +66,10 @@ static av_cold int roq_dpcm_encode_init(AVCodecContext *avctx) } avctx->frame_size = ROQ_FRAME_SIZE; - avctx->bit_rate = (ROQ_HEADER_SIZE + ROQ_FRAME_SIZE * avctx->channels) * + avctx->bit_rate = (ROQ_HEADER_SIZE + ROQ_FRAME_SIZE * channels) * (22050 / ROQ_FRAME_SIZE) * 8; - context->frame_buffer = av_malloc(8 * ROQ_FRAME_SIZE * avctx->channels * + context->frame_buffer = av_malloc(8 * ROQ_FRAME_SIZE * channels * sizeof(*context->frame_buffer)); if (!context->frame_buffer) return AVERROR(ENOMEM); @@ -123,17 +124,18 @@ static int roq_dpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, { int i, stereo, data_size, ret; const int16_t *in = frame ? (const int16_t *)frame->data[0] : NULL; + int channels = avctx->ch_layout.nb_channels; uint8_t *out; ROQDPCMContext *context = avctx->priv_data; - stereo = (avctx->channels == 2); + stereo = (channels == 2); if (!in && context->input_frames >= 8) return 0; if (in && context->input_frames < 8) { - memcpy(&context->frame_buffer[context->buffered_samples * avctx->channels], - in, avctx->frame_size * avctx->channels * sizeof(*in)); + memcpy(&context->frame_buffer[context->buffered_samples * channels], + in, avctx->frame_size * channels * sizeof(*in)); context->buffered_samples += avctx->frame_size; if (context->input_frames == 0) context->first_pts = frame->pts; @@ -151,9 +153,9 @@ static int roq_dpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, } if (context->input_frames == 7) - data_size = avctx->channels * context->buffered_samples; + data_size = channels * context->buffered_samples; else - data_size = avctx->channels * avctx->frame_size; + data_size = channels * avctx->frame_size; ret = ff_get_encode_buffer(avctx, avpkt, ROQ_HEADER_SIZE + data_size, 0); if (ret < 0) @@ -175,7 +177,7 @@ static int roq_dpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, *out++ = dpcm_predict(&context->lastSample[i & 1], *in++); avpkt->pts = context->input_frames <= 7 ? context->first_pts : frame->pts; - avpkt->duration = data_size / avctx->channels; + avpkt->duration = data_size / channels; context->input_frames++; if (!in) @@ -185,17 +187,17 @@ static int roq_dpcm_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, return 0; } -const AVCodec ff_roq_dpcm_encoder = { - .name = "roq_dpcm", - .long_name = NULL_IF_CONFIG_SMALL("id RoQ DPCM"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_ROQ_DPCM, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, +const FFCodec ff_roq_dpcm_encoder = { + .p.name = "roq_dpcm", + .p.long_name = NULL_IF_CONFIG_SMALL("id RoQ DPCM"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_ROQ_DPCM, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, .priv_data_size = sizeof(ROQDPCMContext), .init = roq_dpcm_encode_init, - .encode2 = roq_dpcm_encode_frame, + FF_CODEC_ENCODE_CB(roq_dpcm_encode_frame), .close = roq_dpcm_encode_close, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/roqvideodec.c b/libavcodec/roqvideodec.c index a3217035e..3e796b18b 100644 --- a/libavcodec/roqvideodec.c +++ b/libavcodec/roqvideodec.c @@ -30,6 +30,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" #include "roqvideo.h" @@ -190,9 +191,8 @@ static av_cold int roq_decode_init(AVCodecContext *avctx) return 0; } -static int roq_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int roq_decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; @@ -213,7 +213,7 @@ static int roq_decode_frame(AVCodecContext *avctx, bytestream2_init(&gb, buf, buf_size); roqvideo_decode_frame(s, &gb); - if ((ret = av_frame_ref(data, s->current_frame)) < 0) + if ((ret = av_frame_ref(rframe, s->current_frame)) < 0) return ret; *got_frame = 1; @@ -233,15 +233,15 @@ static av_cold int roq_decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_roq_decoder = { - .name = "roqvideo", - .long_name = NULL_IF_CONFIG_SMALL("id RoQ video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_ROQ, +const FFCodec ff_roq_decoder = { + .p.name = "roqvideo", + .p.long_name = NULL_IF_CONFIG_SMALL("id RoQ video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_ROQ, .priv_data_size = sizeof(RoqContext), .init = roq_decode_init, .close = roq_decode_end, - .decode = roq_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(roq_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/roqvideoenc.c b/libavcodec/roqvideoenc.c index 95012f7c1..c0c67dbed 100644 --- a/libavcodec/roqvideoenc.c +++ b/libavcodec/roqvideoenc.c @@ -61,6 +61,7 @@ #include "libavutil/opt.h" #include "roqvideo.h" #include "bytestream.h" +#include "codec_internal.h" #include "elbg.h" #include "encode.h" #include "internal.h" @@ -1080,8 +1081,8 @@ static int roq_encode_frame(AVCodecContext *avctx, AVPacket *pkt, if (enc->first_frame) { /* Alloc memory for the reconstruction data (we must know the stride for that) */ - if ((ret = ff_get_buffer(avctx, roq->current_frame, 0)) < 0 || - (ret = ff_get_buffer(avctx, roq->last_frame, 0)) < 0) + if ((ret = ff_encode_alloc_frame(avctx, roq->current_frame)) < 0 || + (ret = ff_encode_alloc_frame(avctx, roq->last_frame )) < 0) return ret; /* Before the first video frame, write a "video info" chunk */ @@ -1117,17 +1118,17 @@ static const AVClass roq_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_roq_encoder = { - .name = "roqvideo", - .long_name = NULL_IF_CONFIG_SMALL("id RoQ video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_ROQ, +const FFCodec ff_roq_encoder = { + .p.name = "roqvideo", + .p.long_name = NULL_IF_CONFIG_SMALL("id RoQ video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_ROQ, .priv_data_size = sizeof(RoqEncContext), .init = roq_encode_init, - .encode2 = roq_encode_frame, + FF_CODEC_ENCODE_CB(roq_encode_frame), .close = roq_encode_end, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUVJ444P, + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_NONE }, - .priv_class = &roq_class, + .p.priv_class = &roq_class, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/rpza.c b/libavcodec/rpza.c index 270cfcc97..703f05e7b 100644 --- a/libavcodec/rpza.c +++ b/libavcodec/rpza.c @@ -42,6 +42,7 @@ #include "libavutil/internal.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" typedef struct RpzaContext { @@ -255,9 +256,8 @@ static av_cold int rpza_decode_init(AVCodecContext *avctx) return 0; } -static int rpza_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int rpza_decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *avpkt) { RpzaContext *s = avctx->priv_data; int ret; @@ -268,7 +268,7 @@ static int rpza_decode_frame(AVCodecContext *avctx, if (ret < 0) return ret; - if ((ret = av_frame_ref(data, s->frame)) < 0) + if ((ret = av_frame_ref(rframe, s->frame)) < 0) return ret; *got_frame = 1; @@ -286,15 +286,15 @@ static av_cold int rpza_decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_rpza_decoder = { - .name = "rpza", - .long_name = NULL_IF_CONFIG_SMALL("QuickTime video (RPZA)"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_RPZA, +const FFCodec ff_rpza_decoder = { + .p.name = "rpza", + .p.long_name = NULL_IF_CONFIG_SMALL("QuickTime video (RPZA)"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_RPZA, .priv_data_size = sizeof(RpzaContext), .init = rpza_decode_init, .close = rpza_decode_end, - .decode = rpza_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(rpza_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/rpzaenc.c b/libavcodec/rpzaenc.c index 337b1faf5..50b68bb8b 100644 --- a/libavcodec/rpzaenc.c +++ b/libavcodec/rpzaenc.c @@ -28,8 +28,8 @@ #include "libavutil/opt.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "put_bits.h" typedef struct RpzaContext { @@ -843,17 +843,17 @@ static const AVClass rpza_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_rpza_encoder = { - .name = "rpza", - .long_name = NULL_IF_CONFIG_SMALL("QuickTime video (RPZA)"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_RPZA, +const FFCodec ff_rpza_encoder = { + .p.name = "rpza", + .p.long_name = NULL_IF_CONFIG_SMALL("QuickTime video (RPZA)"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_RPZA, .priv_data_size = sizeof(RpzaContext), - .priv_class = &rpza_class, + .p.priv_class = &rpza_class, .init = rpza_encode_init, - .encode2 = rpza_encode_frame, + FF_CODEC_ENCODE_CB(rpza_encode_frame), .close = rpza_encode_end, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, - .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_RGB555, + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_RGB555, AV_PIX_FMT_NONE}, }; diff --git a/libavcodec/rscc.c b/libavcodec/rscc.c index 0ec54ac1b..f4fa78671 100644 --- a/libavcodec/rscc.c +++ b/libavcodec/rscc.c @@ -43,6 +43,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "decode.h" #include "internal.h" @@ -147,13 +148,12 @@ static av_cold int rscc_close(AVCodecContext *avctx) return 0; } -static int rscc_decode_frame(AVCodecContext *avctx, void *data, - int *got_frame, AVPacket *avpkt) +static int rscc_decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { RsccContext *ctx = avctx->priv_data; GetByteContext *gbc = &ctx->gbc; GetByteContext tiles_gbc; - AVFrame *frame = data; const uint8_t *pixels, *raw; uint8_t *inflated_tiles = NULL; int tiles_nb, packed_size, pixel_size = 0; @@ -362,16 +362,16 @@ end: return ret; } -const AVCodec ff_rscc_decoder = { - .name = "rscc", - .long_name = NULL_IF_CONFIG_SMALL("innoHeim/Rsupport Screen Capture Codec"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_RSCC, +const FFCodec ff_rscc_decoder = { + .p.name = "rscc", + .p.long_name = NULL_IF_CONFIG_SMALL("innoHeim/Rsupport Screen Capture Codec"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_RSCC, .init = rscc_init, - .decode = rscc_decode_frame, + FF_CODEC_DECODE_CB(rscc_decode_frame), .close = rscc_close, .priv_data_size = sizeof(RsccContext), - .capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/rv10.c b/libavcodec/rv10.c index d8261c34c..e394a63a2 100644 --- a/libavcodec/rv10.c +++ b/libavcodec/rv10.c @@ -31,16 +31,19 @@ #include "libavutil/thread.h" #include "avcodec.h" +#include "codec_internal.h" #include "error_resilience.h" #include "h263.h" #include "h263data.h" +#include "h263dec.h" #include "internal.h" #include "mpeg_er.h" #include "mpegutils.h" #include "mpegvideo.h" +#include "mpegvideodec.h" #include "mpeg4video.h" #include "mpegvideodata.h" -#include "rv10.h" +#include "rv10dec.h" #define RV_GET_MAJOR_VER(x) ((x) >> 28) #define RV_GET_MINOR_VER(x) (((x) >> 20) & 0xFF) @@ -149,7 +152,6 @@ static int rv10_decode_picture_header(MpegEncContext *s) } skip_bits(&s->gb, 3); /* ignored */ s->f_code = 1; - s->unrestricted_mv = 1; return mb_count; } @@ -298,7 +300,6 @@ static int rv20_decode_picture_header(RVDecContext *rv, int whole_size) skip_bits(&s->gb, 5); s->f_code = 1; - s->unrestricted_mv = 1; s->h263_aic = s->pict_type == AV_PICTURE_TYPE_I; s->modified_quant = 1; if (!s->avctx->lowres) @@ -339,7 +340,7 @@ static av_cold void rv10_build_vlc(VLC *vlc, const uint16_t len_count[15], static av_cold void rv10_init_static(void) { - static VLC_TYPE table[1472 + 992][2]; + static VLCElem table[1472 + 992]; rv_dc_lum.table = table; rv_dc_lum.table_allocated = 1472; @@ -348,8 +349,8 @@ static av_cold void rv10_init_static(void) for (int i = 0; i < 1 << (DC_VLC_BITS - 7 /* Length of skip prefix */); i++) { /* All codes beginning with 0x7F have the same length and value. * Modifying the table directly saves us the useless subtables. */ - rv_dc_lum.table[(0x7F << (DC_VLC_BITS - 7)) + i][0] = 255; - rv_dc_lum.table[(0x7F << (DC_VLC_BITS - 7)) + i][1] = 18; + rv_dc_lum.table[(0x7F << (DC_VLC_BITS - 7)) + i].sym = 255; + rv_dc_lum.table[(0x7F << (DC_VLC_BITS - 7)) + i].len = 18; } rv_dc_chrom.table = &table[1472]; rv_dc_chrom.table_allocated = 992; @@ -357,8 +358,8 @@ static av_cold void rv10_init_static(void) rv_sym_run_len, FF_ARRAY_ELEMS(rv_sym_run_len) - 2); for (int i = 0; i < 1 << (DC_VLC_BITS - 9 /* Length of skip prefix */); i++) { /* Same as above. */ - rv_dc_chrom.table[(0x1FE << (DC_VLC_BITS - 9)) + i][0] = 255; - rv_dc_chrom.table[(0x1FE << (DC_VLC_BITS - 9)) + i][1] = 18; + rv_dc_chrom.table[(0x1FE << (DC_VLC_BITS - 9)) + i].sym = 255; + rv_dc_chrom.table[(0x1FE << (DC_VLC_BITS - 9)) + i].len = 18; } ff_h263_decode_init_vlc(); } @@ -592,13 +593,12 @@ static int get_slice_offset(AVCodecContext *avctx, const uint8_t *buf, int n) return AV_RL32(buf + n * 8); } -static int rv10_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int rv10_decode_frame(AVCodecContext *avctx, AVFrame *pict, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; MpegEncContext *s = avctx->priv_data; - AVFrame *pict = data; int i, ret; int slice_count; const uint8_t *slices_hdr = NULL; @@ -662,12 +662,12 @@ static int rv10_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, if ((ret = av_frame_ref(pict, s->current_picture_ptr->f)) < 0) return ret; ff_print_debug_info(s, s->current_picture_ptr, pict); - ff_mpv_export_qp_table(s, pict, s->current_picture_ptr, FF_QSCALE_TYPE_MPEG1); + ff_mpv_export_qp_table(s, pict, s->current_picture_ptr, FF_MPV_QSCALE_TYPE_MPEG1); } else if (s->last_picture_ptr) { if ((ret = av_frame_ref(pict, s->last_picture_ptr->f)) < 0) return ret; ff_print_debug_info(s, s->last_picture_ptr, pict); - ff_mpv_export_qp_table(s, pict,s->last_picture_ptr, FF_QSCALE_TYPE_MPEG1); + ff_mpv_export_qp_table(s, pict,s->last_picture_ptr, FF_MPV_QSCALE_TYPE_MPEG1); } if (s->last_picture_ptr || s->low_delay) { @@ -681,36 +681,38 @@ static int rv10_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, return avpkt->size; } -const AVCodec ff_rv10_decoder = { - .name = "rv10", - .long_name = NULL_IF_CONFIG_SMALL("RealVideo 1.0"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_RV10, +const FFCodec ff_rv10_decoder = { + .p.name = "rv10", + .p.long_name = NULL_IF_CONFIG_SMALL("RealVideo 1.0"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_RV10, .priv_data_size = sizeof(RVDecContext), .init = rv10_decode_init, .close = rv10_decode_end, - .decode = rv10_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, - .max_lowres = 3, - .pix_fmts = (const enum AVPixelFormat[]) { + FF_CODEC_DECODE_CB(rv10_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + .p.max_lowres = 3, + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, }; -const AVCodec ff_rv20_decoder = { - .name = "rv20", - .long_name = NULL_IF_CONFIG_SMALL("RealVideo 2.0"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_RV20, +const FFCodec ff_rv20_decoder = { + .p.name = "rv20", + .p.long_name = NULL_IF_CONFIG_SMALL("RealVideo 2.0"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_RV20, .priv_data_size = sizeof(RVDecContext), .init = rv10_decode_init, .close = rv10_decode_end, - .decode = rv10_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, + FF_CODEC_DECODE_CB(rv10_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, .flush = ff_mpeg_flush, - .max_lowres = 3, - .pix_fmts = (const enum AVPixelFormat[]) { + .p.max_lowres = 3, + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, diff --git a/libavcodec/rv10dec.h b/libavcodec/rv10dec.h new file mode 100644 index 000000000..daa6b8d65 --- /dev/null +++ b/libavcodec/rv10dec.h @@ -0,0 +1,28 @@ +/* + * RV10/RV20 decoder + * + * 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_RV10DEC_H +#define AVCODEC_RV10DEC_H + +#include "mpegvideo.h" + +int ff_rv_decode_dc(MpegEncContext *s, int n); + +#endif /* AVCODEC_RV10DEC_H */ diff --git a/libavcodec/rv10enc.c b/libavcodec/rv10enc.c index 72b25e0c5..7560e6026 100644 --- a/libavcodec/rv10enc.c +++ b/libavcodec/rv10enc.c @@ -25,9 +25,11 @@ * RV10 encoder */ +#include "codec_internal.h" #include "mpegvideo.h" +#include "mpegvideoenc.h" #include "put_bits.h" -#include "rv10.h" +#include "rv10enc.h" int ff_rv10_encode_picture_header(MpegEncContext *s, int picture_number) { @@ -63,16 +65,16 @@ int ff_rv10_encode_picture_header(MpegEncContext *s, int picture_number) return 0; } -const AVCodec ff_rv10_encoder = { - .name = "rv10", - .long_name = NULL_IF_CONFIG_SMALL("RealVideo 1.0"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_RV10, - .priv_class = &ff_mpv_enc_class, +const FFCodec ff_rv10_encoder = { + .p.name = "rv10", + .p.long_name = NULL_IF_CONFIG_SMALL("RealVideo 1.0"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_RV10, + .p.priv_class = &ff_mpv_enc_class, .priv_data_size = sizeof(MpegEncContext), .init = ff_mpv_encode_init, - .encode2 = ff_mpv_encode_picture, + FF_CODEC_ENCODE_CB(ff_mpv_encode_picture), .close = ff_mpv_encode_end, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, }; diff --git a/libavcodec/rv10enc.h b/libavcodec/rv10enc.h new file mode 100644 index 000000000..66672f808 --- /dev/null +++ b/libavcodec/rv10enc.h @@ -0,0 +1,29 @@ +/* + * RV10/RV20 encoder + * + * 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_RV10ENC_H +#define AVCODEC_RV10ENC_H + +#include "mpegvideo.h" + +int ff_rv10_encode_picture_header(MpegEncContext *s, int picture_number); +void ff_rv20_encode_picture_header(MpegEncContext *s, int picture_number); + +#endif /* AVCODEC_RV10ENC_H */ diff --git a/libavcodec/rv20enc.c b/libavcodec/rv20enc.c index 19b6aab27..422188e21 100644 --- a/libavcodec/rv20enc.c +++ b/libavcodec/rv20enc.c @@ -25,12 +25,14 @@ * RV20 encoder */ +#include "codec_internal.h" #include "mpegvideo.h" #include "mpegvideodata.h" -#include "h263.h" +#include "mpegvideoenc.h" #include "h263data.h" +#include "h263enc.h" #include "put_bits.h" -#include "rv10.h" +#include "rv10enc.h" void ff_rv20_encode_picture_header(MpegEncContext *s, int picture_number){ put_bits(&s->pb, 2, s->pict_type); //I 0 vs. 1 ? @@ -60,16 +62,16 @@ void ff_rv20_encode_picture_header(MpegEncContext *s, int picture_number){ } } -const AVCodec ff_rv20_encoder = { - .name = "rv20", - .long_name = NULL_IF_CONFIG_SMALL("RealVideo 2.0"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_RV20, - .priv_class = &ff_mpv_enc_class, +const FFCodec ff_rv20_encoder = { + .p.name = "rv20", + .p.long_name = NULL_IF_CONFIG_SMALL("RealVideo 2.0"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_RV20, + .p.priv_class = &ff_mpv_enc_class, .priv_data_size = sizeof(MpegEncContext), .init = ff_mpv_encode_init, - .encode2 = ff_mpv_encode_picture, + FF_CODEC_ENCODE_CB(ff_mpv_encode_picture), .close = ff_mpv_encode_end, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, }; diff --git a/libavcodec/rv30.c b/libavcodec/rv30.c index 751647beb..8fd8498d9 100644 --- a/libavcodec/rv30.c +++ b/libavcodec/rv30.c @@ -25,8 +25,10 @@ */ #include "avcodec.h" +#include "codec_internal.h" #include "mpegutils.h" #include "mpegvideo.h" +#include "mpegvideodec.h" #include "golomb.h" #include "rv34.h" @@ -289,22 +291,23 @@ static av_cold int rv30_decode_init(AVCodecContext *avctx) return 0; } -const AVCodec ff_rv30_decoder = { - .name = "rv30", - .long_name = NULL_IF_CONFIG_SMALL("RealVideo 3.0"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_RV30, +const FFCodec ff_rv30_decoder = { + .p.name = "rv30", + .p.long_name = NULL_IF_CONFIG_SMALL("RealVideo 3.0"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_RV30, .priv_data_size = sizeof(RV34DecContext), .init = rv30_decode_init, .close = ff_rv34_decode_end, - .decode = ff_rv34_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | + FF_CODEC_DECODE_CB(ff_rv34_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_FRAME_THREADS, .flush = ff_mpeg_flush, - .pix_fmts = (const enum AVPixelFormat[]) { + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, .update_thread_context = ONLY_IF_THREADS_ENABLED(ff_rv34_decode_update_thread_context), - .caps_internal = FF_CODEC_CAP_ALLOCATE_PROGRESS, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_ALLOCATE_PROGRESS, }; diff --git a/libavcodec/rv34.c b/libavcodec/rv34.c index e68072de0..5f3b7d31c 100644 --- a/libavcodec/rv34.c +++ b/libavcodec/rv34.c @@ -35,6 +35,7 @@ #include "error_resilience.h" #include "mpegutils.h" #include "mpegvideo.h" +#include "mpegvideodec.h" #include "golomb.h" #include "internal.h" #include "mathops.h" @@ -42,6 +43,7 @@ #include "qpeldsp.h" #include "rectangle.h" #include "thread.h" +#include "threadframe.h" #include "rv34vlc.h" #include "rv34data.h" @@ -79,7 +81,7 @@ static int rv34_decode_mv(RV34DecContext *r, int block_type); * @{ */ -static VLC_TYPE table_data[117592][2]; +static VLCElem table_data[117592]; /** * Generate VLC from codeword lengths. @@ -1571,13 +1573,13 @@ static int finish_frame(AVCodecContext *avctx, AVFrame *pict) if ((ret = av_frame_ref(pict, s->current_picture_ptr->f)) < 0) return ret; ff_print_debug_info(s, s->current_picture_ptr, pict); - ff_mpv_export_qp_table(s, pict, s->current_picture_ptr, FF_QSCALE_TYPE_MPEG1); + ff_mpv_export_qp_table(s, pict, s->current_picture_ptr, FF_MPV_QSCALE_TYPE_MPEG1); got_picture = 1; } else if (s->last_picture_ptr) { if ((ret = av_frame_ref(pict, s->last_picture_ptr->f)) < 0) return ret; ff_print_debug_info(s, s->last_picture_ptr, pict); - ff_mpv_export_qp_table(s, pict, s->last_picture_ptr, FF_QSCALE_TYPE_MPEG1); + ff_mpv_export_qp_table(s, pict, s->last_picture_ptr, FF_MPV_QSCALE_TYPE_MPEG1); got_picture = 1; } @@ -1594,15 +1596,13 @@ static AVRational update_sar(int old_w, int old_h, AVRational sar, int new_w, in return sar; } -int ff_rv34_decode_frame(AVCodecContext *avctx, - void *data, int *got_picture_ptr, - AVPacket *avpkt) +int ff_rv34_decode_frame(AVCodecContext *avctx, AVFrame *pict, + int *got_picture_ptr, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; RV34DecContext *r = avctx->priv_data; MpegEncContext *s = &r->s; - AVFrame *pict = data; SliceInfo si; int i, ret; int slice_count; diff --git a/libavcodec/rv34.h b/libavcodec/rv34.h index 53b29dc24..84789625c 100644 --- a/libavcodec/rv34.h +++ b/libavcodec/rv34.h @@ -136,7 +136,8 @@ typedef struct RV34DecContext{ */ int ff_rv34_get_start_offset(GetBitContext *gb, int blocks); int ff_rv34_decode_init(AVCodecContext *avctx); -int ff_rv34_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt); +int ff_rv34_decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt); int ff_rv34_decode_end(AVCodecContext *avctx); int ff_rv34_decode_update_thread_context(AVCodecContext *dst, const AVCodecContext *src); diff --git a/libavcodec/rv34_parser.c b/libavcodec/rv34_parser.c index 03469ed0d..e17bc8562 100644 --- a/libavcodec/rv34_parser.c +++ b/libavcodec/rv34_parser.c @@ -24,6 +24,8 @@ * RV30/40 parser */ +#include "config_components.h" + #include "parser.h" #include "libavutil/intreadwrite.h" diff --git a/libavcodec/rv34dsp.c b/libavcodec/rv34dsp.c index c3f245eb8..8f9d88396 100644 --- a/libavcodec/rv34dsp.c +++ b/libavcodec/rv34dsp.c @@ -136,8 +136,9 @@ av_cold void ff_rv34dsp_init(RV34DSPContext *c) c->rv34_idct_add = rv34_idct_add_c; c->rv34_idct_dc_add = rv34_idct_dc_add_c; - if (ARCH_ARM) - ff_rv34dsp_init_arm(c); - if (ARCH_X86) - ff_rv34dsp_init_x86(c); +#if ARCH_ARM + ff_rv34dsp_init_arm(c); +#elif ARCH_X86 + ff_rv34dsp_init_x86(c); +#endif } diff --git a/libavcodec/rv40.c b/libavcodec/rv40.c index 31a7a04e5..b9469819f 100644 --- a/libavcodec/rv40.c +++ b/libavcodec/rv40.c @@ -27,10 +27,13 @@ #include "config.h" #include "libavutil/imgutils.h" +#include "libavutil/thread.h" #include "avcodec.h" +#include "codec_internal.h" #include "mpegutils.h" #include "mpegvideo.h" +#include "mpegvideodec.h" #include "golomb.h" #include "rv34.h" @@ -44,7 +47,7 @@ static VLC ptype_vlc[NUM_PTYPE_VLCS], btype_vlc[NUM_BTYPE_VLCS]; static av_cold void rv40_init_table(VLC *vlc, unsigned *offset, int nb_bits, int nb_codes, const uint8_t (*tab)[2]) { - static VLC_TYPE vlc_buf[11776][2]; + static VLCElem vlc_buf[11776]; vlc->table = &vlc_buf[*offset]; vlc->table_allocated = 1 << nb_bits; @@ -61,7 +64,7 @@ static av_cold void rv40_init_table(VLC *vlc, unsigned *offset, int nb_bits, static av_cold void rv40_init_tables(void) { int i, offset = 0; - static VLC_TYPE aic_mode2_table[11814][2]; + static VLCElem aic_mode2_table[11814]; rv40_init_table(&aic_top_vlc, &offset, AIC_TOP_BITS, AIC_TOP_SIZE, rv40_aic_top_vlc_tab); @@ -553,14 +556,13 @@ static void rv40_loop_filter(RV34DecContext *r, int row) */ static av_cold int rv40_decode_init(AVCodecContext *avctx) { + static AVOnce init_static_once = AV_ONCE_INIT; RV34DecContext *r = avctx->priv_data; int ret; r->rv30 = 0; if ((ret = ff_rv34_decode_init(avctx)) < 0) return ret; - if(!aic_top_vlc.bits) - rv40_init_tables(); r->parse_slice_header = rv40_parse_slice_header; r->decode_intra_types = rv40_decode_intra_types; r->decode_mb_info = rv40_decode_mb_info; @@ -568,25 +570,27 @@ static av_cold int rv40_decode_init(AVCodecContext *avctx) r->luma_dc_quant_i = rv40_luma_dc_quant[0]; r->luma_dc_quant_p = rv40_luma_dc_quant[1]; ff_rv40dsp_init(&r->rdsp); + ff_thread_once(&init_static_once, rv40_init_tables); return 0; } -const AVCodec ff_rv40_decoder = { - .name = "rv40", - .long_name = NULL_IF_CONFIG_SMALL("RealVideo 4.0"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_RV40, +const FFCodec ff_rv40_decoder = { + .p.name = "rv40", + .p.long_name = NULL_IF_CONFIG_SMALL("RealVideo 4.0"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_RV40, .priv_data_size = sizeof(RV34DecContext), .init = rv40_decode_init, .close = ff_rv34_decode_end, - .decode = ff_rv34_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | + FF_CODEC_DECODE_CB(ff_rv34_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_FRAME_THREADS, .flush = ff_mpeg_flush, - .pix_fmts = (const enum AVPixelFormat[]) { + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, .update_thread_context = ONLY_IF_THREADS_ENABLED(ff_rv34_decode_update_thread_context), - .caps_internal = FF_CODEC_CAP_ALLOCATE_PROGRESS, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_ALLOCATE_PROGRESS, }; diff --git a/libavcodec/rv40dsp.c b/libavcodec/rv40dsp.c index 414c4d30b..a09179ae8 100644 --- a/libavcodec/rv40dsp.c +++ b/libavcodec/rv40dsp.c @@ -705,10 +705,11 @@ av_cold void ff_rv40dsp_init(RV34DSPContext *c) c->rv40_loop_filter_strength[0] = rv40_h_loop_filter_strength; c->rv40_loop_filter_strength[1] = rv40_v_loop_filter_strength; - if (ARCH_AARCH64) - ff_rv40dsp_init_aarch64(c); - if (ARCH_ARM) - ff_rv40dsp_init_arm(c); - if (ARCH_X86) - ff_rv40dsp_init_x86(c); +#if ARCH_AARCH64 + ff_rv40dsp_init_aarch64(c); +#elif ARCH_ARM + ff_rv40dsp_init_arm(c); +#elif ARCH_X86 + ff_rv40dsp_init_x86(c); +#endif } diff --git a/libavcodec/s302m.c b/libavcodec/s302m.c index b09c1293a..fb7b6e240 100644 --- a/libavcodec/s302m.c +++ b/libavcodec/s302m.c @@ -24,7 +24,9 @@ #include "libavutil/intreadwrite.h" #include "libavutil/opt.h" #include "libavutil/log.h" +#include "libavutil/reverse.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "mathops.h" @@ -72,32 +74,37 @@ static int s302m_parse_frame_header(AVCodecContext *avctx, const uint8_t *buf, else avctx->sample_fmt = AV_SAMPLE_FMT_S16; - avctx->channels = channels; + av_channel_layout_uninit(&avctx->ch_layout); switch(channels) { case 2: - avctx->channel_layout = AV_CH_LAYOUT_STEREO; + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; break; case 4: - avctx->channel_layout = AV_CH_LAYOUT_QUAD; + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_QUAD; break; case 6: - avctx->channel_layout = AV_CH_LAYOUT_5POINT1_BACK; + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1_BACK; break; case 8: - avctx->channel_layout = AV_CH_LAYOUT_5POINT1_BACK | AV_CH_LAYOUT_STEREO_DOWNMIX; + av_channel_layout_from_mask(&avctx->ch_layout, + AV_CH_LAYOUT_5POINT1_BACK | AV_CH_LAYOUT_STEREO_DOWNMIX); + break; + default: + avctx->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + avctx->ch_layout.nb_channels = channels; + break; } return frame_size; } -static int s302m_decode_frame(AVCodecContext *avctx, void *data, +static int s302m_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { S302Context *s = avctx->priv_data; - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; - int block_size, ret; + int block_size, ret, channels; int i; int non_pcm_data_type = -1; @@ -110,13 +117,14 @@ static int s302m_decode_frame(AVCodecContext *avctx, void *data, /* get output buffer */ block_size = (avctx->bits_per_raw_sample + 4) / 4; - frame->nb_samples = 2 * (buf_size / block_size) / avctx->channels; + channels = avctx->ch_layout.nb_channels; + frame->nb_samples = 2 * (buf_size / block_size) / channels; if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; - avctx->bit_rate = 48000 * avctx->channels * (avctx->bits_per_raw_sample + 4) + + avctx->bit_rate = 48000 * channels * (avctx->bits_per_raw_sample + 4) + 32 * 48000 / frame->nb_samples; - buf_size = (frame->nb_samples * avctx->channels / 2) * block_size; + buf_size = (frame->nb_samples * channels / 2) * block_size; if (avctx->bits_per_raw_sample == 24) { uint32_t *o = (uint32_t *)frame->data[0]; @@ -131,7 +139,7 @@ static int s302m_decode_frame(AVCodecContext *avctx, void *data, buf += 7; } o = (uint32_t *)frame->data[0]; - if (avctx->channels == 2) + if (channels == 2) for (i=0; inb_samples * 2 - 6; i+=2) { if (o[i] || o[i+1] || o[i+2] || o[i+3]) break; @@ -152,7 +160,7 @@ static int s302m_decode_frame(AVCodecContext *avctx, void *data, buf += 6; } o = (uint32_t *)frame->data[0]; - if (avctx->channels == 2) + if (channels == 2) for (i=0; inb_samples * 2 - 6; i+=2) { if (o[i] || o[i+1] || o[i+2] || o[i+3]) break; @@ -172,7 +180,7 @@ static int s302m_decode_frame(AVCodecContext *avctx, void *data, buf += 5; } o = (uint16_t *)frame->data[0]; - if (avctx->channels == 2) + if (channels == 2) for (i=0; inb_samples * 2 - 6; i+=2) { if (o[i] || o[i+1] || o[i+2] || o[i+3]) break; @@ -219,14 +227,14 @@ static const AVClass s302m_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_s302m_decoder = { - .name = "s302m", - .long_name = NULL_IF_CONFIG_SMALL("SMPTE 302M"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_S302M, +const FFCodec ff_s302m_decoder = { + .p.name = "s302m", + .p.long_name = NULL_IF_CONFIG_SMALL("SMPTE 302M"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_S302M, + .p.priv_class = &s302m_class, .priv_data_size = sizeof(S302Context), - .decode = s302m_decode_frame, - .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + FF_CODEC_DECODE_CB(s302m_decode_frame), + .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1, - .priv_class = &s302m_class, }; diff --git a/libavcodec/s302menc.c b/libavcodec/s302menc.c index 528d712e7..b6f9501bf 100644 --- a/libavcodec/s302menc.c +++ b/libavcodec/s302menc.c @@ -21,9 +21,10 @@ */ #include "libavutil/channel_layout.h" +#include "libavutil/reverse.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "mathops.h" #include "put_bits.h" @@ -37,10 +38,10 @@ static av_cold int s302m_encode_init(AVCodecContext *avctx) { S302MEncContext *s = avctx->priv_data; - if (avctx->channels & 1 || avctx->channels > 8) { + if (avctx->ch_layout.nb_channels & 1 || avctx->ch_layout.nb_channels > 8) { av_log(avctx, AV_LOG_ERROR, "Encoding %d channel(s) is not allowed. Only 2, 4, 6 and 8 channels are supported.\n", - avctx->channels); + avctx->ch_layout.nb_channels); return AVERROR(EINVAL); } @@ -61,7 +62,7 @@ static av_cold int s302m_encode_init(AVCodecContext *avctx) } avctx->frame_size = 0; - avctx->bit_rate = 48000 * avctx->channels * + avctx->bit_rate = 48000 * avctx->ch_layout.nb_channels * (avctx->bits_per_raw_sample + 4); s->framing_index = 0; @@ -72,9 +73,9 @@ static int s302m_encode2_frame(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet_ptr) { S302MEncContext *s = avctx->priv_data; + const int nb_channels = avctx->ch_layout.nb_channels; const int buf_size = AES3_HEADER_LEN + - (frame->nb_samples * - avctx->channels * + (frame->nb_samples * nb_channels * (avctx->bits_per_raw_sample + 4)) / 8; int ret, c, channels; uint8_t *o; @@ -91,7 +92,7 @@ static int s302m_encode2_frame(AVCodecContext *avctx, AVPacket *avpkt, o = avpkt->data; init_put_bits(&pb, o, buf_size); put_bits(&pb, 16, buf_size - AES3_HEADER_LEN); - put_bits(&pb, 2, (avctx->channels - 2) >> 1); // number of channels + put_bits(&pb, 2, (nb_channels - 2) >> 1); // number of channels put_bits(&pb, 8, 0); // channel ID put_bits(&pb, 2, (avctx->bits_per_raw_sample - 16) / 4); // bits per samples (0 = 16bit, 1 = 20bit, 2 = 24bit) put_bits(&pb, 4, 0); // alignments @@ -104,7 +105,7 @@ static int s302m_encode2_frame(AVCodecContext *avctx, AVPacket *avpkt, for (c = 0; c < frame->nb_samples; c++) { uint8_t vucf = s->framing_index == 0 ? 0x10: 0; - for (channels = 0; channels < avctx->channels; channels += 2) { + for (channels = 0; channels < nb_channels; channels += 2) { o[0] = ff_reverse[(samples[0] & 0x0000FF00) >> 8]; o[1] = ff_reverse[(samples[0] & 0x00FF0000) >> 16]; o[2] = ff_reverse[(samples[0] & 0xFF000000) >> 24]; @@ -126,7 +127,7 @@ static int s302m_encode2_frame(AVCodecContext *avctx, AVPacket *avpkt, for (c = 0; c < frame->nb_samples; c++) { uint8_t vucf = s->framing_index == 0 ? 0x80: 0; - for (channels = 0; channels < avctx->channels; channels += 2) { + for (channels = 0; channels < nb_channels; channels += 2) { o[0] = ff_reverse[ (samples[0] & 0x000FF000) >> 12]; o[1] = ff_reverse[ (samples[0] & 0x0FF00000) >> 20]; o[2] = ff_reverse[((samples[0] & 0xF0000000) >> 28) | vucf]; @@ -147,7 +148,7 @@ static int s302m_encode2_frame(AVCodecContext *avctx, AVPacket *avpkt, for (c = 0; c < frame->nb_samples; c++) { uint8_t vucf = s->framing_index == 0 ? 0x10 : 0; - for (channels = 0; channels < avctx->channels; channels += 2) { + for (channels = 0; channels < nb_channels; channels += 2) { o[0] = ff_reverse[ samples[0] & 0xFF]; o[1] = ff_reverse[(samples[0] & 0xFF00) >> 8]; o[2] = ff_reverse[(samples[1] & 0x0F) << 4] | vucf; @@ -169,21 +170,21 @@ static int s302m_encode2_frame(AVCodecContext *avctx, AVPacket *avpkt, return 0; } -const AVCodec ff_s302m_encoder = { - .name = "s302m", - .long_name = NULL_IF_CONFIG_SMALL("SMPTE 302M"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_S302M, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_EXPERIMENTAL | +const FFCodec ff_s302m_encoder = { + .p.name = "s302m", + .p.long_name = NULL_IF_CONFIG_SMALL("SMPTE 302M"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_S302M, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_EXPERIMENTAL | AV_CODEC_CAP_VARIABLE_FRAME_SIZE, .priv_data_size = sizeof(S302MEncContext), .init = s302m_encode_init, - .encode2 = s302m_encode2_frame, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S32, + FF_CODEC_ENCODE_CB(s302m_encode2_frame), + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, - .supported_samplerates = (const int[]) { 48000, 0 }, - /* .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_STEREO, + .p.supported_samplerates = (const int[]) { 48000, 0 }, + /* .p.channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_STEREO, AV_CH_LAYOUT_QUAD, AV_CH_LAYOUT_5POINT1_BACK, AV_CH_LAYOUT_5POINT1_BACK | AV_CH_LAYOUT_STEREO_DOWNMIX, diff --git a/libavcodec/samidec.c b/libavcodec/samidec.c index 32d07447b..cf5dec955 100644 --- a/libavcodec/samidec.c +++ b/libavcodec/samidec.c @@ -27,8 +27,8 @@ #include "ass.h" #include "libavutil/avstring.h" #include "libavutil/bprint.h" +#include "codec_internal.h" #include "htmlsubtitles.h" -#include "internal.h" typedef struct { AVBPrint source; @@ -132,10 +132,9 @@ end: return ret; } -static int sami_decode_frame(AVCodecContext *avctx, - void *data, int *got_sub_ptr, AVPacket *avpkt) +static int sami_decode_frame(AVCodecContext *avctx, AVSubtitle *sub, + int *got_sub_ptr, const AVPacket *avpkt) { - AVSubtitle *sub = data; const char *ptr = avpkt->data; SAMIContext *sami = avctx->priv_data; @@ -181,15 +180,15 @@ static void sami_flush(AVCodecContext *avctx) sami->readorder = 0; } -const AVCodec ff_sami_decoder = { - .name = "sami", - .long_name = NULL_IF_CONFIG_SMALL("SAMI subtitle"), - .type = AVMEDIA_TYPE_SUBTITLE, - .id = AV_CODEC_ID_SAMI, +const FFCodec ff_sami_decoder = { + .p.name = "sami", + .p.long_name = NULL_IF_CONFIG_SMALL("SAMI subtitle"), + .p.type = AVMEDIA_TYPE_SUBTITLE, + .p.id = AV_CODEC_ID_SAMI, .priv_data_size = sizeof(SAMIContext), .init = sami_init, .close = sami_close, - .decode = sami_decode_frame, + FF_CODEC_DECODE_SUB_CB(sami_decode_frame), .flush = sami_flush, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/sanm.c b/libavcodec/sanm.c index 9506bbe04..7f094c8bb 100644 --- a/libavcodec/sanm.c +++ b/libavcodec/sanm.c @@ -27,6 +27,7 @@ #include "avcodec.h" #include "bytestream.h" #include "copy_block.h" +#include "codec_internal.h" #include "internal.h" #define NGLYPHS 256 @@ -1386,13 +1387,13 @@ static int copy_output(SANMVideoContext *ctx, SANMFrameHeader *hdr) return 0; } -static int decode_frame(AVCodecContext *avctx, void *data, +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *pkt) { SANMVideoContext *ctx = avctx->priv_data; int i, ret; - ctx->frame = data; + ctx->frame = frame; bytestream2_init(&ctx->gb, pkt->data, pkt->size); if (!ctx->version) { @@ -1515,15 +1516,15 @@ static int decode_frame(AVCodecContext *avctx, void *data, return pkt->size; } -const AVCodec ff_sanm_decoder = { - .name = "sanm", - .long_name = NULL_IF_CONFIG_SMALL("LucasArts SANM/Smush video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_SANM, +const FFCodec ff_sanm_decoder = { + .p.name = "sanm", + .p.long_name = NULL_IF_CONFIG_SMALL("LucasArts SANM/Smush video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_SANM, .priv_data_size = sizeof(SANMVideoContext), .init = decode_init, .close = decode_end, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/sbc_parser.c b/libavcodec/sbc_parser.c index 8bf726b39..2d427cc7c 100644 --- a/libavcodec/sbc_parser.c +++ b/libavcodec/sbc_parser.c @@ -41,7 +41,9 @@ static int sbc_parse_header(AVCodecParserContext *s, AVCodecContext *avctx, return -1; if (data[0] == MSBC_SYNCWORD && data[1] == 0 && data[2] == 0) { - avctx->channels = 1; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + avctx->ch_layout.nb_channels = 1; avctx->sample_rate = 16000; avctx->frame_size = 120; s->duration = avctx->frame_size; @@ -64,7 +66,9 @@ static int sbc_parse_header(AVCodecParserContext *s, AVCodecContext *avctx, + ((((mode == SBC_MODE_DUAL_CHANNEL) + 1) * blocks * bitpool + (joint * subbands)) + 7) / 8; - avctx->channels = channels; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + avctx->ch_layout.nb_channels = channels; avctx->sample_rate = sample_rates[sr]; avctx->frame_size = subbands * blocks; s->duration = avctx->frame_size; diff --git a/libavcodec/sbcdec.c b/libavcodec/sbcdec.c index e14d8c895..99af7e165 100644 --- a/libavcodec/sbcdec.c +++ b/libavcodec/sbcdec.c @@ -31,6 +31,7 @@ */ #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "libavutil/channel_layout.h" #include "libavutil/intreadwrite.h" @@ -336,12 +337,10 @@ static int sbc_decode_init(AVCodecContext *avctx) return 0; } -static int sbc_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame_ptr, - AVPacket *avpkt) +static int sbc_decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame_ptr, AVPacket *avpkt) { SBCDecContext *sbc = avctx->priv_data; - AVFrame *frame = data; int ret, frame_length; if (!sbc) @@ -351,7 +350,9 @@ static int sbc_decode_frame(AVCodecContext *avctx, if (frame_length <= 0) return frame_length; - avctx->channels = sbc->frame.channels; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + avctx->ch_layout.nb_channels = sbc->frame.channels; frame->nb_samples = sbc->frame.blocks * sbc->frame.subbands; if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) @@ -364,19 +365,24 @@ static int sbc_decode_frame(AVCodecContext *avctx, return frame_length; } -const 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, +const FFCodec ff_sbc_decoder = { + .p.name = "sbc", + .p.long_name = NULL_IF_CONFIG_SMALL("SBC (low-complexity subband codec)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_SBC, .priv_data_size = sizeof(SBCDecContext), .init = sbc_decode_init, - .decode = sbc_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + FF_CODEC_DECODE_CB(sbc_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, - .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO, +#if FF_API_OLD_CHANNEL_LAYOUT + .p.channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO, AV_CH_LAYOUT_STEREO, 0}, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, +#endif + .p.ch_layouts = (const AVChannelLayout[]) { AV_CHANNEL_LAYOUT_MONO, + AV_CHANNEL_LAYOUT_STEREO, + { 0 } }, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_NONE }, - .supported_samplerates = (const int[]) { 16000, 32000, 44100, 48000, 0 }, + .p.supported_samplerates = (const int[]) { 16000, 32000, 44100, 48000, 0 }, }; diff --git a/libavcodec/sbcdsp.c b/libavcodec/sbcdsp.c index e745595da..400526ce6 100644 --- a/libavcodec/sbcdsp.c +++ b/libavcodec/sbcdsp.c @@ -380,8 +380,9 @@ 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); +#if ARCH_ARM + ff_sbcdsp_init_arm(s); +#elif ARCH_X86 + ff_sbcdsp_init_x86(s); +#endif } diff --git a/libavcodec/sbcenc.c b/libavcodec/sbcenc.c index 45156277b..18ac4fb9b 100644 --- a/libavcodec/sbcenc.c +++ b/libavcodec/sbcenc.c @@ -33,8 +33,8 @@ #include "libavutil/channel_layout.h" #include "libavutil/opt.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "profiles.h" #include "put_bits.h" #include "sbc.h" @@ -202,7 +202,7 @@ static int sbc_encode_init(AVCodecContext *avctx) sbc->msbc = 1; if (sbc->msbc) { - if (avctx->channels != 1) { + if (avctx->ch_layout.nb_channels != 1) { av_log(avctx, AV_LOG_ERROR, "mSBC require mono channel.\n"); return AVERROR(EINVAL); } @@ -227,7 +227,7 @@ static int sbc_encode_init(AVCodecContext *avctx) return AVERROR(EINVAL); } - if (avctx->channels == 1) { + if (avctx->ch_layout.nb_channels == 1) { frame->mode = SBC_MODE_MONO; if (sbc->max_delay <= 3000 || avctx->bit_rate > 270000) frame->subbands = 4; @@ -251,7 +251,7 @@ static int sbc_encode_init(AVCodecContext *avctx) 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 + - 4 * frame->subbands * avctx->ch_layout.nb_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; @@ -263,8 +263,8 @@ static int sbc_encode_init(AVCodecContext *avctx) 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->channels = avctx->ch_layout.nb_channels; + frame->codesize = frame->subbands * frame->blocks * avctx->ch_layout.nb_channels * 2; frame->crc_ctx = av_crc_get_table(AV_CRC_8_EBU); memset(&sbc->dsp.X, 0, sizeof(sbc->dsp.X)); @@ -343,21 +343,26 @@ static const AVClass sbc_class = { .version = LIBAVUTIL_VERSION_INT, }; -const 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, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME, +const FFCodec ff_sbc_encoder = { + .p.name = "sbc", + .p.long_name = NULL_IF_CONFIG_SMALL("SBC (low-complexity subband codec)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_SBC, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME, .priv_data_size = sizeof(SBCEncContext), .init = sbc_encode_init, - .encode2 = sbc_encode_frame, + FF_CODEC_ENCODE_CB(sbc_encode_frame), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, - .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO, +#if FF_API_OLD_CHANNEL_LAYOUT + .p.channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO, AV_CH_LAYOUT_STEREO, 0}, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16, +#endif + .p.ch_layouts = (const AVChannelLayout[]) { AV_CHANNEL_LAYOUT_MONO, + AV_CHANNEL_LAYOUT_STEREO, + { 0 } }, + .p.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), + .p.supported_samplerates = (const int[]) { 16000, 32000, 44100, 48000, 0 }, + .p.priv_class = &sbc_class, + .p.profiles = NULL_IF_CONFIG_SMALL(ff_sbc_profiles), }; diff --git a/libavcodec/sbrdsp_fixed.c b/libavcodec/sbrdsp_fixed.c index 43fcc90ae..0d34a2a71 100644 --- a/libavcodec/sbrdsp_fixed.c +++ b/libavcodec/sbrdsp_fixed.c @@ -114,8 +114,8 @@ static void sbr_qmf_deint_neg_c(int *v, const int *src) { int i; for (i = 0; i < 32; i++) { - v[ i] = ( src[63 - 2*i ] + 0x10) >> 5; - v[63 - i] = (-src[63 - 2*i - 1] + 0x10) >> 5; + v[ i] = (int)(0x10U + src[63 - 2*i ]) >> 5; + v[63 - i] = (int)(0x10U - src[63 - 2*i - 1]) >> 5; } } diff --git a/libavcodec/sbrdsp_template.c b/libavcodec/sbrdsp_template.c index 37a3365b9..b3737c0fd 100644 --- a/libavcodec/sbrdsp_template.c +++ b/libavcodec/sbrdsp_template.c @@ -92,13 +92,14 @@ av_cold void AAC_RENAME(ff_sbrdsp_init)(SBRDSPContext *s) s->hf_apply_noise[3] = sbr_hf_apply_noise_3; #if !USE_FIXED - if (ARCH_ARM) - ff_sbrdsp_init_arm(s); - if (ARCH_AARCH64) - ff_sbrdsp_init_aarch64(s); - if (ARCH_X86) - ff_sbrdsp_init_x86(s); - if (ARCH_MIPS) - ff_sbrdsp_init_mips(s); +#if ARCH_ARM + ff_sbrdsp_init_arm(s); +#elif ARCH_AARCH64 + ff_sbrdsp_init_aarch64(s); +#elif ARCH_X86 + ff_sbrdsp_init_x86(s); +#elif ARCH_MIPS + ff_sbrdsp_init_mips(s); +#endif #endif /* !USE_FIXED */ } diff --git a/libavcodec/scpr.c b/libavcodec/scpr.c index ba6e849c6..0623b73c8 100644 --- a/libavcodec/scpr.c +++ b/libavcodec/scpr.c @@ -26,6 +26,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" #include "scpr.h" #include "scpr3.h" @@ -491,12 +492,11 @@ static int decompress_p(AVCodecContext *avctx, return 0; } -static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { SCPRContext *s = avctx->priv_data; GetByteContext *gb = &s->gb; - AVFrame *frame = data; int ret, type; if (avctx->bits_per_coded_sample == 16) { @@ -581,7 +581,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, return AVERROR_INVALIDDATA; if (avctx->bits_per_coded_sample != 16) { - ret = av_frame_ref(data, s->current_frame); + ret = av_frame_ref(frame, s->current_frame); if (ret < 0) return ret; } else { @@ -667,16 +667,16 @@ static av_cold int decode_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_scpr_decoder = { - .name = "scpr", - .long_name = NULL_IF_CONFIG_SMALL("ScreenPressor"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_SCPR, +const FFCodec ff_scpr_decoder = { + .p.name = "scpr", + .p.long_name = NULL_IF_CONFIG_SMALL("ScreenPressor"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_SCPR, .priv_data_size = sizeof(SCPRContext), .init = decode_init, .close = decode_close, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/scpr.h b/libavcodec/scpr.h index 15cb87c46..d161a42c6 100644 --- a/libavcodec/scpr.h +++ b/libavcodec/scpr.h @@ -23,13 +23,8 @@ #ifndef AVCODEC_SCPR_H #define AVCODEC_SCPR_H -#include -#include -#include - #include "avcodec.h" #include "bytestream.h" -#include "internal.h" #include "scpr3.h" typedef struct RangeCoder { diff --git a/libavcodec/scpr3.h b/libavcodec/scpr3.h index 92ad96888..8988300ce 100644 --- a/libavcodec/scpr3.h +++ b/libavcodec/scpr3.h @@ -23,12 +23,7 @@ #ifndef AVCODEC_SCPR3_H #define AVCODEC_SCPR3_H -#include -#include -#include - -#include "avcodec.h" -#include "internal.h" +#include typedef struct PixelModel3 { uint8_t type; diff --git a/libavcodec/screenpresso.c b/libavcodec/screenpresso.c index dd4df6d40..8a4a8cde9 100644 --- a/libavcodec/screenpresso.c +++ b/libavcodec/screenpresso.c @@ -42,6 +42,7 @@ #include "libavutil/mem.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" typedef struct ScreenpressoContext { @@ -101,11 +102,10 @@ static void sum_delta_flipped(uint8_t *dst, int dst_linesize, } } -static int screenpresso_decode_frame(AVCodecContext *avctx, void *data, +static int screenpresso_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt) { ScreenpressoContext *ctx = avctx->priv_data; - AVFrame *frame = data; uLongf length = ctx->inflated_size; int keyframe, component_size, src_linesize; int ret; @@ -183,16 +183,16 @@ static int screenpresso_decode_frame(AVCodecContext *avctx, void *data, return avpkt->size; } -const AVCodec ff_screenpresso_decoder = { - .name = "screenpresso", - .long_name = NULL_IF_CONFIG_SMALL("Screenpresso"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_SCREENPRESSO, +const FFCodec ff_screenpresso_decoder = { + .p.name = "screenpresso", + .p.long_name = NULL_IF_CONFIG_SMALL("Screenpresso"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_SCREENPRESSO, .init = screenpresso_init, - .decode = screenpresso_decode_frame, + FF_CODEC_DECODE_CB(screenpresso_decode_frame), .close = screenpresso_close, .priv_data_size = sizeof(ScreenpressoContext), - .capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/setts_bsf.c b/libavcodec/setts_bsf.c index d604f91f7..9c27b24a3 100644 --- a/libavcodec/setts_bsf.c +++ b/libavcodec/setts_bsf.c @@ -35,13 +35,20 @@ static const char *const var_names[] = { "POS", ///< original position in the file of the frame "PREV_INPTS", ///< previous input PTS "PREV_INDTS", ///< previous input DTS + "PREV_INDURATION", ///< previous input duration "PREV_OUTPTS", ///< previous output PTS "PREV_OUTDTS", ///< previous output DTS + "PREV_OUTDURATION", ///< previous output duration + "NEXT_PTS", ///< next input PTS + "NEXT_DTS", ///< next input DTS + "NEXT_DURATION", ///< next input duration "PTS", ///< original PTS in the file of the frame "DTS", ///< original DTS in the file of the frame + "DURATION", ///< original duration in the file of the frame "STARTPTS", ///< PTS at start of movie "STARTDTS", ///< DTS at start of movie - "TB", ///< timebase of the stream + "TB", ///< input timebase of the stream + "TB_OUT", ///< output timebase of the stream "SR", ///< sample rate of the stream "NOPTS", ///< The AV_NOPTS_VALUE constant NULL @@ -53,13 +60,20 @@ enum var_name { VAR_POS, VAR_PREV_INPTS, VAR_PREV_INDTS, + VAR_PREV_INDUR, VAR_PREV_OUTPTS, VAR_PREV_OUTDTS, + VAR_PREV_OUTDUR, + VAR_NEXT_PTS, + VAR_NEXT_DTS, + VAR_NEXT_DUR, VAR_PTS, VAR_DTS, + VAR_DURATION, VAR_STARTPTS, VAR_STARTDTS, VAR_TB, + VAR_TB_OUT, VAR_SR, VAR_NOPTS, VAR_VARS_NB @@ -71,21 +85,22 @@ typedef struct SetTSContext { char *ts_str; char *pts_str; char *dts_str; + char *duration_str; + + AVRational time_base; int64_t frame_number; - int64_t start_pts; - int64_t start_dts; - int64_t prev_inpts; - int64_t prev_indts; - int64_t prev_outpts; - int64_t prev_outdts; - double var_values[VAR_VARS_NB]; AVExpr *ts_expr; AVExpr *pts_expr; AVExpr *dts_expr; + AVExpr *duration_expr; + + AVPacket *prev_inpkt; + AVPacket *prev_outpkt; + AVPacket *cur_pkt; } SetTSContext; static int setts_init(AVBSFContext *ctx) @@ -93,12 +108,24 @@ static int setts_init(AVBSFContext *ctx) SetTSContext *s = ctx->priv_data; int ret; + s->prev_inpkt = av_packet_alloc(); + s->prev_outpkt = av_packet_alloc(); + s->cur_pkt = av_packet_alloc(); + if (!s->prev_inpkt || !s->prev_outpkt || !s->cur_pkt) + return AVERROR(ENOMEM); + if ((ret = av_expr_parse(&s->ts_expr, s->ts_str, var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) { av_log(ctx, AV_LOG_ERROR, "Error while parsing ts expression '%s'\n", s->ts_str); return ret; } + if ((ret = av_expr_parse(&s->duration_expr, s->duration_str, + var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) { + av_log(ctx, AV_LOG_ERROR, "Error while parsing duration expression '%s'\n", s->duration_str); + return ret; + } + if (s->pts_str) { if ((ret = av_expr_parse(&s->pts_expr, s->pts_str, var_names, NULL, NULL, NULL, NULL, 0, ctx)) < 0) { @@ -115,14 +142,16 @@ static int setts_init(AVBSFContext *ctx) } } + if (s->time_base.num > 0 && s->time_base.den > 0) + ctx->time_base_out = s->time_base; + s->frame_number= 0; - s->start_pts = AV_NOPTS_VALUE; - s->start_dts = AV_NOPTS_VALUE; - s->prev_inpts = AV_NOPTS_VALUE; - s->prev_indts = AV_NOPTS_VALUE; - s->prev_outpts = AV_NOPTS_VALUE; - s->prev_outdts = AV_NOPTS_VALUE; + s->var_values[VAR_STARTPTS] = AV_NOPTS_VALUE; + s->var_values[VAR_STARTDTS] = AV_NOPTS_VALUE; s->var_values[VAR_NOPTS] = AV_NOPTS_VALUE; + s->var_values[VAR_TB] = ctx->time_base_in.den ? av_q2d(ctx->time_base_in) : 0; + s->var_values[VAR_TB_OUT]= ctx->time_base_out.den ? av_q2d(ctx->time_base_out) : 0; + s->var_values[VAR_SR] = ctx->par_in->sample_rate; return 0; } @@ -130,56 +159,73 @@ static int setts_init(AVBSFContext *ctx) static int setts_filter(AVBSFContext *ctx, AVPacket *pkt) { SetTSContext *s = ctx->priv_data; - int64_t new_ts, new_pts, new_dts; + int64_t new_ts, new_pts, new_dts, new_duration; int ret; ret = ff_bsf_get_packet_ref(ctx, pkt); - if (ret < 0) + if (ret < 0 && (ret != AVERROR_EOF || !s->cur_pkt->data)) return ret; - if (s->start_pts == AV_NOPTS_VALUE) - s->start_pts = pkt->pts; + if (!s->cur_pkt->data) { + av_packet_move_ref(s->cur_pkt, pkt); + return AVERROR(EAGAIN); + } - if (s->start_dts == AV_NOPTS_VALUE) - s->start_dts = pkt->dts; + if (s->var_values[VAR_STARTPTS] == AV_NOPTS_VALUE) + s->var_values[VAR_STARTPTS] = s->cur_pkt->pts; + + if (s->var_values[VAR_STARTDTS] == AV_NOPTS_VALUE) + s->var_values[VAR_STARTDTS] = s->cur_pkt->dts; s->var_values[VAR_N] = s->frame_number++; - s->var_values[VAR_TS] = pkt->dts; - s->var_values[VAR_POS] = pkt->pos; - s->var_values[VAR_PTS] = pkt->pts; - s->var_values[VAR_DTS] = pkt->dts; - s->var_values[VAR_PREV_INPTS] = s->prev_inpts; - s->var_values[VAR_PREV_INDTS] = s->prev_indts; - s->var_values[VAR_PREV_OUTPTS] = s->prev_outpts; - s->var_values[VAR_PREV_OUTDTS] = s->prev_outdts; - s->var_values[VAR_STARTPTS] = s->start_pts; - s->var_values[VAR_STARTDTS] = s->start_dts; - s->var_values[VAR_TB] = ctx->time_base_out.den ? av_q2d(ctx->time_base_out) : 0; - s->var_values[VAR_SR] = ctx->par_in->sample_rate; + s->var_values[VAR_TS] = s->cur_pkt->dts; + s->var_values[VAR_POS] = s->cur_pkt->pos; + s->var_values[VAR_PTS] = s->cur_pkt->pts; + s->var_values[VAR_DTS] = s->cur_pkt->dts; + s->var_values[VAR_DURATION] = s->cur_pkt->duration; + s->var_values[VAR_PREV_INPTS] = s->prev_inpkt->pts; + s->var_values[VAR_PREV_INDTS] = s->prev_inpkt->dts; + s->var_values[VAR_PREV_INDUR] = s->prev_inpkt->duration; + s->var_values[VAR_PREV_OUTPTS] = s->prev_outpkt->pts; + s->var_values[VAR_PREV_OUTDTS] = s->prev_outpkt->dts; + s->var_values[VAR_PREV_OUTDUR] = s->prev_outpkt->duration; + s->var_values[VAR_NEXT_PTS] = pkt->pts; + s->var_values[VAR_NEXT_DTS] = pkt->dts; + s->var_values[VAR_NEXT_DUR] = pkt->duration; new_ts = llrint(av_expr_eval(s->ts_expr, s->var_values, NULL)); + new_duration = llrint(av_expr_eval(s->duration_expr, s->var_values, NULL)); if (s->pts_str) { - s->var_values[VAR_TS] = pkt->pts; + s->var_values[VAR_TS] = s->cur_pkt->pts; new_pts = llrint(av_expr_eval(s->pts_expr, s->var_values, NULL)); } else { new_pts = new_ts; } if (s->dts_str) { - s->var_values[VAR_TS] = pkt->dts; + s->var_values[VAR_TS] = s->cur_pkt->dts; new_dts = llrint(av_expr_eval(s->dts_expr, s->var_values, NULL)); } else { new_dts = new_ts; } - s->prev_inpts = pkt->pts; - s->prev_indts = pkt->dts; - s->prev_outpts = new_pts; - s->prev_outdts = new_dts; + av_packet_unref(s->prev_inpkt); + av_packet_unref(s->prev_outpkt); + av_packet_move_ref(s->prev_inpkt, s->cur_pkt); + av_packet_move_ref(s->cur_pkt, pkt); + + ret = av_packet_ref(pkt, s->prev_inpkt); + if (ret < 0) + return ret; pkt->pts = new_pts; pkt->dts = new_dts; + pkt->duration = new_duration; + + ret = av_packet_ref(s->prev_outpkt, pkt); + if (ret < 0) + av_packet_unref(pkt); return ret; } @@ -188,12 +234,18 @@ static void setts_close(AVBSFContext *bsf) { SetTSContext *s = bsf->priv_data; + av_packet_free(&s->prev_inpkt); + av_packet_free(&s->prev_outpkt); + av_packet_free(&s->cur_pkt); + av_expr_free(s->ts_expr); s->ts_expr = NULL; av_expr_free(s->pts_expr); s->pts_expr = NULL; av_expr_free(s->dts_expr); s->dts_expr = NULL; + av_expr_free(s->duration_expr); + s->duration_expr = NULL; } #define OFFSET(x) offsetof(SetTSContext, x) @@ -203,6 +255,8 @@ static const AVOption options[] = { { "ts", "set expression for packet PTS and DTS", OFFSET(ts_str), AV_OPT_TYPE_STRING, {.str="TS"}, 0, 0, FLAGS }, { "pts", "set expression for packet PTS", OFFSET(pts_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, { "dts", "set expression for packet DTS", OFFSET(dts_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + { "duration", "set expression for packet duration", OFFSET(duration_str), AV_OPT_TYPE_STRING, {.str="DURATION"}, 0, 0, FLAGS }, + { "time_base", "set output timebase", OFFSET(time_base), AV_OPT_TYPE_RATIONAL, {.dbl=0}, 0, INT_MAX, FLAGS }, { NULL }, }; @@ -213,10 +267,10 @@ static const AVClass setts_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVBitStreamFilter ff_setts_bsf = { - .name = "setts", +const FFBitStreamFilter ff_setts_bsf = { + .p.name = "setts", + .p.priv_class = &setts_class, .priv_data_size = sizeof(SetTSContext), - .priv_class = &setts_class, .init = setts_init, .close = setts_close, .filter = setts_filter, diff --git a/libavcodec/sga.c b/libavcodec/sga.c index 1bc6b0b14..cdd37feb7 100644 --- a/libavcodec/sga.c +++ b/libavcodec/sga.c @@ -22,6 +22,7 @@ #include "avcodec.h" #include "get_bits.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" #define PALDATA_FOLLOWS_TILEDATA 4 @@ -305,12 +306,11 @@ static int decode_tiledata(AVCodecContext *avctx) return 0; } -static int sga_decode_frame(AVCodecContext *avctx, void *data, +static int sga_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt) { SGAVideoContext *s = avctx->priv_data; GetByteContext *gb = &s->gb; - AVFrame *frame = data; int ret, type; if (avpkt->size <= 14) @@ -519,15 +519,15 @@ static av_cold int sga_decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_sga_decoder = { - .name = "sga", - .long_name = NULL_IF_CONFIG_SMALL("Digital Pictures SGA Video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_SGA_VIDEO, +const FFCodec ff_sga_decoder = { + .p.name = "sga", + .p.long_name = NULL_IF_CONFIG_SMALL("Digital Pictures SGA Video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_SGA_VIDEO, .priv_data_size = sizeof(SGAVideoContext), .init = sga_decode_init, - .decode = sga_decode_frame, + FF_CODEC_DECODE_CB(sga_decode_frame), .close = sga_decode_end, - .capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/sgidec.c b/libavcodec/sgidec.c index 5fa3bf4a4..b23e205c3 100644 --- a/libavcodec/sgidec.c +++ b/libavcodec/sgidec.c @@ -22,6 +22,7 @@ #include "libavutil/imgutils.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" #include "sgi.h" @@ -198,12 +199,10 @@ static int read_uncompressed_sgi(unsigned char *out_buf, SgiState *s) return 0; } -static int decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *p, + int *got_frame, AVPacket *avpkt) { SgiState *s = avctx->priv_data; - AVFrame *p = data; unsigned int dimension, rle; int ret = 0; uint8_t *out_buf, *out_end; @@ -287,14 +286,14 @@ static av_cold int sgi_decode_init(AVCodecContext *avctx) return 0; } -const AVCodec ff_sgi_decoder = { - .name = "sgi", - .long_name = NULL_IF_CONFIG_SMALL("SGI image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_SGI, +const FFCodec ff_sgi_decoder = { + .p.name = "sgi", + .p.long_name = NULL_IF_CONFIG_SMALL("SGI image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_SGI, .priv_data_size = sizeof(SgiState), - .decode = decode_frame, + FF_CODEC_DECODE_CB(decode_frame), .init = sgi_decode_init, - .capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/sgienc.c b/libavcodec/sgienc.c index 5ed5e71cd..93cb95f07 100644 --- a/libavcodec/sgienc.c +++ b/libavcodec/sgienc.c @@ -23,8 +23,8 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "sgi.h" #include "rle.h" @@ -270,16 +270,16 @@ static const AVClass sgi_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_sgi_encoder = { - .name = "sgi", - .long_name = NULL_IF_CONFIG_SMALL("SGI image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_SGI, +const FFCodec ff_sgi_encoder = { + .p.name = "sgi", + .p.long_name = NULL_IF_CONFIG_SMALL("SGI image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_SGI, .priv_data_size = sizeof(SgiContext), - .priv_class = &sgi_class, + .p.priv_class = &sgi_class, .init = encode_init, - .encode2 = encode_frame, - .pix_fmts = (const enum AVPixelFormat[]) { + FF_CODEC_ENCODE_CB(encode_frame), + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, AV_PIX_FMT_RGB48LE, AV_PIX_FMT_RGB48BE, AV_PIX_FMT_RGBA64LE, AV_PIX_FMT_RGBA64BE, diff --git a/libavcodec/sgirledec.c b/libavcodec/sgirledec.c index aa5107fe2..e04b9b1ca 100644 --- a/libavcodec/sgirledec.c +++ b/libavcodec/sgirledec.c @@ -29,6 +29,7 @@ #include "libavutil/common.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" static av_cold int sgirle_decode_init(AVCodecContext *avctx) @@ -109,10 +110,9 @@ static int decode_sgirle8(AVCodecContext *avctx, uint8_t *dst, return 0; } -static int sgirle_decode_frame(AVCodecContext *avctx, void *data, +static int sgirle_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt) { - AVFrame *frame = data; int ret; if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) @@ -131,13 +131,13 @@ static int sgirle_decode_frame(AVCodecContext *avctx, void *data, return avpkt->size; } -const AVCodec ff_sgirle_decoder = { - .name = "sgirle", - .long_name = NULL_IF_CONFIG_SMALL("Silicon Graphics RLE 8-bit video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_SGIRLE, +const FFCodec ff_sgirle_decoder = { + .p.name = "sgirle", + .p.long_name = NULL_IF_CONFIG_SMALL("Silicon Graphics RLE 8-bit video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_SGIRLE, .init = sgirle_decode_init, - .decode = sgirle_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(sgirle_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/sheervideo.c b/libavcodec/sheervideo.c index fb5a39303..327bf85ed 100644 --- a/libavcodec/sheervideo.c +++ b/libavcodec/sheervideo.c @@ -19,17 +19,13 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include -#include -#include - #define CACHED_BITSTREAM_READER !ARCH_X86_32 #define SHEER_VLC_BITS 12 #include "libavutil/intreadwrite.h" #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" -#include "internal.h" #include "thread.h" #include "sheervideodata.h" @@ -1805,14 +1801,11 @@ static av_cold int build_vlc(VLC *vlc, const SheerTable *table) lens, sizeof(*lens), NULL, 0, 0, 0, 0, NULL); } -static int decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *p, + int *got_frame, AVPacket *avpkt) { SheerVideoContext *s = avctx->priv_data; - ThreadFrame frame = { .f = data }; const SheerTable *table; - AVFrame *p = data; GetBitContext gb; unsigned format; int ret; @@ -1982,7 +1975,7 @@ static int decode_frame(AVCodecContext *avctx, p->pict_type = AV_PICTURE_TYPE_I; p->key_frame = 1; - if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, p, 0)) < 0) return ret; if ((ret = init_get_bits8(&gb, avpkt->data + 20, avpkt->size - 20)) < 0) @@ -2005,13 +1998,13 @@ static av_cold int decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_sheervideo_decoder = { - .name = "sheervideo", - .long_name = NULL_IF_CONFIG_SMALL("BitJazz SheerVideo"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_SHEERVIDEO, +const FFCodec ff_sheervideo_decoder = { + .p.name = "sheervideo", + .p.long_name = NULL_IF_CONFIG_SMALL("BitJazz SheerVideo"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_SHEERVIDEO, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, .priv_data_size = sizeof(SheerVideoContext), .close = decode_end, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + FF_CODEC_DECODE_CB(decode_frame), }; diff --git a/libavcodec/shorten.c b/libavcodec/shorten.c index fde5c4b98..27074e930 100644 --- a/libavcodec/shorten.c +++ b/libavcodec/shorten.c @@ -29,6 +29,7 @@ #include "avcodec.h" #include "bswapdsp.h" #include "bytestream.h" +#include "codec_internal.h" #include "get_bits.h" #include "golomb.h" #include "internal.h" @@ -428,7 +429,11 @@ static int read_header(ShortenContext *s) s->channels = 0; return AVERROR_INVALIDDATA; } - s->avctx->channels = s->channels; + if (s->avctx->ch_layout.nb_channels != s->channels) { + av_channel_layout_uninit(&s->avctx->ch_layout); + s->avctx->ch_layout.nb_channels = s->channels; + s->avctx->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + } /* get blocksize if version > 0 */ if (s->version > 0) { @@ -517,10 +522,9 @@ end: return 0; } -static int shorten_decode_frame(AVCodecContext *avctx, void *data, +static int shorten_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; ShortenContext *s = avctx->priv_data; @@ -799,20 +803,20 @@ static av_cold int shorten_decode_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_shorten_decoder = { - .name = "shorten", - .long_name = NULL_IF_CONFIG_SMALL("Shorten"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_SHORTEN, +const FFCodec ff_shorten_decoder = { + .p.name = "shorten", + .p.long_name = NULL_IF_CONFIG_SMALL("Shorten"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_SHORTEN, .priv_data_size = sizeof(ShortenContext), .init = shorten_decode_init, .close = shorten_decode_close, - .decode = shorten_decode_frame, - .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + FF_CODEC_DECODE_CB(shorten_decode_frame), + .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SUBFRAMES , - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_U8P, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, diff --git a/libavcodec/sipr.c b/libavcodec/sipr.c index a792b22c9..9d11f2c5c 100644 --- a/libavcodec/sipr.c +++ b/libavcodec/sipr.c @@ -31,6 +31,7 @@ #define BITSTREAM_READER_LE #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" #include "lsp.h" @@ -512,18 +513,17 @@ static av_cold int sipr_decoder_init(AVCodecContext * avctx) for (i = 0; i < 4; i++) ctx->energy_history[i] = -14; - avctx->channels = 1; - avctx->channel_layout = AV_CH_LAYOUT_MONO; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; avctx->sample_fmt = AV_SAMPLE_FMT_FLT; return 0; } -static int sipr_decode_frame(AVCodecContext *avctx, void *data, +static int sipr_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { SiprContext *ctx = avctx->priv_data; - AVFrame *frame = data; const uint8_t *buf=avpkt->data; SiprParameters parm; const SiprModeParam *mode_par = &modes[ctx->mode]; @@ -562,14 +562,14 @@ static int sipr_decode_frame(AVCodecContext *avctx, void *data, return mode_par->bits_per_frame >> 3; } -const AVCodec ff_sipr_decoder = { - .name = "sipr", - .long_name = NULL_IF_CONFIG_SMALL("RealAudio SIPR / ACELP.NET"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_SIPR, +const FFCodec ff_sipr_decoder = { + .p.name = "sipr", + .p.long_name = NULL_IF_CONFIG_SMALL("RealAudio SIPR / ACELP.NET"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_SIPR, .priv_data_size = sizeof(SiprContext), .init = sipr_decoder_init, - .decode = sipr_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + FF_CODEC_DECODE_CB(sipr_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/siren.c b/libavcodec/siren.c index bdb249144..b613ee113 100644 --- a/libavcodec/siren.c +++ b/libavcodec/siren.c @@ -27,6 +27,7 @@ #include "libavutil/mem_internal.h" #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" #include "mathops.h" @@ -398,8 +399,8 @@ static av_cold int siren_init(AVCodecContext *avctx) s->imdct_prev = s->imdct_buf[2]; s->window = s->imdct_buf[3]; - avctx->channels = 1; - avctx->channel_layout = AV_CH_LAYOUT_MONO; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; avctx->sample_fmt = AV_SAMPLE_FMT_FLT; s->rate_control_possibilities = 16; @@ -702,12 +703,11 @@ static int decode_vector(SirenContext *s, int number_of_regions, return error == 1 ? AVERROR_INVALIDDATA : (get_bits_left(gb) - s->checksum_bits); } -static int siren_decode(AVCodecContext *avctx, void *data, +static int siren_decode(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt) { SirenContext *s = avctx->priv_data; GetBitContext *gb = &s->gb; - AVFrame *frame = data; int ret, number_of_valid_coefs = REGION_SIZE * s->number_of_regions; int frame_error = 0, rate_control = 0; int bits_per_frame; @@ -841,33 +841,33 @@ static av_cold int siren_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_siren_decoder = { - .name = "siren", - .long_name = NULL_IF_CONFIG_SMALL("Siren"), +const FFCodec ff_siren_decoder = { + .p.name = "siren", + .p.long_name = NULL_IF_CONFIG_SMALL("Siren"), .priv_data_size = sizeof(SirenContext), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_SIREN, + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_SIREN, .init = siren_init, .close = siren_close, - .decode = siren_decode, + FF_CODEC_DECODE_CB(siren_decode), .flush = siren_flush, - .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; -const AVCodec ff_msnsiren_decoder = { - .name = "msnsiren", - .long_name = NULL_IF_CONFIG_SMALL("MSN Siren"), +const FFCodec ff_msnsiren_decoder = { + .p.name = "msnsiren", + .p.long_name = NULL_IF_CONFIG_SMALL("MSN Siren"), .priv_data_size = sizeof(SirenContext), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_MSNSIREN, + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_MSNSIREN, .init = siren_init, .close = siren_close, - .decode = siren_decode, + FF_CODEC_DECODE_CB(siren_decode), .flush = siren_flush, - .capabilities = AV_CODEC_CAP_CHANNEL_CONF | + .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, diff --git a/libavcodec/smacker.c b/libavcodec/smacker.c index 75ab5d712..9d02968d6 100644 --- a/libavcodec/smacker.c +++ b/libavcodec/smacker.c @@ -50,6 +50,7 @@ #endif #define BITSTREAM_READER_LE #include "bytestream.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" #include "mathops.h" @@ -370,8 +371,8 @@ static av_always_inline int smk_get_code(GetBitContext *gb, int *recode, int *la return v; } -static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *avpkt) { SmackVContext * const smk = avctx->priv_data; uint8_t *out; @@ -517,7 +518,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, } - if ((ret = av_frame_ref(data, smk->pic)) < 0) + if ((ret = av_frame_ref(rframe, smk->pic)) < 0) return ret; *got_frame = 1; @@ -572,11 +573,13 @@ static av_cold int decode_init(AVCodecContext *avctx) static av_cold int smka_decode_init(AVCodecContext *avctx) { - if (avctx->channels < 1 || avctx->channels > 2) { + int channels = avctx->ch_layout.nb_channels; + if (channels < 1 || channels > 2) { av_log(avctx, AV_LOG_ERROR, "invalid number of channels\n"); return AVERROR_INVALIDDATA; } - avctx->channel_layout = (avctx->channels==2) ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO; + av_channel_layout_uninit(&avctx->ch_layout); + av_channel_layout_default(&avctx->ch_layout, channels); avctx->sample_fmt = avctx->bits_per_coded_sample == 8 ? AV_SAMPLE_FMT_U8 : AV_SAMPLE_FMT_S16; return 0; @@ -585,10 +588,9 @@ static av_cold int smka_decode_init(AVCodecContext *avctx) /** * Decode Smacker audio data */ -static int smka_decode_frame(AVCodecContext *avctx, void *data, +static int smka_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; GetBitContext gb; @@ -599,7 +601,7 @@ static int smka_decode_frame(AVCodecContext *avctx, void *data, int i, res, ret; int unp_size; int bits, stereo; - unsigned pred[2], val; + unsigned pred[2], val, val2; if (buf_size <= 4) { av_log(avctx, AV_LOG_ERROR, "packet is too small\n"); @@ -623,7 +625,7 @@ static int smka_decode_frame(AVCodecContext *avctx, void *data, } stereo = get_bits1(&gb); bits = get_bits1(&gb); - if (stereo ^ (avctx->channels != 1)) { + if (stereo ^ (avctx->ch_layout.nb_channels != 1)) { av_log(avctx, AV_LOG_ERROR, "channels mismatch\n"); return AVERROR_INVALIDDATA; } @@ -633,8 +635,8 @@ static int smka_decode_frame(AVCodecContext *avctx, void *data, } /* get output buffer */ - frame->nb_samples = unp_size / (avctx->channels * (bits + 1)); - if (unp_size % (avctx->channels * (bits + 1))) { + frame->nb_samples = unp_size / (avctx->ch_layout.nb_channels * (bits + 1)); + if (unp_size % (avctx->ch_layout.nb_channels * (bits + 1))) { av_log(avctx, AV_LOG_ERROR, "The buffer does not contain an integer number of samples\n"); return AVERROR_INVALIDDATA; @@ -670,24 +672,44 @@ static int smka_decode_frame(AVCodecContext *avctx, void *data, pred[i] = av_bswap16(get_bits(&gb, 16)); for(i = 0; i <= stereo; i++) *samples++ = pred[i]; - for(; i < unp_size / 2; i++) { - unsigned idx = 2 * (i & stereo); - if (get_bits_left(&gb) < 0) { - ret = AVERROR_INVALIDDATA; - goto error; + unp_size /= 2; + + if (vlc[0 ].table || vlc[ 1].table || + vlc[2*stereo].table || vlc[2*stereo+1].table) { + for(; i < unp_size ; i++) { + unsigned idx = 2 * (i & stereo); + if (get_bits_left(&gb) < 0) { + ret = AVERROR_INVALIDDATA; + goto error; + } + if (vlc[idx].table) + res = get_vlc2(&gb, vlc[idx].table, SMKTREE_BITS, 3); + else + res = values[idx]; + val = res; + if (vlc[++idx].table) + res = get_vlc2(&gb, vlc[idx].table, SMKTREE_BITS, 3); + else + res = values[idx]; + val |= res << 8; + pred[idx / 2] += val; + *samples++ = pred[idx / 2]; + } + } else if (stereo) { + val = 256*values[1] + values[0]; + val2 = 256*values[3] + values[2]; + for(; i < unp_size; i+=2) { + pred[0] += val; + pred[1] += val2; + *samples++ = pred[0]; + *samples++ = pred[1]; + } + } else { + val = 256*values[1] + values[0]; + for(; i < unp_size; i++) { + pred[0] += val; + *samples++ = pred[0]; } - if (vlc[idx].table) - res = get_vlc2(&gb, vlc[idx].table, SMKTREE_BITS, 3); - else - res = values[idx]; - val = res; - if (vlc[++idx].table) - res = get_vlc2(&gb, vlc[idx].table, SMKTREE_BITS, 3); - else - res = values[idx]; - val |= res << 8; - pred[idx / 2] += val; - *samples++ = pred[idx / 2]; } } else { //8-bit data for(i = stereo; i >= 0; i--) @@ -720,26 +742,26 @@ error: return ret; } -const AVCodec ff_smacker_decoder = { - .name = "smackvid", - .long_name = NULL_IF_CONFIG_SMALL("Smacker video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_SMACKVIDEO, +const FFCodec ff_smacker_decoder = { + .p.name = "smackvid", + .p.long_name = NULL_IF_CONFIG_SMALL("Smacker video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_SMACKVIDEO, .priv_data_size = sizeof(SmackVContext), .init = decode_init, .close = decode_end, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE, }; -const AVCodec ff_smackaud_decoder = { - .name = "smackaud", - .long_name = NULL_IF_CONFIG_SMALL("Smacker audio"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_SMACKAUDIO, +const FFCodec ff_smackaud_decoder = { + .p.name = "smackaud", + .p.long_name = NULL_IF_CONFIG_SMALL("Smacker audio"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_SMACKAUDIO, .init = smka_decode_init, - .decode = smka_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(smka_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/smc.c b/libavcodec/smc.c index 9cd86216a..313d8edba 100644 --- a/libavcodec/smc.c +++ b/libavcodec/smc.c @@ -35,6 +35,7 @@ #include "libavutil/intreadwrite.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "decode.h" #include "internal.h" @@ -427,9 +428,8 @@ static av_cold int smc_decode_init(AVCodecContext *avctx) return 0; } -static int smc_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int smc_decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; @@ -452,7 +452,7 @@ static int smc_decode_frame(AVCodecContext *avctx, return ret; *got_frame = 1; - if ((ret = av_frame_ref(data, s->frame)) < 0) + if ((ret = av_frame_ref(rframe, s->frame)) < 0) return ret; /* always report that the buffer was completely consumed */ @@ -468,15 +468,15 @@ static av_cold int smc_decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_smc_decoder = { - .name = "smc", - .long_name = NULL_IF_CONFIG_SMALL("QuickTime Graphics (SMC)"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_SMC, +const FFCodec ff_smc_decoder = { + .p.name = "smc", + .p.long_name = NULL_IF_CONFIG_SMALL("QuickTime Graphics (SMC)"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_SMC, .priv_data_size = sizeof(SmcContext), .init = smc_decode_init, .close = smc_decode_end, - .decode = smc_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(smc_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/smcenc.c b/libavcodec/smcenc.c index 52795efb5..e1137098d 100644 --- a/libavcodec/smcenc.c +++ b/libavcodec/smcenc.c @@ -27,8 +27,8 @@ #include "libavutil/common.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "bytestream.h" #define CPAIR 2 @@ -548,16 +548,16 @@ static int smc_encode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_smc_encoder = { - .name = "smc", - .long_name = NULL_IF_CONFIG_SMALL("QuickTime Graphics (SMC)"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_SMC, +const FFCodec ff_smc_encoder = { + .p.name = "smc", + .p.long_name = NULL_IF_CONFIG_SMALL("QuickTime Graphics (SMC)"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_SMC, .priv_data_size = sizeof(SMCContext), .init = smc_encode_init, - .encode2 = smc_encode_frame, + FF_CODEC_ENCODE_CB(smc_encode_frame), .close = smc_encode_end, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, - .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_PAL8, + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_PAL8, AV_PIX_FMT_NONE}, }; diff --git a/libavcodec/snow.c b/libavcodec/snow.c index e0fb58042..293a0eb7d 100644 --- a/libavcodec/snow.c +++ b/libavcodec/snow.c @@ -23,6 +23,7 @@ #include "libavutil/opt.h" #include "libavutil/thread.h" #include "avcodec.h" +#include "encode.h" #include "me_cmp.h" #include "snow_dwt.h" #include "internal.h" @@ -31,7 +32,6 @@ #include "rangecoder.h" #include "mathops.h" -#include "h263.h" void ff_snow_inner_add_yblock(const uint8_t *obmc, const int obmc_stride, uint8_t * * block, int b_w, int b_h, @@ -77,8 +77,11 @@ int ff_snow_get_buffer(SnowContext *s, AVFrame *frame) if (edges_needed) { frame->width += 2 * EDGE_WIDTH; frame->height += 2 * EDGE_WIDTH; - } - if ((ret = ff_get_buffer(s->avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0) + + ret = ff_encode_alloc_frame(s->avctx, frame); + } else + ret = ff_get_buffer(s->avctx, frame, AV_GET_BUFFER_FLAG_REF); + if (ret < 0) return ret; if (edges_needed) { for (i = 0; frame->data[i]; i++) { @@ -514,16 +517,20 @@ int ff_snow_common_init_after_header(AVCodecContext *avctx) { int ret, emu_buf_size; if(!s->scratchbuf) { - if ((ret = ff_get_buffer(s->avctx, s->mconly_picture, - AV_GET_BUFFER_FLAG_REF)) < 0) - return ret; + if (av_codec_is_decoder(avctx->codec)) { + if ((ret = ff_get_buffer(s->avctx, s->mconly_picture, + AV_GET_BUFFER_FLAG_REF)) < 0) + return ret; + } + emu_buf_size = FFMAX(s->mconly_picture->linesize[0], 2*avctx->width+256) * (2 * MB_SIZE + HTAPS_MAX - 1); if (!FF_ALLOCZ_TYPED_ARRAY(s->scratchbuf, FFMAX(s->mconly_picture->linesize[0], 2*avctx->width+256) * 7 * MB_SIZE) || !FF_ALLOCZ_TYPED_ARRAY(s->emu_edge_buffer, emu_buf_size)) return AVERROR(ENOMEM); } - if(s->mconly_picture->format != avctx->pix_fmt) { + if (av_codec_is_decoder(avctx->codec) && + s->mconly_picture->format != avctx->pix_fmt) { av_log(avctx, AV_LOG_ERROR, "pixel format changed\n"); return AVERROR_INVALIDDATA; } diff --git a/libavcodec/snow.h b/libavcodec/snow.h index 8795491cf..f5beca66e 100644 --- a/libavcodec/snow.h +++ b/libavcodec/snow.h @@ -35,6 +35,8 @@ #include "mpegvideo.h" #include "h264qpel.h" +#define SNOW_MAX_PLANES 4 + #define FF_ME_ITER 3 #define MID_STATE 128 @@ -188,7 +190,7 @@ typedef struct SnowContext{ AVMotionVector *avmv; unsigned avmv_size; int avmv_index; - uint64_t encoding_error[AV_NUM_DATA_POINTERS]; + uint64_t encoding_error[SNOW_MAX_PLANES]; int pred; }SnowContext; diff --git a/libavcodec/snow_dwt.c b/libavcodec/snow_dwt.c index c093ebff0..e196fefd2 100644 --- a/libavcodec/snow_dwt.c +++ b/libavcodec/snow_dwt.c @@ -853,8 +853,9 @@ av_cold void ff_dwt_init(SnowDWTContext *c) c->horizontal_compose97i = snow_horizontal_compose97i; c->inner_add_yblock = ff_snow_inner_add_yblock; - if (HAVE_MMX) - ff_dwt_init_x86(c); +#if ARCH_X86 && HAVE_MMX + ff_dwt_init_x86(c); +#endif } diff --git a/libavcodec/snowdec.c b/libavcodec/snowdec.c index cd2265aba..92ff87731 100644 --- a/libavcodec/snowdec.c +++ b/libavcodec/snowdec.c @@ -22,15 +22,13 @@ #include "libavutil/log.h" #include "libavutil/opt.h" #include "avcodec.h" +#include "codec_internal.h" #include "snow_dwt.h" -#include "internal.h" #include "snow.h" #include "rangecoder.h" #include "mathops.h" -#include "h263.h" - static av_always_inline void predict_slice_buffered(SnowContext *s, slice_buffer * sb, IDWTELEM * old_buffer, int plane_index, int add, int mb_y){ Plane *p= &s->plane[plane_index]; const int mb_w= s->b_width << s->block_max_depth; @@ -438,15 +436,14 @@ static int decode_blocks(SnowContext *s){ return 0; } -static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *picture, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; SnowContext *s = avctx->priv_data; RangeCoder * const c= &s->c; int bytes_read; - AVFrame *picture = data; int level, orientation, plane_index; int res; @@ -656,16 +653,16 @@ static av_cold int decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_snow_decoder = { - .name = "snow", - .long_name = NULL_IF_CONFIG_SMALL("Snow"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_SNOW, +const FFCodec ff_snow_decoder = { + .p.name = "snow", + .p.long_name = NULL_IF_CONFIG_SMALL("Snow"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_SNOW, .priv_data_size = sizeof(SnowContext), .init = ff_snow_common_init, .close = decode_end, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1 /*| AV_CODEC_CAP_DRAW_HORIZ_BAND*/, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 /*| AV_CODEC_CAP_DRAW_HORIZ_BAND*/, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/snowenc.c b/libavcodec/snowenc.c index 96b0d320b..207948675 100644 --- a/libavcodec/snowenc.c +++ b/libavcodec/snowenc.c @@ -24,8 +24,8 @@ #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "packet_internal.h" #include "snow_dwt.h" #include "snow.h" @@ -34,7 +34,7 @@ #include "mathops.h" #include "mpegvideo.h" -#include "h263.h" +#include "h263enc.h" static av_cold int encode_init(AVCodecContext *avctx) { @@ -1647,7 +1647,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, s->m.avctx= s->avctx; s->m. last_picture.f = s->last_picture[0]; - s->m. new_picture.f = s->input_picture; + s->m. new_picture = s->input_picture; s->m. last_picture_ptr= &s->m. last_picture; s->m.linesize = stride; s->m.uvlinesize= s->current_picture->linesize[1]; @@ -1858,7 +1858,7 @@ redo_frame: ff_side_data_set_encoder_stats(pkt, s->current_picture->quality, s->encoding_error, - (s->avctx->flags&AV_CODEC_FLAG_PSNR) ? 4 : 0, + (s->avctx->flags&AV_CODEC_FLAG_PSNR) ? SNOW_MAX_PLANES : 0, s->current_picture->pict_type); pkt->size = ff_rac_terminate(c, 0); @@ -1912,21 +1912,21 @@ static const AVClass snowenc_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_snow_encoder = { - .name = "snow", - .long_name = NULL_IF_CONFIG_SMALL("Snow"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_SNOW, +const FFCodec ff_snow_encoder = { + .p.name = "snow", + .p.long_name = NULL_IF_CONFIG_SMALL("Snow"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_SNOW, .priv_data_size = sizeof(SnowContext), .init = encode_init, - .encode2 = encode_frame, + FF_CODEC_ENCODE_CB(encode_frame), .close = encode_end, - .pix_fmts = (const enum AVPixelFormat[]){ + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE }, - .priv_class = &snowenc_class, + .p.priv_class = &snowenc_class, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/sonic.c b/libavcodec/sonic.c index b4935e7ea..dfb055d80 100644 --- a/libavcodec/sonic.c +++ b/libavcodec/sonic.c @@ -18,11 +18,16 @@ * 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_components.h" + #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" #include "get_bits.h" #include "golomb.h" #include "internal.h" +#include "put_golomb.h" #include "rangecoder.h" @@ -597,13 +602,13 @@ static av_cold int sonic_encode_init(AVCodecContext *avctx) s->version = 2; - if (avctx->channels > MAX_CHANNELS) + if (avctx->ch_layout.nb_channels > MAX_CHANNELS) { av_log(avctx, AV_LOG_ERROR, "Only mono and stereo streams are supported by now\n"); return AVERROR(EINVAL); /* only stereo or mono for now */ } - if (avctx->channels == 2) + if (avctx->ch_layout.nb_channels == 2) s->decorrelation = MID_SIDE; else s->decorrelation = 3; @@ -636,7 +641,7 @@ static av_cold int sonic_encode_init(AVCodecContext *avctx) for (i = 0; i < s->num_taps; i++) s->tap_quant[i] = ff_sqrt(i+1); - s->channels = avctx->channels; + s->channels = avctx->ch_layout.nb_channels; s->samplerate = avctx->sample_rate; s->block_align = 2048LL*s->samplerate/(44100*s->downsampling); @@ -852,7 +857,7 @@ static av_cold int sonic_decode_init(AVCodecContext *avctx) int i; int ret; - s->channels = avctx->channels; + s->channels = avctx->ch_layout.nb_channels; s->samplerate = avctx->sample_rate; if (!avctx->extradata) @@ -895,7 +900,9 @@ static av_cold int sonic_decode_init(AVCodecContext *avctx) av_log(avctx, AV_LOG_ERROR, "Only mono and stereo streams are supported by now\n"); return AVERROR_INVALIDDATA; } - avctx->channels = s->channels; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + avctx->ch_layout.nb_channels = s->channels; s->lossless = get_bits1(&gb); if (!s->lossless) @@ -973,9 +980,8 @@ static av_cold int sonic_decode_close(AVCodecContext *avctx) return 0; } -static int sonic_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame_ptr, - AVPacket *avpkt) +static int sonic_decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame_ptr, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; @@ -984,11 +990,10 @@ static int sonic_decode_frame(AVCodecContext *avctx, uint8_t state[32]; int i, quant, ch, j, ret; int16_t *samples; - AVFrame *frame = data; if (buf_size == 0) return 0; - frame->nb_samples = s->frame_size / avctx->channels; + frame->nb_samples = s->frame_size / avctx->ch_layout.nb_channels; if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; samples = (int16_t *)frame->data[0]; @@ -1071,47 +1076,47 @@ static int sonic_decode_frame(AVCodecContext *avctx, return buf_size; } -const AVCodec ff_sonic_decoder = { - .name = "sonic", - .long_name = NULL_IF_CONFIG_SMALL("Sonic"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_SONIC, +const FFCodec ff_sonic_decoder = { + .p.name = "sonic", + .p.long_name = NULL_IF_CONFIG_SMALL("Sonic"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_SONIC, .priv_data_size = sizeof(SonicContext), .init = sonic_decode_init, .close = sonic_decode_close, - .decode = sonic_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_EXPERIMENTAL | AV_CODEC_CAP_CHANNEL_CONF, + FF_CODEC_DECODE_CB(sonic_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_EXPERIMENTAL | AV_CODEC_CAP_CHANNEL_CONF, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; #endif /* CONFIG_SONIC_DECODER */ #if CONFIG_SONIC_ENCODER -const AVCodec ff_sonic_encoder = { - .name = "sonic", - .long_name = NULL_IF_CONFIG_SMALL("Sonic"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_SONIC, +const FFCodec ff_sonic_encoder = { + .p.name = "sonic", + .p.long_name = NULL_IF_CONFIG_SMALL("Sonic"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_SONIC, .priv_data_size = sizeof(SonicContext), .init = sonic_encode_init, - .encode2 = sonic_encode_frame, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, - .capabilities = AV_CODEC_CAP_EXPERIMENTAL, + FF_CODEC_ENCODE_CB(sonic_encode_frame), + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, + .p.capabilities = AV_CODEC_CAP_EXPERIMENTAL, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .close = sonic_encode_close, }; #endif #if CONFIG_SONIC_LS_ENCODER -const AVCodec ff_sonic_ls_encoder = { - .name = "sonicls", - .long_name = NULL_IF_CONFIG_SMALL("Sonic lossless"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_SONIC_LS, +const FFCodec ff_sonic_ls_encoder = { + .p.name = "sonicls", + .p.long_name = NULL_IF_CONFIG_SMALL("Sonic lossless"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_SONIC_LS, .priv_data_size = sizeof(SonicContext), .init = sonic_encode_init, - .encode2 = sonic_encode_frame, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, - .capabilities = AV_CODEC_CAP_EXPERIMENTAL, + FF_CODEC_ENCODE_CB(sonic_encode_frame), + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }, + .p.capabilities = AV_CODEC_CAP_EXPERIMENTAL, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .close = sonic_encode_close, }; diff --git a/libavcodec/sp5xdec.c b/libavcodec/sp5xdec.c index a1b43f8f8..aa4d3d771 100644 --- a/libavcodec/sp5xdec.c +++ b/libavcodec/sp5xdec.c @@ -24,8 +24,10 @@ * Sunplus JPEG decoder (SP5X). */ +#include "config_components.h" + #include "avcodec.h" -#include "internal.h" +#include "codec_internal.h" #include "mjpeg.h" #include "mjpegdec.h" #include "sp5x.h" @@ -90,33 +92,33 @@ int ff_sp5x_process_packet(AVCodecContext *avctx, AVPacket *avpkt) } #if CONFIG_SP5X_DECODER -const AVCodec ff_sp5x_decoder = { - .name = "sp5x", - .long_name = NULL_IF_CONFIG_SMALL("Sunplus JPEG (SP5X)"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_SP5X, +const FFCodec ff_sp5x_decoder = { + .p.name = "sp5x", + .p.long_name = NULL_IF_CONFIG_SMALL("Sunplus JPEG (SP5X)"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_SP5X, .priv_data_size = sizeof(MJpegDecodeContext), .init = ff_mjpeg_decode_init, .close = ff_mjpeg_decode_end, - .receive_frame = ff_mjpeg_receive_frame, - .capabilities = AV_CODEC_CAP_DR1, - .max_lowres = 3, + FF_CODEC_RECEIVE_FRAME_CB(ff_mjpeg_receive_frame), + .p.capabilities = AV_CODEC_CAP_DR1, + .p.max_lowres = 3, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_SETS_PKT_DTS, }; #endif #if CONFIG_AMV_DECODER -const AVCodec ff_amv_decoder = { - .name = "amv", - .long_name = NULL_IF_CONFIG_SMALL("AMV Video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_AMV, +const FFCodec ff_amv_decoder = { + .p.name = "amv", + .p.long_name = NULL_IF_CONFIG_SMALL("AMV Video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_AMV, .priv_data_size = sizeof(MJpegDecodeContext), .init = ff_mjpeg_decode_init, .close = ff_mjpeg_decode_end, - .receive_frame = ff_mjpeg_receive_frame, - .max_lowres = 3, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_RECEIVE_FRAME_CB(ff_mjpeg_receive_frame), + .p.max_lowres = 3, + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_SETS_PKT_DTS, }; diff --git a/libavcodec/speedhq.c b/libavcodec/speedhq.c index 743dacc6c..4cfd4ce73 100644 --- a/libavcodec/speedhq.c +++ b/libavcodec/speedhq.c @@ -27,15 +27,19 @@ #define BITSTREAM_READER_LE #include "config.h" +#include "config_components.h" #include "libavutil/attributes.h" #include "libavutil/mem_internal.h" #include "avcodec.h" +#include "blockdsp.h" +#include "codec_internal.h" #include "get_bits.h" +#include "idctdsp.h" #include "internal.h" #include "libavutil/thread.h" #include "mathops.h" -#include "mpeg12.h" +#include "mpeg12dec.h" #include "mpeg12data.h" #include "mpeg12vlc.h" @@ -485,14 +489,12 @@ static void compute_quant_matrix(int *output, int qscale) for (i = 0; i < 64; i++) output[i] = unscaled_quant_matrix[ff_zigzag_direct[i]] * qscale; } -static int speedhq_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int speedhq_decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { SHQContext * const s = avctx->priv_data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; - AVFrame *frame = data; uint8_t quality; uint32_t second_field_offset; int ret; @@ -722,15 +724,15 @@ static av_cold int speedhq_decode_init(AVCodecContext *avctx) return 0; } -const AVCodec ff_speedhq_decoder = { - .name = "speedhq", - .long_name = NULL_IF_CONFIG_SMALL("NewTek SpeedHQ"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_SPEEDHQ, +const FFCodec ff_speedhq_decoder = { + .p.name = "speedhq", + .p.long_name = NULL_IF_CONFIG_SMALL("NewTek SpeedHQ"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_SPEEDHQ, .priv_data_size = sizeof(SHQContext), .init = speedhq_decode_init, - .decode = speedhq_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(speedhq_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif /* CONFIG_SPEEDHQ_DECODER */ diff --git a/libavcodec/speedhqenc.c b/libavcodec/speedhqenc.c index 4a2b422f1..7a53d8694 100644 --- a/libavcodec/speedhqenc.c +++ b/libavcodec/speedhqenc.c @@ -27,12 +27,16 @@ * SpeedHQ encoder. */ -#include "libavutil/pixdesc.h" +#include "config_components.h" + #include "libavutil/thread.h" #include "avcodec.h" -#include "mpeg12.h" +#include "codec_internal.h" +#include "mpeg12data.h" +#include "mpeg12enc.h" #include "mpegvideo.h" +#include "mpegvideoenc.h" #include "speedhqenc.h" extern RLTable ff_rl_speedhq; @@ -53,6 +57,12 @@ static uint32_t speedhq_chr_dc_uni[512]; static uint8_t uni_speedhq_ac_vlc_len[64 * 64 * 2]; +typedef struct SpeedHQEncContext { + MpegEncContext m; + + int slice_start; +} SpeedHQEncContext; + static av_cold void speedhq_init_static_data(void) { ff_rl_init(&ff_rl_speedhq, speedhq_static_rl_table_store); @@ -86,8 +96,6 @@ av_cold int ff_speedhq_encode_init(MpegEncContext *s) { static AVOnce init_static_once = AV_ONCE_INIT; - av_assert0(s->slice_context_count == 1); - if (s->width > 65500 || s->height > 65500) { av_log(s, AV_LOG_ERROR, "SpeedHQ does not support resolutions above 65500x65500\n"); return AVERROR(EINVAL); @@ -122,24 +130,27 @@ av_cold int ff_speedhq_encode_init(MpegEncContext *s) void ff_speedhq_encode_picture_header(MpegEncContext *s) { + SpeedHQEncContext *ctx = (SpeedHQEncContext*)s; + put_bits_le(&s->pb, 8, 100 - s->qscale * 2); /* FIXME why doubled */ put_bits_le(&s->pb, 24, 4); /* no second field */ + ctx->slice_start = 4; /* length of first slice, will be filled out later */ - s->slice_start = 4; put_bits_le(&s->pb, 24, 0); } void ff_speedhq_end_slice(MpegEncContext *s) { + SpeedHQEncContext *ctx = (SpeedHQEncContext*)s; int slice_len; flush_put_bits_le(&s->pb); - slice_len = s->pb.buf_ptr - (s->pb.buf + s->slice_start); - AV_WL24(s->pb.buf + s->slice_start, slice_len); + slice_len = put_bytes_output(&s->pb) - ctx->slice_start; + AV_WL24(s->pb.buf + ctx->slice_start, slice_len); /* length of next slice, will be filled out later */ - s->slice_start = s->pb.buf_ptr - s->pb.buf; + ctx->slice_start = put_bytes_output(&s->pb); put_bits_le(&s->pb, 24, 0); } @@ -212,8 +223,9 @@ static void encode_block(MpegEncContext *s, int16_t *block, int n) put_bits_le(&s->pb, ff_rl_speedhq.table_vlc[code][1] + 1, ff_rl_speedhq.table_vlc[code][0] + (sign << ff_rl_speedhq.table_vlc[code][1])); } else { - /* escape seems to be pretty rare <5% so I do not optimize it */ - put_bits_le(&s->pb, ff_rl_speedhq.table_vlc[121][1], ff_rl_speedhq.table_vlc[121][0]); + /* escape seems to be pretty rare <5% so I do not optimize it; + * the values correspond to ff_rl_speedhq.table_vlc[121] */ + put_bits_le(&s->pb, 6, 32); /* escape: only clip in this case */ put_bits_le(&s->pb, 6, run); put_bits_le(&s->pb, 12, level + 2048); @@ -221,8 +233,8 @@ static void encode_block(MpegEncContext *s, int16_t *block, int n) last_non_zero = i; } } - /* end of block */ - put_bits_le(&s->pb, ff_rl_speedhq.table_vlc[122][1], ff_rl_speedhq.table_vlc[122][0]); + /* end of block; the values correspond to ff_rl_speedhq.table_vlc[122] */ + put_bits_le(&s->pb, 4, 6); } void ff_speedhq_encode_mb(MpegEncContext *s, int16_t block[12][64]) @@ -265,18 +277,18 @@ int ff_speedhq_mb_y_order_to_mb(int mb_y_order, int mb_height, int *first_in_sli } #if CONFIG_SPEEDHQ_ENCODER -const AVCodec ff_speedhq_encoder = { - .name = "speedhq", - .long_name = NULL_IF_CONFIG_SMALL("NewTek SpeedHQ"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_SPEEDHQ, - .priv_class = &ff_mpv_enc_class, - .priv_data_size = sizeof(MpegEncContext), +const FFCodec ff_speedhq_encoder = { + .p.name = "speedhq", + .p.long_name = NULL_IF_CONFIG_SMALL("NewTek SpeedHQ"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_SPEEDHQ, + .p.priv_class = &ff_mpv_enc_class, + .priv_data_size = sizeof(SpeedHQEncContext), .init = ff_mpv_encode_init, - .encode2 = ff_mpv_encode_picture, + FF_CODEC_ENCODE_CB(ff_mpv_encode_picture), .close = ff_mpv_encode_end, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .pix_fmts = (const enum AVPixelFormat[]) { + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_NONE }, diff --git a/libavcodec/speexdec.c b/libavcodec/speexdec.c index ee95417de..3251eda82 100644 --- a/libavcodec/speexdec.c +++ b/libavcodec/speexdec.c @@ -55,6 +55,7 @@ #include "libavutil/float_dsp.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" #include "speexdata.h" @@ -1450,7 +1451,7 @@ static av_cold int speex_decode_init(AVCodecContext *avctx) if (s->rate <= 0) return AVERROR_INVALIDDATA; - s->nb_channels = avctx->channels; + s->nb_channels = avctx->ch_layout.nb_channels; if (s->nb_channels <= 0) return AVERROR_INVALIDDATA; @@ -1492,7 +1493,9 @@ static av_cold int speex_decode_init(AVCodecContext *avctx) if (s->bitrate > 0) avctx->bit_rate = s->bitrate; - avctx->channels = s->nb_channels; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + avctx->ch_layout.nb_channels = s->nb_channels; avctx->sample_rate = s->rate; avctx->sample_fmt = AV_SAMPLE_FMT_FLT; @@ -1530,11 +1533,10 @@ static void speex_decode_stereo(float *data, int frame_size, StereoState *stereo } } -static int speex_decode_frame(AVCodecContext *avctx, void *data, +static int speex_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { SpeexContext *s = avctx->priv_data; - AVFrame *frame = data; const float scale = 1.f / 32768.f; int buf_size = avpkt->size; float *dst; @@ -1554,12 +1556,12 @@ static int speex_decode_frame(AVCodecContext *avctx, void *data, ret = speex_modes[s->mode].decode(avctx, &s->st[s->mode], &s->gb, dst + i * s->frame_size); if (ret < 0) return ret; - if (avctx->channels == 2) + if (avctx->ch_layout.nb_channels == 2) speex_decode_stereo(dst + i * s->frame_size, s->frame_size, &s->stereo); } dst = (float *)frame->extended_data[0]; - s->fdsp->vector_fmul_scalar(dst, dst, scale, frame->nb_samples * frame->channels); + s->fdsp->vector_fmul_scalar(dst, dst, scale, frame->nb_samples * frame->ch_layout.nb_channels); frame->nb_samples = s->frame_size * s->frames_per_packet; *got_frame_ptr = 1; @@ -1574,15 +1576,15 @@ static av_cold int speex_decode_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_speex_decoder = { - .name = "speex", - .long_name = NULL_IF_CONFIG_SMALL("Speex"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_SPEEX, +const FFCodec ff_speex_decoder = { + .p.name = "speex", + .p.long_name = NULL_IF_CONFIG_SMALL("Speex"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_SPEEX, .init = speex_decode_init, - .decode = speex_decode_frame, + FF_CODEC_DECODE_CB(speex_decode_frame), .close = speex_decode_close, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .priv_data_size = sizeof(SpeexContext), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/srtdec.c b/libavcodec/srtdec.c index 4f16226b8..b2df34474 100644 --- a/libavcodec/srtdec.c +++ b/libavcodec/srtdec.c @@ -19,14 +19,16 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/avstring.h" #include "libavutil/common.h" #include "libavutil/intreadwrite.h" #include "libavutil/parseutils.h" #include "avcodec.h" #include "ass.h" +#include "codec_internal.h" #include "htmlsubtitles.h" -#include "internal.h" static int srt_to_ass(AVCodecContext *avctx, AVBPrint *dst, const char *in, int x1, int y1, int x2, int y2) @@ -53,10 +55,9 @@ static int srt_to_ass(AVCodecContext *avctx, AVBPrint *dst, return ff_htmlmarkup_to_ass(avctx, dst, in); } -static int srt_decode_frame(AVCodecContext *avctx, - void *data, int *got_sub_ptr, AVPacket *avpkt) +static int srt_decode_frame(AVCodecContext *avctx, AVSubtitle *sub, + int *got_sub_ptr, const AVPacket *avpkt) { - AVSubtitle *sub = data; AVBPrint buffer; int x1 = -1, y1 = -1, x2 = -1, y2 = -1; int ret; @@ -89,13 +90,13 @@ static int srt_decode_frame(AVCodecContext *avctx, #if CONFIG_SRT_DECODER /* deprecated decoder */ -const AVCodec ff_srt_decoder = { - .name = "srt", - .long_name = NULL_IF_CONFIG_SMALL("SubRip subtitle"), - .type = AVMEDIA_TYPE_SUBTITLE, - .id = AV_CODEC_ID_SUBRIP, +const FFCodec ff_srt_decoder = { + .p.name = "srt", + .p.long_name = NULL_IF_CONFIG_SMALL("SubRip subtitle"), + .p.type = AVMEDIA_TYPE_SUBTITLE, + .p.id = AV_CODEC_ID_SUBRIP, .init = ff_ass_subtitle_header_default, - .decode = srt_decode_frame, + FF_CODEC_DECODE_SUB_CB(srt_decode_frame), .flush = ff_ass_decoder_flush, .priv_data_size = sizeof(FFASSDecoderContext), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, @@ -103,13 +104,13 @@ const AVCodec ff_srt_decoder = { #endif #if CONFIG_SUBRIP_DECODER -const AVCodec ff_subrip_decoder = { - .name = "subrip", - .long_name = NULL_IF_CONFIG_SMALL("SubRip subtitle"), - .type = AVMEDIA_TYPE_SUBTITLE, - .id = AV_CODEC_ID_SUBRIP, +const FFCodec ff_subrip_decoder = { + .p.name = "subrip", + .p.long_name = NULL_IF_CONFIG_SMALL("SubRip subtitle"), + .p.type = AVMEDIA_TYPE_SUBTITLE, + .p.id = AV_CODEC_ID_SUBRIP, .init = ff_ass_subtitle_header_default, - .decode = srt_decode_frame, + FF_CODEC_DECODE_SUB_CB(srt_decode_frame), .flush = ff_ass_decoder_flush, .priv_data_size = sizeof(FFASSDecoderContext), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, diff --git a/libavcodec/srtenc.c b/libavcodec/srtenc.c index 2e3ac5577..51456c8b9 100644 --- a/libavcodec/srtenc.c +++ b/libavcodec/srtenc.c @@ -19,13 +19,15 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include #include "avcodec.h" #include "libavutil/avstring.h" #include "libavutil/bprint.h" #include "ass_split.h" #include "ass.h" -#include "internal.h" +#include "codec_internal.h" #define SRT_STACK_SIZE 64 @@ -291,42 +293,42 @@ static int srt_encode_close(AVCodecContext *avctx) #if CONFIG_SRT_ENCODER /* deprecated encoder */ -const AVCodec ff_srt_encoder = { - .name = "srt", - .long_name = NULL_IF_CONFIG_SMALL("SubRip subtitle"), - .type = AVMEDIA_TYPE_SUBTITLE, - .id = AV_CODEC_ID_SUBRIP, +const FFCodec ff_srt_encoder = { + .p.name = "srt", + .p.long_name = NULL_IF_CONFIG_SMALL("SubRip subtitle"), + .p.type = AVMEDIA_TYPE_SUBTITLE, + .p.id = AV_CODEC_ID_SUBRIP, .priv_data_size = sizeof(SRTContext), .init = srt_encode_init, - .encode_sub = srt_encode_frame, + FF_CODEC_ENCODE_SUB_CB(srt_encode_frame), .close = srt_encode_close, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_SUBRIP_ENCODER -const AVCodec ff_subrip_encoder = { - .name = "subrip", - .long_name = NULL_IF_CONFIG_SMALL("SubRip subtitle"), - .type = AVMEDIA_TYPE_SUBTITLE, - .id = AV_CODEC_ID_SUBRIP, +const FFCodec ff_subrip_encoder = { + .p.name = "subrip", + .p.long_name = NULL_IF_CONFIG_SMALL("SubRip subtitle"), + .p.type = AVMEDIA_TYPE_SUBTITLE, + .p.id = AV_CODEC_ID_SUBRIP, .priv_data_size = sizeof(SRTContext), .init = srt_encode_init, - .encode_sub = srt_encode_frame, + FF_CODEC_ENCODE_SUB_CB(srt_encode_frame), .close = srt_encode_close, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_TEXT_ENCODER -const AVCodec ff_text_encoder = { - .name = "text", - .long_name = NULL_IF_CONFIG_SMALL("Raw text subtitle"), - .type = AVMEDIA_TYPE_SUBTITLE, - .id = AV_CODEC_ID_TEXT, +const FFCodec ff_text_encoder = { + .p.name = "text", + .p.long_name = NULL_IF_CONFIG_SMALL("Raw text subtitle"), + .p.type = AVMEDIA_TYPE_SUBTITLE, + .p.id = AV_CODEC_ID_TEXT, .priv_data_size = sizeof(SRTContext), .init = srt_encode_init, - .encode_sub = text_encode_frame, + FF_CODEC_ENCODE_SUB_CB(text_encode_frame), .close = srt_encode_close, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/startcode.h b/libavcodec/startcode.h index cfa02b086..8b75832aa 100644 --- a/libavcodec/startcode.h +++ b/libavcodec/startcode.h @@ -27,6 +27,10 @@ #include +const uint8_t *avpriv_find_start_code(const uint8_t *p, + const uint8_t *end, + uint32_t *state); + int ff_startcode_find_candidate_c(const uint8_t *buf, int size); #endif /* AVCODEC_STARTCODE_H */ diff --git a/libavcodec/subviewerdec.c b/libavcodec/subviewerdec.c index 5c650d0cd..2bda5fa5c 100644 --- a/libavcodec/subviewerdec.c +++ b/libavcodec/subviewerdec.c @@ -26,7 +26,7 @@ #include "avcodec.h" #include "ass.h" -#include "internal.h" +#include "codec_internal.h" #include "libavutil/bprint.h" static int subviewer_event_to_ass(AVBPrint *buf, const char *p) @@ -47,11 +47,10 @@ static int subviewer_event_to_ass(AVBPrint *buf, const char *p) return 0; } -static int subviewer_decode_frame(AVCodecContext *avctx, - void *data, int *got_sub_ptr, AVPacket *avpkt) +static int subviewer_decode_frame(AVCodecContext *avctx, AVSubtitle *sub, + int *got_sub_ptr, const AVPacket *avpkt) { int ret = 0; - AVSubtitle *sub = data; const char *ptr = avpkt->data; FFASSDecoderContext *s = avctx->priv_data; AVBPrint buf; @@ -66,12 +65,12 @@ static int subviewer_decode_frame(AVCodecContext *avctx, return avpkt->size; } -const AVCodec ff_subviewer_decoder = { - .name = "subviewer", - .long_name = NULL_IF_CONFIG_SMALL("SubViewer subtitle"), - .type = AVMEDIA_TYPE_SUBTITLE, - .id = AV_CODEC_ID_SUBVIEWER, - .decode = subviewer_decode_frame, +const FFCodec ff_subviewer_decoder = { + .p.name = "subviewer", + .p.long_name = NULL_IF_CONFIG_SMALL("SubViewer subtitle"), + .p.type = AVMEDIA_TYPE_SUBTITLE, + .p.id = AV_CODEC_ID_SUBVIEWER, + FF_CODEC_DECODE_SUB_CB(subviewer_decode_frame), .init = ff_ass_subtitle_header_default, .flush = ff_ass_decoder_flush, .priv_data_size = sizeof(FFASSDecoderContext), diff --git a/libavcodec/sunrast.c b/libavcodec/sunrast.c index 7e9a9b0be..e543757a3 100644 --- a/libavcodec/sunrast.c +++ b/libavcodec/sunrast.c @@ -23,15 +23,15 @@ #include "libavutil/intreadwrite.h" #include "libavutil/imgutils.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "sunrast.h" -static int sunrast_decode_frame(AVCodecContext *avctx, void *data, +static int sunrast_decode_frame(AVCodecContext *avctx, AVFrame *p, int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; const uint8_t *buf_end = avpkt->data + avpkt->size; - AVFrame * const p = data; unsigned int w, h, depth, type, maptype, maplength, stride, x, y, len, alen; uint8_t *ptr, *ptr2 = NULL; const uint8_t *bufstart = buf; @@ -205,11 +205,11 @@ static int sunrast_decode_frame(AVCodecContext *avctx, void *data, return buf - bufstart; } -const AVCodec ff_sunrast_decoder = { - .name = "sunrast", - .long_name = NULL_IF_CONFIG_SMALL("Sun Rasterfile image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_SUNRAST, - .decode = sunrast_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, +const FFCodec ff_sunrast_decoder = { + .p.name = "sunrast", + .p.long_name = NULL_IF_CONFIG_SMALL("Sun Rasterfile image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_SUNRAST, + .p.capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(sunrast_decode_frame), }; diff --git a/libavcodec/sunrastenc.c b/libavcodec/sunrastenc.c index 965ee5b81..6245e592c 100644 --- a/libavcodec/sunrastenc.c +++ b/libavcodec/sunrastenc.c @@ -23,8 +23,8 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "sunrast.h" typedef struct SUNRASTContext { @@ -208,16 +208,16 @@ static const AVClass sunrast_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_sunrast_encoder = { - .name = "sunrast", - .long_name = NULL_IF_CONFIG_SMALL("Sun Rasterfile image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_SUNRAST, +const FFCodec ff_sunrast_encoder = { + .p.name = "sunrast", + .p.long_name = NULL_IF_CONFIG_SMALL("Sun Rasterfile image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_SUNRAST, .priv_data_size = sizeof(SUNRASTContext), .init = sunrast_encode_init, - .encode2 = sunrast_encode_frame, - .priv_class = &sunrast_class, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_BGR24, + FF_CODEC_ENCODE_CB(sunrast_encode_frame), + .p.priv_class = &sunrast_class, + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_BGR24, AV_PIX_FMT_PAL8, AV_PIX_FMT_GRAY8, AV_PIX_FMT_MONOWHITE, diff --git a/libavcodec/svq1dec.c b/libavcodec/svq1dec.c index a67d1866b..6fb50575b 100644 --- a/libavcodec/svq1dec.c +++ b/libavcodec/svq1dec.c @@ -36,8 +36,9 @@ #include "libavutil/thread.h" #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" -#include "h263.h" +#include "h263data.h" #include "hpeldsp.h" #include "internal.h" #include "mathops.h" @@ -616,13 +617,12 @@ static int svq1_decode_frame_header(AVCodecContext *avctx, AVFrame *frame) return 0; } -static int svq1_decode_frame(AVCodecContext *avctx, void *data, +static int svq1_decode_frame(AVCodecContext *avctx, AVFrame *cur, int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; SVQ1Context *s = avctx->priv_data; - AVFrame *cur = data; uint8_t *current; int result, i, x, y, width, height; int ret; @@ -777,7 +777,7 @@ static av_cold void svq1_static_init(void) for (int i = 0, offset = 0; i < 6; i++) { static const uint8_t sizes[2][6] = { { 14, 10, 14, 18, 16, 18 }, { 10, 10, 14, 14, 14, 16 } }; - static VLC_TYPE table[168][2]; + static VLCElem table[168]; svq1_intra_multistage[i].table = &table[offset]; svq1_intra_multistage[i].table_allocated = sizes[0][i]; offset += sizes[0][i]; @@ -843,18 +843,18 @@ static void svq1_flush(AVCodecContext *avctx) av_frame_unref(s->prev); } -const AVCodec ff_svq1_decoder = { - .name = "svq1", - .long_name = NULL_IF_CONFIG_SMALL("Sorenson Vector Quantizer 1 / Sorenson Video 1 / SVQ1"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_SVQ1, +const FFCodec ff_svq1_decoder = { + .p.name = "svq1", + .p.long_name = NULL_IF_CONFIG_SMALL("Sorenson Vector Quantizer 1 / Sorenson Video 1 / SVQ1"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_SVQ1, .priv_data_size = sizeof(SVQ1Context), .init = svq1_decode_init, .close = svq1_decode_end, - .decode = svq1_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(svq1_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .flush = svq1_flush, - .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV410P, + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV410P, AV_PIX_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/svq1enc.c b/libavcodec/svq1enc.c index 11cbd9718..3c2d59463 100644 --- a/libavcodec/svq1enc.c +++ b/libavcodec/svq1enc.c @@ -27,11 +27,13 @@ */ #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" #include "hpeldsp.h" #include "me_cmp.h" #include "mpegvideo.h" #include "h263.h" +#include "h263enc.h" #include "internal.h" #include "mpegutils.h" #include "packet_internal.h" @@ -275,7 +277,7 @@ static int svq1_encode_plane(SVQ1EncContext *s, int plane, s->m.last_picture.f->data[0] = ref_plane; s->m.linesize = s->m.last_picture.f->linesize[0] = - s->m.new_picture.f->linesize[0] = + s->m.new_picture->linesize[0] = s->m.current_picture.f->linesize[0] = stride; s->m.width = width; s->m.height = height; @@ -325,7 +327,7 @@ static int svq1_encode_plane(SVQ1EncContext *s, int plane, s->m.me.dia_size = s->avctx->dia_size; s->m.first_slice_line = 1; for (y = 0; y < block_height; y++) { - s->m.new_picture.f->data[0] = src - y * 16 * stride; // ugly + s->m.new_picture->data[0] = src - y * 16 * stride; // ugly s->m.mb_y = y; for (i = 0; i < 16 && i + 16 * y < height; i++) { @@ -566,10 +568,11 @@ static av_cold int svq1_encode_init(AVCodecContext *avctx) return AVERROR(ENOMEM); } - if (ARCH_PPC) - ff_svq1enc_init_ppc(s); - if (ARCH_X86) - ff_svq1enc_init_x86(s); +#if ARCH_PPC + ff_svq1enc_init_ppc(s); +#elif ARCH_X86 + ff_svq1enc_init_x86(s); +#endif ff_h263_encode_init(&s->m); // mv_penalty @@ -593,12 +596,12 @@ static int svq1_encode_frame(AVCodecContext *avctx, AVPacket *pkt, } if (!s->current_picture->data[0]) { - if ((ret = ff_get_buffer(avctx, s->current_picture, 0)) < 0) { + if ((ret = ff_encode_alloc_frame(avctx, s->current_picture)) < 0) { return ret; } } if (!s->last_picture->data[0]) { - ret = ff_get_buffer(avctx, s->last_picture, 0); + ret = ff_encode_alloc_frame(avctx, s->last_picture); if (ret < 0) return ret; } @@ -674,17 +677,17 @@ static const AVClass svq1enc_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_svq1_encoder = { - .name = "svq1", - .long_name = NULL_IF_CONFIG_SMALL("Sorenson Vector Quantizer 1 / Sorenson Video 1 / SVQ1"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_SVQ1, +const FFCodec ff_svq1_encoder = { + .p.name = "svq1", + .p.long_name = NULL_IF_CONFIG_SMALL("Sorenson Vector Quantizer 1 / Sorenson Video 1 / SVQ1"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_SVQ1, .priv_data_size = sizeof(SVQ1EncContext), - .priv_class = &svq1enc_class, + .p.priv_class = &svq1enc_class, .init = svq1_encode_init, - .encode2 = svq1_encode_frame, + FF_CODEC_ENCODE_CB(svq1_encode_frame), .close = svq1_encode_end, - .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV410P, + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV410P, AV_PIX_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/svq3.c b/libavcodec/svq3.c index e329578af..f03846692 100644 --- a/libavcodec/svq3.c +++ b/libavcodec/svq3.c @@ -46,16 +46,20 @@ #include "libavutil/crc.h" #include "libavutil/mem_internal.h" +#include "codec_internal.h" #include "internal.h" #include "avcodec.h" #include "mpegutils.h" -#include "h264dec.h" #include "h264data.h" +#include "h264dsp.h" +#include "h264pred.h" +#include "h264_parse.h" #include "golomb.h" #include "hpeldsp.h" #include "mathops.h" #include "rectangle.h" #include "tpeldsp.h" +#include "videodsp.h" #if CONFIG_ZLIB #include @@ -98,7 +102,6 @@ typedef struct SVQ3Context { int has_watermark; uint32_t watermark_key; int adaptive_quant; - int next_p_frame_damaged; int h_edge_pos; int v_edge_pos; int last_frame_output; @@ -129,7 +132,6 @@ typedef struct SVQ3Context { int8_t (*intra4x4_pred_mode); unsigned int top_samples_available; - unsigned int topright_samples_available; unsigned int left_samples_available; uint8_t *edge_emu_buffer; @@ -639,15 +641,10 @@ static av_always_inline void hl_decode_mb_predict_luma(SVQ3Context *s, const int dir = s->intra4x4_pred_mode_cache[scan8[i]]; uint8_t *topright; - int nnz, tr; + int nnz; if (dir == DIAG_DOWN_LEFT_PRED || dir == VERT_LEFT_PRED) { - const int topright_avail = (s->topright_samples_available << i) & 0x8000; av_assert2(s->mb_y || linesize <= block_offset[i]); - if (!topright_avail) { - tr = ptr[3 - linesize] * 0x01010101u; - topright = (uint8_t *)&tr; - } else - topright = ptr + 4 - linesize; + topright = ptr + 4 - linesize; } else topright = NULL; @@ -722,7 +719,6 @@ static int svq3_decode_mb(SVQ3Context *s, unsigned int mb_type) s->top_samples_available = (s->mb_y == 0) ? 0x33FF : 0xFFFF; s->left_samples_available = (s->mb_x == 0) ? 0x5F5F : 0xFFFF; - s->topright_samples_available = 0xFFFF; if (mb_type == 0) { /* SKIP */ if (s->pict_type == AV_PICTURE_TYPE_P || @@ -1375,7 +1371,7 @@ fail: return ret; } -static int svq3_decode_frame(AVCodecContext *avctx, void *data, +static int svq3_decode_frame(AVCodecContext *avctx, AVFrame *rframe, int *got_frame, AVPacket *avpkt) { SVQ3Context *s = avctx->priv_data; @@ -1386,7 +1382,7 @@ static int svq3_decode_frame(AVCodecContext *avctx, void *data, /* special case for last picture */ if (buf_size == 0) { if (s->next_pic->f->data[0] && !s->low_delay && !s->last_frame_output) { - ret = av_frame_ref(data, s->next_pic->f); + ret = av_frame_ref(rframe, s->next_pic->f); if (ret < 0) return ret; s->last_frame_output = 1; @@ -1470,13 +1466,6 @@ static int svq3_decode_frame(AVCodecContext *avctx, void *data, avctx->skip_frame >= AVDISCARD_ALL) return 0; - if (s->next_p_frame_damaged) { - if (s->pict_type == AV_PICTURE_TYPE_B) - return 0; - else - s->next_p_frame_damaged = 0; - } - if (s->pict_type == AV_PICTURE_TYPE_B) { s->frame_num_offset = s->slice_num - s->prev_frame_num; @@ -1564,9 +1553,9 @@ static int svq3_decode_frame(AVCodecContext *avctx, void *data, } if (s->pict_type == AV_PICTURE_TYPE_B || s->low_delay) - ret = av_frame_ref(data, s->cur_pic->f); + ret = av_frame_ref(rframe, s->cur_pic->f); else if (s->last_pic->f->data[0]) - ret = av_frame_ref(data, s->last_pic->f); + ret = av_frame_ref(rframe, s->last_pic->f); if (ret < 0) return ret; @@ -1599,19 +1588,19 @@ static av_cold int svq3_decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_svq3_decoder = { - .name = "svq3", - .long_name = NULL_IF_CONFIG_SMALL("Sorenson Vector Quantizer 3 / Sorenson Video 3 / SVQ3"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_SVQ3, +const FFCodec ff_svq3_decoder = { + .p.name = "svq3", + .p.long_name = NULL_IF_CONFIG_SMALL("Sorenson Vector Quantizer 3 / Sorenson Video 3 / SVQ3"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_SVQ3, .priv_data_size = sizeof(SVQ3Context), .init = svq3_decode_init, .close = svq3_decode_end, - .decode = svq3_decode_frame, - .capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | + FF_CODEC_DECODE_CB(svq3_decode_frame), + .p.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, - .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUVJ420P, + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_NONE}, - .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/synth_filter.c b/libavcodec/synth_filter.c index 1c5dab5c5..f30cf360d 100644 --- a/libavcodec/synth_filter.c +++ b/libavcodec/synth_filter.c @@ -175,10 +175,11 @@ av_cold void ff_synth_filter_init(SynthFilterContext *c) c->synth_filter_fixed = synth_filter_fixed; c->synth_filter_fixed_64 = synth_filter_fixed_64; - if (ARCH_AARCH64) - ff_synth_filter_init_aarch64(c); - if (ARCH_ARM) - ff_synth_filter_init_arm(c); - if (ARCH_X86) - ff_synth_filter_init_x86(c); +#if ARCH_AARCH64 + ff_synth_filter_init_aarch64(c); +#elif ARCH_ARM + ff_synth_filter_init_arm(c); +#elif ARCH_X86 + ff_synth_filter_init_x86(c); +#endif } diff --git a/libavcodec/tableprint_vlc.h b/libavcodec/tableprint_vlc.h index 0cbd7a9d2..b97c1f9cf 100644 --- a/libavcodec/tableprint_vlc.h +++ b/libavcodec/tableprint_vlc.h @@ -23,7 +23,6 @@ #ifndef AVCODEC_TABLEPRINT_VLC_H #define AVCODEC_TABLEPRINT_VLC_H -#define FFMPEG_CONFIG_H #define AVUTIL_LOG_H #define av_log(a, ...) while(0) #define ff_dlog(a, ...) while(0) @@ -36,28 +35,26 @@ #define AVUTIL_INTERNAL_H #define avpriv_request_sample(...) #include "tableprint.h" -#include "get_bits.h" -#include "mathtables.c" +#include "vlc.h" #include "libavutil/reverse.c" -#include "bitstream.c" +#include "vlc.c" -#define REPLACE_DEFINE2(type) write_##type##_array -#define REPLACE_DEFINE(type) REPLACE_DEFINE2(type) -static void write_VLC_TYPE_array(const VLC_TYPE *p, int s) { - REPLACE_DEFINE(VLC_TYPE)(p, s); -} +// The following will have to be modified if VLCBaseType changes. +WRITE_1D_FUNC_ARGV(VLCElem, 3, "{ .sym =%5" PRId16 ", .len =%2"PRIi16 " }", + data[i].sym, data[i].len) -WRITE_2D_FUNC(VLC_TYPE) - -static void write_vlc_type(const VLC *vlc, VLC_TYPE (*base_table)[2], const char *base_table_name) +static void write_vlc_type(const VLC *vlc, const VLCElem *base_table, const char *base_table_name) { printf(" .bits = %i,\n", vlc->bits); // Unfortunately need to cast away const currently - printf(" .table = (VLC_TYPE (*)[2])(%s + 0x%x),\n", base_table_name, (int)(vlc->table - base_table)); + printf(" .table = (VLCElem *)(%s + 0x%x),\n", base_table_name, (int)(vlc->table - base_table)); printf(" .table_size = 0x%x,\n", vlc->table_size); printf(" .table_allocated = 0x%x,\n", vlc->table_allocated); } +#define WRITE_VLC_TABLE(prefix, name) \ + WRITE_ARRAY(prefix, VLCElem, name) + #define WRITE_VLC_TYPE(prefix, name, base_table) \ do { \ printf(prefix" VLC "#name" = {\n"); \ diff --git a/libavcodec/tak.h b/libavcodec/tak.h index dc45a8c07..606911897 100644 --- a/libavcodec/tak.h +++ b/libavcodec/tak.h @@ -44,7 +44,6 @@ #define TAK_LAST_FRAME_SIZE_BITS 24 #define TAK_ENCODER_CODEC_BITS 6 #define TAK_ENCODER_PROFILE_BITS 4 -#define TAK_ENCODER_VERSION_BITS 24 #define TAK_SAMPLE_RATE_MIN 6000 #define TAK_CHANNELS_MIN 1 #define TAK_BPS_MIN 8 diff --git a/libavcodec/takdec.c b/libavcodec/takdec.c index 926dbf611..47978fcd4 100644 --- a/libavcodec/takdec.c +++ b/libavcodec/takdec.c @@ -33,7 +33,7 @@ #include "audiodsp.h" #include "thread.h" #include "avcodec.h" -#include "internal.h" +#include "codec_internal.h" #include "unary.h" #include "tak.h" #include "takdsp.h" @@ -674,12 +674,10 @@ static int decorrelate(TAKDecContext *s, int c1, int c2, int length) return 0; } -static int tak_decode_frame(AVCodecContext *avctx, void *data, +static int tak_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *pkt) { TAKDecContext *s = avctx->priv_data; - AVFrame *frame = data; - ThreadFrame tframe = { .f = data }; GetBitContext *gb = &s->gb; int chan, i, ret, hsize; @@ -734,20 +732,25 @@ static int tak_decode_frame(AVCodecContext *avctx, void *data, avctx->sample_rate = s->ti.sample_rate; set_sample_rate_params(avctx); } - if (s->ti.ch_layout) - avctx->channel_layout = s->ti.ch_layout; - avctx->channels = s->ti.channels; + + av_channel_layout_uninit(&avctx->ch_layout); + if (s->ti.ch_layout) { + av_channel_layout_from_mask(&avctx->ch_layout, s->ti.ch_layout); + } else { + avctx->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + avctx->ch_layout.nb_channels = s->ti.channels; + } s->nb_samples = s->ti.last_frame_samples ? s->ti.last_frame_samples : s->ti.frame_samples; frame->nb_samples = s->nb_samples; - if ((ret = ff_thread_get_buffer(avctx, &tframe, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, frame, 0)) < 0) return ret; ff_thread_finish_setup(avctx); if (avctx->bits_per_raw_sample <= 16) { - int buf_size = av_samples_get_buffer_size(NULL, avctx->channels, + int buf_size = av_samples_get_buffer_size(NULL, avctx->ch_layout.nb_channels, s->nb_samples, AV_SAMPLE_FMT_S32P, 0); if (buf_size < 0) @@ -756,28 +759,28 @@ static int tak_decode_frame(AVCodecContext *avctx, void *data, if (!s->decode_buffer) return AVERROR(ENOMEM); ret = av_samples_fill_arrays((uint8_t **)s->decoded, NULL, - s->decode_buffer, avctx->channels, + s->decode_buffer, avctx->ch_layout.nb_channels, s->nb_samples, AV_SAMPLE_FMT_S32P, 0); if (ret < 0) return ret; } else { - for (chan = 0; chan < avctx->channels; chan++) + for (chan = 0; chan < avctx->ch_layout.nb_channels; chan++) s->decoded[chan] = (int32_t *)frame->extended_data[chan]; } if (s->nb_samples < 16) { - for (chan = 0; chan < avctx->channels; chan++) { + for (chan = 0; chan < avctx->ch_layout.nb_channels; chan++) { int32_t *decoded = s->decoded[chan]; for (i = 0; i < s->nb_samples; i++) decoded[i] = get_sbits(gb, avctx->bits_per_raw_sample); } } else { if (s->ti.codec == TAK_CODEC_MONO_STEREO) { - for (chan = 0; chan < avctx->channels; chan++) + for (chan = 0; chan < avctx->ch_layout.nb_channels; chan++) if (ret = decode_channel(s, chan)) return ret; - if (avctx->channels == 2) { + if (avctx->ch_layout.nb_channels == 2) { s->nb_subframes = get_bits(gb, 1) + 1; if (s->nb_subframes > 1) { s->subframe_len[1] = get_bits(gb, 6); @@ -792,13 +795,13 @@ static int tak_decode_frame(AVCodecContext *avctx, void *data, int ch_mask = 0; chan = get_bits(gb, 4) + 1; - if (chan > avctx->channels) + if (chan > avctx->ch_layout.nb_channels) return AVERROR_INVALIDDATA; for (i = 0; i < chan; i++) { int nbit = get_bits(gb, 4); - if (nbit >= avctx->channels) + if (nbit >= avctx->ch_layout.nb_channels) return AVERROR_INVALIDDATA; if (ch_mask & 1 << nbit) @@ -808,10 +811,10 @@ static int tak_decode_frame(AVCodecContext *avctx, void *data, if (s->mcdparams[i].present) { s->mcdparams[i].index = get_bits(gb, 2); s->mcdparams[i].chan2 = get_bits(gb, 4); - if (s->mcdparams[i].chan2 >= avctx->channels) { + if (s->mcdparams[i].chan2 >= avctx->ch_layout.nb_channels) { av_log(avctx, AV_LOG_ERROR, "invalid channel 2 (%d) for %d channel(s)\n", - s->mcdparams[i].chan2, avctx->channels); + s->mcdparams[i].chan2, avctx->ch_layout.nb_channels); return AVERROR_INVALIDDATA; } if (s->mcdparams[i].index == 1) { @@ -829,7 +832,7 @@ static int tak_decode_frame(AVCodecContext *avctx, void *data, ch_mask |= 1 << nbit; } } else { - chan = avctx->channels; + chan = avctx->ch_layout.nb_channels; for (i = 0; i < chan; i++) { s->mcdparams[i].present = 0; s->mcdparams[i].chan1 = i; @@ -855,7 +858,7 @@ static int tak_decode_frame(AVCodecContext *avctx, void *data, } } - for (chan = 0; chan < avctx->channels; chan++) { + for (chan = 0; chan < avctx->ch_layout.nb_channels; chan++) { int32_t *decoded = s->decoded[chan]; if (s->lpc_mode[chan]) @@ -886,7 +889,7 @@ static int tak_decode_frame(AVCodecContext *avctx, void *data, /* convert to output buffer */ switch (avctx->sample_fmt) { case AV_SAMPLE_FMT_U8P: - for (chan = 0; chan < avctx->channels; chan++) { + for (chan = 0; chan < avctx->ch_layout.nb_channels; chan++) { uint8_t *samples = (uint8_t *)frame->extended_data[chan]; int32_t *decoded = s->decoded[chan]; for (i = 0; i < s->nb_samples; i++) @@ -894,7 +897,7 @@ static int tak_decode_frame(AVCodecContext *avctx, void *data, } break; case AV_SAMPLE_FMT_S16P: - for (chan = 0; chan < avctx->channels; chan++) { + for (chan = 0; chan < avctx->ch_layout.nb_channels; chan++) { int16_t *samples = (int16_t *)frame->extended_data[chan]; int32_t *decoded = s->decoded[chan]; for (i = 0; i < s->nb_samples; i++) @@ -902,7 +905,7 @@ static int tak_decode_frame(AVCodecContext *avctx, void *data, } break; case AV_SAMPLE_FMT_S32P: - for (chan = 0; chan < avctx->channels; chan++) { + for (chan = 0; chan < avctx->ch_layout.nb_channels; chan++) { int32_t *samples = (int32_t *)frame->extended_data[chan]; for (i = 0; i < s->nb_samples; i++) samples[i] *= 1U << 8; @@ -938,18 +941,18 @@ static av_cold int tak_decode_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_tak_decoder = { - .name = "tak", - .long_name = NULL_IF_CONFIG_SMALL("TAK (Tom's lossless Audio Kompressor)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_TAK, +const FFCodec ff_tak_decoder = { + .p.name = "tak", + .p.long_name = NULL_IF_CONFIG_SMALL("TAK (Tom's lossless Audio Kompressor)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_TAK, .priv_data_size = sizeof(TAKDecContext), .init = tak_decode_init, .close = tak_decode_close, - .decode = tak_decode_frame, + FF_CODEC_DECODE_CB(tak_decode_frame), .update_thread_context = ONLY_IF_THREADS_ENABLED(update_thread_context), - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_CHANNEL_CONF, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_U8P, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_CHANNEL_CONF, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_U8P, AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_NONE }, diff --git a/libavcodec/takdsp.c b/libavcodec/takdsp.c index a8f9dba34..881d7be5f 100644 --- a/libavcodec/takdsp.c +++ b/libavcodec/takdsp.c @@ -77,6 +77,7 @@ av_cold void ff_takdsp_init(TAKDSPContext *c) c->decorrelate_sm = decorrelate_sm; c->decorrelate_sf = decorrelate_sf; - if (ARCH_X86) - ff_takdsp_init_x86(c); +#if ARCH_X86 + ff_takdsp_init_x86(c); +#endif } diff --git a/libavcodec/targa.c b/libavcodec/targa.c index b0048621d..833576c6b 100644 --- a/libavcodec/targa.c +++ b/libavcodec/targa.c @@ -23,6 +23,7 @@ #include "libavutil/imgutils.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" #include "targa.h" @@ -106,12 +107,10 @@ static int targa_decode_rle(AVCodecContext *avctx, TargaContext *s, return 0; } -static int decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *p, + int *got_frame, AVPacket *avpkt) { TargaContext * const s = avctx->priv_data; - AVFrame * const p = data; uint8_t *dst; int stride; int idlen, pal, compr, y, w, h, bpp, flags, ret; @@ -306,12 +305,12 @@ static int decode_frame(AVCodecContext *avctx, return avpkt->size; } -const AVCodec ff_targa_decoder = { - .name = "targa", - .long_name = NULL_IF_CONFIG_SMALL("Truevision Targa image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_TARGA, +const FFCodec ff_targa_decoder = { + .p.name = "targa", + .p.long_name = NULL_IF_CONFIG_SMALL("Truevision Targa image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_TARGA, + .p.capabilities = AV_CODEC_CAP_DR1, .priv_data_size = sizeof(TargaContext), - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), }; diff --git a/libavcodec/targa_y216dec.c b/libavcodec/targa_y216dec.c index 93b5148a1..bf33dc8a6 100644 --- a/libavcodec/targa_y216dec.c +++ b/libavcodec/targa_y216dec.c @@ -20,6 +20,7 @@ */ #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" static av_cold int y216_decode_init(AVCodecContext *avctx) @@ -30,10 +31,9 @@ static av_cold int y216_decode_init(AVCodecContext *avctx) return 0; } -static int y216_decode_frame(AVCodecContext *avctx, void *data, +static int y216_decode_frame(AVCodecContext *avctx, AVFrame *pic, int *got_frame, AVPacket *avpkt) { - AVFrame *pic = data; const uint16_t *src = (uint16_t *)avpkt->data; uint16_t *y, *u, *v; int aligned_width = FFALIGN(avctx->width, 4); @@ -73,13 +73,13 @@ static int y216_decode_frame(AVCodecContext *avctx, void *data, return avpkt->size; } -const AVCodec ff_targa_y216_decoder = { - .name = "targa_y216", - .long_name = NULL_IF_CONFIG_SMALL("Pinnacle TARGA CineWave YUV16"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_TARGA_Y216, +const FFCodec ff_targa_y216_decoder = { + .p.name = "targa_y216", + .p.long_name = NULL_IF_CONFIG_SMALL("Pinnacle TARGA CineWave YUV16"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_TARGA_Y216, .init = y216_decode_init, - .decode = y216_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(y216_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/targaenc.c b/libavcodec/targaenc.c index cf1733bb2..84e208686 100644 --- a/libavcodec/targaenc.c +++ b/libavcodec/targaenc.c @@ -27,8 +27,8 @@ #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "rle.h" #include "targa.h" @@ -202,16 +202,16 @@ static const AVClass targa_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_targa_encoder = { - .name = "targa", - .long_name = NULL_IF_CONFIG_SMALL("Truevision Targa image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_TARGA, +const FFCodec ff_targa_encoder = { + .p.name = "targa", + .p.long_name = NULL_IF_CONFIG_SMALL("Truevision Targa image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_TARGA, .priv_data_size = sizeof(TargaContext), - .priv_class = &targa_class, + .p.priv_class = &targa_class, .init = targa_encode_init, - .encode2 = targa_encode_frame, - .pix_fmts = (const enum AVPixelFormat[]){ + FF_CODEC_ENCODE_CB(targa_encode_frame), + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_BGR24, AV_PIX_FMT_BGRA, AV_PIX_FMT_RGB555LE, AV_PIX_FMT_GRAY8, AV_PIX_FMT_PAL8, AV_PIX_FMT_NONE }, diff --git a/libavcodec/tdsc.c b/libavcodec/tdsc.c index 79bdc422e..0cf17d75d 100644 --- a/libavcodec/tdsc.c +++ b/libavcodec/tdsc.c @@ -40,6 +40,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" #define BITMAPINFOHEADER_SIZE 0x28 @@ -521,11 +522,10 @@ static int tdsc_parse_dtsm(AVCodecContext *avctx) return 0; } -static int tdsc_decode_frame(AVCodecContext *avctx, void *data, +static int tdsc_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt) { TDSCContext *ctx = avctx->priv_data; - AVFrame *frame = data; int ret, tag_header, keyframe = 0; uLongf dlen; @@ -621,16 +621,16 @@ static int tdsc_decode_frame(AVCodecContext *avctx, void *data, return avpkt->size; } -const AVCodec ff_tdsc_decoder = { - .name = "tdsc", - .long_name = NULL_IF_CONFIG_SMALL("TDSC"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_TDSC, +const FFCodec ff_tdsc_decoder = { + .p.name = "tdsc", + .p.long_name = NULL_IF_CONFIG_SMALL("TDSC"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_TDSC, .init = tdsc_init, - .decode = tdsc_decode_frame, + FF_CODEC_DECODE_CB(tdsc_decode_frame), .close = tdsc_close, .priv_data_size = sizeof(TDSCContext), - .capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/tests/avcodec.c b/libavcodec/tests/avcodec.c index 5d0ff9432..08b5fbede 100644 --- a/libavcodec/tests/avcodec.c +++ b/libavcodec/tests/avcodec.c @@ -19,6 +19,7 @@ #include "libavutil/opt.h" #include "libavcodec/codec.h" #include "libavcodec/codec_desc.h" +#include "libavcodec/codec_internal.h" #include "libavcodec/internal.h" static const char *get_type_string(enum AVMediaType type) @@ -36,14 +37,14 @@ do { \ #define ERR(msg) ERR_INTERNAL(msg, ) #define ERR_EXT(msg, ...) ERR_INTERNAL(msg, , __VA_ARGS__) -static int priv_data_size_wrong(const AVCodec *codec) +static int priv_data_size_wrong(const FFCodec *codec) { if (codec->priv_data_size < 0 || - codec->priv_class && codec->priv_data_size < sizeof(AVClass*)) + codec->p.priv_class && codec->priv_data_size < sizeof(AVClass*)) return 1; - if (!codec->priv_class || !codec->priv_class->option) + if (!codec->p.priv_class || !codec->p.priv_class->option) return 0; - for (const AVOption *opt = codec->priv_class->option; opt->name; opt++) { + for (const AVOption *opt = codec->p.priv_class->option; opt->name; opt++) { if (opt->offset >= codec->priv_data_size || opt->type == AV_OPT_TYPE_CONST && opt->offset != 0 || opt->type != AV_OPT_TYPE_CONST && (opt->offset < sizeof(AVClass*) || opt->offset < 0)) { @@ -61,8 +62,9 @@ int main(void){ int ret = 0; while (codec = av_codec_iterate(&iter)) { + const FFCodec *const codec2 = ffcodec(codec); const AVCodecDescriptor *desc; - int is_decoder, is_encoder; + int is_decoder = 0, is_encoder = 0; if (!codec->name) { AV_LOG("Codec for format %s has no name\n", @@ -76,7 +78,7 @@ int main(void){ ERR_EXT("Codec %s has unsupported type %s\n", get_type_string(codec->type)); if (codec->type != AVMEDIA_TYPE_AUDIO) { - if (codec->channel_layouts || codec->sample_fmts || + if (codec->ch_layouts || codec->sample_fmts || codec->supported_samplerates) ERR("Non-audio codec %s has audio-only fields set\n"); if (codec->capabilities & (AV_CODEC_CAP_SMALL_LAST_FRAME | @@ -87,31 +89,52 @@ int main(void){ if (codec->type != AVMEDIA_TYPE_VIDEO) { if (codec->pix_fmts || codec->supported_framerates) ERR("Non-video codec %s has video-only fields set\n"); - if (codec->caps_internal & FF_CODEC_CAP_EXPORTS_CROPPING) + if (codec2->caps_internal & FF_CODEC_CAP_EXPORTS_CROPPING) ERR("Non-video codec %s exports cropping\n"); } - if (codec->caps_internal & FF_CODEC_CAP_SLICE_THREAD_HAS_MF && + if (codec2->caps_internal & FF_CODEC_CAP_SLICE_THREAD_HAS_MF && !(codec->capabilities & AV_CODEC_CAP_SLICE_THREADS)) ERR("Codec %s wants mainfunction despite not being " "slice-threading capable"); - if (codec->caps_internal & FF_CODEC_CAP_AUTO_THREADS && + if (codec2->caps_internal & FF_CODEC_CAP_AUTO_THREADS && !(codec->capabilities & (AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_OTHER_THREADS))) ERR("Codec %s has private-only threading support\n"); - is_decoder = av_codec_is_decoder(codec); - is_encoder = av_codec_is_encoder(codec); - if (!!is_decoder + !!is_encoder != 1) { - ERR("Codec %s is decoder and encoder or neither.\n"); + switch (codec2->cb_type) { + case FF_CODEC_CB_TYPE_DECODE: + case FF_CODEC_CB_TYPE_DECODE_SUB: + case FF_CODEC_CB_TYPE_RECEIVE_FRAME: + is_decoder = 1; + break; + case FF_CODEC_CB_TYPE_ENCODE: + case FF_CODEC_CB_TYPE_ENCODE_SUB: + case FF_CODEC_CB_TYPE_RECEIVE_PACKET: + is_encoder = 1; + break; + default: + ERR("Codec %s has unknown cb_type\n"); continue; } + if (is_decoder != av_codec_is_decoder(codec) || + is_encoder != av_codec_is_encoder(codec)) { + ERR("Codec %s cb_type and av_codec_is_(de|en)coder inconsistent.\n"); + continue; + } +#define CHECK(TYPE, type) (codec2->cb_type == FF_CODEC_CB_TYPE_ ## TYPE && !codec2->cb.type) + if (CHECK(DECODE, decode) || CHECK(DECODE_SUB, decode_sub) || + CHECK(RECEIVE_PACKET, receive_packet) || + CHECK(ENCODE, encode) || CHECK(ENCODE_SUB, encode_sub) || + CHECK(RECEIVE_FRAME, receive_frame)) { + ERR_EXT("Codec %s does not implement its %s callback.\n", + is_decoder ? "decoding" : "encoding"); + } +#undef CHECK if (is_encoder) { - if (codec->type == AVMEDIA_TYPE_SUBTITLE ^ !!codec->encode_sub) + if ((codec->type == AVMEDIA_TYPE_SUBTITLE) != (codec2->cb_type == FF_CODEC_CB_TYPE_ENCODE_SUB)) ERR("Encoder %s is both subtitle encoder and not subtitle encoder."); - if (!!codec->encode_sub + !!codec->encode2 + !!codec->receive_packet != 1) - ERR("Encoder %s does not implement exactly one encode API.\n"); - if (codec->update_thread_context || codec->update_thread_context_for_user || codec->bsfs) + if (codec2->update_thread_context || codec2->update_thread_context_for_user || codec2->bsfs) ERR("Encoder %s has decoder-only thread functions or bsf.\n"); if (codec->type == AVMEDIA_TYPE_AUDIO) { if (!codec->sample_fmts) { @@ -119,7 +142,7 @@ int main(void){ ret = 1; } } - if (codec->caps_internal & (FF_CODEC_CAP_ALLOCATE_PROGRESS | + if (codec2->caps_internal & (FF_CODEC_CAP_ALLOCATE_PROGRESS | FF_CODEC_CAP_SETS_PKT_DTS | FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM | FF_CODEC_CAP_EXPORTS_CROPPING | @@ -133,26 +156,24 @@ int main(void){ codec->capabilities & AV_CODEC_CAP_ENCODER_FLUSH) ERR("Frame-threaded encoder %s claims to support flushing\n"); } else { - if (codec->type == AVMEDIA_TYPE_SUBTITLE && !codec->decode) - ERR("Subtitle decoder %s does not implement decode callback\n"); - if (codec->type == AVMEDIA_TYPE_SUBTITLE && codec->bsfs) + if ((codec->type == AVMEDIA_TYPE_SUBTITLE) != (codec2->cb_type == FF_CODEC_CB_TYPE_DECODE_SUB)) + ERR("Subtitle decoder %s does not implement decode_sub callback\n"); + if (codec->type == AVMEDIA_TYPE_SUBTITLE && codec2->bsfs) ERR("Automatic bitstream filtering unsupported for subtitles; " "yet decoder %s has it set\n"); - if (!!codec->decode + !!codec->receive_frame != 1) - ERR("Decoder %s does not implement exactly one decode API.\n"); if (codec->capabilities & (AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_VARIABLE_FRAME_SIZE | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE | AV_CODEC_CAP_ENCODER_FLUSH)) ERR("Decoder %s has encoder-only capabilities\n"); - if (codec->caps_internal & FF_CODEC_CAP_ALLOCATE_PROGRESS && + if (codec2->caps_internal & FF_CODEC_CAP_ALLOCATE_PROGRESS && !(codec->capabilities & AV_CODEC_CAP_FRAME_THREADS)) ERR("Decoder %s wants allocated progress without supporting" "frame threads\n"); } - if (priv_data_size_wrong(codec)) + if (priv_data_size_wrong(codec2)) ERR_EXT("Private context of codec %s is impossibly-sized (size %d).", - codec->priv_data_size); + codec2->priv_data_size); if (!(desc = avcodec_descriptor_get(codec->id))) { ERR("Codec %s lacks a corresponding descriptor\n"); } else if (desc->type != codec->type) diff --git a/libavcodec/tests/cabac.c b/libavcodec/tests/cabac.c index b84a96ce8..d9f98c68e 100644 --- a/libavcodec/tests/cabac.c +++ b/libavcodec/tests/cabac.c @@ -18,12 +18,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavcodec/cabac_functions.h" #include "libavcodec/cabac.c" #define SIZE 10240 #include "libavutil/lfg.h" -#include "libavcodec/avcodec.h" #include "libavcodec/put_bits.h" typedef struct CABACTestContext { diff --git a/libavcodec/tests/dct.c b/libavcodec/tests/dct.c index eab39e946..c847af2f1 100644 --- a/libavcodec/tests/dct.c +++ b/libavcodec/tests/dct.c @@ -26,6 +26,7 @@ */ #include "config.h" +#include "config_components.h" #include #include #include diff --git a/libavcodec/tests/fft.c b/libavcodec/tests/fft.c index 9a5e5bd1c..cc951b0dd 100644 --- a/libavcodec/tests/fft.c +++ b/libavcodec/tests/fft.c @@ -38,6 +38,7 @@ #include #include "libavutil/cpu.h" +#include "libavutil/error.h" #include "libavutil/lfg.h" #include "libavutil/log.h" #include "libavutil/mathematics.h" diff --git a/libavcodec/tests/golomb.c b/libavcodec/tests/golomb.c index 85b8a9390..061cc013c 100644 --- a/libavcodec/tests/golomb.c +++ b/libavcodec/tests/golomb.c @@ -27,6 +27,7 @@ #include "libavcodec/get_bits.h" #include "libavcodec/golomb.h" #include "libavcodec/put_bits.h" +#include "libavcodec/put_golomb.h" #define COUNT 8191 #define SIZE (COUNT * 4) diff --git a/libavcodec/tests/jpeg2000dwt.c b/libavcodec/tests/jpeg2000dwt.c index 80b33bee7..0e5a6ed94 100644 --- a/libavcodec/tests/jpeg2000dwt.c +++ b/libavcodec/tests/jpeg2000dwt.c @@ -20,6 +20,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include +#include + +#include "libavutil/common.h" + #include "libavcodec/jpeg2000dwt.c" #include "libavutil/lfg.h" diff --git a/libavcodec/tests/rangecoder.c b/libavcodec/tests/rangecoder.c index ca96e13c9..fd858535a 100644 --- a/libavcodec/tests/rangecoder.c +++ b/libavcodec/tests/rangecoder.c @@ -19,6 +19,7 @@ #include #include +#include "libavutil/error.h" #include "libavutil/lfg.h" #include "libavutil/log.h" diff --git a/libavcodec/tests/snowenc.c b/libavcodec/tests/snowenc.c index 07af1f2cf..e423ab054 100644 --- a/libavcodec/tests/snowenc.c +++ b/libavcodec/tests/snowenc.c @@ -114,16 +114,6 @@ int main(void){ } printf("};\n"); { - int level=2; - int w= width >> (s.spatial_decomposition_count-level); - //int h= height >> (s.spatial_decomposition_count-level); - int stride= width << (s.spatial_decomposition_count-level); - DWTELEM *buf= buffer[0]; - int64_t error=0; - - buf+=w; - buf+=stride>>1; - memset(buffer[0], 0, sizeof(int)*width*height); for(y=0; ydata; TextContext *text = avctx->priv_data; @@ -79,15 +80,15 @@ static const AVClass textsub_decoder_class = { }; #if CONFIG_TEXT_DECODER -const AVCodec ff_text_decoder = { - .name = "text", - .long_name = NULL_IF_CONFIG_SMALL("Raw text subtitle"), +const FFCodec ff_text_decoder = { + .p.name = "text", + .p.long_name = NULL_IF_CONFIG_SMALL("Raw text subtitle"), .priv_data_size = sizeof(TextContext), - .type = AVMEDIA_TYPE_SUBTITLE, - .id = AV_CODEC_ID_TEXT, - .decode = text_decode_frame, + .p.type = AVMEDIA_TYPE_SUBTITLE, + .p.id = AV_CODEC_ID_TEXT, + FF_CODEC_DECODE_SUB_CB(text_decode_frame), .init = ff_ass_subtitle_header_default, - .priv_class = &textsub_decoder_class, + .p.priv_class = &textsub_decoder_class, .flush = text_flush, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; @@ -103,60 +104,60 @@ static int linebreak_init(AVCodecContext *avctx) } #if CONFIG_VPLAYER_DECODER -const AVCodec ff_vplayer_decoder = { - .name = "vplayer", - .long_name = NULL_IF_CONFIG_SMALL("VPlayer subtitle"), +const FFCodec ff_vplayer_decoder = { + .p.name = "vplayer", + .p.long_name = NULL_IF_CONFIG_SMALL("VPlayer subtitle"), .priv_data_size = sizeof(TextContext), - .type = AVMEDIA_TYPE_SUBTITLE, - .id = AV_CODEC_ID_VPLAYER, - .decode = text_decode_frame, + .p.type = AVMEDIA_TYPE_SUBTITLE, + .p.id = AV_CODEC_ID_VPLAYER, + FF_CODEC_DECODE_SUB_CB(text_decode_frame), .init = linebreak_init, - .priv_class = &textsub_decoder_class, + .p.priv_class = &textsub_decoder_class, .flush = text_flush, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_STL_DECODER -const AVCodec ff_stl_decoder = { - .name = "stl", - .long_name = NULL_IF_CONFIG_SMALL("Spruce subtitle format"), +const FFCodec ff_stl_decoder = { + .p.name = "stl", + .p.long_name = NULL_IF_CONFIG_SMALL("Spruce subtitle format"), .priv_data_size = sizeof(TextContext), - .type = AVMEDIA_TYPE_SUBTITLE, - .id = AV_CODEC_ID_STL, - .decode = text_decode_frame, + .p.type = AVMEDIA_TYPE_SUBTITLE, + .p.id = AV_CODEC_ID_STL, + FF_CODEC_DECODE_SUB_CB(text_decode_frame), .init = linebreak_init, - .priv_class = &textsub_decoder_class, + .p.priv_class = &textsub_decoder_class, .flush = text_flush, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_PJS_DECODER -const AVCodec ff_pjs_decoder = { - .name = "pjs", - .long_name = NULL_IF_CONFIG_SMALL("PJS subtitle"), +const FFCodec ff_pjs_decoder = { + .p.name = "pjs", + .p.long_name = NULL_IF_CONFIG_SMALL("PJS subtitle"), .priv_data_size = sizeof(TextContext), - .type = AVMEDIA_TYPE_SUBTITLE, - .id = AV_CODEC_ID_PJS, - .decode = text_decode_frame, + .p.type = AVMEDIA_TYPE_SUBTITLE, + .p.id = AV_CODEC_ID_PJS, + FF_CODEC_DECODE_SUB_CB(text_decode_frame), .init = linebreak_init, - .priv_class = &textsub_decoder_class, + .p.priv_class = &textsub_decoder_class, .flush = text_flush, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_SUBVIEWER1_DECODER -const AVCodec ff_subviewer1_decoder = { - .name = "subviewer1", - .long_name = NULL_IF_CONFIG_SMALL("SubViewer1 subtitle"), +const FFCodec ff_subviewer1_decoder = { + .p.name = "subviewer1", + .p.long_name = NULL_IF_CONFIG_SMALL("SubViewer1 subtitle"), .priv_data_size = sizeof(TextContext), - .type = AVMEDIA_TYPE_SUBTITLE, - .id = AV_CODEC_ID_SUBVIEWER1, - .decode = text_decode_frame, + .p.type = AVMEDIA_TYPE_SUBTITLE, + .p.id = AV_CODEC_ID_SUBVIEWER1, + FF_CODEC_DECODE_SUB_CB(text_decode_frame), .init = linebreak_init, - .priv_class = &textsub_decoder_class, + .p.priv_class = &textsub_decoder_class, .flush = text_flush, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/texturedsp.c b/libavcodec/texturedsp.c index b7dd8baa1..b8938213e 100644 --- a/libavcodec/texturedsp.c +++ b/libavcodec/texturedsp.c @@ -652,3 +652,7 @@ av_cold void ff_texturedsp_init(TextureDSPContext *c) c->rgtc2u_block = rgtc2u_block; c->dxn3dc_block = dxn3dc_block; } + +#define TEXTUREDSP_FUNC_NAME ff_texturedsp_decompress_thread +#define TEXTUREDSP_TEX_FUNC(a, b, c) tex_funct(a, b, c) +#include "texturedsp_template.c" diff --git a/libavcodec/texturedsp.h b/libavcodec/texturedsp.h index 90ceb2b6a..e15d3c2b0 100644 --- a/libavcodec/texturedsp.h +++ b/libavcodec/texturedsp.h @@ -39,6 +39,8 @@ #include #include +#include "avcodec.h" + #define TEXTURE_BLOCK_W 4 #define TEXTURE_BLOCK_H 4 @@ -60,7 +62,28 @@ typedef struct TextureDSPContext { int (*dxn3dc_block) (uint8_t *dst, ptrdiff_t stride, const uint8_t *block); } TextureDSPContext; +typedef struct TextureDSPThreadContext { + union { + const uint8_t *in; // Input frame data + uint8_t *out; // Output frame data + } frame_data; + ptrdiff_t stride; // Frame linesize + union { + const uint8_t *in; // Compressed texture for decompression + uint8_t *out; // Compressed texture of compression + } tex_data; + int tex_ratio; // Number of compressed bytes in a texture block + int raw_ratio; // Number bytes in a line of a raw block + int slice_count; // Number of slices for threaded operations + + /* Pointer to the selected compress or decompress function. */ + int (*tex_funct)(uint8_t *dst, ptrdiff_t stride, const uint8_t *block); +} TextureDSPThreadContext; + void ff_texturedsp_init(TextureDSPContext *c); void ff_texturedspenc_init(TextureDSPContext *c); +int ff_texturedsp_decompress_thread(AVCodecContext *avctx, void *arg, int slice, int thread_nb); +int ff_texturedsp_compress_thread(AVCodecContext *avctx, void *arg, int slice, int thread_nb); + #endif /* AVCODEC_TEXTUREDSP_H */ diff --git a/libavcodec/texturedsp_template.c b/libavcodec/texturedsp_template.c new file mode 100644 index 000000000..bd193aa97 --- /dev/null +++ b/libavcodec/texturedsp_template.c @@ -0,0 +1,57 @@ +/* + * Texture block compression and decompression + * Copyright (C) 2015 Vittorio Giovara + * + * 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 + * + */ + +int TEXTUREDSP_FUNC_NAME(AVCodecContext *avctx, void *arg, + int slice, int thread_nb) +{ + TextureDSPThreadContext *ctx = arg; + uint8_t *d = ctx->tex_data.out; + int w_block = avctx->coded_width / TEXTURE_BLOCK_W; + int h_block = avctx->coded_height / 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 still remainder blocks to be accounted for */ + if (slice < remainder_blocks) + end_slice++; + + for (y = start_slice; y < end_slice; y++) { + uint8_t *p = ctx->frame_data.out + y * ctx->stride * TEXTURE_BLOCK_H; + int off = y * w_block; + for (x = 0; x < w_block; x++) { + ctx->TEXTUREDSP_TEX_FUNC(p + x * ctx->raw_ratio, ctx->stride, + d + (off + x) * ctx->tex_ratio); + } + } + + return 0; +} diff --git a/libavcodec/texturedspenc.c b/libavcodec/texturedspenc.c index 3d68e0cf3..7ae28ea13 100644 --- a/libavcodec/texturedspenc.c +++ b/libavcodec/texturedspenc.c @@ -181,9 +181,9 @@ static unsigned int match_colors(const uint8_t *block, ptrdiff_t stride, int x, y, k = 0; int c0_point, half_point, c3_point; uint8_t color[16]; - static const int indexMap[8] = { - 0 << 30, 2 << 30, 0 << 30, 2 << 30, - 3 << 30, 3 << 30, 1 << 30, 1 << 30, + static const uint32_t indexMap[8] = { + 0U << 30, 2U << 30, 0U << 30, 2U << 30, + 3U << 30, 3U << 30, 1U << 30, 1U << 30, }; /* Fill color and compute direction for each component */ @@ -255,11 +255,11 @@ static void optimize_colors(const uint8_t *block, ptrdiff_t stride, muv = minv = maxv = bp[0]; for (y = 0; y < 4; y++) { - for (x = 4; x < 4; x += 4) { + for (x = 0; x < 4; x++) { muv += bp[x * 4 + y * stride]; - if (bp[x] < minv) + if (bp[x * 4 + y * stride] < minv) minv = bp[x * 4 + y * stride]; - else if (bp[x] > maxv) + else if (bp[x * 4 + y * stride] > maxv) maxv = bp[x * 4 + y * stride]; } } @@ -670,3 +670,7 @@ av_cold void ff_texturedspenc_init(TextureDSPContext *c) c->dxt5ys_block = dxt5ys_block; c->rgtc1u_alpha_block = rgtc1u_alpha_block; } + +#define TEXTUREDSP_FUNC_NAME ff_texturedsp_compress_thread +#define TEXTUREDSP_TEX_FUNC(a, b, c) tex_funct(c, b, a) +#include "texturedsp_template.c" diff --git a/libavcodec/thread.h b/libavcodec/thread.h index d7d2ddd8f..92cbd927f 100644 --- a/libavcodec/thread.h +++ b/libavcodec/thread.h @@ -31,14 +31,6 @@ #include "avcodec.h" -typedef struct ThreadFrame { - AVFrame *f; - AVCodecContext *owner[2]; - // progress->data is an array of 2 ints holding progress for top/bottom - // fields - AVBufferRef *progress; -} ThreadFrame; - /** * Wait for decoding threads to finish and reset internal state. * Called by avcodec_flush_buffers(). @@ -52,10 +44,10 @@ void ff_thread_flush(AVCodecContext *avctx); * Returns the next available frame in picture. *got_picture_ptr * will be 0 if none is available. * The return value on success is the size of the consumed packet for - * compatibility with AVCodec.decode. This means the decoder + * compatibility with FFCodec.decode. This means the decoder * has to consume the full packet. * - * Parameters are the same as AVCodec.decode. + * Parameters are the same as FFCodec.decode. */ int ff_thread_decode_frame(AVCodecContext *avctx, AVFrame *picture, int *got_picture_ptr, AVPacket *avpkt); @@ -70,32 +62,6 @@ int ff_thread_decode_frame(AVCodecContext *avctx, AVFrame *picture, */ void ff_thread_finish_setup(AVCodecContext *avctx); -/** - * Notify later decoding threads when part of their reference picture is ready. - * Call this when some part of the picture is finished decoding. - * Later calls with lower values of progress have no effect. - * - * @param f The picture being decoded. - * @param progress Value, in arbitrary units, of how much of the picture has decoded. - * @param field The field being decoded, for field-picture codecs. - * 0 for top field or frame pictures, 1 for bottom field. - */ -void ff_thread_report_progress(ThreadFrame *f, int progress, int field); - -/** - * Wait for earlier decoding threads to finish reference pictures. - * Call this before accessing some part of a picture, with a given - * value for progress, and it will return after the responsible decoding - * thread calls ff_thread_report_progress() with the same or - * higher value for progress. - * - * @param f The picture being referenced. - * @param progress Value, in arbitrary units, to wait for. - * @param field The field being referenced, for field-picture codecs. - * 0 for top field or frame pictures, 1 for bottom field. - */ -void ff_thread_await_progress(ThreadFrame *f, int progress, int field); - #if FF_API_THREAD_SAFE_CALLBACKS /** * Wrapper around get_format() for frame-multithreaded codecs. @@ -118,7 +84,7 @@ enum AVPixelFormat ff_thread_get_format(AVCodecContext *avctx, const enum AVPixe * @param avctx The current context. * @param f The frame to write into. */ -int ff_thread_get_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags); +int ff_thread_get_buffer(AVCodecContext *avctx, AVFrame *f, int flags); /** * Wrapper around release_buffer() frame-for multithreaded codecs. @@ -131,9 +97,7 @@ int ff_thread_get_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags); * @param avctx The current context. * @param f The picture being released. */ -void ff_thread_release_buffer(AVCodecContext *avctx, ThreadFrame *f); - -int ff_thread_ref_frame(ThreadFrame *dst, const ThreadFrame *src); +void ff_thread_release_buffer(AVCodecContext *avctx, AVFrame *f); int ff_thread_init(AVCodecContext *s); int ff_slice_thread_execute_with_mainfunc(AVCodecContext *avctx, @@ -142,6 +106,7 @@ int ff_slice_thread_execute_with_mainfunc(AVCodecContext *avctx, void ff_thread_free(AVCodecContext *s); int ff_alloc_entries(AVCodecContext *avctx, int count); void ff_reset_entries(AVCodecContext *avctx); +int ff_slice_thread_init_progress(AVCodecContext *avctx); void ff_thread_report_progress2(AVCodecContext *avctx, int field, int thread, int n); void ff_thread_await_progress2(AVCodecContext *avctx, int field, int thread, int shift); diff --git a/libavcodec/threadframe.h b/libavcodec/threadframe.h new file mode 100644 index 000000000..dea4dadc6 --- /dev/null +++ b/libavcodec/threadframe.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2022 Andreas Rheinhardt + * + * 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_THREADFRAME_H +#define AVCODEC_THREADFRAME_H + +#include "libavutil/frame.h" +#include "avcodec.h" + +typedef struct ThreadFrame { + AVFrame *f; + AVCodecContext *owner[2]; + // progress->data is an array of 2 ints holding progress for top/bottom + // fields + AVBufferRef *progress; +} ThreadFrame; + +/** + * Notify later decoding threads when part of their reference picture is ready. + * Call this when some part of the picture is finished decoding. + * Later calls with lower values of progress have no effect. + * + * @param f The picture being decoded. + * @param progress Value, in arbitrary units, of how much of the picture has decoded. + * @param field The field being decoded, for field-picture codecs. + * 0 for top field or frame pictures, 1 for bottom field. + */ +void ff_thread_report_progress(ThreadFrame *f, int progress, int field); + +/** + * Wait for earlier decoding threads to finish reference pictures. + * Call this before accessing some part of a picture, with a given + * value for progress, and it will return after the responsible decoding + * thread calls ff_thread_report_progress() with the same or + * higher value for progress. + * + * @param f The picture being referenced. + * @param progress Value, in arbitrary units, to wait for. + * @param field The field being referenced, for field-picture codecs. + * 0 for top field or frame pictures, 1 for bottom field. + */ +void ff_thread_await_progress(ThreadFrame *f, int progress, int field); + +/** + * Wrapper around ff_get_buffer() for frame-multithreaded codecs. + * Call this function instead of ff_get_buffer() if you might need + * to wait for progress on this frame. + * Cannot be called after the codec has called ff_thread_finish_setup(). + * + * @param avctx The current context. + * @param f The frame to write into. + * @note: It is fine to call this with codecs that do not support + * frame threading. + */ +int ff_thread_get_ext_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags); + +/** + * Unref a ThreadFrame. + * + * This is basically a wrapper around av_frame_unref() and should + * be called instead of it. + * + * @param avctx The current context. + * @param f The picture being released. + */ +void ff_thread_release_ext_buffer(AVCodecContext *avctx, ThreadFrame *f); + +int ff_thread_ref_frame(ThreadFrame *dst, const ThreadFrame *src); + +#endif diff --git a/libavcodec/tiertexseqv.c b/libavcodec/tiertexseqv.c index 7170eb315..618275a57 100644 --- a/libavcodec/tiertexseqv.c +++ b/libavcodec/tiertexseqv.c @@ -26,6 +26,7 @@ #define BITSTREAM_READER_LE #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" @@ -229,9 +230,8 @@ static av_cold int seqvideo_decode_init(AVCodecContext *avctx) return 0; } -static int seqvideo_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int seqvideo_decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; @@ -245,7 +245,7 @@ static int seqvideo_decode_frame(AVCodecContext *avctx, if (seqvideo_decode(seq, buf, buf_size)) return AVERROR_INVALIDDATA; - if ((ret = av_frame_ref(data, seq->frame)) < 0) + if ((ret = av_frame_ref(rframe, seq->frame)) < 0) return ret; *got_frame = 1; @@ -261,15 +261,15 @@ static av_cold int seqvideo_decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_tiertexseqvideo_decoder = { - .name = "tiertexseqvideo", - .long_name = NULL_IF_CONFIG_SMALL("Tiertex Limited SEQ video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_TIERTEXSEQVIDEO, +const FFCodec ff_tiertexseqvideo_decoder = { + .p.name = "tiertexseqvideo", + .p.long_name = NULL_IF_CONFIG_SMALL("Tiertex Limited SEQ video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_TIERTEXSEQVIDEO, .priv_data_size = sizeof(SeqVideoContext), .init = seqvideo_decode_init, .close = seqvideo_decode_end, - .decode = seqvideo_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(seqvideo_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index fd85d104d..2d40626cc 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -39,8 +39,10 @@ #include "libavutil/intreadwrite.h" #include "libavutil/imgutils.h" #include "libavutil/opt.h" +#include "libavutil/reverse.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "faxcompr.h" #include "internal.h" #include "lzw.h" @@ -759,6 +761,7 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid if (s->is_bayer) { av_assert0(width == (s->bpp * s->width + 7) >> 3); } + av_assert0(!(s->is_bayer && is_yuv)); if (p->format == AV_PIX_FMT_GRAY12) { av_fast_padded_malloc(&s->yuv_line, &s->yuv_line_size, width); if (s->yuv_line == NULL) { @@ -842,6 +845,8 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid av_log(s->avctx, AV_LOG_ERROR, "More than one DNG JPEG strips unsupported\n"); return AVERROR_PATCHWELCOME; } + if (!s->is_bayer) + return AVERROR_PATCHWELCOME; if ((ret = dng_decode_jpeg(s->avctx, p, s->stripsize, 0, 0, s->width, s->height)) < 0) return ret; return 0; @@ -960,6 +965,9 @@ static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame, int pos_x = 0, pos_y = 0; int ret; + if (s->tile_width <= 0 || s->tile_length <= 0) + return AVERROR_INVALIDDATA; + has_width_leftover = (s->width % s->tile_width != 0); has_height_leftover = (s->height % s->tile_length != 0); @@ -1016,7 +1024,7 @@ static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame, return avpkt->size; } -static int init_image(TiffContext *s, ThreadFrame *frame) +static int init_image(TiffContext *s, AVFrame *frame) { int ret; int create_gray_palette = 0; @@ -1177,11 +1185,11 @@ static int init_image(TiffContext *s, ThreadFrame *frame) return ret; if (s->avctx->pix_fmt == AV_PIX_FMT_PAL8) { if (!create_gray_palette) - memcpy(frame->f->data[1], s->palette, sizeof(s->palette)); + memcpy(frame->data[1], s->palette, sizeof(s->palette)); else { /* make default grayscale pal */ int i; - uint32_t *pal = (uint32_t *)frame->f->data[1]; + uint32_t *pal = (uint32_t *)frame->data[1]; for (i = 0; i < 1<bpp; i++) pal[i] = 0xFFU << 24 | i * 255 / ((1<bpp) - 1) * 0x010101; } @@ -1241,8 +1249,8 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame) value = ff_tget(&s->gb, TIFF_LONG, s->le); value2 = ff_tget(&s->gb, TIFF_LONG, s->le); if (!value2) { - av_log(s->avctx, AV_LOG_ERROR, "Invalid denominator in rational\n"); - return AVERROR_INVALIDDATA; + av_log(s->avctx, AV_LOG_WARNING, "Invalid denominator in rational\n"); + value2 = 1; } break; @@ -1421,8 +1429,8 @@ static int tiff_decode_tag(TiffContext *s, AVFrame *frame) value = ff_tget(&s->gb, TIFF_LONG, s->le); value2 = ff_tget(&s->gb, TIFF_LONG, s->le); if (!value2) { - av_log(s->avctx, AV_LOG_ERROR, "Invalid black level denominator\n"); - return AVERROR_INVALIDDATA; + av_log(s->avctx, AV_LOG_WARNING, "Invalid black level denominator\n"); + value2 = 1; } s->black_level = value / value2; @@ -1738,12 +1746,10 @@ end: return 0; } -static int decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *p, + int *got_frame, AVPacket *avpkt) { TiffContext *const s = avctx->priv_data; - AVFrame *const p = data; - ThreadFrame frame = { .f = data }; unsigned off, last_off; int le, ret, plane, planes; int i, j, entries, stride; @@ -1894,7 +1900,7 @@ again: } /* now we have the data and may start decoding */ - if ((ret = init_image(s, &frame)) < 0) + if ((ret = init_image(s, p)) < 0) return ret; if (!s->is_tiled || has_strip_bits) { @@ -1939,7 +1945,7 @@ again: avpriv_report_missing_feature(avctx, "DNG JPG-compressed tiled non-bayer-encoded images"); return AVERROR_PATCHWELCOME; } else { - if ((ret = dng_decode_tiles(avctx, (AVFrame*)data, avpkt)) > 0) + if ((ret = dng_decode_tiles(avctx, p, avpkt)) > 0) *got_frame = 1; return ret; } @@ -2177,16 +2183,16 @@ static const AVClass tiff_decoder_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_tiff_decoder = { - .name = "tiff", - .long_name = NULL_IF_CONFIG_SMALL("TIFF image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_TIFF, +const FFCodec ff_tiff_decoder = { + .p.name = "tiff", + .p.long_name = NULL_IF_CONFIG_SMALL("TIFF image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_TIFF, .priv_data_size = sizeof(TiffContext), .init = tiff_init, .close = tiff_end, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .priv_class = &tiff_decoder_class, + .p.priv_class = &tiff_decoder_class, }; diff --git a/libavcodec/tiffenc.c b/libavcodec/tiffenc.c index a6c523364..2f2742e56 100644 --- a/libavcodec/tiffenc.c +++ b/libavcodec/tiffenc.c @@ -36,12 +36,13 @@ #include "libavutil/pixdesc.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "lzw.h" #include "put_bits.h" #include "rle.h" #include "tiff.h" +#include "version.h" #define TIFF_MAX_ENTRY 32 @@ -568,17 +569,17 @@ static const AVClass tiffenc_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_tiff_encoder = { - .name = "tiff", - .long_name = NULL_IF_CONFIG_SMALL("TIFF image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_TIFF, +const FFCodec ff_tiff_encoder = { + .p.name = "tiff", + .p.long_name = NULL_IF_CONFIG_SMALL("TIFF image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_TIFF, .priv_data_size = sizeof(TiffEncoderContext), .init = encode_init, .close = encode_close, - .capabilities = AV_CODEC_CAP_FRAME_THREADS, - .encode2 = encode_frame, - .pix_fmts = (const enum AVPixelFormat[]) { + .p.capabilities = AV_CODEC_CAP_FRAME_THREADS, + FF_CODEC_ENCODE_CB(encode_frame), + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_RGB24, AV_PIX_FMT_RGB48LE, AV_PIX_FMT_PAL8, AV_PIX_FMT_RGBA, AV_PIX_FMT_RGBA64LE, AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY8A, AV_PIX_FMT_GRAY16LE, AV_PIX_FMT_YA16LE, @@ -587,6 +588,6 @@ const AVCodec ff_tiff_encoder = { AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_NONE }, - .priv_class = &tiffenc_class, + .p.priv_class = &tiffenc_class, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/tmv.c b/libavcodec/tmv.c index 67aeb2366..d1685a0ae 100644 --- a/libavcodec/tmv.c +++ b/libavcodec/tmv.c @@ -29,16 +29,16 @@ #include #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "libavutil/internal.h" #include "libavutil/xga_font_data.h" #include "cga_data.h" -static int tmv_decode_frame(AVCodecContext *avctx, void *data, +static int tmv_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt) { - AVFrame *frame = data; const uint8_t *src = avpkt->data; uint8_t *dst; unsigned char_cols = avctx->width >> 3; @@ -86,13 +86,13 @@ static av_cold int tmv_decode_init(AVCodecContext *avctx) return 0; } -const AVCodec ff_tmv_decoder = { - .name = "tmv", - .long_name = NULL_IF_CONFIG_SMALL("8088flex TMV"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_TMV, +const FFCodec ff_tmv_decoder = { + .p.name = "tmv", + .p.long_name = NULL_IF_CONFIG_SMALL("8088flex TMV"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_TMV, .init = tmv_decode_init, - .decode = tmv_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(tmv_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/trace_headers_bsf.c b/libavcodec/trace_headers_bsf.c index a9b024741..028b0a1e5 100644 --- a/libavcodec/trace_headers_bsf.c +++ b/libavcodec/trace_headers_bsf.c @@ -16,10 +16,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include +#include #include "libavutil/avstring.h" -#include "libavutil/common.h" +#include "libavutil/avutil.h" #include "libavutil/log.h" #include "bsf.h" @@ -117,11 +117,11 @@ static int trace_headers(AVBSFContext *bsf, AVPacket *pkt) return err; } -const AVBitStreamFilter ff_trace_headers_bsf = { - .name = "trace_headers", +const FFBitStreamFilter ff_trace_headers_bsf = { + .p.name = "trace_headers", + .p.codec_ids = ff_cbs_all_codec_ids, .priv_data_size = sizeof(TraceHeadersContext), .init = &trace_headers_init, .close = &trace_headers_close, .filter = &trace_headers, - .codec_ids = ff_cbs_all_codec_ids, }; diff --git a/libavcodec/truehd_core_bsf.c b/libavcodec/truehd_core_bsf.c index cc2779cc2..ee1060b02 100644 --- a/libavcodec/truehd_core_bsf.c +++ b/libavcodec/truehd_core_bsf.c @@ -173,10 +173,10 @@ static const enum AVCodecID codec_ids[] = { AV_CODEC_ID_TRUEHD, AV_CODEC_ID_NONE, }; -const AVBitStreamFilter ff_truehd_core_bsf = { - .name = "truehd_core", +const FFBitStreamFilter ff_truehd_core_bsf = { + .p.name = "truehd_core", + .p.codec_ids = codec_ids, .priv_data_size = sizeof(TrueHDCoreContext), .filter = truehd_core_filter, .flush = truehd_core_flush, - .codec_ids = codec_ids, }; diff --git a/libavcodec/truemotion1.c b/libavcodec/truemotion1.c index 32d8fb400..64d9b8fed 100644 --- a/libavcodec/truemotion1.c +++ b/libavcodec/truemotion1.c @@ -34,6 +34,7 @@ #include #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "libavutil/imgutils.h" #include "libavutil/internal.h" @@ -868,9 +869,8 @@ static void truemotion1_decode_24bit(TrueMotion1Context *s) } -static int truemotion1_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int truemotion1_decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int ret, buf_size = avpkt->size; @@ -891,7 +891,7 @@ static int truemotion1_decode_frame(AVCodecContext *avctx, truemotion1_decode_16bit(s); } - if ((ret = av_frame_ref(data, s->frame)) < 0) + if ((ret = av_frame_ref(rframe, s->frame)) < 0) return ret; *got_frame = 1; @@ -910,15 +910,15 @@ static av_cold int truemotion1_decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_truemotion1_decoder = { - .name = "truemotion1", - .long_name = NULL_IF_CONFIG_SMALL("Duck TrueMotion 1.0"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_TRUEMOTION1, +const FFCodec ff_truemotion1_decoder = { + .p.name = "truemotion1", + .p.long_name = NULL_IF_CONFIG_SMALL("Duck TrueMotion 1.0"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_TRUEMOTION1, .priv_data_size = sizeof(TrueMotion1Context), .init = truemotion1_decode_init, .close = truemotion1_decode_end, - .decode = truemotion1_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(truemotion1_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/truemotion2.c b/libavcodec/truemotion2.c index f29db593f..3fd956ee1 100644 --- a/libavcodec/truemotion2.c +++ b/libavcodec/truemotion2.c @@ -29,6 +29,7 @@ #include "avcodec.h" #include "bswapdsp.h" #include "bytestream.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" @@ -885,9 +886,8 @@ static const int tm2_stream_order[TM2_NUM_STREAMS] = { #define TM2_HEADER_SIZE 40 -static int decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *avpkt) { TM2Context * const l = avctx->priv_data; const uint8_t *buf = avpkt->data; @@ -938,7 +938,7 @@ static int decode_frame(AVCodecContext *avctx, l->cur = !l->cur; *got_frame = 1; - ret = av_frame_ref(data, l->pic); + ret = av_frame_ref(rframe, l->pic); return (ret < 0) ? ret : buf_size; } @@ -1008,15 +1008,15 @@ static av_cold int decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_truemotion2_decoder = { - .name = "truemotion2", - .long_name = NULL_IF_CONFIG_SMALL("Duck TrueMotion 2.0"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_TRUEMOTION2, +const FFCodec ff_truemotion2_decoder = { + .p.name = "truemotion2", + .p.long_name = NULL_IF_CONFIG_SMALL("Duck TrueMotion 2.0"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_TRUEMOTION2, .priv_data_size = sizeof(TM2Context), .init = decode_init, .close = decode_end, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/truemotion2rt.c b/libavcodec/truemotion2rt.c index b6a19581a..a3686fc1a 100644 --- a/libavcodec/truemotion2rt.c +++ b/libavcodec/truemotion2rt.c @@ -28,6 +28,7 @@ #define BITSTREAM_READER_LE #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" @@ -101,11 +102,10 @@ static int truemotion2rt_decode_header(AVCodecContext *avctx, const AVPacket *av return header_size; } -static int truemotion2rt_decode_frame(AVCodecContext *avctx, void *data, +static int truemotion2rt_decode_frame(AVCodecContext *avctx, AVFrame *p, int *got_frame, AVPacket *avpkt) { TrueMotion2RTContext *s = avctx->priv_data; - AVFrame * const p = data; GetBitContext *gb = &s->gb; uint8_t *dst; int x, y, delta_mode; @@ -219,14 +219,14 @@ static av_cold int truemotion2rt_decode_init(AVCodecContext *avctx) return 0; } -const AVCodec ff_truemotion2rt_decoder = { - .name = "truemotion2rt", - .long_name = NULL_IF_CONFIG_SMALL("Duck TrueMotion 2.0 Real Time"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_TRUEMOTION2RT, +const FFCodec ff_truemotion2rt_decoder = { + .p.name = "truemotion2rt", + .p.long_name = NULL_IF_CONFIG_SMALL("Duck TrueMotion 2.0 Real Time"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_TRUEMOTION2RT, .priv_data_size = sizeof(TrueMotion2RTContext), .init = truemotion2rt_decode_init, - .decode = truemotion2rt_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(truemotion2rt_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/truespeech.c b/libavcodec/truespeech.c index a65ced15d..e472cb824 100644 --- a/libavcodec/truespeech.c +++ b/libavcodec/truespeech.c @@ -25,6 +25,7 @@ #include "avcodec.h" #include "bswapdsp.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" @@ -64,12 +65,13 @@ static av_cold int truespeech_decode_init(AVCodecContext * avctx) { TSContext *c = avctx->priv_data; - if (avctx->channels != 1) { - avpriv_request_sample(avctx, "Channel count %d", avctx->channels); + if (avctx->ch_layout.nb_channels != 1) { + avpriv_request_sample(avctx, "Channel count %d", avctx->ch_layout.nb_channels); return AVERROR_PATCHWELCOME; } - avctx->channel_layout = AV_CH_LAYOUT_MONO; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; avctx->sample_fmt = AV_SAMPLE_FMT_S16; ff_bswapdsp_init(&c->bdsp); @@ -304,10 +306,9 @@ static void truespeech_save_prevvec(TSContext *c) c->prevfilt[i] = c->cvector[i]; } -static int truespeech_decode_frame(AVCodecContext *avctx, void *data, +static int truespeech_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; TSContext *c = avctx->priv_data; @@ -355,14 +356,14 @@ static int truespeech_decode_frame(AVCodecContext *avctx, void *data, return buf_size; } -const AVCodec ff_truespeech_decoder = { - .name = "truespeech", - .long_name = NULL_IF_CONFIG_SMALL("DSP Group TrueSpeech"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_TRUESPEECH, +const FFCodec ff_truespeech_decoder = { + .p.name = "truespeech", + .p.long_name = NULL_IF_CONFIG_SMALL("DSP Group TrueSpeech"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_TRUESPEECH, .priv_data_size = sizeof(TSContext), .init = truespeech_decode_init, - .decode = truespeech_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(truespeech_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/tscc.c b/libavcodec/tscc.c index 841f0c0d1..7343d7aac 100644 --- a/libavcodec/tscc.c +++ b/libavcodec/tscc.c @@ -38,9 +38,11 @@ #include #include "avcodec.h" +#include "codec_internal.h" #include "decode.h" #include "internal.h" #include "msrledec.h" +#include "zlib_wrapper.h" #include @@ -57,18 +59,18 @@ typedef struct TsccContext { unsigned char* decomp_buf; GetByteContext gb; int height; - int zlib_init_ok; - z_stream zstream; + FFZStream zstream; uint32_t pal[256]; } CamtasiaContext; -static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; CamtasiaContext * const c = avctx->priv_data; + z_stream *const zstream = &c->zstream.zstream; AVFrame *frame = c->frame; int ret; int palette_has_changed = 0; @@ -77,16 +79,16 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, palette_has_changed = ff_copy_palette(c->pal, avpkt, avctx); } - ret = inflateReset(&c->zstream); + ret = inflateReset(zstream); if (ret != Z_OK) { av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", ret); return AVERROR_UNKNOWN; } - c->zstream.next_in = buf; - c->zstream.avail_in = buf_size; - c->zstream.next_out = c->decomp_buf; - c->zstream.avail_out = c->decomp_size; - ret = inflate(&c->zstream, Z_FINISH); + zstream->next_in = buf; + zstream->avail_in = buf_size; + zstream->next_out = c->decomp_buf; + zstream->avail_out = c->decomp_size; + ret = inflate(zstream, Z_FINISH); // Z_DATA_ERROR means empty picture if (ret == Z_DATA_ERROR && !palette_has_changed) { return buf_size; @@ -102,7 +104,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, if (ret != Z_DATA_ERROR) { bytestream2_init(&c->gb, c->decomp_buf, - c->decomp_size - c->zstream.avail_out); + c->decomp_size - zstream->avail_out); ff_msrle_decode(avctx, frame, c->bpp, &c->gb); } @@ -112,7 +114,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, memcpy(frame->data[1], c->pal, AVPALETTE_SIZE); } - if ((ret = av_frame_ref(data, frame)) < 0) + if ((ret = av_frame_ref(rframe, frame)) < 0) return ret; *got_frame = 1; @@ -123,7 +125,6 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, static av_cold int decode_init(AVCodecContext *avctx) { CamtasiaContext * const c = avctx->priv_data; - int zret; // Zlib return code c->avctx = avctx; @@ -151,21 +152,11 @@ static av_cold int decode_init(AVCodecContext *avctx) } } - c->zstream.zalloc = Z_NULL; - c->zstream.zfree = Z_NULL; - c->zstream.opaque = Z_NULL; - zret = inflateInit(&c->zstream); - if (zret != Z_OK) { - av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret); - return AVERROR_UNKNOWN; - } - c->zlib_init_ok = 1; - c->frame = av_frame_alloc(); if (!c->frame) return AVERROR(ENOMEM); - return 0; + return ff_inflate_init(&c->zstream, avctx); } static av_cold int decode_end(AVCodecContext *avctx) @@ -174,22 +165,20 @@ static av_cold int decode_end(AVCodecContext *avctx) av_freep(&c->decomp_buf); av_frame_free(&c->frame); - - if (c->zlib_init_ok) - inflateEnd(&c->zstream); + ff_inflate_end(&c->zstream); return 0; } -const AVCodec ff_tscc_decoder = { - .name = "camtasia", - .long_name = NULL_IF_CONFIG_SMALL("TechSmith Screen Capture Codec"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_TSCC, +const FFCodec ff_tscc_decoder = { + .p.name = "camtasia", + .p.long_name = NULL_IF_CONFIG_SMALL("TechSmith Screen Capture Codec"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_TSCC, .priv_data_size = sizeof(CamtasiaContext), .init = decode_init, .close = decode_end, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/tscc2.c b/libavcodec/tscc2.c index 419a7775b..f6950fbbb 100644 --- a/libavcodec/tscc2.c +++ b/libavcodec/tscc2.c @@ -31,6 +31,7 @@ #define BITSTREAM_READER_LE #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" #include "mathops.h" @@ -56,7 +57,7 @@ static av_cold void tscc2_init_vlc(VLC *vlc, int *offset, int nb_codes, const uint8_t *lens, const void *syms, int sym_length) { - static VLC_TYPE vlc_buf[15442][2]; + static VLCElem vlc_buf[15442]; vlc->table = &vlc_buf[*offset]; vlc->table_allocated = FF_ARRAY_ELEMS(vlc_buf) - *offset; @@ -204,7 +205,7 @@ static int tscc2_decode_slice(TSCC2Context *c, int mb_y, return 0; } -static int tscc2_decode_frame(AVCodecContext *avctx, void *data, +static int tscc2_decode_frame(AVCodecContext *avctx, AVFrame *rframe, int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; @@ -312,7 +313,7 @@ static int tscc2_decode_frame(AVCodecContext *avctx, void *data, } *got_frame = 1; - if ((ret = av_frame_ref(data, c->pic)) < 0) + if ((ret = av_frame_ref(rframe, c->pic)) < 0) return ret; /* always report that the buffer was completely consumed */ @@ -355,15 +356,15 @@ static av_cold int tscc2_decode_init(AVCodecContext *avctx) return 0; } -const AVCodec ff_tscc2_decoder = { - .name = "tscc2", - .long_name = NULL_IF_CONFIG_SMALL("TechSmith Screen Codec 2"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_TSCC2, +const FFCodec ff_tscc2_decoder = { + .p.name = "tscc2", + .p.long_name = NULL_IF_CONFIG_SMALL("TechSmith Screen Codec 2"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_TSCC2, .priv_data_size = sizeof(TSCC2Context), .init = tscc2_decode_init, .close = tscc2_decode_end, - .decode = tscc2_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(tscc2_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/tta.c b/libavcodec/tta.c index 17b4ca903..74be140d5 100644 --- a/libavcodec/tta.c +++ b/libavcodec/tta.c @@ -38,10 +38,10 @@ #include "ttadata.h" #include "ttadsp.h" #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" #include "thread.h" #include "unary.h" -#include "internal.h" #define FORMAT_SIMPLE 1 #define FORMAT_ENCRYPTED 2 @@ -113,11 +113,9 @@ static int allocate_buffers(AVCodecContext *avctx) return AVERROR(ENOMEM); } else s->decode_buffer = NULL; - s->ch_ctx = av_malloc_array(avctx->channels, sizeof(*s->ch_ctx)); - if (!s->ch_ctx) { - av_freep(&s->decode_buffer); + s->ch_ctx = av_malloc_array(avctx->ch_layout.nb_channels, sizeof(*s->ch_ctx)); + if (!s->ch_ctx) return AVERROR(ENOMEM); - } return 0; } @@ -156,9 +154,17 @@ static av_cold int tta_decode_init(AVCodecContext * avctx) } AV_WL64(s->crc_pass, tta_check_crc64(s->pass)); } - avctx->channels = s->channels = get_bits(&gb, 16); - if (s->channels > 1 && s->channels < 9) - avctx->channel_layout = tta_channel_layouts[s->channels-2]; + + s->channels = get_bits(&gb, 16); + + av_channel_layout_uninit(&avctx->ch_layout); + if (s->channels > 1 && s->channels < 9) { + av_channel_layout_from_mask(&avctx->ch_layout, tta_channel_layouts[s->channels-2]); + } else { + avctx->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + avctx->ch_layout.nb_channels = s->channels; + } + avctx->bits_per_raw_sample = get_bits(&gb, 16); s->bps = (avctx->bits_per_raw_sample + 7) / 8; avctx->sample_rate = get_bits_long(&gb, 32); @@ -199,7 +205,7 @@ static av_cold int tta_decode_init(AVCodecContext * avctx) (s->last_frame_length ? 1 : 0); av_log(avctx, AV_LOG_DEBUG, "format: %d chans: %d bps: %d rate: %d block: %d\n", - s->format, avctx->channels, avctx->bits_per_coded_sample, avctx->sample_rate, + s->format, avctx->ch_layout.nb_channels, avctx->bits_per_coded_sample, avctx->sample_rate, avctx->block_align); av_log(avctx, AV_LOG_DEBUG, "data_length: %d frame_length: %d last: %d total: %d\n", s->data_length, s->frame_length, s->last_frame_length, total_frames); @@ -218,11 +224,9 @@ static av_cold int tta_decode_init(AVCodecContext * avctx) return allocate_buffers(avctx); } -static int tta_decode_frame(AVCodecContext *avctx, void *data, +static int tta_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; - ThreadFrame tframe = { .f = data }; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; TTAContext *s = avctx->priv_data; @@ -242,7 +246,7 @@ static int tta_decode_frame(AVCodecContext *avctx, void *data, /* get output buffer */ frame->nb_samples = framelen; - if ((ret = ff_thread_get_buffer(avctx, &tframe, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, frame, 0)) < 0) return ret; // decode directly to output buffer for 24-bit sample format @@ -416,16 +420,16 @@ static const AVClass tta_decoder_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_tta_decoder = { - .name = "tta", - .long_name = NULL_IF_CONFIG_SMALL("TTA (True Audio)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_TTA, +const FFCodec ff_tta_decoder = { + .p.name = "tta", + .p.long_name = NULL_IF_CONFIG_SMALL("TTA (True Audio)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_TTA, .priv_data_size = sizeof(TTAContext), .init = tta_decode_init, .close = tta_decode_close, - .decode = tta_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_CHANNEL_CONF, - .priv_class = &tta_decoder_class, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + FF_CODEC_DECODE_CB(tta_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_CHANNEL_CONF, + .p.priv_class = &tta_decoder_class, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/ttadata.c b/libavcodec/ttadata.c index aa9f418a7..297d70948 100644 --- a/libavcodec/ttadata.c +++ b/libavcodec/ttadata.c @@ -18,6 +18,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include "ttadata.h" const uint32_t ff_tta_shift_1[] = { diff --git a/libavcodec/ttadata.h b/libavcodec/ttadata.h index 48c4cd035..1ec1d749c 100644 --- a/libavcodec/ttadata.h +++ b/libavcodec/ttadata.h @@ -21,7 +21,7 @@ #ifndef AVCODEC_TTADATA_H #define AVCODEC_TTADATA_H -#include "internal.h" +#include #define MAX_ORDER 16 typedef struct TTAFilter { diff --git a/libavcodec/ttadsp.c b/libavcodec/ttadsp.c index 99dd66a0c..fe9e3c69e 100644 --- a/libavcodec/ttadsp.c +++ b/libavcodec/ttadsp.c @@ -56,6 +56,7 @@ av_cold void ff_ttadsp_init(TTADSPContext *c) { c->filter_process = tta_filter_process_c; - if (ARCH_X86) - ff_ttadsp_init_x86(c); +#if ARCH_X86 + ff_ttadsp_init_x86(c); +#endif } diff --git a/libavcodec/ttaenc.c b/libavcodec/ttaenc.c index addaf30bb..b7d4aafdc 100644 --- a/libavcodec/ttaenc.c +++ b/libavcodec/ttaenc.c @@ -22,6 +22,7 @@ #include "ttadata.h" #include "ttaencdsp.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" #include "put_bits.h" #include "internal.h" @@ -56,7 +57,7 @@ static av_cold int tta_encode_init(AVCodecContext *avctx) s->bps = avctx->bits_per_raw_sample >> 3; avctx->frame_size = 256 * avctx->sample_rate / 245; - s->ch_ctx = av_malloc_array(avctx->channels, sizeof(*s->ch_ctx)); + s->ch_ctx = av_malloc_array(avctx->ch_layout.nb_channels, sizeof(*s->ch_ctx)); if (!s->ch_ctx) return AVERROR(ENOMEM); @@ -89,7 +90,7 @@ static int tta_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, TTAEncContext *s = avctx->priv_data; PutBitContext pb; int ret, i, out_bytes, cur_chan, res, samples; - int64_t pkt_size = frame->nb_samples * 2LL * avctx->channels * s->bps; + int64_t pkt_size = frame->nb_samples * 2LL * avctx->ch_layout.nb_channels * s->bps; pkt_alloc: cur_chan = 0, res = 0, samples = 0; @@ -98,13 +99,13 @@ pkt_alloc: init_put_bits(&pb, avpkt->data, avpkt->size); // init per channel states - for (i = 0; i < avctx->channels; i++) { + for (i = 0; i < avctx->ch_layout.nb_channels; i++) { s->ch_ctx[i].predictor = 0; ff_tta_filter_init(&s->ch_ctx[i].filter, ff_tta_filter_configs[s->bps - 1]); ff_tta_rice_init(&s->ch_ctx[i].rice, 10, 10); } - for (i = 0; i < frame->nb_samples * avctx->channels; i++) { + for (i = 0; i < frame->nb_samples * avctx->ch_layout.nb_channels; i++) { TTAChannel *c = &s->ch_ctx[cur_chan]; TTAFilter *filter = &c->filter; TTARice *rice = &c->rice; @@ -113,8 +114,8 @@ pkt_alloc: value = get_sample(frame, samples++, avctx->sample_fmt); - if (avctx->channels > 1) { - if (cur_chan < avctx->channels - 1) + if (avctx->ch_layout.nb_channels > 1) { + if (cur_chan < avctx->ch_layout.nb_channels - 1) value = res = get_sample(frame, samples, avctx->sample_fmt) - value; else value -= res / 2; @@ -176,7 +177,7 @@ pkt_alloc: if (k) put_bits(&pb, k, outval & (ff_tta_shift_1[k] - 1)); - if (cur_chan < avctx->channels - 1) + if (cur_chan < avctx->ch_layout.nb_channels - 1) cur_chan++; else cur_chan = 0; @@ -201,17 +202,17 @@ static av_cold int tta_encode_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_tta_encoder = { - .name = "tta", - .long_name = NULL_IF_CONFIG_SMALL("TTA (True Audio)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_TTA, +const FFCodec ff_tta_encoder = { + .p.name = "tta", + .p.long_name = NULL_IF_CONFIG_SMALL("TTA (True Audio)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_TTA, .priv_data_size = sizeof(TTAEncContext), .init = tta_encode_init, .close = tta_encode_close, - .encode2 = tta_encode_frame, - .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_U8, + FF_CODEC_ENCODE_CB(tta_encode_frame), + .p.capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME, + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE }, diff --git a/libavcodec/ttaencdsp.c b/libavcodec/ttaencdsp.c index 6ba594e9f..0efdc109b 100644 --- a/libavcodec/ttaencdsp.c +++ b/libavcodec/ttaencdsp.c @@ -54,6 +54,7 @@ av_cold void ff_ttaencdsp_init(TTAEncDSPContext *c) { c->filter_process = ttaenc_filter_process_c; - if (ARCH_X86) - ff_ttaencdsp_init_x86(c); +#if ARCH_X86 + ff_ttaencdsp_init_x86(c); +#endif } diff --git a/libavcodec/ttmlenc.c b/libavcodec/ttmlenc.c index ad2eddfdd..be1d8fb2e 100644 --- a/libavcodec/ttmlenc.c +++ b/libavcodec/ttmlenc.c @@ -28,7 +28,7 @@ */ #include "avcodec.h" -#include "internal.h" +#include "codec_internal.h" #include "libavutil/avstring.h" #include "libavutil/bprint.h" #include "libavutil/internal.h" @@ -383,14 +383,14 @@ static av_cold int ttml_encode_init(AVCodecContext *avctx) return 0; } -const AVCodec ff_ttml_encoder = { - .name = "ttml", - .long_name = NULL_IF_CONFIG_SMALL("TTML subtitle"), - .type = AVMEDIA_TYPE_SUBTITLE, - .id = AV_CODEC_ID_TTML, +const FFCodec ff_ttml_encoder = { + .p.name = "ttml", + .p.long_name = NULL_IF_CONFIG_SMALL("TTML subtitle"), + .p.type = AVMEDIA_TYPE_SUBTITLE, + .p.id = AV_CODEC_ID_TTML, .priv_data_size = sizeof(TTMLContext), .init = ttml_encode_init, - .encode_sub = ttml_encode_frame, + FF_CODEC_ENCODE_SUB_CB(ttml_encode_frame), .close = ttml_encode_close, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/twinvq.c b/libavcodec/twinvq.c index 6dfaf06b1..ba84c8c6b 100644 --- a/libavcodec/twinvq.c +++ b/libavcodec/twinvq.c @@ -217,17 +217,18 @@ static void dec_gain(TwinVQContext *tctx, const TwinVQModeTab *mtab = tctx->mtab; const TwinVQFrameData *bits = &tctx->bits[tctx->cur_frame]; int i, j; + int channels = tctx->avctx->ch_layout.nb_channels; int sub = mtab->fmode[ftype].sub; float step = TWINVQ_AMP_MAX / ((1 << TWINVQ_GAIN_BITS) - 1); float sub_step = TWINVQ_SUB_AMP_MAX / ((1 << TWINVQ_SUB_GAIN_BITS) - 1); if (ftype == TWINVQ_FT_LONG) { - for (i = 0; i < tctx->avctx->channels; i++) + for (i = 0; i < channels; i++) out[i] = (1.0 / (1 << 13)) * twinvq_mulawinv(step * 0.5 + step * bits->gain_bits[i], TWINVQ_AMP_MAX, TWINVQ_MULAW_MU); } else { - for (i = 0; i < tctx->avctx->channels; i++) { + for (i = 0; i < channels; i++) { float val = (1.0 / (1 << 23)) * twinvq_mulawinv(step * 0.5 + step * bits->gain_bits[i], TWINVQ_AMP_MAX, TWINVQ_MULAW_MU); @@ -380,10 +381,11 @@ static void imdct_output(TwinVQContext *tctx, enum TwinVQFrameType ftype, { const TwinVQModeTab *mtab = tctx->mtab; float *prev_buf = tctx->prev_frame + tctx->last_block_pos[0]; + int channels = tctx->avctx->ch_layout.nb_channels; int size1, size2, i; float *out1, *out2; - for (i = 0; i < tctx->avctx->channels; i++) + for (i = 0; i < channels; i++) imdct_and_window(tctx, ftype, wtype, tctx->spectrum + i * mtab->size, prev_buf + 2 * i * mtab->size, @@ -399,7 +401,7 @@ static void imdct_output(TwinVQContext *tctx, enum TwinVQFrameType ftype, memcpy(out1, prev_buf, size1 * sizeof(*out1)); memcpy(out1 + size1, tctx->curr_frame, size2 * sizeof(*out1)); - if (tctx->avctx->channels == 2) { + if (channels == 2) { out2 = &out[1][0] + offset; memcpy(out2, &prev_buf[2 * mtab->size], size1 * sizeof(*out2)); @@ -414,7 +416,7 @@ static void read_and_decode_spectrum(TwinVQContext *tctx, float *out, { const TwinVQModeTab *mtab = tctx->mtab; TwinVQFrameData *bits = &tctx->bits[tctx->cur_frame]; - int channels = tctx->avctx->channels; + int channels = tctx->avctx->ch_layout.nb_channels; int sub = mtab->fmode[ftype].sub; int block_size = mtab->size / sub; float gain[TWINVQ_CHANNELS_MAX * TWINVQ_SUBBLOCKS_MAX]; @@ -473,10 +475,9 @@ const enum TwinVQFrameType ff_twinvq_wtype_to_ftype_table[] = { TWINVQ_FT_MEDIUM }; -int ff_twinvq_decode_frame(AVCodecContext *avctx, void *data, +int ff_twinvq_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; TwinVQContext *tctx = avctx->priv_data; @@ -536,7 +537,7 @@ static av_cold int init_mdct_win(TwinVQContext *tctx) const TwinVQModeTab *mtab = tctx->mtab; int size_s = mtab->size / mtab->fmode[TWINVQ_FT_SHORT].sub; int size_m = mtab->size / mtab->fmode[TWINVQ_FT_MEDIUM].sub; - int channels = tctx->avctx->channels; + int channels = tctx->avctx->ch_layout.nb_channels; float norm = channels == 1 ? 2.0 : 1.0; int table_size = 2 * mtab->size * channels; @@ -645,10 +646,10 @@ static av_cold void construct_perm_table(TwinVQContext *tctx, int16_t *tmp_perm = (int16_t *)tctx->tmp_buf; if (ftype == TWINVQ_FT_PPC) { - size = tctx->avctx->channels; + size = tctx->avctx->ch_layout.nb_channels; block_size = mtab->ppc_shape_len; } else { - size = tctx->avctx->channels * mtab->fmode[ftype].sub; + size = tctx->avctx->ch_layout.nb_channels * mtab->fmode[ftype].sub; block_size = mtab->size / mtab->fmode[ftype].sub; } @@ -666,7 +667,7 @@ static av_cold void construct_perm_table(TwinVQContext *tctx, static av_cold void init_bitstream_params(TwinVQContext *tctx) { const TwinVQModeTab *mtab = tctx->mtab; - int n_ch = tctx->avctx->channels; + int n_ch = tctx->avctx->ch_layout.nb_channels; int total_fr_bits = tctx->avctx->bit_rate * mtab->size / tctx->avctx->sample_rate; @@ -783,13 +784,10 @@ av_cold int ff_twinvq_decode_init(AVCodecContext *avctx) tctx->frames_per_packet = frames_per_packet; tctx->fdsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT); - if (!tctx->fdsp) { - ff_twinvq_decode_close(avctx); + if (!tctx->fdsp) return AVERROR(ENOMEM); - } if ((ret = init_mdct_win(tctx))) { av_log(avctx, AV_LOG_ERROR, "Error initializing MDCT\n"); - ff_twinvq_decode_close(avctx); return ret; } init_bitstream_params(tctx); diff --git a/libavcodec/twinvq.h b/libavcodec/twinvq.h index 24e5ebcd0..b3c881cfa 100644 --- a/libavcodec/twinvq.h +++ b/libavcodec/twinvq.h @@ -29,7 +29,6 @@ #include "libavutil/float_dsp.h" #include "avcodec.h" #include "fft.h" -#include "internal.h" enum TwinVQCodec { TWINVQ_CODEC_VQF, @@ -195,9 +194,10 @@ static inline float twinvq_mulawinv(float y, float clip, float mu) return clip * FFSIGN(y) * (exp(log(1 + mu) * fabs(y)) - 1) / mu; } -int ff_twinvq_decode_frame(AVCodecContext *avctx, void *data, +int ff_twinvq_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt); int ff_twinvq_decode_close(AVCodecContext *avctx); +/** Requires the caller to call ff_twinvq_decode_close() upon failure. */ int ff_twinvq_decode_init(AVCodecContext *avctx); #endif /* AVCODEC_TWINVQ_H */ diff --git a/libavcodec/twinvqdec.c b/libavcodec/twinvqdec.c index 1fbe0bc32..6dfa57f00 100644 --- a/libavcodec/twinvqdec.c +++ b/libavcodec/twinvqdec.c @@ -24,8 +24,8 @@ #include "libavutil/channel_layout.h" #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" -#include "internal.h" #include "twinvq.h" #include "metasound_data.h" #include "twinvq_data.h" @@ -181,7 +181,7 @@ static void decode_ppc(TwinVQContext *tctx, int period_coef, int g_coef, { const TwinVQModeTab *mtab = tctx->mtab; int isampf = tctx->avctx->sample_rate / 1000; - int ibps = tctx->avctx->bit_rate / (1000 * tctx->avctx->channels); + int ibps = tctx->avctx->bit_rate / (1000 * tctx->avctx->ch_layout.nb_channels); int min_period = ROUNDED_DIV(40 * 2 * mtab->size, isampf); int max_period = ROUNDED_DIV(40 * 2 * mtab->size * 6, isampf); int period_range = max_period - min_period; @@ -254,7 +254,7 @@ static int twinvq_read_bitstream(AVCodecContext *avctx, TwinVQContext *tctx, { TwinVQFrameData *bits = &tctx->bits[0]; const TwinVQModeTab *mtab = tctx->mtab; - int channels = tctx->avctx->channels; + int channels = tctx->avctx->ch_layout.nb_channels; int sub; GetBitContext gb; int i, j, k, ret; @@ -319,14 +319,14 @@ static int twinvq_read_bitstream(AVCodecContext *avctx, TwinVQContext *tctx, static av_cold int twinvq_decode_init(AVCodecContext *avctx) { - int isampf, ibps; + int isampf, ibps, channels; TwinVQContext *tctx = avctx->priv_data; if (!avctx->extradata || avctx->extradata_size < 12) { av_log(avctx, AV_LOG_ERROR, "Missing or incomplete extradata\n"); return AVERROR_INVALIDDATA; } - avctx->channels = AV_RB32(avctx->extradata) + 1; + channels = AV_RB32(avctx->extradata) + 1; avctx->bit_rate = AV_RB32(avctx->extradata + 4) * 1000; isampf = AV_RB32(avctx->extradata + 8); @@ -349,15 +349,15 @@ static av_cold int twinvq_decode_init(AVCodecContext *avctx) break; } - if (avctx->channels <= 0 || avctx->channels > TWINVQ_CHANNELS_MAX) { + if (channels <= 0 || channels > TWINVQ_CHANNELS_MAX) { av_log(avctx, AV_LOG_ERROR, "Unsupported number of channels: %i\n", - avctx->channels); + channels); return -1; } - avctx->channel_layout = avctx->channels == 1 ? AV_CH_LAYOUT_MONO - : AV_CH_LAYOUT_STEREO; + av_channel_layout_uninit(&avctx->ch_layout); + av_channel_layout_default(&avctx->ch_layout, channels); - ibps = avctx->bit_rate / (1000 * avctx->channels); + ibps = avctx->bit_rate / (1000 * channels); if (ibps < 8 || ibps > 48) { av_log(avctx, AV_LOG_ERROR, "Bad bitrate per channel value %d\n", ibps); return AVERROR_INVALIDDATA; @@ -414,17 +414,17 @@ static av_cold int twinvq_decode_init(AVCodecContext *avctx) return ff_twinvq_decode_init(avctx); } -const AVCodec ff_twinvq_decoder = { - .name = "twinvq", - .long_name = NULL_IF_CONFIG_SMALL("VQF TwinVQ"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_TWINVQ, +const FFCodec ff_twinvq_decoder = { + .p.name = "twinvq", + .p.long_name = NULL_IF_CONFIG_SMALL("VQF TwinVQ"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_TWINVQ, .priv_data_size = sizeof(TwinVQContext), .init = twinvq_decode_init, .close = ff_twinvq_decode_close, - .decode = ff_twinvq_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + FF_CODEC_DECODE_CB(ff_twinvq_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/txd.c b/libavcodec/txd.c index 93e4fa960..8b1da773a 100644 --- a/libavcodec/txd.c +++ b/libavcodec/txd.c @@ -25,17 +25,18 @@ #include "libavutil/imgutils.h" #include "bytestream.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "texturedsp.h" #define TXD_DXT1 0x31545844 #define TXD_DXT3 0x33545844 -static int txd_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) { +static int txd_decode_frame(AVCodecContext *avctx, AVFrame *p, + int *got_frame, AVPacket *avpkt) +{ GetByteContext gb; TextureDSPContext dxtc; - AVFrame * const p = data; unsigned int version, w, h, d3d_format, depth, stride, flags; unsigned int y, v; uint8_t *ptr; @@ -163,11 +164,11 @@ unsupported: return AVERROR_PATCHWELCOME; } -const AVCodec ff_txd_decoder = { - .name = "txd", - .long_name = NULL_IF_CONFIG_SMALL("Renderware TXD (TeXture Dictionary) image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_TXD, - .decode = txd_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, +const FFCodec ff_txd_decoder = { + .p.name = "txd", + .p.long_name = NULL_IF_CONFIG_SMALL("Renderware TXD (TeXture Dictionary) image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_TXD, + .p.capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(txd_decode_frame), }; diff --git a/libavcodec/ulti.c b/libavcodec/ulti.c index 55548ae3f..a8bec9cce 100644 --- a/libavcodec/ulti.c +++ b/libavcodec/ulti.c @@ -30,6 +30,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" #include "ulti_cb.h" @@ -213,9 +214,8 @@ static void ulti_grad(AVFrame *frame, int x, int y, uint8_t *Y, int chroma, int ulti_convert_yuv(frame, x, y, Luma, chroma); } -static int ulti_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int ulti_decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; @@ -407,7 +407,7 @@ static int ulti_decode_frame(AVCodecContext *avctx, } *got_frame = 1; - if ((ret = av_frame_ref(data, s->frame)) < 0) + if ((ret = av_frame_ref(rframe, s->frame)) < 0) return ret; return buf_size; @@ -418,15 +418,15 @@ err: return AVERROR_INVALIDDATA; } -const AVCodec ff_ulti_decoder = { - .name = "ultimotion", - .long_name = NULL_IF_CONFIG_SMALL("IBM UltiMotion"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_ULTI, +const FFCodec ff_ulti_decoder = { + .p.name = "ultimotion", + .p.long_name = NULL_IF_CONFIG_SMALL("IBM UltiMotion"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_ULTI, .priv_data_size = sizeof(UltimotionDecodeContext), .init = ulti_decode_init, .close = ulti_decode_end, - .decode = ulti_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(ulti_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/utils.c b/libavcodec/utils.c index b19befef2..f78475d0a 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -27,7 +27,6 @@ #include "config.h" #include "libavutil/avassert.h" -#include "libavutil/avstring.h" #include "libavutil/channel_layout.h" #include "libavutil/intreadwrite.h" #include "libavutil/mem.h" @@ -36,16 +35,15 @@ #include "libavutil/pixfmt.h" #include "avcodec.h" #include "codec.h" +#include "codec_internal.h" #include "hwconfig.h" #include "thread.h" +#include "threadframe.h" #include "internal.h" #include "put_bits.h" -#include "raw.h" +#include "startcode.h" #include -#include -#include #include -#include void av_fast_padded_malloc(void *ptr, unsigned int *size, size_t min_size) { @@ -73,14 +71,20 @@ void av_fast_padded_mallocz(void *ptr, unsigned int *size, size_t min_size) memset(*p, 0, min_size + AV_INPUT_BUFFER_PADDING_SIZE); } -int av_codec_is_encoder(const AVCodec *codec) +int av_codec_is_encoder(const AVCodec *avcodec) { - return codec && (codec->encode_sub || codec->encode2 || codec->receive_packet); + const FFCodec *const codec = ffcodec(avcodec); + return codec && (codec->cb_type == FF_CODEC_CB_TYPE_ENCODE || + codec->cb_type == FF_CODEC_CB_TYPE_ENCODE_SUB || + codec->cb_type == FF_CODEC_CB_TYPE_RECEIVE_PACKET); } -int av_codec_is_decoder(const AVCodec *codec) +int av_codec_is_decoder(const AVCodec *avcodec) { - return codec && (codec->decode || codec->receive_frame); + const FFCodec *const codec = ffcodec(avcodec); + return codec && (codec->cb_type == FF_CODEC_CB_TYPE_DECODE || + codec->cb_type == FF_CODEC_CB_TYPE_DECODE_SUB || + codec->cb_type == FF_CODEC_CB_TYPE_RECEIVE_FRAME); } int ff_set_dimensions(AVCodecContext *s, int width, int height) @@ -437,7 +441,7 @@ void ff_color_frame(AVFrame *frame, const int c[4]) } int avpriv_codec_get_cap_skip_frame_fill_param(const AVCodec *codec){ - return !!(codec->caps_internal & FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM); + return !!(ffcodec(codec)->caps_internal & FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM); } const char *avcodec_get_name(enum AVCodecID id) @@ -491,6 +495,8 @@ const char *avcodec_profile_name(enum AVCodecID codec_id, int profile) int av_get_exact_bits_per_sample(enum AVCodecID codec_id) { switch (codec_id) { + case AV_CODEC_ID_DFPWM: + return 1; case AV_CODEC_ID_8SVX_EXP: case AV_CODEC_ID_8SVX_FIB: case AV_CODEC_ID_ADPCM_ARGO: @@ -580,6 +586,8 @@ enum AVCodecID av_get_pcm_codec(enum AVSampleFormat fmt, int be) int av_get_bits_per_sample(enum AVCodecID codec_id) { switch (codec_id) { + case AV_CODEC_ID_DFPWM: + return 1; case AV_CODEC_ID_ADPCM_SBPRO_2: return 2; case AV_CODEC_ID_ADPCM_SBPRO_3: @@ -805,8 +813,16 @@ static int get_audio_frame_duration(enum AVCodecID id, int sr, int ch, int ba, int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes) { - int duration = get_audio_frame_duration(avctx->codec_id, avctx->sample_rate, - avctx->channels, avctx->block_align, + int channels = avctx->ch_layout.nb_channels; + int duration; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + if (!channels) + channels = avctx->channels; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + duration = get_audio_frame_duration(avctx->codec_id, avctx->sample_rate, + channels, avctx->block_align, avctx->codec_tag, avctx->bits_per_coded_sample, avctx->bit_rate, avctx->extradata, avctx->frame_size, frame_bytes); @@ -815,8 +831,16 @@ int av_get_audio_frame_duration(AVCodecContext *avctx, int frame_bytes) int av_get_audio_frame_duration2(AVCodecParameters *par, int frame_bytes) { - int duration = get_audio_frame_duration(par->codec_id, par->sample_rate, - par->channels, par->block_align, + int channels = par->ch_layout.nb_channels; + int duration; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + if (!channels) + channels = par->channels; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + duration = get_audio_frame_duration(par->codec_id, par->sample_rate, + channels, par->block_align, par->codec_tag, par->bits_per_coded_sample, par->bit_rate, par->extradata, par->frame_size, frame_bytes); @@ -852,8 +876,9 @@ 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) +const AVCodecHWConfig *avcodec_get_hw_config(const AVCodec *avcodec, int index) { + const FFCodec *const codec = ffcodec(avcodec); int i; if (!codec->hw_configs || index < 0) return NULL; @@ -878,7 +903,7 @@ int ff_thread_ref_frame(ThreadFrame *dst, const ThreadFrame *src) if (src->progress && !(dst->progress = av_buffer_ref(src->progress))) { - ff_thread_release_buffer(dst->owner[0], dst); + ff_thread_release_ext_buffer(dst->owner[0], dst); return AVERROR(ENOMEM); } @@ -892,14 +917,26 @@ enum AVPixelFormat ff_thread_get_format(AVCodecContext *avctx, const enum AVPixe return ff_get_format(avctx, fmt); } -int ff_thread_get_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags) +int ff_thread_get_buffer(AVCodecContext *avctx, AVFrame *f, int flags) +{ + return ff_get_buffer(avctx, f, flags); +} + +int ff_thread_get_ext_buffer(AVCodecContext *avctx, ThreadFrame *f, int flags) { f->owner[0] = f->owner[1] = avctx; return ff_get_buffer(avctx, f->f, flags); } -void ff_thread_release_buffer(AVCodecContext *avctx, ThreadFrame *f) +void ff_thread_release_buffer(AVCodecContext *avctx, AVFrame *f) { + if (f) + av_frame_unref(f); +} + +void ff_thread_release_ext_buffer(AVCodecContext *avctx, ThreadFrame *f) +{ + f->owner[0] = f->owner[1] = NULL; if (f->f) av_frame_unref(f->f); } @@ -921,6 +958,11 @@ int ff_thread_can_start_frame(AVCodecContext *avctx) return 1; } +int ff_slice_thread_init_progress(AVCodecContext *avctx) +{ + return 0; +} + int ff_alloc_entries(AVCodecContext *avctx, int count) { return 0; diff --git a/libavcodec/utvideodec.c b/libavcodec/utvideodec.c index b39d8a794..03ee8f0b1 100644 --- a/libavcodec/utvideodec.c +++ b/libavcodec/utvideodec.c @@ -35,8 +35,8 @@ #include "avcodec.h" #include "bswapdsp.h" #include "bytestream.h" +#include "codec_internal.h" #include "get_bits.h" -#include "internal.h" #include "thread.h" #include "utvideo.h" @@ -557,8 +557,8 @@ static void restore_gradient_planar_il(UtvideoContext *c, uint8_t *src, ptrdiff_ } } -static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; @@ -568,9 +568,8 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, int plane_size, max_slice_size = 0, slice_start, slice_end, slice_size; int ret; GetByteContext gb; - ThreadFrame frame = { .f = data }; - if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, frame, 0)) < 0) return ret; /* parse plane structure to get frame flags and validate slice offsets */ @@ -709,80 +708,80 @@ 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], - frame.f->linesize[i], avctx->width, + ret = decode_plane(c, i, frame->data[i], + frame->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_planar(c, frame.f->data[i], - frame.f->linesize[i], avctx->width, + restore_median_planar(c, frame->data[i], + frame->linesize[i], avctx->width, avctx->height, c->slices, 0); } else { - restore_median_planar_il(c, frame.f->data[i], - frame.f->linesize[i], + restore_median_planar_il(c, frame->data[i], + frame->linesize[i], 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, + restore_gradient_planar(c, frame->data[i], + frame->linesize[i], avctx->width, avctx->height, c->slices, 0); } else { - restore_gradient_planar_il(c, frame.f->data[i], - frame.f->linesize[i], + restore_gradient_planar_il(c, frame->data[i], + frame->linesize[i], avctx->width, avctx->height, c->slices, 0); } } } - c->utdsp.restore_rgb_planes(frame.f->data[2], frame.f->data[0], frame.f->data[1], - frame.f->linesize[2], frame.f->linesize[0], frame.f->linesize[1], + c->utdsp.restore_rgb_planes(frame->data[2], frame->data[0], frame->data[1], + frame->linesize[2], frame->linesize[0], frame->linesize[1], 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], - frame.f->linesize[i] / 2, avctx->width, + ret = decode_plane10(c, i, (uint16_t *)frame->data[i], + frame->linesize[i] / 2, avctx->width, avctx->height, plane_start[i], plane_start[i + 1] - 1024, c->frame_pred == PRED_LEFT); if (ret) return ret; } - c->utdsp.restore_rgb_planes10((uint16_t *)frame.f->data[2], (uint16_t *)frame.f->data[0], (uint16_t *)frame.f->data[1], - frame.f->linesize[2] / 2, frame.f->linesize[0] / 2, frame.f->linesize[1] / 2, + c->utdsp.restore_rgb_planes10((uint16_t *)frame->data[2], (uint16_t *)frame->data[0], (uint16_t *)frame->data[1], + frame->linesize[2] / 2, frame->linesize[0] / 2, frame->linesize[1] / 2, 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], frame.f->linesize[i], + ret = decode_plane(c, i, frame->data[i], frame->linesize[i], avctx->width >> !!i, avctx->height >> !!i, plane_start[i], c->frame_pred == PRED_LEFT); if (ret) return ret; if (c->frame_pred == PRED_MEDIAN) { if (!c->interlaced) { - restore_median_planar(c, frame.f->data[i], frame.f->linesize[i], + restore_median_planar(c, frame->data[i], frame->linesize[i], avctx->width >> !!i, avctx->height >> !!i, c->slices, !i); } else { - restore_median_planar_il(c, frame.f->data[i], frame.f->linesize[i], + restore_median_planar_il(c, frame->data[i], frame->linesize[i], avctx->width >> !!i, 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], + restore_gradient_planar(c, frame->data[i], frame->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], + restore_gradient_planar_il(c, frame->data[i], frame->linesize[i], avctx->width >> !!i, avctx->height >> !!i, c->slices, !i); @@ -792,28 +791,28 @@ 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], frame.f->linesize[i], + ret = decode_plane(c, i, frame->data[i], frame->linesize[i], avctx->width >> !!i, 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_planar(c, frame.f->data[i], frame.f->linesize[i], + restore_median_planar(c, frame->data[i], frame->linesize[i], avctx->width >> !!i, avctx->height, c->slices, 0); } else { - restore_median_planar_il(c, frame.f->data[i], frame.f->linesize[i], + restore_median_planar_il(c, frame->data[i], frame->linesize[i], 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], + restore_gradient_planar(c, frame->data[i], frame->linesize[i], avctx->width >> !!i, avctx->height, c->slices, 0); } else { - restore_gradient_planar_il(c, frame.f->data[i], frame.f->linesize[i], + restore_gradient_planar_il(c, frame->data[i], frame->linesize[i], avctx->width >> !!i, avctx->height, c->slices, 0); } @@ -822,28 +821,28 @@ 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], frame.f->linesize[i], + ret = decode_plane(c, i, frame->data[i], frame->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_planar(c, frame.f->data[i], frame.f->linesize[i], + restore_median_planar(c, frame->data[i], frame->linesize[i], avctx->width, avctx->height, c->slices, 0); } else { - restore_median_planar_il(c, frame.f->data[i], frame.f->linesize[i], + restore_median_planar_il(c, frame->data[i], frame->linesize[i], 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], + restore_gradient_planar(c, frame->data[i], frame->linesize[i], avctx->width, avctx->height, c->slices, 0); } else { - restore_gradient_planar_il(c, frame.f->data[i], frame.f->linesize[i], + restore_gradient_planar_il(c, frame->data[i], frame->linesize[i], avctx->width, avctx->height, c->slices, 0); } @@ -852,7 +851,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, break; case AV_PIX_FMT_YUV420P10: for (i = 0; i < 3; i++) { - ret = decode_plane10(c, i, (uint16_t *)frame.f->data[i], frame.f->linesize[i] / 2, + ret = decode_plane10(c, i, (uint16_t *)frame->data[i], frame->linesize[i] / 2, avctx->width >> !!i, avctx->height >> !!i, plane_start[i], plane_start[i + 1] - 1024, c->frame_pred == PRED_LEFT); if (ret) @@ -861,7 +860,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], frame.f->linesize[i] / 2, + ret = decode_plane10(c, i, (uint16_t *)frame->data[i], frame->linesize[i] / 2, avctx->width >> !!i, avctx->height, plane_start[i], plane_start[i + 1] - 1024, c->frame_pred == PRED_LEFT); if (ret) @@ -870,9 +869,9 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, break; } - frame.f->key_frame = 1; - frame.f->pict_type = AV_PICTURE_TYPE_I; - frame.f->interlaced_frame = !!c->interlaced; + frame->key_frame = 1; + frame->pict_type = AV_PICTURE_TYPE_I; + frame->interlaced_frame = !!c->interlaced; *got_frame = 1; @@ -1051,15 +1050,15 @@ static av_cold int decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_utvideo_decoder = { - .name = "utvideo", - .long_name = NULL_IF_CONFIG_SMALL("Ut Video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_UTVIDEO, +const FFCodec ff_utvideo_decoder = { + .p.name = "utvideo", + .p.long_name = NULL_IF_CONFIG_SMALL("Ut Video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_UTVIDEO, .priv_data_size = sizeof(UtvideoContext), .init = decode_init, .close = decode_end, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/utvideodsp.c b/libavcodec/utvideodsp.c index 0831a6b97..6db0abf8d 100644 --- a/libavcodec/utvideodsp.c +++ b/libavcodec/utvideodsp.c @@ -77,6 +77,7 @@ av_cold void ff_utvideodsp_init(UTVideoDSPContext *c) c->restore_rgb_planes = restore_rgb_planes_c; c->restore_rgb_planes10 = restore_rgb_planes10_c; - if (ARCH_X86) - ff_utvideodsp_init_x86(c); +#if ARCH_X86 + ff_utvideodsp_init_x86(c); +#endif } diff --git a/libavcodec/utvideoenc.c b/libavcodec/utvideoenc.c index 30907faa0..15a53a609 100644 --- a/libavcodec/utvideoenc.c +++ b/libavcodec/utvideoenc.c @@ -29,8 +29,8 @@ #include "libavutil/opt.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "bswapdsp.h" #include "bytestream.h" #include "put_bits.h" @@ -643,18 +643,18 @@ static const AVClass utvideo_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_utvideo_encoder = { - .name = "utvideo", - .long_name = NULL_IF_CONFIG_SMALL("Ut Video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_UTVIDEO, +const FFCodec ff_utvideo_encoder = { + .p.name = "utvideo", + .p.long_name = NULL_IF_CONFIG_SMALL("Ut Video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_UTVIDEO, .priv_data_size = sizeof(UtvideoContext), - .priv_class = &utvideo_class, + .p.priv_class = &utvideo_class, .init = utvideo_encode_init, - .encode2 = utvideo_encode_frame, + FF_CODEC_ENCODE_CB(utvideo_encode_frame), .close = utvideo_encode_close, - .capabilities = AV_CODEC_CAP_FRAME_THREADS, - .pix_fmts = (const enum AVPixelFormat[]) { + .p.capabilities = AV_CODEC_CAP_FRAME_THREADS, + .p.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_NONE }, diff --git a/libavcodec/v210_template.c b/libavcodec/v210_template.c index 9e1d9f9cd..9f40bfe97 100644 --- a/libavcodec/v210_template.c +++ b/libavcodec/v210_template.c @@ -22,16 +22,6 @@ #include "bytestream.h" #include "internal.h" -#define CLIP(v, depth) av_clip(v, 1<<(depth-8), ((1<> 10) & 0x3FF; \ - *c++ = (val >> 20) & 0x3FF; \ - } while (0) - typedef struct ThreadData { AVFrame *frame; uint8_t *buf; int stride; } ThreadData; -static void v210_planar_unpack_c(const uint32_t *src, uint16_t *y, uint16_t *u, uint16_t *v, int width) -{ - uint32_t val; - int i; - - for( i = 0; i < width-5; i += 6 ){ - READ_PIXELS(u, y, v); - READ_PIXELS(y, u, y); - READ_PIXELS(v, y, u); - READ_PIXELS(y, v, y); - } -} - -av_cold void ff_v210dec_init(V210DecContext *s) -{ - s->unpack_frame = v210_planar_unpack_c; - if (ARCH_X86) - ff_v210_x86_init(s); -} - static av_cold int decode_init(AVCodecContext *avctx) { V210DecContext *s = avctx->priv_data; @@ -77,94 +51,126 @@ static av_cold int decode_init(AVCodecContext *avctx) return 0; } +static void decode_row(const uint32_t *src, uint16_t *y, uint16_t *u, uint16_t *v, const int width, + void (*unpack_frame)(const uint32_t *src, uint16_t *y, uint16_t *u, uint16_t *v, int width)) +{ + uint32_t val; + int w = (FFMAX(0, width - 12) / 12) * 12; + + unpack_frame(src, y, u, v, w); + + y += w; + u += w >> 1; + v += w >> 1; + src += (w << 1) / 3; + + while (w < width - 5) { + READ_PIXELS(u, y, v); + READ_PIXELS(y, u, y); + READ_PIXELS(v, y, u); + READ_PIXELS(y, v, y); + w += 6; + } + + if (w++ < width) { + READ_PIXELS(u, y, v); + + if (w++ < width) { + val = av_le2ne32(*src++); + *y++ = val & 0x3FF; + + if (w++ < width) { + *u++ = (val >> 10) & 0x3FF; + *y++ = (val >> 20) & 0x3FF; + val = av_le2ne32(*src++); + *v++ = val & 0x3FF; + + if (w++ < width) { + *y++ = (val >> 10) & 0x3FF; + + if (w++ < width) { + *u++ = (val >> 20) & 0x3FF; + val = av_le2ne32(*src++); + *y++ = val & 0x3FF; + *v++ = (val >> 10) & 0x3FF; + + if (w++ < width) + *y++ = (val >> 20) & 0x3FF; + } + } + } + } + } +} + static int v210_decode_slice(AVCodecContext *avctx, void *arg, int jobnr, int threadnr) { V210DecContext *s = avctx->priv_data; - int h, w; ThreadData *td = arg; AVFrame *frame = td->frame; int stride = td->stride; int slice_start = (avctx->height * jobnr) / s->thread_count; int slice_end = (avctx->height * (jobnr+1)) / s->thread_count; uint8_t *psrc = td->buf + stride * slice_start; - uint16_t *y, *u, *v; - - y = (uint16_t*)frame->data[0] + slice_start * frame->linesize[0] / 2; - u = (uint16_t*)frame->data[1] + slice_start * frame->linesize[1] / 2; - v = (uint16_t*)frame->data[2] + slice_start * frame->linesize[2] / 2; - for (h = slice_start; h < slice_end; h++) { - const uint32_t *src = (const uint32_t*)psrc; - uint32_t val; - - w = (avctx->width / 12) * 12; - s->unpack_frame(src, y, u, v, w); - - y += w; - u += w >> 1; - v += w >> 1; - src += (w << 1) / 3; - - if (w < avctx->width - 5) { - READ_PIXELS(u, y, v); - READ_PIXELS(y, u, y); - READ_PIXELS(v, y, u); - READ_PIXELS(y, v, y); - w += 6; - } - - if (w < avctx->width - 1) { - READ_PIXELS(u, y, v); - - val = av_le2ne32(*src++); - *y++ = val & 0x3FF; - if (w < avctx->width - 3) { - *u++ = (val >> 10) & 0x3FF; - *y++ = (val >> 20) & 0x3FF; - - val = av_le2ne32(*src++); - *v++ = val & 0x3FF; - *y++ = (val >> 10) & 0x3FF; - } - } + int16_t *py = (uint16_t*)frame->data[0] + slice_start * frame->linesize[0] / 2; + int16_t *pu = (uint16_t*)frame->data[1] + slice_start * frame->linesize[1] / 2; + int16_t *pv = (uint16_t*)frame->data[2] + slice_start * frame->linesize[2] / 2; + for (int h = slice_start; h < slice_end; h++) { + decode_row((const uint32_t *)psrc, py, pu, pv, avctx->width, s->unpack_frame); psrc += stride; - y += frame->linesize[0] / 2 - avctx->width + (avctx->width & 1); - u += frame->linesize[1] / 2 - avctx->width / 2; - v += frame->linesize[2] / 2 - avctx->width / 2; + py += frame->linesize[0] / 2; + pu += frame->linesize[1] / 2; + pv += frame->linesize[2] / 2; } return 0; } -static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int v210_stride(int width, int align) { + int aligned_width = ((width + align - 1) / align) * align; + return aligned_width * 8 / 3; +} + +static int decode_frame(AVCodecContext *avctx, AVFrame *pic, + int *got_frame, AVPacket *avpkt) { V210DecContext *s = avctx->priv_data; ThreadData td; int ret, stride, aligned_input; - ThreadFrame frame = { .f = data }; - AVFrame *pic = data; const uint8_t *psrc = avpkt->data; if (s->custom_stride ) - stride = s->custom_stride; + stride = s->custom_stride > 0 ? s->custom_stride : 0; else { - int aligned_width = ((avctx->width + 47) / 48) * 48; - stride = aligned_width * 8 / 3; - } - - if (avpkt->size < stride * avctx->height) { - if ((((avctx->width + 23) / 24) * 24 * 8) / 3 * avctx->height == avpkt->size) { - stride = avpkt->size / avctx->height; - if (!s->stride_warning_shown) - av_log(avctx, AV_LOG_WARNING, "Broken v210 with too small padding (64 byte) detected\n"); - s->stride_warning_shown = 1; - } else { - av_log(avctx, AV_LOG_ERROR, "packet too small\n"); - return AVERROR_INVALIDDATA; + stride = v210_stride(avctx->width, 48); + if (avpkt->size < stride * avctx->height) { + int align; + for (align = 24; align >= 6; align >>= 1) { + int small_stride = v210_stride(avctx->width, align); + if (avpkt->size == small_stride * avctx->height) { + stride = small_stride; + if (!s->stride_warning_shown) + av_log(avctx, AV_LOG_WARNING, "Broken v210 with too small padding (%d byte) detected\n", align * 8 / 3); + s->stride_warning_shown = 1; + break; + } + } + if (align < 6 && avctx->codec_tag == MKTAG('b', 'x', 'y', '2')) + stride = 0; } } - td.stride = stride; + + if (stride == 0 && ((avctx->width & 1) || (int64_t)avctx->width * avctx->height > INT_MAX / 6)) { + av_log(avctx, AV_LOG_ERROR, "Strideless v210 is not supported for size %dx%d\n", avctx->width, avctx->height); + return AVERROR_INVALIDDATA; + } + + if (stride > 0 && avpkt->size < (int64_t)stride * avctx->height || + stride == 0 && avpkt->size < v210_stride(avctx->width * avctx->height, 6)) { + av_log(avctx, AV_LOG_ERROR, "packet too small\n"); + return AVERROR_INVALIDDATA; + } if ( avctx->codec_tag == MKTAG('C', '2', '1', '0') && avpkt->size > 64 && AV_RN32(psrc) == AV_RN32("INFO") @@ -177,15 +183,27 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, ff_v210dec_init(s); } - if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, pic, 0)) < 0) return ret; pic->pict_type = AV_PICTURE_TYPE_I; pic->key_frame = 1; - td.buf = (uint8_t*)psrc; - td.frame = pic; - avctx->execute2(avctx, v210_decode_slice, &td, NULL, s->thread_count); + if (stride) { + td.stride = stride; + td.buf = (uint8_t*)psrc; + td.frame = pic; + avctx->execute2(avctx, v210_decode_slice, &td, NULL, s->thread_count); + } else { + uint8_t *pointers[4]; + int linesizes[4]; + int ret = av_image_alloc(pointers, linesizes, avctx->width, avctx->height, avctx->pix_fmt, 1); + if (ret < 0) + return ret; + decode_row((const uint32_t *)psrc, (uint16_t *)pointers[0], (uint16_t *)pointers[1], (uint16_t *)pointers[2], avctx->width * avctx->height, s->unpack_frame); + av_image_copy(pic->data, pic->linesize, (const uint8_t **)pointers, linesizes, avctx->pix_fmt, avctx->width, avctx->height); + av_freep(&pointers[0]); + } if (avctx->field_order > AV_FIELD_PROGRESSIVE) { /* we have interlaced material flagged in container */ @@ -202,7 +220,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, #define V210DEC_FLAGS AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM static const AVOption v210dec_options[] = { {"custom_stride", "Custom V210 stride", offsetof(V210DecContext, custom_stride), AV_OPT_TYPE_INT, - {.i64 = 0}, INT_MIN, INT_MAX, V210DEC_FLAGS}, + {.i64 = 0}, -1, INT_MAX, V210DEC_FLAGS}, {NULL} }; @@ -213,17 +231,17 @@ static const AVClass v210dec_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_v210_decoder = { - .name = "v210", - .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_V210, +const FFCodec ff_v210_decoder = { + .p.name = "v210", + .p.long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_V210, .priv_data_size = sizeof(V210DecContext), .init = decode_init, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS, - .priv_class = &v210dec_class, + .p.priv_class = &v210dec_class, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/v210dec.h b/libavcodec/v210dec.h index 662e26631..87ba38e15 100644 --- a/libavcodec/v210dec.h +++ b/libavcodec/v210dec.h @@ -32,7 +32,6 @@ typedef struct { void (*unpack_frame)(const uint32_t *src, uint16_t *y, uint16_t *u, uint16_t *v, int width); } V210DecContext; -void ff_v210dec_init(V210DecContext *s); void ff_v210_x86_init(V210DecContext *s); #endif /* AVCODEC_V210DEC_H */ diff --git a/libavcodec/v210dec_init.h b/libavcodec/v210dec_init.h new file mode 100644 index 000000000..c7a232fe8 --- /dev/null +++ b/libavcodec/v210dec_init.h @@ -0,0 +1,62 @@ +/* + * V210 decoder DSP init + * + * Copyright (C) 2009 Michael Niedermayer + * Copyright (c) 2009 Baptiste Coudurier + * + * 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_V210DEC_INIT_H +#define AVCODEC_V210DEC_INIT_H + +#include + +#include "config.h" +#include "libavutil/attributes.h" +#include "libavutil/bswap.h" +#include "v210dec.h" + +#define READ_PIXELS(a, b, c) \ + do { \ + val = av_le2ne32(*src++); \ + *a++ = val & 0x3FF; \ + *b++ = (val >> 10) & 0x3FF; \ + *c++ = (val >> 20) & 0x3FF; \ + } while (0) + +static void v210_planar_unpack_c(const uint32_t *src, uint16_t *y, uint16_t *u, uint16_t *v, int width) +{ + uint32_t val; + + for (int i = 0; i < width - 5; i += 6) { + READ_PIXELS(u, y, v); + READ_PIXELS(y, u, y); + READ_PIXELS(v, y, u); + READ_PIXELS(y, v, y); + } +} + +static av_unused av_cold void ff_v210dec_init(V210DecContext *s) +{ + s->unpack_frame = v210_planar_unpack_c; +#if ARCH_X86 + ff_v210_x86_init(s); +#endif +} + +#endif /* AVCODEC_V210DEC_INIT_H */ diff --git a/libavcodec/v210enc.c b/libavcodec/v210enc.c index 16c4f82cf..de2e405ef 100644 --- a/libavcodec/v210enc.c +++ b/libavcodec/v210enc.c @@ -23,9 +23,11 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "encode.h" #include "internal.h" #include "v210enc.h" +#include "v210enc_init.h" #define TYPE uint8_t #define DEPTH 8 @@ -47,52 +49,6 @@ #undef BYTES_PER_PIXEL #undef TYPE -static void v210_planar_pack_8_c(const uint8_t *y, const uint8_t *u, - const uint8_t *v, uint8_t *dst, - ptrdiff_t width) -{ - uint32_t val; - int i; - - /* unroll this to match the assembly */ - for (i = 0; i < width - 11; i += 12) { - WRITE_PIXELS(u, y, v, 8); - WRITE_PIXELS(y, u, y, 8); - WRITE_PIXELS(v, y, u, 8); - WRITE_PIXELS(y, v, y, 8); - WRITE_PIXELS(u, y, v, 8); - WRITE_PIXELS(y, u, y, 8); - WRITE_PIXELS(v, y, u, 8); - WRITE_PIXELS(y, v, y, 8); - } -} - -static void v210_planar_pack_10_c(const uint16_t *y, const uint16_t *u, - const uint16_t *v, uint8_t *dst, - ptrdiff_t width) -{ - uint32_t val; - int i; - - for (i = 0; i < width - 5; i += 6) { - WRITE_PIXELS(u, y, v, 10); - WRITE_PIXELS(y, u, y, 10); - WRITE_PIXELS(v, y, u, 10); - WRITE_PIXELS(y, v, y, 10); - } -} - -av_cold void ff_v210enc_init(V210EncContext *s) -{ - s->pack_line_8 = v210_planar_pack_8_c; - s->pack_line_10 = v210_planar_pack_10_c; - s->sample_factor_8 = 2; - s->sample_factor_10 = 1; - - if (ARCH_X86) - ff_v210enc_init_x86(s); -} - static av_cold int encode_init(AVCodecContext *avctx) { V210EncContext *s = avctx->priv_data; @@ -151,15 +107,15 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, return 0; } -const AVCodec ff_v210_encoder = { - .name = "v210", - .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_V210, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, +const FFCodec ff_v210_encoder = { + .p.name = "v210", + .p.long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_V210, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, .priv_data_size = sizeof(V210EncContext), .init = encode_init, - .encode2 = encode_frame, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV422P, AV_PIX_FMT_NONE }, + FF_CODEC_ENCODE_CB(encode_frame), + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV422P, AV_PIX_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/v210enc.h b/libavcodec/v210enc.h index 51305c1a2..b74fd33db 100644 --- a/libavcodec/v210enc.h +++ b/libavcodec/v210enc.h @@ -32,8 +32,6 @@ typedef struct V210EncContext { int sample_factor_10; } V210EncContext; -void ff_v210enc_init(V210EncContext *s); - void ff_v210enc_init_x86(V210EncContext *s); #endif /* AVCODEC_V210ENC_H */ diff --git a/libavcodec/v210enc_init.h b/libavcodec/v210enc_init.h new file mode 100644 index 000000000..a0e5622f4 --- /dev/null +++ b/libavcodec/v210enc_init.h @@ -0,0 +1,91 @@ +/* + * V210 encoder DSP init + * + * Copyright (C) 2009 Michael Niedermayer + * Copyright (c) 2009 Baptiste Coudurier + * + * 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_V210ENC_INIT_H +#define AVCODEC_V210ENC_INIT_H + +#include +#include + +#include "config.h" +#include "libavutil/attributes.h" +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" +#include "v210enc.h" + +#define CLIP(v, depth) av_clip(v, 1<<(depth-8), ((1<pack_line_8 = v210_planar_pack_8_c; + s->pack_line_10 = v210_planar_pack_10_c; + s->sample_factor_8 = 2; + s->sample_factor_10 = 1; + +#if ARCH_X86 + ff_v210enc_init_x86(s); +#endif +} + +#endif /* AVCODEC_V210ENC_INIT_H */ diff --git a/libavcodec/v210x.c b/libavcodec/v210x.c index 797f229a2..18d3e637b 100644 --- a/libavcodec/v210x.c +++ b/libavcodec/v210x.c @@ -19,6 +19,7 @@ */ #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "libavutil/bswap.h" #include "libavutil/internal.h" @@ -35,11 +36,10 @@ static av_cold int decode_init(AVCodecContext *avctx) return 0; } -static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *pic, + int *got_frame, AVPacket *avpkt) { const uint32_t *src = (const uint32_t *)avpkt->data; - AVFrame *pic = data; int width = avctx->width; int y = 0; uint16_t *ydst, *udst, *vdst, *yend; @@ -119,13 +119,13 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, return avpkt->size; } -const AVCodec ff_v210x_decoder = { - .name = "v210x", - .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_V210X, +const FFCodec ff_v210x_decoder = { + .p.name = "v210x", + .p.long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_V210X, .init = decode_init, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/v308dec.c b/libavcodec/v308dec.c index d059474b3..5f8cbc634 100644 --- a/libavcodec/v308dec.c +++ b/libavcodec/v308dec.c @@ -20,6 +20,7 @@ */ #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" static av_cold int v308_decode_init(AVCodecContext *avctx) @@ -32,10 +33,9 @@ static av_cold int v308_decode_init(AVCodecContext *avctx) return 0; } -static int v308_decode_frame(AVCodecContext *avctx, void *data, +static int v308_decode_frame(AVCodecContext *avctx, AVFrame *pic, int *got_frame, AVPacket *avpkt) { - AVFrame *pic = data; const uint8_t *src = avpkt->data; uint8_t *y, *u, *v; int i, j, ret; @@ -72,13 +72,13 @@ static int v308_decode_frame(AVCodecContext *avctx, void *data, return avpkt->size; } -const AVCodec ff_v308_decoder = { - .name = "v308", - .long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed 4:4:4"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_V308, +const FFCodec ff_v308_decoder = { + .p.name = "v308", + .p.long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed 4:4:4"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_V308, .init = v308_decode_init, - .decode = v308_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(v308_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/v308enc.c b/libavcodec/v308enc.c index 85fb20729..c4f07a123 100644 --- a/libavcodec/v308enc.c +++ b/libavcodec/v308enc.c @@ -22,6 +22,7 @@ #include "libavutil/intreadwrite.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" #include "internal.h" @@ -69,14 +70,14 @@ static int v308_encode_frame(AVCodecContext *avctx, AVPacket *pkt, return 0; } -const AVCodec ff_v308_encoder = { - .name = "v308", - .long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed 4:4:4"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_V308, - .capabilities = AV_CODEC_CAP_DR1, +const FFCodec ff_v308_encoder = { + .p.name = "v308", + .p.long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed 4:4:4"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_V308, + .p.capabilities = AV_CODEC_CAP_DR1, .init = v308_encode_init, - .encode2 = v308_encode_frame, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV444P, AV_PIX_FMT_NONE }, + FF_CODEC_ENCODE_CB(v308_encode_frame), + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV444P, AV_PIX_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/v408dec.c b/libavcodec/v408dec.c index 749b3b65e..02024959c 100644 --- a/libavcodec/v408dec.c +++ b/libavcodec/v408dec.c @@ -19,7 +19,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" static av_cold int v408_decode_init(AVCodecContext *avctx) @@ -29,10 +32,9 @@ static av_cold int v408_decode_init(AVCodecContext *avctx) return 0; } -static int v408_decode_frame(AVCodecContext *avctx, void *data, +static int v408_decode_frame(AVCodecContext *avctx, AVFrame *pic, int *got_frame, AVPacket *avpkt) { - AVFrame *pic = data; const uint8_t *src = avpkt->data; uint8_t *y, *u, *v, *a; int i, j, ret; @@ -80,26 +82,26 @@ static int v408_decode_frame(AVCodecContext *avctx, void *data, } #if CONFIG_AYUV_DECODER -const AVCodec ff_ayuv_decoder = { - .name = "ayuv", - .long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed MS 4:4:4:4"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_AYUV, +const FFCodec ff_ayuv_decoder = { + .p.name = "ayuv", + .p.long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed MS 4:4:4:4"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_AYUV, .init = v408_decode_init, - .decode = v408_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(v408_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_V408_DECODER -const AVCodec ff_v408_decoder = { - .name = "v408", - .long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed QT 4:4:4:4"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_V408, +const FFCodec ff_v408_decoder = { + .p.name = "v408", + .p.long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed QT 4:4:4:4"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_V408, .init = v408_decode_init, - .decode = v408_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(v408_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif diff --git a/libavcodec/v408enc.c b/libavcodec/v408enc.c index 31bf48406..157ed8510 100644 --- a/libavcodec/v408enc.c +++ b/libavcodec/v408enc.c @@ -20,8 +20,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/intreadwrite.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" #include "internal.h" @@ -77,28 +80,28 @@ static int v408_encode_frame(AVCodecContext *avctx, AVPacket *pkt, static const enum AVPixelFormat pix_fmt[] = { AV_PIX_FMT_YUVA444P, AV_PIX_FMT_NONE }; #if CONFIG_AYUV_ENCODER -const AVCodec ff_ayuv_encoder = { - .name = "ayuv", - .long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed MS 4:4:4:4"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_AYUV, - .capabilities = AV_CODEC_CAP_DR1, +const FFCodec ff_ayuv_encoder = { + .p.name = "ayuv", + .p.long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed MS 4:4:4:4"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_AYUV, + .p.capabilities = AV_CODEC_CAP_DR1, .init = v408_encode_init, - .encode2 = v408_encode_frame, - .pix_fmts = pix_fmt, + FF_CODEC_ENCODE_CB(v408_encode_frame), + .p.pix_fmts = pix_fmt, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif #if CONFIG_V408_ENCODER -const AVCodec ff_v408_encoder = { - .name = "v408", - .long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed QT 4:4:4:4"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_V408, - .capabilities = AV_CODEC_CAP_DR1, +const FFCodec ff_v408_encoder = { + .p.name = "v408", + .p.long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed QT 4:4:4:4"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_V408, + .p.capabilities = AV_CODEC_CAP_DR1, .init = v408_encode_init, - .encode2 = v408_encode_frame, - .pix_fmts = pix_fmt, + FF_CODEC_ENCODE_CB(v408_encode_frame), + .p.pix_fmts = pix_fmt, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; #endif diff --git a/libavcodec/v410dec.c b/libavcodec/v410dec.c index c23f84942..e67cb820b 100644 --- a/libavcodec/v410dec.c +++ b/libavcodec/v410dec.c @@ -23,12 +23,12 @@ #include "libavutil/common.h" #include "libavutil/intreadwrite.h" #include "avcodec.h" -#include "internal.h" +#include "codec_internal.h" #include "thread.h" typedef struct ThreadData { AVFrame *frame; - uint8_t *buf; + const uint8_t *buf; int stride; } ThreadData; @@ -85,13 +85,11 @@ static int v410_decode_slice(AVCodecContext *avctx, void *arg, int jobnr, int th return 0; } -static int v410_decode_frame(AVCodecContext *avctx, void *data, +static int v410_decode_frame(AVCodecContext *avctx, AVFrame *pic, int *got_frame, AVPacket *avpkt) { ThreadData td; - ThreadFrame frame = { .f = data }; - AVFrame *pic = data; - uint8_t *src = avpkt->data; + const uint8_t *src = avpkt->data; int ret; int thread_count = av_clip(avctx->thread_count, 1, avctx->height/4); @@ -101,7 +99,7 @@ static int v410_decode_frame(AVCodecContext *avctx, void *data, return AVERROR(EINVAL); } - if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, pic, 0)) < 0) return ret; pic->key_frame = 1; @@ -116,14 +114,14 @@ static int v410_decode_frame(AVCodecContext *avctx, void *data, return avpkt->size; } -const AVCodec ff_v410_decoder = { - .name = "v410", - .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:4:4 10-bit"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_V410, +const FFCodec ff_v410_decoder = { + .p.name = "v410", + .p.long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:4:4 10-bit"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_V410, .init = v410_decode_init, - .decode = v410_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS | + FF_CODEC_DECODE_CB(v410_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/v410enc.c b/libavcodec/v410enc.c index d14ecd5d2..88a2ce346 100644 --- a/libavcodec/v410enc.c +++ b/libavcodec/v410enc.c @@ -23,6 +23,7 @@ #include "libavutil/common.h" #include "libavutil/intreadwrite.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" #include "internal.h" @@ -73,14 +74,14 @@ static int v410_encode_frame(AVCodecContext *avctx, AVPacket *pkt, return 0; } -const AVCodec ff_v410_encoder = { - .name = "v410", - .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:4:4 10-bit"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_V410, - .capabilities = AV_CODEC_CAP_DR1, +const FFCodec ff_v410_encoder = { + .p.name = "v410", + .p.long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:4:4 10-bit"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_V410, + .p.capabilities = AV_CODEC_CAP_DR1, .init = v410_encode_init, - .encode2 = v410_encode_frame, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV444P10, AV_PIX_FMT_NONE }, + FF_CODEC_ENCODE_CB(v410_encode_frame), + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV444P10, AV_PIX_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/v4l2_buffers.c b/libavcodec/v4l2_buffers.c index 4b2679eb3..3f5471067 100644 --- a/libavcodec/v4l2_buffers.c +++ b/libavcodec/v4l2_buffers.c @@ -28,7 +28,6 @@ #include #include #include "libavcodec/avcodec.h" -#include "libavcodec/internal.h" #include "libavutil/pixdesc.h" #include "v4l2_context.h" #include "v4l2_buffers.h" diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c index a181f884d..e891649f9 100644 --- a/libavcodec/v4l2_context.c +++ b/libavcodec/v4l2_context.c @@ -178,7 +178,7 @@ static int v4l2_handle_event(V4L2Context *ctx) V4L2m2mContext *s = ctx_to_m2mctx(ctx); struct v4l2_format cap_fmt = s->capture.format; struct v4l2_event evt = { 0 }; - int reinit, ret; + int ret; ret = ioctl(s->fd, VIDIOC_DQEVENT, &evt); if (ret < 0) { @@ -200,8 +200,7 @@ static int v4l2_handle_event(V4L2Context *ctx) return 0; } - reinit = v4l2_resolution_changed(&s->capture, &cap_fmt); - if (reinit) { + if (v4l2_resolution_changed(&s->capture, &cap_fmt)) { s->capture.height = v4l2_get_height(&cap_fmt); s->capture.width = v4l2_get_width(&cap_fmt); s->capture.sample_aspect_ratio = v4l2_get_sar(&s->capture); @@ -210,28 +209,20 @@ static int v4l2_handle_event(V4L2Context *ctx) return 0; } - if (reinit) - s->reinit = 1; + s->reinit = 1; - if (reinit) { - if (s->avctx) - ret = ff_set_dimensions(s->avctx, s->capture.width, s->capture.height); - if (ret < 0) - av_log(logger(ctx), AV_LOG_WARNING, "update avcodec height and width\n"); + if (s->avctx) + ret = ff_set_dimensions(s->avctx, s->capture.width, s->capture.height); + if (ret < 0) + av_log(logger(ctx), AV_LOG_WARNING, "update avcodec height and width\n"); - ret = ff_v4l2_m2m_codec_reinit(s); - if (ret) { - av_log(logger(ctx), AV_LOG_ERROR, "v4l2_m2m_codec_reinit\n"); - return AVERROR(EINVAL); - } - goto reinit_run; + ret = ff_v4l2_m2m_codec_reinit(s); + if (ret) { + av_log(logger(ctx), AV_LOG_ERROR, "v4l2_m2m_codec_reinit\n"); + return AVERROR(EINVAL); } - /* dummy event received */ - return 0; - /* reinit executed */ -reinit_run: return 1; } diff --git a/libavcodec/v4l2_m2m.c b/libavcodec/v4l2_m2m.c index cdfd57981..984936004 100644 --- a/libavcodec/v4l2_m2m.c +++ b/libavcodec/v4l2_m2m.c @@ -28,7 +28,6 @@ #include #include #include "libavcodec/avcodec.h" -#include "libavcodec/internal.h" #include "libavutil/pixdesc.h" #include "libavutil/imgutils.h" #include "libavutil/pixfmt.h" @@ -245,82 +244,6 @@ int ff_v4l2_m2m_codec_reinit(V4L2m2mContext *s) return 0; } -int ff_v4l2_m2m_codec_full_reinit(V4L2m2mContext *s) -{ - void *log_ctx = s->avctx; - int ret; - - av_log(log_ctx, AV_LOG_DEBUG, "%s full reinit\n", s->devname); - - /* wait for pending buffer references */ - if (atomic_load(&s->refcount)) - while(sem_wait(&s->refsync) == -1 && errno == EINTR); - - ret = ff_v4l2_context_set_status(&s->output, VIDIOC_STREAMOFF); - if (ret) { - av_log(log_ctx, AV_LOG_ERROR, "output VIDIOC_STREAMOFF\n"); - goto error; - } - - ret = ff_v4l2_context_set_status(&s->capture, VIDIOC_STREAMOFF); - if (ret) { - av_log(log_ctx, 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; - - ret = ff_v4l2_context_get_format(&s->output, 0); - if (ret) { - av_log(log_ctx, AV_LOG_DEBUG, "v4l2 output format not supported\n"); - goto error; - } - - ret = ff_v4l2_context_get_format(&s->capture, 0); - if (ret) { - av_log(log_ctx, AV_LOG_DEBUG, "v4l2 capture format not supported\n"); - goto error; - } - - ret = ff_v4l2_context_set_format(&s->output); - if (ret) { - av_log(log_ctx, AV_LOG_ERROR, "can't set v4l2 output format\n"); - goto error; - } - - ret = ff_v4l2_context_set_format(&s->capture); - if (ret) { - av_log(log_ctx, AV_LOG_ERROR, "can't to set v4l2 capture format\n"); - goto error; - } - - ret = ff_v4l2_context_init(&s->output); - if (ret) { - av_log(log_ctx, AV_LOG_ERROR, "no v4l2 output context's buffers\n"); - goto error; - } - - /* decoder's buffers need to be updated at a later stage */ - if (s->avctx && !av_codec_is_decoder(s->avctx->codec)) { - ret = ff_v4l2_context_init(&s->capture); - if (ret) { - av_log(log_ctx, AV_LOG_ERROR, "no v4l2 capture context's buffers\n"); - goto error; - } - } - - return 0; - -error: - return ret; -} - static void v4l2_m2m_destroy_context(void *opaque, uint8_t *context) { V4L2m2mContext *s = (V4L2m2mContext*)context; @@ -328,7 +251,8 @@ static void v4l2_m2m_destroy_context(void *opaque, uint8_t *context) ff_v4l2_context_release(&s->capture); sem_destroy(&s->refsync); - close(s->fd); + if (s->fd >= 0) + close(s->fd); av_frame_unref(s->frame); av_frame_free(&s->frame); av_packet_unref(&s->buf_pkt); diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c index b0c3d30ac..8a51dec3f 100644 --- a/libavcodec/v4l2_m2m_dec.c +++ b/libavcodec/v4l2_m2m_dec.c @@ -27,8 +27,8 @@ #include "libavutil/pixdesc.h" #include "libavutil/opt.h" #include "libavcodec/avcodec.h" +#include "codec_internal.h" #include "libavcodec/decode.h" -#include "libavcodec/internal.h" #include "v4l2_context.h" #include "v4l2_m2m.h" @@ -240,20 +240,20 @@ static const AVOption options[] = { #define M2MDEC(NAME, LONGNAME, CODEC, bsf_name) \ M2MDEC_CLASS(NAME) \ - const AVCodec ff_ ## NAME ## _v4l2m2m_decoder = { \ - .name = #NAME "_v4l2m2m" , \ - .long_name = NULL_IF_CONFIG_SMALL("V4L2 mem2mem " LONGNAME " decoder wrapper"), \ - .type = AVMEDIA_TYPE_VIDEO, \ - .id = CODEC , \ + const FFCodec ff_ ## NAME ## _v4l2m2m_decoder = { \ + .p.name = #NAME "_v4l2m2m" , \ + .p.long_name = NULL_IF_CONFIG_SMALL("V4L2 mem2mem " LONGNAME " decoder wrapper"), \ + .p.type = AVMEDIA_TYPE_VIDEO, \ + .p.id = CODEC , \ .priv_data_size = sizeof(V4L2m2mPriv), \ - .priv_class = &v4l2_m2m_ ## NAME ## _dec_class, \ + .p.priv_class = &v4l2_m2m_ ## NAME ## _dec_class, \ .init = v4l2_decode_init, \ - .receive_frame = v4l2_receive_frame, \ + FF_CODEC_RECEIVE_FRAME_CB(v4l2_receive_frame), \ .close = v4l2_decode_close, \ .bsfs = bsf_name, \ - .capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, \ + .p.capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, \ .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS | FF_CODEC_CAP_INIT_CLEANUP, \ - .wrapper_name = "v4l2m2m", \ + .p.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 043fe80c6..20f81df75 100644 --- a/libavcodec/v4l2_m2m_enc.c +++ b/libavcodec/v4l2_m2m_enc.c @@ -26,10 +26,10 @@ #include #include "encode.h" #include "libavcodec/avcodec.h" -#include "libavcodec/internal.h" #include "libavutil/pixdesc.h" #include "libavutil/pixfmt.h" #include "libavutil/opt.h" +#include "codec_internal.h" #include "profiles.h" #include "v4l2_context.h" #include "v4l2_m2m.h" @@ -405,7 +405,7 @@ static const AVOption options[] = { { NULL }, }; -static const AVCodecDefault v4l2_m2m_defaults[] = { +static const FFCodecDefault v4l2_m2m_defaults[] = { { "qmin", "-1" }, { "qmax", "-1" }, { NULL }, @@ -421,20 +421,20 @@ static const AVCodecDefault v4l2_m2m_defaults[] = { #define M2MENC(NAME, LONGNAME, OPTIONS_NAME, CODEC) \ M2MENC_CLASS(NAME, OPTIONS_NAME) \ - const AVCodec ff_ ## NAME ## _v4l2m2m_encoder = { \ - .name = #NAME "_v4l2m2m" , \ - .long_name = NULL_IF_CONFIG_SMALL("V4L2 mem2mem " LONGNAME " encoder wrapper"), \ - .type = AVMEDIA_TYPE_VIDEO, \ - .id = CODEC , \ + const FFCodec ff_ ## NAME ## _v4l2m2m_encoder = { \ + .p.name = #NAME "_v4l2m2m" , \ + .p.long_name = NULL_IF_CONFIG_SMALL("V4L2 mem2mem " LONGNAME " encoder wrapper"), \ + .p.type = AVMEDIA_TYPE_VIDEO, \ + .p.id = CODEC , \ .priv_data_size = sizeof(V4L2m2mPriv), \ - .priv_class = &v4l2_m2m_ ## NAME ##_enc_class, \ + .p.priv_class = &v4l2_m2m_ ## NAME ##_enc_class, \ .init = v4l2_encode_init, \ - .receive_packet = v4l2_receive_packet, \ + FF_CODEC_RECEIVE_PACKET_CB(v4l2_receive_packet), \ .close = v4l2_encode_close, \ .defaults = v4l2_m2m_defaults, \ - .capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY, \ + .p.capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY, \ .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, \ - .wrapper_name = "v4l2m2m", \ + .p.wrapper_name = "v4l2m2m", \ } M2MENC(mpeg4,"MPEG4", mpeg4_options, AV_CODEC_ID_MPEG4); diff --git a/libavcodec/vaapi_av1.c b/libavcodec/vaapi_av1.c index 5985493b8..63374c31c 100644 --- a/libavcodec/vaapi_av1.c +++ b/libavcodec/vaapi_av1.c @@ -18,14 +18,16 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/frame.h" #include "libavutil/pixdesc.h" #include "hwconfig.h" #include "vaapi_decode.h" #include "internal.h" #include "av1dec.h" +#include "thread.h" typedef struct VAAPIAV1FrameRef { - ThreadFrame frame; + AVFrame *frame; int valid; } VAAPIAV1FrameRef; @@ -40,13 +42,13 @@ typedef struct VAAPIAV1DecContext { * used to apply film grain and push to downstream. */ VAAPIAV1FrameRef ref_tab[AV1_NUM_REF_FRAMES]; - ThreadFrame tmp_frame; + AVFrame *tmp_frame; } VAAPIAV1DecContext; static VASurfaceID vaapi_av1_surface_id(AV1Frame *vf) { if (vf) - return ff_vaapi_get_surface_id(vf->tf.f); + return ff_vaapi_get_surface_id(vf->f); else return VA_INVALID_SURFACE; } @@ -73,16 +75,16 @@ static int vaapi_av1_decode_init(AVCodecContext *avctx) { VAAPIAV1DecContext *ctx = avctx->internal->hwaccel_priv_data; - ctx->tmp_frame.f = av_frame_alloc(); - if (!ctx->tmp_frame.f) { + ctx->tmp_frame = av_frame_alloc(); + if (!ctx->tmp_frame) { av_log(avctx, AV_LOG_ERROR, "Failed to allocate frame.\n"); return AVERROR(ENOMEM); } for (int i = 0; i < FF_ARRAY_ELEMS(ctx->ref_tab); i++) { - ctx->ref_tab[i].frame.f = av_frame_alloc(); - if (!ctx->ref_tab[i].frame.f) { + ctx->ref_tab[i].frame = av_frame_alloc(); + if (!ctx->ref_tab[i].frame) { av_log(avctx, AV_LOG_ERROR, "Failed to allocate reference table frame %d.\n", i); return AVERROR(ENOMEM); @@ -97,14 +99,14 @@ static int vaapi_av1_decode_uninit(AVCodecContext *avctx) { VAAPIAV1DecContext *ctx = avctx->internal->hwaccel_priv_data; - if (ctx->tmp_frame.f->buf[0]) - ff_thread_release_buffer(avctx, &ctx->tmp_frame); - av_frame_free(&ctx->tmp_frame.f); + if (ctx->tmp_frame->buf[0]) + ff_thread_release_buffer(avctx, ctx->tmp_frame); + av_frame_free(&ctx->tmp_frame); for (int i = 0; i < FF_ARRAY_ELEMS(ctx->ref_tab); i++) { - if (ctx->ref_tab[i].frame.f->buf[0]) - ff_thread_release_buffer(avctx, &ctx->ref_tab[i].frame); - av_frame_free(&ctx->ref_tab[i].frame.f); + if (ctx->ref_tab[i].frame->buf[0]) + ff_thread_release_buffer(avctx, ctx->ref_tab[i].frame); + av_frame_free(&ctx->ref_tab[i].frame); } return ff_vaapi_decode_uninit(avctx); @@ -135,12 +137,12 @@ static int vaapi_av1_start_frame(AVCodecContext *avctx, goto fail; if (apply_grain) { - if (ctx->tmp_frame.f->buf[0]) - ff_thread_release_buffer(avctx, &ctx->tmp_frame); - err = ff_thread_get_buffer(avctx, &ctx->tmp_frame, AV_GET_BUFFER_FLAG_REF); + if (ctx->tmp_frame->buf[0]) + ff_thread_release_buffer(avctx, ctx->tmp_frame); + err = ff_thread_get_buffer(avctx, ctx->tmp_frame, AV_GET_BUFFER_FLAG_REF); if (err < 0) goto fail; - pic->output_surface = ff_vaapi_get_surface_id(ctx->tmp_frame.f); + pic->output_surface = ff_vaapi_get_surface_id(ctx->tmp_frame); } else { pic->output_surface = vaapi_av1_surface_id(&s->cur_frame); } @@ -276,7 +278,7 @@ static int vaapi_av1_start_frame(AVCodecContext *avctx, pic_param.ref_frame_map[i] = VA_INVALID_ID; else pic_param.ref_frame_map[i] = ctx->ref_tab[i].valid ? - ff_vaapi_get_surface_id(ctx->ref_tab[i].frame.f) : + ff_vaapi_get_surface_id(ctx->ref_tab[i].frame) : vaapi_av1_surface_id(&s->ref[i]); } for (int i = 0; i < AV1_REFS_PER_FRAME; i++) { @@ -380,11 +382,11 @@ static int vaapi_av1_end_frame(AVCodecContext *avctx) for (int i = 0; i < AV1_NUM_REF_FRAMES; i++) { if (header->refresh_frame_flags & (1 << i)) { - if (ctx->ref_tab[i].frame.f->buf[0]) - ff_thread_release_buffer(avctx, &ctx->ref_tab[i].frame); + if (ctx->ref_tab[i].frame->buf[0]) + ff_thread_release_buffer(avctx, ctx->ref_tab[i].frame); if (apply_grain) { - ret = ff_thread_ref_frame(&ctx->ref_tab[i].frame, &ctx->tmp_frame); + ret = av_frame_ref(ctx->ref_tab[i].frame, ctx->tmp_frame); if (ret < 0) return ret; ctx->ref_tab[i].valid = 1; diff --git a/libavcodec/vaapi_decode.c b/libavcodec/vaapi_decode.c index 665af370e..a7abddb06 100644 --- a/libavcodec/vaapi_decode.c +++ b/libavcodec/vaapi_decode.c @@ -16,6 +16,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/avassert.h" #include "libavutil/common.h" #include "libavutil/pixdesc.h" @@ -650,7 +652,7 @@ int ff_vaapi_decode_init(AVCodecContext *avctx) ctx->hwctx = ctx->device->hwctx; err = vaapi_decode_make_config(avctx, ctx->frames->device_ref, - &ctx->va_config, avctx->hw_frames_ctx); + &ctx->va_config, NULL); if (err) goto fail; diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 3bf379b1a..284ce2988 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -16,6 +16,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include #include @@ -150,11 +152,25 @@ static int vaapi_encode_wait(AVCodecContext *avctx, "(input surface %#x).\n", pic->display_order, pic->encode_order, pic->input_surface); - vas = vaSyncSurface(ctx->hwctx->display, pic->input_surface); - if (vas != VA_STATUS_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to sync to picture completion: " - "%d (%s).\n", vas, vaErrorStr(vas)); - return AVERROR(EIO); +#if VA_CHECK_VERSION(1, 9, 0) + if (ctx->has_sync_buffer_func) { + vas = vaSyncBuffer(ctx->hwctx->display, + pic->output_buffer, + VA_TIMEOUT_INFINITE); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to sync to output buffer completion: " + "%d (%s).\n", vas, vaErrorStr(vas)); + return AVERROR(EIO); + } + } else +#endif + { // If vaSyncBuffer is not implemented, try old version API. + vas = vaSyncSurface(ctx->hwctx->display, pic->input_surface); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to sync to picture completion: " + "%d (%s).\n", vas, vaErrorStr(vas)); + return AVERROR(EIO); + } } // Input is definitely finished with now. @@ -349,6 +365,17 @@ static int vaapi_encode_issue(AVCodecContext *avctx, goto fail; } +#if VA_CHECK_VERSION(1, 5, 0) + if (ctx->max_frame_size) { + err = vaapi_encode_make_misc_param_buffer(avctx, pic, + VAEncMiscParameterTypeMaxFrameSize, + &ctx->mfs_params, + sizeof(ctx->mfs_params)); + if (err < 0) + goto fail; + } +#endif + if (pic->type == PICTURE_TYPE_IDR) { if (ctx->va_packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE && ctx->codec->write_sequence_header) { @@ -951,8 +978,10 @@ static int vaapi_encode_pick_next(AVCodecContext *avctx, if (!pic && ctx->end_of_stream) { --b_counter; pic = ctx->pic_end; - if (pic->encode_issued) + if (pic->encode_complete) return AVERROR_EOF; + else if (pic->encode_issued) + return AVERROR(EAGAIN); } if (!pic) { @@ -1123,7 +1152,8 @@ static int vaapi_encode_send_frame(AVCodecContext *avctx, AVFrame *frame) if (ctx->input_order == ctx->decode_delay) ctx->dts_pts_diff = pic->pts - ctx->first_pts; if (ctx->output_delay > 0) - ctx->ts_ring[ctx->input_order % (3 * ctx->output_delay)] = pic->pts; + ctx->ts_ring[ctx->input_order % + (3 * ctx->output_delay + ctx->async_depth)] = pic->pts; pic->display_order = ctx->input_order; ++ctx->input_order; @@ -1177,18 +1207,47 @@ int ff_vaapi_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt) return AVERROR(EAGAIN); } - pic = NULL; - err = vaapi_encode_pick_next(avctx, &pic); - if (err < 0) - return err; - av_assert0(pic); + if (ctx->has_sync_buffer_func) { + pic = NULL; - pic->encode_order = ctx->encode_order++; + if (av_fifo_can_write(ctx->encode_fifo)) { + err = vaapi_encode_pick_next(avctx, &pic); + if (!err) { + av_assert0(pic); + pic->encode_order = ctx->encode_order + + av_fifo_can_read(ctx->encode_fifo); + err = vaapi_encode_issue(avctx, pic); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Encode failed: %d.\n", err); + return err; + } + av_fifo_write(ctx->encode_fifo, &pic, 1); + } + } - err = vaapi_encode_issue(avctx, pic); - if (err < 0) { - av_log(avctx, AV_LOG_ERROR, "Encode failed: %d.\n", err); - return err; + if (!av_fifo_can_read(ctx->encode_fifo)) + return err; + + // More frames can be buffered + if (av_fifo_can_write(ctx->encode_fifo) && !ctx->end_of_stream) + return AVERROR(EAGAIN); + + av_fifo_read(ctx->encode_fifo, &pic, 1); + ctx->encode_order = pic->encode_order + 1; + } else { + pic = NULL; + err = vaapi_encode_pick_next(avctx, &pic); + if (err < 0) + return err; + av_assert0(pic); + + pic->encode_order = ctx->encode_order++; + + err = vaapi_encode_issue(avctx, pic); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Encode failed: %d.\n", err); + return err; + } } err = vaapi_encode_output(avctx, pic, pkt); @@ -1206,7 +1265,7 @@ int ff_vaapi_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt) pkt->dts = ctx->ts_ring[pic->encode_order] - ctx->dts_pts_diff; } else { pkt->dts = ctx->ts_ring[(pic->encode_order - ctx->decode_delay) % - (3 * ctx->output_delay)]; + (3 * ctx->output_delay + ctx->async_depth)]; } av_log(avctx, AV_LOG_DEBUG, "Output packet: pts %"PRId64" dts %"PRId64".\n", pkt->pts, pkt->dts); @@ -1821,12 +1880,70 @@ rc_mode_found: return 0; } +static av_cold int vaapi_encode_init_max_frame_size(AVCodecContext *avctx) +{ +#if VA_CHECK_VERSION(1, 5, 0) + VAAPIEncodeContext *ctx = avctx->priv_data; + VAConfigAttrib attr = { VAConfigAttribMaxFrameSize }; + VAStatus vas; + + if (ctx->va_rc_mode == VA_RC_CQP) { + ctx->max_frame_size = 0; + av_log(avctx, AV_LOG_ERROR, "Max frame size is invalid in CQP rate " + "control mode.\n"); + return AVERROR(EINVAL); + } + + vas = vaGetConfigAttributes(ctx->hwctx->display, + ctx->va_profile, + ctx->va_entrypoint, + &attr, 1); + if (vas != VA_STATUS_SUCCESS) { + ctx->max_frame_size = 0; + av_log(avctx, AV_LOG_ERROR, "Failed to query max frame size " + "config attribute: %d (%s).\n", vas, vaErrorStr(vas)); + return AVERROR_EXTERNAL; + } + + if (attr.value == VA_ATTRIB_NOT_SUPPORTED) { + ctx->max_frame_size = 0; + av_log(avctx, AV_LOG_ERROR, "Max frame size attribute " + "is not supported.\n"); + return AVERROR(EINVAL); + } else { + VAConfigAttribValMaxFrameSize attr_mfs; + attr_mfs.value = attr.value; + // Prefer to use VAEncMiscParameterTypeMaxFrameSize for max frame size. + if (!attr_mfs.bits.max_frame_size && attr_mfs.bits.multiple_pass) { + ctx->max_frame_size = 0; + av_log(avctx, AV_LOG_ERROR, "Driver only supports multiple pass " + "max frame size which has not been implemented in FFmpeg.\n"); + return AVERROR(EINVAL); + } + + ctx->mfs_params = (VAEncMiscParameterBufferMaxFrameSize){ + .max_frame_size = ctx->max_frame_size * 8, + }; + + av_log(avctx, AV_LOG_VERBOSE, "Set max frame size: %d bytes.\n", + ctx->max_frame_size); + } +#else + av_log(avctx, AV_LOG_ERROR, "The max frame size option is not supported with " + "this VAAPI version.\n"); + return AVERROR(EINVAL); +#endif + + return 0; +} + static av_cold int vaapi_encode_init_gop_structure(AVCodecContext *avctx) { VAAPIEncodeContext *ctx = avctx->priv_data; VAStatus vas; VAConfigAttrib attr = { VAConfigAttribEncMaxRefFrames }; uint32_t ref_l0, ref_l1; + int prediction_pre_only; vas = vaGetConfigAttributes(ctx->hwctx->display, ctx->va_profile, @@ -1845,6 +1962,51 @@ static av_cold int vaapi_encode_init_gop_structure(AVCodecContext *avctx) ref_l1 = attr.value >> 16 & 0xffff; } + ctx->p_to_gpb = 0; + prediction_pre_only = 0; + +#if VA_CHECK_VERSION(1, 9, 0) + if (!(ctx->codec->flags & FLAG_INTRA_ONLY || + avctx->gop_size <= 1)) { + attr = (VAConfigAttrib) { VAConfigAttribPredictionDirection }; + 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 prediction direction " + "attribute: %d (%s).\n", vas, vaErrorStr(vas)); + return AVERROR_EXTERNAL; + } else if (attr.value == VA_ATTRIB_NOT_SUPPORTED) { + av_log(avctx, AV_LOG_VERBOSE, "Driver does not report any additional " + "prediction constraints.\n"); + } else { + if (((ref_l0 > 0 || ref_l1 > 0) && !(attr.value & VA_PREDICTION_DIRECTION_PREVIOUS)) || + ((ref_l1 == 0) && (attr.value & (VA_PREDICTION_DIRECTION_FUTURE | VA_PREDICTION_DIRECTION_BI_NOT_EMPTY)))) { + av_log(avctx, AV_LOG_ERROR, "Driver report incorrect prediction " + "direction attribute.\n"); + return AVERROR_EXTERNAL; + } + + if (!(attr.value & VA_PREDICTION_DIRECTION_FUTURE)) { + if (ref_l0 > 0 && ref_l1 > 0) { + prediction_pre_only = 1; + av_log(avctx, AV_LOG_VERBOSE, "Driver only support same reference " + "lists for B-frames.\n"); + } + } + + if (attr.value & VA_PREDICTION_DIRECTION_BI_NOT_EMPTY) { + if (ref_l0 > 0 && ref_l1 > 0) { + ctx->p_to_gpb = 1; + av_log(avctx, AV_LOG_VERBOSE, "Driver does not support P-frames, " + "replacing them with B-frames.\n"); + } + } + } + } +#endif + if (ctx->codec->flags & FLAG_INTRA_ONLY || avctx->gop_size <= 1) { av_log(avctx, AV_LOG_VERBOSE, "Using intra frames only.\n"); @@ -1854,15 +2016,26 @@ static av_cold int vaapi_encode_init_gop_structure(AVCodecContext *avctx) "reference frames.\n"); return AVERROR(EINVAL); } else if (!(ctx->codec->flags & FLAG_B_PICTURES) || - ref_l1 < 1 || avctx->max_b_frames < 1) { - av_log(avctx, AV_LOG_VERBOSE, "Using intra and P-frames " - "(supported references: %d / %d).\n", ref_l0, ref_l1); + ref_l1 < 1 || avctx->max_b_frames < 1 || + prediction_pre_only) { + if (ctx->p_to_gpb) + av_log(avctx, AV_LOG_VERBOSE, "Using intra and B-frames " + "(supported references: %d / %d).\n", + ref_l0, ref_l1); + else + av_log(avctx, AV_LOG_VERBOSE, "Using intra and P-frames " + "(supported references: %d / %d).\n", ref_l0, ref_l1); ctx->gop_size = avctx->gop_size; ctx->p_per_i = INT_MAX; ctx->b_per_p = 0; } else { - av_log(avctx, AV_LOG_VERBOSE, "Using intra, P- and B-frames " - "(supported references: %d / %d).\n", ref_l0, ref_l1); + if (ctx->p_to_gpb) + av_log(avctx, AV_LOG_VERBOSE, "Using intra and B-frames " + "(supported references: %d / %d).\n", + ref_l0, ref_l1); + else + av_log(avctx, AV_LOG_VERBOSE, "Using intra, P- and B-frames " + "(supported references: %d / %d).\n", ref_l0, ref_l1); ctx->gop_size = avctx->gop_size; ctx->p_per_i = INT_MAX; ctx->b_per_p = avctx->max_b_frames; @@ -2012,6 +2185,8 @@ static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx) return 0; } + av_assert0(ctx->slice_block_height > 0 && ctx->slice_block_width > 0); + ctx->slice_block_rows = (avctx->height + ctx->slice_block_height - 1) / ctx->slice_block_height; ctx->slice_block_cols = (avctx->width + ctx->slice_block_width - 1) / @@ -2401,6 +2576,20 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx) if (err < 0) goto fail; + if (ctx->codec->get_encoder_caps) { + err = ctx->codec->get_encoder_caps(avctx); + if (err < 0) + goto fail; + } else { + // Assume 16x16 blocks. + ctx->surface_width = FFALIGN(avctx->width, 16); + ctx->surface_height = FFALIGN(avctx->height, 16); + if (ctx->codec->flags & FLAG_SLICE_CONTROL) { + ctx->slice_block_width = 16; + ctx->slice_block_height = 16; + } + } + err = vaapi_encode_init_rate_control(avctx); if (err < 0) goto fail; @@ -2427,6 +2616,12 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx) goto fail; } + if (ctx->max_frame_size) { + err = vaapi_encode_init_max_frame_size(avctx); + if (err < 0) + goto fail; + } + vas = vaCreateConfig(ctx->hwctx->display, ctx->va_profile, ctx->va_entrypoint, ctx->config_attributes, ctx->nb_config_attributes, @@ -2522,6 +2717,19 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx) } } +#if VA_CHECK_VERSION(1, 9, 0) + // check vaSyncBuffer function + vas = vaSyncBuffer(ctx->hwctx->display, VA_INVALID_ID, 0); + if (vas != VA_STATUS_ERROR_UNIMPLEMENTED) { + ctx->has_sync_buffer_func = 1; + ctx->encode_fifo = av_fifo_alloc2(ctx->async_depth, + sizeof(VAAPIEncodePicture *), + 0); + if (!ctx->encode_fifo) + return AVERROR(ENOMEM); + } +#endif + return 0; fail: @@ -2559,6 +2767,7 @@ av_cold int ff_vaapi_encode_close(AVCodecContext *avctx) av_freep(&ctx->codec_sequence_params); av_freep(&ctx->codec_picture_params); + av_fifo_freep2(&ctx->encode_fifo); av_buffer_unref(&ctx->recon_frames_ref); av_buffer_unref(&ctx->input_frames_ref); diff --git a/libavcodec/vaapi_encode.h b/libavcodec/vaapi_encode.h index b41604a88..359f954ff 100644 --- a/libavcodec/vaapi_encode.h +++ b/libavcodec/vaapi_encode.h @@ -29,6 +29,7 @@ #include "libavutil/hwcontext.h" #include "libavutil/hwcontext_vaapi.h" +#include "libavutil/fifo.h" #include "avcodec.h" #include "hwconfig.h" @@ -47,6 +48,7 @@ enum { MAX_TILE_ROWS = 22, // A.4.1: table A.6 allows at most 20 tile columns for any level. MAX_TILE_COLS = 20, + MAX_ASYNC_DEPTH = 64, }; extern const AVCodecHWConfigInternal *const ff_vaapi_encode_hw_configs[]; @@ -189,6 +191,9 @@ typedef struct VAAPIEncodeContext { // Desired B frame reference depth. int desired_b_depth; + // Max Frame Size + int max_frame_size; + // Explicitly set RC mode (otherwise attempt to pick from // available modes). int explicit_rc_mode; @@ -266,6 +271,7 @@ typedef struct VAAPIEncodeContext { VAEncMiscParameterRateControl rc_params; VAEncMiscParameterHRD hrd_params; VAEncMiscParameterFrameRate fr_params; + VAEncMiscParameterBufferMaxFrameSize mfs_params; #if VA_CHECK_VERSION(0, 36, 0) VAEncMiscParameterBufferQualityLevel quality_params; #endif @@ -297,7 +303,8 @@ typedef struct VAAPIEncodeContext { // Timestamp handling. int64_t first_pts; int64_t dts_pts_diff; - int64_t ts_ring[MAX_REORDER_DELAY * 3]; + int64_t ts_ring[MAX_REORDER_DELAY * 3 + + MAX_ASYNC_DEPTH]; // Slice structure. int slice_block_rows; @@ -328,6 +335,7 @@ typedef struct VAAPIEncodeContext { int idr_counter; int gop_counter; int end_of_stream; + int p_to_gpb; // Whether the driver supports ROI at all. int roi_allowed; @@ -345,6 +353,13 @@ typedef struct VAAPIEncodeContext { int roi_warned; AVFrame *frame; + + // Whether the driver support vaSyncBuffer + int has_sync_buffer_func; + // Store buffered pic + AVFifo *encode_fifo; + // Max number of frame buffered in encoder. + int async_depth; } VAAPIEncodeContext; enum { @@ -375,6 +390,13 @@ typedef struct VAAPIEncodeType { // factor depending on RC mode. int default_quality; + // Determine encode parameters like block sizes for surface alignment + // and slices. This may need to query the profile and entrypoint, + // which will be available when this function is called. If not set, + // assume that all blocks are 16x16 and that surfaces should be + // aligned to match this. + int (*get_encoder_caps)(AVCodecContext *avctx); + // Perform any extra codec-specific configuration after the // codec context is initialised (set up the private data and // add any necessary global parameters). @@ -455,7 +477,16 @@ int ff_vaapi_encode_close(AVCodecContext *avctx); { "b_depth", \ "Maximum B-frame reference depth", \ OFFSET(common.desired_b_depth), AV_OPT_TYPE_INT, \ - { .i64 = 1 }, 1, INT_MAX, FLAGS } + { .i64 = 1 }, 1, INT_MAX, FLAGS }, \ + { "async_depth", "Maximum processing parallelism. " \ + "Increase this to improve single channel performance. This option " \ + "doesn't work if driver doesn't implement vaSyncBuffer function.", \ + OFFSET(common.async_depth), AV_OPT_TYPE_INT, \ + { .i64 = 2 }, 1, MAX_ASYNC_DEPTH, FLAGS }, \ + { "max_frame_size", \ + "Maximum frame size (in bytes)",\ + OFFSET(common.max_frame_size), AV_OPT_TYPE_INT, \ + { .i64 = 0 }, 0, INT_MAX, FLAGS } #define VAAPI_ENCODE_RC_MODE(name, desc) \ { #name, desc, 0, AV_OPT_TYPE_CONST, { .i64 = RC_MODE_ ## name }, \ diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c index ff37de1f7..7a6b54ab6 100644 --- a/libavcodec/vaapi_encode_h264.c +++ b/libavcodec/vaapi_encode_h264.c @@ -29,11 +29,12 @@ #include "avcodec.h" #include "cbs.h" #include "cbs_h264.h" +#include "codec_internal.h" #include "h264.h" #include "h264_levels.h" #include "h264_sei.h" -#include "internal.h" #include "vaapi_encode.h" +#include "version.h" enum { SEI_TIMING = 0x01, @@ -1304,7 +1305,7 @@ static const AVOption vaapi_encode_h264_options[] = { { NULL }, }; -static const AVCodecDefault vaapi_encode_h264_defaults[] = { +static const FFCodecDefault vaapi_encode_h264_defaults[] = { { "b", "0" }, { "bf", "2" }, { "g", "120" }, @@ -1324,24 +1325,24 @@ static const AVClass vaapi_encode_h264_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_h264_vaapi_encoder = { - .name = "h264_vaapi", - .long_name = NULL_IF_CONFIG_SMALL("H.264/AVC (VAAPI)"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_H264, +const FFCodec ff_h264_vaapi_encoder = { + .p.name = "h264_vaapi", + .p.long_name = NULL_IF_CONFIG_SMALL("H.264/AVC (VAAPI)"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_H264, .priv_data_size = sizeof(VAAPIEncodeH264Context), .init = &vaapi_encode_h264_init, - .receive_packet = &ff_vaapi_encode_receive_packet, + FF_CODEC_RECEIVE_PACKET_CB(&ff_vaapi_encode_receive_packet), .close = &vaapi_encode_h264_close, - .priv_class = &vaapi_encode_h264_class, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | + .p.priv_class = &vaapi_encode_h264_class, + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .defaults = vaapi_encode_h264_defaults, - .pix_fmts = (const enum AVPixelFormat[]) { + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_VAAPI, AV_PIX_FMT_NONE, }, .hw_configs = ff_vaapi_encode_hw_configs, - .wrapper_name = "vaapi", + .p.wrapper_name = "vaapi", }; diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c index e1dc53dfa..456307d57 100644 --- a/libavcodec/vaapi_encode_h265.c +++ b/libavcodec/vaapi_encode_h265.c @@ -30,10 +30,10 @@ #include "avcodec.h" #include "cbs.h" #include "cbs_h265.h" +#include "codec_internal.h" #include "h265_profile_level.h" #include "hevc.h" #include "hevc_sei.h" -#include "internal.h" #include "put_bits.h" #include "vaapi_encode.h" @@ -55,6 +55,13 @@ typedef struct VAAPIEncodeH265Picture { typedef struct VAAPIEncodeH265Context { VAAPIEncodeContext common; + // Encoder features. + uint32_t va_features; + // Block size info. + uint32_t va_bs; + uint32_t ctu_size; + uint32_t min_cb_size; + // User options. int qp; int aud; @@ -299,17 +306,21 @@ static int vaapi_encode_h265_init_sequence_params(AVCodecContext *avctx) ptl->general_profile_idc = avctx->profile; ptl->general_tier_flag = priv->tier; - if (chroma_format == 1) { - ptl->general_profile_compatibility_flag[1] = bit_depth == 8; - ptl->general_profile_compatibility_flag[2] = bit_depth <= 10; + ptl->general_profile_compatibility_flag[ptl->general_profile_idc] = 1; + + if (ptl->general_profile_compatibility_flag[1]) + ptl->general_profile_compatibility_flag[2] = 1; + if (ptl->general_profile_compatibility_flag[3]) { + ptl->general_profile_compatibility_flag[1] = 1; + ptl->general_profile_compatibility_flag[2] = 1; } - ptl->general_profile_compatibility_flag[4] = 1; ptl->general_progressive_source_flag = 1; ptl->general_interlaced_source_flag = 0; ptl->general_non_packed_constraint_flag = 1; ptl->general_frame_only_constraint_flag = 1; + ptl->general_max_14bit_constraint_flag = bit_depth <= 14; ptl->general_max_12bit_constraint_flag = bit_depth <= 12; ptl->general_max_10bit_constraint_flag = bit_depth <= 10; ptl->general_max_8bit_constraint_flag = bit_depth == 8; @@ -319,6 +330,7 @@ static int vaapi_encode_h265_init_sequence_params(AVCodecContext *avctx) ptl->general_max_monochrome_constraint_flag = chroma_format == 0; ptl->general_intra_constraint_flag = ctx->gop_size == 1; + ptl->general_one_picture_only_constraint_flag = 0; ptl->general_lower_bit_rate_constraint_flag = 1; @@ -418,9 +430,9 @@ static int vaapi_encode_h265_init_sequence_params(AVCodecContext *avctx) 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. + // These values come from the capabilities of the first encoder + // implementation in the i965 driver on Intel Skylake. They may + // fail badly with other platforms or drivers. // 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; @@ -438,6 +450,42 @@ static int vaapi_encode_h265_init_sequence_params(AVCodecContext *avctx) sps->pcm_enabled_flag = 0; +// update sps setting according to queried result +#if VA_CHECK_VERSION(1, 13, 0) + if (priv->va_features) { + VAConfigAttribValEncHEVCFeatures features = { .value = priv->va_features }; + + // Enable feature if get queried result is VA_FEATURE_SUPPORTED | VA_FEATURE_REQUIRED + sps->amp_enabled_flag = + !!features.bits.amp; + sps->sample_adaptive_offset_enabled_flag = + !!features.bits.sao; + sps->sps_temporal_mvp_enabled_flag = + !!features.bits.temporal_mvp; + sps->pcm_enabled_flag = + !!features.bits.pcm; + } + + if (priv->va_bs) { + VAConfigAttribValEncHEVCBlockSizes bs = { .value = priv->va_bs }; + sps->log2_min_luma_coding_block_size_minus3 = + ff_ctz(priv->min_cb_size) - 3; + sps->log2_diff_max_min_luma_coding_block_size = + ff_ctz(priv->ctu_size) - ff_ctz(priv->min_cb_size); + + sps->log2_min_luma_transform_block_size_minus2 = + bs.bits.log2_min_luma_transform_block_size_minus2; + sps->log2_diff_max_min_luma_transform_block_size = + bs.bits.log2_max_luma_transform_block_size_minus2 - + bs.bits.log2_min_luma_transform_block_size_minus2; + + sps->max_transform_hierarchy_depth_inter = + bs.bits.max_max_transform_hierarchy_depth_inter; + sps->max_transform_hierarchy_depth_intra = + bs.bits.max_max_transform_hierarchy_depth_intra; + } +#endif + // 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. @@ -530,6 +578,23 @@ static int vaapi_encode_h265_init_sequence_params(AVCodecContext *avctx) pps->cu_qp_delta_enabled_flag = (ctx->va_rc_mode != VA_RC_CQP); pps->diff_cu_qp_delta_depth = 0; +// update pps setting according to queried result +#if VA_CHECK_VERSION(1, 13, 0) + if (priv->va_features) { + VAConfigAttribValEncHEVCFeatures features = { .value = priv->va_features }; + if (ctx->va_rc_mode != VA_RC_CQP) + pps->cu_qp_delta_enabled_flag = + !!features.bits.cu_qp_delta; + + pps->transform_skip_enabled_flag = + !!features.bits.transform_skip; + // set diff_cu_qp_delta_depth as its max value if cu_qp_delta enabled. Otherwise + // 0 will make cu_qp_delta invalid. + if (pps->cu_qp_delta_enabled_flag) + pps->diff_cu_qp_delta_depth = sps->log2_diff_max_min_luma_coding_block_size; + } +#endif + if (ctx->tile_rows && ctx->tile_cols) { int uniform_spacing; @@ -631,8 +696,8 @@ static int vaapi_encode_h265_init_sequence_params(AVCodecContext *avctx) .coded_buf = VA_INVALID_ID, - .collocated_ref_pic_index = 0xff, - + .collocated_ref_pic_index = sps->sps_temporal_mvp_enabled_flag ? + 0 : 0xff, .last_picture = 0, .pic_init_qp = pps->init_qp_minus26 + 26, @@ -665,6 +730,8 @@ static int vaapi_encode_h265_init_sequence_params(AVCodecContext *avctx) .entropy_coding_sync_enabled_flag = pps->entropy_coding_sync_enabled_flag, .loop_filter_across_tiles_enabled_flag = pps->loop_filter_across_tiles_enabled_flag, + .pps_loop_filter_across_slices_enabled_flag = + pps->pps_loop_filter_across_slices_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, @@ -886,6 +953,7 @@ static int vaapi_encode_h265_init_slice_params(AVCodecContext *avctx, VAAPIEncodePicture *pic, VAAPIEncodeSlice *slice) { + VAAPIEncodeContext *ctx = avctx->priv_data; VAAPIEncodeH265Context *priv = avctx->priv_data; VAAPIEncodeH265Picture *hpic = pic->priv_data; const H265RawSPS *sps = &priv->raw_sps; @@ -908,6 +976,9 @@ static int vaapi_encode_h265_init_slice_params(AVCodecContext *avctx, sh->slice_type = hpic->slice_type; + if (sh->slice_type == HEVC_SLICE_P && ctx->p_to_gpb) + sh->slice_type = HEVC_SLICE_B; + sh->slice_pic_order_cnt_lsb = hpic->pic_order_cnt & (1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4)) - 1; @@ -988,10 +1059,13 @@ static int vaapi_encode_h265_init_slice_params(AVCodecContext *avctx, sh->num_long_term_sps = 0; sh->num_long_term_pics = 0; + // when this flag is not present, it is inerred to 1. + sh->collocated_from_l0_flag = 1; 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; + if (sh->slice_type == HEVC_SLICE_B) + sh->collocated_from_l0_flag = 1; sh->collocated_ref_idx = 0; } @@ -1066,6 +1140,9 @@ static int vaapi_encode_h265_init_slice_params(AVCodecContext *avctx, av_assert0(pic->type == PICTURE_TYPE_P || pic->type == PICTURE_TYPE_B); vslice->ref_pic_list0[0] = vpic->reference_frames[0]; + if (ctx->p_to_gpb && pic->type == PICTURE_TYPE_P) + // Reference for GPB B-frame, L0 == L1 + vslice->ref_pic_list1[0] = vpic->reference_frames[0]; } if (pic->nb_refs >= 2) { // Forward reference for B-frame. @@ -1073,6 +1150,76 @@ static int vaapi_encode_h265_init_slice_params(AVCodecContext *avctx, vslice->ref_pic_list1[0] = vpic->reference_frames[1]; } + if (pic->type == PICTURE_TYPE_P && ctx->p_to_gpb) { + vslice->slice_type = HEVC_SLICE_B; + for (i = 0; i < FF_ARRAY_ELEMS(vslice->ref_pic_list0); i++) { + vslice->ref_pic_list1[i].picture_id = vslice->ref_pic_list0[i].picture_id; + vslice->ref_pic_list1[i].flags = vslice->ref_pic_list0[i].flags; + } + } + + return 0; +} + +static av_cold int vaapi_encode_h265_get_encoder_caps(AVCodecContext *avctx) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + VAAPIEncodeH265Context *priv = avctx->priv_data; + +#if VA_CHECK_VERSION(1, 13, 0) + { + VAConfigAttribValEncHEVCBlockSizes block_size; + VAConfigAttrib attr; + VAStatus vas; + + attr.type = VAConfigAttribEncHEVCFeatures; + vas = vaGetConfigAttributes(ctx->hwctx->display, ctx->va_profile, + ctx->va_entrypoint, &attr, 1); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to query encoder " + "features, using guessed defaults.\n"); + return AVERROR_EXTERNAL; + } else if (attr.value == VA_ATTRIB_NOT_SUPPORTED) { + av_log(avctx, AV_LOG_WARNING, "Driver does not advertise " + "encoder features, using guessed defaults.\n"); + } else { + priv->va_features = attr.value; + } + + attr.type = VAConfigAttribEncHEVCBlockSizes; + vas = vaGetConfigAttributes(ctx->hwctx->display, ctx->va_profile, + ctx->va_entrypoint, &attr, 1); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to query encoder " + "block size, using guessed defaults.\n"); + return AVERROR_EXTERNAL; + } else if (attr.value == VA_ATTRIB_NOT_SUPPORTED) { + av_log(avctx, AV_LOG_WARNING, "Driver does not advertise " + "encoder block size, using guessed defaults.\n"); + } else { + priv->va_bs = block_size.value = attr.value; + + priv->ctu_size = + 1 << block_size.bits.log2_max_coding_tree_block_size_minus3 + 3; + priv->min_cb_size = + 1 << block_size.bits.log2_min_luma_coding_block_size_minus3 + 3; + } + } +#endif + + if (!priv->ctu_size) { + priv->ctu_size = 32; + priv->min_cb_size = 16; + } + av_log(avctx, AV_LOG_VERBOSE, "Using CTU size %dx%d, " + "min CB size %dx%d.\n", priv->ctu_size, priv->ctu_size, + priv->min_cb_size, priv->min_cb_size); + + ctx->surface_width = FFALIGN(avctx->width, priv->min_cb_size); + ctx->surface_height = FFALIGN(avctx->height, priv->min_cb_size); + + ctx->slice_block_width = ctx->slice_block_height = priv->ctu_size; + return 0; } @@ -1145,6 +1292,7 @@ static const VAAPIEncodeType vaapi_encode_type_h265 = { .default_quality = 25, + .get_encoder_caps = &vaapi_encode_h265_get_encoder_caps, .configure = &vaapi_encode_h265_configure, .picture_priv_data_size = sizeof(VAAPIEncodeH265Picture), @@ -1190,12 +1338,6 @@ static av_cold int vaapi_encode_h265_init(AVCodecContext *avctx) VA_ENC_PACKED_HEADER_SLICE | // Slice headers. VA_ENC_PACKED_HEADER_MISC; // SEI - ctx->surface_width = FFALIGN(avctx->width, 16); - ctx->surface_height = FFALIGN(avctx->height, 16); - - // CTU size is currently hard-coded to 32. - ctx->slice_block_width = ctx->slice_block_height = 32; - if (priv->qp > 0) ctx->explicit_qp = priv->qp; @@ -1282,7 +1424,7 @@ static const AVOption vaapi_encode_h265_options[] = { { NULL }, }; -static const AVCodecDefault vaapi_encode_h265_defaults[] = { +static const FFCodecDefault vaapi_encode_h265_defaults[] = { { "b", "0" }, { "bf", "2" }, { "g", "120" }, @@ -1302,24 +1444,24 @@ static const AVClass vaapi_encode_h265_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_hevc_vaapi_encoder = { - .name = "hevc_vaapi", - .long_name = NULL_IF_CONFIG_SMALL("H.265/HEVC (VAAPI)"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_HEVC, +const FFCodec ff_hevc_vaapi_encoder = { + .p.name = "hevc_vaapi", + .p.long_name = NULL_IF_CONFIG_SMALL("H.265/HEVC (VAAPI)"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_HEVC, .priv_data_size = sizeof(VAAPIEncodeH265Context), .init = &vaapi_encode_h265_init, - .receive_packet = &ff_vaapi_encode_receive_packet, + FF_CODEC_RECEIVE_PACKET_CB(&ff_vaapi_encode_receive_packet), .close = &vaapi_encode_h265_close, - .priv_class = &vaapi_encode_h265_class, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | + .p.priv_class = &vaapi_encode_h265_class, + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .defaults = vaapi_encode_h265_defaults, - .pix_fmts = (const enum AVPixelFormat[]) { + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_VAAPI, AV_PIX_FMT_NONE, }, .hw_configs = ff_vaapi_encode_hw_configs, - .wrapper_name = "vaapi", + .p.wrapper_name = "vaapi", }; diff --git a/libavcodec/vaapi_encode_mjpeg.c b/libavcodec/vaapi_encode_mjpeg.c index 6206b23e5..92960145a 100644 --- a/libavcodec/vaapi_encode_mjpeg.c +++ b/libavcodec/vaapi_encode_mjpeg.c @@ -29,7 +29,7 @@ #include "bytestream.h" #include "cbs.h" #include "cbs_jpeg.h" -#include "internal.h" +#include "codec_internal.h" #include "jpegtables.h" #include "mjpeg.h" #include "put_bits.h" @@ -434,6 +434,20 @@ static int vaapi_encode_mjpeg_init_slice_params(AVCodecContext *avctx, return 0; } +static av_cold int vaapi_encode_mjpeg_get_encoder_caps(AVCodecContext *avctx) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + const AVPixFmtDescriptor *desc; + + desc = av_pix_fmt_desc_get(ctx->input_frames->sw_format); + av_assert0(desc); + + ctx->surface_width = FFALIGN(avctx->width, 8 << desc->log2_chroma_w); + ctx->surface_height = FFALIGN(avctx->height, 8 << desc->log2_chroma_h); + + return 0; +} + static av_cold int vaapi_encode_mjpeg_configure(AVCodecContext *avctx) { VAAPIEncodeContext *ctx = avctx->priv_data; @@ -483,6 +497,7 @@ static const VAAPIEncodeType vaapi_encode_type_mjpeg = { .flags = FLAG_CONSTANT_QUALITY_ONLY | FLAG_INTRA_ONLY, + .get_encoder_caps = &vaapi_encode_mjpeg_get_encoder_caps, .configure = &vaapi_encode_mjpeg_configure, .default_quality = 80, @@ -509,9 +524,6 @@ static av_cold int vaapi_encode_mjpeg_init(AVCodecContext *avctx) ctx->desired_packed_headers = VA_ENC_PACKED_HEADER_RAW_DATA; - ctx->surface_width = FFALIGN(avctx->width, 8); - ctx->surface_height = FFALIGN(avctx->height, 8); - return ff_vaapi_encode_init(avctx); } @@ -540,7 +552,7 @@ static const AVOption vaapi_encode_mjpeg_options[] = { { NULL }, }; -static const AVCodecDefault vaapi_encode_mjpeg_defaults[] = { +static const FFCodecDefault vaapi_encode_mjpeg_defaults[] = { { "b", "0" }, { NULL }, }; @@ -552,23 +564,23 @@ static const AVClass vaapi_encode_mjpeg_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_mjpeg_vaapi_encoder = { - .name = "mjpeg_vaapi", - .long_name = NULL_IF_CONFIG_SMALL("MJPEG (VAAPI)"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MJPEG, +const FFCodec ff_mjpeg_vaapi_encoder = { + .p.name = "mjpeg_vaapi", + .p.long_name = NULL_IF_CONFIG_SMALL("MJPEG (VAAPI)"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MJPEG, .priv_data_size = sizeof(VAAPIEncodeMJPEGContext), .init = &vaapi_encode_mjpeg_init, - .receive_packet = &ff_vaapi_encode_receive_packet, + FF_CODEC_RECEIVE_PACKET_CB(&ff_vaapi_encode_receive_packet), .close = &vaapi_encode_mjpeg_close, - .priv_class = &vaapi_encode_mjpeg_class, - .capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DR1, + .p.priv_class = &vaapi_encode_mjpeg_class, + .p.capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .defaults = vaapi_encode_mjpeg_defaults, - .pix_fmts = (const enum AVPixelFormat[]) { + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_VAAPI, AV_PIX_FMT_NONE, }, .hw_configs = ff_vaapi_encode_hw_configs, - .wrapper_name = "vaapi", + .p.wrapper_name = "vaapi", }; diff --git a/libavcodec/vaapi_encode_mpeg2.c b/libavcodec/vaapi_encode_mpeg2.c index af3a63dab..01d1b2490 100644 --- a/libavcodec/vaapi_encode_mpeg2.c +++ b/libavcodec/vaapi_encode_mpeg2.c @@ -20,10 +20,12 @@ #include #include "libavutil/avassert.h" +#include "libavutil/opt.h" #include "avcodec.h" #include "cbs.h" #include "cbs_mpeg2.h" +#include "codec_internal.h" #include "mpeg12.h" #include "vaapi_encode.h" @@ -621,9 +623,6 @@ static av_cold int vaapi_encode_mpeg2_init(AVCodecContext *avctx) ctx->desired_packed_headers = VA_ENC_PACKED_HEADER_SEQUENCE | VA_ENC_PACKED_HEADER_PICTURE; - ctx->surface_width = FFALIGN(avctx->width, 16); - ctx->surface_height = FFALIGN(avctx->height, 16); - return ff_vaapi_encode_init(avctx); } @@ -668,7 +667,7 @@ static const AVOption vaapi_encode_mpeg2_options[] = { { NULL }, }; -static const AVCodecDefault vaapi_encode_mpeg2_defaults[] = { +static const FFCodecDefault vaapi_encode_mpeg2_defaults[] = { { "b", "0" }, { "bf", "1" }, { "g", "120" }, @@ -688,24 +687,24 @@ static const AVClass vaapi_encode_mpeg2_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_mpeg2_vaapi_encoder = { - .name = "mpeg2_vaapi", - .long_name = NULL_IF_CONFIG_SMALL("MPEG-2 (VAAPI)"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_MPEG2VIDEO, +const FFCodec ff_mpeg2_vaapi_encoder = { + .p.name = "mpeg2_vaapi", + .p.long_name = NULL_IF_CONFIG_SMALL("MPEG-2 (VAAPI)"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_MPEG2VIDEO, .priv_data_size = sizeof(VAAPIEncodeMPEG2Context), .init = &vaapi_encode_mpeg2_init, - .receive_packet = &ff_vaapi_encode_receive_packet, + FF_CODEC_RECEIVE_PACKET_CB(&ff_vaapi_encode_receive_packet), .close = &vaapi_encode_mpeg2_close, - .priv_class = &vaapi_encode_mpeg2_class, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | + .p.priv_class = &vaapi_encode_mpeg2_class, + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .defaults = vaapi_encode_mpeg2_defaults, - .pix_fmts = (const enum AVPixelFormat[]) { + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_VAAPI, AV_PIX_FMT_NONE, }, .hw_configs = ff_vaapi_encode_hw_configs, - .wrapper_name = "vaapi", + .p.wrapper_name = "vaapi", }; diff --git a/libavcodec/vaapi_encode_vp8.c b/libavcodec/vaapi_encode_vp8.c index 7d4578f67..e1d737950 100644 --- a/libavcodec/vaapi_encode_vp8.c +++ b/libavcodec/vaapi_encode_vp8.c @@ -26,7 +26,7 @@ #include "libavutil/pixfmt.h" #include "avcodec.h" -#include "internal.h" +#include "codec_internal.h" #include "vaapi_encode.h" #include "vp8.h" @@ -210,9 +210,6 @@ static av_cold int vaapi_encode_vp8_init(AVCodecContext *avctx) // adding them anyway. ctx->desired_packed_headers = 0; - ctx->surface_width = FFALIGN(avctx->width, 16); - ctx->surface_height = FFALIGN(avctx->height, 16); - return ff_vaapi_encode_init(avctx); } @@ -229,7 +226,7 @@ static const AVOption vaapi_encode_vp8_options[] = { { NULL }, }; -static const AVCodecDefault vaapi_encode_vp8_defaults[] = { +static const FFCodecDefault vaapi_encode_vp8_defaults[] = { { "b", "0" }, { "bf", "0" }, { "g", "120" }, @@ -245,24 +242,24 @@ static const AVClass vaapi_encode_vp8_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_vp8_vaapi_encoder = { - .name = "vp8_vaapi", - .long_name = NULL_IF_CONFIG_SMALL("VP8 (VAAPI)"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_VP8, +const FFCodec ff_vp8_vaapi_encoder = { + .p.name = "vp8_vaapi", + .p.long_name = NULL_IF_CONFIG_SMALL("VP8 (VAAPI)"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_VP8, .priv_data_size = sizeof(VAAPIEncodeVP8Context), .init = &vaapi_encode_vp8_init, - .receive_packet = &ff_vaapi_encode_receive_packet, + FF_CODEC_RECEIVE_PACKET_CB(&ff_vaapi_encode_receive_packet), .close = &ff_vaapi_encode_close, - .priv_class = &vaapi_encode_vp8_class, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | + .p.priv_class = &vaapi_encode_vp8_class, + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .defaults = vaapi_encode_vp8_defaults, - .pix_fmts = (const enum AVPixelFormat[]) { + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_VAAPI, AV_PIX_FMT_NONE, }, .hw_configs = ff_vaapi_encode_hw_configs, - .wrapper_name = "vaapi", + .p.wrapper_name = "vaapi", }; diff --git a/libavcodec/vaapi_encode_vp9.c b/libavcodec/vaapi_encode_vp9.c index be706e3bd..52373543d 100644 --- a/libavcodec/vaapi_encode_vp9.c +++ b/libavcodec/vaapi_encode_vp9.c @@ -26,7 +26,7 @@ #include "libavutil/pixfmt.h" #include "avcodec.h" -#include "internal.h" +#include "codec_internal.h" #include "vaapi_encode.h" #define VP9_MAX_QUANT 255 @@ -184,6 +184,17 @@ static int vaapi_encode_vp9_init_picture_params(AVCodecContext *avctx, return 0; } +static av_cold int vaapi_encode_vp9_get_encoder_caps(AVCodecContext *avctx) +{ + VAAPIEncodeContext *ctx = avctx->priv_data; + + // Surfaces must be aligned to 64x64 superblock boundaries. + ctx->surface_width = FFALIGN(avctx->width, 64); + ctx->surface_height = FFALIGN(avctx->height, 64); + + return 0; +} + static av_cold int vaapi_encode_vp9_configure(AVCodecContext *avctx) { VAAPIEncodeContext *ctx = avctx->priv_data; @@ -231,6 +242,7 @@ static const VAAPIEncodeType vaapi_encode_type_vp9 = { .picture_priv_data_size = sizeof(VAAPIEncodeVP9Picture), + .get_encoder_caps = &vaapi_encode_vp9_get_encoder_caps, .configure = &vaapi_encode_vp9_configure, .sequence_params_size = sizeof(VAEncSequenceParameterBufferVP9), @@ -251,10 +263,6 @@ static av_cold int vaapi_encode_vp9_init(AVCodecContext *avctx) // can write its own headers and there is no metadata to include. ctx->desired_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); } @@ -271,7 +279,7 @@ static const AVOption vaapi_encode_vp9_options[] = { { NULL }, }; -static const AVCodecDefault vaapi_encode_vp9_defaults[] = { +static const FFCodecDefault vaapi_encode_vp9_defaults[] = { { "b", "0" }, { "bf", "0" }, { "g", "250" }, @@ -287,24 +295,24 @@ static const AVClass vaapi_encode_vp9_class = { .version = LIBAVUTIL_VERSION_INT, }; -const 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, +const FFCodec ff_vp9_vaapi_encoder = { + .p.name = "vp9_vaapi", + .p.long_name = NULL_IF_CONFIG_SMALL("VP9 (VAAPI)"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_VP9, .priv_data_size = sizeof(VAAPIEncodeVP9Context), .init = &vaapi_encode_vp9_init, - .receive_packet = &ff_vaapi_encode_receive_packet, + FF_CODEC_RECEIVE_PACKET_CB(&ff_vaapi_encode_receive_packet), .close = &ff_vaapi_encode_close, - .priv_class = &vaapi_encode_vp9_class, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | + .p.priv_class = &vaapi_encode_vp9_class, + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .defaults = vaapi_encode_vp9_defaults, - .pix_fmts = (const enum AVPixelFormat[]) { + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_VAAPI, AV_PIX_FMT_NONE, }, .hw_configs = ff_vaapi_encode_hw_configs, - .wrapper_name = "vaapi", + .p.wrapper_name = "vaapi", }; diff --git a/libavcodec/vaapi_hevc.c b/libavcodec/vaapi_hevc.c index 9083331c4..d82975979 100644 --- a/libavcodec/vaapi_hevc.c +++ b/libavcodec/vaapi_hevc.c @@ -322,11 +322,20 @@ fail: return ret; } -static void fill_pred_weight_table(const HEVCContext *h, +static void fill_pred_weight_table(AVCodecContext *avctx, + const HEVCContext *h, const SliceHeader *sh, VASliceParameterBufferHEVC *slice_param) { int i; +#if VA_CHECK_VERSION(1, 2, 0) + int is_rext = avctx->profile >= FF_PROFILE_HEVC_REXT; +#else + int is_rext = 0; + if (avctx->profile >= FF_PROFILE_HEVC_REXT) + av_log(avctx, AV_LOG_WARNING, "Please consider to update to VAAPI 1.2.0 " + "or above, which can support REXT related setting correctly.\n"); +#endif memset(slice_param->delta_luma_weight_l0, 0, sizeof(slice_param->delta_luma_weight_l0)); memset(slice_param->delta_luma_weight_l1, 0, sizeof(slice_param->delta_luma_weight_l1)); @@ -353,21 +362,25 @@ static void fill_pred_weight_table(const HEVCContext *h, for (i = 0; i < 15 && i < sh->nb_refs[L0]; i++) { slice_param->delta_luma_weight_l0[i] = sh->luma_weight_l0[i] - (1 << sh->luma_log2_weight_denom); - slice_param->luma_offset_l0[i] = sh->luma_offset_l0[i]; slice_param->delta_chroma_weight_l0[i][0] = sh->chroma_weight_l0[i][0] - (1 << sh->chroma_log2_weight_denom); slice_param->delta_chroma_weight_l0[i][1] = sh->chroma_weight_l0[i][1] - (1 << sh->chroma_log2_weight_denom); - slice_param->ChromaOffsetL0[i][0] = sh->chroma_offset_l0[i][0]; - slice_param->ChromaOffsetL0[i][1] = sh->chroma_offset_l0[i][1]; + if (!is_rext) { + slice_param->luma_offset_l0[i] = sh->luma_offset_l0[i]; + slice_param->ChromaOffsetL0[i][0] = sh->chroma_offset_l0[i][0]; + slice_param->ChromaOffsetL0[i][1] = sh->chroma_offset_l0[i][1]; + } } if (sh->slice_type == HEVC_SLICE_B) { for (i = 0; i < 15 && i < sh->nb_refs[L1]; i++) { slice_param->delta_luma_weight_l1[i] = sh->luma_weight_l1[i] - (1 << sh->luma_log2_weight_denom); - slice_param->luma_offset_l1[i] = sh->luma_offset_l1[i]; slice_param->delta_chroma_weight_l1[i][0] = sh->chroma_weight_l1[i][0] - (1 << sh->chroma_log2_weight_denom); slice_param->delta_chroma_weight_l1[i][1] = sh->chroma_weight_l1[i][1] - (1 << sh->chroma_log2_weight_denom); - slice_param->ChromaOffsetL1[i][0] = sh->chroma_offset_l1[i][0]; - slice_param->ChromaOffsetL1[i][1] = sh->chroma_offset_l1[i][1]; + if (!is_rext) { + slice_param->luma_offset_l1[i] = sh->luma_offset_l1[i]; + slice_param->ChromaOffsetL1[i][0] = sh->chroma_offset_l1[i][0]; + slice_param->ChromaOffsetL1[i][1] = sh->chroma_offset_l1[i][1]; + } } } } @@ -462,7 +475,7 @@ static int vaapi_hevc_decode_slice(AVCodecContext *avctx, last_slice_param->RefPicList[list_idx][i] = get_ref_pic_index(h, rpl->ref[i]); } - fill_pred_weight_table(h, sh, last_slice_param); + fill_pred_weight_table(avctx, h, sh, last_slice_param); #if VA_CHECK_VERSION(1, 2, 0) if (avctx->profile == FF_PROFILE_HEVC_REXT) { @@ -471,15 +484,25 @@ static int vaapi_hevc_decode_slice(AVCodecContext *avctx, .cu_chroma_qp_offset_enabled_flag = sh->cu_chroma_qp_offset_enabled_flag, }, }; + for (i = 0; i < 15 && i < sh->nb_refs[L0]; i++) { + pic->last_slice_param.rext.luma_offset_l0[i] = sh->luma_offset_l0[i]; + pic->last_slice_param.rext.ChromaOffsetL0[i][0] = sh->chroma_offset_l0[i][0]; + pic->last_slice_param.rext.ChromaOffsetL0[i][1] = sh->chroma_offset_l0[i][1]; + } - memcpy(pic->last_slice_param.rext.luma_offset_l0, pic->last_slice_param.base.luma_offset_l0, - sizeof(pic->last_slice_param.base.luma_offset_l0)); - memcpy(pic->last_slice_param.rext.luma_offset_l1, pic->last_slice_param.base.luma_offset_l1, - sizeof(pic->last_slice_param.base.luma_offset_l1)); - memcpy(pic->last_slice_param.rext.ChromaOffsetL0, pic->last_slice_param.base.ChromaOffsetL0, - sizeof(pic->last_slice_param.base.ChromaOffsetL0)); - memcpy(pic->last_slice_param.rext.ChromaOffsetL1, pic->last_slice_param.base.ChromaOffsetL1, - sizeof(pic->last_slice_param.base.ChromaOffsetL1)); + for (i = 0; i < 15 && i < sh->nb_refs[L0]; i++) { + pic->last_slice_param.rext.luma_offset_l0[i] = sh->luma_offset_l0[i]; + pic->last_slice_param.rext.ChromaOffsetL0[i][0] = sh->chroma_offset_l0[i][0]; + pic->last_slice_param.rext.ChromaOffsetL0[i][1] = sh->chroma_offset_l0[i][1]; + } + + if (sh->slice_type == HEVC_SLICE_B) { + for (i = 0; i < 15 && i < sh->nb_refs[L1]; i++) { + pic->last_slice_param.rext.luma_offset_l1[i] = sh->luma_offset_l1[i]; + pic->last_slice_param.rext.ChromaOffsetL1[i][0] = sh->chroma_offset_l1[i][0]; + pic->last_slice_param.rext.ChromaOffsetL1[i][1] = sh->chroma_offset_l1[i][1]; + } + } } #endif diff --git a/libavcodec/vaapi_mpeg2.c b/libavcodec/vaapi_mpeg2.c index 26e0cd827..5e2b88913 100644 --- a/libavcodec/vaapi_mpeg2.c +++ b/libavcodec/vaapi_mpeg2.c @@ -23,7 +23,7 @@ #include "hwconfig.h" #include "mpegutils.h" #include "mpegvideo.h" -#include "internal.h" +#include "mpegvideodec.h" #include "vaapi_decode.h" /** Reconstruct bitstream f_code */ diff --git a/libavcodec/vaapi_mpeg4.c b/libavcodec/vaapi_mpeg4.c index 71e155154..ca3f3b22f 100644 --- a/libavcodec/vaapi_mpeg4.c +++ b/libavcodec/vaapi_mpeg4.c @@ -20,11 +20,13 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "h263.h" #include "hwconfig.h" -#include "internal.h" -#include "mpeg4video.h" +#include "mpeg4videodec.h" #include "mpegvideo.h" +#include "mpegvideodec.h" #include "vaapi_decode.h" /** Reconstruct bitstream intra_dc_vlc_thr */ diff --git a/libavcodec/vaapi_vc1.c b/libavcodec/vaapi_vc1.c index 4e9607d9b..d82336a3b 100644 --- a/libavcodec/vaapi_vc1.c +++ b/libavcodec/vaapi_vc1.c @@ -20,8 +20,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "hwconfig.h" -#include "internal.h" +#include "mpegvideodec.h" #include "vaapi_decode.h" #include "vc1.h" #include "vc1data.h" diff --git a/libavcodec/vb.c b/libavcodec/vb.c index eac2427ce..82b4ea85c 100644 --- a/libavcodec/vb.c +++ b/libavcodec/vb.c @@ -29,6 +29,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" enum VBFlags { @@ -188,11 +189,10 @@ static int vb_decode_framedata(VBDecContext *c, int offset) return 0; } -static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { VBDecContext * const c = avctx->priv_data; - AVFrame *frame = data; uint8_t *outptr, *srcptr; int i, j, ret; int flags; @@ -278,15 +278,15 @@ static av_cold int decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_vb_decoder = { - .name = "vb", - .long_name = NULL_IF_CONFIG_SMALL("Beam Software VB"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_VB, +const FFCodec ff_vb_decoder = { + .p.name = "vb", + .p.long_name = NULL_IF_CONFIG_SMALL("Beam Software VB"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_VB, .priv_data_size = sizeof(VBDecContext), .init = decode_init, .close = decode_end, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/vble.c b/libavcodec/vble.c index f1400959e..f7ab17d62 100644 --- a/libavcodec/vble.c +++ b/libavcodec/vble.c @@ -28,8 +28,8 @@ #define BITSTREAM_READER_LE #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" -#include "internal.h" #include "lossless_videodsp.h" #include "mathops.h" #include "thread.h" @@ -114,18 +114,16 @@ static void vble_restore_plane(VBLEContext *ctx, AVFrame *pic, } } -static int vble_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int vble_decode_frame(AVCodecContext *avctx, AVFrame *pic, + int *got_frame, AVPacket *avpkt) { VBLEContext *ctx = avctx->priv_data; - AVFrame *pic = data; GetBitContext gb; const uint8_t *src = avpkt->data; int version; int offset = 0; int width_uv = avctx->width / 2, height_uv = avctx->height / 2; int ret; - ThreadFrame frame = { .f = data }; if (avpkt->size < 4 || avpkt->size - 4 > INT_MAX/8) { av_log(avctx, AV_LOG_ERROR, "Invalid packet size\n"); @@ -133,7 +131,7 @@ static int vble_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, } /* Allocate buffer */ - if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, pic, 0)) < 0) return ret; /* Set flags */ @@ -203,15 +201,15 @@ static av_cold int vble_decode_init(AVCodecContext *avctx) return 0; } -const AVCodec ff_vble_decoder = { - .name = "vble", - .long_name = NULL_IF_CONFIG_SMALL("VBLE Lossless Codec"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_VBLE, +const FFCodec ff_vble_decoder = { + .p.name = "vble", + .p.long_name = NULL_IF_CONFIG_SMALL("VBLE Lossless Codec"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_VBLE, .priv_data_size = sizeof(VBLEContext), .init = vble_decode_init, .close = vble_decode_close, - .decode = vble_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + FF_CODEC_DECODE_CB(vble_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/vbn.h b/libavcodec/vbn.h new file mode 100644 index 000000000..8660786de --- /dev/null +++ b/libavcodec/vbn.h @@ -0,0 +1,50 @@ +/* + * VBN format definitions + * + * 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 + * VBN format definitions. + */ + +#ifndef AVCODEC_VBN_H +#define AVCODEC_VBN_H + +#define VBN_MAGIC 0x900df11e +#define VBN_MAJOR 3 +#define VBN_MINOR 4 + +#define VBN_HEADER_SIZE 192 + +#define VBN_FORMAT_RAW 0 +#define VBN_FORMAT_LZ 1 +#define VBN_FORMAT_DXT1 2 +#define VBN_FORMAT_DXT5 3 + +#define VBN_COMPRESSION_NONE 0 +#define VBN_COMPRESSION_LZW 0x100 + +#define VBN_PIX_ALPHA 0 +#define VBN_PIX_LUMINANCE 1 +#define VBN_PIX_LUMINANCE_ALPHA 2 +#define VBN_PIX_RGB 3 +#define VBN_PIX_RGBA 5 +#define VBN_PIX_INDEX 6 + +#endif /* AVCODEC_VBN_H */ diff --git a/libavcodec/vbndec.c b/libavcodec/vbndec.c new file mode 100644 index 000000000..a6046c766 --- /dev/null +++ b/libavcodec/vbndec.c @@ -0,0 +1,186 @@ +/* + * Vizrt Binary Image decoder + * + * 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 + * Vizrt Binary Image decoder + */ + +#include "avcodec.h" +#include "bytestream.h" +#include "codec_internal.h" +#include "internal.h" +#include "texturedsp.h" +#include "vbn.h" +#include "libavutil/imgutils.h" + +typedef struct VBNContext { + TextureDSPContext texdsp; + TextureDSPThreadContext dec; +} VBNContext; + +static av_cold int vbn_init(AVCodecContext *avctx) +{ + VBNContext *ctx = avctx->priv_data; + ff_texturedsp_init(&ctx->texdsp); + return 0; +} + +static int decompress(AVCodecContext *avctx, GetByteContext *gb, + int compression, uint8_t **outbuf) +{ + if (compression == VBN_COMPRESSION_NONE) // outbuf is left NULL because gb->buf can be used directly + return bytestream2_get_bytes_left(gb); + + av_log(avctx, AV_LOG_ERROR, "Unsupported VBN compression: 0x%08x\n", compression); + return AVERROR_PATCHWELCOME; +} + +static int vbn_decode_frame(AVCodecContext *avctx, + AVFrame *frame, int *got_frame, + AVPacket *avpkt) +{ + VBNContext *ctx = avctx->priv_data; + GetByteContext gb0, *const gb = &gb0; + uint8_t *image_buf = NULL; + int image_len; + int width, height, components, format, compression, pix_fmt, linesize, data_size; + int ret; + + bytestream2_init(gb, avpkt->data, avpkt->size); + + if (bytestream2_get_bytes_left(gb) < VBN_HEADER_SIZE) { + av_log(avctx, AV_LOG_ERROR, "VBN header truncated\n"); + return AVERROR_INVALIDDATA; + } + + if (bytestream2_get_le32u(gb) != VBN_MAGIC || + bytestream2_get_le32u(gb) != VBN_MAJOR || + bytestream2_get_le32u(gb) != VBN_MINOR) { + av_log(avctx, AV_LOG_ERROR, "Invalid VBN header\n"); + return AVERROR_INVALIDDATA; + } + + width = bytestream2_get_le32u(gb); + height = bytestream2_get_le32u(gb); + components = bytestream2_get_le32u(gb); + format = bytestream2_get_le32u(gb); + pix_fmt = bytestream2_get_le32u(gb); + bytestream2_get_le32u(gb); // mipmaps + data_size = bytestream2_get_le32u(gb); + bytestream2_seek(gb, VBN_HEADER_SIZE, SEEK_SET); + + compression = format & 0xffffff00; + format = format & 0xff; + + if (data_size != bytestream2_get_bytes_left(gb)) { + av_log(avctx, AV_LOG_ERROR, "Truncated packet\n"); + return AVERROR_INVALIDDATA; + } + + if (pix_fmt != VBN_PIX_RGBA && pix_fmt != VBN_PIX_RGB) { + av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format: 0x%08x\n", pix_fmt); + return AVERROR_PATCHWELCOME; + } + + ret = ff_set_dimensions(avctx, width, height); + if (ret < 0) + return ret; + + if (format == VBN_FORMAT_RAW) { + if (pix_fmt == VBN_PIX_RGB && components == 3) { + avctx->pix_fmt = AV_PIX_FMT_RGB24; + linesize = avctx->width * 3; + } else if (pix_fmt == VBN_PIX_RGBA && components == 4) { + avctx->pix_fmt = AV_PIX_FMT_RGBA; + linesize = avctx->width * 4; + } else { + av_log(avctx, AV_LOG_ERROR, "Unsupported number of components: %d\n", components); + return AVERROR_PATCHWELCOME; + } + } else if (format == VBN_FORMAT_DXT1 || format == VBN_FORMAT_DXT5) { + if (avctx->width % TEXTURE_BLOCK_W || avctx->height % TEXTURE_BLOCK_H) { + av_log(avctx, AV_LOG_ERROR, "DXTx compression only supports 4 pixel aligned resolutions\n"); + return AVERROR_INVALIDDATA; + } + + avctx->pix_fmt = AV_PIX_FMT_RGBA; + if (format == VBN_FORMAT_DXT1) { + ctx->dec.tex_funct = ctx->texdsp.dxt1_block; + ctx->dec.tex_ratio = 8; + linesize = avctx->coded_width / 2; + } else { + ctx->dec.tex_funct = ctx->texdsp.dxt5_block; + ctx->dec.tex_ratio = 16; + linesize = avctx->coded_width; + } + } else { + av_log(avctx, AV_LOG_ERROR, "Unsupported VBN format: 0x%02x\n", format); + return AVERROR_PATCHWELCOME; + } + + image_len = decompress(avctx, gb, compression, &image_buf); + if (image_len < 0) + return image_len; + + if (image_len < linesize * avctx->coded_height) { + av_log(avctx, AV_LOG_ERROR, "Insufficent data\n"); + ret = AVERROR_INVALIDDATA; + goto out; + } + + ret = ff_get_buffer(avctx, frame, 0); + if (ret < 0) + goto out; + + frame->pict_type = AV_PICTURE_TYPE_I; + frame->key_frame = 1; + + if (format == VBN_FORMAT_RAW) { + uint8_t *flipped = frame->data[0] + frame->linesize[0] * (frame->height - 1); + av_image_copy_plane(flipped, -frame->linesize[0], image_buf ? image_buf : gb->buffer, linesize, linesize, frame->height); + } else { + ctx->dec.slice_count = av_clip(avctx->thread_count, 1, avctx->coded_height / TEXTURE_BLOCK_H); + ctx->dec.tex_data.in = image_buf ? image_buf : gb->buffer; + ctx->dec.raw_ratio = 16; + ctx->dec.frame_data.out = frame->data[0] + frame->linesize[0] * (frame->height - 1); + ctx->dec.stride = -frame->linesize[0]; + avctx->execute2(avctx, ff_texturedsp_decompress_thread, &ctx->dec, NULL, ctx->dec.slice_count); + } + + *got_frame = 1; + ret = avpkt->size; + +out: + av_freep(&image_buf); + return ret; +} + +const FFCodec ff_vbn_decoder = { + .p.name = "vbn", + .p.long_name = NULL_IF_CONFIG_SMALL("Vizrt Binary Image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_VBN, + .init = vbn_init, + FF_CODEC_DECODE_CB(vbn_decode_frame), + .priv_data_size = sizeof(VBNContext), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE +}; diff --git a/libavcodec/vbnenc.c b/libavcodec/vbnenc.c new file mode 100644 index 000000000..de35a44d3 --- /dev/null +++ b/libavcodec/vbnenc.c @@ -0,0 +1,166 @@ +/* + * Vizrt Binary Image encoder + * + * 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 + * Vizrt Binary Image encoder + */ + +#include "avcodec.h" +#include "bytestream.h" +#include "codec_internal.h" +#include "encode.h" +#include "texturedsp.h" +#include "vbn.h" + +#include "libavutil/imgutils.h" +#include "libavutil/frame.h" +#include "libavutil/opt.h" + +typedef struct VBNContext { + AVClass *class; + TextureDSPContext dxtc; + int format; + TextureDSPThreadContext enc; +} VBNContext; + +static int vbn_encode(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) +{ + VBNContext *ctx = avctx->priv_data; + PutByteContext pb0, *const pb = &pb0; + int ret; + ptrdiff_t linesize; + int64_t pkt_size; + + ret = av_image_check_size2(frame->width, frame->height, INT_MAX, frame->format, 0, avctx); + if (ret < 0) + return ret; + + if (ctx->format == VBN_FORMAT_DXT1 || ctx->format == VBN_FORMAT_DXT5) { + if (frame->width % TEXTURE_BLOCK_W || frame->height % TEXTURE_BLOCK_H) { + av_log(avctx, AV_LOG_ERROR, "Video size %dx%d is not multiple of 4\n", frame->width, frame->height); + return AVERROR(EINVAL); + } + if (frame->format != AV_PIX_FMT_RGBA) { + av_log(avctx, AV_LOG_ERROR, "DXT formats only support RGBA pixel format\n"); + return AVERROR(EINVAL); + } + ctx->enc.raw_ratio = 16; + ctx->enc.slice_count = av_clip(avctx->thread_count, 1, avctx->height / TEXTURE_BLOCK_H); + } + + switch (ctx->format) { + case VBN_FORMAT_DXT1: + linesize = frame->width / 2; + ctx->enc.tex_funct = ctx->dxtc.dxt1_block; + ctx->enc.tex_ratio = 8; + break; + case VBN_FORMAT_DXT5: + linesize = frame->width; + ctx->enc.tex_funct = ctx->dxtc.dxt5_block; + ctx->enc.tex_ratio = 16; + break; + case VBN_FORMAT_RAW: + linesize = av_image_get_linesize(frame->format, frame->width, 0); + if (linesize < 0) + return linesize; + break; + default: + av_log(avctx, AV_LOG_ERROR, "Invalid format %02X\n", ctx->format); + return AVERROR(EINVAL); + } + + pkt_size = VBN_HEADER_SIZE + linesize * frame->height; + if (pkt_size > INT_MAX) + return AVERROR(EINVAL); + + if ((ret = ff_get_encode_buffer(avctx, pkt, pkt_size, 0)) < 0) + return ret; + + memset(pkt->data, 0, VBN_HEADER_SIZE); + bytestream2_init_writer(pb, pkt->data, pkt_size); + bytestream2_put_le32u(pb, VBN_MAGIC); + bytestream2_put_le32u(pb, VBN_MAJOR); + bytestream2_put_le32u(pb, VBN_MINOR); + bytestream2_put_le32u(pb, frame->width); + bytestream2_put_le32u(pb, frame->height); + bytestream2_put_le32u(pb, frame->format == AV_PIX_FMT_RGBA ? 4 : 3); + bytestream2_put_le32u(pb, ctx->format); + bytestream2_put_le32u(pb, frame->format == AV_PIX_FMT_RGBA ? VBN_PIX_RGBA : VBN_PIX_RGB); + bytestream2_put_le32u(pb, 0); // mipmaps + bytestream2_put_le32u(pb, pkt_size - VBN_HEADER_SIZE); + bytestream2_seek_p(pb, 64, SEEK_SET); + bytestream2_put_le32u(pb, pkt_size - VBN_HEADER_SIZE); + + if (ctx->format == VBN_FORMAT_DXT1 || ctx->format == VBN_FORMAT_DXT5) { + ctx->enc.frame_data.in = (frame->height - 1) * frame->linesize[0] + frame->data[0]; + ctx->enc.stride = -frame->linesize[0]; + ctx->enc.tex_data.out = pkt->data + VBN_HEADER_SIZE; + avctx->execute2(avctx, ff_texturedsp_compress_thread, &ctx->enc, NULL, ctx->enc.slice_count); + } else { + uint8_t *flipped = frame->data[0] + frame->linesize[0] * (frame->height - 1); + av_image_copy_plane(pkt->data + VBN_HEADER_SIZE, linesize, flipped, -frame->linesize[0], linesize, frame->height); + } + + *got_packet = 1; + return 0; +} + +static av_cold int vbn_init(AVCodecContext *avctx) +{ + VBNContext *ctx = avctx->priv_data; + ff_texturedspenc_init(&ctx->dxtc); + return 0; +} + +#define OFFSET(x) offsetof(VBNContext, x) +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "format", "Texture format", OFFSET(format), AV_OPT_TYPE_INT, { .i64 = VBN_FORMAT_DXT5 }, VBN_FORMAT_RAW, VBN_FORMAT_DXT5, FLAGS, "format" }, + { "raw", "RAW texture", 0, AV_OPT_TYPE_CONST, { .i64 = VBN_FORMAT_RAW }, 0, 0, FLAGS, "format" }, + { "dxt1", "DXT1 texture", 0, AV_OPT_TYPE_CONST, { .i64 = VBN_FORMAT_DXT1 }, 0, 0, FLAGS, "format" }, + { "dxt5", "DXT5 texture", 0, AV_OPT_TYPE_CONST, { .i64 = VBN_FORMAT_DXT5 }, 0, 0, FLAGS, "format" }, + { NULL }, +}; + +static const AVClass vbnenc_class = { + .class_name = "VBN encoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +const FFCodec ff_vbn_encoder = { + .p.name = "vbn", + .p.long_name = NULL_IF_CONFIG_SMALL("Vizrt Binary Image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_VBN, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS, + .p.priv_class = &vbnenc_class, + .init = vbn_init, + FF_CODEC_ENCODE_CB(vbn_encode), + .priv_data_size = sizeof(VBNContext), + .p.pix_fmts = (const enum AVPixelFormat[]) { + AV_PIX_FMT_RGBA, AV_PIX_FMT_RGB24, AV_PIX_FMT_NONE, + }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_INIT_CLEANUP, +}; diff --git a/libavcodec/vc1.c b/libavcodec/vc1.c index 40e2b4d69..1070b8ca9 100644 --- a/libavcodec/vc1.c +++ b/libavcodec/vc1.c @@ -1584,115 +1584,114 @@ static const uint16_t vlc_offs[] = { static av_cold void vc1_init_static(void) { - int i = 0; - static VLC_TYPE vlc_table[32372][2]; + static VLCElem vlc_table[32372]; - INIT_VLC_STATIC(&ff_vc1_bfraction_vlc, VC1_BFRACTION_VLC_BITS, 23, - ff_vc1_bfraction_bits, 1, 1, - ff_vc1_bfraction_codes, 1, 1, 1 << VC1_BFRACTION_VLC_BITS); - INIT_VLC_STATIC(&ff_vc1_norm2_vlc, VC1_NORM2_VLC_BITS, 4, - ff_vc1_norm2_bits, 1, 1, - ff_vc1_norm2_codes, 1, 1, 1 << VC1_NORM2_VLC_BITS); - INIT_VLC_STATIC(&ff_vc1_norm6_vlc, VC1_NORM6_VLC_BITS, 64, - ff_vc1_norm6_bits, 1, 1, - ff_vc1_norm6_codes, 2, 2, 556); - INIT_VLC_STATIC(&ff_vc1_imode_vlc, VC1_IMODE_VLC_BITS, 7, - ff_vc1_imode_bits, 1, 1, - ff_vc1_imode_codes, 1, 1, 1 << VC1_IMODE_VLC_BITS); - for (i = 0; i < 3; i++) { - ff_vc1_ttmb_vlc[i].table = &vlc_table[vlc_offs[i * 3 + 0]]; - ff_vc1_ttmb_vlc[i].table_allocated = vlc_offs[i * 3 + 1] - vlc_offs[i * 3 + 0]; - init_vlc(&ff_vc1_ttmb_vlc[i], VC1_TTMB_VLC_BITS, 16, - ff_vc1_ttmb_bits[i], 1, 1, - ff_vc1_ttmb_codes[i], 2, 2, INIT_VLC_USE_NEW_STATIC); - ff_vc1_ttblk_vlc[i].table = &vlc_table[vlc_offs[i * 3 + 1]]; - ff_vc1_ttblk_vlc[i].table_allocated = vlc_offs[i * 3 + 2] - vlc_offs[i * 3 + 1]; - init_vlc(&ff_vc1_ttblk_vlc[i], VC1_TTBLK_VLC_BITS, 8, - ff_vc1_ttblk_bits[i], 1, 1, - ff_vc1_ttblk_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); - ff_vc1_subblkpat_vlc[i].table = &vlc_table[vlc_offs[i * 3 + 2]]; - ff_vc1_subblkpat_vlc[i].table_allocated = vlc_offs[i * 3 + 3] - vlc_offs[i * 3 + 2]; - init_vlc(&ff_vc1_subblkpat_vlc[i], VC1_SUBBLKPAT_VLC_BITS, 15, - ff_vc1_subblkpat_bits[i], 1, 1, - ff_vc1_subblkpat_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); - } - for (i = 0; i < 4; i++) { - ff_vc1_4mv_block_pattern_vlc[i].table = &vlc_table[vlc_offs[i * 3 + 9]]; - ff_vc1_4mv_block_pattern_vlc[i].table_allocated = vlc_offs[i * 3 + 10] - vlc_offs[i * 3 + 9]; - init_vlc(&ff_vc1_4mv_block_pattern_vlc[i], VC1_4MV_BLOCK_PATTERN_VLC_BITS, 16, - ff_vc1_4mv_block_pattern_bits[i], 1, 1, - ff_vc1_4mv_block_pattern_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); - ff_vc1_cbpcy_p_vlc[i].table = &vlc_table[vlc_offs[i * 3 + 10]]; - ff_vc1_cbpcy_p_vlc[i].table_allocated = vlc_offs[i * 3 + 11] - vlc_offs[i * 3 + 10]; - init_vlc(&ff_vc1_cbpcy_p_vlc[i], VC1_CBPCY_P_VLC_BITS, 64, - ff_vc1_cbpcy_p_bits[i], 1, 1, - ff_vc1_cbpcy_p_codes[i], 2, 2, INIT_VLC_USE_NEW_STATIC); - ff_vc1_mv_diff_vlc[i].table = &vlc_table[vlc_offs[i * 3 + 11]]; - ff_vc1_mv_diff_vlc[i].table_allocated = vlc_offs[i * 3 + 12] - vlc_offs[i * 3 + 11]; - init_vlc(&ff_vc1_mv_diff_vlc[i], VC1_MV_DIFF_VLC_BITS, 73, - ff_vc1_mv_diff_bits[i], 1, 1, - ff_vc1_mv_diff_codes[i], 2, 2, INIT_VLC_USE_NEW_STATIC); - } - for (i = 0; i < 8; i++) { - ff_vc1_ac_coeff_table[i].table = &vlc_table[vlc_offs[i * 2 + 21]]; - ff_vc1_ac_coeff_table[i].table_allocated = vlc_offs[i * 2 + 22] - vlc_offs[i * 2 + 21]; - init_vlc(&ff_vc1_ac_coeff_table[i], AC_VLC_BITS, ff_vc1_ac_sizes[i], - &vc1_ac_tables[i][0][1], 8, 4, - &vc1_ac_tables[i][0][0], 8, 4, INIT_VLC_USE_NEW_STATIC); - /* initialize interlaced MVDATA tables (2-Ref) */ - ff_vc1_2ref_mvdata_vlc[i].table = &vlc_table[vlc_offs[i * 2 + 22]]; - ff_vc1_2ref_mvdata_vlc[i].table_allocated = vlc_offs[i * 2 + 23] - vlc_offs[i * 2 + 22]; - init_vlc(&ff_vc1_2ref_mvdata_vlc[i], VC1_2REF_MVDATA_VLC_BITS, 126, - ff_vc1_2ref_mvdata_bits[i], 1, 1, - ff_vc1_2ref_mvdata_codes[i], 4, 4, INIT_VLC_USE_NEW_STATIC); - } - for (i = 0; i < 4; i++) { - /* initialize 4MV MBMODE VLC tables for interlaced frame P picture */ - ff_vc1_intfr_4mv_mbmode_vlc[i].table = &vlc_table[vlc_offs[i * 3 + 37]]; - ff_vc1_intfr_4mv_mbmode_vlc[i].table_allocated = vlc_offs[i * 3 + 38] - vlc_offs[i * 3 + 37]; - init_vlc(&ff_vc1_intfr_4mv_mbmode_vlc[i], VC1_INTFR_4MV_MBMODE_VLC_BITS, 15, - ff_vc1_intfr_4mv_mbmode_bits[i], 1, 1, - ff_vc1_intfr_4mv_mbmode_codes[i], 2, 2, INIT_VLC_USE_NEW_STATIC); - /* initialize NON-4MV MBMODE VLC tables for the same */ - ff_vc1_intfr_non4mv_mbmode_vlc[i].table = &vlc_table[vlc_offs[i * 3 + 38]]; - ff_vc1_intfr_non4mv_mbmode_vlc[i].table_allocated = vlc_offs[i * 3 + 39] - vlc_offs[i * 3 + 38]; - init_vlc(&ff_vc1_intfr_non4mv_mbmode_vlc[i], VC1_INTFR_NON4MV_MBMODE_VLC_BITS, 9, - ff_vc1_intfr_non4mv_mbmode_bits[i], 1, 1, - ff_vc1_intfr_non4mv_mbmode_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); - /* initialize interlaced MVDATA tables (1-Ref) */ - ff_vc1_1ref_mvdata_vlc[i].table = &vlc_table[vlc_offs[i * 3 + 39]]; - ff_vc1_1ref_mvdata_vlc[i].table_allocated = vlc_offs[i * 3 + 40] - vlc_offs[i * 3 + 39]; - init_vlc(&ff_vc1_1ref_mvdata_vlc[i], VC1_1REF_MVDATA_VLC_BITS, 72, - ff_vc1_1ref_mvdata_bits[i], 1, 1, - ff_vc1_1ref_mvdata_codes[i], 4, 4, INIT_VLC_USE_NEW_STATIC); - } - for (i = 0; i < 4; i++) { - /* Initialize 2MV Block pattern VLC tables */ - ff_vc1_2mv_block_pattern_vlc[i].table = &vlc_table[vlc_offs[i + 49]]; - ff_vc1_2mv_block_pattern_vlc[i].table_allocated = vlc_offs[i + 50] - vlc_offs[i + 49]; - init_vlc(&ff_vc1_2mv_block_pattern_vlc[i], VC1_2MV_BLOCK_PATTERN_VLC_BITS, 4, - ff_vc1_2mv_block_pattern_bits[i], 1, 1, - ff_vc1_2mv_block_pattern_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); - } - for (i = 0; i < 8; i++) { - /* Initialize interlaced CBPCY VLC tables (Table 124 - Table 131) */ - ff_vc1_icbpcy_vlc[i].table = &vlc_table[vlc_offs[i * 3 + 53]]; - ff_vc1_icbpcy_vlc[i].table_allocated = vlc_offs[i * 3 + 54] - vlc_offs[i * 3 + 53]; - init_vlc(&ff_vc1_icbpcy_vlc[i], VC1_ICBPCY_VLC_BITS, 63, - ff_vc1_icbpcy_p_bits[i], 1, 1, - ff_vc1_icbpcy_p_codes[i], 2, 2, INIT_VLC_USE_NEW_STATIC); - /* Initialize interlaced field picture MBMODE VLC tables */ - ff_vc1_if_mmv_mbmode_vlc[i].table = &vlc_table[vlc_offs[i * 3 + 54]]; - ff_vc1_if_mmv_mbmode_vlc[i].table_allocated = vlc_offs[i * 3 + 55] - vlc_offs[i * 3 + 54]; - init_vlc(&ff_vc1_if_mmv_mbmode_vlc[i], VC1_IF_MMV_MBMODE_VLC_BITS, 8, - ff_vc1_if_mmv_mbmode_bits[i], 1, 1, - ff_vc1_if_mmv_mbmode_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); - ff_vc1_if_1mv_mbmode_vlc[i].table = &vlc_table[vlc_offs[i * 3 + 55]]; - ff_vc1_if_1mv_mbmode_vlc[i].table_allocated = vlc_offs[i * 3 + 56] - vlc_offs[i * 3 + 55]; - init_vlc(&ff_vc1_if_1mv_mbmode_vlc[i], VC1_IF_1MV_MBMODE_VLC_BITS, 6, - ff_vc1_if_1mv_mbmode_bits[i], 1, 1, - ff_vc1_if_1mv_mbmode_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); - } + INIT_VLC_STATIC(&ff_vc1_bfraction_vlc, VC1_BFRACTION_VLC_BITS, 23, + ff_vc1_bfraction_bits, 1, 1, + ff_vc1_bfraction_codes, 1, 1, 1 << VC1_BFRACTION_VLC_BITS); + INIT_VLC_STATIC(&ff_vc1_norm2_vlc, VC1_NORM2_VLC_BITS, 4, + ff_vc1_norm2_bits, 1, 1, + ff_vc1_norm2_codes, 1, 1, 1 << VC1_NORM2_VLC_BITS); + INIT_VLC_STATIC(&ff_vc1_norm6_vlc, VC1_NORM6_VLC_BITS, 64, + ff_vc1_norm6_bits, 1, 1, + ff_vc1_norm6_codes, 2, 2, 556); + INIT_VLC_STATIC(&ff_vc1_imode_vlc, VC1_IMODE_VLC_BITS, 7, + ff_vc1_imode_bits, 1, 1, + ff_vc1_imode_codes, 1, 1, 1 << VC1_IMODE_VLC_BITS); + for (int i = 0; i < 3; i++) { + ff_vc1_ttmb_vlc[i].table = &vlc_table[vlc_offs[i * 3 + 0]]; + ff_vc1_ttmb_vlc[i].table_allocated = vlc_offs[i * 3 + 1] - vlc_offs[i * 3 + 0]; + init_vlc(&ff_vc1_ttmb_vlc[i], VC1_TTMB_VLC_BITS, 16, + ff_vc1_ttmb_bits[i], 1, 1, + ff_vc1_ttmb_codes[i], 2, 2, INIT_VLC_USE_NEW_STATIC); + ff_vc1_ttblk_vlc[i].table = &vlc_table[vlc_offs[i * 3 + 1]]; + ff_vc1_ttblk_vlc[i].table_allocated = vlc_offs[i * 3 + 2] - vlc_offs[i * 3 + 1]; + init_vlc(&ff_vc1_ttblk_vlc[i], VC1_TTBLK_VLC_BITS, 8, + ff_vc1_ttblk_bits[i], 1, 1, + ff_vc1_ttblk_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); + ff_vc1_subblkpat_vlc[i].table = &vlc_table[vlc_offs[i * 3 + 2]]; + ff_vc1_subblkpat_vlc[i].table_allocated = vlc_offs[i * 3 + 3] - vlc_offs[i * 3 + 2]; + init_vlc(&ff_vc1_subblkpat_vlc[i], VC1_SUBBLKPAT_VLC_BITS, 15, + ff_vc1_subblkpat_bits[i], 1, 1, + ff_vc1_subblkpat_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); + } + for (int i = 0; i < 4; i++) { + ff_vc1_4mv_block_pattern_vlc[i].table = &vlc_table[vlc_offs[i * 3 + 9]]; + ff_vc1_4mv_block_pattern_vlc[i].table_allocated = vlc_offs[i * 3 + 10] - vlc_offs[i * 3 + 9]; + init_vlc(&ff_vc1_4mv_block_pattern_vlc[i], VC1_4MV_BLOCK_PATTERN_VLC_BITS, 16, + ff_vc1_4mv_block_pattern_bits[i], 1, 1, + ff_vc1_4mv_block_pattern_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); + ff_vc1_cbpcy_p_vlc[i].table = &vlc_table[vlc_offs[i * 3 + 10]]; + ff_vc1_cbpcy_p_vlc[i].table_allocated = vlc_offs[i * 3 + 11] - vlc_offs[i * 3 + 10]; + init_vlc(&ff_vc1_cbpcy_p_vlc[i], VC1_CBPCY_P_VLC_BITS, 64, + ff_vc1_cbpcy_p_bits[i], 1, 1, + ff_vc1_cbpcy_p_codes[i], 2, 2, INIT_VLC_USE_NEW_STATIC); + ff_vc1_mv_diff_vlc[i].table = &vlc_table[vlc_offs[i * 3 + 11]]; + ff_vc1_mv_diff_vlc[i].table_allocated = vlc_offs[i * 3 + 12] - vlc_offs[i * 3 + 11]; + init_vlc(&ff_vc1_mv_diff_vlc[i], VC1_MV_DIFF_VLC_BITS, 73, + ff_vc1_mv_diff_bits[i], 1, 1, + ff_vc1_mv_diff_codes[i], 2, 2, INIT_VLC_USE_NEW_STATIC); + } + for (int i = 0; i < 8; i++) { + ff_vc1_ac_coeff_table[i].table = &vlc_table[vlc_offs[i * 2 + 21]]; + ff_vc1_ac_coeff_table[i].table_allocated = vlc_offs[i * 2 + 22] - vlc_offs[i * 2 + 21]; + init_vlc(&ff_vc1_ac_coeff_table[i], AC_VLC_BITS, ff_vc1_ac_sizes[i], + &vc1_ac_tables[i][0][1], 8, 4, + &vc1_ac_tables[i][0][0], 8, 4, INIT_VLC_USE_NEW_STATIC); + /* initialize interlaced MVDATA tables (2-Ref) */ + ff_vc1_2ref_mvdata_vlc[i].table = &vlc_table[vlc_offs[i * 2 + 22]]; + ff_vc1_2ref_mvdata_vlc[i].table_allocated = vlc_offs[i * 2 + 23] - vlc_offs[i * 2 + 22]; + init_vlc(&ff_vc1_2ref_mvdata_vlc[i], VC1_2REF_MVDATA_VLC_BITS, 126, + ff_vc1_2ref_mvdata_bits[i], 1, 1, + ff_vc1_2ref_mvdata_codes[i], 4, 4, INIT_VLC_USE_NEW_STATIC); + } + for (int i = 0; i < 4; i++) { + /* initialize 4MV MBMODE VLC tables for interlaced frame P picture */ + ff_vc1_intfr_4mv_mbmode_vlc[i].table = &vlc_table[vlc_offs[i * 3 + 37]]; + ff_vc1_intfr_4mv_mbmode_vlc[i].table_allocated = vlc_offs[i * 3 + 38] - vlc_offs[i * 3 + 37]; + init_vlc(&ff_vc1_intfr_4mv_mbmode_vlc[i], VC1_INTFR_4MV_MBMODE_VLC_BITS, 15, + ff_vc1_intfr_4mv_mbmode_bits[i], 1, 1, + ff_vc1_intfr_4mv_mbmode_codes[i], 2, 2, INIT_VLC_USE_NEW_STATIC); + /* initialize NON-4MV MBMODE VLC tables for the same */ + ff_vc1_intfr_non4mv_mbmode_vlc[i].table = &vlc_table[vlc_offs[i * 3 + 38]]; + ff_vc1_intfr_non4mv_mbmode_vlc[i].table_allocated = vlc_offs[i * 3 + 39] - vlc_offs[i * 3 + 38]; + init_vlc(&ff_vc1_intfr_non4mv_mbmode_vlc[i], VC1_INTFR_NON4MV_MBMODE_VLC_BITS, 9, + ff_vc1_intfr_non4mv_mbmode_bits[i], 1, 1, + ff_vc1_intfr_non4mv_mbmode_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); + /* initialize interlaced MVDATA tables (1-Ref) */ + ff_vc1_1ref_mvdata_vlc[i].table = &vlc_table[vlc_offs[i * 3 + 39]]; + ff_vc1_1ref_mvdata_vlc[i].table_allocated = vlc_offs[i * 3 + 40] - vlc_offs[i * 3 + 39]; + init_vlc(&ff_vc1_1ref_mvdata_vlc[i], VC1_1REF_MVDATA_VLC_BITS, 72, + ff_vc1_1ref_mvdata_bits[i], 1, 1, + ff_vc1_1ref_mvdata_codes[i], 4, 4, INIT_VLC_USE_NEW_STATIC); + } + for (int i = 0; i < 4; i++) { + /* Initialize 2MV Block pattern VLC tables */ + ff_vc1_2mv_block_pattern_vlc[i].table = &vlc_table[vlc_offs[i + 49]]; + ff_vc1_2mv_block_pattern_vlc[i].table_allocated = vlc_offs[i + 50] - vlc_offs[i + 49]; + init_vlc(&ff_vc1_2mv_block_pattern_vlc[i], VC1_2MV_BLOCK_PATTERN_VLC_BITS, 4, + ff_vc1_2mv_block_pattern_bits[i], 1, 1, + ff_vc1_2mv_block_pattern_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); + } + for (int i = 0; i < 8; i++) { + /* Initialize interlaced CBPCY VLC tables (Table 124 - Table 131) */ + ff_vc1_icbpcy_vlc[i].table = &vlc_table[vlc_offs[i * 3 + 53]]; + ff_vc1_icbpcy_vlc[i].table_allocated = vlc_offs[i * 3 + 54] - vlc_offs[i * 3 + 53]; + init_vlc(&ff_vc1_icbpcy_vlc[i], VC1_ICBPCY_VLC_BITS, 63, + ff_vc1_icbpcy_p_bits[i], 1, 1, + ff_vc1_icbpcy_p_codes[i], 2, 2, INIT_VLC_USE_NEW_STATIC); + /* Initialize interlaced field picture MBMODE VLC tables */ + ff_vc1_if_mmv_mbmode_vlc[i].table = &vlc_table[vlc_offs[i * 3 + 54]]; + ff_vc1_if_mmv_mbmode_vlc[i].table_allocated = vlc_offs[i * 3 + 55] - vlc_offs[i * 3 + 54]; + init_vlc(&ff_vc1_if_mmv_mbmode_vlc[i], VC1_IF_MMV_MBMODE_VLC_BITS, 8, + ff_vc1_if_mmv_mbmode_bits[i], 1, 1, + ff_vc1_if_mmv_mbmode_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); + ff_vc1_if_1mv_mbmode_vlc[i].table = &vlc_table[vlc_offs[i * 3 + 55]]; + ff_vc1_if_1mv_mbmode_vlc[i].table_allocated = vlc_offs[i * 3 + 56] - vlc_offs[i * 3 + 55]; + init_vlc(&ff_vc1_if_1mv_mbmode_vlc[i], VC1_IF_1MV_MBMODE_VLC_BITS, 6, + ff_vc1_if_1mv_mbmode_bits[i], 1, 1, + ff_vc1_if_1mv_mbmode_codes[i], 1, 1, INIT_VLC_USE_NEW_STATIC); + } } /** diff --git a/libavcodec/vc1_block.c b/libavcodec/vc1_block.c index c922efe4c..119df4081 100644 --- a/libavcodec/vc1_block.c +++ b/libavcodec/vc1_block.c @@ -29,6 +29,7 @@ #include "avcodec.h" #include "mpegutils.h" #include "mpegvideo.h" +#include "mpegvideodec.h" #include "msmpeg4data.h" #include "unary.h" #include "vc1.h" diff --git a/libavcodec/vc1_common.h b/libavcodec/vc1_common.h index b46c33f7e..c0f0c8c2e 100644 --- a/libavcodec/vc1_common.h +++ b/libavcodec/vc1_common.h @@ -26,7 +26,7 @@ #include #include "libavutil/attributes.h" -#include "internal.h" +#include "startcode.h" /** Markers used in VC-1 AP frame data */ //@{ diff --git a/libavcodec/vc1_parser.c b/libavcodec/vc1_parser.c index 00896ddb0..8257e0ccf 100644 --- a/libavcodec/vc1_parser.c +++ b/libavcodec/vc1_parser.c @@ -29,7 +29,6 @@ #include "parser.h" #include "vc1.h" #include "get_bits.h" -#include "internal.h" /** The maximum number of bytes of a sequence, entry point or * frame header whose values we pay any attention to */ diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c index 267d72d15..a7d556c37 100644 --- a/libavcodec/vc1dec.c +++ b/libavcodec/vc1dec.c @@ -26,15 +26,19 @@ * VC-1 and WMV3 decoder */ +#include "config_components.h" + #include "avcodec.h" #include "blockdsp.h" +#include "codec_internal.h" #include "get_bits.h" #include "hwconfig.h" #include "internal.h" #include "mpeg_er.h" #include "mpegvideo.h" -#include "msmpeg4.h" +#include "mpegvideodec.h" #include "msmpeg4data.h" +#include "msmpeg4dec.h" #include "profiles.h" #include "vc1.h" #include "vc1data.h" @@ -487,7 +491,7 @@ static av_cold int vc1_decode_init(AVCodecContext *avctx) size = next - start - 4; if (size <= 0) continue; - buf2_size = vc1_unescape_buffer(start + 4, size, buf2); + buf2_size = v->vc1dsp.vc1_unescape_buffer(start + 4, size, buf2); init_get_bits(&gb, buf2, buf2_size * 8); switch (AV_RB32(start)) { case VC1_CODE_SEQHDR: @@ -619,14 +623,13 @@ av_cold int ff_vc1_decode_end(AVCodecContext *avctx) /** Decode a VC1/WMV3 frame * @todo TODO: Handle VC-1 IDUs (Transport level?) */ -static int vc1_decode_frame(AVCodecContext *avctx, void *data, +static int vc1_decode_frame(AVCodecContext *avctx, AVFrame *pict, int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size, n_slices = 0, i, ret; VC1Context *v = avctx->priv_data; MpegEncContext *s = &v->s; - AVFrame *pict = data; uint8_t *buf2 = NULL; const uint8_t *buf_start = buf, *buf_start_second_field = NULL; int mb_height, n_slices1=-1; @@ -677,7 +680,7 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, case VC1_CODE_FRAME: if (avctx->hwaccel) buf_start = start; - buf_size2 = vc1_unescape_buffer(start + 4, size, buf2); + buf_size2 = v->vc1dsp.vc1_unescape_buffer(start + 4, size, buf2); break; case VC1_CODE_FIELD: { int buf_size3; @@ -694,8 +697,8 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, ret = AVERROR(ENOMEM); goto err; } - buf_size3 = vc1_unescape_buffer(start + 4, size, - slices[n_slices].buf); + buf_size3 = v->vc1dsp.vc1_unescape_buffer(start + 4, size, + slices[n_slices].buf); init_get_bits(&slices[n_slices].gb, slices[n_slices].buf, buf_size3 << 3); slices[n_slices].mby_start = avctx->coded_height + 31 >> 5; @@ -706,7 +709,7 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, break; } case VC1_CODE_ENTRYPOINT: /* it should be before frame data */ - buf_size2 = vc1_unescape_buffer(start + 4, size, buf2); + buf_size2 = v->vc1dsp.vc1_unescape_buffer(start + 4, size, buf2); init_get_bits(&s->gb, buf2, buf_size2 * 8); ff_vc1_decode_entry_point(avctx, v, &s->gb); break; @@ -723,8 +726,8 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, ret = AVERROR(ENOMEM); goto err; } - buf_size3 = vc1_unescape_buffer(start + 4, size, - slices[n_slices].buf); + buf_size3 = v->vc1dsp.vc1_unescape_buffer(start + 4, size, + slices[n_slices].buf); init_get_bits(&slices[n_slices].gb, slices[n_slices].buf, buf_size3 << 3); slices[n_slices].mby_start = get_bits(&slices[n_slices].gb, 9); @@ -758,7 +761,7 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, ret = AVERROR(ENOMEM); goto err; } - buf_size3 = vc1_unescape_buffer(divider + 4, buf + buf_size - divider - 4, slices[n_slices].buf); + buf_size3 = v->vc1dsp.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 >> 1; @@ -767,9 +770,9 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, n_slices1 = n_slices - 1; n_slices++; } - buf_size2 = vc1_unescape_buffer(buf, divider - buf, buf2); + buf_size2 = v->vc1dsp.vc1_unescape_buffer(buf, divider - buf, buf2); } else { - buf_size2 = vc1_unescape_buffer(buf, buf_size, buf2); + buf_size2 = v->vc1dsp.vc1_unescape_buffer(buf, buf_size, buf2); } init_get_bits(&s->gb, buf2, buf_size2*8); } else{ @@ -872,13 +875,6 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, goto end; } - if (s->next_p_frame_damaged) { - if (s->pict_type == AV_PICTURE_TYPE_B) - goto end; - else - s->next_p_frame_damaged = 0; - } - if ((ret = ff_mpv_frame_start(s, avctx)) < 0) { goto err; } @@ -1205,18 +1201,19 @@ static const enum AVPixelFormat vc1_hwaccel_pixfmt_list_420[] = { AV_PIX_FMT_NONE }; -const AVCodec ff_vc1_decoder = { - .name = "vc1", - .long_name = NULL_IF_CONFIG_SMALL("SMPTE VC-1"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_VC1, +const FFCodec ff_vc1_decoder = { + .p.name = "vc1", + .p.long_name = NULL_IF_CONFIG_SMALL("SMPTE VC-1"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_VC1, .priv_data_size = sizeof(VC1Context), .init = vc1_decode_init, .close = ff_vc1_decode_end, - .decode = vc1_decode_frame, + FF_CODEC_DECODE_CB(vc1_decode_frame), .flush = ff_mpeg_flush, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, - .pix_fmts = vc1_hwaccel_pixfmt_list_420, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + .p.pix_fmts = vc1_hwaccel_pixfmt_list_420, .hw_configs = (const AVCodecHWConfigInternal *const []) { #if CONFIG_VC1_DXVA2_HWACCEL HWACCEL_DXVA2(vc1), @@ -1238,22 +1235,23 @@ const AVCodec ff_vc1_decoder = { #endif NULL }, - .profiles = NULL_IF_CONFIG_SMALL(ff_vc1_profiles) + .p.profiles = NULL_IF_CONFIG_SMALL(ff_vc1_profiles) }; #if CONFIG_WMV3_DECODER -const AVCodec ff_wmv3_decoder = { - .name = "wmv3", - .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 9"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_WMV3, +const FFCodec ff_wmv3_decoder = { + .p.name = "wmv3", + .p.long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 9"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_WMV3, .priv_data_size = sizeof(VC1Context), .init = vc1_decode_init, .close = ff_vc1_decode_end, - .decode = vc1_decode_frame, + FF_CODEC_DECODE_CB(vc1_decode_frame), .flush = ff_mpeg_flush, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, - .pix_fmts = vc1_hwaccel_pixfmt_list_420, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + .p.pix_fmts = vc1_hwaccel_pixfmt_list_420, .hw_configs = (const AVCodecHWConfigInternal *const []) { #if CONFIG_WMV3_DXVA2_HWACCEL HWACCEL_DXVA2(wmv3), @@ -1275,23 +1273,24 @@ const AVCodec ff_wmv3_decoder = { #endif NULL }, - .profiles = NULL_IF_CONFIG_SMALL(ff_vc1_profiles) + .p.profiles = NULL_IF_CONFIG_SMALL(ff_vc1_profiles) }; #endif #if CONFIG_WMV3IMAGE_DECODER -const AVCodec ff_wmv3image_decoder = { - .name = "wmv3image", - .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 9 Image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_WMV3IMAGE, +const FFCodec ff_wmv3image_decoder = { + .p.name = "wmv3image", + .p.long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 9 Image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_WMV3IMAGE, .priv_data_size = sizeof(VC1Context), .init = vc1_decode_init, .close = ff_vc1_decode_end, - .decode = vc1_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(vc1_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, .flush = vc1_sprite_flush, - .pix_fmts = (const enum AVPixelFormat[]) { + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, @@ -1299,18 +1298,19 @@ const AVCodec ff_wmv3image_decoder = { #endif #if CONFIG_VC1IMAGE_DECODER -const AVCodec ff_vc1image_decoder = { - .name = "vc1image", - .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 9 Image v2"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_VC1IMAGE, +const FFCodec ff_vc1image_decoder = { + .p.name = "vc1image", + .p.long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 9 Image v2"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_VC1IMAGE, .priv_data_size = sizeof(VC1Context), .init = vc1_decode_init, .close = ff_vc1_decode_end, - .decode = vc1_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(vc1_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, .flush = vc1_sprite_flush, - .pix_fmts = (const enum AVPixelFormat[]) { + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, diff --git a/libavcodec/vc1dsp.c b/libavcodec/vc1dsp.c index 04fc8b12f..62c553bc0 100644 --- a/libavcodec/vc1dsp.c +++ b/libavcodec/vc1dsp.c @@ -24,6 +24,8 @@ * VC-1 and WMV3 decoder */ +#include "config_components.h" + #include "libavutil/avassert.h" #include "libavutil/common.h" #include "libavutil/intreadwrite.h" @@ -32,9 +34,10 @@ #include "rnd_avg.h" #include "vc1dsp.h" #include "startcode.h" +#include "vc1_common.h" /* Apply overlap transform to horizontal edge */ -static void vc1_v_overlap_c(uint8_t *src, int stride) +static void vc1_v_overlap_c(uint8_t *src, ptrdiff_t stride) { int i; int a, b, c, d; @@ -58,7 +61,7 @@ static void vc1_v_overlap_c(uint8_t *src, int stride) } /* Apply overlap transform to vertical edge */ -static void vc1_h_overlap_c(uint8_t *src, int stride) +static void vc1_h_overlap_c(uint8_t *src, ptrdiff_t stride) { int i; int a, b, c, d; @@ -107,7 +110,7 @@ static void vc1_v_s_overlap_c(int16_t *top, int16_t *bottom) } } -static void vc1_h_s_overlap_c(int16_t *left, int16_t *right, int left_stride, int right_stride, int flags) +static void vc1_h_s_overlap_c(int16_t *left, int16_t *right, ptrdiff_t left_stride, ptrdiff_t right_stride, int flags) { int i; int a, b, c, d; @@ -144,7 +147,7 @@ static void vc1_h_s_overlap_c(int16_t *left, int16_t *right, int left_stride, in * @return whether other 3 pairs should be filtered or not * @see 8.6 */ -static av_always_inline int vc1_filter_line(uint8_t *src, int stride, int pq) +static av_always_inline int vc1_filter_line(uint8_t *src, ptrdiff_t stride, int pq) { int a0 = (2 * (src[-2 * stride] - src[1 * stride]) - 5 * (src[-1 * stride] - src[0 * stride]) + 4) >> 3; @@ -193,7 +196,7 @@ static av_always_inline int vc1_filter_line(uint8_t *src, int stride, int pq) * @param pq block quantizer * @see 8.6 */ -static inline void vc1_loop_filter(uint8_t *src, int step, int stride, +static inline void vc1_loop_filter(uint8_t *src, int step, ptrdiff_t stride, int len, int pq) { int i; @@ -210,32 +213,32 @@ static inline void vc1_loop_filter(uint8_t *src, int step, int stride, } } -static void vc1_v_loop_filter4_c(uint8_t *src, int stride, int pq) +static void vc1_v_loop_filter4_c(uint8_t *src, ptrdiff_t stride, int pq) { vc1_loop_filter(src, 1, stride, 4, pq); } -static void vc1_h_loop_filter4_c(uint8_t *src, int stride, int pq) +static void vc1_h_loop_filter4_c(uint8_t *src, ptrdiff_t stride, int pq) { vc1_loop_filter(src, stride, 1, 4, pq); } -static void vc1_v_loop_filter8_c(uint8_t *src, int stride, int pq) +static void vc1_v_loop_filter8_c(uint8_t *src, ptrdiff_t stride, int pq) { vc1_loop_filter(src, 1, stride, 8, pq); } -static void vc1_h_loop_filter8_c(uint8_t *src, int stride, int pq) +static void vc1_h_loop_filter8_c(uint8_t *src, ptrdiff_t stride, int pq) { vc1_loop_filter(src, stride, 1, 8, pq); } -static void vc1_v_loop_filter16_c(uint8_t *src, int stride, int pq) +static void vc1_v_loop_filter16_c(uint8_t *src, ptrdiff_t stride, int pq) { vc1_loop_filter(src, 1, stride, 16, pq); } -static void vc1_h_loop_filter16_c(uint8_t *src, int stride, int pq) +static void vc1_h_loop_filter16_c(uint8_t *src, ptrdiff_t stride, int pq) { vc1_loop_filter(src, stride, 1, 16, pq); } @@ -1028,17 +1031,19 @@ av_cold void ff_vc1dsp_init(VC1DSPContext *dsp) #endif /* CONFIG_WMV3IMAGE_DECODER || CONFIG_VC1IMAGE_DECODER */ dsp->startcode_find_candidate = ff_startcode_find_candidate_c; + dsp->vc1_unescape_buffer = vc1_unescape_buffer; - if (ARCH_AARCH64) - ff_vc1dsp_init_aarch64(dsp); - if (ARCH_ARM) - ff_vc1dsp_init_arm(dsp); - if (ARCH_PPC) - ff_vc1dsp_init_ppc(dsp); - if (ARCH_X86) - ff_vc1dsp_init_x86(dsp); - if (ARCH_MIPS) - ff_vc1dsp_init_mips(dsp); - if (ARCH_LOONGARCH) - ff_vc1dsp_init_loongarch(dsp); +#if ARCH_AARCH64 + ff_vc1dsp_init_aarch64(dsp); +#elif ARCH_ARM + ff_vc1dsp_init_arm(dsp); +#elif ARCH_PPC + ff_vc1dsp_init_ppc(dsp); +#elif ARCH_X86 + ff_vc1dsp_init_x86(dsp); +#elif ARCH_MIPS + ff_vc1dsp_init_mips(dsp); +#elif ARCH_LOONGARCH + ff_vc1dsp_init_loongarch(dsp); +#endif } diff --git a/libavcodec/vc1dsp.h b/libavcodec/vc1dsp.h index c6443acb2..7ed1776ca 100644 --- a/libavcodec/vc1dsp.h +++ b/libavcodec/vc1dsp.h @@ -42,16 +42,16 @@ typedef struct VC1DSPContext { void (*vc1_inv_trans_8x4_dc)(uint8_t *dest, ptrdiff_t stride, int16_t *block); void (*vc1_inv_trans_4x8_dc)(uint8_t *dest, ptrdiff_t stride, int16_t *block); void (*vc1_inv_trans_4x4_dc)(uint8_t *dest, ptrdiff_t stride, int16_t *block); - void (*vc1_v_overlap)(uint8_t *src, int stride); - void (*vc1_h_overlap)(uint8_t *src, int stride); + void (*vc1_v_overlap)(uint8_t *src, ptrdiff_t stride); + void (*vc1_h_overlap)(uint8_t *src, ptrdiff_t stride); void (*vc1_v_s_overlap)(int16_t *top, int16_t *bottom); - void (*vc1_h_s_overlap)(int16_t *left, int16_t *right, int left_stride, int right_stride, int flags); - void (*vc1_v_loop_filter4)(uint8_t *src, int stride, int pq); - void (*vc1_h_loop_filter4)(uint8_t *src, int stride, int pq); - void (*vc1_v_loop_filter8)(uint8_t *src, int stride, int pq); - void (*vc1_h_loop_filter8)(uint8_t *src, int stride, int pq); - void (*vc1_v_loop_filter16)(uint8_t *src, int stride, int pq); - void (*vc1_h_loop_filter16)(uint8_t *src, int stride, int pq); + void (*vc1_h_s_overlap)(int16_t *left, int16_t *right, ptrdiff_t left_stride, ptrdiff_t right_stride, int flags); + void (*vc1_v_loop_filter4)(uint8_t *src, ptrdiff_t stride, int pq); + void (*vc1_h_loop_filter4)(uint8_t *src, ptrdiff_t stride, int pq); + void (*vc1_v_loop_filter8)(uint8_t *src, ptrdiff_t stride, int pq); + void (*vc1_h_loop_filter8)(uint8_t *src, ptrdiff_t stride, int pq); + void (*vc1_v_loop_filter16)(uint8_t *src, ptrdiff_t stride, int pq); + void (*vc1_h_loop_filter16)(uint8_t *src, ptrdiff_t stride, int pq); /* put 8x8 block with bicubic interpolation and quarterpel precision * last argument is actually round value instead of height @@ -80,6 +80,9 @@ typedef struct VC1DSPContext { * one or more further zero bytes and a one byte. */ int (*startcode_find_candidate)(const uint8_t *buf, int size); + + /* Copy a buffer, removing startcode emulation escape bytes as we go */ + int (*vc1_unescape_buffer)(const uint8_t *src, int size, uint8_t *dst); } VC1DSPContext; void ff_vc1dsp_init(VC1DSPContext* c); diff --git a/libavcodec/vc2enc.c b/libavcodec/vc2enc.c index f0d2cdf62..1e3127f08 100644 --- a/libavcodec/vc2enc.c +++ b/libavcodec/vc2enc.c @@ -21,10 +21,11 @@ #include "libavutil/pixdesc.h" #include "libavutil/opt.h" +#include "libavutil/version.h" +#include "codec_internal.h" #include "dirac.h" #include "encode.h" #include "put_bits.h" -#include "internal.h" #include "version.h" #include "vc2enc_dwt.h" @@ -1135,7 +1136,7 @@ static av_cold int vc2_encode_init(AVCodecContext *avctx) p->coef_stride = FFALIGN(p->dwt_width, 32); p->coef_buf = av_mallocz(p->coef_stride*p->dwt_height*sizeof(dwtcoef)); if (!p->coef_buf) - goto alloc_fail; + return AVERROR(ENOMEM); for (level = s->wavelet_depth-1; level >= 0; level--) { w = w >> 1; h = h >> 1; @@ -1154,7 +1155,7 @@ static av_cold int vc2_encode_init(AVCodecContext *avctx) s->plane[i].coef_stride, s->plane[i].dwt_height, s->slice_width, s->slice_height)) - goto alloc_fail; + return AVERROR(ENOMEM); } /* Slices */ @@ -1163,7 +1164,7 @@ static av_cold int vc2_encode_init(AVCodecContext *avctx) s->slice_args = av_calloc(s->num_x*s->num_y, sizeof(SliceArgs)); if (!s->slice_args) - goto alloc_fail; + return AVERROR(ENOMEM); for (i = 0; i < 116; i++) { const uint64_t qf = ff_dirac_qscale_tab[i]; @@ -1183,11 +1184,6 @@ static av_cold int vc2_encode_init(AVCodecContext *avctx) } return 0; - -alloc_fail: - vc2_encode_end(avctx); - av_log(avctx, AV_LOG_ERROR, "Unable to allocate memory!\n"); - return AVERROR(ENOMEM); } #define VC2ENC_FLAGS (AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) @@ -1216,7 +1212,7 @@ static const AVClass vc2enc_class = { .version = LIBAVUTIL_VERSION_INT }; -static const AVCodecDefault vc2enc_defaults[] = { +static const FFCodecDefault vc2enc_defaults[] = { { "b", "600000000" }, { NULL }, }; @@ -1228,18 +1224,18 @@ static const enum AVPixelFormat allowed_pix_fmts[] = { AV_PIX_FMT_NONE }; -const AVCodec ff_vc2_encoder = { - .name = "vc2", - .long_name = NULL_IF_CONFIG_SMALL("SMPTE VC-2"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_DIRAC, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS, +const FFCodec ff_vc2_encoder = { + .p.name = "vc2", + .p.long_name = NULL_IF_CONFIG_SMALL("SMPTE VC-2"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_DIRAC, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .priv_data_size = sizeof(VC2EncContext), .init = vc2_encode_init, .close = vc2_encode_end, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, - .encode2 = vc2_encode_frame, - .priv_class = &vc2enc_class, + FF_CODEC_ENCODE_CB(vc2_encode_frame), + .p.priv_class = &vc2enc_class, .defaults = vc2enc_defaults, - .pix_fmts = allowed_pix_fmts + .p.pix_fmts = allowed_pix_fmts }; diff --git a/libavcodec/vc2enc_dwt.c b/libavcodec/vc2enc_dwt.c index a8d3f1c66..441af040e 100644 --- a/libavcodec/vc2enc_dwt.c +++ b/libavcodec/vc2enc_dwt.c @@ -276,6 +276,8 @@ av_cold int ff_vc2enc_init_transforms(VC2TransformContext *s, int p_stride, av_cold void ff_vc2enc_free_transforms(VC2TransformContext *s) { - av_free(s->buffer - s->padding); - s->buffer = NULL; + if (s->buffer) { + av_free(s->buffer - s->padding); + s->buffer = NULL; + } } diff --git a/libavcodec/vcr1.c b/libavcodec/vcr1.c index 996c9118a..4aed1eeaf 100644 --- a/libavcodec/vcr1.c +++ b/libavcodec/vcr1.c @@ -25,6 +25,7 @@ */ #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "libavutil/avassert.h" #include "libavutil/internal.h" @@ -46,11 +47,10 @@ static av_cold int vcr1_decode_init(AVCodecContext *avctx) return 0; } -static int vcr1_decode_frame(AVCodecContext *avctx, void *data, +static int vcr1_decode_frame(AVCodecContext *avctx, AVFrame *p, int *got_frame, AVPacket *avpkt) { VCR1Context *const a = avctx->priv_data; - AVFrame *const p = data; const uint8_t *bytestream = avpkt->data; const uint8_t *bytestream_end = bytestream + avpkt->size; int i, x, y, ret; @@ -121,14 +121,14 @@ static int vcr1_decode_frame(AVCodecContext *avctx, void *data, return bytestream - avpkt->data; } -const AVCodec ff_vcr1_decoder = { - .name = "vcr1", - .long_name = NULL_IF_CONFIG_SMALL("ATI VCR1"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_VCR1, +const FFCodec ff_vcr1_decoder = { + .p.name = "vcr1", + .p.long_name = NULL_IF_CONFIG_SMALL("ATI VCR1"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_VCR1, .priv_data_size = sizeof(VCR1Context), .init = vcr1_decode_init, - .decode = vcr1_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(vcr1_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/vdpau.c b/libavcodec/vdpau.c index 7c29746ad..0bb793c01 100644 --- a/libavcodec/vdpau.c +++ b/libavcodec/vdpau.c @@ -21,12 +21,14 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include #include "avcodec.h" #include "decode.h" #include "internal.h" -#include "h264dec.h" +#include "mpegvideodec.h" #include "vc1.h" #include "vdpau.h" #include "vdpau_internal.h" diff --git a/libavcodec/vdpau_av1.c b/libavcodec/vdpau_av1.c new file mode 100644 index 000000000..3c3c8e61d --- /dev/null +++ b/libavcodec/vdpau_av1.c @@ -0,0 +1,370 @@ +/* + * AV1 HW decode acceleration through VDPAU + * + * Copyright (c) 2022 Manoj Gupta Bonda + * + * 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/pixdesc.h" +#include "avcodec.h" +#include "internal.h" +#include "av1dec.h" +#include "hwconfig.h" +#include "vdpau.h" +#include "vdpau_internal.h" + +static int get_bit_depth_from_seq(const AV1RawSequenceHeader *seq) +{ + if (seq->seq_profile == 2 && seq->color_config.high_bitdepth) { + return seq->color_config.twelve_bit ? 12 : 10; + } else if (seq->seq_profile <= 2 && seq->color_config.high_bitdepth) { + return 10; + } else { + return 8; + } +} + +static int vdpau_av1_start_frame(AVCodecContext *avctx, + const uint8_t *buffer, uint32_t size) +{ + AV1DecContext *s = avctx->priv_data; + const AV1RawSequenceHeader *seq = s->raw_seq; + const AV1RawFrameHeader *frame_header = s->raw_frame_header; + const AV1RawFilmGrainParams *film_grain = &s->cur_frame.film_grain; + + struct vdpau_picture_context *pic_ctx = s->cur_frame.hwaccel_picture_private; + int i,j; + + unsigned char remap_lr_type[4] = { AV1_RESTORE_NONE, AV1_RESTORE_SWITCHABLE, AV1_RESTORE_WIENER, AV1_RESTORE_SGRPROJ }; + + + VdpPictureInfoAV1 *info = &pic_ctx->info.av1; + const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(avctx->sw_pix_fmt); + if (!pixdesc) { + return AV_PIX_FMT_NONE; + } + + info->width = avctx->width; + info->height = avctx->height; + + + info->frame_offset = frame_header->order_hint; + + /* Sequence Header */ + info->profile = seq->seq_profile; + info->use_128x128_superblock = seq->use_128x128_superblock; + info->subsampling_x = seq->color_config.subsampling_x; + info->subsampling_y = seq->color_config.subsampling_y; + info->mono_chrome = seq->color_config.mono_chrome; + info->bit_depth_minus8 = get_bit_depth_from_seq(seq) - 8; + info->enable_filter_intra = seq->enable_filter_intra; + info->enable_intra_edge_filter = seq->enable_intra_edge_filter; + info->enable_interintra_compound = seq->enable_interintra_compound; + info->enable_masked_compound = seq->enable_masked_compound; + info->enable_dual_filter = seq->enable_dual_filter; + info->enable_order_hint = seq->enable_order_hint; + info->order_hint_bits_minus1 = seq->order_hint_bits_minus_1; + info->enable_jnt_comp = seq->enable_jnt_comp; + info->enable_superres = seq->enable_superres; + info->enable_cdef = seq->enable_cdef; + info->enable_restoration = seq->enable_restoration; + info->enable_fgs = seq->film_grain_params_present; + + /* Frame Header */ + info->frame_type = frame_header->frame_type; + info->show_frame = frame_header->show_frame; + info->disable_cdf_update = frame_header->disable_cdf_update; + info->allow_screen_content_tools = frame_header->allow_screen_content_tools; + info->force_integer_mv = frame_header->force_integer_mv || + frame_header->frame_type == AV1_FRAME_INTRA_ONLY || + frame_header->frame_type == AV1_FRAME_KEY; + info->coded_denom = frame_header->coded_denom; + info->allow_intrabc = frame_header->allow_intrabc; + info->allow_high_precision_mv = frame_header->allow_high_precision_mv; + info->interp_filter = frame_header->interpolation_filter; + info->switchable_motion_mode = frame_header->is_motion_mode_switchable; + info->use_ref_frame_mvs = frame_header->use_ref_frame_mvs; + info->disable_frame_end_update_cdf = frame_header->disable_frame_end_update_cdf; + info->delta_q_present = frame_header->delta_q_present; + info->delta_q_res = frame_header->delta_q_res; + info->using_qmatrix = frame_header->using_qmatrix; + info->coded_lossless = s->cur_frame.coded_lossless; + info->use_superres = frame_header->use_superres; + info->tx_mode = frame_header->tx_mode; + info->reference_mode = frame_header->reference_select; + info->allow_warped_motion = frame_header->allow_warped_motion; + info->reduced_tx_set = frame_header->reduced_tx_set; + info->skip_mode = frame_header->skip_mode_present; + + /* Tiling Info */ + info->num_tile_cols = frame_header->tile_cols; + info->num_tile_rows = frame_header->tile_rows; + info->context_update_tile_id = frame_header->context_update_tile_id; + + /* CDEF */ + info->cdef_damping_minus_3 = frame_header->cdef_damping_minus_3; + info->cdef_bits = frame_header->cdef_bits; + + /* SkipModeFrames */ + info->SkipModeFrame0 = frame_header->skip_mode_present ? + s->cur_frame.skip_mode_frame_idx[0] : 0; + info->SkipModeFrame1 = frame_header->skip_mode_present ? + s->cur_frame.skip_mode_frame_idx[1] : 0; + + /* QP Information */ + info->base_qindex = frame_header->base_q_idx; + info->qp_y_dc_delta_q = frame_header->delta_q_y_dc; + info->qp_u_dc_delta_q = frame_header->delta_q_u_dc; + info->qp_v_dc_delta_q = frame_header->delta_q_v_dc; + info->qp_u_ac_delta_q = frame_header->delta_q_u_ac; + info->qp_v_ac_delta_q = frame_header->delta_q_v_ac; + info->qm_y = frame_header->qm_y; + info->qm_u = frame_header->qm_u; + info->qm_v = frame_header->qm_v; + + /* Segmentation */ + info->segmentation_enabled = frame_header->segmentation_enabled; + info->segmentation_update_map = frame_header->segmentation_update_map; + info->segmentation_update_data = frame_header->segmentation_update_data; + info->segmentation_temporal_update = frame_header->segmentation_temporal_update; + + /* Loopfilter */ + info->loop_filter_level[0] = frame_header->loop_filter_level[0]; + info->loop_filter_level[1] = frame_header->loop_filter_level[1]; + info->loop_filter_level_u = frame_header->loop_filter_level[2]; + info->loop_filter_level_v = frame_header->loop_filter_level[3]; + info->loop_filter_sharpness = frame_header->loop_filter_sharpness; + info->loop_filter_delta_enabled = frame_header->loop_filter_delta_enabled; + info->loop_filter_delta_update = frame_header->loop_filter_delta_update; + info->loop_filter_mode_deltas[0] = frame_header->loop_filter_mode_deltas[0]; + info->loop_filter_mode_deltas[1] = frame_header->loop_filter_mode_deltas[1]; + info->delta_lf_present = frame_header->delta_lf_present; + info->delta_lf_res = frame_header->delta_lf_res; + info->delta_lf_multi = frame_header->delta_lf_multi; + + /* Restoration */ + info->lr_type[0] = remap_lr_type[frame_header->lr_type[0]]; + info->lr_type[1] = remap_lr_type[frame_header->lr_type[1]]; + info->lr_type[2] = remap_lr_type[frame_header->lr_type[2]]; + info->lr_unit_size[0] = 1 + frame_header->lr_unit_shift; + info->lr_unit_size[1] = 1 + frame_header->lr_unit_shift - frame_header->lr_uv_shift; + info->lr_unit_size[2] = 1 + frame_header->lr_unit_shift - frame_header->lr_uv_shift; + + /* Reference Frames */ + info->temporal_layer_id = s->cur_frame.temporal_id; + info->spatial_layer_id = s->cur_frame.spatial_id; + + /* Film Grain Params */ + info->apply_grain = film_grain->apply_grain; + info->overlap_flag = film_grain->overlap_flag; + info->scaling_shift_minus8 = film_grain->grain_scaling_minus_8; + info->chroma_scaling_from_luma = film_grain->chroma_scaling_from_luma; + info->ar_coeff_lag = film_grain->ar_coeff_lag; + info->ar_coeff_shift_minus6 = film_grain->ar_coeff_shift_minus_6; + info->grain_scale_shift = film_grain->grain_scale_shift; + info->clip_to_restricted_range = film_grain->clip_to_restricted_range; + info->num_y_points = film_grain->num_y_points; + info->num_cb_points = film_grain->num_cb_points; + info->num_cr_points = film_grain->num_cr_points; + info->random_seed = film_grain->grain_seed; + info->cb_mult = film_grain->cb_mult; + info->cb_luma_mult = film_grain->cb_luma_mult; + info->cb_offset = film_grain->cb_offset; + info->cr_mult = film_grain->cr_mult; + info->cr_luma_mult = film_grain->cr_luma_mult; + info->cr_offset = film_grain->cr_offset; + + /* Tiling Info */ + for (i = 0; i < frame_header->tile_cols; ++i) { + info->tile_widths[i] = frame_header->width_in_sbs_minus_1[i] + 1; + } + for (i = 0; i < frame_header->tile_rows; ++i) { + info->tile_heights[i] = frame_header->height_in_sbs_minus_1[i] + 1; + } + + /* CDEF */ + for (i = 0; i < (1 << frame_header->cdef_bits); ++i) { + info->cdef_y_strength[i] = (frame_header->cdef_y_pri_strength[i] & 0x0F) | (frame_header->cdef_y_sec_strength[i] << 4); + info->cdef_uv_strength[i] = (frame_header->cdef_uv_pri_strength[i] & 0x0F) | (frame_header->cdef_uv_sec_strength[i] << 4); + } + + + /* Segmentation */ + for (i = 0; i < AV1_MAX_SEGMENTS; ++i) { + info->segmentation_feature_mask[i] = 0; + for (j = 0; j < AV1_SEG_LVL_MAX; ++j) { + info->segmentation_feature_mask[i] |= frame_header->feature_enabled[i][j] << j; + info->segmentation_feature_data[i][j] = frame_header->feature_value[i][j]; + } + } + + for (i = 0; i < AV1_NUM_REF_FRAMES; ++i) { + /* Loopfilter */ + info->loop_filter_ref_deltas[i] = frame_header->loop_filter_ref_deltas[i]; + + /* Reference Frames */ + info->ref_frame_map[i] = ff_vdpau_get_surface_id(s->ref[i].f) ? ff_vdpau_get_surface_id(s->ref[i].f) : VDP_INVALID_HANDLE; + } + + if (frame_header->primary_ref_frame == AV1_PRIMARY_REF_NONE) { + info->primary_ref_frame = -1; + } else { + int8_t pri_ref_idx = frame_header->ref_frame_idx[frame_header->primary_ref_frame]; + info->primary_ref_frame = info->ref_frame_map[pri_ref_idx]; + } + + for (i = 0; i < AV1_REFS_PER_FRAME; ++i) { + /* Ref Frame List */ + int8_t ref_idx = frame_header->ref_frame_idx[i]; + AVFrame *ref_frame = s->ref[ref_idx].f; + + info->ref_frame[i].index = info->ref_frame_map[ref_idx]; + info->ref_frame[i].width = ref_frame->width; + info->ref_frame[i].height = ref_frame->height; + + /* Global Motion */ + info->global_motion[i].invalid = !frame_header->is_global[AV1_REF_FRAME_LAST + i]; + info->global_motion[i].wmtype = s->cur_frame.gm_type[AV1_REF_FRAME_LAST + i]; + for (j = 0; j < 6; ++j) { + info->global_motion[i].wmmat[j] = s->cur_frame.gm_params[AV1_REF_FRAME_LAST + i][j]; + } + } + + /* Film Grain Params */ + if (film_grain->apply_grain) { + for (i = 0; i < 14; ++i) { + info->scaling_points_y[i][0] = film_grain->point_y_value[i]; + info->scaling_points_y[i][1] = film_grain->point_y_scaling[i]; + } + for (i = 0; i < 10; ++i) { + info->scaling_points_cb[i][0] = film_grain->point_cb_value[i]; + info->scaling_points_cb[i][1] = film_grain->point_cb_scaling[i]; + info->scaling_points_cr[i][0] = film_grain->point_cr_value[i]; + info->scaling_points_cr[i][1] = film_grain->point_cr_scaling[i]; + } + for (i = 0; i < 24; ++i) { + info->ar_coeffs_y[i] = (short)film_grain->ar_coeffs_y_plus_128[i] - 128; + } + for (i = 0; i < 25; ++i) { + info->ar_coeffs_cb[i] = (short)film_grain->ar_coeffs_cb_plus_128[i] - 128; + info->ar_coeffs_cr[i] = (short)film_grain->ar_coeffs_cr_plus_128[i] - 128; + } + } + + + return ff_vdpau_common_start_frame(pic_ctx, buffer, size); + +} + +static int vdpau_av1_decode_slice(AVCodecContext *avctx, + const uint8_t *buffer, uint32_t size) +{ + const AV1DecContext *s = avctx->priv_data; + const AV1RawFrameHeader *frame_header = s->raw_frame_header; + struct vdpau_picture_context *pic_ctx = s->cur_frame.hwaccel_picture_private; + VdpPictureInfoAV1 *info = &pic_ctx->info.av1; + int val; + int nb_slices; + VdpBitstreamBuffer *buffers = pic_ctx->bitstream_buffers; + int bitstream_len = 0; + + nb_slices = frame_header->tile_cols * frame_header->tile_rows; + /* Shortcut if all tiles are in the same buffer*/ + if (nb_slices == s->tg_end - s->tg_start + 1) { + for (int i = 0; i < nb_slices; ++i) { + info->tile_info[i*2 ] = s->tile_group_info[i].tile_offset; + info->tile_info[i*2 + 1] = info->tile_info[i*2] + s->tile_group_info[i].tile_size; + } + val = ff_vdpau_add_buffer(pic_ctx, buffer, size); + if (val) { + return val; + } + + return 0; + } + + for(int i = 0; i < pic_ctx->bitstream_buffers_used; i++) { + bitstream_len += buffers->bitstream_bytes; + buffers++; + } + + for (uint32_t tile_num = s->tg_start; tile_num <= s->tg_end; ++tile_num) { + info->tile_info[tile_num*2 ] = bitstream_len + s->tile_group_info[tile_num].tile_offset; + info->tile_info[tile_num*2 + 1] = info->tile_info[tile_num*2] + s->tile_group_info[tile_num].tile_size; + } + + val = ff_vdpau_add_buffer(pic_ctx, buffer, size); + if (val) { + return val; + } + + return 0; +} + +static int vdpau_av1_end_frame(AVCodecContext *avctx) +{ + const AV1DecContext *s = avctx->priv_data; + struct vdpau_picture_context *pic_ctx = s->cur_frame.hwaccel_picture_private; + + int val; + + val = ff_vdpau_common_end_frame(avctx, s->cur_frame.f, pic_ctx); + if (val < 0) + return val; + + return 0; +} + +static int vdpau_av1_init(AVCodecContext *avctx) +{ + VdpDecoderProfile profile; + uint32_t level = avctx->level; + + switch (avctx->profile) { + case FF_PROFILE_AV1_MAIN: + profile = VDP_DECODER_PROFILE_AV1_MAIN; + break; + case FF_PROFILE_AV1_HIGH: + profile = VDP_DECODER_PROFILE_AV1_HIGH; + break; + case FF_PROFILE_AV1_PROFESSIONAL: + profile = VDP_DECODER_PROFILE_AV1_PROFESSIONAL; + break; + default: + return AVERROR(ENOTSUP); + } + + return ff_vdpau_common_init(avctx, profile, level); +} + +const AVHWAccel ff_av1_vdpau_hwaccel = { + .name = "av1_vdpau", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_AV1, + .pix_fmt = AV_PIX_FMT_VDPAU, + .start_frame = vdpau_av1_start_frame, + .end_frame = vdpau_av1_end_frame, + .decode_slice = vdpau_av1_decode_slice, + .frame_priv_data_size = sizeof(struct vdpau_picture_context), + .init = vdpau_av1_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_h264.c b/libavcodec/vdpau_h264.c index 5ba73dafd..525e20849 100644 --- a/libavcodec/vdpau_h264.c +++ b/libavcodec/vdpau_h264.c @@ -24,7 +24,6 @@ #include #include "avcodec.h" -#include "internal.h" #include "h264dec.h" #include "h264_ps.h" #include "hwconfig.h" diff --git a/libavcodec/vdpau_hevc.c b/libavcodec/vdpau_hevc.c index c17de0c5d..2669040f7 100644 --- a/libavcodec/vdpau_hevc.c +++ b/libavcodec/vdpau_hevc.c @@ -23,7 +23,6 @@ #include #include "avcodec.h" -#include "internal.h" #include "hevc_data.h" #include "hevcdec.h" #include "hwconfig.h" diff --git a/libavcodec/vdpau_internal.h b/libavcodec/vdpau_internal.h index b6ea078cb..347576e0c 100644 --- a/libavcodec/vdpau_internal.h +++ b/libavcodec/vdpau_internal.h @@ -57,6 +57,9 @@ union VDPAUPictureInfo { #ifdef VDP_DECODER_PROFILE_VP9_PROFILE_0 VdpPictureInfoVP9 vp9; #endif +#ifdef VDP_DECODER_PROFILE_AV1_MAIN + VdpPictureInfoAV1 av1; +#endif }; typedef struct VDPAUHWContext { diff --git a/libavcodec/vdpau_mpeg12.c b/libavcodec/vdpau_mpeg12.c index 72220ffb4..354239cad 100644 --- a/libavcodec/vdpau_mpeg12.c +++ b/libavcodec/vdpau_mpeg12.c @@ -21,6 +21,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include #include "avcodec.h" diff --git a/libavcodec/vdpau_mpeg4.c b/libavcodec/vdpau_mpeg4.c index 93b25beb1..6e082eefc 100644 --- a/libavcodec/vdpau_mpeg4.c +++ b/libavcodec/vdpau_mpeg4.c @@ -25,7 +25,7 @@ #include "avcodec.h" #include "hwconfig.h" -#include "mpeg4video.h" +#include "mpeg4videodec.h" #include "vdpau.h" #include "vdpau_internal.h" diff --git a/libavcodec/vdpau_vc1.c b/libavcodec/vdpau_vc1.c index 96c91b58b..00b33f420 100644 --- a/libavcodec/vdpau_vc1.c +++ b/libavcodec/vdpau_vc1.c @@ -21,6 +21,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include #include "avcodec.h" diff --git a/libavcodec/vdpau_vp9.c b/libavcodec/vdpau_vp9.c index a8609d647..49fe18189 100644 --- a/libavcodec/vdpau_vp9.c +++ b/libavcodec/vdpau_vp9.c @@ -23,7 +23,6 @@ #include #include "libavutil/pixdesc.h" #include "avcodec.h" -#include "internal.h" #include "vp9data.h" #include "vp9dec.h" #include "hwconfig.h" diff --git a/libavcodec/version.c b/libavcodec/version.c new file mode 100644 index 000000000..d7966b201 --- /dev/null +++ b/libavcodec/version.c @@ -0,0 +1,50 @@ +/* + * Version functions. + * + * 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/avassert.h" +#include "avcodec.h" +#include "codec_id.h" +#include "version.h" + +#include "libavutil/ffversion.h" +const char av_codec_ffversion[] = "FFmpeg version " FFMPEG_VERSION; + +unsigned avcodec_version(void) +{ + av_assert0(AV_CODEC_ID_PCM_S8_PLANAR==65563); + av_assert0(AV_CODEC_ID_ADPCM_G722==69660); + av_assert0(AV_CODEC_ID_SRT==94216); + av_assert0(LIBAVCODEC_VERSION_MICRO >= 100); + + return LIBAVCODEC_VERSION_INT; +} + +const char *avcodec_configuration(void) +{ + return FFMPEG_CONFIGURATION; +} + +const char *avcodec_license(void) +{ +#define LICENSE_PREFIX "libavcodec license: " + return &LICENSE_PREFIX FFMPEG_LICENSE[sizeof(LICENSE_PREFIX) - 1]; +} diff --git a/libavcodec/version.h b/libavcodec/version.h index 4d7743184..376388c5b 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -27,8 +27,9 @@ #include "libavutil/version.h" -#define LIBAVCODEC_VERSION_MAJOR 59 -#define LIBAVCODEC_VERSION_MINOR 18 +#include "version_major.h" + +#define LIBAVCODEC_VERSION_MINOR 37 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ @@ -41,27 +42,4 @@ #define LIBAVCODEC_IDENT "Lavc" AV_STRINGIFY(LIBAVCODEC_VERSION) -/** - * FF_API_* defines may be placed below to indicate public API that will be - * 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. - * - * @note, when bumping the major version it is recommended to manually - * disable each FF_API_* in its own commit instead of disabling them all - * at once through the bump. This improves the git bisect-ability of the change. - */ - -#define FF_API_OPENH264_SLICE_MODE (LIBAVCODEC_VERSION_MAJOR < 60) -#define FF_API_OPENH264_CABAC (LIBAVCODEC_VERSION_MAJOR < 60) -#define FF_API_UNUSED_CODEC_CAPS (LIBAVCODEC_VERSION_MAJOR < 60) -#define FF_API_THREAD_SAFE_CALLBACKS (LIBAVCODEC_VERSION_MAJOR < 60) -#define FF_API_DEBUG_MV (LIBAVCODEC_VERSION_MAJOR < 60) -#define FF_API_GET_FRAME_CLASS (LIBAVCODEC_VERSION_MAJOR < 60) -#define FF_API_AUTO_THREADS (LIBAVCODEC_VERSION_MAJOR < 60) -#define FF_API_INIT_PACKET (LIBAVCODEC_VERSION_MAJOR < 60) -#define FF_API_AVCTX_TIMEBASE (LIBAVCODEC_VERSION_MAJOR < 60) -#define FF_API_MPEGVIDEO_OPTS (LIBAVCODEC_VERSION_MAJOR < 60) -#define FF_API_FLAG_TRUNCATED (LIBAVCODEC_VERSION_MAJOR < 60) -#define FF_API_SUB_TEXT_FORMAT (LIBAVCODEC_VERSION_MAJOR < 60) - #endif /* AVCODEC_VERSION_H */ diff --git a/libavcodec/version_major.h b/libavcodec/version_major.h new file mode 100644 index 000000000..1e23ed5e0 --- /dev/null +++ b/libavcodec/version_major.h @@ -0,0 +1,54 @@ +/* + * 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_VERSION_MAJOR_H +#define AVCODEC_VERSION_MAJOR_H + +/** + * @file + * @ingroup libavc + * Libavcodec version macros. + */ + +#define LIBAVCODEC_VERSION_MAJOR 59 + +/** + * FF_API_* defines may be placed below to indicate public API that will be + * 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. + * + * @note, when bumping the major version it is recommended to manually + * disable each FF_API_* in its own commit instead of disabling them all + * at once through the bump. This improves the git bisect-ability of the change. + */ + +#define FF_API_OPENH264_SLICE_MODE (LIBAVCODEC_VERSION_MAJOR < 60) +#define FF_API_OPENH264_CABAC (LIBAVCODEC_VERSION_MAJOR < 60) +#define FF_API_UNUSED_CODEC_CAPS (LIBAVCODEC_VERSION_MAJOR < 60) +#define FF_API_THREAD_SAFE_CALLBACKS (LIBAVCODEC_VERSION_MAJOR < 60) +#define FF_API_DEBUG_MV (LIBAVCODEC_VERSION_MAJOR < 60) +#define FF_API_GET_FRAME_CLASS (LIBAVCODEC_VERSION_MAJOR < 60) +#define FF_API_AUTO_THREADS (LIBAVCODEC_VERSION_MAJOR < 60) +#define FF_API_INIT_PACKET (LIBAVCODEC_VERSION_MAJOR < 60) +#define FF_API_AVCTX_TIMEBASE (LIBAVCODEC_VERSION_MAJOR < 60) +#define FF_API_FLAG_TRUNCATED (LIBAVCODEC_VERSION_MAJOR < 60) +#define FF_API_SUB_TEXT_FORMAT (LIBAVCODEC_VERSION_MAJOR < 60) +#define FF_API_IDCT_NONE (LIBAVCODEC_VERSION_MAJOR < 60) +#define FF_API_SVTAV1_OPTS (LIBAVCODEC_VERSION_MAJOR < 60) + +#endif /* AVCODEC_VERSION_MAJOR_H */ diff --git a/libavcodec/videodsp.c b/libavcodec/videodsp.c index ce9e9eb14..90dc1aacb 100644 --- a/libavcodec/videodsp.c +++ b/libavcodec/videodsp.c @@ -18,9 +18,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config.h" #include "libavutil/attributes.h" #include "libavutil/avassert.h" -#include "libavutil/common.h" +#include "libavutil/macros.h" #include "videodsp.h" #define BIT_DEPTH 8 @@ -44,14 +45,17 @@ av_cold void ff_videodsp_init(VideoDSPContext *ctx, int bpc) ctx->emulated_edge_mc = ff_emulated_edge_mc_16; } - if (ARCH_AARCH64) - ff_videodsp_init_aarch64(ctx, bpc); - if (ARCH_ARM) - ff_videodsp_init_arm(ctx, bpc); - if (ARCH_PPC) - ff_videodsp_init_ppc(ctx, bpc); - if (ARCH_X86) - ff_videodsp_init_x86(ctx, bpc); - if (ARCH_MIPS) - ff_videodsp_init_mips(ctx, bpc); +#if ARCH_AARCH64 + ff_videodsp_init_aarch64(ctx, bpc); +#elif ARCH_ARM + ff_videodsp_init_arm(ctx, bpc); +#elif ARCH_PPC + ff_videodsp_init_ppc(ctx, bpc); +#elif ARCH_X86 + ff_videodsp_init_x86(ctx, bpc); +#elif ARCH_MIPS + ff_videodsp_init_mips(ctx, bpc); +#elif ARCH_LOONGARCH64 + ff_videodsp_init_loongarch(ctx, bpc); +#endif } diff --git a/libavcodec/videodsp.h b/libavcodec/videodsp.h index c0545f22b..b5219d236 100644 --- a/libavcodec/videodsp.h +++ b/libavcodec/videodsp.h @@ -36,7 +36,6 @@ void ff_emulated_edge_mc_ ## depth(uint8_t *dst, const uint8_t *src, \ int src_x, int src_y, int w, int h); EMULATED_EDGE(8) -EMULATED_EDGE(16) typedef struct VideoDSPContext { /** @@ -84,5 +83,6 @@ void ff_videodsp_init_arm(VideoDSPContext *ctx, int bpc); void ff_videodsp_init_ppc(VideoDSPContext *ctx, int bpc); void ff_videodsp_init_x86(VideoDSPContext *ctx, int bpc); void ff_videodsp_init_mips(VideoDSPContext *ctx, int bpc); +void ff_videodsp_init_loongarch(VideoDSPContext *ctx, int bpc); #endif /* AVCODEC_VIDEODSP_H */ diff --git a/libavcodec/videodsp_template.c b/libavcodec/videodsp_template.c index 55123a584..324d70f2c 100644 --- a/libavcodec/videodsp_template.c +++ b/libavcodec/videodsp_template.c @@ -20,6 +20,10 @@ */ #include "bit_depth_template.c" +#if BIT_DEPTH != 8 +// ff_emulated_edge_mc_8 is used by the x86 MpegVideoDSP API. +static +#endif void FUNC(ff_emulated_edge_mc)(uint8_t *buf, const uint8_t *src, ptrdiff_t buf_linesize, ptrdiff_t src_linesize, diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c index 51d4eacfd..ce83c2594 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -21,6 +21,7 @@ */ #include "config.h" +#include "config_components.h" #include "videotoolbox.h" #include "libavutil/hwcontext_videotoolbox.h" #include "vt_internal.h" @@ -29,6 +30,7 @@ #include "libavutil/pixdesc.h" #include "bytestream.h" #include "decode.h" +#include "internal.h" #include "h264dec.h" #include "hevcdec.h" #include "mpegvideo.h" @@ -164,14 +166,13 @@ static int escape_ps(uint8_t* dst, const uint8_t* src, int src_size) src[i + 2] <= 0x03) { if (dst) { *p++ = src[i++]; - *p++ = src[i++]; + *p++ = src[i]; *p++ = 0x03; } else { - i += 2; + i++; } size++; - } - if (dst) + } else if (dst) *p++ = src[i]; } @@ -245,7 +246,7 @@ CFDataRef ff_videotoolbox_hvcc_extradata_create(AVCodecContext *avctx) for (i = 0; i < HEVC_MAX_##T##PS_COUNT; i++) { \ if (h->ps.t##ps_list[i]) { \ const HEVC##T##PS *lps = (const HEVC##T##PS *)h->ps.t##ps_list[i]->data; \ - vt_extradata_size += 2 + lps->data_size; \ + vt_extradata_size += 2 + escape_ps(NULL, lps->data, lps->data_size); \ num_##t##ps++; \ } \ } @@ -272,7 +273,16 @@ CFDataRef ff_videotoolbox_hvcc_extradata_create(AVCodecContext *avctx) ptlc.profile_idc); /* unsigned int(32) general_profile_compatibility_flags; */ - memcpy(p + 2, ptlc.profile_compatibility_flag, 4); + for (i = 0; i < 4; i++) { + AV_W8(p + 2 + i, ptlc.profile_compatibility_flag[i * 8] << 7 | + ptlc.profile_compatibility_flag[i * 8 + 1] << 6 | + ptlc.profile_compatibility_flag[i * 8 + 2] << 5 | + ptlc.profile_compatibility_flag[i * 8 + 3] << 4 | + ptlc.profile_compatibility_flag[i * 8 + 4] << 3 | + ptlc.profile_compatibility_flag[i * 8 + 5] << 2 | + ptlc.profile_compatibility_flag[i * 8 + 6] << 1 | + ptlc.profile_compatibility_flag[i * 8 + 7]); + } /* unsigned int(48) general_constraint_indicator_flags; */ AV_W8(p + 6, ptlc.progressive_source_flag << 7 | @@ -318,13 +328,13 @@ CFDataRef ff_videotoolbox_hvcc_extradata_create(AVCodecContext *avctx) * bit(5) reserved = ‘11111’b; * unsigned int(3) bitDepthLumaMinus8; */ - AV_W8(p + 17, (sps->bit_depth - 8) | 0xfc); + AV_W8(p + 17, (sps->bit_depth - 8) | 0xf8); /* * bit(5) reserved = ‘11111’b; * unsigned int(3) bitDepthChromaMinus8; */ - AV_W8(p + 18, (sps->bit_depth_chroma - 8) | 0xfc); + AV_W8(p + 18, (sps->bit_depth_chroma - 8) | 0xf8); /* bit(16) avgFrameRate; */ AV_WB16(p + 19, 0); @@ -359,11 +369,11 @@ CFDataRef ff_videotoolbox_hvcc_extradata_create(AVCodecContext *avctx) for (i = 0; i < HEVC_MAX_##T##PS_COUNT; i++) { \ if (h->ps.t##ps_list[i]) { \ const HEVC##T##PS *lps = (const HEVC##T##PS *)h->ps.t##ps_list[i]->data; \ + int size = escape_ps(p + 2, lps->data, lps->data_size); \ /* unsigned int(16) nalUnitLength; */ \ - AV_WB16(p, lps->data_size); \ + AV_WB16(p, size); \ /* bit(8*nalUnitLength) nalUnit; */ \ - memcpy(p + 2, lps->data, lps->data_size); \ - p += 2 + lps->data_size; \ + p += 2 + size; \ } \ } @@ -689,7 +699,7 @@ static void videotoolbox_decoder_callback(void *opaque, } if (!image_buffer) { - av_log(avctx, AV_LOG_DEBUG, "vt decoder cb: output image buffer is null\n"); + av_log(avctx, status ? AV_LOG_WARNING : AV_LOG_DEBUG, "vt decoder cb: output image buffer is null: %i\n", status); return; } diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index 418ff00b8..69d9fe75b 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -30,6 +30,7 @@ #include "libavcodec/avcodec.h" #include "libavutil/pixdesc.h" #include "libavutil/hwcontext_videotoolbox.h" +#include "codec_internal.h" #include "internal.h" #include #include "atsc_a53.h" @@ -99,6 +100,7 @@ static struct{ CFStringRef kVTCompressionPropertyKey_RealTime; CFStringRef kVTCompressionPropertyKey_TargetQualityForAlpha; + CFStringRef kVTCompressionPropertyKey_PrioritizeEncodingSpeedOverQuality; CFStringRef kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder; CFStringRef kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncoder; @@ -160,6 +162,8 @@ static void loadVTEncSymbols(){ GET_SYM(kVTCompressionPropertyKey_RealTime, "RealTime"); GET_SYM(kVTCompressionPropertyKey_TargetQualityForAlpha, "TargetQualityForAlpha"); + GET_SYM(kVTCompressionPropertyKey_PrioritizeEncodingSpeedOverQuality, + "PrioritizeEncodingSpeedOverQuality"); GET_SYM(kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder, "EnableHardwareAcceleratedVideoEncoder"); @@ -236,6 +240,7 @@ typedef struct VTEncContext { int allow_sw; int require_sw; double alpha_quality; + int prio_speed; bool flushing; int has_b_frames; @@ -1145,6 +1150,15 @@ static int vtenc_create_encoder(AVCodecContext *avctx, return AVERROR_EXTERNAL; } + if (vtctx->prio_speed >= 0) { + status = VTSessionSetProperty(vtctx->session, + compat_keys.kVTCompressionPropertyKey_PrioritizeEncodingSpeedOverQuality, + vtctx->prio_speed ? kCFBooleanTrue : kCFBooleanFalse); + if (status) { + av_log(avctx, AV_LOG_WARNING, "PrioritizeEncodingSpeedOverQuality property is not supported on this device. Ignoring.\n"); + } + } + if ((vtctx->codec_id == AV_CODEC_ID_H264 || vtctx->codec_id == AV_CODEC_ID_HEVC) && max_rate > 0) { bytes_per_second_value = max_rate >> 3; @@ -2681,7 +2695,9 @@ static const enum AVPixelFormat prores_pix_fmts[] = { { "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 }, + OFFSET(frames_after), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, \ + { "prio_speed", "prioritize encoding speed", OFFSET(prio_speed), AV_OPT_TYPE_BOOL, \ + { .i64 = -1 }, -1, 1, VE }, \ #define OFFSET(x) offsetof(VTEncContext, x) static const AVOption h264_options[] = { @@ -2722,18 +2738,18 @@ static const AVClass h264_videotoolbox_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_h264_videotoolbox_encoder = { - .name = "h264_videotoolbox", - .long_name = NULL_IF_CONFIG_SMALL("VideoToolbox H.264 Encoder"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_H264, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, +const FFCodec ff_h264_videotoolbox_encoder = { + .p.name = "h264_videotoolbox", + .p.long_name = NULL_IF_CONFIG_SMALL("VideoToolbox H.264 Encoder"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_H264, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, .priv_data_size = sizeof(VTEncContext), - .pix_fmts = avc_pix_fmts, + .p.pix_fmts = avc_pix_fmts, .init = vtenc_init, - .encode2 = vtenc_frame, + FF_CODEC_ENCODE_CB(vtenc_frame), .close = vtenc_close, - .priv_class = &h264_videotoolbox_class, + .p.priv_class = &h264_videotoolbox_class, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; @@ -2756,22 +2772,22 @@ static const AVClass hevc_videotoolbox_class = { .version = LIBAVUTIL_VERSION_INT, }; -const 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, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | +const FFCodec ff_hevc_videotoolbox_encoder = { + .p.name = "hevc_videotoolbox", + .p.long_name = NULL_IF_CONFIG_SMALL("VideoToolbox H.265 Encoder"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_HEVC, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, .priv_data_size = sizeof(VTEncContext), - .pix_fmts = hevc_pix_fmts, + .p.pix_fmts = hevc_pix_fmts, .init = vtenc_init, - .encode2 = vtenc_frame, + FF_CODEC_ENCODE_CB(vtenc_frame), .close = vtenc_close, - .priv_class = &hevc_videotoolbox_class, + .p.priv_class = &hevc_videotoolbox_class, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .wrapper_name = "videotoolbox", + .p.wrapper_name = "videotoolbox", }; static const AVOption prores_options[] = { @@ -2795,20 +2811,20 @@ static const AVClass prores_videotoolbox_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_prores_videotoolbox_encoder = { - .name = "prores_videotoolbox", - .long_name = NULL_IF_CONFIG_SMALL("VideoToolbox ProRes Encoder"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_PRORES, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | +const FFCodec ff_prores_videotoolbox_encoder = { + .p.name = "prores_videotoolbox", + .p.long_name = NULL_IF_CONFIG_SMALL("VideoToolbox ProRes Encoder"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_PRORES, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE, .priv_data_size = sizeof(VTEncContext), - .pix_fmts = prores_pix_fmts, + .p.pix_fmts = prores_pix_fmts, .init = vtenc_init, - .encode2 = vtenc_frame, + FF_CODEC_ENCODE_CB(vtenc_frame), .close = vtenc_close, - .priv_class = &prores_videotoolbox_class, + .p.priv_class = &prores_videotoolbox_class, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .wrapper_name = "videotoolbox", + .p.wrapper_name = "videotoolbox", }; diff --git a/libavcodec/vima.c b/libavcodec/vima.c index c9a81e440..73276056c 100644 --- a/libavcodec/vima.c +++ b/libavcodec/vima.c @@ -30,6 +30,7 @@ #include "adpcm_data.h" #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" @@ -116,11 +117,10 @@ static av_cold int decode_init(AVCodecContext *avctx) return 0; } -static int decode_frame(AVCodecContext *avctx, void *data, +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *pkt) { GetBitContext gb; - AVFrame *frame = data; int16_t pcm_data[2]; uint32_t samples; int8_t channel_hint[2]; @@ -147,9 +147,8 @@ static int decode_frame(AVCodecContext *avctx, void *data, channel_hint[0] = ~channel_hint[0]; channels = 2; } - avctx->channels = channels; - avctx->channel_layout = (channels == 2) ? AV_CH_LAYOUT_STEREO - : AV_CH_LAYOUT_MONO; + av_channel_layout_uninit(&avctx->ch_layout); + av_channel_layout_default(&avctx->ch_layout, channels); pcm_data[0] = get_sbits(&gb, 16); if (channels > 1) { channel_hint[1] = get_sbits(&gb, 8); @@ -208,13 +207,13 @@ static int decode_frame(AVCodecContext *avctx, void *data, return pkt->size; } -const AVCodec ff_adpcm_vima_decoder = { - .name = "adpcm_vima", - .long_name = NULL_IF_CONFIG_SMALL("LucasArts VIMA audio"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_ADPCM_VIMA, +const FFCodec ff_adpcm_vima_decoder = { + .p.name = "adpcm_vima", + .p.long_name = NULL_IF_CONFIG_SMALL("LucasArts VIMA audio"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_ADPCM_VIMA, .init = decode_init, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/vlc.c b/libavcodec/vlc.c new file mode 100644 index 000000000..96f2b28c7 --- /dev/null +++ b/libavcodec/vlc.c @@ -0,0 +1,378 @@ +/* + * API for creating VLC trees + * Copyright (c) 2000, 2001 Fabrice Bellard + * Copyright (c) 2002-2004 Michael Niedermayer + * Copyright (c) 2010 Loren Merritt + * + * 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 "libavutil/attributes.h" +#include "libavutil/avassert.h" +#include "libavutil/error.h" +#include "libavutil/internal.h" +#include "libavutil/log.h" +#include "libavutil/macros.h" +#include "libavutil/mem.h" +#include "libavutil/qsort.h" +#include "libavutil/reverse.h" +#include "vlc.h" + +#define GET_DATA(v, table, i, wrap, size) \ +{ \ + const uint8_t *ptr = (const uint8_t *)table + i * wrap; \ + switch(size) { \ + case 1: \ + v = *(const uint8_t *)ptr; \ + break; \ + case 2: \ + v = *(const uint16_t *)ptr; \ + break; \ + case 4: \ + default: \ + av_assert1(size == 4); \ + v = *(const uint32_t *)ptr; \ + break; \ + } \ +} + + +static int alloc_table(VLC *vlc, int size, int use_static) +{ + int index = vlc->table_size; + + vlc->table_size += size; + if (vlc->table_size > vlc->table_allocated) { + if (use_static) + abort(); // cannot do anything, init_vlc() is used with too little memory + vlc->table_allocated += (1 << vlc->bits); + vlc->table = av_realloc_f(vlc->table, vlc->table_allocated, sizeof(*vlc->table)); + if (!vlc->table) { + vlc->table_allocated = 0; + vlc->table_size = 0; + return AVERROR(ENOMEM); + } + memset(vlc->table + vlc->table_allocated - (1 << vlc->bits), 0, sizeof(*vlc->table) << vlc->bits); + } + return index; +} + +#define LOCALBUF_ELEMS 1500 // the maximum currently needed is 1296 by rv34 + +static av_always_inline uint32_t bitswap_32(uint32_t x) +{ + return (uint32_t)ff_reverse[ x & 0xFF] << 24 | + (uint32_t)ff_reverse[(x >> 8) & 0xFF] << 16 | + (uint32_t)ff_reverse[(x >> 16) & 0xFF] << 8 | + (uint32_t)ff_reverse[ x >> 24]; +} + +typedef struct VLCcode { + uint8_t bits; + VLCBaseType symbol; + /** codeword, with the first bit-to-be-read in the msb + * (even if intended for a little-endian bitstream reader) */ + uint32_t code; +} VLCcode; + +static int vlc_common_init(VLC *vlc, int nb_bits, int nb_codes, + VLCcode **buf, int flags) +{ + vlc->bits = nb_bits; + vlc->table_size = 0; + if (flags & INIT_VLC_USE_NEW_STATIC) { + av_assert0(nb_codes <= LOCALBUF_ELEMS); + } else { + vlc->table = NULL; + vlc->table_allocated = 0; + } + if (nb_codes > LOCALBUF_ELEMS) { + *buf = av_malloc_array(nb_codes, sizeof(VLCcode)); + if (!*buf) + return AVERROR(ENOMEM); + } + + return 0; +} + +static int compare_vlcspec(const void *a, const void *b) +{ + const VLCcode *sa = a, *sb = b; + return (sa->code >> 1) - (sb->code >> 1); +} + +/** + * Build VLC decoding tables suitable for use with get_vlc(). + * + * @param vlc the context to be initialized + * + * @param table_nb_bits max length of vlc codes to store directly in this table + * (Longer codes are delegated to subtables.) + * + * @param nb_codes number of elements in codes[] + * + * @param codes descriptions of the vlc codes + * These must be ordered such that codes going into the same subtable are contiguous. + * Sorting by VLCcode.code is sufficient, though not necessary. + */ +static int build_table(VLC *vlc, int table_nb_bits, int nb_codes, + VLCcode *codes, int flags) +{ + int table_size, table_index; + VLCElem *table; + + if (table_nb_bits > 30) + return AVERROR(EINVAL); + table_size = 1 << table_nb_bits; + table_index = alloc_table(vlc, table_size, flags & INIT_VLC_USE_NEW_STATIC); + ff_dlog(NULL, "new table index=%d size=%d\n", table_index, table_size); + if (table_index < 0) + return table_index; + table = &vlc->table[table_index]; + + /* first pass: map codes and compute auxiliary table sizes */ + for (int i = 0; i < nb_codes; i++) { + int n = codes[i].bits; + uint32_t code = codes[i].code; + int symbol = codes[i].symbol; + ff_dlog(NULL, "i=%d n=%d code=0x%"PRIx32"\n", i, n, code); + if (n <= table_nb_bits) { + /* no need to add another table */ + int j = code >> (32 - table_nb_bits); + int nb = 1 << (table_nb_bits - n); + int inc = 1; + + if (flags & INIT_VLC_OUTPUT_LE) { + j = bitswap_32(code); + inc = 1 << n; + } + for (int k = 0; k < nb; k++) { + int bits = table[j].len; + int oldsym = table[j].sym; + ff_dlog(NULL, "%4x: code=%d n=%d\n", j, i, n); + if ((bits || oldsym) && (bits != n || oldsym != symbol)) { + av_log(NULL, AV_LOG_ERROR, "incorrect codes\n"); + return AVERROR_INVALIDDATA; + } + table[j].len = n; + table[j].sym = symbol; + j += inc; + } + } else { + /* fill auxiliary table recursively */ + uint32_t code_prefix; + int index, subtable_bits, j, k; + + n -= table_nb_bits; + code_prefix = code >> (32 - table_nb_bits); + subtable_bits = n; + codes[i].bits = n; + codes[i].code = code << table_nb_bits; + for (k = i + 1; k < nb_codes; k++) { + n = codes[k].bits - table_nb_bits; + if (n <= 0) + break; + code = codes[k].code; + if (code >> (32 - table_nb_bits) != code_prefix) + break; + codes[k].bits = n; + codes[k].code = code << table_nb_bits; + subtable_bits = FFMAX(subtable_bits, n); + } + subtable_bits = FFMIN(subtable_bits, table_nb_bits); + j = (flags & INIT_VLC_OUTPUT_LE) ? bitswap_32(code_prefix) >> (32 - table_nb_bits) : code_prefix; + table[j].len = -subtable_bits; + ff_dlog(NULL, "%4x: n=%d (subtable)\n", + j, codes[i].bits + table_nb_bits); + index = build_table(vlc, subtable_bits, k-i, codes+i, flags); + if (index < 0) + return index; + /* note: realloc has been done, so reload tables */ + table = &vlc->table[table_index]; + table[j].sym = index; + if (table[j].sym != index) { + avpriv_request_sample(NULL, "strange codes"); + return AVERROR_PATCHWELCOME; + } + i = k-1; + } + } + + for (int i = 0; i < table_size; i++) { + if (table[i].len == 0) + table[i].sym = -1; + } + + return table_index; +} + +static int vlc_common_end(VLC *vlc, int nb_bits, int nb_codes, VLCcode *codes, + int flags, VLCcode localbuf[LOCALBUF_ELEMS]) +{ + int ret = build_table(vlc, nb_bits, nb_codes, codes, flags); + + if (flags & INIT_VLC_USE_NEW_STATIC) { + if (vlc->table_size != vlc->table_allocated && + !(flags & (INIT_VLC_STATIC_OVERLONG & ~INIT_VLC_USE_NEW_STATIC))) + av_log(NULL, AV_LOG_ERROR, "needed %d had %d\n", vlc->table_size, vlc->table_allocated); + av_assert0(ret >= 0); + } else { + if (codes != localbuf) + av_free(codes); + if (ret < 0) { + av_freep(&vlc->table); + return ret; + } + } + return 0; +} + +/* Build VLC decoding tables suitable for use with get_vlc(). + + 'nb_bits' sets the decoding table size (2^nb_bits) entries. The + bigger it is, the faster is the decoding. But it should not be too + big to save memory and L1 cache. '9' is a good compromise. + + 'nb_codes' : number of vlcs codes + + 'bits' : table which gives the size (in bits) of each vlc code. + + 'codes' : table which gives the bit pattern of of each vlc code. + + 'symbols' : table which gives the values to be returned from get_vlc(). + + 'xxx_wrap' : give the number of bytes between each entry of the + 'bits' or 'codes' tables. + + 'xxx_size' : gives the number of bytes of each entry of the 'bits' + or 'codes' tables. Currently 1,2 and 4 are supported. + + 'wrap' and 'size' make it possible to use any memory configuration and types + (byte/word/long) to store the 'bits', 'codes', and 'symbols' tables. +*/ +int ff_init_vlc_sparse(VLC *vlc, int nb_bits, int nb_codes, + const void *bits, int bits_wrap, int bits_size, + const void *codes, int codes_wrap, int codes_size, + const void *symbols, int symbols_wrap, int symbols_size, + int flags) +{ + VLCcode localbuf[LOCALBUF_ELEMS], *buf = localbuf; + int j, ret; + + ret = vlc_common_init(vlc, nb_bits, nb_codes, &buf, flags); + if (ret < 0) + return ret; + + av_assert0(symbols_size <= 2 || !symbols); + j = 0; +#define COPY(condition)\ + for (int i = 0; i < nb_codes; i++) { \ + unsigned len; \ + GET_DATA(len, bits, i, bits_wrap, bits_size); \ + if (!(condition)) \ + continue; \ + if (len > 3*nb_bits || len > 32) { \ + av_log(NULL, AV_LOG_ERROR, "Too long VLC (%u) in init_vlc\n", len);\ + if (buf != localbuf) \ + av_free(buf); \ + return AVERROR(EINVAL); \ + } \ + buf[j].bits = len; \ + GET_DATA(buf[j].code, codes, i, codes_wrap, codes_size); \ + if (buf[j].code >= (1LL< nb_bits); + // qsort is the slowest part of init_vlc, and could probably be improved or avoided + AV_QSORT(buf, j, struct VLCcode, compare_vlcspec); + COPY(len && len <= nb_bits); + nb_codes = j; + + return vlc_common_end(vlc, nb_bits, nb_codes, buf, + flags, localbuf); +} + +int ff_init_vlc_from_lengths(VLC *vlc, int nb_bits, int nb_codes, + const int8_t *lens, int lens_wrap, + const void *symbols, int symbols_wrap, int symbols_size, + int offset, int flags, void *logctx) +{ + VLCcode localbuf[LOCALBUF_ELEMS], *buf = localbuf; + uint64_t code; + int ret, j, len_max = FFMIN(32, 3 * nb_bits); + + ret = vlc_common_init(vlc, nb_bits, nb_codes, &buf, flags); + if (ret < 0) + return ret; + + j = code = 0; + for (int i = 0; i < nb_codes; i++, lens += lens_wrap) { + int len = *lens; + if (len > 0) { + unsigned sym; + + buf[j].bits = len; + if (symbols) + GET_DATA(sym, symbols, i, symbols_wrap, symbols_size) + else + sym = i; + buf[j].symbol = sym + offset; + buf[j++].code = code; + } else if (len < 0) { + len = -len; + } else + continue; + if (len > len_max || code & ((1U << (32 - len)) - 1)) { + av_log(logctx, AV_LOG_ERROR, "Invalid VLC (length %u)\n", len); + goto fail; + } + code += 1U << (32 - len); + if (code > UINT32_MAX + 1ULL) { + av_log(logctx, AV_LOG_ERROR, "Overdetermined VLC tree\n"); + goto fail; + } + } + return vlc_common_end(vlc, nb_bits, j, buf, flags, localbuf); +fail: + if (buf != localbuf) + av_free(buf); + return AVERROR_INVALIDDATA; +} + +void ff_free_vlc(VLC *vlc) +{ + av_freep(&vlc->table); +} diff --git a/libavcodec/vlc.h b/libavcodec/vlc.h index 6879c3ca6..e63c48475 100644 --- a/libavcodec/vlc.h +++ b/libavcodec/vlc.h @@ -21,11 +21,16 @@ #include -#define VLC_TYPE int16_t +// When changing this, be sure to also update tableprint_vlc.h accordingly. +typedef int16_t VLCBaseType; + +typedef struct VLCElem { + VLCBaseType sym, len; +} VLCElem; typedef struct VLC { int bits; - VLC_TYPE (*table)[2]; ///< code, bits + VLCElem *table; int table_size, table_allocated; } VLC; @@ -98,7 +103,7 @@ void ff_free_vlc(VLC *vlc); #define INIT_CUSTOM_VLC_SPARSE_STATIC(vlc, bits, a, b, c, d, e, f, g, \ h, i, j, flags, static_size) \ do { \ - static VLC_TYPE table[static_size][2]; \ + static VLCElem table[static_size]; \ (vlc)->table = table; \ (vlc)->table_allocated = static_size; \ ff_init_vlc_sparse(vlc, bits, a, b, c, d, e, f, g, h, i, j, \ @@ -127,7 +132,7 @@ void ff_free_vlc(VLC *vlc); symbols, symbols_wrap, symbols_size, \ offset, flags, static_size) \ do { \ - static VLC_TYPE table[static_size][2]; \ + static VLCElem table[static_size]; \ (vlc)->table = table; \ (vlc)->table_allocated = static_size; \ ff_init_vlc_from_lengths(vlc, bits, nb_codes, lens, len_wrap, \ diff --git a/libavcodec/vmdaudio.c b/libavcodec/vmdaudio.c index 53aef660e..2e6e358b6 100644 --- a/libavcodec/vmdaudio.c +++ b/libavcodec/vmdaudio.c @@ -41,6 +41,7 @@ #include "libavutil/intreadwrite.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #define BLOCK_TYPE_AUDIO 1 @@ -71,20 +72,20 @@ static const uint16_t vmdaudio_table[128] = { static av_cold int vmdaudio_decode_init(AVCodecContext *avctx) { VmdAudioContext *s = avctx->priv_data; + int channels = avctx->ch_layout.nb_channels; - if (avctx->channels < 1 || avctx->channels > 2) { + if (channels < 1 || channels > 2) { av_log(avctx, AV_LOG_ERROR, "invalid number of channels\n"); return AVERROR(EINVAL); } - if (avctx->block_align < 1 || avctx->block_align % avctx->channels || - avctx->block_align > INT_MAX - avctx->channels - ) { + if (avctx->block_align < 1 || avctx->block_align % channels || + avctx->block_align > INT_MAX - channels) { av_log(avctx, AV_LOG_ERROR, "invalid block align\n"); return AVERROR(EINVAL); } - avctx->channel_layout = avctx->channels == 1 ? AV_CH_LAYOUT_MONO : - AV_CH_LAYOUT_STEREO; + av_channel_layout_uninit(&avctx->ch_layout); + av_channel_layout_default(&avctx->ch_layout, channels); if (avctx->bits_per_coded_sample == 16) avctx->sample_fmt = AV_SAMPLE_FMT_S16; @@ -92,11 +93,11 @@ static av_cold int vmdaudio_decode_init(AVCodecContext *avctx) avctx->sample_fmt = AV_SAMPLE_FMT_U8; s->out_bps = av_get_bytes_per_sample(avctx->sample_fmt); - s->chunk_size = avctx->block_align + avctx->channels * (s->out_bps == 2); + s->chunk_size = avctx->block_align + channels * (s->out_bps == 2); av_log(avctx, AV_LOG_DEBUG, "%d channels, %d bits/sample, " "block align = %d, sample rate = %d\n", - avctx->channels, avctx->bits_per_coded_sample, avctx->block_align, + channels, avctx->bits_per_coded_sample, avctx->block_align, avctx->sample_rate); return 0; @@ -131,10 +132,9 @@ static void decode_audio_s16(int16_t *out, const uint8_t *buf, int buf_size, } } -static int vmdaudio_decode_frame(AVCodecContext *avctx, void *data, +static int vmdaudio_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; const uint8_t *buf = avpkt->data; const uint8_t *buf_end; int buf_size = avpkt->size; @@ -143,6 +143,7 @@ static int vmdaudio_decode_frame(AVCodecContext *avctx, void *data, int ret; uint8_t *output_samples_u8; int16_t *output_samples_s16; + int channels = avctx->ch_layout.nb_channels; if (buf_size < 16) { av_log(avctx, AV_LOG_WARNING, "skipping small junk packet\n"); @@ -186,7 +187,7 @@ static int vmdaudio_decode_frame(AVCodecContext *avctx, void *data, /* get output buffer */ frame->nb_samples = ((silent_chunks + audio_chunks) * avctx->block_align) / - avctx->channels; + avctx->ch_layout.nb_channels; if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; output_samples_u8 = frame->data[0]; @@ -195,7 +196,7 @@ static int vmdaudio_decode_frame(AVCodecContext *avctx, void *data, /* decode silent chunks */ if (silent_chunks > 0) { int silent_size = avctx->block_align * silent_chunks; - av_assert0(avctx->block_align * silent_chunks <= frame->nb_samples * avctx->channels); + av_assert0(avctx->block_align * silent_chunks <= frame->nb_samples * avctx->ch_layout.nb_channels); if (s->out_bps == 2) { memset(output_samples_s16, 0x00, silent_size * 2); @@ -209,11 +210,10 @@ static int vmdaudio_decode_frame(AVCodecContext *avctx, void *data, /* decode audio chunks */ if (audio_chunks > 0) { buf_end = buf + buf_size; - av_assert0((buf_size & (avctx->channels > 1)) == 0); + av_assert0((buf_size & (avctx->ch_layout.nb_channels > 1)) == 0); while (buf_end - buf >= s->chunk_size) { if (s->out_bps == 2) { - decode_audio_s16(output_samples_s16, buf, s->chunk_size, - avctx->channels); + decode_audio_s16(output_samples_s16, buf, s->chunk_size, channels); output_samples_s16 += avctx->block_align; } else { memcpy(output_samples_u8, buf, s->chunk_size); @@ -228,14 +228,14 @@ static int vmdaudio_decode_frame(AVCodecContext *avctx, void *data, return avpkt->size; } -const AVCodec ff_vmdaudio_decoder = { - .name = "vmdaudio", - .long_name = NULL_IF_CONFIG_SMALL("Sierra VMD audio"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_VMDAUDIO, +const FFCodec ff_vmdaudio_decoder = { + .p.name = "vmdaudio", + .p.long_name = NULL_IF_CONFIG_SMALL("Sierra VMD audio"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_VMDAUDIO, .priv_data_size = sizeof(VmdAudioContext), .init = vmdaudio_decode_init, - .decode = vmdaudio_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(vmdaudio_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/vmdvideo.c b/libavcodec/vmdvideo.c index e0349cba6..947f09b73 100644 --- a/libavcodec/vmdvideo.c +++ b/libavcodec/vmdvideo.c @@ -39,6 +39,7 @@ #include "libavutil/intreadwrite.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "bytestream.h" @@ -429,14 +430,12 @@ static av_cold int vmdvideo_decode_init(AVCodecContext *avctx) return 0; } -static int vmdvideo_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int vmdvideo_decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; VmdVideoContext *s = avctx->priv_data; - AVFrame *frame = data; int ret; s->buf = buf; @@ -465,15 +464,15 @@ static int vmdvideo_decode_frame(AVCodecContext *avctx, return buf_size; } -const AVCodec ff_vmdvideo_decoder = { - .name = "vmdvideo", - .long_name = NULL_IF_CONFIG_SMALL("Sierra VMD video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_VMDVIDEO, +const FFCodec ff_vmdvideo_decoder = { + .p.name = "vmdvideo", + .p.long_name = NULL_IF_CONFIG_SMALL("Sierra VMD video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_VMDVIDEO, .priv_data_size = sizeof(VmdVideoContext), .init = vmdvideo_decode_init, .close = vmdvideo_decode_end, - .decode = vmdvideo_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(vmdvideo_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/vmnc.c b/libavcodec/vmnc.c index 645a2f575..cc790984a 100644 --- a/libavcodec/vmnc.c +++ b/libavcodec/vmnc.c @@ -31,6 +31,7 @@ #include "libavutil/common.h" #include "libavutil/intreadwrite.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "bytestream.h" @@ -323,8 +324,8 @@ static void reset_buffers(VmncContext *c) } -static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; @@ -517,7 +518,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, } } *got_frame = 1; - if ((ret = av_frame_ref(data, c->pic)) < 0) + if ((ret = av_frame_ref(rframe, c->pic)) < 0) return ret; /* always report that the buffer was completely consumed */ @@ -572,15 +573,15 @@ static av_cold int decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_vmnc_decoder = { - .name = "vmnc", - .long_name = NULL_IF_CONFIG_SMALL("VMware Screen Codec / VMware Video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_VMNC, +const FFCodec ff_vmnc_decoder = { + .p.name = "vmnc", + .p.long_name = NULL_IF_CONFIG_SMALL("VMware Screen Codec / VMware Video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_VMNC, .priv_data_size = sizeof(VmncContext), .init = decode_init, .close = decode_end, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/vorbis.h b/libavcodec/vorbis.h index 69ddbd298..f80187fee 100644 --- a/libavcodec/vorbis.h +++ b/libavcodec/vorbis.h @@ -26,7 +26,10 @@ extern const float ff_vorbis_floor1_inverse_db_table[256]; extern const float * const ff_vorbis_vwin[8]; extern const uint8_t ff_vorbis_channel_layout_offsets[8][8]; +#if FF_API_OLD_CHANNEL_LAYOUT extern const uint64_t ff_vorbis_channel_layouts[9]; +#endif +extern const AVChannelLayout ff_vorbis_ch_layouts[9]; typedef struct vorbis_floor1_entry { uint16_t x; diff --git a/libavcodec/vorbis_data.c b/libavcodec/vorbis_data.c index fd7e291de..4f4ea03f1 100644 --- a/libavcodec/vorbis_data.c +++ b/libavcodec/vorbis_data.c @@ -34,6 +34,7 @@ const uint8_t ff_vorbis_channel_layout_offsets[8][8] = { { 0, 2, 1, 7, 5, 6, 3, 4 }, }; +#if FF_API_OLD_CHANNEL_LAYOUT const uint64_t ff_vorbis_channel_layouts[9] = { AV_CH_LAYOUT_MONO, AV_CH_LAYOUT_STEREO, @@ -45,6 +46,23 @@ const uint64_t ff_vorbis_channel_layouts[9] = { AV_CH_LAYOUT_7POINT1, 0 }; +#endif + +const AVChannelLayout ff_vorbis_ch_layouts[9] = { + AV_CHANNEL_LAYOUT_MONO, + AV_CHANNEL_LAYOUT_STEREO, + AV_CHANNEL_LAYOUT_SURROUND, + AV_CHANNEL_LAYOUT_QUAD, + AV_CHANNEL_LAYOUT_5POINT0_BACK, + AV_CHANNEL_LAYOUT_5POINT1_BACK, + { + .nb_channels = 7, + .order = AV_CHANNEL_ORDER_NATIVE, + .u.mask = AV_CH_LAYOUT_5POINT1 | AV_CH_BACK_CENTER, + }, + AV_CHANNEL_LAYOUT_7POINT1, + { 0 } +}; DECLARE_ALIGNED(16, static const float, vwin64)[32] = { 0.0009460463F, 0.0085006468F, 0.0235352254F, 0.0458950567F, diff --git a/libavcodec/vorbis_parser.c b/libavcodec/vorbis_parser.c index 194ae13da..a7d15d4ce 100644 --- a/libavcodec/vorbis_parser.c +++ b/libavcodec/vorbis_parser.c @@ -25,6 +25,8 @@ * Determines the duration for each packet. */ +#include "config_components.h" + #include "libavutil/log.h" #include "get_bits.h" diff --git a/libavcodec/vorbisdec.c b/libavcodec/vorbisdec.c index 6e07bc5a8..6ba0e1d81 100644 --- a/libavcodec/vorbisdec.c +++ b/libavcodec/vorbisdec.c @@ -34,6 +34,7 @@ #define BITSTREAM_READER_LE #include "avcodec.h" +#include "codec_internal.h" #include "fft.h" #include "get_bits.h" #include "internal.h" @@ -1077,12 +1078,14 @@ static av_cold int vorbis_decode_init(AVCodecContext *avctx) return ret; } - if (vc->audio_channels > 8) - avctx->channel_layout = 0; - else - avctx->channel_layout = ff_vorbis_channel_layouts[vc->audio_channels - 1]; + av_channel_layout_uninit(&avctx->ch_layout); + if (vc->audio_channels > 8) { + avctx->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + avctx->ch_layout.nb_channels = vc->audio_channels; + } else { + av_channel_layout_copy(&avctx->ch_layout, &ff_vorbis_ch_layouts[vc->audio_channels - 1]); + } - avctx->channels = vc->audio_channels; avctx->sample_rate = vc->audio_samplerate; return 0; @@ -1764,13 +1767,12 @@ static int vorbis_parse_audio_packet(vorbis_context *vc, float **floor_ptr) // Return the decoded audio packet through the standard api -static int vorbis_decode_frame(AVCodecContext *avctx, void *data, +static int vorbis_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; vorbis_context *vc = avctx->priv_data; - AVFrame *frame = data; GetBitContext *gb = &vc->gb; float *channel_ptrs[255]; int i, len, ret; @@ -1788,12 +1790,14 @@ static int vorbis_decode_frame(AVCodecContext *avctx, void *data, return ret; } - if (vc->audio_channels > 8) - avctx->channel_layout = 0; - else - avctx->channel_layout = ff_vorbis_channel_layouts[vc->audio_channels - 1]; + av_channel_layout_uninit(&avctx->ch_layout); + if (vc->audio_channels > 8) { + avctx->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + avctx->ch_layout.nb_channels = vc->audio_channels; + } else { + av_channel_layout_copy(&avctx->ch_layout, &ff_vorbis_ch_layouts[vc->audio_channels - 1]); + } - avctx->channels = vc->audio_channels; avctx->sample_rate = vc->audio_samplerate; return buf_size; } @@ -1880,19 +1884,22 @@ static av_cold void vorbis_decode_flush(AVCodecContext *avctx) vc->first_frame = 0; } -const AVCodec ff_vorbis_decoder = { - .name = "vorbis", - .long_name = NULL_IF_CONFIG_SMALL("Vorbis"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_VORBIS, +const FFCodec ff_vorbis_decoder = { + .p.name = "vorbis", + .p.long_name = NULL_IF_CONFIG_SMALL("Vorbis"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_VORBIS, .priv_data_size = sizeof(vorbis_context), .init = vorbis_decode_init, .close = vorbis_decode_close, - .decode = vorbis_decode_frame, + FF_CODEC_DECODE_CB(vorbis_decode_frame), .flush = vorbis_decode_flush, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, - .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, - .channel_layouts = ff_vorbis_channel_layouts, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, +#if FF_API_OLD_CHANNEL_LAYOUT + .p.channel_layouts = ff_vorbis_channel_layouts, +#endif + .p.ch_layouts = ff_vorbis_ch_layouts, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, }; diff --git a/libavcodec/vorbisdsp.c b/libavcodec/vorbisdsp.c index 362a27629..e94b65cb7 100644 --- a/libavcodec/vorbisdsp.c +++ b/libavcodec/vorbisdsp.c @@ -25,12 +25,13 @@ av_cold void ff_vorbisdsp_init(VorbisDSPContext *dsp) { dsp->vorbis_inverse_coupling = ff_vorbis_inverse_coupling; - if (ARCH_AARCH64) - ff_vorbisdsp_init_aarch64(dsp); - if (ARCH_ARM) - ff_vorbisdsp_init_arm(dsp); - if (ARCH_PPC) - ff_vorbisdsp_init_ppc(dsp); - if (ARCH_X86) - ff_vorbisdsp_init_x86(dsp); +#if ARCH_AARCH64 + ff_vorbisdsp_init_aarch64(dsp); +#elif ARCH_ARM + ff_vorbisdsp_init_arm(dsp); +#elif ARCH_PPC + ff_vorbisdsp_init_ppc(dsp); +#elif ARCH_X86 + ff_vorbisdsp_init_x86(dsp); +#endif } diff --git a/libavcodec/vorbisenc.c b/libavcodec/vorbisenc.c index 858c6ac6d..0db8aeb2b 100644 --- a/libavcodec/vorbisenc.c +++ b/libavcodec/vorbisenc.c @@ -28,8 +28,8 @@ #include "libavutil/float_dsp.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "fft.h" #include "mathops.h" #include "vorbis.h" @@ -276,7 +276,7 @@ static int create_vorbis_context(vorbis_enc_context *venc, const uint8_t *clens, *quant; int i, book, ret; - venc->channels = avctx->channels; + venc->channels = avctx->ch_layout.nb_channels; venc->sample_rate = avctx->sample_rate; venc->log2_blocksize[0] = venc->log2_blocksize[1] = 11; @@ -1038,7 +1038,8 @@ static AVFrame *spawn_empty_frame(AVCodecContext *avctx, int channels) f->format = avctx->sample_fmt; f->nb_samples = avctx->frame_size; - f->channel_layout = avctx->channel_layout; + f->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + f->ch_layout.nb_channels = channels; if (av_frame_get_buffer(f, 4)) { av_frame_free(&f); @@ -1267,13 +1268,13 @@ static av_cold int vorbis_encode_init(AVCodecContext *avctx) vorbis_enc_context *venc = avctx->priv_data; int ret; - if (avctx->channels != 2) { + if (avctx->ch_layout.nb_channels != 2) { av_log(avctx, AV_LOG_ERROR, "Current FFmpeg Vorbis encoder only supports 2 channels.\n"); return -1; } if ((ret = create_vorbis_context(venc, avctx)) < 0) - goto error; + return ret; avctx->bit_rate = 0; if (avctx->flags & AV_CODEC_FLAG_QSCALE) @@ -1283,7 +1284,7 @@ static av_cold int vorbis_encode_init(AVCodecContext *avctx) venc->quality *= venc->quality; if ((ret = put_main_header(venc, (uint8_t**)&avctx->extradata)) < 0) - goto error; + return ret; avctx->extradata_size = ret; avctx->frame_size = 64; @@ -1292,22 +1293,19 @@ static av_cold int vorbis_encode_init(AVCodecContext *avctx) ff_af_queue_init(avctx, &venc->afq); return 0; -error: - vorbis_encode_close(avctx); - return ret; } -const AVCodec ff_vorbis_encoder = { - .name = "vorbis", - .long_name = NULL_IF_CONFIG_SMALL("Vorbis"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_VORBIS, +const FFCodec ff_vorbis_encoder = { + .p.name = "vorbis", + .p.long_name = NULL_IF_CONFIG_SMALL("Vorbis"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_VORBIS, .priv_data_size = sizeof(vorbis_enc_context), .init = vorbis_encode_init, - .encode2 = vorbis_encode_frame, + FF_CODEC_ENCODE_CB(vorbis_encode_frame), .close = vorbis_encode_close, - .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_EXPERIMENTAL, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP, + .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_EXPERIMENTAL, + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/vp3.c b/libavcodec/vp3.c index 5b9ba60f4..8ca1b0dfe 100644 --- a/libavcodec/vp3.c +++ b/libavcodec/vp3.c @@ -30,6 +30,8 @@ * Theora decoder by Alex Beregszaszi */ +#include "config_components.h" + #include #include #include @@ -38,11 +40,13 @@ #include "libavutil/mem_internal.h" #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" #include "hpeldsp.h" #include "internal.h" #include "mathops.h" #include "thread.h" +#include "threadframe.h" #include "videodsp.h" #include "vp3data.h" #include "vp4data.h" @@ -332,11 +336,11 @@ static void vp3_decode_flush(AVCodecContext *avctx) Vp3DecodeContext *s = avctx->priv_data; if (s->golden_frame.f) - ff_thread_release_buffer(avctx, &s->golden_frame); + ff_thread_release_ext_buffer(avctx, &s->golden_frame); if (s->last_frame.f) - ff_thread_release_buffer(avctx, &s->last_frame); + ff_thread_release_ext_buffer(avctx, &s->last_frame); if (s->current_frame.f) - ff_thread_release_buffer(avctx, &s->current_frame); + ff_thread_release_ext_buffer(avctx, &s->current_frame); } static av_cold int vp3_decode_end(AVCodecContext *avctx) @@ -1193,7 +1197,7 @@ static int unpack_vlcs(Vp3DecodeContext *s, GetBitContext *gb, /* local references to structure members to avoid repeated dereferences */ int *coded_fragment_list = s->coded_fragment_list[plane]; Vp3Fragment *all_fragments = s->all_fragments; - VLC_TYPE(*vlc_table)[2] = table->table; + const VLCElem *vlc_table = table->table; if (num_coeffs < 0) { av_log(s->avctx, AV_LOG_ERROR, @@ -2506,25 +2510,25 @@ static int update_frames(AVCodecContext *avctx) int ret = 0; /* shuffle frames (last = current) */ - ff_thread_release_buffer(avctx, &s->last_frame); + ff_thread_release_ext_buffer(avctx, &s->last_frame); ret = ff_thread_ref_frame(&s->last_frame, &s->current_frame); if (ret < 0) goto fail; if (s->keyframe) { - ff_thread_release_buffer(avctx, &s->golden_frame); + ff_thread_release_ext_buffer(avctx, &s->golden_frame); ret = ff_thread_ref_frame(&s->golden_frame, &s->current_frame); } fail: - ff_thread_release_buffer(avctx, &s->current_frame); + ff_thread_release_ext_buffer(avctx, &s->current_frame); return ret; } #if HAVE_THREADS static int ref_frame(Vp3DecodeContext *s, ThreadFrame *dst, ThreadFrame *src) { - ff_thread_release_buffer(s->avctx, dst); + ff_thread_release_ext_buffer(s->avctx, dst); if (src->f->data[0]) return ff_thread_ref_frame(dst, src); return 0; @@ -2582,11 +2586,9 @@ static int vp3_update_thread_context(AVCodecContext *dst, const AVCodecContext * } #endif -static int vp3_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int vp3_decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; Vp3DecodeContext *s = avctx->priv_data; @@ -2674,11 +2676,17 @@ static int vp3_decode_frame(AVCodecContext *avctx, s->current_frame.f->pict_type = s->keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; s->current_frame.f->key_frame = s->keyframe; - if ((ret = ff_thread_get_buffer(avctx, &s->current_frame, AV_GET_BUFFER_FLAG_REF)) < 0) + if ((ret = ff_thread_get_ext_buffer(avctx, &s->current_frame, + AV_GET_BUFFER_FLAG_REF)) < 0) goto error; - if (!s->edge_emu_buffer) + if (!s->edge_emu_buffer) { s->edge_emu_buffer = av_malloc(9 * FFABS(s->current_frame.f->linesize[0])); + if (!s->edge_emu_buffer) { + ret = AVERROR(ENOMEM); + goto error; + } + } if (s->keyframe) { if (!s->theora) { @@ -2733,10 +2741,10 @@ static int vp3_decode_frame(AVCodecContext *avctx, "vp3: first frame not a keyframe\n"); s->golden_frame.f->pict_type = AV_PICTURE_TYPE_I; - if ((ret = ff_thread_get_buffer(avctx, &s->golden_frame, - AV_GET_BUFFER_FLAG_REF)) < 0) + if ((ret = ff_thread_get_ext_buffer(avctx, &s->golden_frame, + AV_GET_BUFFER_FLAG_REF)) < 0) goto error; - ff_thread_release_buffer(avctx, &s->last_frame); + ff_thread_release_ext_buffer(avctx, &s->last_frame); if ((ret = ff_thread_ref_frame(&s->last_frame, &s->golden_frame)) < 0) goto error; @@ -2808,7 +2816,7 @@ static int vp3_decode_frame(AVCodecContext *avctx, vp3_draw_horiz_band(s, s->height); /* output frame, offset as needed */ - if ((ret = av_frame_ref(data, s->current_frame.f)) < 0) + if ((ret = av_frame_ref(frame, s->current_frame.f)) < 0) return ret; frame->crop_left = s->offset_x; @@ -3149,10 +3157,10 @@ static av_cold int theora_decode_init(AVCodecContext *avctx) "Unknown Theora config packet: %d\n", ptype & ~0x80); break; } - if (ptype != 0x81 && 8 * header_len[i] != get_bits_count(&gb)) + if (ptype != 0x81 && get_bits_left(&gb) >= 8U) av_log(avctx, AV_LOG_WARNING, "%d bits left in packet %X\n", - 8 * header_len[i] - get_bits_count(&gb), ptype); + get_bits_left(&gb), ptype); if (s->theora < 0x030200) break; } @@ -3160,16 +3168,16 @@ static av_cold int theora_decode_init(AVCodecContext *avctx) return vp3_decode_init(avctx); } -const AVCodec ff_theora_decoder = { - .name = "theora", - .long_name = NULL_IF_CONFIG_SMALL("Theora"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_THEORA, +const FFCodec ff_theora_decoder = { + .p.name = "theora", + .p.long_name = NULL_IF_CONFIG_SMALL("Theora"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_THEORA, .priv_data_size = sizeof(Vp3DecodeContext), .init = theora_decode_init, .close = vp3_decode_end, - .decode = vp3_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DRAW_HORIZ_BAND | + FF_CODEC_DECODE_CB(vp3_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_FRAME_THREADS, .flush = vp3_decode_flush, .update_thread_context = ONLY_IF_THREADS_ENABLED(vp3_update_thread_context), @@ -3178,16 +3186,16 @@ const AVCodec ff_theora_decoder = { }; #endif -const AVCodec ff_vp3_decoder = { - .name = "vp3", - .long_name = NULL_IF_CONFIG_SMALL("On2 VP3"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_VP3, +const FFCodec ff_vp3_decoder = { + .p.name = "vp3", + .p.long_name = NULL_IF_CONFIG_SMALL("On2 VP3"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_VP3, .priv_data_size = sizeof(Vp3DecodeContext), .init = vp3_decode_init, .close = vp3_decode_end, - .decode = vp3_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DRAW_HORIZ_BAND | + FF_CODEC_DECODE_CB(vp3_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_FRAME_THREADS, .flush = vp3_decode_flush, .update_thread_context = ONLY_IF_THREADS_ENABLED(vp3_update_thread_context), @@ -3196,16 +3204,16 @@ const AVCodec ff_vp3_decoder = { }; #if CONFIG_VP4_DECODER -const AVCodec ff_vp4_decoder = { - .name = "vp4", - .long_name = NULL_IF_CONFIG_SMALL("On2 VP4"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_VP4, +const FFCodec ff_vp4_decoder = { + .p.name = "vp4", + .p.long_name = NULL_IF_CONFIG_SMALL("On2 VP4"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_VP4, .priv_data_size = sizeof(Vp3DecodeContext), .init = vp3_decode_init, .close = vp3_decode_end, - .decode = vp3_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DRAW_HORIZ_BAND | + FF_CODEC_DECODE_CB(vp3_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_FRAME_THREADS, .flush = vp3_decode_flush, .update_thread_context = ONLY_IF_THREADS_ENABLED(vp3_update_thread_context), diff --git a/libavcodec/vp3dsp.c b/libavcodec/vp3dsp.c index f06834f42..b4621f07e 100644 --- a/libavcodec/vp3dsp.c +++ b/libavcodec/vp3dsp.c @@ -455,14 +455,15 @@ av_cold void ff_vp3dsp_init(VP3DSPContext *c, int flags) c->v_loop_filter = c->v_loop_filter_unaligned = vp3_v_loop_filter_8_c; c->h_loop_filter = c->h_loop_filter_unaligned = vp3_h_loop_filter_8_c; - if (ARCH_ARM) - ff_vp3dsp_init_arm(c, flags); - if (ARCH_PPC) - ff_vp3dsp_init_ppc(c, flags); - if (ARCH_X86) - ff_vp3dsp_init_x86(c, flags); - if (ARCH_MIPS) - ff_vp3dsp_init_mips(c, flags); +#if ARCH_ARM + ff_vp3dsp_init_arm(c, flags); +#elif ARCH_PPC + ff_vp3dsp_init_ppc(c, flags); +#elif ARCH_X86 + ff_vp3dsp_init_x86(c, flags); +#elif ARCH_MIPS + ff_vp3dsp_init_mips(c, flags); +#endif } /* diff --git a/libavcodec/vp5.c b/libavcodec/vp5.c index f68c62527..7ec381b5e 100644 --- a/libavcodec/vp5.c +++ b/libavcodec/vp5.c @@ -27,6 +27,7 @@ #include #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "vp56.h" @@ -282,7 +283,7 @@ static av_cold int vp5_decode_init(AVCodecContext *avctx) VP56Context *s = avctx->priv_data; int ret; - if ((ret = ff_vp56_init(avctx, 1, 0)) < 0) + if ((ret = ff_vp56_init_context(avctx, s, 1, 0)) < 0) return ret; ff_vp5dsp_init(&s->vp56dsp); s->vp56_coord_div = vp5_coord_div; @@ -296,14 +297,21 @@ static av_cold int vp5_decode_init(AVCodecContext *avctx) return 0; } -const AVCodec ff_vp5_decoder = { - .name = "vp5", - .long_name = NULL_IF_CONFIG_SMALL("On2 VP5"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_VP5, +static av_cold int vp56_free(AVCodecContext *avctx) +{ + VP56Context *const s = avctx->priv_data; + return ff_vp56_free_context(s); +} + +const FFCodec ff_vp5_decoder = { + .p.name = "vp5", + .p.long_name = NULL_IF_CONFIG_SMALL("On2 VP5"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_VP5, .priv_data_size = sizeof(VP56Context), .init = vp5_decode_init, - .close = ff_vp56_free, - .decode = ff_vp56_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + .close = vp56_free, + FF_CODEC_DECODE_CB(ff_vp56_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/vp56.c b/libavcodec/vp56.c index 695f37e97..a2efca1c9 100644 --- a/libavcodec/vp56.c +++ b/libavcodec/vp56.c @@ -565,8 +565,8 @@ static int vp56_size_changed(VP56Context *s) static int ff_vp56_decode_mbs(AVCodecContext *avctx, void *, int, int); -int ff_vp56_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +int ff_vp56_decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; VP56Context *s = avctx->priv_data; @@ -649,7 +649,7 @@ int ff_vp56_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, if (s->discard_frame) return AVERROR_INVALIDDATA; - if ((res = av_frame_ref(data, p)) < 0) + if ((res = av_frame_ref(rframe, p)) < 0) return res; *got_frame = 1; @@ -773,12 +773,6 @@ next: return 0; } -av_cold int ff_vp56_init(AVCodecContext *avctx, int flip, int has_alpha) -{ - VP56Context *s = avctx->priv_data; - return ff_vp56_init_context(avctx, s, flip, has_alpha); -} - av_cold int ff_vp56_init_context(AVCodecContext *avctx, VP56Context *s, int flip, int has_alpha) { @@ -800,10 +794,8 @@ av_cold int ff_vp56_init_context(AVCodecContext *avctx, VP56Context *s, for (i = 0; i < FF_ARRAY_ELEMS(s->frames); i++) { s->frames[i] = av_frame_alloc(); - if (!s->frames[i]) { - ff_vp56_free(avctx); + if (!s->frames[i]) return AVERROR(ENOMEM); - } } s->edge_emu_buffer_alloc = NULL; @@ -832,12 +824,6 @@ av_cold int ff_vp56_init_context(AVCodecContext *avctx, VP56Context *s, return 0; } -av_cold int ff_vp56_free(AVCodecContext *avctx) -{ - VP56Context *s = avctx->priv_data; - return ff_vp56_free_context(s); -} - av_cold int ff_vp56_free_context(VP56Context *s) { int i; diff --git a/libavcodec/vp56.h b/libavcodec/vp56.h index 46090f25c..d2e6ad3ed 100644 --- a/libavcodec/vp56.h +++ b/libavcodec/vp56.h @@ -216,14 +216,16 @@ struct vp56_context { }; -int ff_vp56_init(AVCodecContext *avctx, int flip, int has_alpha); +/** + * Initializes an VP56Context. Expects its caller to clean up + * in case of error. + */ int ff_vp56_init_context(AVCodecContext *avctx, VP56Context *s, int flip, int has_alpha); -int ff_vp56_free(AVCodecContext *avctx); int ff_vp56_free_context(VP56Context *s); void ff_vp56_init_dequant(VP56Context *s, int quantizer); -int ff_vp56_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt); +int ff_vp56_decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt); /** diff --git a/libavcodec/vp56data.h b/libavcodec/vp56data.h index 3be268c31..aaca1fd08 100644 --- a/libavcodec/vp56data.h +++ b/libavcodec/vp56data.h @@ -26,7 +26,7 @@ #ifndef AVCODEC_VP56DATA_H #define AVCODEC_VP56DATA_H -#include "libavutil/common.h" +#include #include "vp56.h" extern const uint8_t ff_vp56_b2p[]; diff --git a/libavcodec/vp56dsp.c b/libavcodec/vp56dsp.c index de6803e0f..a66871238 100644 --- a/libavcodec/vp56dsp.c +++ b/libavcodec/vp56dsp.c @@ -22,6 +22,7 @@ #include #include "config.h" +#include "config_components.h" #include "libavutil/attributes.h" #include "vp56dsp.h" #include "libavutil/common.h" @@ -76,9 +77,10 @@ av_cold void ff_vp6dsp_init(VP56DSPContext *s) { s->vp6_filter_diag4 = ff_vp6_filter_diag4_c; - if (ARCH_ARM) - ff_vp6dsp_init_arm(s); - if (ARCH_X86) - ff_vp6dsp_init_x86(s); +#if ARCH_ARM + ff_vp6dsp_init_arm(s); +#elif ARCH_X86 + ff_vp6dsp_init_x86(s); +#endif } #endif /* CONFIG_VP6_DECODER */ diff --git a/libavcodec/vp56rac.c b/libavcodec/vp56rac.c index 64fb6a99b..19e7dcf2b 100644 --- a/libavcodec/vp56rac.c +++ b/libavcodec/vp56rac.c @@ -19,7 +19,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/common.h" +#include +#include "libavutil/error.h" +#include "bytestream.h" #include "vp56.h" const uint8_t ff_vp56_norm_shift[256]= { diff --git a/libavcodec/vp6.c b/libavcodec/vp6.c index d02437079..19dc754fe 100644 --- a/libavcodec/vp6.c +++ b/libavcodec/vp6.c @@ -30,6 +30,7 @@ #include #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" #include "huffman.h" #include "internal.h" @@ -637,33 +638,15 @@ static void vp6_filter(VP56Context *s, uint8_t *dst, uint8_t *src, } } -static av_cold void vp6_decode_init_context(VP56Context *s); - -static av_cold int vp6_decode_init(AVCodecContext *avctx) +static av_cold int vp6_decode_init_context(AVCodecContext *avctx, + VP56Context *s, int flip, int has_alpha) { - VP56Context *s = avctx->priv_data; - int ret; - - if ((ret = ff_vp56_init(avctx, avctx->codec->id == AV_CODEC_ID_VP6, - avctx->codec->id == AV_CODEC_ID_VP6A)) < 0) + int ret = ff_vp56_init_context(avctx, s, flip, has_alpha); + if (ret < 0) return ret; + ff_vp6dsp_init(&s->vp56dsp); - vp6_decode_init_context(s); - - if (s->has_alpha) { - s->alpha_context = av_mallocz(sizeof(VP56Context)); - ff_vp56_init_context(avctx, s->alpha_context, - s->flip == -1, s->has_alpha); - ff_vp6dsp_init(&s->alpha_context->vp56dsp); - vp6_decode_init_context(s->alpha_context); - } - - return 0; -} - -static av_cold void vp6_decode_init_context(VP56Context *s) -{ s->deblock_filtering = 0; s->vp56_coord_div = vp6_coord_div; s->parse_vector_adjustment = vp6_parse_vector_adjustment; @@ -672,6 +655,30 @@ static av_cold void vp6_decode_init_context(VP56Context *s) s->parse_vector_models = vp6_parse_vector_models; s->parse_coeff_models = vp6_parse_coeff_models; s->parse_header = vp6_parse_header; + + return 0; +} + +static av_cold int vp6_decode_init(AVCodecContext *avctx) +{ + VP56Context *s = avctx->priv_data; + int ret; + + ret = vp6_decode_init_context(avctx, s, avctx->codec_id == AV_CODEC_ID_VP6, + avctx->codec_id == AV_CODEC_ID_VP6A); + if (ret < 0) + return ret; + + if (s->has_alpha) { + /* Can only happen for ff_vp6a_decoder */ + s->alpha_context = &s[1]; + ret = vp6_decode_init_context(avctx, s->alpha_context, + s->flip == -1, s->has_alpha); + if (ret < 0) + return ret; + } + + return 0; } static av_cold void vp6_decode_free_context(VP56Context *s); @@ -680,13 +687,11 @@ static av_cold int vp6_decode_free(AVCodecContext *avctx) { VP56Context *s = avctx->priv_data; - ff_vp56_free(avctx); vp6_decode_free_context(s); if (s->alpha_context) { - ff_vp56_free_context(s->alpha_context); vp6_decode_free_context(s->alpha_context); - av_freep(&s->alpha_context); + s->alpha_context = NULL; } return 0; @@ -696,6 +701,8 @@ static av_cold void vp6_decode_free_context(VP56Context *s) { int pt, ct, cg; + ff_vp56_free_context(s); + for (pt=0; pt<2; pt++) { ff_free_vlc(&s->dccv_vlc[pt]); ff_free_vlc(&s->runv_vlc[pt]); @@ -705,40 +712,43 @@ static av_cold void vp6_decode_free_context(VP56Context *s) } } -const AVCodec ff_vp6_decoder = { - .name = "vp6", - .long_name = NULL_IF_CONFIG_SMALL("On2 VP6"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_VP6, +const FFCodec ff_vp6_decoder = { + .p.name = "vp6", + .p.long_name = NULL_IF_CONFIG_SMALL("On2 VP6"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_VP6, .priv_data_size = sizeof(VP56Context), .init = vp6_decode_init, .close = vp6_decode_free, - .decode = ff_vp56_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(ff_vp56_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; /* flash version, not flipped upside-down */ -const AVCodec ff_vp6f_decoder = { - .name = "vp6f", - .long_name = NULL_IF_CONFIG_SMALL("On2 VP6 (Flash version)"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_VP6F, +const FFCodec ff_vp6f_decoder = { + .p.name = "vp6f", + .p.long_name = NULL_IF_CONFIG_SMALL("On2 VP6 (Flash version)"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_VP6F, .priv_data_size = sizeof(VP56Context), .init = vp6_decode_init, .close = vp6_decode_free, - .decode = ff_vp56_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(ff_vp56_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; /* flash version, not flipped upside-down, with alpha channel */ -const AVCodec ff_vp6a_decoder = { - .name = "vp6a", - .long_name = NULL_IF_CONFIG_SMALL("On2 VP6 (Flash version, with alpha channel)"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_VP6A, - .priv_data_size = sizeof(VP56Context), +const FFCodec ff_vp6a_decoder = { + .p.name = "vp6a", + .p.long_name = NULL_IF_CONFIG_SMALL("On2 VP6 (Flash version, with alpha channel)"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_VP6A, + .priv_data_size = 2 /* Main context + alpha context */ * sizeof(VP56Context), .init = vp6_decode_init, .close = vp6_decode_free, - .decode = ff_vp56_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS, + FF_CODEC_DECODE_CB(ff_vp56_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/vp8.c b/libavcodec/vp8.c index a70d94bd8..f521f2c9d 100644 --- a/libavcodec/vp8.c +++ b/libavcodec/vp8.c @@ -24,15 +24,19 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/imgutils.h" #include "libavutil/mem_internal.h" #include "avcodec.h" +#include "codec_internal.h" #include "hwconfig.h" #include "internal.h" #include "mathops.h" #include "rectangle.h" #include "thread.h" +#include "threadframe.h" #include "vp8.h" #include "vp8data.h" @@ -71,8 +75,8 @@ static void free_buffers(VP8Context *s) static int vp8_alloc_frame(VP8Context *s, VP8Frame *f, int ref) { int ret; - if ((ret = ff_thread_get_buffer(s->avctx, &f->tf, - ref ? AV_GET_BUFFER_FLAG_REF : 0)) < 0) + if ((ret = ff_thread_get_ext_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))) goto fail; @@ -89,7 +93,7 @@ static int vp8_alloc_frame(VP8Context *s, VP8Frame *f, int ref) fail: av_buffer_unref(&f->seg_map); - ff_thread_release_buffer(s->avctx, &f->tf); + ff_thread_release_ext_buffer(s->avctx, &f->tf); return AVERROR(ENOMEM); } @@ -98,7 +102,7 @@ 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); + ff_thread_release_ext_buffer(s->avctx, &f->tf); } #if CONFIG_VP8_DECODER @@ -2621,7 +2625,7 @@ static int vp8_decode_mb_row_sliced(AVCodecContext *avctx, void *tdata, } static av_always_inline -int vp78_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, +int vp78_decode_frame(AVCodecContext *avctx, AVFrame *rframe, int *got_frame, const AVPacket *avpkt, int is_vp7) { VP8Context *s = avctx->priv_data; @@ -2719,7 +2723,7 @@ int vp78_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, s->next_framep[VP56_FRAME_CURRENT] = curframe; - if (avctx->codec->update_thread_context) + if (ffcodec(avctx->codec)->update_thread_context) ff_thread_finish_setup(avctx); if (avctx->hwaccel) { @@ -2796,7 +2800,7 @@ skip_decode: s->prob[0] = s->prob[1]; if (!s->invisible) { - if ((ret = av_frame_ref(data, curframe->tf.f)) < 0) + if ((ret = av_frame_ref(rframe, curframe->tf.f)) < 0) return ret; *got_frame = 1; } @@ -2807,17 +2811,17 @@ err: return ret; } -int ff_vp8_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +int ff_vp8_decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { - return vp78_decode_frame(avctx, data, got_frame, avpkt, IS_VP8); + return vp78_decode_frame(avctx, frame, got_frame, avpkt, IS_VP8); } #if CONFIG_VP7_DECODER -static int vp7_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int vp7_decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { - return vp78_decode_frame(avctx, data, got_frame, avpkt, IS_VP7); + return vp78_decode_frame(avctx, frame, got_frame, avpkt, IS_VP7); } #endif /* CONFIG_VP7_DECODER */ @@ -2826,9 +2830,6 @@ av_cold int ff_vp8_decode_free(AVCodecContext *avctx) VP8Context *s = avctx->priv_data; int i; - if (!s) - return 0; - vp8_decode_flush_impl(avctx, 1); for (i = 0; i < FF_ARRAY_ELEMS(s->frames); i++) av_frame_free(&s->frames[i].tf.f); @@ -2938,32 +2939,32 @@ static int vp8_decode_update_thread_context(AVCodecContext *dst, #endif /* CONFIG_VP8_DECODER */ #if CONFIG_VP7_DECODER -const AVCodec ff_vp7_decoder = { - .name = "vp7", - .long_name = NULL_IF_CONFIG_SMALL("On2 VP7"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_VP7, +const FFCodec ff_vp7_decoder = { + .p.name = "vp7", + .p.long_name = NULL_IF_CONFIG_SMALL("On2 VP7"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_VP7, .priv_data_size = sizeof(VP8Context), .init = vp7_decode_init, .close = ff_vp8_decode_free, - .decode = vp7_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(vp7_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, .flush = vp8_decode_flush, }; #endif /* CONFIG_VP7_DECODER */ #if CONFIG_VP8_DECODER -const AVCodec ff_vp8_decoder = { - .name = "vp8", - .long_name = NULL_IF_CONFIG_SMALL("On2 VP8"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_VP8, +const FFCodec ff_vp8_decoder = { + .p.name = "vp8", + .p.long_name = NULL_IF_CONFIG_SMALL("On2 VP8"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_VP8, .priv_data_size = sizeof(VP8Context), .init = ff_vp8_decode_init, .close = ff_vp8_decode_free, - .decode = ff_vp8_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | + FF_CODEC_DECODE_CB(ff_vp8_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_SLICE_THREADS, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_ALLOCATE_PROGRESS, diff --git a/libavcodec/vp8.h b/libavcodec/vp8.h index e6091dfe0..8fe45573e 100644 --- a/libavcodec/vp8.h +++ b/libavcodec/vp8.h @@ -33,7 +33,7 @@ #include "libavutil/thread.h" #include "h264pred.h" -#include "thread.h" +#include "threadframe.h" #include "vp56.h" #include "vp8dsp.h" @@ -344,8 +344,8 @@ typedef struct VP8Context { int ff_vp8_decode_init(AVCodecContext *avctx); -int ff_vp8_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt); +int ff_vp8_decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt); int ff_vp8_decode_free(AVCodecContext *avctx); diff --git a/libavcodec/vp8dsp.c b/libavcodec/vp8dsp.c index 732a483b6..a92774ed5 100644 --- a/libavcodec/vp8dsp.c +++ b/libavcodec/vp8dsp.c @@ -25,6 +25,8 @@ * VP8 compatible video decoder */ +#include "config_components.h" + #include "libavutil/common.h" #include "libavutil/intreadwrite.h" @@ -673,14 +675,15 @@ av_cold void ff_vp78dsp_init(VP8DSPContext *dsp) VP78_BILINEAR_MC_FUNC(1, 8); VP78_BILINEAR_MC_FUNC(2, 4); - if (ARCH_AARCH64) - ff_vp78dsp_init_aarch64(dsp); - if (ARCH_ARM) - ff_vp78dsp_init_arm(dsp); - if (ARCH_PPC) - ff_vp78dsp_init_ppc(dsp); - if (ARCH_X86) - ff_vp78dsp_init_x86(dsp); +#if ARCH_AARCH64 + ff_vp78dsp_init_aarch64(dsp); +#elif ARCH_ARM + ff_vp78dsp_init_arm(dsp); +#elif ARCH_PPC + ff_vp78dsp_init_ppc(dsp); +#elif ARCH_X86 + ff_vp78dsp_init_x86(dsp); +#endif } #if CONFIG_VP7_DECODER @@ -735,15 +738,16 @@ av_cold void ff_vp8dsp_init(VP8DSPContext *dsp) dsp->vp8_v_loop_filter_simple = vp8_v_loop_filter_simple_c; dsp->vp8_h_loop_filter_simple = vp8_h_loop_filter_simple_c; - if (ARCH_AARCH64) - ff_vp8dsp_init_aarch64(dsp); - if (ARCH_ARM) - ff_vp8dsp_init_arm(dsp); - if (ARCH_X86) - ff_vp8dsp_init_x86(dsp); - if (ARCH_MIPS) - ff_vp8dsp_init_mips(dsp); - if (ARCH_LOONGARCH) - ff_vp8dsp_init_loongarch(dsp); +#if ARCH_AARCH64 + ff_vp8dsp_init_aarch64(dsp); +#elif ARCH_ARM + ff_vp8dsp_init_arm(dsp); +#elif ARCH_X86 + ff_vp8dsp_init_x86(dsp); +#elif ARCH_MIPS + ff_vp8dsp_init_mips(dsp); +#elif ARCH_LOONGARCH + ff_vp8dsp_init_loongarch(dsp); +#endif } #endif /* CONFIG_VP8_DECODER */ diff --git a/libavcodec/vp9.c b/libavcodec/vp9.c index 24841c5b9..fee79fb45 100644 --- a/libavcodec/vp9.c +++ b/libavcodec/vp9.c @@ -21,12 +21,16 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" #include "hwconfig.h" #include "internal.h" #include "profiles.h" #include "thread.h" +#include "threadframe.h" #include "pthread_internal.h" #include "videodsp.h" @@ -92,7 +96,7 @@ static void vp9_tile_data_free(VP9TileData *td) static void vp9_frame_unref(AVCodecContext *avctx, VP9Frame *f) { - ff_thread_release_buffer(avctx, &f->tf); + ff_thread_release_ext_buffer(avctx, &f->tf); av_buffer_unref(&f->extradata); av_buffer_unref(&f->hwaccel_priv_buf); f->segmentation_map = NULL; @@ -104,7 +108,7 @@ static int vp9_frame_alloc(AVCodecContext *avctx, VP9Frame *f) VP9Context *s = avctx->priv_data; int ret, sz; - ret = ff_thread_get_buffer(avctx, &f->tf, AV_GET_BUFFER_FLAG_REF); + ret = ff_thread_get_ext_buffer(avctx, &f->tf, AV_GET_BUFFER_FLAG_REF); if (ret < 0) return ret; @@ -1236,9 +1240,9 @@ static av_cold int vp9_decode_free(AVCodecContext *avctx) } av_buffer_pool_uninit(&s->frame_extradata_pool); for (i = 0; i < 8; i++) { - ff_thread_release_buffer(avctx, &s->s.refs[i]); + ff_thread_release_ext_buffer(avctx, &s->s.refs[i]); av_frame_free(&s->s.refs[i].f); - ff_thread_release_buffer(avctx, &s->next_refs[i]); + ff_thread_release_ext_buffer(avctx, &s->next_refs[i]); av_frame_free(&s->next_refs[i].f); } @@ -1546,7 +1550,7 @@ static int vp9_export_enc_params(VP9Context *s, VP9Frame *frame) return 0; } -static int vp9_decode_frame(AVCodecContext *avctx, void *frame, +static int vp9_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *pkt) { const uint8_t *data = pkt->data; @@ -1566,11 +1570,11 @@ static int vp9_decode_frame(AVCodecContext *avctx, void *frame, } if ((ret = av_frame_ref(frame, s->s.refs[ref].f)) < 0) return ret; - ((AVFrame *)frame)->pts = pkt->pts; - ((AVFrame *)frame)->pkt_dts = pkt->dts; + frame->pts = pkt->pts; + frame->pkt_dts = pkt->dts; for (i = 0; i < 8; i++) { if (s->next_refs[i].f->buf[0]) - ff_thread_release_buffer(avctx, &s->next_refs[i]); + ff_thread_release_ext_buffer(avctx, &s->next_refs[i]); if (s->s.refs[i].f->buf[0] && (ret = ff_thread_ref_frame(&s->next_refs[i], &s->s.refs[i])) < 0) return ret; @@ -1610,7 +1614,7 @@ static int vp9_decode_frame(AVCodecContext *avctx, void *frame, // ref frame setup for (i = 0; i < 8; i++) { if (s->next_refs[i].f->buf[0]) - ff_thread_release_buffer(avctx, &s->next_refs[i]); + ff_thread_release_ext_buffer(avctx, &s->next_refs[i]); if (s->s.h.refreshrefmask & (1 << i)) { ret = ff_thread_ref_frame(&s->next_refs[i], &s->s.frames[CUR_FRAME].tf); } else if (s->s.refs[i].f->buf[0]) { @@ -1759,7 +1763,7 @@ finish: // ref frame setup for (i = 0; i < 8; i++) { if (s->s.refs[i].f->buf[0]) - ff_thread_release_buffer(avctx, &s->s.refs[i]); + ff_thread_release_ext_buffer(avctx, &s->s.refs[i]); if (s->next_refs[i].f->buf[0] && (ret = ff_thread_ref_frame(&s->s.refs[i], &s->next_refs[i])) < 0) return ret; @@ -1782,7 +1786,7 @@ static void vp9_decode_flush(AVCodecContext *avctx) for (i = 0; i < 3; i++) vp9_frame_unref(avctx, &s->s.frames[i]); for (i = 0; i < 8; i++) - ff_thread_release_buffer(avctx, &s->s.refs[i]); + ff_thread_release_ext_buffer(avctx, &s->s.refs[i]); } static av_cold int vp9_decode_init(AVCodecContext *avctx) @@ -1831,7 +1835,7 @@ static int vp9_decode_update_thread_context(AVCodecContext *dst, const AVCodecCo } for (i = 0; i < 8; i++) { if (s->s.refs[i].f->buf[0]) - ff_thread_release_buffer(dst, &s->s.refs[i]); + ff_thread_release_ext_buffer(dst, &s->s.refs[i]); if (ssrc->next_refs[i].f->buf[0]) { if ((ret = ff_thread_ref_frame(&s->s.refs[i], &ssrc->next_refs[i])) < 0) return ret; @@ -1862,22 +1866,22 @@ static int vp9_decode_update_thread_context(AVCodecContext *dst, const AVCodecCo } #endif -const AVCodec ff_vp9_decoder = { - .name = "vp9", - .long_name = NULL_IF_CONFIG_SMALL("Google VP9"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_VP9, +const FFCodec ff_vp9_decoder = { + .p.name = "vp9", + .p.long_name = NULL_IF_CONFIG_SMALL("Google VP9"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_VP9, .priv_data_size = sizeof(VP9Context), .init = vp9_decode_init, .close = vp9_decode_free, - .decode = vp9_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_SLICE_THREADS, + FF_CODEC_DECODE_CB(vp9_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_SLICE_THREADS, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_SLICE_THREAD_HAS_MF | FF_CODEC_CAP_ALLOCATE_PROGRESS, .flush = vp9_decode_flush, .update_thread_context = ONLY_IF_THREADS_ENABLED(vp9_decode_update_thread_context), - .profiles = NULL_IF_CONFIG_SMALL(ff_vp9_profiles), + .p.profiles = NULL_IF_CONFIG_SMALL(ff_vp9_profiles), .bsfs = "vp9_superframe_split", .hw_configs = (const AVCodecHWConfigInternal *const []) { #if CONFIG_VP9_DXVA2_HWACCEL diff --git a/libavcodec/vp9_metadata_bsf.c b/libavcodec/vp9_metadata_bsf.c index d904a0088..40d1b21c6 100644 --- a/libavcodec/vp9_metadata_bsf.c +++ b/libavcodec/vp9_metadata_bsf.c @@ -16,11 +16,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/avstring.h" -#include "libavutil/common.h" +#include "libavutil/log.h" #include "libavutil/opt.h" #include "bsf.h" +#include "bsf_internal.h" #include "cbs.h" #include "cbs_bsf.h" #include "cbs_vp9.h" @@ -135,12 +135,12 @@ static const enum AVCodecID vp9_metadata_codec_ids[] = { AV_CODEC_ID_VP9, AV_CODEC_ID_NONE, }; -const AVBitStreamFilter ff_vp9_metadata_bsf = { - .name = "vp9_metadata", +const FFBitStreamFilter ff_vp9_metadata_bsf = { + .p.name = "vp9_metadata", + .p.codec_ids = vp9_metadata_codec_ids, + .p.priv_class = &vp9_metadata_class, .priv_data_size = sizeof(VP9MetadataContext), - .priv_class = &vp9_metadata_class, .init = &vp9_metadata_init, .close = &ff_cbs_bsf_generic_close, .filter = &ff_cbs_bsf_generic_filter, - .codec_ids = vp9_metadata_codec_ids, }; diff --git a/libavcodec/vp9_raw_reorder_bsf.c b/libavcodec/vp9_raw_reorder_bsf.c index 1608360fe..d36093316 100644 --- a/libavcodec/vp9_raw_reorder_bsf.c +++ b/libavcodec/vp9_raw_reorder_bsf.c @@ -390,34 +390,25 @@ fail: return err; } -static void vp9_raw_reorder_flush(AVBSFContext *bsf) +static av_cold void vp9_raw_reorder_flush_close(AVBSFContext *bsf) { VP9RawReorderContext *ctx = bsf->priv_data; for (int s = 0; s < FRAME_SLOTS; s++) vp9_raw_reorder_clear_slot(ctx, s); - ctx->next_frame = NULL; + vp9_raw_reorder_frame_free(&ctx->next_frame); ctx->sequence = 0; } -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", +const FFBitStreamFilter ff_vp9_raw_reorder_bsf = { + .p.name = "vp9_raw_reorder", + .p.codec_ids = vp9_raw_reorder_codec_ids, .priv_data_size = sizeof(VP9RawReorderContext), - .close = &vp9_raw_reorder_close, - .flush = &vp9_raw_reorder_flush, .filter = &vp9_raw_reorder_filter, - .codec_ids = vp9_raw_reorder_codec_ids, + .flush = &vp9_raw_reorder_flush_close, + .close = &vp9_raw_reorder_flush_close, }; diff --git a/libavcodec/vp9_superframe_bsf.c b/libavcodec/vp9_superframe_bsf.c index df9b97fa3..a0978c7ef 100644 --- a/libavcodec/vp9_superframe_bsf.c +++ b/libavcodec/vp9_superframe_bsf.c @@ -220,12 +220,12 @@ static const enum AVCodecID codec_ids[] = { AV_CODEC_ID_VP9, AV_CODEC_ID_NONE, }; -const AVBitStreamFilter ff_vp9_superframe_bsf = { - .name = "vp9_superframe", +const FFBitStreamFilter ff_vp9_superframe_bsf = { + .p.name = "vp9_superframe", + .p.codec_ids = codec_ids, .priv_data_size = sizeof(VP9BSFContext), .filter = vp9_superframe_filter, .init = vp9_superframe_init, .flush = vp9_superframe_flush, .close = vp9_superframe_close, - .codec_ids = codec_ids, }; diff --git a/libavcodec/vp9_superframe_split_bsf.c b/libavcodec/vp9_superframe_split_bsf.c index c9cf21b54..cddd48119 100644 --- a/libavcodec/vp9_superframe_split_bsf.c +++ b/libavcodec/vp9_superframe_split_bsf.c @@ -159,12 +159,12 @@ static void vp9_superframe_split_uninit(AVBSFContext *ctx) av_packet_free(&s->buffer_pkt); } -const AVBitStreamFilter ff_vp9_superframe_split_bsf = { - .name = "vp9_superframe_split", +const FFBitStreamFilter ff_vp9_superframe_split_bsf = { + .p.name = "vp9_superframe_split", + .p.codec_ids = (const enum AVCodecID []){ AV_CODEC_ID_VP9, AV_CODEC_ID_NONE }, .priv_data_size = sizeof(VP9SFSplitContext), .init = vp9_superframe_split_init, .flush = vp9_superframe_split_flush, .close = vp9_superframe_split_uninit, .filter = vp9_superframe_split_filter, - .codec_ids = (const enum AVCodecID []){ AV_CODEC_ID_VP9, AV_CODEC_ID_NONE }, }; diff --git a/libavcodec/vp9block.c b/libavcodec/vp9block.c index 5e6cded2b..5fdda6354 100644 --- a/libavcodec/vp9block.c +++ b/libavcodec/vp9block.c @@ -23,6 +23,7 @@ #include "libavutil/avassert.h" +#include "threadframe.h" #include "vp56.h" #include "vp9.h" #include "vp9data.h" diff --git a/libavcodec/vp9dsp.c b/libavcodec/vp9dsp.c index 82bfe394d..d8ddf74d4 100644 --- a/libavcodec/vp9dsp.c +++ b/libavcodec/vp9dsp.c @@ -21,8 +21,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config.h" + +#include "libavutil/attributes.h" #include "libavutil/avassert.h" -#include "libavutil/common.h" #include "libavutil/mem_internal.h" #include "vp9dsp.h" @@ -94,9 +96,15 @@ av_cold void ff_vp9dsp_init(VP9DSPContext *dsp, int bpp, int bitexact) ff_vp9dsp_init_12(dsp); } - if (ARCH_AARCH64) ff_vp9dsp_init_aarch64(dsp, bpp); - if (ARCH_ARM) ff_vp9dsp_init_arm(dsp, bpp); - if (ARCH_X86) ff_vp9dsp_init_x86(dsp, bpp, bitexact); - if (ARCH_MIPS) ff_vp9dsp_init_mips(dsp, bpp); - if (ARCH_LOONGARCH) ff_vp9dsp_init_loongarch(dsp, bpp); +#if ARCH_AARCH64 + ff_vp9dsp_init_aarch64(dsp, bpp); +#elif ARCH_ARM + ff_vp9dsp_init_arm(dsp, bpp); +#elif ARCH_X86 + ff_vp9dsp_init_x86(dsp, bpp, bitexact); +#elif ARCH_MIPS + ff_vp9dsp_init_mips(dsp, bpp); +#elif ARCH_LOONGARCH + ff_vp9dsp_init_loongarch(dsp, bpp); +#endif } diff --git a/libavcodec/vp9mvs.c b/libavcodec/vp9mvs.c index 88db1c341..ddce9b6c8 100644 --- a/libavcodec/vp9mvs.c +++ b/libavcodec/vp9mvs.c @@ -21,7 +21,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "internal.h" +#include "threadframe.h" #include "vp56.h" #include "vp9.h" #include "vp9data.h" diff --git a/libavcodec/vp9recon.c b/libavcodec/vp9recon.c index 503091e54..bfafde8c9 100644 --- a/libavcodec/vp9recon.c +++ b/libavcodec/vp9recon.c @@ -24,6 +24,7 @@ #include "libavutil/avassert.h" #include "libavutil/mem_internal.h" +#include "threadframe.h" #include "videodsp.h" #include "vp9data.h" #include "vp9dec.h" diff --git a/libavcodec/vp9shared.h b/libavcodec/vp9shared.h index 54726df74..ebaa11d2c 100644 --- a/libavcodec/vp9shared.h +++ b/libavcodec/vp9shared.h @@ -28,7 +28,7 @@ #include #include "vp9.h" -#include "thread.h" +#include "threadframe.h" #include "vp56.h" enum BlockPartition { diff --git a/libavcodec/vqavideo.c b/libavcodec/vqavideo.c index 1d97855e6..62f930ed9 100644 --- a/libavcodec/vqavideo.c +++ b/libavcodec/vqavideo.c @@ -77,6 +77,7 @@ #include "libavutil/imgutils.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" #define PALETTE_COUNT 256 @@ -793,9 +794,8 @@ static int vqa_decode_frame_hicolor(VqaContext *s, AVFrame *frame) return 0; } -static int vqa_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int vqa_decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *avpkt) { VqaContext *s = avctx->priv_data; int res; @@ -820,7 +820,7 @@ static int vqa_decode_frame(AVCodecContext *avctx, return AVERROR_BUG; } - if ((res = av_frame_ref(data, s->frame)) < 0) + if ((res = av_frame_ref(rframe, s->frame)) < 0) return res; *got_frame = 1; @@ -841,21 +841,21 @@ static av_cold int vqa_decode_end(AVCodecContext *avctx) return 0; } -static const AVCodecDefault vqa_defaults[] = { +static const FFCodecDefault vqa_defaults[] = { { "max_pixels", "640*480" }, { NULL }, }; -const AVCodec ff_vqa_decoder = { - .name = "vqavideo", - .long_name = NULL_IF_CONFIG_SMALL("Westwood Studios VQA (Vector Quantized Animation) video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_WS_VQA, +const FFCodec ff_vqa_decoder = { + .p.name = "vqavideo", + .p.long_name = NULL_IF_CONFIG_SMALL("Westwood Studios VQA (Vector Quantized Animation) video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_WS_VQA, .priv_data_size = sizeof(VqaContext), .init = vqa_decode_init, .close = vqa_decode_end, - .decode = vqa_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(vqa_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .defaults = vqa_defaults, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/wavpack.c b/libavcodec/wavpack.c index 6b2ec19bf..8bfbb654e 100644 --- a/libavcodec/wavpack.c +++ b/libavcodec/wavpack.c @@ -26,9 +26,10 @@ #define BITSTREAM_READER_LE #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "get_bits.h" -#include "internal.h" #include "thread.h" +#include "threadframe.h" #include "unary.h" #include "wavpack.h" #include "dsd.h" @@ -1018,7 +1019,7 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src) if (dst == src) return 0; - ff_thread_release_buffer(dst, &fdst->curr_frame); + ff_thread_release_ext_buffer(dst, &fdst->curr_frame); if (fsrc->curr_frame.f->data[0]) { if ((ret = ff_thread_ref_frame(&fdst->curr_frame, &fsrc->curr_frame)) < 0) return ret; @@ -1065,10 +1066,10 @@ static av_cold int wavpack_decode_end(AVCodecContext *avctx) av_freep(&s->fdec[i]); s->fdec_num = 0; - ff_thread_release_buffer(avctx, &s->curr_frame); + ff_thread_release_ext_buffer(avctx, &s->curr_frame); av_frame_free(&s->curr_frame.f); - ff_thread_release_buffer(avctx, &s->prev_frame); + ff_thread_release_ext_buffer(avctx, &s->prev_frame); av_frame_free(&s->prev_frame.f); av_buffer_unref(&s->dsd_ref); @@ -1302,14 +1303,16 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no, av_log(avctx, AV_LOG_ERROR, "Invalid INT32INFO, extra_bits = %d (> 30)\n", val[0]); continue; - } else if (val[0]) { + } else { s->extra_bits = val[0]; - } else if (val[1]) { + } + if (val[1]) s->shift = val[1]; - } else if (val[2]) { + if (val[2]) { s->and = s->or = 1; s->shift = val[2]; - } else if (val[3]) { + } + if (val[3]) { s->and = 1; s->shift = val[3]; } @@ -1412,25 +1415,23 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no, size = bytestream2_get_byte(&gb); chan |= (bytestream2_get_byte(&gb) & 0xF) << 8; chan += 1; - if (avctx->channels != chan) + if (avctx->ch_layout.nb_channels != chan) av_log(avctx, AV_LOG_WARNING, "%i channels signalled" - " instead of %i.\n", chan, avctx->channels); + " instead of %i.\n", chan, avctx->ch_layout.nb_channels); chmask = bytestream2_get_le24(&gb); break; case 5: size = bytestream2_get_byte(&gb); chan |= (bytestream2_get_byte(&gb) & 0xF) << 8; chan += 1; - if (avctx->channels != chan) + if (avctx->ch_layout.nb_channels != chan) av_log(avctx, AV_LOG_WARNING, "%i channels signalled" - " instead of %i.\n", chan, avctx->channels); + " instead of %i.\n", chan, avctx->ch_layout.nb_channels); chmask = bytestream2_get_le32(&gb); break; default: av_log(avctx, AV_LOG_ERROR, "Invalid channel info size %d\n", size); - chan = avctx->channels; - chmask = avctx->channel_layout; } break; case WP_ID_SAMPLE_RATE: @@ -1494,8 +1495,7 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no, } if (!wc->ch_offset) { - int new_channels = avctx->channels; - uint64_t new_chmask = avctx->channel_layout; + AVChannelLayout new_ch_layout = { 0 }; int new_samplerate; int sr = (s->frame_flags >> 23) & 0xf; if (sr == 0xf) { @@ -1512,53 +1512,55 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no, new_samplerate *= rate_x; if (multiblock) { - if (chan) - new_channels = chan; - if (chmask) - new_chmask = chmask; + if (chmask) { + av_channel_layout_from_mask(&new_ch_layout, chmask); + if (chan && new_ch_layout.nb_channels != chan) { + av_log(avctx, AV_LOG_ERROR, "Channel mask does not match the channel count\n"); + return AVERROR_INVALIDDATA; + } + } else { + ret = av_channel_layout_copy(&new_ch_layout, &avctx->ch_layout); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Error copying channel layout\n"); + return ret; + } + } } else { - new_channels = s->stereo ? 2 : 1; - new_chmask = s->stereo ? AV_CH_LAYOUT_STEREO : - AV_CH_LAYOUT_MONO; - } - - if (new_chmask && - av_get_channel_layout_nb_channels(new_chmask) != new_channels) { - av_log(avctx, AV_LOG_ERROR, "Channel mask does not match the channel count\n"); - return AVERROR_INVALIDDATA; + av_channel_layout_default(&new_ch_layout, s->stereo + 1); } /* clear DSD state if stream properties change */ - if (new_channels != wc->dsd_channels || - new_chmask != avctx->channel_layout || + if (new_ch_layout.nb_channels != wc->dsd_channels || + av_channel_layout_compare(&new_ch_layout, &avctx->ch_layout) || new_samplerate != avctx->sample_rate || !!got_dsd != !!wc->dsdctx) { - ret = wv_dsd_reset(wc, got_dsd ? new_channels : 0); + ret = wv_dsd_reset(wc, got_dsd ? new_ch_layout.nb_channels : 0); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Error reinitializing the DSD context\n"); return ret; } - ff_thread_release_buffer(avctx, &wc->curr_frame); + ff_thread_release_ext_buffer(avctx, &wc->curr_frame); } - avctx->channels = new_channels; - avctx->channel_layout = new_chmask; + av_channel_layout_copy(&avctx->ch_layout, &new_ch_layout); avctx->sample_rate = new_samplerate; avctx->sample_fmt = sample_fmt; avctx->bits_per_raw_sample = orig_bpp; - ff_thread_release_buffer(avctx, &wc->prev_frame); + ff_thread_release_ext_buffer(avctx, &wc->prev_frame); FFSWAP(ThreadFrame, wc->curr_frame, wc->prev_frame); /* get output buffer */ wc->curr_frame.f->nb_samples = s->samples; - if ((ret = ff_thread_get_buffer(avctx, &wc->curr_frame, AV_GET_BUFFER_FLAG_REF)) < 0) + ret = ff_thread_get_ext_buffer(avctx, &wc->curr_frame, + AV_GET_BUFFER_FLAG_REF); + if (ret < 0) return ret; wc->frame = wc->curr_frame.f; ff_thread_finish_setup(avctx); } - if (wc->ch_offset + s->stereo >= avctx->channels) { + if (wc->ch_offset + s->stereo >= avctx->ch_layout.nb_channels) { av_log(avctx, AV_LOG_WARNING, "Too many channels coded in a packet.\n"); return ((avctx->err_recognition & AV_EF_EXPLODE) || !wc->ch_offset) ? AVERROR_INVALIDDATA : 0; } @@ -1624,7 +1626,7 @@ static int dsd_channel(AVCodecContext *avctx, void *frmptr, int jobnr, int threa return 0; } -static int wavpack_decode_frame(AVCodecContext *avctx, void *data, +static int wavpack_decode_frame(AVCodecContext *avctx, AVFrame *rframe, int *got_frame_ptr, AVPacket *avpkt) { WavpackContext *s = avctx->priv_data; @@ -1668,21 +1670,21 @@ static int wavpack_decode_frame(AVCodecContext *avctx, void *data, buf_size -= frame_size; } - if (s->ch_offset != avctx->channels) { + if (s->ch_offset != avctx->ch_layout.nb_channels) { av_log(avctx, AV_LOG_ERROR, "Not enough channels coded in a packet.\n"); ret = AVERROR_INVALIDDATA; goto error; } ff_thread_await_progress(&s->prev_frame, INT_MAX, 0); - ff_thread_release_buffer(avctx, &s->prev_frame); + ff_thread_release_ext_buffer(avctx, &s->prev_frame); if (s->modulation == MODULATION_DSD) - avctx->execute2(avctx, dsd_channel, s->frame, NULL, avctx->channels); + avctx->execute2(avctx, dsd_channel, s->frame, NULL, avctx->ch_layout.nb_channels); ff_thread_report_progress(&s->curr_frame, INT_MAX, 0); - if ((ret = av_frame_ref(data, s->frame)) < 0) + if ((ret = av_frame_ref(rframe, s->frame)) < 0) return ret; *got_frame_ptr = 1; @@ -1692,25 +1694,25 @@ static int wavpack_decode_frame(AVCodecContext *avctx, void *data, error: if (s->frame) { ff_thread_await_progress(&s->prev_frame, INT_MAX, 0); - ff_thread_release_buffer(avctx, &s->prev_frame); + ff_thread_release_ext_buffer(avctx, &s->prev_frame); ff_thread_report_progress(&s->curr_frame, INT_MAX, 0); } return ret; } -const AVCodec ff_wavpack_decoder = { - .name = "wavpack", - .long_name = NULL_IF_CONFIG_SMALL("WavPack"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_WAVPACK, +const FFCodec ff_wavpack_decoder = { + .p.name = "wavpack", + .p.long_name = NULL_IF_CONFIG_SMALL("WavPack"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_WAVPACK, .priv_data_size = sizeof(WavpackContext), .init = wavpack_decode_init, .close = wavpack_decode_end, - .decode = wavpack_decode_frame, + FF_CODEC_DECODE_CB(wavpack_decode_frame), .flush = wavpack_decode_flush, .update_thread_context = ONLY_IF_THREADS_ENABLED(update_thread_context), - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_CHANNEL_CONF, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_ALLOCATE_PROGRESS, diff --git a/libavcodec/wavpack.h b/libavcodec/wavpack.h index 7e7dfce2b..9f62f8406 100644 --- a/libavcodec/wavpack.h +++ b/libavcodec/wavpack.h @@ -22,7 +22,10 @@ #ifndef AVCODEC_WAVPACK_H #define AVCODEC_WAVPACK_H -#include "libavutil/common.h" +#include +#include +#include "libavutil/attributes.h" +#include "libavutil/intmath.h" #define MAX_TERMS 16 #define MAX_TERM 8 diff --git a/libavcodec/wavpackenc.c b/libavcodec/wavpackenc.c index dc4f4e303..1f95768c0 100644 --- a/libavcodec/wavpackenc.c +++ b/libavcodec/wavpackenc.c @@ -24,6 +24,7 @@ #include "libavutil/intreadwrite.h" #include "libavutil/opt.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" #include "internal.h" #include "put_bits.h" @@ -130,8 +131,8 @@ static av_cold int wavpack_encode_init(AVCodecContext *avctx) s->avctx = avctx; - if (avctx->channels > 255) { - av_log(avctx, AV_LOG_ERROR, "Invalid channel count: %d\n", avctx->channels); + if (avctx->ch_layout.nb_channels > 255) { + av_log(avctx, AV_LOG_ERROR, "Invalid channel count: %d\n", avctx->ch_layout.nb_channels); return AVERROR(EINVAL); } @@ -142,10 +143,10 @@ static av_cold int wavpack_encode_init(AVCodecContext *avctx) else block_samples = avctx->sample_rate; - while (block_samples * avctx->channels > WV_MAX_SAMPLES) + while (block_samples * avctx->ch_layout.nb_channels > WV_MAX_SAMPLES) block_samples /= 2; - while (block_samples * avctx->channels < 40000) + while (block_samples * avctx->ch_layout.nb_channels < 40000) block_samples *= 2; avctx->frame_size = block_samples; } else if (avctx->frame_size && (avctx->frame_size < 128 || @@ -2572,7 +2573,7 @@ static int wavpack_encode_block(WavPackEncodeContext *s, s->ch_offset += 1 + !(s->flags & WV_MONO); - if (s->ch_offset == s->avctx->channels) + if (s->ch_offset == s->avctx->ch_layout.nb_channels) s->flags |= WV_FINAL_BLOCK; bytestream2_init_writer(&pb, out, out_size); @@ -2587,11 +2588,12 @@ static int wavpack_encode_block(WavPackEncodeContext *s, bytestream2_put_le32(&pb, crc); if (s->flags & WV_INITIAL_BLOCK && - s->avctx->channel_layout != AV_CH_LAYOUT_MONO && - s->avctx->channel_layout != AV_CH_LAYOUT_STEREO) { + s->avctx->ch_layout.order == AV_CHANNEL_ORDER_NATIVE && + s->avctx->ch_layout.u.mask != AV_CH_LAYOUT_MONO && + s->avctx->ch_layout.u.mask != AV_CH_LAYOUT_STEREO) { put_metadata_block(&pb, WP_ID_CHANINFO, 5); - bytestream2_put_byte(&pb, s->avctx->channels); - bytestream2_put_le32(&pb, s->avctx->channel_layout); + bytestream2_put_byte(&pb, s->avctx->ch_layout.nb_channels); + bytestream2_put_le32(&pb, s->avctx->ch_layout.u.mask); bytestream2_put_byte(&pb, 0); } @@ -2862,20 +2864,20 @@ static int wavpack_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, sizeof(int32_t) * s->block_samples); if (!s->samples[0]) return AVERROR(ENOMEM); - if (avctx->channels > 1) { + if (avctx->ch_layout.nb_channels > 1) { av_fast_padded_malloc(&s->samples[1], &s->samples_size[1], sizeof(int32_t) * s->block_samples); if (!s->samples[1]) return AVERROR(ENOMEM); } - buf_size = s->block_samples * avctx->channels * 8 - + 200 * avctx->channels /* for headers */; + buf_size = s->block_samples * avctx->ch_layout.nb_channels * 8 + + 200 * avctx->ch_layout.nb_channels /* for headers */; if ((ret = ff_alloc_packet(avctx, avpkt, buf_size)) < 0) return ret; buf = avpkt->data; - for (s->ch_offset = 0; s->ch_offset < avctx->channels;) { + for (s->ch_offset = 0; s->ch_offset < avctx->ch_layout.nb_channels;) { set_samplerate(s); switch (s->avctx->sample_fmt) { @@ -2885,7 +2887,7 @@ static int wavpack_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, } fill_buffer(s, frame->extended_data[s->ch_offset], s->samples[0], s->block_samples); - if (avctx->channels - s->ch_offset == 1) { + if (avctx->ch_layout.nb_channels - s->ch_offset == 1) { s->flags |= WV_MONO; } else { s->flags |= WV_CROSS_DECORR; @@ -2959,18 +2961,18 @@ static const AVClass wavpack_encoder_class = { .version = LIBAVUTIL_VERSION_INT, }; -const AVCodec ff_wavpack_encoder = { - .name = "wavpack", - .long_name = NULL_IF_CONFIG_SMALL("WavPack"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_WAVPACK, +const FFCodec ff_wavpack_encoder = { + .p.name = "wavpack", + .p.long_name = NULL_IF_CONFIG_SMALL("WavPack"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_WAVPACK, .priv_data_size = sizeof(WavPackEncodeContext), - .priv_class = &wavpack_encoder_class, + .p.priv_class = &wavpack_encoder_class, .init = wavpack_encode_init, - .encode2 = wavpack_encode_frame, + FF_CODEC_ENCODE_CB(wavpack_encode_frame), .close = wavpack_encode_close, - .capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME, - .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_U8P, + .p.capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME, + .p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_U8P, AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_FLTP, diff --git a/libavcodec/wavpackenc.h b/libavcodec/wavpackenc.h index 11914337c..b6d12e8a5 100644 --- a/libavcodec/wavpackenc.h +++ b/libavcodec/wavpackenc.h @@ -21,6 +21,8 @@ #ifndef AVCODEC_WAVPACKENC_H #define AVCODEC_WAVPACKENC_H +#include +#include "libavutil/macros.h" #include "wavpack.h" typedef struct WavPackDecorrSpec { diff --git a/libavcodec/wcmv.c b/libavcodec/wcmv.c index 04c597e76..ac135f685 100644 --- a/libavcodec/wcmv.c +++ b/libavcodec/wcmv.c @@ -28,28 +28,29 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" +#include "zlib_wrapper.h" #include typedef struct WCMVContext { int bpp; - z_stream zstream; + FFZStream zstream; AVFrame *prev_frame; uint8_t block_data[65536*8]; } WCMVContext; -static int decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { WCMVContext *s = avctx->priv_data; - AVFrame *frame = data; + z_stream *const zstream = &s->zstream.zstream; int skip, blocks, zret, ret, intra = 0, flags = 0, bpp = s->bpp; GetByteContext gb; uint8_t *dst; - ret = inflateReset(&s->zstream); + ret = inflateReset(zstream); if (ret != Z_OK) { av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", ret); return AVERROR_EXTERNAL; @@ -78,19 +79,19 @@ static int decode_frame(AVCodecContext *avctx, if (size > avpkt->size - skip) return AVERROR_INVALIDDATA; - s->zstream.next_in = avpkt->data + skip; - s->zstream.avail_in = size; - s->zstream.next_out = s->block_data; - s->zstream.avail_out = sizeof(s->block_data); + zstream->next_in = avpkt->data + skip; + zstream->avail_in = size; + zstream->next_out = s->block_data; + zstream->avail_out = sizeof(s->block_data); - zret = inflate(&s->zstream, Z_FINISH); + zret = inflate(zstream, Z_FINISH); if (zret != Z_STREAM_END) { av_log(avctx, AV_LOG_ERROR, "Inflate failed with return code: %d.\n", zret); return AVERROR_INVALIDDATA; } - ret = inflateReset(&s->zstream); + ret = inflateReset(zstream); if (ret != Z_OK) { av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", ret); return AVERROR_EXTERNAL; @@ -119,8 +120,8 @@ static int decode_frame(AVCodecContext *avctx, skip = bytestream2_tell(&gb); - s->zstream.next_in = avpkt->data + skip; - s->zstream.avail_in = avpkt->size - skip; + zstream->next_in = avpkt->data + skip; + zstream->avail_in = avpkt->size - skip; bytestream2_init(&gb, s->block_data, blocks * 8); } else if (blocks) { @@ -148,8 +149,8 @@ static int decode_frame(AVCodecContext *avctx, skip = bytestream2_tell(&gb); - s->zstream.next_in = avpkt->data + skip; - s->zstream.avail_in = avpkt->size - skip; + zstream->next_in = avpkt->data + skip; + zstream->avail_in = avpkt->size - skip; bytestream2_seek(&gb, 2, SEEK_SET); } @@ -182,10 +183,10 @@ static int decode_frame(AVCodecContext *avctx, dst = s->prev_frame->data[0] + (avctx->height - y - 1) * s->prev_frame->linesize[0] + x * bpp; for (int i = 0; i < h; i++) { - s->zstream.next_out = dst; - s->zstream.avail_out = w * bpp; + zstream->next_out = dst; + zstream->avail_out = w * bpp; - zret = inflate(&s->zstream, Z_SYNC_FLUSH); + zret = inflate(zstream, Z_SYNC_FLUSH); if (zret != Z_OK && zret != Z_STREAM_END) { av_log(avctx, AV_LOG_ERROR, "Inflate failed with return code: %d.\n", zret); @@ -210,7 +211,6 @@ static int decode_frame(AVCodecContext *avctx, static av_cold int decode_init(AVCodecContext *avctx) { WCMVContext *s = avctx->priv_data; - int zret; switch (avctx->bits_per_coded_sample) { case 16: avctx->pix_fmt = AV_PIX_FMT_RGB565LE; break; @@ -223,20 +223,11 @@ static av_cold int decode_init(AVCodecContext *avctx) s->bpp = avctx->bits_per_coded_sample >> 3; - s->zstream.zalloc = Z_NULL; - s->zstream.zfree = Z_NULL; - s->zstream.opaque = Z_NULL; - zret = inflateInit(&s->zstream); - if (zret != Z_OK) { - av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret); - return AVERROR_EXTERNAL; - } - s->prev_frame = av_frame_alloc(); if (!s->prev_frame) return AVERROR(ENOMEM); - return 0; + return ff_inflate_init(&s->zstream, avctx); } static av_cold int decode_close(AVCodecContext *avctx) @@ -244,21 +235,21 @@ static av_cold int decode_close(AVCodecContext *avctx) WCMVContext *s = avctx->priv_data; av_frame_free(&s->prev_frame); - inflateEnd(&s->zstream); + ff_inflate_end(&s->zstream); return 0; } -const AVCodec ff_wcmv_decoder = { - .name = "wcmv", - .long_name = NULL_IF_CONFIG_SMALL("WinCAM Motion Video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_WCMV, +const FFCodec ff_wcmv_decoder = { + .p.name = "wcmv", + .p.long_name = NULL_IF_CONFIG_SMALL("WinCAM Motion Video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_WCMV, .priv_data_size = sizeof(WCMVContext), .init = decode_init, .close = decode_close, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/webp.c b/libavcodec/webp.c index d5a81fd52..e57a5a291 100644 --- a/libavcodec/webp.c +++ b/libavcodec/webp.c @@ -45,10 +45,12 @@ #define BITSTREAM_READER_LE #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "exif.h" #include "get_bits.h" #include "internal.h" #include "thread.h" +#include "tiff_common.h" #include "vp8.h" #define VP8X_FLAG_ANIMATION 0x02 @@ -198,7 +200,7 @@ typedef struct WebPContext { int has_alpha; /* has a separate alpha chunk */ enum AlphaCompression alpha_compression; /* compression type for alpha chunk */ enum AlphaFilter alpha_filter; /* filtering method for alpha chunk */ - uint8_t *alpha_data; /* alpha chunk data */ + const uint8_t *alpha_data; /* alpha chunk data */ int alpha_data_size; /* alpha chunk data size */ int has_exif; /* set after an EXIF chunk has been processed */ int has_iccp; /* set after an ICCP chunk has been processed */ @@ -568,8 +570,7 @@ static int decode_entropy_coded_image(WebPContext *s, enum ImageRole role, img->frame->height = h; if (role == IMAGE_ROLE_ARGB && !img->is_alpha_primary) { - ThreadFrame pt = { .f = img->frame }; - ret = ff_thread_get_buffer(s->avctx, &pt, 0); + ret = ff_thread_get_buffer(s->avctx, img->frame, 0); } else ret = av_frame_get_buffer(img->frame, 1); if (ret < 0) @@ -1083,7 +1084,7 @@ static void update_canvas_size(AVCodecContext *avctx, int w, int h) } static int vp8_lossless_decode_frame(AVCodecContext *avctx, AVFrame *p, - int *got_frame, uint8_t *data_start, + int *got_frame, const uint8_t *data_start, unsigned int data_size, int is_alpha_chunk) { WebPContext *s = avctx->priv_data; @@ -1239,7 +1240,7 @@ static void alpha_inverse_prediction(AVFrame *frame, enum AlphaFilter m) } static int vp8_lossy_decode_alpha(AVCodecContext *avctx, AVFrame *p, - uint8_t *data_start, + const uint8_t *data_start, unsigned int data_size) { WebPContext *s = avctx->priv_data; @@ -1333,10 +1334,9 @@ static int vp8_lossy_decode_frame(AVCodecContext *avctx, AVFrame *p, return ret; } -static int webp_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int webp_decode_frame(AVCodecContext *avctx, AVFrame *p, + int *got_frame, AVPacket *avpkt) { - AVFrame * const p = data; WebPContext *s = avctx->priv_data; GetByteContext gb; int ret; @@ -1479,7 +1479,7 @@ static int webp_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, goto exif_end; } - av_dict_copy(&((AVFrame *) data)->metadata, exif_metadata, 0); + av_dict_copy(&p->metadata, exif_metadata, 0); exif_end: av_dict_free(&exif_metadata); @@ -1555,15 +1555,15 @@ static av_cold int webp_decode_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_webp_decoder = { - .name = "webp", - .long_name = NULL_IF_CONFIG_SMALL("WebP image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_WEBP, +const FFCodec ff_webp_decoder = { + .p.name = "webp", + .p.long_name = NULL_IF_CONFIG_SMALL("WebP image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_WEBP, .priv_data_size = sizeof(WebPContext), .init = webp_decode_init, - .decode = webp_decode_frame, + FF_CODEC_DECODE_CB(webp_decode_frame), .close = webp_decode_close, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/webvttdec.c b/libavcodec/webvttdec.c index 0093f328f..fcf1062d8 100644 --- a/libavcodec/webvttdec.c +++ b/libavcodec/webvttdec.c @@ -27,7 +27,7 @@ #include "avcodec.h" #include "ass.h" -#include "internal.h" +#include "codec_internal.h" #include "libavutil/bprint.h" static const struct { @@ -80,11 +80,10 @@ static int webvtt_event_to_ass(AVBPrint *buf, const char *p) return 0; } -static int webvtt_decode_frame(AVCodecContext *avctx, - void *data, int *got_sub_ptr, AVPacket *avpkt) +static int webvtt_decode_frame(AVCodecContext *avctx, AVSubtitle *sub, + int *got_sub_ptr, const AVPacket *avpkt) { int ret = 0; - AVSubtitle *sub = data; const char *ptr = avpkt->data; FFASSDecoderContext *s = avctx->priv_data; AVBPrint buf; @@ -99,12 +98,12 @@ static int webvtt_decode_frame(AVCodecContext *avctx, return avpkt->size; } -const AVCodec ff_webvtt_decoder = { - .name = "webvtt", - .long_name = NULL_IF_CONFIG_SMALL("WebVTT subtitle"), - .type = AVMEDIA_TYPE_SUBTITLE, - .id = AV_CODEC_ID_WEBVTT, - .decode = webvtt_decode_frame, +const FFCodec ff_webvtt_decoder = { + .p.name = "webvtt", + .p.long_name = NULL_IF_CONFIG_SMALL("WebVTT subtitle"), + .p.type = AVMEDIA_TYPE_SUBTITLE, + .p.id = AV_CODEC_ID_WEBVTT, + FF_CODEC_DECODE_SUB_CB(webvtt_decode_frame), .init = ff_ass_subtitle_header_default, .flush = ff_ass_decoder_flush, .priv_data_size = sizeof(FFASSDecoderContext), diff --git a/libavcodec/webvttenc.c b/libavcodec/webvttenc.c index 89b49e42b..e433bb457 100644 --- a/libavcodec/webvttenc.c +++ b/libavcodec/webvttenc.c @@ -26,7 +26,7 @@ #include "libavutil/bprint.h" #include "ass_split.h" #include "ass.h" -#include "internal.h" +#include "codec_internal.h" #define WEBVTT_STACK_SIZE 64 typedef struct { @@ -211,14 +211,14 @@ static av_cold int webvtt_encode_init(AVCodecContext *avctx) return s->ass_ctx ? 0 : AVERROR_INVALIDDATA; } -const AVCodec ff_webvtt_encoder = { - .name = "webvtt", - .long_name = NULL_IF_CONFIG_SMALL("WebVTT subtitle"), - .type = AVMEDIA_TYPE_SUBTITLE, - .id = AV_CODEC_ID_WEBVTT, +const FFCodec ff_webvtt_encoder = { + .p.name = "webvtt", + .p.long_name = NULL_IF_CONFIG_SMALL("WebVTT subtitle"), + .p.type = AVMEDIA_TYPE_SUBTITLE, + .p.id = AV_CODEC_ID_WEBVTT, .priv_data_size = sizeof(WebVTTContext), .init = webvtt_encode_init, - .encode_sub = webvtt_encode_frame, + FF_CODEC_ENCODE_SUB_CB(webvtt_encode_frame), .close = webvtt_encode_close, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/wma.c b/libavcodec/wma.c index d9fda2dbf..ddf50d087 100644 --- a/libavcodec/wma.c +++ b/libavcodec/wma.c @@ -22,7 +22,6 @@ #include "libavutil/attributes.h" #include "avcodec.h" -#include "internal.h" #include "sinewin.h" #include "wma.h" #include "wma_common.h" @@ -79,6 +78,7 @@ static av_cold int init_coef_vlc(VLC *vlc, uint16_t **prun_table, av_cold int ff_wma_init(AVCodecContext *avctx, int flags2) { WMACodecContext *s = avctx->priv_data; + int channels = avctx->ch_layout.nb_channels; int i, ret; float bps1, high_freq; float bps; @@ -86,7 +86,7 @@ av_cold int ff_wma_init(AVCodecContext *avctx, int flags2) int coef_vlc_table; if (avctx->sample_rate <= 0 || avctx->sample_rate > 50000 || - avctx->channels <= 0 || avctx->channels > 2 || + channels <= 0 || channels > 2 || avctx->bit_rate <= 0) return -1; @@ -107,7 +107,7 @@ av_cold int ff_wma_init(AVCodecContext *avctx, int flags2) if (s->use_variable_block_len) { int nb_max, nb; nb = ((flags2 >> 3) & 3) + 1; - if ((avctx->bit_rate / avctx->channels) >= 32000) + if ((avctx->bit_rate / channels) >= 32000) nb += 2; nb_max = s->frame_len_bits - BLOCK_MIN_BITS; if (nb > nb_max) @@ -136,7 +136,7 @@ av_cold int ff_wma_init(AVCodecContext *avctx, int flags2) } bps = (float) avctx->bit_rate / - (float) (avctx->channels * avctx->sample_rate); + (float) (channels * avctx->sample_rate); s->byte_offset_bits = av_log2((int) (bps * s->frame_len / 8.0 + 0.5)) + 2; if (s->byte_offset_bits + 3 > MIN_CACHE_BITS) { av_log(avctx, AV_LOG_ERROR, "byte_offset_bits %d is too large\n", s->byte_offset_bits); @@ -146,7 +146,7 @@ av_cold int ff_wma_init(AVCodecContext *avctx, int flags2) /* compute high frequency value and choose if noise coding should * be activated */ bps1 = bps; - if (avctx->channels == 2) + if (channels == 2) bps1 = bps * 1.6; if (sample_rate1 == 44100) { if (bps1 >= 0.61) @@ -184,7 +184,7 @@ av_cold int ff_wma_init(AVCodecContext *avctx, int flags2) } ff_dlog(s->avctx, "flags2=0x%x\n", flags2); ff_dlog(s->avctx, "version=%d channels=%d sample_rate=%d bitrate=%"PRId64" block_align=%d\n", - s->version, avctx->channels, avctx->sample_rate, avctx->bit_rate, + s->version, channels, avctx->sample_rate, avctx->bit_rate, avctx->block_align); ff_dlog(s->avctx, "bps=%f bps1=%f high_freq=%f bitoffset=%d\n", bps, bps1, high_freq, s->byte_offset_bits); diff --git a/libavcodec/wmadec.c b/libavcodec/wmadec.c index 9955aaa7d..825bd6cdb 100644 --- a/libavcodec/wmadec.c +++ b/libavcodec/wmadec.c @@ -33,10 +33,13 @@ * should be 4 extra bytes for v1 data and 6 extra bytes for v2 data. */ +#include "config_components.h" + #include "libavutil/attributes.h" #include "libavutil/ffmath.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "wma.h" @@ -439,6 +442,7 @@ static void wma_window(WMACodecContext *s, float *out) */ static int wma_decode_block(WMACodecContext *s) { + int channels = s->avctx->ch_layout.nb_channels; int n, v, a, ch, bsize; int coef_nb_bits, total_gain; int nb_coefs[MAX_CHANNELS]; @@ -504,10 +508,10 @@ static int wma_decode_block(WMACodecContext *s) return -1; } - if (s->avctx->channels == 2) + if (channels == 2) s->ms_stereo = get_bits1(&s->gb); v = 0; - for (ch = 0; ch < s->avctx->channels; ch++) { + for (ch = 0; ch < channels; ch++) { a = get_bits1(&s->gb); s->channel_coded[ch] = a; v |= a; @@ -538,12 +542,12 @@ static int wma_decode_block(WMACodecContext *s) /* compute number of coefficients */ n = s->coefs_end[bsize] - s->coefs_start; - for (ch = 0; ch < s->avctx->channels; ch++) + for (ch = 0; ch < channels; ch++) nb_coefs[ch] = n; /* complex coding */ if (s->use_noise_coding) { - for (ch = 0; ch < s->avctx->channels; ch++) { + for (ch = 0; ch < channels; ch++) { if (s->channel_coded[ch]) { int i, n, a; n = s->exponent_high_sizes[bsize]; @@ -556,7 +560,7 @@ static int wma_decode_block(WMACodecContext *s) } } } - for (ch = 0; ch < s->avctx->channels; ch++) { + for (ch = 0; ch < channels; ch++) { if (s->channel_coded[ch]) { int i, n, val; @@ -579,7 +583,7 @@ static int wma_decode_block(WMACodecContext *s) /* exponents can be reused in short blocks. */ if ((s->block_len_bits == s->frame_len_bits) || get_bits1(&s->gb)) { - for (ch = 0; ch < s->avctx->channels; ch++) { + for (ch = 0; ch < channels; ch++) { if (s->channel_coded[ch]) { if (s->use_exp_vlc) { if (decode_exp_vlc(s, ch) < 0) @@ -593,13 +597,13 @@ static int wma_decode_block(WMACodecContext *s) } } - for (ch = 0; ch < s->avctx->channels; ch++) { + for (ch = 0; ch < channels; ch++) { if (s->channel_coded[ch] && !s->exponents_initialized[ch]) return AVERROR_INVALIDDATA; } /* parse spectral coefficients : just RLE encoding */ - for (ch = 0; ch < s->avctx->channels; ch++) { + for (ch = 0; ch < channels; ch++) { if (s->channel_coded[ch]) { int tindex; WMACoef *ptr = &s->coefs1[ch][0]; @@ -616,7 +620,7 @@ static int wma_decode_block(WMACodecContext *s) if (ret < 0) return ret; } - if (s->version == 1 && s->avctx->channels >= 2) + if (s->version == 1 && channels >= 2) align_get_bits(&s->gb); } @@ -629,7 +633,7 @@ static int wma_decode_block(WMACodecContext *s) } /* finally compute the MDCT coefficients */ - for (ch = 0; ch < s->avctx->channels; ch++) { + for (ch = 0; ch < channels; ch++) { if (s->channel_coded[ch]) { WMACoef *coefs1; float *coefs, *exponents, mult, mult1, noise; @@ -730,7 +734,7 @@ static int wma_decode_block(WMACodecContext *s) } #ifdef TRACE - for (ch = 0; ch < s->avctx->channels; ch++) { + for (ch = 0; ch < channels; ch++) { if (s->channel_coded[ch]) { dump_floats(s, "exponents", 3, s->exponents[ch], s->block_len); dump_floats(s, "coefs", 1, s->coefs[ch], s->block_len); @@ -754,7 +758,7 @@ static int wma_decode_block(WMACodecContext *s) next: mdct = &s->mdct_ctx[bsize]; - for (ch = 0; ch < s->avctx->channels; ch++) { + for (ch = 0; ch < channels; ch++) { int n4, index; n4 = s->block_len / 2; @@ -799,7 +803,7 @@ static int wma_decode_frame(WMACodecContext *s, float **samples, break; } - for (ch = 0; ch < s->avctx->channels; ch++) { + for (ch = 0; ch < s->avctx->ch_layout.nb_channels; ch++) { /* copy current block to output */ memcpy(samples[ch] + samples_offset, s->frame_out[ch], s->frame_len * sizeof(*s->frame_out[ch])); @@ -816,10 +820,9 @@ static int wma_decode_frame(WMACodecContext *s, float **samples, return 0; } -static int wma_decode_superframe(AVCodecContext *avctx, void *data, +static int wma_decode_superframe(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; WMACodecContext *s = avctx->priv_data; @@ -838,7 +841,7 @@ static int wma_decode_superframe(AVCodecContext *avctx, void *data, if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; - for (i = 0; i < s->avctx->channels; i++) + for (i = 0; i < s->avctx->ch_layout.nb_channels; i++) memcpy(frame->extended_data[i], &s->frame_out[i][0], frame->nb_samples * sizeof(s->frame_out[i][0])); @@ -970,9 +973,9 @@ static int wma_decode_superframe(AVCodecContext *avctx, void *data, samples_offset += s->frame_len; } - ff_dlog(s->avctx, "%d %d %d %d outbytes:%"PTRDIFF_SPECIFIER" eaten:%d\n", + ff_dlog(s->avctx, "%d %d %d %d eaten:%d\n", s->frame_len_bits, s->block_len_bits, s->frame_len, s->block_len, - (int8_t *) samples - (int8_t *) data, avctx->block_align); + avctx->block_align); *got_frame_ptr = 1; @@ -996,35 +999,35 @@ static av_cold void flush(AVCodecContext *avctx) } #if CONFIG_WMAV1_DECODER -const AVCodec ff_wmav1_decoder = { - .name = "wmav1", - .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 1"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_WMAV1, +const FFCodec ff_wmav1_decoder = { + .p.name = "wmav1", + .p.long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 1"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_WMAV1, .priv_data_size = sizeof(WMACodecContext), .init = wma_decode_init, .close = ff_wma_end, - .decode = wma_decode_superframe, + FF_CODEC_DECODE_CB(wma_decode_superframe), .flush = flush, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; #endif #if CONFIG_WMAV2_DECODER -const AVCodec ff_wmav2_decoder = { - .name = "wmav2", - .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 2"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_WMAV2, +const FFCodec ff_wmav2_decoder = { + .p.name = "wmav2", + .p.long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 2"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_WMAV2, .priv_data_size = sizeof(WMACodecContext), .init = wma_decode_init, .close = ff_wma_end, - .decode = wma_decode_superframe, + FF_CODEC_DECODE_CB(wma_decode_superframe), .flush = flush, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/wmaenc.c b/libavcodec/wmaenc.c index 66e3537cb..28a7546eb 100644 --- a/libavcodec/wmaenc.c +++ b/libavcodec/wmaenc.c @@ -19,10 +19,13 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/attributes.h" #include "libavutil/ffmath.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" #include "internal.h" #include "wma.h" @@ -38,10 +41,10 @@ static av_cold int encode_init(AVCodecContext *avctx) s->avctx = avctx; - if (avctx->channels > MAX_CHANNELS) { + if (avctx->ch_layout.nb_channels > MAX_CHANNELS) { av_log(avctx, AV_LOG_ERROR, "too many channels: got %i, need %i or fewer\n", - avctx->channels, MAX_CHANNELS); + avctx->ch_layout.nb_channels, MAX_CHANNELS); return AVERROR(EINVAL); } @@ -82,7 +85,7 @@ static av_cold int encode_init(AVCodecContext *avctx) s->use_exp_vlc = flags2 & 0x0001; s->use_bit_reservoir = flags2 & 0x0002; s->use_variable_block_len = flags2 & 0x0004; - if (avctx->channels == 2) + if (avctx->ch_layout.nb_channels == 2) s->ms_stereo = 1; if ((ret = ff_wma_init(avctx, flags2)) < 0) @@ -116,7 +119,7 @@ static int apply_window_and_mdct(AVCodecContext *avctx, const AVFrame *frame) int window_len = 1 << s->block_len_bits; float n = 2.0 * 32768.0 / window_len; - for (ch = 0; ch < avctx->channels; ch++) { + for (ch = 0; ch < avctx->ch_layout.nb_channels; ch++) { memcpy(s->output, s->frame_out[ch], window_len * sizeof(*s->output)); s->fdsp->vector_fmul_scalar(s->frame_out[ch], audio[ch], n, len); s->fdsp->vector_fmul_reverse(&s->output[window_len], s->frame_out[ch], @@ -186,6 +189,7 @@ static void encode_exp_vlc(WMACodecContext *s, int ch, const int *exp_param) static int encode_block(WMACodecContext *s, float (*src_coefs)[BLOCK_MAX_SIZE], int total_gain) { + int channels = s->avctx->ch_layout.nb_channels; int v, bsize, ch, coef_nb_bits, parse_exponents; float mdct_norm; int nb_coefs[MAX_CHANNELS]; @@ -213,7 +217,7 @@ static int encode_block(WMACodecContext *s, float (*src_coefs)[BLOCK_MAX_SIZE], // FIXME factor v = s->coefs_end[bsize] - s->coefs_start; - for (ch = 0; ch < s->avctx->channels; ch++) + for (ch = 0; ch < channels; ch++) nb_coefs[ch] = v; { int n4 = s->block_len / 2; @@ -222,17 +226,17 @@ static int encode_block(WMACodecContext *s, float (*src_coefs)[BLOCK_MAX_SIZE], mdct_norm *= sqrt(n4); } - if (s->avctx->channels == 2) + if (channels == 2) put_bits(&s->pb, 1, !!s->ms_stereo); - for (ch = 0; ch < s->avctx->channels; ch++) { + for (ch = 0; ch < channels; ch++) { // FIXME only set channel_coded when needed, instead of always s->channel_coded[ch] = 1; if (s->channel_coded[ch]) init_exp(s, ch, fixed_exp); } - for (ch = 0; ch < s->avctx->channels; ch++) { + for (ch = 0; ch < channels; ch++) { if (s->channel_coded[ch]) { WMACoef *coefs1; float *coefs, *exponents, mult; @@ -260,7 +264,7 @@ static int encode_block(WMACodecContext *s, float (*src_coefs)[BLOCK_MAX_SIZE], } v = 0; - for (ch = 0; ch < s->avctx->channels; ch++) { + for (ch = 0; ch < channels; ch++) { int a = s->channel_coded[ch]; put_bits(&s->pb, 1, a); v |= a; @@ -276,7 +280,7 @@ static int encode_block(WMACodecContext *s, float (*src_coefs)[BLOCK_MAX_SIZE], coef_nb_bits = ff_wma_total_gain_to_bits(total_gain); if (s->use_noise_coding) { - for (ch = 0; ch < s->avctx->channels; ch++) { + for (ch = 0; ch < channels; ch++) { if (s->channel_coded[ch]) { int i, n; n = s->exponent_high_sizes[bsize]; @@ -294,7 +298,7 @@ static int encode_block(WMACodecContext *s, float (*src_coefs)[BLOCK_MAX_SIZE], put_bits(&s->pb, 1, parse_exponents); if (parse_exponents) { - for (ch = 0; ch < s->avctx->channels; ch++) { + for (ch = 0; ch < channels; ch++) { if (s->channel_coded[ch]) { if (s->use_exp_vlc) { encode_exp_vlc(s, ch, fixed_exp); @@ -307,7 +311,7 @@ static int encode_block(WMACodecContext *s, float (*src_coefs)[BLOCK_MAX_SIZE], } else av_assert0(0); // FIXME not implemented - for (ch = 0; ch < s->avctx->channels; ch++) { + for (ch = 0; ch < channels; ch++) { if (s->channel_coded[ch]) { int run, tindex; WMACoef *ptr, *eptr; @@ -346,7 +350,7 @@ static int encode_block(WMACodecContext *s, float (*src_coefs)[BLOCK_MAX_SIZE], put_bits(&s->pb, s->coef_vlcs[tindex]->huffbits[1], s->coef_vlcs[tindex]->huffcodes[1]); } - if (s->version == 1 && s->avctx->channels >= 2) + if (s->version == 1 && channels >= 2) align_put_bits(&s->pb); } return 0; @@ -429,31 +433,31 @@ static int encode_superframe(AVCodecContext *avctx, AVPacket *avpkt, } #if CONFIG_WMAV1_ENCODER -const AVCodec ff_wmav1_encoder = { - .name = "wmav1", - .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 1"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_WMAV1, +const FFCodec ff_wmav1_encoder = { + .p.name = "wmav1", + .p.long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 1"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_WMAV1, .priv_data_size = sizeof(WMACodecContext), .init = encode_init, - .encode2 = encode_superframe, + FF_CODEC_ENCODE_CB(encode_superframe), .close = ff_wma_end, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; #endif #if CONFIG_WMAV2_ENCODER -const AVCodec ff_wmav2_encoder = { - .name = "wmav2", - .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 2"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_WMAV2, +const FFCodec ff_wmav2_encoder = { + .p.name = "wmav2", + .p.long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 2"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_WMAV2, .priv_data_size = sizeof(WMACodecContext), .init = encode_init, - .encode2 = encode_superframe, + FF_CODEC_ENCODE_CB(encode_superframe), .close = ff_wma_end, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/wmalosslessdec.c b/libavcodec/wmalosslessdec.c index 74c91f4f7..16c6713cd 100644 --- a/libavcodec/wmalosslessdec.c +++ b/libavcodec/wmalosslessdec.c @@ -29,6 +29,7 @@ #include "libavutil/mem_internal.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "get_bits.h" #include "put_bits.h" @@ -190,22 +191,6 @@ static av_cold int decode_init(AVCodecContext *avctx) return AVERROR(EINVAL); } - av_assert0(avctx->channels >= 0); - if (avctx->channels > WMALL_MAX_CHANNELS) { - avpriv_request_sample(avctx, - "More than " AV_STRINGIFY(WMALL_MAX_CHANNELS) " channels"); - return AVERROR_PATCHWELCOME; - } - - s->max_frame_size = MAX_FRAMESIZE * avctx->channels; - s->frame_data = av_mallocz(s->max_frame_size + AV_INPUT_BUFFER_PADDING_SIZE); - if (!s->frame_data) - return AVERROR(ENOMEM); - - s->avctx = avctx; - ff_llauddsp_init(&s->dsp); - init_put_bits(&s->pb, s->frame_data, s->max_frame_size); - if (avctx->extradata_size >= 18) { s->decode_flags = AV_RL16(edata_ptr + 14); channel_mask = AV_RL32(edata_ptr + 2); @@ -230,6 +215,38 @@ static av_cold int decode_init(AVCodecContext *avctx) return AVERROR_PATCHWELCOME; } + if (channel_mask) { + av_channel_layout_uninit(&avctx->ch_layout); + av_channel_layout_from_mask(&avctx->ch_layout, channel_mask); + } + av_assert0(avctx->ch_layout.nb_channels >= 0); + if (avctx->ch_layout.nb_channels > WMALL_MAX_CHANNELS) { + avpriv_request_sample(avctx, + "More than " AV_STRINGIFY(WMALL_MAX_CHANNELS) " channels"); + return AVERROR_PATCHWELCOME; + } + + s->num_channels = avctx->ch_layout.nb_channels; + + /* extract lfe channel position */ + s->lfe_channel = -1; + + if (channel_mask & 8) { + unsigned int mask; + for (mask = 1; mask < 16; mask <<= 1) + if (channel_mask & mask) + ++s->lfe_channel; + } + + s->max_frame_size = MAX_FRAMESIZE * avctx->ch_layout.nb_channels; + s->frame_data = av_mallocz(s->max_frame_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!s->frame_data) + return AVERROR(ENOMEM); + + s->avctx = avctx; + ff_llauddsp_init(&s->dsp); + init_put_bits(&s->pb, s->frame_data, s->max_frame_size); + /* generic init */ s->log2_frame_size = av_log2(avctx->block_align) + 4; @@ -244,7 +261,7 @@ static av_cold int decode_init(AVCodecContext *avctx) av_assert0(s->samples_per_frame <= WMALL_BLOCK_MAX_SIZE); /* init previous block len */ - for (i = 0; i < avctx->channels; i++) + for (i = 0; i < avctx->ch_layout.nb_channels; i++) s->channel[i].prev_block_len = s->samples_per_frame; /* subframe info */ @@ -263,23 +280,10 @@ static av_cold int decode_init(AVCodecContext *avctx) return AVERROR_INVALIDDATA; } - s->num_channels = avctx->channels; - - /* extract lfe channel position */ - s->lfe_channel = -1; - - if (channel_mask & 8) { - unsigned int mask; - for (mask = 1; mask < 16; mask <<= 1) - if (channel_mask & mask) - ++s->lfe_channel; - } - s->frame = av_frame_alloc(); if (!s->frame) return AVERROR(ENOMEM); - avctx->channel_layout = channel_mask; return 0; } @@ -1179,8 +1183,8 @@ static void save_bits(WmallDecodeCtx *s, GetBitContext* gb, int len, skip_bits(&s->gb, s->frame_offset); } -static int decode_packet(AVCodecContext *avctx, void *data, int *got_frame_ptr, - AVPacket* avpkt) +static int decode_packet(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame_ptr, AVPacket* avpkt) { WmallDecodeCtx *s = avctx->priv_data; GetBitContext* gb = &s->pgb; @@ -1293,7 +1297,7 @@ static int decode_packet(AVCodecContext *avctx, void *data, int *got_frame_ptr, } *got_frame_ptr = s->frame->nb_samples > 0; - av_frame_move_ref(data, s->frame); + av_frame_move_ref(rframe, s->frame); s->packet_offset = get_bits_count(gb) & 7; @@ -1323,19 +1327,19 @@ static av_cold int decode_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_wmalossless_decoder = { - .name = "wmalossless", - .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio Lossless"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_WMALOSSLESS, +const FFCodec ff_wmalossless_decoder = { + .p.name = "wmalossless", + .p.long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio Lossless"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_WMALOSSLESS, .priv_data_size = sizeof(WmallDecodeCtx), .init = decode_init, .close = decode_close, - .decode = decode_packet, + FF_CODEC_DECODE_CB(decode_packet), .flush = flush, - .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, + .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_NONE }, }; diff --git a/libavcodec/wmaprodec.c b/libavcodec/wmaprodec.c index ba7bddc51..9cf763acd 100644 --- a/libavcodec/wmaprodec.c +++ b/libavcodec/wmaprodec.c @@ -97,6 +97,7 @@ #include "libavutil/thread.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "get_bits.h" #include "put_bits.h" @@ -384,7 +385,7 @@ static av_cold int decode_init(WMAProDecodeCtx *s, AVCodecContext *avctx, int nu s->decode_flags = 0x10d6; s->bits_per_sample = 16; channel_mask = 0; //AV_RL32(edata_ptr+2); /* not always in expected order */ - if ((num_stream+1) * XMA_MAX_CHANNELS_STREAM > avctx->channels) /* stream config is 2ch + 2ch + ... + 1/2ch */ + if ((num_stream+1) * XMA_MAX_CHANNELS_STREAM > avctx->ch_layout.nb_channels) /* stream config is 2ch + 2ch + ... + 1/2ch */ s->nb_channels = 1; else s->nb_channels = 2; @@ -402,7 +403,7 @@ static av_cold int decode_init(WMAProDecodeCtx *s, AVCodecContext *avctx, int nu s->decode_flags = AV_RL16(edata_ptr+14); channel_mask = AV_RL32(edata_ptr+2); s->bits_per_sample = AV_RL16(edata_ptr); - s->nb_channels = avctx->channels; + s->nb_channels = channel_mask ? av_popcount(channel_mask) : avctx->ch_layout.nb_channels; if (s->bits_per_sample > 32 || s->bits_per_sample < 1) { avpriv_request_sample(avctx, "bits per sample is %d", s->bits_per_sample); @@ -474,7 +475,7 @@ static av_cold int decode_init(WMAProDecodeCtx *s, AVCodecContext *avctx, int nu av_log(avctx, AV_LOG_ERROR, "invalid number of channels per XMA stream %d\n", s->nb_channels); return AVERROR_INVALIDDATA; - } else if (s->nb_channels > WMAPRO_MAX_CHANNELS || s->nb_channels > avctx->channels) { + } else if (s->nb_channels > WMAPRO_MAX_CHANNELS || s->nb_channels > avctx->ch_layout.nb_channels) { avpriv_request_sample(avctx, "More than %d channels", WMAPRO_MAX_CHANNELS); return AVERROR_PATCHWELCOME; @@ -575,8 +576,13 @@ static av_cold int decode_init(WMAProDecodeCtx *s, AVCodecContext *avctx, int nu if (avctx->debug & FF_DEBUG_BITSTREAM) dump_context(s); - if (avctx->codec_id == AV_CODEC_ID_WMAPRO) - avctx->channel_layout = channel_mask; + if (avctx->codec_id == AV_CODEC_ID_WMAPRO) { + if (channel_mask) { + av_channel_layout_uninit(&avctx->ch_layout); + av_channel_layout_from_mask(&avctx->ch_layout, channel_mask); + } else + avctx->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + } ff_thread_once(&init_static_once, decode_init_static); @@ -1604,7 +1610,7 @@ static void save_bits(WMAProDecodeCtx *s, GetBitContext* gb, int len, } static int decode_packet(AVCodecContext *avctx, WMAProDecodeCtx *s, - void *data, int *got_frame_ptr, AVPacket *avpkt) + AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { GetBitContext* gb = &s->pgb; const uint8_t* buf = avpkt->data; @@ -1616,7 +1622,6 @@ static int decode_packet(AVCodecContext *avctx, WMAProDecodeCtx *s, *got_frame_ptr = 0; if (!buf_size) { - AVFrame *frame = data; int i; /** Must output remaining samples after stream end. WMAPRO 5.1 created @@ -1708,7 +1713,7 @@ static int decode_packet(AVCodecContext *avctx, WMAProDecodeCtx *s, /** decode the cross packet frame if it is valid */ if (!s->packet_loss) - decode_frame(s, data, got_frame_ptr); + decode_frame(s, frame, got_frame_ptr); } else if (s->num_saved_bits - s->frame_offset) { ff_dlog(avctx, "ignoring %x previously saved bits\n", s->num_saved_bits - s->frame_offset); @@ -1739,7 +1744,7 @@ static int decode_packet(AVCodecContext *avctx, WMAProDecodeCtx *s, frame_size <= remaining_bits(s, gb)) { save_bits(s, gb, frame_size, 0); if (!s->packet_loss) - s->packet_done = !decode_frame(s, data, got_frame_ptr); + s->packet_done = !decode_frame(s, frame, got_frame_ptr); } 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 @@ -1749,7 +1754,7 @@ static int decode_packet(AVCodecContext *avctx, WMAProDecodeCtx *s, therefore we save the incoming packet first, then we append the "previous frame" data from the next packet so that we get a buffer that only contains full frames */ - s->packet_done = !decode_frame(s, data, got_frame_ptr); + s->packet_done = !decode_frame(s, frame, got_frame_ptr); } else { s->packet_done = 1; } @@ -1772,10 +1777,8 @@ static int decode_packet(AVCodecContext *avctx, WMAProDecodeCtx *s, return AVERROR_INVALIDDATA; if (s->trim_start && avctx->codec_id == AV_CODEC_ID_WMAPRO) { - AVFrame *frame = data; - if (s->trim_start < frame->nb_samples) { - for (int ch = 0; ch < frame->channels; ch++) + for (int ch = 0; ch < frame->ch_layout.nb_channels; ch++) frame->extended_data[ch] += s->trim_start * 4; frame->nb_samples -= s->trim_start; @@ -1787,8 +1790,6 @@ static int decode_packet(AVCodecContext *avctx, WMAProDecodeCtx *s, } if (s->trim_end && avctx->codec_id == AV_CODEC_ID_WMAPRO) { - AVFrame *frame = data; - if (s->trim_end < frame->nb_samples) { frame->nb_samples -= s->trim_end; } else { @@ -1808,11 +1809,10 @@ static int decode_packet(AVCodecContext *avctx, WMAProDecodeCtx *s, *@param avpkt input packet *@return number of bytes that were read from the input buffer */ -static int wmapro_decode_packet(AVCodecContext *avctx, void *data, +static int wmapro_decode_packet(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { WMAProDecodeCtx *s = avctx->priv_data; - AVFrame *frame = data; int ret; /* get output buffer */ @@ -1822,15 +1822,14 @@ static int wmapro_decode_packet(AVCodecContext *avctx, void *data, return 0; } - return decode_packet(avctx, s, data, got_frame_ptr, avpkt); + return decode_packet(avctx, s, frame, got_frame_ptr, avpkt); } -static int xma_decode_packet(AVCodecContext *avctx, void *data, +static int xma_decode_packet(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { XMADecodeCtx *s = avctx->priv_data; int got_stream_frame_ptr = 0; - AVFrame *frame = data; int i, ret = 0, eof = 0; if (!s->frames[s->current_stream]->data[0]) { @@ -1952,13 +1951,18 @@ static av_cold int xma_decode_init(AVCodecContext *avctx) XMADecodeCtx *s = avctx->priv_data; int i, ret, start_channels = 0; - if (avctx->channels <= 0 || avctx->extradata_size == 0) + if (avctx->ch_layout.nb_channels <= 0 || avctx->extradata_size == 0) return AVERROR_INVALIDDATA; /* get stream config */ if (avctx->codec_id == AV_CODEC_ID_XMA2 && avctx->extradata_size == 34) { /* XMA2WAVEFORMATEX */ + unsigned int channel_mask = AV_RL32(avctx->extradata + 2); + if (channel_mask) { + av_channel_layout_uninit(&avctx->ch_layout); + av_channel_layout_from_mask(&avctx->ch_layout, channel_mask); + } else + avctx->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; s->num_streams = AV_RL16(avctx->extradata); - avctx->channel_layout = AV_RL32(avctx->extradata + 2); } else if (avctx->codec_id == AV_CODEC_ID_XMA2 && avctx->extradata_size >= 2) { /* XMA2WAVEFORMAT */ s->num_streams = avctx->extradata[1]; if (avctx->extradata_size != (32 + ((avctx->extradata[0]==3)?0:8) + 4*s->num_streams)) { @@ -1979,7 +1983,7 @@ static av_cold int xma_decode_init(AVCodecContext *avctx) } /* encoder supports up to 64 streams / 64*2 channels (would have to alloc arrays) */ - if (avctx->channels > XMA_MAX_CHANNELS || s->num_streams > XMA_MAX_STREAMS || + if (avctx->ch_layout.nb_channels > XMA_MAX_CHANNELS || s->num_streams > XMA_MAX_STREAMS || s->num_streams <= 0 ) { avpriv_request_sample(avctx, "More than %d channels in %d streams", XMA_MAX_CHANNELS, s->num_streams); @@ -1999,7 +2003,7 @@ static av_cold int xma_decode_init(AVCodecContext *avctx) s->start_channel[i] = start_channels; start_channels += s->xma[i].nb_channels; } - if (start_channels != avctx->channels) + if (start_channels != avctx->ch_layout.nb_channels) return AVERROR_INVALIDDATA; for (int i = 0; i < XMA_MAX_STREAMS; i++) { @@ -2076,49 +2080,49 @@ static void xma_flush(AVCodecContext *avctx) /** *@brief wmapro decoder */ -const AVCodec ff_wmapro_decoder = { - .name = "wmapro", - .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 9 Professional"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_WMAPRO, +const FFCodec ff_wmapro_decoder = { + .p.name = "wmapro", + .p.long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 9 Professional"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_WMAPRO, .priv_data_size = sizeof(WMAProDecodeCtx), .init = wmapro_decode_init, .close = wmapro_decode_end, - .decode = wmapro_decode_packet, - .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(wmapro_decode_packet), + .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1, .flush = wmapro_flush, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; -const AVCodec ff_xma1_decoder = { - .name = "xma1", - .long_name = NULL_IF_CONFIG_SMALL("Xbox Media Audio 1"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_XMA1, +const FFCodec ff_xma1_decoder = { + .p.name = "xma1", + .p.long_name = NULL_IF_CONFIG_SMALL("Xbox Media Audio 1"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_XMA1, .priv_data_size = sizeof(XMADecodeCtx), .init = xma_decode_init, .close = xma_decode_end, - .decode = xma_decode_packet, - .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + FF_CODEC_DECODE_CB(xma_decode_packet), + .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; -const AVCodec ff_xma2_decoder = { - .name = "xma2", - .long_name = NULL_IF_CONFIG_SMALL("Xbox Media Audio 2"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_XMA2, +const FFCodec ff_xma2_decoder = { + .p.name = "xma2", + .p.long_name = NULL_IF_CONFIG_SMALL("Xbox Media Audio 2"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_XMA2, .priv_data_size = sizeof(XMADecodeCtx), .init = xma_decode_init, .close = xma_decode_end, - .decode = xma_decode_packet, + FF_CODEC_DECODE_CB(xma_decode_packet), .flush = xma_flush, - .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, - .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, + .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, + .p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/wmavoice.c b/libavcodec/wmavoice.c index e096b8029..c52ab876b 100644 --- a/libavcodec/wmavoice.c +++ b/libavcodec/wmavoice.c @@ -32,6 +32,7 @@ #include "libavutil/mem_internal.h" #include "libavutil/thread.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "get_bits.h" #include "put_bits.h" @@ -475,8 +476,8 @@ static av_cold int wmavoice_decode_init(AVCodecContext *ctx) 2 * (s->block_conv_table[1] - 2 * s->min_pitch_val); s->block_pitch_nbits = av_ceil_log2(s->block_pitch_range); - ctx->channels = 1; - ctx->channel_layout = AV_CH_LAYOUT_MONO; + av_channel_layout_uninit(&ctx->ch_layout); + ctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; ctx->sample_fmt = AV_SAMPLE_FMT_FLT; return 0; @@ -1902,7 +1903,7 @@ static void copy_bits(PutBitContext *pb, * * For more information about frames, see #synth_superframe(). */ -static int wmavoice_decode_packet(AVCodecContext *ctx, void *data, +static int wmavoice_decode_packet(AVCodecContext *ctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { WMAVoiceContext *s = ctx->priv_data; @@ -1941,7 +1942,7 @@ static int wmavoice_decode_packet(AVCodecContext *ctx, void *data, copy_bits(&s->pb, avpkt->data, size, gb, s->spillover_nbits); flush_put_bits(&s->pb); s->sframe_cache_size += s->spillover_nbits; - if ((res = synth_superframe(ctx, data, got_frame_ptr)) == 0 && + if ((res = synth_superframe(ctx, frame, got_frame_ptr)) == 0 && *got_frame_ptr) { cnt += s->spillover_nbits; s->skip_bits_next = cnt & 7; @@ -1964,7 +1965,7 @@ static int wmavoice_decode_packet(AVCodecContext *ctx, void *data, *got_frame_ptr = 0; return size; } else if (s->nb_superframes > 0) { - if ((res = synth_superframe(ctx, data, got_frame_ptr)) < 0) { + if ((res = synth_superframe(ctx, frame, got_frame_ptr)) < 0) { return res; } else if (*got_frame_ptr) { int cnt = get_bits_count(gb); @@ -1997,16 +1998,16 @@ static av_cold int wmavoice_decode_end(AVCodecContext *ctx) return 0; } -const AVCodec ff_wmavoice_decoder = { - .name = "wmavoice", - .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio Voice"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_WMAVOICE, +const FFCodec ff_wmavoice_decoder = { + .p.name = "wmavoice", + .p.long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio Voice"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_WMAVOICE, .priv_data_size = sizeof(WMAVoiceContext), .init = wmavoice_decode_init, .close = wmavoice_decode_end, - .decode = wmavoice_decode_packet, - .capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, + FF_CODEC_DECODE_CB(wmavoice_decode_packet), + .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .flush = wmavoice_flush, }; diff --git a/libavcodec/wmv2.c b/libavcodec/wmv2.c index 327c5bdae..8d1d117de 100644 --- a/libavcodec/wmv2.c +++ b/libavcodec/wmv2.c @@ -20,27 +20,20 @@ #include "avcodec.h" #include "idctdsp.h" -#include "mpegutils.h" #include "mpegvideo.h" #include "msmpeg4data.h" -#include "simple_idct.h" #include "wmv2.h" -#include "wmv2data.h" -av_cold void ff_wmv2_common_init(Wmv2Context *w) +av_cold void ff_wmv2_common_init(MpegEncContext *s) { - MpegEncContext *const s = &w->s; + WMV2Context *const w = s->private_ctx; ff_blockdsp_init(&s->bdsp, s->avctx); ff_wmv2dsp_init(&w->wdsp); s->idsp.perm_type = w->wdsp.idct_perm; ff_init_scantable_permutation(s->idsp.idct_permutation, w->wdsp.idct_perm); - ff_init_scantable(s->idsp.idct_permutation, &w->abt_scantable[0], - ff_wmv2_scantableA); - ff_init_scantable(s->idsp.idct_permutation, &w->abt_scantable[1], - ff_wmv2_scantableB); ff_init_scantable(s->idsp.idct_permutation, &s->intra_scantable, ff_wmv1_scantable[1]); ff_init_scantable(s->idsp.idct_permutation, &s->intra_h_scantable, @@ -54,55 +47,12 @@ av_cold void ff_wmv2_common_init(Wmv2Context *w) s->idsp.idct = NULL; } -static void wmv2_add_block(Wmv2Context *w, int16_t *block1, - uint8_t *dst, int stride, int n) -{ - MpegEncContext *const s = &w->s; - - if (s->block_last_index[n] >= 0) { - switch (w->abt_type_table[n]) { - case 0: - w->wdsp.idct_add(dst, stride, block1); - break; - case 1: - ff_simple_idct84_add(dst, stride, block1); - ff_simple_idct84_add(dst + 4 * stride, stride, w->abt_block2[n]); - s->bdsp.clear_block(w->abt_block2[n]); - break; - case 2: - ff_simple_idct48_add(dst, stride, block1); - ff_simple_idct48_add(dst + 4, stride, w->abt_block2[n]); - s->bdsp.clear_block(w->abt_block2[n]); - break; - default: - av_log(s->avctx, AV_LOG_ERROR, "internal error in WMV2 abt\n"); - } - } -} - -void ff_wmv2_add_mb(MpegEncContext *s, int16_t block1[6][64], - uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr) -{ - Wmv2Context *const w = (Wmv2Context *) s; - - wmv2_add_block(w, block1[0], dest_y, s->linesize, 0); - wmv2_add_block(w, block1[1], dest_y + 8, s->linesize, 1); - wmv2_add_block(w, block1[2], dest_y + 8 * s->linesize, s->linesize, 2); - wmv2_add_block(w, block1[3], dest_y + 8 + 8 * s->linesize, s->linesize, 3); - - if (s->avctx->flags & AV_CODEC_FLAG_GRAY) - return; - - wmv2_add_block(w, block1[4], dest_cb, s->uvlinesize, 4); - wmv2_add_block(w, block1[5], dest_cr, s->uvlinesize, 5); -} - void ff_mspel_motion(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, uint8_t **ref_picture, op_pixels_func (*pix_op)[4], int motion_x, int motion_y, int h) { - Wmv2Context *const w = (Wmv2Context *) s; + WMV2Context *const w = s->private_ctx; uint8_t *ptr; int dxy, mx, my, src_x, src_y, v_edge_pos; ptrdiff_t offset, linesize, uvlinesize; diff --git a/libavcodec/wmv2.h b/libavcodec/wmv2.h index 1798dbabc..cdd58cf01 100644 --- a/libavcodec/wmv2.h +++ b/libavcodec/wmv2.h @@ -21,9 +21,6 @@ #ifndef AVCODEC_WMV2_H #define AVCODEC_WMV2_H -#include "libavutil/mem_internal.h" - -#include "intrax8.h" #include "mpegvideo.h" #include "wmv2dsp.h" @@ -33,38 +30,12 @@ #define SKIP_TYPE_COL 3 -typedef struct Wmv2Context { - MpegEncContext s; - IntraX8Context x8; +typedef struct WMV2Context { WMV2DSPContext wdsp; - int j_type_bit; - int j_type; - int abt_flag; - int abt_type; - int abt_type_table[6]; - int per_mb_abt; - int per_block_abt; - int mspel_bit; - int cbp_table_index; - int top_left_mv_flag; - int per_mb_rl_bit; - int skip_type; int hshift; +} WMV2Context; - ScanTable abt_scantable[2]; - DECLARE_ALIGNED(32, int16_t, abt_block2)[6][64]; -} Wmv2Context; - -void ff_wmv2_common_init(Wmv2Context *w); - -int ff_wmv2_decode_mb(MpegEncContext *s, int16_t block[6][64]); -int ff_wmv2_encode_picture_header(MpegEncContext * s, int picture_number); -void ff_wmv2_encode_mb(MpegEncContext * s, int16_t block[6][64], - int motion_x, int motion_y); -int ff_wmv2_decode_picture_header(MpegEncContext * s); -int ff_wmv2_decode_secondary_picture_header(MpegEncContext * s); -void ff_wmv2_add_mb(MpegEncContext *s, int16_t block[6][64], - uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr); +void ff_wmv2_common_init(MpegEncContext *s); void ff_mspel_motion(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr, diff --git a/libavcodec/wmv2dec.c b/libavcodec/wmv2dec.c index c500e3e77..bf0e609c0 100644 --- a/libavcodec/wmv2dec.c +++ b/libavcodec/wmv2dec.c @@ -18,19 +18,88 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/mem_internal.h" + #include "avcodec.h" -#include "h263.h" -#include "internal.h" +#include "codec_internal.h" +#include "h263dec.h" #include "intrax8.h" #include "mathops.h" #include "mpegutils.h" #include "mpegvideo.h" #include "msmpeg4.h" #include "msmpeg4data.h" +#include "msmpeg4dec.h" +#include "simple_idct.h" #include "wmv2.h" +#include "wmv2data.h" +#include "wmv2dec.h" +typedef struct WMV2DecContext { + MpegEncContext s; + WMV2Context common; + IntraX8Context x8; + int j_type_bit; + int j_type; + int abt_flag; + int abt_type; + int abt_type_table[6]; + int per_mb_abt; + int per_block_abt; + int mspel_bit; + int cbp_table_index; + int top_left_mv_flag; + int per_mb_rl_bit; + int skip_type; -static int parse_mb_skip(Wmv2Context *w) + ScanTable abt_scantable[2]; + DECLARE_ALIGNED(32, int16_t, abt_block2)[6][64]; +} WMV2DecContext; + +static void wmv2_add_block(WMV2DecContext *w, int16_t *block1, + uint8_t *dst, int stride, int n) +{ + MpegEncContext *const s = &w->s; + + if (s->block_last_index[n] >= 0) { + switch (w->abt_type_table[n]) { + case 0: + w->common.wdsp.idct_add(dst, stride, block1); + break; + case 1: + ff_simple_idct84_add(dst, stride, block1); + ff_simple_idct84_add(dst + 4 * stride, stride, w->abt_block2[n]); + s->bdsp.clear_block(w->abt_block2[n]); + break; + case 2: + ff_simple_idct48_add(dst, stride, block1); + ff_simple_idct48_add(dst + 4, stride, w->abt_block2[n]); + s->bdsp.clear_block(w->abt_block2[n]); + break; + default: + av_log(s->avctx, AV_LOG_ERROR, "internal error in WMV2 abt\n"); + } + } +} + +void ff_wmv2_add_mb(MpegEncContext *s, int16_t block1[6][64], + uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr) +{ + WMV2DecContext *const w = (WMV2DecContext *) s; + + wmv2_add_block(w, block1[0], dest_y, s->linesize, 0); + wmv2_add_block(w, block1[1], dest_y + 8, s->linesize, 1); + wmv2_add_block(w, block1[2], dest_y + 8 * s->linesize, s->linesize, 2); + wmv2_add_block(w, block1[3], dest_y + 8 + 8 * s->linesize, s->linesize, 3); + + if (s->avctx->flags & AV_CODEC_FLAG_GRAY) + return; + + wmv2_add_block(w, block1[4], dest_cb, s->uvlinesize, 4); + wmv2_add_block(w, block1[5], dest_cr, s->uvlinesize, 5); +} + +static int parse_mb_skip(WMV2DecContext *w) { int mb_x, mb_y; int coded_mb_count = 0; @@ -95,7 +164,7 @@ static int parse_mb_skip(Wmv2Context *w) return 0; } -static int decode_ext_header(Wmv2Context *w) +static int decode_ext_header(WMV2DecContext *w) { MpegEncContext *const s = &w->s; GetBitContext gb; @@ -135,7 +204,7 @@ static int decode_ext_header(Wmv2Context *w) int ff_wmv2_decode_picture_header(MpegEncContext *s) { - Wmv2Context *const w = (Wmv2Context *) s; + WMV2DecContext *const w = (WMV2DecContext *) s; int code; if (s->picture_number == 0) @@ -170,7 +239,7 @@ int ff_wmv2_decode_picture_header(MpegEncContext *s) int ff_wmv2_decode_secondary_picture_header(MpegEncContext *s) { - Wmv2Context *const w = (Wmv2Context *) s; + WMV2DecContext *const w = (WMV2DecContext *) s; if (s->pict_type == AV_PICTURE_TYPE_I) { if (w->j_type_bit) @@ -278,19 +347,19 @@ int ff_wmv2_decode_secondary_picture_header(MpegEncContext *s) return 0; } -static inline void wmv2_decode_motion(Wmv2Context *w, int *mx_ptr, int *my_ptr) +static inline void wmv2_decode_motion(WMV2DecContext *w, int *mx_ptr, int *my_ptr) { MpegEncContext *const s = &w->s; ff_msmpeg4_decode_motion(s, mx_ptr, my_ptr); if ((((*mx_ptr) | (*my_ptr)) & 1) && s->mspel) - w->hshift = get_bits1(&s->gb); + w->common.hshift = get_bits1(&s->gb); else - w->hshift = 0; + w->common.hshift = 0; } -static int16_t *wmv2_pred_motion(Wmv2Context *w, int *px, int *py) +static int16_t *wmv2_pred_motion(WMV2DecContext *w, int *px, int *py) { MpegEncContext *const s = &w->s; int xy, wrap, diff, type; @@ -335,7 +404,7 @@ static int16_t *wmv2_pred_motion(Wmv2Context *w, int *px, int *py) return mot_val; } -static inline int wmv2_decode_inter_block(Wmv2Context *w, int16_t *block, +static inline int wmv2_decode_inter_block(WMV2DecContext *w, int16_t *block, int n, int cbp) { MpegEncContext *const s = &w->s; @@ -377,7 +446,9 @@ static inline int wmv2_decode_inter_block(Wmv2Context *w, int16_t *block, int ff_wmv2_decode_mb(MpegEncContext *s, int16_t block[6][64]) { - Wmv2Context *const w = (Wmv2Context *) s; + /* The following is only allowed because this encoder + * does not use slice threading. */ + WMV2DecContext *const w = (WMV2DecContext *) s; int cbp, code, i, ret; uint8_t *coded_val; @@ -395,7 +466,7 @@ int ff_wmv2_decode_mb(MpegEncContext *s, int16_t block[6][64]) s->mv[0][0][0] = 0; s->mv[0][0][1] = 0; s->mb_skipped = 1; - w->hshift = 0; + w->common.hshift = 0; return 0; } if (get_bits_left(&s->gb) <= 0) @@ -492,13 +563,20 @@ int ff_wmv2_decode_mb(MpegEncContext *s, int16_t block[6][64]) static av_cold int wmv2_decode_init(AVCodecContext *avctx) { - Wmv2Context *const w = avctx->priv_data; + WMV2DecContext *const w = avctx->priv_data; + MpegEncContext *const s = &w->s; int ret; + s->private_ctx = &w->common; + if ((ret = ff_msmpeg4_decode_init(avctx)) < 0) return ret; - ff_wmv2_common_init(w); + ff_wmv2_common_init(s); + ff_init_scantable(s->idsp.idct_permutation, &w->abt_scantable[0], + ff_wmv2_scantableA); + ff_init_scantable(s->idsp.idct_permutation, &w->abt_scantable[1], + ff_wmv2_scantableB); return ff_intrax8_common_init(avctx, &w->x8, &w->s.idsp, w->s.block, w->s.block_last_index, @@ -507,23 +585,23 @@ static av_cold int wmv2_decode_init(AVCodecContext *avctx) static av_cold int wmv2_decode_end(AVCodecContext *avctx) { - Wmv2Context *w = avctx->priv_data; + WMV2DecContext *const w = avctx->priv_data; ff_intrax8_common_end(&w->x8); return ff_h263_decode_end(avctx); } -const AVCodec ff_wmv2_decoder = { - .name = "wmv2", - .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 8"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_WMV2, - .priv_data_size = sizeof(Wmv2Context), +const FFCodec ff_wmv2_decoder = { + .p.name = "wmv2", + .p.long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 8"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_WMV2, + .priv_data_size = sizeof(WMV2DecContext), .init = wmv2_decode_init, .close = wmv2_decode_end, - .decode = ff_h263_decode_frame, - .capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1, - .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, - .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, + FF_CODEC_DECODE_CB(ff_h263_decode_frame), + .p.capabilities = AV_CODEC_CAP_DRAW_HORIZ_BAND | AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, }; diff --git a/libavcodec/wmv2dec.h b/libavcodec/wmv2dec.h new file mode 100644 index 000000000..cc410afe1 --- /dev/null +++ b/libavcodec/wmv2dec.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2002 The FFmpeg Project + * + * 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_WMV2DEC_H +#define AVCODEC_WMV2DEC_H + +#include "mpegvideo.h" + +int ff_wmv2_decode_mb(MpegEncContext *s, int16_t block[6][64]); +int ff_wmv2_decode_picture_header(MpegEncContext * s); +int ff_wmv2_decode_secondary_picture_header(MpegEncContext * s); +void ff_wmv2_add_mb(MpegEncContext *s, int16_t block[6][64], + uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr); + +#endif diff --git a/libavcodec/wmv2dsp.c b/libavcodec/wmv2dsp.c index 3bd482176..4ad8a596b 100644 --- a/libavcodec/wmv2dsp.c +++ b/libavcodec/wmv2dsp.c @@ -264,6 +264,7 @@ av_cold void ff_wmv2dsp_init(WMV2DSPContext *c) c->put_mspel_pixels_tab[6] = put_mspel8_mc22_c; c->put_mspel_pixels_tab[7] = put_mspel8_mc32_c; - if (ARCH_MIPS) - ff_wmv2dsp_init_mips(c); +#if ARCH_MIPS + ff_wmv2dsp_init_mips(c); +#endif } diff --git a/libavcodec/wmv2enc.c b/libavcodec/wmv2enc.c index ab5365d1f..88211ac17 100644 --- a/libavcodec/wmv2enc.c +++ b/libavcodec/wmv2enc.c @@ -19,16 +19,33 @@ */ #include "avcodec.h" +#include "codec_internal.h" #include "h263.h" #include "mpegvideo.h" +#include "mpegvideoenc.h" #include "msmpeg4.h" +#include "msmpeg4enc.h" #include "msmpeg4data.h" #include "wmv2.h" +#include "wmv2enc.h" +typedef struct WMV2EncContext { + MSMPEG4EncContext msmpeg4; + WMV2Context common; + int j_type_bit; + int j_type; + int abt_flag; + int abt_type; + int per_mb_abt; + int mspel_bit; + int cbp_table_index; + int top_left_mv_flag; + int per_mb_rl_bit; +} WMV2EncContext; -static int encode_ext_header(Wmv2Context *w) +static int encode_ext_header(WMV2EncContext *w) { - MpegEncContext *const s = &w->s; + MpegEncContext *const s = &w->msmpeg4.s; PutBitContext pb; int code; @@ -54,12 +71,14 @@ static int encode_ext_header(Wmv2Context *w) static av_cold int wmv2_encode_init(AVCodecContext *avctx) { - Wmv2Context *const w = avctx->priv_data; + WMV2EncContext *const w = avctx->priv_data; + MpegEncContext *const s = &w->msmpeg4.s; + s->private_ctx = &w->common; if (ff_mpv_encode_init(avctx) < 0) return -1; - ff_wmv2_common_init(w); + ff_wmv2_common_init(s); avctx->extradata_size = 4; avctx->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); @@ -73,7 +92,7 @@ static av_cold int wmv2_encode_init(AVCodecContext *avctx) int ff_wmv2_encode_picture_header(MpegEncContext *s, int picture_number) { - Wmv2Context *const w = (Wmv2Context *) s; + WMV2EncContext *const w = (WMV2EncContext *) s; put_bits(&s->pb, 1, s->pict_type - 1); if (s->pict_type == AV_PICTURE_TYPE_I) @@ -147,7 +166,7 @@ int ff_wmv2_encode_picture_header(MpegEncContext *s, int picture_number) void ff_wmv2_encode_mb(MpegEncContext *s, int16_t block[6][64], int motion_x, int motion_y) { - Wmv2Context *const w = (Wmv2Context *) s; + WMV2EncContext *const w = (WMV2EncContext *) s; int cbp, coded_cbp, i; int pred_x, pred_y; uint8_t *coded_block; @@ -214,17 +233,17 @@ void ff_wmv2_encode_mb(MpegEncContext *s, int16_t block[6][64], s->p_tex_bits += get_bits_diff(s); } -const AVCodec ff_wmv2_encoder = { - .name = "wmv2", - .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 8"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_WMV2, - .priv_class = &ff_mpv_enc_class, - .priv_data_size = sizeof(Wmv2Context), +const FFCodec ff_wmv2_encoder = { + .p.name = "wmv2", + .p.long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 8"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_WMV2, + .p.priv_class = &ff_mpv_enc_class, + .priv_data_size = sizeof(WMV2EncContext), .init = wmv2_encode_init, - .encode2 = ff_mpv_encode_picture, + FF_CODEC_ENCODE_CB(ff_mpv_encode_picture), .close = ff_mpv_encode_end, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, - .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, }; diff --git a/libavcodec/wmv2enc.h b/libavcodec/wmv2enc.h new file mode 100644 index 000000000..3f7f5104a --- /dev/null +++ b/libavcodec/wmv2enc.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2002 The FFmpeg Project + * + * 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_WMV2ENC_H +#define AVCODEC_WMV2ENC_H + +#include "mpegvideo.h" + +int ff_wmv2_encode_picture_header(MpegEncContext * s, int picture_number); +void ff_wmv2_encode_mb(MpegEncContext * s, int16_t block[6][64], + int motion_x, int motion_y); + + +#endif diff --git a/libavcodec/wnv1.c b/libavcodec/wnv1.c index 5d6c91d2d..6251c0018 100644 --- a/libavcodec/wnv1.c +++ b/libavcodec/wnv1.c @@ -28,6 +28,7 @@ #define BITSTREAM_READER_LE #include "avcodec.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" @@ -51,13 +52,11 @@ static inline int wnv1_get_code(GetBitContext *gb, int shift, int base_value) return base_value + v * (1 << shift); } -static int decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *p, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; - AVFrame * const p = data; GetBitContext gb; unsigned char *Y,*U,*V; int i, j, ret, shift; @@ -126,6 +125,9 @@ static av_cold int decode_init(AVCodecContext *avctx) { static AVOnce init_static_once = AV_ONCE_INIT; + if (avctx->width <= 1) + return AVERROR_INVALIDDATA; + avctx->pix_fmt = AV_PIX_FMT_YUV422P; ff_thread_once(&init_static_once, wnv1_init_static); @@ -133,13 +135,13 @@ static av_cold int decode_init(AVCodecContext *avctx) return 0; } -const AVCodec ff_wnv1_decoder = { - .name = "wnv1", - .long_name = NULL_IF_CONFIG_SMALL("Winnov WNV1"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_WNV1, +const FFCodec ff_wnv1_decoder = { + .p.name = "wnv1", + .p.long_name = NULL_IF_CONFIG_SMALL("Winnov WNV1"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_WNV1, .init = decode_init, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/wrapped_avframe.c b/libavcodec/wrapped_avframe.c index a7834b86e..06c274eed 100644 --- a/libavcodec/wrapped_avframe.c +++ b/libavcodec/wrapped_avframe.c @@ -25,8 +25,8 @@ */ #include "avcodec.h" +#include "codec_internal.h" #include "decode.h" -#include "internal.h" #include "libavutil/internal.h" #include "libavutil/frame.h" @@ -76,10 +76,10 @@ static int wrapped_avframe_encode(AVCodecContext *avctx, AVPacket *pkt, return 0; } -static int wrapped_avframe_decode(AVCodecContext *avctx, void *data, +static int wrapped_avframe_decode(AVCodecContext *avctx, AVFrame *out, int *got_frame, AVPacket *pkt) { - AVFrame *in, *out; + AVFrame *in; int err; if (!(pkt->flags & AV_PKT_FLAG_TRUSTED)) { @@ -91,7 +91,6 @@ static int wrapped_avframe_decode(AVCodecContext *avctx, void *data, return AVERROR(EINVAL); in = (AVFrame*)pkt->data; - out = data; err = ff_decode_frame_props(avctx, out); if (err < 0) @@ -99,30 +98,24 @@ 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; } -const AVCodec ff_wrapped_avframe_encoder = { - .name = "wrapped_avframe", - .long_name = NULL_IF_CONFIG_SMALL("AVFrame to AVPacket passthrough"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_WRAPPED_AVFRAME, - .encode2 = wrapped_avframe_encode, +const FFCodec ff_wrapped_avframe_encoder = { + .p.name = "wrapped_avframe", + .p.long_name = NULL_IF_CONFIG_SMALL("AVFrame to AVPacket passthrough"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_WRAPPED_AVFRAME, + FF_CODEC_ENCODE_CB(wrapped_avframe_encode), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; -const AVCodec ff_wrapped_avframe_decoder = { - .name = "wrapped_avframe", - .long_name = NULL_IF_CONFIG_SMALL("AVPacket to AVFrame passthrough"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_WRAPPED_AVFRAME, - .decode = wrapped_avframe_decode, +const FFCodec ff_wrapped_avframe_decoder = { + .p.name = "wrapped_avframe", + .p.long_name = NULL_IF_CONFIG_SMALL("AVPacket to AVFrame passthrough"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_WRAPPED_AVFRAME, + FF_CODEC_DECODE_CB(wrapped_avframe_decode), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/ws-snd1.c b/libavcodec/ws-snd1.c index aa8cd0f5f..8d072297e 100644 --- a/libavcodec/ws-snd1.c +++ b/libavcodec/ws-snd1.c @@ -25,6 +25,7 @@ #include "libavutil/common.h" #include "libavutil/intreadwrite.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" /** @@ -43,17 +44,16 @@ static const int8_t ws_adpcm_4bit[] = { static av_cold int ws_snd_decode_init(AVCodecContext *avctx) { - avctx->channels = 1; - avctx->channel_layout = AV_CH_LAYOUT_MONO; + av_channel_layout_uninit(&avctx->ch_layout); + avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; avctx->sample_fmt = AV_SAMPLE_FMT_U8; return 0; } -static int ws_snd_decode_frame(AVCodecContext *avctx, void *data, +static int ws_snd_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt) { - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; @@ -170,13 +170,13 @@ static int ws_snd_decode_frame(AVCodecContext *avctx, void *data, return buf_size; } -const AVCodec ff_ws_snd1_decoder = { - .name = "ws_snd1", - .long_name = NULL_IF_CONFIG_SMALL("Westwood Audio (SND1)"), - .type = AVMEDIA_TYPE_AUDIO, - .id = AV_CODEC_ID_WESTWOOD_SND1, +const FFCodec ff_ws_snd1_decoder = { + .p.name = "ws_snd1", + .p.long_name = NULL_IF_CONFIG_SMALL("Westwood Audio (SND1)"), + .p.type = AVMEDIA_TYPE_AUDIO, + .p.id = AV_CODEC_ID_WESTWOOD_SND1, .init = ws_snd_decode_init, - .decode = ws_snd_decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, + FF_CODEC_DECODE_CB(ws_snd_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/x86/ac3dsp.asm b/libavcodec/x86/ac3dsp.asm index 4ddaa9432..c11a94ca9 100644 --- a/libavcodec/x86/ac3dsp.asm +++ b/libavcodec/x86/ac3dsp.asm @@ -63,14 +63,7 @@ cglobal ac3_exponent_min, 3, 4, 2, exp, reuse_blks, expn, offset REP_RET %endmacro -%define LOOP_ALIGN -INIT_MMX mmx -AC3_EXPONENT_MIN -%if HAVE_MMXEXT_EXTERNAL %define LOOP_ALIGN ALIGN 16 -INIT_MMX mmxext -AC3_EXPONENT_MIN -%endif %if HAVE_SSE2_EXTERNAL INIT_XMM sse2 AC3_EXPONENT_MIN @@ -81,60 +74,6 @@ AC3_EXPONENT_MIN ; void ff_float_to_fixed24(int32_t *dst, const float *src, unsigned int len) ;----------------------------------------------------------------------------- -; The 3DNow! version is not bit-identical because pf2id uses truncation rather -; than round-to-nearest. -INIT_MMX 3dnow -cglobal float_to_fixed24, 3, 3, 0, dst, src, len - movq m0, [pf_1_24] -.loop: - movq m1, [srcq ] - movq m2, [srcq+8 ] - movq m3, [srcq+16] - movq m4, [srcq+24] - pfmul m1, m0 - pfmul m2, m0 - pfmul m3, m0 - pfmul m4, m0 - pf2id m1, m1 - pf2id m2, m2 - pf2id m3, m3 - pf2id m4, m4 - movq [dstq ], m1 - movq [dstq+8 ], m2 - movq [dstq+16], m3 - movq [dstq+24], m4 - add srcq, 32 - add dstq, 32 - sub lend, 8 - ja .loop - femms - RET - -INIT_XMM sse -cglobal float_to_fixed24, 3, 3, 3, dst, src, len - movaps m0, [pf_1_24] -.loop: - movaps m1, [srcq ] - movaps m2, [srcq+16] - mulps m1, m0 - mulps m2, m0 - cvtps2pi mm0, m1 - movhlps m1, m1 - cvtps2pi mm1, m1 - cvtps2pi mm2, m2 - movhlps m2, m2 - cvtps2pi mm3, m2 - movq [dstq ], mm0 - movq [dstq+ 8], mm1 - movq [dstq+16], mm2 - movq [dstq+24], mm3 - add srcq, 32 - add dstq, 32 - sub lend, 8 - ja .loop - emms - RET - INIT_XMM sse2 cglobal float_to_fixed24, 3, 3, 9, dst, src, len movaps m0, [pf_1_24] diff --git a/libavcodec/x86/ac3dsp_init.c b/libavcodec/x86/ac3dsp_init.c index 923c3e0a3..75a341bc9 100644 --- a/libavcodec/x86/ac3dsp_init.c +++ b/libavcodec/x86/ac3dsp_init.c @@ -22,15 +22,10 @@ #include "libavutil/attributes.h" #include "libavutil/x86/asm.h" #include "libavutil/x86/cpu.h" -#include "libavcodec/ac3.h" #include "libavcodec/ac3dsp.h" -void ff_ac3_exponent_min_mmx (uint8_t *exp, int num_reuse_blocks, int nb_coefs); -void ff_ac3_exponent_min_mmxext(uint8_t *exp, int num_reuse_blocks, int nb_coefs); void ff_ac3_exponent_min_sse2 (uint8_t *exp, int num_reuse_blocks, int nb_coefs); -void ff_float_to_fixed24_3dnow(int32_t *dst, const float *src, unsigned int len); -void ff_float_to_fixed24_sse (int32_t *dst, const float *src, unsigned int len); void ff_float_to_fixed24_sse2 (int32_t *dst, const float *src, unsigned int len); int ff_ac3_compute_mantissa_size_sse2(uint16_t mant_cnt[6][16]); @@ -42,20 +37,6 @@ av_cold void ff_ac3dsp_init_x86(AC3DSPContext *c, int bit_exact) { int cpu_flags = av_get_cpu_flags(); - if (EXTERNAL_MMX(cpu_flags)) { - c->ac3_exponent_min = ff_ac3_exponent_min_mmx; - } - if (EXTERNAL_AMD3DNOW(cpu_flags)) { - if (!bit_exact) { - c->float_to_fixed24 = ff_float_to_fixed24_3dnow; - } - } - if (EXTERNAL_MMXEXT(cpu_flags)) { - c->ac3_exponent_min = ff_ac3_exponent_min_mmxext; - } - if (EXTERNAL_SSE(cpu_flags)) { - c->float_to_fixed24 = ff_float_to_fixed24_sse; - } if (EXTERNAL_SSE2(cpu_flags)) { c->ac3_exponent_min = ff_ac3_exponent_min_sse2; c->float_to_fixed24 = ff_float_to_fixed24_sse2; diff --git a/libavcodec/x86/audiodsp.asm b/libavcodec/x86/audiodsp.asm index de395e5fa..b604b0443 100644 --- a/libavcodec/x86/audiodsp.asm +++ b/libavcodec/x86/audiodsp.asm @@ -23,8 +23,8 @@ SECTION .text -%macro SCALARPRODUCT 0 ; int ff_scalarproduct_int16(int16_t *v1, int16_t *v2, int order) +INIT_XMM sse2 cglobal scalarproduct_int16, 3,3,3, v1, v2, order add orderd, orderd add v1q, orderq @@ -42,16 +42,7 @@ cglobal scalarproduct_int16, 3,3,3, v1, v2, order jl .loop HADDD m2, m0 movd eax, m2 -%if mmsize == 8 - emms -%endif RET -%endmacro - -INIT_MMX mmxext -SCALARPRODUCT -INIT_XMM sse2 -SCALARPRODUCT ;----------------------------------------------------------------------------- @@ -117,8 +108,6 @@ cglobal vector_clip_int32%5, 5,5,%1, dst, src, min, max, len REP_RET %endmacro -INIT_MMX mmx -VECTOR_CLIP_INT32 0, 1, 0, 0 INIT_XMM sse2 VECTOR_CLIP_INT32 6, 1, 0, 0, _int VECTOR_CLIP_INT32 6, 2, 0, 1 diff --git a/libavcodec/x86/audiodsp_init.c b/libavcodec/x86/audiodsp_init.c index 98e296c26..aa5e43e57 100644 --- a/libavcodec/x86/audiodsp_init.c +++ b/libavcodec/x86/audiodsp_init.c @@ -24,13 +24,9 @@ #include "libavutil/x86/cpu.h" #include "libavcodec/audiodsp.h" -int32_t ff_scalarproduct_int16_mmxext(const int16_t *v1, const int16_t *v2, - int order); int32_t ff_scalarproduct_int16_sse2(const int16_t *v1, const int16_t *v2, int order); -void ff_vector_clip_int32_mmx(int32_t *dst, const int32_t *src, - int32_t min, int32_t max, unsigned int len); void ff_vector_clip_int32_sse2(int32_t *dst, const int32_t *src, int32_t min, int32_t max, unsigned int len); void ff_vector_clip_int32_int_sse2(int32_t *dst, const int32_t *src, @@ -44,12 +40,6 @@ av_cold void ff_audiodsp_init_x86(AudioDSPContext *c) { int cpu_flags = av_get_cpu_flags(); - if (EXTERNAL_MMX(cpu_flags)) - c->vector_clip_int32 = ff_vector_clip_int32_mmx; - - if (EXTERNAL_MMXEXT(cpu_flags)) - c->scalarproduct_int16 = ff_scalarproduct_int16_mmxext; - if (EXTERNAL_SSE(cpu_flags)) c->vector_clipf = ff_vector_clipf_sse; diff --git a/libavcodec/x86/blockdsp.asm b/libavcodec/x86/blockdsp.asm index 9d203df8f..e380308d4 100644 --- a/libavcodec/x86/blockdsp.asm +++ b/libavcodec/x86/blockdsp.asm @@ -46,9 +46,6 @@ cglobal clear_block, 1, 1, %1, blocks RET %endmacro -INIT_MMX mmx -%define ZERO pxor -CLEAR_BLOCK 0, 4 INIT_XMM sse %define ZERO xorps CLEAR_BLOCK 1, 2 @@ -78,9 +75,6 @@ cglobal clear_blocks, 1, 2, %1, blocks, len RET %endmacro -INIT_MMX mmx -%define ZERO pxor -CLEAR_BLOCKS 0 INIT_XMM sse %define ZERO xorps CLEAR_BLOCKS 1 diff --git a/libavcodec/x86/blockdsp_init.c b/libavcodec/x86/blockdsp_init.c index 8b01a447c..b0ff9376d 100644 --- a/libavcodec/x86/blockdsp_init.c +++ b/libavcodec/x86/blockdsp_init.c @@ -20,16 +20,12 @@ #include "config.h" #include "libavutil/attributes.h" -#include "libavutil/internal.h" #include "libavutil/cpu.h" #include "libavutil/x86/cpu.h" #include "libavcodec/blockdsp.h" -#include "libavcodec/version.h" -void ff_clear_block_mmx(int16_t *block); void ff_clear_block_sse(int16_t *block); void ff_clear_block_avx(int16_t *block); -void ff_clear_blocks_mmx(int16_t *blocks); void ff_clear_blocks_sse(int16_t *blocks); void ff_clear_blocks_avx(int16_t *blocks); @@ -39,15 +35,6 @@ av_cold void ff_blockdsp_init_x86(BlockDSPContext *c, #if HAVE_X86ASM int cpu_flags = av_get_cpu_flags(); - if (EXTERNAL_MMX(cpu_flags)) { - c->clear_block = ff_clear_block_mmx; - c->clear_blocks = ff_clear_blocks_mmx; - } - - /* XvMCCreateBlocks() may not allocate 16-byte aligned blocks */ - if (CONFIG_XVMC && avctx->hwaccel && avctx->hwaccel->decode_mb) - return; - if (EXTERNAL_SSE(cpu_flags)) { c->clear_block = ff_clear_block_sse; c->clear_blocks = ff_clear_blocks_sse; diff --git a/libavcodec/x86/cavsdsp.c b/libavcodec/x86/cavsdsp.c index f974f93fc..7ceb51a23 100644 --- a/libavcodec/x86/cavsdsp.c +++ b/libavcodec/x86/cavsdsp.c @@ -36,16 +36,7 @@ #include "config.h" -#if HAVE_MMX_EXTERNAL - -void ff_cavs_idct8_mmx(int16_t *out, const int16_t *in); - -static void cavs_idct8_add_mmx(uint8_t *dst, int16_t *block, ptrdiff_t stride) -{ - LOCAL_ALIGNED(16, int16_t, b2, [64]); - ff_cavs_idct8_mmx(b2, block); - ff_add_pixels_clamped_mmx(b2, dst, stride); -} +#if HAVE_SSE2_EXTERNAL void ff_cavs_idct8_sse2(int16_t *out, const int16_t *in); @@ -56,9 +47,9 @@ static void cavs_idct8_add_sse2(uint8_t *dst, int16_t *block, ptrdiff_t stride) ff_add_pixels_clamped_sse2(b2, dst, stride); } -#endif /* HAVE_MMX_EXTERNAL */ +#endif /* HAVE_SSE2_EXTERNAL */ -#if (HAVE_MMXEXT_INLINE || HAVE_AMD3DNOW_INLINE) +#if HAVE_MMXEXT_INLINE /***************************************************************************** * @@ -326,7 +317,7 @@ static void OPNAME ## cavs_qpel ## SIZE ## _mc03_ ## MMX(uint8_t *dst, const uin "pavgb " #temp ", " #a " \n\t"\ "mov" #size " " #a ", " #b " \n\t" -#endif /* (HAVE_MMXEXT_INLINE || HAVE_AMD3DNOW_INLINE) */ +#endif /* HAVE_MMXEXT_INLINE */ #if HAVE_MMX_EXTERNAL static void put_cavs_qpel8_mc00_mmx(uint8_t *dst, const uint8_t *src, @@ -335,36 +326,12 @@ static void put_cavs_qpel8_mc00_mmx(uint8_t *dst, const uint8_t *src, ff_put_pixels8_mmx(dst, src, stride, 8); } -static void avg_cavs_qpel8_mc00_mmx(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride) -{ - ff_avg_pixels8_mmx(dst, src, stride, 8); -} - static void avg_cavs_qpel8_mc00_mmxext(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) { ff_avg_pixels8_mmxext(dst, src, stride, 8); } -static void put_cavs_qpel16_mc00_mmx(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride) -{ - ff_put_pixels16_mmx(dst, src, stride, 16); -} - -static void avg_cavs_qpel16_mc00_mmx(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride) -{ - ff_avg_pixels16_mmx(dst, src, stride, 16); -} - -static void avg_cavs_qpel16_mc00_mmxext(uint8_t *dst, const uint8_t *src, - ptrdiff_t stride) -{ - ff_avg_pixels16_mmxext(dst, src, stride, 16); -} - static void put_cavs_qpel16_mc00_sse2(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) { @@ -382,13 +349,7 @@ static av_cold void cavsdsp_init_mmx(CAVSDSPContext *c, AVCodecContext *avctx) { #if HAVE_MMX_EXTERNAL - c->put_cavs_qpel_pixels_tab[0][0] = put_cavs_qpel16_mc00_mmx; c->put_cavs_qpel_pixels_tab[1][0] = put_cavs_qpel8_mc00_mmx; - c->avg_cavs_qpel_pixels_tab[0][0] = avg_cavs_qpel16_mc00_mmx; - c->avg_cavs_qpel_pixels_tab[1][0] = avg_cavs_qpel8_mc00_mmx; - - c->cavs_idct8_add = cavs_idct8_add_mmx; - c->idct_perm = FF_IDCT_PERM_TRANSPOSE; #endif /* HAVE_MMX_EXTERNAL */ } @@ -408,25 +369,6 @@ CAVS_MC(avg_, 8, mmxext) CAVS_MC(avg_, 16, mmxext) #endif /* HAVE_MMXEXT_INLINE */ -#if HAVE_AMD3DNOW_INLINE -QPEL_CAVS(put_, PUT_OP, 3dnow) -QPEL_CAVS(avg_, AVG_3DNOW_OP, 3dnow) - -CAVS_MC(put_, 8, 3dnow) -CAVS_MC(put_, 16,3dnow) -CAVS_MC(avg_, 8, 3dnow) -CAVS_MC(avg_, 16,3dnow) - -static av_cold void cavsdsp_init_3dnow(CAVSDSPContext *c, - AVCodecContext *avctx) -{ - DSPFUNC(put, 0, 16, 3dnow); - DSPFUNC(put, 1, 8, 3dnow); - DSPFUNC(avg, 0, 16, 3dnow); - DSPFUNC(avg, 1, 8, 3dnow); -} -#endif /* HAVE_AMD3DNOW_INLINE */ - av_cold void ff_cavsdsp_init_x86(CAVSDSPContext *c, AVCodecContext *avctx) { av_unused int cpu_flags = av_get_cpu_flags(); @@ -434,10 +376,6 @@ av_cold void ff_cavsdsp_init_x86(CAVSDSPContext *c, AVCodecContext *avctx) if (X86_MMX(cpu_flags)) cavsdsp_init_mmx(c, avctx); -#if HAVE_AMD3DNOW_INLINE - if (INLINE_AMD3DNOW(cpu_flags)) - cavsdsp_init_3dnow(c, avctx); -#endif /* HAVE_AMD3DNOW_INLINE */ #if HAVE_MMXEXT_INLINE if (INLINE_MMXEXT(cpu_flags)) { DSPFUNC(put, 0, 16, mmxext); @@ -448,7 +386,6 @@ av_cold void ff_cavsdsp_init_x86(CAVSDSPContext *c, AVCodecContext *avctx) #endif #if HAVE_MMX_EXTERNAL if (EXTERNAL_MMXEXT(cpu_flags)) { - c->avg_cavs_qpel_pixels_tab[0][0] = avg_cavs_qpel16_mc00_mmxext; c->avg_cavs_qpel_pixels_tab[1][0] = avg_cavs_qpel8_mc00_mmxext; } #endif diff --git a/libavcodec/x86/cavsidct.asm b/libavcodec/x86/cavsidct.asm index 6c768c264..f133c7354 100644 --- a/libavcodec/x86/cavsidct.asm +++ b/libavcodec/x86/cavsidct.asm @@ -107,68 +107,6 @@ SECTION .text SUMSUB_BA w, 1, 0 ; m1 = dst3, m0 = dst4 %endmacro -INIT_MMX mmx -cglobal cavs_idct8, 2, 4, 8, 8 * 16, out, in, cnt, tmp - mov cntd, 2 - mov tmpq, rsp - -.loop_1: - CAVS_IDCT8_1D inq, [pw_4] - psraw m7, 3 - psraw m6, 3 - psraw m5, 3 - psraw m4, 3 - psraw m3, 3 - psraw m2, 3 - psraw m1, 3 - psraw m0, 3 - mova [tmpq], m7 - TRANSPOSE4x4W 0, 2, 4, 6, 7 - mova [tmpq+1*8], m0 - mova [tmpq+3*8], m2 - mova [tmpq+5*8], m4 - mova [tmpq+7*8], m6 - mova m7, [tmpq] - TRANSPOSE4x4W 7, 5, 3, 1, 0 - mova [tmpq+0*8], m7 - mova [tmpq+2*8], m5 - mova [tmpq+4*8], m3 - mova [tmpq+6*8], m1 - - add inq, mmsize - add tmpq, 64 - dec cntd - jg .loop_1 - - mov cntd, 2 - mov tmpq, rsp -.loop_2: - CAVS_IDCT8_1D tmpq, [pw_64] - psraw m7, 7 - psraw m6, 7 - psraw m5, 7 - psraw m4, 7 - psraw m3, 7 - psraw m2, 7 - psraw m1, 7 - psraw m0, 7 - - mova [outq+0*16], m7 - mova [outq+1*16], m5 - mova [outq+2*16], m3 - mova [outq+3*16], m1 - mova [outq+4*16], m0 - mova [outq+5*16], m2 - mova [outq+6*16], m4 - mova [outq+7*16], m6 - - add outq, mmsize - add tmpq, mmsize - dec cntd - jg .loop_2 - - RET - INIT_XMM sse2 cglobal cavs_idct8, 2, 2, 8 + ARCH_X86_64, 0 - 8 * 16, out, in CAVS_IDCT8_1D inq, [pw_4] diff --git a/libavcodec/x86/dcadsp.asm b/libavcodec/x86/dcadsp.asm index 055361a76..de9fd6f34 100644 --- a/libavcodec/x86/dcadsp.asm +++ b/libavcodec/x86/dcadsp.asm @@ -42,22 +42,13 @@ cglobal lfe_fir0_float, 4, 6, 12 + cpuflag(fma3)*4, samples, lfe, coeff, nblocks cvtdq2ps m5, [lfeq ] shufps m7, m4, m4, q0123 shufps m6, m5, m5, q0123 -%elif cpuflag(sse2) +%else movu m4, [lfeq+16] movu m5, [lfeq ] cvtdq2ps m4, m4 cvtdq2ps m5, m5 pshufd m7, m4, q0123 pshufd m6, m5, q0123 -%else - cvtpi2ps m4, [lfeq+16] - cvtpi2ps m0, [lfeq+24] - cvtpi2ps m5, [lfeq ] - cvtpi2ps m1, [lfeq+8 ] - shufps m4, m0, q1010 - shufps m5, m1, q1010 - shufps m7, m4, m4, q0123 - shufps m6, m5, m5, q0123 %endif .inner_loop: @@ -206,10 +197,6 @@ cglobal lfe_fir0_float, 4, 6, 12 + cpuflag(fma3)*4, samples, lfe, coeff, nblocks RET %endmacro -%if ARCH_X86_32 -INIT_XMM sse -LFE_FIR0_FLOAT -%endif INIT_XMM sse2 LFE_FIR0_FLOAT %if HAVE_AVX_EXTERNAL @@ -235,7 +222,7 @@ cglobal lfe_fir1_float, 4, 6, 10, samples, lfe, coeff, nblocks, cnt1, cnt2 %if cpuflag(avx) cvtdq2ps m4, [lfeq] shufps m5, m4, m4, q0123 -%elif cpuflag(sse2) +%else movu m4, [lfeq] cvtdq2ps m4, m4 pshufd m5, m4, q0123 diff --git a/libavcodec/x86/dcadsp_init.c b/libavcodec/x86/dcadsp_init.c index fc10fb8bc..0c78dd1c9 100644 --- a/libavcodec/x86/dcadsp_init.c +++ b/libavcodec/x86/dcadsp_init.c @@ -27,7 +27,6 @@ void ff_lfe_fir0_float_##opt(float *pcm_samples, int32_t *lfe_samples, \ void ff_lfe_fir1_float_##opt(float *pcm_samples, int32_t *lfe_samples, \ const float *filter_coeff, ptrdiff_t npcmblocks); -LFE_FIR_FLOAT_FUNC(sse) LFE_FIR_FLOAT_FUNC(sse2) LFE_FIR_FLOAT_FUNC(sse3) LFE_FIR_FLOAT_FUNC(avx) @@ -37,8 +36,6 @@ av_cold void ff_dcadsp_init_x86(DCADSPContext *s) { int cpu_flags = av_get_cpu_flags(); - if (ARCH_X86_32 && EXTERNAL_SSE(cpu_flags)) - s->lfe_fir_float[0] = ff_lfe_fir0_float_sse; if (EXTERNAL_SSE2(cpu_flags)) s->lfe_fir_float[0] = ff_lfe_fir0_float_sse2; if (EXTERNAL_SSE3(cpu_flags)) diff --git a/libavcodec/x86/dct32.asm b/libavcodec/x86/dct32.asm index 21e2f21c9..37fba5154 100644 --- a/libavcodec/x86/dct32.asm +++ b/libavcodec/x86/dct32.asm @@ -387,7 +387,7 @@ INIT_XMM %endif -; void ff_dct32_float_sse(FFTSample *out, const FFTSample *in) +; void ff_dct32_float(FFTSample *out, const FFTSample *in) %macro DCT32_FUNC 0 cglobal dct32_float, 2, 3, 16, out, in, tmp ; pass 1 @@ -474,18 +474,8 @@ cglobal dct32_float, 2, 3, 16, out, in, tmp %endmacro %macro LOAD_INV 2 -%if cpuflag(sse2) pshufd %1, %2, 0x1b -%elif cpuflag(sse) - movaps %1, %2 - shufps %1, %1, 0x1b -%endif %endmacro -%if ARCH_X86_32 -INIT_XMM sse -DCT32_FUNC -%endif - INIT_XMM sse2 DCT32_FUNC diff --git a/libavcodec/x86/dct_init.c b/libavcodec/x86/dct_init.c index c31ef9223..d0e4b34dd 100644 --- a/libavcodec/x86/dct_init.c +++ b/libavcodec/x86/dct_init.c @@ -22,7 +22,6 @@ #include "libavutil/x86/cpu.h" #include "libavcodec/dct.h" -void ff_dct32_float_sse(FFTSample *out, const FFTSample *in); void ff_dct32_float_sse2(FFTSample *out, const FFTSample *in); void ff_dct32_float_avx(FFTSample *out, const FFTSample *in); @@ -30,10 +29,6 @@ av_cold void ff_dct_init_x86(DCTContext *s) { int cpu_flags = av_get_cpu_flags(); -#if ARCH_X86_32 - if (EXTERNAL_SSE(cpu_flags)) - s->dct32 = ff_dct32_float_sse; -#endif if (EXTERNAL_SSE2(cpu_flags)) s->dct32 = ff_dct32_float_sse2; if (EXTERNAL_AVX_FAST(cpu_flags)) diff --git a/libavcodec/x86/dirac_dwt.asm b/libavcodec/x86/dirac_dwt.asm index 22a5c2bbb..6c8b3c0d8 100644 --- a/libavcodec/x86/dirac_dwt.asm +++ b/libavcodec/x86/dirac_dwt.asm @@ -293,14 +293,6 @@ cglobal horizontal_compose_dd97i_ssse3, 3,6,8, b, tmp, w, x, w2, b_w2 REP_RET -%if ARCH_X86_64 == 0 -INIT_MMX -COMPOSE_VERTICAL mmx -HAAR_HORIZONTAL mmx, 0 -HAAR_HORIZONTAL mmx, 1 -%endif - -;;INIT_XMM INIT_XMM COMPOSE_VERTICAL sse2 HAAR_HORIZONTAL sse2, 0 diff --git a/libavcodec/x86/dirac_dwt_init.c b/libavcodec/x86/dirac_dwt_init.c index 49a6380ad..920061828 100644 --- a/libavcodec/x86/dirac_dwt_init.c +++ b/libavcodec/x86/dirac_dwt_init.c @@ -134,9 +134,6 @@ static void horizontal_compose_haar1i##ext(uint8_t *_b, uint8_t *_tmp, int w)\ \ #if HAVE_X86ASM -#if !ARCH_X86_64 -COMPOSE_VERTICAL(_mmx, 4) -#endif COMPOSE_VERTICAL(_sse2, 8) @@ -163,34 +160,6 @@ void ff_spatial_idwt_init_x86(DWTContext *d, enum dwt_type type) #if HAVE_X86ASM int mm_flags = av_get_cpu_flags(); -#if !ARCH_X86_64 - if (!(mm_flags & AV_CPU_FLAG_MMX)) - return; - - switch (type) { - case DWT_DIRAC_DD9_7: - d->vertical_compose_l0 = (void*)vertical_compose53iL0_mmx; - d->vertical_compose_h0 = (void*)vertical_compose_dd97iH0_mmx; - break; - case DWT_DIRAC_LEGALL5_3: - d->vertical_compose_l0 = (void*)vertical_compose53iL0_mmx; - d->vertical_compose_h0 = (void*)vertical_compose_dirac53iH0_mmx; - break; - case DWT_DIRAC_DD13_7: - d->vertical_compose_l0 = (void*)vertical_compose_dd137iL0_mmx; - d->vertical_compose_h0 = (void*)vertical_compose_dd97iH0_mmx; - break; - case DWT_DIRAC_HAAR0: - d->vertical_compose = (void*)vertical_compose_haar_mmx; - d->horizontal_compose = horizontal_compose_haar0i_mmx; - break; - case DWT_DIRAC_HAAR1: - d->vertical_compose = (void*)vertical_compose_haar_mmx; - d->horizontal_compose = horizontal_compose_haar1i_mmx; - break; - } -#endif - if (!(mm_flags & AV_CPU_FLAG_SSE2)) return; diff --git a/libavcodec/x86/diracdsp.asm b/libavcodec/x86/diracdsp.asm index 17145baf8..e5e2b1184 100644 --- a/libavcodec/x86/diracdsp.asm +++ b/libavcodec/x86/diracdsp.asm @@ -248,14 +248,6 @@ cglobal add_dirac_obmc%1_%2, 6,6,5, dst, src, stride, obmc, yblen %endm INIT_MMX -%if ARCH_X86_64 == 0 -PUT_RECT mmx -ADD_RECT mmx - -HPEL_FILTER mmx -ADD_OBMC 32, mmx -ADD_OBMC 16, mmx -%endif ADD_OBMC 8, mmx INIT_XMM diff --git a/libavcodec/x86/diracdsp_init.c b/libavcodec/x86/diracdsp_init.c index 8baacf312..f678759dc 100644 --- a/libavcodec/x86/diracdsp_init.c +++ b/libavcodec/x86/diracdsp_init.c @@ -22,19 +22,14 @@ #include "libavcodec/diracdsp.h" #include "fpel.h" -void ff_add_rect_clamped_mmx(uint8_t *, const uint16_t *, int, const int16_t *, int, int, int); void ff_add_rect_clamped_sse2(uint8_t *, const uint16_t *, int, const int16_t *, int, int, int); void ff_add_dirac_obmc8_mmx(uint16_t *dst, const uint8_t *src, int stride, const uint8_t *obmc_weight, int yblen); -void ff_add_dirac_obmc16_mmx(uint16_t *dst, const uint8_t *src, int stride, const uint8_t *obmc_weight, int yblen); -void ff_add_dirac_obmc32_mmx(uint16_t *dst, const uint8_t *src, int stride, const uint8_t *obmc_weight, int yblen); void ff_add_dirac_obmc16_sse2(uint16_t *dst, const uint8_t *src, int stride, const uint8_t *obmc_weight, int yblen); void ff_add_dirac_obmc32_sse2(uint16_t *dst, const uint8_t *src, int stride, const uint8_t *obmc_weight, int yblen); -void ff_put_rect_clamped_mmx(uint8_t *dst, int dst_stride, const int16_t *src, int src_stride, int width, int height); void ff_put_rect_clamped_sse2(uint8_t *dst, int dst_stride, const int16_t *src, int src_stride, int width, int height); -void ff_put_signed_rect_clamped_mmx(uint8_t *dst, int dst_stride, const int16_t *src, int src_stride, int width, int height); void ff_put_signed_rect_clamped_sse2(uint8_t *dst, int dst_stride, const int16_t *src, int src_stride, int width, int height); void ff_put_signed_rect_clamped_10_sse4(uint8_t *dst, int dst_stride, const uint8_t *src, int src_stride, int width, int height); @@ -87,16 +82,9 @@ static void OPNAME ## _dirac_pixels32_ ## EXT(uint8_t *dst, const uint8_t *src[5 }\ } -DIRAC_PIXOP(put, mmx) -DIRAC_PIXOP(avg, mmx) -DIRAC_PIXOP(avg, mmxext) - DIRAC_PIXOP(put, sse2) DIRAC_PIXOP(avg, sse2) -#if !ARCH_X86_64 -HPEL_FILTER(8, mmx) -#endif HPEL_FILTER(16, sse2) #endif // HAVE_X86ASM @@ -108,19 +96,6 @@ void ff_diracdsp_init_x86(DiracDSPContext* c) if (EXTERNAL_MMX(mm_flags)) { c->add_dirac_obmc[0] = ff_add_dirac_obmc8_mmx; -#if !ARCH_X86_64 - c->add_dirac_obmc[1] = ff_add_dirac_obmc16_mmx; - c->add_dirac_obmc[2] = ff_add_dirac_obmc32_mmx; - c->dirac_hpel_filter = dirac_hpel_filter_mmx; - c->add_rect_clamped = ff_add_rect_clamped_mmx; - c->put_signed_rect_clamped[0] = (void *)ff_put_signed_rect_clamped_mmx; -#endif - PIXFUNC(put, 0, mmx); - PIXFUNC(avg, 0, mmx); - } - - if (EXTERNAL_MMXEXT(mm_flags)) { - PIXFUNC(avg, 0, mmxext); } if (EXTERNAL_SSE2(mm_flags)) { diff --git a/libavcodec/x86/fdct.c b/libavcodec/x86/fdct.c index 033ff1ccc..f4677ff4b 100644 --- a/libavcodec/x86/fdct.c +++ b/libavcodec/x86/fdct.c @@ -30,13 +30,14 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config.h" #include "libavutil/attributes.h" -#include "libavutil/common.h" +#include "libavutil/macros.h" #include "libavutil/mem_internal.h" #include "libavutil/x86/asm.h" #include "fdct.h" -#if HAVE_MMX_INLINE +#if HAVE_SSE2_INLINE ////////////////////////////////////////////////////////////////////// // @@ -70,8 +71,6 @@ DECLARE_ALIGNED(16, static const int16_t, ocos_4_16)[8] = { DECLARE_ALIGNED(16, static const int16_t, fdct_one_corr)[8] = { X8(1) }; -DECLARE_ALIGNED(8, static const int32_t, fdct_r_row)[2] = {RND_FRW_ROW, RND_FRW_ROW }; - static const struct { DECLARE_ALIGNED(16, const int32_t, fdct_r_row_sse2)[4]; @@ -81,80 +80,6 @@ static const struct }}; //DECLARE_ALIGNED(16, static const long, fdct_r_row_sse2)[4] = {RND_FRW_ROW, RND_FRW_ROW, RND_FRW_ROW, RND_FRW_ROW}; -DECLARE_ALIGNED(8, static const int16_t, tab_frw_01234567)[] = { // forward_dct coeff table - 16384, 16384, 22725, 19266, - 16384, 16384, 12873, 4520, - 21407, 8867, 19266, -4520, - -8867, -21407, -22725, -12873, - 16384, -16384, 12873, -22725, - -16384, 16384, 4520, 19266, - 8867, -21407, 4520, -12873, - 21407, -8867, 19266, -22725, - - 22725, 22725, 31521, 26722, - 22725, 22725, 17855, 6270, - 29692, 12299, 26722, -6270, - -12299, -29692, -31521, -17855, - 22725, -22725, 17855, -31521, - -22725, 22725, 6270, 26722, - 12299, -29692, 6270, -17855, - 29692, -12299, 26722, -31521, - - 21407, 21407, 29692, 25172, - 21407, 21407, 16819, 5906, - 27969, 11585, 25172, -5906, - -11585, -27969, -29692, -16819, - 21407, -21407, 16819, -29692, - -21407, 21407, 5906, 25172, - 11585, -27969, 5906, -16819, - 27969, -11585, 25172, -29692, - - 19266, 19266, 26722, 22654, - 19266, 19266, 15137, 5315, - 25172, 10426, 22654, -5315, - -10426, -25172, -26722, -15137, - 19266, -19266, 15137, -26722, - -19266, 19266, 5315, 22654, - 10426, -25172, 5315, -15137, - 25172, -10426, 22654, -26722, - - 16384, 16384, 22725, 19266, - 16384, 16384, 12873, 4520, - 21407, 8867, 19266, -4520, - -8867, -21407, -22725, -12873, - 16384, -16384, 12873, -22725, - -16384, 16384, 4520, 19266, - 8867, -21407, 4520, -12873, - 21407, -8867, 19266, -22725, - - 19266, 19266, 26722, 22654, - 19266, 19266, 15137, 5315, - 25172, 10426, 22654, -5315, - -10426, -25172, -26722, -15137, - 19266, -19266, 15137, -26722, - -19266, 19266, 5315, 22654, - 10426, -25172, 5315, -15137, - 25172, -10426, 22654, -26722, - - 21407, 21407, 29692, 25172, - 21407, 21407, 16819, 5906, - 27969, 11585, 25172, -5906, - -11585, -27969, -29692, -16819, - 21407, -21407, 16819, -29692, - -21407, 21407, 5906, 25172, - 11585, -27969, 5906, -16819, - 27969, -11585, 25172, -29692, - - 22725, 22725, 31521, 26722, - 22725, 22725, 17855, 6270, - 29692, 12299, 26722, -6270, - -12299, -29692, -31521, -17855, - 22725, -22725, 17855, -31521, - -22725, 22725, 6270, 26722, - 12299, -29692, 6270, -17855, - 29692, -12299, 26722, -31521, -}; - static const struct { DECLARE_ALIGNED(16, const int16_t, tab_frw_01234567_sse2)[256]; @@ -374,7 +299,6 @@ static av_always_inline void fdct_col_##cpu(const int16_t *in, int16_t *out, int "r" (out + offset), "r" (ocos_4_16)); \ } -FDCT_COL(mmx, mm, movq) FDCT_COL(sse2, xmm, movdqa) static av_always_inline void fdct_row_sse2(const int16_t *in, int16_t *out) @@ -442,148 +366,6 @@ static av_always_inline void fdct_row_sse2(const int16_t *in, int16_t *out) ); } -static av_always_inline void fdct_row_mmxext(const int16_t *in, int16_t *out, - const int16_t *table) -{ - __asm__ volatile ( - "pshufw $0x1B, 8(%0), %%mm5 \n\t" - "movq (%0), %%mm0 \n\t" - "movq %%mm0, %%mm1 \n\t" - "paddsw %%mm5, %%mm0 \n\t" - "psubsw %%mm5, %%mm1 \n\t" - "movq %%mm0, %%mm2 \n\t" - "punpckldq %%mm1, %%mm0 \n\t" - "punpckhdq %%mm1, %%mm2 \n\t" - "movq (%1), %%mm1 \n\t" - "movq 8(%1), %%mm3 \n\t" - "movq 16(%1), %%mm4 \n\t" - "movq 24(%1), %%mm5 \n\t" - "movq 32(%1), %%mm6 \n\t" - "movq 40(%1), %%mm7 \n\t" - "pmaddwd %%mm0, %%mm1 \n\t" - "pmaddwd %%mm2, %%mm3 \n\t" - "pmaddwd %%mm0, %%mm4 \n\t" - "pmaddwd %%mm2, %%mm5 \n\t" - "pmaddwd %%mm0, %%mm6 \n\t" - "pmaddwd %%mm2, %%mm7 \n\t" - "pmaddwd 48(%1), %%mm0 \n\t" - "pmaddwd 56(%1), %%mm2 \n\t" - "paddd %%mm1, %%mm3 \n\t" - "paddd %%mm4, %%mm5 \n\t" - "paddd %%mm6, %%mm7 \n\t" - "paddd %%mm0, %%mm2 \n\t" - "movq (%2), %%mm0 \n\t" - "paddd %%mm0, %%mm3 \n\t" - "paddd %%mm0, %%mm5 \n\t" - "paddd %%mm0, %%mm7 \n\t" - "paddd %%mm0, %%mm2 \n\t" - "psrad $"S(SHIFT_FRW_ROW)", %%mm3 \n\t" - "psrad $"S(SHIFT_FRW_ROW)", %%mm5 \n\t" - "psrad $"S(SHIFT_FRW_ROW)", %%mm7 \n\t" - "psrad $"S(SHIFT_FRW_ROW)", %%mm2 \n\t" - "packssdw %%mm5, %%mm3 \n\t" - "packssdw %%mm2, %%mm7 \n\t" - "movq %%mm3, (%3) \n\t" - "movq %%mm7, 8(%3) \n\t" - : - : "r" (in), "r" (table), "r" (fdct_r_row), "r" (out)); -} - -static av_always_inline void fdct_row_mmx(const int16_t *in, int16_t *out, const int16_t *table) -{ - //FIXME reorder (I do not have an old MMX-only CPU here to benchmark ...) - __asm__ volatile( - "movd 12(%0), %%mm1 \n\t" - "punpcklwd 8(%0), %%mm1 \n\t" - "movq %%mm1, %%mm2 \n\t" - "psrlq $0x20, %%mm1 \n\t" - "movq 0(%0), %%mm0 \n\t" - "punpcklwd %%mm2, %%mm1 \n\t" - "movq %%mm0, %%mm5 \n\t" - "paddsw %%mm1, %%mm0 \n\t" - "psubsw %%mm1, %%mm5 \n\t" - "movq %%mm0, %%mm2 \n\t" - "punpckldq %%mm5, %%mm0 \n\t" - "punpckhdq %%mm5, %%mm2 \n\t" - "movq 0(%1), %%mm1 \n\t" - "movq 8(%1), %%mm3 \n\t" - "movq 16(%1), %%mm4 \n\t" - "movq 24(%1), %%mm5 \n\t" - "movq 32(%1), %%mm6 \n\t" - "movq 40(%1), %%mm7 \n\t" - "pmaddwd %%mm0, %%mm1 \n\t" - "pmaddwd %%mm2, %%mm3 \n\t" - "pmaddwd %%mm0, %%mm4 \n\t" - "pmaddwd %%mm2, %%mm5 \n\t" - "pmaddwd %%mm0, %%mm6 \n\t" - "pmaddwd %%mm2, %%mm7 \n\t" - "pmaddwd 48(%1), %%mm0 \n\t" - "pmaddwd 56(%1), %%mm2 \n\t" - "paddd %%mm1, %%mm3 \n\t" - "paddd %%mm4, %%mm5 \n\t" - "paddd %%mm6, %%mm7 \n\t" - "paddd %%mm0, %%mm2 \n\t" - "movq (%2), %%mm0 \n\t" - "paddd %%mm0, %%mm3 \n\t" - "paddd %%mm0, %%mm5 \n\t" - "paddd %%mm0, %%mm7 \n\t" - "paddd %%mm0, %%mm2 \n\t" - "psrad $"S(SHIFT_FRW_ROW)", %%mm3 \n\t" - "psrad $"S(SHIFT_FRW_ROW)", %%mm5 \n\t" - "psrad $"S(SHIFT_FRW_ROW)", %%mm7 \n\t" - "psrad $"S(SHIFT_FRW_ROW)", %%mm2 \n\t" - "packssdw %%mm5, %%mm3 \n\t" - "packssdw %%mm2, %%mm7 \n\t" - "movq %%mm3, 0(%3) \n\t" - "movq %%mm7, 8(%3) \n\t" - : - : "r" (in), "r" (table), "r" (fdct_r_row), "r" (out)); -} - -void ff_fdct_mmx(int16_t *block) -{ - DECLARE_ALIGNED(8, int64_t, align_tmp)[16]; - int16_t * block1= (int16_t*)align_tmp; - const int16_t *table= tab_frw_01234567; - int i; - - fdct_col_mmx(block, block1, 0); - fdct_col_mmx(block, block1, 4); - - for(i=8;i>0;i--) { - fdct_row_mmx(block1, block, table); - block1 += 8; - table += 32; - block += 8; - } -} - -#endif /* HAVE_MMX_INLINE */ - -#if HAVE_MMXEXT_INLINE - -void ff_fdct_mmxext(int16_t *block) -{ - DECLARE_ALIGNED(8, int64_t, align_tmp)[16]; - int16_t *block1= (int16_t*)align_tmp; - const int16_t *table= tab_frw_01234567; - int i; - - fdct_col_mmx(block, block1, 0); - fdct_col_mmx(block, block1, 4); - - for(i=8;i>0;i--) { - fdct_row_mmxext(block1, block, table); - block1 += 8; - table += 32; - block += 8; - } -} - -#endif /* HAVE_MMXEXT_INLINE */ - -#if HAVE_SSE2_INLINE - void ff_fdct_sse2(int16_t *block) { DECLARE_ALIGNED(16, int64_t, align_tmp)[16]; diff --git a/libavcodec/x86/fdct.h b/libavcodec/x86/fdct.h index 648cdc535..164d4fb30 100644 --- a/libavcodec/x86/fdct.h +++ b/libavcodec/x86/fdct.h @@ -21,8 +21,6 @@ #include -void ff_fdct_mmx(int16_t *block); -void ff_fdct_mmxext(int16_t *block); void ff_fdct_sse2(int16_t *block); #endif /* AVCODEC_X86_FDCT_H */ diff --git a/libavcodec/x86/fdctdsp_init.c b/libavcodec/x86/fdctdsp_init.c index 0cb5fd625..92a842433 100644 --- a/libavcodec/x86/fdctdsp_init.c +++ b/libavcodec/x86/fdctdsp_init.c @@ -31,12 +31,6 @@ av_cold void ff_fdctdsp_init_x86(FDCTDSPContext *c, AVCodecContext *avctx, if (!high_bit_depth) { if ((dct_algo == FF_DCT_AUTO || dct_algo == FF_DCT_MMX)) { - if (INLINE_MMX(cpu_flags)) - c->fdct = ff_fdct_mmx; - - if (INLINE_MMXEXT(cpu_flags)) - c->fdct = ff_fdct_mmxext; - if (INLINE_SSE2(cpu_flags)) c->fdct = ff_fdct_sse2; } diff --git a/libavcodec/x86/fft.asm b/libavcodec/x86/fft.asm index a671e8f48..a44596e56 100644 --- a/libavcodec/x86/fft.asm +++ b/libavcodec/x86/fft.asm @@ -1,5 +1,5 @@ ;****************************************************************************** -;* FFT transform with SSE/3DNow optimizations +;* FFT transform with SSE/AVX optimizations ;* Copyright (c) 2008 Loren Merritt ;* Copyright (c) 2011 Vitor Sessak ;* @@ -92,29 +92,6 @@ cextern cos_ %+ i SECTION .text -%macro T2_3DNOW 4 ; z0, z1, mem0, mem1 - mova %1, %3 - mova %2, %1 - pfadd %1, %4 - pfsub %2, %4 -%endmacro - -%macro T4_3DNOW 6 ; z0, z1, z2, z3, tmp0, tmp1 - mova %5, %3 - pfsub %3, %4 - pfadd %5, %4 ; {t6,t5} - pxor %3, [ps_m1p1] ; {t8,t7} - mova %6, %1 - movd [r0+12], %3 - punpckhdq %3, [r0+8] - pfadd %1, %5 ; {r0,i0} - pfsub %6, %5 ; {r2,i2} - mova %4, %2 - pfadd %2, %3 ; {r1,i1} - pfsub %4, %3 ; {r3,i3} - SWAP %3, %6 -%endmacro - ; in: %1 = {r0,i0,r2,i2,r4,i4,r6,i6} ; %2 = {r1,i1,r3,i3,r5,i5,r7,i7} ; %3, %4, %5 tmp @@ -199,7 +176,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) || cpuflag(3dnow) +%elif cpuflag(sse) mova %3, %2 unpcklps %2, %1 unpckhps %3, %1 @@ -310,12 +287,6 @@ IF%1 mova Z(1), m5 %endif %endmacro -%macro PUNPCK 3 - mova %3, %1 - punpckldq %1, %2 - punpckhdq %3, %2 -%endmacro - %define Z(x) [r0+mmsize*x] %define Z2(x) [r0+mmsize*x] %define ZH(x) [r0+mmsize*x+mmsize/2] @@ -462,68 +433,6 @@ fft16_sse: ret -%macro FFT48_3DNOW 0 -align 16 -fft4 %+ SUFFIX: - T2_3DNOW m0, m1, Z(0), Z(1) - mova m2, Z(2) - mova m3, Z(3) - T4_3DNOW m0, m1, m2, m3, m4, m5 - PUNPCK m0, m1, m4 - PUNPCK m2, m3, m5 - mova Z(0), m0 - mova Z(1), m4 - mova Z(2), m2 - mova Z(3), m5 - ret - -align 16 -fft8 %+ SUFFIX: - T2_3DNOW m0, m1, Z(0), Z(1) - mova m2, Z(2) - mova m3, Z(3) - T4_3DNOW m0, m1, m2, m3, m4, m5 - mova Z(0), m0 - mova Z(2), m2 - T2_3DNOW m4, m5, Z(4), Z(5) - T2_3DNOW m6, m7, Z2(6), Z2(7) - PSWAPD m0, m5 - PSWAPD m2, m7 - pxor m0, [ps_m1p1] - pxor m2, [ps_m1p1] - pfsub m5, m0 - pfadd m7, m2 - pfmul m5, [ps_root2] - pfmul m7, [ps_root2] - T4_3DNOW m1, m3, m5, m7, m0, m2 - mova Z(5), m5 - mova Z2(7), m7 - mova m0, Z(0) - mova m2, Z(2) - T4_3DNOW m0, m2, m4, m6, m5, m7 - PUNPCK m0, m1, m5 - PUNPCK m2, m3, m7 - mova Z(0), m0 - mova Z(1), m5 - mova Z(2), m2 - mova Z(3), m7 - PUNPCK m4, Z(5), m5 - PUNPCK m6, Z2(7), m7 - mova Z(4), m4 - mova Z(5), m5 - mova Z2(6), m6 - mova Z2(7), m7 - ret -%endmacro - -%if ARCH_X86_32 -INIT_MMX 3dnowext -FFT48_3DNOW - -INIT_MMX 3dnow -FFT48_3DNOW -%endif - %define Z(x) [zcq + o1q*(x&6) + mmsize*(x&1)] %define Z2(x) [zcq + o3q + mmsize*(x&1)] %define ZH(x) [zcq + o1q*(x&6) + mmsize*(x&1) + mmsize/2] @@ -575,7 +484,7 @@ INIT_XMM sse DECL_PASS pass_sse, PASS_BIG 1 DECL_PASS pass_interleave_sse, PASS_BIG 0 -%macro FFT_CALC_FUNC 0 +INIT_XMM sse cglobal fft_calc, 2,5,8 mov r3d, [r0 + FFTContext.nbits] PUSH r1 @@ -592,36 +501,16 @@ cglobal fft_calc, 2,5,8 shl r2, cl sub r4, r2 .loop: -%if mmsize == 8 - PSWAPD m0, [r4 + r2 + 4] - mova [r4 + r2 + 4], m0 -%else movaps xmm0, [r4 + r2] movaps xmm1, xmm0 unpcklps xmm0, [r4 + r2 + 16] unpckhps xmm1, [r4 + r2 + 16] movaps [r4 + r2], xmm0 movaps [r4 + r2 + 16], xmm1 -%endif add r2, mmsize*2 jl .loop .end: -%if cpuflag(3dnow) - femms - RET -%else REP_RET -%endif -%endmacro - -%if ARCH_X86_32 -INIT_MMX 3dnow -FFT_CALC_FUNC -INIT_MMX 3dnowext -FFT_CALC_FUNC -%endif -INIT_XMM sse -FFT_CALC_FUNC cglobal fft_permute, 2,7,1 mov r4, [r0 + FFTContext.revtab] @@ -656,7 +545,7 @@ cglobal fft_permute, 2,7,1 jl .loopcopy REP_RET -%macro IMDCT_CALC_FUNC 0 +INIT_XMM sse cglobal imdct_calc, 3,5,3 mov r3d, [r0 + FFTContext.mdctsize] mov r4, [r0 + FFTContext.imdcthalf] @@ -684,52 +573,17 @@ cglobal imdct_calc, 3,5,3 neg r2 mova m2, [ps_neg] .loop: -%if mmsize == 8 - PSWAPD m0, [r1 + r3] - PSWAPD m1, [r0 + r2] - pxor m0, m2 -%else mova m0, [r1 + r3] mova m1, [r0 + r2] shufps m0, m0, 0x1b shufps m1, m1, 0x1b xorps m0, m2 -%endif mova [r0 + r3], m1 mova [r1 + r2], m0 sub r3, mmsize add r2, mmsize jl .loop -%if cpuflag(3dnow) - femms - RET -%else REP_RET -%endif -%endmacro - -%if ARCH_X86_32 -INIT_MMX 3dnow -IMDCT_CALC_FUNC -INIT_MMX 3dnowext -IMDCT_CALC_FUNC -%endif - -INIT_XMM sse -IMDCT_CALC_FUNC - -%if ARCH_X86_32 -INIT_MMX 3dnow -%define mulps pfmul -%define addps pfadd -%define subps pfsub -%define unpcklps punpckldq -%define unpckhps punpckhdq -DECL_PASS pass_3dnow, PASS_SMALL 1, [wq], [wq+o1q] -DECL_PASS pass_interleave_3dnow, PASS_BIG 0 -%define pass_3dnowext pass_3dnow -%define pass_interleave_3dnowext pass_interleave_3dnow -%endif %ifdef PIC %define SECTION_REL - $$ @@ -785,14 +639,6 @@ DECL_FFT 6, _interleave INIT_XMM sse DECL_FFT 5 DECL_FFT 5, _interleave -%if ARCH_X86_32 -INIT_MMX 3dnow -DECL_FFT 4 -DECL_FFT 4, _interleave -INIT_MMX 3dnowext -DECL_FFT 4 -DECL_FFT 4, _interleave -%endif INIT_XMM sse %undef mulps @@ -802,37 +648,6 @@ INIT_XMM sse %undef unpckhps %macro PREROTATER 5 ;-2*k, 2*k, input+n4, tcos+n8, tsin+n8 -%if mmsize == 8 ; j*2+2-n4, n4-2-j*2, input+n4, tcos+n8, tsin+n8 - PSWAPD m0, [%3+%2*4] - movq m2, [%3+%1*4-8] - movq m3, m0 - punpckldq m0, m2 - punpckhdq m2, m3 - movd m1, [%4+%1*2-4] ; tcos[j] - movd m3, [%4+%2*2] ; tcos[n4-j-1] - punpckldq m1, [%5+%1*2-4] ; tsin[j] - punpckldq m3, [%5+%2*2] ; tsin[n4-j-1] - - mova m4, m0 - PSWAPD m5, m1 - pfmul m0, m1 - pfmul m4, m5 - mova m6, m2 - PSWAPD m5, m3 - pfmul m2, m3 - pfmul m6, m5 -%if cpuflag(3dnowext) - pfpnacc m0, m4 - pfpnacc m2, m6 -%else - SBUTTERFLY dq, 0, 4, 1 - SBUTTERFLY dq, 2, 6, 3 - pxor m4, m7 - pxor m6, m7 - pfadd m0, m4 - pfadd m2, m6 -%endif -%else movaps xmm0, [%3+%2*4] movaps xmm1, [%3+%1*4-0x10] movaps xmm2, xmm0 @@ -853,29 +668,15 @@ INIT_XMM sse movaps xmm0, xmm1 unpcklps xmm1, xmm2 unpckhps xmm0, xmm2 -%endif %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 5 ;j, k, z+n8, tcos+n8, tsin+n8 @@ -909,7 +710,7 @@ INIT_XMM sse sub %2, 0x20 add %1, 0x20 jl .post -%elif cpuflag(sse) +%else movaps xmm1, [%3+%1*2] movaps xmm0, [%3+%1*2+0x10] CMUL %1, xmm0, xmm1, %3, %4, %5 @@ -931,24 +732,6 @@ INIT_XMM sse sub %2, 0x10 add %1, 0x10 jl .post -%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 - movd [%3+%1*2+12], m3 - psrlq m0, 32 - psrlq m1, 32 - psrlq m2, 32 - psrlq m3, 32 - movd [%3+%1*2+ 8], m0 - movd [%3+%2*2+ 4], m1 - movd [%3+%2*2+ 8], m2 - movd [%3+%1*2+ 4], m3 - sub %2, 8 - add %1, 8 - jl .post %endif %endmacro @@ -981,39 +764,21 @@ cglobal imdct_half, 3,12,8; FFTContext *s, FFTSample *output, const FFTSample *i push rrevtab %endif -%if mmsize == 8 - sub r3, 2 -%else sub r3, 4 -%endif -%if ARCH_X86_64 || mmsize == 8 +%if ARCH_X86_64 xor r4, r4 sub r4, r3 %endif -%if notcpuflag(3dnowext) && mmsize == 8 - movd m7, [ps_neg] -%endif .pre: %if ARCH_X86_64 == 0 ;unspill -%if mmsize != 8 xor r4, r4 sub r4, r3 -%endif mov rtcos, [esp+8] mov rtsin, [esp+4] %endif PREROTATER r4, r3, r2, rtcos, rtsin -%if mmsize == 8 - mov r6, [esp] ; rrevtab = ptr+n8 - movzx r5, word [rrevtab+r4-2] ; rrevtab[j] - movzx r6, word [rrevtab+r3] ; rrevtab[n4-j-1] - mova [r1+r5*8], m0 - mova [r1+r6*8], m2 - add r4, 2 - sub r3, 2 -%else %if ARCH_X86_64 movzx r5, word [rrevtab+r4-4] movzx r6, word [rrevtab+r4-2] @@ -1036,7 +801,6 @@ cglobal imdct_half, 3,12,8; FFTContext *s, FFTSample *output, const FFTSample *i movhps [r1+r4*8], xmm1 %endif sub r3, 4 -%endif jns .pre mov r5, r0 @@ -1061,23 +825,12 @@ cglobal imdct_half, 3,12,8; FFTContext *s, FFTSample *output, const FFTSample *i POSROTATESHUF r0, r1, r6, rtcos, rtsin %if ARCH_X86_64 == 0 add esp, 12 -%endif -%if mmsize == 8 - femms %endif RET %endmacro DECL_IMDCT -%if ARCH_X86_32 -INIT_MMX 3dnow -DECL_IMDCT - -INIT_MMX 3dnowext -DECL_IMDCT -%endif - INIT_YMM avx %if HAVE_AVX_EXTERNAL diff --git a/libavcodec/x86/fft.h b/libavcodec/x86/fft.h index 398091eb1..37418ec1f 100644 --- a/libavcodec/x86/fft.h +++ b/libavcodec/x86/fft.h @@ -24,13 +24,7 @@ void ff_fft_permute_sse(FFTContext *s, FFTComplex *z); void ff_fft_calc_avx(FFTContext *s, FFTComplex *z); void ff_fft_calc_sse(FFTContext *s, FFTComplex *z); -void ff_fft_calc_3dnow(FFTContext *s, FFTComplex *z); -void ff_fft_calc_3dnowext(FFTContext *s, FFTComplex *z); -void ff_imdct_calc_3dnow(FFTContext *s, FFTSample *output, const FFTSample *input); -void ff_imdct_half_3dnow(FFTContext *s, FFTSample *output, const FFTSample *input); -void ff_imdct_calc_3dnowext(FFTContext *s, FFTSample *output, const FFTSample *input); -void ff_imdct_half_3dnowext(FFTContext *s, FFTSample *output, const FFTSample *input); void ff_imdct_calc_sse(FFTContext *s, FFTSample *output, const FFTSample *input); void ff_imdct_half_sse(FFTContext *s, FFTSample *output, const FFTSample *input); void ff_imdct_half_avx(FFTContext *s, FFTSample *output, const FFTSample *input); diff --git a/libavcodec/x86/fft_init.c b/libavcodec/x86/fft_init.c index 928f1dcda..df79d57dc 100644 --- a/libavcodec/x86/fft_init.c +++ b/libavcodec/x86/fft_init.c @@ -31,20 +31,6 @@ av_cold void ff_fft_init_x86(FFTContext *s) if (s->nbits > 16) return; -#if ARCH_X86_32 - if (EXTERNAL_AMD3DNOW(cpu_flags)) { - s->imdct_calc = ff_imdct_calc_3dnow; - s->imdct_half = ff_imdct_half_3dnow; - s->fft_calc = ff_fft_calc_3dnow; - } - - if (EXTERNAL_AMD3DNOWEXT(cpu_flags)) { - s->imdct_calc = ff_imdct_calc_3dnowext; - s->imdct_half = ff_imdct_half_3dnowext; - s->fft_calc = ff_fft_calc_3dnowext; - } -#endif /* ARCH_X86_32 */ - if (EXTERNAL_SSE(cpu_flags)) { s->imdct_calc = ff_imdct_calc_sse; s->imdct_half = ff_imdct_half_sse; diff --git a/libavcodec/x86/flacdsp_init.c b/libavcodec/x86/flacdsp_init.c index 6315b6903..ed2e5ed15 100644 --- a/libavcodec/x86/flacdsp_init.c +++ b/libavcodec/x86/flacdsp_init.c @@ -22,6 +22,7 @@ #include "libavcodec/flacdsp.h" #include "libavutil/x86/cpu.h" #include "config.h" +#include "config_components.h" void ff_flac_lpc_32_sse4(int32_t *samples, const int coeffs[32], int order, int qlevel, int len); diff --git a/libavcodec/x86/fmtconvert.asm b/libavcodec/x86/fmtconvert.asm index 8f62a0a09..e70df4662 100644 --- a/libavcodec/x86/fmtconvert.asm +++ b/libavcodec/x86/fmtconvert.asm @@ -44,35 +44,17 @@ cglobal int32_to_float_fmul_scalar, 4, 4, %1, dst, src, mul, len add dstq, lenq neg lenq .loop: -%if cpuflag(sse2) cvtdq2ps m1, [srcq+lenq ] cvtdq2ps m2, [srcq+lenq+16] -%else - cvtpi2ps m1, [srcq+lenq ] - cvtpi2ps m3, [srcq+lenq+ 8] - cvtpi2ps m2, [srcq+lenq+16] - cvtpi2ps m4, [srcq+lenq+24] - movlhps m1, m3 - movlhps m2, m4 -%endif mulps m1, m0 mulps m2, m0 mova [dstq+lenq ], m1 mova [dstq+lenq+16], m2 add lenq, 32 jl .loop -%if notcpuflag(sse2) - ;; cvtpi2ps switches to MMX even if the source is a memory location - ;; possible an error in documentation since every tested CPU disagrees with - ;; that. Use emms anyway since the vast majority of machines will use the - ;; SSE2 variant - emms -%endif RET %endmacro -INIT_XMM sse -INT32_TO_FLOAT_FMUL_SCALAR 5 INIT_XMM sse2 INT32_TO_FLOAT_FMUL_SCALAR 3 @@ -89,17 +71,8 @@ cglobal int32_to_float_fmul_array8, 5, 5, 5, c, dst, src, mul, len .loop: movss m0, [mulq] SPLATD m0 -%if cpuflag(sse2) cvtdq2ps m1, [srcq+lenq ] cvtdq2ps m2, [srcq+lenq+16] -%else - cvtpi2ps m1, [srcq+lenq ] - cvtpi2ps m3, [srcq+lenq+ 8] - cvtpi2ps m2, [srcq+lenq+16] - cvtpi2ps m4, [srcq+lenq+24] - movlhps m1, m3 - movlhps m2, m4 -%endif mulps m1, m0 mulps m2, m0 mova [dstq+lenq ], m1 @@ -107,18 +80,9 @@ cglobal int32_to_float_fmul_array8, 5, 5, 5, c, dst, src, mul, len add mulq, 4 add lenq, 32 jl .loop -%if notcpuflag(sse2) - ;; cvtpi2ps switches to MMX even if the source is a memory location - ;; possible an error in documentation since every tested CPU disagrees with - ;; that. Use emms anyway since the vast majority of machines will use the - ;; SSE2 variant - emms -%endif RET %endmacro -INIT_XMM sse -INT32_TO_FLOAT_FMUL_ARRAY8 INIT_XMM sse2 INT32_TO_FLOAT_FMUL_ARRAY8 diff --git a/libavcodec/x86/fmtconvert_init.c b/libavcodec/x86/fmtconvert_init.c index df097054e..58b396856 100644 --- a/libavcodec/x86/fmtconvert_init.c +++ b/libavcodec/x86/fmtconvert_init.c @@ -29,10 +29,7 @@ #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); -void ff_int32_to_float_fmul_array8_sse (FmtConvertContext *c, float *dst, const int32_t *src, - const float *mul, int len); void ff_int32_to_float_fmul_array8_sse2(FmtConvertContext *c, float *dst, const int32_t *src, const float *mul, int len); @@ -43,10 +40,6 @@ av_cold void ff_fmt_convert_init_x86(FmtConvertContext *c, AVCodecContext *avctx #if HAVE_X86ASM int cpu_flags = av_get_cpu_flags(); - if (EXTERNAL_SSE(cpu_flags)) { - c->int32_to_float_fmul_scalar = ff_int32_to_float_fmul_scalar_sse; - c->int32_to_float_fmul_array8 = ff_int32_to_float_fmul_array8_sse; - } if (EXTERNAL_SSE2(cpu_flags)) { c->int32_to_float_fmul_scalar = ff_int32_to_float_fmul_scalar_sse2; c->int32_to_float_fmul_array8 = ff_int32_to_float_fmul_array8_sse2; diff --git a/libavcodec/x86/fpel.asm b/libavcodec/x86/fpel.asm index 961a1587a..ebe8e4375 100644 --- a/libavcodec/x86/fpel.asm +++ b/libavcodec/x86/fpel.asm @@ -90,9 +90,7 @@ cglobal %1_pixels%2, 4,5,4 INIT_MMX mmx OP_PIXELS put, 4 -OP_PIXELS avg, 4 OP_PIXELS put, 8 -OP_PIXELS avg, 8 OP_PIXELS put, 16 OP_PIXELS avg, 16 diff --git a/libavcodec/x86/h264_chromamc.asm b/libavcodec/x86/h264_chromamc.asm index b5a78b537..e562efd69 100644 --- a/libavcodec/x86/h264_chromamc.asm +++ b/libavcodec/x86/h264_chromamc.asm @@ -446,13 +446,6 @@ chroma_mc4_mmx_func avg, h264 chroma_mc4_mmx_func avg, rv40 chroma_mc2_mmx_func avg, h264 -INIT_MMX 3dnow -chroma_mc8_mmx_func avg, h264, _rnd -chroma_mc8_mmx_func avg, vc1, _nornd -chroma_mc8_mmx_func avg, rv40 -chroma_mc4_mmx_func avg, h264 -chroma_mc4_mmx_func avg, rv40 - %macro chroma_mc8_ssse3_func 2-3 cglobal %1_%2_chroma_mc8%3, 6, 7, 8 mov r6d, r5d diff --git a/libavcodec/x86/h264_deblock.asm b/libavcodec/x86/h264_deblock.asm index a2e745cd8..479e6c346 100644 --- a/libavcodec/x86/h264_deblock.asm +++ b/libavcodec/x86/h264_deblock.asm @@ -581,8 +581,6 @@ cglobal deblock_h_luma_8, 0,5,8,0x60+12 RET %endmacro ; DEBLOCK_LUMA -INIT_MMX mmxext -DEBLOCK_LUMA v8, 8 INIT_XMM sse2 DEBLOCK_LUMA v, 16 %if HAVE_AVX_EXTERNAL @@ -864,200 +862,6 @@ DEBLOCK_LUMA_INTRA v INIT_XMM avx DEBLOCK_LUMA_INTRA v %endif -%if ARCH_X86_64 == 0 -INIT_MMX mmxext -DEBLOCK_LUMA_INTRA v8 -%endif - -INIT_MMX mmxext - -%macro CHROMA_V_START 0 - dec r2d ; alpha-1 - dec r3d ; beta-1 - mov t5, r0 - sub t5, r1 - sub t5, r1 -%endmacro - -%macro CHROMA_H_START 0 - dec r2d - dec r3d - sub r0, 2 - lea t6, [r1*3] - mov t5, r0 - add r0, t6 -%endmacro - -%define t5 r5 -%define t6 r6 - -;----------------------------------------------------------------------------- -; void ff_deblock_v_chroma(uint8_t *pix, int stride, int alpha, int beta, -; int8_t *tc0) -;----------------------------------------------------------------------------- -cglobal deblock_v_chroma_8, 5,6 - CHROMA_V_START - movq m0, [t5] - movq m1, [t5+r1] - movq m2, [r0] - movq m3, [r0+r1] - call ff_chroma_inter_body_mmxext - movq [t5+r1], m1 - movq [r0], m2 - RET - -;----------------------------------------------------------------------------- -; void ff_deblock_h_chroma(uint8_t *pix, int stride, int alpha, int beta, -; int8_t *tc0) -;----------------------------------------------------------------------------- -cglobal deblock_h_chroma_8, 5,7 -%if ARCH_X86_64 - ; This could use the red zone on 64 bit unix to avoid the stack pointer - ; readjustment, but valgrind assumes the red zone is clobbered on - ; function calls and returns. - sub rsp, 16 - %define buf0 [rsp] - %define buf1 [rsp+8] -%else - %define buf0 r0m - %define buf1 r2m -%endif - CHROMA_H_START - TRANSPOSE4x8_LOAD bw, wd, dq, PASS8ROWS(t5, r0, r1, t6) - movq buf0, m0 - movq buf1, m3 - LOAD_MASK r2d, r3d - movd m6, [r4] ; tc0 - punpcklbw m6, m6 - pand m7, m6 - DEBLOCK_P0_Q0 - movq m0, buf0 - movq m3, buf1 - TRANSPOSE8x4B_STORE PASS8ROWS(t5, r0, r1, t6) -%if ARCH_X86_64 - add rsp, 16 -%endif - RET - -ALIGN 16 -ff_chroma_inter_body_mmxext: - LOAD_MASK r2d, r3d - movd m6, [r4] ; tc0 - punpcklbw m6, m6 - pand m7, m6 - DEBLOCK_P0_Q0 - ret - -%define t5 r4 -%define t6 r5 - -cglobal deblock_h_chroma422_8, 5, 6 - SUB rsp, (1+ARCH_X86_64*2)*mmsize - %if ARCH_X86_64 - %define buf0 [rsp+16] - %define buf1 [rsp+8] - %else - %define buf0 r0m - %define buf1 r2m - %endif - - movd m6, [r4] - punpcklbw m6, m6 - movq [rsp], m6 - CHROMA_H_START - - TRANSPOSE4x8B_LOAD PASS8ROWS(t5, r0, r1, t6) - movq buf0, m0 - movq buf1, m3 - LOAD_MASK r2d, r3d - movd m6, [rsp] - punpcklwd m6, m6 - pand m7, m6 - DEBLOCK_P0_Q0 - movq m0, buf0 - movq m3, buf1 - TRANSPOSE8x4B_STORE PASS8ROWS(t5, r0, r1, t6) - - lea r0, [r0+r1*8] - lea t5, [t5+r1*8] - - TRANSPOSE4x8B_LOAD PASS8ROWS(t5, r0, r1, t6) - movq buf0, m0 - movq buf1, m3 - LOAD_MASK r2d, r3d - movd m6, [rsp+4] - punpcklwd m6, m6 - pand m7, m6 - DEBLOCK_P0_Q0 - movq m0, buf0 - movq m3, buf1 - TRANSPOSE8x4B_STORE PASS8ROWS(t5, r0, r1, t6) - ADD rsp, (1+ARCH_X86_64*2)*mmsize -RET - -; in: %1=p0 %2=p1 %3=q1 -; out: p0 = (p0 + q1 + 2*p1 + 2) >> 2 -%macro CHROMA_INTRA_P0 3 - movq m4, %1 - pxor m4, %3 - pand m4, [pb_1] ; m4 = (p0^q1)&1 - pavgb %1, %3 - psubusb %1, m4 - pavgb %1, %2 ; dst = avg(p1, avg(p0,q1) - ((p0^q1)&1)) -%endmacro - -;------------------------------------------------------------------------------ -; void ff_deblock_v_chroma_intra(uint8_t *pix, int stride, int alpha, int beta) -;------------------------------------------------------------------------------ -cglobal deblock_v_chroma_intra_8, 4,5 - CHROMA_V_START - movq m0, [t5] - movq m1, [t5+r1] - movq m2, [r0] - movq m3, [r0+r1] - call ff_chroma_intra_body_mmxext - movq [t5+r1], m1 - movq [r0], m2 - RET - -;------------------------------------------------------------------------------ -; void ff_deblock_h_chroma_intra(uint8_t *pix, int stride, int alpha, int beta) -;------------------------------------------------------------------------------ -cglobal deblock_h_chroma_intra_8, 4,6 - CHROMA_H_START - TRANSPOSE4x8_LOAD bw, wd, dq, PASS8ROWS(t5, r0, r1, t6) - call ff_chroma_intra_body_mmxext - TRANSPOSE8x4B_STORE PASS8ROWS(t5, r0, r1, t6) - RET - -cglobal deblock_h_chroma422_intra_8, 4, 6 - CHROMA_H_START - TRANSPOSE4x8_LOAD bw, wd, dq, PASS8ROWS(t5, r0, r1, t6) - call ff_chroma_intra_body_mmxext - TRANSPOSE8x4B_STORE PASS8ROWS(t5, r0, r1, t6) - - lea r0, [r0+r1*8] - lea t5, [t5+r1*8] - - TRANSPOSE4x8_LOAD bw, wd, dq, PASS8ROWS(t5, r0, r1, t6) - call ff_chroma_intra_body_mmxext - TRANSPOSE8x4B_STORE PASS8ROWS(t5, r0, r1, t6) -RET - -ALIGN 16 -ff_chroma_intra_body_mmxext: - LOAD_MASK r2d, r3d - movq m5, m1 - movq m6, m2 - CHROMA_INTRA_P0 m1, m0, m3 - CHROMA_INTRA_P0 m2, m3, m0 - psubb m1, m5 - psubb m2, m6 - pand m1, m7 - pand m2, m7 - paddb m1, m5 - paddb m2, m6 - ret %macro LOAD_8_ROWS 8 movd m0, %1 diff --git a/libavcodec/x86/h264_deblock_10bit.asm b/libavcodec/x86/h264_deblock_10bit.asm index 1af3257a6..23971b5cb 100644 --- a/libavcodec/x86/h264_deblock_10bit.asm +++ b/libavcodec/x86/h264_deblock_10bit.asm @@ -798,9 +798,11 @@ cglobal deblock_h_luma_intra_10, 4,7,8*(mmsize/16) %endmacro %if ARCH_X86_64 == 0 +%if HAVE_ALIGNED_STACK == 0 INIT_MMX mmxext DEBLOCK_LUMA DEBLOCK_LUMA_INTRA +%endif INIT_XMM sse2 DEBLOCK_LUMA DEBLOCK_LUMA_INTRA @@ -938,10 +940,6 @@ cglobal deblock_v_chroma_10, 5,7-(mmsize/16),8*(mmsize/16) sub r0, r1 shl r2d, 2 shl r3d, 2 -%if mmsize < 16 - mov r6, 16/mmsize -.loop: -%endif CHROMA_V_LOAD r5 LOAD_AB m4, m5, r2d, r3d LOAD_MASK m0, m1, m2, m3, m4, m5, m7, m6, m4 @@ -952,16 +950,7 @@ cglobal deblock_v_chroma_10, 5,7-(mmsize/16),8*(mmsize/16) pand m7, m6 DEBLOCK_P0_Q0 m1, m2, m0, m3, m7, m5, m6 CHROMA_V_STORE -%if mmsize < 16 - add r0, mmsize - add r5, mmsize - add r4, mmsize/4 - dec r6 - jg .loop - REP_RET -%else RET -%endif ;----------------------------------------------------------------------------- ; void ff_deblock_v_chroma_intra_10(uint16_t *pix, int stride, int alpha, @@ -973,24 +962,12 @@ cglobal deblock_v_chroma_intra_10, 4,6-(mmsize/16),8*(mmsize/16) sub r0, r1 shl r2d, 2 shl r3d, 2 -%if mmsize < 16 - mov r5, 16/mmsize -.loop: -%endif CHROMA_V_LOAD r4 LOAD_AB m4, m5, r2d, r3d LOAD_MASK m0, m1, m2, m3, m4, m5, m7, m6, m4 CHROMA_DEBLOCK_P0_Q0_INTRA m1, m2, m0, m3, m7, m5, m6 CHROMA_V_STORE -%if mmsize < 16 - add r0, mmsize - add r4, mmsize - dec r5 - jg .loop - REP_RET -%else RET -%endif ;----------------------------------------------------------------------------- ; void ff_deblock_h_chroma_10(uint16_t *pix, int stride, int alpha, int beta, @@ -1002,10 +979,6 @@ cglobal deblock_h_chroma_10, 5, 7, 8, 0-2*mmsize, pix_, stride_, alpha_, beta_, mov r5, pix_q lea r6, [3*stride_q] add r5, r6 -%if mmsize == 8 - mov r6d, 2 - .loop: -%endif CHROMA_H_LOAD r5, r6, [rsp], [rsp + mmsize] LOAD_AB m4, m5, alpha_d, beta_d @@ -1018,13 +991,6 @@ cglobal deblock_h_chroma_10, 5, 7, 8, 0-2*mmsize, pix_, stride_, alpha_, beta_, DEBLOCK_P0_Q0 m1, m2, m0, m3, m7, m5, m6 CHROMA_H_STORE r5, r6, [rsp], [rsp + mmsize] -%if mmsize == 8 - lea pix_q, [pix_q + 4*stride_q] - lea r5, [r5 + 4*stride_q] - add tc0_q, 2 - dec r6d - jg .loop -%endif RET ;----------------------------------------------------------------------------- @@ -1068,10 +1034,6 @@ RET %endmacro -%if ARCH_X86_64 == 0 -INIT_MMX mmxext -DEBLOCK_CHROMA -%endif INIT_XMM sse2 DEBLOCK_CHROMA %if HAVE_AVX_EXTERNAL diff --git a/libavcodec/x86/h264_idct.asm b/libavcodec/x86/h264_idct.asm index c54f9f1a6..9b5920d3b 100644 --- a/libavcodec/x86/h264_idct.asm +++ b/libavcodec/x86/h264_idct.asm @@ -87,13 +87,6 @@ SECTION .text STORE_DIFFx2 m2, m3, m4, m5, m7, 6, %1, %3 %endmacro -INIT_MMX mmx -; void ff_h264_idct_add_8_mmx(uint8_t *dst, int16_t *block, int stride) -cglobal h264_idct_add_8, 3, 3, 0 - movsxdifnidn r2, r2d - IDCT4_ADD r0, r1, r2 - RET - %macro IDCT8_1D 2 psraw m0, m1, 1 SWAP 0, 1 @@ -207,23 +200,6 @@ cglobal h264_idct_add_8, 3, 3, 0 STORE_DIFFx2 m1, m2, m5, m6, m7, 6, %1, %3 %endmacro -INIT_MMX mmx -; void ff_h264_idct8_add_8_mmx(uint8_t *dst, int16_t *block, int stride) -cglobal h264_idct8_add_8, 3, 4, 0 - movsxdifnidn r2, r2d - %assign pad 128+4-(stack_offset&7) - SUB rsp, pad - - add word [r1], 32 - IDCT8_ADD_MMX_START r1 , rsp - IDCT8_ADD_MMX_START r1+8, rsp+64 - lea r3, [r0+4] - IDCT8_ADD_MMX_END r0 , rsp, r2, r1 - IDCT8_ADD_MMX_END r3 , rsp+8, r2 - - ADD rsp, pad - RET - ; %1=uint8_t *dst, %2=int16_t *block, %3=int stride %macro IDCT8_ADD_SSE 4 IDCT8_1D_FULL %2 @@ -315,16 +291,7 @@ cglobal h264_idct8_add_8, 3, 4, 10 %endmacro INIT_MMX mmxext -; void ff_h264_idct_dc_add_8_mmxext(uint8_t *dst, int16_t *block, int stride) %if ARCH_X86_64 -cglobal h264_idct_dc_add_8, 3, 4, 0 - movsxd r2, r2d - movsx r3, word [r1] - mov dword [r1], 0 - DC_ADD_MMXEXT_INIT r3, r2 - DC_ADD_MMXEXT_OP movh, r0, r2, r3 - RET - ; void ff_h264_idct8_dc_add_8_mmxext(uint8_t *dst, int16_t *block, int stride) cglobal h264_idct8_dc_add_8, 3, 4, 0 movsxd r2, r2d @@ -336,15 +303,6 @@ cglobal h264_idct8_dc_add_8, 3, 4, 0 DC_ADD_MMXEXT_OP mova, r0, r2, r3 RET %else -; void ff_h264_idct_dc_add_8_mmxext(uint8_t *dst, int16_t *block, int stride) -cglobal h264_idct_dc_add_8, 2, 3, 0 - movsx r2, word [r1] - mov dword [r1], 0 - mov r1, r2m - DC_ADD_MMXEXT_INIT r2, r1 - DC_ADD_MMXEXT_OP movh, r0, r1, r2 - RET - ; void ff_h264_idct8_dc_add_8_mmxext(uint8_t *dst, int16_t *block, int stride) cglobal h264_idct8_dc_add_8, 2, 3, 0 movsx r2, word [r1] @@ -357,247 +315,6 @@ cglobal h264_idct8_dc_add_8, 2, 3, 0 RET %endif -INIT_MMX mmx -; void ff_h264_idct_add16_8_mmx(uint8_t *dst, const int *block_offset, -; int16_t *block, int stride, -; const uint8_t nnzc[6 * 8]) -cglobal h264_idct_add16_8, 5, 7 + npicregs, 0, dst, block_offset, block, stride, nnzc, cntr, coeff, picreg - movsxdifnidn r3, r3d - xor r5, r5 -%ifdef PIC - lea picregq, [scan8_mem] -%endif -.nextblock: - movzx r6, byte [scan8+r5] - movzx r6, byte [r4+r6] - test r6, r6 - jz .skipblock - mov r6d, dword [r1+r5*4] - lea r6, [r0+r6] - IDCT4_ADD r6, r2, r3 -.skipblock: - inc r5 - add r2, 32 - cmp r5, 16 - jl .nextblock - REP_RET - -; void ff_h264_idct8_add4_8_mmx(uint8_t *dst, const int *block_offset, -; int16_t *block, int stride, -; const uint8_t nnzc[6 * 8]) -cglobal h264_idct8_add4_8, 5, 7 + npicregs, 0, dst, block_offset, block, stride, nnzc, cntr, coeff, picreg - movsxdifnidn r3, r3d - %assign pad 128+4-(stack_offset&7) - SUB rsp, pad - - xor r5, r5 -%ifdef PIC - lea picregq, [scan8_mem] -%endif -.nextblock: - movzx r6, byte [scan8+r5] - movzx r6, byte [r4+r6] - test r6, r6 - jz .skipblock - mov r6d, dword [r1+r5*4] - add r6, r0 - add word [r2], 32 - IDCT8_ADD_MMX_START r2 , rsp - IDCT8_ADD_MMX_START r2+8, rsp+64 - IDCT8_ADD_MMX_END r6 , rsp, r3, r2 - mov r6d, dword [r1+r5*4] - lea r6, [r0+r6+4] - IDCT8_ADD_MMX_END r6 , rsp+8, r3 -.skipblock: - add r5, 4 - add r2, 128 - cmp r5, 16 - jl .nextblock - ADD rsp, pad - RET - -INIT_MMX mmxext -; void ff_h264_idct_add16_8_mmxext(uint8_t *dst, const int *block_offset, -; int16_t *block, int stride, -; const uint8_t nnzc[6 * 8]) -cglobal h264_idct_add16_8, 5, 8 + npicregs, 0, dst1, block_offset, block, stride, nnzc, cntr, coeff, dst2, picreg - movsxdifnidn r3, r3d - xor r5, r5 -%ifdef PIC - lea picregq, [scan8_mem] -%endif -.nextblock: - movzx r6, byte [scan8+r5] - movzx r6, byte [r4+r6] - test r6, r6 - jz .skipblock - cmp r6, 1 - jnz .no_dc - movsx r6, word [r2] - test r6, r6 - jz .no_dc - mov word [r2], 0 - DC_ADD_MMXEXT_INIT r6, r3 -%if ARCH_X86_64 == 0 -%define dst2q r1 -%define dst2d r1d -%endif - mov dst2d, dword [r1+r5*4] - lea dst2q, [r0+dst2q] - DC_ADD_MMXEXT_OP movh, dst2q, r3, r6 -%if ARCH_X86_64 == 0 - mov r1, r1m -%endif - inc r5 - add r2, 32 - cmp r5, 16 - jl .nextblock - REP_RET -.no_dc: - mov r6d, dword [r1+r5*4] - add r6, r0 - IDCT4_ADD r6, r2, r3 -.skipblock: - inc r5 - add r2, 32 - cmp r5, 16 - jl .nextblock - REP_RET - -INIT_MMX mmx -; void ff_h264_idct_add16intra_8_mmx(uint8_t *dst, const int *block_offset, -; int16_t *block, int stride, -; const uint8_t nnzc[6 * 8]) -cglobal h264_idct_add16intra_8, 5, 7 + npicregs, 0, dst, block_offset, block, stride, nnzc, cntr, coeff, picreg - movsxdifnidn r3, r3d - xor r5, r5 -%ifdef PIC - lea picregq, [scan8_mem] -%endif -.nextblock: - movzx r6, byte [scan8+r5] - movzx r6, byte [r4+r6] - or r6w, word [r2] - test r6, r6 - jz .skipblock - mov r6d, dword [r1+r5*4] - add r6, r0 - IDCT4_ADD r6, r2, r3 -.skipblock: - inc r5 - add r2, 32 - cmp r5, 16 - jl .nextblock - REP_RET - -INIT_MMX mmxext -; void ff_h264_idct_add16intra_8_mmxext(uint8_t *dst, const int *block_offset, -; int16_t *block, int stride, -; const uint8_t nnzc[6 * 8]) -cglobal h264_idct_add16intra_8, 5, 8 + npicregs, 0, dst1, block_offset, block, stride, nnzc, cntr, coeff, dst2, picreg - movsxdifnidn r3, r3d - xor r5, r5 -%ifdef PIC - lea picregq, [scan8_mem] -%endif -.nextblock: - movzx r6, byte [scan8+r5] - movzx r6, byte [r4+r6] - test r6, r6 - jz .try_dc - mov r6d, dword [r1+r5*4] - lea r6, [r0+r6] - IDCT4_ADD r6, r2, r3 - inc r5 - add r2, 32 - cmp r5, 16 - jl .nextblock - REP_RET -.try_dc: - movsx r6, word [r2] - test r6, r6 - jz .skipblock - mov word [r2], 0 - DC_ADD_MMXEXT_INIT r6, r3 -%if ARCH_X86_64 == 0 -%define dst2q r1 -%define dst2d r1d -%endif - mov dst2d, dword [r1+r5*4] - add dst2q, r0 - DC_ADD_MMXEXT_OP movh, dst2q, r3, r6 -%if ARCH_X86_64 == 0 - mov r1, r1m -%endif -.skipblock: - inc r5 - add r2, 32 - cmp r5, 16 - jl .nextblock - REP_RET - -; void ff_h264_idct8_add4_8_mmxext(uint8_t *dst, const int *block_offset, -; int16_t *block, int stride, -; const uint8_t nnzc[6 * 8]) -cglobal h264_idct8_add4_8, 5, 8 + npicregs, 0, dst1, block_offset, block, stride, nnzc, cntr, coeff, dst2, picreg - movsxdifnidn r3, r3d - %assign pad 128+4-(stack_offset&7) - SUB rsp, pad - - xor r5, r5 -%ifdef PIC - lea picregq, [scan8_mem] -%endif -.nextblock: - movzx r6, byte [scan8+r5] - movzx r6, byte [r4+r6] - test r6, r6 - jz .skipblock - cmp r6, 1 - jnz .no_dc - movsx r6, word [r2] - test r6, r6 - jz .no_dc - mov word [r2], 0 - DC_ADD_MMXEXT_INIT r6, r3 -%if ARCH_X86_64 == 0 -%define dst2q r1 -%define dst2d r1d -%endif - mov dst2d, dword [r1+r5*4] - lea dst2q, [r0+dst2q] - DC_ADD_MMXEXT_OP mova, dst2q, r3, r6 - lea dst2q, [dst2q+r3*4] - DC_ADD_MMXEXT_OP mova, dst2q, r3, r6 -%if ARCH_X86_64 == 0 - mov r1, r1m -%endif - add r5, 4 - add r2, 128 - cmp r5, 16 - jl .nextblock - - ADD rsp, pad - RET -.no_dc: - mov r6d, dword [r1+r5*4] - add r6, r0 - add word [r2], 32 - IDCT8_ADD_MMX_START r2 , rsp - IDCT8_ADD_MMX_START r2+8, rsp+64 - IDCT8_ADD_MMX_END r6 , rsp, r3, r2 - mov r6d, dword [r1+r5*4] - lea r6, [r0+r6+4] - IDCT8_ADD_MMX_END r6 , rsp+8, r3 -.skipblock: - add r5, 4 - add r2, 128 - cmp r5, 16 - jl .nextblock - - ADD rsp, pad - RET - INIT_XMM sse2 ; void ff_h264_idct8_add4_8_sse2(uint8_t *dst, const int *block_offset, ; int16_t *block, int stride, @@ -678,30 +395,6 @@ h264_idct_add8_mmx_plane: jnz .nextblock rep ret -; void ff_h264_idct_add8_8_mmx(uint8_t **dest, const int *block_offset, -; int16_t *block, int stride, -; const uint8_t nnzc[6 * 8]) -cglobal h264_idct_add8_8, 5, 8 + npicregs, 0, dst1, block_offset, block, stride, nnzc, cntr, coeff, dst2, picreg - movsxdifnidn r3, r3d - mov r5, 16 - add r2, 512 -%ifdef PIC - lea picregq, [scan8_mem] -%endif -%if ARCH_X86_64 - mov dst2q, r0 -%endif - call h264_idct_add8_mmx_plane - mov r5, 32 - add r2, 384 -%if ARCH_X86_64 - add dst2q, gprsize -%else - add r0mp, gprsize -%endif - call h264_idct_add8_mmx_plane - RET ; TODO: check rep ret after a function call - cglobal h264_idct_add8_422_8, 5, 8 + npicregs, 0, dst1, block_offset, block, stride, nnzc, cntr, coeff, dst2, picreg ; dst1, block_offset, block, stride, nnzc, cntr, coeff, dst2, picreg movsxdifnidn r3, r3d @@ -734,74 +427,6 @@ cglobal h264_idct_add8_422_8, 5, 8 + npicregs, 0, dst1, block_offset, block, str RET ; TODO: check rep ret after a function call -h264_idct_add8_mmxext_plane: - movsxdifnidn r3, r3d -.nextblock: - movzx r6, byte [scan8+r5] - movzx r6, byte [r4+r6] - test r6, r6 - jz .try_dc -%if ARCH_X86_64 - mov r0d, dword [r1+r5*4] - add r0, [dst2q] -%else - mov r0, r1m ; XXX r1m here is actually r0m of the calling func - mov r0, [r0] - add r0, dword [r1+r5*4] -%endif - IDCT4_ADD r0, r2, r3 - inc r5 - add r2, 32 - test r5, 3 - jnz .nextblock - rep ret -.try_dc: - movsx r6, word [r2] - test r6, r6 - jz .skipblock - mov word [r2], 0 - DC_ADD_MMXEXT_INIT r6, r3 -%if ARCH_X86_64 - mov r0d, dword [r1+r5*4] - add r0, [dst2q] -%else - mov r0, r1m ; XXX r1m here is actually r0m of the calling func - mov r0, [r0] - add r0, dword [r1+r5*4] -%endif - DC_ADD_MMXEXT_OP movh, r0, r3, r6 -.skipblock: - inc r5 - add r2, 32 - test r5, 3 - jnz .nextblock - rep ret - -INIT_MMX mmxext -; void ff_h264_idct_add8_8_mmxext(uint8_t **dest, const int *block_offset, -; int16_t *block, int stride, -; const uint8_t nnzc[6 * 8]) -cglobal h264_idct_add8_8, 5, 8 + npicregs, 0, dst1, block_offset, block, stride, nnzc, cntr, coeff, dst2, picreg - movsxdifnidn r3, r3d - mov r5, 16 - add r2, 512 -%if ARCH_X86_64 - mov dst2q, r0 -%endif -%ifdef PIC - lea picregq, [scan8_mem] -%endif - call h264_idct_add8_mmxext_plane - mov r5, 32 - add r2, 384 -%if ARCH_X86_64 - add dst2q, gprsize -%else - add r0mp, gprsize -%endif - call h264_idct_add8_mmxext_plane - RET ; TODO: check rep ret after a function call - ; r0 = uint8_t *dst, r2 = int16_t *block, r3 = int stride, r6=clobbered h264_idct_dc_add8_mmxext: movsxdifnidn r3, r3d @@ -1129,18 +754,11 @@ cglobal h264_luma_dc_dequant_idct, 3, 4, %1 inc t1d shr t3d, t0b sub t1d, t0d -%if cpuflag(sse2) movd xmm6, t1d DEQUANT_STORE xmm6 -%else - movd m6, t1d - DEQUANT_STORE m6 -%endif RET %endmacro -INIT_MMX mmx -IDCT_DC_DEQUANT 0 INIT_MMX sse2 IDCT_DC_DEQUANT 7 diff --git a/libavcodec/x86/h264_intrapred.asm b/libavcodec/x86/h264_intrapred.asm index b36c198fb..31840a147 100644 --- a/libavcodec/x86/h264_intrapred.asm +++ b/libavcodec/x86/h264_intrapred.asm @@ -48,22 +48,6 @@ cextern pw_8 ; void ff_pred16x16_vertical_8(uint8_t *src, ptrdiff_t stride) ;----------------------------------------------------------------------------- -INIT_MMX mmx -cglobal pred16x16_vertical_8, 2,3 - sub r0, r1 - mov r2, 8 - movq mm0, [r0+0] - movq mm1, [r0+8] -.loop: - movq [r0+r1*1+0], mm0 - movq [r0+r1*1+8], mm1 - movq [r0+r1*2+0], mm0 - movq [r0+r1*2+8], mm1 - lea r0, [r0+r1*2] - dec r2 - jg .loop - REP_RET - INIT_XMM sse cglobal pred16x16_vertical_8, 2,3 sub r0, r1 @@ -114,8 +98,6 @@ cglobal pred16x16_horizontal_8, 2,3 REP_RET %endmacro -INIT_MMX mmx -PRED16x16_H INIT_MMX mmxext PRED16x16_H INIT_XMM ssse3 @@ -154,14 +136,6 @@ cglobal pred16x16_dc_8, 2,7 %endif SPLATB_REG m0, r2, m1 -%if mmsize==8 - mov r3d, 8 -.loop: - mova [r4+r1*0+0], m0 - mova [r4+r1*0+8], m0 - mova [r4+r1*1+0], m0 - mova [r4+r1*1+8], m0 -%else mov r3d, 4 .loop: mova [r4+r1*0], m0 @@ -169,15 +143,12 @@ cglobal pred16x16_dc_8, 2,7 lea r4, [r4+r1*2] mova [r4+r1*0], m0 mova [r4+r1*1], m0 -%endif lea r4, [r4+r1*2] dec r3d jg .loop REP_RET %endmacro -INIT_MMX mmxext -PRED16x16_DC INIT_XMM sse2 PRED16x16_DC INIT_XMM ssse3 @@ -187,47 +158,6 @@ PRED16x16_DC ; void ff_pred16x16_tm_vp8_8(uint8_t *src, ptrdiff_t stride) ;----------------------------------------------------------------------------- -%macro PRED16x16_TM 0 -cglobal pred16x16_tm_vp8_8, 2,5 - sub r0, r1 - pxor mm7, mm7 - movq mm0, [r0+0] - movq mm2, [r0+8] - movq mm1, mm0 - movq mm3, mm2 - punpcklbw mm0, mm7 - punpckhbw mm1, mm7 - punpcklbw mm2, mm7 - punpckhbw mm3, mm7 - movzx r3d, byte [r0-1] - mov r4d, 16 -.loop: - movzx r2d, byte [r0+r1-1] - sub r2d, r3d - movd mm4, r2d - SPLATW mm4, mm4, 0 - movq mm5, mm4 - movq mm6, mm4 - movq mm7, mm4 - paddw mm4, mm0 - paddw mm5, mm1 - paddw mm6, mm2 - paddw mm7, mm3 - packuswb mm4, mm5 - packuswb mm6, mm7 - movq [r0+r1+0], mm4 - movq [r0+r1+8], mm6 - add r0, r1 - dec r4d - jg .loop - REP_RET -%endmacro - -INIT_MMX mmx -PRED16x16_TM -INIT_MMX mmxext -PRED16x16_TM - INIT_XMM sse2 cglobal pred16x16_tm_vp8_8, 2,6,6 sub r0, r1 @@ -311,22 +241,6 @@ cglobal pred16x16_plane_%1_8, 2,9,7 neg r1 ; -stride movh m0, [r0+r1 -1] -%if mmsize == 8 - pxor m4, m4 - movh m1, [r0+r1 +3 ] - movh m2, [r0+r1 +8 ] - movh m3, [r0+r1 +12] - punpcklbw m0, m4 - punpcklbw m1, m4 - punpcklbw m2, m4 - punpcklbw m3, m4 - pmullw m0, [pw_m8tom1 ] - pmullw m1, [pw_m8tom1+8] - pmullw m2, [pw_1to8 ] - pmullw m3, [pw_1to8 +8] - paddw m0, m2 - paddw m1, m3 -%else ; mmsize == 16 %if cpuflag(ssse3) movhps m0, [r0+r1 +8] pmaddubsw m0, [plane_shuf] ; H coefficients @@ -340,21 +254,10 @@ cglobal pred16x16_plane_%1_8, 2,9,7 paddw m0, m1 %endif movhlps m1, m0 -%endif paddw m0, m1 -%if cpuflag(mmxext) PSHUFLW m1, m0, 0xE -%elif cpuflag(mmx) - mova m1, m0 - psrlq m1, 32 -%endif paddw m0, m1 -%if cpuflag(mmxext) PSHUFLW m1, m0, 0x1 -%elif cpuflag(mmx) - mova m1, m0 - psrlq m1, 16 -%endif paddw m0, m1 ; sum of H coefficients lea r4, [r0+r2*8-1] @@ -496,24 +399,10 @@ cglobal pred16x16_plane_%1_8, 2,9,7 SWAP 0, 1 %endif mova m2, m0 -%if mmsize == 8 - mova m5, m0 -%endif pmullw m0, [pw_0to7] ; 0*H, 1*H, ..., 7*H (words) -%if mmsize == 16 psllw m2, 3 -%else - psllw m5, 3 - psllw m2, 2 - mova m6, m5 - paddw m6, m2 -%endif paddw m0, m3 ; a + {0,1,2,3,4,5,6,7}*H paddw m2, m0 ; a + {8,9,10,11,12,13,14,15}*H -%if mmsize == 8 - paddw m5, m0 ; a + {8,9,10,11}*H - paddw m6, m0 ; a + {12,13,14,15}*H -%endif mov r4, 8 .loop: @@ -523,20 +412,8 @@ cglobal pred16x16_plane_%1_8, 2,9,7 psraw m4, 5 packuswb m3, m4 mova [r0], m3 -%if mmsize == 8 - mova m3, m5 ; b[8..11] - mova m4, m6 ; b[12..15] - psraw m3, 5 - psraw m4, 5 - packuswb m3, m4 - mova [r0+8], m3 -%endif paddw m0, m1 paddw m2, m1 -%if mmsize == 8 - paddw m5, m1 - paddw m6, m1 -%endif mova m3, m0 ; b[0..7] mova m4, m2 ; b[8..15] @@ -544,20 +421,8 @@ cglobal pred16x16_plane_%1_8, 2,9,7 psraw m4, 5 packuswb m3, m4 mova [r0+r2], m3 -%if mmsize == 8 - mova m3, m5 ; b[8..11] - mova m4, m6 ; b[12..15] - psraw m3, 5 - psraw m4, 5 - packuswb m3, m4 - mova [r0+r2+8], m3 -%endif paddw m0, m1 paddw m2, m1 -%if mmsize == 8 - paddw m5, m1 - paddw m6, m1 -%endif lea r0, [r0+r2*2] dec r4 @@ -565,14 +430,6 @@ cglobal pred16x16_plane_%1_8, 2,9,7 REP_RET %endmacro -INIT_MMX mmx -H264_PRED16x16_PLANE h264 -H264_PRED16x16_PLANE rv40 -H264_PRED16x16_PLANE svq3 -INIT_MMX mmxext -H264_PRED16x16_PLANE h264 -H264_PRED16x16_PLANE rv40 -H264_PRED16x16_PLANE svq3 INIT_XMM sse2 H264_PRED16x16_PLANE h264 H264_PRED16x16_PLANE rv40 @@ -592,14 +449,6 @@ cglobal pred8x8_plane_8, 2,9,7 neg r1 ; -stride movd m0, [r0+r1 -1] -%if mmsize == 8 - pxor m2, m2 - movh m1, [r0+r1 +4 ] - punpcklbw m0, m2 - punpcklbw m1, m2 - pmullw m0, [pw_m4to4] - pmullw m1, [pw_m4to4+8] -%else ; mmsize == 16 %if cpuflag(ssse3) movhps m0, [r0+r1 +4] ; this reads 4 bytes more than necessary pmaddubsw m0, [plane8_shuf] ; H coefficients @@ -611,25 +460,14 @@ cglobal pred8x8_plane_8, 2,9,7 pmullw m0, [pw_m4to4] %endif movhlps m1, m0 -%endif paddw m0, m1 %if notcpuflag(ssse3) -%if cpuflag(mmxext) PSHUFLW m1, m0, 0xE -%elif cpuflag(mmx) - mova m1, m0 - psrlq m1, 32 -%endif paddw m0, m1 %endif ; !ssse3 -%if cpuflag(mmxext) PSHUFLW m1, m0, 0x1 -%elif cpuflag(mmx) - mova m1, m0 - psrlq m1, 16 -%endif paddw m0, m1 ; sum of H coefficients lea r4, [r0+r2*4-1] @@ -699,20 +537,12 @@ cglobal pred8x8_plane_8, 2,9,7 SPLATW m0, m0, 0 ; H SPLATW m1, m1, 0 ; V SPLATW m3, m3, 0 ; a -%if mmsize == 8 - mova m2, m0 -%endif pmullw m0, [pw_0to7] ; 0*H, 1*H, ..., 7*H (words) paddw m0, m3 ; a + {0,1,2,3,4,5,6,7}*H -%if mmsize == 8 - psllw m2, 2 - paddw m2, m0 ; a + {4,5,6,7}*H -%endif mov r4, 4 ALIGN 16 .loop: -%if mmsize == 16 mova m3, m0 ; b[0..7] paddw m0, m1 psraw m3, 5 @@ -722,24 +552,6 @@ ALIGN 16 packuswb m3, m4 movh [r0], m3 movhps [r0+r2], m3 -%else ; mmsize == 8 - mova m3, m0 ; b[0..3] - mova m4, m2 ; b[4..7] - paddw m0, m1 - paddw m2, m1 - psraw m3, 5 - psraw m4, 5 - mova m5, m0 ; V+b[0..3] - mova m6, m2 ; V+b[4..7] - paddw m0, m1 - paddw m2, m1 - psraw m5, 5 - psraw m6, 5 - packuswb m3, m4 - packuswb m5, m6 - mova [r0], m3 - mova [r0+r2], m5 -%endif lea r0, [r0+r2*2] dec r4 @@ -747,10 +559,6 @@ ALIGN 16 REP_RET %endmacro -INIT_MMX mmx -H264_PRED8x8_PLANE -INIT_MMX mmxext -H264_PRED8x8_PLANE INIT_XMM sse2 H264_PRED8x8_PLANE INIT_XMM ssse3 @@ -794,8 +602,6 @@ cglobal pred8x8_horizontal_8, 2,3 REP_RET %endmacro -INIT_MMX mmx -PRED8x8_H INIT_MMX mmxext PRED8x8_H INIT_MMX ssse3 @@ -937,46 +743,6 @@ cglobal pred8x8_dc_rv40_8, 2,7 ; void ff_pred8x8_tm_vp8_8(uint8_t *src, ptrdiff_t stride) ;----------------------------------------------------------------------------- -%macro PRED8x8_TM 0 -cglobal pred8x8_tm_vp8_8, 2,6 - sub r0, r1 - pxor mm7, mm7 - movq mm0, [r0] - movq mm1, mm0 - punpcklbw mm0, mm7 - punpckhbw mm1, mm7 - movzx r4d, byte [r0-1] - mov r5d, 4 -.loop: - movzx r2d, byte [r0+r1*1-1] - movzx r3d, byte [r0+r1*2-1] - sub r2d, r4d - sub r3d, r4d - movd mm2, r2d - movd mm4, r3d - SPLATW mm2, mm2, 0 - SPLATW mm4, mm4, 0 - movq mm3, mm2 - movq mm5, mm4 - paddw mm2, mm0 - paddw mm3, mm1 - paddw mm4, mm0 - paddw mm5, mm1 - packuswb mm2, mm3 - packuswb mm4, mm5 - movq [r0+r1*1], mm2 - movq [r0+r1*2], mm4 - lea r0, [r0+r1*2] - dec r5d - jg .loop - REP_RET -%endmacro - -INIT_MMX mmx -PRED8x8_TM -INIT_MMX mmxext -PRED8x8_TM - INIT_XMM sse2 cglobal pred8x8_tm_vp8_8, 2,6,4 sub r0, r1 @@ -1333,114 +1099,6 @@ PRED8x8L_VERTICAL ; int has_topright, ptrdiff_t stride) ;----------------------------------------------------------------------------- -INIT_MMX mmxext -cglobal pred8x8l_down_left_8, 4,5 - sub r0, r3 - movq mm0, [r0-8] - movq mm3, [r0] - movq mm1, [r0+8] - movq mm2, mm3 - movq mm4, mm3 - PALIGNR mm2, mm0, 7, mm0 - PALIGNR mm1, mm4, 1, mm4 - test r1d, r1d - jz .fix_lt_2 - test r2d, r2d - jz .fix_tr_1 - jmp .do_top -.fix_lt_2: - movq mm5, mm3 - pxor mm5, mm2 - psllq mm5, 56 - psrlq mm5, 56 - pxor mm2, mm5 - test r2d, r2d - jnz .do_top -.fix_tr_1: - movq mm5, mm3 - pxor mm5, mm1 - psrlq mm5, 56 - psllq mm5, 56 - pxor mm1, mm5 - jmp .do_top -.fix_tr_2: - punpckhbw mm3, mm3 - pshufw mm1, mm3, 0xFF - jmp .do_topright -.do_top: - PRED4x4_LOWPASS mm4, mm2, mm1, mm3, mm5 - movq mm7, mm4 - test r2d, r2d - jz .fix_tr_2 - movq mm0, [r0+8] - movq mm5, mm0 - movq mm2, mm0 - movq mm4, mm0 - psrlq mm5, 56 - PALIGNR mm2, mm3, 7, mm3 - PALIGNR mm5, mm4, 1, mm4 - PRED4x4_LOWPASS mm1, mm2, mm5, mm0, mm4 -.do_topright: - lea r1, [r0+r3*2] - movq mm6, mm1 - psrlq mm1, 56 - movq mm4, mm1 - lea r2, [r1+r3*2] - movq mm2, mm6 - PALIGNR mm2, mm7, 1, mm0 - movq mm3, mm6 - PALIGNR mm3, mm7, 7, mm0 - PALIGNR mm4, mm6, 1, mm0 - movq mm5, mm7 - movq mm1, mm7 - movq mm7, mm6 - lea r4, [r2+r3*2] - psllq mm1, 8 - PRED4x4_LOWPASS mm0, mm1, mm2, mm5, mm6 - PRED4x4_LOWPASS mm1, mm3, mm4, mm7, mm6 - movq [r4+r3*2], mm1 - movq mm2, mm0 - psllq mm1, 8 - psrlq mm2, 56 - psllq mm0, 8 - por mm1, mm2 - movq [r4+r3*1], mm1 - movq mm2, mm0 - psllq mm1, 8 - psrlq mm2, 56 - psllq mm0, 8 - por mm1, mm2 - movq [r2+r3*2], mm1 - movq mm2, mm0 - psllq mm1, 8 - psrlq mm2, 56 - psllq mm0, 8 - por mm1, mm2 - movq [r2+r3*1], mm1 - movq mm2, mm0 - psllq mm1, 8 - psrlq mm2, 56 - psllq mm0, 8 - por mm1, mm2 - movq [r1+r3*2], mm1 - movq mm2, mm0 - psllq mm1, 8 - psrlq mm2, 56 - psllq mm0, 8 - por mm1, mm2 - movq [r1+r3*1], mm1 - movq mm2, mm0 - psllq mm1, 8 - psrlq mm2, 56 - psllq mm0, 8 - por mm1, mm2 - movq [r0+r3*2], mm1 - psllq mm1, 8 - psrlq mm0, 56 - por mm1, mm0 - movq [r0+r3*1], mm1 - RET - %macro PRED8x8L_DOWN_LEFT 0 cglobal pred8x8l_down_left_8, 4,4 sub r0, r3 @@ -1530,142 +1188,10 @@ INIT_MMX ssse3 PRED8x8L_DOWN_LEFT ;----------------------------------------------------------------------------- -; void ff_pred8x8l_down_right_8_mmxext(uint8_t *src, int has_topleft, -; int has_topright, ptrdiff_t stride) +; void ff_pred8x8l_down_right_8(uint8_t *src, int has_topleft, +; int has_topright, ptrdiff_t stride) ;----------------------------------------------------------------------------- -INIT_MMX mmxext -cglobal pred8x8l_down_right_8, 4,5 - sub r0, r3 - lea r4, [r0+r3*2] - movq mm0, [r0+r3*1-8] - punpckhbw mm0, [r0+r3*0-8] - movq mm1, [r4+r3*1-8] - punpckhbw mm1, [r0+r3*2-8] - mov r4, r0 - punpckhwd mm1, mm0 - lea r0, [r0+r3*4] - movq mm2, [r0+r3*1-8] - punpckhbw mm2, [r0+r3*0-8] - lea r0, [r0+r3*2] - movq mm3, [r0+r3*1-8] - punpckhbw mm3, [r0+r3*0-8] - punpckhwd mm3, mm2 - punpckhdq mm3, mm1 - lea r0, [r0+r3*2] - movq mm0, [r0+r3*0-8] - movq mm1, [r4] - mov r0, r4 - movq mm4, mm3 - movq mm2, mm3 - PALIGNR mm4, mm0, 7, mm0 - PALIGNR mm1, mm2, 1, mm2 - test r1d, r1d ; top_left - jz .fix_lt_1 -.do_left: - movq mm0, mm4 - PRED4x4_LOWPASS mm2, mm1, mm4, mm3, mm5 - movq mm4, mm0 - movq mm7, mm2 - movq mm6, mm2 - PRED4x4_LOWPASS mm1, mm3, mm0, mm4, mm5 - psllq mm1, 56 - PALIGNR mm7, mm1, 7, mm3 - movq mm0, [r0-8] - movq mm3, [r0] - movq mm1, [r0+8] - movq mm2, mm3 - movq mm4, mm3 - PALIGNR mm2, mm0, 7, mm0 - PALIGNR mm1, mm4, 1, mm4 - test r1d, r1d ; top_left - jz .fix_lt_2 - test r2d, r2d ; top_right - jz .fix_tr_1 -.do_top: - PRED4x4_LOWPASS mm4, mm2, mm1, mm3, mm5 - movq mm5, mm4 - jmp .body -.fix_lt_1: - movq mm5, mm3 - pxor mm5, mm4 - psrlq mm5, 56 - psllq mm5, 48 - pxor mm1, mm5 - jmp .do_left -.fix_lt_2: - movq mm5, mm3 - pxor mm5, mm2 - psllq mm5, 56 - psrlq mm5, 56 - pxor mm2, mm5 - test r2d, r2d ; top_right - jnz .do_top -.fix_tr_1: - movq mm5, mm3 - pxor mm5, mm1 - psrlq mm5, 56 - psllq mm5, 56 - pxor mm1, mm5 - jmp .do_top -.body: - lea r1, [r0+r3*2] - movq mm1, mm7 - movq mm7, mm5 - movq mm5, mm6 - movq mm2, mm7 - lea r2, [r1+r3*2] - PALIGNR mm2, mm6, 1, mm0 - movq mm3, mm7 - PALIGNR mm3, mm6, 7, mm0 - movq mm4, mm7 - lea r4, [r2+r3*2] - psrlq mm4, 8 - PRED4x4_LOWPASS mm0, mm1, mm2, mm5, mm6 - PRED4x4_LOWPASS mm1, mm3, mm4, mm7, mm6 - movq [r4+r3*2], mm0 - movq mm2, mm1 - psrlq mm0, 8 - psllq mm2, 56 - psrlq mm1, 8 - por mm0, mm2 - movq [r4+r3*1], mm0 - movq mm2, mm1 - psrlq mm0, 8 - psllq mm2, 56 - psrlq mm1, 8 - por mm0, mm2 - movq [r2+r3*2], mm0 - movq mm2, mm1 - psrlq mm0, 8 - psllq mm2, 56 - psrlq mm1, 8 - por mm0, mm2 - movq [r2+r3*1], mm0 - movq mm2, mm1 - psrlq mm0, 8 - psllq mm2, 56 - psrlq mm1, 8 - por mm0, mm2 - movq [r1+r3*2], mm0 - movq mm2, mm1 - psrlq mm0, 8 - psllq mm2, 56 - psrlq mm1, 8 - por mm0, mm2 - movq [r1+r3*1], mm0 - movq mm2, mm1 - psrlq mm0, 8 - psllq mm2, 56 - psrlq mm1, 8 - por mm0, mm2 - movq [r0+r3*2], mm0 - psrlq mm0, 8 - psllq mm1, 56 - por mm0, mm1 - movq [r0+r3*1], mm0 - RET - %macro PRED8x8L_DOWN_RIGHT 0 cglobal pred8x8l_down_right_8, 4,5 sub r0, r3 @@ -1786,113 +1312,6 @@ PRED8x8L_DOWN_RIGHT ; int has_topright, ptrdiff_t stride) ;----------------------------------------------------------------------------- -INIT_MMX mmxext -cglobal pred8x8l_vertical_right_8, 4,5 - sub r0, r3 - lea r4, [r0+r3*2] - movq mm0, [r0+r3*1-8] - punpckhbw mm0, [r0+r3*0-8] - movq mm1, [r4+r3*1-8] - punpckhbw mm1, [r0+r3*2-8] - mov r4, r0 - punpckhwd mm1, mm0 - lea r0, [r0+r3*4] - movq mm2, [r0+r3*1-8] - punpckhbw mm2, [r0+r3*0-8] - lea r0, [r0+r3*2] - movq mm3, [r0+r3*1-8] - punpckhbw mm3, [r0+r3*0-8] - punpckhwd mm3, mm2 - punpckhdq mm3, mm1 - lea r0, [r0+r3*2] - movq mm0, [r0+r3*0-8] - movq mm1, [r4] - mov r0, r4 - movq mm4, mm3 - movq mm2, mm3 - PALIGNR mm4, mm0, 7, mm0 - PALIGNR mm1, mm2, 1, mm2 - test r1d, r1d - jz .fix_lt_1 - jmp .do_left -.fix_lt_1: - movq mm5, mm3 - pxor mm5, mm4 - psrlq mm5, 56 - psllq mm5, 48 - pxor mm1, mm5 - jmp .do_left -.fix_lt_2: - movq mm5, mm3 - pxor mm5, mm2 - psllq mm5, 56 - psrlq mm5, 56 - pxor mm2, mm5 - test r2d, r2d - jnz .do_top -.fix_tr_1: - movq mm5, mm3 - pxor mm5, mm1 - psrlq mm5, 56 - psllq mm5, 56 - pxor mm1, mm5 - jmp .do_top -.do_left: - movq mm0, mm4 - PRED4x4_LOWPASS mm2, mm1, mm4, mm3, mm5 - movq mm7, mm2 - movq mm0, [r0-8] - movq mm3, [r0] - movq mm1, [r0+8] - movq mm2, mm3 - movq mm4, mm3 - PALIGNR mm2, mm0, 7, mm0 - PALIGNR mm1, mm4, 1, mm4 - test r1d, r1d - jz .fix_lt_2 - test r2d, r2d - jz .fix_tr_1 -.do_top: - PRED4x4_LOWPASS mm6, mm2, mm1, mm3, mm5 - lea r1, [r0+r3*2] - movq mm2, mm6 - movq mm3, mm6 - PALIGNR mm3, mm7, 7, mm0 - PALIGNR mm6, mm7, 6, mm1 - movq mm4, mm3 - pavgb mm3, mm2 - lea r2, [r1+r3*2] - PRED4x4_LOWPASS mm0, mm6, mm2, mm4, mm5 - movq [r0+r3*1], mm3 - movq [r0+r3*2], mm0 - movq mm5, mm0 - movq mm6, mm3 - movq mm1, mm7 - movq mm2, mm1 - psllq mm2, 8 - movq mm3, mm1 - psllq mm3, 16 - lea r4, [r2+r3*2] - PRED4x4_LOWPASS mm0, mm1, mm3, mm2, mm4 - PALIGNR mm6, mm0, 7, mm2 - movq [r1+r3*1], mm6 - psllq mm0, 8 - PALIGNR mm5, mm0, 7, mm1 - movq [r1+r3*2], mm5 - psllq mm0, 8 - PALIGNR mm6, mm0, 7, mm2 - movq [r2+r3*1], mm6 - psllq mm0, 8 - PALIGNR mm5, mm0, 7, mm1 - movq [r2+r3*2], mm5 - psllq mm0, 8 - PALIGNR mm6, mm0, 7, mm2 - movq [r4+r3*1], mm6 - psllq mm0, 8 - PALIGNR mm5, mm0, 7, mm1 - movq [r4+r3*2], mm5 - RET - %macro PRED8x8L_VERTICAL_RIGHT 0 cglobal pred8x8l_vertical_right_8, 4,5,7 ; manually spill XMM registers for Win64 because @@ -2192,121 +1611,6 @@ PRED8x8L_HORIZONTAL_UP ; int has_topright, ptrdiff_t stride) ;----------------------------------------------------------------------------- -INIT_MMX mmxext -cglobal pred8x8l_horizontal_down_8, 4,5 - sub r0, r3 - lea r4, [r0+r3*2] - movq mm0, [r0+r3*1-8] - punpckhbw mm0, [r0+r3*0-8] - movq mm1, [r4+r3*1-8] - punpckhbw mm1, [r0+r3*2-8] - mov r4, r0 - punpckhwd mm1, mm0 - lea r0, [r0+r3*4] - movq mm2, [r0+r3*1-8] - punpckhbw mm2, [r0+r3*0-8] - lea r0, [r0+r3*2] - movq mm3, [r0+r3*1-8] - punpckhbw mm3, [r0+r3*0-8] - punpckhwd mm3, mm2 - punpckhdq mm3, mm1 - lea r0, [r0+r3*2] - movq mm0, [r0+r3*0-8] - movq mm1, [r4] - mov r0, r4 - movq mm4, mm3 - movq mm2, mm3 - PALIGNR mm4, mm0, 7, mm0 - PALIGNR mm1, mm2, 1, mm2 - test r1d, r1d - jnz .do_left -.fix_lt_1: - movq mm5, mm3 - pxor mm5, mm4 - psrlq mm5, 56 - psllq mm5, 48 - pxor mm1, mm5 - jmp .do_left -.fix_lt_2: - movq mm5, mm3 - pxor mm5, mm2 - psllq mm5, 56 - psrlq mm5, 56 - pxor mm2, mm5 - test r2d, r2d - jnz .do_top -.fix_tr_1: - movq mm5, mm3 - pxor mm5, mm1 - psrlq mm5, 56 - psllq mm5, 56 - pxor mm1, mm5 - jmp .do_top -.do_left: - movq mm0, mm4 - PRED4x4_LOWPASS mm2, mm1, mm4, mm3, mm5 - movq mm4, mm0 - movq mm7, mm2 - movq mm6, mm2 - PRED4x4_LOWPASS mm1, mm3, mm0, mm4, mm5 - psllq mm1, 56 - PALIGNR mm7, mm1, 7, mm3 - movq mm0, [r0-8] - movq mm3, [r0] - movq mm1, [r0+8] - movq mm2, mm3 - movq mm4, mm3 - PALIGNR mm2, mm0, 7, mm0 - PALIGNR mm1, mm4, 1, mm4 - test r1d, r1d - jz .fix_lt_2 - test r2d, r2d - jz .fix_tr_1 -.do_top: - PRED4x4_LOWPASS mm4, mm2, mm1, mm3, mm5 - movq mm5, mm4 - lea r1, [r0+r3*2] - psllq mm7, 56 - movq mm2, mm5 - movq mm3, mm6 - movq mm4, mm2 - PALIGNR mm2, mm6, 7, mm5 - PALIGNR mm6, mm7, 7, mm0 - lea r2, [r1+r3*2] - PALIGNR mm4, mm3, 1, mm7 - movq mm5, mm3 - pavgb mm3, mm6 - PRED4x4_LOWPASS mm0, mm4, mm6, mm5, mm7 - movq mm4, mm2 - movq mm1, mm2 - lea r4, [r2+r3*2] - psrlq mm4, 16 - psrlq mm1, 8 - PRED4x4_LOWPASS mm6, mm4, mm2, mm1, mm5 - movq mm7, mm3 - punpcklbw mm3, mm0 - punpckhbw mm7, mm0 - movq mm1, mm7 - movq mm0, mm7 - movq mm4, mm7 - movq [r4+r3*2], mm3 - PALIGNR mm7, mm3, 2, mm5 - movq [r4+r3*1], mm7 - PALIGNR mm1, mm3, 4, mm5 - movq [r2+r3*2], mm1 - PALIGNR mm0, mm3, 6, mm3 - movq [r2+r3*1], mm0 - movq mm2, mm6 - movq mm3, mm6 - movq [r1+r3*2], mm4 - PALIGNR mm6, mm4, 2, mm5 - movq [r1+r3*1], mm6 - PALIGNR mm2, mm4, 4, mm5 - movq [r0+r3*2], mm2 - PALIGNR mm3, mm4, 6, mm4 - movq [r0+r3*1], mm3 - RET - %macro PRED8x8L_HORIZONTAL_DOWN 0 cglobal pred8x8l_horizontal_down_8, 4,5 sub r0, r3 @@ -2472,7 +1776,7 @@ cglobal pred4x4_dc_8, 3,5 ; ptrdiff_t stride) ;----------------------------------------------------------------------------- -%macro PRED4x4_TM 0 +INIT_MMX mmxext cglobal pred4x4_tm_vp8_8, 3,6 sub r0, r2 pxor mm7, mm7 @@ -2487,15 +1791,8 @@ cglobal pred4x4_tm_vp8_8, 3,6 sub r3d, r4d movd mm2, r1d movd mm4, r3d -%if cpuflag(mmxext) pshufw mm2, mm2, 0 pshufw mm4, mm4, 0 -%else - punpcklwd mm2, mm2 - punpcklwd mm4, mm4 - punpckldq mm2, mm2 - punpckldq mm4, mm4 -%endif paddw mm2, mm0 paddw mm4, mm0 packuswb mm2, mm2 @@ -2506,12 +1803,6 @@ cglobal pred4x4_tm_vp8_8, 3,6 dec r5d jg .loop REP_RET -%endmacro - -INIT_MMX mmx -PRED4x4_TM -INIT_MMX mmxext -PRED4x4_TM INIT_XMM ssse3 cglobal pred4x4_tm_vp8_8, 3,3 diff --git a/libavcodec/x86/h264_intrapred_10bit.asm b/libavcodec/x86/h264_intrapred_10bit.asm index 629e0a72e..c4645d434 100644 --- a/libavcodec/x86/h264_intrapred_10bit.asm +++ b/libavcodec/x86/h264_intrapred_10bit.asm @@ -334,12 +334,7 @@ cglobal pred8x8_horizontal_10, 2, 3 ;----------------------------------------------------------------------------- %macro MOV8 2-3 ; sort of a hack, but it works -%if mmsize==8 - movq [%1+0], %2 - movq [%1+8], %3 -%else movdqa [%1], %2 -%endif %endmacro %macro PRED8x8_DC 1 @@ -348,17 +343,9 @@ cglobal pred8x8_dc_10, 2, 6 pxor m4, m4 movq m0, [r0+0] movq m1, [r0+8] -%if mmsize==16 punpcklwd m0, m1 movhlps m1, m0 paddw m0, m1 -%else - pshufw m2, m0, 00001110b - pshufw m3, m1, 00001110b - paddw m0, m2 - paddw m1, m3 - punpcklwd m0, m1 -%endif %1 m2, m0, 00001110b paddw m0, m2 @@ -389,17 +376,10 @@ cglobal pred8x8_dc_10, 2, 6 paddw m0, m3 psrlw m0, 2 pavgw m0, m4 ; s0+s2, s1, s3, s1+s3 -%if mmsize==16 punpcklwd m0, m0 pshufd m3, m0, 11111010b punpckldq m0, m0 SWAP 0,1 -%else - pshufw m1, m0, 0x00 - pshufw m2, m0, 0x55 - pshufw m3, m0, 0xaa - pshufw m4, m0, 0xff -%endif MOV8 r0+r1*1, m1, m2 MOV8 r0+r1*2, m1, m2 MOV8 r0+r5*1, m1, m2 @@ -411,8 +391,6 @@ cglobal pred8x8_dc_10, 2, 6 RET %endmacro -INIT_MMX mmxext -PRED8x8_DC pshufw INIT_XMM sse2 PRED8x8_DC pshuflw @@ -510,7 +488,7 @@ cglobal pred8x8_plane_10, 2, 7, 7 ; void ff_pred8x8l_128_dc_10(pixel *src, int has_topleft, int has_topright, ; ptrdiff_t stride) ;----------------------------------------------------------------------------- -%macro PRED8x8L_128_DC 0 +INIT_XMM sse2 cglobal pred8x8l_128_dc_10, 4, 4 mova m0, [pw_512] ; (1<<(BIT_DEPTH-1)) lea r1, [r3*3] @@ -524,12 +502,6 @@ cglobal pred8x8l_128_dc_10, 4, 4 MOV8 r2+r3*2, m0, m0 MOV8 r2+r1*1, m0, m0 RET -%endmacro - -INIT_MMX mmxext -PRED8x8L_128_DC -INIT_XMM sse2 -PRED8x8L_128_DC ;----------------------------------------------------------------------------- ; void ff_pred8x8l_top_dc_10(pixel *src, int has_topleft, int has_topright, @@ -1008,22 +980,14 @@ PRED8x8L_HORIZONTAL_UP %macro MOV16 3-5 mova [%1+ 0], %2 mova [%1+mmsize], %3 -%if mmsize==8 - mova [%1+ 16], %4 - mova [%1+ 24], %5 -%endif %endmacro -%macro PRED16x16_VERTICAL 0 +INIT_XMM sse2 cglobal pred16x16_vertical_10, 2, 3 sub r0, r1 mov r2d, 8 mova m0, [r0+ 0] mova m1, [r0+mmsize] -%if mmsize==8 - mova m2, [r0+16] - mova m3, [r0+24] -%endif .loop: MOV16 r0+r1*1, m0, m1, m2, m3 MOV16 r0+r1*2, m0, m1, m2, m3 @@ -1031,17 +995,11 @@ cglobal pred16x16_vertical_10, 2, 3 dec r2d jg .loop REP_RET -%endmacro - -INIT_MMX mmxext -PRED16x16_VERTICAL -INIT_XMM sse2 -PRED16x16_VERTICAL ;----------------------------------------------------------------------------- ; void ff_pred16x16_horizontal_10(pixel *src, ptrdiff_t stride) ;----------------------------------------------------------------------------- -%macro PRED16x16_HORIZONTAL 0 +INIT_XMM sse2 cglobal pred16x16_horizontal_10, 2, 3 mov r2d, 8 .vloop: @@ -1055,26 +1013,16 @@ cglobal pred16x16_horizontal_10, 2, 3 dec r2d jg .vloop REP_RET -%endmacro - -INIT_MMX mmxext -PRED16x16_HORIZONTAL -INIT_XMM sse2 -PRED16x16_HORIZONTAL ;----------------------------------------------------------------------------- ; void ff_pred16x16_dc_10(pixel *src, ptrdiff_t stride) ;----------------------------------------------------------------------------- -%macro PRED16x16_DC 0 +INIT_XMM sse2 cglobal pred16x16_dc_10, 2, 6 mov r5, r0 sub r0, r1 mova m0, [r0+0] paddw m0, [r0+mmsize] -%if mmsize==8 - paddw m0, [r0+16] - paddw m0, [r0+24] -%endif HADDW m0, m2 lea r0, [r0+r1-2] @@ -1101,25 +1049,15 @@ cglobal pred16x16_dc_10, 2, 6 dec r3d jg .loop REP_RET -%endmacro - -INIT_MMX mmxext -PRED16x16_DC -INIT_XMM sse2 -PRED16x16_DC ;----------------------------------------------------------------------------- ; void ff_pred16x16_top_dc_10(pixel *src, ptrdiff_t stride) ;----------------------------------------------------------------------------- -%macro PRED16x16_TOP_DC 0 +INIT_XMM sse2 cglobal pred16x16_top_dc_10, 2, 3 sub r0, r1 mova m0, [r0+0] paddw m0, [r0+mmsize] -%if mmsize==8 - paddw m0, [r0+16] - paddw m0, [r0+24] -%endif HADDW m0, m2 SPLATW m0, m0 @@ -1133,17 +1071,11 @@ cglobal pred16x16_top_dc_10, 2, 3 dec r2d jg .loop REP_RET -%endmacro - -INIT_MMX mmxext -PRED16x16_TOP_DC -INIT_XMM sse2 -PRED16x16_TOP_DC ;----------------------------------------------------------------------------- ; void ff_pred16x16_left_dc_10(pixel *src, ptrdiff_t stride) ;----------------------------------------------------------------------------- -%macro PRED16x16_LEFT_DC 0 +INIT_XMM sse2 cglobal pred16x16_left_dc_10, 2, 6 mov r5, r0 @@ -1170,17 +1102,11 @@ cglobal pred16x16_left_dc_10, 2, 6 dec r3d jg .loop REP_RET -%endmacro - -INIT_MMX mmxext -PRED16x16_LEFT_DC -INIT_XMM sse2 -PRED16x16_LEFT_DC ;----------------------------------------------------------------------------- ; void ff_pred16x16_128_dc_10(pixel *src, ptrdiff_t stride) ;----------------------------------------------------------------------------- -%macro PRED16x16_128_DC 0 +INIT_XMM sse2 cglobal pred16x16_128_dc_10, 2,3 mova m0, [pw_512] mov r2d, 8 @@ -1191,9 +1117,3 @@ cglobal pred16x16_128_dc_10, 2,3 dec r2d jg .loop REP_RET -%endmacro - -INIT_MMX mmxext -PRED16x16_128_DC -INIT_XMM sse2 -PRED16x16_128_DC diff --git a/libavcodec/x86/h264_intrapred_init.c b/libavcodec/x86/h264_intrapred_init.c index a95cfbca5..ee46927a2 100644 --- a/libavcodec/x86/h264_intrapred_init.c +++ b/libavcodec/x86/h264_intrapred_init.c @@ -52,7 +52,6 @@ PRED4x4(horizontal_down, 10, avx) void ff_pred8x8_ ## TYPE ## _ ## DEPTH ## _ ## OPT (uint8_t *src, \ ptrdiff_t stride); -PRED8x8(dc, 10, mmxext) PRED8x8(dc, 10, sse2) PRED8x8(top_dc, 10, sse2) PRED8x8(plane, 10, sse2) @@ -67,7 +66,6 @@ void ff_pred8x8l_ ## TYPE ## _ ## DEPTH ## _ ## OPT (uint8_t *src, \ PRED8x8L(dc, 10, sse2) PRED8x8L(dc, 10, avx) -PRED8x8L(128_dc, 10, mmxext) PRED8x8L(128_dc, 10, sse2) PRED8x8L(top_dc, 10, sse2) PRED8x8L(top_dc, 10, avx) @@ -93,42 +91,25 @@ PRED8x8L(horizontal_up, 10, avx) void ff_pred16x16_ ## TYPE ## _ ## DEPTH ## _ ## OPT (uint8_t *src, \ ptrdiff_t stride); -PRED16x16(dc, 10, mmxext) PRED16x16(dc, 10, sse2) -PRED16x16(top_dc, 10, mmxext) PRED16x16(top_dc, 10, sse2) -PRED16x16(128_dc, 10, mmxext) PRED16x16(128_dc, 10, sse2) -PRED16x16(left_dc, 10, mmxext) PRED16x16(left_dc, 10, sse2) -PRED16x16(vertical, 10, mmxext) PRED16x16(vertical, 10, sse2) -PRED16x16(horizontal, 10, mmxext) PRED16x16(horizontal, 10, sse2) /* 8-bit versions */ -PRED16x16(vertical, 8, mmx) PRED16x16(vertical, 8, sse) -PRED16x16(horizontal, 8, mmx) PRED16x16(horizontal, 8, mmxext) PRED16x16(horizontal, 8, ssse3) -PRED16x16(dc, 8, mmxext) PRED16x16(dc, 8, sse2) PRED16x16(dc, 8, ssse3) -PRED16x16(plane_h264, 8, mmx) -PRED16x16(plane_h264, 8, mmxext) PRED16x16(plane_h264, 8, sse2) PRED16x16(plane_h264, 8, ssse3) -PRED16x16(plane_rv40, 8, mmx) -PRED16x16(plane_rv40, 8, mmxext) PRED16x16(plane_rv40, 8, sse2) PRED16x16(plane_rv40, 8, ssse3) -PRED16x16(plane_svq3, 8, mmx) -PRED16x16(plane_svq3, 8, mmxext) PRED16x16(plane_svq3, 8, sse2) PRED16x16(plane_svq3, 8, ssse3) -PRED16x16(tm_vp8, 8, mmx) -PRED16x16(tm_vp8, 8, mmxext) PRED16x16(tm_vp8, 8, sse2) PRED16x16(tm_vp8, 8, avx2) @@ -136,15 +117,10 @@ PRED8x8(top_dc, 8, mmxext) PRED8x8(dc_rv40, 8, mmxext) PRED8x8(dc, 8, mmxext) PRED8x8(vertical, 8, mmx) -PRED8x8(horizontal, 8, mmx) PRED8x8(horizontal, 8, mmxext) PRED8x8(horizontal, 8, ssse3) -PRED8x8(plane, 8, mmx) -PRED8x8(plane, 8, mmxext) PRED8x8(plane, 8, sse2) PRED8x8(plane, 8, ssse3) -PRED8x8(tm_vp8, 8, mmx) -PRED8x8(tm_vp8, 8, mmxext) PRED8x8(tm_vp8, 8, sse2) PRED8x8(tm_vp8, 8, ssse3) @@ -156,20 +132,16 @@ PRED8x8L(horizontal, 8, mmxext) PRED8x8L(horizontal, 8, ssse3) PRED8x8L(vertical, 8, mmxext) PRED8x8L(vertical, 8, ssse3) -PRED8x8L(down_left, 8, mmxext) PRED8x8L(down_left, 8, sse2) PRED8x8L(down_left, 8, ssse3) -PRED8x8L(down_right, 8, mmxext) PRED8x8L(down_right, 8, sse2) PRED8x8L(down_right, 8, ssse3) -PRED8x8L(vertical_right, 8, mmxext) PRED8x8L(vertical_right, 8, sse2) PRED8x8L(vertical_right, 8, ssse3) PRED8x8L(vertical_left, 8, sse2) PRED8x8L(vertical_left, 8, ssse3) PRED8x8L(horizontal_up, 8, mmxext) PRED8x8L(horizontal_up, 8, ssse3) -PRED8x8L(horizontal_down, 8, mmxext) PRED8x8L(horizontal_down, 8, sse2) PRED8x8L(horizontal_down, 8, ssse3) @@ -180,7 +152,6 @@ PRED4x4(vertical_left, 8, mmxext) PRED4x4(vertical_right, 8, mmxext) PRED4x4(horizontal_up, 8, mmxext) PRED4x4(horizontal_down, 8, mmxext) -PRED4x4(tm_vp8, 8, mmx) PRED4x4(tm_vp8, 8, mmxext) PRED4x4(tm_vp8, 8, ssse3) PRED4x4(vertical_vp8, 8, mmxext) @@ -193,44 +164,20 @@ av_cold void ff_h264_pred_init_x86(H264PredContext *h, int codec_id, if (bit_depth == 8) { if (EXTERNAL_MMX(cpu_flags)) { - h->pred16x16[VERT_PRED8x8 ] = ff_pred16x16_vertical_8_mmx; - h->pred16x16[HOR_PRED8x8 ] = ff_pred16x16_horizontal_8_mmx; if (chroma_format_idc <= 1) { h->pred8x8 [VERT_PRED8x8 ] = ff_pred8x8_vertical_8_mmx; - h->pred8x8 [HOR_PRED8x8 ] = ff_pred8x8_horizontal_8_mmx; - } - if (codec_id == AV_CODEC_ID_VP7 || codec_id == AV_CODEC_ID_VP8) { - h->pred16x16[PLANE_PRED8x8 ] = ff_pred16x16_tm_vp8_8_mmx; - h->pred8x8 [PLANE_PRED8x8 ] = ff_pred8x8_tm_vp8_8_mmx; - h->pred4x4 [TM_VP8_PRED ] = ff_pred4x4_tm_vp8_8_mmx; - } else { - if (chroma_format_idc <= 1) - h->pred8x8 [PLANE_PRED8x8] = ff_pred8x8_plane_8_mmx; - if (codec_id == AV_CODEC_ID_SVQ3) { - if (cpu_flags & AV_CPU_FLAG_CMOV) - h->pred16x16[PLANE_PRED8x8] = ff_pred16x16_plane_svq3_8_mmx; - } else if (codec_id == AV_CODEC_ID_RV40) { - h->pred16x16[PLANE_PRED8x8] = ff_pred16x16_plane_rv40_8_mmx; - } else { - h->pred16x16[PLANE_PRED8x8] = ff_pred16x16_plane_h264_8_mmx; - } } } if (EXTERNAL_MMXEXT(cpu_flags)) { h->pred16x16[HOR_PRED8x8 ] = ff_pred16x16_horizontal_8_mmxext; - h->pred16x16[DC_PRED8x8 ] = ff_pred16x16_dc_8_mmxext; if (chroma_format_idc <= 1) h->pred8x8[HOR_PRED8x8 ] = ff_pred8x8_horizontal_8_mmxext; h->pred8x8l [TOP_DC_PRED ] = ff_pred8x8l_top_dc_8_mmxext; h->pred8x8l [DC_PRED ] = ff_pred8x8l_dc_8_mmxext; h->pred8x8l [HOR_PRED ] = ff_pred8x8l_horizontal_8_mmxext; h->pred8x8l [VERT_PRED ] = ff_pred8x8l_vertical_8_mmxext; - h->pred8x8l [DIAG_DOWN_RIGHT_PRED ] = ff_pred8x8l_down_right_8_mmxext; - h->pred8x8l [VERT_RIGHT_PRED ] = ff_pred8x8l_vertical_right_8_mmxext; h->pred8x8l [HOR_UP_PRED ] = ff_pred8x8l_horizontal_up_8_mmxext; - h->pred8x8l [DIAG_DOWN_LEFT_PRED ] = ff_pred8x8l_down_left_8_mmxext; - h->pred8x8l [HOR_DOWN_PRED ] = ff_pred8x8l_horizontal_down_8_mmxext; h->pred4x4 [DIAG_DOWN_RIGHT_PRED ] = ff_pred4x4_down_right_8_mmxext; h->pred4x4 [VERT_RIGHT_PRED ] = ff_pred4x4_vertical_right_8_mmxext; h->pred4x4 [HOR_DOWN_PRED ] = ff_pred4x4_horizontal_down_8_mmxext; @@ -252,21 +199,9 @@ av_cold void ff_h264_pred_init_x86(H264PredContext *h, int codec_id, } } if (codec_id == AV_CODEC_ID_VP7 || codec_id == AV_CODEC_ID_VP8) { - h->pred16x16[PLANE_PRED8x8 ] = ff_pred16x16_tm_vp8_8_mmxext; h->pred8x8 [DC_PRED8x8 ] = ff_pred8x8_dc_rv40_8_mmxext; - h->pred8x8 [PLANE_PRED8x8 ] = ff_pred8x8_tm_vp8_8_mmxext; h->pred4x4 [TM_VP8_PRED ] = ff_pred4x4_tm_vp8_8_mmxext; h->pred4x4 [VERT_PRED ] = ff_pred4x4_vertical_vp8_8_mmxext; - } else { - if (chroma_format_idc <= 1) - h->pred8x8 [PLANE_PRED8x8] = ff_pred8x8_plane_8_mmxext; - if (codec_id == AV_CODEC_ID_SVQ3) { - h->pred16x16[PLANE_PRED8x8 ] = ff_pred16x16_plane_svq3_8_mmxext; - } else if (codec_id == AV_CODEC_ID_RV40) { - h->pred16x16[PLANE_PRED8x8 ] = ff_pred16x16_plane_rv40_8_mmxext; - } else { - h->pred16x16[PLANE_PRED8x8 ] = ff_pred16x16_plane_h264_8_mmxext; - } } } @@ -337,18 +272,6 @@ av_cold void ff_h264_pred_init_x86(H264PredContext *h, int codec_id, if (EXTERNAL_MMXEXT(cpu_flags)) { h->pred4x4[DC_PRED ] = ff_pred4x4_dc_10_mmxext; h->pred4x4[HOR_UP_PRED ] = ff_pred4x4_horizontal_up_10_mmxext; - - if (chroma_format_idc <= 1) - h->pred8x8[DC_PRED8x8 ] = ff_pred8x8_dc_10_mmxext; - - h->pred8x8l[DC_128_PRED ] = ff_pred8x8l_128_dc_10_mmxext; - - h->pred16x16[DC_PRED8x8 ] = ff_pred16x16_dc_10_mmxext; - h->pred16x16[TOP_DC_PRED8x8 ] = ff_pred16x16_top_dc_10_mmxext; - h->pred16x16[DC_128_PRED8x8 ] = ff_pred16x16_128_dc_10_mmxext; - h->pred16x16[LEFT_DC_PRED8x8 ] = ff_pred16x16_left_dc_10_mmxext; - h->pred16x16[VERT_PRED8x8 ] = ff_pred16x16_vertical_10_mmxext; - h->pred16x16[HOR_PRED8x8 ] = ff_pred16x16_horizontal_10_mmxext; } if (EXTERNAL_SSE2(cpu_flags)) { h->pred4x4[DIAG_DOWN_LEFT_PRED ] = ff_pred4x4_down_left_10_sse2; diff --git a/libavcodec/x86/h264_qpel.c b/libavcodec/x86/h264_qpel.c index 320d98933..b9b1edcd9 100644 --- a/libavcodec/x86/h264_qpel.c +++ b/libavcodec/x86/h264_qpel.c @@ -24,7 +24,6 @@ #include "libavutil/mem_internal.h" #include "libavutil/x86/asm.h" #include "libavutil/x86/cpu.h" -#include "libavcodec/h264dec.h" #include "libavcodec/h264qpel.h" #include "libavcodec/pixels.h" #include "fpel.h" @@ -58,11 +57,9 @@ void ff_ ## OPNAME ## _h264_qpel4_h_lowpass_l2_mmxext(uint8_t *dst, const uint8_ void ff_ ## OPNAME ## _h264_qpel8_h_lowpass_l2_mmxext(uint8_t *dst, const uint8_t *src, const uint8_t *src2, int dstStride, int src2Stride);\ void ff_ ## OPNAME ## _h264_qpel8_h_lowpass_l2_ssse3(uint8_t *dst, const uint8_t *src, const uint8_t *src2, int dstStride, int src2Stride);\ void ff_ ## OPNAME ## _h264_qpel4_v_lowpass_mmxext(uint8_t *dst, const uint8_t *src, int dstStride, int srcStride);\ -void ff_ ## OPNAME ## _h264_qpel8or16_v_lowpass_op_mmxext(uint8_t *dst, const uint8_t *src, int dstStride, int srcStride, int h);\ void ff_ ## OPNAME ## _h264_qpel8or16_v_lowpass_sse2(uint8_t *dst, const uint8_t *src, int dstStride, int srcStride, int h);\ void ff_ ## OPNAME ## _h264_qpel4_hv_lowpass_v_mmxext(const uint8_t *src, int16_t *tmp, int srcStride);\ void ff_ ## OPNAME ## _h264_qpel4_hv_lowpass_h_mmxext(int16_t *tmp, uint8_t *dst, int dstStride);\ -void ff_ ## OPNAME ## _h264_qpel8or16_hv1_lowpass_op_mmxext(const uint8_t *src, int16_t *tmp, int srcStride, int size);\ void ff_ ## OPNAME ## _h264_qpel8or16_hv1_lowpass_op_sse2(const uint8_t *src, int16_t *tmp, int srcStride, int size);\ void ff_ ## OPNAME ## _h264_qpel8or16_hv2_lowpass_op_mmxext(uint8_t *dst, int16_t *tmp, int dstStride, int unused, int h);\ void ff_ ## OPNAME ## _h264_qpel8or16_hv2_lowpass_ssse3(uint8_t *dst, int16_t *tmp, int dstStride, int tmpStride, int size);\ @@ -72,17 +69,6 @@ void ff_ ## OPNAME ## _pixels8_l2_shift5_mmxext(uint8_t *dst, const int16_t *src DEF_QPEL(avg) DEF_QPEL(put) -static av_always_inline void ff_put_h264_qpel8or16_hv1_lowpass_mmxext(int16_t *tmp, const uint8_t *src, int tmpStride, int srcStride, int size) -{ - int w = (size + 8) >> 2; - src -= 2 * srcStride + 2; - while (w--) { - ff_put_h264_qpel8or16_hv1_lowpass_op_mmxext(src, tmp, srcStride, size); - tmp += 4; - src += 4; - } -} - #define QPEL_H264(OPNAME, OP, MMX)\ static av_always_inline void ff_ ## OPNAME ## h264_qpel4_hv_lowpass_ ## MMX(uint8_t *dst, int16_t *tmp, const uint8_t *src, int dstStride, int tmpStride, int srcStride){\ int w=3;\ @@ -96,13 +82,6 @@ static av_always_inline void ff_ ## OPNAME ## h264_qpel4_hv_lowpass_ ## MMX(uint ff_ ## OPNAME ## h264_qpel4_hv_lowpass_h_mmxext(tmp, dst, dstStride);\ }\ \ -static av_always_inline void ff_ ## OPNAME ## h264_qpel8or16_v_lowpass_ ## MMX(uint8_t *dst, const uint8_t *src, int dstStride, int srcStride, int h){\ - src -= 2*srcStride;\ - ff_ ## OPNAME ## h264_qpel8or16_v_lowpass_op_mmxext(dst, src, dstStride, srcStride, h);\ - src += 4;\ - dst += 4;\ - ff_ ## OPNAME ## h264_qpel8or16_v_lowpass_op_mmxext(dst, src, dstStride, srcStride, h);\ -}\ static av_always_inline void ff_ ## OPNAME ## h264_qpel8or16_hv2_lowpass_ ## MMX(uint8_t *dst, int16_t *tmp, int dstStride, int tmpStride, int size){\ int w = size>>4;\ do{\ @@ -112,14 +91,6 @@ static av_always_inline void ff_ ## OPNAME ## h264_qpel8or16_hv2_lowpass_ ## MMX }while(w--);\ }\ \ -static av_always_inline void ff_ ## OPNAME ## h264_qpel8_v_lowpass_ ## MMX(uint8_t *dst, const uint8_t *src, int dstStride, int srcStride){\ - ff_ ## OPNAME ## h264_qpel8or16_v_lowpass_ ## MMX(dst , src , dstStride, srcStride, 8);\ -}\ -static av_always_inline void ff_ ## OPNAME ## h264_qpel16_v_lowpass_ ## MMX(uint8_t *dst, const uint8_t *src, int dstStride, int srcStride){\ - ff_ ## OPNAME ## h264_qpel8or16_v_lowpass_ ## MMX(dst , src , dstStride, srcStride, 16);\ - ff_ ## OPNAME ## h264_qpel8or16_v_lowpass_ ## MMX(dst+8, src+8, dstStride, srcStride, 16);\ -}\ -\ static av_always_inline void ff_ ## OPNAME ## h264_qpel16_h_lowpass_ ## MMX(uint8_t *dst, const uint8_t *src, int dstStride, int srcStride){\ ff_ ## OPNAME ## h264_qpel8_h_lowpass_ ## MMX(dst , src , dstStride, srcStride);\ ff_ ## OPNAME ## h264_qpel8_h_lowpass_ ## MMX(dst+8, src+8, dstStride, srcStride);\ @@ -139,18 +110,6 @@ static av_always_inline void ff_ ## OPNAME ## h264_qpel16_h_lowpass_l2_ ## MMX(u ff_ ## OPNAME ## h264_qpel8_h_lowpass_l2_ ## MMX(dst+8, src+8, src2+8, dstStride, src2Stride);\ }\ \ -static av_always_inline void ff_ ## OPNAME ## h264_qpel8or16_hv_lowpass_ ## MMX(uint8_t *dst, int16_t *tmp, const uint8_t *src, int dstStride, int tmpStride, int srcStride, int size){\ - ff_put_h264_qpel8or16_hv1_lowpass_ ## MMX(tmp, src, tmpStride, srcStride, size);\ - ff_ ## OPNAME ## h264_qpel8or16_hv2_lowpass_ ## MMX(dst, tmp, dstStride, tmpStride, size);\ -}\ -static av_always_inline void ff_ ## OPNAME ## h264_qpel8_hv_lowpass_ ## MMX(uint8_t *dst, int16_t *tmp, const uint8_t *src, int dstStride, int tmpStride, int srcStride){\ - ff_ ## OPNAME ## h264_qpel8or16_hv_lowpass_ ## MMX(dst , tmp , src , dstStride, tmpStride, srcStride, 8);\ -}\ -\ -static av_always_inline void ff_ ## OPNAME ## h264_qpel16_hv_lowpass_ ## MMX(uint8_t *dst, int16_t *tmp, const uint8_t *src, int dstStride, int tmpStride, int srcStride){\ - ff_ ## OPNAME ## h264_qpel8or16_hv_lowpass_ ## MMX(dst , tmp , src , dstStride, tmpStride, srcStride, 16);\ -}\ -\ static av_always_inline void ff_ ## OPNAME ## pixels16_l2_shift5_ ## MMX(uint8_t *dst, const int16_t *src16, const uint8_t *src8, int dstStride, int src8Stride, int h)\ {\ ff_ ## OPNAME ## pixels8_l2_shift5_ ## MMX(dst , src16 , src8 , dstStride, src8Stride, h);\ @@ -237,7 +196,11 @@ static av_always_inline void ff_ ## OPNAME ## h264_qpel16_hv_lowpass_ ## MMX(uin #define ff_put_h264_qpel8or16_hv2_lowpass_sse2 ff_put_h264_qpel8or16_hv2_lowpass_mmxext #define ff_avg_h264_qpel8or16_hv2_lowpass_sse2 ff_avg_h264_qpel8or16_hv2_lowpass_mmxext -#define H264_MC(OPNAME, SIZE, MMX, ALIGN) \ +#define H264_MC_C_H(OPNAME, SIZE, MMX, ALIGN) \ +H264_MC_C(OPNAME, SIZE, MMX, ALIGN)\ +H264_MC_H(OPNAME, SIZE, MMX, ALIGN)\ + +#define H264_MC_C_V_H_HV(OPNAME, SIZE, MMX, ALIGN) \ H264_MC_C(OPNAME, SIZE, MMX, ALIGN)\ H264_MC_V(OPNAME, SIZE, MMX, ALIGN)\ H264_MC_H(OPNAME, SIZE, MMX, ALIGN)\ @@ -373,13 +336,9 @@ static void OPNAME ## h264_qpel ## SIZE ## _mc32_ ## MMX(uint8_t *dst, const uin ff_ ## OPNAME ## pixels ## SIZE ## _l2_shift5_mmxext(dst, halfV+3, halfHV, stride, SIZE, SIZE);\ }\ -#define H264_MC_4816(MMX)\ -H264_MC(put_, 4, MMX, 8)\ -H264_MC(put_, 8, MMX, 8)\ -H264_MC(put_, 16,MMX, 8)\ -H264_MC(avg_, 4, MMX, 8)\ -H264_MC(avg_, 8, MMX, 8)\ -H264_MC(avg_, 16,MMX, 8)\ +#define H264_MC(QPEL, SIZE, MMX, ALIGN)\ +QPEL(put_, SIZE, MMX, ALIGN) \ +QPEL(avg_, SIZE, MMX, ALIGN) \ #define H264_MC_816(QPEL, XMM)\ QPEL(put_, 8, XMM, 16)\ @@ -398,7 +357,9 @@ QPEL_H264_H_XMM(avg_,AVG_MMXEXT_OP, ssse3) QPEL_H264_HV_XMM(put_, PUT_OP, ssse3) QPEL_H264_HV_XMM(avg_,AVG_MMXEXT_OP, ssse3) -H264_MC_4816(mmxext) +H264_MC(H264_MC_C_V_H_HV, 4, mmxext, 8) +H264_MC(H264_MC_C_H, 8, mmxext, 8) +H264_MC(H264_MC_C_H, 16, mmxext, 8) H264_MC_816(H264_MC_V, sse2) H264_MC_816(H264_MC_HV, sse2) H264_MC_816(H264_MC_H, ssse3) @@ -410,13 +371,9 @@ H264_MC_816(H264_MC_HV, ssse3) void ff_ ## OP ## _h264_qpel ## NUM ## _ ## TYPE ## _ ## DEPTH ## _ ## OPT \ (uint8_t *dst, const uint8_t *src, ptrdiff_t stride); -#define LUMA_MC_ALL(DEPTH, TYPE, OPT) \ +#define LUMA_MC_4(DEPTH, TYPE, OPT) \ LUMA_MC_OP(put, 4, DEPTH, TYPE, OPT) \ - LUMA_MC_OP(avg, 4, DEPTH, TYPE, OPT) \ - LUMA_MC_OP(put, 8, DEPTH, TYPE, OPT) \ - LUMA_MC_OP(avg, 8, DEPTH, TYPE, OPT) \ - LUMA_MC_OP(put, 16, DEPTH, TYPE, OPT) \ - LUMA_MC_OP(avg, 16, DEPTH, TYPE, OPT) + LUMA_MC_OP(avg, 4, DEPTH, TYPE, OPT) #define LUMA_MC_816(DEPTH, TYPE, OPT) \ LUMA_MC_OP(put, 8, DEPTH, TYPE, OPT) \ @@ -424,22 +381,22 @@ void ff_ ## OP ## _h264_qpel ## NUM ## _ ## TYPE ## _ ## DEPTH ## _ ## OPT \ LUMA_MC_OP(put, 16, DEPTH, TYPE, OPT) \ LUMA_MC_OP(avg, 16, DEPTH, TYPE, OPT) -LUMA_MC_ALL(10, mc00, mmxext) -LUMA_MC_ALL(10, mc10, mmxext) -LUMA_MC_ALL(10, mc20, mmxext) -LUMA_MC_ALL(10, mc30, mmxext) -LUMA_MC_ALL(10, mc01, mmxext) -LUMA_MC_ALL(10, mc11, mmxext) -LUMA_MC_ALL(10, mc21, mmxext) -LUMA_MC_ALL(10, mc31, mmxext) -LUMA_MC_ALL(10, mc02, mmxext) -LUMA_MC_ALL(10, mc12, mmxext) -LUMA_MC_ALL(10, mc22, mmxext) -LUMA_MC_ALL(10, mc32, mmxext) -LUMA_MC_ALL(10, mc03, mmxext) -LUMA_MC_ALL(10, mc13, mmxext) -LUMA_MC_ALL(10, mc23, mmxext) -LUMA_MC_ALL(10, mc33, mmxext) +LUMA_MC_4(10, mc00, mmxext) +LUMA_MC_4(10, mc10, mmxext) +LUMA_MC_4(10, mc20, mmxext) +LUMA_MC_4(10, mc30, mmxext) +LUMA_MC_4(10, mc01, mmxext) +LUMA_MC_4(10, mc11, mmxext) +LUMA_MC_4(10, mc21, mmxext) +LUMA_MC_4(10, mc31, mmxext) +LUMA_MC_4(10, mc02, mmxext) +LUMA_MC_4(10, mc12, mmxext) +LUMA_MC_4(10, mc22, mmxext) +LUMA_MC_4(10, mc32, mmxext) +LUMA_MC_4(10, mc03, mmxext) +LUMA_MC_4(10, mc13, mmxext) +LUMA_MC_4(10, mc23, mmxext) +LUMA_MC_4(10, mc33, mmxext) LUMA_MC_816(10, mc00, sse2) LUMA_MC_816(10, mc10, sse2) @@ -464,50 +421,18 @@ LUMA_MC_816(10, mc13, sse2) LUMA_MC_816(10, mc23, sse2) LUMA_MC_816(10, mc33, sse2) -#define QPEL16_OPMC(OP, MC, MMX)\ -void ff_ ## OP ## _h264_qpel16_ ## MC ## _10_ ## MMX(uint8_t *dst, const uint8_t *src, ptrdiff_t stride){\ - ff_ ## OP ## _h264_qpel8_ ## MC ## _10_ ## MMX(dst , src , stride);\ - ff_ ## OP ## _h264_qpel8_ ## MC ## _10_ ## MMX(dst+16, src+16, stride);\ - src += 8*stride;\ - dst += 8*stride;\ - ff_ ## OP ## _h264_qpel8_ ## MC ## _10_ ## MMX(dst , src , stride);\ - ff_ ## OP ## _h264_qpel8_ ## MC ## _10_ ## MMX(dst+16, src+16, stride);\ -} - -#define QPEL16_OP(MC, MMX)\ -QPEL16_OPMC(put, MC, MMX)\ -QPEL16_OPMC(avg, MC, MMX) - -#define QPEL16(MMX)\ -QPEL16_OP(mc00, MMX)\ -QPEL16_OP(mc01, MMX)\ -QPEL16_OP(mc02, MMX)\ -QPEL16_OP(mc03, MMX)\ -QPEL16_OP(mc10, MMX)\ -QPEL16_OP(mc11, MMX)\ -QPEL16_OP(mc12, MMX)\ -QPEL16_OP(mc13, MMX)\ -QPEL16_OP(mc20, MMX)\ -QPEL16_OP(mc21, MMX)\ -QPEL16_OP(mc22, MMX)\ -QPEL16_OP(mc23, MMX)\ -QPEL16_OP(mc30, MMX)\ -QPEL16_OP(mc31, MMX)\ -QPEL16_OP(mc32, MMX)\ -QPEL16_OP(mc33, MMX) - -#if ARCH_X86_32 // ARCH_X86_64 implies SSE2+ -QPEL16(mmxext) -#endif - #endif /* HAVE_X86ASM */ -#define SET_QPEL_FUNCS(PFX, IDX, SIZE, CPU, PREFIX) \ +#define SET_QPEL_FUNCS0123(PFX, IDX, SIZE, CPU, PREFIX) \ do { \ c->PFX ## _pixels_tab[IDX][ 0] = PREFIX ## PFX ## SIZE ## _mc00_ ## CPU; \ c->PFX ## _pixels_tab[IDX][ 1] = PREFIX ## PFX ## SIZE ## _mc10_ ## CPU; \ c->PFX ## _pixels_tab[IDX][ 2] = PREFIX ## PFX ## SIZE ## _mc20_ ## CPU; \ c->PFX ## _pixels_tab[IDX][ 3] = PREFIX ## PFX ## SIZE ## _mc30_ ## CPU; \ + } while (0) +#define SET_QPEL_FUNCS(PFX, IDX, SIZE, CPU, PREFIX) \ + do { \ + SET_QPEL_FUNCS0123(PFX, IDX, SIZE, CPU, PREFIX); \ c->PFX ## _pixels_tab[IDX][ 4] = PREFIX ## PFX ## SIZE ## _mc01_ ## CPU; \ c->PFX ## _pixels_tab[IDX][ 5] = PREFIX ## PFX ## SIZE ## _mc11_ ## CPU; \ c->PFX ## _pixels_tab[IDX][ 6] = PREFIX ## PFX ## SIZE ## _mc21_ ## CPU; \ @@ -546,19 +471,13 @@ av_cold void ff_h264qpel_init_x86(H264QpelContext *c, int bit_depth) if (EXTERNAL_MMXEXT(cpu_flags)) { if (!high_bit_depth) { - SET_QPEL_FUNCS(put_h264_qpel, 0, 16, mmxext, ); - SET_QPEL_FUNCS(put_h264_qpel, 1, 8, mmxext, ); + SET_QPEL_FUNCS0123(put_h264_qpel, 0, 16, mmxext, ); + SET_QPEL_FUNCS0123(put_h264_qpel, 1, 8, mmxext, ); SET_QPEL_FUNCS(put_h264_qpel, 2, 4, mmxext, ); - SET_QPEL_FUNCS(avg_h264_qpel, 0, 16, mmxext, ); - SET_QPEL_FUNCS(avg_h264_qpel, 1, 8, mmxext, ); + SET_QPEL_FUNCS0123(avg_h264_qpel, 0, 16, mmxext, ); + SET_QPEL_FUNCS0123(avg_h264_qpel, 1, 8, mmxext, ); SET_QPEL_FUNCS(avg_h264_qpel, 2, 4, mmxext, ); } else if (bit_depth == 10) { -#if ARCH_X86_32 - SET_QPEL_FUNCS(avg_h264_qpel, 0, 16, 10_mmxext, ff_); - SET_QPEL_FUNCS(put_h264_qpel, 0, 16, 10_mmxext, ff_); - SET_QPEL_FUNCS(put_h264_qpel, 1, 8, 10_mmxext, ff_); - SET_QPEL_FUNCS(avg_h264_qpel, 1, 8, 10_mmxext, ff_); -#endif SET_QPEL_FUNCS(put_h264_qpel, 2, 4, 10_mmxext, ff_); SET_QPEL_FUNCS(avg_h264_qpel, 2, 4, 10_mmxext, ff_); } diff --git a/libavcodec/x86/h264_qpel_10bit.asm b/libavcodec/x86/h264_qpel_10bit.asm index 872268300..c862cb222 100644 --- a/libavcodec/x86/h264_qpel_10bit.asm +++ b/libavcodec/x86/h264_qpel_10bit.asm @@ -153,7 +153,7 @@ cglobal %1_h264_qpel%4_%2_10, %5,%6 + 2,%7 ;cpu, put/avg, mc, 4/8, ... %macro cglobal_mc 6 %assign i %3*2 -%if ARCH_X86_32 || cpuflag(sse2) +%if cpuflag(sse2) MCAxA_OP %1, %2, %3, i, %4,%5,%6 %endif diff --git a/libavcodec/x86/h264_qpel_8bit.asm b/libavcodec/x86/h264_qpel_8bit.asm index 2d287ba44..6269b3cf4 100644 --- a/libavcodec/x86/h264_qpel_8bit.asm +++ b/libavcodec/x86/h264_qpel_8bit.asm @@ -461,10 +461,6 @@ cglobal %1_h264_qpel8or16_v_lowpass_op, 5,5,8 ; dst, src, dstStride, srcStride, REP_RET %endmacro -INIT_MMX mmxext -QPEL8OR16_V_LOWPASS_OP put -QPEL8OR16_V_LOWPASS_OP avg - INIT_XMM sse2 QPEL8OR16_V_LOWPASS_OP put QPEL8OR16_V_LOWPASS_OP avg @@ -581,10 +577,6 @@ cglobal %1_h264_qpel8or16_hv1_lowpass_op, 4,4,8 ; src, tmp, srcStride, size REP_RET %endmacro -INIT_MMX mmxext -QPEL8OR16_HV1_LOWPASS_OP put -QPEL8OR16_HV1_LOWPASS_OP avg - INIT_XMM sse2 QPEL8OR16_HV1_LOWPASS_OP put diff --git a/libavcodec/x86/h264_weight.asm b/libavcodec/x86/h264_weight.asm index 0975d74fc..6076e64ae 100644 --- a/libavcodec/x86/h264_weight.asm +++ b/libavcodec/x86/h264_weight.asm @@ -70,19 +70,6 @@ SECTION .text packuswb m0, m1 %endmacro -INIT_MMX mmxext -cglobal h264_weight_16, 6, 6, 0 - WEIGHT_SETUP -.nextrow: - WEIGHT_OP 0, 4 - mova [r0 ], m0 - WEIGHT_OP 8, 12 - mova [r0+8], m0 - add r0, r1 - dec r2d - jnz .nextrow - REP_RET - %macro WEIGHT_FUNC_MM 2 cglobal h264_weight_%1, 6, 6, %2 WEIGHT_SETUP @@ -95,8 +82,6 @@ cglobal h264_weight_%1, 6, 6, %2 REP_RET %endmacro -INIT_MMX mmxext -WEIGHT_FUNC_MM 8, 0 INIT_XMM sse2 WEIGHT_FUNC_MM 16, 8 @@ -198,25 +183,6 @@ WEIGHT_FUNC_HALF_MM 8, 8 packuswb m0, m1 %endmacro -INIT_MMX mmxext -cglobal h264_biweight_16, 7, 8, 0 - BIWEIGHT_SETUP - movifnidn r3d, r3m -.nextrow: - BIWEIGHT_STEPA 0, 1, 0 - BIWEIGHT_STEPA 1, 2, 4 - BIWEIGHT_STEPB - mova [r0], m0 - BIWEIGHT_STEPA 0, 1, 8 - BIWEIGHT_STEPA 1, 2, 12 - BIWEIGHT_STEPB - mova [r0+8], m0 - add r0, r2 - add r1, r2 - dec r3d - jnz .nextrow - REP_RET - %macro BIWEIGHT_FUNC_MM 2 cglobal h264_biweight_%1, 7, 8, %2 BIWEIGHT_SETUP @@ -233,8 +199,6 @@ cglobal h264_biweight_%1, 7, 8, %2 REP_RET %endmacro -INIT_MMX mmxext -BIWEIGHT_FUNC_MM 8, 0 INIT_XMM sse2 BIWEIGHT_FUNC_MM 16, 8 diff --git a/libavcodec/x86/h264chroma_init.c b/libavcodec/x86/h264chroma_init.c index 36bf29df0..7c0f49217 100644 --- a/libavcodec/x86/h264chroma_init.c +++ b/libavcodec/x86/h264chroma_init.c @@ -28,15 +28,11 @@ void ff_put_h264_chroma_mc8_rnd_mmx (uint8_t *dst, uint8_t *src, ptrdiff_t stride, int h, int x, int y); void ff_avg_h264_chroma_mc8_rnd_mmxext(uint8_t *dst, uint8_t *src, ptrdiff_t stride, int h, int x, int y); -void ff_avg_h264_chroma_mc8_rnd_3dnow(uint8_t *dst, uint8_t *src, - ptrdiff_t stride, int h, int x, int y); void ff_put_h264_chroma_mc4_mmx (uint8_t *dst, uint8_t *src, ptrdiff_t stride, int h, int x, int y); void ff_avg_h264_chroma_mc4_mmxext (uint8_t *dst, uint8_t *src, ptrdiff_t stride, int h, int x, int y); -void ff_avg_h264_chroma_mc4_3dnow (uint8_t *dst, uint8_t *src, - ptrdiff_t stride, int h, int x, int y); void ff_put_h264_chroma_mc2_mmxext (uint8_t *dst, uint8_t *src, ptrdiff_t stride, int h, int x, int y); @@ -77,11 +73,6 @@ av_cold void ff_h264chroma_init_x86(H264ChromaContext *c, int bit_depth) c->put_h264_chroma_pixels_tab[1] = ff_put_h264_chroma_mc4_mmx; } - if (EXTERNAL_AMD3DNOW(cpu_flags) && !high_bit_depth) { - c->avg_h264_chroma_pixels_tab[0] = ff_avg_h264_chroma_mc8_rnd_3dnow; - c->avg_h264_chroma_pixels_tab[1] = ff_avg_h264_chroma_mc4_3dnow; - } - if (EXTERNAL_MMXEXT(cpu_flags) && !high_bit_depth) { c->avg_h264_chroma_pixels_tab[0] = ff_avg_h264_chroma_mc8_rnd_mmxext; c->avg_h264_chroma_pixels_tab[1] = ff_avg_h264_chroma_mc4_mmxext; diff --git a/libavcodec/x86/h264dsp_init.c b/libavcodec/x86/h264dsp_init.c index c9a96c7dc..dc8fc4f72 100644 --- a/libavcodec/x86/h264dsp_init.c +++ b/libavcodec/x86/h264dsp_init.c @@ -31,17 +31,14 @@ void ff_h264_idct ## NUM ## _add_ ## DEPTH ## _ ## OPT(uint8_t *dst, \ int16_t *block, \ int stride); -IDCT_ADD_FUNC(, 8, mmx) IDCT_ADD_FUNC(, 8, sse2) IDCT_ADD_FUNC(, 8, avx) IDCT_ADD_FUNC(, 10, sse2) -IDCT_ADD_FUNC(_dc, 8, mmxext) IDCT_ADD_FUNC(_dc, 8, sse2) IDCT_ADD_FUNC(_dc, 8, avx) IDCT_ADD_FUNC(_dc, 10, mmxext) IDCT_ADD_FUNC(8_dc, 8, mmxext) IDCT_ADD_FUNC(8_dc, 10, sse2) -IDCT_ADD_FUNC(8, 8, mmx) IDCT_ADD_FUNC(8, 8, sse2) IDCT_ADD_FUNC(8, 10, sse2) IDCT_ADD_FUNC(, 10, avx) @@ -54,17 +51,11 @@ void ff_h264_idct ## NUM ## _add ## REP ## _ ## DEPTH ## _ ## OPT \ (uint8_t *dst, const int *block_offset, \ int16_t *block, int stride, const uint8_t nnzc[5 * 8]); -IDCT_ADD_REP_FUNC(8, 4, 8, mmx) -IDCT_ADD_REP_FUNC(8, 4, 8, mmxext) IDCT_ADD_REP_FUNC(8, 4, 8, sse2) IDCT_ADD_REP_FUNC(8, 4, 10, sse2) IDCT_ADD_REP_FUNC(8, 4, 10, avx) -IDCT_ADD_REP_FUNC(, 16, 8, mmx) -IDCT_ADD_REP_FUNC(, 16, 8, mmxext) IDCT_ADD_REP_FUNC(, 16, 8, sse2) IDCT_ADD_REP_FUNC(, 16, 10, sse2) -IDCT_ADD_REP_FUNC(, 16intra, 8, mmx) -IDCT_ADD_REP_FUNC(, 16intra, 8, mmxext) IDCT_ADD_REP_FUNC(, 16intra, 8, sse2) IDCT_ADD_REP_FUNC(, 16intra, 10, sse2) IDCT_ADD_REP_FUNC(, 16, 10, avx) @@ -76,8 +67,6 @@ void ff_h264_idct ## NUM ## _add ## REP ## _ ## DEPTH ## _ ## OPT \ (uint8_t **dst, const int *block_offset, \ int16_t *block, int stride, const uint8_t nnzc[15 * 8]); -IDCT_ADD_REP_FUNC2(, 8, 8, mmx) -IDCT_ADD_REP_FUNC2(, 8, 8, mmxext) IDCT_ADD_REP_FUNC2(, 8, 8, sse2) IDCT_ADD_REP_FUNC2(, 8, 10, sse2) IDCT_ADD_REP_FUNC2(, 8, 10, avx) @@ -87,7 +76,6 @@ IDCT_ADD_REP_FUNC2(, 8_422, 8, mmx) IDCT_ADD_REP_FUNC2(, 8_422, 10, sse2) IDCT_ADD_REP_FUNC2(, 8_422, 10, avx) -void ff_h264_luma_dc_dequant_idct_mmx(int16_t *output, int16_t *input, int qmul); void ff_h264_luma_dc_dequant_idct_sse2(int16_t *output, int16_t *input, int qmul); /***********************************/ @@ -112,14 +100,6 @@ void ff_deblock_ ## DIR ## _ ## TYPE ## _ ## DEPTH ## _ ## OPT(uint8_t *pix, \ int beta); #define LF_FUNCS(type, depth) \ -LF_FUNC(h, chroma, depth, mmxext) \ -LF_IFUNC(h, chroma_intra, depth, mmxext) \ -LF_FUNC(h, chroma422, depth, mmxext) \ -LF_IFUNC(h, chroma422_intra, depth, mmxext) \ -LF_FUNC(v, chroma, depth, mmxext) \ -LF_IFUNC(v, chroma_intra, depth, mmxext) \ -LF_FUNC(h, luma, depth, mmxext) \ -LF_IFUNC(h, luma_intra, depth, mmxext) \ LF_FUNC(h, luma, depth, sse2) \ LF_IFUNC(h, luma_intra, depth, sse2) \ LF_FUNC(v, luma, depth, sse2) \ @@ -147,27 +127,10 @@ LF_FUNC(h, luma_mbaff, 8, avx) LF_FUNCS(uint8_t, 8) LF_FUNCS(uint16_t, 10) -#if ARCH_X86_32 && HAVE_MMXEXT_EXTERNAL -LF_FUNC(v8, luma, 8, mmxext) -static void deblock_v_luma_8_mmxext(uint8_t *pix, int stride, int alpha, - int beta, int8_t *tc0) -{ - if ((tc0[0] & tc0[1]) >= 0) - ff_deblock_v8_luma_8_mmxext(pix + 0, stride, alpha, beta, tc0); - if ((tc0[2] & tc0[3]) >= 0) - ff_deblock_v8_luma_8_mmxext(pix + 8, stride, alpha, beta, tc0 + 2); -} -LF_IFUNC(v8, luma_intra, 8, mmxext) -static void deblock_v_luma_intra_8_mmxext(uint8_t *pix, int stride, - int alpha, int beta) -{ - ff_deblock_v8_luma_intra_8_mmxext(pix + 0, stride, alpha, beta); - ff_deblock_v8_luma_intra_8_mmxext(pix + 8, stride, alpha, beta); -} -#endif /* ARCH_X86_32 && HAVE_MMXEXT_EXTERNAL */ - LF_FUNC(v, luma, 10, mmxext) +LF_FUNC(h, luma, 10, mmxext) LF_IFUNC(v, luma_intra, 10, mmxext) +LF_IFUNC(h, luma_intra, 10, mmxext) /***********************************/ /* weighted prediction */ @@ -187,14 +150,13 @@ void ff_h264_biweight_ ## W ## _ ## OPT(uint8_t *dst, uint8_t *src, \ H264_WEIGHT(W, mmxext) \ H264_BIWEIGHT(W, mmxext) -#define H264_BIWEIGHT_MMX_SSE(W) \ - H264_BIWEIGHT_MMX(W) \ +#define H264_BIWEIGHT_SSE(W) \ H264_WEIGHT(W, sse2) \ H264_BIWEIGHT(W, sse2) \ H264_BIWEIGHT(W, ssse3) -H264_BIWEIGHT_MMX_SSE(16) -H264_BIWEIGHT_MMX_SSE(8) +H264_BIWEIGHT_SSE(16) +H264_BIWEIGHT_SSE(8) H264_BIWEIGHT_MMX(4) #define H264_WEIGHT_10(W, DEPTH, OPT) \ @@ -236,52 +198,16 @@ av_cold void ff_h264dsp_init_x86(H264DSPContext *c, const int bit_depth, if (bit_depth == 8) { if (EXTERNAL_MMX(cpu_flags)) { - c->h264_idct_dc_add = - c->h264_idct_add = ff_h264_idct_add_8_mmx; - c->h264_idct8_dc_add = - c->h264_idct8_add = ff_h264_idct8_add_8_mmx; - - c->h264_idct_add16 = ff_h264_idct_add16_8_mmx; - c->h264_idct8_add4 = ff_h264_idct8_add4_8_mmx; if (chroma_format_idc <= 1) { - c->h264_idct_add8 = ff_h264_idct_add8_8_mmx; } else { c->h264_idct_add8 = ff_h264_idct_add8_422_8_mmx; } - c->h264_idct_add16intra = ff_h264_idct_add16intra_8_mmx; - if (cpu_flags & AV_CPU_FLAG_CMOV) - c->h264_luma_dc_dequant_idct = ff_h264_luma_dc_dequant_idct_mmx; } if (EXTERNAL_MMXEXT(cpu_flags)) { - c->h264_idct_dc_add = ff_h264_idct_dc_add_8_mmxext; c->h264_idct8_dc_add = ff_h264_idct8_dc_add_8_mmxext; - c->h264_idct_add16 = ff_h264_idct_add16_8_mmxext; - c->h264_idct8_add4 = ff_h264_idct8_add4_8_mmxext; - if (chroma_format_idc <= 1) - c->h264_idct_add8 = ff_h264_idct_add8_8_mmxext; - c->h264_idct_add16intra = ff_h264_idct_add16intra_8_mmxext; - c->h264_v_loop_filter_chroma = ff_deblock_v_chroma_8_mmxext; - c->h264_v_loop_filter_chroma_intra = ff_deblock_v_chroma_intra_8_mmxext; - if (chroma_format_idc <= 1) { - c->h264_h_loop_filter_chroma = ff_deblock_h_chroma_8_mmxext; - c->h264_h_loop_filter_chroma_intra = ff_deblock_h_chroma_intra_8_mmxext; - } else { - c->h264_h_loop_filter_chroma = ff_deblock_h_chroma422_8_mmxext; - c->h264_h_loop_filter_chroma_intra = ff_deblock_h_chroma422_intra_8_mmxext; - } -#if ARCH_X86_32 && HAVE_MMXEXT_EXTERNAL - c->h264_v_loop_filter_luma = deblock_v_luma_8_mmxext; - c->h264_h_loop_filter_luma = ff_deblock_h_luma_8_mmxext; - c->h264_v_loop_filter_luma_intra = deblock_v_luma_intra_8_mmxext; - c->h264_h_loop_filter_luma_intra = ff_deblock_h_luma_intra_8_mmxext; -#endif /* ARCH_X86_32 && HAVE_MMXEXT_EXTERNAL */ - c->weight_h264_pixels_tab[0] = ff_h264_weight_16_mmxext; - c->weight_h264_pixels_tab[1] = ff_h264_weight_8_mmxext; c->weight_h264_pixels_tab[2] = ff_h264_weight_4_mmxext; - c->biweight_h264_pixels_tab[0] = ff_h264_biweight_16_mmxext; - c->biweight_h264_pixels_tab[1] = ff_h264_biweight_8_mmxext; c->biweight_h264_pixels_tab[2] = ff_h264_biweight_4_mmxext; } if (EXTERNAL_SSE2(cpu_flags)) { @@ -350,19 +276,12 @@ av_cold void ff_h264dsp_init_x86(H264DSPContext *c, const int bit_depth, } } else if (bit_depth == 10) { if (EXTERNAL_MMXEXT(cpu_flags)) { -#if ARCH_X86_32 - c->h264_v_loop_filter_chroma = ff_deblock_v_chroma_10_mmxext; - c->h264_v_loop_filter_chroma_intra = ff_deblock_v_chroma_intra_10_mmxext; - if (chroma_format_idc <= 1) { - c->h264_h_loop_filter_chroma = ff_deblock_h_chroma_10_mmxext; - } else { - c->h264_h_loop_filter_chroma = ff_deblock_h_chroma422_10_mmxext; - } +#if ARCH_X86_32 && !HAVE_ALIGNED_STACK c->h264_v_loop_filter_luma = ff_deblock_v_luma_10_mmxext; c->h264_h_loop_filter_luma = ff_deblock_h_luma_10_mmxext; c->h264_v_loop_filter_luma_intra = ff_deblock_v_luma_intra_10_mmxext; c->h264_h_loop_filter_luma_intra = ff_deblock_h_luma_intra_10_mmxext; -#endif /* ARCH_X86_32 */ +#endif /* ARCH_X86_32 && !HAVE_ALIGNED_STACK */ c->h264_idct_dc_add = ff_h264_idct_dc_add_10_mmxext; } if (EXTERNAL_SSE2(cpu_flags)) { diff --git a/libavcodec/x86/hevc_idct.asm b/libavcodec/x86/hevc_idct.asm index 1eb1973f2..ce41f3382 100644 --- a/libavcodec/x86/hevc_idct.asm +++ b/libavcodec/x86/hevc_idct.asm @@ -811,7 +811,6 @@ cglobal hevc_idct_32x32_%1, 1, 6, 16, 256, coeffs %macro INIT_IDCT_DC 1 INIT_MMX mmxext IDCT_DC_NL 4, %1 -IDCT_DC 8, 2, %1 INIT_XMM sse2 IDCT_DC_NL 8, %1 diff --git a/libavcodec/x86/hevc_mc.asm b/libavcodec/x86/hevc_mc.asm index ff6ed0711..e159adccc 100644 --- a/libavcodec/x86/hevc_mc.asm +++ b/libavcodec/x86/hevc_mc.asm @@ -87,6 +87,46 @@ QPEL_TABLE 12, 4, w, sse4 QPEL_TABLE 8,16, b, avx2 QPEL_TABLE 10, 8, w, avx2 +QPEL_TABLE 4, 1, b, avx512icl_h +QPEL_TABLE 8, 1, b, avx512icl_h +QPEL_TABLE 8, 1, d, avx512icl_v +QPEL_TABLE 16, 1, b, avx512icl_h +QPEL_TABLE 32, 1, b, avx512icl_h +QPEL_TABLE 64, 1, b, avx512icl_h + +pb_qpel_shuffle_index: db 0, 1, 2, 3 + db 1, 2, 3, 4 + db 2, 3, 4, 5 + db 3, 4, 5, 6 + db 4, 5, 6, 7 + db 5, 6, 7, 8 + db 6, 7, 8, 9 + db 7, 8, 9, 10 + db 8, 9, 10, 11 + db 9, 10, 11, 12 + db 10, 11, 12, 13 + db 11, 12, 13, 14 + db 12, 13, 14, 15 + db 13, 14, 15, 16 + db 14, 15, 16, 17 + db 15, 16, 17, 18 + db 4, 5, 6, 7 + db 5, 6, 7, 8 + db 6, 7, 8, 9 + db 7, 8, 9, 10 + db 8, 9, 10, 11 + db 9, 10, 11, 12 + db 10, 11, 12, 13 + db 11, 12, 13, 14 + db 12, 13, 14, 15 + db 13, 14, 15, 16 + db 14, 15, 16, 17 + db 15, 16, 17, 18 + db 16, 17, 18, 19 + db 17, 18, 19, 20 + db 18, 19, 20, 21 + db 19, 20, 21, 22 + SECTION .text %define MAX_PB_SIZE 64 @@ -1670,3 +1710,152 @@ HEVC_PUT_HEVC_QPEL_HV 16, 10 %endif ;AVX2 %endif ; ARCH_X86_64 + +%macro QPEL_FILTER_H 5 +%define %%table hevc_qpel_filters_avx512icl_h_%1 +%assign %%offset 4 + dec %2q + shl %2q, 3 +%ifdef PIC + lea %5q, [%%table] + %define FILTER %5q +%else + %define FILTER %%table +%endif + vpbroadcastd m%3, [FILTER + %2q + 0*%%offset] + vpbroadcastd m%4, [FILTER + %2q + 1*%%offset] +%endmacro + +%macro QPEL_FILTER_V 5 + vpbroadcastd m%3, [%5 + %2q + 4*%4] +%endmacro + +%macro QPEL_LOAD_SHUF 2 + movu m%1, [pb_qpel_shuffle_index + 0] + movu m%2, [pb_qpel_shuffle_index + 64] +%endmacro + +; required: m0-m5 +; %1: dst register index +; %2: name for src +; %3: optional offset +%macro QPEL_H_LOAD_COMPUTE 2-3 +%assign %%offset 0 +%if %0 == 3 +%assign %%offset %3 +%endif + pxor m%1, m%1 +%if mmsize == 64 + movu ym4, [%2q + %%offset - 3] +%else + movu xm4, [%2q + %%offset - 3] +%endif + vpermb m5, m2, m4 + vpermb m4, m3, m4 + vpdpbusd m%1, m5, m0 + vpdpbusd m%1, m4, m1 +%endmacro + +%macro HEVC_PUT_HEVC_QPEL_AVX512ICL 2 +cglobal hevc_put_hevc_qpel_h%1_%2, 5, 6, 8, dst, src, srcstride, height, mx, tmp + QPEL_FILTER_H %1, mx, 0, 1, tmp + QPEL_LOAD_SHUF 2, 3 +.loop: + QPEL_H_LOAD_COMPUTE 6, src +%if %1 == 4 + vpmovdw xm6, m6 + movq [dstq], xm6 +%else + vpmovdw [dstq], m6 +%endif +%if %1 > 16 + QPEL_H_LOAD_COMPUTE 7, src, 16 + vpmovdw [dstq + 32], m7 +%endif +%if %1 > 32 + QPEL_H_LOAD_COMPUTE 6, src, 32 + QPEL_H_LOAD_COMPUTE 7, src, 48 + vpmovdw [dstq + 64], m6 + vpmovdw [dstq + 96], m7 +%endif + LOOP_END dst, src, srcstride + RET +%endmacro + +%macro HEVC_PUT_HEVC_QPEL_HV_AVX512ICL 2 +cglobal hevc_put_hevc_qpel_hv%1_%2, 6, 7, 27, dst, src, srcstride, height, mx, my, tmp +%assign %%shift 6 +%assign %%extra 7 + QPEL_FILTER_H %1, mx, 0, 1, tmp + QPEL_LOAD_SHUF 2, 3 + lea tmpq, [srcstrideq*3] + sub srcq, tmpq + sub myq, 1 + shl myq, 5 +%define %%table hevc_qpel_filters_avx512icl_v_%1 +%ifdef PIC + lea tmpq, [%%table] + %define FILTER tmpq +%else + %define FILTER %%table +%endif +%assign %%i 6 +%assign %%j 0 +%rep %1 + QPEL_FILTER_V %1, my, %%i, %%j, FILTER + %assign %%i %%i+1 + %assign %%j %%j+1 +%endrep +%rep %%extra + QPEL_H_LOAD_COMPUTE %%i, src + add srcq, srcstrideq +%assign %%i %%i+1 +%endrep +.loop: + QPEL_H_LOAD_COMPUTE %%i, src + vpmulld m22, m14, m6 + vpmulld m23, m15, m7 + vpmulld m24, m16, m8 + vpmulld m25, m17, m9 + vpaddd m26, m22, m23 + vpaddd m24, m25 + vpaddd m26, m24 + vpmulld m22, m18, m10 + vpmulld m23, m19, m11 + vpmulld m24, m20, m12 + vpmulld m25, m21, m13 + vpaddd m22, m22, m23 + vpaddd m24, m25 + vpaddd m26, m24 + vpaddd m22, m26 + mova m14, m15 + mova m15, m16 + mova m16, m17 + mova m17, m18 + mova m18, m19 + mova m19, m20 + mova m20, m21 + vpsrad m22, %%shift + vpmovdw [dstq], m22 + LOOP_END dst, src, srcstride + + RET +%endmacro + +%if ARCH_X86_64 +%if HAVE_AVX512ICL_EXTERNAL + +INIT_XMM avx512icl +HEVC_PUT_HEVC_QPEL_AVX512ICL 4, 8 + +INIT_YMM avx512icl +HEVC_PUT_HEVC_QPEL_AVX512ICL 8, 8 +HEVC_PUT_HEVC_QPEL_HV_AVX512ICL 8, 8 + +INIT_ZMM avx512icl +HEVC_PUT_HEVC_QPEL_AVX512ICL 16, 8 +HEVC_PUT_HEVC_QPEL_AVX512ICL 32, 8 +HEVC_PUT_HEVC_QPEL_AVX512ICL 64, 8 + +%endif +%endif diff --git a/libavcodec/x86/hevcdsp.h b/libavcodec/x86/hevcdsp.h index 67be0a905..24e35bc03 100644 --- a/libavcodec/x86/hevcdsp.h +++ b/libavcodec/x86/hevcdsp.h @@ -233,6 +233,13 @@ WEIGHTING_PROTOTYPES(8, sse4); WEIGHTING_PROTOTYPES(10, sse4); WEIGHTING_PROTOTYPES(12, sse4); +void ff_hevc_put_hevc_qpel_h4_8_avx512icl(int16_t *dst, uint8_t *_src, ptrdiff_t _srcstride, int height, intptr_t mx, intptr_t my, int width); +void ff_hevc_put_hevc_qpel_h8_8_avx512icl(int16_t *dst, uint8_t *_src, ptrdiff_t _srcstride, int height, intptr_t mx, intptr_t my, int width); +void ff_hevc_put_hevc_qpel_h16_8_avx512icl(int16_t *dst, uint8_t *_src, ptrdiff_t _srcstride, int height, intptr_t mx, intptr_t my, int width); +void ff_hevc_put_hevc_qpel_h32_8_avx512icl(int16_t *dst, uint8_t *_src, ptrdiff_t _srcstride, int height, intptr_t mx, intptr_t my, int width); +void ff_hevc_put_hevc_qpel_h64_8_avx512icl(int16_t *dst, uint8_t *_src, ptrdiff_t _srcstride, int height, intptr_t mx, intptr_t my, int width); +void ff_hevc_put_hevc_qpel_hv8_8_avx512icl(int16_t *dst, uint8_t *_src, ptrdiff_t _srcstride, int height, intptr_t mx, intptr_t my, int width); + /////////////////////////////////////////////////////////////////////////////// // TRANSFORM_ADD /////////////////////////////////////////////////////////////////////////////// diff --git a/libavcodec/x86/hevcdsp_init.c b/libavcodec/x86/hevcdsp_init.c index 8a3fa2744..f7a5b28be 100644 --- a/libavcodec/x86/hevcdsp_init.c +++ b/libavcodec/x86/hevcdsp_init.c @@ -25,7 +25,6 @@ #include "libavutil/mem_internal.h" #include "libavutil/x86/asm.h" #include "libavutil/x86/cpu.h" -#include "libavcodec/get_bits.h" /* required for hevcdsp.h GetBitContext */ #include "libavcodec/hevcdsp.h" #include "libavcodec/x86/hevcdsp.h" @@ -65,7 +64,6 @@ void ff_hevc_idct_ ## W ## _dc_10_ ## opt(int16_t *coeffs); \ void ff_hevc_idct_ ## W ## _dc_12_ ## opt(int16_t *coeffs) IDCT_DC_FUNCS(4x4, mmxext); -IDCT_DC_FUNCS(8x8, mmxext); IDCT_DC_FUNCS(8x8, sse2); IDCT_DC_FUNCS(16x16, sse2); IDCT_DC_FUNCS(32x32, sse2); @@ -713,7 +711,6 @@ void ff_hevc_dsp_init_x86(HEVCDSPContext *c, const int bit_depth) if (bit_depth == 8) { if (EXTERNAL_MMXEXT(cpu_flags)) { c->idct_dc[0] = ff_hevc_idct_4x4_dc_8_mmxext; - c->idct_dc[1] = ff_hevc_idct_8x8_dc_8_mmxext; c->add_residual[0] = ff_hevc_add_residual_4_8_mmxext; } @@ -878,11 +875,18 @@ void ff_hevc_dsp_init_x86(HEVCDSPContext *c, const int bit_depth) c->add_residual[3] = ff_hevc_add_residual_32_8_avx2; } + if (EXTERNAL_AVX512ICL(cpu_flags) && ARCH_X86_64) { + c->put_hevc_qpel[1][0][1] = ff_hevc_put_hevc_qpel_h4_8_avx512icl; + c->put_hevc_qpel[3][0][1] = ff_hevc_put_hevc_qpel_h8_8_avx512icl; + c->put_hevc_qpel[5][0][1] = ff_hevc_put_hevc_qpel_h16_8_avx512icl; + c->put_hevc_qpel[7][0][1] = ff_hevc_put_hevc_qpel_h32_8_avx512icl; + c->put_hevc_qpel[9][0][1] = ff_hevc_put_hevc_qpel_h64_8_avx512icl; + c->put_hevc_qpel[3][1][1] = ff_hevc_put_hevc_qpel_hv8_8_avx512icl; + } } else if (bit_depth == 10) { if (EXTERNAL_MMXEXT(cpu_flags)) { c->add_residual[0] = ff_hevc_add_residual_4_10_mmxext; c->idct_dc[0] = ff_hevc_idct_4x4_dc_10_mmxext; - c->idct_dc[1] = ff_hevc_idct_8x8_dc_10_mmxext; } if (EXTERNAL_SSE2(cpu_flags)) { c->hevc_v_loop_filter_chroma = ff_hevc_v_loop_filter_chroma_10_sse2; @@ -1098,7 +1102,6 @@ void ff_hevc_dsp_init_x86(HEVCDSPContext *c, const int bit_depth) } else if (bit_depth == 12) { if (EXTERNAL_MMXEXT(cpu_flags)) { c->idct_dc[0] = ff_hevc_idct_4x4_dc_12_mmxext; - c->idct_dc[1] = ff_hevc_idct_8x8_dc_12_mmxext; } if (EXTERNAL_SSE2(cpu_flags)) { c->hevc_v_loop_filter_chroma = ff_hevc_v_loop_filter_chroma_12_sse2; diff --git a/libavcodec/x86/hpeldsp.asm b/libavcodec/x86/hpeldsp.asm index ce5d7a4e2..b3a270a17 100644 --- a/libavcodec/x86/hpeldsp.asm +++ b/libavcodec/x86/hpeldsp.asm @@ -83,8 +83,6 @@ cglobal put_pixels8_x2, 4,5 INIT_MMX mmxext PUT_PIXELS8_X2 -INIT_MMX 3dnow -PUT_PIXELS8_X2 ; void ff_put_pixels16_x2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) @@ -127,15 +125,13 @@ cglobal put_pixels16_x2, 4,5 INIT_MMX mmxext PUT_PIXELS_16 -INIT_MMX 3dnow -PUT_PIXELS_16 ; The 8_X2 macro can easily be used here INIT_XMM sse2 PUT_PIXELS8_X2 ; void ff_put_no_rnd_pixels8_x2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) -%macro PUT_NO_RND_PIXELS8_X2 0 +INIT_MMX mmxext cglobal put_no_rnd_pixels8_x2, 4,5 mova m6, [pb_1] lea r4, [r2*2] @@ -167,12 +163,6 @@ cglobal put_no_rnd_pixels8_x2, 4,5 sub r3d, 4 jne .loop REP_RET -%endmacro - -INIT_MMX mmxext -PUT_NO_RND_PIXELS8_X2 -INIT_MMX 3dnow -PUT_NO_RND_PIXELS8_X2 ; void ff_put_pixels8_y2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) @@ -209,15 +199,13 @@ cglobal put_pixels8_y2, 4,5 INIT_MMX mmxext PUT_PIXELS8_Y2 -INIT_MMX 3dnow -PUT_PIXELS8_Y2 ; actually, put_pixels16_y2_sse2 INIT_XMM sse2 PUT_PIXELS8_Y2 ; void ff_put_no_rnd_pixels8_y2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) -%macro PUT_NO_RND_PIXELS8_Y2 0 +INIT_MMX mmxext cglobal put_no_rnd_pixels8_y2, 4,5 mova m6, [pb_1] lea r4, [r2+r2] @@ -245,42 +233,6 @@ cglobal put_no_rnd_pixels8_y2, 4,5 sub r3d, 4 jne .loop REP_RET -%endmacro - -INIT_MMX mmxext -PUT_NO_RND_PIXELS8_Y2 -INIT_MMX 3dnow -PUT_NO_RND_PIXELS8_Y2 - - -; void ff_avg_pixels8(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) -%macro AVG_PIXELS8 0 -cglobal avg_pixels8, 4,5 - lea r4, [r2*2] -.loop: - mova m0, [r0] - mova m1, [r0+r2] - PAVGB m0, [r1] - PAVGB m1, [r1+r2] - mova [r0], m0 - mova [r0+r2], m1 - add r1, r4 - add r0, r4 - mova m0, [r0] - mova m1, [r0+r2] - PAVGB m0, [r1] - PAVGB m1, [r1+r2] - add r1, r4 - mova [r0], m0 - mova [r0+r2], m1 - add r0, r4 - sub r3d, 4 - jne .loop - REP_RET -%endmacro - -INIT_MMX 3dnow -AVG_PIXELS8 ; void ff_avg_pixels8_x2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) @@ -291,10 +243,6 @@ cglobal avg_pixels16_x2, 4,5,4 cglobal avg_pixels8_x2, 4,5 %endif lea r4, [r2*2] -%if notcpuflag(mmxext) - pcmpeqd m5, m5 - paddb m5, m5 -%endif .loop: movu m0, [r1] movu m2, [r1+r2] @@ -335,12 +283,8 @@ cglobal avg_pixels8_x2, 4,5 REP_RET %endmacro -INIT_MMX mmx -AVG_PIXELS8_X2 INIT_MMX mmxext AVG_PIXELS8_X2 -INIT_MMX 3dnow -AVG_PIXELS8_X2 ; actually avg_pixels16_x2 INIT_XMM sse2 AVG_PIXELS8_X2 @@ -384,8 +328,6 @@ cglobal avg_pixels8_y2, 4,5 INIT_MMX mmxext AVG_PIXELS8_Y2 -INIT_MMX 3dnow -AVG_PIXELS8_Y2 ; actually avg_pixels16_y2 INIT_XMM sse2 AVG_PIXELS8_Y2 @@ -394,7 +336,7 @@ AVG_PIXELS8_Y2 ; void ff_avg_pixels8_xy2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) ; Note this is not correctly rounded, and is therefore used for ; not-bitexact output -%macro AVG_APPROX_PIXELS8_XY2 0 +INIT_MMX mmxext cglobal avg_approx_pixels8_xy2, 4,5 mova m6, [pb_1] lea r4, [r2*2] @@ -429,12 +371,6 @@ cglobal avg_approx_pixels8_xy2, 4,5 sub r3d, 4 jne .loop REP_RET -%endmacro - -INIT_MMX mmxext -AVG_APPROX_PIXELS8_XY2 -INIT_MMX 3dnow -AVG_APPROX_PIXELS8_XY2 ; void ff_avg_pixels16_xy2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) @@ -517,8 +453,6 @@ cglobal %1_pixels8_xy2, 4,5 INIT_MMX mmxext SET_PIXELS_XY2 avg -INIT_MMX 3dnow -SET_PIXELS_XY2 avg INIT_XMM sse2 SET_PIXELS_XY2 put SET_PIXELS_XY2 avg diff --git a/libavcodec/x86/hpeldsp.h b/libavcodec/x86/hpeldsp.h index bf97029b5..fd740da72 100644 --- a/libavcodec/x86/hpeldsp.h +++ b/libavcodec/x86/hpeldsp.h @@ -45,8 +45,6 @@ void ff_put_pixels8_xy2_mmx(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); void ff_put_pixels8_xy2_ssse3(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); -void ff_put_pixels16_xy2_mmx(uint8_t *block, const uint8_t *pixels, - ptrdiff_t line_size, int h); void ff_put_pixels16_xy2_sse2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); void ff_put_pixels16_xy2_ssse3(uint8_t *block, const uint8_t *pixels, diff --git a/libavcodec/x86/hpeldsp_init.c b/libavcodec/x86/hpeldsp_init.c index d89928cec..09c48c341 100644 --- a/libavcodec/x86/hpeldsp_init.c +++ b/libavcodec/x86/hpeldsp_init.c @@ -22,6 +22,8 @@ * MMX optimization by Nick Kurshev */ +#include "config_components.h" + #include "libavutil/attributes.h" #include "libavutil/cpu.h" #include "libavutil/x86/cpu.h" @@ -33,12 +35,8 @@ void ff_put_pixels8_x2_mmxext(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); -void ff_put_pixels8_x2_3dnow(uint8_t *block, const uint8_t *pixels, - ptrdiff_t line_size, int h); void ff_put_pixels16_x2_mmxext(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); -void ff_put_pixels16_x2_3dnow(uint8_t *block, const uint8_t *pixels, - ptrdiff_t line_size, int h); void ff_put_pixels16_x2_sse2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); void ff_avg_pixels16_x2_sse2(uint8_t *block, const uint8_t *pixels, @@ -49,42 +47,21 @@ void ff_avg_pixels16_y2_sse2(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); void ff_put_no_rnd_pixels8_x2_mmxext(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); -void ff_put_no_rnd_pixels8_x2_3dnow(uint8_t *block, const uint8_t *pixels, - ptrdiff_t line_size, int h); void ff_put_pixels8_y2_mmxext(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); -void ff_put_pixels8_y2_3dnow(uint8_t *block, const uint8_t *pixels, - ptrdiff_t line_size, int h); void ff_put_no_rnd_pixels8_y2_mmxext(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); -void ff_put_no_rnd_pixels8_y2_3dnow(uint8_t *block, const uint8_t *pixels, - ptrdiff_t line_size, int h); -void ff_avg_pixels8_3dnow(uint8_t *block, const uint8_t *pixels, - ptrdiff_t line_size, int h); void ff_avg_pixels8_x2_mmxext(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); -void ff_avg_pixels8_x2_3dnow(uint8_t *block, const uint8_t *pixels, - ptrdiff_t line_size, int h); void ff_avg_pixels8_y2_mmxext(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); -void ff_avg_pixels8_y2_3dnow(uint8_t *block, const uint8_t *pixels, - ptrdiff_t line_size, int h); -void ff_avg_pixels8_xy2_3dnow(uint8_t *block, const uint8_t *pixels, - ptrdiff_t line_size, int h); void ff_avg_approx_pixels8_xy2_mmxext(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); -void ff_avg_approx_pixels8_xy2_3dnow(uint8_t *block, const uint8_t *pixels, - ptrdiff_t line_size, int h); -#define avg_pixels8_mmx ff_avg_pixels8_mmx -#define avg_pixels8_x2_mmx ff_avg_pixels8_x2_mmx #define avg_pixels16_mmx ff_avg_pixels16_mmx -#define avg_pixels8_xy2_mmx ff_avg_pixels8_xy2_mmx -#define avg_pixels16_xy2_mmx ff_avg_pixels16_xy2_mmx #define put_pixels8_mmx ff_put_pixels8_mmx #define put_pixels16_mmx ff_put_pixels16_mmx #define put_pixels8_xy2_mmx ff_put_pixels8_xy2_mmx -#define put_pixels16_xy2_mmx ff_put_pixels16_xy2_mmx #define avg_no_rnd_pixels16_mmx ff_avg_pixels16_mmx #define put_no_rnd_pixels8_mmx ff_put_pixels8_mmx #define put_no_rnd_pixels16_mmx ff_put_pixels16_mmx @@ -119,30 +96,19 @@ CALL_2X_PIXELS(put_no_rnd_pixels16_xy2_mmx, put_no_rnd_pixels8_xy2_mmx, 8) /***********************************/ /* MMX rounding */ -#define DEF(x, y) x ## _ ## y ## _mmx #define SET_RND MOVQ_WTWO -#define PAVGBP(a, b, c, d, e, f) PAVGBP_MMX(a, b, c, d, e, f) -#define PAVGB(a, b, c, e) PAVGB_MMX(a, b, c, e) - -#include "hpeldsp_rnd_template.c" - -#undef DEF #define DEF(x, y) ff_ ## x ## _ ## y ## _mmx #define STATIC +#define NO_AVG #include "rnd_template.c" +#undef NO_AVG #undef DEF #undef SET_RND -#undef PAVGBP -#undef PAVGB #if HAVE_MMX -CALL_2X_PIXELS(avg_pixels16_y2_mmx, avg_pixels8_y2_mmx, 8) -CALL_2X_PIXELS(put_pixels16_y2_mmx, put_pixels8_y2_mmx, 8) - -CALL_2X_PIXELS_EXPORT(ff_avg_pixels16_xy2_mmx, ff_avg_pixels8_xy2_mmx, 8) -CALL_2X_PIXELS_EXPORT(ff_put_pixels16_xy2_mmx, ff_put_pixels8_xy2_mmx, 8) +CALL_2X_PIXELS(put_pixels16_xy2_mmx, ff_put_pixels8_xy2_mmx, 8) #endif #endif /* HAVE_INLINE_ASM */ @@ -160,46 +126,42 @@ CALL_2X_PIXELS_EXPORT(ff_put_pixels16_xy2_mmx, ff_put_pixels8_xy2_mmx, 8) CALL_2X_PIXELS(avg_pixels16_xy2 ## CPUEXT, ff_avg_pixels8_xy2 ## CPUEXT, 8) \ CALL_2X_PIXELS(avg_approx_pixels16_xy2## CPUEXT, ff_avg_approx_pixels8_xy2## CPUEXT, 8) -HPELDSP_AVG_PIXELS16(_3dnow) HPELDSP_AVG_PIXELS16(_mmxext) #endif /* HAVE_X86ASM */ #define SET_HPEL_FUNCS_EXT(PFX, IDX, SIZE, CPU) \ if (HAVE_MMX_EXTERNAL) \ - c->PFX ## _pixels_tab IDX [0] = PFX ## _pixels ## SIZE ## _ ## CPU; + c->PFX ## _pixels_tab IDX [0] = PFX ## _pixels ## SIZE ## _ ## CPU #if HAVE_MMX_INLINE -#define SET_HPEL_FUNCS(PFX, IDX, SIZE, CPU) \ +#define SET_HPEL_FUNCS03(PFX, IDX, SIZE, CPU) \ do { \ - SET_HPEL_FUNCS_EXT(PFX, IDX, SIZE, CPU) \ - c->PFX ## _pixels_tab IDX [1] = PFX ## _pixels ## SIZE ## _x2_ ## CPU; \ - c->PFX ## _pixels_tab IDX [2] = PFX ## _pixels ## SIZE ## _y2_ ## CPU; \ + SET_HPEL_FUNCS_EXT(PFX, IDX, SIZE, CPU); \ c->PFX ## _pixels_tab IDX [3] = PFX ## _pixels ## SIZE ## _xy2_ ## CPU; \ } while (0) +#define SET_HPEL_FUNCS12(PFX, IDX, SIZE, CPU) \ + do { \ + c->PFX ## _pixels_tab IDX [1] = PFX ## _pixels ## SIZE ## _x2_ ## CPU; \ + c->PFX ## _pixels_tab IDX [2] = PFX ## _pixels ## SIZE ## _y2_ ## CPU; \ + } while (0) #else +#define SET_HPEL_FUNCS03(PFX, IDX, SIZE, CPU) SET_HPEL_FUNCS_EXT(PFX, IDX, SIZE, CPU) +#define SET_HPEL_FUNCS12(PFX, IDX, SIZE, CPU) ((void)0) +#endif #define SET_HPEL_FUNCS(PFX, IDX, SIZE, CPU) \ do { \ - SET_HPEL_FUNCS_EXT(PFX, IDX, SIZE, CPU) \ + SET_HPEL_FUNCS03(PFX, IDX, SIZE, CPU); \ + SET_HPEL_FUNCS12(PFX, IDX, SIZE, CPU); \ } while (0) -#endif static void hpeldsp_init_mmx(HpelDSPContext *c, int flags) { - SET_HPEL_FUNCS(put, [0], 16, mmx); + SET_HPEL_FUNCS03(put, [0], 16, mmx); SET_HPEL_FUNCS(put_no_rnd, [0], 16, mmx); - SET_HPEL_FUNCS(avg, [0], 16, mmx); SET_HPEL_FUNCS(avg_no_rnd, , 16, mmx); - SET_HPEL_FUNCS(put, [1], 8, mmx); + SET_HPEL_FUNCS03(put, [1], 8, mmx); SET_HPEL_FUNCS(put_no_rnd, [1], 8, mmx); - if (HAVE_MMX_EXTERNAL) { - c->avg_pixels_tab[1][0] = ff_avg_pixels8_mmx; - c->avg_pixels_tab[1][1] = ff_avg_pixels8_x2_mmx; - } -#if HAVE_MMX_INLINE - c->avg_pixels_tab[1][2] = avg_pixels8_y2_mmx; - c->avg_pixels_tab[1][3] = ff_avg_pixels8_xy2_mmx; -#endif } static void hpeldsp_init_mmxext(HpelDSPContext *c, int flags) @@ -233,37 +195,6 @@ static void hpeldsp_init_mmxext(HpelDSPContext *c, int flags) #endif /* HAVE_MMXEXT_EXTERNAL */ } -static void hpeldsp_init_3dnow(HpelDSPContext *c, int flags) -{ -#if HAVE_AMD3DNOW_EXTERNAL - c->put_pixels_tab[0][1] = ff_put_pixels16_x2_3dnow; - c->put_pixels_tab[0][2] = put_pixels16_y2_3dnow; - - c->avg_pixels_tab[0][0] = avg_pixels16_3dnow; - c->avg_pixels_tab[0][1] = avg_pixels16_x2_3dnow; - c->avg_pixels_tab[0][2] = avg_pixels16_y2_3dnow; - c->avg_pixels_tab[0][3] = avg_pixels16_xy2_3dnow; - - c->put_pixels_tab[1][1] = ff_put_pixels8_x2_3dnow; - c->put_pixels_tab[1][2] = ff_put_pixels8_y2_3dnow; - - c->avg_pixels_tab[1][0] = ff_avg_pixels8_3dnow; - c->avg_pixels_tab[1][1] = ff_avg_pixels8_x2_3dnow; - c->avg_pixels_tab[1][2] = ff_avg_pixels8_y2_3dnow; - c->avg_pixels_tab[1][3] = ff_avg_pixels8_xy2_3dnow; - - if (!(flags & AV_CODEC_FLAG_BITEXACT)){ - c->put_no_rnd_pixels_tab[0][1] = put_no_rnd_pixels16_x2_3dnow; - c->put_no_rnd_pixels_tab[0][2] = put_no_rnd_pixels16_y2_3dnow; - c->put_no_rnd_pixels_tab[1][1] = ff_put_no_rnd_pixels8_x2_3dnow; - c->put_no_rnd_pixels_tab[1][2] = ff_put_no_rnd_pixels8_y2_3dnow; - - c->avg_pixels_tab[0][3] = avg_approx_pixels16_xy2_3dnow; - c->avg_pixels_tab[1][3] = ff_avg_approx_pixels8_xy2_3dnow; - } -#endif /* HAVE_AMD3DNOW_EXTERNAL */ -} - static void hpeldsp_init_sse2_fast(HpelDSPContext *c, int flags) { #if HAVE_SSE2_EXTERNAL @@ -296,9 +227,6 @@ av_cold void ff_hpeldsp_init_x86(HpelDSPContext *c, int flags) if (INLINE_MMX(cpu_flags)) hpeldsp_init_mmx(c, flags); - if (EXTERNAL_AMD3DNOW(cpu_flags)) - hpeldsp_init_3dnow(c, flags); - if (EXTERNAL_MMXEXT(cpu_flags)) hpeldsp_init_mmxext(c, flags); diff --git a/libavcodec/x86/hpeldsp_vp3.asm b/libavcodec/x86/hpeldsp_vp3.asm index cba96d06c..88ca8e8e0 100644 --- a/libavcodec/x86/hpeldsp_vp3.asm +++ b/libavcodec/x86/hpeldsp_vp3.asm @@ -23,7 +23,7 @@ SECTION .text ; void ff_put_no_rnd_pixels8_x2_exact(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) -%macro PUT_NO_RND_PIXELS8_X2_EXACT 0 +INIT_MMX mmxext cglobal put_no_rnd_pixels8_x2_exact, 4,5 lea r4, [r2*3] pcmpeqb m6, m6 @@ -61,16 +61,10 @@ cglobal put_no_rnd_pixels8_x2_exact, 4,5 sub r3d, 4 jg .loop REP_RET -%endmacro - -INIT_MMX mmxext -PUT_NO_RND_PIXELS8_X2_EXACT -INIT_MMX 3dnow -PUT_NO_RND_PIXELS8_X2_EXACT ; void ff_put_no_rnd_pixels8_y2_exact(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h) -%macro PUT_NO_RND_PIXELS8_Y2_EXACT 0 +INIT_MMX mmxext cglobal put_no_rnd_pixels8_y2_exact, 4,5 lea r4, [r2*3] mova m0, [r1] @@ -103,9 +97,3 @@ cglobal put_no_rnd_pixels8_y2_exact, 4,5 sub r3d, 4 jg .loop REP_RET -%endmacro - -INIT_MMX mmxext -PUT_NO_RND_PIXELS8_Y2_EXACT -INIT_MMX 3dnow -PUT_NO_RND_PIXELS8_Y2_EXACT diff --git a/libavcodec/x86/hpeldsp_vp3_init.c b/libavcodec/x86/hpeldsp_vp3_init.c index 5979f4123..1dbd1ba6f 100644 --- a/libavcodec/x86/hpeldsp_vp3_init.c +++ b/libavcodec/x86/hpeldsp_vp3_init.c @@ -28,25 +28,12 @@ void ff_put_no_rnd_pixels8_x2_exact_mmxext(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); -void ff_put_no_rnd_pixels8_x2_exact_3dnow(uint8_t *block, - const uint8_t *pixels, - ptrdiff_t line_size, int h); void ff_put_no_rnd_pixels8_y2_exact_mmxext(uint8_t *block, const uint8_t *pixels, ptrdiff_t line_size, int h); -void ff_put_no_rnd_pixels8_y2_exact_3dnow(uint8_t *block, - const uint8_t *pixels, - ptrdiff_t line_size, int h); av_cold void ff_hpeldsp_vp3_init_x86(HpelDSPContext *c, int cpu_flags, int flags) { - if (EXTERNAL_AMD3DNOW(cpu_flags)) { - if (flags & AV_CODEC_FLAG_BITEXACT) { - c->put_no_rnd_pixels_tab[1][1] = ff_put_no_rnd_pixels8_x2_exact_3dnow; - c->put_no_rnd_pixels_tab[1][2] = ff_put_no_rnd_pixels8_y2_exact_3dnow; - } - } - if (EXTERNAL_MMXEXT(cpu_flags)) { if (flags & AV_CODEC_FLAG_BITEXACT) { c->put_no_rnd_pixels_tab[1][1] = ff_put_no_rnd_pixels8_x2_exact_mmxext; diff --git a/libavcodec/x86/huffyuvdsp.asm b/libavcodec/x86/huffyuvdsp.asm index a1231f1b2..c5c40e991 100644 --- a/libavcodec/x86/huffyuvdsp.asm +++ b/libavcodec/x86/huffyuvdsp.asm @@ -32,24 +32,15 @@ SECTION .text %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 @@ -60,7 +51,7 @@ ADD_INT16 ; void add_hfyu_left_pred_bgr32(uint8_t *dst, const uint8_t *src, ; intptr_t w, uint8_t *left) -%macro LEFT_BGR32 0 +INIT_XMM sse2 cglobal add_hfyu_left_pred_bgr32, 4,4,3, dst, src, w, left shl wq, 2 movd m0, [leftq] @@ -71,17 +62,12 @@ cglobal add_hfyu_left_pred_bgr32, 4,4,3, dst, src, w, left .loop: movu m1, [srcq+wq] mova m2, m1 -%if mmsize == 8 - punpckhdq m0, m0 -%endif LSHIFT m1, 4 paddb m1, m2 -%if mmsize == 16 pshufd m0, m0, q3333 mova m2, m1 LSHIFT m1, 8 paddb m1, m2 -%endif paddb m0, m1 movu [dstq+wq], m0 add wq, mmsize @@ -89,14 +75,7 @@ cglobal add_hfyu_left_pred_bgr32, 4,4,3, dst, src, w, left movd m0, [dstq-4] movd [leftq], m0 REP_RET -%endmacro -%if ARCH_X86_32 -INIT_MMX mmx -LEFT_BGR32 -%endif -INIT_XMM sse2 -LEFT_BGR32 ; void add_hfyu_median_prediction_mmxext(uint8_t *dst, const uint8_t *top, const uint8_t *diff, int mask, int w, int *left, int *left_top) INIT_MMX mmxext diff --git a/libavcodec/x86/huffyuvdsp_init.c b/libavcodec/x86/huffyuvdsp_init.c index eb10de383..239d3ca31 100644 --- a/libavcodec/x86/huffyuvdsp_init.c +++ b/libavcodec/x86/huffyuvdsp_init.c @@ -26,12 +26,9 @@ #include "libavutil/x86/cpu.h" #include "libavcodec/huffyuvdsp.h" -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); void ff_add_hfyu_left_pred_bgr32_sse2(uint8_t *dst, const uint8_t *src, intptr_t w, uint8_t *left); void ff_add_hfyu_median_pred_int16_mmxext(uint16_t *dst, const uint16_t *top, const uint16_t *diff, unsigned mask, int w, int *left, int *left_top); @@ -41,11 +38,6 @@ av_cold void ff_huffyuvdsp_init_x86(HuffYUVDSPContext *c, enum AVPixelFormat pix int cpu_flags = av_get_cpu_flags(); const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(pix_fmt); - if (ARCH_X86_32 && EXTERNAL_MMX(cpu_flags)) { - c->add_hfyu_left_pred_bgr32 = ff_add_hfyu_left_pred_bgr32_mmx; - c->add_int16 = ff_add_int16_mmx; - } - if (EXTERNAL_MMXEXT(cpu_flags) && pix_desc && pix_desc->comp[0].depth<16) { c->add_hfyu_median_pred_int16 = ff_add_hfyu_median_pred_int16_mmxext; } diff --git a/libavcodec/x86/huffyuvencdsp.asm b/libavcodec/x86/huffyuvencdsp.asm index d994fd0fd..8bfd0face 100644 --- a/libavcodec/x86/huffyuvencdsp.asm +++ b/libavcodec/x86/huffyuvencdsp.asm @@ -36,26 +36,17 @@ SECTION .text %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 diff --git a/libavcodec/x86/huffyuvencdsp_init.c b/libavcodec/x86/huffyuvencdsp_init.c index 6c6e068cf..cc6dc5a56 100644 --- a/libavcodec/x86/huffyuvencdsp_init.c +++ b/libavcodec/x86/huffyuvencdsp_init.c @@ -28,8 +28,6 @@ #include "libavutil/x86/cpu.h" #include "libavcodec/huffyuvencdsp.h" -void ff_diff_int16_mmx (uint16_t *dst, const uint16_t *src1, const uint16_t *src2, - 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, @@ -42,10 +40,6 @@ av_cold void ff_huffyuvencdsp_init_x86(HuffYUVEncDSPContext *c, AVCodecContext * av_unused int cpu_flags = av_get_cpu_flags(); const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(avctx->pix_fmt); - if (ARCH_X86_32 && EXTERNAL_MMX(cpu_flags)) { - c->diff_int16 = ff_diff_int16_mmx; - } - if (EXTERNAL_MMXEXT(cpu_flags) && pix_desc && pix_desc->comp[0].depth<16) { c->sub_hfyu_median_pred_int16 = ff_sub_hfyu_median_pred_int16_mmxext; } diff --git a/libavcodec/x86/idctdsp.asm b/libavcodec/x86/idctdsp.asm index 089425a9a..1cfdb5419 100644 --- a/libavcodec/x86/idctdsp.asm +++ b/libavcodec/x86/idctdsp.asm @@ -37,47 +37,24 @@ SECTION .text %macro PUT_SIGNED_PIXELS_CLAMPED_HALF 1 mova m1, [blockq+mmsize*0+%1] mova m2, [blockq+mmsize*2+%1] -%if mmsize == 8 - mova m3, [blockq+mmsize*4+%1] - mova m4, [blockq+mmsize*6+%1] -%endif packsswb m1, [blockq+mmsize*1+%1] packsswb m2, [blockq+mmsize*3+%1] -%if mmsize == 8 - packsswb m3, [blockq+mmsize*5+%1] - packsswb m4, [blockq+mmsize*7+%1] -%endif paddb m1, m0 paddb m2, m0 -%if mmsize == 8 - paddb m3, m0 - paddb m4, m0 - movq [pixelsq+lsizeq*0], m1 - movq [pixelsq+lsizeq*1], m2 - movq [pixelsq+lsizeq*2], m3 - movq [pixelsq+lsize3q ], m4 -%else movq [pixelsq+lsizeq*0], m1 movhps [pixelsq+lsizeq*1], m1 movq [pixelsq+lsizeq*2], m2 movhps [pixelsq+lsize3q ], m2 -%endif %endmacro -%macro PUT_SIGNED_PIXELS_CLAMPED 1 -cglobal put_signed_pixels_clamped, 3, 4, %1, block, pixels, lsize, lsize3 +INIT_XMM sse2 +cglobal put_signed_pixels_clamped, 3, 4, 3, block, pixels, lsize, lsize3 mova m0, [pb_80] lea lsize3q, [lsizeq*3] PUT_SIGNED_PIXELS_CLAMPED_HALF 0 lea pixelsq, [pixelsq+lsizeq*4] PUT_SIGNED_PIXELS_CLAMPED_HALF 64 RET -%endmacro - -INIT_MMX mmx -PUT_SIGNED_PIXELS_CLAMPED 0 -INIT_XMM sse2 -PUT_SIGNED_PIXELS_CLAMPED 3 ;-------------------------------------------------------------------------- ; void ff_put_pixels_clamped(const int16_t *block, uint8_t *pixels, @@ -87,40 +64,21 @@ PUT_SIGNED_PIXELS_CLAMPED 3 %macro PUT_PIXELS_CLAMPED_HALF 1 mova m0, [blockq+mmsize*0+%1] mova m1, [blockq+mmsize*2+%1] -%if mmsize == 8 - mova m2, [blockq+mmsize*4+%1] - mova m3, [blockq+mmsize*6+%1] -%endif packuswb m0, [blockq+mmsize*1+%1] packuswb m1, [blockq+mmsize*3+%1] -%if mmsize == 8 - packuswb m2, [blockq+mmsize*5+%1] - packuswb m3, [blockq+mmsize*7+%1] - movq [pixelsq], m0 - movq [lsizeq+pixelsq], m1 - movq [2*lsizeq+pixelsq], m2 - movq [lsize3q+pixelsq], m3 -%else movq [pixelsq], m0 movhps [lsizeq+pixelsq], m0 movq [2*lsizeq+pixelsq], m1 movhps [lsize3q+pixelsq], m1 -%endif %endmacro -%macro PUT_PIXELS_CLAMPED 0 +INIT_XMM sse2 cglobal put_pixels_clamped, 3, 4, 2, block, pixels, lsize, lsize3 lea lsize3q, [lsizeq*3] PUT_PIXELS_CLAMPED_HALF 0 lea pixelsq, [pixelsq+lsizeq*4] PUT_PIXELS_CLAMPED_HALF 64 RET -%endmacro - -INIT_MMX mmx -PUT_PIXELS_CLAMPED -INIT_XMM sse2 -PUT_PIXELS_CLAMPED ;-------------------------------------------------------------------------- ; void ff_add_pixels_clamped(const int16_t *block, uint8_t *pixels, @@ -130,41 +88,18 @@ PUT_PIXELS_CLAMPED %macro ADD_PIXELS_CLAMPED 1 mova m0, [blockq+mmsize*0+%1] mova m1, [blockq+mmsize*1+%1] -%if mmsize == 8 - mova m5, [blockq+mmsize*2+%1] - mova m6, [blockq+mmsize*3+%1] -%endif movq m2, [pixelsq] movq m3, [pixelsq+lsizeq] -%if mmsize == 8 - mova m7, m2 - punpcklbw m2, m4 - punpckhbw m7, m4 - paddsw m0, m2 - paddsw m1, m7 - mova m7, m3 - punpcklbw m3, m4 - punpckhbw m7, m4 - paddsw m5, m3 - paddsw m6, m7 -%else punpcklbw m2, m4 punpcklbw m3, m4 paddsw m0, m2 paddsw m1, m3 -%endif packuswb m0, m1 -%if mmsize == 8 - packuswb m5, m6 - movq [pixelsq], m0 - movq [pixelsq+lsizeq], m5 -%else movq [pixelsq], m0 movhps [pixelsq+lsizeq], m0 -%endif %endmacro -%macro ADD_PIXELS_CLAMPED 0 +INIT_XMM sse2 cglobal add_pixels_clamped, 3, 3, 5, block, pixels, lsize pxor m4, m4 ADD_PIXELS_CLAMPED 0 @@ -175,9 +110,3 @@ cglobal add_pixels_clamped, 3, 3, 5, block, pixels, lsize lea pixelsq, [pixelsq+lsizeq*2] ADD_PIXELS_CLAMPED 96 RET -%endmacro - -INIT_MMX mmx -ADD_PIXELS_CLAMPED -INIT_XMM sse2 -ADD_PIXELS_CLAMPED diff --git a/libavcodec/x86/idctdsp.h b/libavcodec/x86/idctdsp.h index 0d0bdb5f5..738e4e36e 100644 --- a/libavcodec/x86/idctdsp.h +++ b/libavcodec/x86/idctdsp.h @@ -22,16 +22,10 @@ #include #include -void ff_add_pixels_clamped_mmx(const int16_t *block, uint8_t *pixels, - ptrdiff_t line_size); void ff_add_pixels_clamped_sse2(const int16_t *block, uint8_t *pixels, ptrdiff_t line_size); -void ff_put_pixels_clamped_mmx(const int16_t *block, uint8_t *pixels, - ptrdiff_t line_size); void ff_put_pixels_clamped_sse2(const int16_t *block, uint8_t *pixels, ptrdiff_t line_size); -void ff_put_signed_pixels_clamped_mmx(const int16_t *block, uint8_t *pixels, - ptrdiff_t line_size); void ff_put_signed_pixels_clamped_sse2(const int16_t *block, uint8_t *pixels, ptrdiff_t line_size); diff --git a/libavcodec/x86/idctdsp_init.c b/libavcodec/x86/idctdsp_init.c index 9103b92ce..f28a1ad74 100644 --- a/libavcodec/x86/idctdsp_init.c +++ b/libavcodec/x86/idctdsp_init.c @@ -63,28 +63,24 @@ av_cold void ff_idctdsp_init_x86(IDCTDSPContext *c, AVCodecContext *avctx, { int cpu_flags = av_get_cpu_flags(); +#if ARCH_X86_32 if (EXTERNAL_MMX(cpu_flags)) { - c->put_signed_pixels_clamped = ff_put_signed_pixels_clamped_mmx; - c->put_pixels_clamped = ff_put_pixels_clamped_mmx; - c->add_pixels_clamped = ff_add_pixels_clamped_mmx; - if (!high_bit_depth && avctx->lowres == 0 && (avctx->idct_algo == FF_IDCT_AUTO || avctx->idct_algo == FF_IDCT_SIMPLEAUTO || avctx->idct_algo == FF_IDCT_SIMPLEMMX)) { - c->idct_put = ff_simple_idct_put_mmx; - c->idct_add = ff_simple_idct_add_mmx; c->idct = ff_simple_idct_mmx; - c->perm_type = FF_IDCT_PERM_SIMPLE; } } +#endif if (EXTERNAL_SSE2(cpu_flags)) { c->put_signed_pixels_clamped = ff_put_signed_pixels_clamped_sse2; c->put_pixels_clamped = ff_put_pixels_clamped_sse2; c->add_pixels_clamped = ff_add_pixels_clamped_sse2; +#if ARCH_X86_32 if (!high_bit_depth && avctx->lowres == 0 && (avctx->idct_algo == FF_IDCT_AUTO || @@ -94,6 +90,7 @@ av_cold void ff_idctdsp_init_x86(IDCTDSPContext *c, AVCodecContext *avctx, c->idct_add = ff_simple_idct_add_sse2; c->perm_type = FF_IDCT_PERM_SIMPLE; } +#endif if (ARCH_X86_64 && !high_bit_depth && diff --git a/libavcodec/x86/imdct36.asm b/libavcodec/x86/imdct36.asm index b386ab95f..888c6bf4d 100644 --- a/libavcodec/x86/imdct36.asm +++ b/libavcodec/x86/imdct36.asm @@ -373,11 +373,6 @@ cglobal imdct36_float, 4,4,9, out, buf, in, win RET %endmacro -%if ARCH_X86_32 -INIT_XMM sse -DEFINE_IMDCT -%endif - INIT_XMM sse2 DEFINE_IMDCT diff --git a/libavcodec/x86/lossless_audiodsp.asm b/libavcodec/x86/lossless_audiodsp.asm index 063d7b41a..ff18eb708 100644 --- a/libavcodec/x86/lossless_audiodsp.asm +++ b/libavcodec/x86/lossless_audiodsp.asm @@ -22,18 +22,14 @@ SECTION .text -%macro SCALARPRODUCT 0 ; int ff_scalarproduct_and_madd_int16(int16_t *v1, int16_t *v2, int16_t *v3, ; int order, int mul) +INIT_XMM sse2 cglobal scalarproduct_and_madd_int16, 4,4,8, v1, v2, v3, order, mul shl orderq, 1 movd m7, mulm -%if mmsize == 16 pshuflw m7, m7, 0 punpcklqdq m7, m7 -%else - pshufw m7, m7, 0 -%endif pxor m6, m6 add v1q, orderq add v2q, orderq @@ -61,12 +57,6 @@ cglobal scalarproduct_and_madd_int16, 4,4,8, v1, v2, v3, order, mul HADDD m6, m0 movd eax, m6 RET -%endmacro - -INIT_MMX mmxext -SCALARPRODUCT -INIT_XMM sse2 -SCALARPRODUCT INIT_XMM sse4 ; int ff_scalarproduct_and_madd_int32(int16_t *v1, int32_t *v2, int16_t *v3, diff --git a/libavcodec/x86/lossless_audiodsp_init.c b/libavcodec/x86/lossless_audiodsp_init.c index f74c7e436..462329db3 100644 --- a/libavcodec/x86/lossless_audiodsp_init.c +++ b/libavcodec/x86/lossless_audiodsp_init.c @@ -21,9 +21,6 @@ #include "libavutil/x86/cpu.h" #include "libavcodec/lossless_audiodsp.h" -int32_t ff_scalarproduct_and_madd_int16_mmxext(int16_t *v1, const int16_t *v2, - const int16_t *v3, - int order, int mul); int32_t ff_scalarproduct_and_madd_int16_sse2(int16_t *v1, const int16_t *v2, const int16_t *v3, int order, int mul); @@ -40,9 +37,6 @@ av_cold void ff_llauddsp_init_x86(LLAudDSPContext *c) #if HAVE_X86ASM int cpu_flags = av_get_cpu_flags(); - if (EXTERNAL_MMXEXT(cpu_flags)) - c->scalarproduct_and_madd_int16 = ff_scalarproduct_and_madd_int16_mmxext; - if (EXTERNAL_SSE2(cpu_flags)) c->scalarproduct_and_madd_int16 = ff_scalarproduct_and_madd_int16_sse2; diff --git a/libavcodec/x86/lossless_videodsp.asm b/libavcodec/x86/lossless_videodsp.asm index 0a1b7091c..eb1b80506 100644 --- a/libavcodec/x86/lossless_videodsp.asm +++ b/libavcodec/x86/lossless_videodsp.asm @@ -38,11 +38,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) +; void ff_add_median_pred(uint8_t *dst, const uint8_t *top, +; const uint8_t *diff, int w, +; int *left, int *left_top) ;------------------------------------------------------------------------------ -%macro MEDIAN_PRED 0 +INIT_XMM sse2 cglobal add_median_pred, 6,6,8, dst, top, diff, w, left, left_top movu m0, [topq] mova m2, m0 @@ -100,14 +100,6 @@ cglobal add_median_pred, 6,6,8, dst, top, diff, w, left, left_top movzx r2d, byte [topq-1] mov [left_topq], r2d RET -%endmacro - -%if ARCH_X86_32 -INIT_MMX mmxext -MEDIAN_PRED -%endif -INIT_XMM sse2 -MEDIAN_PRED %macro ADD_LEFT_LOOP 2 ; %1 = dst_is_aligned, %2 = src_is_aligned @@ -240,10 +232,6 @@ cglobal add_bytes, 3,4,2, dst, src, w, size REP_RET %endmacro -%if ARCH_X86_32 -INIT_MMX mmx -ADD_BYTES -%endif INIT_XMM sse2 ADD_BYTES diff --git a/libavcodec/x86/lossless_videodsp_init.c b/libavcodec/x86/lossless_videodsp_init.c index 6d71f14e7..5690cacaa 100644 --- a/libavcodec/x86/lossless_videodsp_init.c +++ b/libavcodec/x86/lossless_videodsp_init.c @@ -19,17 +19,12 @@ */ #include "config.h" -#include "libavutil/x86/asm.h" #include "../lossless_videodsp.h" #include "libavutil/x86/cpu.h" -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, - int *left, int *left_top); void ff_add_median_pred_sse2(uint8_t *dst, const uint8_t *top, const uint8_t *diff, ptrdiff_t w, int *left, int *left_top); @@ -47,63 +42,10 @@ int ff_add_left_pred_int16_unaligned_ssse3(uint16_t *dst, const uint16_t *src, u 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, - int *left, int *left_top) -{ - x86_reg w2 = -w; - x86_reg x; - int l = *left & 0xff; - int tl = *left_top & 0xff; - int t; - __asm__ volatile ( - "mov %7, %3 \n" - "1: \n" - "movzbl (%3, %4), %2 \n" - "mov %2, %k3 \n" - "sub %b1, %b3 \n" - "add %b0, %b3 \n" - "mov %2, %1 \n" - "cmp %0, %2 \n" - "cmovg %0, %2 \n" - "cmovg %1, %0 \n" - "cmp %k3, %0 \n" - "cmovg %k3, %0 \n" - "mov %7, %3 \n" - "cmp %2, %0 \n" - "cmovl %2, %0 \n" - "add (%6, %4), %b0 \n" - "mov %b0, (%5, %4) \n" - "inc %4 \n" - "jl 1b \n" - : "+&q"(l), "+&q"(tl), "=&r"(t), "=&q"(x), "+&r"(w2) - : "r"(dst + w), "r"(diff + w), "rm"(top + w) - ); - *left = l; - *left_top = tl; -} -#endif - void ff_llviddsp_init_x86(LLVidDSPContext *c) { int cpu_flags = av_get_cpu_flags(); -#if HAVE_INLINE_ASM && HAVE_7REGS && ARCH_X86_32 - if (cpu_flags & AV_CPU_FLAG_CMOV) - c->add_median_pred = add_median_pred_cmov; -#endif - - if (ARCH_X86_32 && EXTERNAL_MMX(cpu_flags)) { - c->add_bytes = ff_add_bytes_mmx; - } - - if (ARCH_X86_32 && EXTERNAL_MMXEXT(cpu_flags)) { - /* slower than cmov version on AMD */ - if (!(cpu_flags & AV_CPU_FLAG_3DNOW)) - c->add_median_pred = ff_add_median_pred_mmxext; - } - if (EXTERNAL_SSE2(cpu_flags)) { c->add_bytes = ff_add_bytes_sse2; c->add_median_pred = ff_add_median_pred_sse2; diff --git a/libavcodec/x86/lossless_videoencdsp.asm b/libavcodec/x86/lossless_videoencdsp.asm index fb1204f0f..2e1d01bc2 100644 --- a/libavcodec/x86/lossless_videoencdsp.asm +++ b/libavcodec/x86/lossless_videoencdsp.asm @@ -113,15 +113,6 @@ cglobal diff_bytes, 4,5,2, dst, src1, src2, w REP_RET %endmacro -%if ARCH_X86_32 -INIT_MMX mmx -DIFF_BYTES_PROLOGUE - %define regsize mmsize - DIFF_BYTES_LOOP_PREP .skip_main_aa, .end_aa - DIFF_BYTES_BODY a, a -%undef i -%endif - INIT_XMM sse2 DIFF_BYTES_PROLOGUE %define regsize mmsize diff --git a/libavcodec/x86/lossless_videoencdsp_init.c b/libavcodec/x86/lossless_videoencdsp_init.c index 40407add5..b3efcfdcd 100644 --- a/libavcodec/x86/lossless_videoencdsp_init.c +++ b/libavcodec/x86/lossless_videoencdsp_init.c @@ -29,8 +29,6 @@ #include "libavcodec/lossless_videoencdsp.h" #include "libavcodec/mathops.h" -void ff_diff_bytes_mmx(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, - intptr_t w); void ff_diff_bytes_sse2(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, intptr_t w); void ff_diff_bytes_avx2(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, @@ -87,10 +85,6 @@ av_cold void ff_llvidencdsp_init_x86(LLVidEncDSPContext *c) { av_unused int cpu_flags = av_get_cpu_flags(); - if (ARCH_X86_32 && EXTERNAL_MMX(cpu_flags)) { - c->diff_bytes = ff_diff_bytes_mmx; - } - #if HAVE_INLINE_ASM if (INLINE_MMXEXT(cpu_flags)) { c->sub_median_pred = sub_median_pred_mmxext; diff --git a/libavcodec/x86/lpc.c b/libavcodec/x86/lpc.c index 544083bd3..40fc29fc0 100644 --- a/libavcodec/x86/lpc.c +++ b/libavcodec/x86/lpc.c @@ -154,7 +154,7 @@ av_cold void ff_lpc_init_x86(LPCContext *c) #if HAVE_SSE2_INLINE int cpu_flags = av_get_cpu_flags(); - if (INLINE_SSE2(cpu_flags) || INLINE_SSE2_SLOW(cpu_flags)) { + if (INLINE_SSE2_SLOW(cpu_flags)) { c->lpc_apply_welch_window = lpc_apply_welch_window_sse2; c->lpc_compute_autocorr = lpc_compute_autocorr_sse2; } diff --git a/libavcodec/x86/mdct15_init.c b/libavcodec/x86/mdct15_init.c index 641bfd043..ea7301e1e 100644 --- a/libavcodec/x86/mdct15_init.c +++ b/libavcodec/x86/mdct15_init.c @@ -20,6 +20,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + #include "config.h" #include "libavutil/attributes.h" @@ -87,13 +89,15 @@ av_cold void ff_mdct15_init_x86(MDCT15Context *s) if (EXTERNAL_SSE3(cpu_flags)) s->postreindex = ff_mdct15_postreindex_sse3; - if (ARCH_X86_64 && EXTERNAL_AVX(cpu_flags)) { +#if ARCH_X86_64 + if (EXTERNAL_AVX(cpu_flags)) { s->fft15 = ff_fft15_avx; adjust_twiddles = 1; } - if (ARCH_X86_64 && EXTERNAL_AVX2_FAST(cpu_flags)) + if (EXTERNAL_AVX2_FAST(cpu_flags)) s->postreindex = ff_mdct15_postreindex_avx2; +#endif if (adjust_twiddles) perm_twiddles(s); diff --git a/libavcodec/x86/me_cmp.asm b/libavcodec/x86/me_cmp.asm index ad06d485a..10809bbfb 100644 --- a/libavcodec/x86/me_cmp.asm +++ b/libavcodec/x86/me_cmp.asm @@ -261,11 +261,10 @@ hadamard8_16_wrapper 0, 14 %endif %endmacro -INIT_MMX mmx -HADAMARD8_DIFF - +%if HAVE_ALIGNED_STACK == 0 INIT_MMX mmxext HADAMARD8_DIFF +%endif INIT_XMM sse2 %if ARCH_X86_64 @@ -385,10 +384,6 @@ cglobal sum_abs_dctelem, 1, 1, %1, block RET %endmacro -INIT_MMX mmx -SUM_ABS_DCTELEM 0, 4 -INIT_MMX mmxext -SUM_ABS_DCTELEM 0, 4 INIT_XMM sse2 SUM_ABS_DCTELEM 7, 2 INIT_XMM ssse3 diff --git a/libavcodec/x86/me_cmp_init.c b/libavcodec/x86/me_cmp_init.c index 9af911bb8..61e9396b8 100644 --- a/libavcodec/x86/me_cmp_init.c +++ b/libavcodec/x86/me_cmp_init.c @@ -30,8 +30,6 @@ #include "libavcodec/me_cmp.h" #include "libavcodec/mpegvideo.h" -int ff_sum_abs_dctelem_mmx(int16_t *block); -int ff_sum_abs_dctelem_mmxext(int16_t *block); int ff_sum_abs_dctelem_sse2(int16_t *block); int ff_sum_abs_dctelem_ssse3(int16_t *block); int ff_sse8_mmx(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, @@ -85,7 +83,6 @@ int ff_vsad16_approx_sse2(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, int ff_hadamard8_diff16_ ## cpu(MpegEncContext *s, uint8_t *src1, \ uint8_t *src2, ptrdiff_t stride, int h); -hadamard_func(mmx) hadamard_func(mmxext) hadamard_func(sse2) hadamard_func(ssse3) @@ -126,232 +123,12 @@ static int nsse8_mmx(MpegEncContext *c, uint8_t *pix1, uint8_t *pix2, #if HAVE_INLINE_ASM -static int vsad_intra16_mmx(MpegEncContext *v, uint8_t *pix, uint8_t *dummy, - ptrdiff_t stride, int h) -{ - int tmp; - - av_assert2(((uintptr_t) pix & 7) == 0); - av_assert2((stride & 7) == 0); - -#define SUM(in0, in1, out0, out1) \ - "movq (%0), %%mm2\n" \ - "movq 8(%0), %%mm3\n" \ - "add %2,%0\n" \ - "movq %%mm2, " #out0 "\n" \ - "movq %%mm3, " #out1 "\n" \ - "psubusb " #in0 ", %%mm2\n" \ - "psubusb " #in1 ", %%mm3\n" \ - "psubusb " #out0 ", " #in0 "\n" \ - "psubusb " #out1 ", " #in1 "\n" \ - "por %%mm2, " #in0 "\n" \ - "por %%mm3, " #in1 "\n" \ - "movq " #in0 ", %%mm2\n" \ - "movq " #in1 ", %%mm3\n" \ - "punpcklbw %%mm7, " #in0 "\n" \ - "punpcklbw %%mm7, " #in1 "\n" \ - "punpckhbw %%mm7, %%mm2\n" \ - "punpckhbw %%mm7, %%mm3\n" \ - "paddw " #in1 ", " #in0 "\n" \ - "paddw %%mm3, %%mm2\n" \ - "paddw %%mm2, " #in0 "\n" \ - "paddw " #in0 ", %%mm6\n" - - - __asm__ volatile ( - "movl %3, %%ecx\n" - "pxor %%mm6, %%mm6\n" - "pxor %%mm7, %%mm7\n" - "movq (%0), %%mm0\n" - "movq 8(%0), %%mm1\n" - "add %2, %0\n" - "jmp 2f\n" - "1:\n" - - SUM(%%mm4, %%mm5, %%mm0, %%mm1) - "2:\n" - SUM(%%mm0, %%mm1, %%mm4, %%mm5) - - "subl $2, %%ecx\n" - "jnz 1b\n" - - "movq %%mm6, %%mm0\n" - "psrlq $32, %%mm6\n" - "paddw %%mm6, %%mm0\n" - "movq %%mm0, %%mm6\n" - "psrlq $16, %%mm0\n" - "paddw %%mm6, %%mm0\n" - "movd %%mm0, %1\n" - : "+r" (pix), "=r" (tmp) - : "r" (stride), "m" (h) - : "%ecx"); - - return tmp & 0xFFFF; -} -#undef SUM - -static int vsad16_mmx(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, - ptrdiff_t stride, int h) -{ - int tmp; - - av_assert2(((uintptr_t)pix1 & 7) == 0); - av_assert2(((uintptr_t)pix2 & 7) == 0); - av_assert2((stride & 7) == 0); - -#define SUM(in0, in1, out0, out1) \ - "movq (%0), %%mm2\n" \ - "movq (%1), " #out0 "\n" \ - "movq 8(%0), %%mm3\n" \ - "movq 8(%1), " #out1 "\n" \ - "add %3, %0\n" \ - "add %3, %1\n" \ - "psubb " #out0 ", %%mm2\n" \ - "psubb " #out1 ", %%mm3\n" \ - "pxor %%mm7, %%mm2\n" \ - "pxor %%mm7, %%mm3\n" \ - "movq %%mm2, " #out0 "\n" \ - "movq %%mm3, " #out1 "\n" \ - "psubusb " #in0 ", %%mm2\n" \ - "psubusb " #in1 ", %%mm3\n" \ - "psubusb " #out0 ", " #in0 "\n" \ - "psubusb " #out1 ", " #in1 "\n" \ - "por %%mm2, " #in0 "\n" \ - "por %%mm3, " #in1 "\n" \ - "movq " #in0 ", %%mm2\n" \ - "movq " #in1 ", %%mm3\n" \ - "punpcklbw %%mm7, " #in0 "\n" \ - "punpcklbw %%mm7, " #in1 "\n" \ - "punpckhbw %%mm7, %%mm2\n" \ - "punpckhbw %%mm7, %%mm3\n" \ - "paddw " #in1 ", " #in0 "\n" \ - "paddw %%mm3, %%mm2\n" \ - "paddw %%mm2, " #in0 "\n" \ - "paddw " #in0 ", %%mm6\n" - - - __asm__ volatile ( - "movl %4, %%ecx\n" - "pxor %%mm6, %%mm6\n" - "pcmpeqw %%mm7, %%mm7\n" - "psllw $15, %%mm7\n" - "packsswb %%mm7, %%mm7\n" - "movq (%0), %%mm0\n" - "movq (%1), %%mm2\n" - "movq 8(%0), %%mm1\n" - "movq 8(%1), %%mm3\n" - "add %3, %0\n" - "add %3, %1\n" - "psubb %%mm2, %%mm0\n" - "psubb %%mm3, %%mm1\n" - "pxor %%mm7, %%mm0\n" - "pxor %%mm7, %%mm1\n" - "jmp 2f\n" - "1:\n" - - SUM(%%mm4, %%mm5, %%mm0, %%mm1) - "2:\n" - SUM(%%mm0, %%mm1, %%mm4, %%mm5) - - "subl $2, %%ecx\n" - "jnz 1b\n" - - "movq %%mm6, %%mm0\n" - "psrlq $32, %%mm6\n" - "paddw %%mm6, %%mm0\n" - "movq %%mm0, %%mm6\n" - "psrlq $16, %%mm0\n" - "paddw %%mm6, %%mm0\n" - "movd %%mm0, %2\n" - : "+r" (pix1), "+r" (pix2), "=r" (tmp) - : "r" (stride), "m" (h) - : "%ecx"); - - return tmp & 0x7FFF; -} -#undef SUM - DECLARE_ASM_CONST(8, uint64_t, round_tab)[3] = { 0x0000000000000000ULL, 0x0001000100010001ULL, 0x0002000200020002ULL, }; -static inline void sad8_1_mmx(uint8_t *blk1, uint8_t *blk2, - ptrdiff_t stride, int h) -{ - x86_reg len = -stride * h; - __asm__ volatile ( - ".p2align 4 \n\t" - "1: \n\t" - "movq (%1, %%"FF_REG_a"), %%mm0 \n\t" - "movq (%2, %%"FF_REG_a"), %%mm2 \n\t" - "movq (%2, %%"FF_REG_a"), %%mm4 \n\t" - "add %3, %%"FF_REG_a" \n\t" - "psubusb %%mm0, %%mm2 \n\t" - "psubusb %%mm4, %%mm0 \n\t" - "movq (%1, %%"FF_REG_a"), %%mm1 \n\t" - "movq (%2, %%"FF_REG_a"), %%mm3 \n\t" - "movq (%2, %%"FF_REG_a"), %%mm5 \n\t" - "psubusb %%mm1, %%mm3 \n\t" - "psubusb %%mm5, %%mm1 \n\t" - "por %%mm2, %%mm0 \n\t" - "por %%mm1, %%mm3 \n\t" - "movq %%mm0, %%mm1 \n\t" - "movq %%mm3, %%mm2 \n\t" - "punpcklbw %%mm7, %%mm0 \n\t" - "punpckhbw %%mm7, %%mm1 \n\t" - "punpcklbw %%mm7, %%mm3 \n\t" - "punpckhbw %%mm7, %%mm2 \n\t" - "paddw %%mm1, %%mm0 \n\t" - "paddw %%mm3, %%mm2 \n\t" - "paddw %%mm2, %%mm0 \n\t" - "paddw %%mm0, %%mm6 \n\t" - "add %3, %%"FF_REG_a" \n\t" - " js 1b \n\t" - : "+a" (len) - : "r" (blk1 - len), "r" (blk2 - len), "r" (stride)); -} - -static inline void sad8_2_mmx(uint8_t *blk1a, uint8_t *blk1b, uint8_t *blk2, - ptrdiff_t stride, int h) -{ - x86_reg len = -stride * h; - __asm__ volatile ( - ".p2align 4 \n\t" - "1: \n\t" - "movq (%1, %%"FF_REG_a"), %%mm0 \n\t" - "movq (%2, %%"FF_REG_a"), %%mm1 \n\t" - "movq (%1, %%"FF_REG_a"), %%mm2 \n\t" - "movq (%2, %%"FF_REG_a"), %%mm3 \n\t" - "punpcklbw %%mm7, %%mm0 \n\t" - "punpcklbw %%mm7, %%mm1 \n\t" - "punpckhbw %%mm7, %%mm2 \n\t" - "punpckhbw %%mm7, %%mm3 \n\t" - "paddw %%mm0, %%mm1 \n\t" - "paddw %%mm2, %%mm3 \n\t" - "movq (%3, %%"FF_REG_a"), %%mm4 \n\t" - "movq (%3, %%"FF_REG_a"), %%mm2 \n\t" - "paddw %%mm5, %%mm1 \n\t" - "paddw %%mm5, %%mm3 \n\t" - "psrlw $1, %%mm1 \n\t" - "psrlw $1, %%mm3 \n\t" - "packuswb %%mm3, %%mm1 \n\t" - "psubusb %%mm1, %%mm4 \n\t" - "psubusb %%mm2, %%mm1 \n\t" - "por %%mm4, %%mm1 \n\t" - "movq %%mm1, %%mm0 \n\t" - "punpcklbw %%mm7, %%mm0 \n\t" - "punpckhbw %%mm7, %%mm1 \n\t" - "paddw %%mm1, %%mm0 \n\t" - "paddw %%mm0, %%mm6 \n\t" - "add %4, %%"FF_REG_a" \n\t" - " js 1b \n\t" - : "+a" (len) - : "r" (blk1a - len), "r" (blk1b - len), "r" (blk2 - len), - "r" (stride)); -} - static inline void sad8_4_mmx(uint8_t *blk1, uint8_t *blk2, ptrdiff_t stride, int h) { @@ -421,63 +198,7 @@ static inline int sum_mmx(void) return ret & 0xFFFF; } -static inline void sad8_x2a_mmx(uint8_t *blk1, uint8_t *blk2, - ptrdiff_t stride, int h) -{ - sad8_2_mmx(blk1, blk1 + 1, blk2, stride, h); -} - -static inline void sad8_y2a_mmx(uint8_t *blk1, uint8_t *blk2, - ptrdiff_t stride, int h) -{ - sad8_2_mmx(blk1, blk1 + stride, blk2, stride, h); -} - -#define PIX_SAD(suf) \ -static int sad8_ ## suf(MpegEncContext *v, uint8_t *blk2, \ - uint8_t *blk1, ptrdiff_t stride, int h) \ -{ \ - av_assert2(h == 8); \ - __asm__ volatile ( \ - "pxor %%mm7, %%mm7 \n\t" \ - "pxor %%mm6, %%mm6 \n\t" \ - :); \ - \ - sad8_1_ ## suf(blk1, blk2, stride, 8); \ - \ - return sum_ ## suf(); \ -} \ - \ -static int sad8_x2_ ## suf(MpegEncContext *v, uint8_t *blk2, \ - uint8_t *blk1, ptrdiff_t stride, int h) \ -{ \ - av_assert2(h == 8); \ - __asm__ volatile ( \ - "pxor %%mm7, %%mm7 \n\t" \ - "pxor %%mm6, %%mm6 \n\t" \ - "movq %0, %%mm5 \n\t" \ - :: "m" (round_tab[1])); \ - \ - sad8_x2a_ ## suf(blk1, blk2, stride, 8); \ - \ - return sum_ ## suf(); \ -} \ - \ -static int sad8_y2_ ## suf(MpegEncContext *v, uint8_t *blk2, \ - uint8_t *blk1, ptrdiff_t stride, int h) \ -{ \ - av_assert2(h == 8); \ - __asm__ volatile ( \ - "pxor %%mm7, %%mm7 \n\t" \ - "pxor %%mm6, %%mm6 \n\t" \ - "movq %0, %%mm5 \n\t" \ - :: "m" (round_tab[1])); \ - \ - sad8_y2a_ ## suf(blk1, blk2, stride, 8); \ - \ - return sum_ ## suf(); \ -} \ - \ +#define PIX_SADXY(suf) \ static int sad8_xy2_ ## suf(MpegEncContext *v, uint8_t *blk2, \ uint8_t *blk1, ptrdiff_t stride, int h) \ { \ @@ -492,50 +213,6 @@ static int sad8_xy2_ ## suf(MpegEncContext *v, uint8_t *blk2, \ return sum_ ## suf(); \ } \ \ -static int sad16_ ## suf(MpegEncContext *v, uint8_t *blk2, \ - uint8_t *blk1, ptrdiff_t stride, int h) \ -{ \ - __asm__ volatile ( \ - "pxor %%mm7, %%mm7 \n\t" \ - "pxor %%mm6, %%mm6 \n\t" \ - :); \ - \ - sad8_1_ ## suf(blk1, blk2, stride, h); \ - sad8_1_ ## suf(blk1 + 8, blk2 + 8, stride, h); \ - \ - return sum_ ## suf(); \ -} \ - \ -static int sad16_x2_ ## suf(MpegEncContext *v, uint8_t *blk2, \ - uint8_t *blk1, ptrdiff_t stride, int h) \ -{ \ - __asm__ volatile ( \ - "pxor %%mm7, %%mm7 \n\t" \ - "pxor %%mm6, %%mm6 \n\t" \ - "movq %0, %%mm5 \n\t" \ - :: "m" (round_tab[1])); \ - \ - sad8_x2a_ ## suf(blk1, blk2, stride, h); \ - sad8_x2a_ ## suf(blk1 + 8, blk2 + 8, stride, h); \ - \ - return sum_ ## suf(); \ -} \ - \ -static int sad16_y2_ ## suf(MpegEncContext *v, uint8_t *blk2, \ - uint8_t *blk1, ptrdiff_t stride, int h) \ -{ \ - __asm__ volatile ( \ - "pxor %%mm7, %%mm7 \n\t" \ - "pxor %%mm6, %%mm6 \n\t" \ - "movq %0, %%mm5 \n\t" \ - :: "m" (round_tab[1])); \ - \ - sad8_y2a_ ## suf(blk1, blk2, stride, h); \ - sad8_y2a_ ## suf(blk1 + 8, blk2 + 8, stride, h); \ - \ - return sum_ ## suf(); \ -} \ - \ static int sad16_xy2_ ## suf(MpegEncContext *v, uint8_t *blk2, \ uint8_t *blk1, ptrdiff_t stride, int h) \ { \ @@ -550,7 +227,7 @@ static int sad16_xy2_ ## suf(MpegEncContext *v, uint8_t *blk2, \ return sum_ ## suf(); \ } \ -PIX_SAD(mmx) +PIX_SADXY(mmx) #endif /* HAVE_INLINE_ASM */ @@ -560,32 +237,13 @@ av_cold void ff_me_cmp_init_x86(MECmpContext *c, AVCodecContext *avctx) #if HAVE_INLINE_ASM if (INLINE_MMX(cpu_flags)) { - c->pix_abs[0][0] = sad16_mmx; - c->pix_abs[0][1] = sad16_x2_mmx; - c->pix_abs[0][2] = sad16_y2_mmx; c->pix_abs[0][3] = sad16_xy2_mmx; - c->pix_abs[1][0] = sad8_mmx; - c->pix_abs[1][1] = sad8_x2_mmx; - c->pix_abs[1][2] = sad8_y2_mmx; c->pix_abs[1][3] = sad8_xy2_mmx; - - c->sad[0] = sad16_mmx; - c->sad[1] = sad8_mmx; - - c->vsad[4] = vsad_intra16_mmx; - - if (!(avctx->flags & AV_CODEC_FLAG_BITEXACT)) { - c->vsad[0] = vsad16_mmx; - } } #endif /* HAVE_INLINE_ASM */ if (EXTERNAL_MMX(cpu_flags)) { - c->hadamard8_diff[0] = ff_hadamard8_diff16_mmx; - c->hadamard8_diff[1] = ff_hadamard8_diff_mmx; - c->sum_abs_dctelem = ff_sum_abs_dctelem_mmx; - c->sse[0] = ff_sse16_mmx; c->sse[1] = ff_sse8_mmx; #if HAVE_X86ASM c->nsse[0] = nsse16_mmx; @@ -594,9 +252,10 @@ av_cold void ff_me_cmp_init_x86(MECmpContext *c, AVCodecContext *avctx) } if (EXTERNAL_MMXEXT(cpu_flags)) { +#if !HAVE_ALIGNED_STACK c->hadamard8_diff[0] = ff_hadamard8_diff16_mmxext; c->hadamard8_diff[1] = ff_hadamard8_diff_mmxext; - c->sum_abs_dctelem = ff_sum_abs_dctelem_mmxext; +#endif c->sad[0] = ff_sad16_mmxext; c->sad[1] = ff_sad8_mmxext; diff --git a/libavcodec/x86/mpegaudiodsp.c b/libavcodec/x86/mpegaudiodsp.c index 50692f29c..6586fe072 100644 --- a/libavcodec/x86/mpegaudiodsp.c +++ b/libavcodec/x86/mpegaudiodsp.c @@ -19,9 +19,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + +#include "config.h" #include "libavutil/attributes.h" #include "libavutil/cpu.h" -#include "libavutil/internal.h" #include "libavutil/mem_internal.h" #include "libavutil/x86/asm.h" #include "libavutil/x86/cpu.h" @@ -32,9 +34,6 @@ static void imdct36_blocks_ ## CPU(float *out, float *buf, float *in, int count, void ff_imdct36_float_ ## CPU(float *out, float *buf, float *in, float *win); #if HAVE_X86ASM -#if ARCH_X86_32 -DECL(sse) -#endif DECL(sse2) DECL(sse3) DECL(ssse3) @@ -228,9 +227,6 @@ static void imdct36_blocks_ ## CPU1(float *out, float *buf, float *in, \ } #if HAVE_SSE -#if ARCH_X86_32 -DECL_IMDCT_BLOCKS(sse,sse) -#endif DECL_IMDCT_BLOCKS(sse2,sse) DECL_IMDCT_BLOCKS(sse3,sse) DECL_IMDCT_BLOCKS(ssse3,sse) @@ -269,11 +265,6 @@ av_cold void ff_mpadsp_init_x86(MPADSPContext *s) #if HAVE_X86ASM #if HAVE_SSE -#if ARCH_X86_32 - if (EXTERNAL_SSE(cpu_flags)) { - s->imdct36_blocks_float = imdct36_blocks_sse; - } -#endif if (EXTERNAL_SSE2(cpu_flags)) { s->imdct36_blocks_float = imdct36_blocks_sse2; } diff --git a/libavcodec/x86/mpegvideoenc.c b/libavcodec/x86/mpegvideoenc.c index 4bad6a87e..612e7ff75 100644 --- a/libavcodec/x86/mpegvideoenc.c +++ b/libavcodec/x86/mpegvideoenc.c @@ -26,7 +26,7 @@ #include "libavutil/x86/cpu.h" #include "libavcodec/avcodec.h" #include "libavcodec/dct.h" -#include "libavcodec/mpegvideo.h" +#include "libavcodec/mpegvideoenc.h" /* not permutated inverse zigzag_direct + 1 for MMX quantizer */ DECLARE_ALIGNED(16, static const uint16_t, inv_zigzag_direct16)[64] = { @@ -42,34 +42,9 @@ DECLARE_ALIGNED(16, static const uint16_t, inv_zigzag_direct16)[64] = { #if HAVE_6REGS -#if HAVE_MMX_INLINE -#define COMPILE_TEMPLATE_MMXEXT 0 -#define COMPILE_TEMPLATE_SSE2 0 -#define COMPILE_TEMPLATE_SSSE3 0 -#define RENAME(a) a ## _mmx -#define RENAME_FDCT(a) a ## _mmx -#include "mpegvideoenc_template.c" -#endif /* HAVE_MMX_INLINE */ - -#if HAVE_MMXEXT_INLINE -#undef COMPILE_TEMPLATE_SSSE3 -#undef COMPILE_TEMPLATE_SSE2 -#undef COMPILE_TEMPLATE_MMXEXT -#define COMPILE_TEMPLATE_MMXEXT 1 -#define COMPILE_TEMPLATE_SSE2 0 -#define COMPILE_TEMPLATE_SSSE3 0 -#undef RENAME -#undef RENAME_FDCT -#define RENAME(a) a ## _mmxext -#define RENAME_FDCT(a) a ## _mmxext -#include "mpegvideoenc_template.c" -#endif /* HAVE_MMXEXT_INLINE */ - #if HAVE_SSE2_INLINE -#undef COMPILE_TEMPLATE_MMXEXT #undef COMPILE_TEMPLATE_SSE2 #undef COMPILE_TEMPLATE_SSSE3 -#define COMPILE_TEMPLATE_MMXEXT 0 #define COMPILE_TEMPLATE_SSE2 1 #define COMPILE_TEMPLATE_SSSE3 0 #undef RENAME @@ -80,10 +55,8 @@ DECLARE_ALIGNED(16, static const uint16_t, inv_zigzag_direct16)[64] = { #endif /* HAVE_SSE2_INLINE */ #if HAVE_SSSE3_INLINE -#undef COMPILE_TEMPLATE_MMXEXT #undef COMPILE_TEMPLATE_SSE2 #undef COMPILE_TEMPLATE_SSSE3 -#define COMPILE_TEMPLATE_MMXEXT 0 #define COMPILE_TEMPLATE_SSE2 1 #define COMPILE_TEMPLATE_SSSE3 1 #undef RENAME @@ -96,62 +69,6 @@ DECLARE_ALIGNED(16, static const uint16_t, inv_zigzag_direct16)[64] = { #endif /* HAVE_6REGS */ #if HAVE_INLINE_ASM -#if HAVE_MMX_INLINE -static void denoise_dct_mmx(MpegEncContext *s, int16_t *block){ - const int intra= s->mb_intra; - int *sum= s->dct_error_sum[intra]; - uint16_t *offset= s->dct_offset[intra]; - - s->dct_count[intra]++; - - __asm__ volatile( - "pxor %%mm7, %%mm7 \n\t" - "1: \n\t" - "pxor %%mm0, %%mm0 \n\t" - "pxor %%mm1, %%mm1 \n\t" - "movq (%0), %%mm2 \n\t" - "movq 8(%0), %%mm3 \n\t" - "pcmpgtw %%mm2, %%mm0 \n\t" - "pcmpgtw %%mm3, %%mm1 \n\t" - "pxor %%mm0, %%mm2 \n\t" - "pxor %%mm1, %%mm3 \n\t" - "psubw %%mm0, %%mm2 \n\t" - "psubw %%mm1, %%mm3 \n\t" - "movq %%mm2, %%mm4 \n\t" - "movq %%mm3, %%mm5 \n\t" - "psubusw (%2), %%mm2 \n\t" - "psubusw 8(%2), %%mm3 \n\t" - "pxor %%mm0, %%mm2 \n\t" - "pxor %%mm1, %%mm3 \n\t" - "psubw %%mm0, %%mm2 \n\t" - "psubw %%mm1, %%mm3 \n\t" - "movq %%mm2, (%0) \n\t" - "movq %%mm3, 8(%0) \n\t" - "movq %%mm4, %%mm2 \n\t" - "movq %%mm5, %%mm3 \n\t" - "punpcklwd %%mm7, %%mm4 \n\t" - "punpckhwd %%mm7, %%mm2 \n\t" - "punpcklwd %%mm7, %%mm5 \n\t" - "punpckhwd %%mm7, %%mm3 \n\t" - "paddd (%1), %%mm4 \n\t" - "paddd 8(%1), %%mm2 \n\t" - "paddd 16(%1), %%mm5 \n\t" - "paddd 24(%1), %%mm3 \n\t" - "movq %%mm4, (%1) \n\t" - "movq %%mm2, 8(%1) \n\t" - "movq %%mm5, 16(%1) \n\t" - "movq %%mm3, 24(%1) \n\t" - "add $16, %0 \n\t" - "add $32, %1 \n\t" - "add $16, %2 \n\t" - "cmp %3, %0 \n\t" - " jb 1b \n\t" - : "+r" (block), "+r" (sum), "+r" (offset) - : "r"(block+64) - ); -} -#endif /* HAVE_MMX_INLINE */ - #if HAVE_SSE2_INLINE static void denoise_dct_sse2(MpegEncContext *s, int16_t *block){ const int intra= s->mb_intra; @@ -218,17 +135,6 @@ av_cold void ff_dct_encode_init_x86(MpegEncContext *s) if (dct_algo == FF_DCT_AUTO || dct_algo == FF_DCT_MMX) { #if HAVE_MMX_INLINE int cpu_flags = av_get_cpu_flags(); - if (INLINE_MMX(cpu_flags)) { -#if HAVE_6REGS - s->dct_quantize = dct_quantize_mmx; -#endif - s->denoise_dct = denoise_dct_mmx; - } -#endif -#if HAVE_6REGS && HAVE_MMXEXT_INLINE - if (INLINE_MMXEXT(cpu_flags)) - s->dct_quantize = dct_quantize_mmxext; -#endif #if HAVE_SSE2_INLINE if (INLINE_SSE2(cpu_flags)) { #if HAVE_6REGS @@ -240,6 +146,7 @@ av_cold void ff_dct_encode_init_x86(MpegEncContext *s) #if HAVE_6REGS && HAVE_SSSE3_INLINE if (INLINE_SSSE3(cpu_flags)) s->dct_quantize = dct_quantize_ssse3; +#endif #endif } } diff --git a/libavcodec/x86/mpegvideoenc_template.c b/libavcodec/x86/mpegvideoenc_template.c index 30c06a6b2..b5b0a5ffa 100644 --- a/libavcodec/x86/mpegvideoenc_template.c +++ b/libavcodec/x86/mpegvideoenc_template.c @@ -57,15 +57,6 @@ #define MMREG_WIDTH "8" #define MM "%%mm" #define MOVQ "movq" -#if COMPILE_TEMPLATE_MMXEXT -#define SPREADW(a) "pshufw $0, "a", "a" \n\t" -#define PMAXW(a,b) "pmaxsw "a", "b" \n\t" -#define PMAX(a,b) \ - "pshufw $0x0E, "a", "b" \n\t"\ - PMAXW(b, a)\ - "pshufw $0x01, "a", "b" \n\t"\ - PMAXW(b, a) -#else #define SPREADW(a) \ "punpcklwd "a", "a" \n\t"\ "punpcklwd "a", "a" \n\t" @@ -81,7 +72,6 @@ PMAXW(b, a) #endif -#endif #if COMPILE_TEMPLATE_SSSE3 #define SAVE_SIGN(a,b) \ diff --git a/libavcodec/x86/mpegvideoencdsp.asm b/libavcodec/x86/mpegvideoencdsp.asm index aec73f82d..e3d88f01c 100644 --- a/libavcodec/x86/mpegvideoencdsp.asm +++ b/libavcodec/x86/mpegvideoencdsp.asm @@ -23,21 +23,15 @@ %include "libavutil/x86/x86util.asm" -SECTION_RODATA - -cextern pw_1 - SECTION .text -; int ff_pix_sum16_mmx(uint8_t *pix, int line_size) +; int ff_pix_sum16(uint8_t *pix, int line_size) ; %1 = number of loops ; %2 = number of GPRs used %macro PIX_SUM16 3 cglobal pix_sum16, 2, %2, 6 movsxdifnidn r1, r1d mov r2, %1 -%if mmsize == 16 lea r3, [r1*3] -%endif %if notcpuflag(xop) pxor m5, m5 %endif @@ -50,56 +44,27 @@ cglobal pix_sum16, 2, %2, 6 vphaddubq m3, [r0+r3] %else mova m0, [r0] -%if mmsize == 8 - mova m1, [r0+8] -%if cpuflag(mmxext) - mova m2, [r0+r1] - mova m3, [r0+r1+8] -%endif -%else ; sse2 mova m1, [r0+r1] mova m2, [r0+r1*2] mova m3, [r0+r3] -%endif -%if cpuflag(mmxext) psadbw m0, m5 psadbw m1, m5 psadbw m2, m5 psadbw m3, m5 -%else ; mmx - punpckhbw m2, m0, m5 - punpcklbw m0, m5 - punpckhbw m3, m1, m5 - punpcklbw m1, m5 -%endif ; cpuflag(mmxext) %endif ; cpuflag(xop) paddw m1, m0 paddw m3, m2 paddw m3, m1 paddw m4, m3 -%if cpuflag(mmxext) lea r0, [r0+r1*%3] -%else - add r0, r1 -%endif dec r2 jne .loop -%if mmsize == 16 pshufd m0, m4, q0032 paddd m4, m0 -%elif notcpuflag(mmxext) - HADDW m4, m5 -%endif movd eax, m4 RET %endmacro -%if ARCH_X86_32 -INIT_MMX mmx -PIX_SUM16 16, 3, 0 -INIT_MMX mmxext -PIX_SUM16 8, 4, 2 -%endif INIT_XMM sse2 PIX_SUM16 4, 4, 4 %if HAVE_XOP_EXTERNAL @@ -107,7 +72,7 @@ INIT_XMM xop PIX_SUM16 4, 4, 4 %endif -; int ff_pix_norm1_mmx(uint8_t *pix, int line_size) +; int ff_pix_norm1(uint8_t *pix, int line_size) ; %1 = number of xmm registers used ; %2 = number of loops %macro PIX_NORM1 2 @@ -118,11 +83,7 @@ cglobal pix_norm1, 2, 3, %1 pxor m5, m5 .loop: mova m2, [r0+0] -%if mmsize == 8 - mova m3, [r0+8] -%else mova m3, [r0+r1] -%endif punpckhbw m1, m2, m0 punpcklbw m2, m0 punpckhbw m4, m3, m0 @@ -135,11 +96,7 @@ cglobal pix_norm1, 2, 3, %1 paddd m4, m3 paddd m5, m2 paddd m5, m4 -%if mmsize == 8 - add r0, r1 -%else lea r0, [r0+r1*2] -%endif dec r2 jne .loop HADDD m5, m1 @@ -147,8 +104,6 @@ cglobal pix_norm1, 2, 3, %1 RET %endmacro -INIT_MMX mmx -PIX_NORM1 0, 16 INIT_XMM sse2 PIX_NORM1 6, 8 diff --git a/libavcodec/x86/mpegvideoencdsp_init.c b/libavcodec/x86/mpegvideoencdsp_init.c index 532836cec..b9c80b538 100644 --- a/libavcodec/x86/mpegvideoencdsp_init.c +++ b/libavcodec/x86/mpegvideoencdsp_init.c @@ -23,11 +23,8 @@ #include "libavcodec/avcodec.h" #include "libavcodec/mpegvideoencdsp.h" -int ff_pix_sum16_mmx(uint8_t *pix, int line_size); -int ff_pix_sum16_mmxext(uint8_t *pix, int line_size); int ff_pix_sum16_sse2(uint8_t *pix, int line_size); int ff_pix_sum16_xop(uint8_t *pix, int line_size); -int ff_pix_norm1_mmx(uint8_t *pix, int line_size); int ff_pix_norm1_sse2(uint8_t *pix, int line_size); #if HAVE_INLINE_ASM @@ -219,17 +216,6 @@ av_cold void ff_mpegvideoencdsp_init_x86(MpegvideoEncDSPContext *c, { int cpu_flags = av_get_cpu_flags(); -#if ARCH_X86_32 - if (EXTERNAL_MMX(cpu_flags)) { - c->pix_sum = ff_pix_sum16_mmx; - c->pix_norm1 = ff_pix_norm1_mmx; - } - - if (EXTERNAL_MMXEXT(cpu_flags)) { - c->pix_sum = ff_pix_sum16_mmxext; - } -#endif - if (EXTERNAL_SSE2(cpu_flags)) { c->pix_sum = ff_pix_sum16_sse2; c->pix_norm1 = ff_pix_norm1_sse2; diff --git a/libavcodec/x86/pixblockdsp.asm b/libavcodec/x86/pixblockdsp.asm index 440fe29bc..5fdd2914e 100644 --- a/libavcodec/x86/pixblockdsp.asm +++ b/libavcodec/x86/pixblockdsp.asm @@ -25,30 +25,6 @@ SECTION .text -INIT_MMX mmx -; void ff_get_pixels_mmx(int16_t *block, const uint8_t *pixels, ptrdiff_t stride) -cglobal get_pixels, 3,4 - add r0, 128 - mov r3, -128 - pxor m7, m7 -.loop: - mova m0, [r1] - mova m2, [r1+r2] - mova m1, m0 - mova m3, m2 - punpcklbw m0, m7 - punpckhbw m1, m7 - punpcklbw m2, m7 - punpckhbw m3, m7 - mova [r0+r3+ 0], m0 - mova [r0+r3+ 8], m1 - mova [r0+r3+16], m2 - mova [r0+r3+24], m3 - lea r1, [r1+r2*2] - add r3, 32 - js .loop - REP_RET - INIT_XMM sse2 cglobal get_pixels, 3, 4, 5 lea r3, [r2*3] @@ -80,9 +56,9 @@ cglobal get_pixels, 3, 4, 5 mova [r0+0x70], m3 RET -; void ff_diff_pixels_mmx(int16_t *block, const uint8_t *s1, const uint8_t *s2, -; ptrdiff_t stride); -%macro DIFF_PIXELS 0 +; void ff_diff_pixels(int16_t *block, const uint8_t *s1, const uint8_t *s2, +; ptrdiff_t stride); +INIT_XMM sse2 cglobal diff_pixels, 4,5,5 pxor m4, m4 add r0, 128 @@ -90,39 +66,18 @@ cglobal diff_pixels, 4,5,5 .loop: movq m0, [r1] movq m2, [r2] -%if mmsize == 8 - movq m1, m0 - movq m3, m2 - punpcklbw m0, m4 - punpckhbw m1, m4 - punpcklbw m2, m4 - punpckhbw m3, m4 -%else movq m1, [r1+r3] movq m3, [r2+r3] punpcklbw m0, m4 punpcklbw m1, m4 punpcklbw m2, m4 punpcklbw m3, m4 -%endif psubw m0, m2 psubw m1, m3 mova [r0+r4+0], m0 mova [r0+r4+mmsize], m1 -%if mmsize == 8 - add r1, r3 - add r2, r3 -%else lea r1, [r1+r3*2] lea r2, [r2+r3*2] -%endif add r4, 2 * mmsize jne .loop RET -%endmacro - -INIT_MMX mmx -DIFF_PIXELS - -INIT_XMM sse2 -DIFF_PIXELS diff --git a/libavcodec/x86/pixblockdsp_init.c b/libavcodec/x86/pixblockdsp_init.c index 3a5eb6959..51f2a0033 100644 --- a/libavcodec/x86/pixblockdsp_init.c +++ b/libavcodec/x86/pixblockdsp_init.c @@ -23,10 +23,7 @@ #include "libavutil/x86/cpu.h" #include "libavcodec/pixblockdsp.h" -void ff_get_pixels_mmx(int16_t *block, const uint8_t *pixels, ptrdiff_t stride); void ff_get_pixels_sse2(int16_t *block, const uint8_t *pixels, ptrdiff_t stride); -void ff_diff_pixels_mmx(int16_t *block, const uint8_t *s1, const uint8_t *s2, - ptrdiff_t stride); void ff_diff_pixels_sse2(int16_t *block, const uint8_t *s1, const uint8_t *s2, ptrdiff_t stride); @@ -36,15 +33,6 @@ av_cold void ff_pixblockdsp_init_x86(PixblockDSPContext *c, { int cpu_flags = av_get_cpu_flags(); - if (EXTERNAL_MMX(cpu_flags)) { - if (!high_bit_depth) { - c->get_pixels_unaligned = - c->get_pixels = ff_get_pixels_mmx; - } - c->diff_pixels_unaligned = - c->diff_pixels = ff_diff_pixels_mmx; - } - if (EXTERNAL_SSE2(cpu_flags)) { if (!high_bit_depth) { c->get_pixels_unaligned = diff --git a/libavcodec/x86/pngdsp_init.c b/libavcodec/x86/pngdsp_init.c index 7dca62c67..edbe866c2 100644 --- a/libavcodec/x86/pngdsp_init.c +++ b/libavcodec/x86/pngdsp_init.c @@ -19,8 +19,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include +#include "config.h" #include "libavutil/attributes.h" -#include "libavutil/common.h" #include "libavutil/x86/cpu.h" #include "libavcodec/pngdsp.h" diff --git a/libavcodec/x86/qpeldsp.asm b/libavcodec/x86/qpeldsp.asm index 282faed14..3a6a65065 100644 --- a/libavcodec/x86/qpeldsp.asm +++ b/libavcodec/x86/qpeldsp.asm @@ -166,8 +166,6 @@ cglobal put_no_rnd_pixels16_l2, 6,6 INIT_MMX mmxext PUT_NO_RND_PIXELS16_l2 -INIT_MMX 3dnow -PUT_NO_RND_PIXELS16_l2 %macro MPEG4_QPEL16_H_LOWPASS 1 cglobal %1_mpeg4_qpel16_h_lowpass, 5, 5, 0, 16 diff --git a/libavcodec/x86/rnd_template.c b/libavcodec/x86/rnd_template.c index 09946bd23..b825eeba6 100644 --- a/libavcodec/x86/rnd_template.c +++ b/libavcodec/x86/rnd_template.c @@ -97,6 +97,7 @@ av_unused STATIC void DEF(put, pixels8_xy2)(uint8_t *block, const uint8_t *pixel :FF_REG_a, "memory"); } +#ifndef NO_AVG // avg_pixels // this routine is 'slightly' suboptimal but mostly unused av_unused STATIC void DEF(avg, pixels8_xy2)(uint8_t *block, const uint8_t *pixels, @@ -173,3 +174,4 @@ av_unused STATIC void DEF(avg, pixels8_xy2)(uint8_t *block, const uint8_t *pixel :"D"(block), "r"((x86_reg)line_size) :FF_REG_a, "memory"); } +#endif diff --git a/libavcodec/x86/rv34dsp.asm b/libavcodec/x86/rv34dsp.asm index 692b4acfc..0a3d99c53 100644 --- a/libavcodec/x86/rv34dsp.asm +++ b/libavcodec/x86/rv34dsp.asm @@ -44,10 +44,10 @@ SECTION .text sar %1, 10 %endmacro -%macro rv34_idct 1 -cglobal rv34_idct_%1, 1, 2, 0 +INIT_MMX mmxext +cglobal rv34_idct_dc_noround, 1, 2, 0 movsx r1, word [r0] - IDCT_DC r1 + IDCT_DC_NOROUND r1 movd m0, r1d pshufw m0, m0, 0 movq [r0+ 0], m0 @@ -55,50 +55,6 @@ cglobal rv34_idct_%1, 1, 2, 0 movq [r0+16], m0 movq [r0+24], m0 REP_RET -%endmacro - -INIT_MMX mmxext -%define IDCT_DC IDCT_DC_ROUND -rv34_idct dc -%define IDCT_DC IDCT_DC_NOROUND -rv34_idct dc_noround - -; ff_rv34_idct_dc_add_mmx(uint8_t *dst, int stride, int dc); -%if ARCH_X86_32 -INIT_MMX mmx -cglobal rv34_idct_dc_add, 3, 3 - ; calculate DC - IDCT_DC_ROUND r2 - pxor m1, m1 - movd m0, r2d - psubw m1, m0 - packuswb m0, m0 - packuswb m1, m1 - punpcklbw m0, m0 - punpcklbw m1, m1 - punpcklwd m0, m0 - punpcklwd m1, m1 - - ; add DC - lea r2, [r0+r1*2] - movh m2, [r0] - movh m3, [r0+r1] - movh m4, [r2] - movh m5, [r2+r1] - paddusb m2, m0 - paddusb m3, m0 - paddusb m4, m0 - paddusb m5, m0 - psubusb m2, m1 - psubusb m3, m1 - psubusb m4, m1 - psubusb m5, m1 - movh [r0], m2 - movh [r0+r1], m3 - movh [r2], m4 - movh [r2+r1], m5 - RET -%endif ; Load coeffs and perform row transform ; Output: coeffs in mm[0467], rounder in mm5 diff --git a/libavcodec/x86/rv34dsp_init.c b/libavcodec/x86/rv34dsp_init.c index 731012245..caa5c2d65 100644 --- a/libavcodec/x86/rv34dsp_init.c +++ b/libavcodec/x86/rv34dsp_init.c @@ -26,7 +26,6 @@ void ff_rv34_idct_dc_mmxext(int16_t *block); void ff_rv34_idct_dc_noround_mmxext(int16_t *block); -void ff_rv34_idct_dc_add_mmx(uint8_t *dst, ptrdiff_t stride, int dc); void ff_rv34_idct_dc_add_sse2(uint8_t *dst, ptrdiff_t stride, int dc); void ff_rv34_idct_dc_add_sse4(uint8_t *dst, ptrdiff_t stride, int dc); void ff_rv34_idct_add_mmxext(uint8_t *dst, ptrdiff_t stride, int16_t *block); @@ -35,8 +34,6 @@ av_cold void ff_rv34dsp_init_x86(RV34DSPContext* c) { int cpu_flags = av_get_cpu_flags(); - if (ARCH_X86_32 && EXTERNAL_MMX(cpu_flags)) - c->rv34_idct_dc_add = ff_rv34_idct_dc_add_mmx; if (EXTERNAL_MMXEXT(cpu_flags)) { c->rv34_inv_transform_dc = ff_rv34_idct_dc_noround_mmxext; c->rv34_idct_add = ff_rv34_idct_add_mmxext; diff --git a/libavcodec/x86/rv40dsp.asm b/libavcodec/x86/rv40dsp.asm index bcad1aee8..f2ce236d4 100644 --- a/libavcodec/x86/rv40dsp.asm +++ b/libavcodec/x86/rv40dsp.asm @@ -230,20 +230,6 @@ cglobal %1_rv40_qpel_h, 6, 6+npicregs, 12, dst, dststride, src, srcstride, heigh REP_RET %endmacro -%if ARCH_X86_32 -INIT_MMX mmx -FILTER_V put -FILTER_H put - -INIT_MMX mmxext -FILTER_V avg -FILTER_H avg - -INIT_MMX 3dnow -FILTER_V avg -FILTER_H avg -%endif - INIT_XMM sse2 FILTER_H put FILTER_H avg @@ -481,12 +467,6 @@ cglobal rv40_weight_func_%1_%2, 6, 7, 8 REP_RET %endmacro -INIT_MMX mmxext -RV40_WEIGHT rnd, 8, 3 -RV40_WEIGHT rnd, 16, 4 -RV40_WEIGHT nornd, 8, 3 -RV40_WEIGHT nornd, 16, 4 - INIT_XMM sse2 RV40_WEIGHT rnd, 8, 3 RV40_WEIGHT rnd, 16, 4 diff --git a/libavcodec/x86/rv40dsp_init.c b/libavcodec/x86/rv40dsp_init.c index 7a05ab14a..a04c5a544 100644 --- a/libavcodec/x86/rv40dsp_init.c +++ b/libavcodec/x86/rv40dsp_init.c @@ -44,15 +44,11 @@ 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, ptrdiff_t stride, int h, int x, int y); -void ff_avg_rv40_chroma_mc8_3dnow(uint8_t *dst, uint8_t *src, - ptrdiff_t stride, int h, int x, int y); void ff_put_rv40_chroma_mc4_mmx (uint8_t *dst, uint8_t *src, ptrdiff_t stride, int h, int x, int y); void ff_avg_rv40_chroma_mc4_mmxext(uint8_t *dst, uint8_t *src, ptrdiff_t stride, int h, int x, int y); -void ff_avg_rv40_chroma_mc4_3dnow(uint8_t *dst, uint8_t *src, - ptrdiff_t stride, int h, int x, int y); #define DECLARE_WEIGHT(opt) \ void ff_rv40_weight_func_rnd_16_##opt(uint8_t *dst, uint8_t *src1, uint8_t *src2, \ @@ -63,7 +59,6 @@ void ff_rv40_weight_func_nornd_16_##opt(uint8_t *dst, uint8_t *src1, uint8_t *sr int w1, int w2, ptrdiff_t stride); \ void ff_rv40_weight_func_nornd_8_##opt (uint8_t *dst, uint8_t *src1, uint8_t *src2, \ int w1, int w2, ptrdiff_t stride); -DECLARE_WEIGHT(mmxext) DECLARE_WEIGHT(sse2) DECLARE_WEIGHT(ssse3) @@ -148,25 +143,6 @@ QPEL_MC_DECL(avg_, _ssse3) QPEL_MC_DECL(put_, _sse2) QPEL_MC_DECL(avg_, _sse2) -#if ARCH_X86_32 -#undef LOOPSIZE -#undef HCOFF -#undef VCOFF -#define LOOPSIZE 4 -#define HCOFF(x) (64 * ((x) - 1)) -#define VCOFF(x) (64 * ((x) - 1)) - -QPEL_MC_DECL(put_, _mmx) - -#define ff_put_rv40_qpel_h_mmxext ff_put_rv40_qpel_h_mmx -#define ff_put_rv40_qpel_v_mmxext ff_put_rv40_qpel_v_mmx -QPEL_MC_DECL(avg_, _mmxext) - -#define ff_put_rv40_qpel_h_3dnow ff_put_rv40_qpel_h_mmx -#define ff_put_rv40_qpel_v_3dnow ff_put_rv40_qpel_v_mmx -QPEL_MC_DECL(avg_, _3dnow) -#endif - /** @{ */ /** Set one function */ #define QPEL_FUNC_SET(OP, SIZE, PH, PV, OPT) \ @@ -207,9 +183,6 @@ DEFINE_FN(avg, 16, ssse3) #if HAVE_MMX_INLINE DEFINE_FN(put, 8, mmx) -DEFINE_FN(avg, 8, mmx) -DEFINE_FN(put, 16, mmx) -DEFINE_FN(avg, 16, mmx) #endif av_cold void ff_rv40dsp_init_x86(RV34DSPContext *c) @@ -218,10 +191,7 @@ av_cold void ff_rv40dsp_init_x86(RV34DSPContext *c) #if HAVE_MMX_INLINE if (INLINE_MMX(cpu_flags)) { - c->put_pixels_tab[0][15] = put_rv40_qpel16_mc33_mmx; c->put_pixels_tab[1][15] = put_rv40_qpel8_mc33_mmx; - c->avg_pixels_tab[0][15] = avg_rv40_qpel16_mc33_mmx; - c->avg_pixels_tab[1][15] = avg_rv40_qpel8_mc33_mmx; } #endif /* HAVE_MMX_INLINE */ @@ -229,28 +199,11 @@ av_cold void ff_rv40dsp_init_x86(RV34DSPContext *c) 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; -#if ARCH_X86_32 - QPEL_MC_SET(put_, _mmx) -#endif - } - if (EXTERNAL_AMD3DNOW(cpu_flags)) { - c->avg_chroma_pixels_tab[0] = ff_avg_rv40_chroma_mc8_3dnow; - c->avg_chroma_pixels_tab[1] = ff_avg_rv40_chroma_mc4_3dnow; -#if ARCH_X86_32 - QPEL_MC_SET(avg_, _3dnow) -#endif } if (EXTERNAL_MMXEXT(cpu_flags)) { c->avg_pixels_tab[1][15] = avg_rv40_qpel8_mc33_mmxext; c->avg_chroma_pixels_tab[0] = ff_avg_rv40_chroma_mc8_mmxext; c->avg_chroma_pixels_tab[1] = ff_avg_rv40_chroma_mc4_mmxext; - c->rv40_weight_pixels_tab[0][0] = ff_rv40_weight_func_rnd_16_mmxext; - c->rv40_weight_pixels_tab[0][1] = ff_rv40_weight_func_rnd_8_mmxext; - c->rv40_weight_pixels_tab[1][0] = ff_rv40_weight_func_nornd_16_mmxext; - c->rv40_weight_pixels_tab[1][1] = ff_rv40_weight_func_nornd_8_mmxext; -#if ARCH_X86_32 - QPEL_MC_SET(avg_, _mmxext) -#endif } if (EXTERNAL_SSE2(cpu_flags)) { c->put_pixels_tab[0][15] = put_rv40_qpel16_mc33_sse2; diff --git a/libavcodec/x86/sbrdsp.asm b/libavcodec/x86/sbrdsp.asm index 62bbe512e..87dcdc43c 100644 --- a/libavcodec/x86/sbrdsp.asm +++ b/libavcodec/x86/sbrdsp.asm @@ -251,7 +251,7 @@ cglobal sbr_neg_odd_64, 1,2,4,z REP_RET ; void ff_sbr_qmf_deint_bfly_sse2(float *v, const float *src0, const float *src1) -%macro SBR_QMF_DEINT_BFLY 0 +INIT_XMM sse2 cglobal sbr_qmf_deint_bfly, 3,5,8, v,src0,src1,vrev,c mov cq, 64*4-2*mmsize lea vrevq, [vq + 64*4] @@ -260,17 +260,10 @@ cglobal sbr_qmf_deint_bfly, 3,5,8, v,src0,src1,vrev,c mova m1, [src1q] mova m4, [src0q+cq+mmsize] mova m5, [src1q+mmsize] -%if cpuflag(sse2) pshufd m2, m0, q0123 pshufd m3, m1, q0123 pshufd m6, m4, q0123 pshufd m7, m5, q0123 -%else - shufps m2, m0, m0, q0123 - shufps m3, m1, m1, q0123 - shufps m6, m4, m4, q0123 - shufps m7, m5, m5, q0123 -%endif addps m5, m2 subps m0, m7 addps m1, m6 @@ -284,13 +277,6 @@ cglobal sbr_qmf_deint_bfly, 3,5,8, v,src0,src1,vrev,c sub cq, 2*mmsize jge .loop REP_RET -%endmacro - -INIT_XMM sse -SBR_QMF_DEINT_BFLY - -INIT_XMM sse2 -SBR_QMF_DEINT_BFLY INIT_XMM sse2 cglobal sbr_qmf_pre_shuffle, 1,4,6,z diff --git a/libavcodec/x86/sbrdsp_init.c b/libavcodec/x86/sbrdsp_init.c index 6911a1a51..999f68122 100644 --- a/libavcodec/x86/sbrdsp_init.c +++ b/libavcodec/x86/sbrdsp_init.c @@ -34,7 +34,6 @@ void ff_sbr_hf_gen_sse(float (*X_high)[2], const float (*X_low)[2], float bw, int start, int end); void ff_sbr_neg_odd_64_sse(float *z); void ff_sbr_qmf_post_shuffle_sse(float W[32][2], const float *z); -void ff_sbr_qmf_deint_bfly_sse(float *v, const float *src0, const float *src1); void ff_sbr_qmf_deint_bfly_sse2(float *v, const float *src0, const float *src1); void ff_sbr_qmf_pre_shuffle_sse2(float *z); @@ -67,7 +66,6 @@ av_cold void ff_sbrdsp_init_x86(SBRDSPContext *s) s->hf_g_filt = ff_sbr_hf_g_filt_sse; s->hf_gen = ff_sbr_hf_gen_sse; s->qmf_post_shuffle = ff_sbr_qmf_post_shuffle_sse; - s->qmf_deint_bfly = ff_sbr_qmf_deint_bfly_sse; s->qmf_deint_neg = ff_sbr_qmf_deint_neg_sse; s->autocorrelate = ff_sbr_autocorrelate_sse; } diff --git a/libavcodec/x86/simple_idct.asm b/libavcodec/x86/simple_idct.asm index 6fedbb578..dcf0da6df 100644 --- a/libavcodec/x86/simple_idct.asm +++ b/libavcodec/x86/simple_idct.asm @@ -25,6 +25,7 @@ %include "libavutil/x86/x86util.asm" +%if ARCH_X86_32 SECTION_RODATA cextern pb_80 @@ -846,26 +847,6 @@ cglobal simple_idct, 1, 2, 8, 128, block, t0 IDCT RET -cglobal simple_idct_put, 3, 5, 8, 128, pixels, lsize, block, lsize3, t0 - IDCT - lea lsize3q, [lsizeq*3] - PUT_PIXELS_CLAMPED_HALF 0 - lea pixelsq, [pixelsq+lsizeq*4] - PUT_PIXELS_CLAMPED_HALF 64 -RET - -cglobal simple_idct_add, 3, 4, 8, 128, pixels, lsize, block, t0 - IDCT - pxor m4, m4 - ADD_PIXELS_CLAMPED 0 - lea pixelsq, [pixelsq+lsizeq*2] - ADD_PIXELS_CLAMPED 32 - lea pixelsq, [pixelsq+lsizeq*2] - ADD_PIXELS_CLAMPED 64 - lea pixelsq, [pixelsq+lsizeq*2] - ADD_PIXELS_CLAMPED 96 -RET - INIT_XMM sse2 cglobal simple_idct_put, 3, 5, 8, 128, pixels, lsize, block, lsize3, t0 @@ -887,3 +868,4 @@ cglobal simple_idct_add, 3, 4, 8, 128, pixels, lsize, block, t0 lea pixelsq, [pixelsq+lsizeq*2] ADD_PIXELS_CLAMPED 96 RET +%endif diff --git a/libavcodec/x86/svq1enc.asm b/libavcodec/x86/svq1enc.asm index a87632836..123e86ba2 100644 --- a/libavcodec/x86/svq1enc.asm +++ b/libavcodec/x86/svq1enc.asm @@ -23,39 +23,19 @@ SECTION .text -%macro SSD_INT8_VS_INT16 0 +INIT_XMM sse2 cglobal ssd_int8_vs_int16, 3, 3, 3, pix1, pix2, size pxor m0, m0 .loop: sub sizeq, 8 movq m1, [pix1q + sizeq] mova m2, [pix2q + sizeq*2] -%if mmsize == 8 - movq m3, [pix2q + sizeq*2 + mmsize] - punpckhbw m4, m1 - punpcklbw m1, m1 - psraw m4, 8 - psraw m1, 8 - psubw m3, m4 - psubw m2, m1 - pmaddwd m3, m3 - pmaddwd m2, m2 - paddd m0, m3 - paddd m0, m2 -%else punpcklbw m1, m1 psraw m1, 8 psubw m2, m1 pmaddwd m2, m2 paddd m0, m2 -%endif jg .loop HADDD m0, m1 movd eax, m0 RET -%endmacro - -INIT_MMX mmx -SSD_INT8_VS_INT16 -INIT_XMM sse2 -SSD_INT8_VS_INT16 diff --git a/libavcodec/x86/svq1enc_init.c b/libavcodec/x86/svq1enc_init.c index 40b4b0e18..787a5245f 100644 --- a/libavcodec/x86/svq1enc_init.c +++ b/libavcodec/x86/svq1enc_init.c @@ -24,8 +24,6 @@ #include "libavutil/x86/cpu.h" #include "libavcodec/svq1enc.h" -int ff_ssd_int8_vs_int16_mmx(const int8_t *pix1, const int16_t *pix2, - intptr_t size); int ff_ssd_int8_vs_int16_sse2(const int8_t *pix1, const int16_t *pix2, intptr_t size); @@ -33,9 +31,6 @@ av_cold void ff_svq1enc_init_x86(SVQ1EncContext *c) { int cpu_flags = av_get_cpu_flags(); - if (EXTERNAL_MMX(cpu_flags)) { - c->ssd_int8_vs_int16 = ff_ssd_int8_vs_int16_mmx; - } if (EXTERNAL_SSE2(cpu_flags)) { c->ssd_int8_vs_int16 = ff_ssd_int8_vs_int16_sse2; } diff --git a/libavcodec/x86/synth_filter.asm b/libavcodec/x86/synth_filter.asm index bc1a48f40..22f57c330 100644 --- a/libavcodec/x86/synth_filter.asm +++ b/libavcodec/x86/synth_filter.asm @@ -115,7 +115,7 @@ cglobal synth_filter_inner, 0, 6 + 4 * ARCH_X86_64, 7 + 6 * ARCH_X86_64, \ synth_buf, synth_buf2, window, out, off, scale %define scale m0 %if ARCH_X86_32 || WIN64 -%if cpuflag(sse2) && notcpuflag(avx) +%if notcpuflag(avx) movd scale, scalem SPLATD m0 %else @@ -234,10 +234,6 @@ cglobal synth_filter_inner, 0, 6 + 4 * ARCH_X86_64, 7 + 6 * ARCH_X86_64, \ RET %endmacro -%if ARCH_X86_32 -INIT_XMM sse -SYNTH_FILTER -%endif INIT_XMM sse2 SYNTH_FILTER INIT_YMM avx diff --git a/libavcodec/x86/synth_filter_init.c b/libavcodec/x86/synth_filter_init.c index 35e2b47a3..7c76ac8d0 100644 --- a/libavcodec/x86/synth_filter_init.c +++ b/libavcodec/x86/synth_filter_init.c @@ -43,9 +43,6 @@ static void synth_filter_##opt(FFTContext *imdct, \ } \ #if HAVE_X86ASM -#if ARCH_X86_32 -SYNTH_FILTER_FUNC(sse) -#endif SYNTH_FILTER_FUNC(sse2) SYNTH_FILTER_FUNC(avx) SYNTH_FILTER_FUNC(fma3) @@ -56,11 +53,6 @@ av_cold void ff_synth_filter_init_x86(SynthFilterContext *s) #if HAVE_X86ASM int cpu_flags = av_get_cpu_flags(); -#if ARCH_X86_32 - if (EXTERNAL_SSE(cpu_flags)) { - s->synth_filter_float = synth_filter_sse; - } -#endif if (EXTERNAL_SSE2(cpu_flags)) { s->synth_filter_float = synth_filter_sse2; } diff --git a/libavcodec/x86/vc1dsp_init.c b/libavcodec/x86/vc1dsp_init.c index 8e0c284cc..b1f68b098 100644 --- a/libavcodec/x86/vc1dsp_init.c +++ b/libavcodec/x86/vc1dsp_init.c @@ -33,32 +33,34 @@ #include "vc1dsp.h" #include "config.h" -#define LOOP_FILTER(EXT) \ -void ff_vc1_v_loop_filter4_ ## EXT(uint8_t *src, int stride, int pq); \ -void ff_vc1_h_loop_filter4_ ## EXT(uint8_t *src, int stride, int pq); \ -void ff_vc1_v_loop_filter8_ ## EXT(uint8_t *src, int stride, int pq); \ -void ff_vc1_h_loop_filter8_ ## EXT(uint8_t *src, int stride, int pq); \ +#define LOOP_FILTER4(EXT) \ +void ff_vc1_v_loop_filter4_ ## EXT(uint8_t *src, ptrdiff_t stride, int pq); \ +void ff_vc1_h_loop_filter4_ ## EXT(uint8_t *src, ptrdiff_t stride, int pq); +#define LOOP_FILTER816(EXT) \ +void ff_vc1_v_loop_filter8_ ## EXT(uint8_t *src, ptrdiff_t stride, int pq); \ +void ff_vc1_h_loop_filter8_ ## EXT(uint8_t *src, ptrdiff_t stride, int pq); \ \ -static void vc1_v_loop_filter16_ ## EXT(uint8_t *src, int stride, int pq) \ +static void vc1_v_loop_filter16_ ## EXT(uint8_t *src, ptrdiff_t stride, int pq) \ { \ ff_vc1_v_loop_filter8_ ## EXT(src, stride, pq); \ ff_vc1_v_loop_filter8_ ## EXT(src+8, stride, pq); \ } \ \ -static void vc1_h_loop_filter16_ ## EXT(uint8_t *src, int stride, int pq) \ +static void vc1_h_loop_filter16_ ## EXT(uint8_t *src, ptrdiff_t stride, int pq) \ { \ ff_vc1_h_loop_filter8_ ## EXT(src, stride, pq); \ ff_vc1_h_loop_filter8_ ## EXT(src+8*stride, stride, pq); \ } #if HAVE_X86ASM -LOOP_FILTER(mmxext) -LOOP_FILTER(sse2) -LOOP_FILTER(ssse3) +LOOP_FILTER4(mmxext) +LOOP_FILTER816(sse2) +LOOP_FILTER4(ssse3) +LOOP_FILTER816(ssse3) -void ff_vc1_h_loop_filter8_sse4(uint8_t *src, int stride, int pq); +void ff_vc1_h_loop_filter8_sse4(uint8_t *src, ptrdiff_t stride, int pq); -static void vc1_h_loop_filter16_sse4(uint8_t *src, int stride, int pq) +static void vc1_h_loop_filter16_sse4(uint8_t *src, ptrdiff_t stride, int pq) { ff_vc1_h_loop_filter8_sse4(src, stride, pq); ff_vc1_h_loop_filter8_sse4(src+8*stride, stride, pq); @@ -72,11 +74,7 @@ static void vc1_h_loop_filter16_sse4(uint8_t *src, int stride, int pq) } DECLARE_FUNCTION(put_, 8, _mmx) -DECLARE_FUNCTION(put_, 16, _mmx) -DECLARE_FUNCTION(avg_, 8, _mmx) -DECLARE_FUNCTION(avg_, 16, _mmx) DECLARE_FUNCTION(avg_, 8, _mmxext) -DECLARE_FUNCTION(avg_, 16, _mmxext) DECLARE_FUNCTION(put_, 16, _sse2) DECLARE_FUNCTION(avg_, 16, _sse2) @@ -86,8 +84,6 @@ void ff_put_vc1_chroma_mc8_nornd_mmx (uint8_t *dst, uint8_t *src, ptrdiff_t stride, int h, int x, int y); void ff_avg_vc1_chroma_mc8_nornd_mmxext(uint8_t *dst, uint8_t *src, ptrdiff_t stride, int h, int x, int y); -void ff_avg_vc1_chroma_mc8_nornd_3dnow(uint8_t *dst, uint8_t *src, - ptrdiff_t stride, int h, int x, int y); void ff_put_vc1_chroma_mc8_nornd_ssse3(uint8_t *dst, uint8_t *src, ptrdiff_t stride, int h, int x, int y); void ff_avg_vc1_chroma_mc8_nornd_ssse3(uint8_t *dst, uint8_t *src, @@ -114,9 +110,10 @@ av_cold void ff_vc1dsp_init_x86(VC1DSPContext *dsp) if (EXTERNAL_MMXEXT(cpu_flags)) ff_vc1dsp_init_mmxext(dsp); -#define ASSIGN_LF(EXT) \ +#define ASSIGN_LF4(EXT) \ dsp->vc1_v_loop_filter4 = ff_vc1_v_loop_filter4_ ## EXT; \ - dsp->vc1_h_loop_filter4 = ff_vc1_h_loop_filter4_ ## EXT; \ + dsp->vc1_h_loop_filter4 = ff_vc1_h_loop_filter4_ ## EXT +#define ASSIGN_LF816(EXT) \ dsp->vc1_v_loop_filter8 = ff_vc1_v_loop_filter8_ ## EXT; \ dsp->vc1_h_loop_filter8 = ff_vc1_h_loop_filter8_ ## EXT; \ dsp->vc1_v_loop_filter16 = vc1_v_loop_filter16_ ## EXT; \ @@ -127,19 +124,12 @@ av_cold void ff_vc1dsp_init_x86(VC1DSPContext *dsp) dsp->put_no_rnd_vc1_chroma_pixels_tab[0] = ff_put_vc1_chroma_mc8_nornd_mmx; dsp->put_vc1_mspel_pixels_tab[1][0] = put_vc1_mspel_mc00_8_mmx; - dsp->put_vc1_mspel_pixels_tab[0][0] = put_vc1_mspel_mc00_16_mmx; - dsp->avg_vc1_mspel_pixels_tab[1][0] = avg_vc1_mspel_mc00_8_mmx; - dsp->avg_vc1_mspel_pixels_tab[0][0] = avg_vc1_mspel_mc00_16_mmx; - } - if (EXTERNAL_AMD3DNOW(cpu_flags)) { - dsp->avg_no_rnd_vc1_chroma_pixels_tab[0] = ff_avg_vc1_chroma_mc8_nornd_3dnow; } if (EXTERNAL_MMXEXT(cpu_flags)) { - ASSIGN_LF(mmxext); + ASSIGN_LF4(mmxext); dsp->avg_no_rnd_vc1_chroma_pixels_tab[0] = ff_avg_vc1_chroma_mc8_nornd_mmxext; dsp->avg_vc1_mspel_pixels_tab[1][0] = avg_vc1_mspel_mc00_8_mmxext; - dsp->avg_vc1_mspel_pixels_tab[0][0] = avg_vc1_mspel_mc00_16_mmxext; dsp->vc1_inv_trans_8x8_dc = ff_vc1_inv_trans_8x8_dc_mmxext; dsp->vc1_inv_trans_4x8_dc = ff_vc1_inv_trans_4x8_dc_mmxext; @@ -147,16 +137,14 @@ av_cold void ff_vc1dsp_init_x86(VC1DSPContext *dsp) dsp->vc1_inv_trans_4x4_dc = ff_vc1_inv_trans_4x4_dc_mmxext; } if (EXTERNAL_SSE2(cpu_flags)) { - dsp->vc1_v_loop_filter8 = ff_vc1_v_loop_filter8_sse2; - dsp->vc1_h_loop_filter8 = ff_vc1_h_loop_filter8_sse2; - dsp->vc1_v_loop_filter16 = vc1_v_loop_filter16_sse2; - dsp->vc1_h_loop_filter16 = vc1_h_loop_filter16_sse2; + ASSIGN_LF816(sse2); dsp->put_vc1_mspel_pixels_tab[0][0] = put_vc1_mspel_mc00_16_sse2; dsp->avg_vc1_mspel_pixels_tab[0][0] = avg_vc1_mspel_mc00_16_sse2; } if (EXTERNAL_SSSE3(cpu_flags)) { - ASSIGN_LF(ssse3); + ASSIGN_LF4(ssse3); + ASSIGN_LF816(ssse3); dsp->put_no_rnd_vc1_chroma_pixels_tab[0] = ff_put_vc1_chroma_mc8_nornd_ssse3; dsp->avg_no_rnd_vc1_chroma_pixels_tab[0] = ff_avg_vc1_chroma_mc8_nornd_ssse3; } diff --git a/libavcodec/x86/vc1dsp_loopfilter.asm b/libavcodec/x86/vc1dsp_loopfilter.asm index fd33bd13d..49f67255c 100644 --- a/libavcodec/x86/vc1dsp_loopfilter.asm +++ b/libavcodec/x86/vc1dsp_loopfilter.asm @@ -228,89 +228,61 @@ SECTION .text imul r2, 0x01010101 %endmacro -%macro VC1_LF 0 -cglobal vc1_v_loop_filter_internal - VC1_V_LOOP_FILTER 4, d - ret - -cglobal vc1_h_loop_filter_internal - VC1_H_LOOP_FILTER 4, r4 - ret - -; void ff_vc1_v_loop_filter4_mmxext(uint8_t *src, int stride, int pq) +; void ff_vc1_v_loop_filter4_mmxext(uint8_t *src, ptrdiff_t stride, int pq) +INIT_MMX mmxext cglobal vc1_v_loop_filter4, 3,5,0 START_V_FILTER - call vc1_v_loop_filter_internal + VC1_V_LOOP_FILTER 4, d RET -; void ff_vc1_h_loop_filter4_mmxext(uint8_t *src, int stride, int pq) +; void ff_vc1_h_loop_filter4_mmxext(uint8_t *src, ptrdiff_t stride, int pq) +INIT_MMX mmxext cglobal vc1_h_loop_filter4, 3,5,0 START_H_FILTER 4 - call vc1_h_loop_filter_internal + VC1_H_LOOP_FILTER 4, r4 RET -; void ff_vc1_v_loop_filter8_mmxext(uint8_t *src, int stride, int pq) -cglobal vc1_v_loop_filter8, 3,5,0 - START_V_FILTER - call vc1_v_loop_filter_internal - add r4, 4 - add r0, 4 - call vc1_v_loop_filter_internal - RET - -; void ff_vc1_h_loop_filter8_mmxext(uint8_t *src, int stride, int pq) -cglobal vc1_h_loop_filter8, 3,5,0 - START_H_FILTER 4 - call vc1_h_loop_filter_internal - lea r0, [r0+4*r1] - call vc1_h_loop_filter_internal - RET -%endmacro - -INIT_MMX mmxext -VC1_LF - INIT_XMM sse2 -; void ff_vc1_v_loop_filter8_sse2(uint8_t *src, int stride, int pq) +; void ff_vc1_v_loop_filter8_sse2(uint8_t *src, ptrdiff_t stride, int pq) cglobal vc1_v_loop_filter8, 3,5,8 START_V_FILTER VC1_V_LOOP_FILTER 8, q RET -; void ff_vc1_h_loop_filter8_sse2(uint8_t *src, int stride, int pq) +; void ff_vc1_h_loop_filter8_sse2(uint8_t *src, ptrdiff_t stride, int pq) cglobal vc1_h_loop_filter8, 3,6,8 START_H_FILTER 8 VC1_H_LOOP_FILTER 8, r5 RET INIT_MMX ssse3 -; void ff_vc1_v_loop_filter4_ssse3(uint8_t *src, int stride, int pq) +; void ff_vc1_v_loop_filter4_ssse3(uint8_t *src, ptrdiff_t stride, int pq) cglobal vc1_v_loop_filter4, 3,5,0 START_V_FILTER VC1_V_LOOP_FILTER 4, d RET -; void ff_vc1_h_loop_filter4_ssse3(uint8_t *src, int stride, int pq) +; void ff_vc1_h_loop_filter4_ssse3(uint8_t *src, ptrdiff_t stride, int pq) cglobal vc1_h_loop_filter4, 3,5,0 START_H_FILTER 4 VC1_H_LOOP_FILTER 4, r4 RET INIT_XMM ssse3 -; void ff_vc1_v_loop_filter8_ssse3(uint8_t *src, int stride, int pq) +; void ff_vc1_v_loop_filter8_ssse3(uint8_t *src, ptrdiff_t stride, int pq) cglobal vc1_v_loop_filter8, 3,5,8 START_V_FILTER VC1_V_LOOP_FILTER 8, q RET -; void ff_vc1_h_loop_filter8_ssse3(uint8_t *src, int stride, int pq) +; void ff_vc1_h_loop_filter8_ssse3(uint8_t *src, ptrdiff_t stride, int pq) cglobal vc1_h_loop_filter8, 3,6,8 START_H_FILTER 8 VC1_H_LOOP_FILTER 8, r5 RET INIT_XMM sse4 -; void ff_vc1_h_loop_filter8_sse4(uint8_t *src, int stride, int pq) +; void ff_vc1_h_loop_filter8_sse4(uint8_t *src, ptrdiff_t stride, int pq) cglobal vc1_h_loop_filter8, 3,5,8 START_H_FILTER 8 VC1_H_LOOP_FILTER 8 diff --git a/libavcodec/x86/videodsp.asm b/libavcodec/x86/videodsp.asm index e23786070..b19a8300c 100644 --- a/libavcodec/x86/videodsp.asm +++ b/libavcodec/x86/videodsp.asm @@ -45,7 +45,6 @@ SECTION .text jnz .%1_y_loop %endmacro -%macro vvar_fn 0 ; .----. <- zero ; | | <- top is copied from first line in body of source ; |----| <- start_y @@ -53,6 +52,7 @@ SECTION .text ; |----| <- end_y ; | | <- bottom is copied from last line in body of source ; '----' <- bh +INIT_XMM sse %if ARCH_X86_64 cglobal emu_edge_vvar, 7, 8, 1, dst, dst_stride, src, src_stride, \ start_y, end_y, bh, w @@ -81,15 +81,6 @@ cglobal emu_edge_vvar, 1, 6, 1, dst, src, start_y, end_y, bh, w V_COPY_ROW bottom, bhq ; v_copy_row(bottom, bh) .end: ; } RET -%endmacro - -%if ARCH_X86_32 -INIT_MMX mmx -vvar_fn -%endif - -INIT_XMM sse -vvar_fn %macro hvar_fn 0 cglobal emu_edge_hvar, 5, 6, 1, dst, dst_stride, start_x, n_words, h, w @@ -105,11 +96,7 @@ cglobal emu_edge_hvar, 5, 6, 1, dst, dst_stride, start_x, n_words, h, w imul wd, 0x01010101 ; w *= 0x01010101 movd m0, wd mov wq, n_wordsq ; initialize w -%if cpuflag(sse2) pshufd m0, m0, q0000 ; splat -%else ; mmx - punpckldq m0, m0 ; splat -%endif ; mmx/sse %endif ; avx2 .x_loop: ; do { movu [dstq+wq*2], m0 ; write($reg, $mmsize) @@ -123,11 +110,6 @@ cglobal emu_edge_hvar, 5, 6, 1, dst, dst_stride, start_x, n_words, h, w RET %endmacro -%if ARCH_X86_32 -INIT_MMX mmx -hvar_fn -%endif - INIT_XMM sse2 hvar_fn @@ -338,9 +320,6 @@ cglobal emu_edge_vfix %+ %%n, 1, 5, 1, dst, src, start_y, end_y, bh INIT_MMX mmx VERTICAL_EXTEND 1, 15 -%if ARCH_X86_32 -VERTICAL_EXTEND 16, 22 -%endif INIT_XMM sse VERTICAL_EXTEND 16, 22 @@ -438,9 +417,6 @@ cglobal emu_edge_hfix %+ %%n, 4, 5, 1, dst, dst_stride, start_x, bh, val INIT_MMX mmx H_EXTEND 2, 14 -%if ARCH_X86_32 -H_EXTEND 16, 22 -%endif INIT_XMM sse2 H_EXTEND 16, 22 @@ -450,19 +426,11 @@ INIT_XMM avx2 H_EXTEND 8, 22 %endif -%macro PREFETCH_FN 1 +INIT_MMX mmxext cglobal prefetch, 3, 3, 0, buf, stride, h .loop: - %1 [bufq] + prefetcht0 [bufq] add bufq, strideq dec hd jg .loop REP_RET -%endmacro - -INIT_MMX mmxext -PREFETCH_FN prefetcht0 -%if ARCH_X86_32 -INIT_MMX 3dnow -PREFETCH_FN prefetch -%endif diff --git a/libavcodec/x86/videodsp_init.c b/libavcodec/x86/videodsp_init.c index 961424aa1..a14c9635f 100644 --- a/libavcodec/x86/videodsp_init.c +++ b/libavcodec/x86/videodsp_init.c @@ -52,26 +52,6 @@ extern emu_edge_vfix_func ff_emu_edge_vfix12_mmx; extern emu_edge_vfix_func ff_emu_edge_vfix13_mmx; extern emu_edge_vfix_func ff_emu_edge_vfix14_mmx; extern emu_edge_vfix_func ff_emu_edge_vfix15_mmx; -extern emu_edge_vfix_func ff_emu_edge_vfix16_mmx; -extern emu_edge_vfix_func ff_emu_edge_vfix17_mmx; -extern emu_edge_vfix_func ff_emu_edge_vfix18_mmx; -extern emu_edge_vfix_func ff_emu_edge_vfix19_mmx; -extern emu_edge_vfix_func ff_emu_edge_vfix20_mmx; -extern emu_edge_vfix_func ff_emu_edge_vfix21_mmx; -extern emu_edge_vfix_func ff_emu_edge_vfix22_mmx; -#if ARCH_X86_32 -static emu_edge_vfix_func * const vfixtbl_mmx[22] = { - &ff_emu_edge_vfix1_mmx, &ff_emu_edge_vfix2_mmx, &ff_emu_edge_vfix3_mmx, - &ff_emu_edge_vfix4_mmx, &ff_emu_edge_vfix5_mmx, &ff_emu_edge_vfix6_mmx, - &ff_emu_edge_vfix7_mmx, &ff_emu_edge_vfix8_mmx, &ff_emu_edge_vfix9_mmx, - &ff_emu_edge_vfix10_mmx, &ff_emu_edge_vfix11_mmx, &ff_emu_edge_vfix12_mmx, - &ff_emu_edge_vfix13_mmx, &ff_emu_edge_vfix14_mmx, &ff_emu_edge_vfix15_mmx, - &ff_emu_edge_vfix16_mmx, &ff_emu_edge_vfix17_mmx, &ff_emu_edge_vfix18_mmx, - &ff_emu_edge_vfix19_mmx, &ff_emu_edge_vfix20_mmx, &ff_emu_edge_vfix21_mmx, - &ff_emu_edge_vfix22_mmx -}; -#endif -extern emu_edge_vvar_func ff_emu_edge_vvar_mmx; extern emu_edge_vfix_func ff_emu_edge_vfix16_sse; extern emu_edge_vfix_func ff_emu_edge_vfix17_sse; extern emu_edge_vfix_func ff_emu_edge_vfix18_sse; @@ -103,19 +83,6 @@ extern emu_edge_hfix_func ff_emu_edge_hfix8_mmx; extern emu_edge_hfix_func ff_emu_edge_hfix10_mmx; extern emu_edge_hfix_func ff_emu_edge_hfix12_mmx; extern emu_edge_hfix_func ff_emu_edge_hfix14_mmx; -extern emu_edge_hfix_func ff_emu_edge_hfix16_mmx; -extern emu_edge_hfix_func ff_emu_edge_hfix18_mmx; -extern emu_edge_hfix_func ff_emu_edge_hfix20_mmx; -extern emu_edge_hfix_func ff_emu_edge_hfix22_mmx; -#if ARCH_X86_32 -static emu_edge_hfix_func * const hfixtbl_mmx[11] = { - ff_emu_edge_hfix2_mmx, ff_emu_edge_hfix4_mmx, ff_emu_edge_hfix6_mmx, - ff_emu_edge_hfix8_mmx, ff_emu_edge_hfix10_mmx, ff_emu_edge_hfix12_mmx, - ff_emu_edge_hfix14_mmx, ff_emu_edge_hfix16_mmx, ff_emu_edge_hfix18_mmx, - ff_emu_edge_hfix20_mmx, ff_emu_edge_hfix22_mmx -}; -#endif -extern emu_edge_hvar_func ff_emu_edge_hvar_mmx; extern emu_edge_hfix_func ff_emu_edge_hfix16_sse2; extern emu_edge_hfix_func ff_emu_edge_hfix18_sse2; extern emu_edge_hfix_func ff_emu_edge_hfix20_sse2; @@ -221,30 +188,6 @@ static av_always_inline void emulated_edge_mc(uint8_t *dst, const uint8_t *src, } } -#if ARCH_X86_32 -static av_noinline void emulated_edge_mc_mmx(uint8_t *buf, const uint8_t *src, - ptrdiff_t buf_stride, - ptrdiff_t src_stride, - int block_w, int block_h, - int src_x, int src_y, int w, int h) -{ - emulated_edge_mc(buf, src, buf_stride, src_stride, block_w, block_h, - src_x, src_y, w, h, vfixtbl_mmx, &ff_emu_edge_vvar_mmx, - hfixtbl_mmx, &ff_emu_edge_hvar_mmx); -} - -static av_noinline void emulated_edge_mc_sse(uint8_t *buf, const uint8_t *src, - ptrdiff_t buf_stride, - ptrdiff_t src_stride, - int block_w, int block_h, - int src_x, int src_y, int w, int h) -{ - emulated_edge_mc(buf, src, buf_stride, src_stride, block_w, block_h, - src_x, src_y, w, h, vfixtbl_sse, &ff_emu_edge_vvar_sse, - hfixtbl_mmx, &ff_emu_edge_hvar_mmx); -} -#endif - static av_noinline void emulated_edge_mc_sse2(uint8_t *buf, const uint8_t *src, ptrdiff_t buf_stride, ptrdiff_t src_stride, @@ -273,29 +216,15 @@ static av_noinline void emulated_edge_mc_avx2(uint8_t *buf, const uint8_t *src, #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_X86ASM int cpu_flags = av_get_cpu_flags(); -#if ARCH_X86_32 - if (EXTERNAL_MMX(cpu_flags) && bpc <= 8) { - ctx->emulated_edge_mc = emulated_edge_mc_mmx; - } - if (EXTERNAL_AMD3DNOW(cpu_flags)) { - ctx->prefetch = ff_prefetch_3dnow; - } -#endif /* ARCH_X86_32 */ if (EXTERNAL_MMXEXT(cpu_flags)) { ctx->prefetch = ff_prefetch_mmxext; } -#if ARCH_X86_32 - if (EXTERNAL_SSE(cpu_flags) && bpc <= 8) { - ctx->emulated_edge_mc = emulated_edge_mc_sse; - } -#endif /* ARCH_X86_32 */ if (EXTERNAL_SSE2(cpu_flags) && bpc <= 8) { ctx->emulated_edge_mc = emulated_edge_mc_sse2; } diff --git a/libavcodec/x86/vorbisdsp.asm b/libavcodec/x86/vorbisdsp.asm index d95229671..9afe2eb35 100644 --- a/libavcodec/x86/vorbisdsp.asm +++ b/libavcodec/x86/vorbisdsp.asm @@ -27,35 +27,6 @@ pdw_80000000: times 4 dd 0x80000000 SECTION .text -%if ARCH_X86_32 -INIT_MMX 3dnow -cglobal vorbis_inverse_coupling, 3, 3, 6, mag, ang, block_size - pxor m7, m7 - lea magq, [magq+block_sizeq*4] - lea angq, [angq+block_sizeq*4] - neg block_sizeq -.loop: - mova m0, [magq+block_sizeq*4] - mova m1, [angq+block_sizeq*4] - mova m2, m0 - mova m3, m1 - pfcmpge m2, m7 ; m <= 0.0 - pfcmpge m3, m7 ; a <= 0.0 - pslld m2, 31 ; keep only the sign bit - pxor m1, m2 - mova m4, m3 - pand m3, m1 - pandn m4, m1 - pfadd m3, m0 ; a = m + ((a < 0) & (a ^ sign(m))) - pfsub m0, m4 ; m = m + ((a > 0) & (a ^ sign(m))) - mova [angq+block_sizeq*4], m3 - mova [magq+block_sizeq*4], m0 - add block_sizeq, 2 - jl .loop - femms - RET -%endif - INIT_XMM sse cglobal vorbis_inverse_coupling, 3, 3, 6, mag, ang, block_size mova m5, [pdw_80000000] diff --git a/libavcodec/x86/vorbisdsp_init.c b/libavcodec/x86/vorbisdsp_init.c index bc1cc43a1..da9f9e685 100644 --- a/libavcodec/x86/vorbisdsp_init.c +++ b/libavcodec/x86/vorbisdsp_init.c @@ -24,8 +24,6 @@ #include "libavutil/x86/cpu.h" #include "libavcodec/vorbisdsp.h" -void ff_vorbis_inverse_coupling_3dnow(float *mag, float *ang, - intptr_t blocksize); void ff_vorbis_inverse_coupling_sse(float *mag, float *ang, intptr_t blocksize); @@ -33,10 +31,6 @@ av_cold void ff_vorbisdsp_init_x86(VorbisDSPContext *dsp) { int cpu_flags = av_get_cpu_flags(); -#if ARCH_X86_32 - if (EXTERNAL_AMD3DNOW(cpu_flags)) - dsp->vorbis_inverse_coupling = ff_vorbis_inverse_coupling_3dnow; -#endif /* ARCH_X86_32 */ if (EXTERNAL_SSE(cpu_flags)) dsp->vorbis_inverse_coupling = ff_vorbis_inverse_coupling_sse; } diff --git a/libavcodec/x86/vp3dsp.asm b/libavcodec/x86/vp3dsp.asm index d88d5a1ed..005ecbc9a 100644 --- a/libavcodec/x86/vp3dsp.asm +++ b/libavcodec/x86/vp3dsp.asm @@ -571,40 +571,25 @@ cglobal vp3_idct_put, 3, 4, 9 mova m1, [r2+mmsize*2+%%i] mova m2, [r2+mmsize*4+%%i] mova m3, [r2+mmsize*6+%%i] -%if mmsize == 8 - packsswb m0, [r2+mmsize*8+%%i] - packsswb m1, [r2+mmsize*10+%%i] - packsswb m2, [r2+mmsize*12+%%i] - packsswb m3, [r2+mmsize*14+%%i] -%else packsswb m0, [r2+mmsize*1+%%i] packsswb m1, [r2+mmsize*3+%%i] packsswb m2, [r2+mmsize*5+%%i] packsswb m3, [r2+mmsize*7+%%i] -%endif paddb m0, m4 paddb m1, m4 paddb m2, m4 paddb m3, m4 movq [r0 ], m0 -%if mmsize == 8 - movq [r0+r1 ], m1 - movq [r0+r1*2], m2 - movq [r0+r3 ], m3 -%else movhps [r0+r1 ], m0 movq [r0+r1*2], m1 movhps [r0+r3 ], m1 -%endif %if %%i == 0 lea r0, [r0+r1*4] %endif -%if mmsize == 16 movq [r0 ], m2 movhps [r0+r1 ], m2 movq [r0+r1*2], m3 movhps [r0+r3 ], m3 -%endif %assign %%i %%i+8 %endrep @@ -621,7 +606,6 @@ cglobal vp3_idct_add, 3, 4, 9 lea r3, [r1*3] pxor m4, m4 -%if mmsize == 16 %assign %%i 0 %rep 2 movq m0, [r0] @@ -647,47 +631,6 @@ cglobal vp3_idct_add, 3, 4, 9 %endif %assign %%i %%i+64 %endrep -%else -%assign %%i 0 -%rep 2 - movq m0, [r0] - movq m1, [r0+r1] - movq m2, [r0+r1*2] - movq m3, [r0+r3] - movq m5, m0 - movq m6, m1 - movq m7, m2 - punpcklbw m0, m4 - punpcklbw m1, m4 - punpcklbw m2, m4 - punpckhbw m5, m4 - punpckhbw m6, m4 - punpckhbw m7, m4 - paddsw m0, [r2+ 0+%%i] - paddsw m1, [r2+16+%%i] - paddsw m2, [r2+32+%%i] - paddsw m5, [r2+64+%%i] - paddsw m6, [r2+80+%%i] - paddsw m7, [r2+96+%%i] - packuswb m0, m5 - movq m5, m3 - punpcklbw m3, m4 - punpckhbw m5, m4 - packuswb m1, m6 - paddsw m3, [r2+48+%%i] - paddsw m5, [r2+112+%%i] - packuswb m2, m7 - packuswb m3, m5 - movq [r0 ], m0 - movq [r0+r1 ], m1 - movq [r0+r1*2], m2 - movq [r0+r3 ], m3 -%if %%i == 0 - lea r0, [r0+r1*4] -%endif -%assign %%i %%i+8 -%endrep -%endif %assign %%i 0 %rep 128/mmsize mova [r2+%%i], m4 @@ -696,11 +639,6 @@ cglobal vp3_idct_add, 3, 4, 9 RET %endmacro -%if ARCH_X86_32 -INIT_MMX mmx -vp3_idct_funcs -%endif - INIT_XMM sse2 vp3_idct_funcs diff --git a/libavcodec/x86/vp3dsp_init.c b/libavcodec/x86/vp3dsp_init.c index ba47e1c6c..f54fa57b3 100644 --- a/libavcodec/x86/vp3dsp_init.c +++ b/libavcodec/x86/vp3dsp_init.c @@ -26,9 +26,6 @@ #include "libavcodec/avcodec.h" #include "libavcodec/vp3dsp.h" -void ff_vp3_idct_put_mmx(uint8_t *dest, ptrdiff_t stride, int16_t *block); -void ff_vp3_idct_add_mmx(uint8_t *dest, ptrdiff_t stride, int16_t *block); - void ff_vp3_idct_put_sse2(uint8_t *dest, ptrdiff_t stride, int16_t *block); void ff_vp3_idct_add_sse2(uint8_t *dest, ptrdiff_t stride, int16_t *block); @@ -49,10 +46,6 @@ av_cold void ff_vp3dsp_init_x86(VP3DSPContext *c, int flags) if (EXTERNAL_MMX(cpu_flags)) { c->put_no_rnd_pixels_l2 = ff_put_vp_no_rnd_pixels8_l2_mmx; -#if ARCH_X86_32 - c->idct_put = ff_vp3_idct_put_mmx; - c->idct_add = ff_vp3_idct_add_mmx; -#endif } if (EXTERNAL_MMXEXT(cpu_flags)) { diff --git a/libavcodec/x86/vp6dsp.asm b/libavcodec/x86/vp6dsp.asm index 0be531e5c..512fe89de 100644 --- a/libavcodec/x86/vp6dsp.asm +++ b/libavcodec/x86/vp6dsp.asm @@ -114,18 +114,13 @@ SECTION .text %endif ; mmsize == 8/16 %endmacro -%macro vp6_filter_diag4 0 ; void ff_vp6_filter_diag4_(uint8_t *dst, uint8_t *src, ptrdiff_t stride, ; const int16_t h_weight[4], const int16_t v_weights[4]) +INIT_XMM sse2 cglobal vp6_filter_diag4, 5, 7, 8 mov r5, rsp ; backup stack pointer and rsp, ~(mmsize-1) ; align stack -%if mmsize == 16 sub rsp, 8*11 -%else - sub rsp, 8*15 - movq m6, [pw_64] -%endif sub r1, r2 @@ -156,12 +151,3 @@ cglobal vp6_filter_diag4, 5, 7, 8 mov rsp, r5 ; restore stack pointer RET -%endmacro - -%if ARCH_X86_32 -INIT_MMX mmx -vp6_filter_diag4 -%endif - -INIT_XMM sse2 -vp6_filter_diag4 diff --git a/libavcodec/x86/vp6dsp_init.c b/libavcodec/x86/vp6dsp_init.c index ce498931d..83d45ec36 100644 --- a/libavcodec/x86/vp6dsp_init.c +++ b/libavcodec/x86/vp6dsp_init.c @@ -25,8 +25,6 @@ #include "libavutil/x86/cpu.h" #include "libavcodec/vp56dsp.h" -void ff_vp6_filter_diag4_mmx(uint8_t *dst, uint8_t *src, ptrdiff_t stride, - const int16_t *h_weights,const int16_t *v_weights); void ff_vp6_filter_diag4_sse2(uint8_t *dst, uint8_t *src, ptrdiff_t stride, const int16_t *h_weights,const int16_t *v_weights); @@ -34,11 +32,6 @@ av_cold void ff_vp6dsp_init_x86(VP56DSPContext *c) { int cpu_flags = av_get_cpu_flags(); -#if ARCH_X86_32 - if (EXTERNAL_MMX(cpu_flags)) { - c->vp6_filter_diag4 = ff_vp6_filter_diag4_mmx; - } -#endif if (EXTERNAL_SSE2(cpu_flags)) { c->vp6_filter_diag4 = ff_vp6_filter_diag4_sse2; } diff --git a/libavcodec/x86/vp8dsp.asm b/libavcodec/x86/vp8dsp.asm index 75de5690a..1c59e884e 100644 --- a/libavcodec/x86/vp8dsp.asm +++ b/libavcodec/x86/vp8dsp.asm @@ -840,25 +840,6 @@ cglobal put_vp8_pixels8, 5, 5, 0, dst, dststride, src, srcstride, height jg .nextrow REP_RET -%if ARCH_X86_32 -INIT_MMX mmx -cglobal put_vp8_pixels16, 5, 5, 0, dst, dststride, src, srcstride, height -.nextrow: - movq mm0, [srcq+srcstrideq*0+0] - movq mm1, [srcq+srcstrideq*0+8] - movq mm2, [srcq+srcstrideq*1+0] - movq mm3, [srcq+srcstrideq*1+8] - lea srcq, [srcq+srcstrideq*2] - movq [dstq+dststrideq*0+0], mm0 - movq [dstq+dststrideq*0+8], mm1 - movq [dstq+dststrideq*1+0], mm2 - movq [dstq+dststrideq*1+8], mm3 - lea dstq, [dstq+dststrideq*2] - sub heightd, 2 - jg .nextrow - REP_RET -%endif - INIT_XMM sse cglobal put_vp8_pixels16, 5, 5, 2, dst, dststride, src, srcstride, height .nextrow: @@ -895,32 +876,6 @@ cglobal put_vp8_pixels16, 5, 5, 2, dst, dststride, src, srcstride, height %4 [dst2q+strideq+%3], m5 %endmacro -%if ARCH_X86_32 -INIT_MMX mmx -cglobal vp8_idct_dc_add, 3, 3, 0, dst, block, stride - ; load data - movd m0, [blockq] - - ; calculate DC - paddw m0, [pw_4] - pxor m1, m1 - psraw m0, 3 - movd [blockq], m1 - psubw m1, m0 - packuswb m0, m0 - packuswb m1, m1 - punpcklbw m0, m0 - punpcklbw m1, m1 - punpcklwd m0, m0 - punpcklwd m1, m1 - - ; add DC - DEFINE_ARGS dst1, dst2, stride - lea dst2q, [dst1q+strideq*2] - ADD_DC m0, m1, 0, movh - RET -%endif - %macro VP8_IDCT_DC_ADD 0 cglobal vp8_idct_dc_add, 3, 3, 6, dst, block, stride ; load data @@ -971,44 +926,6 @@ VP8_IDCT_DC_ADD ; void ff_vp8_idct_dc_add4y_(uint8_t *dst, int16_t block[4][16], ptrdiff_t stride); ;----------------------------------------------------------------------------- -%if ARCH_X86_32 -INIT_MMX mmx -cglobal vp8_idct_dc_add4y, 3, 3, 0, dst, block, stride - ; load data - movd m0, [blockq+32*0] ; A - movd m1, [blockq+32*2] ; C - punpcklwd m0, [blockq+32*1] ; A B - punpcklwd m1, [blockq+32*3] ; C D - punpckldq m0, m1 ; A B C D - pxor m6, m6 - - ; calculate DC - paddw m0, [pw_4] - movd [blockq+32*0], m6 - movd [blockq+32*1], m6 - movd [blockq+32*2], m6 - movd [blockq+32*3], m6 - psraw m0, 3 - psubw m6, m0 - packuswb m0, m0 - packuswb m6, m6 - punpcklbw m0, m0 ; AABBCCDD - punpcklbw m6, m6 ; AABBCCDD - movq m1, m0 - movq m7, m6 - punpcklbw m0, m0 ; AAAABBBB - punpckhbw m1, m1 ; CCCCDDDD - punpcklbw m6, m6 ; AAAABBBB - punpckhbw m7, m7 ; CCCCDDDD - - ; add DC - DEFINE_ARGS dst1, dst2, stride - lea dst2q, [dst1q+strideq*2] - ADD_DC m0, m6, 0, mova - ADD_DC m1, m7, 8, mova - RET -%endif - INIT_XMM sse2 cglobal vp8_idct_dc_add4y, 3, 3, 6, dst, block, stride ; load data @@ -1117,7 +1034,7 @@ cglobal vp8_idct_dc_add4uv, 3, 3, 0, dst, block, stride SWAP %4, %3 %endmacro -%macro VP8_IDCT_ADD 0 +INIT_MMX sse cglobal vp8_idct_add, 3, 3, 0, dst, block, stride ; load block data movq m0, [blockq+ 0] @@ -1126,17 +1043,9 @@ cglobal vp8_idct_add, 3, 3, 0, dst, block, stride movq m3, [blockq+24] movq m6, [pw_20091] movq m7, [pw_17734] -%if cpuflag(sse) xorps xmm0, xmm0 movaps [blockq+ 0], xmm0 movaps [blockq+16], xmm0 -%else - pxor m4, m4 - movq [blockq+ 0], m4 - movq [blockq+ 8], m4 - movq [blockq+16], m4 - movq [blockq+24], m4 -%endif ; actual IDCT VP8_IDCT_TRANSFORM4x4_1D 0, 1, 2, 3, 4, 5 @@ -1153,14 +1062,6 @@ cglobal vp8_idct_add, 3, 3, 0, dst, block, stride STORE_DIFFx2 m2, m3, m6, m7, m4, 3, dst2q, strideq RET -%endmacro - -%if ARCH_X86_32 -INIT_MMX mmx -VP8_IDCT_ADD -%endif -INIT_MMX sse -VP8_IDCT_ADD ;----------------------------------------------------------------------------- ; void ff_vp8_luma_dc_wht(int16_t block[4][4][16], int16_t dc[16]) @@ -1193,23 +1094,15 @@ VP8_IDCT_ADD SWAP %1, %4, %3 %endmacro -%macro VP8_DC_WHT 0 +INIT_MMX sse cglobal vp8_luma_dc_wht, 2, 3, 0, block, dc1, dc2 movq m0, [dc1q] movq m1, [dc1q+8] movq m2, [dc1q+16] movq m3, [dc1q+24] -%if cpuflag(sse) xorps xmm0, xmm0 movaps [dc1q+ 0], xmm0 movaps [dc1q+16], xmm0 -%else - pxor m4, m4 - movq [dc1q+ 0], m4 - movq [dc1q+ 8], m4 - movq [dc1q+16], m4 - movq [dc1q+24], m4 -%endif HADAMARD4_1D 0, 1, 2, 3 TRANSPOSE4x4W 0, 1, 2, 3, 4 paddw m0, [pw_3] @@ -1221,11 +1114,3 @@ cglobal vp8_luma_dc_wht, 2, 3, 0, block, dc1, dc2 SCATTER_WHT 0, 1, 0 SCATTER_WHT 2, 3, 2 RET -%endmacro - -%if ARCH_X86_32 -INIT_MMX mmx -VP8_DC_WHT -%endif -INIT_MMX sse -VP8_DC_WHT diff --git a/libavcodec/x86/vp8dsp_init.c b/libavcodec/x86/vp8dsp_init.c index 289f1d511..cceb346ce 100644 --- a/libavcodec/x86/vp8dsp_init.c +++ b/libavcodec/x86/vp8dsp_init.c @@ -112,9 +112,6 @@ void ff_put_vp8_bilinear8_v_ssse3 (uint8_t *dst, ptrdiff_t dststride, void ff_put_vp8_pixels8_mmx (uint8_t *dst, ptrdiff_t dststride, uint8_t *src, ptrdiff_t srcstride, int height, int mx, int my); -void ff_put_vp8_pixels16_mmx(uint8_t *dst, ptrdiff_t dststride, - uint8_t *src, ptrdiff_t srcstride, - int height, int mx, int my); void ff_put_vp8_pixels16_sse(uint8_t *dst, ptrdiff_t dststride, uint8_t *src, ptrdiff_t srcstride, int height, int mx, int my); @@ -140,19 +137,6 @@ static void ff_put_vp8_ ## FILTERTYPE ## 8_ ## TAPTYPE ## _ ## OPT( \ dst + 4, dststride, src + 4, srcstride, height, mx, my); \ } -#if ARCH_X86_32 -TAP_W8 (mmxext, epel, h4) -TAP_W8 (mmxext, epel, h6) -TAP_W16(mmxext, epel, h6) -TAP_W8 (mmxext, epel, v4) -TAP_W8 (mmxext, epel, v6) -TAP_W16(mmxext, epel, v6) -TAP_W8 (mmxext, bilinear, h) -TAP_W16(mmxext, bilinear, h) -TAP_W8 (mmxext, bilinear, v) -TAP_W16(mmxext, bilinear, v) -#endif - TAP_W16(sse2, epel, h6) TAP_W16(sse2, epel, v6) TAP_W16(sse2, bilinear, h) @@ -177,16 +161,8 @@ static void ff_put_vp8_epel ## SIZE ## _h ## TAPNUMX ## v ## TAPNUMY ## _ ## OPT dst, dststride, tmpptr, SIZE, height, mx, my); \ } -#if ARCH_X86_32 -#define HVTAPMMX(x, y) \ -HVTAP(mmxext, 8, x, y, 4, 8) \ -HVTAP(mmxext, 8, x, y, 8, 16) - -HVTAP(mmxext, 8, 6, 6, 16, 16) -#else #define HVTAPMMX(x, y) \ HVTAP(mmxext, 8, x, y, 4, 8) -#endif HVTAPMMX(4, 4) HVTAPMMX(4, 6) @@ -221,31 +197,21 @@ static void ff_put_vp8_bilinear ## SIZE ## _hv_ ## OPT( \ } HVBILIN(mmxext, 8, 4, 8) -#if ARCH_X86_32 -HVBILIN(mmxext, 8, 8, 16) -HVBILIN(mmxext, 8, 16, 16) -#endif HVBILIN(sse2, 8, 8, 16) HVBILIN(sse2, 8, 16, 16) HVBILIN(ssse3, 8, 4, 8) HVBILIN(ssse3, 8, 8, 16) HVBILIN(ssse3, 8, 16, 16) -void ff_vp8_idct_dc_add_mmx(uint8_t *dst, int16_t block[16], - ptrdiff_t stride); void ff_vp8_idct_dc_add_sse2(uint8_t *dst, int16_t block[16], ptrdiff_t stride); void ff_vp8_idct_dc_add_sse4(uint8_t *dst, int16_t block[16], ptrdiff_t stride); -void ff_vp8_idct_dc_add4y_mmx(uint8_t *dst, int16_t block[4][16], - ptrdiff_t stride); void ff_vp8_idct_dc_add4y_sse2(uint8_t *dst, int16_t block[4][16], ptrdiff_t stride); void ff_vp8_idct_dc_add4uv_mmx(uint8_t *dst, int16_t block[2][16], ptrdiff_t stride); -void ff_vp8_luma_dc_wht_mmx(int16_t block[4][4][16], int16_t dc[16]); void ff_vp8_luma_dc_wht_sse(int16_t block[4][4][16], int16_t dc[16]); -void ff_vp8_idct_add_mmx(uint8_t *dst, int16_t block[16], ptrdiff_t stride); void ff_vp8_idct_add_sse(uint8_t *dst, int16_t block[16], ptrdiff_t stride); #define DECLARE_LOOP_FILTER(NAME) \ @@ -284,8 +250,6 @@ void ff_vp8_h_loop_filter8uv_mbedge_ ## NAME(uint8_t *dstU, \ ptrdiff_t s, \ int e, int i, int hvt); -DECLARE_LOOP_FILTER(mmx) -DECLARE_LOOP_FILTER(mmxext) DECLARE_LOOP_FILTER(sse2) DECLARE_LOOP_FILTER(ssse3) DECLARE_LOOP_FILTER(sse4) @@ -322,10 +286,6 @@ av_cold void ff_vp78dsp_init_x86(VP8DSPContext *c) int cpu_flags = av_get_cpu_flags(); if (EXTERNAL_MMX(cpu_flags)) { -#if ARCH_X86_32 - c->put_vp8_epel_pixels_tab[0][0][0] = - c->put_vp8_bilinear_pixels_tab[0][0][0] = ff_put_vp8_pixels16_mmx; -#endif c->put_vp8_epel_pixels_tab[1][0][0] = c->put_vp8_bilinear_pixels_tab[1][0][0] = ff_put_vp8_pixels8_mmx; } @@ -335,12 +295,6 @@ av_cold void ff_vp78dsp_init_x86(VP8DSPContext *c) if (EXTERNAL_MMXEXT(cpu_flags)) { VP8_MC_FUNC(2, 4, mmxext); VP8_BILINEAR_MC_FUNC(2, 4, mmxext); -#if ARCH_X86_32 - VP8_LUMA_MC_FUNC(0, 16, mmxext); - VP8_MC_FUNC(1, 8, mmxext); - VP8_BILINEAR_MC_FUNC(0, 16, mmxext); - VP8_BILINEAR_MC_FUNC(1, 8, mmxext); -#endif } if (EXTERNAL_SSE(cpu_flags)) { @@ -348,7 +302,7 @@ av_cold void ff_vp78dsp_init_x86(VP8DSPContext *c) c->put_vp8_bilinear_pixels_tab[0][0][0] = ff_put_vp8_pixels16_sse; } - if (EXTERNAL_SSE2(cpu_flags) || EXTERNAL_SSE2_SLOW(cpu_flags)) { + if (EXTERNAL_SSE2_SLOW(cpu_flags)) { VP8_LUMA_MC_FUNC(0, 16, sse2); VP8_MC_FUNC(1, 8, sse2); VP8_BILINEAR_MC_FUNC(0, 16, sse2); @@ -373,44 +327,6 @@ av_cold void ff_vp8dsp_init_x86(VP8DSPContext *c) if (EXTERNAL_MMX(cpu_flags)) { c->vp8_idct_dc_add4uv = ff_vp8_idct_dc_add4uv_mmx; -#if ARCH_X86_32 - c->vp8_idct_dc_add = ff_vp8_idct_dc_add_mmx; - c->vp8_idct_dc_add4y = ff_vp8_idct_dc_add4y_mmx; - c->vp8_idct_add = ff_vp8_idct_add_mmx; - c->vp8_luma_dc_wht = ff_vp8_luma_dc_wht_mmx; - - c->vp8_v_loop_filter_simple = ff_vp8_v_loop_filter_simple_mmx; - c->vp8_h_loop_filter_simple = ff_vp8_h_loop_filter_simple_mmx; - - c->vp8_v_loop_filter16y_inner = ff_vp8_v_loop_filter16y_inner_mmx; - c->vp8_h_loop_filter16y_inner = ff_vp8_h_loop_filter16y_inner_mmx; - c->vp8_v_loop_filter8uv_inner = ff_vp8_v_loop_filter8uv_inner_mmx; - c->vp8_h_loop_filter8uv_inner = ff_vp8_h_loop_filter8uv_inner_mmx; - - c->vp8_v_loop_filter16y = ff_vp8_v_loop_filter16y_mbedge_mmx; - c->vp8_h_loop_filter16y = ff_vp8_h_loop_filter16y_mbedge_mmx; - c->vp8_v_loop_filter8uv = ff_vp8_v_loop_filter8uv_mbedge_mmx; - c->vp8_h_loop_filter8uv = ff_vp8_h_loop_filter8uv_mbedge_mmx; -#endif - } - - /* note that 4-tap width=16 functions are missing because w=16 - * is only used for luma, and luma is always a copy or sixtap. */ - if (EXTERNAL_MMXEXT(cpu_flags)) { -#if ARCH_X86_32 - c->vp8_v_loop_filter_simple = ff_vp8_v_loop_filter_simple_mmxext; - c->vp8_h_loop_filter_simple = ff_vp8_h_loop_filter_simple_mmxext; - - c->vp8_v_loop_filter16y_inner = ff_vp8_v_loop_filter16y_inner_mmxext; - c->vp8_h_loop_filter16y_inner = ff_vp8_h_loop_filter16y_inner_mmxext; - c->vp8_v_loop_filter8uv_inner = ff_vp8_v_loop_filter8uv_inner_mmxext; - c->vp8_h_loop_filter8uv_inner = ff_vp8_h_loop_filter8uv_inner_mmxext; - - c->vp8_v_loop_filter16y = ff_vp8_v_loop_filter16y_mbedge_mmxext; - c->vp8_h_loop_filter16y = ff_vp8_h_loop_filter16y_mbedge_mmxext; - c->vp8_v_loop_filter8uv = ff_vp8_v_loop_filter8uv_mbedge_mmxext; - c->vp8_h_loop_filter8uv = ff_vp8_h_loop_filter8uv_mbedge_mmxext; -#endif } if (EXTERNAL_SSE(cpu_flags)) { @@ -418,7 +334,7 @@ av_cold void ff_vp8dsp_init_x86(VP8DSPContext *c) c->vp8_luma_dc_wht = ff_vp8_luma_dc_wht_sse; } - if (EXTERNAL_SSE2(cpu_flags) || EXTERNAL_SSE2_SLOW(cpu_flags)) { + if (EXTERNAL_SSE2_SLOW(cpu_flags)) { c->vp8_v_loop_filter_simple = ff_vp8_v_loop_filter_simple_sse2; c->vp8_v_loop_filter16y_inner = ff_vp8_v_loop_filter16y_inner_sse2; diff --git a/libavcodec/x86/vp8dsp_loopfilter.asm b/libavcodec/x86/vp8dsp_loopfilter.asm index caeb40526..ef397efd3 100644 --- a/libavcodec/x86/vp8dsp_loopfilter.asm +++ b/libavcodec/x86/vp8dsp_loopfilter.asm @@ -46,30 +46,6 @@ SECTION .text ; void ff_vp8_h/v_loop_filter_simple_(uint8_t *dst, ptrdiff_t stride, int flim); ;----------------------------------------------------------------------------- -; macro called with 7 mm register indexes as argument, and 4 regular registers -; -; first 4 mm registers will carry the transposed pixel data -; the other three are scratchspace (one would be sufficient, but this allows -; for more spreading/pipelining and thus faster execution on OOE CPUs) -; -; first two regular registers are buf+4*stride and buf+5*stride -; third is -stride, fourth is +stride -%macro READ_8x4_INTERLEAVED 11 - ; interleave 8 (A-H) rows of 4 pixels each - movd m%1, [%8+%10*4] ; A0-3 - movd m%5, [%9+%10*4] ; B0-3 - movd m%2, [%8+%10*2] ; C0-3 - movd m%6, [%8+%10] ; D0-3 - movd m%3, [%8] ; E0-3 - movd m%7, [%9] ; F0-3 - movd m%4, [%9+%11] ; G0-3 - punpcklbw m%1, m%5 ; A/B interleaved - movd m%5, [%9+%11*2] ; H0-3 - punpcklbw m%2, m%6 ; C/D interleaved - punpcklbw m%3, m%7 ; E/F interleaved - punpcklbw m%4, m%5 ; G/H interleaved -%endmacro - ; macro called with 7 mm register indexes as argument, and 5 regular registers ; first 11 mean the same as READ_8x4_TRANSPOSED above ; fifth regular register is scratchspace to reach the bottom 8 rows, it @@ -112,26 +88,6 @@ SECTION .text punpcklbw m%4, m%5 ; G/H/O/P interleaved %endmacro -; write 4 mm registers of 2 dwords each -; first four arguments are mm register indexes containing source data -; last four are registers containing buf+4*stride, buf+5*stride, -; -stride and +stride -%macro WRITE_4x2D 8 - ; write out (2 dwords per register) - movd [%5+%7*4], m%1 - movd [%5+%7*2], m%2 - movd [%5], m%3 - movd [%6+%8], m%4 - punpckhdq m%1, m%1 - punpckhdq m%2, m%2 - punpckhdq m%3, m%3 - punpckhdq m%4, m%4 - movd [%6+%7*4], m%1 - movd [%5+%7], m%2 - movd [%6], m%3 - movd [%6+%8*2], m%4 -%endmacro - ; write 4 xmm registers of 4 dwords each ; arguments same as WRITE_2x4D, but with an extra register, so that the 5 regular ; registers contain buf+4*stride, buf+5*stride, buf+12*stride, -stride and +stride @@ -192,42 +148,6 @@ SECTION .text movd [%7+%9*2], m%4 %endmacro -; write 4 or 8 words in the mmx/xmm registers as 8 lines -; 1 and 2 are the registers to write, this can be the same (for SSE2) -; for pre-SSE4: -; 3 is a general-purpose register that we will clobber -; for SSE4: -; 3 is a pointer to the destination's 5th line -; 4 is a pointer to the destination's 4th line -; 5/6 is -stride and +stride -%macro WRITE_2x4W 6 - movd %3d, %1 - punpckhdq %1, %1 - mov [%4+%5*4], %3w - shr %3, 16 - add %4, %6 - mov [%4+%5*4], %3w - - movd %3d, %1 - add %4, %5 - mov [%4+%5*2], %3w - shr %3, 16 - mov [%4+%5 ], %3w - - movd %3d, %2 - punpckhdq %2, %2 - mov [%4 ], %3w - shr %3, 16 - mov [%4+%6 ], %3w - - movd %3d, %2 - add %4, %6 - mov [%4+%6 ], %3w - shr %3, 16 - mov [%4+%6*2], %3w - add %4, %5 -%endmacro - %macro WRITE_8W 5 %if cpuflag(sse4) pextrw [%3+%4*4], %1, 0 @@ -269,29 +189,19 @@ SECTION .text %macro SIMPLE_LOOPFILTER 2 cglobal vp8_%1_loop_filter_simple, 3, %2, 8, dst, stride, flim, cntr -%if mmsize == 8 ; mmx/mmxext - mov cntrq, 2 -%endif %if cpuflag(ssse3) pxor m0, m0 %endif SPLATB_REG m7, flim, m0 ; splat "flim" into register ; set up indexes to address 4 rows -%if mmsize == 8 - DEFINE_ARGS dst1, mstride, stride, cntr, dst2 -%else DEFINE_ARGS dst1, mstride, stride, dst3, dst2 -%endif mov strideq, mstrideq neg mstrideq %ifidn %1, h lea dst1q, [dst1q+4*strideq-2] %endif -%if mmsize == 8 ; mmx / mmxext -.next8px: -%endif %ifidn %1, v ; read 4 half/full rows of pixels mova m0, [dst1q+mstrideq*2] ; p1 @@ -301,11 +211,7 @@ cglobal vp8_%1_loop_filter_simple, 3, %2, 8, dst, stride, flim, cntr %else ; h lea dst2q, [dst1q+ strideq] -%if mmsize == 8 ; mmx/mmxext - READ_8x4_INTERLEAVED 0, 1, 2, 3, 4, 5, 6, dst1q, dst2q, mstrideq, strideq -%else ; sse2 READ_16x4_INTERLEAVED 0, 1, 2, 3, 4, 5, 6, dst1q, dst2q, mstrideq, strideq, dst3q -%endif TRANSPOSE4x4W 0, 1, 2, 3, 4 %endif @@ -380,7 +286,6 @@ cglobal vp8_%1_loop_filter_simple, 3, %2, 8, dst, stride, flim, cntr inc dst1q SBUTTERFLY bw, 6, 4, 0 -%if mmsize == 16 ; sse2 %if cpuflag(sse4) inc dst2q %endif @@ -390,35 +295,11 @@ cglobal vp8_%1_loop_filter_simple, 3, %2, 8, dst, stride, flim, cntr inc dst3q %endif WRITE_8W m4, dst3q, dst2q, mstrideq, strideq -%else ; mmx/mmxext - WRITE_2x4W m6, m4, dst2q, dst1q, mstrideq, strideq -%endif %endif -%if mmsize == 8 ; mmx/mmxext - ; next 8 pixels -%ifidn %1, v - add dst1q, 8 ; advance 8 cols = pixels -%else ; h - lea dst1q, [dst1q+strideq*8-1] ; advance 8 rows = lines -%endif - dec cntrq - jg .next8px - REP_RET -%else ; sse2 RET -%endif %endmacro -%if ARCH_X86_32 -INIT_MMX mmx -SIMPLE_LOOPFILTER v, 4 -SIMPLE_LOOPFILTER h, 5 -INIT_MMX mmxext -SIMPLE_LOOPFILTER v, 4 -SIMPLE_LOOPFILTER h, 5 -%endif - INIT_XMM sse2 SIMPLE_LOOPFILTER v, 3 SIMPLE_LOOPFILTER h, 5 @@ -485,9 +366,6 @@ cglobal vp8_%1_loop_filter16y_inner, 5, 5, 13, stack_size, dst, stride, flimE, f %if %2 == 8 ; chroma DEFINE_ARGS dst1, dst8, mstride, stride, dst2 -%elif mmsize == 8 - DEFINE_ARGS dst1, mstride, stride, dst2, cntr - mov cntrq, 2 %else DEFINE_ARGS dst1, mstride, stride, dst2, dst8 %endif @@ -500,9 +378,6 @@ cglobal vp8_%1_loop_filter16y_inner, 5, 5, 13, stack_size, dst, stride, flimE, f %endif %endif -%if mmsize == 8 -.next8px: -%endif ; read lea dst2q, [dst1q+strideq] %ifidn %1, v @@ -527,33 +402,7 @@ cglobal vp8_%1_loop_filter16y_inner, 5, 5, 13, stack_size, dst, stride, flimE, f movhps m7, [dst8q+ strideq*2] add dst8q, mstrideq %endif -%elif mmsize == 8 ; mmx/mmxext (h) - ; read 8 rows of 8px each - movu m0, [dst1q+mstrideq*4] - movu m1, [dst2q+mstrideq*4] - movu m2, [dst1q+mstrideq*2] - movu m3, [dst1q+mstrideq ] - movu m4, [dst1q] - movu m5, [dst2q] - movu m6, [dst2q+ strideq ] - - ; 8x8 transpose - TRANSPOSE4x4B 0, 1, 2, 3, 7 - mova m_q0backup, m1 - movu m7, [dst2q+ strideq*2] - TRANSPOSE4x4B 4, 5, 6, 7, 1 - SBUTTERFLY dq, 0, 4, 1 ; p3/p2 - SBUTTERFLY dq, 2, 6, 1 ; q0/q1 - SBUTTERFLY dq, 3, 7, 1 ; q2/q3 - mova m1, m_q0backup - mova m_q0backup, m2 ; store q0 - SBUTTERFLY dq, 1, 5, 2 ; p1/p0 - mova m_p0backup, m5 ; store p0 - SWAP 1, 4 - SWAP 2, 4 - SWAP 6, 3 - SWAP 5, 3 -%else ; sse2 (h) +%else ; h %if %2 == 16 lea dst8q, [dst1q+ strideq*8] %endif @@ -641,25 +490,9 @@ cglobal vp8_%1_loop_filter16y_inner, 5, 5, 13, stack_size, dst, stride, flimE, f psubusb m6, m5 ; q2-q1 por m6, m4 ; abs(q2-q1) -%if notcpuflag(mmxext) - mova m4, m_flimI - pxor m3, m3 - psubusb m0, m4 - psubusb m1, m4 - psubusb m7, m4 - psubusb m6, m4 - pcmpeqb m0, m3 ; abs(p3-p2) <= I - pcmpeqb m1, m3 ; abs(p2-p1) <= I - pcmpeqb m7, m3 ; abs(q3-q2) <= I - pcmpeqb m6, m3 ; abs(q2-q1) <= I - pand m0, m1 - pand m7, m6 - pand m0, m7 -%else ; mmxext/sse2 pmaxub m0, m1 pmaxub m6, m7 pmaxub m0, m6 -%endif ; normal_limit and high_edge_variance for p1-p0, q1-q0 SWAP 7, 3 ; now m7 is zero @@ -681,18 +514,8 @@ cglobal vp8_%1_loop_filter16y_inner, 5, 5, 13, stack_size, dst, stride, flimE, f psubusb m1, m3 ; p1-p0 psubusb m6, m2 ; p0-p1 por m1, m6 ; abs(p1-p0) -%if notcpuflag(mmxext) - mova m6, m1 - psubusb m1, m4 - psubusb m6, m_hevthr - pcmpeqb m1, m7 ; abs(p1-p0) <= I - pcmpeqb m6, m7 ; abs(p1-p0) <= hev_thresh - pand m0, m1 - mova m_maskres, m6 -%else ; mmxext/sse2 pmaxub m0, m1 ; max_I SWAP 1, 4 ; max_hev_thresh -%endif SWAP 6, 4 ; now m6 is I %ifidn %1, v @@ -712,17 +535,6 @@ cglobal vp8_%1_loop_filter16y_inner, 5, 5, 13, stack_size, dst, stride, flimE, f psubusb m1, m5 ; q0-q1 psubusb m7, m4 ; q1-q0 por m1, m7 ; abs(q1-q0) -%if notcpuflag(mmxext) - mova m7, m1 - psubusb m1, m6 - psubusb m7, m_hevthr - pxor m6, m6 - pcmpeqb m1, m6 ; abs(q1-q0) <= I - pcmpeqb m7, m6 ; abs(q1-q0) <= hev_thresh - mova m6, m_maskres - pand m0, m1 ; abs([pq][321]-[pq][210]) <= I - pand m6, m7 -%else ; mmxext/sse2 pxor m7, m7 pmaxub m0, m1 pmaxub m6, m1 @@ -730,7 +542,6 @@ cglobal vp8_%1_loop_filter16y_inner, 5, 5, 13, stack_size, dst, stride, flimE, f psubusb m6, m_hevthr pcmpeqb m0, m7 ; max(abs(..)) <= I pcmpeqb m6, m7 ; !(max(abs..) > thresh) -%endif %ifdef m12 SWAP 6, 12 %else @@ -820,25 +631,12 @@ cglobal vp8_%1_loop_filter16y_inner, 5, 5, 13, stack_size, dst, stride, flimE, f %else mova m6, m_maskres %endif -%if notcpuflag(mmxext) - mova m7, [pb_1] -%else ; mmxext/sse2 pxor m7, m7 -%endif pand m0, m6 pand m1, m6 -%if notcpuflag(mmxext) - paddusb m0, m7 - pand m1, [pb_FE] - pandn m7, m0 - psrlq m1, 1 - psrlq m7, 1 - SWAP 0, 7 -%else ; mmxext/sse2 psubusb m1, [pb_1] pavgb m0, m7 ; a pavgb m1, m7 ; -a -%endif psubusb m5, m0 psubusb m2, m1 paddusb m5, m1 ; q1-a @@ -863,51 +661,13 @@ cglobal vp8_%1_loop_filter16y_inner, 5, 5, 13, stack_size, dst, stride, flimE, f ; 4x8/16 transpose TRANSPOSE4x4B 2, 3, 4, 5, 6 -%if mmsize == 8 ; mmx/mmxext (h) - WRITE_4x2D 2, 3, 4, 5, dst1q, dst2q, mstrideq, strideq -%else ; sse2 (h) lea dst8q, [dst8q+mstrideq +2] WRITE_4x4D 2, 3, 4, 5, dst1q, dst2q, dst8q, mstrideq, strideq, %2 %endif -%endif -%if mmsize == 8 -%if %2 == 8 ; chroma -%ifidn %1, h - sub dst1q, 2 -%endif - cmp dst1q, dst8q - mov dst1q, dst8q - jnz .next8px -%else -%ifidn %1, h - lea dst1q, [dst1q+ strideq*8-2] -%else ; v - add dst1q, 8 -%endif - dec cntrq - jg .next8px -%endif - REP_RET -%else ; mmsize == 16 RET -%endif %endmacro -%if ARCH_X86_32 -INIT_MMX mmx -INNER_LOOPFILTER v, 16 -INNER_LOOPFILTER h, 16 -INNER_LOOPFILTER v, 8 -INNER_LOOPFILTER h, 8 - -INIT_MMX mmxext -INNER_LOOPFILTER v, 16 -INNER_LOOPFILTER h, 16 -INNER_LOOPFILTER v, 8 -INNER_LOOPFILTER h, 8 -%endif - INIT_XMM sse2 INNER_LOOPFILTER v, 16 INNER_LOOPFILTER h, 16 @@ -992,9 +752,6 @@ cglobal vp8_%1_loop_filter16y_mbedge, 5, 5, 15, stack_size, dst1, stride, flimE, %if %2 == 8 ; chroma DEFINE_ARGS dst1, dst8, mstride, stride, dst2 -%elif mmsize == 8 - DEFINE_ARGS dst1, mstride, stride, dst2, cntr - mov cntrq, 2 %else DEFINE_ARGS dst1, mstride, stride, dst2, dst8 %endif @@ -1007,9 +764,6 @@ cglobal vp8_%1_loop_filter16y_mbedge, 5, 5, 15, stack_size, dst1, stride, flimE, %endif %endif -%if mmsize == 8 -.next8px: -%endif ; read lea dst2q, [dst1q+ strideq ] %ifidn %1, v @@ -1034,33 +788,7 @@ cglobal vp8_%1_loop_filter16y_mbedge, 5, 5, 15, stack_size, dst1, stride, flimE, movhps m7, [dst8q+ strideq*2] add dst8q, mstrideq %endif -%elif mmsize == 8 ; mmx/mmxext (h) - ; read 8 rows of 8px each - movu m0, [dst1q+mstrideq*4] - movu m1, [dst2q+mstrideq*4] - movu m2, [dst1q+mstrideq*2] - movu m3, [dst1q+mstrideq ] - movu m4, [dst1q] - movu m5, [dst2q] - movu m6, [dst2q+ strideq ] - - ; 8x8 transpose - TRANSPOSE4x4B 0, 1, 2, 3, 7 - mova m_q0backup, m1 - movu m7, [dst2q+ strideq*2] - TRANSPOSE4x4B 4, 5, 6, 7, 1 - SBUTTERFLY dq, 0, 4, 1 ; p3/p2 - SBUTTERFLY dq, 2, 6, 1 ; q0/q1 - SBUTTERFLY dq, 3, 7, 1 ; q2/q3 - mova m1, m_q0backup - mova m_q0backup, m2 ; store q0 - SBUTTERFLY dq, 1, 5, 2 ; p1/p0 - mova m_p0backup, m5 ; store p0 - SWAP 1, 4 - SWAP 2, 4 - SWAP 6, 3 - SWAP 5, 3 -%else ; sse2 (h) +%else ; h %if %2 == 16 lea dst8q, [dst1q+ strideq*8 ] %endif @@ -1150,25 +878,9 @@ cglobal vp8_%1_loop_filter16y_mbedge, 5, 5, 15, stack_size, dst1, stride, flimE, psubusb m6, m5 ; q2-q1 por m6, m4 ; abs(q2-q1) -%if notcpuflag(mmxext) - mova m4, m_flimI - pxor m3, m3 - psubusb m0, m4 - psubusb m1, m4 - psubusb m7, m4 - psubusb m6, m4 - pcmpeqb m0, m3 ; abs(p3-p2) <= I - pcmpeqb m1, m3 ; abs(p2-p1) <= I - pcmpeqb m7, m3 ; abs(q3-q2) <= I - pcmpeqb m6, m3 ; abs(q2-q1) <= I - pand m0, m1 - pand m7, m6 - pand m0, m7 -%else ; mmxext/sse2 pmaxub m0, m1 pmaxub m6, m7 pmaxub m0, m6 -%endif ; normal_limit and high_edge_variance for p1-p0, q1-q0 SWAP 7, 3 ; now m7 is zero @@ -1190,18 +902,8 @@ cglobal vp8_%1_loop_filter16y_mbedge, 5, 5, 15, stack_size, dst1, stride, flimE, psubusb m1, m3 ; p1-p0 psubusb m6, m2 ; p0-p1 por m1, m6 ; abs(p1-p0) -%if notcpuflag(mmxext) - mova m6, m1 - psubusb m1, m4 - psubusb m6, m_hevthr - pcmpeqb m1, m7 ; abs(p1-p0) <= I - pcmpeqb m6, m7 ; abs(p1-p0) <= hev_thresh - pand m0, m1 - mova m_maskres, m6 -%else ; mmxext/sse2 pmaxub m0, m1 ; max_I SWAP 1, 4 ; max_hev_thresh -%endif SWAP 6, 4 ; now m6 is I %ifidn %1, v @@ -1221,17 +923,6 @@ cglobal vp8_%1_loop_filter16y_mbedge, 5, 5, 15, stack_size, dst1, stride, flimE, psubusb m1, m5 ; q0-q1 psubusb m7, m4 ; q1-q0 por m1, m7 ; abs(q1-q0) -%if notcpuflag(mmxext) - mova m7, m1 - psubusb m1, m6 - psubusb m7, m_hevthr - pxor m6, m6 - pcmpeqb m1, m6 ; abs(q1-q0) <= I - pcmpeqb m7, m6 ; abs(q1-q0) <= hev_thresh - mova m6, m_maskres - pand m0, m1 ; abs([pq][321]-[pq][210]) <= I - pand m6, m7 -%else ; mmxext/sse2 pxor m7, m7 pmaxub m0, m1 pmaxub m6, m1 @@ -1239,7 +930,6 @@ cglobal vp8_%1_loop_filter16y_mbedge, 5, 5, 15, stack_size, dst1, stride, flimE, psubusb m6, m_hevthr pcmpeqb m0, m7 ; max(abs(..)) <= I pcmpeqb m6, m7 ; !(max(abs..) > thresh) -%endif %ifdef m12 SWAP 6, 12 %else @@ -1510,11 +1200,6 @@ cglobal vp8_%1_loop_filter16y_mbedge, 5, 5, 15, stack_size, dst1, stride, flimE, TRANSPOSE4x4B 1, 2, 3, 4, 0 SBUTTERFLY bw, 5, 6, 0 -%if mmsize == 8 ; mmx/mmxext (h) - WRITE_4x2D 1, 2, 3, 4, dst1q, dst2q, mstrideq, strideq - add dst1q, 4 - WRITE_2x4W m5, m6, dst2q, dst1q, mstrideq, strideq -%else ; sse2 (h) lea dst8q, [dst8q+mstrideq+1] WRITE_4x4D 1, 2, 3, 4, dst1q, dst2q, dst8q, mstrideq, strideq, %2 lea dst1q, [dst2q+mstrideq+4] @@ -1528,45 +1213,10 @@ cglobal vp8_%1_loop_filter16y_mbedge, 5, 5, 15, stack_size, dst1, stride, flimE, %endif WRITE_8W m6, dst2q, dst8q, mstrideq, strideq %endif -%endif -%if mmsize == 8 -%if %2 == 8 ; chroma -%ifidn %1, h - sub dst1q, 5 -%endif - cmp dst1q, dst8q - mov dst1q, dst8q - jnz .next8px -%else -%ifidn %1, h - lea dst1q, [dst1q+ strideq*8-5] -%else ; v - add dst1q, 8 -%endif - dec cntrq - jg .next8px -%endif - REP_RET -%else ; mmsize == 16 RET -%endif %endmacro -%if ARCH_X86_32 -INIT_MMX mmx -MBEDGE_LOOPFILTER v, 16 -MBEDGE_LOOPFILTER h, 16 -MBEDGE_LOOPFILTER v, 8 -MBEDGE_LOOPFILTER h, 8 - -INIT_MMX mmxext -MBEDGE_LOOPFILTER v, 16 -MBEDGE_LOOPFILTER h, 16 -MBEDGE_LOOPFILTER v, 8 -MBEDGE_LOOPFILTER h, 8 -%endif - INIT_XMM sse2 MBEDGE_LOOPFILTER v, 16 MBEDGE_LOOPFILTER h, 16 diff --git a/libavcodec/x86/vp9dsp_init_16bpp.c b/libavcodec/x86/vp9dsp_init_16bpp.c index 27e746aea..e5afea151 100644 --- a/libavcodec/x86/vp9dsp_init_16bpp.c +++ b/libavcodec/x86/vp9dsp_init_16bpp.c @@ -54,6 +54,8 @@ decl_ipred_fn(dl, 16, 16, avx2); decl_ipred_fn(dl, 32, 16, avx2); decl_ipred_fn(dr, 16, 16, avx2); decl_ipred_fn(dr, 32, 16, avx2); +decl_ipred_fn(vl, 16, 16, avx2); +decl_ipred_fn(hd, 16, 16, avx2); #define decl_ipred_dir_funcs(type) \ decl_ipred_fns(type, 16, sse2, sse2); \ @@ -139,6 +141,8 @@ av_cold void ff_vp9dsp_init_16bpp_x86(VP9DSPContext *dsp) init_ipred_func(dl, DIAG_DOWN_LEFT, 16, 16, avx2); init_ipred_func(dl, DIAG_DOWN_LEFT, 32, 16, avx2); init_ipred_func(dr, DIAG_DOWN_RIGHT, 16, 16, avx2); + init_ipred_func(vl, VERT_LEFT, 16, 16, avx2); + init_ipred_func(hd, HOR_DOWN, 16, 16, avx2); #if ARCH_X86_64 init_ipred_func(dr, DIAG_DOWN_RIGHT, 32, 16, avx2); #endif diff --git a/libavcodec/x86/vp9intrapred_16bpp.asm b/libavcodec/x86/vp9intrapred_16bpp.asm index 32b698243..808056a80 100644 --- a/libavcodec/x86/vp9intrapred_16bpp.asm +++ b/libavcodec/x86/vp9intrapred_16bpp.asm @@ -1222,6 +1222,111 @@ cglobal vp9_ipred_dr_16x16_16, 4, 5, 6, dst, stride, l, a mova [dst3q+strideq*4], m5 ; 7 RET +cglobal vp9_ipred_vl_16x16_16, 4, 5, 7, dst, stride, l, a + movifnidn aq, amp + mova m0, [aq] ; abcdefghijklmnop + vpbroadcastw xm1, [aq+30] ; pppppppp + vperm2i128 m2, m0, m1, q0201 ; ijklmnoppppppppp + vpalignr m3, m2, m0, 2 ; bcdefghijklmnopp + vperm2i128 m4, m3, m1, q0201 ; jklmnopppppppppp + vpalignr m5, m2, m0, 4 ; cdefghijklmnoppp + vperm2i128 m6, m5, m1, q0201 ; klmnoppppppppppp + LOWPASS 5, 3, 0 ; BCDEFGHIJKLMNOPP + LOWPASS 6, 4, 2 ; JKLMNOPPPPPPPPPP + pavgw m3, m0 ; abcdefghijklmnop + pavgw m4, m2 ; ijklmnoppppppppp + DEFINE_ARGS dst, stride, stride3, stride5, dst4 + lea dst4q, [dstq+strideq*4] + lea stride3q, [strideq*3] + lea stride5q, [stride3q+strideq*2] + + mova [dstq+strideq*0], m3 ; 0 abcdefghijklmnop + mova [dstq+strideq*1], m5 ; 1 BCDEFGHIJKLMNOPP + vpalignr m0, m4, m3, 2 + vpalignr m1, m6, m5, 2 + mova [dstq+strideq*2 ], m0 ; 2 bcdefghijklmnopp + mova [dstq+stride3q*1], m1 ; 3 CDEFGHIJKLMNOPPP + vpalignr m0, m4, m3, 4 + vpalignr m1, m6, m5, 4 + mova [dst4q+strideq*0], m0 ; 4 cdefghijklmnoppp + mova [dstq+stride5q*1], m1 ; 5 DEFGHIJKLMNOPPPP + vpalignr m0, m4, m3, 6 + vpalignr m1, m6, m5, 6 + mova [ dstq+stride3q*2], m0 ; 6 defghijklmnopppp + mova [dst4q+stride3q*1], m1 ; 7 EFGHIJKLMNOPPPPP + vpalignr m0, m4, m3, 8 + vpalignr m1, m6, m5, 8 + mova [ dstq+strideq*8], m0 ; 8 efghijklmnoppppp + mova [dst4q+stride5q*1], m1 ; 9 FGHIJKLMNOPPPPPP + vpalignr m0, m4, m3, 10 + mova [dstq+stride5q*2], m0 ; 10 fghijklmnopppppp + vpalignr m0, m4, m3, 12 + mova [dst4q+strideq*8], m0 ; 12 ghijklmnoppppppp + vpalignr m0, m4, m3, 14 + mova [dst4q+stride5q*2], m0 ; 14 hijklmnopppppppp + sub dst4q, strideq + vpalignr m1, m6, m5, 10 + mova [dst4q+strideq*8], m1 ; 11 GHIJKLMNOPPPPPPP + vpalignr m1, m6, m5, 12 + mova [dst4q+stride5q*2], m1 ; 13 HIJKLMNOPPPPPPPP + vpalignr m1, m6, m5, 14 + mova [dst4q+stride3q*4], m1 ; 15 IJKLMNOPPPPPPPPP + RET + +cglobal vp9_ipred_hd_16x16_16, 4, 5, 7, dst, stride, l, a + movu m0, [aq-2] ; *abcdefghijklmno + mova m1, [lq] ; klmnopqrstuvwxyz + vperm2i128 m2, m1, m0, q0201 ; stuvwxyz*abcdefg + vpalignr m3, m2, m1, 2 ; lmnopqrstuvwxyz* + vpalignr m4, m2, m1, 4 ; mnopqrstuvwxyz*a + LOWPASS 4, 3, 1 ; LMNOPQRSTUVWXYZ# + pavgw m3, m1 ; klmnopqrstuvwxyz + mova m1, [aq] ; abcdefghijklmnop + movu m2, [aq+2] ; bcdefghijklmnop. + LOWPASS 2, 1, 0 ; ABCDEFGHIJKLMNO. + vpunpcklwd m0, m3, m4 ; kLlMmNnOsTtUuVvW + vpunpckhwd m1, m3, m4 ; oPpQqRrSwXxYyZz# + vperm2i128 m3, m1, m0, q0002 ; kLlMmNnOoPpQqRrS + vperm2i128 m4, m0, m1, q0301 ; sTtUuVvWwXxYyZz# + vperm2i128 m0, m4, m2, q0201 ; wXxYyZz#ABCDEFGH + vperm2i128 m1, m3, m4, q0201 ; oPpQqRrSsTtUuVvW + DEFINE_ARGS dst, stride, stride3, stride5, dst5 + lea stride3q, [strideq*3] + lea stride5q, [stride3q+strideq*2] + lea dst5q, [dstq+stride5q] + + mova [dst5q+stride5q*2], m3 ; 15 kLlMmNnOoPpQqRrS + mova [dst5q+stride3q*2], m1 ; 11 oPpQqRrSsTtUuVvW + mova [dst5q+strideq*2], m4 ; 7 sTtUuVvWwXxYyZz# + mova [dstq+stride3q*1], m0 ; 3 wXxYyZz#ABCDEFGH + vpalignr m5, m4, m1, 4 + mova [dstq+stride5q*2], m5 ; 10 pQqRrSsTtUuVvWwX + vpalignr m5, m0, m4, 4 + vpalignr m6, m2, m0, 4 + mova [dstq+stride3q*2], m5 ; 6 tUuVvWwXxYyZz#AB + mova [dstq+strideq*2], m6 ; 2 xYyZz#ABCDEFGHIJ + vpalignr m5, m4, m1, 8 + mova [dst5q+strideq*4], m5 ; 9 qRrSsTtUuVvWwXxY + vpalignr m5, m0, m4, 8 + vpalignr m6, m2, m0, 8 + mova [dstq+stride5q*1], m5 ; 5 uVvWwXxYyZz#ABCD + mova [dstq+strideq*1], m6 ; 1 yZz#ABCDEFGHIJKL + vpalignr m5, m1, m3, 12 + vpalignr m6, m4, m1, 12 + mova [dstq+stride3q*4], m5 ; 12 nOoPpQqRrSsTtUuV + mova [dst5q+stride3q], m6 ; 8 rSsTtUuVvWwXxYyZ + vpalignr m5, m0, m4, 12 + vpalignr m6, m2, m0, 12 + mova [dstq+strideq*4], m5 ; 4 nOoPpQqRrSsTtUuV + mova [dstq+strideq*0], m6 ; 0 z#ABCDEFGHIJKLMN + sub dst5q, strideq + vpalignr m5, m1, m3, 4 + mova [dst5q+stride5q*2], m5 ; 14 lMmNnOoPpQqRrSsT + sub dst5q, strideq + vpalignr m5, m1, m3, 8 + mova [dst5q+stride5q*2], m5 ; 13 mNnOoPpQqRrSsTtU + RET + %if ARCH_X86_64 cglobal vp9_ipred_dr_32x32_16, 4, 7, 10, dst, stride, l, a mova m0, [lq+mmsize*0+0] ; l[0-15] diff --git a/libavcodec/x86/vp9mc.asm b/libavcodec/x86/vp9mc.asm index f64161b2c..efc4cfbef 100644 --- a/libavcodec/x86/vp9mc.asm +++ b/libavcodec/x86/vp9mc.asm @@ -604,7 +604,12 @@ cglobal vp9_%1%2 %+ %%szsuf, 5, 5, %8, dst, dstride, src, sstride, h %%pavg m0, [dstq] %%pavg m1, [dstq+d%3] %%pavg m2, [dstq+d%4] +%if %2 == 4 + %%srcfn m4, [dstq+d%5] + %%pavg m3, m4 +%else %%pavg m3, [dstq+d%5] +%endif %if %2/mmsize == 8 %%pavg m4, [dstq+mmsize*4] %%pavg m5, [dstq+mmsize*5] diff --git a/libavcodec/x86/xvididct.asm b/libavcodec/x86/xvididct.asm index 0220885da..4197551cd 100644 --- a/libavcodec/x86/xvididct.asm +++ b/libavcodec/x86/xvididct.asm @@ -91,145 +91,6 @@ iTab4: dw 0x4b42, 0x6254, 0xb4be, 0x9dac, 0x4b42, 0xd746, 0x4b42, 0xd746 dw 0x3b21, 0x14c3, 0x587e, 0xeb3d, 0x14c3, 0x587e, 0x14c3, 0xc4df dw 0x6862, 0x587e, 0x979e, 0xc4df, 0x3b21, 0x979e, 0x587e, 0x979e -%if ARCH_X86_32 -; ----------------------------------------------------------------------------- -; -; The first stage iDCT 8x8 - inverse DCTs of rows -; -; ----------------------------------------------------------------------------- -; The 8-point inverse DCT direct algorithm -; ----------------------------------------------------------------------------- -; -; static const short w[32] = { -; FIX(cos_4_16), FIX(cos_2_16), FIX(cos_4_16), FIX(cos_6_16), -; FIX(cos_4_16), FIX(cos_6_16), -FIX(cos_4_16), -FIX(cos_2_16), -; FIX(cos_4_16), -FIX(cos_6_16), -FIX(cos_4_16), FIX(cos_2_16), -; FIX(cos_4_16), -FIX(cos_2_16), FIX(cos_4_16), -FIX(cos_6_16), -; FIX(cos_1_16), FIX(cos_3_16), FIX(cos_5_16), FIX(cos_7_16), -; FIX(cos_3_16), -FIX(cos_7_16), -FIX(cos_1_16), -FIX(cos_5_16), -; FIX(cos_5_16), -FIX(cos_1_16), FIX(cos_7_16), FIX(cos_3_16), -; FIX(cos_7_16), -FIX(cos_5_16), FIX(cos_3_16), -FIX(cos_1_16) }; -; -; #define DCT_8_INV_ROW(x, y) -; { -; int a0, a1, a2, a3, b0, b1, b2, b3; -; -; a0 = x[0] * w[0] + x[2] * w[1] + x[4] * w[2] + x[6] * w[3]; -; a1 = x[0] * w[4] + x[2] * w[5] + x[4] * w[6] + x[6] * w[7]; -; a2 = x[0] * w[8] + x[2] * w[9] + x[4] * w[10] + x[6] * w[11]; -; a3 = x[0] * w[12] + x[2] * w[13] + x[4] * w[14] + x[6] * w[15]; -; b0 = x[1] * w[16] + x[3] * w[17] + x[5] * w[18] + x[7] * w[19]; -; b1 = x[1] * w[20] + x[3] * w[21] + x[5] * w[22] + x[7] * w[23]; -; b2 = x[1] * w[24] + x[3] * w[25] + x[5] * w[26] + x[7] * w[27]; -; b3 = x[1] * w[28] + x[3] * w[29] + x[5] * w[30] + x[7] * w[31]; -; -; y[0] = SHIFT_ROUND(a0 + b0); -; y[1] = SHIFT_ROUND(a1 + b1); -; y[2] = SHIFT_ROUND(a2 + b2); -; y[3] = SHIFT_ROUND(a3 + b3); -; y[4] = SHIFT_ROUND(a3 - b3); -; y[5] = SHIFT_ROUND(a2 - b2); -; y[6] = SHIFT_ROUND(a1 - b1); -; y[7] = SHIFT_ROUND(a0 - b0); -; } -; -; ----------------------------------------------------------------------------- -; -; In this implementation the outputs of the iDCT-1D are multiplied -; for rows 0,4 - by cos_4_16, -; for rows 1,7 - by cos_1_16, -; for rows 2,6 - by cos_2_16, -; for rows 3,5 - by cos_3_16 -; and are shifted to the left for better accuracy. -; -; For the constants used, -; FIX(float_const) = (short) (float_const * (1 << 15) + 0.5) -; -; ----------------------------------------------------------------------------- - -; ----------------------------------------------------------------------------- -; Tables for mmx processors -; ----------------------------------------------------------------------------- - -; Table for rows 0,4 - constants are multiplied by cos_4_16 -tab_i_04_mmx: dw 16384, 16384, 16384, -16384 - dw 21407, 8867, 8867, -21407 ; w07 w05 w03 w01 - dw 16384, -16384, 16384, 16384 ; w14 w12 w10 w08 - dw -8867, 21407, -21407, -8867 ; w15 w13 w11 w09 - dw 22725, 12873, 19266, -22725 ; w22 w20 w18 w16 - dw 19266, 4520, -4520, -12873 ; w23 w21 w19 w17 - dw 12873, 4520, 4520, 19266 ; w30 w28 w26 w24 - dw -22725, 19266, -12873, -22725 ; w31 w29 w27 w25 -; Table for rows 1,7 - constants are multiplied by cos_1_16 - dw 22725, 22725, 22725, -22725 ; movq-> w06 w04 w02 w00 - dw 29692, 12299, 12299, -29692 ; w07 w05 w03 w01 - dw 22725, -22725, 22725, 22725 ; w14 w12 w10 w08 - dw -12299, 29692, -29692, -12299 ; w15 w13 w11 w09 - dw 31521, 17855, 26722, -31521 ; w22 w20 w18 w16 - dw 26722, 6270, -6270, -17855 ; w23 w21 w19 w17 - dw 17855, 6270, 6270, 26722 ; w30 w28 w26 w24 - dw -31521, 26722, -17855, -31521 ; w31 w29 w27 w25 -; Table for rows 2,6 - constants are multiplied by cos_2_16 - dw 21407, 21407, 21407, -21407 ; movq-> w06 w04 w02 w00 - dw 27969, 11585, 11585, -27969 ; w07 w05 w03 w01 - dw 21407, -21407, 21407, 21407 ; w14 w12 w10 w08 - dw -11585, 27969, -27969, -11585 ; w15 w13 w11 w09 - dw 29692, 16819, 25172, -29692 ; w22 w20 w18 w16 - dw 25172, 5906, -5906, -16819 ; w23 w21 w19 w17 - dw 16819, 5906, 5906, 25172 ; w30 w28 w26 w24 - dw -29692, 25172, -16819, -29692 ; w31 w29 w27 w25 -; Table for rows 3,5 - constants are multiplied by cos_3_16 - dw 19266, 19266, 19266, -19266 ; movq-> w06 w04 w02 w00 - dw 25172, 10426, 10426, -25172 ; w07 w05 w03 w01 - dw 19266, -19266, 19266, 19266 ; w14 w12 w10 w08 - dw -10426, 25172, -25172, -10426 ; w15 w13 w11 w09 - dw 26722, 15137, 22654, -26722 ; w22 w20 w18 w16 - dw 22654, 5315, -5315, -15137 ; w23 w21 w19 w17 - dw 15137, 5315, 5315, 22654 ; w30 w28 w26 w24 - dw -26722, 22654, -15137, -26722 ; w31 w29 w27 w25 - -; ----------------------------------------------------------------------------- -; Tables for xmm processors -; ----------------------------------------------------------------------------- - -; %3 for rows 0,4 - constants are multiplied by cos_4_16 -tab_i_04_xmm: dw 16384, 21407, 16384, 8867 ; movq-> w05 w04 w01 w00 - dw 16384, 8867, -16384, -21407 ; w07 w06 w03 w02 - dw 16384, -8867, 16384, -21407 ; w13 w12 w09 w08 - dw -16384, 21407, 16384, -8867 ; w15 w14 w11 w10 - dw 22725, 19266, 19266, -4520 ; w21 w20 w17 w16 - dw 12873, 4520, -22725, -12873 ; w23 w22 w19 w18 - dw 12873, -22725, 4520, -12873 ; w29 w28 w25 w24 - dw 4520, 19266, 19266, -22725 ; w31 w30 w27 w26 -; %3 for rows 1,7 - constants are multiplied by cos_1_16 - dw 22725, 29692, 22725, 12299 ; movq-> w05 w04 w01 w00 - dw 22725, 12299, -22725, -29692 ; w07 w06 w03 w02 - dw 22725, -12299, 22725, -29692 ; w13 w12 w09 w08 - dw -22725, 29692, 22725, -12299 ; w15 w14 w11 w10 - dw 31521, 26722, 26722, -6270 ; w21 w20 w17 w16 - dw 17855, 6270, -31521, -17855 ; w23 w22 w19 w18 - dw 17855, -31521, 6270, -17855 ; w29 w28 w25 w24 - dw 6270, 26722, 26722, -31521 ; w31 w30 w27 w26 -; %3 for rows 2,6 - constants are multiplied by cos_2_16 - dw 21407, 27969, 21407, 11585 ; movq-> w05 w04 w01 w00 - dw 21407, 11585, -21407, -27969 ; w07 w06 w03 w02 - dw 21407, -11585, 21407, -27969 ; w13 w12 w09 w08 - dw -21407, 27969, 21407, -11585 ; w15 w14 w11 w10 - dw 29692, 25172, 25172, -5906 ; w21 w20 w17 w16 - dw 16819, 5906, -29692, -16819 ; w23 w22 w19 w18 - dw 16819, -29692, 5906, -16819 ; w29 w28 w25 w24 - dw 5906, 25172, 25172, -29692 ; w31 w30 w27 w26 -; %3 for rows 3,5 - constants are multiplied by cos_3_16 - dw 19266, 25172, 19266, 10426 ; movq-> w05 w04 w01 w00 - dw 19266, 10426, -19266, -25172 ; w07 w06 w03 w02 - dw 19266, -10426, 19266, -25172 ; w13 w12 w09 w08 - dw -19266, 25172, 19266, -10426 ; w15 w14 w11 w10 - dw 26722, 22654, 22654, -5315 ; w21 w20 w17 w16 - dw 15137, 5315, -26722, -15137 ; w23 w22 w19 w18 - dw 15137, -26722, 5315, -15137 ; w29 w28 w25 w24 - dw 5315, 22654, 22654, -26722 ; w31 w30 w27 w26 -%endif ; ~ARCH_X86_32 - ; Similar to rounder_0 in MMX code ; 4 first similar, then: 4*8->6*16 5*8->4*16 6/7*8->5*16 walkenIdctRounders: times 4 dd 65536 @@ -709,275 +570,3 @@ INIT_XMM sse2 IDCT_SSE2 0 IDCT_SSE2 1 IDCT_SSE2 2 - -%if ARCH_X86_32 - -; %1=offset %2=tab_offset -; %3=rnd_offset where 4*8->6*16 5*8->4*16 6/7*8->5*16 -%macro DCT_8_INV_ROW 3 - movq mm0, [r0+16*%1+0] ; 0 ; x3 x2 x1 x0 - movq mm1, [r0+16*%1+8] ; 1 ; x7 x6 x5 x4 - movq mm2, mm0 ; 2 ; x3 x2 x1 x0 - movq mm3, [%2+ 0] ; 3 ; w06 w04 w02 w00 -%if cpuflag(mmxext) - pshufw mm0, mm0, 0x88 ; x2 x0 x2 x0 - movq mm4, [%2+ 8] ; 4 ; w07 w06 w03 w02 - movq mm5, mm1 ; 5 ; x7 x6 x5 x4 - pmaddwd mm3, mm0 ; x2*w05+x0*w04 x2*w01+x0*w00 - movq mm6, [%2+32] ; 6 ; w21 w20 w17 w16 - pshufw mm1, mm1, 0x88 ; x6 x4 x6 x4 - pmaddwd mm4, mm1 ; x6*w07+x4*w06 x6*w03+x4*w02 - movq mm7, [%2+40] ; 7; w23 w22 w19 w18 - pshufw mm2, mm2, 0xdd ; x3 x1 x3 x1 - pmaddwd mm6, mm2 ; x3*w21+x1*w20 x3*w17+x1*w16 - pshufw mm5, mm5, 0xdd ; x7 x5 x7 x5 - pmaddwd mm7, mm5 ; x7*w23+x5*w22 x7*w19+x5*w18 - paddd mm3, [walkenIdctRounders + %3] ; +%3 - pmaddwd mm0, [%2+16] ; x2*w13+x0*w12 x2*w09+x0*w08 - paddd mm3, mm4 ; 4 ; a1=sum(even1) a0=sum(even0) - pmaddwd mm1, [%2+24] ; x6*w15+x4*w14 x6*w11+x4*w10 - movq mm4, mm3 ; 4 ; a1 a0 - pmaddwd mm2, [%2+48] ; x3*w29+x1*w28 x3*w25+x1*w24 - paddd mm6, mm7 ; 7 ; b1=sum(odd1) b0=sum(odd0) - pmaddwd mm5, [%2+56] ; x7*w31+x5*w30 x7*w27+x5*w26 - paddd mm3, mm6 ; a1+b1 a0+b0 - paddd mm0, [walkenIdctRounders + %3] ; +%3 - psrad mm3, 11 ; y1=a1+b1 y0=a0+b0 - paddd mm0, mm1 ; 1 ; a3=sum(even3) a2=sum(even2) - psubd mm4, mm6 ; 6 ; a1-b1 a0-b0 - movq mm7, mm0 ; 7 ; a3 a2 - paddd mm2, mm5 ; 5 ; b3=sum(odd3) b2=sum(odd2) - paddd mm0, mm2 ; a3+b3 a2+b2 - psrad mm4, 11 ; y6=a1-b1 y7=a0-b0 - psubd mm7, mm2 ; 2 ; a3-b3 a2-b2 - psrad mm0, 11 ; y3=a3+b3 y2=a2+b2 - psrad mm7, 11 ; y4=a3-b3 y5=a2-b2 - packssdw mm3, mm0 ; 0 ; y3 y2 y1 y0 - packssdw mm7, mm4 ; 4 ; y6 y7 y4 y5 - movq [r0+16*%1+0], mm3 ; 3 ; save y3 y2 y1 y0 - pshufw mm7, mm7, 0xb1 ; y7 y6 y5 y4 -%else - punpcklwd mm0, mm1 ; x5 x1 x4 x0 - movq mm5, mm0 ; 5 ; x5 x1 x4 x0 - punpckldq mm0, mm0 ; x4 x0 x4 x0 - movq mm4, [%2+ 8] ; 4 ; w07 w05 w03 w01 - punpckhwd mm2, mm1 ; 1 ; x7 x3 x6 x2 - pmaddwd mm3, mm0 ; x4*w06+x0*w04 x4*w02+x0*w00 - movq mm6, mm2 ; 6 ; x7 x3 x6 x2 - movq mm1, [%2+32] ; 1 ; w22 w20 w18 w16 - punpckldq mm2, mm2 ; x6 x2 x6 x2 - pmaddwd mm4, mm2 ; x6*w07+x2*w05 x6*w03+x2*w01 - punpckhdq mm5, mm5 ; x5 x1 x5 x1 - pmaddwd mm0, [%2+16] ; x4*w14+x0*w12 x4*w10+x0*w08 - punpckhdq mm6, mm6 ; x7 x3 x7 x3 - movq mm7, [%2+40] ; 7 ; w23 w21 w19 w17 - pmaddwd mm1, mm5 ; x5*w22+x1*w20 x5*w18+x1*w16 - paddd mm3, [walkenIdctRounders + %3] ; +%3 - pmaddwd mm7, mm6 ; x7*w23+x3*w21 x7*w19+x3*w17 - pmaddwd mm2, [%2+24] ; x6*w15+x2*w13 x6*w11+x2*w09 - paddd mm3, mm4 ; 4 ; a1=sum(even1) a0=sum(even0) - pmaddwd mm5, [%2+48] ; x5*w30+x1*w28 x5*w26+x1*w24 - movq mm4, mm3 ; 4 ; a1 a0 - pmaddwd mm6, [%2+56] ; x7*w31+x3*w29 x7*w27+x3*w25 - paddd mm1, mm7 ; 7 ; b1=sum(odd1) b0=sum(odd0) - paddd mm0, [walkenIdctRounders + %3] ; +%3 - psubd mm3, mm1 ; a1-b1 a0-b0 - psrad mm3, 11 ; y6=a1-b1 y7=a0-b0 - paddd mm1, mm4 ; 4 ; a1+b1 a0+b0 - paddd mm0, mm2 ; 2 ; a3=sum(even3) a2=sum(even2) - psrad mm1, 11 ; y1=a1+b1 y0=a0+b0 - paddd mm5, mm6 ; 6 ; b3=sum(odd3) b2=sum(odd2) - movq mm4, mm0 ; 4 ; a3 a2 - paddd mm0, mm5 ; a3+b3 a2+b2 - psubd mm4, mm5 ; 5 ; a3-b3 a2-b2 - psrad mm0, 11 ; y3=a3+b3 y2=a2+b2 - psrad mm4, 11 ; y4=a3-b3 y5=a2-b2 - packssdw mm1, mm0 ; 0 ; y3 y2 y1 y0 - packssdw mm4, mm3 ; 3 ; y6 y7 y4 y5 - movq mm7, mm4 ; 7 ; y6 y7 y4 y5 - psrld mm4, 16 ; 0 y6 0 y4 - pslld mm7, 16 ; y7 0 y5 0 - movq [r0+16*%1+0], mm1 ; 1 ; save y3 y2 y1 y0 - por mm7, mm4 ; 4 ; y7 y6 y5 y4 -%endif - movq [r0+16*%1+8], mm7 ; 7 ; save y7 y6 y5 y4 -%endmacro - -; ----------------------------------------------------------------------------- -; -; The first stage DCT 8x8 - forward DCTs of columns -; -; The %2puts are multiplied -; for rows 0,4 - on cos_4_16, -; for rows 1,7 - on cos_1_16, -; for rows 2,6 - on cos_2_16, -; for rows 3,5 - on cos_3_16 -; and are shifted to the left for rise of accuracy -; -; ----------------------------------------------------------------------------- -; -; The 8-point scaled forward DCT algorithm (26a8m) -; -; ----------------------------------------------------------------------------- -; -;#define DCT_8_FRW_COL(x, y) -; { -; short t0, t1, t2, t3, t4, t5, t6, t7; -; short tp03, tm03, tp12, tm12, tp65, tm65; -; short tp465, tm465, tp765, tm765; -; -; t0 = LEFT_SHIFT(x[0] + x[7]); -; t1 = LEFT_SHIFT(x[1] + x[6]); -; t2 = LEFT_SHIFT(x[2] + x[5]); -; t3 = LEFT_SHIFT(x[3] + x[4]); -; t4 = LEFT_SHIFT(x[3] - x[4]); -; t5 = LEFT_SHIFT(x[2] - x[5]); -; t6 = LEFT_SHIFT(x[1] - x[6]); -; t7 = LEFT_SHIFT(x[0] - x[7]); -; -; tp03 = t0 + t3; -; tm03 = t0 - t3; -; tp12 = t1 + t2; -; tm12 = t1 - t2; -; -; y[0] = tp03 + tp12; -; y[4] = tp03 - tp12; -; -; y[2] = tm03 + tm12 * tg_2_16; -; y[6] = tm03 * tg_2_16 - tm12; -; -; tp65 = (t6 + t5) * cos_4_16; -; tm65 = (t6 - t5) * cos_4_16; -; -; tp765 = t7 + tp65; -; tm765 = t7 - tp65; -; tp465 = t4 + tm65; -; tm465 = t4 - tm65; -; -; y[1] = tp765 + tp465 * tg_1_16; -; y[7] = tp765 * tg_1_16 - tp465; -; y[5] = tm765 * tg_3_16 + tm465; -; y[3] = tm765 - tm465 * tg_3_16; -; } -; -; ----------------------------------------------------------------------------- - -; ----------------------------------------------------------------------------- -; DCT_8_INV_COL_4 INP,OUT -; ----------------------------------------------------------------------------- -%macro DCT_8_INV_COL 1 - movq mm0, [tan3] - movq mm3, [%1+16*3] - movq mm1, mm0 ; tg_3_16 - movq mm5, [%1+16*5] - pmulhw mm0, mm3 ; x3*(tg_3_16-1) - movq mm4, [tan1] - pmulhw mm1, mm5 ; x5*(tg_3_16-1) - movq mm7, [%1+16*7] - movq mm2, mm4 ; tg_1_16 - movq mm6, [%1+16*1] - pmulhw mm4, mm7 ; x7*tg_1_16 - paddsw mm0, mm3 ; x3*tg_3_16 - pmulhw mm2, mm6 ; x1*tg_1_16 - paddsw mm1, mm3 ; x3+x5*(tg_3_16-1) - psubsw mm0, mm5 ; x3*tg_3_16-x5 = tm35 - movq mm3, [sqrt2] - paddsw mm1, mm5 ; x3+x5*tg_3_16 = tp35 - paddsw mm4, mm6 ; x1+tg_1_16*x7 = tp17 - psubsw mm2, mm7 ; x1*tg_1_16-x7 = tm17 - movq mm5, mm4 ; tp17 - movq mm6, mm2 ; tm17 - paddsw mm5, mm1 ; tp17+tp35 = b0 - psubsw mm6, mm0 ; tm17-tm35 = b3 - psubsw mm4, mm1 ; tp17-tp35 = t1 - paddsw mm2, mm0 ; tm17+tm35 = t2 - movq mm7, [tan2] - movq mm1, mm4 ; t1 - movq [%1+3*16], mm5 ; save b0 - paddsw mm1, mm2 ; t1+t2 - movq [%1+5*16], mm6 ; save b3 - psubsw mm4, mm2 ; t1-t2 - movq mm5, [%1+2*16] - movq mm0, mm7 ; tg_2_16 - movq mm6, [%1+6*16] - pmulhw mm0, mm5 ; x2*tg_2_16 - pmulhw mm7, mm6 ; x6*tg_2_16 - pmulhw mm1, mm3 ; ocos_4_16*(t1+t2) = b1/2 - movq mm2, [%1+0*16] - pmulhw mm4, mm3 ; ocos_4_16*(t1-t2) = b2/2 - psubsw mm0, mm6 ; t2*tg_2_16-x6 = tm26 - movq mm3, mm2 ; x0 - movq mm6, [%1+4*16] - paddsw mm7, mm5 ; x2+x6*tg_2_16 = tp26 - paddsw mm2, mm6 ; x0+x4 = tp04 - psubsw mm3, mm6 ; x0-x4 = tm04 - movq mm5, mm2 ; tp04 - movq mm6, mm3 ; tm04 - psubsw mm2, mm7 ; tp04-tp26 = a3 - paddsw mm3, mm0 ; tm04+tm26 = a1 - paddsw mm1, mm1 ; b1 - paddsw mm4, mm4 ; b2 - paddsw mm5, mm7 ; tp04+tp26 = a0 - psubsw mm6, mm0 ; tm04-tm26 = a2 - movq mm7, mm3 ; a1 - movq mm0, mm6 ; a2 - paddsw mm3, mm1 ; a1+b1 - paddsw mm6, mm4 ; a2+b2 - psraw mm3, 6 ; dst1 - psubsw mm7, mm1 ; a1-b1 - psraw mm6, 6 ; dst2 - psubsw mm0, mm4 ; a2-b2 - movq mm1, [%1+3*16] ; load b0 - psraw mm7, 6 ; dst6 - movq mm4, mm5 ; a0 - psraw mm0, 6 ; dst5 - movq [%1+1*16], mm3 - paddsw mm5, mm1 ; a0+b0 - movq [%1+2*16], mm6 - psubsw mm4, mm1 ; a0-b0 - movq mm3, [%1+5*16] ; load b3 - psraw mm5, 6 ; dst0 - movq mm6, mm2 ; a3 - psraw mm4, 6 ; dst7 - movq [%1+5*16], mm0 - paddsw mm2, mm3 ; a3+b3 - movq [%1+6*16], mm7 - psubsw mm6, mm3 ; a3-b3 - movq [%1+0*16], mm5 - psraw mm2, 6 ; dst3 - movq [%1+7*16], mm4 - psraw mm6, 6 ; dst4 - movq [%1+3*16], mm2 - movq [%1+4*16], mm6 -%endmacro - -%macro XVID_IDCT_MMX 0 -cglobal xvid_idct, 1, 1, 0, block -%if cpuflag(mmxext) -%define TAB tab_i_04_xmm -%else -%define TAB tab_i_04_mmx -%endif - ; Process each row - beware of rounder offset - DCT_8_INV_ROW 0, TAB + 64 * 0, 0*16 - DCT_8_INV_ROW 1, TAB + 64 * 1, 1*16 - DCT_8_INV_ROW 2, TAB + 64 * 2, 2*16 - DCT_8_INV_ROW 3, TAB + 64 * 3, 3*16 - DCT_8_INV_ROW 4, TAB + 64 * 0, 6*16 - DCT_8_INV_ROW 5, TAB + 64 * 3, 4*16 - DCT_8_INV_ROW 6, TAB + 64 * 2, 5*16 - DCT_8_INV_ROW 7, TAB + 64 * 1, 5*16 - - ; Process the columns (4 at a time) - DCT_8_INV_COL r0+0 - DCT_8_INV_COL r0+8 - - RET -%endmacro - -INIT_MMX mmx -XVID_IDCT_MMX -INIT_MMX mmxext -XVID_IDCT_MMX - -%endif ; ~ARCH_X86_32 diff --git a/libavcodec/x86/xvididct.h b/libavcodec/x86/xvididct.h index edb5ebfd3..bd6195e39 100644 --- a/libavcodec/x86/xvididct.h +++ b/libavcodec/x86/xvididct.h @@ -29,14 +29,6 @@ #include #include -void ff_xvid_idct_mmx(short *block); -void ff_xvid_idct_mmx_put(uint8_t *dest, ptrdiff_t line_size, int16_t *block); -void ff_xvid_idct_mmx_add(uint8_t *dest, ptrdiff_t line_size, int16_t *block); - -void ff_xvid_idct_mmxext(short *block); -void ff_xvid_idct_mmxext_put(uint8_t *dest, ptrdiff_t line_size, int16_t *block); -void ff_xvid_idct_mmxext_add(uint8_t *dest, ptrdiff_t line_size, int16_t *block); - void ff_xvid_idct_sse2(short *block); void ff_xvid_idct_put_sse2(uint8_t *dest, ptrdiff_t line_size, short *block); void ff_xvid_idct_add_sse2(uint8_t *dest, ptrdiff_t line_size, short *block); diff --git a/libavcodec/x86/xvididct_init.c b/libavcodec/x86/xvididct_init.c index a91b416b7..fda34cc63 100644 --- a/libavcodec/x86/xvididct_init.c +++ b/libavcodec/x86/xvididct_init.c @@ -23,35 +23,8 @@ #include "libavcodec/idctdsp.h" #include "libavcodec/xvididct.h" -#include "idctdsp.h" #include "xvididct.h" -#if ARCH_X86_32 && HAVE_X86ASM -static void xvid_idct_mmx_put(uint8_t *dest, ptrdiff_t line_size, short *block) -{ - ff_xvid_idct_mmx(block); - ff_put_pixels_clamped_mmx(block, dest, line_size); -} - -static void xvid_idct_mmx_add(uint8_t *dest, ptrdiff_t line_size, short *block) -{ - ff_xvid_idct_mmx(block); - ff_add_pixels_clamped_mmx(block, dest, line_size); -} - -static void xvid_idct_mmxext_put(uint8_t *dest, ptrdiff_t line_size, short *block) -{ - ff_xvid_idct_mmxext(block); - ff_put_pixels_clamped_mmx(block, dest, line_size); -} - -static void xvid_idct_mmxext_add(uint8_t *dest, ptrdiff_t line_size, short *block) -{ - ff_xvid_idct_mmxext(block); - ff_add_pixels_clamped_mmx(block, dest, line_size); -} -#endif - av_cold void ff_xvid_idct_init_x86(IDCTDSPContext *c, AVCodecContext *avctx, unsigned high_bit_depth) { @@ -63,22 +36,6 @@ av_cold void ff_xvid_idct_init_x86(IDCTDSPContext *c, AVCodecContext *avctx, avctx->idct_algo == FF_IDCT_XVID)) return; -#if ARCH_X86_32 - if (EXTERNAL_MMX(cpu_flags)) { - c->idct_put = xvid_idct_mmx_put; - c->idct_add = xvid_idct_mmx_add; - c->idct = ff_xvid_idct_mmx; - c->perm_type = FF_IDCT_PERM_NONE; - } - - if (EXTERNAL_MMXEXT(cpu_flags)) { - c->idct_put = xvid_idct_mmxext_put; - c->idct_add = xvid_idct_mmxext_add; - c->idct = ff_xvid_idct_mmxext; - c->perm_type = FF_IDCT_PERM_NONE; - } -#endif - if (EXTERNAL_SSE2(cpu_flags)) { c->idct_put = ff_xvid_idct_put_sse2; c->idct_add = ff_xvid_idct_add_sse2; diff --git a/libavcodec/xan.c b/libavcodec/xan.c index 7ab43db1e..3386a702b 100644 --- a/libavcodec/xan.c +++ b/libavcodec/xan.c @@ -38,6 +38,7 @@ #define BITSTREAM_READER_LE #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "get_bits.h" #include "internal.h" @@ -537,11 +538,9 @@ static const uint8_t gamma_lookup[256] = { }; #endif -static int xan_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int xan_decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int ret, buf_size = avpkt->size; XanContext *s = avctx->priv_data; @@ -635,15 +634,15 @@ static int xan_decode_frame(AVCodecContext *avctx, return buf_size; } -const AVCodec ff_xan_wc3_decoder = { - .name = "xan_wc3", - .long_name = NULL_IF_CONFIG_SMALL("Wing Commander III / Xan"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_XAN_WC3, +const FFCodec ff_xan_wc3_decoder = { + .p.name = "xan_wc3", + .p.long_name = NULL_IF_CONFIG_SMALL("Wing Commander III / Xan"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_XAN_WC3, .priv_data_size = sizeof(XanContext), .init = xan_decode_init, .close = xan_decode_end, - .decode = xan_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(xan_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/xbmdec.c b/libavcodec/xbmdec.c index bed68c33e..62ce46f3a 100644 --- a/libavcodec/xbmdec.c +++ b/libavcodec/xbmdec.c @@ -21,8 +21,10 @@ */ #include "libavutil/avstring.h" +#include "libavutil/reverse.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #include "mathops.h" @@ -63,10 +65,9 @@ static int parse_str_int(const uint8_t *p, const uint8_t *end, const uint8_t *ke return INT_MIN; } -static int xbm_decode_frame(AVCodecContext *avctx, void *data, +static int xbm_decode_frame(AVCodecContext *avctx, AVFrame *p, int *got_frame, AVPacket *avpkt) { - AVFrame *p = data; int ret, linesize, i, j; int width = 0; int height = 0; @@ -136,11 +137,11 @@ static int xbm_decode_frame(AVCodecContext *avctx, void *data, return avpkt->size; } -const AVCodec ff_xbm_decoder = { - .name = "xbm", - .long_name = NULL_IF_CONFIG_SMALL("XBM (X BitMap) image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_XBM, - .decode = xbm_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, +const FFCodec ff_xbm_decoder = { + .p.name = "xbm", + .p.long_name = NULL_IF_CONFIG_SMALL("XBM (X BitMap) image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_XBM, + .p.capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(xbm_decode_frame), }; diff --git a/libavcodec/xbmenc.c b/libavcodec/xbmenc.c index 5e552ce82..60fb16945 100644 --- a/libavcodec/xbmenc.c +++ b/libavcodec/xbmenc.c @@ -20,9 +20,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/reverse.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "mathops.h" #define ANSI_MIN_READLINE 509 @@ -75,12 +76,12 @@ static int xbm_encode_frame(AVCodecContext *avctx, AVPacket *pkt, return 0; } -const AVCodec ff_xbm_encoder = { - .name = "xbm", - .long_name = NULL_IF_CONFIG_SMALL("XBM (X BitMap) image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_XBM, - .encode2 = xbm_encode_frame, - .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_MONOWHITE, +const FFCodec ff_xbm_encoder = { + .p.name = "xbm", + .p.long_name = NULL_IF_CONFIG_SMALL("XBM (X BitMap) image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_XBM, + FF_CODEC_ENCODE_CB(xbm_encode_frame), + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_MONOWHITE, AV_PIX_FMT_NONE }, }; diff --git a/libavcodec/xfacedec.c b/libavcodec/xfacedec.c index 27295ff51..f15bc2d77 100644 --- a/libavcodec/xfacedec.c +++ b/libavcodec/xfacedec.c @@ -27,6 +27,7 @@ #include "libavutil/pixdesc.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" #include "xface.h" @@ -108,9 +109,8 @@ static av_cold int xface_decode_init(AVCodecContext *avctx) return 0; } -static int xface_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int xface_decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { XFaceContext *xface = avctx->priv_data; int ret, i, j, k; @@ -118,7 +118,6 @@ static int xface_decode_frame(AVCodecContext *avctx, BigInt b = {0}; char *buf; int64_t c; - AVFrame *frame = data; if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; @@ -176,14 +175,15 @@ static int xface_decode_frame(AVCodecContext *avctx, return avpkt->size; } -const AVCodec ff_xface_decoder = { - .name = "xface", - .long_name = NULL_IF_CONFIG_SMALL("X-face image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_XFACE, +const FFCodec ff_xface_decoder = { + .p.name = "xface", + .p.long_name = NULL_IF_CONFIG_SMALL("X-face image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_XFACE, + .p.capabilities = AV_CODEC_CAP_DR1, .priv_data_size = sizeof(XFaceContext), .init = xface_decode_init, - .decode = xface_decode_frame, - .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_MONOWHITE, AV_PIX_FMT_NONE }, + FF_CODEC_DECODE_CB(xface_decode_frame), + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_MONOWHITE, AV_PIX_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/xfaceenc.c b/libavcodec/xfaceenc.c index 55815e5c2..a46b7133e 100644 --- a/libavcodec/xfaceenc.c +++ b/libavcodec/xfaceenc.c @@ -26,8 +26,8 @@ #include "xface.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "libavutil/avassert.h" typedef struct XFaceContext { @@ -211,13 +211,13 @@ static int xface_encode_frame(AVCodecContext *avctx, AVPacket *pkt, return 0; } -const AVCodec ff_xface_encoder = { - .name = "xface", - .long_name = NULL_IF_CONFIG_SMALL("X-face image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_XFACE, - .capabilities = AV_CODEC_CAP_DR1, +const FFCodec ff_xface_encoder = { + .p.name = "xface", + .p.long_name = NULL_IF_CONFIG_SMALL("X-face image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_XFACE, + .p.capabilities = AV_CODEC_CAP_DR1, + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_MONOWHITE, AV_PIX_FMT_NONE }, .priv_data_size = sizeof(XFaceContext), - .encode2 = xface_encode_frame, - .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_MONOWHITE, AV_PIX_FMT_NONE }, + FF_CODEC_ENCODE_CB(xface_encode_frame), }; diff --git a/libavcodec/xiph.c b/libavcodec/xiph.c index 3073315e6..218b0813e 100644 --- a/libavcodec/xiph.c +++ b/libavcodec/xiph.c @@ -18,6 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include +#include "libavutil/error.h" #include "libavutil/intreadwrite.h" #include "xiph.h" diff --git a/libavcodec/xiph.h b/libavcodec/xiph.h index 1741a51b6..4ab246952 100644 --- a/libavcodec/xiph.h +++ b/libavcodec/xiph.h @@ -21,7 +21,7 @@ #ifndef AVCODEC_XIPH_H #define AVCODEC_XIPH_H -#include "libavutil/common.h" +#include /** * Split a single extradata buffer into the three headers that most diff --git a/libavcodec/xl.c b/libavcodec/xl.c index 25e5a6444..d2037b9f0 100644 --- a/libavcodec/xl.c +++ b/libavcodec/xl.c @@ -27,6 +27,7 @@ #include "libavutil/common.h" #include "libavutil/intreadwrite.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" static const int xl_table[32] = { @@ -36,13 +37,11 @@ static const int xl_table[32] = { 120, 121, 122, 123, 124, 125, 126, 127 }; -static int decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *p, + int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; - AVFrame *const p = data; uint8_t *Y, *U, *V; int i, j, ret; int stride; @@ -127,13 +126,13 @@ static av_cold int decode_init(AVCodecContext *avctx) return 0; } -const AVCodec ff_xl_decoder = { - .name = "xl", - .long_name = NULL_IF_CONFIG_SMALL("Miro VideoXL"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_VIXL, +const FFCodec ff_xl_decoder = { + .p.name = "xl", + .p.long_name = NULL_IF_CONFIG_SMALL("Miro VideoXL"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_VIXL, .init = decode_init, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/xpmdec.c b/libavcodec/xpmdec.c index a11926ba2..26d076d2e 100644 --- a/libavcodec/xpmdec.c +++ b/libavcodec/xpmdec.c @@ -24,6 +24,7 @@ #include "libavutil/parseutils.h" #include "libavutil/avstring.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" #define MIN_ELEMENT ' ' @@ -302,11 +303,10 @@ static int ascii2index(const uint8_t *cpixel, int cpp) return n; } -static int xpm_decode_frame(AVCodecContext *avctx, void *data, +static int xpm_decode_frame(AVCodecContext *avctx, AVFrame *p, int *got_frame, AVPacket *avpkt) { XPMDecContext *x = avctx->priv_data; - AVFrame *p=data; const uint8_t *end, *ptr; int ncolors, cpp, ret, i, j; int64_t size; @@ -436,13 +436,13 @@ static av_cold int xpm_decode_close(AVCodecContext *avctx) return 0; } -const AVCodec ff_xpm_decoder = { - .name = "xpm", - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_XPM, +const FFCodec ff_xpm_decoder = { + .p.name = "xpm", + .p.long_name = NULL_IF_CONFIG_SMALL("XPM (X PixMap) image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_XPM, + .p.capabilities = AV_CODEC_CAP_DR1, .priv_data_size = sizeof(XPMDecContext), .close = xpm_decode_close, - .decode = xpm_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, - .long_name = NULL_IF_CONFIG_SMALL("XPM (X PixMap) image") + FF_CODEC_DECODE_CB(xpm_decode_frame), }; diff --git a/libavcodec/xsubdec.c b/libavcodec/xsubdec.c index 85cd7d1c2..d62fa164a 100644 --- a/libavcodec/xsubdec.c +++ b/libavcodec/xsubdec.c @@ -24,7 +24,7 @@ #include "avcodec.h" #include "get_bits.h" #include "bytestream.h" -#include "internal.h" +#include "codec_internal.h" static av_cold int decode_init(AVCodecContext *avctx) { avctx->pix_fmt = AV_PIX_FMT_PAL8; @@ -47,11 +47,11 @@ static int64_t parse_timecode(const uint8_t *buf, int64_t packet_time) { return ms - packet_time; } -static int decode_frame(AVCodecContext *avctx, void *data, int *got_sub_ptr, - AVPacket *avpkt) { +static int decode_frame(AVCodecContext *avctx, AVSubtitle *sub, + int *got_sub_ptr, const AVPacket *avpkt) +{ const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; - AVSubtitle *sub = data; AVSubtitleRect *rect; const uint8_t *buf_end = buf + buf_size; uint8_t *bitmap; @@ -154,12 +154,12 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_sub_ptr, return buf_size; } -const AVCodec ff_xsub_decoder = { - .name = "xsub", - .long_name = NULL_IF_CONFIG_SMALL("XSUB"), - .type = AVMEDIA_TYPE_SUBTITLE, - .id = AV_CODEC_ID_XSUB, +const FFCodec ff_xsub_decoder = { + .p.name = "xsub", + .p.long_name = NULL_IF_CONFIG_SMALL("XSUB"), + .p.type = AVMEDIA_TYPE_SUBTITLE, + .p.id = AV_CODEC_ID_XSUB, .init = decode_init, - .decode = decode_frame, + FF_CODEC_DECODE_SUB_CB(decode_frame), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/xsubenc.c b/libavcodec/xsubenc.c index 03d0dc2d8..8ca411e5a 100644 --- a/libavcodec/xsubenc.c +++ b/libavcodec/xsubenc.c @@ -22,7 +22,7 @@ #include "avcodec.h" #include "bytestream.h" -#include "internal.h" +#include "codec_internal.h" #include "put_bits.h" /** @@ -211,12 +211,12 @@ static av_cold int xsub_encoder_init(AVCodecContext *avctx) return 0; } -const AVCodec ff_xsub_encoder = { - .name = "xsub", - .long_name = NULL_IF_CONFIG_SMALL("DivX subtitles (XSUB)"), - .type = AVMEDIA_TYPE_SUBTITLE, - .id = AV_CODEC_ID_XSUB, +const FFCodec ff_xsub_encoder = { + .p.name = "xsub", + .p.long_name = NULL_IF_CONFIG_SMALL("DivX subtitles (XSUB)"), + .p.type = AVMEDIA_TYPE_SUBTITLE, + .p.id = AV_CODEC_ID_XSUB, .init = xsub_encoder_init, - .encode_sub = xsub_encode, + FF_CODEC_ENCODE_SUB_CB(xsub_encode), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/xvididct.c b/libavcodec/xvididct.c index 360deb324..f338901ab 100644 --- a/libavcodec/xvididct.c +++ b/libavcodec/xvididct.c @@ -346,10 +346,11 @@ av_cold void ff_xvid_idct_init(IDCTDSPContext *c, AVCodecContext *avctx) c->perm_type = FF_IDCT_PERM_NONE; } - if (ARCH_X86) - ff_xvid_idct_init_x86(c, avctx, high_bit_depth); - if (ARCH_MIPS) - ff_xvid_idct_init_mips(c, avctx, high_bit_depth); +#if ARCH_X86 + ff_xvid_idct_init_x86(c, avctx, high_bit_depth); +#elif ARCH_MIPS + ff_xvid_idct_init_mips(c, avctx, high_bit_depth); +#endif ff_init_scantable_permutation(c->idct_permutation, c->perm_type); } diff --git a/libavcodec/xvmc.h b/libavcodec/xvmc.h index 465ee78d6..52e70c0d7 100644 --- a/libavcodec/xvmc.h +++ b/libavcodec/xvmc.h @@ -27,10 +27,11 @@ * Public libavcodec XvMC header. */ +#pragma message("XvMC is no longer supported; this header is deprecated and will be removed") + #include #include "libavutil/attributes.h" -#include "version.h" #include "avcodec.h" /** diff --git a/libavcodec/xwddec.c b/libavcodec/xwddec.c index 7b8228332..f8afab598 100644 --- a/libavcodec/xwddec.c +++ b/libavcodec/xwddec.c @@ -25,13 +25,13 @@ #include "libavutil/imgutils.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" #include "xwd.h" -static int xwd_decode_frame(AVCodecContext *avctx, void *data, +static int xwd_decode_frame(AVCodecContext *avctx, AVFrame *p, int *got_frame, AVPacket *avpkt) { - AVFrame *p = data; const uint8_t *buf = avpkt->data; int i, ret, buf_size = avpkt->size; uint32_t version, header_size, vclass, ncolors; @@ -247,11 +247,11 @@ static int xwd_decode_frame(AVCodecContext *avctx, void *data, return buf_size; } -const AVCodec ff_xwd_decoder = { - .name = "xwd", - .long_name = NULL_IF_CONFIG_SMALL("XWD (X Window Dump) image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_XWD, - .decode = xwd_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, +const FFCodec ff_xwd_decoder = { + .p.name = "xwd", + .p.long_name = NULL_IF_CONFIG_SMALL("XWD (X Window Dump) image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_XWD, + .p.capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(xwd_decode_frame), }; diff --git a/libavcodec/xwdenc.c b/libavcodec/xwdenc.c index a65f83abd..0c6dfc656 100644 --- a/libavcodec/xwdenc.c +++ b/libavcodec/xwdenc.c @@ -20,12 +20,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/intreadwrite.h" #include "libavutil/pixdesc.h" #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" #include "xwd.h" #define WINDOW_NAME "lavcxwdenc" @@ -215,14 +214,14 @@ static int xwd_encode_frame(AVCodecContext *avctx, AVPacket *pkt, return 0; } -const AVCodec ff_xwd_encoder = { - .name = "xwd", - .long_name = NULL_IF_CONFIG_SMALL("XWD (X Window Dump) image"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_XWD, - .capabilities = AV_CODEC_CAP_DR1, - .encode2 = xwd_encode_frame, - .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_BGRA, +const FFCodec ff_xwd_encoder = { + .p.name = "xwd", + .p.long_name = NULL_IF_CONFIG_SMALL("XWD (X Window Dump) image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_XWD, + .p.capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_ENCODE_CB(xwd_encode_frame), + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_BGRA, AV_PIX_FMT_RGBA, AV_PIX_FMT_ARGB, AV_PIX_FMT_ABGR, diff --git a/libavcodec/xxan.c b/libavcodec/xxan.c index 7c4aaf281..d73bd4628 100644 --- a/libavcodec/xxan.c +++ b/libavcodec/xxan.c @@ -25,6 +25,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "codec_internal.h" #include "internal.h" typedef struct XanContext { @@ -398,9 +399,8 @@ static int xan_decode_frame_type1(AVCodecContext *avctx) return 0; } -static int xan_decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int xan_decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *avpkt) { XanContext *s = avctx->priv_data; int ftype; @@ -425,7 +425,7 @@ static int xan_decode_frame(AVCodecContext *avctx, if (ret) return ret; - if ((ret = av_frame_ref(data, s->pic)) < 0) + if ((ret = av_frame_ref(rframe, s->pic)) < 0) return ret; *got_frame = 1; @@ -433,15 +433,15 @@ static int xan_decode_frame(AVCodecContext *avctx, return avpkt->size; } -const AVCodec ff_xan_wc4_decoder = { - .name = "xan_wc4", - .long_name = NULL_IF_CONFIG_SMALL("Wing Commander IV / Xxan"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_XAN_WC4, +const FFCodec ff_xan_wc4_decoder = { + .p.name = "xan_wc4", + .p.long_name = NULL_IF_CONFIG_SMALL("Wing Commander IV / Xxan"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_XAN_WC4, .priv_data_size = sizeof(XanContext), .init = xan_decode_init, .close = xan_decode_end, - .decode = xan_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(xan_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/y41pdec.c b/libavcodec/y41pdec.c index e63d184f2..4b1e64aff 100644 --- a/libavcodec/y41pdec.c +++ b/libavcodec/y41pdec.c @@ -21,6 +21,7 @@ */ #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" static av_cold int y41p_decode_init(AVCodecContext *avctx) @@ -35,11 +36,10 @@ static av_cold int y41p_decode_init(AVCodecContext *avctx) return 0; } -static int y41p_decode_frame(AVCodecContext *avctx, void *data, +static int y41p_decode_frame(AVCodecContext *avctx, AVFrame *pic, int *got_frame, AVPacket *avpkt) { - AVFrame *pic = data; - uint8_t *src = avpkt->data; + const uint8_t *src = avpkt->data; uint8_t *y, *u, *v; int i, j, ret; @@ -81,13 +81,13 @@ static int y41p_decode_frame(AVCodecContext *avctx, void *data, return avpkt->size; } -const AVCodec ff_y41p_decoder = { - .name = "y41p", - .long_name = NULL_IF_CONFIG_SMALL("Uncompressed YUV 4:1:1 12-bit"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_Y41P, +const FFCodec ff_y41p_decoder = { + .p.name = "y41p", + .p.long_name = NULL_IF_CONFIG_SMALL("Uncompressed YUV 4:1:1 12-bit"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_Y41P, .init = y41p_decode_init, - .decode = y41p_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(y41p_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/y41penc.c b/libavcodec/y41penc.c index c5b211a1c..390bd10ba 100644 --- a/libavcodec/y41penc.c +++ b/libavcodec/y41penc.c @@ -21,6 +21,7 @@ */ #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" #include "internal.h" @@ -76,15 +77,15 @@ static int y41p_encode_frame(AVCodecContext *avctx, AVPacket *pkt, return 0; } -const AVCodec ff_y41p_encoder = { - .name = "y41p", - .long_name = NULL_IF_CONFIG_SMALL("Uncompressed YUV 4:1:1 12-bit"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_Y41P, - .capabilities = AV_CODEC_CAP_DR1, +const FFCodec ff_y41p_encoder = { + .p.name = "y41p", + .p.long_name = NULL_IF_CONFIG_SMALL("Uncompressed YUV 4:1:1 12-bit"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_Y41P, + .p.capabilities = AV_CODEC_CAP_DR1, .init = y41p_encode_init, - .encode2 = y41p_encode_frame, - .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV411P, + FF_CODEC_ENCODE_CB(y41p_encode_frame), + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV411P, AV_PIX_FMT_NONE }, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/ylc.c b/libavcodec/ylc.c index 1c2b5000f..94d0388f3 100644 --- a/libavcodec/ylc.c +++ b/libavcodec/ylc.c @@ -30,9 +30,9 @@ #include "libavutil/mem.h" #include "avcodec.h" #include "bswapdsp.h" +#include "codec_internal.h" #include "get_bits.h" #include "huffyuvdsp.h" -#include "internal.h" #include "thread.h" #include "unary.h" @@ -278,17 +278,14 @@ static const uint8_t table_v[] = { 0x01, 0x00, }; -static int decode_frame(AVCodecContext *avctx, - void *data, int *got_frame, - AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *p, + int *got_frame, AVPacket *avpkt) { int TL[4] = { 128, 128, 128, 128 }; int L[4] = { 128, 128, 128, 128 }; YLCContext *s = avctx->priv_data; - ThreadFrame frame = { .f = data }; const uint8_t *buf = avpkt->data; int ret, x, y, toffset, boffset; - AVFrame * const p = data; GetBitContext gb; uint8_t *dst; @@ -307,7 +304,7 @@ static int decode_frame(AVCodecContext *avctx, if (toffset >= boffset || boffset >= avpkt->size) return AVERROR_INVALIDDATA; - if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + if ((ret = ff_thread_get_buffer(avctx, p, 0)) < 0) return ret; av_fast_malloc(&s->buffer, &s->buffer_size, @@ -452,15 +449,15 @@ static av_cold int decode_end(AVCodecContext *avctx) return 0; } -const AVCodec ff_ylc_decoder = { - .name = "ylc", - .long_name = NULL_IF_CONFIG_SMALL("YUY2 Lossless Codec"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_YLC, +const FFCodec ff_ylc_decoder = { + .p.name = "ylc", + .p.long_name = NULL_IF_CONFIG_SMALL("YUY2 Lossless Codec"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_YLC, .priv_data_size = sizeof(YLCContext), .init = decode_init, .close = decode_end, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/yop.c b/libavcodec/yop.c index 38014edef..7a11ca77b 100644 --- a/libavcodec/yop.c +++ b/libavcodec/yop.c @@ -29,6 +29,7 @@ #include "libavutil/intreadwrite.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" typedef struct YopDecContext { @@ -39,9 +40,9 @@ typedef struct YopDecContext { int first_color[2]; int frame_data_length; - uint8_t *low_nibble; - uint8_t *srcptr; - uint8_t *src_end; + const uint8_t *low_nibble; + const uint8_t *srcptr; + const uint8_t *src_end; uint8_t *dstptr; uint8_t *dstbuf; } YopDecContext; @@ -190,8 +191,8 @@ static uint8_t yop_get_next_nibble(YopDecContext *s) return ret; } -static int yop_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int yop_decode_frame(AVCodecContext *avctx, AVFrame *rframe, + int *got_frame, AVPacket *avpkt) { YopDecContext *s = avctx->priv_data; AVFrame *frame = s->frame; @@ -258,21 +259,21 @@ static int yop_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, s->dstptr += 2*frame->linesize[0] - x; } - if ((ret = av_frame_ref(data, s->frame)) < 0) + if ((ret = av_frame_ref(rframe, s->frame)) < 0) return ret; *got_frame = 1; return avpkt->size; } -const AVCodec ff_yop_decoder = { - .name = "yop", - .long_name = NULL_IF_CONFIG_SMALL("Psygnosis YOP Video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_YOP, +const FFCodec ff_yop_decoder = { + .p.name = "yop", + .p.long_name = NULL_IF_CONFIG_SMALL("Psygnosis YOP Video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_YOP, .priv_data_size = sizeof(YopDecContext), .init = yop_decode_init, .close = yop_decode_close, - .decode = yop_decode_frame, + FF_CODEC_DECODE_CB(yop_decode_frame), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/yuv4dec.c b/libavcodec/yuv4dec.c index b180e96b5..bbd213e69 100644 --- a/libavcodec/yuv4dec.c +++ b/libavcodec/yuv4dec.c @@ -21,6 +21,7 @@ */ #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" static av_cold int yuv4_decode_init(AVCodecContext *avctx) @@ -30,10 +31,9 @@ static av_cold int yuv4_decode_init(AVCodecContext *avctx) return 0; } -static int yuv4_decode_frame(AVCodecContext *avctx, void *data, +static int yuv4_decode_frame(AVCodecContext *avctx, AVFrame *pic, int *got_frame, AVPacket *avpkt) { - AVFrame *pic = data; const uint8_t *src = avpkt->data; uint8_t *y, *u, *v; int i, j, ret; @@ -73,13 +73,13 @@ static int yuv4_decode_frame(AVCodecContext *avctx, void *data, return avpkt->size; } -const AVCodec ff_yuv4_decoder = { - .name = "yuv4", - .long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed 4:2:0"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_YUV4, +const FFCodec ff_yuv4_decoder = { + .p.name = "yuv4", + .p.long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed 4:2:0"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_YUV4, .init = yuv4_decode_init, - .decode = yuv4_decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(yuv4_decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, }; diff --git a/libavcodec/yuv4enc.c b/libavcodec/yuv4enc.c index 5181a4640..8d7238219 100644 --- a/libavcodec/yuv4enc.c +++ b/libavcodec/yuv4enc.c @@ -21,8 +21,8 @@ */ #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" static int yuv4_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pic, int *got_packet) @@ -59,12 +59,12 @@ static int yuv4_encode_frame(AVCodecContext *avctx, AVPacket *pkt, return 0; } -const AVCodec ff_yuv4_encoder = { - .name = "yuv4", - .long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed 4:2:0"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_YUV4, - .capabilities = AV_CODEC_CAP_DR1, - .encode2 = yuv4_encode_frame, - .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, +const FFCodec ff_yuv4_encoder = { + .p.name = "yuv4", + .p.long_name = NULL_IF_CONFIG_SMALL("Uncompressed packed 4:2:0"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_YUV4, + .p.capabilities = AV_CODEC_CAP_DR1, + .p.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE }, + FF_CODEC_ENCODE_CB(yuv4_encode_frame), }; diff --git a/libavcodec/zerocodec.c b/libavcodec/zerocodec.c index 3bd04567a..08511ca15 100644 --- a/libavcodec/zerocodec.c +++ b/libavcodec/zerocodec.c @@ -19,21 +19,22 @@ #include #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" +#include "zlib_wrapper.h" #include "libavutil/common.h" typedef struct ZeroCodecContext { AVFrame *previous_frame; - z_stream zstream; + FFZStream zstream; } ZeroCodecContext; -static int zerocodec_decode_frame(AVCodecContext *avctx, void *data, +static int zerocodec_decode_frame(AVCodecContext *avctx, AVFrame *pic, int *got_frame, AVPacket *avpkt) { ZeroCodecContext *zc = avctx->priv_data; - AVFrame *pic = data; AVFrame *prev_pic = zc->previous_frame; - z_stream *zstream = &zc->zstream; + z_stream *const zstream = &zc->zstream.zstream; uint8_t *prev = prev_pic->data[0]; uint8_t *dst; int i, j, zret, ret; @@ -106,7 +107,7 @@ static av_cold int zerocodec_decode_close(AVCodecContext *avctx) av_frame_free(&zc->previous_frame); - inflateEnd(&zc->zstream); + ff_inflate_end(&zc->zstream); return 0; } @@ -114,27 +115,15 @@ static av_cold int zerocodec_decode_close(AVCodecContext *avctx) static av_cold int zerocodec_decode_init(AVCodecContext *avctx) { ZeroCodecContext *zc = avctx->priv_data; - z_stream *zstream = &zc->zstream; - int zret; avctx->pix_fmt = AV_PIX_FMT_UYVY422; avctx->bits_per_raw_sample = 8; - zstream->zalloc = Z_NULL; - zstream->zfree = Z_NULL; - zstream->opaque = Z_NULL; - - zret = inflateInit(zstream); - if (zret != Z_OK) { - av_log(avctx, AV_LOG_ERROR, "Could not initialize inflate: %d.\n", zret); - return AVERROR(ENOMEM); - } - zc->previous_frame = av_frame_alloc(); if (!zc->previous_frame) return AVERROR(ENOMEM); - return 0; + return ff_inflate_init(&zc->zstream, avctx); } static void zerocodec_decode_flush(AVCodecContext *avctx) @@ -144,17 +133,17 @@ static void zerocodec_decode_flush(AVCodecContext *avctx) av_frame_unref(zc->previous_frame); } -const AVCodec ff_zerocodec_decoder = { - .type = AVMEDIA_TYPE_VIDEO, - .name = "zerocodec", - .long_name = NULL_IF_CONFIG_SMALL("ZeroCodec Lossless Video"), - .id = AV_CODEC_ID_ZEROCODEC, +const FFCodec ff_zerocodec_decoder = { + .p.type = AVMEDIA_TYPE_VIDEO, + .p.name = "zerocodec", + .p.long_name = NULL_IF_CONFIG_SMALL("ZeroCodec Lossless Video"), + .p.id = AV_CODEC_ID_ZEROCODEC, .priv_data_size = sizeof(ZeroCodecContext), .init = zerocodec_decode_init, - .decode = zerocodec_decode_frame, + FF_CODEC_DECODE_CB(zerocodec_decode_frame), .flush = zerocodec_decode_flush, .close = zerocodec_decode_close, - .capabilities = AV_CODEC_CAP_DR1, + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/zlib_wrapper.c b/libavcodec/zlib_wrapper.c new file mode 100644 index 000000000..e86c83940 --- /dev/null +++ b/libavcodec/zlib_wrapper.c @@ -0,0 +1,102 @@ +/* + * Wrappers for zlib + * Copyright (C) 2022 Andreas Rheinhardt + * + * 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/error.h" +#include "libavutil/log.h" +#include "libavutil/mem.h" +#include "zlib_wrapper.h" + +static void *alloc_wrapper(void *opaque, uInt items, uInt size) +{ + return av_malloc_array(items, size); +} + +static void free_wrapper(void *opaque, void *ptr) +{ + av_free(ptr); +} + +#if CONFIG_INFLATE_WRAPPER +int ff_inflate_init(FFZStream *z, void *logctx) +{ + z_stream *const zstream = &z->zstream; + int zret; + + z->inited = 0; + zstream->next_in = Z_NULL; + zstream->avail_in = 0; + zstream->zalloc = alloc_wrapper; + zstream->zfree = free_wrapper; + zstream->opaque = Z_NULL; + + zret = inflateInit(zstream); + if (zret == Z_OK) { + z->inited = 1; + } else { + av_log(logctx, AV_LOG_ERROR, "inflateInit error %d, message: %s\n", + zret, zstream->msg ? zstream->msg : ""); + return AVERROR_EXTERNAL; + } + return 0; +} + +void ff_inflate_end(FFZStream *z) +{ + if (z->inited) { + z->inited = 0; + inflateEnd(&z->zstream); + } +} +#endif + +#if CONFIG_DEFLATE_WRAPPER +int ff_deflate_init(FFZStream *z, int level, void *logctx) +{ + z_stream *const zstream = &z->zstream; + int zret; + + z->inited = 0; + zstream->zalloc = alloc_wrapper; + zstream->zfree = free_wrapper; + zstream->opaque = Z_NULL; + + zret = deflateInit(zstream, level); + if (zret == Z_OK) { + z->inited = 1; + } else { + av_log(logctx, AV_LOG_ERROR, "deflateInit error %d, message: %s\n", + zret, zstream->msg ? zstream->msg : ""); + return AVERROR_EXTERNAL; + } + return 0; +} + +void ff_deflate_end(FFZStream *z) +{ + if (z->inited) { + z->inited = 0; + deflateEnd(&z->zstream); + } +} +#endif diff --git a/libavcodec/zlib_wrapper.h b/libavcodec/zlib_wrapper.h new file mode 100644 index 000000000..fa8ee654f --- /dev/null +++ b/libavcodec/zlib_wrapper.h @@ -0,0 +1,61 @@ +/* + * Wrappers for zlib + * Copyright (C) 2022 Andreas Rheinhardt + * + * 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_ZLIB_WRAPPER_H +#define AVCODEC_ZLIB_WRAPPER_H + +#include + +typedef struct FFZStream { + z_stream zstream; + int inited; +} FFZStream; + +/** + * Wrapper around inflateInit(). It initializes the fields that zlib + * requires to be initialized before inflateInit(). + * In case of error it also returns an error message to the provided logctx; + * in any case, it sets zstream->inited to indicate whether inflateInit() + * succeeded. + * @return Returns 0 on success or a negative error code on failure + */ +int ff_inflate_init(FFZStream *zstream, void *logctx); + +/** + * Wrapper around inflateEnd(). It calls inflateEnd() iff + * zstream->inited is set and resets zstream->inited. + * It is therefore safe to be called even if + * ff_inflate_init() has never been called on it (or errored out) + * provided that the FFZStream (or just FFZStream.inited) has been zeroed. + */ +void ff_inflate_end(FFZStream *zstream); + +/** + * Wrapper around deflateInit(). It works analogously to ff_inflate_init(). + */ +int ff_deflate_init(FFZStream *zstream, int level, void *logctx); + +/** + * Wrapper around deflateEnd(). It works analogously to ff_inflate_end(). + */ +void ff_deflate_end(FFZStream *zstream); + +#endif /* AVCODEC_ZLIB_WRAPPER_H */ diff --git a/libavcodec/zmbv.c b/libavcodec/zmbv.c index 0a5bb40ad..37c18e3a1 100644 --- a/libavcodec/zmbv.c +++ b/libavcodec/zmbv.c @@ -31,7 +31,9 @@ #include "libavutil/imgutils.h" #include "libavutil/intreadwrite.h" #include "avcodec.h" +#include "codec_internal.h" #include "internal.h" +#include "zlib_wrapper.h" #include @@ -56,7 +58,6 @@ enum ZmbvFormat { typedef struct ZmbvContext { AVCodecContext *avctx; - int zlib_init_ok; int bpp; int alloc_bpp; unsigned int decomp_size; @@ -71,7 +72,7 @@ typedef struct ZmbvContext { int bw, bh, bx, by; int decomp_len; int got_keyframe; - z_stream zstream; + FFZStream zstream; int (*decode_xor)(struct ZmbvContext *c); } ZmbvContext; @@ -409,9 +410,9 @@ static int zmbv_decode_intra(ZmbvContext *c) return 0; } -static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) +static int decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame, AVPacket *avpkt) { - AVFrame *frame = data; const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; ZmbvContext * const c = avctx->priv_data; @@ -493,7 +494,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPac return AVERROR_PATCHWELCOME; } - zret = inflateReset(&c->zstream); + zret = inflateReset(&c->zstream.zstream); if (zret != Z_OK) { av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", zret); return AVERROR_UNKNOWN; @@ -536,17 +537,19 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPac memcpy(c->decomp_buf, buf, len); c->decomp_len = len; } else { // ZLIB-compressed data - c->zstream.total_in = c->zstream.total_out = 0; - c->zstream.next_in = buf; - c->zstream.avail_in = len; - c->zstream.next_out = c->decomp_buf; - c->zstream.avail_out = c->decomp_size; - zret = inflate(&c->zstream, Z_SYNC_FLUSH); + z_stream *const zstream = &c->zstream.zstream; + + zstream->total_in = zstream->total_out = 0; + zstream->next_in = buf; + zstream->avail_in = len; + zstream->next_out = c->decomp_buf; + zstream->avail_out = c->decomp_size; + zret = inflate(zstream, Z_SYNC_FLUSH); if (zret != Z_OK && zret != Z_STREAM_END) { av_log(avctx, AV_LOG_ERROR, "inflate error %d\n", zret); return AVERROR_INVALIDDATA; } - c->decomp_len = c->zstream.total_out; + c->decomp_len = zstream->total_out; } if (expected_size > c->decomp_len || (c->flags & ZMBV_KEYFRAME) && expected_size < c->decomp_len) { @@ -603,7 +606,6 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPac static av_cold int decode_init(AVCodecContext *avctx) { ZmbvContext * const c = avctx->priv_data; - int zret; // Zlib return code c->avctx = avctx; @@ -627,17 +629,7 @@ static av_cold int decode_init(AVCodecContext *avctx) return AVERROR(ENOMEM); } - c->zstream.zalloc = Z_NULL; - c->zstream.zfree = Z_NULL; - c->zstream.opaque = Z_NULL; - zret = inflateInit(&c->zstream); - if (zret != Z_OK) { - av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret); - return AVERROR_UNKNOWN; - } - c->zlib_init_ok = 1; - - return 0; + return ff_inflate_init(&c->zstream, avctx); } static av_cold int decode_end(AVCodecContext *avctx) @@ -648,21 +640,20 @@ static av_cold int decode_end(AVCodecContext *avctx) av_freep(&c->cur); av_freep(&c->prev); - if (c->zlib_init_ok) - inflateEnd(&c->zstream); + ff_inflate_end(&c->zstream); return 0; } -const AVCodec ff_zmbv_decoder = { - .name = "zmbv", - .long_name = NULL_IF_CONFIG_SMALL("Zip Motion Blocks Video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_ZMBV, +const FFCodec ff_zmbv_decoder = { + .p.name = "zmbv", + .p.long_name = NULL_IF_CONFIG_SMALL("Zip Motion Blocks Video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_ZMBV, .priv_data_size = sizeof(ZmbvContext), .init = decode_init, .close = decode_end, - .decode = decode_frame, - .capabilities = AV_CODEC_CAP_DR1, + FF_CODEC_DECODE_CB(decode_frame), + .p.capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/zmbvenc.c b/libavcodec/zmbvenc.c index 8efdbc963..ef21a189a 100644 --- a/libavcodec/zmbvenc.c +++ b/libavcodec/zmbvenc.c @@ -30,8 +30,9 @@ #include "libavutil/common.h" #include "libavutil/intreadwrite.h" #include "avcodec.h" +#include "codec_internal.h" #include "encode.h" -#include "internal.h" +#include "zlib_wrapper.h" #include @@ -74,8 +75,7 @@ typedef struct ZmbvEncContext { int keyint, curfrm; int bypp; enum ZmbvFormat fmt; - int zlib_init_ok; - z_stream zstream; + FFZStream zstream; int score_tab[ZMBV_BLOCK * ZMBV_BLOCK * 4 + 1]; } ZmbvEncContext; @@ -169,6 +169,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pict, int *got_packet) { ZmbvEncContext * const c = avctx->priv_data; + z_stream *const zstream = &c->zstream.zstream; const AVFrame * const p = pict; uint8_t *src, *prev, *buf; uint32_t *palptr; @@ -262,21 +263,21 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, } if (keyframe) - deflateReset(&c->zstream); + deflateReset(zstream); - c->zstream.next_in = c->work_buf; - c->zstream.avail_in = work_size; - c->zstream.total_in = 0; + zstream->next_in = c->work_buf; + zstream->avail_in = work_size; + zstream->total_in = 0; - c->zstream.next_out = c->comp_buf; - c->zstream.avail_out = c->comp_size; - c->zstream.total_out = 0; - if(deflate(&c->zstream, Z_SYNC_FLUSH) != Z_OK){ + zstream->next_out = c->comp_buf; + zstream->avail_out = c->comp_size; + zstream->total_out = 0; + if (deflate(zstream, Z_SYNC_FLUSH) != Z_OK) { av_log(avctx, AV_LOG_ERROR, "Error compressing data\n"); return -1; } - pkt_size = c->zstream.total_out + 1 + 6*keyframe; + pkt_size = zstream->total_out + 1 + 6 * keyframe; if ((ret = ff_get_encode_buffer(avctx, pkt, pkt_size, 0)) < 0) return ret; buf = pkt->data; @@ -292,7 +293,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, *buf++ = ZMBV_BLOCK; // block height pkt->flags |= AV_PKT_FLAG_KEY; } - memcpy(buf, c->comp_buf, c->zstream.total_out); + memcpy(buf, c->comp_buf, zstream->total_out); *got_packet = 1; @@ -307,8 +308,7 @@ static av_cold int encode_end(AVCodecContext *avctx) av_freep(&c->work_buf); av_freep(&c->prev_buf); - if (c->zlib_init_ok) - deflateEnd(&c->zstream); + ff_deflate_end(&c->zstream); return 0; } @@ -319,7 +319,6 @@ static av_cold int encode_end(AVCodecContext *avctx) static av_cold int encode_init(AVCodecContext *avctx) { ZmbvEncContext * const c = avctx->priv_data; - int zret; // Zlib return code int i; int lvl = 9; int prev_size, prev_offset; @@ -408,30 +407,20 @@ static av_cold int encode_init(AVCodecContext *avctx) } c->prev = c->prev_buf + prev_offset; - c->zstream.zalloc = Z_NULL; - c->zstream.zfree = Z_NULL; - c->zstream.opaque = Z_NULL; - zret = deflateInit(&c->zstream, lvl); - if (zret != Z_OK) { - av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret); - return -1; - } - c->zlib_init_ok = 1; - - return 0; + return ff_deflate_init(&c->zstream, lvl, avctx); } -const AVCodec ff_zmbv_encoder = { - .name = "zmbv", - .long_name = NULL_IF_CONFIG_SMALL("Zip Motion Blocks Video"), - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_ZMBV, - .capabilities = AV_CODEC_CAP_DR1, +const FFCodec ff_zmbv_encoder = { + .p.name = "zmbv", + .p.long_name = NULL_IF_CONFIG_SMALL("Zip Motion Blocks Video"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_ZMBV, + .p.capabilities = AV_CODEC_CAP_DR1, .priv_data_size = sizeof(ZmbvEncContext), .init = encode_init, - .encode2 = encode_frame, + FF_CODEC_ENCODE_CB(encode_frame), .close = encode_end, - .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_PAL8, + .p.pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_PAL8, AV_PIX_FMT_RGB555LE, AV_PIX_FMT_RGB565LE, #ifdef ZMBV_ENABLE_24BPP diff --git a/libavdevice/Makefile b/libavdevice/Makefile index 53efda051..bbe2f69dc 100644 --- a/libavdevice/Makefile +++ b/libavdevice/Makefile @@ -3,10 +3,12 @@ DESC = FFmpeg device handling library HEADERS = avdevice.h \ version.h \ + version_major.h \ OBJS = alldevices.o \ avdevice.o \ utils.o \ + version.o \ OBJS-$(HAVE_LIBC_MSVCRT) += file_open.o diff --git a/libavdevice/alsa.c b/libavdevice/alsa.c index ee282fac1..b055f6c1a 100644 --- a/libavdevice/alsa.c +++ b/libavdevice/alsa.c @@ -28,6 +28,8 @@ * @author Nicolas George ( nicolas george normalesup org ) */ +#include "config_components.h" + #include #include "avdevice.h" #include "libavutil/avassert.h" @@ -124,7 +126,7 @@ switch(format) {\ case FORMAT_F32: s->reorder_func = alsa_reorder_f32_out_ ##layout; break;\ } -static av_cold int find_reorder_func(AlsaData *s, int codec_id, uint64_t layout, int out) +static av_cold int find_reorder_func(AlsaData *s, int codec_id, AVChannelLayout *layout, int out) { int format; @@ -133,7 +135,8 @@ static av_cold int find_reorder_func(AlsaData *s, int codec_id, uint64_t layout, return AVERROR(ENOSYS); /* reordering is not needed for QUAD or 2_2 layout */ - if (layout == AV_CH_LAYOUT_QUAD || layout == AV_CH_LAYOUT_2_2) + if (!av_channel_layout_compare(layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_QUAD) || + !av_channel_layout_compare(layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_2_2)) return 0; switch (codec_id) { @@ -154,11 +157,13 @@ static av_cold int find_reorder_func(AlsaData *s, int codec_id, uint64_t layout, default: return AVERROR(ENOSYS); } - if (layout == AV_CH_LAYOUT_5POINT0_BACK || layout == AV_CH_LAYOUT_5POINT0) + if (!av_channel_layout_compare(layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT0_BACK) || + !av_channel_layout_compare(layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT0)) PICK_REORDER(50) - else if (layout == AV_CH_LAYOUT_5POINT1_BACK || layout == AV_CH_LAYOUT_5POINT1) + else if (!av_channel_layout_compare(layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1_BACK) || + !av_channel_layout_compare(layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1)) PICK_REORDER(51) - else if (layout == AV_CH_LAYOUT_7POINT1) + else if (!av_channel_layout_compare(layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_7POINT1)) PICK_REORDER(71) return s->reorder_func ? 0 : AVERROR(ENOSYS); @@ -169,13 +174,13 @@ av_cold int ff_alsa_open(AVFormatContext *ctx, snd_pcm_stream_t mode, int channels, enum AVCodecID *codec_id) { AlsaData *s = ctx->priv_data; + AVChannelLayout *layout = &ctx->streams[0]->codecpar->ch_layout; const char *audio_device; int res, flags = 0; snd_pcm_format_t format; snd_pcm_t *h; snd_pcm_hw_params_t *hw_params; snd_pcm_uframes_t buffer_size, period_size; - uint64_t layout = ctx->streams[0]->codecpar->channel_layout; if (ctx->url[0] == 0) audio_device = "default"; else audio_device = ctx->url; @@ -271,10 +276,10 @@ av_cold int ff_alsa_open(AVFormatContext *ctx, snd_pcm_stream_t mode, snd_pcm_hw_params_free(hw_params); - if (channels > 2 && layout) { + if (channels > 2 && layout->order != AV_CHANNEL_ORDER_UNSPEC) { if (find_reorder_func(s, *codec_id, layout, mode == SND_PCM_STREAM_PLAYBACK) < 0) { char name[128]; - av_get_channel_layout_string(name, sizeof(name), channels, layout); + av_channel_layout_describe(layout, name, sizeof(name)); av_log(ctx, AV_LOG_WARNING, "ALSA channel layout unknown or unimplemented for %s %s.\n", name, mode == SND_PCM_STREAM_PLAYBACK ? "playback" : "capture"); } diff --git a/libavdevice/alsa_dec.c b/libavdevice/alsa_dec.c index e93f31b14..b518bbdac 100644 --- a/libavdevice/alsa_dec.c +++ b/libavdevice/alsa_dec.c @@ -82,7 +82,7 @@ static av_cold int audio_read_header(AVFormatContext *s1) 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; + st->codecpar->ch_layout.nb_channels = s->channels; st->codecpar->frame_size = s->frame_size; avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ /* microseconds instead of seconds, MHz instead of Hz */ diff --git a/libavdevice/alsa_enc.c b/libavdevice/alsa_enc.c index a783d8eca..ac09e33c4 100644 --- a/libavdevice/alsa_enc.c +++ b/libavdevice/alsa_enc.c @@ -44,6 +44,7 @@ #include "libavformat/internal.h" +#include "libavformat/mux.h" #include "avdevice.h" #include "alsa.h" @@ -64,7 +65,7 @@ static av_cold int audio_write_header(AVFormatContext *s1) 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); + st->codecpar->ch_layout.nb_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", @@ -85,7 +86,7 @@ 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; + const uint8_t *buf = pkt->data; size /= s->frame_size; if (pkt->dts != AV_NOPTS_VALUE) diff --git a/libavdevice/android_camera.c b/libavdevice/android_camera.c index f089d1b6f..1934999c1 100644 --- a/libavdevice/android_camera.c +++ b/libavdevice/android_camera.c @@ -43,8 +43,6 @@ #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 diff --git a/libavdevice/avdevice.c b/libavdevice/avdevice.c index 8f460c756..58996404b 100644 --- a/libavdevice/avdevice.c +++ b/libavdevice/avdevice.c @@ -17,14 +17,8 @@ */ #include "libavutil/avassert.h" -#include "libavutil/samplefmt.h" -#include "libavutil/pixfmt.h" #include "avdevice.h" #include "internal.h" -#include "config.h" - -#include "libavutil/ffversion.h" -const char av_device_ffversion[] = "FFmpeg version " FFMPEG_VERSION; #if FF_API_DEVICE_CAPABILITIES const AVOption av_device_capabilities[] = { @@ -32,23 +26,6 @@ const AVOption av_device_capabilities[] = { }; #endif -unsigned avdevice_version(void) -{ - av_assert0(LIBAVDEVICE_VERSION_MICRO >= 100); - return LIBAVDEVICE_VERSION_INT; -} - -const char * avdevice_configuration(void) -{ - return FFMPEG_CONFIGURATION; -} - -const char * avdevice_license(void) -{ -#define LICENSE_PREFIX "libavdevice license: " - return &LICENSE_PREFIX FFMPEG_LICENSE[sizeof(LICENSE_PREFIX) - 1]; -} - int avdevice_app_to_dev_control_message(struct AVFormatContext *s, enum AVAppToDevMessageType type, void *data, size_t data_size) { @@ -98,9 +75,11 @@ int avdevice_list_devices(AVFormatContext *s, AVDeviceInfoList **device_list) ret = s->oformat->get_device_list(s, *device_list); else ret = s->iformat->get_device_list(s, *device_list); - if (ret < 0) + if (ret < 0) { avdevice_free_list_devices(device_list); - return ret; + return ret; + } + return (*device_list)->nb_devices; } static int list_devices_for_context(AVFormatContext *s, AVDictionary *options, diff --git a/libavdevice/avdevice.h b/libavdevice/avdevice.h index 6f24976dc..0b32e59fe 100644 --- a/libavdevice/avdevice.h +++ b/libavdevice/avdevice.h @@ -19,7 +19,13 @@ #ifndef AVDEVICE_AVDEVICE_H #define AVDEVICE_AVDEVICE_H +#include "version_major.h" +#ifndef HAVE_AV_CONFIG_H +/* When included as part of the ffmpeg build, only include the major version + * to avoid unnecessary rebuilds. When included externally, keep including + * the full version information. */ #include "version.h" +#endif /** * @file diff --git a/libavdevice/avfoundation.m b/libavdevice/avfoundation.m index 0cd6e646d..c9de93f77 100644 --- a/libavdevice/avfoundation.m +++ b/libavdevice/avfoundation.m @@ -106,6 +106,7 @@ typedef struct int audio_device_index; int audio_stream_index; + char *url; char *video_filename; char *audio_filename; @@ -299,6 +300,7 @@ static void destroy_context(AVFContext* ctx) ctx->avf_delegate = NULL; ctx->avf_audio_delegate = NULL; + av_freep(&ctx->url); av_freep(&ctx->audio_buffer); pthread_mutex_destroy(&ctx->frame_lock); @@ -308,18 +310,22 @@ static void destroy_context(AVFContext* ctx) } } -static void parse_device_name(AVFormatContext *s) +static int parse_device_name(AVFormatContext *s) { AVFContext *ctx = (AVFContext*)s->priv_data; - char *tmp = av_strdup(s->url); char *save; - if (tmp[0] != ':') { - ctx->video_filename = av_strtok(tmp, ":", &save); + ctx->url = av_strdup(s->url); + + if (!ctx->url) + return AVERROR(ENOMEM); + if (ctx->url[0] != ':') { + ctx->video_filename = av_strtok(ctx->url, ":", &save); ctx->audio_filename = av_strtok(NULL, ":", &save); } else { - ctx->audio_filename = av_strtok(tmp, ":", &save); + ctx->audio_filename = av_strtok(ctx->url, ":", &save); } + return 0; } /** @@ -758,6 +764,7 @@ static int get_audio_config(AVFormatContext *s) static int avf_read_header(AVFormatContext *s) { + int ret = 0; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; uint32_t num_screens = 0; AVFContext *ctx = (AVFContext*)s->priv_data; @@ -810,7 +817,9 @@ static int avf_read_header(AVFormatContext *s) } // parse input filename for video and audio device - parse_device_name(s); + ret = parse_device_name(s); + if (ret) + goto fail; // check for device index given in filename if (ctx->video_device_index == -1 && ctx->video_filename) { @@ -1000,6 +1009,8 @@ static int avf_read_header(AVFormatContext *s) fail: [pool release]; destroy_context(ctx); + if (ret) + return ret; return AVERROR(EIO); } diff --git a/libavdevice/decklink_common_c.h b/libavdevice/decklink_common_c.h index c2577210a..75896ad32 100644 --- a/libavdevice/decklink_common_c.h +++ b/libavdevice/decklink_common_c.h @@ -23,8 +23,11 @@ #ifndef AVDEVICE_DECKLINK_COMMON_C_H #define AVDEVICE_DECKLINK_COMMON_C_H +#include #include +#include "libavutil/log.h" + typedef enum DecklinkPtsSource { PTS_SRC_AUDIO = 1, PTS_SRC_VIDEO = 2, diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp index c97a72d93..7bf5e3724 100644 --- a/libavdevice/decklink_dec.cpp +++ b/libavdevice/decklink_dec.cpp @@ -1060,7 +1060,7 @@ HRESULT decklink_input_callback::VideoInputFrameArrived( BMDTimeValue audio_pts; //hack among hacks - pkt.size = audioFrame->GetSampleFrameCount() * ctx->audio_st->codecpar->channels * (ctx->audio_depth / 8); + pkt.size = audioFrame->GetSampleFrameCount() * ctx->audio_st->codecpar->ch_layout.nb_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, abs_wallclock, ctx->audio_pts_source, ctx->audio_st->time_base, &initial_audio_pts, cctx->copyts); @@ -1296,7 +1296,7 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; 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; + st->codecpar->ch_layout.nb_channels = cctx->audio_channels; avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ ctx->audio_st=st; @@ -1392,8 +1392,8 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx) ctx->teletext_st = st; } - av_log(avctx, AV_LOG_VERBOSE, "Using %d input audio channels\n", ctx->audio_st->codecpar->channels); - result = ctx->dli->EnableAudioInput(bmdAudioSampleRate48kHz, cctx->audio_depth == 32 ? bmdAudioSampleType32bitInteger : bmdAudioSampleType16bitInteger, ctx->audio_st->codecpar->channels); + av_log(avctx, AV_LOG_VERBOSE, "Using %d input audio channels\n", ctx->audio_st->codecpar->ch_layout.nb_channels); + result = ctx->dli->EnableAudioInput(bmdAudioSampleRate48kHz, cctx->audio_depth == 32 ? bmdAudioSampleType32bitInteger : bmdAudioSampleType16bitInteger, ctx->audio_st->codecpar->ch_layout.nb_channels); if (result != S_OK) { av_log(avctx, AV_LOG_ERROR, "Cannot enable audio input\n"); diff --git a/libavdevice/decklink_dec.h b/libavdevice/decklink_dec.h index fbfbe6280..19757be45 100644 --- a/libavdevice/decklink_dec.h +++ b/libavdevice/decklink_dec.h @@ -26,6 +26,8 @@ extern "C" { #endif +#include "libavformat/avformat.h" + int ff_decklink_read_header(AVFormatContext *avctx); int ff_decklink_read_packet(AVFormatContext *avctx, AVPacket *pkt); int ff_decklink_read_close(AVFormatContext *avctx); diff --git a/libavdevice/decklink_enc.cpp b/libavdevice/decklink_enc.cpp index 6dec5f35e..fb686b903 100644 --- a/libavdevice/decklink_enc.cpp +++ b/libavdevice/decklink_enc.cpp @@ -248,14 +248,14 @@ static int decklink_setup_audio(AVFormatContext *avctx, AVStream *st) " Only 48kHz is supported.\n"); return -1; } - if (c->channels != 2 && c->channels != 8 && c->channels != 16) { + if (c->ch_layout.nb_channels != 2 && c->ch_layout.nb_channels != 8 && c->ch_layout.nb_channels != 16) { av_log(avctx, AV_LOG_ERROR, "Unsupported number of channels!" " Only 2, 8 or 16 channels are supported.\n"); return -1; } if (ctx->dlo->EnableAudioOutput(bmdAudioSampleRate48kHz, bmdAudioSampleType16bitInteger, - c->channels, + c->ch_layout.nb_channels, bmdAudioOutputStreamTimestamped) != S_OK) { av_log(avctx, AV_LOG_ERROR, "Could not enable audio output!\n"); return -1; @@ -267,7 +267,7 @@ static int decklink_setup_audio(AVFormatContext *avctx, AVStream *st) /* The device expects the sample rate to be fixed. */ avpriv_set_pts_info(st, 64, 1, c->sample_rate); - ctx->channels = c->channels; + ctx->channels = c->ch_layout.nb_channels; ctx->audio = 1; diff --git a/libavdevice/decklink_enc.h b/libavdevice/decklink_enc.h index 39237673b..5798f19df 100644 --- a/libavdevice/decklink_enc.h +++ b/libavdevice/decklink_enc.h @@ -26,6 +26,8 @@ extern "C" { #endif +#include "libavformat/avformat.h" + int ff_decklink_write_header(AVFormatContext *avctx); int ff_decklink_write_packet(AVFormatContext *avctx, AVPacket *pkt); int ff_decklink_write_trailer(AVFormatContext *avctx); diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index dc20d76b6..5946a72cc 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -552,8 +552,8 @@ dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum, if (!device) goto fail; - device->device_name = av_strdup(friendly_name); - device->device_description = av_strdup(unique_name); + device->device_name = av_strdup(unique_name); + device->device_description = av_strdup(friendly_name); if (!device->device_name || !device->device_description) goto fail; @@ -1003,9 +1003,9 @@ dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype, continue; } if ( - (ctx->sample_rate && ctx->sample_rate != fx->nSamplesPerSec) || - (ctx->sample_size && ctx->sample_size != fx->wBitsPerSample) || - (ctx->channels && ctx->channels != fx->nChannels ) + (requested_sample_rate && requested_sample_rate != fx->nSamplesPerSec) || + (requested_sample_size && requested_sample_size != fx->wBitsPerSample) || + (requested_channels && requested_channels != fx->nChannels ) ) { goto next; } @@ -1621,7 +1621,7 @@ dshow_add_device(AVFormatContext *avctx, par->format = sample_fmt_bits_per_sample(fmt_info->sample_size); par->codec_id = waveform_codec_id(par->format); par->sample_rate = fmt_info->sample_rate; - par->channels = fmt_info->channels; + par->ch_layout.nb_channels = fmt_info->channels; } avpriv_set_pts_info(st, 64, 1, 10000000); diff --git a/libavdevice/fbdev_enc.c b/libavdevice/fbdev_enc.c index 898a630aa..84ec6733f 100644 --- a/libavdevice/fbdev_enc.c +++ b/libavdevice/fbdev_enc.c @@ -100,7 +100,8 @@ static av_cold int fbdev_write_header(AVFormatContext *h) static int fbdev_write_packet(AVFormatContext *h, AVPacket *pkt) { FBDevContext *fbdev = h->priv_data; - uint8_t *pin, *pout; + const uint8_t *pin; + uint8_t *pout; enum AVPixelFormat fb_pix_fmt; int disp_height; int bytes_to_copy; diff --git a/libavdevice/iec61883.c b/libavdevice/iec61883.c index 72e14abff..7223ba2e6 100644 --- a/libavdevice/iec61883.c +++ b/libavdevice/iec61883.c @@ -23,6 +23,8 @@ * libiec61883 interface */ +#include "config_components.h" + #include #include #include diff --git a/libavdevice/jack.c b/libavdevice/jack.c index 0d5465e40..e34eb8961 100644 --- a/libavdevice/jack.c +++ b/libavdevice/jack.c @@ -50,8 +50,8 @@ typedef struct JackData { jack_port_t ** ports; int nports; TimeFilter * timefilter; - AVFifoBuffer * new_pkts; - AVFifoBuffer * filled_pkts; + AVFifo * new_pkts; + AVFifo * filled_pkts; int pkt_xrun; int jack_xrun; } JackData; @@ -81,13 +81,14 @@ static int process_callback(jack_nframes_t nframes, void *arg) self->buffer_size); /* Check if an empty packet is available, and if there's enough space to send it back once filled */ - if ((av_fifo_size(self->new_pkts) < sizeof(pkt)) || (av_fifo_space(self->filled_pkts) < sizeof(pkt))) { + if (!av_fifo_can_read(self->new_pkts) || + !av_fifo_can_write(self->filled_pkts)) { self->pkt_xrun = 1; return 0; } /* Retrieve empty (but allocated) packet */ - av_fifo_generic_read(self->new_pkts, &pkt, sizeof(pkt), NULL); + av_fifo_read(self->new_pkts, &pkt, 1); pkt_data = (float *) pkt.data; latency = 0; @@ -106,7 +107,7 @@ static int process_callback(jack_nframes_t nframes, void *arg) pkt.pts = (cycle_time - (double) latency / (self->nports * self->sample_rate)) * 1000000.0; /* Send the now filled packet back, and increase packet counter */ - av_fifo_generic_write(self->filled_pkts, &pkt, sizeof(pkt), NULL); + av_fifo_write(self->filled_pkts, &pkt, 1); sem_post(&self->packet_count); return 0; @@ -134,12 +135,12 @@ static int supply_new_packets(JackData *self, AVFormatContext *context) /* Supply the process callback with new empty packets, by filling the new * packets FIFO buffer with as many packets as possible. process_callback() * can't do this by itself, because it can't allocate memory in realtime. */ - while (av_fifo_space(self->new_pkts) >= sizeof(pkt)) { + while (av_fifo_can_write(self->new_pkts)) { if ((test = av_new_packet(&pkt, pkt_size)) < 0) { av_log(context, AV_LOG_ERROR, "Could not create packet of size %d\n", pkt_size); return test; } - av_fifo_generic_write(self->new_pkts, &pkt, sizeof(pkt), NULL); + av_fifo_write(self->new_pkts, &pkt, 1); } return 0; } @@ -193,9 +194,9 @@ static int start_jack(AVFormatContext *context) } /* Create FIFO buffers */ - self->filled_pkts = av_fifo_alloc_array(FIFO_PACKETS_NUM, sizeof(AVPacket)); + self->filled_pkts = av_fifo_alloc2(FIFO_PACKETS_NUM, sizeof(AVPacket), 0); /* New packets FIFO with one extra packet for safety against underruns */ - self->new_pkts = av_fifo_alloc_array((FIFO_PACKETS_NUM + 1), sizeof(AVPacket)); + self->new_pkts = av_fifo_alloc2((FIFO_PACKETS_NUM + 1), sizeof(AVPacket), 0); if (!self->new_pkts) { jack_client_close(self->client); return AVERROR(ENOMEM); @@ -209,14 +210,13 @@ static int start_jack(AVFormatContext *context) } -static void free_pkt_fifo(AVFifoBuffer **fifo) +static void free_pkt_fifo(AVFifo **fifop) { + AVFifo *fifo = *fifop; AVPacket pkt; - while (av_fifo_size(*fifo)) { - av_fifo_generic_read(*fifo, &pkt, sizeof(pkt), NULL); + while (av_fifo_read(fifo, &pkt, 1) >= 0) av_packet_unref(&pkt); - } - av_fifo_freep(fifo); + av_fifo_freep2(fifop); } static void stop_jack(JackData *self) @@ -255,7 +255,7 @@ static int audio_read_header(AVFormatContext *context) stream->codecpar->codec_id = AV_CODEC_ID_PCM_F32LE; #endif stream->codecpar->sample_rate = self->sample_rate; - stream->codecpar->channels = self->nports; + stream->codecpar->ch_layout.nb_channels = self->nports; avpriv_set_pts_info(stream, 64, 1, 1000000); /* 64 bits pts in us */ return 0; @@ -313,7 +313,7 @@ static int audio_read_packet(AVFormatContext *context, AVPacket *pkt) } /* Retrieve the packet filled with audio data by process_callback() */ - av_fifo_generic_read(self->filled_pkts, pkt, sizeof(*pkt), NULL); + av_fifo_read(self->filled_pkts, pkt, 1); if ((test = supply_new_packets(self, context))) return test; diff --git a/libavdevice/lavfi.c b/libavdevice/lavfi.c index 710ad7c53..db5d0b94d 100644 --- a/libavdevice/lavfi.c +++ b/libavdevice/lavfi.c @@ -332,9 +332,10 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx) st ->sample_aspect_ratio = par->sample_aspect_ratio = av_buffersink_get_sample_aspect_ratio(sink); } else if (par->codec_type == AVMEDIA_TYPE_AUDIO) { - par->channels = av_buffersink_get_channels(sink); par->sample_rate = av_buffersink_get_sample_rate(sink); - par->channel_layout = av_buffersink_get_channel_layout(sink); + ret = av_buffersink_get_ch_layout(sink, &par->ch_layout); + if (ret < 0) + goto end; par->format = av_buffersink_get_format(sink); par->codec_id = av_get_pcm_codec(par->format, -1); if (par->codec_id == AV_CODEC_ID_NONE) @@ -438,7 +439,7 @@ static int lavfi_read_packet(AVFormatContext *avctx, AVPacket *pkt) frame->format, frame->width, frame->height, 1); } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { size = frame->nb_samples * av_get_bytes_per_sample(frame->format) * - frame->channels; + frame->ch_layout.nb_channels; if ((ret = av_new_packet(pkt, size)) < 0) goto fail; memcpy(pkt->data, frame->data[0], size); diff --git a/libavdevice/libcdio.c b/libavdevice/libcdio.c index 623878fe7..28c339564 100644 --- a/libavdevice/libcdio.c +++ b/libavdevice/libcdio.c @@ -37,6 +37,7 @@ #include "libavutil/opt.h" #include "libavformat/avformat.h" +#include "libavformat/demux.h" #include "libavformat/internal.h" typedef struct CDIOContext { @@ -90,13 +91,14 @@ static av_cold int read_header(AVFormatContext *ctx) else st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE; st->codecpar->sample_rate = 44100; - st->codecpar->channels = 2; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; if (s->drive->audio_last_sector != CDIO_INVALID_LSN && s->drive->audio_first_sector != CDIO_INVALID_LSN) st->duration = s->drive->audio_last_sector - s->drive->audio_first_sector; else if (s->drive->tracks) st->duration = s->drive->disc_toc[s->drive->tracks].dwStartSector; - avpriv_set_pts_info(st, 64, CDIO_CD_FRAMESIZE_RAW, 2 * st->codecpar->channels * st->codecpar->sample_rate); + avpriv_set_pts_info(st, 64, CDIO_CD_FRAMESIZE_RAW, + 2 * st->codecpar->ch_layout.nb_channels * st->codecpar->sample_rate); for (i = 0; i < s->drive->tracks; i++) { char title[16]; diff --git a/libavdevice/openal-dec.c b/libavdevice/openal-dec.c index 54f120313..91a40ae02 100644 --- a/libavdevice/openal-dec.c +++ b/libavdevice/openal-dec.c @@ -159,7 +159,7 @@ static int read_header(AVFormatContext *ctx) par = st->codecpar; par->codec_type = AVMEDIA_TYPE_AUDIO; par->sample_rate = ad->sample_rate; - par->channels = get_al_format_info(ad->sample_format)->channels; + par->ch_layout.nb_channels = get_al_format_info(ad->sample_format)->channels; par->codec_id = get_al_format_info(ad->sample_format)->codec_id; /* This is needed to read the audio data */ diff --git a/libavdevice/opengl_enc.c b/libavdevice/opengl_enc.c index 9302979f4..b2140c80b 100644 --- a/libavdevice/opengl_enc.c +++ b/libavdevice/opengl_enc.c @@ -54,9 +54,9 @@ #include "libavutil/log.h" #include "libavutil/opt.h" #include "libavutil/avassert.h" -#include "libavutil/avstring.h" #include "libavformat/avformat.h" #include "libavformat/internal.h" +#include "libavformat/mux.h" #include "libavdevice/avdevice.h" #include "opengl_enc_shaders.h" diff --git a/libavdevice/oss.c b/libavdevice/oss.c index eddc2ddf1..b042f5887 100644 --- a/libavdevice/oss.c +++ b/libavdevice/oss.c @@ -102,9 +102,11 @@ int ff_oss_audio_open(AVFormatContext *s1, int is_output, switch(tmp) { case AFMT_S16_LE: s->codec_id = AV_CODEC_ID_PCM_S16LE; + s->sample_size = 2; break; case AFMT_S16_BE: s->codec_id = AV_CODEC_ID_PCM_S16BE; + s->sample_size = 2; break; default: av_log(s1, AV_LOG_ERROR, "Soundcard does not support 16 bit sample format\n"); @@ -112,7 +114,7 @@ int ff_oss_audio_open(AVFormatContext *s1, int is_output, return AVERROR(EIO); } err=ioctl(audio_fd, SNDCTL_DSP_SETFMT, &tmp); - CHECK_IOCTL_ERROR(SNDCTL_DSP_SETFMTS) + CHECK_IOCTL_ERROR(SNDCTL_DSP_SETFMT) tmp = (s->channels == 2); err = ioctl(audio_fd, SNDCTL_DSP_STEREO, &tmp); diff --git a/libavdevice/oss.h b/libavdevice/oss.h index 66d1a34cf..f1da2b1be 100644 --- a/libavdevice/oss.h +++ b/libavdevice/oss.h @@ -30,6 +30,7 @@ typedef struct OSSAudioData { AVClass *class; int fd; int sample_rate; + int sample_size; /* in bytes ! */ int channels; int frame_size; /* in bytes ! */ enum AVCodecID codec_id; diff --git a/libavdevice/oss_dec.c b/libavdevice/oss_dec.c index 4f3772c1f..2cdc4324e 100644 --- a/libavdevice/oss_dec.c +++ b/libavdevice/oss_dec.c @@ -59,7 +59,7 @@ static int audio_read_header(AVFormatContext *s1) 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; + st->codecpar->ch_layout.nb_channels = s->channels; avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ return 0; @@ -91,7 +91,7 @@ static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt) bdelay += abufi.bytes; } /* subtract time represented by the number of bytes in the audio fifo */ - cur_time -= (bdelay * 1000000LL) / (s->sample_rate * s->channels); + cur_time -= (bdelay * 1000000LL) / (s->sample_rate * s->sample_size * s->channels); /* convert to wanted units */ pkt->pts = cur_time; diff --git a/libavdevice/oss_enc.c b/libavdevice/oss_enc.c index 3103d2de9..704f434c5 100644 --- a/libavdevice/oss_enc.c +++ b/libavdevice/oss_enc.c @@ -43,7 +43,7 @@ static int audio_write_header(AVFormatContext *s1) st = s1->streams[0]; s->sample_rate = st->codecpar->sample_rate; - s->channels = st->codecpar->channels; + s->channels = st->codecpar->ch_layout.nb_channels; ret = ff_oss_audio_open(s1, 1, s1->url); if (ret < 0) { return AVERROR(EIO); @@ -55,9 +55,9 @@ static int audio_write_header(AVFormatContext *s1) static int audio_write_packet(AVFormatContext *s1, AVPacket *pkt) { OSSAudioData *s = s1->priv_data; + const uint8_t *buf = pkt->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); diff --git a/libavdevice/pulse_audio_dec.c b/libavdevice/pulse_audio_dec.c index b23d08e4d..254546293 100644 --- a/libavdevice/pulse_audio_dec.c +++ b/libavdevice/pulse_audio_dec.c @@ -30,6 +30,7 @@ #include "libavformat/avformat.h" #include "libavformat/internal.h" +#include "libavformat/version.h" #include "pulse_audio_common.h" #include "timefilter.h" @@ -161,7 +162,12 @@ static av_cold int pulse_read_header(AVFormatContext *s) return AVERROR(ENOMEM); } - attr.fragsize = pd->fragment_size; + if (pd->fragment_size == -1) { + // 50 ms fragments/latency by default seem good enough + attr.fragsize = pa_frame_size(&ss) * (pd->sample_rate / 20); + } else { + attr.fragsize = pd->fragment_size; + } if (s->url[0] != '\0' && strcmp(s->url, "default")) device = s->url; @@ -219,7 +225,7 @@ static av_cold int pulse_read_header(AVFormatContext *s) ret = pa_stream_connect_record(pd->stream, device, &attr, PA_STREAM_INTERPOLATE_TIMING - | (pd->fragment_size == -1 ? PA_STREAM_ADJUST_LATENCY : 0) + |PA_STREAM_ADJUST_LATENCY |PA_STREAM_AUTO_TIMING_UPDATE); if (ret < 0) { @@ -259,7 +265,7 @@ static av_cold int pulse_read_header(AVFormatContext *s) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = codec_id; st->codecpar->sample_rate = pd->sample_rate; - st->codecpar->channels = pd->channels; + st->codecpar->ch_layout.nb_channels = pd->channels; avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ pd->timefilter = ff_timefilter_new(1000000.0 / pd->sample_rate, @@ -365,6 +371,7 @@ static int pulse_get_device_list(AVFormatContext *h, AVDeviceInfoList *device_li #define OFFSET(a) offsetof(PulseData, a) #define D AV_OPT_FLAG_DECODING_PARAM +#define DEPR AV_OPT_FLAG_DEPRECATED static const AVOption options[] = { { "server", "set PulseAudio server", OFFSET(server), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, D }, @@ -372,7 +379,7 @@ static const AVOption options[] = { { "stream_name", "set stream description", OFFSET(stream_name), AV_OPT_TYPE_STRING, {.str = "record"}, 0, 0, D }, { "sample_rate", "set sample rate in Hz", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64 = 48000}, 1, INT_MAX, D }, { "channels", "set number of audio channels", OFFSET(channels), AV_OPT_TYPE_INT, {.i64 = 2}, 1, INT_MAX, D }, - { "frame_size", "set number of bytes per frame", OFFSET(frame_size), AV_OPT_TYPE_INT, {.i64 = 1024}, 1, INT_MAX, D }, + { "frame_size", "set number of bytes per frame", OFFSET(frame_size), AV_OPT_TYPE_INT, {.i64 = 1024}, 1, INT_MAX, D | DEPR }, { "fragment_size", "set buffering size, affects latency and cpu usage", OFFSET(fragment_size), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, D }, { "wallclock", "set the initial pts using the current time", OFFSET(wallclock), AV_OPT_TYPE_INT, {.i64 = 1}, -1, 1, D }, { NULL }, diff --git a/libavdevice/pulse_audio_enc.c b/libavdevice/pulse_audio_enc.c index 4ff425d33..d5928e2b3 100644 --- a/libavdevice/pulse_audio_enc.c +++ b/libavdevice/pulse_audio_enc.c @@ -23,6 +23,8 @@ #include #include "libavformat/avformat.h" #include "libavformat/internal.h" +#include "libavformat/mux.h" +#include "libavformat/version.h" #include "libavutil/channel_layout.h" #include "libavutil/internal.h" #include "libavutil/opt.h" @@ -353,58 +355,58 @@ static int pulse_subscribe_events(PulseData *s) return pulse_finish_context_operation(s, op, "pa_context_subscribe"); } -static void pulse_map_channels_to_pulse(int64_t channel_layout, pa_channel_map *channel_map) +static void pulse_map_channels_to_pulse(const AVChannelLayout *channel_layout, pa_channel_map *channel_map) { channel_map->channels = 0; - if (channel_layout & AV_CH_FRONT_LEFT) + if (av_channel_layout_index_from_channel(channel_layout, AV_CHAN_FRONT_LEFT) >= 0) channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_LEFT; - if (channel_layout & AV_CH_FRONT_RIGHT) + if (av_channel_layout_index_from_channel(channel_layout, AV_CHAN_FRONT_RIGHT) >= 0) channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_RIGHT; - if (channel_layout & AV_CH_FRONT_CENTER) + if (av_channel_layout_index_from_channel(channel_layout, AV_CHAN_FRONT_CENTER) >= 0) channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_CENTER; - if (channel_layout & AV_CH_LOW_FREQUENCY) + if (av_channel_layout_index_from_channel(channel_layout, AV_CHAN_LOW_FREQUENCY) >= 0) channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_LFE; - if (channel_layout & AV_CH_BACK_LEFT) + if (av_channel_layout_index_from_channel(channel_layout, AV_CHAN_BACK_LEFT) >= 0) channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_REAR_LEFT; - if (channel_layout & AV_CH_BACK_RIGHT) + if (av_channel_layout_index_from_channel(channel_layout, AV_CHAN_BACK_RIGHT) >= 0) channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_REAR_RIGHT; - if (channel_layout & AV_CH_FRONT_LEFT_OF_CENTER) + if (av_channel_layout_index_from_channel(channel_layout, AV_CHAN_FRONT_LEFT_OF_CENTER) >= 0) channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER; - if (channel_layout & AV_CH_FRONT_RIGHT_OF_CENTER) + if (av_channel_layout_index_from_channel(channel_layout, AV_CHAN_FRONT_RIGHT_OF_CENTER) >= 0) channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER; - if (channel_layout & AV_CH_BACK_CENTER) + if (av_channel_layout_index_from_channel(channel_layout, AV_CHAN_BACK_CENTER) >= 0) channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_REAR_CENTER; - if (channel_layout & AV_CH_SIDE_LEFT) + if (av_channel_layout_index_from_channel(channel_layout, AV_CHAN_SIDE_LEFT) >= 0) channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_SIDE_LEFT; - if (channel_layout & AV_CH_SIDE_RIGHT) + if (av_channel_layout_index_from_channel(channel_layout, AV_CHAN_SIDE_RIGHT) >= 0) channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_SIDE_RIGHT; - if (channel_layout & AV_CH_TOP_CENTER) + if (av_channel_layout_index_from_channel(channel_layout, AV_CHAN_TOP_CENTER) >= 0) channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_CENTER; - if (channel_layout & AV_CH_TOP_FRONT_LEFT) + if (av_channel_layout_index_from_channel(channel_layout, AV_CHAN_TOP_FRONT_LEFT) >= 0) channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_FRONT_LEFT; - if (channel_layout & AV_CH_TOP_FRONT_CENTER) + if (av_channel_layout_index_from_channel(channel_layout, AV_CHAN_TOP_FRONT_CENTER) >= 0) channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_FRONT_CENTER; - if (channel_layout & AV_CH_TOP_FRONT_RIGHT) + if (av_channel_layout_index_from_channel(channel_layout, AV_CHAN_TOP_FRONT_RIGHT) >= 0) channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_FRONT_RIGHT; - if (channel_layout & AV_CH_TOP_BACK_LEFT) + if (av_channel_layout_index_from_channel(channel_layout, AV_CHAN_TOP_BACK_LEFT) >= 0) channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_REAR_LEFT; - if (channel_layout & AV_CH_TOP_BACK_CENTER) + if (av_channel_layout_index_from_channel(channel_layout, AV_CHAN_TOP_BACK_CENTER) >= 0) channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_REAR_CENTER; - if (channel_layout & AV_CH_TOP_BACK_RIGHT) + if (av_channel_layout_index_from_channel(channel_layout, AV_CHAN_TOP_BACK_RIGHT) >= 0) channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_TOP_REAR_RIGHT; - if (channel_layout & AV_CH_STEREO_LEFT) + if (av_channel_layout_index_from_channel(channel_layout, AV_CHAN_STEREO_LEFT) >= 0) channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_LEFT; - if (channel_layout & AV_CH_STEREO_RIGHT) + if (av_channel_layout_index_from_channel(channel_layout, AV_CHAN_STEREO_RIGHT) >= 0) channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_FRONT_RIGHT; - if (channel_layout & AV_CH_WIDE_LEFT) + if (av_channel_layout_index_from_channel(channel_layout, AV_CHAN_WIDE_LEFT) >= 0) channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_AUX0; - if (channel_layout & AV_CH_WIDE_RIGHT) + if (av_channel_layout_index_from_channel(channel_layout, AV_CHAN_WIDE_RIGHT) >= 0) channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_AUX1; - if (channel_layout & AV_CH_SURROUND_DIRECT_LEFT) + if (av_channel_layout_index_from_channel(channel_layout, AV_CHAN_SURROUND_DIRECT_LEFT) >= 0) channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_AUX2; - if (channel_layout & AV_CH_SURROUND_DIRECT_RIGHT) + if (av_channel_layout_index_from_channel(channel_layout, AV_CHAN_SURROUND_DIRECT_RIGHT) >= 0) channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_AUX3; - if (channel_layout & AV_CH_LOW_FREQUENCY_2) + if (av_channel_layout_index_from_channel(channel_layout, AV_CHAN_LOW_FREQUENCY_2) >= 0) channel_map->map[channel_map->channels++] = PA_CHANNEL_POSITION_LFE; } @@ -469,7 +471,7 @@ static av_cold int pulse_write_header(AVFormatContext *h) if (s->buffer_duration) { int64_t bytes = s->buffer_duration; - bytes *= st->codecpar->channels * st->codecpar->sample_rate * + bytes *= st->codecpar->ch_layout.nb_channels * st->codecpar->sample_rate * av_get_bytes_per_sample(st->codecpar->format); bytes /= 1000; buffer_attributes.tlength = FFMAX(s->buffer_size, av_clip64(bytes, 0, UINT32_MAX - 1)); @@ -486,7 +488,7 @@ static av_cold int pulse_write_header(AVFormatContext *h) sample_spec.format = ff_codec_id_to_pulse_format(st->codecpar->codec_id); sample_spec.rate = st->codecpar->sample_rate; - sample_spec.channels = st->codecpar->channels; + sample_spec.channels = st->codecpar->ch_layout.nb_channels; if (!pa_sample_spec_valid(&sample_spec)) { av_log(s, AV_LOG_ERROR, "Invalid sample spec.\n"); return AVERROR(EINVAL); @@ -495,10 +497,10 @@ static av_cold int pulse_write_header(AVFormatContext *h) if (sample_spec.channels == 1) { channel_map.channels = 1; channel_map.map[0] = PA_CHANNEL_POSITION_MONO; - } else if (st->codecpar->channel_layout) { - if (av_get_channel_layout_nb_channels(st->codecpar->channel_layout) != st->codecpar->channels) + } else if (st->codecpar->ch_layout.order != AV_CHANNEL_ORDER_UNSPEC) { + if (!av_channel_layout_check(&st->codecpar->ch_layout)) return AVERROR(EINVAL); - pulse_map_channels_to_pulse(st->codecpar->channel_layout, &channel_map); + pulse_map_channels_to_pulse(&st->codecpar->ch_layout, &channel_map); /* Unknown channel is present in channel_layout, let PulseAudio use its default. */ if (channel_map.channels != sample_spec.channels) { av_log(s, AV_LOG_WARNING, "Unknown channel. Using defaul channel map.\n"); @@ -639,7 +641,7 @@ static int pulse_write_packet(AVFormatContext *h, AVPacket *pkt) } else { AVStream *st = h->streams[0]; AVRational r = { 1, st->codecpar->sample_rate }; - int64_t samples = pkt->size / (av_get_bytes_per_sample(st->codecpar->format) * st->codecpar->channels); + int64_t samples = pkt->size / (av_get_bytes_per_sample(st->codecpar->format) * st->codecpar->ch_layout.nb_channels); s->timestamp += av_rescale_q(samples, r, st->time_base); } @@ -682,7 +684,7 @@ static int pulse_write_frame(AVFormatContext *h, int stream_index, AVERROR(EINVAL) : 0; pkt.data = (*frame)->data[0]; - pkt.size = (*frame)->nb_samples * av_get_bytes_per_sample((*frame)->format) * (*frame)->channels; + pkt.size = (*frame)->nb_samples * av_get_bytes_per_sample((*frame)->format) * (*frame)->ch_layout.nb_channels; pkt.dts = (*frame)->pkt_dts; pkt.duration = (*frame)->pkt_duration; return pulse_write_packet(h, &pkt); diff --git a/libavdevice/sndio_dec.c b/libavdevice/sndio_dec.c index ec8fa4126..605983036 100644 --- a/libavdevice/sndio_dec.c +++ b/libavdevice/sndio_dec.c @@ -49,7 +49,7 @@ static av_cold int audio_read_header(AVFormatContext *s1) 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; + st->codecpar->ch_layout.nb_channels = s->channels; avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ diff --git a/libavdevice/sndio_enc.c b/libavdevice/sndio_enc.c index 2e698d7c3..0cf58fdc6 100644 --- a/libavdevice/sndio_enc.c +++ b/libavdevice/sndio_enc.c @@ -36,7 +36,7 @@ static av_cold int audio_write_header(AVFormatContext *s1) st = s1->streams[0]; s->sample_rate = st->codecpar->sample_rate; - s->channels = st->codecpar->channels; + s->channels = st->codecpar->ch_layout.nb_channels; ret = ff_sndio_open(s1, 1, s1->url); @@ -46,7 +46,7 @@ static av_cold int audio_write_header(AVFormatContext *s1) static int audio_write_packet(AVFormatContext *s1, AVPacket *pkt) { SndioData *s = s1->priv_data; - uint8_t *buf= pkt->data; + const uint8_t *buf = pkt->data; int size = pkt->size; int len, ret; diff --git a/libavdevice/timefilter.c b/libavdevice/timefilter.c index ad6485d5e..a97afc5fd 100644 --- a/libavdevice/timefilter.c +++ b/libavdevice/timefilter.c @@ -22,7 +22,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/common.h" +#include +#include + +#include "libavutil/macros.h" +#include "libavutil/mathematics.h" #include "libavutil/mem.h" #include "timefilter.h" diff --git a/libavdevice/v4l2-common.h b/libavdevice/v4l2-common.h index c7bed3e3b..4fbd15d28 100644 --- a/libavdevice/v4l2-common.h +++ b/libavdevice/v4l2-common.h @@ -21,7 +21,7 @@ #undef __STRICT_ANSI__ //workaround due to broken kernel headers #include "config.h" -#include "libavformat/internal.h" +#include #include #include #include @@ -35,15 +35,8 @@ #endif #include #endif -#include "libavutil/imgutils.h" -#include "libavutil/log.h" -#include "libavutil/opt.h" -#include "avdevice.h" -#include "timefilter.h" -#include "libavutil/parseutils.h" -#include "libavutil/pixdesc.h" -#include "libavutil/time.h" -#include "libavutil/avstring.h" +#include "libavutil/pixfmt.h" +#include "libavcodec/codec_id.h" struct fmt_map { enum AVPixelFormat ff_fmt; diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c index 2ecfb9fae..5340382d5 100644 --- a/libavdevice/v4l2.c +++ b/libavdevice/v4l2.c @@ -34,6 +34,15 @@ #include "libavutil/avassert.h" #include "libavutil/avstring.h" +#include "libavutil/imgutils.h" +#include "libavutil/parseutils.h" +#include "libavutil/pixdesc.h" +#include "libavutil/time.h" +#include "libavcodec/codec_desc.h" +#include "libavformat/demux.h" +#include "libavformat/internal.h" +#include "avdevice.h" +#include "timefilter.h" #include "v4l2-common.h" #include diff --git a/libavdevice/v4l2enc.c b/libavdevice/v4l2enc.c index 787fe5354..b1006461b 100644 --- a/libavdevice/v4l2enc.c +++ b/libavdevice/v4l2enc.c @@ -18,8 +18,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/imgutils.h" +#include "libavutil/pixdesc.h" +#include "libavformat/avformat.h" #include "v4l2-common.h" -#include "avdevice.h" typedef struct { AVClass *class; diff --git a/libavdevice/version.c b/libavdevice/version.c new file mode 100644 index 000000000..92d7f2d15 --- /dev/null +++ b/libavdevice/version.c @@ -0,0 +1,45 @@ +/* + * Version functions. + * + * 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/avassert.h" +#include "avdevice.h" +#include "version.h" + +#include "libavutil/ffversion.h" +const char av_device_ffversion[] = "FFmpeg version " FFMPEG_VERSION; + +unsigned avdevice_version(void) +{ + av_assert0(LIBAVDEVICE_VERSION_MICRO >= 100); + return LIBAVDEVICE_VERSION_INT; +} + +const char * avdevice_configuration(void) +{ + return FFMPEG_CONFIGURATION; +} + +const char * avdevice_license(void) +{ +#define LICENSE_PREFIX "libavdevice license: " + return &LICENSE_PREFIX FFMPEG_LICENSE[sizeof(LICENSE_PREFIX) - 1]; +} diff --git a/libavdevice/version.h b/libavdevice/version.h index 75e337811..a458e0f33 100644 --- a/libavdevice/version.h +++ b/libavdevice/version.h @@ -27,8 +27,9 @@ #include "libavutil/version.h" -#define LIBAVDEVICE_VERSION_MAJOR 59 -#define LIBAVDEVICE_VERSION_MINOR 4 +#include "version_major.h" + +#define LIBAVDEVICE_VERSION_MINOR 7 #define LIBAVDEVICE_VERSION_MICRO 100 #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \ @@ -41,11 +42,4 @@ #define LIBAVDEVICE_IDENT "Lavd" AV_STRINGIFY(LIBAVDEVICE_VERSION) -/** - * FF_API_* defines may be placed below to indicate public API that will be - * 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. - */ -#define FF_API_DEVICE_CAPABILITIES (LIBAVDEVICE_VERSION_MAJOR < 60) - #endif /* AVDEVICE_VERSION_H */ diff --git a/libavdevice/version_major.h b/libavdevice/version_major.h new file mode 100644 index 000000000..d255ff699 --- /dev/null +++ b/libavdevice/version_major.h @@ -0,0 +1,37 @@ +/* + * 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 AVDEVICE_VERSION_MAJOR_H +#define AVDEVICE_VERSION_MAJOR_H + +/** + * @file + * @ingroup lavd + * Libavdevice version macros + */ + +#define LIBAVDEVICE_VERSION_MAJOR 59 + +/** + * FF_API_* defines may be placed below to indicate public API that will be + * 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. + */ +#define FF_API_DEVICE_CAPABILITIES (LIBAVDEVICE_VERSION_MAJOR < 60) + +#endif /* AVDEVICE_VERSION_MAJOR_H */ diff --git a/libavdevice/xv.c b/libavdevice/xv.c index a346f8e30..348c289be 100644 --- a/libavdevice/xv.c +++ b/libavdevice/xv.c @@ -35,7 +35,7 @@ #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "libavutil/imgutils.h" -#include "libavformat/internal.h" +#include "libavformat/mux.h" #include "avdevice.h" typedef struct { diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 01c0338bb..30cc329fb 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -5,6 +5,7 @@ HEADERS = avfilter.h \ buffersink.h \ buffersrc.h \ version.h \ + version_major.h \ OBJS = allfilters.o \ audio.o \ @@ -12,6 +13,7 @@ OBJS = allfilters.o \ avfiltergraph.o \ buffersink.o \ buffersrc.o \ + colorspace.o \ drawutils.o \ fifo.o \ formats.o \ @@ -19,8 +21,10 @@ OBJS = allfilters.o \ framequeue.o \ graphdump.o \ graphparser.o \ + version.o \ video.o \ +OBJS-$(HAVE_LIBC_MSVCRT) += file_open.o OBJS-$(HAVE_THREADS) += pthread.o # subsystems @@ -124,6 +128,7 @@ OBJS-$(CONFIG_CROSSFEED_FILTER) += af_crossfeed.o OBJS-$(CONFIG_CRYSTALIZER_FILTER) += af_crystalizer.o OBJS-$(CONFIG_DCSHIFT_FILTER) += af_dcshift.o OBJS-$(CONFIG_DEESSER_FILTER) += af_deesser.o +OBJS-$(CONFIG_DIALOGUENHANCE_FILTER) += af_dialoguenhance.o OBJS-$(CONFIG_DRMETER_FILTER) += af_drmeter.o OBJS-$(CONFIG_DYNAUDNORM_FILTER) += af_dynaudnorm.o OBJS-$(CONFIG_EARWAX_FILTER) += af_earwax.o @@ -160,6 +165,7 @@ OBJS-$(CONFIG_SURROUND_FILTER) += af_surround.o OBJS-$(CONFIG_TREBLE_FILTER) += af_biquads.o OBJS-$(CONFIG_TREMOLO_FILTER) += af_tremolo.o OBJS-$(CONFIG_VIBRATO_FILTER) += af_vibrato.o generate_wave_table.o +OBJS-$(CONFIG_VIRTUALBASS_FILTER) += af_virtualbass.o OBJS-$(CONFIG_VOLUME_FILTER) += af_volume.o OBJS-$(CONFIG_VOLUMEDETECT_FILTER) += af_volumedetect.o @@ -192,6 +198,9 @@ OBJS-$(CONFIG_BITPLANENOISE_FILTER) += vf_bitplanenoise.o OBJS-$(CONFIG_BLACKDETECT_FILTER) += vf_blackdetect.o OBJS-$(CONFIG_BLACKFRAME_FILTER) += vf_blackframe.o OBJS-$(CONFIG_BLEND_FILTER) += vf_blend.o framesync.o +OBJS-$(CONFIG_BLEND_VULKAN_FILTER) += vf_blend_vulkan.o framesync.o vulkan.o vulkan_filter.o +OBJS-$(CONFIG_BLOCKDETECT_FILTER) += vf_blockdetect.o +OBJS-$(CONFIG_BLURDETECT_FILTER) += vf_blurdetect.o edge_common.o OBJS-$(CONFIG_BM3D_FILTER) += vf_bm3d.o framesync.o OBJS-$(CONFIG_BOXBLUR_FILTER) += vf_boxblur.o boxblur.o OBJS-$(CONFIG_BOXBLUR_OPENCL_FILTER) += vf_avgblur_opencl.o opencl.o \ @@ -201,6 +210,8 @@ OBJS-$(CONFIG_CAS_FILTER) += vf_cas.o OBJS-$(CONFIG_CHROMABER_VULKAN_FILTER) += vf_chromaber_vulkan.o vulkan.o vulkan_filter.o OBJS-$(CONFIG_CHROMAHOLD_FILTER) += vf_chromakey.o OBJS-$(CONFIG_CHROMAKEY_FILTER) += vf_chromakey.o +OBJS-$(CONFIG_CHROMAKEY_CUDA_FILTER) += vf_chromakey_cuda.o vf_chromakey_cuda.ptx.o + OBJS-$(CONFIG_CHROMANR_FILTER) += vf_chromanr.o OBJS-$(CONFIG_CHROMASHIFT_FILTER) += vf_chromashift.o OBJS-$(CONFIG_CIESCOPE_FILTER) += vf_ciescope.o @@ -215,8 +226,9 @@ OBJS-$(CONFIG_COLORKEY_OPENCL_FILTER) += vf_colorkey_opencl.o opencl.o \ opencl/colorkey.o OBJS-$(CONFIG_COLORHOLD_FILTER) += vf_colorkey.o OBJS-$(CONFIG_COLORLEVELS_FILTER) += vf_colorlevels.o +OBJS-$(CONFIG_COLORMAP_FILTER) += vf_colormap.o OBJS-$(CONFIG_COLORMATRIX_FILTER) += vf_colormatrix.o -OBJS-$(CONFIG_COLORSPACE_FILTER) += vf_colorspace.o colorspace.o colorspacedsp.o +OBJS-$(CONFIG_COLORSPACE_FILTER) += vf_colorspace.o colorspacedsp.o OBJS-$(CONFIG_COLORTEMPERATURE_FILTER) += vf_colortemperature.o OBJS-$(CONFIG_CONVOLUTION_FILTER) += vf_convolution.o OBJS-$(CONFIG_CONVOLUTION_OPENCL_FILTER) += vf_convolution_opencl.o opencl.o \ @@ -262,7 +274,7 @@ OBJS-$(CONFIG_DRAWBOX_FILTER) += vf_drawbox.o OBJS-$(CONFIG_DRAWGRAPH_FILTER) += f_drawgraph.o OBJS-$(CONFIG_DRAWGRID_FILTER) += vf_drawbox.o OBJS-$(CONFIG_DRAWTEXT_FILTER) += vf_drawtext.o -OBJS-$(CONFIG_EDGEDETECT_FILTER) += vf_edgedetect.o +OBJS-$(CONFIG_EDGEDETECT_FILTER) += vf_edgedetect.o edge_common.o OBJS-$(CONFIG_ELBG_FILTER) += vf_elbg.o OBJS-$(CONFIG_ENTROPY_FILTER) += vf_entropy.o OBJS-$(CONFIG_EPX_FILTER) += vf_epx.o @@ -274,6 +286,7 @@ OBJS-$(CONFIG_ESTDIF_FILTER) += vf_estdif.o OBJS-$(CONFIG_EXPOSURE_FILTER) += vf_exposure.o OBJS-$(CONFIG_EXTRACTPLANES_FILTER) += vf_extractplanes.o OBJS-$(CONFIG_FADE_FILTER) += vf_fade.o +OBJS-$(CONFIG_FEEDBACK_FILTER) += vf_feedback.o OBJS-$(CONFIG_FFTDNOIZ_FILTER) += vf_fftdnoiz.o OBJS-$(CONFIG_FFTFILT_FILTER) += vf_fftfilt.o OBJS-$(CONFIG_FIELD_FILTER) += vf_field.o @@ -317,6 +330,8 @@ OBJS-$(CONFIG_HWMAP_FILTER) += vf_hwmap.o OBJS-$(CONFIG_HWUPLOAD_CUDA_FILTER) += vf_hwupload_cuda.o OBJS-$(CONFIG_HWUPLOAD_FILTER) += vf_hwupload.o OBJS-$(CONFIG_HYSTERESIS_FILTER) += vf_hysteresis.o framesync.o +OBJS-$(CONFIG_ICCDETECT_FILTER) += vf_iccdetect.o fflcms2.o +OBJS-$(CONFIG_ICCGEN_FILTER) += vf_iccgen.o fflcms2.o OBJS-$(CONFIG_IDENTITY_FILTER) += vf_identity.o OBJS-$(CONFIG_IDET_FILTER) += vf_idet.o OBJS-$(CONFIG_IL_FILTER) += vf_il.o @@ -358,6 +373,7 @@ OBJS-$(CONFIG_MIX_FILTER) += vf_mix.o framesync.o OBJS-$(CONFIG_MONOCHROME_FILTER) += vf_monochrome.o OBJS-$(CONFIG_MORPHO_FILTER) += vf_morpho.o OBJS-$(CONFIG_MPDECIMATE_FILTER) += vf_mpdecimate.o +OBJS-$(CONFIG_MULTIPLY_FILTER) += vf_multiply.o OBJS-$(CONFIG_NEGATE_FILTER) += vf_negate.o OBJS-$(CONFIG_NLMEANS_FILTER) += vf_nlmeans.o OBJS-$(CONFIG_NLMEANS_OPENCL_FILTER) += vf_nlmeans_opencl.o opencl.o opencl/nlmeans.o @@ -375,6 +391,7 @@ OBJS-$(CONFIG_OVERLAY_CUDA_FILTER) += vf_overlay_cuda.o framesync.o vf 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 framesync.o +OBJS-$(CONFIG_OVERLAY_VAAPI_FILTER) += vf_overlay_vaapi.o framesync.o vaapi_vpp.o OBJS-$(CONFIG_OVERLAY_VULKAN_FILTER) += vf_overlay_vulkan.o vulkan.o vulkan_filter.o OBJS-$(CONFIG_OWDENOISE_FILTER) += vf_owdenoise.o OBJS-$(CONFIG_PAD_FILTER) += vf_pad.o @@ -386,6 +403,7 @@ OBJS-$(CONFIG_PERSPECTIVE_FILTER) += vf_perspective.o OBJS-$(CONFIG_PHASE_FILTER) += vf_phase.o OBJS-$(CONFIG_PHOTOSENSITIVITY_FILTER) += vf_photosensitivity.o OBJS-$(CONFIG_PIXDESCTEST_FILTER) += vf_pixdesctest.o +OBJS-$(CONFIG_PIXELIZE_FILTER) += vf_pixelize.o OBJS-$(CONFIG_PIXSCOPE_FILTER) += vf_datascope.o OBJS-$(CONFIG_PP_FILTER) += vf_pp.o qp_table.o OBJS-$(CONFIG_PP7_FILTER) += vf_pp7.o qp_table.o @@ -404,6 +422,8 @@ OBJS-$(CONFIG_READEIA608_FILTER) += vf_readeia608.o OBJS-$(CONFIG_READVITC_FILTER) += vf_readvitc.o OBJS-$(CONFIG_REALTIME_FILTER) += f_realtime.o OBJS-$(CONFIG_REMAP_FILTER) += vf_remap.o framesync.o +OBJS-$(CONFIG_REMAP_OPENCL_FILTER) += vf_remap_opencl.o framesync.o opencl.o \ + opencl/remap.o OBJS-$(CONFIG_REMOVEGRAIN_FILTER) += vf_removegrain.o OBJS-$(CONFIG_REMOVELOGO_FILTER) += bbox.o lswsutils.o lavfutils.o vf_removelogo.o OBJS-$(CONFIG_REPEATFIELDS_FILTER) += vf_repeatfields.o @@ -453,6 +473,7 @@ OBJS-$(CONFIG_SMARTBLUR_FILTER) += vf_smartblur.o OBJS-$(CONFIG_SOBEL_FILTER) += vf_convolution.o OBJS-$(CONFIG_SOBEL_OPENCL_FILTER) += vf_convolution_opencl.o opencl.o \ opencl/convolution.o +OBJS-$(CONFIG_SITI_FILTER) += vf_siti.o OBJS-$(CONFIG_SPLIT_FILTER) += split.o OBJS-$(CONFIG_SPP_FILTER) += vf_spp.o qp_table.o OBJS-$(CONFIG_SR_FILTER) += vf_sr.o @@ -476,8 +497,8 @@ OBJS-$(CONFIG_TLUT2_FILTER) += vf_lut2.o framesync.o OBJS-$(CONFIG_TMEDIAN_FILTER) += vf_xmedian.o framesync.o OBJS-$(CONFIG_TMIDEQUALIZER_FILTER) += vf_tmidequalizer.o OBJS-$(CONFIG_TMIX_FILTER) += vf_mix.o framesync.o -OBJS-$(CONFIG_TONEMAP_FILTER) += vf_tonemap.o colorspace.o -OBJS-$(CONFIG_TONEMAP_OPENCL_FILTER) += vf_tonemap_opencl.o colorspace.o opencl.o \ +OBJS-$(CONFIG_TONEMAP_FILTER) += vf_tonemap.o +OBJS-$(CONFIG_TONEMAP_OPENCL_FILTER) += vf_tonemap_opencl.o opencl.o \ opencl/tonemap.o opencl/colorspace_common.o OBJS-$(CONFIG_TONEMAP_VAAPI_FILTER) += vf_tonemap_vaapi.o vaapi_vpp.o OBJS-$(CONFIG_TPAD_FILTER) += vf_tpad.o @@ -533,6 +554,7 @@ OBJS-$(CONFIG_ALLRGB_FILTER) += vsrc_testsrc.o OBJS-$(CONFIG_ALLYUV_FILTER) += vsrc_testsrc.o OBJS-$(CONFIG_CELLAUTO_FILTER) += vsrc_cellauto.o OBJS-$(CONFIG_COLOR_FILTER) += vsrc_testsrc.o +OBJS-$(CONFIG_COLORCHART_FILTER) += vsrc_testsrc.o OBJS-$(CONFIG_COLORSPECTRUM_FILTER) += vsrc_testsrc.o OBJS-$(CONFIG_COREIMAGESRC_FILTER) += vf_coreimage.o OBJS-$(CONFIG_FREI0R_SRC_FILTER) += vf_frei0r.o @@ -574,6 +596,7 @@ OBJS-$(CONFIG_SHOWWAVESPIC_FILTER) += avf_showwaves.o OBJS-$(CONFIG_SPECTRUMSYNTH_FILTER) += vaf_spectrumsynth.o # multimedia sources +OBJS-$(CONFIG_AVSYNCTEST_FILTER) += src_avsynctest.o OBJS-$(CONFIG_AMOVIE_FILTER) += src_movie.o OBJS-$(CONFIG_MOVIE_FILTER) += src_movie.o @@ -583,6 +606,7 @@ SHLIBOBJS += log2_tab.o # Windows resource file SLIBOBJS-$(HAVE_GNU_WINDRES) += avfilterres.o +SKIPHEADERS-$(CONFIG_LCMS2) += fflcms2.h SKIPHEADERS-$(CONFIG_LIBVIDSTAB) += vidstabutils.h SKIPHEADERS-$(CONFIG_QSVVPP) += qsvvpp.h diff --git a/libavfilter/aeval.c b/libavfilter/aeval.c index 42cfa8132..94d7690ef 100644 --- a/libavfilter/aeval.c +++ b/libavfilter/aeval.c @@ -23,6 +23,8 @@ * eval audio source */ +#include "config_components.h" + #include "libavutil/avstring.h" #include "libavutil/channel_layout.h" #include "libavutil/eval.h" @@ -57,7 +59,7 @@ typedef struct EvalContext { const AVClass *class; char *sample_rate_str; int sample_rate; - int64_t chlayout; + AVChannelLayout chlayout; char *chlayout_str; int nb_channels; ///< number of output channels int nb_in_channels; ///< number of input channels @@ -70,7 +72,6 @@ typedef struct EvalContext { uint64_t n; double var_values[VAR_VARS_NB]; double *channel_values; - int64_t out_channel_layout; } EvalContext; static double val(void *priv, double ch) @@ -181,7 +182,7 @@ static av_cold int init(AVFilterContext *ctx) if (ret < 0) return ret; - ret = parse_channel_expressions(ctx, av_get_channel_layout_nb_channels(eval->chlayout)); + ret = parse_channel_expressions(ctx, eval->chlayout.nb_channels); if (ret < 0) return ret; } @@ -190,8 +191,8 @@ static av_cold int init(AVFilterContext *ctx) if ((ret = parse_channel_expressions(ctx, -1)) < 0) return ret; - eval->chlayout = av_get_default_channel_layout(eval->nb_channels); - if (!eval->chlayout && eval->nb_channels <= 0) { + av_channel_layout_default(&eval->chlayout, eval->nb_channels); + if (eval->nb_channels <= 0) { av_log(ctx, AV_LOG_ERROR, "Invalid number of channels '%d' provided\n", eval->nb_channels); return AVERROR(EINVAL); @@ -217,6 +218,7 @@ static av_cold void uninit(AVFilterContext *ctx) } av_freep(&eval->expr); av_freep(&eval->channel_values); + av_channel_layout_uninit(&eval->chlayout); } static int config_props(AVFilterLink *outlink) @@ -229,9 +231,9 @@ static int config_props(AVFilterLink *outlink) eval->var_values[VAR_S] = eval->sample_rate; eval->var_values[VAR_NB_IN_CHANNELS] = NAN; - eval->var_values[VAR_NB_OUT_CHANNELS] = outlink->channels; + eval->var_values[VAR_NB_OUT_CHANNELS] = outlink->ch_layout.nb_channels; - av_get_channel_layout_string(buf, sizeof(buf), 0, eval->chlayout); + av_channel_layout_describe(&eval->chlayout, buf, sizeof(buf)); av_log(outlink->src, AV_LOG_VERBOSE, "sample_rate:%d chlayout:%s duration:%"PRId64"\n", @@ -244,7 +246,7 @@ static int query_formats(AVFilterContext *ctx) { EvalContext *eval = ctx->priv; static const enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_DBLP, AV_SAMPLE_FMT_NONE }; - int64_t chlayouts[] = { eval->chlayout ? eval->chlayout : FF_COUNT2LAYOUT(eval->nb_channels) , -1 }; + AVChannelLayout chlayouts[] = { eval->chlayout.nb_channels ? eval->chlayout : FF_COUNT2LAYOUT(eval->nb_channels), { 0 } }; int sample_rates[] = { eval->sample_rate, -1 }; int ret; @@ -365,9 +367,7 @@ static int aeval_query_formats(AVFilterContext *ctx) } else { // outlink supports only requested output channel layout layouts = NULL; - if ((ret = ff_add_channel_layout(&layouts, - eval->out_channel_layout ? eval->out_channel_layout : - FF_COUNT2LAYOUT(eval->nb_channels))) < 0) + if ((ret = ff_add_channel_layout(&layouts, &FF_COUNT2LAYOUT(eval->nb_channels))) < 0) return ret; if ((ret = ff_channel_layouts_ref(layouts, &outlink->incfg.channel_layouts)) < 0) return ret; @@ -387,20 +387,21 @@ static int aeval_config_output(AVFilterLink *outlink) int ret; if (eval->same_chlayout) { - eval->chlayout = inlink->channel_layout; + if ((ret = av_channel_layout_copy(&eval->chlayout, &inlink->ch_layout)) < 0) + return ret; - if ((ret = parse_channel_expressions(ctx, inlink->channels)) < 0) + if ((ret = parse_channel_expressions(ctx, inlink->ch_layout.nb_channels)) < 0) return ret; } eval->n = 0; - eval->nb_in_channels = eval->var_values[VAR_NB_IN_CHANNELS] = inlink->channels; - eval->var_values[VAR_NB_OUT_CHANNELS] = outlink->channels; + eval->nb_in_channels = eval->var_values[VAR_NB_IN_CHANNELS] = inlink->ch_layout.nb_channels; + eval->var_values[VAR_NB_OUT_CHANNELS] = outlink->ch_layout.nb_channels; eval->var_values[VAR_S] = inlink->sample_rate; eval->var_values[VAR_T] = NAN; eval->channel_values = av_realloc_f(eval->channel_values, - inlink->channels, sizeof(*eval->channel_values)); + inlink->ch_layout.nb_channels, sizeof(*eval->channel_values)); if (!eval->channel_values) return AVERROR(ENOMEM); @@ -430,10 +431,10 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) eval->var_values[VAR_N] = eval->n; eval->var_values[VAR_T] = t0 + i * (double)1/inlink->sample_rate; - for (j = 0; j < inlink->channels; j++) + for (j = 0; j < inlink->ch_layout.nb_channels; j++) eval->channel_values[j] = *((double *) in->extended_data[j] + i); - for (j = 0; j < outlink->channels; j++) { + for (j = 0; j < outlink->ch_layout.nb_channels; j++) { eval->var_values[VAR_CH] = j; *((double *) out->extended_data[j] + i) = av_expr_eval(eval->expr[j], eval->var_values, eval); diff --git a/libavfilter/af_acontrast.c b/libavfilter/af_acontrast.c index db7ff79d2..a4ed29e30 100644 --- a/libavfilter/af_acontrast.c +++ b/libavfilter/af_acontrast.c @@ -152,7 +152,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) } s->filter((void **)out->extended_data, (const void **)in->extended_data, - in->nb_samples, in->channels, s->contrast / 750); + in->nb_samples, in->ch_layout.nb_channels, s->contrast / 750); if (out != in) av_frame_free(&in); diff --git a/libavfilter/af_acrossover.c b/libavfilter/af_acrossover.c index 9c00e1ddc..417e85713 100644 --- a/libavfilter/af_acrossover.c +++ b/libavfilter/af_acrossover.c @@ -33,6 +33,7 @@ #include "audio.h" #include "avfilter.h" +#include "filters.h" #include "formats.h" #include "internal.h" @@ -57,6 +58,7 @@ typedef struct AudioCrossoverContext { char *gains_str; int order_opt; float level_in; + int precision; int order; int filter_count; @@ -73,7 +75,6 @@ typedef struct AudioCrossoverContext { AVFrame *xover; - AVFrame *input_frame; AVFrame *frames[MAX_BANDS]; int (*filter_channels)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); @@ -99,11 +100,52 @@ static const AVOption acrossover_options[] = { { "20th", "20th order (120 dB/8ve)",0, AV_OPT_TYPE_CONST, {.i64=9}, 0, 0, AF, "m" }, { "level", "set input gain", OFFSET(level_in), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 1, AF }, { "gain", "set output bands gain", OFFSET(gains_str), AV_OPT_TYPE_STRING, {.str="1.f"}, 0, 0, AF }, + { "precision", "set processing precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, AF, "precision" }, + { "auto", "set auto processing precision", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "precision" }, + { "float", "set single-floating point processing precision", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "precision" }, + { "double","set double-floating point processing precision", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF, "precision" }, { NULL } }; AVFILTER_DEFINE_CLASS(acrossover); +static int query_formats(AVFilterContext *ctx) +{ + AudioCrossoverContext *s = ctx->priv; + static const enum AVSampleFormat auto_sample_fmts[] = { + AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_DBLP, + AV_SAMPLE_FMT_NONE + }; + enum AVSampleFormat sample_fmts[] = { + AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_NONE + }; + const enum AVSampleFormat *sample_fmts_list = sample_fmts; + int ret = ff_set_common_all_channel_counts(ctx); + if (ret < 0) + return ret; + + switch (s->precision) { + case 0: + sample_fmts_list = auto_sample_fmts; + break; + case 1: + sample_fmts[0] = AV_SAMPLE_FMT_FLTP; + break; + case 2: + sample_fmts[0] = AV_SAMPLE_FMT_DBLP; + break; + default: + break; + } + ret = ff_set_common_formats_from_list(ctx, sample_fmts_list); + if (ret < 0) + return ret; + + return ff_set_common_all_samplerates(ctx); +} + static int parse_gains(AVFilterContext *ctx) { AudioCrossoverContext *s = ctx->priv; @@ -354,10 +396,10 @@ BIQUAD_PROCESS(dblp, double) static int filter_channels_## name(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \ { \ AudioCrossoverContext *s = ctx->priv; \ - AVFrame *in = s->input_frame; \ + AVFrame *in = arg; \ AVFrame **frames = s->frames; \ - const int start = (in->channels * jobnr) / nb_jobs; \ - const int end = (in->channels * (jobnr+1)) / nb_jobs; \ + const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs; \ + const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; \ const int nb_samples = in->nb_samples; \ const int nb_outs = ctx->nb_outputs; \ const int first_order = s->first_order; \ @@ -480,11 +522,10 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) AVFilterContext *ctx = inlink->dst; AudioCrossoverContext *s = ctx->priv; AVFrame **frames = s->frames; - int i, ret = 0; + int ret = 0; - for (i = 0; i < ctx->nb_outputs; i++) { + for (int i = 0; i < ctx->nb_outputs; i++) { frames[i] = ff_get_audio_buffer(ctx->outputs[i], in->nb_samples); - if (!frames[i]) { ret = AVERROR(ENOMEM); break; @@ -496,11 +537,15 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) if (ret < 0) goto fail; - s->input_frame = in; - ff_filter_execute(ctx, s->filter_channels, NULL, NULL, - FFMIN(inlink->channels, ff_filter_get_nb_threads(ctx))); + ff_filter_execute(ctx, s->filter_channels, in, NULL, + FFMIN(inlink->ch_layout.nb_channels, ff_filter_get_nb_threads(ctx))); + + for (int i = 0; i < ctx->nb_outputs; i++) { + if (ff_outlink_get_status(ctx->outputs[i])) { + av_frame_free(&frames[i]); + continue; + } - for (i = 0; i < ctx->nb_outputs; i++) { ret = ff_filter_frame(ctx->outputs[i], frames[i]); frames[i] = NULL; if (ret < 0) @@ -508,14 +553,55 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) } fail: - for (i = 0; i < ctx->nb_outputs; i++) + for (int i = 0; i < ctx->nb_outputs; i++) av_frame_free(&frames[i]); - av_frame_free(&in); - s->input_frame = NULL; return ret; } +static int activate(AVFilterContext *ctx) +{ + AVFilterLink *inlink = ctx->inputs[0]; + int status, ret; + AVFrame *in; + int64_t pts; + + for (int i = 0; i < ctx->nb_outputs; i++) { + FF_FILTER_FORWARD_STATUS_BACK_ALL(ctx->outputs[i], ctx); + } + + ret = ff_inlink_consume_frame(inlink, &in); + if (ret < 0) + return ret; + if (ret > 0) { + ret = filter_frame(inlink, in); + av_frame_free(&in); + if (ret < 0) + return ret; + } + + if (ff_inlink_acknowledge_status(inlink, &status, &pts)) { + for (int i = 0; i < ctx->nb_outputs; i++) { + if (ff_outlink_get_status(ctx->outputs[i])) + continue; + ff_outlink_set_status(ctx->outputs[i], status, pts); + } + return 0; + } + + for (int i = 0; i < ctx->nb_outputs; i++) { + if (ff_outlink_get_status(ctx->outputs[i])) + continue; + + if (ff_outlink_frame_wanted(ctx->outputs[i])) { + ff_inlink_request_frame(inlink); + return 0; + } + } + + return FFERROR_NOT_READY; +} + static av_cold void uninit(AVFilterContext *ctx) { AudioCrossoverContext *s = ctx->priv; @@ -528,7 +614,6 @@ static const AVFilterPad inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_AUDIO, - .filter_frame = filter_frame, .config_props = config_input, }, }; @@ -539,10 +624,11 @@ const AVFilter ff_af_acrossover = { .priv_size = sizeof(AudioCrossoverContext), .priv_class = &acrossover_class, .init = init, + .activate = activate, .uninit = uninit, FILTER_INPUTS(inputs), .outputs = NULL, - FILTER_SAMPLEFMTS(AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_DBLP), + FILTER_QUERY_FUNC(query_formats), .flags = AVFILTER_FLAG_DYNAMIC_OUTPUTS | AVFILTER_FLAG_SLICE_THREADS, }; diff --git a/libavfilter/af_acrusher.c b/libavfilter/af_acrusher.c index 14d66e88e..5c9f36529 100644 --- a/libavfilter/af_acrusher.c +++ b/libavfilter/af_acrusher.c @@ -244,11 +244,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) s->round = round(s->samples); } - for (c = 0; c < inlink->channels; c++) { + for (c = 0; c < inlink->ch_layout.nb_channels; c++) { double sample = src[c] * level_in; sample = mix * samplereduction(s, &s->sr[c], sample) + src[c] * (1. - mix) * level_in; - dst[c] = bitreduction(s, sample) * level_out; + dst[c] = ctx->is_disabled ? src[c] : bitreduction(s, sample) * level_out; } src += c; dst += c; @@ -296,7 +296,7 @@ static int config_input(AVFilterLink *inlink) s->lfo.amount = .5; if (!s->sr) - s->sr = av_calloc(inlink->channels, sizeof(*s->sr)); + s->sr = av_calloc(inlink->ch_layout.nb_channels, sizeof(*s->sr)); if (!s->sr) return AVERROR(ENOMEM); @@ -342,4 +342,5 @@ const AVFilter ff_af_acrusher = { FILTER_OUTPUTS(avfilter_af_acrusher_outputs), FILTER_SINGLE_SAMPLEFMT(AV_SAMPLE_FMT_DBL), .process_command = process_command, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, }; diff --git a/libavfilter/af_adeclick.c b/libavfilter/af_adeclick.c index 77336e50b..2db9a29fd 100644 --- a/libavfilter/af_adeclick.c +++ b/libavfilter/af_adeclick.c @@ -151,7 +151,7 @@ static int config_input(AVFilterLink *inlink) s->efifo = av_audio_fifo_alloc(inlink->format, 1, s->window_size); if (!s->efifo) return AVERROR(ENOMEM); - s->fifo = av_audio_fifo_alloc(inlink->format, inlink->channels, s->window_size); + s->fifo = av_audio_fifo_alloc(inlink->format, inlink->ch_layout.nb_channels, s->window_size); if (!s->fifo) return AVERROR(ENOMEM); s->overlap_skip = s->method ? (s->window_size - s->hop_size) / 2 : 0; @@ -160,12 +160,12 @@ static int config_input(AVFilterLink *inlink) s->overlap_skip); } - s->nb_channels = inlink->channels; - s->chan = av_calloc(inlink->channels, sizeof(*s->chan)); + s->nb_channels = inlink->ch_layout.nb_channels; + s->chan = av_calloc(inlink->ch_layout.nb_channels, sizeof(*s->chan)); if (!s->chan) return AVERROR(ENOMEM); - for (i = 0; i < inlink->channels; i++) { + for (i = 0; i < inlink->ch_layout.nb_channels; i++) { DeclickChannel *c = &s->chan[i]; c->detection = av_calloc(s->window_size, sizeof(*c->detection)); @@ -557,11 +557,11 @@ static int filter_frame(AVFilterLink *inlink) goto fail; td.out = out; - ret = ff_filter_execute(ctx, filter_channel, &td, NULL, inlink->channels); + ret = ff_filter_execute(ctx, filter_channel, &td, NULL, inlink->ch_layout.nb_channels); if (ret < 0) goto fail; - for (ch = 0; ch < s->in->channels; ch++) { + for (ch = 0; ch < s->in->ch_layout.nb_channels; ch++) { double *is = (double *)s->is->extended_data[ch]; for (j = 0; j < s->hop_size; j++) { @@ -580,7 +580,7 @@ static int filter_frame(AVFilterLink *inlink) s->pts += av_rescale_q(s->hop_size, (AVRational){1, outlink->sample_rate}, outlink->time_base); s->detected_errors += detected_errors; - s->nb_samples += out->nb_samples * inlink->channels; + s->nb_samples += out->nb_samples * inlink->ch_layout.nb_channels; ret = ff_filter_frame(outlink, out); if (ret < 0) diff --git a/libavfilter/af_adecorrelate.c b/libavfilter/af_adecorrelate.c index bac7937c1..cadc62c1f 100644 --- a/libavfilter/af_adecorrelate.c +++ b/libavfilter/af_adecorrelate.c @@ -131,12 +131,12 @@ static int config_input(AVFilterLink *inlink) s->seed = av_get_random_seed(); av_lfg_init(&s->c, s->seed); - s->nb_channels = inlink->channels; - s->ap = av_calloc(inlink->channels, sizeof(*s->ap)); + s->nb_channels = inlink->ch_layout.nb_channels; + s->ap = av_calloc(inlink->ch_layout.nb_channels, sizeof(*s->ap)); if (!s->ap) return AVERROR(ENOMEM); - for (int i = 0; i < inlink->channels; i++) { + for (int i = 0; i < inlink->ch_layout.nb_channels; i++) { for (int j = 0; j < s->stages; j++) { ret = ap_init(&s->ap[i][j], inlink->sample_rate, (double)av_lfg_get(&s->c) / 0xffffffff * 2.2917e-3 + 0.83333e-3); @@ -160,8 +160,8 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo ThreadData *td = arg; AVFrame *out = td->out; AVFrame *in = td->in; - const int start = (in->channels * jobnr) / nb_jobs; - const int end = (in->channels * (jobnr+1)) / nb_jobs; + const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs; + const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; for (int ch = start; ch < end; ch++) s->filter_channel(ctx, ch, in, out); @@ -189,7 +189,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) td.in = in; td.out = out; ff_filter_execute(ctx, filter_channels, &td, NULL, - FFMIN(inlink->channels, ff_filter_get_nb_threads(ctx))); + FFMIN(inlink->ch_layout.nb_channels, ff_filter_get_nb_threads(ctx))); if (out != in) av_frame_free(&in); diff --git a/libavfilter/af_adelay.c b/libavfilter/af_adelay.c index ed8a8ae73..9e63e2d61 100644 --- a/libavfilter/af_adelay.c +++ b/libavfilter/af_adelay.c @@ -31,6 +31,7 @@ typedef struct ChanDelay { int64_t delay; size_t delay_index; size_t index; + unsigned int samples_size; uint8_t *samples; } ChanDelay; @@ -48,13 +49,14 @@ typedef struct AudioDelayContext { void (*delay_channel)(ChanDelay *d, int nb_samples, const uint8_t *src, uint8_t *dst); + int (*resize_channel_samples)(ChanDelay *d, int64_t new_delay); } AudioDelayContext; #define OFFSET(x) offsetof(AudioDelayContext, x) #define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM static const AVOption adelay_options[] = { - { "delays", "set list of delays for each channel", OFFSET(delays), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, A }, + { "delays", "set list of delays for each channel", OFFSET(delays), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, A | AV_OPT_FLAG_RUNTIME_PARAM }, { "all", "use last available delay for remained channels", OFFSET(all), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, A }, { NULL } }; @@ -96,45 +98,112 @@ DELAY(s32, int32_t, 0) DELAY(flt, float, 0) DELAY(dbl, double, 0) +#define CHANGE_DELAY(name, type, fill) \ +static int resize_samples_## name ##p(ChanDelay *d, int64_t new_delay) \ +{ \ + type *samples; \ + \ + if (new_delay == d->delay) { \ + return 0; \ + } \ + \ + if (new_delay == 0) { \ + av_freep(&d->samples); \ + d->samples_size = 0; \ + d->delay = 0; \ + d->index = 0; \ + d->delay_index = 0; \ + return 0; \ + } \ + \ + samples = (type *) av_fast_realloc(d->samples, &d->samples_size, new_delay * sizeof(type)); \ + if (!samples) { \ + return AVERROR(ENOMEM); \ + } \ + \ + if (new_delay < d->delay) { \ + if (d->index > new_delay) { \ + d->index -= new_delay; \ + memmove(samples, &samples[new_delay], d->index * sizeof(type)); \ + d->delay_index = new_delay; \ + } else if (d->delay_index > d->index) { \ + memmove(&samples[d->index], &samples[d->index+(d->delay-new_delay)], \ + (new_delay - d->index) * sizeof(type)); \ + d->delay_index -= d->delay - new_delay; \ + } \ + } else { \ + size_t block_size; \ + if (d->delay_index >= d->delay) { \ + block_size = (d->delay - d->index) * sizeof(type); \ + memmove(&samples[d->index+(new_delay - d->delay)], &samples[d->index], block_size); \ + d->delay_index = new_delay; \ + } else { \ + d->delay_index += new_delay - d->delay; \ + } \ + block_size = (new_delay - d->delay) * sizeof(type); \ + memset(&samples[d->index], fill, block_size); \ + } \ + d->delay = new_delay; \ + d->samples = (void *) samples; \ + return 0; \ +} + +CHANGE_DELAY(u8, uint8_t, 0x80) +CHANGE_DELAY(s16, int16_t, 0) +CHANGE_DELAY(s32, int32_t, 0) +CHANGE_DELAY(flt, float, 0) +CHANGE_DELAY(dbl, double, 0) + +static int parse_delays(char *p, char **saveptr, int64_t *result, AVFilterContext *ctx, int sample_rate) { + float delay, div; + int ret; + char *arg; + char type = 0; + + if (!(arg = av_strtok(p, "|", saveptr))) + return 1; + + ret = av_sscanf(arg, "%"SCNd64"%c", result, &type); + if (ret != 2 || type != 'S') { + div = type == 's' ? 1.0 : 1000.0; + if (av_sscanf(arg, "%f", &delay) != 1) { + av_log(ctx, AV_LOG_ERROR, "Invalid syntax for delay.\n"); + return AVERROR(EINVAL); + } + *result = delay * sample_rate / div; + } + + if (*result < 0) { + av_log(ctx, AV_LOG_ERROR, "Delay must be non negative number.\n"); + return AVERROR(EINVAL); + } + return 0; +} + static int config_input(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; AudioDelayContext *s = ctx->priv; - char *p, *arg, *saveptr = NULL; + char *p, *saveptr = NULL; int i; - s->chandelay = av_calloc(inlink->channels, sizeof(*s->chandelay)); + s->chandelay = av_calloc(inlink->ch_layout.nb_channels, sizeof(*s->chandelay)); if (!s->chandelay) return AVERROR(ENOMEM); - s->nb_delays = inlink->channels; + s->nb_delays = inlink->ch_layout.nb_channels; s->block_align = av_get_bytes_per_sample(inlink->format); p = s->delays; for (i = 0; i < s->nb_delays; i++) { ChanDelay *d = &s->chandelay[i]; - float delay, div; - char type = 0; int ret; - if (!(arg = av_strtok(p, "|", &saveptr))) + ret = parse_delays(p, &saveptr, &d->delay, ctx, inlink->sample_rate); + if (ret == 1) break; - + else if (ret < 0) + return ret; p = NULL; - - ret = av_sscanf(arg, "%"SCNd64"%c", &d->delay, &type); - if (ret != 2 || type != 'S') { - div = type == 's' ? 1.0 : 1000.0; - if (av_sscanf(arg, "%f", &delay) != 1) { - av_log(ctx, AV_LOG_ERROR, "Invalid syntax for delay.\n"); - return AVERROR(EINVAL); - } - d->delay = delay * inlink->sample_rate / div; - } - - if (d->delay < 0) { - av_log(ctx, AV_LOG_ERROR, "Delay must be non negative number.\n"); - return AVERROR(EINVAL); - } } if (s->all && i) { @@ -171,21 +240,81 @@ static int config_input(AVFilterLink *inlink) d->samples = av_malloc_array(d->delay, s->block_align); if (!d->samples) return AVERROR(ENOMEM); + d->samples_size = d->delay * s->block_align; s->max_delay = FFMAX(s->max_delay, d->delay); } switch (inlink->format) { - case AV_SAMPLE_FMT_U8P : s->delay_channel = delay_channel_u8p ; break; - case AV_SAMPLE_FMT_S16P: s->delay_channel = delay_channel_s16p; break; - case AV_SAMPLE_FMT_S32P: s->delay_channel = delay_channel_s32p; break; - case AV_SAMPLE_FMT_FLTP: s->delay_channel = delay_channel_fltp; break; - case AV_SAMPLE_FMT_DBLP: s->delay_channel = delay_channel_dblp; break; + case AV_SAMPLE_FMT_U8P : s->delay_channel = delay_channel_u8p ; + s->resize_channel_samples = resize_samples_u8p; break; + case AV_SAMPLE_FMT_S16P: s->delay_channel = delay_channel_s16p; + s->resize_channel_samples = resize_samples_s16p; break; + case AV_SAMPLE_FMT_S32P: s->delay_channel = delay_channel_s32p; + s->resize_channel_samples = resize_samples_s32p; break; + case AV_SAMPLE_FMT_FLTP: s->delay_channel = delay_channel_fltp; + s->resize_channel_samples = resize_samples_fltp; break; + case AV_SAMPLE_FMT_DBLP: s->delay_channel = delay_channel_dblp; + s->resize_channel_samples = resize_samples_dblp; break; } return 0; } +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + int ret = AVERROR(ENOSYS); + AVFilterLink *inlink = ctx->inputs[0]; + AudioDelayContext *s = ctx->priv; + + if (!strcmp(cmd, "delays")) { + int64_t delay; + char *p, *saveptr = NULL; + int64_t all_delay = -1; + int64_t max_delay = 0; + char *args_cpy = av_strdup(args); + if (args_cpy == NULL) { + return AVERROR(ENOMEM); + } + + ret = 0; + p = args_cpy; + + if (!strncmp(args, "all:", 4)) { + p = &args_cpy[4]; + ret = parse_delays(p, &saveptr, &all_delay, ctx, inlink->sample_rate); + if (ret == 1) + ret = AVERROR(EINVAL); + else if (ret == 0) + delay = all_delay; + } + + if (!ret) { + for (int i = 0; i < s->nb_delays; i++) { + ChanDelay *d = &s->chandelay[i]; + + if (all_delay < 0) { + ret = parse_delays(p, &saveptr, &delay, ctx, inlink->sample_rate); + if (ret != 0) { + ret = 0; + break; + } + p = NULL; + } + + ret = s->resize_channel_samples(d, delay); + if (ret) + break; + max_delay = FFMAX(max_delay, d->delay); + } + s->max_delay = FFMAX(s->max_delay, max_delay); + } + av_freep(&args_cpy); + } + return ret; +} + static int filter_frame(AVFilterLink *inlink, AVFrame *frame) { AVFilterContext *ctx = inlink->dst; @@ -242,7 +371,7 @@ static int activate(AVFilterContext *ctx) av_samples_set_silence(frame->extended_data, 0, frame->nb_samples, - outlink->channels, + outlink->ch_layout.nb_channels, frame->format); frame->pts = s->next_pts; @@ -274,7 +403,7 @@ static int activate(AVFilterContext *ctx) av_samples_set_silence(frame->extended_data, 0, frame->nb_samples, - outlink->channels, + outlink->ch_layout.nb_channels, frame->format); frame->pts = s->next_pts; @@ -330,4 +459,5 @@ const AVFilter ff_af_adelay = { FILTER_SAMPLEFMTS(AV_SAMPLE_FMT_U8P, AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_DBLP), .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, + .process_command = process_command, }; diff --git a/libavfilter/af_adenorm.c b/libavfilter/af_adenorm.c index 3ad1e7f59..583b7fafe 100644 --- a/libavfilter/af_adenorm.c +++ b/libavfilter/af_adenorm.c @@ -39,8 +39,8 @@ typedef struct ADenormContext { int type; int64_t in_samples; - void (*filter)(AVFilterContext *ctx, void *dst, - const void *src, int nb_samples); + void (*filter[NB_TYPES])(AVFilterContext *ctx, void *dst, + const void *src, int nb_samples); } ADenormContext; static void dc_denorm_fltp(AVFilterContext *ctx, void *dstp, @@ -158,30 +158,18 @@ static int config_output(AVFilterLink *outlink) AVFilterContext *ctx = outlink->src; ADenormContext *s = ctx->priv; - switch (s->type) { - case DC_TYPE: - switch (outlink->format) { - case AV_SAMPLE_FMT_FLTP: s->filter = dc_denorm_fltp; break; - case AV_SAMPLE_FMT_DBLP: s->filter = dc_denorm_dblp; break; - } + switch (outlink->format) { + case AV_SAMPLE_FMT_FLTP: + s->filter[DC_TYPE] = dc_denorm_fltp; + s->filter[AC_TYPE] = ac_denorm_fltp; + s->filter[SQ_TYPE] = sq_denorm_fltp; + s->filter[PS_TYPE] = ps_denorm_fltp; break; - case AC_TYPE: - switch (outlink->format) { - case AV_SAMPLE_FMT_FLTP: s->filter = ac_denorm_fltp; break; - case AV_SAMPLE_FMT_DBLP: s->filter = ac_denorm_dblp; break; - } - break; - case SQ_TYPE: - switch (outlink->format) { - case AV_SAMPLE_FMT_FLTP: s->filter = sq_denorm_fltp; break; - case AV_SAMPLE_FMT_DBLP: s->filter = sq_denorm_dblp; break; - } - break; - case PS_TYPE: - switch (outlink->format) { - case AV_SAMPLE_FMT_FLTP: s->filter = ps_denorm_fltp; break; - case AV_SAMPLE_FMT_DBLP: s->filter = ps_denorm_dblp; break; - } + case AV_SAMPLE_FMT_DBLP: + s->filter[DC_TYPE] = dc_denorm_dblp; + s->filter[AC_TYPE] = ac_denorm_dblp; + s->filter[SQ_TYPE] = sq_denorm_dblp; + s->filter[PS_TYPE] = ps_denorm_dblp; break; default: av_assert0(0); @@ -200,13 +188,13 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo ThreadData *td = arg; AVFrame *out = td->out; AVFrame *in = td->in; - const int start = (in->channels * jobnr) / nb_jobs; - const int end = (in->channels * (jobnr+1)) / nb_jobs; + const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs; + const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; for (int ch = start; ch < end; ch++) { - s->filter(ctx, out->extended_data[ch], - in->extended_data[ch], - in->nb_samples); + s->filter[s->type](ctx, out->extended_data[ch], + in->extended_data[ch], + in->nb_samples); } return 0; @@ -234,7 +222,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) s->level = exp(s->level_db / 20. * M_LN10); td.in = in; td.out = out; ff_filter_execute(ctx, filter_channels, &td, NULL, - FFMIN(inlink->channels, ff_filter_get_nb_threads(ctx))); + FFMIN(inlink->ch_layout.nb_channels, ff_filter_get_nb_threads(ctx))); s->in_samples += in->nb_samples; @@ -243,19 +231,6 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) return ff_filter_frame(outlink, out); } -static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, - char *res, int res_len, int flags) -{ - AVFilterLink *outlink = ctx->outputs[0]; - int ret; - - ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); - if (ret < 0) - return ret; - - return config_output(outlink); -} - static const AVFilterPad adenorm_inputs[] = { { .name = "default", @@ -295,7 +270,7 @@ const AVFilter ff_af_adenorm = { FILTER_OUTPUTS(adenorm_outputs), FILTER_SAMPLEFMTS(AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_DBLP), .priv_class = &adenorm_class, - .process_command = process_command, + .process_command = ff_filter_process_command, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, }; diff --git a/libavfilter/af_aderivative.c b/libavfilter/af_aderivative.c index baa272d60..853c0f341 100644 --- a/libavfilter/af_aderivative.c +++ b/libavfilter/af_aderivative.c @@ -16,6 +16,7 @@ * 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" @@ -103,8 +104,18 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) AVFilterContext *ctx = inlink->dst; ADerivativeContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; - AVFrame *out = ff_get_audio_buffer(outlink, in->nb_samples); + AVFrame *out; + if (ctx->is_disabled) { + if (s->prev) + av_samples_set_silence(s->prev->extended_data, 0, 1, + s->prev->ch_layout.nb_channels, + s->prev->format); + + return ff_filter_frame(outlink, in); + } + + out = ff_get_audio_buffer(outlink, in->nb_samples); if (!out) { av_frame_free(&in); return AVERROR(ENOMEM); @@ -120,7 +131,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) } s->filter((void **)out->extended_data, (void **)s->prev->extended_data, (const void **)in->extended_data, - in->nb_samples, in->channels); + in->nb_samples, in->ch_layout.nb_channels); av_frame_free(&in); return ff_filter_frame(outlink, out); @@ -149,23 +160,33 @@ static const AVFilterPad aderivative_outputs[] = { }, }; +static const AVOption aderivative_options[] = { + { NULL } +}; + +AVFILTER_DEFINE_CLASS_EXT(aderivative, "aderivative/aintegral", aderivative_options); + const AVFilter ff_af_aderivative = { .name = "aderivative", .description = NULL_IF_CONFIG_SMALL("Compute derivative of input audio."), .priv_size = sizeof(ADerivativeContext), + .priv_class = &aderivative_class, .uninit = uninit, FILTER_INPUTS(aderivative_inputs), FILTER_OUTPUTS(aderivative_outputs), FILTER_SAMPLEFMTS(AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_DBLP), + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, }; const AVFilter ff_af_aintegral = { .name = "aintegral", .description = NULL_IF_CONFIG_SMALL("Compute integral of input audio."), .priv_size = sizeof(ADerivativeContext), + .priv_class = &aderivative_class, .uninit = uninit, FILTER_INPUTS(aderivative_inputs), FILTER_OUTPUTS(aderivative_outputs), FILTER_SAMPLEFMTS(AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_DBLP), + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, }; diff --git a/libavfilter/af_adynamicequalizer.c b/libavfilter/af_adynamicequalizer.c index f377a5db3..35d1adb9c 100644 --- a/libavfilter/af_adynamicequalizer.c +++ b/libavfilter/af_adynamicequalizer.c @@ -22,7 +22,6 @@ #include "avfilter.h" #include "audio.h" #include "formats.h" -#include "hermite.h" typedef struct AudioDynamicEqualizerContext { const AVClass *class; @@ -42,6 +41,7 @@ typedef struct AudioDynamicEqualizerContext { double attack_coef; double release_coef; int mode; + int type; AVFrame *state; } AudioDynamicEqualizerContext; @@ -113,7 +113,7 @@ static double get_gain(double in, double srate, double makeup, if (Lyg >= state[2]) attslew = 1; } - } else if (2. * (Lxg-thresdb) > width) { + } else if (2. * (Lxg - thresdb) > width) { Lyg = thresdb + (Lxg - thresdb) * iratio; } @@ -121,7 +121,7 @@ static double get_gain(double in, double srate, double makeup, Lxl = Lxg - Lyg; - Ly1 = fmaxf(Lxl, release_coeff * state[1] +(1. - release_coeff) * Lxl); + Ly1 = fmax(Lxl, release_coeff * state[1] +(1. - release_coeff) * Lxl); Lyl = attack_coeff * state[0] + (1. - attack_coeff) * Ly1; cdb = -Lyl; @@ -150,16 +150,17 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo const double range = s->range; const double dfrequency = fmin(s->dfrequency, sample_rate * 0.5); const double tfrequency = fmin(s->tfrequency, sample_rate * 0.5); - const double threshold = log(s->threshold + DBL_EPSILON); + const double threshold = to_dB(s->threshold + DBL_EPSILON); const double release = s->release_coef; const double attack = s->attack_coef; const double dqfactor = s->dqfactor; const double tqfactor = s->tqfactor; const double fg = tan(M_PI * tfrequency / sample_rate); const double dg = tan(M_PI * dfrequency / sample_rate); - const int start = (in->channels * jobnr) / nb_jobs; - const int end = (in->channels * (jobnr+1)) / nb_jobs; + const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs; + const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; const int mode = s->mode; + const int type = s->type; const double knee = s->knee; const double slew = s->slew; const double aattack = exp(-1000. / ((s->attack + 2.0 * (slew - 1.)) * sample_rate)); @@ -186,6 +187,7 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo for (int n = 0; n < out->nb_samples; n++) { double detect, gain, v, listen; double fa[3], fm[3]; + double k, g; detect = listen = get_svf(src[n], dm, da, state); detect = fabs(detect); @@ -194,8 +196,9 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo aattack, iratio, knee, range, threshold, slew, &state[4], attack, release, nc); - { - double k = 1. / (tqfactor * gain); + switch (type) { + case 0: + k = 1. / (tqfactor * gain); fa[0] = 1. / (1. + fg * (fg + k)); fa[1] = fg * fa[0]; @@ -204,6 +207,31 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo fm[0] = 1.; fm[1] = k * (gain * gain - 1.); fm[2] = 0.; + break; + case 1: + k = 1. / tqfactor; + g = fg / sqrt(gain); + + fa[0] = 1. / (1. + g * (g + k)); + fa[1] = g * fa[0]; + fa[2] = g * fa[1]; + + fm[0] = 1.; + fm[1] = k * (gain - 1.); + fm[2] = gain * gain - 1.; + break; + case 2: + k = 1. / tqfactor; + g = fg / sqrt(gain); + + fa[0] = 1. / (1. + g * (g + k)); + fa[1] = g * fa[0]; + fa[2] = g * fa[1]; + + fm[0] = gain * gain; + fm[1] = k * (1. - gain) * gain; + fm[2] = 1. - gain * gain; + break; } v = get_svf(src[n], fm, fa, &state[2]); @@ -245,7 +273,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) td.in = in; td.out = out; ff_filter_execute(ctx, filter_channels, &td, NULL, - FFMIN(outlink->channels, ff_filter_get_nb_threads(ctx))); + FFMIN(outlink->ch_layout.nb_channels, ff_filter_get_nb_threads(ctx))); if (out != in) av_frame_free(&in); @@ -279,6 +307,10 @@ static const AVOption adynamicequalizer_options[] = { { "listen", 0, 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, FLAGS, "mode" }, { "cut", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "mode" }, { "boost", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "mode" }, + { "tftype", "set target filter type", OFFSET(type), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, FLAGS, "type" }, + { "bell", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "type" }, + { "lowshelf", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "type" }, + { "highshelf",0, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "type" }, { NULL } }; diff --git a/libavfilter/af_adynamicsmooth.c b/libavfilter/af_adynamicsmooth.c index 4e00fecc6..3f98d09f5 100644 --- a/libavfilter/af_adynamicsmooth.c +++ b/libavfilter/af_adynamicsmooth.c @@ -63,7 +63,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) av_frame_copy_props(out, in); } - for (int ch = 0; ch < out->channels; ch++) { + for (int ch = 0; ch < out->ch_layout.nb_channels; ch++) { const double *src = (const double *)in->extended_data[ch]; double *dst = (double *)out->extended_data[ch]; double *coeffs = (double *)s->coeffs->extended_data[ch]; diff --git a/libavfilter/af_aecho.c b/libavfilter/af_aecho.c index 73d9f1ac7..e610c30d5 100644 --- a/libavfilter/af_aecho.c +++ b/libavfilter/af_aecho.c @@ -236,7 +236,7 @@ static int config_output(AVFilterLink *outlink) av_freep(&s->delayptrs); return av_samples_alloc_array_and_samples(&s->delayptrs, NULL, - outlink->channels, + outlink->ch_layout.nb_channels, s->max_samples, outlink->format, 0); } @@ -259,7 +259,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) } s->echo_samples(s, s->delayptrs, frame->extended_data, out_frame->extended_data, - frame->nb_samples, inlink->channels); + frame->nb_samples, inlink->ch_layout.nb_channels); s->next_pts = frame->pts + av_rescale_q(frame->nb_samples, (AVRational){1, inlink->sample_rate}, inlink->time_base); @@ -282,11 +282,11 @@ static int request_frame(AVFilterLink *outlink) av_samples_set_silence(frame->extended_data, 0, frame->nb_samples, - outlink->channels, + outlink->ch_layout.nb_channels, frame->format); s->echo_samples(s, s->delayptrs, frame->extended_data, frame->extended_data, - frame->nb_samples, outlink->channels); + frame->nb_samples, outlink->ch_layout.nb_channels); frame->pts = s->next_pts; if (s->next_pts != AV_NOPTS_VALUE) diff --git a/libavfilter/af_aemphasis.c b/libavfilter/af_aemphasis.c index 1adfcdb63..91878987d 100644 --- a/libavfilter/af_aemphasis.c +++ b/libavfilter/af_aemphasis.c @@ -105,8 +105,8 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo ThreadData *td = arg; AVFrame *out = td->out; AVFrame *in = td->in; - const int start = (in->channels * jobnr) / nb_jobs; - const int end = (in->channels * (jobnr+1)) / nb_jobs; + const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs; + const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; for (int ch = start; ch < end; ch++) { const double *src = (const double *)in->extended_data[ch]; @@ -144,7 +144,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) td.in = in; td.out = out; ff_filter_execute(ctx, filter_channels, &td, NULL, - FFMIN(inlink->channels, ff_filter_get_nb_threads(ctx))); + FFMIN(inlink->ch_layout.nb_channels, ff_filter_get_nb_threads(ctx))); if (in != out) av_frame_free(&in); diff --git a/libavfilter/af_aexciter.c b/libavfilter/af_aexciter.c index 5d76f290a..8e829f992 100644 --- a/libavfilter/af_aexciter.c +++ b/libavfilter/af_aexciter.c @@ -195,7 +195,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) dst = (double *)out->data[0]; for (int n = 0; n < in->nb_samples; n++) { - for (int c = 0; c < inlink->channels; c++) { + for (int c = 0; c < inlink->ch_layout.nb_channels; c++) { double sample = src[c] * level_in; sample = distortion_process(s, &s->cp[c], sample); @@ -208,8 +208,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) dst[c] = sample; } - src += inlink->channels; - dst += inlink->channels; + src += inlink->ch_layout.nb_channels; + dst += inlink->ch_layout.nb_channels; } if (in != out) @@ -231,11 +231,11 @@ static int config_input(AVFilterLink *inlink) AExciterContext *s = ctx->priv; if (!s->cp) - s->cp = av_calloc(inlink->channels, sizeof(*s->cp)); + s->cp = av_calloc(inlink->ch_layout.nb_channels, sizeof(*s->cp)); if (!s->cp) return AVERROR(ENOMEM); - for (int i = 0; i < inlink->channels; i++) + for (int i = 0; i < inlink->ch_layout.nb_channels; i++) set_params(&s->cp[i], s->blend, s->drive, inlink->sample_rate, s->freq, s->ceil); diff --git a/libavfilter/af_afade.c b/libavfilter/af_afade.c index c57709050..0445bb729 100644 --- a/libavfilter/af_afade.c +++ b/libavfilter/af_afade.c @@ -23,6 +23,8 @@ * fade audio filter */ +#include "config_components.h" + #include "libavutil/opt.h" #include "audio.h" #include "avfilter.h" @@ -289,7 +291,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf) if ((!s->type && (cur_sample + nb_samples < s->start_sample)) || ( s->type && (s->start_sample + s->nb_samples < cur_sample))) { av_samples_set_silence(out_buf->extended_data, 0, nb_samples, - out_buf->channels, out_buf->format); + out_buf->ch_layout.nb_channels, out_buf->format); } else { int64_t start; @@ -299,7 +301,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf) start = s->start_sample + s->nb_samples - cur_sample; s->fade_samples(out_buf->extended_data, buf->extended_data, - nb_samples, buf->channels, + nb_samples, buf->ch_layout.nb_channels, s->type ? -1 : 1, start, s->nb_samples, s->curve); } @@ -502,7 +504,7 @@ static int activate(AVFilterContext *ctx) s->crossfade_samples(out->extended_data, cf[0]->extended_data, cf[1]->extended_data, - s->nb_samples, out->channels, + s->nb_samples, out->ch_layout.nb_channels, s->curve, s->curve2); out->pts = s->pts; s->pts += av_rescale_q(s->nb_samples, @@ -523,7 +525,7 @@ static int activate(AVFilterContext *ctx) } 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); + outlink->ch_layout.nb_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); @@ -543,7 +545,7 @@ static int activate(AVFilterContext *ctx) } s->fade_samples(out->extended_data, cf[1]->extended_data, s->nb_samples, - outlink->channels, 1, 0, s->nb_samples, s->curve2); + outlink->ch_layout.nb_channels, 1, 0, s->nb_samples, s->curve2); out->pts = s->pts; s->pts += av_rescale_q(s->nb_samples, (AVRational){ 1, outlink->sample_rate }, outlink->time_base); diff --git a/libavfilter/af_afftdn.c b/libavfilter/af_afftdn.c index d1dbbc667..cdb256fa1 100644 --- a/libavfilter/af_afftdn.c +++ b/libavfilter/af_afftdn.c @@ -20,7 +20,6 @@ #include -#include "libavutil/audio_fifo.h" #include "libavutil/avstring.h" #include "libavutil/channel_layout.h" #include "libavutil/opt.h" @@ -31,8 +30,15 @@ #include "filters.h" #define C (M_LN10 * 0.1) -#define RATIO 0.98 -#define RRATIO (1.0 - RATIO) +#define SOLVE_SIZE (5) +#define NB_PROFILE_BANDS (15) + +enum SampleNoiseModes { + SAMPLE_NONE, + SAMPLE_START, + SAMPLE_STOP, + NB_SAMPLEMODES +}; enum OutModes { IN_MODE, @@ -41,6 +47,14 @@ enum OutModes { NB_MODES }; +enum NoiseLinkType { + NONE_LINK, + MIN_LINK, + MAX_LINK, + AVERAGE_LINK, + NB_LINK +}; + enum NoiseType { WHITE_NOISE, VINYL_NOISE, @@ -50,13 +64,14 @@ enum NoiseType { }; typedef struct DeNoiseChannel { - int band_noise[15]; - double noise_band_auto_var[15]; - double noise_band_sample[15]; + double band_noise[NB_PROFILE_BANDS]; + double noise_band_auto_var[NB_PROFILE_BANDS]; + double noise_band_sample[NB_PROFILE_BANDS]; double *amt; double *band_amt; double *band_excit; double *gain; + double *smoothed_gain; double *prior; double *prior_band_excit; double *clean_data; @@ -66,21 +81,25 @@ typedef struct DeNoiseChannel { double *abs_var; double *rel_var; double *min_abs_var; - AVComplexFloat *fft_in; + float *fft_in; AVComplexFloat *fft_out; AVTXContext *fft, *ifft; av_tx_fn tx_fn, itx_fn; - double noise_band_norm[15]; - double noise_band_avr[15]; - double noise_band_avi[15]; - double noise_band_var[15]; + double noise_band_norm[NB_PROFILE_BANDS]; + double noise_band_avr[NB_PROFILE_BANDS]; + double noise_band_avi[NB_PROFILE_BANDS]; + double noise_band_var[NB_PROFILE_BANDS]; - double sfm_threshold; - double sfm_alpha; - double sfm_results[3]; - int sfm_fail_flags[512]; - int sfm_fail_total; + double noise_reduction; + double last_noise_reduction; + double noise_floor; + double last_noise_floor; + double residual_floor; + double last_residual_floor; + double max_gain; + double max_var; + double gain_scale; } DeNoiseChannel; typedef struct AudioFFTDeNoiseContext { @@ -94,18 +113,16 @@ typedef struct AudioFFTDeNoiseContext { int track_noise; int track_residual; int output_mode; + int noise_floor_link; + float ratio; + int gain_smooth; + float band_multiplier; + float floor_offset; - float last_residual_floor; - float last_noise_floor; - float last_noise_reduction; - float last_noise_balance; - int64_t block_count; - - int64_t pts; int channels; int sample_noise; - int sample_noise_start; - int sample_noise_end; + int sample_noise_blocks; + int sample_noise_mode; float sample_rate; int buffer_length; int fft_length; @@ -115,7 +132,7 @@ typedef struct AudioFFTDeNoiseContext { int sample_advance; int number_of_bands; - int band_centre[15]; + int band_centre[NB_PROFILE_BANDS]; int *bin2band; double *window; @@ -124,22 +141,18 @@ typedef struct AudioFFTDeNoiseContext { DeNoiseChannel *dnch; - double max_gain; - double max_var; - double gain_scale; + AVFrame *winframe; + double window_weight; double floor; double sample_floor; - double auto_floor; - int noise_band_edge[17]; + int noise_band_edge[NB_PROFILE_BANDS + 2]; int noise_band_count; - double matrix_a[25]; - double vector_b[5]; - double matrix_b[75]; - double matrix_c[75]; - - AVAudioFifo *fifo; + double matrix_a[SOLVE_SIZE * SOLVE_SIZE]; + double vector_b[SOLVE_SIZE]; + double matrix_b[SOLVE_SIZE * NB_PROFILE_BANDS]; + double matrix_c[SOLVE_SIZE * NB_PROFILE_BANDS]; } AudioFFTDeNoiseContext; #define OFFSET(x) offsetof(AudioFFTDeNoiseContext, x) @@ -147,29 +160,65 @@ typedef struct AudioFFTDeNoiseContext { #define AFR AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption afftdn_options[] = { + { "noise_reduction", "set the noise reduction",OFFSET(noise_reduction), AV_OPT_TYPE_FLOAT,{.dbl = 12}, .01, 97, AFR }, { "nr", "set the noise reduction", OFFSET(noise_reduction), AV_OPT_TYPE_FLOAT, {.dbl = 12}, .01, 97, AFR }, + { "noise_floor", "set the noise floor",OFFSET(noise_floor), AV_OPT_TYPE_FLOAT, {.dbl =-50}, -80,-20, AFR }, { "nf", "set the noise floor", OFFSET(noise_floor), AV_OPT_TYPE_FLOAT, {.dbl =-50}, -80,-20, AFR }, + { "noise_type", "set the noise type", OFFSET(noise_type), AV_OPT_TYPE_INT, {.i64 = WHITE_NOISE}, WHITE_NOISE, NB_NOISE-1, AF, "type" }, { "nt", "set the noise type", OFFSET(noise_type), AV_OPT_TYPE_INT, {.i64 = WHITE_NOISE}, WHITE_NOISE, NB_NOISE-1, AF, "type" }, + { "white", "white noise", 0, AV_OPT_TYPE_CONST, {.i64 = WHITE_NOISE}, 0, 0, AF, "type" }, { "w", "white noise", 0, AV_OPT_TYPE_CONST, {.i64 = WHITE_NOISE}, 0, 0, AF, "type" }, + { "vinyl", "vinyl noise", 0, AV_OPT_TYPE_CONST, {.i64 = VINYL_NOISE}, 0, 0, AF, "type" }, { "v", "vinyl noise", 0, AV_OPT_TYPE_CONST, {.i64 = VINYL_NOISE}, 0, 0, AF, "type" }, + { "shellac", "shellac noise", 0, AV_OPT_TYPE_CONST, {.i64 = SHELLAC_NOISE}, 0, 0, AF, "type" }, { "s", "shellac noise", 0, AV_OPT_TYPE_CONST, {.i64 = SHELLAC_NOISE}, 0, 0, AF, "type" }, + { "custom", "custom noise", 0, AV_OPT_TYPE_CONST, {.i64 = CUSTOM_NOISE}, 0, 0, AF, "type" }, { "c", "custom noise", 0, AV_OPT_TYPE_CONST, {.i64 = CUSTOM_NOISE}, 0, 0, AF, "type" }, + { "band_noise", "set the custom bands noise", OFFSET(band_noise_str), AV_OPT_TYPE_STRING, {.str = 0}, 0, 0, AF }, { "bn", "set the custom bands noise", OFFSET(band_noise_str), AV_OPT_TYPE_STRING, {.str = 0}, 0, 0, AF }, + { "residual_floor", "set the residual floor",OFFSET(residual_floor), AV_OPT_TYPE_FLOAT, {.dbl =-38}, -80,-20, AFR }, { "rf", "set the residual floor", OFFSET(residual_floor), AV_OPT_TYPE_FLOAT, {.dbl =-38}, -80,-20, AFR }, + { "track_noise", "track noise", OFFSET(track_noise), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AFR }, { "tn", "track noise", OFFSET(track_noise), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AFR }, + { "track_residual", "track residual", OFFSET(track_residual), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AFR }, { "tr", "track residual", OFFSET(track_residual), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AFR }, + { "output_mode", "set output mode", OFFSET(output_mode), AV_OPT_TYPE_INT, {.i64 = OUT_MODE}, 0, NB_MODES-1, AFR, "mode" }, { "om", "set output mode", OFFSET(output_mode), AV_OPT_TYPE_INT, {.i64 = OUT_MODE}, 0, NB_MODES-1, AFR, "mode" }, + { "input", "input", 0, AV_OPT_TYPE_CONST, {.i64 = IN_MODE}, 0, 0, AFR, "mode" }, { "i", "input", 0, AV_OPT_TYPE_CONST, {.i64 = IN_MODE}, 0, 0, AFR, "mode" }, + { "output", "output", 0, AV_OPT_TYPE_CONST, {.i64 = OUT_MODE}, 0, 0, AFR, "mode" }, { "o", "output", 0, AV_OPT_TYPE_CONST, {.i64 = OUT_MODE}, 0, 0, AFR, "mode" }, + { "noise", "noise", 0, AV_OPT_TYPE_CONST, {.i64 = NOISE_MODE}, 0, 0, AFR, "mode" }, { "n", "noise", 0, AV_OPT_TYPE_CONST, {.i64 = NOISE_MODE}, 0, 0, AFR, "mode" }, + { "adaptivity", "set adaptivity factor",OFFSET(ratio), AV_OPT_TYPE_FLOAT, {.dbl = 0.5}, 0, 1, AFR }, + { "ad", "set adaptivity factor",OFFSET(ratio), AV_OPT_TYPE_FLOAT, {.dbl = 0.5}, 0, 1, AFR }, + { "floor_offset", "set noise floor offset factor",OFFSET(floor_offset), AV_OPT_TYPE_FLOAT, {.dbl = 1.0}, -2, 2, AFR }, + { "fo", "set noise floor offset factor",OFFSET(floor_offset), AV_OPT_TYPE_FLOAT, {.dbl = 1.0}, -2, 2, AFR }, + { "noise_link", "set the noise floor link",OFFSET(noise_floor_link),AV_OPT_TYPE_INT,{.i64 = MIN_LINK}, 0, NB_LINK-1, AFR, "link" }, + { "nl", "set the noise floor link", OFFSET(noise_floor_link),AV_OPT_TYPE_INT,{.i64 = MIN_LINK}, 0, NB_LINK-1, AFR, "link" }, + { "none", "none", 0, AV_OPT_TYPE_CONST, {.i64 = NONE_LINK}, 0, 0, AFR, "link" }, + { "min", "min", 0, AV_OPT_TYPE_CONST, {.i64 = MIN_LINK}, 0, 0, AFR, "link" }, + { "max", "max", 0, AV_OPT_TYPE_CONST, {.i64 = MAX_LINK}, 0, 0, AFR, "link" }, + { "average", "average", 0, AV_OPT_TYPE_CONST, {.i64 = AVERAGE_LINK}, 0, 0, AFR, "link" }, + { "band_multiplier", "set band multiplier",OFFSET(band_multiplier), AV_OPT_TYPE_FLOAT,{.dbl = 1.25}, 0.2,5, AF }, + { "bm", "set band multiplier", OFFSET(band_multiplier), AV_OPT_TYPE_FLOAT,{.dbl = 1.25}, 0.2,5, AF }, + { "sample_noise", "set sample noise mode",OFFSET(sample_noise_mode),AV_OPT_TYPE_INT,{.i64 = SAMPLE_NONE}, 0, NB_SAMPLEMODES-1, AFR, "sample" }, + { "sn", "set sample noise mode",OFFSET(sample_noise_mode),AV_OPT_TYPE_INT,{.i64 = SAMPLE_NONE}, 0, NB_SAMPLEMODES-1, AFR, "sample" }, + { "none", "none", 0, AV_OPT_TYPE_CONST, {.i64 = SAMPLE_NONE}, 0, 0, AFR, "sample" }, + { "start", "start", 0, AV_OPT_TYPE_CONST, {.i64 = SAMPLE_START}, 0, 0, AFR, "sample" }, + { "begin", "start", 0, AV_OPT_TYPE_CONST, {.i64 = SAMPLE_START}, 0, 0, AFR, "sample" }, + { "stop", "stop", 0, AV_OPT_TYPE_CONST, {.i64 = SAMPLE_STOP}, 0, 0, AFR, "sample" }, + { "end", "stop", 0, AV_OPT_TYPE_CONST, {.i64 = SAMPLE_STOP}, 0, 0, AFR, "sample" }, + { "gain_smooth", "set gain smooth radius",OFFSET(gain_smooth), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 50, AFR }, + { "gs", "set gain smooth radius",OFFSET(gain_smooth), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 50, AFR }, { NULL } }; AVFILTER_DEFINE_CLASS(afftdn); -static int get_band_noise(AudioFFTDeNoiseContext *s, - int band, double a, - double b, double c) +static double get_band_noise(AudioFFTDeNoiseContext *s, + int band, double a, + double b, double c) { double d1, d2, d3; @@ -180,7 +229,7 @@ static int get_band_noise(AudioFFTDeNoiseContext *s, d3 = s->band_centre[band] / c; d3 = 10.0 * log(1.0 + d3 * d3) / M_LN10; - return lrint(-d1 + d2 - d3); + return -d1 + d2 - d3; } static void factor(double *array, int size) @@ -216,70 +265,34 @@ static void solve(double *matrix, double *vector, int size) } } -static int process_get_band_noise(AudioFFTDeNoiseContext *s, - DeNoiseChannel *dnch, - int band) +static double process_get_band_noise(AudioFFTDeNoiseContext *s, + DeNoiseChannel *dnch, + int band) { double product, sum, f; int i = 0; - if (band < 15) + if (band < NB_PROFILE_BANDS) return dnch->band_noise[band]; - for (int j = 0; j < 5; j++) { + for (int j = 0; j < SOLVE_SIZE; j++) { sum = 0.0; - for (int k = 0; k < 15; k++) + for (int k = 0; k < NB_PROFILE_BANDS; k++) sum += s->matrix_b[i++] * dnch->band_noise[k]; s->vector_b[j] = sum; } - solve(s->matrix_a, s->vector_b, 5); - f = (0.5 * s->sample_rate) / s->band_centre[14]; + solve(s->matrix_a, s->vector_b, SOLVE_SIZE); + f = (0.5 * s->sample_rate) / s->band_centre[NB_PROFILE_BANDS-1]; f = 15.0 + log(f / 1.5) / log(1.5); sum = 0.0; product = 1.0; - for (int j = 0; j < 5; j++) { + for (int j = 0; j < SOLVE_SIZE; j++) { sum += product * s->vector_b[j]; product *= f; } - return lrint(sum); -} - -static void calculate_sfm(AudioFFTDeNoiseContext *s, - DeNoiseChannel *dnch, - int start, int end) -{ - double d1 = 0.0, d2 = 1.0; - int i = 0, j = 0; - - for (int k = start; k < end; k++) { - if (dnch->noisy_data[k] > s->sample_floor) { - j++; - d1 += dnch->noisy_data[k]; - d2 *= dnch->noisy_data[k]; - if (d2 > 1.0E100) { - d2 *= 1.0E-100; - i++; - } else if (d2 < 1.0E-100) { - d2 *= 1.0E100; - i--; - } - } - } - if (j > 1) { - d1 /= j; - dnch->sfm_results[0] = d1; - d2 = log(d2) + 230.2585 * i; - d2 /= j; - d1 = log(d1); - dnch->sfm_results[1] = d1; - dnch->sfm_results[2] = d1 - d2; - } else { - dnch->sfm_results[0] = s->auto_floor; - dnch->sfm_results[1] = dnch->sfm_threshold; - dnch->sfm_results[2] = dnch->sfm_threshold; - } + return sum; } static double limit_gain(double a, double b) @@ -291,196 +304,153 @@ static double limit_gain(double a, double b) return 1.0; } -static void process_frame(AudioFFTDeNoiseContext *s, DeNoiseChannel *dnch, +static void spectral_flatness(AudioFFTDeNoiseContext *s, const double *const spectral, + double floor, int len, double *rnum, double *rden) +{ + double num = 0., den = 0.; + int size = 0; + + for (int n = 0; n < len; n++) { + const double v = spectral[n]; + if (v > floor) { + num += log(v); + den += v; + size++; + } + } + + size = FFMAX(size, 1); + + num /= size; + den /= size; + + num = exp(num); + + *rnum = num; + *rden = den; +} + +static void set_parameters(AudioFFTDeNoiseContext *s, DeNoiseChannel *dnch, int update_var, int update_auto_var); + +static double floor_offset(const double *S, int size, double mean) +{ + double offset = 0.0; + + for (int n = 0; n < size; n++) { + const double p = S[n] - mean; + + offset = fmax(offset, fabs(p)); + } + + return offset / mean; +} + +static void process_frame(AVFilterContext *ctx, + AudioFFTDeNoiseContext *s, DeNoiseChannel *dnch, AVComplexFloat *fft_data, double *prior, double *prior_band_excit, int track_noise) { - double d1, d2, d3, gain; - int n, i1; - - d1 = fft_data[0].re * fft_data[0].re; - dnch->noisy_data[0] = d1; - d2 = d1 / dnch->abs_var[0]; - d3 = RATIO * prior[0] + RRATIO * fmax(d2 - 1.0, 0.0); - gain = d3 / (1.0 + d3); - gain *= (gain + M_PI_4 / fmax(d2, 1.0E-6)); - prior[0] = (d2 * gain); - dnch->clean_data[0] = (d1 * gain); - gain = sqrt(gain); - dnch->gain[0] = gain; - n = 0; - for (int i = 1; i < s->fft_length2; i++) { - d1 = fft_data[i].re * fft_data[i].re + fft_data[i].im * fft_data[i].im; - if (d1 > s->sample_floor) - n = i; - - dnch->noisy_data[i] = d1; - d2 = d1 / dnch->abs_var[i]; - d3 = RATIO * prior[i] + RRATIO * fmax(d2 - 1.0, 0.0); - gain = d3 / (1.0 + d3); - gain *= (gain + M_PI_4 / fmax(d2, 1.0E-6)); - prior[i] = d2 * gain; - dnch->clean_data[i] = d1 * gain; - gain = sqrt(gain); - dnch->gain[i] = gain; - } - d1 = fft_data[0].im * fft_data[0].im; - if (d1 > s->sample_floor) - n = s->fft_length2; - - dnch->noisy_data[s->fft_length2] = d1; - d2 = d1 / dnch->abs_var[s->fft_length2]; - d3 = RATIO * prior[s->fft_length2] + RRATIO * fmax(d2 - 1.0, 0.0); - gain = d3 / (1.0 + d3); - gain *= gain + M_PI_4 / fmax(d2, 1.0E-6); - prior[s->fft_length2] = d2 * gain; - dnch->clean_data[s->fft_length2] = d1 * gain; - gain = sqrt(gain); - dnch->gain[s->fft_length2] = gain; - if (n > s->fft_length2 - 2) { - n = s->bin_count; - i1 = s->noise_band_count; - } else { - i1 = 0; - for (int i = 0; i <= s->noise_band_count; i++) { - if (n > 1.1 * s->noise_band_edge[i]) { - i1 = i; - } - } - } - - if (track_noise && (i1 > s->noise_band_count / 2)) { - int j = FFMIN(n, s->noise_band_edge[i1]); - int m = 3, k; - - for (k = i1 - 1; k >= 0; k--) { - int i = s->noise_band_edge[k]; - calculate_sfm(s, dnch, i, j); - dnch->noise_band_sample[k] = dnch->sfm_results[0]; - if (dnch->sfm_results[2] + 0.013 * m * fmax(0.0, dnch->sfm_results[1] - 20.53) >= dnch->sfm_threshold) { - break; - } - j = i; - m++; - } - - if (k < i1 - 1) { - double sum = 0.0, min, max; - int i; - - for (i = i1 - 1; i > k; i--) { - min = log(dnch->noise_band_sample[i] / dnch->noise_band_auto_var[i]); - sum += min; - } - - i = i1 - k - 1; - if (i < 5) { - min = 3.0E-4 * i * i; - } else { - min = 3.0E-4 * (8 * i - 16); - } - if (i < 3) { - max = 2.0E-4 * i * i; - } else { - max = 2.0E-4 * (4 * i - 4); - } - - if (s->track_residual) { - if (s->last_noise_floor > s->last_residual_floor + 9) { - min *= 0.5; - max *= 0.75; - } else if (s->last_noise_floor > s->last_residual_floor + 6) { - min *= 0.4; - max *= 1.0; - } else if (s->last_noise_floor > s->last_residual_floor + 4) { - min *= 0.3; - max *= 1.3; - } else if (s->last_noise_floor > s->last_residual_floor + 2) { - min *= 0.2; - max *= 1.6; - } else if (s->last_noise_floor > s->last_residual_floor) { - min *= 0.1; - max *= 2.0; - } else { - min = 0.0; - max *= 2.5; - } - } - - sum = av_clipd(sum, -min, max); - sum = exp(sum); - for (int i = 0; i < 15; i++) - dnch->noise_band_auto_var[i] *= sum; - } else if (dnch->sfm_results[2] >= dnch->sfm_threshold) { - dnch->sfm_fail_flags[s->block_count & 0x1FF] = 1; - dnch->sfm_fail_total += 1; - } - } - - for (int i = 0; i < s->number_of_bands; i++) { - dnch->band_excit[i] = 0.0; - dnch->band_amt[i] = 0.0; - } + AVFilterLink *outlink = ctx->outputs[0]; + const double *abs_var = dnch->abs_var; + const double ratio = outlink->frame_count_out ? s->ratio : 1.0; + const double rratio = 1. - ratio; + const int *bin2band = s->bin2band; + double *noisy_data = dnch->noisy_data; + double *band_excit = dnch->band_excit; + double *band_amt = dnch->band_amt; + double *smoothed_gain = dnch->smoothed_gain; + double *gain = dnch->gain; for (int i = 0; i < s->bin_count; i++) { - dnch->band_excit[s->bin2band[i]] += dnch->clean_data[i]; + double sqr_new_gain, new_gain, power, mag, mag_abs_var, new_mag_abs_var; + + noisy_data[i] = mag = hypot(fft_data[i].re, fft_data[i].im); + power = mag * mag; + mag_abs_var = power / abs_var[i]; + new_mag_abs_var = ratio * prior[i] + rratio * fmax(mag_abs_var - 1.0, 0.0); + new_gain = new_mag_abs_var / (1.0 + new_mag_abs_var); + sqr_new_gain = new_gain * new_gain; + prior[i] = mag_abs_var * sqr_new_gain; + dnch->clean_data[i] = power * sqr_new_gain; + gain[i] = new_gain; + } + + if (track_noise) { + double flatness, num, den; + + spectral_flatness(s, noisy_data, s->floor, s->bin_count, &num, &den); + + flatness = num / den; + if (flatness > 0.8) { + const double offset = s->floor_offset * floor_offset(noisy_data, s->bin_count, den); + const double new_floor = av_clipd(10.0 * log10(den) - 100.0 + offset, -90., -20.); + + dnch->noise_floor = 0.1 * new_floor + dnch->noise_floor * 0.9; + set_parameters(s, dnch, 1, 1); + } } for (int i = 0; i < s->number_of_bands; i++) { - dnch->band_excit[i] = fmax(dnch->band_excit[i], - s->band_alpha[i] * dnch->band_excit[i] + - s->band_beta[i] * prior_band_excit[i]); - prior_band_excit[i] = dnch->band_excit[i]; + band_excit[i] = 0.0; + band_amt[i] = 0.0; + } + + for (int i = 0; i < s->bin_count; i++) + band_excit[bin2band[i]] += dnch->clean_data[i]; + + for (int i = 0; i < s->number_of_bands; i++) { + band_excit[i] = fmax(band_excit[i], + s->band_alpha[i] * band_excit[i] + + s->band_beta[i] * prior_band_excit[i]); + prior_band_excit[i] = band_excit[i]; } for (int j = 0, i = 0; j < s->number_of_bands; j++) { for (int k = 0; k < s->number_of_bands; k++) { - dnch->band_amt[j] += dnch->spread_function[i++] * dnch->band_excit[k]; + band_amt[j] += dnch->spread_function[i++] * band_excit[k]; } } for (int i = 0; i < s->bin_count; i++) - dnch->amt[i] = dnch->band_amt[s->bin2band[i]]; + dnch->amt[i] = band_amt[bin2band[i]]; - if (dnch->amt[0] > dnch->abs_var[0]) { - dnch->gain[0] = 1.0; - } else if (dnch->amt[0] > dnch->min_abs_var[0]) { - double limit = sqrt(dnch->abs_var[0] / dnch->amt[0]); - dnch->gain[0] = limit_gain(dnch->gain[0], limit); - } else { - dnch->gain[0] = limit_gain(dnch->gain[0], s->max_gain); - } - if (dnch->amt[s->fft_length2] > dnch->abs_var[s->fft_length2]) { - dnch->gain[s->fft_length2] = 1.0; - } else if (dnch->amt[s->fft_length2] > dnch->min_abs_var[s->fft_length2]) { - double limit = sqrt(dnch->abs_var[s->fft_length2] / dnch->amt[s->fft_length2]); - dnch->gain[s->fft_length2] = limit_gain(dnch->gain[s->fft_length2], limit); - } else { - dnch->gain[s->fft_length2] = limit_gain(dnch->gain[s->fft_length2], s->max_gain); - } - - for (int i = 1; i < s->fft_length2; i++) { - if (dnch->amt[i] > dnch->abs_var[i]) { - dnch->gain[i] = 1.0; + for (int i = 0; i < s->bin_count; i++) { + if (dnch->amt[i] > abs_var[i]) { + gain[i] = 1.0; } else if (dnch->amt[i] > dnch->min_abs_var[i]) { - double limit = sqrt(dnch->abs_var[i] / dnch->amt[i]); - dnch->gain[i] = limit_gain(dnch->gain[i], limit); + const double limit = sqrt(abs_var[i] / dnch->amt[i]); + + gain[i] = limit_gain(gain[i], limit); } else { - dnch->gain[i] = limit_gain(dnch->gain[i], s->max_gain); + gain[i] = limit_gain(gain[i], dnch->max_gain); } } - gain = dnch->gain[0]; - dnch->clean_data[0] = (gain * gain * dnch->noisy_data[0]); - fft_data[0].re *= gain; - gain = dnch->gain[s->fft_length2]; - dnch->clean_data[s->fft_length2] = (gain * gain * dnch->noisy_data[s->fft_length2]); - fft_data[0].im *= gain; - for (int i = 1; i < s->fft_length2; i++) { - gain = dnch->gain[i]; - dnch->clean_data[i] = (gain * gain * dnch->noisy_data[i]); - fft_data[i].re *= gain; - fft_data[i].im *= gain; + memcpy(smoothed_gain, gain, s->bin_count * sizeof(*smoothed_gain)); + if (s->gain_smooth > 0) { + const int r = s->gain_smooth; + + for (int i = r; i < s->bin_count - r; i++) { + const double gc = gain[i]; + double num = 0., den = 0.; + + for (int j = -r; j <= r; j++) { + const double g = gain[i + j]; + const double d = 1. - fabs(g - gc); + + num += g * d; + den += d; + } + + smoothed_gain[i] = num / den; + } + } + + for (int i = 0; i < s->bin_count; i++) { + const double new_gain = smoothed_gain[i]; + + fft_data[i].re *= new_gain; + fft_data[i].im *= new_gain; } } @@ -503,8 +473,8 @@ static int get_band_edge(AudioFFTDeNoiseContext *s, int band) { int i; - if (band == 15) { - i = lrint(s->band_centre[14] * 1.224745); + if (band == NB_PROFILE_BANDS) { + i = lrint(s->band_centre[NB_PROFILE_BANDS - 1] * 1.224745); } else { i = lrint(s->band_centre[band] / 1.224745); } @@ -520,11 +490,11 @@ static void set_band_parameters(AudioFFTDeNoiseContext *s, d5 = 0.0; band_noise = process_get_band_noise(s, dnch, 0); - for (int m = j; m <= s->fft_length2; m++) { + for (int m = j; m < s->bin_count; m++) { if (m == j) { i = j; d5 = band_noise; - if (k == 15) { + if (k >= NB_PROFILE_BANDS) { j = s->bin_count; } else { j = s->fft_length * get_band_centre(s, k) / s->sample_rate; @@ -537,78 +507,98 @@ static void set_band_parameters(AudioFFTDeNoiseContext *s, d4 = (m - i) / d2; dnch->rel_var[m] = exp((d5 * d3 + band_noise * d4) * C); } - dnch->rel_var[s->fft_length2] = exp(band_noise * C); - for (i = 0; i < 15; i++) - dnch->noise_band_auto_var[i] = s->max_var * exp((process_get_band_noise(s, dnch, i) - 2.0) * C); - - for (i = 0; i <= s->fft_length2; i++) { - dnch->abs_var[i] = fmax(s->max_var * dnch->rel_var[i], 1.0); - dnch->min_abs_var[i] = s->gain_scale * dnch->abs_var[i]; - } + for (i = 0; i < NB_PROFILE_BANDS; i++) + dnch->noise_band_auto_var[i] = dnch->max_var * exp((process_get_band_noise(s, dnch, i) - 2.0) * C); } static void read_custom_noise(AudioFFTDeNoiseContext *s, int ch) { DeNoiseChannel *dnch = &s->dnch[ch]; - char *p, *arg, *saveptr = NULL; - int i, ret, band_noise[15] = { 0 }; + char *custom_noise_str, *p, *arg, *saveptr = NULL; + double band_noise[NB_PROFILE_BANDS] = { 0.f }; + int ret; if (!s->band_noise_str) return; - p = av_strdup(s->band_noise_str); + custom_noise_str = p = av_strdup(s->band_noise_str); if (!p) return; - for (i = 0; i < 15; i++) { + for (int i = 0; i < NB_PROFILE_BANDS; i++) { + float noise; + if (!(arg = av_strtok(p, "| ", &saveptr))) break; p = NULL; - ret = av_sscanf(arg, "%d", &band_noise[i]); + ret = av_sscanf(arg, "%f", &noise); if (ret != 1) { - av_log(s, AV_LOG_ERROR, "Custom band noise must be integer.\n"); + av_log(s, AV_LOG_ERROR, "Custom band noise must be float.\n"); break; } - band_noise[i] = av_clip(band_noise[i], -24, 24); + band_noise[i] = av_clipd(noise, -24., 24.); } - av_free(p); + av_free(custom_noise_str); memcpy(dnch->band_noise, band_noise, sizeof(band_noise)); } -static void set_parameters(AudioFFTDeNoiseContext *s) +static void set_parameters(AudioFFTDeNoiseContext *s, DeNoiseChannel *dnch, int update_var, int update_auto_var) { - if (s->last_noise_floor != s->noise_floor) - s->last_noise_floor = s->noise_floor; + if (dnch->last_noise_floor != dnch->noise_floor) + dnch->last_noise_floor = dnch->noise_floor; if (s->track_residual) - s->last_noise_floor = fmaxf(s->last_noise_floor, s->residual_floor); + dnch->last_noise_floor = fmax(dnch->last_noise_floor, dnch->residual_floor); - s->max_var = s->floor * exp((100.0 + s->last_noise_floor) * C); + dnch->max_var = s->floor * exp((100.0 + dnch->last_noise_floor) * C); + if (update_auto_var) { + for (int i = 0; i < NB_PROFILE_BANDS; i++) + dnch->noise_band_auto_var[i] = dnch->max_var * exp((process_get_band_noise(s, dnch, i) - 2.0) * C); + } if (s->track_residual) { - s->last_residual_floor = s->residual_floor; - s->last_noise_reduction = fmax(s->last_noise_floor - s->last_residual_floor, 0); - s->max_gain = exp(s->last_noise_reduction * (0.5 * C)); - } else if (s->noise_reduction != s->last_noise_reduction) { - s->last_noise_reduction = s->noise_reduction; - s->last_residual_floor = av_clipf(s->last_noise_floor - s->last_noise_reduction, -80, -20); - s->max_gain = exp(s->last_noise_reduction * (0.5 * C)); + if (update_var || dnch->last_residual_floor != dnch->residual_floor) { + update_var = 1; + dnch->last_residual_floor = dnch->residual_floor; + dnch->last_noise_reduction = fmax(dnch->last_noise_floor - dnch->last_residual_floor + 100., 0); + dnch->max_gain = exp(dnch->last_noise_reduction * (0.5 * C)); + } + } else if (update_var || dnch->noise_reduction != dnch->last_noise_reduction) { + update_var = 1; + dnch->last_noise_reduction = dnch->noise_reduction; + dnch->last_residual_floor = av_clipd(dnch->last_noise_floor - dnch->last_noise_reduction, -80, -20); + dnch->max_gain = exp(dnch->last_noise_reduction * (0.5 * C)); } - s->gain_scale = 1.0 / (s->max_gain * s->max_gain); - - for (int ch = 0; ch < s->channels; ch++) { - DeNoiseChannel *dnch = &s->dnch[ch]; + dnch->gain_scale = 1.0 / (dnch->max_gain * dnch->max_gain); + if (update_var) { set_band_parameters(s, dnch); + + for (int i = 0; i < s->bin_count; i++) { + dnch->abs_var[i] = fmax(dnch->max_var * dnch->rel_var[i], 1.0); + dnch->min_abs_var[i] = dnch->gain_scale * dnch->abs_var[i]; + } } } +static void reduce_mean(double *band_noise) +{ + double mean = 0.f; + + for (int i = 0; i < NB_PROFILE_BANDS; i++) + mean += band_noise[i]; + mean /= NB_PROFILE_BANDS; + + for (int i = 0; i < NB_PROFILE_BANDS; i++) + band_noise[i] -= mean; +} + static int config_input(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; @@ -616,22 +606,21 @@ static int config_input(AVFilterLink *inlink) double wscale, sar, sum, sdiv; int i, j, k, m, n, ret; - s->dnch = av_calloc(inlink->channels, sizeof(*s->dnch)); + s->dnch = av_calloc(inlink->ch_layout.nb_channels, sizeof(*s->dnch)); if (!s->dnch) return AVERROR(ENOMEM); - s->pts = AV_NOPTS_VALUE; - s->channels = inlink->channels; + s->channels = inlink->ch_layout.nb_channels; s->sample_rate = inlink->sample_rate; s->sample_advance = s->sample_rate / 80; s->window_length = 3 * s->sample_advance; s->fft_length2 = 1 << (32 - ff_clz(s->window_length)); - s->fft_length = s->fft_length2 * 2; + s->fft_length = s->fft_length2; s->buffer_length = s->fft_length * 2; - s->bin_count = s->fft_length2 + 1; + s->bin_count = s->fft_length2 / 2 + 1; s->band_centre[0] = 80; - for (i = 1; i < 15; i++) { + for (i = 1; i < NB_PROFILE_BANDS; i++) { s->band_centre[i] = lrint(1.5 * s->band_centre[i - 1] + 5.0); if (s->band_centre[i] < 1000) { s->band_centre[i] = 10 * (s->band_centre[i] / 10); @@ -644,24 +633,24 @@ static int config_input(AVFilterLink *inlink) } } - for (j = 0; j < 5; j++) { - for (k = 0; k < 5; k++) { - s->matrix_a[j + k * 5] = 0.0; - for (m = 0; m < 15; m++) - s->matrix_a[j + k * 5] += pow(m, j + k); + for (j = 0; j < SOLVE_SIZE; j++) { + for (k = 0; k < SOLVE_SIZE; k++) { + s->matrix_a[j + k * SOLVE_SIZE] = 0.0; + for (m = 0; m < NB_PROFILE_BANDS; m++) + s->matrix_a[j + k * SOLVE_SIZE] += pow(m, j + k); } } - factor(s->matrix_a, 5); + factor(s->matrix_a, SOLVE_SIZE); i = 0; - for (j = 0; j < 5; j++) - for (k = 0; k < 15; k++) + for (j = 0; j < SOLVE_SIZE; j++) + for (k = 0; k < NB_PROFILE_BANDS; k++) s->matrix_b[i++] = pow(k, j); i = 0; - for (j = 0; j < 15; j++) - for (k = 0; k < 5; k++) + for (j = 0; j < NB_PROFILE_BANDS; j++) + for (k = 0; k < SOLVE_SIZE; k++) s->matrix_c[i++] = pow(j, k); s->window = av_calloc(s->window_length, sizeof(*s->window)); @@ -669,33 +658,33 @@ static int config_input(AVFilterLink *inlink) if (!s->window || !s->bin2band) return AVERROR(ENOMEM); - sdiv = s->sample_rate / 17640.0; - for (i = 0; i <= s->fft_length2; i++) + sdiv = s->band_multiplier; + for (i = 0; i < s->bin_count; i++) s->bin2band[i] = lrint(sdiv * freq2bark((0.5 * i * s->sample_rate) / s->fft_length2)); - s->number_of_bands = s->bin2band[s->fft_length2] + 1; + s->number_of_bands = s->bin2band[s->bin_count - 1] + 1; s->band_alpha = av_calloc(s->number_of_bands, sizeof(*s->band_alpha)); s->band_beta = av_calloc(s->number_of_bands, sizeof(*s->band_beta)); if (!s->band_alpha || !s->band_beta) return AVERROR(ENOMEM); - for (int ch = 0; ch < inlink->channels; ch++) { + for (int ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { DeNoiseChannel *dnch = &s->dnch[ch]; - float scale; + float scale = 1.f; switch (s->noise_type) { case WHITE_NOISE: - for (i = 0; i < 15; i++) - dnch->band_noise[i] = 0; + for (i = 0; i < NB_PROFILE_BANDS; i++) + dnch->band_noise[i] = 0.; break; case VINYL_NOISE: - for (i = 0; i < 15; i++) - dnch->band_noise[i] = get_band_noise(s, i, 50.0, 500.5, 2125.0) + FFMAX(i - 7, 0); + for (i = 0; i < NB_PROFILE_BANDS; i++) + dnch->band_noise[i] = get_band_noise(s, i, 50.0, 500.5, 2125.0); break; case SHELLAC_NOISE: - for (i = 0; i < 15; i++) - dnch->band_noise[i] = get_band_noise(s, i, 1.0, 500.0, 1.0E10) + FFMAX(i - 12, -5); + for (i = 0; i < NB_PROFILE_BANDS; i++) + dnch->band_noise[i] = get_band_noise(s, i, 1.0, 500.0, 1.0E10); break; case CUSTOM_NOISE: read_custom_noise(s, ch); @@ -704,24 +693,13 @@ static int config_input(AVFilterLink *inlink) return AVERROR_BUG; } - - dnch->sfm_threshold = 0.8; - dnch->sfm_alpha = 0.05; - for (i = 0; i < 512; i++) - dnch->sfm_fail_flags[i] = 0; - - dnch->sfm_fail_total = 0; - j = FFMAX((int)(10.0 * (1.3 - dnch->sfm_threshold)), 1); - - for (i = 0; i < 512; i += j) { - dnch->sfm_fail_flags[i] = 1; - dnch->sfm_fail_total += 1; - } + reduce_mean(dnch->band_noise); dnch->amt = av_calloc(s->bin_count, sizeof(*dnch->amt)); dnch->band_amt = av_calloc(s->number_of_bands, sizeof(*dnch->band_amt)); dnch->band_excit = av_calloc(s->number_of_bands, sizeof(*dnch->band_excit)); dnch->gain = av_calloc(s->bin_count, sizeof(*dnch->gain)); + dnch->smoothed_gain = av_calloc(s->bin_count, sizeof(*dnch->smoothed_gain)); dnch->prior = av_calloc(s->bin_count, sizeof(*dnch->prior)); dnch->prior_band_excit = av_calloc(s->number_of_bands, sizeof(*dnch->prior_band_excit)); dnch->clean_data = av_calloc(s->bin_count, sizeof(*dnch->clean_data)); @@ -730,12 +708,12 @@ static int config_input(AVFilterLink *inlink) dnch->abs_var = av_calloc(s->bin_count, sizeof(*dnch->abs_var)); dnch->rel_var = av_calloc(s->bin_count, sizeof(*dnch->rel_var)); dnch->min_abs_var = av_calloc(s->bin_count, sizeof(*dnch->min_abs_var)); - dnch->fft_in = av_calloc(s->fft_length2 + 1, sizeof(*dnch->fft_in)); + dnch->fft_in = av_calloc(s->fft_length2, sizeof(*dnch->fft_in)); dnch->fft_out = av_calloc(s->fft_length2 + 1, sizeof(*dnch->fft_out)); - ret = av_tx_init(&dnch->fft, &dnch->tx_fn, AV_TX_FLOAT_FFT, 0, s->fft_length2, &scale, 0); + ret = av_tx_init(&dnch->fft, &dnch->tx_fn, AV_TX_FLOAT_RDFT, 0, s->fft_length2, &scale, 0); if (ret < 0) return ret; - ret = av_tx_init(&dnch->ifft, &dnch->itx_fn, AV_TX_FLOAT_FFT, 1, s->fft_length2, &scale, 0); + ret = av_tx_init(&dnch->ifft, &dnch->itx_fn, AV_TX_FLOAT_RDFT, 1, s->fft_length2, &scale, 0); if (ret < 0) return ret; dnch->spread_function = av_calloc(s->number_of_bands * s->number_of_bands, @@ -745,6 +723,7 @@ static int config_input(AVFilterLink *inlink) !dnch->band_amt || !dnch->band_excit || !dnch->gain || + !dnch->smoothed_gain || !dnch->prior || !dnch->prior_band_excit || !dnch->clean_data || @@ -761,10 +740,9 @@ static int config_input(AVFilterLink *inlink) return AVERROR(ENOMEM); } - for (int ch = 0; ch < inlink->channels; ch++) { + for (int ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { DeNoiseChannel *dnch = &s->dnch[ch]; double *prior_band_excit = dnch->prior_band_excit; - double *prior = dnch->prior; double min, max; double p1, p2; @@ -788,7 +766,7 @@ static int config_input(AVFilterLink *inlink) prior_band_excit[m] = 0.0; } - for (m = 0; m <= s->fft_length2; m++) + for (m = 0; m < s->bin_count; m++) dnch->band_excit[s->bin2band[m]] += 1.0; j = 0; @@ -808,8 +786,6 @@ static int config_input(AVFilterLink *inlink) dnch->band_excit[i] = av_clipd(dnch->band_excit[i], min, max); } - for (int i = 0; i <= s->fft_length2; i++) - prior[i] = RRATIO; for (int i = 0; i < s->buffer_length; i++) dnch->out_samples[i] = 0; @@ -821,7 +797,7 @@ static int config_input(AVFilterLink *inlink) j = 0; sar = s->sample_advance / s->sample_rate; - for (int i = 0; i <= s->fft_length2; i++) { + for (int i = 0; i < s->bin_count; i++) { if ((i == s->fft_length2) || (s->bin2band[i] > j)) { double d6 = (i - 1) * s->sample_rate / s->fft_length; double d7 = fmin(0.008 + 2.2 / d6, 0.03); @@ -831,7 +807,11 @@ static int config_input(AVFilterLink *inlink) } } - wscale = sqrt(16.0 / (9.0 * s->fft_length)); + s->winframe = ff_get_audio_buffer(inlink, s->window_length); + if (!s->winframe) + return AVERROR(ENOMEM); + + wscale = sqrt(8.0 / (9.0 * s->fft_length)); sum = 0.0; for (int i = 0; i < s->window_length; i++) { double d10 = sin(i * M_PI / s->window_length); @@ -843,94 +823,33 @@ static int config_input(AVFilterLink *inlink) s->window_weight = 0.5 * sum; s->floor = (1LL << 48) * exp(-23.025558369790467) * s->window_weight; s->sample_floor = s->floor * exp(4.144600506562284); - s->auto_floor = s->floor * exp(6.907667510937141); - set_parameters(s); + for (int ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { + DeNoiseChannel *dnch = &s->dnch[ch]; + + dnch->noise_reduction = s->noise_reduction; + dnch->noise_floor = s->noise_floor; + dnch->residual_floor = s->residual_floor; + + set_parameters(s, dnch, 1, 1); + } s->noise_band_edge[0] = FFMIN(s->fft_length2, s->fft_length * get_band_edge(s, 0) / s->sample_rate); i = 0; - for (int j = 1; j < 16; j++) { + for (int j = 1; j < NB_PROFILE_BANDS + 1; j++) { s->noise_band_edge[j] = FFMIN(s->fft_length2, s->fft_length * get_band_edge(s, j) / s->sample_rate); if (s->noise_band_edge[j] > lrint(1.1 * s->noise_band_edge[j - 1])) i++; - s->noise_band_edge[16] = i; + s->noise_band_edge[NB_PROFILE_BANDS + 1] = i; } - s->noise_band_count = s->noise_band_edge[16]; - - s->fifo = av_audio_fifo_alloc(inlink->format, inlink->channels, s->fft_length); - if (!s->fifo) - return AVERROR(ENOMEM); + s->noise_band_count = s->noise_band_edge[NB_PROFILE_BANDS + 1]; return 0; } -static void preprocess(AVComplexFloat *in, int len) -{ - double d1, d2, d3, d4, d5, d6, d7, d8, d9, d10; - int n, i, k; - - d5 = 2.0 * M_PI / len; - d8 = sin(0.5 * d5); - d8 = -2.0 * d8 * d8; - d7 = sin(d5); - d9 = 1.0 + d8; - d6 = d7; - n = len / 2; - - for (i = 1; i < len / 4; i++) { - k = n - i; - d2 = 0.5 * (in[i].re + in[k].re); - d1 = 0.5 * (in[i].im - in[k].im); - d4 = 0.5 * (in[i].im + in[k].im); - d3 = 0.5 * (in[k].re - in[i].re); - in[i].re = d2 + d9 * d4 + d6 * d3; - in[i].im = d1 + d9 * d3 - d6 * d4; - in[k].re = d2 - d9 * d4 - d6 * d3; - in[k].im = -d1 + d9 * d3 - d6 * d4; - d10 = d9; - d9 += d9 * d8 - d6 * d7; - d6 += d6 * d8 + d10 * d7; - } - - d2 = in[0].re; - in[0].re = d2 + in[0].im; - in[0].im = d2 - in[0].im; -} - -static void postprocess(AVComplexFloat *in, int len) -{ - double d1, d2, d3, d4, d5, d6, d7, d8, d9, d10; - int n, i, k; - - d5 = 2.0 * M_PI / len; - d8 = sin(0.5 * d5); - d8 = -2.0 * d8 * d8; - d7 = sin(d5); - d9 = 1.0 + d8; - d6 = d7; - n = len / 2; - for (i = 1; i < len / 4; i++) { - k = n - i; - d2 = 0.5 * (in[i].re + in[k].re); - d1 = 0.5 * (in[i].im - in[k].im); - d4 = 0.5 * (in[i].re - in[k].re); - d3 = 0.5 * (in[i].im + in[k].im); - in[i].re = d2 - d9 * d3 - d6 * d4; - in[i].im = d1 + d9 * d4 - d6 * d3; - in[k].re = d2 + d9 * d3 + d6 * d4; - in[k].im = -d1 + d9 * d4 - d6 * d3; - d10 = d9; - d9 += d9 * d8 - d6 * d7; - d6 += d6 * d8 + d10 * d7; - } - d2 = in[0].re; - in[0].re = 0.5 * (d2 + in[0].im); - in[0].im = 0.5 * (d2 - in[0].im); -} - static void init_sample_noise(DeNoiseChannel *dnch) { - for (int i = 0; i < 15; i++) { + for (int i = 0; i < NB_PROFILE_BANDS; i++) { dnch->noise_band_norm[i] = 0.0; dnch->noise_band_avr[i] = 0.0; dnch->noise_band_avi[i] = 0.0; @@ -946,29 +865,19 @@ static void sample_noise_block(AudioFFTDeNoiseContext *s, double mag2, var = 0.0, avr = 0.0, avi = 0.0; int edge, j, k, n, edgemax; - for (int i = 0; i < s->window_length; i++) { - dnch->fft_in[i].re = s->window[i] * src[i] * (1LL << 24); - dnch->fft_in[i].im = 0.0; - } + for (int i = 0; i < s->window_length; i++) + dnch->fft_in[i] = s->window[i] * src[i] * (1LL << 23); - for (int i = s->window_length; i < s->fft_length2; i++) { - dnch->fft_in[i].re = 0.0; - dnch->fft_in[i].im = 0.0; - } + for (int i = s->window_length; i < s->fft_length2; i++) + dnch->fft_in[i] = 0.0; dnch->tx_fn(dnch->fft, dnch->fft_out, dnch->fft_in, sizeof(float)); - preprocess(dnch->fft_out, s->fft_length); - edge = s->noise_band_edge[0]; j = edge; k = 0; n = j; - edgemax = fmin(s->fft_length2, s->noise_band_edge[15]); - dnch->fft_out[s->fft_length2].re = dnch->fft_out[0].im; - dnch->fft_out[0].im = 0.0; - dnch->fft_out[s->fft_length2].im = 0.0; - + edgemax = fmin(s->fft_length2, s->noise_band_edge[NB_PROFILE_BANDS]); for (int i = j; i <= edgemax; i++) { if ((i == j) && (i < edgemax)) { if (j > edge) { @@ -980,7 +889,7 @@ static void sample_noise_block(AudioFFTDeNoiseContext *s, k++; edge = j; j = s->noise_band_edge[k]; - if (k == 15) { + if (k == NB_PROFILE_BANDS) { j++; } var = 0.0; @@ -994,7 +903,6 @@ static void sample_noise_block(AudioFFTDeNoiseContext *s, mag2 = fmax(mag2, s->sample_floor); - dnch->noisy_data[i] = mag2; var += mag2; n++; } @@ -1016,262 +924,218 @@ static void finish_sample_noise(AudioFFTDeNoiseContext *s, dnch->noise_band_var[i] -= dnch->noise_band_avr[i] * dnch->noise_band_avr[i] + dnch->noise_band_avi[i] * dnch->noise_band_avi[i]; dnch->noise_band_auto_var[i] = dnch->noise_band_var[i]; - sample_noise[i] = (1.0 / C) * log(dnch->noise_band_var[i] / s->floor) - 100.0; + sample_noise[i] = 10.0 * log10(dnch->noise_band_var[i] / s->floor) - 100.0; } - if (s->noise_band_count < 15) { - for (int i = s->noise_band_count; i < 15; i++) + if (s->noise_band_count < NB_PROFILE_BANDS) { + for (int i = s->noise_band_count; i < NB_PROFILE_BANDS; i++) sample_noise[i] = sample_noise[i - 1]; } } static void set_noise_profile(AudioFFTDeNoiseContext *s, DeNoiseChannel *dnch, - double *sample_noise, - int new_profile) + double *sample_noise) { - int new_band_noise[15]; - double temp[15]; - double sum = 0.0, d1; - float new_noise_floor; - int i = 0, n; + double new_band_noise[NB_PROFILE_BANDS]; + double temp[NB_PROFILE_BANDS]; + double sum = 0.0; - for (int m = 0; m < 15; m++) + for (int m = 0; m < NB_PROFILE_BANDS; m++) temp[m] = sample_noise[m]; - if (new_profile) { - for (int m = 0; m < 5; m++) { - sum = 0.0; - for (n = 0; n < 15; n++) - sum += s->matrix_b[i++] * temp[n]; - s->vector_b[m] = sum; - } - solve(s->matrix_a, s->vector_b, 5); - i = 0; - for (int m = 0; m < 15; m++) { - sum = 0.0; - for (n = 0; n < 5; n++) - sum += s->matrix_c[i++] * s->vector_b[n]; - temp[m] = sum; - } + for (int m = 0, i = 0; m < SOLVE_SIZE; m++) { + sum = 0.0; + for (int n = 0; n < NB_PROFILE_BANDS; n++) + sum += s->matrix_b[i++] * temp[n]; + s->vector_b[m] = sum; + } + solve(s->matrix_a, s->vector_b, SOLVE_SIZE); + for (int m = 0, i = 0; m < NB_PROFILE_BANDS; m++) { + sum = 0.0; + for (int n = 0; n < SOLVE_SIZE; n++) + sum += s->matrix_c[i++] * s->vector_b[n]; + temp[m] = sum; } - sum = 0.0; - for (int m = 0; m < 15; m++) - sum += temp[m]; + reduce_mean(temp); - d1 = (int)(sum / 15.0 - 0.5); - if (!new_profile) - i = lrint(temp[7] - d1); - - for (d1 -= dnch->band_noise[7] - i; d1 > -20.0; d1 -= 1.0) - ; - - for (int m = 0; m < 15; m++) - temp[m] -= d1; - - new_noise_floor = d1 + 2.5; - - if (new_profile) { - av_log(s, AV_LOG_INFO, "bn="); - for (int m = 0; m < 15; m++) { - new_band_noise[m] = lrint(temp[m]); - new_band_noise[m] = av_clip(new_band_noise[m], -24, 24); - av_log(s, AV_LOG_INFO, "%d ", new_band_noise[m]); - } - av_log(s, AV_LOG_INFO, "\n"); - memcpy(dnch->band_noise, new_band_noise, sizeof(new_band_noise)); + av_log(s, AV_LOG_INFO, "bn="); + for (int m = 0; m < NB_PROFILE_BANDS; m++) { + new_band_noise[m] = temp[m]; + new_band_noise[m] = av_clipd(new_band_noise[m], -24.0, 24.0); + av_log(s, AV_LOG_INFO, "%f ", new_band_noise[m]); } - - if (s->track_noise) - s->noise_floor = new_noise_floor; + av_log(s, AV_LOG_INFO, "\n"); + memcpy(dnch->band_noise, new_band_noise, sizeof(new_band_noise)); } -typedef struct ThreadData { - AVFrame *in; -} ThreadData; - static int filter_channel(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { AudioFFTDeNoiseContext *s = ctx->priv; - ThreadData *td = arg; - AVFrame *in = td->in; - const int start = (in->channels * jobnr) / nb_jobs; - const int end = (in->channels * (jobnr+1)) / nb_jobs; + AVFrame *in = arg; + const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs; + const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; + const int window_length = s->window_length; + const double *window = s->window; for (int ch = start; ch < end; ch++) { DeNoiseChannel *dnch = &s->dnch[ch]; const float *src = (const float *)in->extended_data[ch]; double *dst = dnch->out_samples; + float *fft_in = dnch->fft_in; - if (s->track_noise) { - int i = s->block_count & 0x1FF; + for (int m = 0; m < window_length; m++) + fft_in[m] = window[m] * src[m] * (1LL << 23); - if (dnch->sfm_fail_flags[i]) - dnch->sfm_fail_total--; - dnch->sfm_fail_flags[i] = 0; - dnch->sfm_threshold *= 1.0 - dnch->sfm_alpha; - dnch->sfm_threshold += dnch->sfm_alpha * (0.5 + (1.0 / 640) * dnch->sfm_fail_total); - } + for (int m = window_length; m < s->fft_length2; m++) + fft_in[m] = 0; - for (int m = 0; m < s->window_length; m++) { - dnch->fft_in[m].re = s->window[m] * src[m] * (1LL << 24); - dnch->fft_in[m].im = 0; - } + dnch->tx_fn(dnch->fft, dnch->fft_out, fft_in, sizeof(float)); - for (int m = s->window_length; m < s->fft_length2; m++) { - dnch->fft_in[m].re = 0; - dnch->fft_in[m].im = 0; - } - - dnch->tx_fn(dnch->fft, dnch->fft_out, dnch->fft_in, sizeof(float)); - - preprocess(dnch->fft_out, s->fft_length); - process_frame(s, dnch, dnch->fft_out, + process_frame(ctx, s, dnch, dnch->fft_out, dnch->prior, dnch->prior_band_excit, s->track_noise); - postprocess(dnch->fft_out, s->fft_length); - dnch->itx_fn(dnch->ifft, dnch->fft_in, dnch->fft_out, sizeof(float)); + dnch->itx_fn(dnch->ifft, fft_in, dnch->fft_out, sizeof(float)); - for (int m = 0; m < s->window_length; m++) - dst[m] += s->window[m] * dnch->fft_in[m].re / (1LL << 24); + for (int m = 0; m < window_length; m++) + dst[m] += s->window[m] * fft_in[m] / (1LL << 23); } return 0; } -static void get_auto_noise_levels(AudioFFTDeNoiseContext *s, - DeNoiseChannel *dnch, - double *levels) -{ - if (s->noise_band_count > 0) { - for (int i = 0; i < s->noise_band_count; i++) { - levels[i] = (1.0 / C) * log(dnch->noise_band_auto_var[i] / s->floor) - 100.0; - } - if (s->noise_band_count < 15) { - for (int i = s->noise_band_count; i < 15; i++) - levels[i] = levels[i - 1]; - } - } else { - for (int i = 0; i < 15; i++) { - levels[i] = -100.0; - } - } -} - -static int output_frame(AVFilterLink *inlink) +static int output_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; AudioFFTDeNoiseContext *s = ctx->priv; const int output_mode = ctx->is_disabled ? IN_MODE : s->output_mode; - AVFrame *out = NULL, *in = NULL; - ThreadData td; - int ret = 0; + const int offset = s->window_length - s->sample_advance; + AVFrame *out; - in = ff_get_audio_buffer(outlink, s->window_length); - if (!in) - return AVERROR(ENOMEM); + for (int ch = 0; ch < s->channels; ch++) { + float *src = (float *)s->winframe->extended_data[ch]; - ret = av_audio_fifo_peek(s->fifo, (void **)in->extended_data, s->window_length); - if (ret < 0) - goto end; - - if (s->track_noise) { - for (int ch = 0; ch < inlink->channels; ch++) { - DeNoiseChannel *dnch = &s->dnch[ch]; - double levels[15]; - - get_auto_noise_levels(s, dnch, levels); - set_noise_profile(s, dnch, levels, 0); - } - - if (s->noise_floor != s->last_noise_floor) - set_parameters(s); + memmove(src, &src[s->sample_advance], offset * sizeof(float)); + memcpy(&src[offset], in->extended_data[ch], in->nb_samples * sizeof(float)); + memset(&src[offset + in->nb_samples], 0, (s->sample_advance - in->nb_samples) * sizeof(float)); } - if (s->sample_noise_start) { - for (int ch = 0; ch < inlink->channels; ch++) { + if (s->track_noise) { + double average = 0.0, min = DBL_MAX, max = -DBL_MAX; + + for (int ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { + DeNoiseChannel *dnch = &s->dnch[ch]; + + average += dnch->noise_floor; + max = fmax(max, dnch->noise_floor); + min = fmin(min, dnch->noise_floor); + } + + average /= inlink->ch_layout.nb_channels; + + for (int ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { + DeNoiseChannel *dnch = &s->dnch[ch]; + + switch (s->noise_floor_link) { + case MIN_LINK: dnch->noise_floor = min; break; + case MAX_LINK: dnch->noise_floor = max; break; + case AVERAGE_LINK: dnch->noise_floor = average; break; + case NONE_LINK: + default: + break; + } + + if (dnch->noise_floor != dnch->last_noise_floor) + set_parameters(s, dnch, 1, 0); + } + } + + if (s->sample_noise_mode == SAMPLE_START) { + for (int ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { DeNoiseChannel *dnch = &s->dnch[ch]; init_sample_noise(dnch); } - s->sample_noise_start = 0; + s->sample_noise_mode = SAMPLE_NONE; s->sample_noise = 1; + s->sample_noise_blocks = 0; } if (s->sample_noise) { - for (int ch = 0; ch < inlink->channels; ch++) { + for (int ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { DeNoiseChannel *dnch = &s->dnch[ch]; - sample_noise_block(s, dnch, in, ch); + sample_noise_block(s, dnch, s->winframe, ch); } + s->sample_noise_blocks++; } - if (s->sample_noise_end) { - for (int ch = 0; ch < inlink->channels; ch++) { + if (s->sample_noise_mode == SAMPLE_STOP) { + for (int ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { DeNoiseChannel *dnch = &s->dnch[ch]; - double sample_noise[15]; + double sample_noise[NB_PROFILE_BANDS]; + if (s->sample_noise_blocks <= 0) + break; finish_sample_noise(s, dnch, sample_noise); - set_noise_profile(s, dnch, sample_noise, 1); - set_band_parameters(s, dnch); + set_noise_profile(s, dnch, sample_noise); + set_parameters(s, dnch, 1, 1); } s->sample_noise = 0; - s->sample_noise_end = 0; + s->sample_noise_blocks = 0; + s->sample_noise_mode = SAMPLE_NONE; } - s->block_count++; - td.in = in; - ff_filter_execute(ctx, filter_channel, &td, NULL, - FFMIN(outlink->channels, ff_filter_get_nb_threads(ctx))); + ff_filter_execute(ctx, filter_channel, s->winframe, NULL, + FFMIN(outlink->ch_layout.nb_channels, ff_filter_get_nb_threads(ctx))); - out = ff_get_audio_buffer(outlink, s->sample_advance); - if (!out) { - ret = AVERROR(ENOMEM); - goto end; + 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); + } + + out->pts = in->pts; } - for (int ch = 0; ch < inlink->channels; ch++) { + for (int ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { DeNoiseChannel *dnch = &s->dnch[ch]; double *src = dnch->out_samples; - float *orig = (float *)in->extended_data[ch]; + const float *orig = (const float *)s->winframe->extended_data[ch]; float *dst = (float *)out->extended_data[ch]; switch (output_mode) { case IN_MODE: - for (int m = 0; m < s->sample_advance; m++) + for (int m = 0; m < out->nb_samples; m++) dst[m] = orig[m]; break; case OUT_MODE: - for (int m = 0; m < s->sample_advance; m++) + for (int m = 0; m < out->nb_samples; m++) dst[m] = src[m]; break; case NOISE_MODE: - for (int m = 0; m < s->sample_advance; m++) + for (int m = 0; m < out->nb_samples; m++) dst[m] = orig[m] - src[m]; break; default: + if (in != out) + av_frame_free(&in); av_frame_free(&out); - ret = AVERROR_BUG; - goto end; + return AVERROR_BUG; } memmove(src, src + s->sample_advance, (s->window_length - s->sample_advance) * sizeof(*src)); memset(src + (s->window_length - s->sample_advance), 0, s->sample_advance * sizeof(*src)); } - av_audio_fifo_drain(s->fifo, s->sample_advance); - - out->pts = s->pts; - ret = ff_filter_frame(outlink, out); - if (ret < 0) - goto end; - s->pts += av_rescale_q(s->sample_advance, (AVRational){1, outlink->sample_rate}, outlink->time_base); -end: - av_frame_free(&in); - - return ret; + if (out != in) + av_frame_free(&in); + return ff_filter_frame(outlink, out); } static int activate(AVFilterContext *ctx) @@ -1279,35 +1143,25 @@ static int activate(AVFilterContext *ctx) AVFilterLink *inlink = ctx->inputs[0]; AVFilterLink *outlink = ctx->outputs[0]; AudioFFTDeNoiseContext *s = ctx->priv; - AVFrame *frame = NULL; + AVFrame *in = NULL; int ret; FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); - ret = ff_inlink_consume_frame(inlink, &frame); + ret = ff_inlink_consume_samples(inlink, s->sample_advance, s->sample_advance, &in); if (ret < 0) return ret; + if (ret > 0) + return output_frame(inlink, in); - if (ret > 0) { - if (s->pts == AV_NOPTS_VALUE) - s->pts = frame->pts; - - ret = av_audio_fifo_write(s->fifo, (void **)frame->extended_data, frame->nb_samples); - av_frame_free(&frame); - if (ret < 0) - return ret; - } - - if (av_audio_fifo_size(s->fifo) >= s->window_length) - return output_frame(inlink); - - FF_FILTER_FORWARD_STATUS(inlink, outlink); - if (ff_outlink_frame_wanted(outlink) && - av_audio_fifo_size(s->fifo) < s->window_length) { - ff_inlink_request_frame(inlink); + if (ff_inlink_queued_samples(inlink) >= s->sample_advance) { + ff_filter_set_ready(ctx, 10); return 0; } + FF_FILTER_FORWARD_STATUS(inlink, outlink); + FF_FILTER_FORWARD_WANTED(outlink, inlink); + return FFERROR_NOT_READY; } @@ -1319,6 +1173,7 @@ static av_cold void uninit(AVFilterContext *ctx) av_freep(&s->bin2band); av_freep(&s->band_alpha); av_freep(&s->band_beta); + av_frame_free(&s->winframe); if (s->dnch) { for (int ch = 0; ch < s->channels; ch++) { @@ -1327,6 +1182,7 @@ static av_cold void uninit(AVFilterContext *ctx) av_freep(&dnch->band_amt); av_freep(&dnch->band_excit); av_freep(&dnch->gain); + av_freep(&dnch->smoothed_gain); av_freep(&dnch->prior); av_freep(&dnch->prior_band_excit); av_freep(&dnch->clean_data); @@ -1343,36 +1199,30 @@ static av_cold void uninit(AVFilterContext *ctx) } av_freep(&s->dnch); } - - av_audio_fifo_free(s->fifo); } static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, char *res, int res_len, int flags) { AudioFFTDeNoiseContext *s = ctx->priv; - int need_reset = 0; int ret = 0; - if (!strcmp(cmd, "sample_noise") || - !strcmp(cmd, "sn")) { - if (!strcmp(args, "start")) { - s->sample_noise_start = 1; - s->sample_noise_end = 0; - } else if (!strcmp(args, "end") || - !strcmp(args, "stop")) { - s->sample_noise_start = 0; - s->sample_noise_end = 1; - } - } else { - ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); - if (ret < 0) - return ret; - need_reset = 1; - } + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; - if (need_reset) - set_parameters(s); + if (!strcmp(cmd, "sample_noise") || !strcmp(cmd, "sn")) + return 0; + + for (int ch = 0; ch < s->channels; ch++) { + DeNoiseChannel *dnch = &s->dnch[ch]; + + dnch->noise_reduction = s->noise_reduction; + dnch->noise_floor = s->noise_floor; + dnch->residual_floor = s->residual_floor; + + set_parameters(s, dnch, 1, 1); + } return 0; } diff --git a/libavfilter/af_afftfilt.c b/libavfilter/af_afftfilt.c index 691feeae3..b10fa24b0 100644 --- a/libavfilter/af_afftfilt.c +++ b/libavfilter/af_afftfilt.c @@ -18,7 +18,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/audio_fifo.h" #include "libavutil/avstring.h" #include "libavfilter/internal.h" #include "libavutil/common.h" @@ -36,7 +35,7 @@ typedef struct AFFTFiltContext { char *img_str; int fft_size; - AVTXContext *fft, *ifft; + AVTXContext **fft, **ifft; av_tx_fn tx_fn, itx_fn; AVComplexFloat **fft_in; AVComplexFloat **fft_out; @@ -46,12 +45,10 @@ typedef struct AFFTFiltContext { int window_size; AVExpr **real; AVExpr **imag; - AVAudioFifo *fifo; - int64_t pts; int hop_size; float overlap; + AVFrame *window; AVFrame *buffer; - int eof; int win_func; float *window_func_lut; } AFFTFiltContext; @@ -107,37 +104,45 @@ static int config_input(AVFilterLink *inlink) AFFTFiltContext *s = ctx->priv; char *saveptr = NULL; int ret = 0, ch; - float overlap, scale; + float overlap, scale = 1.f; char *args; const char *last_expr = "1"; int buf_size; - s->channels = inlink->channels; - s->pts = AV_NOPTS_VALUE; - ret = av_tx_init(&s->fft, &s->tx_fn, AV_TX_FLOAT_FFT, 0, s->fft_size, &scale, 0); - if (ret < 0) - return ret; + s->channels = inlink->ch_layout.nb_channels; + s->fft = av_calloc(s->channels, sizeof(*s->fft)); + s->ifft = av_calloc(s->channels, sizeof(*s->ifft)); + if (!s->fft || !s->ifft) + return AVERROR(ENOMEM); - ret = av_tx_init(&s->ifft, &s->itx_fn, AV_TX_FLOAT_FFT, 1, s->fft_size, &scale, 0); - if (ret < 0) - return ret; + for (int ch = 0; ch < s->channels; ch++) { + ret = av_tx_init(&s->fft[ch], &s->tx_fn, AV_TX_FLOAT_FFT, 0, s->fft_size, &scale, 0); + if (ret < 0) + return ret; + } + + for (int ch = 0; ch < s->channels; ch++) { + ret = av_tx_init(&s->ifft[ch], &s->itx_fn, AV_TX_FLOAT_FFT, 1, s->fft_size, &scale, 0); + if (ret < 0) + return ret; + } s->window_size = s->fft_size; buf_size = FFALIGN(s->window_size, av_cpu_max_align()); - s->fft_in = av_calloc(inlink->channels, sizeof(*s->fft_in)); + s->fft_in = av_calloc(inlink->ch_layout.nb_channels, sizeof(*s->fft_in)); if (!s->fft_in) return AVERROR(ENOMEM); - s->fft_out = av_calloc(inlink->channels, sizeof(*s->fft_out)); + s->fft_out = av_calloc(inlink->ch_layout.nb_channels, sizeof(*s->fft_out)); if (!s->fft_out) return AVERROR(ENOMEM); - s->fft_temp = av_calloc(inlink->channels, sizeof(*s->fft_temp)); + s->fft_temp = av_calloc(inlink->ch_layout.nb_channels, sizeof(*s->fft_temp)); if (!s->fft_temp) return AVERROR(ENOMEM); - for (ch = 0; ch < inlink->channels; ch++) { + for (ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { s->fft_in[ch] = av_calloc(buf_size, sizeof(**s->fft_in)); if (!s->fft_in[ch]) return AVERROR(ENOMEM); @@ -151,11 +156,11 @@ static int config_input(AVFilterLink *inlink) return AVERROR(ENOMEM); } - s->real = av_calloc(inlink->channels, sizeof(*s->real)); + s->real = av_calloc(inlink->ch_layout.nb_channels, sizeof(*s->real)); if (!s->real) return AVERROR(ENOMEM); - s->imag = av_calloc(inlink->channels, sizeof(*s->imag)); + s->imag = av_calloc(inlink->ch_layout.nb_channels, sizeof(*s->imag)); if (!s->imag) return AVERROR(ENOMEM); @@ -163,7 +168,7 @@ static int config_input(AVFilterLink *inlink) if (!args) return AVERROR(ENOMEM); - for (ch = 0; ch < inlink->channels; ch++) { + for (ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { char *arg = av_strtok(ch == 0 ? args : NULL, "|", &saveptr); ret = av_expr_parse(&s->real[ch], arg ? arg : last_expr, var_names, @@ -183,7 +188,7 @@ static int config_input(AVFilterLink *inlink) saveptr = NULL; last_expr = "1"; - for (ch = 0; ch < inlink->channels; ch++) { + for (ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { char *arg = av_strtok(ch == 0 ? args : NULL, "|", &saveptr); ret = av_expr_parse(&s->imag[ch], arg ? arg : last_expr, var_names, @@ -196,15 +201,13 @@ static int config_input(AVFilterLink *inlink) av_freep(&args); - s->fifo = av_audio_fifo_alloc(inlink->format, inlink->channels, s->window_size); - if (!s->fifo) - return AVERROR(ENOMEM); - s->window_func_lut = av_realloc_f(s->window_func_lut, s->window_size, sizeof(*s->window_func_lut)); if (!s->window_func_lut) return AVERROR(ENOMEM); generate_window_func(s->window_func_lut, s->window_size, s->win_func, &overlap); + for (int i = 0; i < s->window_size; i++) + s->window_func_lut[i] = sqrtf(s->window_func_lut[i] / s->window_size); if (s->overlap == 1) s->overlap = overlap; @@ -212,6 +215,10 @@ static int config_input(AVFilterLink *inlink) if (s->hop_size <= 0) return AVERROR(EINVAL); + s->window = ff_get_audio_buffer(inlink, s->window_size * 2); + if (!s->window) + return AVERROR(ENOMEM); + s->buffer = ff_get_audio_buffer(inlink, s->window_size * 2); if (!s->buffer) return AVERROR(ENOMEM); @@ -222,68 +229,50 @@ fail: return ret; } -static int filter_frame(AVFilterLink *inlink) +static int tx_channel(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - AVFilterContext *ctx = inlink->dst; - AVFilterLink *outlink = ctx->outputs[0]; AFFTFiltContext *s = ctx->priv; - const int window_size = s->window_size; - const float f = 1. / (s->window_size / 2); - double values[VAR_VARS_NB]; - AVFrame *out, *in = NULL; - int ch, n, ret, i; + const int channels = s->channels; + const int start = (channels * jobnr) / nb_jobs; + const int end = (channels * (jobnr+1)) / nb_jobs; - if (!in) { - in = ff_get_audio_buffer(outlink, window_size); - if (!in) - return AVERROR(ENOMEM); - } - - ret = av_audio_fifo_peek(s->fifo, (void **)in->extended_data, window_size); - if (ret < 0) - goto fail; - - for (ch = 0; ch < inlink->channels; ch++) { - const float *src = (float *)in->extended_data[ch]; - AVComplexFloat *fft_in = s->fft_in[ch]; - - for (n = 0; n < in->nb_samples; n++) { - fft_in[n].re = src[n] * s->window_func_lut[n]; - fft_in[n].im = 0; - } - - for (; n < window_size; n++) { - fft_in[n].re = 0; - fft_in[n].im = 0; - } - } - - values[VAR_PTS] = s->pts; - values[VAR_SAMPLE_RATE] = inlink->sample_rate; - values[VAR_NBBINS] = window_size / 2; - values[VAR_CHANNELS] = inlink->channels; - - for (ch = 0; ch < inlink->channels; ch++) { + for (int ch = start; ch < end; ch++) { AVComplexFloat *fft_in = s->fft_in[ch]; AVComplexFloat *fft_out = s->fft_out[ch]; - s->tx_fn(s->fft, fft_out, fft_in, sizeof(float)); + s->tx_fn(s->fft[ch], fft_out, fft_in, sizeof(float)); } - for (ch = 0; ch < inlink->channels; ch++) { + return 0; +} + +static int filter_channel(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + AFFTFiltContext *s = ctx->priv; + const int window_size = s->window_size; + const float *window_lut = s->window_func_lut; + const float f = sqrtf(1.f - s->overlap); + const int channels = s->channels; + const int start = (channels * jobnr) / nb_jobs; + const int end = (channels * (jobnr+1)) / nb_jobs; + double values[VAR_VARS_NB]; + + memcpy(values, arg, sizeof(values)); + + for (int ch = start; ch < end; ch++) { AVComplexFloat *fft_out = s->fft_out[ch]; AVComplexFloat *fft_temp = s->fft_temp[ch]; float *buf = (float *)s->buffer->extended_data[ch]; - int x; + values[VAR_CHANNEL] = ch; if (ctx->is_disabled) { - for (n = 0; n <= window_size / 2; n++) { + for (int n = 0; n < window_size; n++) { fft_temp[n].re = fft_out[n].re; fft_temp[n].im = fft_out[n].im; } } else { - for (n = 0; n <= window_size / 2; n++) { + for (int n = 0; n <= window_size / 2; n++) { float fr, fi; values[VAR_BIN] = n; @@ -296,44 +285,80 @@ static int filter_frame(AVFilterLink *inlink) fft_temp[n].re = fr; fft_temp[n].im = fi; } + + for (int n = window_size / 2 + 1, x = window_size / 2 - 1; n < window_size; n++, x--) { + fft_temp[n].re = fft_temp[x].re; + fft_temp[n].im = -fft_temp[x].im; + } } - for (n = window_size / 2 + 1, x = window_size / 2 - 1; n < window_size; n++, x--) { - fft_temp[n].re = fft_temp[x].re; - fft_temp[n].im = -fft_temp[x].im; - } + s->itx_fn(s->ifft[ch], fft_out, fft_temp, sizeof(float)); - s->itx_fn(s->ifft, fft_out, fft_temp, sizeof(float)); + memmove(buf, buf + s->hop_size, window_size * sizeof(float)); + for (int i = 0; i < window_size; i++) + buf[i] += fft_out[i].re * window_lut[i] * f; + } - for (i = 0; i < window_size; i++) { - buf[i] += s->fft_out[ch][i].re * f; + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + AFFTFiltContext *s = ctx->priv; + const int window_size = s->window_size; + const float *window_lut = s->window_func_lut; + double values[VAR_VARS_NB]; + int ch, n, ret; + AVFrame *out; + + for (ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { + const int offset = s->window_size - s->hop_size; + float *src = (float *)s->window->extended_data[ch]; + AVComplexFloat *fft_in = s->fft_in[ch]; + + memmove(src, &src[s->hop_size], offset * sizeof(float)); + memcpy(&src[offset], in->extended_data[ch], in->nb_samples * sizeof(float)); + memset(&src[offset + in->nb_samples], 0, (s->hop_size - in->nb_samples) * sizeof(float)); + + for (n = 0; n < window_size; n++) { + fft_in[n].re = src[n] * window_lut[n]; + fft_in[n].im = 0; } } + values[VAR_PTS] = in->pts; + values[VAR_SAMPLE_RATE] = inlink->sample_rate; + values[VAR_NBBINS] = window_size / 2; + values[VAR_CHANNELS] = inlink->ch_layout.nb_channels; + + ff_filter_execute(ctx, tx_channel, NULL, NULL, + FFMIN(s->channels, ff_filter_get_nb_threads(ctx))); + + ff_filter_execute(ctx, filter_channel, values, NULL, + FFMIN(s->channels, ff_filter_get_nb_threads(ctx))); + out = ff_get_audio_buffer(outlink, s->hop_size); if (!out) { ret = AVERROR(ENOMEM); goto fail; } - out->pts = s->pts; - s->pts += av_rescale_q(s->hop_size, (AVRational){1, outlink->sample_rate}, outlink->time_base); + out->pts = in->pts; + out->nb_samples = in->nb_samples; - for (ch = 0; ch < inlink->channels; ch++) { + for (ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { float *dst = (float *)out->extended_data[ch]; float *buf = (float *)s->buffer->extended_data[ch]; - for (n = 0; n < s->hop_size; n++) - dst[n] = buf[n] * (1.f - s->overlap); - memmove(buf, buf + s->hop_size, window_size * 4); + memcpy(dst, buf, s->hop_size * sizeof(float)); } ret = ff_filter_frame(outlink, out); if (ret < 0) goto fail; - av_audio_fifo_drain(s->fifo, s->hop_size); - fail: av_frame_free(&in); return ret < 0 ? ret : 0; @@ -350,48 +375,21 @@ static int activate(AVFilterContext *ctx) FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); - if (!s->eof && av_audio_fifo_size(s->fifo) < s->window_size) { - ret = ff_inlink_consume_frame(inlink, &in); - if (ret < 0) - return ret; - - if (ret > 0) { - 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; - } - } - - if ((av_audio_fifo_size(s->fifo) >= s->window_size) || - (av_audio_fifo_size(s->fifo) > 0 && s->eof)) { - ret = filter_frame(inlink); - if (av_audio_fifo_size(s->fifo) >= s->window_size) - ff_filter_set_ready(ctx, 100); + ret = ff_inlink_consume_samples(inlink, s->hop_size, s->hop_size, &in); + if (ret < 0) return ret; - } - if (!s->eof && ff_inlink_acknowledge_status(inlink, &status, &pts)) { - if (status == AVERROR_EOF) { - s->eof = 1; - if (av_audio_fifo_size(s->fifo) >= 0) { - ff_filter_set_ready(ctx, 100); - return 0; - } - } - } + if (ret > 0) + ret = filter_frame(inlink, in); + if (ret < 0) + return ret; - if (s->eof && av_audio_fifo_size(s->fifo) <= 0) { - ff_outlink_set_status(outlink, AVERROR_EOF, s->pts); + if (ff_inlink_acknowledge_status(inlink, &status, &pts)) { + ff_outlink_set_status(outlink, status, pts); return 0; } - if (!s->eof) - FF_FILTER_FORWARD_WANTED(outlink, inlink); + FF_FILTER_FORWARD_WANTED(outlink, inlink); return FFERROR_NOT_READY; } @@ -401,10 +399,12 @@ static av_cold void uninit(AVFilterContext *ctx) AFFTFiltContext *s = ctx->priv; int i; - av_tx_uninit(&s->fft); - av_tx_uninit(&s->ifft); for (i = 0; i < s->channels; i++) { + if (s->ifft) + av_tx_uninit(&s->ifft[i]); + if (s->fft) + av_tx_uninit(&s->fft[i]); if (s->fft_in) av_freep(&s->fft_in[i]); if (s->fft_out) @@ -412,6 +412,9 @@ static av_cold void uninit(AVFilterContext *ctx) if (s->fft_temp) av_freep(&s->fft_temp[i]); } + + av_freep(&s->fft); + av_freep(&s->ifft); av_freep(&s->fft_in); av_freep(&s->fft_out); av_freep(&s->fft_temp); @@ -424,9 +427,8 @@ static av_cold void uninit(AVFilterContext *ctx) av_freep(&s->real); av_freep(&s->imag); av_frame_free(&s->buffer); + av_frame_free(&s->window); av_freep(&s->window_func_lut); - - av_audio_fifo_free(s->fifo); } static const AVFilterPad inputs[] = { @@ -454,5 +456,6 @@ const AVFilter ff_af_afftfilt = { FILTER_SINGLE_SAMPLEFMT(AV_SAMPLE_FMT_FLTP), .activate = activate, .uninit = uninit, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | + AVFILTER_FLAG_SLICE_THREADS, }; diff --git a/libavfilter/af_afir.c b/libavfilter/af_afir.c index ace5087e9..e1fe7d6a6 100644 --- a/libavfilter/af_afir.c +++ b/libavfilter/af_afir.c @@ -25,14 +25,17 @@ #include +#include "libavutil/tx.h" #include "libavutil/avstring.h" #include "libavutil/channel_layout.h" #include "libavutil/common.h" #include "libavutil/float_dsp.h" +#include "libavutil/frame.h" #include "libavutil/intreadwrite.h" +#include "libavutil/log.h" #include "libavutil/opt.h" +#include "libavutil/rational.h" #include "libavutil/xga_font_data.h" -#include "libavcodec/avfft.h" #include "audio.h" #include "avfilter.h" @@ -40,203 +43,7 @@ #include "formats.h" #include "internal.h" #include "af_afir.h" - -static void fcmul_add_c(float *sum, const float *t, const float *c, ptrdiff_t len) -{ - int n; - - for (n = 0; n < len; n++) { - const float cre = c[2 * n ]; - const float cim = c[2 * n + 1]; - const float tre = t[2 * n ]; - const float tim = t[2 * n + 1]; - - sum[2 * n ] += tre * cre - tim * cim; - sum[2 * n + 1] += tre * cim + tim * cre; - } - - sum[2 * n] += t[2 * n] * c[2 * n]; -} - -static void direct(const float *in, const FFTComplex *ir, int len, float *out) -{ - for (int n = 0; n < len; n++) - for (int m = 0; m <= n; m++) - out[n] += ir[m].re * in[n - m]; -} - -static void fir_fadd(AudioFIRContext *s, float *dst, const float *src, int nb_samples) -{ - if ((nb_samples & 15) == 0 && nb_samples >= 16) { - s->fdsp->vector_fmac_scalar(dst, src, 1.f, nb_samples); - } else { - for (int n = 0; n < nb_samples; n++) - dst[n] += src[n]; - } -} - -static int fir_quantum(AVFilterContext *ctx, AVFrame *out, int ch, int offset) -{ - AudioFIRContext *s = ctx->priv; - const float *in = (const float *)s->in->extended_data[ch] + offset; - float *block, *buf, *ptr = (float *)out->extended_data[ch] + offset; - const int nb_samples = FFMIN(s->min_part_size, out->nb_samples - offset); - int n, i, j; - - for (int segment = 0; segment < s->nb_segments; segment++) { - AudioFIRSegment *seg = &s->seg[segment]; - float *src = (float *)seg->input->extended_data[ch]; - float *dst = (float *)seg->output->extended_data[ch]; - float *sum = (float *)seg->sum->extended_data[ch]; - - if (s->min_part_size >= 8) { - s->fdsp->vector_fmul_scalar(src + seg->input_offset, in, s->dry_gain, FFALIGN(nb_samples, 4)); - emms_c(); - } else { - for (n = 0; n < nb_samples; n++) - src[seg->input_offset + n] = in[n] * s->dry_gain; - } - - seg->output_offset[ch] += s->min_part_size; - if (seg->output_offset[ch] == seg->part_size) { - seg->output_offset[ch] = 0; - } else { - memmove(src, src + s->min_part_size, (seg->input_size - s->min_part_size) * sizeof(*src)); - - dst += seg->output_offset[ch]; - fir_fadd(s, ptr, dst, nb_samples); - continue; - } - - if (seg->part_size < 8) { - memset(dst, 0, sizeof(*dst) * seg->part_size * seg->nb_partitions); - - j = seg->part_index[ch]; - - for (i = 0; i < seg->nb_partitions; i++) { - const int coffset = j * seg->coeff_size; - const FFTComplex *coeff = (const FFTComplex *)seg->coeff->extended_data[ch * !s->one2many] + coffset; - - direct(src, coeff, nb_samples, dst); - - if (j == 0) - j = seg->nb_partitions; - j--; - } - - seg->part_index[ch] = (seg->part_index[ch] + 1) % seg->nb_partitions; - - memmove(src, src + s->min_part_size, (seg->input_size - s->min_part_size) * sizeof(*src)); - - for (n = 0; n < nb_samples; n++) { - ptr[n] += dst[n]; - } - continue; - } - - memset(sum, 0, sizeof(*sum) * seg->fft_length); - block = (float *)seg->block->extended_data[ch] + seg->part_index[ch] * seg->block_size; - memset(block + seg->part_size, 0, sizeof(*block) * (seg->fft_length - seg->part_size)); - - memcpy(block, src, sizeof(*src) * seg->part_size); - - av_rdft_calc(seg->rdft[ch], block); - block[2 * seg->part_size] = block[1]; - block[1] = 0; - - j = seg->part_index[ch]; - - for (i = 0; i < seg->nb_partitions; i++) { - const int coffset = j * seg->coeff_size; - const float *block = (const float *)seg->block->extended_data[ch] + i * seg->block_size; - const FFTComplex *coeff = (const FFTComplex *)seg->coeff->extended_data[ch * !s->one2many] + coffset; - - s->afirdsp.fcmul_add(sum, block, (const float *)coeff, seg->part_size); - - if (j == 0) - j = seg->nb_partitions; - j--; - } - - sum[1] = sum[2 * seg->part_size]; - av_rdft_calc(seg->irdft[ch], sum); - - buf = (float *)seg->buffer->extended_data[ch]; - fir_fadd(s, buf, sum, seg->part_size); - - memcpy(dst, buf, seg->part_size * sizeof(*dst)); - - buf = (float *)seg->buffer->extended_data[ch]; - memcpy(buf, sum + seg->part_size, seg->part_size * sizeof(*buf)); - - seg->part_index[ch] = (seg->part_index[ch] + 1) % seg->nb_partitions; - - memmove(src, src + s->min_part_size, (seg->input_size - s->min_part_size) * sizeof(*src)); - - fir_fadd(s, ptr, dst, nb_samples); - } - - if (s->min_part_size >= 8) { - s->fdsp->vector_fmul_scalar(ptr, ptr, s->wet_gain, FFALIGN(nb_samples, 4)); - emms_c(); - } else { - for (n = 0; n < nb_samples; n++) - ptr[n] *= s->wet_gain; - } - - return 0; -} - -static int fir_channel(AVFilterContext *ctx, AVFrame *out, int ch) -{ - AudioFIRContext *s = ctx->priv; - - for (int offset = 0; offset < out->nb_samples; offset += s->min_part_size) { - fir_quantum(ctx, out, ch, offset); - } - - return 0; -} - -static int fir_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) -{ - AVFrame *out = arg; - const int start = (out->channels * jobnr) / nb_jobs; - const int end = (out->channels * (jobnr+1)) / nb_jobs; - - for (int ch = start; ch < end; ch++) { - fir_channel(ctx, out, ch); - } - - return 0; -} - -static int fir_frame(AudioFIRContext *s, AVFrame *in, AVFilterLink *outlink) -{ - AVFilterContext *ctx = outlink->src; - AVFrame *out = NULL; - - out = ff_get_audio_buffer(outlink, in->nb_samples); - if (!out) { - av_frame_free(&in); - return AVERROR(ENOMEM); - } - - if (s->pts == AV_NOPTS_VALUE) - s->pts = in->pts; - s->in = in; - ff_filter_execute(ctx, fir_channels, out, NULL, - FFMIN(outlink->channels, ff_filter_get_nb_threads(ctx))); - - out->pts = s->pts; - if (s->pts != AV_NOPTS_VALUE) - s->pts += av_rescale_q(out->nb_samples, (AVRational){1, outlink->sample_rate}, outlink->time_base); - - av_frame_free(&in); - s->in = NULL; - - return ff_filter_frame(outlink, out); -} +#include "af_afirdsp.h" static void drawtext(AVFrame *pic, int x, int y, const char *txt, uint32_t color) { @@ -287,93 +94,64 @@ static void draw_line(AVFrame *out, int x0, int y0, int x1, int y1, uint32_t col } } -static void draw_response(AVFilterContext *ctx, AVFrame *out) +#define DEPTH 32 +#include "afir_template.c" + +#undef DEPTH +#define DEPTH 64 +#include "afir_template.c" + +static int fir_channel(AVFilterContext *ctx, AVFrame *out, int ch) { AudioFIRContext *s = ctx->priv; - float *mag, *phase, *delay, min = FLT_MAX, max = FLT_MIN; - float min_delay = FLT_MAX, max_delay = FLT_MIN; - int prev_ymag = -1, prev_yphase = -1, prev_ydelay = -1; - char text[32]; - int channel, i, x; - memset(out->data[0], 0, s->h * out->linesize[0]); - - phase = av_malloc_array(s->w, sizeof(*phase)); - mag = av_malloc_array(s->w, sizeof(*mag)); - delay = av_malloc_array(s->w, sizeof(*delay)); - if (!mag || !phase || !delay) - goto end; - - channel = av_clip(s->ir_channel, 0, s->ir[s->selir]->channels - 1); - for (i = 0; i < s->w; i++) { - const float *src = (const float *)s->ir[s->selir]->extended_data[channel]; - double w = i * M_PI / (s->w - 1); - double div, real_num = 0., imag_num = 0., real = 0., imag = 0.; - - for (x = 0; x < s->nb_taps; x++) { - real += cos(-x * w) * src[x]; - imag += sin(-x * w) * src[x]; - real_num += cos(-x * w) * src[x] * x; - imag_num += sin(-x * w) * src[x] * x; + for (int offset = 0; offset < out->nb_samples; offset += s->min_part_size) { + switch (s->format) { + case AV_SAMPLE_FMT_FLTP: + fir_quantum_float(ctx, out, ch, offset); + break; + case AV_SAMPLE_FMT_DBLP: + fir_quantum_double(ctx, out, ch, offset); + break; } - - mag[i] = hypot(real, imag); - phase[i] = atan2(imag, real); - div = real * real + imag * imag; - delay[i] = (real_num * real + imag_num * imag) / div; - min = fminf(min, mag[i]); - max = fmaxf(max, mag[i]); - min_delay = fminf(min_delay, delay[i]); - max_delay = fmaxf(max_delay, delay[i]); } - for (i = 0; i < s->w; i++) { - int ymag = mag[i] / max * (s->h - 1); - int ydelay = (delay[i] - min_delay) / (max_delay - min_delay) * (s->h - 1); - int yphase = (0.5 * (1. + phase[i] / M_PI)) * (s->h - 1); + return 0; +} - ymag = s->h - 1 - av_clip(ymag, 0, s->h - 1); - yphase = s->h - 1 - av_clip(yphase, 0, s->h - 1); - ydelay = s->h - 1 - av_clip(ydelay, 0, s->h - 1); +static int fir_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + AVFrame *out = arg; + const int start = (out->ch_layout.nb_channels * jobnr) / nb_jobs; + const int end = (out->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; - if (prev_ymag < 0) - prev_ymag = ymag; - if (prev_yphase < 0) - prev_yphase = yphase; - if (prev_ydelay < 0) - prev_ydelay = ydelay; - - draw_line(out, i, ymag, FFMAX(i - 1, 0), prev_ymag, 0xFFFF00FF); - draw_line(out, i, yphase, FFMAX(i - 1, 0), prev_yphase, 0xFF00FF00); - draw_line(out, i, ydelay, FFMAX(i - 1, 0), prev_ydelay, 0xFF00FFFF); - - prev_ymag = ymag; - prev_yphase = yphase; - prev_ydelay = ydelay; + for (int ch = start; ch < end; ch++) { + fir_channel(ctx, out, ch); } - if (s->w > 400 && s->h > 100) { - drawtext(out, 2, 2, "Max Magnitude:", 0xDDDDDDDD); - snprintf(text, sizeof(text), "%.2f", max); - drawtext(out, 15 * 8 + 2, 2, text, 0xDDDDDDDD); + return 0; +} - drawtext(out, 2, 12, "Min Magnitude:", 0xDDDDDDDD); - snprintf(text, sizeof(text), "%.2f", min); - drawtext(out, 15 * 8 + 2, 12, text, 0xDDDDDDDD); +static int fir_frame(AudioFIRContext *s, AVFrame *in, AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + AVFrame *out = NULL; - drawtext(out, 2, 22, "Max Delay:", 0xDDDDDDDD); - snprintf(text, sizeof(text), "%.2f", max_delay); - drawtext(out, 11 * 8 + 2, 22, text, 0xDDDDDDDD); - - drawtext(out, 2, 32, "Min Delay:", 0xDDDDDDDD); - snprintf(text, sizeof(text), "%.2f", min_delay); - drawtext(out, 11 * 8 + 2, 32, text, 0xDDDDDDDD); + out = ff_get_audio_buffer(outlink, in->nb_samples); + if (!out) { + av_frame_free(&in); + return AVERROR(ENOMEM); } + out->pts = in->pts; -end: - av_free(delay); - av_free(phase); - av_free(mag); + s->in = in; + ff_filter_execute(ctx, fir_channels, out, NULL, + FFMIN(outlink->ch_layout.nb_channels, ff_filter_get_nb_threads(ctx))); + + av_frame_free(&in); + s->in = NULL; + + return ff_filter_frame(outlink, out); } static int init_segment(AVFilterContext *ctx, AudioFIRSegment *seg, @@ -381,9 +159,9 @@ static int init_segment(AVFilterContext *ctx, AudioFIRSegment *seg, { AudioFIRContext *s = ctx->priv; - seg->rdft = av_calloc(ctx->inputs[0]->channels, sizeof(*seg->rdft)); - seg->irdft = av_calloc(ctx->inputs[0]->channels, sizeof(*seg->irdft)); - if (!seg->rdft || !seg->irdft) + seg->tx = av_calloc(ctx->inputs[0]->ch_layout.nb_channels, sizeof(*seg->tx)); + seg->itx = av_calloc(ctx->inputs[0]->ch_layout.nb_channels, sizeof(*seg->itx)); + if (!seg->tx || !seg->itx) return AVERROR(ENOMEM); seg->fft_length = part_size * 2 + 1; @@ -394,25 +172,39 @@ static int init_segment(AVFilterContext *ctx, AudioFIRSegment *seg, seg->input_size = offset + s->min_part_size; seg->input_offset = offset; - seg->part_index = av_calloc(ctx->inputs[0]->channels, sizeof(*seg->part_index)); - seg->output_offset = av_calloc(ctx->inputs[0]->channels, sizeof(*seg->output_offset)); + seg->part_index = av_calloc(ctx->inputs[0]->ch_layout.nb_channels, sizeof(*seg->part_index)); + seg->output_offset = av_calloc(ctx->inputs[0]->ch_layout.nb_channels, sizeof(*seg->output_offset)); if (!seg->part_index || !seg->output_offset) return AVERROR(ENOMEM); - for (int ch = 0; ch < ctx->inputs[0]->channels && part_size >= 8; ch++) { - seg->rdft[ch] = av_rdft_init(av_log2(2 * part_size), DFT_R2C); - seg->irdft[ch] = av_rdft_init(av_log2(2 * part_size), IDFT_C2R); - if (!seg->rdft[ch] || !seg->irdft[ch]) + for (int ch = 0; ch < ctx->inputs[0]->ch_layout.nb_channels && part_size >= 8; ch++) { + double dscale = 1.0, idscale = 1.0 / part_size; + float fscale = 1.f, ifscale = 1.f / part_size; + + switch (s->format) { + case AV_SAMPLE_FMT_FLTP: + av_tx_init(&seg->tx[ch], &seg->tx_fn, AV_TX_FLOAT_RDFT, 0, 2 * part_size, &fscale, 0); + av_tx_init(&seg->itx[ch], &seg->itx_fn, AV_TX_FLOAT_RDFT, 1, 2 * part_size, &ifscale, 0); + break; + case AV_SAMPLE_FMT_DBLP: + av_tx_init(&seg->tx[ch], &seg->tx_fn, AV_TX_DOUBLE_RDFT, 0, 2 * part_size, &dscale, 0); + av_tx_init(&seg->itx[ch], &seg->itx_fn, AV_TX_DOUBLE_RDFT, 1, 2 * part_size, &idscale, 0); + break; + } + + if (!seg->tx[ch] || !seg->itx[ch]) return AVERROR(ENOMEM); } - seg->sum = ff_get_audio_buffer(ctx->inputs[0], seg->fft_length); - seg->block = ff_get_audio_buffer(ctx->inputs[0], seg->nb_partitions * seg->block_size); + seg->sumin = ff_get_audio_buffer(ctx->inputs[0], seg->fft_length); + seg->sumout = ff_get_audio_buffer(ctx->inputs[0], seg->fft_length); + seg->blockin = ff_get_audio_buffer(ctx->inputs[0], seg->nb_partitions * seg->block_size); + seg->blockout = ff_get_audio_buffer(ctx->inputs[0], seg->nb_partitions * seg->block_size); seg->buffer = ff_get_audio_buffer(ctx->inputs[0], seg->part_size); seg->coeff = ff_get_audio_buffer(ctx->inputs[1 + s->selir], seg->nb_partitions * seg->coeff_size * 2); seg->input = ff_get_audio_buffer(ctx->inputs[0], seg->input_size); seg->output = ff_get_audio_buffer(ctx->inputs[0], seg->part_size); - if (!seg->buffer || !seg->sum || !seg->block || !seg->coeff || !seg->input || !seg->output) + if (!seg->buffer || !seg->sumin || !seg->sumout || !seg->blockin || !seg->blockout || !seg->coeff || !seg->input || !seg->output) return AVERROR(ENOMEM); return 0; @@ -422,25 +214,27 @@ static void uninit_segment(AVFilterContext *ctx, AudioFIRSegment *seg) { AudioFIRContext *s = ctx->priv; - if (seg->rdft) { + if (seg->tx) { for (int ch = 0; ch < s->nb_channels; ch++) { - av_rdft_end(seg->rdft[ch]); + av_tx_uninit(&seg->tx[ch]); } } - av_freep(&seg->rdft); + av_freep(&seg->tx); - if (seg->irdft) { + if (seg->itx) { for (int ch = 0; ch < s->nb_channels; ch++) { - av_rdft_end(seg->irdft[ch]); + av_tx_uninit(&seg->itx[ch]); } } - av_freep(&seg->irdft); + av_freep(&seg->itx); av_freep(&seg->output_offset); av_freep(&seg->part_index); - av_frame_free(&seg->block); - av_frame_free(&seg->sum); + av_frame_free(&seg->blockin); + av_frame_free(&seg->blockout); + av_frame_free(&seg->sumin); + av_frame_free(&seg->sumout); av_frame_free(&seg->buffer); av_frame_free(&seg->coeff); av_frame_free(&seg->input); @@ -451,8 +245,7 @@ static void uninit_segment(AVFilterContext *ctx, AudioFIRSegment *seg) static int convert_coeffs(AVFilterContext *ctx) { AudioFIRContext *s = ctx->priv; - int ret, i, ch, n, cur_nb_taps; - float power = 0; + int ret, i, cur_nb_taps; if (!s->nb_taps) { int part_size, max_part_size; @@ -495,113 +288,42 @@ static int convert_coeffs(AVFilterContext *ctx) return AVERROR_BUG; } - if (s->response) - draw_response(ctx, s->video); + if (s->response) { + switch (s->format) { + case AV_SAMPLE_FMT_FLTP: + draw_response_float(ctx, s->video); + break; + case AV_SAMPLE_FMT_DBLP: + draw_response_double(ctx, s->video); + break; + } + } s->gain = 1; cur_nb_taps = s->ir[s->selir]->nb_samples; - switch (s->gtype) { - case -1: - /* nothing to do */ + switch (s->format) { + case AV_SAMPLE_FMT_FLTP: + ret = get_power_float(ctx, s, cur_nb_taps); break; - case 0: - for (ch = 0; ch < ctx->inputs[1 + s->selir]->channels; ch++) { - float *time = (float *)s->ir[s->selir]->extended_data[!s->one2many * ch]; - - for (i = 0; i < cur_nb_taps; i++) - power += FFABS(time[i]); - } - s->gain = ctx->inputs[1 + s->selir]->channels / power; + case AV_SAMPLE_FMT_DBLP: + ret = get_power_double(ctx, s, cur_nb_taps); break; - case 1: - for (ch = 0; ch < ctx->inputs[1 + s->selir]->channels; ch++) { - float *time = (float *)s->ir[s->selir]->extended_data[!s->one2many * ch]; - - for (i = 0; i < cur_nb_taps; i++) - power += time[i]; - } - s->gain = ctx->inputs[1 + s->selir]->channels / power; - break; - case 2: - for (ch = 0; ch < ctx->inputs[1 + s->selir]->channels; ch++) { - float *time = (float *)s->ir[s->selir]->extended_data[!s->one2many * ch]; - - for (i = 0; i < cur_nb_taps; i++) - power += time[i] * time[i]; - } - s->gain = sqrtf(ch / power); - break; - default: - return AVERROR_BUG; } - s->gain = FFMIN(s->gain * s->ir_gain, 1.f); - av_log(ctx, AV_LOG_DEBUG, "power %f, gain %f\n", power, s->gain); - for (ch = 0; ch < ctx->inputs[1 + s->selir]->channels; ch++) { - float *time = (float *)s->ir[s->selir]->extended_data[!s->one2many * ch]; - - s->fdsp->vector_fmul_scalar(time, time, s->gain, FFALIGN(cur_nb_taps, 4)); - } + if (ret < 0) + return ret; av_log(ctx, AV_LOG_DEBUG, "nb_taps: %d\n", cur_nb_taps); av_log(ctx, AV_LOG_DEBUG, "nb_segments: %d\n", s->nb_segments); - for (ch = 0; ch < ctx->inputs[1 + s->selir]->channels; ch++) { - float *time = (float *)s->ir[s->selir]->extended_data[!s->one2many * ch]; - int toffset = 0; - - for (i = FFMAX(1, s->length * s->nb_taps); i < s->nb_taps; i++) - time[i] = 0; - - av_log(ctx, AV_LOG_DEBUG, "channel: %d\n", ch); - - for (int segment = 0; segment < s->nb_segments; segment++) { - AudioFIRSegment *seg = &s->seg[segment]; - float *block = (float *)seg->block->extended_data[ch]; - FFTComplex *coeff = (FFTComplex *)seg->coeff->extended_data[ch]; - - av_log(ctx, AV_LOG_DEBUG, "segment: %d\n", segment); - - for (i = 0; i < seg->nb_partitions; i++) { - const float scale = 1.f / seg->part_size; - const int coffset = i * seg->coeff_size; - const int remaining = s->nb_taps - toffset; - const int size = remaining >= seg->part_size ? seg->part_size : remaining; - - if (size < 8) { - for (n = 0; n < size; n++) - coeff[coffset + n].re = time[toffset + n]; - - toffset += size; - continue; - } - - memset(block, 0, sizeof(*block) * seg->fft_length); - memcpy(block, time + toffset, size * sizeof(*block)); - - av_rdft_calc(seg->rdft[0], block); - - coeff[coffset].re = block[0] * scale; - coeff[coffset].im = 0; - for (n = 1; n < seg->part_size; n++) { - coeff[coffset + n].re = block[2 * n] * scale; - coeff[coffset + n].im = block[2 * n + 1] * scale; - } - coeff[coffset + seg->part_size].re = block[1] * scale; - coeff[coffset + seg->part_size].im = 0; - - toffset += size; - } - - av_log(ctx, AV_LOG_DEBUG, "nb_partitions: %d\n", seg->nb_partitions); - av_log(ctx, AV_LOG_DEBUG, "partition size: %d\n", seg->part_size); - av_log(ctx, AV_LOG_DEBUG, "block size: %d\n", seg->block_size); - av_log(ctx, AV_LOG_DEBUG, "fft_length: %d\n", seg->fft_length); - av_log(ctx, AV_LOG_DEBUG, "coeff_size: %d\n", seg->coeff_size); - av_log(ctx, AV_LOG_DEBUG, "input_size: %d\n", seg->input_size); - av_log(ctx, AV_LOG_DEBUG, "input_offset: %d\n", seg->input_offset); - } + switch (s->format) { + case AV_SAMPLE_FMT_FLTP: + convert_channels_float(ctx, s); + break; + case AV_SAMPLE_FMT_DBLP: + convert_channels_double(ctx, s); + break; } s->have_coeffs = 1; @@ -715,9 +437,10 @@ static int activate(AVFilterContext *ctx) static int query_formats(AVFilterContext *ctx) { AudioFIRContext *s = ctx->priv; - static const enum AVSampleFormat sample_fmts[] = { - AV_SAMPLE_FMT_FLTP, - AV_SAMPLE_FMT_NONE + static const enum AVSampleFormat sample_fmts[3][3] = { + { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_DBLP, AV_SAMPLE_FMT_NONE }, + { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, + { AV_SAMPLE_FMT_DBLP, AV_SAMPLE_FMT_NONE }, }; static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_RGB0, @@ -745,7 +468,7 @@ static int query_formats(AVFilterContext *ctx) if ((ret = ff_channel_layouts_ref(layouts, &ctx->outputs[0]->incfg.channel_layouts)) < 0) return ret; - ret = ff_add_channel_layout(&mono, AV_CH_LAYOUT_MONO); + ret = ff_add_channel_layout(&mono, &(AVChannelLayout)AV_CHANNEL_LAYOUT_MONO); if (ret) return ret; for (int i = 1; i < ctx->nb_inputs; i++) { @@ -754,7 +477,7 @@ static int query_formats(AVFilterContext *ctx) } } - if ((ret = ff_set_common_formats_from_list(ctx, sample_fmts)) < 0) + if ((ret = ff_set_common_formats_from_list(ctx, sample_fmts[s->precision])) < 0) return ret; return ff_set_common_all_samplerates(ctx); @@ -764,16 +487,23 @@ static int config_output(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; AudioFIRContext *s = ctx->priv; + int ret; - s->one2many = ctx->inputs[1 + s->selir]->channels == 1; + s->one2many = ctx->inputs[1 + s->selir]->ch_layout.nb_channels == 1; outlink->sample_rate = ctx->inputs[0]->sample_rate; outlink->time_base = ctx->inputs[0]->time_base; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS outlink->channel_layout = ctx->inputs[0]->channel_layout; - outlink->channels = ctx->inputs[0]->channels; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + if ((ret = av_channel_layout_copy(&outlink->ch_layout, &ctx->inputs[0]->ch_layout)) < 0) + return ret; + outlink->ch_layout.nb_channels = ctx->inputs[0]->ch_layout.nb_channels; - s->nb_channels = outlink->channels; - s->nb_coef_channels = ctx->inputs[1 + s->selir]->channels; - s->pts = AV_NOPTS_VALUE; + s->nb_channels = outlink->ch_layout.nb_channels; + s->nb_coef_channels = ctx->inputs[1 + s->selir]->ch_layout.nb_channels; + s->format = outlink->format; return 0; } @@ -814,14 +544,6 @@ static int config_video(AVFilterLink *outlink) return 0; } -void ff_afir_init(AudioFIRDSPContext *dsp) -{ - dsp->fcmul_add = fcmul_add_c; - - if (ARCH_X86) - ff_afir_init_x86(dsp); -} - static av_cold int init(AVFilterContext *ctx) { AudioFIRContext *s = ctx->priv; @@ -932,6 +654,10 @@ static const AVOption afir_options[] = { { "maxp", "set max partition size", OFFSET(maxp), AV_OPT_TYPE_INT, {.i64=8192}, 8, 32768, AF }, { "nbirs", "set number of input IRs",OFFSET(nb_irs),AV_OPT_TYPE_INT, {.i64=1}, 1, 32, AF }, { "ir", "select IR", OFFSET(selir), AV_OPT_TYPE_INT, {.i64=0}, 0, 31, AFR }, + { "precision", "set processing precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, AF, "precision" }, + { "auto", "set auto processing precision", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "precision" }, + { "float", "set single-floating point processing precision", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "precision" }, + { "double","set double-floating point processing precision", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF, "precision" }, { NULL } }; diff --git a/libavfilter/af_afir.h b/libavfilter/af_afir.h index 4f4467584..e82fc5858 100644 --- a/libavfilter/af_afir.h +++ b/libavfilter/af_afir.h @@ -21,15 +21,12 @@ #ifndef AVFILTER_AFIR_H #define AVFILTER_AFIR_H -#include "libavutil/common.h" #include "libavutil/float_dsp.h" -#include "libavutil/opt.h" -#include "libavcodec/avfft.h" - -#include "audio.h" +#include "libavutil/frame.h" +#include "libavutil/rational.h" +#include "libavutil/tx.h" #include "avfilter.h" -#include "formats.h" -#include "internal.h" +#include "af_afirdsp.h" typedef struct AudioFIRSegment { int nb_partitions; @@ -43,21 +40,19 @@ typedef struct AudioFIRSegment { int *output_offset; int *part_index; - AVFrame *sum; - AVFrame *block; + AVFrame *sumin; + AVFrame *sumout; + AVFrame *blockin; + AVFrame *blockout; AVFrame *buffer; AVFrame *coeff; AVFrame *input; AVFrame *output; - RDFTContext **rdft, **irdft; + AVTXContext **tx, **itx; + av_tx_fn tx_fn, itx_fn; } AudioFIRSegment; -typedef struct AudioFIRDSPContext { - void (*fcmul_add)(float *sum, const float *t, const float *c, - ptrdiff_t len); -} AudioFIRDSPContext; - typedef struct AudioFIRContext { const AVClass *class; @@ -76,8 +71,10 @@ typedef struct AudioFIRContext { int maxp; int nb_irs; int selir; + int precision; + int format; - float gain; + double gain; int eof_coeffs[32]; int have_coeffs; @@ -97,10 +94,6 @@ typedef struct AudioFIRContext { AudioFIRDSPContext afirdsp; AVFloatDSPContext *fdsp; - } AudioFIRContext; -void ff_afir_init(AudioFIRDSPContext *s); -void ff_afir_init_x86(AudioFIRDSPContext *s); - #endif /* AVFILTER_AFIR_H */ diff --git a/libavfilter/af_afirdsp.h b/libavfilter/af_afirdsp.h new file mode 100644 index 000000000..420850139 --- /dev/null +++ b/libavfilter/af_afirdsp.h @@ -0,0 +1,82 @@ +/* + * 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 + */ + +#ifndef AVFILTER_AFIRDSP_H +#define AVFILTER_AFIRDSP_H + +#include + +#include "config.h" +#include "libavutil/attributes.h" + +typedef struct AudioFIRDSPContext { + void (*fcmul_add)(float *sum, const float *t, const float *c, + ptrdiff_t len); + void (*dcmul_add)(double *sum, const double *t, const double *c, + ptrdiff_t len); +} AudioFIRDSPContext; + +void ff_afir_init_x86(AudioFIRDSPContext *s); + +static void fcmul_add_c(float *sum, const float *t, const float *c, ptrdiff_t len) +{ + int n; + + for (n = 0; n < len; n++) { + const float cre = c[2 * n ]; + const float cim = c[2 * n + 1]; + const float tre = t[2 * n ]; + const float tim = t[2 * n + 1]; + + sum[2 * n ] += tre * cre - tim * cim; + sum[2 * n + 1] += tre * cim + tim * cre; + } + + sum[2 * n] += t[2 * n] * c[2 * n]; +} + +static void dcmul_add_c(double *sum, const double *t, const double *c, ptrdiff_t len) +{ + int n; + + for (n = 0; n < len; n++) { + const double cre = c[2 * n ]; + const double cim = c[2 * n + 1]; + const double tre = t[2 * n ]; + const double tim = t[2 * n + 1]; + + sum[2 * n ] += tre * cre - tim * cim; + sum[2 * n + 1] += tre * cim + tim * cre; + } + + sum[2 * n] += t[2 * n] * c[2 * n]; +} + +static av_unused void ff_afir_init(AudioFIRDSPContext *dsp) +{ + dsp->fcmul_add = fcmul_add_c; + dsp->dcmul_add = dcmul_add_c; + +#if ARCH_X86 + ff_afir_init_x86(dsp); +#endif +} + +#endif /* AVFILTER_AFIRDSP_H */ diff --git a/libavfilter/af_aformat.c b/libavfilter/af_aformat.c index ed3c75311..a14e4c124 100644 --- a/libavfilter/af_aformat.c +++ b/libavfilter/af_aformat.c @@ -62,19 +62,12 @@ AVFILTER_DEFINE_CLASS(aformat); #define PARSE_FORMATS(str, type, list, add_to_list, get_fmt, none, desc) \ do { \ - char *next, *cur = str, sep; \ + char *next, *cur = str; \ int ret; \ \ - if (str && strchr(str, ',')) { \ - av_log(ctx, AV_LOG_WARNING, "This syntax is deprecated, use '|' to "\ - "separate %s.\n", desc); \ - sep = ','; \ - } else \ - sep = '|'; \ - \ while (cur) { \ type fmt; \ - next = strchr(cur, sep); \ + next = strchr(cur, '|'); \ if (next) \ *next++ = 0; \ \ @@ -96,17 +89,59 @@ static int get_sample_rate(const char *samplerate) return FFMAX(ret, 0); } +static int parse_channel_layouts(AVFilterContext *ctx) +{ + AFormatContext *s = ctx->priv; + char *next, *cur = s->channel_layouts_str; + AVChannelLayout fmt = { 0 }; + int ret; + + while (cur) { + next = strchr(cur, '|'); + if (next) + *next++ = 0; + + ret = av_channel_layout_from_string(&fmt, cur); + if (ret < 0) { +#if FF_API_OLD_CHANNEL_LAYOUT + uint64_t mask; +FF_DISABLE_DEPRECATION_WARNINGS + mask = av_get_channel_layout(cur); + if (!mask) { +#endif + av_log(ctx, AV_LOG_ERROR, "Error parsing channel layout: %s.\n", cur); + return AVERROR(EINVAL); +#if FF_API_OLD_CHANNEL_LAYOUT + } +FF_ENABLE_DEPRECATION_WARNINGS + av_log(ctx, AV_LOG_WARNING, "Channel layout '%s' uses a deprecated syntax.\n", + cur); + av_channel_layout_from_mask(&fmt, mask); +#endif + } + ret = ff_add_channel_layout(&s->channel_layouts, &fmt); + av_channel_layout_uninit(&fmt); + if (ret < 0) + return ret; + + cur = next; + } + + return 0; +} + static av_cold int init(AVFilterContext *ctx) { AFormatContext *s = ctx->priv; + int ret; PARSE_FORMATS(s->formats_str, enum AVSampleFormat, s->formats, ff_add_format, av_get_sample_fmt, AV_SAMPLE_FMT_NONE, "sample format"); PARSE_FORMATS(s->sample_rates_str, int, s->sample_rates, ff_add_format, get_sample_rate, 0, "sample rate"); - PARSE_FORMATS(s->channel_layouts_str, uint64_t, s->channel_layouts, - ff_add_channel_layout, av_get_channel_layout, 0, - "channel layout"); + ret = parse_channel_layouts(ctx); + if (ret < 0) + return ret; return 0; } diff --git a/libavfilter/af_afreqshift.c b/libavfilter/af_afreqshift.c index 731e97afe..70bf8e419 100644 --- a/libavfilter/af_afreqshift.c +++ b/libavfilter/af_afreqshift.c @@ -290,8 +290,8 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo ThreadData *td = arg; AVFrame *out = td->out; AVFrame *in = td->in; - const int start = (in->channels * jobnr) / nb_jobs; - const int end = (in->channels * (jobnr+1)) / nb_jobs; + const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs; + const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; for (int ch = start; ch < end; ch++) s->filter_channel(ctx, ch, in, out); @@ -324,7 +324,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) td.in = in; td.out = out; ff_filter_execute(ctx, filter_channels, &td, NULL, - FFMIN(inlink->channels, ff_filter_get_nb_threads(ctx))); + FFMIN(inlink->ch_layout.nb_channels, ff_filter_get_nb_threads(ctx))); s->in_samples += in->nb_samples; diff --git a/libavfilter/af_afwtdn.c b/libavfilter/af_afwtdn.c index 09b504d63..cf41b6f4b 100644 --- a/libavfilter/af_afwtdn.c +++ b/libavfilter/af_afwtdn.c @@ -1037,14 +1037,14 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) s->padd_samples -= s->nb_samples - (in ? in->nb_samples: 0); if (in) av_samples_copy(new_in->extended_data, in->extended_data, 0, 0, - in->nb_samples, in->channels, in->format); + in->nb_samples, in->ch_layout.nb_channels, in->format); av_frame_free(&in); in = new_in; } td.in = in; td.out = out; - ff_filter_execute(ctx, s->filter_channel, &td, NULL, inlink->channels); + ff_filter_execute(ctx, s->filter_channel, &td, NULL, inlink->ch_layout.nb_channels); if (s->need_profile) s->got_profile = 1; @@ -1059,7 +1059,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) FF_FILTER_FORWARD_WANTED(outlink, inlink); return 0; } else if (s->drop_samples > 0) { - for (int ch = 0; ch < out->channels; ch++) { + for (int ch = 0; ch < out->ch_layout.nb_channels; ch++) { memmove(out->extended_data[ch], out->extended_data[ch] + s->drop_samples * sizeof(double), (in->nb_samples - s->drop_samples) * sizeof(double)); @@ -1164,7 +1164,7 @@ static int config_output(AVFilterLink *outlink) !s->new_stddev || !s->new_absmean) return AVERROR(ENOMEM); - s->channels = outlink->channels; + s->channels = outlink->ch_layout.nb_channels; s->overlap_length = max_left_ext(s->wavelet_length, s->levels); s->prev_length = s->overlap_length; s->drop_samples = s->overlap_length; diff --git a/libavfilter/af_agate.c b/libavfilter/af_agate.c index 682f17c7d..51bc8c04d 100644 --- a/libavfilter/af_agate.c +++ b/libavfilter/af_agate.c @@ -23,6 +23,8 @@ * Audio (Sidechain) Gate filter */ +#include "config_components.h" + #include "libavutil/audio_fifo.h" #include "libavutil/channel_layout.h" #include "libavutil/opt.h" @@ -150,19 +152,19 @@ static void gate(AudioGateContext *s, const double release_coeff = s->release_coeff; int n, c; - for (n = 0; n < nb_samples; n++, src += inlink->channels, dst += inlink->channels, scsrc += sclink->channels) { + for (n = 0; n < nb_samples; n++, src += inlink->ch_layout.nb_channels, dst += inlink->ch_layout.nb_channels, scsrc += sclink->ch_layout.nb_channels) { double abs_sample = fabs(scsrc[0] * level_sc), gain = 1.0; double factor; int detected; if (s->link == 1) { - for (c = 1; c < sclink->channels; c++) + for (c = 1; c < sclink->ch_layout.nb_channels; c++) abs_sample = FFMAX(fabs(scsrc[c] * level_sc), abs_sample); } else { - for (c = 1; c < sclink->channels; c++) + for (c = 1; c < sclink->ch_layout.nb_channels; c++) abs_sample += fabs(scsrc[c] * level_sc); - abs_sample /= sclink->channels; + abs_sample /= sclink->ch_layout.nb_channels; } if (s->detection) @@ -181,7 +183,7 @@ static void gate(AudioGateContext *s, s->range, s->mode); factor = ctx->is_disabled ? 1.f : level_in * gain * makeup; - for (c = 0; c < inlink->channels; c++) + for (c = 0; c < inlink->ch_layout.nb_channels; c++) dst[c] = src[c] * factor; } } @@ -344,8 +346,8 @@ static int scconfig_output(AVFilterLink *outlink) outlink->time_base = ctx->inputs[0]->time_base; - s->fifo[0] = av_audio_fifo_alloc(ctx->inputs[0]->format, ctx->inputs[0]->channels, 1024); - s->fifo[1] = av_audio_fifo_alloc(ctx->inputs[1]->format, ctx->inputs[1]->channels, 1024); + s->fifo[0] = av_audio_fifo_alloc(ctx->inputs[0]->format, ctx->inputs[0]->ch_layout.nb_channels, 1024); + s->fifo[1] = av_audio_fifo_alloc(ctx->inputs[1]->format, ctx->inputs[1]->ch_layout.nb_channels, 1024); if (!s->fifo[0] || !s->fifo[1]) return AVERROR(ENOMEM); diff --git a/libavfilter/af_aiir.c b/libavfilter/af_aiir.c index 8a4b4814f..3e7ec78b6 100644 --- a/libavfilter/af_aiir.c +++ b/libavfilter/af_aiir.c @@ -1263,35 +1263,35 @@ static int config_output(AVFilterLink *outlink) AVFilterLink *inlink = ctx->inputs[0]; int ch, ret, i; - s->channels = inlink->channels; + s->channels = inlink->ch_layout.nb_channels; s->iir = av_calloc(s->channels, sizeof(*s->iir)); if (!s->iir) return AVERROR(ENOMEM); - ret = read_gains(ctx, s->g_str, inlink->channels); + ret = read_gains(ctx, s->g_str, inlink->ch_layout.nb_channels); if (ret < 0) return ret; - ret = read_channels(ctx, inlink->channels, s->a_str, 0); + ret = read_channels(ctx, inlink->ch_layout.nb_channels, s->a_str, 0); if (ret < 0) return ret; - ret = read_channels(ctx, inlink->channels, s->b_str, 1); + ret = read_channels(ctx, inlink->ch_layout.nb_channels, s->b_str, 1); if (ret < 0) return ret; if (s->format == -1) { - convert_sf2tf(ctx, inlink->channels); + convert_sf2tf(ctx, inlink->ch_layout.nb_channels); s->format = 0; } else if (s->format == 2) { - convert_pr2zp(ctx, inlink->channels); + convert_pr2zp(ctx, inlink->ch_layout.nb_channels); } else if (s->format == 3) { - convert_pd2zp(ctx, inlink->channels); + convert_pd2zp(ctx, inlink->ch_layout.nb_channels); } else if (s->format == 4) { - convert_sp2zp(ctx, inlink->channels); + convert_sp2zp(ctx, inlink->ch_layout.nb_channels); } if (s->format > 0) { - check_stability(ctx, inlink->channels); + check_stability(ctx, inlink->ch_layout.nb_channels); } av_frame_free(&s->video); @@ -1309,7 +1309,7 @@ static int config_output(AVFilterLink *outlink) 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); + ret = convert_zp2tf(ctx, inlink->ch_layout.nb_channels); if (ret < 0) return ret; } else if (s->format == -2 && s->process > 0) { @@ -1322,21 +1322,21 @@ static int config_output(AVFilterLink *outlink) av_log(ctx, AV_LOG_ERROR, "Parallel processing is not implemented for transfer function.\n"); return AVERROR_PATCHWELCOME; } else if (s->format > 0 && s->process == 1) { - ret = decompose_zp2biquads(ctx, inlink->channels); + ret = decompose_zp2biquads(ctx, inlink->ch_layout.nb_channels); if (ret < 0) return ret; } else if (s->format > 0 && s->process == 2) { if (s->precision > 1) av_log(ctx, AV_LOG_WARNING, "Parallel processing is not recommended for fixed-point precisions.\n"); - ret = decompose_zp2biquads(ctx, inlink->channels); + ret = decompose_zp2biquads(ctx, inlink->ch_layout.nb_channels); if (ret < 0) return ret; - ret = convert_serial2parallel(ctx, inlink->channels); + ret = convert_serial2parallel(ctx, inlink->ch_layout.nb_channels); if (ret < 0) return ret; } - for (ch = 0; s->format == -2 && ch < inlink->channels; ch++) { + for (ch = 0; s->format == -2 && ch < inlink->ch_layout.nb_channels; ch++) { IIRChannel *iir = &s->iir[ch]; if (iir->nb_ab[0] != iir->nb_ab[1] + 1) { @@ -1345,7 +1345,7 @@ static int config_output(AVFilterLink *outlink) } } - for (ch = 0; s->format == 0 && ch < inlink->channels; ch++) { + for (ch = 0; s->format == 0 && ch < inlink->ch_layout.nb_channels; ch++) { IIRChannel *iir = &s->iir[ch]; for (i = 1; i < iir->nb_ab[0]; i++) { @@ -1401,9 +1401,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) td.in = in; td.out = out; - ff_filter_execute(ctx, s->iir_channel, &td, NULL, outlink->channels); + ff_filter_execute(ctx, s->iir_channel, &td, NULL, outlink->ch_layout.nb_channels); - for (ch = 0; ch < outlink->channels; ch++) { + for (ch = 0; ch < outlink->ch_layout.nb_channels; ch++) { 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); diff --git a/libavfilter/af_alimiter.c b/libavfilter/af_alimiter.c index 211941a51..622dc6632 100644 --- a/libavfilter/af_alimiter.c +++ b/libavfilter/af_alimiter.c @@ -26,6 +26,7 @@ #include "libavutil/channel_layout.h" #include "libavutil/common.h" +#include "libavutil/fifo.h" #include "libavutil/opt.h" #include "audio.h" @@ -33,6 +34,11 @@ #include "formats.h" #include "internal.h" +typedef struct MetaItem { + int64_t pts; + int nb_samples; +} MetaItem; + typedef struct AudioLimiterContext { const AVClass *class; @@ -55,6 +61,14 @@ typedef struct AudioLimiterContext { int *nextpos; double *nextdelta; + int in_trim; + int out_pad; + int64_t next_in_pts; + int64_t next_out_pts; + int latency; + + AVFifo *fifo; + double delta; int nextiter; int nextlen; @@ -73,6 +87,7 @@ static const AVOption alimiter_options[] = { { "asc", "enable asc", OFFSET(auto_release), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, AF }, { "asc_level", "set asc level", OFFSET(asc_coeff), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 1, AF }, { "level", "auto level", OFFSET(auto_level), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, AF }, + { "latency", "compensate delay", OFFSET(latency), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, AF }, { NULL } }; @@ -116,7 +131,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) AudioLimiterContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; const double *src = (const double *)in->data[0]; - const int channels = inlink->channels; + const int channels = inlink->ch_layout.nb_channels; const int buffer_size = s->buffer_size; double *dst, *buffer = s->buffer; const double release = s->release; @@ -129,6 +144,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) AVFrame *out; double *buf; int n, c, i; + int new_out_samples; + int64_t out_duration; + int64_t in_duration; + int64_t in_pts; + MetaItem meta; if (av_frame_is_writable(in)) { out = in; @@ -269,20 +289,77 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) dst += channels; } + in_duration = av_rescale_q(in->nb_samples, inlink->time_base, av_make_q(1, in->sample_rate)); + in_pts = in->pts; + meta = (MetaItem){ in->pts, in->nb_samples }; + av_fifo_write(s->fifo, &meta, 1); if (in != out) av_frame_free(&in); + new_out_samples = out->nb_samples; + if (s->in_trim > 0) { + int trim = FFMIN(new_out_samples, s->in_trim); + new_out_samples -= trim; + s->in_trim -= trim; + } + + if (new_out_samples <= 0) { + av_frame_free(&out); + return 0; + } else if (new_out_samples < out->nb_samples) { + int offset = out->nb_samples - new_out_samples; + memmove(out->extended_data[0], out->extended_data[0] + sizeof(double) * offset * out->ch_layout.nb_channels, + sizeof(double) * new_out_samples * out->ch_layout.nb_channels); + out->nb_samples = new_out_samples; + s->in_trim = 0; + } + + av_fifo_read(s->fifo, &meta, 1); + + out_duration = av_rescale_q(out->nb_samples, inlink->time_base, av_make_q(1, out->sample_rate)); + in_duration = av_rescale_q(meta.nb_samples, inlink->time_base, av_make_q(1, out->sample_rate)); + in_pts = meta.pts; + + if (s->next_out_pts != AV_NOPTS_VALUE && out->pts != s->next_out_pts && + s->next_in_pts != AV_NOPTS_VALUE && in_pts == s->next_in_pts) { + out->pts = s->next_out_pts; + } else { + out->pts = in_pts; + } + s->next_in_pts = in_pts + in_duration; + s->next_out_pts = out->pts + out_duration; + return ff_filter_frame(outlink, out); } +static int request_frame(AVFilterLink* outlink) +{ + AVFilterContext *ctx = outlink->src; + AudioLimiterContext *s = (AudioLimiterContext*)ctx->priv; + int ret; + + ret = ff_request_frame(ctx->inputs[0]); + + if (ret == AVERROR_EOF && s->out_pad > 0) { + AVFrame *frame = ff_get_audio_buffer(outlink, FFMIN(1024, s->out_pad)); + if (!frame) + return AVERROR(ENOMEM); + + s->out_pad -= frame->nb_samples; + frame->pts = s->next_in_pts; + return filter_frame(ctx->inputs[0], frame); + } + return ret; +} + static int config_input(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; AudioLimiterContext *s = ctx->priv; int obuffer_size; - obuffer_size = inlink->sample_rate * inlink->channels * 100 / 1000. + inlink->channels; - if (obuffer_size < inlink->channels) + obuffer_size = inlink->sample_rate * inlink->ch_layout.nb_channels * 100 / 1000. + inlink->ch_layout.nb_channels; + if (obuffer_size < inlink->ch_layout.nb_channels) return AVERROR(EINVAL); s->buffer = av_calloc(obuffer_size, sizeof(*s->buffer)); @@ -292,8 +369,17 @@ static int config_input(AVFilterLink *inlink) return AVERROR(ENOMEM); memset(s->nextpos, -1, obuffer_size * sizeof(*s->nextpos)); - s->buffer_size = inlink->sample_rate * s->attack * inlink->channels; - s->buffer_size -= s->buffer_size % inlink->channels; + s->buffer_size = inlink->sample_rate * s->attack * inlink->ch_layout.nb_channels; + s->buffer_size -= s->buffer_size % inlink->ch_layout.nb_channels; + if (s->latency) + s->in_trim = s->out_pad = s->buffer_size / inlink->ch_layout.nb_channels - 1; + s->next_out_pts = AV_NOPTS_VALUE; + s->next_in_pts = AV_NOPTS_VALUE; + + s->fifo = av_fifo_alloc2(8, sizeof(MetaItem), AV_FIFO_FLAG_AUTO_GROW); + if (!s->fifo) { + return AVERROR(ENOMEM); + } if (s->buffer_size <= 0) { av_log(ctx, AV_LOG_ERROR, "Attack is too small.\n"); @@ -310,6 +396,8 @@ static av_cold void uninit(AVFilterContext *ctx) av_freep(&s->buffer); av_freep(&s->nextdelta); av_freep(&s->nextpos); + + av_fifo_freep2(&s->fifo); } static const AVFilterPad alimiter_inputs[] = { @@ -325,6 +413,7 @@ static const AVFilterPad alimiter_outputs[] = { { .name = "default", .type = AVMEDIA_TYPE_AUDIO, + .request_frame = request_frame, }, }; diff --git a/libavfilter/af_amerge.c b/libavfilter/af_amerge.c index 9109af22c..8bcc0ac5b 100644 --- a/libavfilter/af_amerge.c +++ b/libavfilter/af_amerge.c @@ -73,7 +73,8 @@ static int query_formats(AVFilterContext *ctx) AV_SAMPLE_FMT_NONE }; AMergeContext *s = ctx->priv; - int64_t inlayout[SWR_CH_MAX], outlayout = 0; + AVChannelLayout *inlayout[SWR_CH_MAX] = { NULL }, outlayout = { 0 }; + uint64_t outmask = 0; AVFilterChannelLayouts *layouts; int i, ret, overlap = 0, nb_ch = 0; @@ -84,20 +85,21 @@ static int query_formats(AVFilterContext *ctx) "No channel layout for input %d\n", i + 1); return AVERROR(EAGAIN); } - inlayout[i] = ctx->inputs[i]->incfg.channel_layouts->channel_layouts[0]; + inlayout[i] = &ctx->inputs[i]->incfg.channel_layouts->channel_layouts[0]; if (ctx->inputs[i]->incfg.channel_layouts->nb_channel_layouts > 1) { char buf[256]; - av_get_channel_layout_string(buf, sizeof(buf), 0, inlayout[i]); + av_channel_layout_describe(inlayout[i], buf, sizeof(buf)); av_log(ctx, AV_LOG_INFO, "Using \"%s\" for input %d\n", buf, i + 1); } s->in[i].nb_ch = FF_LAYOUT2COUNT(inlayout[i]); if (s->in[i].nb_ch) { overlap++; } else { - s->in[i].nb_ch = av_get_channel_layout_nb_channels(inlayout[i]); - if (outlayout & inlayout[i]) + s->in[i].nb_ch = inlayout[i]->nb_channels; + if (av_channel_layout_subset(inlayout[i], outmask)) overlap++; - outlayout |= inlayout[i]; + outmask |= inlayout[i]->order == AV_CHANNEL_ORDER_NATIVE ? + inlayout[i]->u.mask : 0; } nb_ch += s->in[i].nb_ch; } @@ -111,19 +113,20 @@ static int query_formats(AVFilterContext *ctx) "output layout will be determined by the number of distinct input channels\n"); for (i = 0; i < nb_ch; i++) s->route[i] = i; - outlayout = av_get_default_channel_layout(nb_ch); - if (!outlayout && nb_ch) - outlayout = 0xFFFFFFFFFFFFFFFFULL >> (64 - nb_ch); + av_channel_layout_default(&outlayout, nb_ch); + if (!KNOWN(&outlayout) && nb_ch) + av_channel_layout_from_mask(&outlayout, 0xFFFFFFFFFFFFFFFFULL >> (64 - nb_ch)); } else { int *route[SWR_CH_MAX]; int c, out_ch_number = 0; + av_channel_layout_from_mask(&outlayout, outmask); route[0] = s->route; for (i = 1; i < s->nb_inputs; i++) route[i] = route[i - 1] + s->in[i - 1].nb_ch; for (c = 0; c < 64; c++) for (i = 0; i < s->nb_inputs; i++) - if ((inlayout[i] >> c) & 1) + if (av_channel_layout_index_from_channel(inlayout[i], c) >= 0) *(route[i]++) = out_ch_number++; } if ((ret = ff_set_common_formats_from_list(ctx, packed_sample_fmts)) < 0) @@ -136,7 +139,7 @@ static int query_formats(AVFilterContext *ctx) return ret; } layouts = NULL; - if ((ret = ff_add_channel_layout(&layouts, outlayout)) < 0) + if ((ret = ff_add_channel_layout(&layouts, &outlayout)) < 0) return ret; if ((ret = ff_channel_layouts_ref(layouts, &ctx->outputs[0]->incfg.channel_layouts)) < 0) return ret; @@ -149,6 +152,7 @@ static int config_output(AVFilterLink *outlink) AVFilterContext *ctx = outlink->src; AMergeContext *s = ctx->priv; AVBPrint bp; + char buf[128]; int i; s->bps = av_get_bytes_per_sample(ctx->outputs[0]->format); @@ -157,10 +161,12 @@ static int config_output(AVFilterLink *outlink) av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC); for (i = 0; i < s->nb_inputs; i++) { av_bprintf(&bp, "%sin%d:", i ? " + " : "", i); - av_bprint_channel_layout(&bp, -1, ctx->inputs[i]->channel_layout); + av_channel_layout_describe(&ctx->inputs[i]->ch_layout, buf, sizeof(buf)); + av_bprintf(&bp, "%s", buf); } av_bprintf(&bp, " -> out:"); - av_bprint_channel_layout(&bp, -1, ctx->outputs[0]->channel_layout); + av_channel_layout_describe(&ctx->outputs[0]->ch_layout, buf, sizeof(buf)); + av_bprintf(&bp, "%s", buf); av_log(ctx, AV_LOG_VERBOSE, "%s\n", bp.str); return 0; @@ -237,8 +243,14 @@ static int try_push_frame(AVFilterContext *ctx, int nb_samples) outbuf->pts = inbuf[0]->pts; outbuf->nb_samples = nb_samples; + if ((ret = av_channel_layout_copy(&outbuf->ch_layout, &outlink->ch_layout)) < 0) + return ret; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS outbuf->channel_layout = outlink->channel_layout; - outbuf->channels = outlink->channels; + outbuf->channels = outlink->ch_layout.nb_channels; +FF_ENABLE_DEPRECATION_WARNINGS +#endif while (nb_samples) { /* Unroll the most common sample formats: speed +~350% for the loop, diff --git a/libavfilter/af_amix.c b/libavfilter/af_amix.c index 3f51d43ac..d7e00ab1f 100644 --- a/libavfilter/af_amix.c +++ b/libavfilter/af_amix.c @@ -261,7 +261,7 @@ static int config_output(AVFilterLink *outlink) if (!s->fifos) return AVERROR(ENOMEM); - s->nb_channels = outlink->channels; + s->nb_channels = outlink->ch_layout.nb_channels; for (i = 0; i < s->nb_inputs; i++) { s->fifos[i] = av_audio_fifo_alloc(outlink->format, s->nb_channels, 1024); if (!s->fifos[i]) @@ -282,7 +282,7 @@ static int config_output(AVFilterLink *outlink) s->scale_norm[i] = s->weight_sum / FFABS(s->weights[i]); calculate_scales(s, 0); - av_get_channel_layout_string(buf, sizeof(buf), -1, outlink->channel_layout); + av_channel_layout_describe(&outlink->ch_layout, buf, sizeof(buf)); av_log(ctx, AV_LOG_VERBOSE, "inputs:%d fmt:%s srate:%d cl:%s\n", s->nb_inputs, diff --git a/libavfilter/af_amultiply.c b/libavfilter/af_amultiply.c index 5de711bad..97728954a 100644 --- a/libavfilter/af_amultiply.c +++ b/libavfilter/af_amultiply.c @@ -128,8 +128,8 @@ static int config_output(AVFilterLink *outlink) AudioMultiplyContext *s = ctx->priv; AVFilterLink *inlink = ctx->inputs[0]; - s->channels = inlink->channels; - s->planes = av_sample_fmt_is_planar(inlink->format) ? inlink->channels : 1; + s->channels = inlink->ch_layout.nb_channels; + s->planes = av_sample_fmt_is_planar(inlink->format) ? inlink->ch_layout.nb_channels : 1; s->samples_align = 16; return 0; diff --git a/libavfilter/af_anequalizer.c b/libavfilter/af_anequalizer.c index 57a9b7634..c7b9a83d9 100644 --- a/libavfilter/af_anequalizer.c +++ b/libavfilter/af_anequalizer.c @@ -103,7 +103,7 @@ static void draw_curves(AVFilterContext *ctx, AVFilterLink *inlink, AVFrame *out memset(out->data[0], 0, s->h * out->linesize[0]); - for (ch = 0; ch < inlink->channels; ch++) { + for (ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { uint8_t fg[4] = { 0xff, 0xff, 0xff, 0xff }; int prev_v = -1; double f; @@ -577,8 +577,8 @@ static int config_input(AVFilterLink *inlink) if (!args) return AVERROR(ENOMEM); - s->nb_allocated = 32 * inlink->channels; - s->filters = av_calloc(inlink->channels, 32 * sizeof(*s->filters)); + s->nb_allocated = 32 * inlink->ch_layout.nb_channels; + s->filters = av_calloc(inlink->ch_layout.nb_channels, 32 * sizeof(*s->filters)); if (!s->filters) { s->nb_allocated = 0; av_free(args); @@ -610,7 +610,7 @@ static int config_input(AVFilterLink *inlink) s->filters[s->nb_filters].ignore = 1; if (s->filters[s->nb_filters].channel < 0 || - s->filters[s->nb_filters].channel >= inlink->channels) + s->filters[s->nb_filters].channel >= inlink->ch_layout.nb_channels) s->filters[s->nb_filters].ignore = 1; s->filters[s->nb_filters].type = av_clip(s->filters[s->nb_filters].type, 0, NB_TYPES - 1); @@ -698,8 +698,8 @@ static int filter_channels(AVFilterContext *ctx, void *arg, { AudioNEqualizerContext *s = ctx->priv; AVFrame *buf = arg; - const int start = (buf->channels * jobnr) / nb_jobs; - const int end = (buf->channels * (jobnr+1)) / nb_jobs; + const int start = (buf->ch_layout.nb_channels * jobnr) / nb_jobs; + const int end = (buf->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; for (int i = 0; i < s->nb_filters; i++) { EqualizatorFilter *f = &s->filters[i]; @@ -731,7 +731,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf) if (!ctx->is_disabled) ff_filter_execute(ctx, filter_channels, buf, NULL, - FFMIN(inlink->channels, ff_filter_get_nb_threads(ctx))); + FFMIN(inlink->ch_layout.nb_channels, ff_filter_get_nb_threads(ctx))); if (s->draw_curves) { AVFrame *clone; diff --git a/libavfilter/af_anlmdn.c b/libavfilter/af_anlmdn.c index 141e5f398..8f01c5f8a 100644 --- a/libavfilter/af_anlmdn.c +++ b/libavfilter/af_anlmdn.c @@ -21,20 +21,18 @@ #include #include "libavutil/avassert.h" -#include "libavutil/audio_fifo.h" #include "libavutil/avstring.h" #include "libavutil/opt.h" #include "avfilter.h" #include "audio.h" #include "formats.h" +#include "filters.h" #include "af_anlmdndsp.h" #define WEIGHT_LUT_NBITS 20 #define WEIGHT_LUT_SIZE (1<compute_distance_ssd = compute_distance_ssd_c; dsp->compute_cache = compute_cache_c; - if (ARCH_X86) - ff_anlmdn_init_x86(dsp); +#if ARCH_X86 + ff_anlmdn_init_x86(dsp); +#endif } static int config_filter(AVFilterContext *ctx) @@ -127,7 +128,6 @@ static int config_filter(AVFilterContext *ctx) AudioNLMeansContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; int newK, newS, newH, newN; - AVFrame *new_in, *new_cache; newK = av_rescale(s->pd, outlink->sample_rate, AV_TIME_BASE); newS = av_rescale(s->rd, outlink->sample_rate, AV_TIME_BASE); @@ -138,8 +138,11 @@ static int config_filter(AVFilterContext *ctx) av_log(ctx, AV_LOG_DEBUG, "K:%d S:%d H:%d N:%d\n", newK, newS, newH, newN); if (!s->cache || s->cache->nb_samples < newS * 2) { - new_cache = ff_get_audio_buffer(outlink, newS * 2); + AVFrame *new_cache = ff_get_audio_buffer(outlink, newS * 2); if (new_cache) { + if (s->cache) + av_samples_copy(new_cache->extended_data, s->cache->extended_data, 0, 0, + s->cache->nb_samples, new_cache->ch_layout.nb_channels, new_cache->format); av_frame_free(&s->cache); s->cache = new_cache; } else { @@ -149,6 +152,21 @@ static int config_filter(AVFilterContext *ctx) if (!s->cache) return AVERROR(ENOMEM); + if (!s->window || s->window->nb_samples < newN) { + AVFrame *new_window = ff_get_audio_buffer(outlink, newN); + if (new_window) { + if (s->window) + av_samples_copy(new_window->extended_data, s->window->extended_data, 0, 0, + s->window->nb_samples, new_window->ch_layout.nb_channels, new_window->format); + av_frame_free(&s->window); + s->window = new_window; + } else { + return AVERROR(ENOMEM); + } + } + if (!s->window) + return AVERROR(ENOMEM); + s->pdiff_lut_scale = 1.f / s->m * WEIGHT_LUT_SIZE; for (int i = 0; i < WEIGHT_LUT_SIZE; i++) { float w = -i / s->pdiff_lut_scale; @@ -156,18 +174,6 @@ static int config_filter(AVFilterContext *ctx) s->weight_lut[i] = expf(w); } - if (!s->in || s->in->nb_samples < newN) { - new_in = ff_get_audio_buffer(outlink, newN); - if (new_in) { - av_frame_free(&s->in); - s->in = new_in; - } else { - return AVERROR(ENOMEM); - } - } - if (!s->in) - return AVERROR(ENOMEM); - s->K = newK; s->S = newS; s->H = newH; @@ -182,21 +188,10 @@ static int config_output(AVFilterLink *outlink) AudioNLMeansContext *s = ctx->priv; int ret; - s->eof_left = -1; - s->pts = AV_NOPTS_VALUE; - ret = config_filter(ctx); if (ret < 0) return ret; - s->fifo = av_audio_fifo_alloc(outlink->format, outlink->channels, s->N); - if (!s->fifo) - return AVERROR(ENOMEM); - - ret = av_audio_fifo_write(s->fifo, (void **)s->in->extended_data, s->K + s->S); - if (ret < 0) - return ret; - ff_anlmdn_init(&s->dsp); return 0; @@ -208,14 +203,25 @@ static int filter_channel(AVFilterContext *ctx, void *arg, int ch, int nb_jobs) AVFrame *out = arg; const int S = s->S; const int K = s->K; + const int N = s->N; + const int H = s->H; const int om = s->om; - const float *f = (const float *)(s->in->extended_data[ch]) + K; + const float *f = (const float *)(s->window->extended_data[ch]) + K; float *cache = (float *)s->cache->extended_data[ch]; const float sw = (65536.f / (4 * K + 2)) / sqrtf(s->a); - float *dst = (float *)out->extended_data[ch] + s->offset; - const float smooth = s->m; + float *dst = (float *)out->extended_data[ch]; + const float *const weight_lut = s->weight_lut; + const float pdiff_lut_scale = s->pdiff_lut_scale; + const float smooth = fminf(s->m, WEIGHT_LUT_SIZE / pdiff_lut_scale); + const int offset = N - H; + float *src = (float *)s->window->extended_data[ch]; + const AVFrame *const in = s->in; - for (int i = S; i < s->H + S; i++) { + memmove(src, &src[H], offset * sizeof(float)); + memcpy(&src[offset], in->extended_data[ch], in->nb_samples * sizeof(float)); + memset(&src[offset + in->nb_samples], 0, (H - in->nb_samples) * sizeof(float)); + + for (int i = S; i < H + S; i++) { float P = 0.f, Q = 0.f; int v = 0; @@ -231,26 +237,24 @@ static int filter_channel(AVFilterContext *ctx, void *arg, int ch, int nb_jobs) } for (int j = 0; j < 2 * S && !ctx->is_disabled; j++) { - const float distance = cache[j]; + float distance = cache[j]; unsigned weight_lut_idx; float w; - if (distance < 0.f) { - cache[j] = 0.f; - continue; - } + if (distance < 0.f) + cache[j] = distance = 0.f; w = distance * sw; if (w >= smooth) continue; - weight_lut_idx = w * s->pdiff_lut_scale; + weight_lut_idx = w * pdiff_lut_scale; av_assert2(weight_lut_idx < WEIGHT_LUT_SIZE); - w = s->weight_lut[weight_lut_idx]; + w = weight_lut[weight_lut_idx]; P += w * f[i - S + j + (j >= S)]; Q += w; } P += f[i]; - Q += 1; + Q += 1.f; switch (om) { case IN_MODE: dst[i - S] = f[i]; break; @@ -267,77 +271,56 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; AudioNLMeansContext *s = ctx->priv; - AVFrame *out = NULL; - int available, wanted, ret; + AVFrame *out; - if (s->pts == AV_NOPTS_VALUE) - s->pts = in->pts; - - ret = av_audio_fifo_write(s->fifo, (void **)in->extended_data, - in->nb_samples); - av_frame_free(&in); - - s->offset = 0; - available = av_audio_fifo_size(s->fifo); - wanted = (available / s->H) * s->H; - - if (wanted >= s->H && available >= s->N) { - out = ff_get_audio_buffer(outlink, wanted); - if (!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); - } - - while (available >= s->N) { - ret = av_audio_fifo_peek(s->fifo, (void **)s->in->extended_data, s->N); - if (ret < 0) - break; - - ff_filter_execute(ctx, filter_channel, out, NULL, inlink->channels); - - av_audio_fifo_drain(s->fifo, s->H); - - s->offset += s->H; - available -= s->H; - } - - if (out) { - out->pts = s->pts; - out->nb_samples = s->offset; - if (s->eof_left >= 0) { - out->nb_samples = FFMIN(s->eof_left, s->offset); - s->eof_left -= out->nb_samples; } - s->pts += av_rescale_q(s->offset, (AVRational){1, outlink->sample_rate}, outlink->time_base); - return ff_filter_frame(outlink, out); + out->pts = in->pts; } - return ret; + s->in = in; + ff_filter_execute(ctx, filter_channel, out, NULL, inlink->ch_layout.nb_channels); + + if (out != in) + av_frame_free(&in); + return ff_filter_frame(outlink, out); } -static int request_frame(AVFilterLink *outlink) +static int activate(AVFilterContext *ctx) { - AVFilterContext *ctx = outlink->src; + AVFilterLink *inlink = ctx->inputs[0]; + AVFilterLink *outlink = ctx->outputs[0]; AudioNLMeansContext *s = ctx->priv; - int ret; + AVFrame *in = NULL; + int ret = 0, status; + int64_t pts; - ret = ff_request_frame(ctx->inputs[0]); + FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); - if (ret == AVERROR_EOF && s->eof_left != 0) { - AVFrame *in; + ret = ff_inlink_consume_samples(inlink, s->H, s->H, &in); + if (ret < 0) + return ret; - if (s->eof_left < 0) - s->eof_left = av_audio_fifo_size(s->fifo) - (s->S + s->K); - if (s->eof_left <= 0) - return AVERROR_EOF; - in = ff_get_audio_buffer(outlink, s->H); - if (!in) - return AVERROR(ENOMEM); - - return filter_frame(ctx->inputs[0], in); + if (ret > 0) { + return filter_frame(inlink, in); + } else if (ff_inlink_acknowledge_status(inlink, &status, &pts)) { + ff_outlink_set_status(outlink, status, pts); + return 0; + } else { + if (ff_inlink_queued_samples(inlink) >= s->H) { + ff_filter_set_ready(ctx, 10); + } else if (ff_outlink_frame_wanted(outlink)) { + ff_inlink_request_frame(inlink); + } + return 0; } - - return ret; } static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, @@ -349,27 +332,21 @@ static int process_command(AVFilterContext *ctx, const char *cmd, const char *ar if (ret < 0) return ret; - ret = config_filter(ctx); - if (ret < 0) - return ret; - - return 0; + return config_filter(ctx); } static av_cold void uninit(AVFilterContext *ctx) { AudioNLMeansContext *s = ctx->priv; - av_audio_fifo_free(s->fifo); - av_frame_free(&s->in); av_frame_free(&s->cache); + av_frame_free(&s->window); } static const AVFilterPad inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_AUDIO, - .filter_frame = filter_frame, }, }; @@ -378,7 +355,6 @@ static const AVFilterPad outputs[] = { .name = "default", .type = AVMEDIA_TYPE_AUDIO, .config_props = config_output, - .request_frame = request_frame, }, }; @@ -387,6 +363,7 @@ const AVFilter ff_af_anlmdn = { .description = NULL_IF_CONFIG_SMALL("Reduce broadband noise from stream using Non-Local Means."), .priv_size = sizeof(AudioNLMeansContext), .priv_class = &anlmdn_class, + .activate = activate, .uninit = uninit, FILTER_INPUTS(inputs), FILTER_OUTPUTS(outputs), diff --git a/libavfilter/af_anlms.c b/libavfilter/af_anlms.c index f20e3c0e8..6658cd294 100644 --- a/libavfilter/af_anlms.c +++ b/libavfilter/af_anlms.c @@ -156,8 +156,8 @@ static int process_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_j { AudioNLMSContext *s = ctx->priv; AVFrame *out = arg; - const int start = (out->channels * jobnr) / nb_jobs; - const int end = (out->channels * (jobnr+1)) / nb_jobs; + const int start = (out->ch_layout.nb_channels * jobnr) / nb_jobs; + const int end = (out->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; for (int c = start; c < end; c++) { const float *input = (const float *)s->frame[0]->extended_data[c]; @@ -168,8 +168,11 @@ static int process_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_j int *offset = (int *)s->offset->extended_data[c]; float *output = (float *)out->extended_data[c]; - for (int n = 0; n < out->nb_samples; n++) + for (int n = 0; n < out->nb_samples; n++) { output[n] = process_sample(s, input[n], desired[n], delay, coeffs, tmp, offset); + if (ctx->is_disabled) + output[n] = input[n]; + } } return 0; @@ -208,7 +211,7 @@ static int activate(AVFilterContext *ctx) } ff_filter_execute(ctx, process_channels, out, NULL, - FFMIN(ctx->outputs[0]->channels, ff_filter_get_nb_threads(ctx))); + FFMIN(ctx->outputs[0]->ch_layout.nb_channels, ff_filter_get_nb_threads(ctx))); out->pts = s->frame[0]->pts; @@ -314,7 +317,8 @@ const AVFilter ff_af_anlms = { FILTER_INPUTS(inputs), FILTER_OUTPUTS(outputs), FILTER_QUERY_FUNC(query_formats), - .flags = AVFILTER_FLAG_SLICE_THREADS, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | + AVFILTER_FLAG_SLICE_THREADS, .process_command = ff_filter_process_command, }; @@ -329,6 +333,7 @@ const AVFilter ff_af_anlmf = { FILTER_INPUTS(inputs), FILTER_OUTPUTS(outputs), FILTER_QUERY_FUNC(query_formats), - .flags = AVFILTER_FLAG_SLICE_THREADS, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | + AVFILTER_FLAG_SLICE_THREADS, .process_command = ff_filter_process_command, }; diff --git a/libavfilter/af_apad.c b/libavfilter/af_apad.c index ae73f0b6b..df17c9a53 100644 --- a/libavfilter/af_apad.c +++ b/libavfilter/af_apad.c @@ -121,7 +121,7 @@ static int request_frame(AVFilterLink *outlink) av_samples_set_silence(outsamplesref->extended_data, 0, n_out, - outsamplesref->channels, + outsamplesref->ch_layout.nb_channels, outsamplesref->format); outsamplesref->pts = s->next_pts; diff --git a/libavfilter/af_aphaser.c b/libavfilter/af_aphaser.c index 2d9580267..1f5dcb1f9 100644 --- a/libavfilter/af_aphaser.c +++ b/libavfilter/af_aphaser.c @@ -177,7 +177,7 @@ static int config_output(AVFilterLink *outlink) av_log(outlink->src, AV_LOG_ERROR, "delay is too small\n"); return AVERROR(EINVAL); } - s->delay_buffer = av_calloc(s->delay_buffer_length, sizeof(*s->delay_buffer) * inlink->channels); + s->delay_buffer = av_calloc(s->delay_buffer_length, sizeof(*s->delay_buffer) * inlink->ch_layout.nb_channels); s->modulation_buffer_length = inlink->sample_rate / s->speed + 0.5; s->modulation_buffer = av_malloc_array(s->modulation_buffer_length, sizeof(*s->modulation_buffer)); @@ -223,7 +223,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inbuf) } s->phaser(s, inbuf->extended_data, outbuf->extended_data, - outbuf->nb_samples, outbuf->channels); + outbuf->nb_samples, outbuf->ch_layout.nb_channels); if (inbuf != outbuf) av_frame_free(&inbuf); diff --git a/libavfilter/af_apsyclip.c b/libavfilter/af_apsyclip.c index dc3a8e97e..b739422e8 100644 --- a/libavfilter/af_apsyclip.c +++ b/libavfilter/af_apsyclip.c @@ -87,7 +87,7 @@ static void generate_hann_window(float *window, float *inv_window, int size) window[i] = value; // 1/window to calculate unwindowed peak. - inv_window[i] = value > 0.01f ? 1.f / value : 0.f; + inv_window[i] = value > 0.1f ? 1.f / value : 0.f; } } @@ -186,7 +186,7 @@ static int config_input(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; AudioPsyClipContext *s = ctx->priv; - static const int points[][2] = { {0,14}, {125,14}, {250,16}, {500,18}, {1000,20}, {2000,20}, {4000,20}, {8000,15}, {16000,5}, {20000,-10} }; + static const int points[][2] = { {0,14}, {125,14}, {250,16}, {500,18}, {1000,20}, {2000,20}, {4000,20}, {8000,17}, {16000,14}, {20000,-10} }; static const int num_points = 10; float scale; int ret; @@ -244,7 +244,7 @@ static int config_input(AVFilterLink *inlink) generate_spread_table(s); - s->channels = inlink->channels; + s->channels = inlink->ch_layout.nb_channels; s->tx_ctx = av_calloc(s->channels, sizeof(*s->tx_ctx)); s->itx_ctx = av_calloc(s->channels, sizeof(*s->itx_ctx)); @@ -292,10 +292,9 @@ static void calculate_mask_curve(AudioPsyClipContext *s, if (i == 0) { magnitude = FFABS(spectrum[0]); } else if (i == s->fft_size / 2) { - magnitude = FFABS(spectrum[1]); + magnitude = FFABS(spectrum[s->fft_size]); } else { - // although the negative frequencies are omitted because they are redundant, - // the magnitude of the positive frequencies are not doubled. + // Because the input signal is real, the + and - frequencies are redundant. // Multiply the magnitude by 2 to simulate adding up the + and - frequencies. magnitude = hypotf(spectrum[2 * i], spectrum[2 * i + 1]) * 2; } @@ -315,10 +314,9 @@ static void calculate_mask_curve(AudioPsyClipContext *s, for (int i = s->num_psy_bins; i < s->fft_size / 2 + 1; i++) { float magnitude; if (i == s->fft_size / 2) { - magnitude = FFABS(spectrum[1]); + magnitude = FFABS(spectrum[s->fft_size]); } else { - // although the negative frequencies are omitted because they are redundant, - // the magnitude of the positive frequencies are not doubled. + // Because the input signal is real, the + and - frequencies are redundant. // Multiply the magnitude by 2 to simulate adding up the + and - frequencies. magnitude = hypotf(spectrum[2 * i], spectrum[2 * i + 1]) * 2; } @@ -360,19 +358,20 @@ static void limit_clip_spectrum(AudioPsyClipContext *s, for (int i = 1; i < s->fft_size / 2; i++) { float real = clip_spectrum[i * 2]; float imag = clip_spectrum[i * 2 + 1]; - // although the negative frequencies are omitted because they are redundant, - // the magnitude of the positive frequencies are not doubled. + // Because the input signal is real, the + and - frequencies are redundant. // Multiply the magnitude by 2 to simulate adding up the + and - frequencies. relative_distortion_level = hypotf(real, imag) * 2 / mask_curve[i]; if (relative_distortion_level > 1.0) { clip_spectrum[i * 2] /= relative_distortion_level; clip_spectrum[i * 2 + 1] /= relative_distortion_level; + clip_spectrum[s->fft_size * 2 - i * 2] /= relative_distortion_level; + clip_spectrum[s->fft_size * 2 - i * 2 + 1] /= relative_distortion_level; } } // bin N/2 - relative_distortion_level = FFABS(clip_spectrum[1]) / mask_curve[s->fft_size / 2]; + relative_distortion_level = FFABS(clip_spectrum[s->fft_size]) / mask_curve[s->fft_size / 2]; if (relative_distortion_level > 1.f) - clip_spectrum[1] /= relative_distortion_level; + clip_spectrum[s->fft_size] /= relative_distortion_level; } static void r2c(float *buffer, int size) @@ -533,8 +532,8 @@ static int psy_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { AudioPsyClipContext *s = ctx->priv; AVFrame *out = arg; - const int start = (out->channels * jobnr) / nb_jobs; - const int end = (out->channels * (jobnr+1)) / nb_jobs; + const int start = (out->ch_layout.nb_channels * jobnr) / nb_jobs; + const int end = (out->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; for (int ch = start; ch < end; ch++) psy_channel(ctx, s->in, out, ch); @@ -558,7 +557,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) s->in = in; ff_filter_execute(ctx, psy_channels, out, NULL, - FFMIN(outlink->channels, ff_filter_get_nb_threads(ctx))); + FFMIN(outlink->ch_layout.nb_channels, ff_filter_get_nb_threads(ctx))); out->pts = in->pts; out->nb_samples = in->nb_samples; diff --git a/libavfilter/af_apulsator.c b/libavfilter/af_apulsator.c index c2a8de0e0..d4d3c59c3 100644 --- a/libavfilter/af_apulsator.c +++ b/libavfilter/af_apulsator.c @@ -192,7 +192,7 @@ static int query_formats(AVFilterContext *ctx) if ((ret = ff_add_format (&formats, AV_SAMPLE_FMT_DBL )) < 0 || (ret = ff_set_common_formats (ctx , formats )) < 0 || - (ret = ff_add_channel_layout (&layout , AV_CH_LAYOUT_STEREO)) < 0 || + (ret = ff_add_channel_layout (&layout , &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO)) < 0 || (ret = ff_set_common_channel_layouts (ctx , layout )) < 0) return ret; diff --git a/libavfilter/af_aresample.c b/libavfilter/af_aresample.c index 6e1be5b7e..971c861d0 100644 --- a/libavfilter/af_aresample.c +++ b/libavfilter/af_aresample.c @@ -65,7 +65,8 @@ static int query_formats(AVFilterContext *ctx) { AResampleContext *aresample = ctx->priv; enum AVSampleFormat out_format; - int64_t out_rate, out_layout; + AVChannelLayout out_layout = { 0 }; + int64_t out_rate; AVFilterLink *inlink = ctx->inputs[0]; AVFilterLink *outlink = ctx->outputs[0]; @@ -79,7 +80,6 @@ static int query_formats(AVFilterContext *ctx) av_opt_set_int(aresample->swr, "osr", aresample->sample_rate_arg, 0); av_opt_get_sample_fmt(aresample->swr, "osf", 0, &out_format); av_opt_get_int(aresample->swr, "osr", 0, &out_rate); - av_opt_get_int(aresample->swr, "ocl", 0, &out_layout); in_formats = ff_all_formats(AVMEDIA_TYPE_AUDIO); if ((ret = ff_formats_ref(in_formats, &inlink->outcfg.formats)) < 0) @@ -111,11 +111,13 @@ static int query_formats(AVFilterContext *ctx) if ((ret = ff_formats_ref(out_formats, &outlink->incfg.formats)) < 0) return ret; - if(out_layout) { - int64_t layout_list[] = { out_layout, -1 }; - out_layouts = ff_make_format64_list(layout_list); + av_opt_get_chlayout(aresample->swr, "ochl", 0, &out_layout); + if (av_channel_layout_check(&out_layout)) { + const AVChannelLayout layout_list[] = { out_layout, { 0 } }; + out_layouts = ff_make_channel_layout_list(layout_list); } else out_layouts = ff_all_channel_counts(); + av_channel_layout_uninit(&out_layout); return ff_channel_layouts_ref(out_layouts, &outlink->incfg.channel_layouts); } @@ -127,42 +129,41 @@ static int config_output(AVFilterLink *outlink) AVFilterContext *ctx = outlink->src; AVFilterLink *inlink = ctx->inputs[0]; AResampleContext *aresample = ctx->priv; - int64_t out_rate, out_layout; + AVChannelLayout out_layout = { 0 }; + int64_t out_rate; enum AVSampleFormat out_format; char inchl_buf[128], outchl_buf[128]; - aresample->swr = swr_alloc_set_opts(aresample->swr, - outlink->channel_layout, outlink->format, outlink->sample_rate, - inlink->channel_layout, inlink->format, inlink->sample_rate, - 0, ctx); - if (!aresample->swr) - return AVERROR(ENOMEM); - if (!inlink->channel_layout) - av_opt_set_int(aresample->swr, "ich", inlink->channels, 0); - if (!outlink->channel_layout) - av_opt_set_int(aresample->swr, "och", outlink->channels, 0); + ret = swr_alloc_set_opts2(&aresample->swr, + &outlink->ch_layout, outlink->format, outlink->sample_rate, + &inlink->ch_layout, inlink->format, inlink->sample_rate, + 0, ctx); + if (ret < 0) + return ret; ret = swr_init(aresample->swr); if (ret < 0) return ret; av_opt_get_int(aresample->swr, "osr", 0, &out_rate); - av_opt_get_int(aresample->swr, "ocl", 0, &out_layout); + av_opt_get_chlayout(aresample->swr, "ochl", 0, &out_layout); av_opt_get_sample_fmt(aresample->swr, "osf", 0, &out_format); outlink->time_base = (AVRational) {1, out_rate}; av_assert0(outlink->sample_rate == out_rate); - av_assert0(outlink->channel_layout == out_layout || !outlink->channel_layout); + av_assert0(!av_channel_layout_compare(&outlink->ch_layout, &out_layout)); av_assert0(outlink->format == out_format); + av_channel_layout_uninit(&out_layout); + aresample->ratio = (double)outlink->sample_rate / inlink->sample_rate; - av_get_channel_layout_string(inchl_buf, sizeof(inchl_buf), inlink ->channels, inlink ->channel_layout); - av_get_channel_layout_string(outchl_buf, sizeof(outchl_buf), outlink->channels, outlink->channel_layout); + av_channel_layout_describe(&inlink ->ch_layout, inchl_buf, sizeof(inchl_buf)); + av_channel_layout_describe(&outlink->ch_layout, outchl_buf, sizeof(outchl_buf)); av_log(ctx, AV_LOG_VERBOSE, "ch:%d chl:%s fmt:%s r:%dHz -> ch:%d chl:%s fmt:%s r:%dHz\n", - inlink ->channels, inchl_buf, av_get_sample_fmt_name(inlink->format), inlink->sample_rate, - outlink->channels, outchl_buf, av_get_sample_fmt_name(outlink->format), outlink->sample_rate); + inlink ->ch_layout.nb_channels, inchl_buf, av_get_sample_fmt_name(inlink->format), inlink->sample_rate, + outlink->ch_layout.nb_channels, outchl_buf, av_get_sample_fmt_name(outlink->format), outlink->sample_rate); return 0; } @@ -189,8 +190,15 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamplesref) av_frame_copy_props(outsamplesref, insamplesref); outsamplesref->format = outlink->format; - outsamplesref->channels = outlink->channels; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + outsamplesref->channels = outlink->ch_layout.nb_channels; outsamplesref->channel_layout = outlink->channel_layout; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + ret = av_channel_layout_copy(&outsamplesref->ch_layout, &outlink->ch_layout); + if (ret < 0) + return ret; outsamplesref->sample_rate = outlink->sample_rate; if(insamplesref->pts != AV_NOPTS_VALUE) { diff --git a/libavfilter/af_arnndn.c b/libavfilter/af_arnndn.c index 3115c4ae0..5e3403ca6 100644 --- a/libavfilter/af_arnndn.c +++ b/libavfilter/af_arnndn.c @@ -353,7 +353,7 @@ static int config_input(AVFilterLink *inlink) AudioRNNContext *s = ctx->priv; int ret = 0; - s->channels = inlink->channels; + s->channels = inlink->ch_layout.nb_channels; if (!s->st) s->st = av_calloc(s->channels, sizeof(DenoiseState)); @@ -1413,8 +1413,8 @@ static int rnnoise_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_j ThreadData *td = arg; AVFrame *in = td->in; AVFrame *out = td->out; - const int start = (out->channels * jobnr) / nb_jobs; - const int end = (out->channels * (jobnr+1)) / nb_jobs; + const int start = (out->ch_layout.nb_channels * jobnr) / nb_jobs; + const int end = (out->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; for (int ch = start; ch < end; ch++) { rnnoise_channel(s, &s->st[ch], @@ -1442,7 +1442,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) td.in = in; td.out = out; ff_filter_execute(ctx, rnnoise_channels, &td, NULL, - FFMIN(outlink->channels, ff_filter_get_nb_threads(ctx))); + FFMIN(outlink->ch_layout.nb_channels, ff_filter_get_nb_threads(ctx))); av_frame_free(&in); return ff_filter_frame(outlink, out); @@ -1478,7 +1478,7 @@ static int open_model(AVFilterContext *ctx, RNNModel **model) if (!s->model_name) return AVERROR(EINVAL); - f = av_fopen_utf8(s->model_name, "r"); + f = avpriv_fopen_utf8(s->model_name, "r"); if (!f) { av_log(ctx, AV_LOG_ERROR, "Failed to open model file: %s\n", s->model_name); return AVERROR(EINVAL); diff --git a/libavfilter/af_asdr.c b/libavfilter/af_asdr.c index addfe5f15..a40246f28 100644 --- a/libavfilter/af_asdr.c +++ b/libavfilter/af_asdr.c @@ -41,7 +41,7 @@ static void sdr(AVFilterContext *ctx, const AVFrame *u, const AVFrame *v) { AudioSDRContext *s = ctx->priv; - for (int ch = 0; ch < u->channels; ch++) { + for (int ch = 0; ch < u->ch_layout.nb_channels; ch++) { const double *const us = (double *)u->extended_data[ch]; const double *const vs = (double *)v->extended_data[ch]; double sum_uv = s->sum_uv[ch]; @@ -117,10 +117,10 @@ static int config_output(AVFilterLink *outlink) s->pts = AV_NOPTS_VALUE; - s->channels = inlink->channels; + s->channels = inlink->ch_layout.nb_channels; - s->sum_u = av_calloc(outlink->channels, sizeof(*s->sum_u)); - s->sum_uv = av_calloc(outlink->channels, sizeof(*s->sum_uv)); + s->sum_u = av_calloc(outlink->ch_layout.nb_channels, sizeof(*s->sum_u)); + s->sum_uv = av_calloc(outlink->ch_layout.nb_channels, sizeof(*s->sum_uv)); if (!s->sum_u || !s->sum_uv) return AVERROR(ENOMEM); diff --git a/libavfilter/af_asetnsamples.c b/libavfilter/af_asetnsamples.c index 71788f2a7..74d3fde35 100644 --- a/libavfilter/af_asetnsamples.c +++ b/libavfilter/af_asetnsamples.c @@ -66,12 +66,8 @@ static int activate(AVFilterContext *ctx) return ret; if (ret > 0) { - if (!s->pad || frame->nb_samples == s->nb_out_samples) { - ret = ff_filter_frame(outlink, frame); - if (ff_inlink_queued_samples(inlink) >= s->nb_out_samples) - ff_filter_set_ready(ctx, 100); - return ret; - } + if (!s->pad || frame->nb_samples == s->nb_out_samples) + return ff_filter_frame(outlink, frame); pad_frame = ff_get_audio_buffer(outlink, s->nb_out_samples); if (!pad_frame) { @@ -87,15 +83,19 @@ static int activate(AVFilterContext *ctx) } av_samples_copy(pad_frame->extended_data, frame->extended_data, - 0, 0, frame->nb_samples, frame->channels, frame->format); + 0, 0, frame->nb_samples, frame->ch_layout.nb_channels, frame->format); av_samples_set_silence(pad_frame->extended_data, frame->nb_samples, - s->nb_out_samples - frame->nb_samples, frame->channels, + s->nb_out_samples - frame->nb_samples, frame->ch_layout.nb_channels, frame->format); av_frame_free(&frame); return ff_filter_frame(outlink, pad_frame); } FF_FILTER_FORWARD_STATUS(inlink, outlink); + if (ff_inlink_queued_samples(inlink) >= s->nb_out_samples) { + ff_filter_set_ready(ctx, 100); + return 0; + } FF_FILTER_FORWARD_WANTED(outlink, inlink); return FFERROR_NOT_READY; diff --git a/libavfilter/af_ashowinfo.c b/libavfilter/af_ashowinfo.c index c76756db6..36ba38b47 100644 --- a/libavfilter/af_ashowinfo.c +++ b/libavfilter/af_ashowinfo.c @@ -178,9 +178,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf) { AVFilterContext *ctx = inlink->dst; AShowInfoContext *s = ctx->priv; +#if FF_API_OLD_CHANNEL_LAYOUT + AVChannelLayout layout = { 0 }; +#endif char chlayout_str[128]; uint32_t checksum = 0; - int channels = inlink->channels; + int channels = inlink->ch_layout.nb_channels; int planar = av_sample_fmt_is_planar(buf->format); int block_align = av_get_bytes_per_sample(buf->format) * (planar ? 1 : channels); int data_size = buf->nb_samples * block_align; @@ -200,8 +203,14 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf) s->plane_checksums[0]; } - av_get_channel_layout_string(chlayout_str, sizeof(chlayout_str), buf->channels, - buf->channel_layout); +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + if (av_channel_layout_from_mask(&layout, buf->channel_layout)) { + av_channel_layout_describe(&layout, chlayout_str, sizeof(chlayout_str)); +FF_ENABLE_DEPRECATION_WARNINGS + } else if (buf->ch_layout.nb_channels) +#endif + av_channel_layout_describe(&buf->ch_layout, chlayout_str, sizeof(chlayout_str)); av_log(ctx, AV_LOG_INFO, "n:%"PRId64" pts:%s pts_time:%s pos:%"PRId64" " @@ -210,7 +219,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf) inlink->frame_count_out, av_ts2str(buf->pts), av_ts2timestr(buf->pts, &inlink->time_base), buf->pkt_pos, - av_get_sample_fmt_name(buf->format), buf->channels, chlayout_str, + av_get_sample_fmt_name(buf->format), buf->ch_layout.nb_channels, chlayout_str, buf->sample_rate, buf->nb_samples, checksum); diff --git a/libavfilter/af_asoftclip.c b/libavfilter/af_asoftclip.c index 6ffde4431..6212e1d6f 100644 --- a/libavfilter/af_asoftclip.c +++ b/libavfilter/af_asoftclip.c @@ -440,7 +440,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) } nb_samples = in->nb_samples; - channels = in->channels; + channels = in->ch_layout.nb_channels; td.in = in; td.out = out; diff --git a/libavfilter/af_aspectralstats.c b/libavfilter/af_aspectralstats.c index da418d22b..cac5d01bc 100644 --- a/libavfilter/af_aspectralstats.c +++ b/libavfilter/af_aspectralstats.c @@ -21,7 +21,6 @@ #include #include -#include "libavutil/audio_fifo.h" #include "libavutil/opt.h" #include "libavutil/tx.h" #include "audio.h" @@ -54,16 +53,14 @@ typedef struct AudioSpectralStatsContext { int nb_channels; int hop_size; ChannelSpectralStats *stats; - AVAudioFifo *fifo; float *window_func_lut; - int64_t pts; - int eof; av_tx_fn tx_fn; AVTXContext **fft; AVComplexFloat **fft_in; AVComplexFloat **fft_out; float **prev_magnitude; float **magnitude; + AVFrame *window; } AudioSpectralStatsContext; #define OFFSET(x) offsetof(AudioSpectralStatsContext, x) @@ -84,11 +81,7 @@ static int config_output(AVFilterLink *outlink) float overlap, scale; int ret; - s->nb_channels = outlink->channels; - s->fifo = av_audio_fifo_alloc(outlink->format, s->nb_channels, s->win_size); - if (!s->fifo) - return AVERROR(ENOMEM); - + s->nb_channels = outlink->ch_layout.nb_channels; s->window_func_lut = av_realloc_f(s->window_func_lut, s->win_size, sizeof(*s->window_func_lut)); if (!s->window_func_lut) @@ -147,6 +140,10 @@ static int config_output(AVFilterLink *outlink) return AVERROR(ENOMEM); } + s->window = ff_get_audio_buffer(outlink, s->win_size); + if (!s->window) + return AVERROR(ENOMEM); + return 0; } @@ -392,14 +389,15 @@ static float spectral_rolloff(const float *const spectral, int size, int max_fre static int filter_channel(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { AudioSpectralStatsContext *s = ctx->priv; + const float *window_func_lut = s->window_func_lut; AVFrame *in = arg; const int channels = s->nb_channels; - const int samples = in->nb_samples; const int start = (channels * jobnr) / nb_jobs; const int end = (channels * (jobnr+1)) / nb_jobs; + const int offset = s->win_size - s->hop_size; for (int ch = start; ch < end; ch++) { - const float *const src = (const float *const)in->extended_data[ch]; + float *window = (float *)s->window->extended_data[ch]; ChannelSpectralStats *stats = &s->stats[ch]; AVComplexFloat *fft_out = s->fft_out[ch]; AVComplexFloat *fft_in = s->fft_in[ch]; @@ -407,13 +405,12 @@ static int filter_channel(AVFilterContext *ctx, void *arg, int jobnr, int nb_job float *prev_magnitude = s->prev_magnitude[ch]; const float scale = 1.f / s->win_size; - for (int n = 0; n < samples; n++) { - fft_in[n].re = src[n] * s->window_func_lut[n]; - fft_in[n].im = 0; - } + memmove(window, &window[s->hop_size], offset * sizeof(float)); + memcpy(&window[offset], in->extended_data[ch], in->nb_samples * sizeof(float)); + memset(&window[offset + in->nb_samples], 0, (s->hop_size - in->nb_samples) * sizeof(float)); - for (int n = in->nb_samples; n < s->win_size; n++) { - fft_in[n].re = 0; + for (int n = 0; n < s->win_size; n++) { + fft_in[n].re = window[n] * window_func_lut[n]; fft_in[n].im = 0; } @@ -447,102 +444,71 @@ static int filter_channel(AVFilterContext *ctx, void *arg, int jobnr, int nb_job return 0; } -static int filter_frame(AVFilterLink *inlink) +static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; AudioSpectralStatsContext *s = ctx->priv; AVDictionary **metadata; - AVFrame *out, *in = NULL; - int ret = 0; + AVFrame *out; + int ret; - out = ff_get_audio_buffer(outlink, s->hop_size); - if (!out) { - ret = AVERROR(ENOMEM); - goto fail; - } - - if (!in) { - in = ff_get_audio_buffer(outlink, s->win_size); - if (!in) + 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); + } + ret = av_frame_copy_props(out, in); + if (ret < 0) + goto fail; + ret = av_frame_copy(out, in); + if (ret < 0) + goto fail; } - ret = av_audio_fifo_peek(s->fifo, (void **)in->extended_data, s->win_size); - if (ret < 0) - goto fail; - metadata = &out->metadata; ff_filter_execute(ctx, filter_channel, in, NULL, - FFMIN(inlink->channels, ff_filter_get_nb_threads(ctx))); + FFMIN(inlink->ch_layout.nb_channels, ff_filter_get_nb_threads(ctx))); set_metadata(s, metadata); - out->pts = s->pts; - s->pts += av_rescale_q(s->hop_size, (AVRational){1, outlink->sample_rate}, outlink->time_base); - - av_audio_fifo_read(s->fifo, (void **)out->extended_data, s->hop_size); - - av_frame_free(&in); + if (out != in) + av_frame_free(&in); return ff_filter_frame(outlink, out); fail: av_frame_free(&in); - return ret < 0 ? ret : 0; + av_frame_free(&out); + return ret; } static int activate(AVFilterContext *ctx) { - AVFilterLink *inlink = ctx->inputs[0]; - AVFilterLink *outlink = ctx->outputs[0]; AudioSpectralStatsContext *s = ctx->priv; - AVFrame *in = NULL; - int ret = 0, status; - int64_t pts; + AVFilterLink *outlink = ctx->outputs[0]; + AVFilterLink *inlink = ctx->inputs[0]; + AVFrame *in; + int ret; FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); - if (!s->eof && av_audio_fifo_size(s->fifo) < s->win_size) { - ret = ff_inlink_consume_frame(inlink, &in); - if (ret < 0) - return ret; - - if (ret > 0) { - 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; - } - } - - if ((av_audio_fifo_size(s->fifo) >= s->win_size) || - (av_audio_fifo_size(s->fifo) > 0 && s->eof)) { - ret = filter_frame(inlink); - if (av_audio_fifo_size(s->fifo) >= s->win_size) - ff_filter_set_ready(ctx, 100); + ret = ff_inlink_consume_samples(inlink, s->hop_size, s->hop_size, &in); + if (ret < 0) + return ret; + if (ret > 0) + ret = filter_frame(inlink, in); + if (ret < 0) return ret; - } - if (!s->eof && ff_inlink_acknowledge_status(inlink, &status, &pts)) { - if (status == AVERROR_EOF) { - s->eof = 1; - if (av_audio_fifo_size(s->fifo) >= 0) { - ff_filter_set_ready(ctx, 100); - return 0; - } - } - } - - if (s->eof && av_audio_fifo_size(s->fifo) <= 0) { - ff_outlink_set_status(outlink, AVERROR_EOF, s->pts); + if (ff_inlink_queued_samples(inlink) >= s->hop_size) { + ff_filter_set_ready(ctx, 10); return 0; } - if (!s->eof) - FF_FILTER_FORWARD_WANTED(outlink, inlink); + FF_FILTER_FORWARD_STATUS(inlink, outlink); + FF_FILTER_FORWARD_WANTED(outlink, inlink); return FFERROR_NOT_READY; } @@ -572,8 +538,7 @@ static av_cold void uninit(AVFilterContext *ctx) av_freep(&s->stats); av_freep(&s->window_func_lut); - av_audio_fifo_free(s->fifo); - s->fifo = NULL; + av_frame_free(&s->window); } static const AVFilterPad aspectralstats_inputs[] = { diff --git a/libavfilter/af_asr.c b/libavfilter/af_asr.c index 42250e79e..b402f5ff2 100644 --- a/libavfilter/af_asr.c +++ b/libavfilter/af_asr.c @@ -131,7 +131,7 @@ static int query_formats(AVFilterContext *ctx) if ((ret = ff_add_format (&formats, AV_SAMPLE_FMT_S16 )) < 0 || (ret = ff_set_common_formats (ctx , formats )) < 0 || - (ret = ff_add_channel_layout (&layout , AV_CH_LAYOUT_MONO )) < 0 || + (ret = ff_add_channel_layout (&layout , &(AVChannelLayout)AV_CHANNEL_LAYOUT_MONO )) < 0 || (ret = ff_set_common_channel_layouts (ctx , layout )) < 0 || (ret = ff_set_common_samplerates_from_list(ctx, sample_rates )) < 0) return ret; diff --git a/libavfilter/af_astats.c b/libavfilter/af_astats.c index 6c79257cb..d59640a3f 100644 --- a/libavfilter/af_astats.c +++ b/libavfilter/af_astats.c @@ -194,12 +194,12 @@ static int config_output(AVFilterLink *outlink) { AudioStatsContext *s = outlink->src->priv; - s->chstats = av_calloc(sizeof(*s->chstats), outlink->channels); + s->chstats = av_calloc(sizeof(*s->chstats), outlink->ch_layout.nb_channels); if (!s->chstats) return AVERROR(ENOMEM); s->tc_samples = FFMAX(s->time_constant * outlink->sample_rate + .5, 1); - s->nb_channels = outlink->channels; + s->nb_channels = outlink->ch_layout.nb_channels; for (int i = 0; i < s->nb_channels; i++) { ChannelStats *p = &s->chstats[i]; @@ -584,8 +584,8 @@ static int filter_channel(AVFilterContext *ctx, void *arg, int jobnr, int nb_job const uint8_t * const * const data = (const uint8_t * const *)buf->extended_data; const int channels = s->nb_channels; const int samples = buf->nb_samples; - const int start = (buf->channels * jobnr) / nb_jobs; - const int end = (buf->channels * (jobnr+1)) / nb_jobs; + const int start = (buf->ch_layout.nb_channels * jobnr) / nb_jobs; + const int end = (buf->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; switch (inlink->format) { case AV_SAMPLE_FMT_DBLP: @@ -638,7 +638,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf) } ff_filter_execute(ctx, filter_channel, buf, NULL, - FFMIN(inlink->channels, ff_filter_get_nb_threads(ctx))); + FFMIN(inlink->ch_layout.nb_channels, ff_filter_get_nb_threads(ctx))); if (s->metadata) set_metadata(s, metadata); diff --git a/libavfilter/af_asubboost.c b/libavfilter/af_asubboost.c index da3e68e84..29a1f66ce 100644 --- a/libavfilter/af_asubboost.c +++ b/libavfilter/af_asubboost.c @@ -29,6 +29,7 @@ typedef struct ASubBoostContext { double dry_gain; double wet_gain; double feedback; + double max_boost; double decay; double delay; double cutoff; @@ -37,6 +38,9 @@ typedef struct ASubBoostContext { double a0, a1, a2; double b0, b1, b2; + char *ch_layout_str; + AVChannelLayout ch_layout; + int *write_pos; int buffer_samples; @@ -75,8 +79,8 @@ static int config_input(AVFilterLink *inlink) ASubBoostContext *s = ctx->priv; s->buffer = ff_get_audio_buffer(inlink, inlink->sample_rate / 10); - s->w = ff_get_audio_buffer(inlink, 2); - s->write_pos = av_calloc(inlink->channels, sizeof(*s->write_pos)); + s->w = ff_get_audio_buffer(inlink, 3); + s->write_pos = av_calloc(inlink->ch_layout.nb_channels, sizeof(*s->write_pos)); if (!s->buffer || !s->w || !s->write_pos) return AVERROR(ENOMEM); @@ -97,13 +101,14 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo const double wet = ctx->is_disabled ? 1. : s->wet_gain; const double dry = ctx->is_disabled ? 1. : s->dry_gain; const double feedback = s->feedback, decay = s->decay; + const double max_boost = s->max_boost; const double b0 = s->b0; const double b1 = s->b1; const double b2 = s->b2; const double a1 = -s->a1; const double a2 = -s->a2; - const int start = (in->channels * jobnr) / nb_jobs; - const int end = (in->channels * (jobnr+1)) / nb_jobs; + const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs; + const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; const int buffer_samples = s->buffer_samples; for (int ch = start; ch < end; ch++) { @@ -112,16 +117,30 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo double *buffer = (double *)s->buffer->extended_data[ch]; double *w = (double *)s->w->extended_data[ch]; int write_pos = s->write_pos[ch]; + enum AVChannel channel = av_channel_layout_channel_from_index(&in->ch_layout, ch); + const int bypass = av_channel_layout_index_from_channel(&s->ch_layout, channel) < 0; + const double a = 0.00001; + const double b = 1. - a; + + if (bypass) { + if (in != out) + memcpy(out->extended_data[ch], in->extended_data[ch], + in->nb_samples * sizeof(double)); + continue; + } for (int n = 0; n < in->nb_samples; n++) { - double out_sample; + double out_sample, boost; out_sample = src[n] * b0 + w[0]; w[0] = b1 * src[n] + w[1] + a1 * out_sample; w[1] = b2 * src[n] + a2 * out_sample; buffer[write_pos] = buffer[write_pos] * decay + out_sample * feedback; - dst[n] = (src[n] * dry + buffer[write_pos] * mix) * wet; + boost = av_clipd((1. - (fabs(src[n] * dry))) / fabs(buffer[write_pos]), 0., max_boost); + w[2] = boost > w[2] ? w[2] * b + a * boost : w[2] * a + b * boost; + w[2] = av_clipd(w[2], 0., max_boost); + dst[n] = (src[n] * dry + w[2] * buffer[write_pos] * mix) * wet; if (++write_pos >= buffer_samples) write_pos = 0; @@ -136,9 +155,18 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; + ASubBoostContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; ThreadData td; AVFrame *out; + int ret; + + ret = av_channel_layout_copy(&s->ch_layout, &inlink->ch_layout); + if (ret < 0) + return ret; + if (strcmp(s->ch_layout_str, "all")) + av_channel_layout_from_string(&s->ch_layout, + s->ch_layout_str); if (av_frame_is_writable(in)) { out = in; @@ -153,7 +181,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) td.in = in; td.out = out; ff_filter_execute(ctx, filter_channels, &td, NULL, - FFMIN(inlink->channels, ff_filter_get_nb_threads(ctx))); + FFMIN(inlink->ch_layout.nb_channels, ff_filter_get_nb_threads(ctx))); if (out != in) av_frame_free(&in); @@ -164,6 +192,7 @@ static av_cold void uninit(AVFilterContext *ctx) { ASubBoostContext *s = ctx->priv; + av_channel_layout_uninit(&s->ch_layout); av_frame_free(&s->buffer); av_frame_free(&s->w); av_freep(&s->write_pos); @@ -185,13 +214,15 @@ static int process_command(AVFilterContext *ctx, const char *cmd, const char *ar #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption asubboost_options[] = { - { "dry", "set dry gain", OFFSET(dry_gain), AV_OPT_TYPE_DOUBLE, {.dbl=0.7}, 0, 1, FLAGS }, - { "wet", "set wet gain", OFFSET(wet_gain), AV_OPT_TYPE_DOUBLE, {.dbl=0.7}, 0, 1, FLAGS }, - { "decay", "set decay", OFFSET(decay), AV_OPT_TYPE_DOUBLE, {.dbl=0.7}, 0, 1, FLAGS }, + { "dry", "set dry gain", OFFSET(dry_gain), AV_OPT_TYPE_DOUBLE, {.dbl=1.0}, 0, 1, FLAGS }, + { "wet", "set wet gain", OFFSET(wet_gain), AV_OPT_TYPE_DOUBLE, {.dbl=1.0}, 0, 1, FLAGS }, + { "boost", "set max boost",OFFSET(max_boost),AV_OPT_TYPE_DOUBLE, {.dbl=2.0}, 1, 12, FLAGS }, + { "decay", "set decay", OFFSET(decay), AV_OPT_TYPE_DOUBLE, {.dbl=0.0}, 0, 1, FLAGS }, { "feedback", "set feedback", OFFSET(feedback), AV_OPT_TYPE_DOUBLE, {.dbl=0.9}, 0, 1, FLAGS }, { "cutoff", "set cutoff", OFFSET(cutoff), AV_OPT_TYPE_DOUBLE, {.dbl=100}, 50, 900, FLAGS }, { "slope", "set slope", OFFSET(slope), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0.0001, 1, FLAGS }, { "delay", "set delay", OFFSET(delay), AV_OPT_TYPE_DOUBLE, {.dbl=20}, 1, 100, FLAGS }, + { "channels", "set channels to filter", OFFSET(ch_layout_str), AV_OPT_TYPE_STRING, {.str="all"}, 0, 0, FLAGS }, { NULL } }; diff --git a/libavfilter/af_asupercut.c b/libavfilter/af_asupercut.c index a4c2d1515..5c06d559e 100644 --- a/libavfilter/af_asupercut.c +++ b/libavfilter/af_asupercut.c @@ -210,8 +210,8 @@ static int filter_channels_## name(AVFilterContext *ctx, void *arg, \ ThreadData *td = arg; \ AVFrame *out = td->out; \ AVFrame *in = td->in; \ - const int start = (in->channels * jobnr) / nb_jobs; \ - const int end = (in->channels * (jobnr+1)) / nb_jobs; \ + const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs; \ + const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; \ const double level = s->level; \ \ for (int ch = start; ch < end; ch++) { \ @@ -286,7 +286,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) td.in = in; td.out = out; ff_filter_execute(ctx, s->filter_channels, &td, NULL, - FFMIN(inlink->channels, ff_filter_get_nb_threads(ctx))); + FFMIN(inlink->ch_layout.nb_channels, ff_filter_get_nb_threads(ctx))); if (out != in) av_frame_free(&in); diff --git a/libavfilter/af_atempo.c b/libavfilter/af_atempo.c index e9a6da797..adbc69b50 100644 --- a/libavfilter/af_atempo.c +++ b/libavfilter/af_atempo.c @@ -39,13 +39,13 @@ */ #include -#include "libavcodec/avfft.h" #include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/channel_layout.h" #include "libavutil/eval.h" #include "libavutil/opt.h" #include "libavutil/samplefmt.h" +#include "libavutil/tx.h" #include "avfilter.h" #include "audio.h" #include "internal.h" @@ -67,7 +67,8 @@ typedef struct AudioFragment { // rDFT transform of the down-mixed mono fragment, used for // fast waveform alignment via correlation in frequency domain: - FFTSample *xdat; + float *xdat_in; + float *xdat; } AudioFragment; /** @@ -140,9 +141,11 @@ typedef struct ATempoContext { FilterState state; // for fast correlation calculation in frequency domain: - RDFTContext *real_to_complex; - RDFTContext *complex_to_real; - FFTSample *correlation; + AVTXContext *real_to_complex; + AVTXContext *complex_to_real; + av_tx_fn r2c_fn, c2r_fn; + float *correlation_in; + float *correlation; // for managing AVFilterPad.request_frame and AVFilterPad.filter_frame AVFrame *dst_buffer; @@ -228,18 +231,18 @@ static void yae_release_buffers(ATempoContext *atempo) av_freep(&atempo->frag[0].data); av_freep(&atempo->frag[1].data); + av_freep(&atempo->frag[0].xdat_in); + av_freep(&atempo->frag[1].xdat_in); av_freep(&atempo->frag[0].xdat); av_freep(&atempo->frag[1].xdat); av_freep(&atempo->buffer); av_freep(&atempo->hann); + av_freep(&atempo->correlation_in); av_freep(&atempo->correlation); - av_rdft_end(atempo->real_to_complex); - atempo->real_to_complex = NULL; - - av_rdft_end(atempo->complex_to_real); - atempo->complex_to_real = NULL; + av_tx_uninit(&atempo->real_to_complex); + av_tx_uninit(&atempo->complex_to_real); } /* av_realloc is not aligned enough; fortunately, the data does not need to @@ -247,7 +250,7 @@ static void yae_release_buffers(ATempoContext *atempo) #define RE_MALLOC_OR_FAIL(field, field_size) \ do { \ av_freep(&field); \ - field = av_malloc(field_size); \ + field = av_calloc(field_size, 1); \ if (!field) { \ yae_release_buffers(atempo); \ return AVERROR(ENOMEM); \ @@ -265,6 +268,7 @@ static int yae_reset(ATempoContext *atempo, { const int sample_size = av_get_bytes_per_sample(format); uint32_t nlevels = 0; + float scale = 1.f, iscale = 1.f; uint32_t pot; int i; @@ -288,29 +292,29 @@ static int yae_reset(ATempoContext *atempo, // initialize audio fragment buffers: RE_MALLOC_OR_FAIL(atempo->frag[0].data, atempo->window * atempo->stride); RE_MALLOC_OR_FAIL(atempo->frag[1].data, atempo->window * atempo->stride); - RE_MALLOC_OR_FAIL(atempo->frag[0].xdat, atempo->window * sizeof(FFTComplex)); - RE_MALLOC_OR_FAIL(atempo->frag[1].xdat, atempo->window * sizeof(FFTComplex)); + RE_MALLOC_OR_FAIL(atempo->frag[0].xdat_in, (atempo->window + 1) * sizeof(AVComplexFloat)); + RE_MALLOC_OR_FAIL(atempo->frag[1].xdat_in, (atempo->window + 1) * sizeof(AVComplexFloat)); + RE_MALLOC_OR_FAIL(atempo->frag[0].xdat, (atempo->window + 1) * sizeof(AVComplexFloat)); + RE_MALLOC_OR_FAIL(atempo->frag[1].xdat, (atempo->window + 1) * sizeof(AVComplexFloat)); // initialize rDFT contexts: - av_rdft_end(atempo->real_to_complex); - atempo->real_to_complex = NULL; + av_tx_uninit(&atempo->real_to_complex); + av_tx_uninit(&atempo->complex_to_real); - av_rdft_end(atempo->complex_to_real); - atempo->complex_to_real = NULL; - - atempo->real_to_complex = av_rdft_init(nlevels + 1, DFT_R2C); + av_tx_init(&atempo->real_to_complex, &atempo->r2c_fn, AV_TX_FLOAT_RDFT, 0, 1 << (nlevels + 1), &scale, 0); if (!atempo->real_to_complex) { yae_release_buffers(atempo); return AVERROR(ENOMEM); } - atempo->complex_to_real = av_rdft_init(nlevels + 1, IDFT_C2R); + av_tx_init(&atempo->complex_to_real, &atempo->c2r_fn, AV_TX_FLOAT_RDFT, 1, 1 << (nlevels + 1), &iscale, 0); if (!atempo->complex_to_real) { yae_release_buffers(atempo); return AVERROR(ENOMEM); } - RE_MALLOC_OR_FAIL(atempo->correlation, atempo->window * sizeof(FFTComplex)); + RE_MALLOC_OR_FAIL(atempo->correlation_in, (atempo->window + 1) * sizeof(AVComplexFloat)); + RE_MALLOC_OR_FAIL(atempo->correlation, atempo->window * sizeof(AVComplexFloat)); atempo->ring = atempo->window * 3; RE_MALLOC_OR_FAIL(atempo->buffer, atempo->ring * atempo->stride); @@ -348,7 +352,7 @@ static int yae_update(AVFilterContext *ctx) const uint8_t *src_end = src + \ frag->nsamples * atempo->channels * sizeof(scalar_type); \ \ - FFTSample *xdat = frag->xdat; \ + float *xdat = frag->xdat_in; \ scalar_type tmp; \ \ if (atempo->channels == 1) { \ @@ -356,27 +360,27 @@ static int yae_update(AVFilterContext *ctx) tmp = *(const scalar_type *)src; \ src += sizeof(scalar_type); \ \ - *xdat = (FFTSample)tmp; \ + *xdat = (float)tmp; \ } \ } else { \ - FFTSample s, max, ti, si; \ + float s, max, ti, si; \ int i; \ \ for (; src < src_end; xdat++) { \ tmp = *(const scalar_type *)src; \ src += sizeof(scalar_type); \ \ - max = (FFTSample)tmp; \ - s = FFMIN((FFTSample)scalar_max, \ - (FFTSample)fabsf(max)); \ + max = (float)tmp; \ + s = FFMIN((float)scalar_max, \ + (float)fabsf(max)); \ \ for (i = 1; i < atempo->channels; i++) { \ tmp = *(const scalar_type *)src; \ src += sizeof(scalar_type); \ \ - ti = (FFTSample)tmp; \ - si = FFMIN((FFTSample)scalar_max, \ - (FFTSample)fabsf(ti)); \ + ti = (float)tmp; \ + si = FFMIN((float)scalar_max, \ + (float)fabsf(ti)); \ \ if (s < si) { \ s = si; \ @@ -399,7 +403,7 @@ static void yae_downmix(ATempoContext *atempo, AudioFragment *frag) const uint8_t *src = frag->data; // init complex data buffer used for FFT and Correlation: - memset(frag->xdat, 0, sizeof(FFTComplex) * atempo->window); + memset(frag->xdat_in, 0, sizeof(AVComplexFloat) * (atempo->window + 1)); if (atempo->format == AV_SAMPLE_FMT_U8) { yae_init_xdat(uint8_t, 127); @@ -598,32 +602,24 @@ static void yae_advance_to_next_frag(ATempoContext *atempo) * Multiply two vectors of complex numbers (result of real_to_complex rDFT) * and transform back via complex_to_real rDFT. */ -static void yae_xcorr_via_rdft(FFTSample *xcorr, - RDFTContext *complex_to_real, - const FFTComplex *xa, - const FFTComplex *xb, +static void yae_xcorr_via_rdft(float *xcorr_in, + float *xcorr, + AVTXContext *complex_to_real, + av_tx_fn c2r_fn, + const AVComplexFloat *xa, + const AVComplexFloat *xb, const int window) { - FFTComplex *xc = (FFTComplex *)xcorr; + AVComplexFloat *xc = (AVComplexFloat *)xcorr_in; int i; - // NOTE: first element requires special care -- Given Y = rDFT(X), - // Im(Y[0]) and Im(Y[N/2]) are always zero, therefore av_rdft_calc - // stores Re(Y[N/2]) in place of Im(Y[0]). - - xc->re = xa->re * xb->re; - xc->im = xa->im * xb->im; - xa++; - xb++; - xc++; - - for (i = 1; i < window; i++, xa++, xb++, xc++) { + for (i = 0; i <= window; i++, xa++, xb++, xc++) { xc->re = (xa->re * xb->re + xa->im * xb->im); xc->im = (xa->im * xb->re - xa->re * xb->im); } // apply inverse rDFT: - av_rdft_calc(complex_to_real, xcorr); + c2r_fn(complex_to_real, xcorr, xcorr_in, sizeof(float)); } /** @@ -637,21 +633,25 @@ static int yae_align(AudioFragment *frag, const int window, const int delta_max, const int drift, - FFTSample *correlation, - RDFTContext *complex_to_real) + float *correlation_in, + float *correlation, + AVTXContext *complex_to_real, + av_tx_fn c2r_fn) { int best_offset = -drift; - FFTSample best_metric = -FLT_MAX; - FFTSample *xcorr; + float best_metric = -FLT_MAX; + float *xcorr; int i0; int i1; int i; - yae_xcorr_via_rdft(correlation, + yae_xcorr_via_rdft(correlation_in, + correlation, complex_to_real, - (const FFTComplex *)prev->xdat, - (const FFTComplex *)frag->xdat, + c2r_fn, + (const AVComplexFloat *)prev->xdat, + (const AVComplexFloat *)frag->xdat, window); // identify search window boundaries: @@ -665,11 +665,11 @@ static int yae_align(AudioFragment *frag, xcorr = correlation + i0; for (i = i0; i < i1; i++, xcorr++) { - FFTSample metric = *xcorr; + float metric = *xcorr; // normalize: - FFTSample drifti = (FFTSample)(drift + i); - metric *= drifti * (FFTSample)(i - i0) * (FFTSample)(i1 - i); + float drifti = (float)(drift + i); + metric *= drifti * (float)(i - i0) * (float)(i1 - i); if (metric > best_metric) { best_metric = metric; @@ -706,8 +706,10 @@ static int yae_adjust_position(ATempoContext *atempo) atempo->window, delta_max, drift, + atempo->correlation_in, atempo->correlation, - atempo->complex_to_real); + atempo->complex_to_real, + atempo->c2r_fn); if (correction) { // adjust fragment position: @@ -833,7 +835,7 @@ yae_apply(ATempoContext *atempo, yae_downmix(atempo, yae_curr_frag(atempo)); // apply rDFT: - av_rdft_calc(atempo->real_to_complex, yae_curr_frag(atempo)->xdat); + atempo->r2c_fn(atempo->real_to_complex, yae_curr_frag(atempo)->xdat, yae_curr_frag(atempo)->xdat_in, sizeof(float)); // must load the second fragment before alignment can start: if (!atempo->nfrag) { @@ -865,7 +867,7 @@ yae_apply(ATempoContext *atempo, yae_downmix(atempo, yae_curr_frag(atempo)); // apply rDFT: - av_rdft_calc(atempo->real_to_complex, yae_curr_frag(atempo)->xdat); + atempo->r2c_fn(atempo->real_to_complex, yae_curr_frag(atempo)->xdat, yae_curr_frag(atempo)->xdat_in, sizeof(float)); atempo->state = YAE_OUTPUT_OVERLAP_ADD; } @@ -929,7 +931,7 @@ static int yae_flush(ATempoContext *atempo, yae_downmix(atempo, frag); // apply rDFT: - av_rdft_calc(atempo->real_to_complex, frag->xdat); + atempo->r2c_fn(atempo->real_to_complex, frag->xdat, frag->xdat_in, sizeof(float)); // align current fragment to previous fragment: if (yae_adjust_position(atempo)) { @@ -1016,7 +1018,7 @@ static int config_props(AVFilterLink *inlink) enum AVSampleFormat format = inlink->format; int sample_rate = (int)inlink->sample_rate; - return yae_reset(atempo, format, sample_rate, inlink->channels); + return yae_reset(atempo, format, sample_rate, inlink->ch_layout.nb_channels); } static int push_samples(ATempoContext *atempo, diff --git a/libavfilter/af_atilt.c b/libavfilter/af_atilt.c index a6f7782af..9ece531ea 100644 --- a/libavfilter/af_atilt.c +++ b/libavfilter/af_atilt.c @@ -125,8 +125,8 @@ static int filter_channels_## name(AVFilterContext *ctx, void *arg, \ ThreadData *td = arg; \ AVFrame *out = td->out; \ AVFrame *in = td->in; \ - const int start = (in->channels * jobnr) / nb_jobs; \ - const int end = (in->channels * (jobnr+1)) / nb_jobs; \ + const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs; \ + const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; \ const type level = s->level; \ \ for (int ch = start; ch < end; ch++) { \ @@ -196,7 +196,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) } td.in = in; td.out = out; - ff_filter_execute(ctx, s->filter_channels, &td, NULL, FFMIN(inlink->channels, + ff_filter_execute(ctx, s->filter_channels, &td, NULL, FFMIN(inlink->ch_layout.nb_channels, ff_filter_get_nb_threads(ctx))); if (out != in) diff --git a/libavfilter/af_axcorrelate.c b/libavfilter/af_axcorrelate.c index d0a91cd83..9be3f1c92 100644 --- a/libavfilter/af_axcorrelate.c +++ b/libavfilter/af_axcorrelate.c @@ -113,7 +113,7 @@ static int xcorrelate_slow_##suffix(AVFilterContext *ctx, \ const int size = FFMIN(available, s->size); \ int used; \ \ - for (int ch = 0; ch < out->channels; ch++) { \ + for (int ch = 0; ch < out->ch_layout.nb_channels; ch++) { \ const type *x = (const type *)s->cache[0]->extended_data[ch]; \ const type *y = (const type *)s->cache[1]->extended_data[ch]; \ type *sumx = (type *)s->mean_sum[0]->extended_data[ch]; \ @@ -155,7 +155,7 @@ static int xcorrelate_fast_##suffix(AVFilterContext *ctx, AVFrame *out, \ const int size = FFMIN(available, s->size); \ int used; \ \ - for (int ch = 0; ch < out->channels; ch++) { \ + for (int ch = 0; ch < out->ch_layout.nb_channels; ch++) { \ const type *x = (const type *)s->cache[0]->extended_data[ch]; \ const type *y = (const type *)s->cache[1]->extended_data[ch]; \ type *num_sum = (type *)s->num_sum->extended_data[ch]; \ @@ -299,8 +299,8 @@ static int config_output(AVFilterLink *outlink) s->pts = AV_NOPTS_VALUE; - s->fifo[0] = av_audio_fifo_alloc(outlink->format, outlink->channels, s->size); - s->fifo[1] = av_audio_fifo_alloc(outlink->format, outlink->channels, s->size); + s->fifo[0] = av_audio_fifo_alloc(outlink->format, outlink->ch_layout.nb_channels, s->size); + s->fifo[1] = av_audio_fifo_alloc(outlink->format, outlink->ch_layout.nb_channels, s->size); if (!s->fifo[0] || !s->fifo[1]) return AVERROR(ENOMEM); diff --git a/libavfilter/af_biquads.c b/libavfilter/af_biquads.c index ee42b2a03..03165bf22 100644 --- a/libavfilter/af_biquads.c +++ b/libavfilter/af_biquads.c @@ -62,12 +62,15 @@ * V */ +#include "config_components.h" + #include "libavutil/avassert.h" #include "libavutil/channel_layout.h" #include "libavutil/ffmath.h" #include "libavutil/opt.h" #include "audio.h" #include "avfilter.h" +#include "filters.h" #include "internal.h" enum FilterType { @@ -82,6 +85,7 @@ enum FilterType { lowpass, lowshelf, highshelf, + tiltshelf, }; enum WidthType { @@ -97,15 +101,19 @@ enum WidthType { enum TransformType { DI, DII, + TDI, TDII, LATT, SVF, + ZDF, NB_TTYPE, }; typedef struct ChanCache { double i1, i2; double o1, o2; + double ri1, ri2; + double ro1, ro2; int clippings; } ChanCache; @@ -118,6 +126,7 @@ typedef struct BiquadsContext { int csg; int transform_type; int precision; + int block_samples; int bypass; @@ -125,7 +134,8 @@ typedef struct BiquadsContext { double frequency; double width; double mix; - uint64_t channels; + char *ch_layout_str; + AVChannelLayout ch_layout; int normalize; int order; @@ -135,12 +145,17 @@ typedef struct BiquadsContext { double oa0, oa1, oa2; double ob0, ob1, ob2; + AVFrame *block[3]; + ChanCache *cache; int block_align; + int64_t pts; + int nb_samples; + void (*filter)(struct BiquadsContext *s, const void *ibuf, void *obuf, int len, double *i1, double *i2, double *o1, double *o2, - double b0, double b1, double b2, double a1, double a2, int *clippings, + double b0, double b1, double b2, double a0, double a1, double a2, int *clippings, int disabled); } BiquadsContext; @@ -193,7 +208,7 @@ static void biquad_## name (BiquadsContext *s, \ double *in1, double *in2, \ double *out1, double *out2, \ double b0, double b1, double b2, \ - double a1, double a2, int *clippings, \ + double a0, double a1, double a2, int *clippings, \ int disabled) \ { \ const type *ibuf = input; \ @@ -276,7 +291,7 @@ static void biquad_dii_## name (BiquadsContext *s, \ double *z1, double *z2, \ double *unused1, double *unused2, \ double b0, double b1, double b2, \ - double a1, double a2, int *clippings, \ + double a0, double a1, double a2, int *clippings, \ int disabled) \ { \ const type *ibuf = input; \ @@ -318,13 +333,69 @@ BIQUAD_DII_FILTER(s32, int32_t, INT32_MIN, INT32_MAX, 1) BIQUAD_DII_FILTER(flt, float, -1., 1., 0) BIQUAD_DII_FILTER(dbl, double, -1., 1., 0) +#define BIQUAD_TDI_FILTER(name, type, min, max, need_clipping) \ +static void biquad_tdi_## name (BiquadsContext *s, \ + const void *input, void *output, int len, \ + double *z1, double *z2, \ + double *z3, double *z4, \ + double b0, double b1, double b2, \ + double a0, double a1, double a2, int *clippings, \ + int disabled) \ +{ \ + const type *ibuf = input; \ + type *obuf = output; \ + double s1 = *z1; \ + double s2 = *z2; \ + double s3 = *z3; \ + double s4 = *z4; \ + double wet = s->mix; \ + double dry = 1. - wet; \ + double in, out; \ + \ + a1 = -a1; \ + a2 = -a2; \ + \ + for (int i = 0; i < len; i++) { \ + double t1, t2, t3, t4; \ + in = ibuf[i] + s1; \ + t1 = in * a1 + s2; \ + t2 = in * a2; \ + t3 = in * b1 + s4; \ + t4 = in * b2; \ + out = b0 * in + s3; \ + out = out * wet + in * dry; \ + s1 = t1; s2 = t2; s3 = t3; s4 = t4; \ + if (disabled) { \ + obuf[i] = in; \ + } else if (need_clipping && out < min) { \ + (*clippings)++; \ + obuf[i] = min; \ + } else if (need_clipping && out > max) { \ + (*clippings)++; \ + obuf[i] = max; \ + } else { \ + obuf[i] = out; \ + } \ + } \ + \ + *z1 = s1; \ + *z2 = s2; \ + *z3 = s3; \ + *z4 = s4; \ +} + +BIQUAD_TDI_FILTER(s16, int16_t, INT16_MIN, INT16_MAX, 1) +BIQUAD_TDI_FILTER(s32, int32_t, INT32_MIN, INT32_MAX, 1) +BIQUAD_TDI_FILTER(flt, float, -1., 1., 0) +BIQUAD_TDI_FILTER(dbl, double, -1., 1., 0) + #define BIQUAD_TDII_FILTER(name, type, min, max, need_clipping) \ static void biquad_tdii_## name (BiquadsContext *s, \ const void *input, void *output, int len, \ double *z1, double *z2, \ double *unused1, double *unused2, \ double b0, double b1, double b2, \ - double a1, double a2, int *clippings, \ + double a0, double a1, double a2, int *clippings, \ int disabled) \ { \ const type *ibuf = input; \ @@ -371,7 +442,8 @@ static void biquad_latt_## name (BiquadsContext *s, \ double *z1, double *z2, \ double *unused1, double *unused2, \ double v0, double v1, double v2, \ - double k0, double k1, int *clippings, \ + double unused, double k0, double k1, \ + int *clippings, \ int disabled) \ { \ const type *ibuf = input; \ @@ -426,7 +498,7 @@ static void biquad_svf_## name (BiquadsContext *s, \ double *y0, double *y1, \ double *unused1, double *unused2, \ double b0, double b1, double b2, \ - double a1, double a2, int *clippings, \ + double a0, double a1, double a2, int *clippings, \ int disabled) \ { \ const type *ibuf = input; \ @@ -468,6 +540,56 @@ BIQUAD_SVF_FILTER(s32, int32_t, INT32_MIN, INT32_MAX, 1) BIQUAD_SVF_FILTER(flt, float, -1., 1., 0) BIQUAD_SVF_FILTER(dbl, double, -1., 1., 0) +#define BIQUAD_ZDF_FILTER(name, type, min, max, need_clipping) \ +static void biquad_zdf_## name (BiquadsContext *s, \ + const void *input, void *output, int len, \ + double *y0, double *y1, \ + double *unused1, double *unused2, \ + double m0, double m1, double m2, \ + double a0, double a1, double a2, int *clippings, \ + int disabled) \ +{ \ + const type *ibuf = input; \ + type *obuf = output; \ + double b0 = *y0; \ + double b1 = *y1; \ + double wet = s->mix; \ + double dry = 1. - wet; \ + double out; \ + \ + for (int i = 0; i < len; i++) { \ + const double in = ibuf[i]; \ + const double v0 = in; \ + const double v3 = v0 - b1; \ + const double v1 = a0 * b0 + a1 * v3; \ + const double v2 = b1 + a1 * b0 + a2 * v3; \ + \ + b0 = 2. * v1 - b0; \ + b1 = 2. * v2 - b1; \ + \ + out = m0 * v0 + m1 * v1 + m2 * v2; \ + out = out * wet + in * dry; \ + if (disabled) { \ + obuf[i] = in; \ + } else if (need_clipping && out < min) { \ + (*clippings)++; \ + obuf[i] = min; \ + } else if (need_clipping && out > max) { \ + (*clippings)++; \ + obuf[i] = max; \ + } else { \ + obuf[i] = out; \ + } \ + } \ + *y0 = b0; \ + *y1 = b1; \ +} + +BIQUAD_ZDF_FILTER(s16, int16_t, INT16_MIN, INT16_MAX, 1) +BIQUAD_ZDF_FILTER(s32, int32_t, INT32_MIN, INT32_MAX, 1) +BIQUAD_ZDF_FILTER(flt, float, -1., 1., 0) +BIQUAD_ZDF_FILTER(dbl, double, -1., 1., 0) + static void convert_dir2latt(BiquadsContext *s) { double k0, k1, v0, v1, v2; @@ -503,12 +625,172 @@ static void convert_dir2svf(BiquadsContext *s) s->b2 = b[2]; } +static double convert_width2qfactor(double width, + double frequency, + double gain, + double sample_rate, + int width_type) +{ + double w0 = 2. * M_PI * frequency / sample_rate; + double A = ff_exp10(gain / 40.); + double ret; + + switch (width_type) { + case NONE: + case QFACTOR: + ret = width; + break; + case HERTZ: + ret = frequency / width; + break; + case KHERTZ: + ret = frequency / (width * 1000.); + break; + case OCTAVE: + ret = 1. / (2. * sinh(log(2.) / 2. * width * w0 / sin(w0))); + break; + case SLOPE: + ret = 1. / sqrt((A + 1. / A) * (1. / width - 1.) + 2.); + break; + default: + av_assert0(0); + break; + } + + return ret; +} + +static void convert_dir2zdf(BiquadsContext *s, int sample_rate) +{ + double Q = convert_width2qfactor(s->width, s->frequency, s->gain, sample_rate, s->width_type); + double g, k, A; + double a[3]; + double m[3]; + + switch (s->filter_type) { + case biquad: + a[0] = s->oa0; + a[1] = s->oa1; + a[2] = s->oa2; + m[0] = s->ob0; + m[1] = s->ob1; + m[2] = s->ob2; + break; + case equalizer: + A = ff_exp10(s->gain / 40.); + g = tan(M_PI * s->frequency / sample_rate); + k = 1. / (Q * A); + a[0] = 1. / (1. + g * (g + k)); + a[1] = g * a[0]; + a[2] = g * a[1]; + m[0] = 1.; + m[1] = k * (A * A - 1.); + m[2] = 0.; + break; + case bass: + case lowshelf: + A = ff_exp10(s->gain / 40.); + g = tan(M_PI * s->frequency / sample_rate) / sqrt(A); + k = 1. / Q; + a[0] = 1. / (1. + g * (g + k)); + a[1] = g * a[0]; + a[2] = g * a[1]; + m[0] = 1.; + m[1] = k * (A - 1.); + m[2] = A * A - 1.; + break; + case tiltshelf: + A = ff_exp10(s->gain / 20.); + g = tan(M_PI * s->frequency / sample_rate) / sqrt(A); + k = 1. / Q; + a[0] = 1. / (1. + g * (g + k)); + a[1] = g * a[0]; + a[2] = g * a[1]; + m[0] = 1./ A; + m[1] = k * (A - 1.) / A; + m[2] = (A * A - 1.) / A; + break; + case treble: + case highshelf: + A = ff_exp10(s->gain / 40.); + g = tan(M_PI * s->frequency / sample_rate) / sqrt(A); + k = 1. / Q; + a[0] = 1. / (1. + g * (g + k)); + a[1] = g * a[0]; + a[2] = g * a[1]; + m[0] = A * A; + m[1] = k * (1. - A) * A; + m[2] = 1. - A * A; + break; + case bandpass: + g = tan(M_PI * s->frequency / sample_rate); + k = 1. / Q; + a[0] = 1. / (1. + g * (g + k)); + a[1] = g * a[0]; + a[2] = g * a[1]; + m[0] = 0.; + m[1] = s->csg ? 1. : 2.; + m[2] = 0.; + break; + case bandreject: + g = tan(M_PI * s->frequency / sample_rate); + k = 1. / Q; + a[0] = 1. / (1. + g * (g + k)); + a[1] = g * a[0]; + a[2] = g * a[1]; + m[0] = 1.; + m[1] = -k; + m[2] = 0.; + break; + case lowpass: + g = tan(M_PI * s->frequency / sample_rate); + k = 1. / Q; + a[0] = 1. / (1. + g * (g + k)); + a[1] = g * a[0]; + a[2] = g * a[1]; + m[0] = 0.; + m[1] = 0.; + m[2] = 1.; + break; + case highpass: + g = tan(M_PI * s->frequency / sample_rate); + k = 1. / Q; + a[0] = 1. / (1. + g * (g + k)); + a[1] = g * a[0]; + a[2] = g * a[1]; + m[0] = 1.; + m[1] = -k; + m[2] = -1.; + break; + case allpass: + g = tan(M_PI * s->frequency / sample_rate); + k = 1. / Q; + a[0] = 1. / (1. + g * (g + k)); + a[1] = g * a[0]; + a[2] = g * a[1]; + m[0] = 1.; + m[1] = -2. * k; + m[2] = 0.; + break; + default: + av_assert0(0); + } + + s->a0 = a[0]; + s->a1 = a[1]; + s->a2 = a[2]; + s->b0 = m[0]; + s->b1 = m[1]; + s->b2 = m[2]; +} + static int config_filter(AVFilterLink *outlink, int reset) { AVFilterContext *ctx = outlink->src; BiquadsContext *s = ctx->priv; AVFilterLink *inlink = ctx->inputs[0]; - double A = ff_exp10(s->gain / 40); + double gain = s->gain * ((s->filter_type == tiltshelf) + 1.); + double A = ff_exp10(gain / 40); double w0 = 2 * M_PI * s->frequency / inlink->sample_rate; double K = tan(w0 / 2.); double alpha, beta; @@ -566,9 +848,10 @@ static int config_filter(AVFilterLink *outlink, int reset) break; case bass: beta = sqrt((A * A + 1) - (A - 1) * (A - 1)); + case tiltshelf: case lowshelf: if (s->poles == 1) { - double A = ff_exp10(s->gain / 20); + double A = ff_exp10(gain / 20); double ro = -sin(w0 / 2. - M_PI_4) / sin(w0 / 2. + M_PI_4); double n = (A + 1) / (A - 1); double alpha1 = A == 1. ? 0. : n - FFSIGN(n) * sqrt(n * n - 1); @@ -594,7 +877,7 @@ static int config_filter(AVFilterLink *outlink, int reset) beta = sqrt((A * A + 1) - (A - 1) * (A - 1)); case highshelf: if (s->poles == 1) { - double A = ff_exp10(s->gain / 20); + double A = ff_exp10(gain / 20); double ro = sin(w0 / 2. - M_PI_4) / sin(w0 / 2. + M_PI_4); double n = (A + 1) / (A - 1); double alpha1 = A == 1. ? 0. : n - FFSIGN(n) * sqrt(n * n - 1); @@ -716,11 +999,29 @@ static int config_filter(AVFilterLink *outlink, int reset) s->b2 *= factor; } - s->cache = av_realloc_f(s->cache, sizeof(ChanCache), inlink->channels); + switch (s->filter_type) { + case tiltshelf: + s->b0 /= A; + s->b1 /= A; + s->b2 /= A; + break; + } + + s->cache = av_realloc_f(s->cache, sizeof(ChanCache), inlink->ch_layout.nb_channels); if (!s->cache) return AVERROR(ENOMEM); if (reset) - memset(s->cache, 0, sizeof(ChanCache) * inlink->channels); + memset(s->cache, 0, sizeof(ChanCache) * inlink->ch_layout.nb_channels); + + if (reset && s->block_samples > 0) { + for (int i = 0; i < 3; i++) { + s->block[i] = ff_get_audio_buffer(outlink, s->block_samples * 2); + if (!s->block[i]) + return AVERROR(ENOMEM); + av_samples_set_silence(s->block[i]->extended_data, 0, s->block_samples * 2, + s->block[i]->ch_layout.nb_channels, s->block[i]->format); + } + } switch (s->transform_type) { case DI: @@ -757,6 +1058,23 @@ static int config_filter(AVFilterLink *outlink, int reset) default: av_assert0(0); } break; + case TDI: + switch (inlink->format) { + case AV_SAMPLE_FMT_S16P: + s->filter = biquad_tdi_s16; + break; + case AV_SAMPLE_FMT_S32P: + s->filter = biquad_tdi_s32; + break; + case AV_SAMPLE_FMT_FLTP: + s->filter = biquad_tdi_flt; + break; + case AV_SAMPLE_FMT_DBLP: + s->filter = biquad_tdi_dbl; + break; + default: av_assert0(0); + } + break; case TDII: switch (inlink->format) { case AV_SAMPLE_FMT_S16P: @@ -808,6 +1126,23 @@ static int config_filter(AVFilterLink *outlink, int reset) default: av_assert0(0); } break; + case ZDF: + switch (inlink->format) { + case AV_SAMPLE_FMT_S16P: + s->filter = biquad_zdf_s16; + break; + case AV_SAMPLE_FMT_S32P: + s->filter = biquad_zdf_s32; + break; + case AV_SAMPLE_FMT_FLTP: + s->filter = biquad_zdf_flt; + break; + case AV_SAMPLE_FMT_DBLP: + s->filter = biquad_zdf_dbl; + break; + default: av_assert0(0); + } + break; default: av_assert0(0); } @@ -818,6 +1153,8 @@ static int config_filter(AVFilterLink *outlink, int reset) convert_dir2latt(s); else if (s->transform_type == SVF) convert_dir2svf(s); + else if (s->transform_type == ZDF) + convert_dir2zdf(s, inlink->sample_rate); return 0; } @@ -829,8 +1166,44 @@ static int config_output(AVFilterLink *outlink) typedef struct ThreadData { AVFrame *in, *out; + int eof; } ThreadData; +static void reverse_samples(AVFrame *out, AVFrame *in, int p, + int oo, int io, int nb_samples) +{ + switch (out->format) { + case AV_SAMPLE_FMT_S16P: { + const int16_t *src = ((const int16_t *)in->extended_data[p]) + io; + int16_t *dst = ((int16_t *)out->extended_data[p]) + oo; + for (int i = 0, j = nb_samples - 1; i < nb_samples; i++, j--) + dst[i] = src[j]; + } + break; + case AV_SAMPLE_FMT_S32P: { + const int32_t *src = ((const int32_t *)in->extended_data[p]) + io; + int32_t *dst = ((int32_t *)out->extended_data[p]) + oo; + for (int i = 0, j = nb_samples - 1; i < nb_samples; i++, j--) + dst[i] = src[j]; + } + break; + case AV_SAMPLE_FMT_FLTP: { + const float *src = ((const float *)in->extended_data[p]) + io; + float *dst = ((float *)out->extended_data[p]) + oo; + for (int i = 0, j = nb_samples - 1; i < nb_samples; i++, j--) + dst[i] = src[j]; + } + break; + case AV_SAMPLE_FMT_DBLP: { + const double *src = ((const double *)in->extended_data[p]) + io; + double *dst = ((double *)out->extended_data[p]) + oo; + for (int i = 0, j = nb_samples - 1; i < nb_samples; i++, j--) + dst[i] = src[j]; + } + break; + } +} + static int filter_channel(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { AVFilterLink *inlink = ctx->inputs[0]; @@ -838,42 +1211,88 @@ static int filter_channel(AVFilterContext *ctx, void *arg, int jobnr, int nb_job AVFrame *buf = td->in; AVFrame *out_buf = td->out; BiquadsContext *s = ctx->priv; - const int start = (buf->channels * jobnr) / nb_jobs; - const int end = (buf->channels * (jobnr+1)) / nb_jobs; + const int start = (buf->ch_layout.nb_channels * jobnr) / nb_jobs; + const int end = (buf->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; int ch; for (ch = start; ch < end; ch++) { - if (!((av_channel_layout_extract_channel(inlink->channel_layout, ch) & s->channels))) { + enum AVChannel channel = av_channel_layout_channel_from_index(&inlink->ch_layout, ch); + + if (av_channel_layout_index_from_channel(&s->ch_layout, channel) < 0) { if (buf != out_buf) memcpy(out_buf->extended_data[ch], buf->extended_data[ch], buf->nb_samples * s->block_align); continue; } - s->filter(s, buf->extended_data[ch], out_buf->extended_data[ch], buf->nb_samples, - &s->cache[ch].i1, &s->cache[ch].i2, &s->cache[ch].o1, &s->cache[ch].o2, - s->b0, s->b1, s->b2, s->a1, s->a2, &s->cache[ch].clippings, ctx->is_disabled); + if (!s->block_samples) { + s->filter(s, buf->extended_data[ch], out_buf->extended_data[ch], buf->nb_samples, + &s->cache[ch].i1, &s->cache[ch].i2, &s->cache[ch].o1, &s->cache[ch].o2, + s->b0, s->b1, s->b2, s->a0, s->a1, s->a2, &s->cache[ch].clippings, ctx->is_disabled); + } else if (td->eof) { + memcpy(out_buf->extended_data[ch], s->block[1]->extended_data[ch] + s->block_align * s->block_samples, + s->nb_samples * s->block_align); + } else { + memcpy(s->block[0]->extended_data[ch] + s->block_align * s->block_samples, buf->extended_data[ch], + buf->nb_samples * s->block_align); + memset(s->block[0]->extended_data[ch] + s->block_align * (s->block_samples + buf->nb_samples), + 0, (s->block_samples - buf->nb_samples) * s->block_align); + s->filter(s, s->block[0]->extended_data[ch], s->block[1]->extended_data[ch], s->block_samples, + &s->cache[ch].i1, &s->cache[ch].i2, &s->cache[ch].o1, &s->cache[ch].o2, + s->b0, s->b1, s->b2, s->a0, s->a1, s->a2, &s->cache[ch].clippings, ctx->is_disabled); + s->cache[ch].ri1 = s->cache[ch].i1; + s->cache[ch].ri2 = s->cache[ch].i2; + s->cache[ch].ro1 = s->cache[ch].o1; + s->cache[ch].ro2 = s->cache[ch].o2; + s->filter(s, s->block[0]->extended_data[ch] + s->block_samples * s->block_align, + s->block[1]->extended_data[ch] + s->block_samples * s->block_align, + s->block_samples, + &s->cache[ch].ri1, &s->cache[ch].ri2, &s->cache[ch].ro1, &s->cache[ch].ro2, + s->b0, s->b1, s->b2, s->a0, s->a1, s->a2, &s->cache[ch].clippings, ctx->is_disabled); + reverse_samples(s->block[2], s->block[1], ch, 0, 0, 2 * s->block_samples); + s->cache[ch].ri1 = 0.; + s->cache[ch].ri2 = 0.; + s->cache[ch].ro1 = 0.; + s->cache[ch].ro2 = 0.; + s->filter(s, s->block[2]->extended_data[ch], s->block[2]->extended_data[ch], 2 * s->block_samples, + &s->cache[ch].ri1, &s->cache[ch].ri2, &s->cache[ch].ro1, &s->cache[ch].ro2, + s->b0, s->b1, s->b2, s->a0, s->a1, s->a2, &s->cache[ch].clippings, ctx->is_disabled); + reverse_samples(s->block[1], s->block[2], ch, 0, 0, 2 * s->block_samples); + memcpy(out_buf->extended_data[ch], s->block[1]->extended_data[ch], + s->block_samples * s->block_align); + memmove(s->block[0]->extended_data[ch], s->block[0]->extended_data[ch] + s->block_align * s->block_samples, + s->block_samples * s->block_align); + } } return 0; } -static int filter_frame(AVFilterLink *inlink, AVFrame *buf) +static int filter_frame(AVFilterLink *inlink, AVFrame *buf, int eof) { AVFilterContext *ctx = inlink->dst; BiquadsContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; AVFrame *out_buf; ThreadData td; - int ch; + int ch, ret, drop = 0; if (s->bypass) return ff_filter_frame(outlink, buf); - if (av_frame_is_writable(buf)) { + ret = av_channel_layout_copy(&s->ch_layout, &inlink->ch_layout); + if (ret < 0) { + av_frame_free(&buf); + return ret; + } + if (strcmp(s->ch_layout_str, "all")) + av_channel_layout_from_string(&s->ch_layout, + s->ch_layout_str); + + if (av_frame_is_writable(buf) && s->block_samples == 0) { out_buf = buf; } else { - out_buf = ff_get_audio_buffer(outlink, buf->nb_samples); + out_buf = ff_get_audio_buffer(outlink, s->block_samples > 0 ? s->block_samples : buf->nb_samples); if (!out_buf) { av_frame_free(&buf); return AVERROR(ENOMEM); @@ -881,22 +1300,87 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *buf) av_frame_copy_props(out_buf, buf); } + if (s->block_samples > 0 && s->pts == AV_NOPTS_VALUE) + drop = 1; td.in = buf; td.out = out_buf; + td.eof = eof; ff_filter_execute(ctx, filter_channel, &td, NULL, - FFMIN(outlink->channels, ff_filter_get_nb_threads(ctx))); + FFMIN(outlink->ch_layout.nb_channels, ff_filter_get_nb_threads(ctx))); - for (ch = 0; ch < outlink->channels; ch++) { + for (ch = 0; ch < outlink->ch_layout.nb_channels; ch++) { if (s->cache[ch].clippings > 0) av_log(ctx, AV_LOG_WARNING, "Channel %d clipping %d times. Please reduce gain.\n", ch, s->cache[ch].clippings); s->cache[ch].clippings = 0; } + if (s->block_samples > 0) { + int nb_samples = buf->nb_samples; + int64_t pts = buf->pts; + + out_buf->pts = s->pts; + out_buf->nb_samples = s->nb_samples; + s->pts = pts; + s->nb_samples = nb_samples; + } + if (buf != out_buf) av_frame_free(&buf); - return ff_filter_frame(outlink, out_buf); + if (!drop) + return ff_filter_frame(outlink, out_buf); + else { + av_frame_free(&out_buf); + ff_filter_set_ready(ctx, 10); + return 0; + } +} + +static int activate(AVFilterContext *ctx) +{ + AVFilterLink *inlink = ctx->inputs[0]; + AVFilterLink *outlink = ctx->outputs[0]; + BiquadsContext *s = ctx->priv; + AVFrame *in = NULL; + int64_t pts; + int status; + int ret; + + FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); + + if (s->block_samples > 0) { + ret = ff_inlink_consume_samples(inlink, s->block_samples, s->block_samples, &in); + } else { + ret = ff_inlink_consume_frame(inlink, &in); + } + if (ret < 0) + return ret; + if (ret > 0) + return filter_frame(inlink, in, 0); + + if (s->block_samples > 0 && ff_inlink_queued_samples(inlink) >= s->block_samples) { + ff_filter_set_ready(ctx, 10); + return 0; + } + + if (ff_inlink_acknowledge_status(inlink, &status, &pts)) { + if (s->block_samples > 0) { + AVFrame *in = ff_get_audio_buffer(outlink, s->block_samples); + if (!in) + return AVERROR(ENOMEM); + + ret = filter_frame(inlink, in, 1); + } + + ff_outlink_set_status(outlink, status, pts); + + return ret; + } + + FF_FILTER_FORWARD_WANTED(outlink, inlink); + + return FFERROR_NOT_READY; } static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, @@ -916,14 +1400,16 @@ static av_cold void uninit(AVFilterContext *ctx) { BiquadsContext *s = ctx->priv; + for (int i = 0; i < 3; i++) + av_frame_free(&s->block[i]); av_freep(&s->cache); + av_channel_layout_uninit(&s->ch_layout); } static const AVFilterPad inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_AUDIO, - .filter_frame = filter_frame, }, }; @@ -944,15 +1430,17 @@ static av_cold int name_##_init(AVFilterContext *ctx) \ { \ BiquadsContext *s = ctx->priv; \ s->filter_type = name_; \ + s->pts = AV_NOPTS_VALUE; \ return 0; \ } \ \ -const AVFilter ff_af_##name_ = { \ +const AVFilter ff_af_##name_ = { \ .name = #name_, \ .description = NULL_IF_CONFIG_SMALL(description_), \ .priv_class = &priv_class_##_class, \ .priv_size = sizeof(BiquadsContext), \ .init = name_##_init, \ + .activate = activate, \ .uninit = uninit, \ FILTER_INPUTS(inputs), \ FILTER_OUTPUTS(outputs), \ @@ -965,41 +1453,63 @@ const AVFilter ff_af_##name_ = { \ AVFILTER_DEFINE_CLASS(name); \ DEFINE_BIQUAD_FILTER_2(name, description, name) +#define WIDTH_OPTION(x) \ + {"width", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=x}, 0, 99999, FLAGS}, \ + {"w", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=x}, 0, 99999, FLAGS} + +#define WIDTH_TYPE_OPTION(x) \ + {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=x}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"}, \ + {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=x}, 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"} + +#define MIX_CHANNELS_NORMALIZE_OPTION(x, y, z) \ + {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=x}, 0, 1, FLAGS}, \ + {"m", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=x}, 0, 1, FLAGS}, \ + {"channels", "set channels to filter", OFFSET(ch_layout_str), AV_OPT_TYPE_STRING, {.str=y}, 0, 0, FLAGS}, \ + {"c", "set channels to filter", OFFSET(ch_layout_str), AV_OPT_TYPE_STRING, {.str=y}, 0, 0, FLAGS}, \ + {"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=z}, 0, 1, FLAGS}, \ + {"n", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=z}, 0, 1, FLAGS} + +#define TRANSFORM_OPTION(x) \ + {"transform", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=x}, 0, NB_TTYPE-1, AF, "transform_type"}, \ + {"a", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=x}, 0, NB_TTYPE-1, AF, "transform_type"}, \ + {"di", "direct form I", 0, AV_OPT_TYPE_CONST, {.i64=DI}, 0, 0, AF, "transform_type"}, \ + {"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"}, \ + {"tdi", "transposed direct form I", 0, AV_OPT_TYPE_CONST, {.i64=TDI}, 0, 0, AF, "transform_type"}, \ + {"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"}, \ + {"latt", "lattice-ladder form", 0, AV_OPT_TYPE_CONST, {.i64=LATT}, 0, 0, AF, "transform_type"}, \ + {"svf", "state variable filter form", 0, AV_OPT_TYPE_CONST, {.i64=SVF}, 0, 0, AF, "transform_type"}, \ + {"zdf", "zero-delay filter form", 0, AV_OPT_TYPE_CONST, {.i64=ZDF}, 0, 0, AF, "transform_type"} + +#define PRECISION_OPTION(x) \ + {"precision", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=x}, -1, 3, AF, "precision"}, \ + {"r", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=x}, -1, 3, AF, "precision"}, \ + {"auto", "automatic", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, AF, "precision"}, \ + {"s16", "signed 16-bit", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "precision"}, \ + {"s32", "signed 32-bit", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "precision"}, \ + {"f32", "floating-point single", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF, "precision"}, \ + {"f64", "floating-point double", 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, AF, "precision"} + +#define BLOCKSIZE_OPTION(x) \ + {"blocksize", "set the block size", OFFSET(block_samples), AV_OPT_TYPE_INT, {.i64=x}, 0, 32768, AF}, \ + {"b", "set the block size", OFFSET(block_samples), AV_OPT_TYPE_INT, {.i64=x}, 0, 32768, AF} + #if CONFIG_EQUALIZER_FILTER 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, 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, 99999, FLAGS}, - {"w", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 99999, FLAGS}, + WIDTH_TYPE_OPTION(QFACTOR), + WIDTH_OPTION(1.0), {"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}, - {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS}, - {"m", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 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}, - {"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, - {"n", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, - {"transform", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"}, - {"a", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"}, - {"di", "direct form I", 0, AV_OPT_TYPE_CONST, {.i64=DI}, 0, 0, AF, "transform_type"}, - {"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"}, - {"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"}, - {"latt", "lattice-ladder form", 0, AV_OPT_TYPE_CONST, {.i64=LATT}, 0, 0, AF, "transform_type"}, - {"svf", "state variable filter form", 0, AV_OPT_TYPE_CONST, {.i64=SVF}, 0, 0, AF, "transform_type"}, - {"precision", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, - {"r", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, - {"auto", "automatic", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, AF, "precision"}, - {"s16", "signed 16-bit", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "precision"}, - {"s32", "signed 32-bit", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "precision"}, - {"f32", "floating-point single", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF, "precision"}, - {"f64", "floating-point double", 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, AF, "precision"}, + MIX_CHANNELS_NORMALIZE_OPTION(1, "all", 0), + TRANSFORM_OPTION(DI), + PRECISION_OPTION(-1), + BLOCKSIZE_OPTION(0), {NULL} }; @@ -1009,39 +1519,16 @@ DEFINE_BIQUAD_FILTER(equalizer, "Apply two-pole peaking equalization (EQ) filter static const AVOption bass_lowshelf_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, 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}, + WIDTH_TYPE_OPTION(QFACTOR), + WIDTH_OPTION(0.5), {"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}, {"poles", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, AF}, {"p", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, AF}, - {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS}, - {"m", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 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}, - {"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, - {"n", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, - {"transform", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"}, - {"a", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"}, - {"di", "direct form I", 0, AV_OPT_TYPE_CONST, {.i64=DI}, 0, 0, AF, "transform_type"}, - {"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"}, - {"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"}, - {"latt", "lattice-ladder form", 0, AV_OPT_TYPE_CONST, {.i64=LATT}, 0, 0, AF, "transform_type"}, - {"svf", "state variable filter form", 0, AV_OPT_TYPE_CONST, {.i64=SVF}, 0, 0, AF, "transform_type"}, - {"precision", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, - {"r", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, - {"auto", "automatic", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, AF, "precision"}, - {"s16", "signed 16-bit", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "precision"}, - {"s32", "signed 32-bit", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "precision"}, - {"f32", "floating-point single", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF, "precision"}, - {"f64", "floating-point double", 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, AF, "precision"}, + MIX_CHANNELS_NORMALIZE_OPTION(1, "all", 0), + TRANSFORM_OPTION(DI), + PRECISION_OPTION(-1), + BLOCKSIZE_OPTION(0), {NULL} }; @@ -1054,47 +1541,24 @@ DEFINE_BIQUAD_FILTER_2(bass, "Boost or cut lower frequencies.", bass_lowshelf); DEFINE_BIQUAD_FILTER_2(lowshelf, "Apply a low shelf filter.", bass_lowshelf); #endif /* CONFIG_LOWSHELF_FILTER */ #endif /* CONFIG_BASS_FILTER || CONFIG LOWSHELF_FILTER */ -#if CONFIG_TREBLE_FILTER || CONFIG_HIGHSHELF_FILTER +#if CONFIG_TREBLE_FILTER || CONFIG_HIGHSHELF_FILTER || CONFIG_TILTSHELF_FILTER static const AVOption treble_highshelf_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, 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}, + WIDTH_TYPE_OPTION(QFACTOR), + WIDTH_OPTION(0.5), {"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}, {"poles", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, AF}, {"p", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, AF}, - {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS}, - {"m", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 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}, - {"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, - {"n", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, - {"transform", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"}, - {"a", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"}, - {"di", "direct form I", 0, AV_OPT_TYPE_CONST, {.i64=DI}, 0, 0, AF, "transform_type"}, - {"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"}, - {"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"}, - {"latt", "lattice-ladder form", 0, AV_OPT_TYPE_CONST, {.i64=LATT}, 0, 0, AF, "transform_type"}, - {"svf", "state variable filter form", 0, AV_OPT_TYPE_CONST, {.i64=SVF}, 0, 0, AF, "transform_type"}, - {"precision", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, - {"r", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, - {"auto", "automatic", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, AF, "precision"}, - {"s16", "signed 16-bit", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "precision"}, - {"s32", "signed 32-bit", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "precision"}, - {"f32", "floating-point single", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF, "precision"}, - {"f64", "floating-point double", 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, AF, "precision"}, + MIX_CHANNELS_NORMALIZE_OPTION(1, "all", 0), + TRANSFORM_OPTION(DI), + PRECISION_OPTION(-1), + BLOCKSIZE_OPTION(0), {NULL} }; -AVFILTER_DEFINE_CLASS_EXT(treble_highshelf, "treble/highshelf", +AVFILTER_DEFINE_CLASS_EXT(treble_highshelf, "treble/high/tiltshelf", treble_highshelf_options); #if CONFIG_TREBLE_FILTER @@ -1104,41 +1568,23 @@ DEFINE_BIQUAD_FILTER_2(treble, "Boost or cut upper frequencies.", treble_highshe #if CONFIG_HIGHSHELF_FILTER DEFINE_BIQUAD_FILTER_2(highshelf, "Apply a high shelf filter.", treble_highshelf); #endif /* CONFIG_HIGHSHELF_FILTER */ -#endif /* CONFIG_TREBLE_FILTER || CONFIG_HIGHSHELF_FILTER */ + +#if CONFIG_TILTSHELF_FILTER +DEFINE_BIQUAD_FILTER_2(tiltshelf, "Apply a tilt shelf filter.", treble_highshelf); +#endif +#endif /* CONFIG_TREBLE_FILTER || CONFIG_HIGHSHELF_FILTER || CONFIG_TILTSHELF_FILTER */ + #if CONFIG_BANDPASS_FILTER 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, 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, 99999, FLAGS}, - {"w", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS}, + WIDTH_TYPE_OPTION(QFACTOR), + WIDTH_OPTION(0.5), {"csg", "use constant skirt gain", OFFSET(csg), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, - {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS}, - {"m", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 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}, - {"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, - {"n", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, - {"transform", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"}, - {"a", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"}, - {"di", "direct form I", 0, AV_OPT_TYPE_CONST, {.i64=DI}, 0, 0, AF, "transform_type"}, - {"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"}, - {"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"}, - {"latt", "lattice-ladder form", 0, AV_OPT_TYPE_CONST, {.i64=LATT}, 0, 0, AF, "transform_type"}, - {"svf", "state variable filter form", 0, AV_OPT_TYPE_CONST, {.i64=SVF}, 0, 0, AF, "transform_type"}, - {"precision", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, - {"r", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, - {"auto", "automatic", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, AF, "precision"}, - {"s16", "signed 16-bit", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "precision"}, - {"s32", "signed 32-bit", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "precision"}, - {"f32", "floating-point single", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF, "precision"}, - {"f64", "floating-point double", 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, AF, "precision"}, + MIX_CHANNELS_NORMALIZE_OPTION(1, "all", 0), + TRANSFORM_OPTION(DI), + PRECISION_OPTION(-1), + BLOCKSIZE_OPTION(0), {NULL} }; @@ -1148,35 +1594,12 @@ 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, 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, 99999, FLAGS}, - {"w", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS}, - {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS}, - {"m", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 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}, - {"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, - {"n", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, - {"transform", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"}, - {"a", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"}, - {"di", "direct form I", 0, AV_OPT_TYPE_CONST, {.i64=DI}, 0, 0, AF, "transform_type"}, - {"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"}, - {"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"}, - {"latt", "lattice-ladder form", 0, AV_OPT_TYPE_CONST, {.i64=LATT}, 0, 0, AF, "transform_type"}, - {"svf", "state variable filter form", 0, AV_OPT_TYPE_CONST, {.i64=SVF}, 0, 0, AF, "transform_type"}, - {"precision", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, - {"r", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, - {"auto", "automatic", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, AF, "precision"}, - {"s16", "signed 16-bit", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "precision"}, - {"s32", "signed 32-bit", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "precision"}, - {"f32", "floating-point single", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF, "precision"}, - {"f64", "floating-point double", 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, AF, "precision"}, + WIDTH_TYPE_OPTION(QFACTOR), + WIDTH_OPTION(0.5), + MIX_CHANNELS_NORMALIZE_OPTION(1, "all", 0), + TRANSFORM_OPTION(DI), + PRECISION_OPTION(-1), + BLOCKSIZE_OPTION(0), {NULL} }; @@ -1186,37 +1609,14 @@ 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, 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}, + WIDTH_TYPE_OPTION(QFACTOR), + WIDTH_OPTION(0.707), {"poles", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, AF}, {"p", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, AF}, - {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS}, - {"m", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 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}, - {"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, - {"n", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, - {"transform", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"}, - {"a", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"}, - {"di", "direct form I", 0, AV_OPT_TYPE_CONST, {.i64=DI}, 0, 0, AF, "transform_type"}, - {"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"}, - {"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"}, - {"latt", "lattice-ladder form", 0, AV_OPT_TYPE_CONST, {.i64=LATT}, 0, 0, AF, "transform_type"}, - {"svf", "state variable filter form", 0, AV_OPT_TYPE_CONST, {.i64=SVF}, 0, 0, AF, "transform_type"}, - {"precision", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, - {"r", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, - {"auto", "automatic", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, AF, "precision"}, - {"s16", "signed 16-bit", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "precision"}, - {"s32", "signed 32-bit", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "precision"}, - {"f32", "floating-point single", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF, "precision"}, - {"f64", "floating-point double", 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, AF, "precision"}, + MIX_CHANNELS_NORMALIZE_OPTION(1, "all", 0), + TRANSFORM_OPTION(DI), + PRECISION_OPTION(-1), + BLOCKSIZE_OPTION(0), {NULL} }; @@ -1226,37 +1626,14 @@ 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, 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}, + WIDTH_TYPE_OPTION(QFACTOR), + WIDTH_OPTION(0.707), {"poles", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, AF}, {"p", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, AF}, - {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS}, - {"m", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 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}, - {"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, - {"n", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, - {"transform", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"}, - {"a", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"}, - {"di", "direct form I", 0, AV_OPT_TYPE_CONST, {.i64=DI}, 0, 0, AF, "transform_type"}, - {"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"}, - {"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"}, - {"latt", "lattice-ladder form", 0, AV_OPT_TYPE_CONST, {.i64=LATT}, 0, 0, AF, "transform_type"}, - {"svf", "state variable filter form", 0, AV_OPT_TYPE_CONST, {.i64=SVF}, 0, 0, AF, "transform_type"}, - {"precision", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, - {"r", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, - {"auto", "automatic", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, AF, "precision"}, - {"s16", "signed 16-bit", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "precision"}, - {"s32", "signed 32-bit", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "precision"}, - {"f32", "floating-point single", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF, "precision"}, - {"f64", "floating-point double", 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, AF, "precision"}, + MIX_CHANNELS_NORMALIZE_OPTION(1, "all", 0), + TRANSFORM_OPTION(DI), + PRECISION_OPTION(-1), + BLOCKSIZE_OPTION(0), {NULL} }; @@ -1266,37 +1643,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, 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}, - {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS}, - {"m", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 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}, - {"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, - {"n", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, + WIDTH_TYPE_OPTION(QFACTOR), + WIDTH_OPTION(0.707), + MIX_CHANNELS_NORMALIZE_OPTION(1, "all", 0), {"order", "set filter order", OFFSET(order), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS}, {"o", "set filter order", OFFSET(order), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS}, - {"transform", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"}, - {"a", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"}, - {"di", "direct form I", 0, AV_OPT_TYPE_CONST, {.i64=DI}, 0, 0, AF, "transform_type"}, - {"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"}, - {"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"}, - {"latt", "lattice-ladder form", 0, AV_OPT_TYPE_CONST, {.i64=LATT}, 0, 0, AF, "transform_type"}, - {"svf", "state variable filter form", 0, AV_OPT_TYPE_CONST, {.i64=SVF}, 0, 0, AF, "transform_type"}, - {"precision", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, - {"r", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, - {"auto", "automatic", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, AF, "precision"}, - {"s16", "signed 16-bit", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "precision"}, - {"s32", "signed 32-bit", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "precision"}, - {"f32", "floating-point single", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF, "precision"}, - {"f64", "floating-point double", 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, AF, "precision"}, + TRANSFORM_OPTION(DI), + PRECISION_OPTION(-1), {NULL} }; @@ -1310,26 +1663,10 @@ static const AVOption biquad_options[] = { {"b0", NULL, OFFSET(ob0), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS}, {"b1", NULL, OFFSET(ob1), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS}, {"b2", NULL, OFFSET(ob2), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS}, - {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS}, - {"m", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 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}, - {"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, - {"n", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, - {"transform", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"}, - {"a", "set transform type", OFFSET(transform_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_TTYPE-1, AF, "transform_type"}, - {"di", "direct form I", 0, AV_OPT_TYPE_CONST, {.i64=DI}, 0, 0, AF, "transform_type"}, - {"dii", "direct form II", 0, AV_OPT_TYPE_CONST, {.i64=DII}, 0, 0, AF, "transform_type"}, - {"tdii", "transposed direct form II", 0, AV_OPT_TYPE_CONST, {.i64=TDII}, 0, 0, AF, "transform_type"}, - {"latt", "lattice-ladder form", 0, AV_OPT_TYPE_CONST, {.i64=LATT}, 0, 0, AF, "transform_type"}, - {"svf", "state variable filter form", 0, AV_OPT_TYPE_CONST, {.i64=SVF}, 0, 0, AF, "transform_type"}, - {"precision", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, - {"r", "set filtering precision", OFFSET(precision), AV_OPT_TYPE_INT, {.i64=-1}, -1, 3, AF, "precision"}, - {"auto", "automatic", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, AF, "precision"}, - {"s16", "signed 16-bit", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AF, "precision"}, - {"s32", "signed 32-bit", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AF, "precision"}, - {"f32", "floating-point single", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, AF, "precision"}, - {"f64", "floating-point double", 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, AF, "precision"}, + MIX_CHANNELS_NORMALIZE_OPTION(1, "all", 0), + TRANSFORM_OPTION(DI), + PRECISION_OPTION(-1), + BLOCKSIZE_OPTION(0), {NULL} }; diff --git a/libavfilter/af_bs2b.c b/libavfilter/af_bs2b.c index 90ae846d9..20e6d8141 100644 --- a/libavfilter/af_bs2b.c +++ b/libavfilter/af_bs2b.c @@ -104,7 +104,7 @@ static int query_formats(AVFilterContext *ctx) }; int ret; - if (ff_add_channel_layout(&layouts, AV_CH_LAYOUT_STEREO) != 0) + if (ff_add_channel_layout(&layouts, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO) != 0) return AVERROR(ENOMEM); ret = ff_set_common_channel_layouts(ctx, layouts); if (ret < 0) diff --git a/libavfilter/af_channelmap.c b/libavfilter/af_channelmap.c index d3ab77920..eb173d20c 100644 --- a/libavfilter/af_channelmap.c +++ b/libavfilter/af_channelmap.c @@ -38,8 +38,8 @@ #include "internal.h" struct ChannelMap { - uint64_t in_channel; - uint64_t out_channel; + int in_channel; + int out_channel; int in_channel_idx; int out_channel_idx; }; @@ -59,7 +59,7 @@ typedef struct ChannelMapContext { const AVClass *class; char *mapping_str; char *channel_layout_str; - uint64_t output_layout; + AVChannelLayout output_layout; struct ChannelMap map[MAX_CH]; int nch; enum MappingMode mode; @@ -105,13 +105,13 @@ static int get_channel_idx(char **map, int *ch, char delim, int max_ch) return 0; } -static int get_channel(char **map, uint64_t *ch, char delim) +static int get_channel(char **map, int *ch, char delim) { char *next = split(*map, delim); if (!next && delim == '-') return AVERROR(EINVAL); - *ch = av_get_channel_layout(*map); - if (av_get_channel_layout_nb_channels(*ch) != 1) + *ch = av_channel_from_string(*map); + if (*ch < 0) return AVERROR(EINVAL); *map = next; return 0; @@ -167,7 +167,7 @@ static av_cold int channelmap_init(AVFilterContext *ctx) for (i = 0; i < map_entries; i++) { int in_ch_idx = -1, out_ch_idx = -1; - uint64_t in_ch = 0, out_ch = 0; + int in_ch = 0, out_ch = 0; static const char err[] = "Failed to parse channel map\n"; switch (mode) { case MAP_ONE_INT: @@ -198,13 +198,13 @@ static av_cold int channelmap_init(AVFilterContext *ctx) case MAP_PAIR_INT_STR: if (get_channel_idx(&mapping, &in_ch_idx, '-', MAX_CH) < 0 || get_channel(&mapping, &out_ch, separator) < 0 || - out_ch & out_ch_mask) { + (1ULL << out_ch) & out_ch_mask) { av_log(ctx, AV_LOG_ERROR, err); return AVERROR(EINVAL); } s->map[i].in_channel_idx = in_ch_idx; s->map[i].out_channel = out_ch; - out_ch_mask |= out_ch; + out_ch_mask |= 1ULL << out_ch; break; case MAP_PAIR_STR_INT: if (get_channel(&mapping, &in_ch, '-') < 0 || @@ -218,42 +218,57 @@ static av_cold int channelmap_init(AVFilterContext *ctx) case MAP_PAIR_STR_STR: if (get_channel(&mapping, &in_ch, '-') < 0 || get_channel(&mapping, &out_ch, separator) < 0 || - out_ch & out_ch_mask) { + (1ULL << out_ch) & out_ch_mask) { av_log(ctx, AV_LOG_ERROR, err); return AVERROR(EINVAL); } s->map[i].in_channel = in_ch; s->map[i].out_channel = out_ch; - out_ch_mask |= out_ch; + out_ch_mask |= 1ULL << out_ch; break; } } s->mode = mode; s->nch = map_entries; - s->output_layout = out_ch_mask ? out_ch_mask : - av_get_default_channel_layout(map_entries); + if (out_ch_mask) + av_channel_layout_from_mask(&s->output_layout, out_ch_mask); + else + av_channel_layout_default(&s->output_layout, map_entries); if (s->channel_layout_str) { - uint64_t fmt; - if ((fmt = av_get_channel_layout(s->channel_layout_str)) == 0) { - av_log(ctx, AV_LOG_ERROR, "Error parsing channel layout: '%s'.\n", + AVChannelLayout fmt = { 0 }; + int ret; + if ((ret = av_channel_layout_from_string(&fmt, s->channel_layout_str)) < 0) { +#if FF_API_OLD_CHANNEL_LAYOUT + uint64_t mask; +FF_DISABLE_DEPRECATION_WARNINGS + if ((mask = av_get_channel_layout(s->channel_layout_str)) == 0) { +#endif + av_log(ctx, AV_LOG_ERROR, "Error parsing channel layout: '%s'.\n", + s->channel_layout_str); + return AVERROR(EINVAL); +#if FF_API_OLD_CHANNEL_LAYOUT + } +FF_ENABLE_DEPRECATION_WARNINGS + av_log(ctx, AV_LOG_WARNING, "Channel layout '%s' uses a deprecated syntax.\n", s->channel_layout_str); - return AVERROR(EINVAL); + av_channel_layout_from_mask(&fmt, mask); +#endif } if (mode == MAP_NONE) { int i; - s->nch = av_get_channel_layout_nb_channels(fmt); + s->nch = fmt.nb_channels; for (i = 0; i < s->nch; i++) { s->map[i].in_channel_idx = i; s->map[i].out_channel_idx = i; } - } else if (out_ch_mask && out_ch_mask != fmt) { - av_get_channel_layout_string(buf, sizeof(buf), 0, out_ch_mask); + } else if (out_ch_mask && av_channel_layout_compare(&s->output_layout, &fmt)) { + av_channel_layout_describe(&s->output_layout, buf, sizeof(buf)); av_log(ctx, AV_LOG_ERROR, "Output channel layout '%s' does not match the list of channel mapped: '%s'.\n", s->channel_layout_str, buf); return AVERROR(EINVAL); - } else if (s->nch != av_get_channel_layout_nb_channels(fmt)) { + } else if (s->nch != fmt.nb_channels) { av_log(ctx, AV_LOG_ERROR, "Output channel layout %s does not match the number of channels mapped %d.\n", s->channel_layout_str, s->nch); @@ -261,7 +276,7 @@ static av_cold int channelmap_init(AVFilterContext *ctx) } s->output_layout = fmt; } - if (!s->output_layout) { + if (!s->output_layout.nb_channels) { av_log(ctx, AV_LOG_ERROR, "Output channel layout is not set and " "cannot be guessed from the maps.\n"); return AVERROR(EINVAL); @@ -269,8 +284,8 @@ static av_cold int channelmap_init(AVFilterContext *ctx) if (mode == MAP_PAIR_INT_STR || mode == MAP_PAIR_STR_STR) { for (i = 0; i < s->nch; i++) { - s->map[i].out_channel_idx = av_get_channel_layout_channel_index( - s->output_layout, s->map[i].out_channel); + s->map[i].out_channel_idx = av_channel_layout_index_from_channel( + &s->output_layout, s->map[i].out_channel); } } @@ -285,7 +300,7 @@ static int channelmap_query_formats(AVFilterContext *ctx) if ((ret = ff_set_common_formats (ctx, ff_planar_sample_fmts())) < 0 || (ret = ff_set_common_all_samplerates(ctx )) < 0 || - (ret = ff_add_channel_layout(&channel_layouts, s->output_layout)) < 0 || + (ret = ff_add_channel_layout(&channel_layouts, &s->output_layout)) < 0 || (ret = ff_channel_layouts_ref(channel_layouts, &ctx->outputs[0]->incfg.channel_layouts)) < 0) return ret; @@ -299,9 +314,9 @@ static int channelmap_filter_frame(AVFilterLink *inlink, AVFrame *buf) AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; const ChannelMapContext *s = ctx->priv; - const int nch_in = inlink->channels; + const int nch_in = inlink->ch_layout.nb_channels; const int nch_out = s->nch; - int ch; + int ch, ret; uint8_t *source_planes[MAX_CH]; memcpy(source_planes, buf->extended_data, @@ -336,8 +351,14 @@ static int channelmap_filter_frame(AVFilterLink *inlink, AVFrame *buf) memcpy(buf->data, buf->extended_data, FFMIN(FF_ARRAY_ELEMS(buf->data), nch_out) * sizeof(buf->data[0])); +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + buf->channels = outlink->ch_layout.nb_channels; buf->channel_layout = outlink->channel_layout; - buf->channels = outlink->channels; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + if ((ret = av_channel_layout_copy(&buf->ch_layout, &outlink->ch_layout)) < 0) + return ret; return ff_filter_frame(outlink, buf); } @@ -346,24 +367,23 @@ static int channelmap_config_input(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; ChannelMapContext *s = ctx->priv; - int nb_channels = inlink->channels; + int nb_channels = inlink->ch_layout.nb_channels; int i, err = 0; - const char *channel_name; + char channel_name[64]; char layout_name[256]; for (i = 0; i < s->nch; i++) { struct ChannelMap *m = &s->map[i]; if (s->mode == MAP_PAIR_STR_INT || s->mode == MAP_PAIR_STR_STR) { - m->in_channel_idx = av_get_channel_layout_channel_index( - inlink->channel_layout, m->in_channel); + m->in_channel_idx = av_channel_layout_index_from_channel( + &inlink->ch_layout, m->in_channel); } if (m->in_channel_idx < 0 || m->in_channel_idx >= nb_channels) { - av_get_channel_layout_string(layout_name, sizeof(layout_name), - nb_channels, inlink->channel_layout); + av_channel_layout_describe(&inlink->ch_layout, layout_name, sizeof(layout_name)); if (m->in_channel) { - channel_name = av_get_channel_name(m->in_channel); + av_channel_name(channel_name, sizeof(channel_name), m->in_channel); av_log(ctx, AV_LOG_ERROR, "input channel '%s' not available from input layout '%s'\n", channel_name, layout_name); diff --git a/libavfilter/af_channelsplit.c b/libavfilter/af_channelsplit.c index 1a2519dd3..b537e1380 100644 --- a/libavfilter/af_channelsplit.c +++ b/libavfilter/af_channelsplit.c @@ -30,13 +30,16 @@ #include "audio.h" #include "avfilter.h" +#include "filters.h" #include "formats.h" #include "internal.h" +#define MAX_CH 64 + typedef struct ChannelSplitContext { const AVClass *class; - uint64_t channel_layout; + AVChannelLayout channel_layout; char *channel_layout_str; char *channels_str; @@ -57,54 +60,72 @@ AVFILTER_DEFINE_CLASS(channelsplit); static av_cold int init(AVFilterContext *ctx) { ChannelSplitContext *s = ctx->priv; - uint64_t channel_layout; - int nb_channels; + AVChannelLayout channel_layout = { 0 }; int all = 0, ret = 0, i; - if (!(s->channel_layout = av_get_channel_layout(s->channel_layout_str))) { + if ((ret = av_channel_layout_from_string(&s->channel_layout, s->channel_layout_str)) < 0) { av_log(ctx, AV_LOG_ERROR, "Error parsing channel layout '%s'.\n", s->channel_layout_str); ret = AVERROR(EINVAL); goto fail; } - if (!strcmp(s->channels_str, "all")) { - nb_channels = av_get_channel_layout_nb_channels(s->channel_layout); - channel_layout = s->channel_layout; + if ((ret = av_channel_layout_copy(&channel_layout, &s->channel_layout)) < 0) + goto fail; all = 1; } else { - if ((ret = av_get_extended_channel_layout(s->channels_str, &channel_layout, &nb_channels)) < 0) - return ret; + if ((ret = av_channel_layout_from_string(&channel_layout, s->channels_str)) < 0) + goto fail; } - for (i = 0; i < nb_channels; i++) { - uint64_t channel = av_channel_layout_extract_channel(channel_layout, i); - AVFilterPad pad = { 0 }; + if (channel_layout.nb_channels > MAX_CH) { + av_log(ctx, AV_LOG_ERROR, "Too many channels\n"); + goto fail; + } + for (i = 0; i < channel_layout.nb_channels; i++) { + enum AVChannel channel = av_channel_layout_channel_from_index(&channel_layout, i); + char buf[64]; + AVFilterPad pad = { .flags = AVFILTERPAD_FLAG_FREE_NAME }; + + av_channel_name(buf, sizeof(buf), channel); pad.type = AVMEDIA_TYPE_AUDIO; - pad.name = av_get_channel_name(channel); + pad.name = av_strdup(buf); + if (!pad.name) { + ret = AVERROR(ENOMEM); + goto fail; + } if (all) { s->map[i] = i; } else { - if ((ret = av_get_channel_layout_channel_index(s->channel_layout, channel)) < 0) { + if ((ret = av_channel_layout_index_from_channel(&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; + pad.name, s->channel_layout_str); + av_freep(&pad.name); + goto fail; } s->map[i] = ret; } if ((ret = ff_append_outpad(ctx, &pad)) < 0) - return ret; + goto fail; } fail: + av_channel_layout_uninit(&channel_layout); return ret; } +static av_cold void uninit(AVFilterContext *ctx) +{ + ChannelSplitContext *s = ctx->priv; + + av_channel_layout_uninit(&s->channel_layout); +} + static int query_formats(AVFilterContext *ctx) { ChannelSplitContext *s = ctx->priv; @@ -115,15 +136,17 @@ static int query_formats(AVFilterContext *ctx) (ret = ff_set_common_all_samplerates(ctx)) < 0) return ret; - if ((ret = ff_add_channel_layout(&in_layouts, s->channel_layout)) < 0 || + if ((ret = ff_add_channel_layout(&in_layouts, &s->channel_layout)) < 0 || (ret = ff_channel_layouts_ref(in_layouts, &ctx->inputs[0]->outcfg.channel_layouts)) < 0) return ret; for (i = 0; i < ctx->nb_outputs; i++) { + AVChannelLayout channel_layout = { 0 }; AVFilterChannelLayouts *out_layouts = NULL; - uint64_t channel = av_channel_layout_extract_channel(s->channel_layout, s->map[i]); + enum AVChannel channel = av_channel_layout_channel_from_index(&s->channel_layout, s->map[i]); - if ((ret = ff_add_channel_layout(&out_layouts, channel)) < 0 || + if ((ret = av_channel_layout_from_mask(&channel_layout, 1ULL << channel)) < 0 || + (ret = ff_add_channel_layout(&out_layouts, &channel_layout)) < 0 || (ret = ff_channel_layouts_ref(out_layouts, &ctx->outputs[i]->incfg.channel_layouts)) < 0) return ret; } @@ -131,38 +154,88 @@ static int query_formats(AVFilterContext *ctx) return 0; } -static int filter_frame(AVFilterLink *inlink, AVFrame *buf) +static int filter_frame(AVFilterLink *outlink, AVFrame *buf) { - AVFilterContext *ctx = inlink->dst; + AVFilterContext *ctx = outlink->src; ChannelSplitContext *s = ctx->priv; - int i, ret = 0; + const int i = FF_OUTLINK_IDX(outlink); + enum AVChannel channel = av_channel_layout_channel_from_index(&buf->ch_layout, s->map[i]); + int ret; - for (i = 0; i < ctx->nb_outputs; i++) { - AVFrame *buf_out = av_frame_clone(buf); + AVFrame *buf_out = av_frame_clone(buf); + if (!buf_out) + return AVERROR(ENOMEM); - if (!buf_out) { - ret = AVERROR(ENOMEM); - break; + buf_out->data[0] = buf_out->extended_data[0] = buf_out->extended_data[s->map[i]]; + ret = av_channel_layout_from_mask(&buf_out->ch_layout, 1ULL << channel); + if (ret < 0) + return ret; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + buf_out->channel_layout = + av_channel_layout_extract_channel(buf->channel_layout, s->map[i]); + buf_out->channels = 1; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + + return ff_filter_frame(ctx->outputs[i], buf_out); +} + +static int activate(AVFilterContext *ctx) +{ + AVFilterLink *inlink = ctx->inputs[0]; + int status, ret; + AVFrame *in; + int64_t pts; + + for (int i = 0; i < ctx->nb_outputs; i++) { + FF_FILTER_FORWARD_STATUS_BACK_ALL(ctx->outputs[i], ctx); + } + + ret = ff_inlink_consume_frame(inlink, &in); + if (ret < 0) + return ret; + if (ret > 0) { + for (int i = 0; i < ctx->nb_outputs; i++) { + if (ff_outlink_get_status(ctx->outputs[i])) + continue; + + ret = filter_frame(ctx->outputs[i], in); + if (ret < 0) + break; } - 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, s->map[i]); - buf_out->channels = 1; - - ret = ff_filter_frame(ctx->outputs[i], buf_out); + av_frame_free(&in); if (ret < 0) - break; + return ret; } - av_frame_free(&buf); - return ret; + + if (ff_inlink_acknowledge_status(inlink, &status, &pts)) { + for (int i = 0; i < ctx->nb_outputs; i++) { + if (ff_outlink_get_status(ctx->outputs[i])) + continue; + ff_outlink_set_status(ctx->outputs[i], status, pts); + } + return 0; + } + + for (int i = 0; i < ctx->nb_outputs; i++) { + if (ff_outlink_get_status(ctx->outputs[i])) + continue; + + if (ff_outlink_frame_wanted(ctx->outputs[i])) { + ff_inlink_request_frame(inlink); + return 0; + } + } + + return FFERROR_NOT_READY; } static const AVFilterPad avfilter_af_channelsplit_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_AUDIO, - .filter_frame = filter_frame, }, }; @@ -172,6 +245,8 @@ const AVFilter ff_af_channelsplit = { .priv_size = sizeof(ChannelSplitContext), .priv_class = &channelsplit_class, .init = init, + .activate = activate, + .uninit = uninit, FILTER_INPUTS(avfilter_af_channelsplit_inputs), .outputs = NULL, FILTER_QUERY_FUNC(query_formats), diff --git a/libavfilter/af_chorus.c b/libavfilter/af_chorus.c index 68de692c4..19826cfb1 100644 --- a/libavfilter/af_chorus.c +++ b/libavfilter/af_chorus.c @@ -161,7 +161,7 @@ static int config_output(AVFilterLink *outlink) float sum_in_volume = 1.0; int n; - s->channels = outlink->channels; + s->channels = outlink->ch_layout.nb_channels; for (n = 0; n < s->num_chorus; n++) { int samples = (int) ((s->delays[n] + s->depths[n]) * outlink->sample_rate / 1000.0); @@ -184,15 +184,15 @@ static int config_output(AVFilterLink *outlink) if (s->in_gain * (sum_in_volume) > 1.0 / s->out_gain) av_log(ctx, AV_LOG_WARNING, "output gain can cause saturation or clipping of output\n"); - s->counter = av_calloc(outlink->channels, sizeof(*s->counter)); + s->counter = av_calloc(outlink->ch_layout.nb_channels, sizeof(*s->counter)); if (!s->counter) return AVERROR(ENOMEM); - s->phase = av_calloc(outlink->channels, sizeof(*s->phase)); + s->phase = av_calloc(outlink->ch_layout.nb_channels, sizeof(*s->phase)); if (!s->phase) return AVERROR(ENOMEM); - for (n = 0; n < outlink->channels; n++) { + for (n = 0; n < outlink->ch_layout.nb_channels; n++) { s->phase[n] = av_calloc(s->num_chorus, sizeof(int)); if (!s->phase[n]) return AVERROR(ENOMEM); @@ -201,7 +201,7 @@ static int config_output(AVFilterLink *outlink) s->fade_out = s->max_samples; return av_samples_alloc_array_and_samples(&s->chorusbuf, NULL, - outlink->channels, + outlink->ch_layout.nb_channels, s->max_samples, outlink->format, 0); } @@ -226,7 +226,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) av_frame_copy_props(out_frame, frame); } - for (c = 0; c < inlink->channels; c++) { + for (c = 0; c < inlink->ch_layout.nb_channels; c++) { const float *src = (const float *)frame->extended_data[c]; float *dst = (float *)out_frame->extended_data[c]; float *chorusbuf = (float *)s->chorusbuf[c]; @@ -280,7 +280,7 @@ static int request_frame(AVFilterLink *outlink) av_samples_set_silence(frame->extended_data, 0, frame->nb_samples, - outlink->channels, + outlink->ch_layout.nb_channels, frame->format); frame->pts = s->next_pts; diff --git a/libavfilter/af_compand.c b/libavfilter/af_compand.c index 2f8a58027..ba90d21ce 100644 --- a/libavfilter/af_compand.c +++ b/libavfilter/af_compand.c @@ -146,7 +146,7 @@ static int compand_nodelay(AVFilterContext *ctx, AVFrame *frame) { CompandContext *s = ctx->priv; AVFilterLink *inlink = ctx->inputs[0]; - const int channels = inlink->channels; + const int channels = inlink->ch_layout.nb_channels; const int nb_samples = frame->nb_samples; AVFrame *out_frame; int chan, i; @@ -192,7 +192,7 @@ static int compand_delay(AVFilterContext *ctx, AVFrame *frame) { CompandContext *s = ctx->priv; AVFilterLink *inlink = ctx->inputs[0]; - const int channels = inlink->channels; + const int channels = inlink->ch_layout.nb_channels; const int nb_samples = frame->nb_samples; int chan, i, av_uninit(dindex), oindex, av_uninit(count); AVFrame *out_frame = NULL; @@ -264,7 +264,7 @@ static int compand_drain(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; CompandContext *s = ctx->priv; - const int channels = outlink->channels; + const int channels = outlink->ch_layout.nb_channels; AVFrame *frame = NULL; int chan, i, dindex; @@ -302,7 +302,7 @@ static int config_output(AVFilterLink *outlink) const int sample_rate = outlink->sample_rate; double radius = s->curve_dB * M_LN10 / 20.0; char *p, *saveptr = NULL; - const int channels = outlink->channels; + const int channels = outlink->ch_layout.nb_channels; int nb_attacks, nb_decays, nb_points; int new_nb_items, num; int i; @@ -503,7 +503,13 @@ static int config_output(AVFilterLink *outlink) s->delay_frame->format = outlink->format; s->delay_frame->nb_samples = s->delay_samples; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS s->delay_frame->channel_layout = outlink->channel_layout; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + if ((err = av_channel_layout_copy(&s->delay_frame->ch_layout, &outlink->ch_layout)) < 0) + return err; err = av_frame_get_buffer(s->delay_frame, 0); if (err) diff --git a/libavfilter/af_compensationdelay.c b/libavfilter/af_compensationdelay.c index 6a58fd21b..c59ebdca9 100644 --- a/libavfilter/af_compensationdelay.c +++ b/libavfilter/af_compensationdelay.c @@ -40,7 +40,7 @@ typedef struct CompensationDelayContext { } CompensationDelayContext; #define OFFSET(x) offsetof(CompensationDelayContext, x) -#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define A (AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM) static const AVOption compensationdelay_options[] = { { "mm", "set mm distance", OFFSET(distance_mm), AV_OPT_TYPE_INT, {.i64=0}, 0, 10, A }, @@ -68,6 +68,7 @@ static int config_input(AVFilterLink *inlink) AVFilterContext *ctx = inlink->dst; CompensationDelayContext *s = ctx->priv; unsigned min_size, new_size = 1; + int ret; s->delay = (s->distance_m * 100. + s->distance_cm * 1. + s->distance_mm * .1) * COMP_DELAY_SOUND_FRONT_DELAY(s->temp) * inlink->sample_rate; @@ -83,7 +84,14 @@ static int config_input(AVFilterLink *inlink) s->buf_size = new_size; s->delay_frame->format = inlink->format; s->delay_frame->nb_samples = new_size; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS s->delay_frame->channel_layout = inlink->channel_layout; + s->delay_frame->channels = inlink->ch_layout.nb_channels; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + if ((ret = av_channel_layout_copy(&s->delay_frame->ch_layout, &inlink->ch_layout)) < 0) + return ret; return av_frame_get_buffer(s->delay_frame, 0); } @@ -91,6 +99,7 @@ static int config_input(AVFilterLink *inlink) static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; CompensationDelayContext *s = ctx->priv; const unsigned b_mask = s->buf_size - 1; const unsigned buf_size = s->buf_size; @@ -101,14 +110,14 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) AVFrame *out; int n, ch; - out = ff_get_audio_buffer(ctx->outputs[0], in->nb_samples); + out = ff_get_audio_buffer(outlink, in->nb_samples); if (!out) { av_frame_free(&in); return AVERROR(ENOMEM); } av_frame_copy_props(out, in); - for (ch = 0; ch < inlink->channels; ch++) { + for (ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { const double *src = (const double *)in->extended_data[ch]; double *dst = (double *)out->extended_data[ch]; double *buffer = (double *)s->delay_frame->extended_data[ch]; @@ -127,8 +136,30 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) } s->w_ptr = w_ptr; + if (ctx->is_disabled) { + av_frame_free(&out); + return ff_filter_frame(outlink, in); + } + av_frame_free(&in); - return ff_filter_frame(ctx->outputs[0], out); + return ff_filter_frame(outlink, out); +} + +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + CompensationDelayContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + s->delay = (s->distance_m * 100. + s->distance_cm * 1. + s->distance_mm * .1) * + COMP_DELAY_SOUND_FRONT_DELAY(s->temp) * outlink->sample_rate; + + return 0; } static av_cold void uninit(AVFilterContext *ctx) @@ -163,4 +194,6 @@ const AVFilter ff_af_compensationdelay = { FILTER_INPUTS(compensationdelay_inputs), FILTER_OUTPUTS(compensationdelay_outputs), FILTER_SINGLE_SAMPLEFMT(AV_SAMPLE_FMT_DBLP), + .process_command = process_command, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, }; diff --git a/libavfilter/af_crossfeed.c b/libavfilter/af_crossfeed.c index ecfbb978d..9a518e525 100644 --- a/libavfilter/af_crossfeed.c +++ b/libavfilter/af_crossfeed.c @@ -21,6 +21,7 @@ #include "libavutil/opt.h" #include "avfilter.h" #include "audio.h" +#include "filters.h" #include "formats.h" typedef struct CrossfeedContext { @@ -31,11 +32,19 @@ typedef struct CrossfeedContext { double slope; double level_in; double level_out; + int block_samples; + int block_size; double a0, a1, a2; double b0, b1, b2; double w1, w2; + + int64_t pts; + int nb_samples; + + double *mid; + double *side[3]; } CrossfeedContext; static int query_formats(AVFilterContext *ctx) @@ -46,7 +55,7 @@ static int query_formats(AVFilterContext *ctx) if ((ret = ff_add_format (&formats, AV_SAMPLE_FMT_DBL )) < 0 || (ret = ff_set_common_formats (ctx , formats )) < 0 || - (ret = ff_add_channel_layout (&layout , AV_CH_LAYOUT_STEREO)) < 0 || + (ret = ff_add_channel_layout (&layout , &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO)) < 0 || (ret = ff_set_common_channel_layouts (ctx , layout )) < 0 || (ret = ff_set_common_all_samplerates (ctx )) < 0) return ret; @@ -77,10 +86,50 @@ static int config_input(AVFilterLink *inlink) s->b1 /= s->a0; s->b2 /= s->a0; + if (s->block_samples == 0 && s->block_size > 0) { + s->block_samples = s->block_size; + s->mid = av_calloc(s->block_samples * 2, sizeof(*s->mid)); + for (int i = 0; i < 3; i++) { + s->side[i] = av_calloc(s->block_samples * 2, sizeof(*s->side[0])); + if (!s->side[i]) + return AVERROR(ENOMEM); + } + } + return 0; } -static int filter_frame(AVFilterLink *inlink, AVFrame *in) +static void reverse_samples(double *dst, const double *src, + int nb_samples) +{ + for (int i = 0, j = nb_samples - 1; i < nb_samples; i++, j--) + dst[i] = src[j]; +} + +static void filter_samples(double *dst, const double *src, + int nb_samples, + double b0, double b1, double b2, + double a1, double a2, + double *sw1, double *sw2) +{ + double w1 = *sw1; + double w2 = *sw2; + + for (int n = 0; n < nb_samples; n++) { + double side = src[n]; + double oside = side * b0 + w1; + + w1 = b1 * side + w2 + a1 * oside; + w2 = b2 * side + a2 * oside; + + dst[n] = oside; + } + + *sw1 = w1; + *sw2 = w2; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in, int eof) { AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; @@ -94,13 +143,13 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) const double a1 = -s->a1; const double a2 = -s->a2; AVFrame *out; + int drop = 0; double *dst; - int n; - if (av_frame_is_writable(in)) { + if (av_frame_is_writable(in) && s->block_samples == 0) { out = in; } else { - out = ff_get_audio_buffer(outlink, in->nb_samples); + out = ff_get_audio_buffer(outlink, s->block_samples > 0 ? s->block_samples : in->nb_samples); if (!out) { av_frame_free(&in); return AVERROR(ENOMEM); @@ -109,26 +158,163 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) } dst = (double *)out->data[0]; - for (n = 0; n < out->nb_samples; n++, src += 2, dst += 2) { - double mid = (src[0] + src[1]) * level_in * .5; - double side = (src[0] - src[1]) * level_in * .5; - double oside = side * b0 + s->w1; + if (s->block_samples > 0 && s->pts == AV_NOPTS_VALUE) + drop = 1; - s->w1 = b1 * side + s->w2 + a1 * oside; - s->w2 = b2 * side + a2 * oside; + if (s->block_samples == 0) { + double w1 = s->w1; + double w2 = s->w2; - if (ctx->is_disabled) { - dst[0] = src[0]; - dst[1] = src[1]; - } else { - dst[0] = (mid + oside) * level_out; - dst[1] = (mid - oside) * level_out; + for (int n = 0; n < out->nb_samples; n++, src += 2, dst += 2) { + double mid = (src[0] + src[1]) * level_in * .5; + double side = (src[0] - src[1]) * level_in * .5; + double oside = side * b0 + w1; + + w1 = b1 * side + w2 + a1 * oside; + w2 = b2 * side + a2 * oside; + + if (ctx->is_disabled) { + dst[0] = src[0]; + dst[1] = src[1]; + } else { + dst[0] = (mid + oside) * level_out; + dst[1] = (mid - oside) * level_out; + } } + + s->w1 = w1; + s->w2 = w2; + } else if (eof) { + const double *src = (const double *)in->data[0]; + double *ssrc = s->side[1] + s->block_samples; + double *msrc = s->mid; + + for (int n = 0; n < out->nb_samples; n++, src += 2, dst += 2) { + if (ctx->is_disabled) { + dst[0] = src[0]; + dst[1] = src[1]; + } else { + dst[0] = (msrc[n] + ssrc[n]) * level_out; + dst[1] = (msrc[n] - ssrc[n]) * level_out; + } + } + } else { + double *mdst = s->mid + s->block_samples; + double *sdst = s->side[0] + s->block_samples; + double *ssrc = s->side[0]; + double *msrc = s->mid; + double w1 = s->w1; + double w2 = s->w2; + + for (int n = 0; n < out->nb_samples; n++, src += 2) { + mdst[n] = (src[0] + src[1]) * level_in * .5; + sdst[n] = (src[0] - src[1]) * level_in * .5; + } + + sdst = s->side[1]; + filter_samples(sdst, ssrc, s->block_samples, + b0, b1, b2, a1, a2, + &w1, &w2); + s->w1 = w1; + s->w2 = w2; + + ssrc = s->side[0] + s->block_samples; + sdst = s->side[1] + s->block_samples; + filter_samples(sdst, ssrc, s->block_samples, + b0, b1, b2, a1, a2, + &w1, &w2); + + reverse_samples(s->side[2], s->side[1], s->block_samples * 2); + w1 = w2 = 0.; + filter_samples(s->side[2], s->side[2], s->block_samples * 2, + b0, b1, b2, a1, a2, + &w1, &w2); + + reverse_samples(s->side[1], s->side[2], s->block_samples * 2); + + src = (const double *)in->data[0]; + ssrc = s->side[1]; + for (int n = 0; n < out->nb_samples; n++, src += 2, dst += 2) { + if (ctx->is_disabled) { + dst[0] = src[0]; + dst[1] = src[1]; + } else { + dst[0] = (msrc[n] + ssrc[n]) * level_out; + dst[1] = (msrc[n] - ssrc[n]) * level_out; + } + } + + memmove(s->mid, s->mid + s->block_samples, + s->block_samples * sizeof(*s->mid)); + memmove(s->side[0], s->side[0] + s->block_samples, + s->block_samples * sizeof(*s->side[0])); + } + + if (s->block_samples > 0) { + int nb_samples = in->nb_samples; + int64_t pts = in->pts; + + out->pts = s->pts; + out->nb_samples = s->nb_samples; + s->pts = pts; + s->nb_samples = nb_samples; } if (out != in) av_frame_free(&in); - return ff_filter_frame(outlink, out); + if (!drop) { + return ff_filter_frame(outlink, out); + } else { + av_frame_free(&out); + ff_filter_set_ready(ctx, 10); + return 0; + } +} + +static int activate(AVFilterContext *ctx) +{ + AVFilterLink *inlink = ctx->inputs[0]; + AVFilterLink *outlink = ctx->outputs[0]; + CrossfeedContext *s = ctx->priv; + AVFrame *in = NULL; + int64_t pts; + int status; + int ret; + + FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); + + if (s->block_samples > 0) { + ret = ff_inlink_consume_samples(inlink, s->block_samples, s->block_samples, &in); + } else { + ret = ff_inlink_consume_frame(inlink, &in); + } + if (ret < 0) + return ret; + if (ret > 0) + return filter_frame(inlink, in, 0); + + if (s->block_samples > 0 && ff_inlink_queued_samples(inlink) >= s->block_samples) { + ff_filter_set_ready(ctx, 10); + return 0; + } + + if (ff_inlink_acknowledge_status(inlink, &status, &pts)) { + if (s->block_samples > 0) { + AVFrame *in = ff_get_audio_buffer(outlink, s->block_samples); + if (!in) + return AVERROR(ENOMEM); + + ret = filter_frame(inlink, in, 1); + } + + ff_outlink_set_status(outlink, status, pts); + + return ret; + } + + FF_FILTER_FORWARD_WANTED(outlink, inlink); + + return FFERROR_NOT_READY; } static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, @@ -143,8 +329,18 @@ static int process_command(AVFilterContext *ctx, const char *cmd, const char *ar return config_input(ctx->inputs[0]); } +static av_cold void uninit(AVFilterContext *ctx) +{ + CrossfeedContext *s = ctx->priv; + + av_freep(&s->mid); + for (int i = 0; i < 3; i++) + av_freep(&s->side[i]); +} + #define OFFSET(x) offsetof(CrossfeedContext, x) #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM +#define AF AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM static const AVOption crossfeed_options[] = { { "strength", "set crossfeed strength", OFFSET(strength), AV_OPT_TYPE_DOUBLE, {.dbl=.2}, 0, 1, FLAGS }, @@ -152,6 +348,7 @@ static const AVOption crossfeed_options[] = { { "slope", "set curve slope", OFFSET(slope), AV_OPT_TYPE_DOUBLE, {.dbl=.5}, .01, 1, FLAGS }, { "level_in", "set level in", OFFSET(level_in), AV_OPT_TYPE_DOUBLE, {.dbl=.9}, 0, 1, FLAGS }, { "level_out", "set level out", OFFSET(level_out), AV_OPT_TYPE_DOUBLE, {.dbl=1.}, 0, 1, FLAGS }, + { "block_size", "set the block size", OFFSET(block_size),AV_OPT_TYPE_INT, {.i64=0}, 0, 32768, AF }, { NULL } }; @@ -161,7 +358,6 @@ static const AVFilterPad inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_AUDIO, - .filter_frame = filter_frame, .config_props = config_input, }, }; @@ -178,6 +374,8 @@ const AVFilter ff_af_crossfeed = { .description = NULL_IF_CONFIG_SMALL("Apply headphone crossfeed filter."), .priv_size = sizeof(CrossfeedContext), .priv_class = &crossfeed_class, + .activate = activate, + .uninit = uninit, FILTER_INPUTS(inputs), FILTER_OUTPUTS(outputs), FILTER_QUERY_FUNC(query_formats), diff --git a/libavfilter/af_crystalizer.c b/libavfilter/af_crystalizer.c index 8d967fd62..449f24a08 100644 --- a/libavfilter/af_crystalizer.c +++ b/libavfilter/af_crystalizer.c @@ -52,197 +52,91 @@ typedef struct ThreadData { float mult; } ThreadData; -static av_always_inline int filter_flt(AVFilterContext *ctx, void *arg, - int jobnr, int nb_jobs, - int inverse, int clip) -{ - ThreadData *td = arg; - void **d = td->d; - void **p = td->p; - const void **s = td->s; - const int nb_samples = td->nb_samples; - const int channels = td->channels; - const float mult = td->mult; - const float scale = 1.f / (-mult + 1.f); - const int start = (channels * jobnr) / nb_jobs; - const int end = (channels * (jobnr+1)) / nb_jobs; - float *prv = p[0]; - int n, c; - - for (c = start; c < end; c++) { - const float *src = s[0]; - float *dst = d[0]; - - for (n = 0; n < nb_samples; n++) { - float current = src[c]; - - if (inverse) { - dst[c] = (current - prv[c] * mult) * scale; - prv[c] = dst[c]; - } else { - dst[c] = current + (current - prv[c]) * mult; - prv[c] = current; - } - if (clip) { - dst[c] = av_clipf(dst[c], -1.f, 1.f); - } - - dst += channels; - src += channels; - } - } - - return 0; +#define filters(fmt, type, inverse, clp, inverset, clip, one, clip_fn, packed) \ +static int filter_## inverse ##_## fmt ##_## clp(AVFilterContext *ctx, \ + void *arg, int jobnr,\ + int nb_jobs) \ +{ \ + ThreadData *td = arg; \ + void **d = td->d; \ + void **p = td->p; \ + const void **s = td->s; \ + const int nb_samples = td->nb_samples; \ + const int channels = td->channels; \ + const type mult = td->mult; \ + const type scale = one / (-mult + one); \ + const int start = (channels * jobnr) / nb_jobs; \ + const int end = (channels * (jobnr+1)) / nb_jobs; \ + \ + if (packed) { \ + type *prv = p[0]; \ + for (int c = start; c < end; c++) { \ + const type *src = s[0]; \ + type *dst = d[0]; \ + \ + for (int n = 0; n < nb_samples; n++) { \ + type current = src[c]; \ + \ + if (inverset) { \ + dst[c] = (current - prv[c] * mult) * scale; \ + prv[c] = dst[c]; \ + } else { \ + dst[c] = current + (current - prv[c]) * mult; \ + prv[c] = current; \ + } \ + if (clip) { \ + dst[c] = clip_fn(dst[c], -one, one); \ + } \ + \ + dst += channels; \ + src += channels; \ + } \ + } \ + } else { \ + for (int c = start; c < end; c++) { \ + const type *src = s[c]; \ + type *dst = d[c]; \ + type *prv = p[c]; \ + \ + for (int n = 0; n < nb_samples; n++) { \ + type current = src[n]; \ + \ + if (inverset) { \ + dst[n] = (current - prv[0] * mult) * scale; \ + prv[0] = dst[n]; \ + } else { \ + dst[n] = current + (current - prv[0]) * mult; \ + prv[0] = current; \ + } \ + if (clip) { \ + dst[n] = clip_fn(dst[n], -one, one); \ + } \ + } \ + } \ + } \ + \ + return 0; \ } -static av_always_inline int filter_dbl(AVFilterContext *ctx, void *arg, - int jobnr, int nb_jobs, - int inverse, int clip) -{ - ThreadData *td = arg; - void **d = td->d; - void **p = td->p; - const void **s = td->s; - const int nb_samples = td->nb_samples; - const int channels = td->channels; - const double mult = td->mult; - const double scale = 1.0 / (-mult + 1.0); - const int start = (channels * jobnr) / nb_jobs; - const int end = (channels * (jobnr+1)) / nb_jobs; - double *prv = p[0]; - int n, c; +filters(flt, float, inverse, noclip, 1, 0, 1.f, av_clipf, 1) +filters(flt, float, inverse, clip, 1, 1, 1.f, av_clipf, 1) +filters(flt, float, noinverse, noclip, 0, 0, 1.f, av_clipf, 1) +filters(flt, float, noinverse, clip, 0, 1, 1.f, av_clipf, 1) - for (c = start; c < end; c++) { - const double *src = s[0]; - double *dst = d[0]; +filters(fltp, float, inverse, noclip, 1, 0, 1.f, av_clipf, 0) +filters(fltp, float, inverse, clip, 1, 1, 1.f, av_clipf, 0) +filters(fltp, float, noinverse, noclip, 0, 0, 1.f, av_clipf, 0) +filters(fltp, float, noinverse, clip, 0, 1, 1.f, av_clipf, 0) - for (n = 0; n < nb_samples; n++) { - double current = src[c]; +filters(dbl, double, inverse, noclip, 1, 0, 1.0, av_clipd, 1) +filters(dbl, double, inverse, clip, 1, 1, 1.0, av_clipd, 1) +filters(dbl, double, noinverse, noclip, 0, 0, 1.0, av_clipd, 1) +filters(dbl, double, noinverse, clip, 0, 1, 1.0, av_clipd, 1) - if (inverse) { - dst[c] = (current - prv[c] * mult) * scale; - prv[c] = dst[c]; - } else { - dst[c] = current + (current - prv[c]) * mult; - prv[c] = current; - } - if (clip) { - dst[c] = av_clipd(dst[c], -1., 1.); - } - - dst += channels; - src += channels; - } - } - - return 0; -} - -static av_always_inline int filter_fltp(AVFilterContext *ctx, void *arg, - int jobnr, int nb_jobs, - int inverse, int clip) -{ - ThreadData *td = arg; - void **d = td->d; - void **p = td->p; - const void **s = td->s; - const int nb_samples = td->nb_samples; - const int channels = td->channels; - const float mult = td->mult; - const float scale = 1.f / (-mult + 1.f); - const int start = (channels * jobnr) / nb_jobs; - const int end = (channels * (jobnr+1)) / nb_jobs; - int n, c; - - for (c = start; c < end; c++) { - const float *src = s[c]; - float *dst = d[c]; - float *prv = p[c]; - - for (n = 0; n < nb_samples; n++) { - float current = src[n]; - - if (inverse) { - dst[n] = (current - prv[0] * mult) * scale; - prv[0] = dst[n]; - } else { - dst[n] = current + (current - prv[0]) * mult; - prv[0] = current; - } - if (clip) { - dst[n] = av_clipf(dst[n], -1.f, 1.f); - } - } - } - - return 0; -} - -static av_always_inline int filter_dblp(AVFilterContext *ctx, void *arg, - int jobnr, int nb_jobs, - int inverse, int clip) -{ - ThreadData *td = arg; - void **d = td->d; - void **p = td->p; - const void **s = td->s; - const int nb_samples = td->nb_samples; - const int channels = td->channels; - const double mult = td->mult; - const double scale = 1.0 / (-mult + 1.0); - const int start = (channels * jobnr) / nb_jobs; - const int end = (channels * (jobnr+1)) / nb_jobs; - int n, c; - - for (c = start; c < end; c++) { - const double *src = s[c]; - double *dst = d[c]; - double *prv = p[c]; - - for (n = 0; n < nb_samples; n++) { - double current = src[n]; - - if (inverse) { - dst[n] = (current - prv[0] * mult) * scale; - prv[0] = dst[n]; - } else { - dst[n] = current + (current - prv[0]) * mult; - prv[0] = current; - } - if (clip) { - dst[n] = av_clipd(dst[n], -1., 1.); - } - } - } - - return 0; -} - -#define filters(fmt, inverse, clip, i, c) \ -static int filter_## inverse ##_## fmt ##_## clip(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \ -{ \ - return filter_## fmt(ctx, arg, jobnr, nb_jobs, i, c); \ -} - -filters(flt, inverse, noclip, 1, 0) -filters(flt, inverse, clip, 1, 1) -filters(flt, noinverse, noclip, 0, 0) -filters(flt, noinverse, clip, 0, 1) - -filters(fltp, inverse, noclip, 1, 0) -filters(fltp, inverse, clip, 1, 1) -filters(fltp, noinverse, noclip, 0, 0) -filters(fltp, noinverse, clip, 0, 1) - -filters(dbl, inverse, noclip, 1, 0) -filters(dbl, inverse, clip, 1, 1) -filters(dbl, noinverse, noclip, 0, 0) -filters(dbl, noinverse, clip, 0, 1) - -filters(dblp, inverse, noclip, 1, 0) -filters(dblp, inverse, clip, 1, 1) -filters(dblp, noinverse, noclip, 0, 0) -filters(dblp, noinverse, clip, 0, 1) +filters(dblp, double, inverse, noclip, 1, 0, 1.0, av_clipd, 0) +filters(dblp, double, inverse, clip, 1, 1, 1.0, av_clipd, 0) +filters(dblp, double, noinverse, noclip, 0, 0, 1.0, av_clipd, 0) +filters(dblp, double, noinverse, clip, 0, 1, 1.0, av_clipd, 0) static int config_input(AVFilterLink *inlink) { @@ -312,10 +206,10 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) td.s = (const void **)in->extended_data; td.p = (void **)s->prev->extended_data; td.nb_samples = in->nb_samples; - td.channels = in->channels; + td.channels = in->ch_layout.nb_channels; td.mult = ctx->is_disabled ? 0.f : s->mult; ff_filter_execute(ctx, s->filter[td.mult >= 0.f][s->clip], &td, NULL, - FFMIN(inlink->channels, ff_filter_get_nb_threads(ctx))); + FFMIN(inlink->ch_layout.nb_channels, ff_filter_get_nb_threads(ctx))); if (out != in) av_frame_free(&in); @@ -330,18 +224,6 @@ static av_cold void uninit(AVFilterContext *ctx) av_frame_free(&s->prev); } -static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, - char *res, int res_len, int flags) -{ - int ret; - - ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); - if (ret < 0) - return ret; - - return config_input(ctx->inputs[0]); -} - static const AVFilterPad inputs[] = { { .name = "default", @@ -368,7 +250,7 @@ const AVFilter ff_af_crystalizer = { FILTER_OUTPUTS(outputs), FILTER_SAMPLEFMTS(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBLP), - .process_command = process_command, + .process_command = ff_filter_process_command, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, }; diff --git a/libavfilter/af_dcshift.c b/libavfilter/af_dcshift.c index da7c16550..480f01f4a 100644 --- a/libavfilter/af_dcshift.c +++ b/libavfilter/af_dcshift.c @@ -73,7 +73,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) } if (s->limitergain > 0) { - for (i = 0; i < inlink->channels; i++) { + for (i = 0; i < inlink->ch_layout.nb_channels; i++) { const int32_t *src = (int32_t *)in->extended_data[i]; int32_t *dst = (int32_t *)out->extended_data[i]; @@ -98,7 +98,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) } } } else { - for (i = 0; i < inlink->channels; i++) { + for (i = 0; i < inlink->ch_layout.nb_channels; i++) { const int32_t *src = (int32_t *)in->extended_data[i]; int32_t *dst = (int32_t *)out->extended_data[i]; diff --git a/libavfilter/af_deesser.c b/libavfilter/af_deesser.c index 1093e242d..cdef83715 100644 --- a/libavfilter/af_deesser.c +++ b/libavfilter/af_deesser.c @@ -73,11 +73,11 @@ static int config_input(AVFilterLink *inlink) AVFilterContext *ctx = inlink->dst; DeesserContext *s = ctx->priv; - s->chan = av_calloc(inlink->channels, sizeof(*s->chan)); + s->chan = av_calloc(inlink->ch_layout.nb_channels, sizeof(*s->chan)); if (!s->chan) return AVERROR(ENOMEM); - for (int i = 0; i < inlink->channels; i++) { + for (int i = 0; i < inlink->ch_layout.nb_channels; i++) { DeesserChannel *chan = &s->chan[i]; chan->ratioA = chan->ratioB = 1.0; @@ -104,7 +104,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) av_frame_copy_props(out, in); } - for (int ch = 0; ch < inlink->channels; ch++) { + for (int ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { DeesserChannel *dec = &s->chan[ch]; double *src = (double *)in->extended_data[ch]; double *dst = (double *)out->extended_data[ch]; diff --git a/libavfilter/af_dialoguenhance.c b/libavfilter/af_dialoguenhance.c new file mode 100644 index 000000000..6ae3162f3 --- /dev/null +++ b/libavfilter/af_dialoguenhance.c @@ -0,0 +1,407 @@ +/* + * Copyright (c) 2022 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 "libavutil/tx.h" +#include "audio.h" +#include "avfilter.h" +#include "filters.h" +#include "internal.h" +#include "window_func.h" + +#include + +typedef struct AudioDialogueEnhancementContext { + const AVClass *class; + + double original, enhance, voice; + + int fft_size; + int overlap; + + float *window; + float prev_vad; + + AVFrame *in; + AVFrame *in_frame; + AVFrame *out_dist_frame; + AVFrame *windowed_frame; + AVFrame *windowed_out; + AVFrame *windowed_prev; + AVFrame *center_frame; + + AVTXContext *tx_ctx[2], *itx_ctx; + av_tx_fn tx_fn, itx_fn; +} AudioDialogueEnhanceContext; + +#define OFFSET(x) offsetof(AudioDialogueEnhanceContext, x) +#define FLAGS AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_RUNTIME_PARAM + +static const AVOption dialoguenhance_options[] = { + { "original", "set original center factor", OFFSET(original), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS }, + { "enhance", "set dialogue enhance factor",OFFSET(enhance), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 3, FLAGS }, + { "voice", "set voice detection factor", OFFSET(voice), AV_OPT_TYPE_DOUBLE, {.dbl=2}, 2,32, FLAGS }, + {NULL} +}; + +AVFILTER_DEFINE_CLASS(dialoguenhance); + +static int query_formats(AVFilterContext *ctx) +{ + AVFilterFormats *formats = NULL; + AVFilterChannelLayouts *in_layout = NULL, *out_layout = NULL; + int ret; + + if ((ret = ff_add_format (&formats, AV_SAMPLE_FMT_FLTP )) < 0 || + (ret = ff_set_common_formats (ctx , formats )) < 0 || + (ret = ff_add_channel_layout (&in_layout , &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO)) < 0 || + (ret = ff_channel_layouts_ref(in_layout, &ctx->inputs[0]->outcfg.channel_layouts)) < 0 || + (ret = ff_add_channel_layout (&out_layout , &(AVChannelLayout)AV_CHANNEL_LAYOUT_SURROUND)) < 0 || + (ret = ff_channel_layouts_ref(out_layout, &ctx->outputs[0]->incfg.channel_layouts)) < 0) + return ret; + + return ff_set_common_all_samplerates(ctx); +} + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + AudioDialogueEnhanceContext *s = ctx->priv; + float scale = 1.f, iscale, overlap; + int ret; + + s->fft_size = inlink->sample_rate > 100000 ? 8192 : inlink->sample_rate > 50000 ? 4096 : 2048; + s->overlap = s->fft_size / 4; + + s->window = av_calloc(s->fft_size, sizeof(*s->window)); + if (!s->window) + return AVERROR(ENOMEM); + + s->in_frame = ff_get_audio_buffer(inlink, s->fft_size * 4); + s->center_frame = ff_get_audio_buffer(inlink, s->fft_size * 4); + s->out_dist_frame = ff_get_audio_buffer(inlink, s->fft_size * 4); + s->windowed_frame = ff_get_audio_buffer(inlink, s->fft_size * 4); + s->windowed_out = ff_get_audio_buffer(inlink, s->fft_size * 4); + s->windowed_prev = ff_get_audio_buffer(inlink, s->fft_size * 4); + if (!s->in_frame || !s->windowed_out || !s->windowed_prev || + !s->out_dist_frame || !s->windowed_frame || !s->center_frame) + return AVERROR(ENOMEM); + + generate_window_func(s->window, s->fft_size, WFUNC_SINE, &overlap); + + iscale = 1.f / s->fft_size; + + ret = av_tx_init(&s->tx_ctx[0], &s->tx_fn, AV_TX_FLOAT_RDFT, 0, s->fft_size, &scale, 0); + if (ret < 0) + return ret; + + ret = av_tx_init(&s->tx_ctx[1], &s->tx_fn, AV_TX_FLOAT_RDFT, 0, s->fft_size, &scale, 0); + if (ret < 0) + return ret; + + ret = av_tx_init(&s->itx_ctx, &s->itx_fn, AV_TX_FLOAT_RDFT, 1, s->fft_size, &iscale, 0); + if (ret < 0) + return ret; + + return 0; +} + +static void apply_window(AudioDialogueEnhanceContext *s, + const float *in_frame, float *out_frame, const int add_to_out_frame) +{ + const float *window = s->window; + + if (add_to_out_frame) { + for (int i = 0; i < s->fft_size; i++) + out_frame[i] += in_frame[i] * window[i]; + } else { + for (int i = 0; i < s->fft_size; i++) + out_frame[i] = in_frame[i] * window[i]; + } +} + +static float sqrf(float x) +{ + return x * x; +} + +static void get_centere(AVComplexFloat *left, AVComplexFloat *right, + AVComplexFloat *center, int N) +{ + for (int i = 0; i < N; i++) { + const float l_re = left[i].re; + const float l_im = left[i].im; + const float r_re = right[i].re; + const float r_im = right[i].im; + const float a = 0.5f * (1.f - sqrtf((sqrf(l_re - r_re) + sqrf(l_im - r_im))/ + (sqrf(l_re + r_re) + sqrf(l_im + r_im) + FLT_EPSILON))); + + center[i].re = a * (l_re + r_re); + center[i].im = a * (l_im + r_im); + } +} + +static float flux(float *curf, float *prevf, int N) +{ + AVComplexFloat *cur = (AVComplexFloat *)curf; + AVComplexFloat *prev = (AVComplexFloat *)prevf; + float sum = 0.f; + + for (int i = 0; i < N; i++) { + float c_re = cur[i].re; + float c_im = cur[i].im; + float p_re = prev[i].re; + float p_im = prev[i].im; + + sum += sqrf(hypotf(c_re, c_im) - hypotf(p_re, p_im)); + } + + return sum; +} + +static float fluxlr(float *lf, float *lpf, + float *rf, float *rpf, + int N) +{ + AVComplexFloat *l = (AVComplexFloat *)lf; + AVComplexFloat *lp = (AVComplexFloat *)lpf; + AVComplexFloat *r = (AVComplexFloat *)rf; + AVComplexFloat *rp = (AVComplexFloat *)rpf; + float sum = 0.f; + + for (int i = 0; i < N; i++) { + float c_re = l[i].re - r[i].re; + float c_im = l[i].im - r[i].im; + float p_re = lp[i].re - rp[i].re; + float p_im = lp[i].im - rp[i].im; + + sum += sqrf(hypotf(c_re, c_im) - hypotf(p_re, p_im)); + } + + return sum; +} + +static float calc_vad(float fc, float flr, float a) +{ + const float vad = a * (fc / (fc + flr) - 0.5f); + + return av_clipf(vad, 0.f, 1.f); +} + +static void get_final(float *c, float *l, + float *r, float vad, int N, + float original, float enhance) +{ + AVComplexFloat *center = (AVComplexFloat *)c; + AVComplexFloat *left = (AVComplexFloat *)l; + AVComplexFloat *right = (AVComplexFloat *)r; + + for (int i = 0; i < N; i++) { + float cP = sqrf(center[i].re) + sqrf(center[i].im); + float lrP = sqrf(left[i].re - right[i].re) + sqrf(left[i].im - right[i].im); + float G = cP / (cP + lrP + FLT_EPSILON); + float re, im; + + re = center[i].re * (original + vad * G * enhance); + im = center[i].im * (original + vad * G * enhance); + + center[i].re = re; + center[i].im = im; + } +} + +static int de_stereo(AVFilterContext *ctx, AVFrame *out) +{ + AudioDialogueEnhanceContext *s = ctx->priv; + float *center = (float *)s->center_frame->extended_data[0]; + float *center_prev = (float *)s->center_frame->extended_data[1]; + float *left_in = (float *)s->in_frame->extended_data[0]; + float *right_in = (float *)s->in_frame->extended_data[1]; + float *left_out = (float *)s->out_dist_frame->extended_data[0]; + float *right_out = (float *)s->out_dist_frame->extended_data[1]; + float *left_samples = (float *)s->in->extended_data[0]; + float *right_samples = (float *)s->in->extended_data[1]; + float *windowed_left = (float *)s->windowed_frame->extended_data[0]; + float *windowed_right = (float *)s->windowed_frame->extended_data[1]; + float *windowed_oleft = (float *)s->windowed_out->extended_data[0]; + float *windowed_oright = (float *)s->windowed_out->extended_data[1]; + float *windowed_pleft = (float *)s->windowed_prev->extended_data[0]; + float *windowed_pright = (float *)s->windowed_prev->extended_data[1]; + float *left_osamples = (float *)out->extended_data[0]; + float *right_osamples = (float *)out->extended_data[1]; + float *center_osamples = (float *)out->extended_data[2]; + const int offset = s->fft_size - s->overlap; + float vad; + + // shift in/out buffers + memmove(left_in, &left_in[s->overlap], offset * sizeof(float)); + memmove(right_in, &right_in[s->overlap], offset * sizeof(float)); + memmove(left_out, &left_out[s->overlap], offset * sizeof(float)); + memmove(right_out, &right_out[s->overlap], offset * sizeof(float)); + + memcpy(&left_in[offset], left_samples, s->overlap * sizeof(float)); + memcpy(&right_in[offset], right_samples, s->overlap * sizeof(float)); + memset(&left_out[offset], 0, s->overlap * sizeof(float)); + memset(&right_out[offset], 0, s->overlap * sizeof(float)); + + apply_window(s, left_in, windowed_left, 0); + apply_window(s, right_in, windowed_right, 0); + + s->tx_fn(s->tx_ctx[0], windowed_oleft, windowed_left, sizeof(float)); + s->tx_fn(s->tx_ctx[1], windowed_oright, windowed_right, sizeof(float)); + + get_centere((AVComplexFloat *)windowed_oleft, + (AVComplexFloat *)windowed_oright, + (AVComplexFloat *)center, + s->fft_size / 2 + 1); + + vad = calc_vad(flux(center, center_prev, s->fft_size / 2 + 1), + fluxlr(windowed_oleft, windowed_pleft, + windowed_oright, windowed_pright, s->fft_size / 2 + 1), s->voice); + vad = vad * 0.1 + 0.9 * s->prev_vad; + s->prev_vad = vad; + + memcpy(center_prev, center, s->fft_size * sizeof(float)); + memcpy(windowed_pleft, windowed_oleft, s->fft_size * sizeof(float)); + memcpy(windowed_pright, windowed_oright, s->fft_size * sizeof(float)); + + get_final(center, windowed_oleft, windowed_oright, vad, s->fft_size / 2 + 1, + s->original, s->enhance); + + s->itx_fn(s->itx_ctx, windowed_oleft, center, sizeof(float)); + + apply_window(s, windowed_oleft, left_out, 1); + + for (int i = 0; i < s->overlap; i++) { + // 4 times overlap with squared hanning window results in 1.5 time increase in amplitude + if (!ctx->is_disabled) + center_osamples[i] = left_out[i] / 1.5f; + else + center_osamples[i] = 0.f; + left_osamples[i] = left_in[i]; + right_osamples[i] = right_in[i]; + } + + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + AudioDialogueEnhanceContext *s = ctx->priv; + AVFrame *out; + int ret; + + out = ff_get_audio_buffer(outlink, s->overlap); + if (!out) { + ret = AVERROR(ENOMEM); + goto fail; + } + + s->in = in; + de_stereo(ctx, out); + + out->pts = in->pts; + out->nb_samples = in->nb_samples; + ret = ff_filter_frame(outlink, out); +fail: + av_frame_free(&in); + s->in = NULL; + return ret < 0 ? ret : 0; +} + +static int activate(AVFilterContext *ctx) +{ + AVFilterLink *inlink = ctx->inputs[0]; + AVFilterLink *outlink = ctx->outputs[0]; + AudioDialogueEnhanceContext *s = ctx->priv; + AVFrame *in = NULL; + int ret = 0, status; + int64_t pts; + + FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); + + ret = ff_inlink_consume_samples(inlink, s->overlap, s->overlap, &in); + if (ret < 0) + return ret; + + if (ret > 0) { + return filter_frame(inlink, in); + } else if (ff_inlink_acknowledge_status(inlink, &status, &pts)) { + ff_outlink_set_status(outlink, status, pts); + return 0; + } else { + if (ff_inlink_queued_samples(inlink) >= s->overlap) { + ff_filter_set_ready(ctx, 10); + } else if (ff_outlink_frame_wanted(outlink)) { + ff_inlink_request_frame(inlink); + } + return 0; + } +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + AudioDialogueEnhanceContext *s = ctx->priv; + + av_freep(&s->window); + + av_frame_free(&s->in_frame); + av_frame_free(&s->center_frame); + av_frame_free(&s->out_dist_frame); + av_frame_free(&s->windowed_frame); + av_frame_free(&s->windowed_out); + av_frame_free(&s->windowed_prev); + + av_tx_uninit(&s->tx_ctx[0]); + av_tx_uninit(&s->tx_ctx[1]); + av_tx_uninit(&s->itx_ctx); +} + +static const AVFilterPad inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .config_props = config_input, + }, +}; + +static const AVFilterPad outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + }, +}; + +const AVFilter ff_af_dialoguenhance = { + .name = "dialoguenhance", + .description = NULL_IF_CONFIG_SMALL("Audio Dialogue Enhancement."), + .priv_size = sizeof(AudioDialogueEnhanceContext), + .priv_class = &dialoguenhance_class, + .uninit = uninit, + FILTER_INPUTS(inputs), + FILTER_OUTPUTS(outputs), + FILTER_QUERY_FUNC(query_formats), + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, + .activate = activate, + .process_command = ff_filter_process_command, +}; diff --git a/libavfilter/af_drmeter.c b/libavfilter/af_drmeter.c index 2021cab14..3e8069133 100644 --- a/libavfilter/af_drmeter.c +++ b/libavfilter/af_drmeter.c @@ -59,10 +59,10 @@ static int config_output(AVFilterLink *outlink) { DRMeterContext *s = outlink->src->priv; - s->chstats = av_calloc(sizeof(*s->chstats), outlink->channels); + s->chstats = av_calloc(sizeof(*s->chstats), outlink->ch_layout.nb_channels); if (!s->chstats) return AVERROR(ENOMEM); - s->nb_channels = outlink->channels; + s->nb_channels = outlink->ch_layout.nb_channels; s->tc_samples = s->time_constant * outlink->sample_rate + .5; return 0; diff --git a/libavfilter/af_dynaudnorm.c b/libavfilter/af_dynaudnorm.c index 783266f8c..4fe1a9ce1 100644 --- a/libavfilter/af_dynaudnorm.c +++ b/libavfilter/af_dynaudnorm.c @@ -27,6 +27,7 @@ #include #include "libavutil/avassert.h" +#include "libavutil/channel_layout.h" #include "libavutil/opt.h" #define MIN_FILTER_SIZE 3 @@ -63,6 +64,7 @@ typedef struct DynamicAudioNormalizerContext { int dc_correction; int channels_coupled; int alt_boundary_mode; + double overlap; double peak_value; double max_amplification; @@ -75,7 +77,10 @@ typedef struct DynamicAudioNormalizerContext { double *weights; int channels; + int sample_advance; int eof; + char *channels_to_filter; + AVChannelLayout ch_layout; int64_t pts; cqueue **gain_history_original; @@ -84,6 +89,8 @@ typedef struct DynamicAudioNormalizerContext { cqueue **threshold_history; cqueue *is_enabled; + + AVFrame *window; } DynamicAudioNormalizerContext; #define OFFSET(x) offsetof(DynamicAudioNormalizerContext, x) @@ -110,6 +117,10 @@ static const AVOption dynaudnorm_options[] = { { "s", "set the compress factor", OFFSET(compress_factor), AV_OPT_TYPE_DOUBLE, {.dbl = 0.0}, 0.0, 30.0, FLAGS }, { "threshold", "set the threshold value", OFFSET(threshold), AV_OPT_TYPE_DOUBLE, {.dbl = 0.0}, 0.0, 1.0, FLAGS }, { "t", "set the threshold value", OFFSET(threshold), AV_OPT_TYPE_DOUBLE, {.dbl = 0.0}, 0.0, 1.0, FLAGS }, + { "channels", "set channels to filter", OFFSET(channels_to_filter),AV_OPT_TYPE_STRING, {.str="all"}, 0, 0, FLAGS }, + { "h", "set channels to filter", OFFSET(channels_to_filter),AV_OPT_TYPE_STRING, {.str="all"}, 0, 0, FLAGS }, + { "overlap", "set the frame overlap", OFFSET(overlap), AV_OPT_TYPE_DOUBLE, {.dbl=.0}, 0.0, 1.0, FLAGS }, + { "o", "set the frame overlap", OFFSET(overlap), AV_OPT_TYPE_DOUBLE, {.dbl=.0}, 0.0, 1.0, FLAGS }, { NULL } }; @@ -238,7 +249,6 @@ static void init_gaussian_filter(DynamicAudioNormalizerContext *s) double total_weight = 0.0; const double sigma = (((s->filter_size / 2.0) - 1.0) / 3.0) + (1.0 / 3.0); double adjust; - int i; // Pre-compute constants const int offset = s->filter_size / 2; @@ -246,7 +256,7 @@ static void init_gaussian_filter(DynamicAudioNormalizerContext *s) const double c2 = 2.0 * sigma * sigma; // Compute weights - for (i = 0; i < s->filter_size; i++) { + for (int i = 0; i < s->filter_size; i++) { const int x = i - offset; s->weights[i] = c1 * exp(-x * x / c2); @@ -255,7 +265,7 @@ static void init_gaussian_filter(DynamicAudioNormalizerContext *s) // Adjust weights adjust = 1.0 / total_weight; - for (i = 0; i < s->filter_size; i++) { + for (int i = 0; i < s->filter_size; i++) { s->weights[i] *= adjust; } } @@ -263,13 +273,12 @@ static void init_gaussian_filter(DynamicAudioNormalizerContext *s) static av_cold void uninit(AVFilterContext *ctx) { DynamicAudioNormalizerContext *s = ctx->priv; - int c; av_freep(&s->prev_amplification_factor); av_freep(&s->dc_correction_value); av_freep(&s->compress_threshold); - for (c = 0; c < s->channels; c++) { + for (int c = 0; c < s->channels; c++) { if (s->gain_history_original) cqueue_free(s->gain_history_original[c]); if (s->gain_history_minimum) @@ -290,28 +299,31 @@ static av_cold void uninit(AVFilterContext *ctx) av_freep(&s->weights); + av_channel_layout_uninit(&s->ch_layout); + ff_bufqueue_discard_all(&s->queue); + + av_frame_free(&s->window); } static int config_input(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; DynamicAudioNormalizerContext *s = ctx->priv; - int c; uninit(ctx); - s->channels = inlink->channels; + s->channels = inlink->ch_layout.nb_channels; s->frame_len = frame_size(inlink->sample_rate, s->frame_len_msec); av_log(ctx, AV_LOG_DEBUG, "frame len %d\n", s->frame_len); - s->prev_amplification_factor = av_malloc_array(inlink->channels, sizeof(*s->prev_amplification_factor)); - s->dc_correction_value = av_calloc(inlink->channels, sizeof(*s->dc_correction_value)); - s->compress_threshold = av_calloc(inlink->channels, sizeof(*s->compress_threshold)); - s->gain_history_original = av_calloc(inlink->channels, sizeof(*s->gain_history_original)); - s->gain_history_minimum = av_calloc(inlink->channels, sizeof(*s->gain_history_minimum)); - s->gain_history_smoothed = av_calloc(inlink->channels, sizeof(*s->gain_history_smoothed)); - s->threshold_history = av_calloc(inlink->channels, sizeof(*s->threshold_history)); + s->prev_amplification_factor = av_malloc_array(inlink->ch_layout.nb_channels, sizeof(*s->prev_amplification_factor)); + s->dc_correction_value = av_calloc(inlink->ch_layout.nb_channels, sizeof(*s->dc_correction_value)); + s->compress_threshold = av_calloc(inlink->ch_layout.nb_channels, sizeof(*s->compress_threshold)); + s->gain_history_original = av_calloc(inlink->ch_layout.nb_channels, sizeof(*s->gain_history_original)); + s->gain_history_minimum = av_calloc(inlink->ch_layout.nb_channels, sizeof(*s->gain_history_minimum)); + s->gain_history_smoothed = av_calloc(inlink->ch_layout.nb_channels, sizeof(*s->gain_history_smoothed)); + s->threshold_history = av_calloc(inlink->ch_layout.nb_channels, sizeof(*s->threshold_history)); s->weights = av_malloc_array(MAX_FILTER_SIZE, sizeof(*s->weights)); s->is_enabled = cqueue_create(s->filter_size, MAX_FILTER_SIZE); if (!s->prev_amplification_factor || !s->dc_correction_value || @@ -321,7 +333,7 @@ static int config_input(AVFilterLink *inlink) !s->is_enabled || !s->weights) return AVERROR(ENOMEM); - for (c = 0; c < inlink->channels; c++) { + for (int c = 0; c < inlink->ch_layout.nb_channels; c++) { s->prev_amplification_factor[c] = 1.0; s->gain_history_original[c] = cqueue_create(s->filter_size, MAX_FILTER_SIZE); @@ -336,6 +348,11 @@ static int config_input(AVFilterLink *inlink) init_gaussian_filter(s); + s->window = ff_get_audio_buffer(ctx->outputs[0], s->frame_len * 2); + if (!s->window) + return AVERROR(ENOMEM); + s->sample_advance = FFMAX(1, lrint(s->frame_len * (1. - s->overlap))); + return 0; } @@ -361,20 +378,19 @@ static inline double bound(const double threshold, const double val) static double find_peak_magnitude(AVFrame *frame, int channel) { double max = DBL_EPSILON; - int c, i; if (channel == -1) { - for (c = 0; c < frame->channels; c++) { + for (int c = 0; c < frame->ch_layout.nb_channels; c++) { double *data_ptr = (double *)frame->extended_data[c]; - for (i = 0; i < frame->nb_samples; i++) - max = FFMAX(max, fabs(data_ptr[i])); + for (int i = 0; i < frame->nb_samples; i++) + max = fmax(max, fabs(data_ptr[i])); } } else { double *data_ptr = (double *)frame->extended_data[channel]; - for (i = 0; i < frame->nb_samples; i++) - max = FFMAX(max, fabs(data_ptr[i])); + for (int i = 0; i < frame->nb_samples; i++) + max = fmax(max, fabs(data_ptr[i])); } return max; @@ -383,28 +399,27 @@ static double find_peak_magnitude(AVFrame *frame, int channel) static double compute_frame_rms(AVFrame *frame, int channel) { double rms_value = 0.0; - int c, i; if (channel == -1) { - for (c = 0; c < frame->channels; c++) { + for (int c = 0; c < frame->ch_layout.nb_channels; c++) { const double *data_ptr = (double *)frame->extended_data[c]; - for (i = 0; i < frame->nb_samples; i++) { + for (int i = 0; i < frame->nb_samples; i++) { rms_value += pow_2(data_ptr[i]); } } - rms_value /= frame->nb_samples * frame->channels; + rms_value /= frame->nb_samples * frame->ch_layout.nb_channels; } else { const double *data_ptr = (double *)frame->extended_data[channel]; - for (i = 0; i < frame->nb_samples; i++) { + for (int i = 0; i < frame->nb_samples; i++) { rms_value += pow_2(data_ptr[i]); } rms_value /= frame->nb_samples; } - return FFMAX(sqrt(rms_value), DBL_EPSILON); + return fmax(sqrt(rms_value), DBL_EPSILON); } static local_gain get_max_local_gain(DynamicAudioNormalizerContext *s, AVFrame *frame, @@ -416,7 +431,7 @@ static local_gain get_max_local_gain(DynamicAudioNormalizerContext *s, AVFrame * local_gain gain; gain.threshold = peak_magnitude > s->threshold; - gain.max_gain = bound(s->max_amplification, FFMIN(maximum_gain, rms_gain)); + gain.max_gain = bound(s->max_amplification, fmin(maximum_gain, rms_gain)); return gain; } @@ -424,10 +439,9 @@ static local_gain get_max_local_gain(DynamicAudioNormalizerContext *s, AVFrame * static double minimum_filter(cqueue *q) { double min = DBL_MAX; - int i; - for (i = 0; i < cqueue_size(q); i++) { - min = FFMIN(min, cqueue_peek(q, i)); + for (int i = 0; i < cqueue_size(q); i++) { + min = fmin(min, cqueue_peek(q, i)); } return min; @@ -435,12 +449,15 @@ static double minimum_filter(cqueue *q) static double gaussian_filter(DynamicAudioNormalizerContext *s, cqueue *q, cqueue *tq) { + const double *weights = s->weights; double result = 0.0, tsum = 0.0; - int i; - for (i = 0; i < cqueue_size(q); i++) { - tsum += cqueue_peek(tq, i) * s->weights[i]; - result += cqueue_peek(q, i) * s->weights[i] * cqueue_peek(tq, i); + for (int i = 0; i < cqueue_size(q); i++) { + double tq_item = cqueue_peek(tq, i); + double q_item = cqueue_peek(q, i); + + tsum += tq_item * weights[i]; + result += tq_item * weights[i] * q_item; } if (tsum == 0.0) @@ -454,7 +471,7 @@ static void update_gain_history(DynamicAudioNormalizerContext *s, int channel, { if (cqueue_empty(s->gain_history_original[channel])) { const int pre_fill_size = s->filter_size / 2; - const double initial_value = s->alt_boundary_mode ? gain.max_gain : FFMIN(1.0, gain.max_gain); + const double initial_value = s->alt_boundary_mode ? gain.max_gain : fmin(1.0, gain.max_gain); s->prev_amplification_factor[channel] = initial_value; @@ -476,7 +493,7 @@ static void update_gain_history(DynamicAudioNormalizerContext *s, int channel, while (cqueue_size(s->gain_history_minimum[channel]) < pre_fill_size) { input++; - initial_value = FFMIN(initial_value, cqueue_peek(s->gain_history_original[channel], input)); + initial_value = fmin(initial_value, cqueue_peek(s->gain_history_original[channel], input)); cqueue_enqueue(s->gain_history_minimum[channel], initial_value); } } @@ -495,7 +512,7 @@ static void update_gain_history(DynamicAudioNormalizerContext *s, int channel, smoothed = gaussian_filter(s, s->gain_history_minimum[channel], s->threshold_history[channel]); limit = cqueue_peek(s->gain_history_original[channel], 0); - smoothed = FFMIN(smoothed, limit); + smoothed = fmin(smoothed, limit); cqueue_enqueue(s->gain_history_smoothed[channel], smoothed); @@ -510,24 +527,31 @@ static inline double update_value(double new, double old, double aggressiveness) return aggressiveness * new + (1.0 - aggressiveness) * old; } +static inline int bypass_channel(DynamicAudioNormalizerContext *s, AVFrame *frame, int ch) +{ + enum AVChannel channel = av_channel_layout_channel_from_index(&frame->ch_layout, ch); + + return av_channel_layout_index_from_channel(&s->ch_layout, channel) < 0; +} + static void perform_dc_correction(DynamicAudioNormalizerContext *s, AVFrame *frame) { const double diff = 1.0 / frame->nb_samples; int is_first_frame = cqueue_empty(s->gain_history_original[0]); - int c, i; - for (c = 0; c < s->channels; c++) { + for (int c = 0; c < s->channels; c++) { + const int bypass = bypass_channel(s, frame, c); double *dst_ptr = (double *)frame->extended_data[c]; double current_average_value = 0.0; double prev_value; - for (i = 0; i < frame->nb_samples; i++) + for (int i = 0; i < frame->nb_samples; i++) current_average_value += dst_ptr[i] * diff; prev_value = is_first_frame ? current_average_value : s->dc_correction_value[c]; s->dc_correction_value[c] = is_first_frame ? current_average_value : update_value(current_average_value, s->dc_correction_value[c], 0.1); - for (i = 0; i < frame->nb_samples; i++) { + for (int i = 0; i < frame->nb_samples && !bypass; i++) { dst_ptr[i] -= fade(prev_value, s->dc_correction_value[c], i, frame->nb_samples); } } @@ -559,13 +583,12 @@ static double compute_frame_std_dev(DynamicAudioNormalizerContext *s, AVFrame *frame, int channel) { double variance = 0.0; - int i, c; if (channel == -1) { - for (c = 0; c < s->channels; c++) { + for (int c = 0; c < s->channels; c++) { const double *data_ptr = (double *)frame->extended_data[c]; - for (i = 0; i < frame->nb_samples; i++) { + for (int i = 0; i < frame->nb_samples; i++) { variance += pow_2(data_ptr[i]); // Assume that MEAN is *zero* } } @@ -573,23 +596,22 @@ static double compute_frame_std_dev(DynamicAudioNormalizerContext *s, } else { const double *data_ptr = (double *)frame->extended_data[channel]; - for (i = 0; i < frame->nb_samples; i++) { + for (int i = 0; i < frame->nb_samples; i++) { variance += pow_2(data_ptr[i]); // Assume that MEAN is *zero* } variance /= frame->nb_samples - 1; } - return FFMAX(sqrt(variance), DBL_EPSILON); + return fmax(sqrt(variance), DBL_EPSILON); } static void perform_compression(DynamicAudioNormalizerContext *s, AVFrame *frame) { int is_first_frame = cqueue_empty(s->gain_history_original[0]); - int c, i; if (s->channels_coupled) { const double standard_deviation = compute_frame_std_dev(s, frame, -1); - const double current_threshold = FFMIN(1.0, s->compress_factor * standard_deviation); + const double current_threshold = fmin(1.0, s->compress_factor * standard_deviation); const double prev_value = is_first_frame ? current_threshold : s->compress_threshold[0]; double prev_actual_thresh, curr_actual_thresh; @@ -598,28 +620,34 @@ static void perform_compression(DynamicAudioNormalizerContext *s, AVFrame *frame prev_actual_thresh = setup_compress_thresh(prev_value); curr_actual_thresh = setup_compress_thresh(s->compress_threshold[0]); - for (c = 0; c < s->channels; c++) { + for (int c = 0; c < s->channels; c++) { double *const dst_ptr = (double *)frame->extended_data[c]; - for (i = 0; i < frame->nb_samples; i++) { + const int bypass = bypass_channel(s, frame, c); + + if (bypass) + continue; + + for (int i = 0; i < frame->nb_samples; i++) { const double localThresh = fade(prev_actual_thresh, curr_actual_thresh, i, frame->nb_samples); dst_ptr[i] = copysign(bound(localThresh, fabs(dst_ptr[i])), dst_ptr[i]); } } } else { - for (c = 0; c < s->channels; c++) { + for (int c = 0; c < s->channels; c++) { + const int bypass = bypass_channel(s, frame, c); const double standard_deviation = compute_frame_std_dev(s, frame, c); - const double current_threshold = setup_compress_thresh(FFMIN(1.0, s->compress_factor * standard_deviation)); - + const double current_threshold = setup_compress_thresh(fmin(1.0, s->compress_factor * standard_deviation)); const double prev_value = is_first_frame ? current_threshold : s->compress_threshold[c]; double prev_actual_thresh, curr_actual_thresh; double *dst_ptr; + s->compress_threshold[c] = is_first_frame ? current_threshold : update_value(current_threshold, s->compress_threshold[c], 1.0/3.0); prev_actual_thresh = setup_compress_thresh(prev_value); curr_actual_thresh = setup_compress_thresh(s->compress_threshold[c]); dst_ptr = (double *)frame->extended_data[c]; - for (i = 0; i < frame->nb_samples; i++) { + for (int i = 0; i < frame->nb_samples && !bypass; i++) { const double localThresh = fade(prev_actual_thresh, curr_actual_thresh, i, frame->nb_samples); dst_ptr[i] = copysign(bound(localThresh, fabs(dst_ptr[i])), dst_ptr[i]); } @@ -627,43 +655,86 @@ static void perform_compression(DynamicAudioNormalizerContext *s, AVFrame *frame } } -static void analyze_frame(DynamicAudioNormalizerContext *s, AVFrame *frame) +static int analyze_frame(DynamicAudioNormalizerContext *s, AVFilterLink *outlink, AVFrame **frame) { - if (s->dc_correction) { - perform_dc_correction(s, frame); + AVFrame *analyze_frame; + + if (s->dc_correction || s->compress_factor > DBL_EPSILON) { + int ret; + + if (!av_frame_is_writable(*frame)) { + AVFrame *out = ff_get_audio_buffer(outlink, (*frame)->nb_samples); + + if (!out) { + av_frame_free(frame); + return AVERROR(ENOMEM); + } + ret = av_frame_copy_props(out, *frame); + if (ret < 0) { + av_frame_free(frame); + av_frame_free(&out); + return ret; + } + ret = av_frame_copy(out, *frame); + if (ret < 0) { + av_frame_free(frame); + av_frame_free(&out); + return ret; + } + + av_frame_free(frame); + *frame = out; + } } - if (s->compress_factor > DBL_EPSILON) { - perform_compression(s, frame); + if (s->dc_correction) + perform_dc_correction(s, *frame); + + if (s->compress_factor > DBL_EPSILON) + perform_compression(s, *frame); + + if (s->frame_len != s->sample_advance) { + const int offset = s->frame_len - s->sample_advance; + + for (int c = 0; c < s->channels; c++) { + double *src = (double *)s->window->extended_data[c]; + + memmove(src, &src[s->sample_advance], offset * sizeof(double)); + memcpy(&src[offset], (*frame)->extended_data[c], (*frame)->nb_samples * sizeof(double)); + memset(&src[offset + (*frame)->nb_samples], 0, (s->sample_advance - (*frame)->nb_samples) * sizeof(double)); + } + + analyze_frame = s->window; + } else { + av_samples_copy(s->window->extended_data, (*frame)->extended_data, 0, 0, + s->frame_len, (*frame)->ch_layout.nb_channels, (*frame)->format); + analyze_frame = *frame; } if (s->channels_coupled) { - const local_gain gain = get_max_local_gain(s, frame, -1); - int c; - - for (c = 0; c < s->channels; c++) + const local_gain gain = get_max_local_gain(s, analyze_frame, -1); + for (int c = 0; c < s->channels; c++) update_gain_history(s, c, gain); } else { - int c; - - for (c = 0; c < s->channels; c++) - update_gain_history(s, c, get_max_local_gain(s, frame, c)); + for (int c = 0; c < s->channels; c++) + update_gain_history(s, c, get_max_local_gain(s, analyze_frame, c)); } + + return 0; } static void amplify_frame(DynamicAudioNormalizerContext *s, AVFrame *in, AVFrame *frame, int enabled) { - int c, i; - - for (c = 0; c < s->channels; c++) { + for (int c = 0; c < s->channels; c++) { + const int bypass = bypass_channel(s, frame, c); const double *src_ptr = (const double *)in->extended_data[c]; double *dst_ptr = (double *)frame->extended_data[c]; double current_amplification_factor; cqueue_dequeue(s->gain_history_smoothed[c], ¤t_amplification_factor); - for (i = 0; i < frame->nb_samples && enabled; i++) { + for (int i = 0; i < frame->nb_samples && enabled && !bypass; i++) { const double amplification_factor = fade(s->prev_amplification_factor[c], current_amplification_factor, i, frame->nb_samples); @@ -680,7 +751,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) AVFilterContext *ctx = inlink->dst; DynamicAudioNormalizerContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; - int ret = 1; + int ret; while (((s->queue.available >= s->filter_size) || (s->eof && s->queue.available)) && @@ -708,9 +779,13 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) if (out != in) av_frame_free(&in); ret = ff_filter_frame(outlink, out); + if (ret < 0) + return ret; } - analyze_frame(s, in); + ret = analyze_frame(s, outlink, &in); + if (ret < 0) + return ret; if (!s->eof) { ff_bufqueue_add(ctx, &s->queue, in); cqueue_enqueue(s->is_enabled, !ctx->is_disabled); @@ -718,23 +793,22 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) av_frame_free(&in); } - return ret; + return 1; } static int flush_buffer(DynamicAudioNormalizerContext *s, AVFilterLink *inlink, AVFilterLink *outlink) { - AVFrame *out = ff_get_audio_buffer(outlink, s->frame_len); - int c, i; + AVFrame *out = ff_get_audio_buffer(outlink, s->sample_advance); if (!out) return AVERROR(ENOMEM); - for (c = 0; c < s->channels; c++) { + for (int c = 0; c < s->channels; c++) { double *dst_ptr = (double *)out->extended_data[c]; - for (i = 0; i < out->nb_samples; i++) { - dst_ptr[i] = s->alt_boundary_mode ? DBL_EPSILON : ((s->target_rms > DBL_EPSILON) ? FFMIN(s->peak_value, s->target_rms) : s->peak_value); + for (int i = 0; i < out->nb_samples; i++) { + dst_ptr[i] = s->alt_boundary_mode ? DBL_EPSILON : ((s->target_rms > DBL_EPSILON) ? fmin(s->peak_value, s->target_rms) : s->peak_value); if (s->dc_correction) { dst_ptr[i] *= ((i % 2) == 1) ? -1 : 1; dst_ptr[i] += s->dc_correction_value[c]; @@ -774,10 +848,16 @@ static int activate(AVFilterContext *ctx) int ret = 0, status; int64_t pts; + ret = av_channel_layout_copy(&s->ch_layout, &inlink->ch_layout); + if (ret < 0) + return ret; + if (strcmp(s->channels_to_filter, "all")) + av_channel_layout_from_string(&s->ch_layout, s->channels_to_filter); + FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); if (!s->eof) { - ret = ff_inlink_consume_samples(inlink, s->frame_len, s->frame_len, &in); + ret = ff_inlink_consume_samples(inlink, s->sample_advance, s->sample_advance, &in); if (ret < 0) return ret; if (ret > 0) { @@ -786,7 +866,7 @@ static int activate(AVFilterContext *ctx) return ret; } - if (ff_inlink_check_available_samples(inlink, s->frame_len) > 0) { + if (ff_inlink_check_available_samples(inlink, s->sample_advance) > 0) { ff_filter_set_ready(ctx, 10); return 0; } @@ -835,6 +915,7 @@ static int process_command(AVFilterContext *ctx, const char *cmd, const char *ar } s->frame_len = frame_size(inlink->sample_rate, s->frame_len_msec); + s->sample_advance = FFMAX(1, lrint(s->frame_len * (1. - s->overlap))); return 0; } diff --git a/libavfilter/af_earwax.c b/libavfilter/af_earwax.c index fa0162abb..f420a5ac5 100644 --- a/libavfilter/af_earwax.c +++ b/libavfilter/af_earwax.c @@ -88,7 +88,7 @@ static int query_formats(AVFilterContext *ctx) if ((ret = ff_add_format (&formats, AV_SAMPLE_FMT_S16P )) < 0 || (ret = ff_set_common_formats (ctx , formats )) < 0 || - (ret = ff_add_channel_layout (&layout , AV_CH_LAYOUT_STEREO )) < 0 || + (ret = ff_add_channel_layout (&layout , &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO)) < 0 || (ret = ff_set_common_channel_layouts (ctx , layout )) < 0 || (ret = ff_set_common_samplerates_from_list(ctx, sample_rates)) < 0) return ret; diff --git a/libavfilter/af_extrastereo.c b/libavfilter/af_extrastereo.c index 1645ccb94..6f1d691d8 100644 --- a/libavfilter/af_extrastereo.c +++ b/libavfilter/af_extrastereo.c @@ -49,7 +49,7 @@ static int query_formats(AVFilterContext *ctx) if ((ret = ff_add_format (&formats, AV_SAMPLE_FMT_FLT )) < 0 || (ret = ff_set_common_formats (ctx , formats )) < 0 || - (ret = ff_add_channel_layout (&layout , AV_CH_LAYOUT_STEREO)) < 0 || + (ret = ff_add_channel_layout (&layout , &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO)) < 0 || (ret = ff_set_common_channel_layouts (ctx , layout )) < 0) return ret; diff --git a/libavfilter/af_firequalizer.c b/libavfilter/af_firequalizer.c index 568b78117..85bdb5920 100644 --- a/libavfilter/af_firequalizer.c +++ b/libavfilter/af_firequalizer.c @@ -604,17 +604,18 @@ static int generate_kernel(AVFilterContext *ctx, const char *gain, const char *g if (ret < 0) return ret; - if (s->dumpfile && (!s->dump_buf || !s->analysis_rdft || !(dump_fp = fopen(s->dumpfile, "w")))) + if (s->dumpfile && (!s->dump_buf || !s->analysis_rdft || !(dump_fp = avpriv_fopen_utf8(s->dumpfile, "w")))) av_log(ctx, AV_LOG_WARNING, "dumping failed.\n"); - vars[VAR_CHS] = inlink->channels; - vars[VAR_CHLAYOUT] = inlink->channel_layout; + vars[VAR_CHS] = inlink->ch_layout.nb_channels; + vars[VAR_CHLAYOUT] = inlink->ch_layout.order == AV_CHANNEL_ORDER_NATIVE ? + inlink->ch_layout.u.mask : 0; vars[VAR_SR] = inlink->sample_rate; - for (ch = 0; ch < inlink->channels; ch++) { + for (ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { float *rdft_buf = s->kernel_tmp_buf + ch * s->rdft_len; double result; vars[VAR_CH] = ch; - vars[VAR_CHID] = av_channel_layout_extract_channel(inlink->channel_layout, ch); + vars[VAR_CHID] = av_channel_layout_channel_from_index(&inlink->ch_layout, ch); vars[VAR_F] = 0.0; if (xlog) vars[VAR_F] = log2(0.05 * vars[VAR_F]); @@ -715,7 +716,7 @@ static int generate_kernel(AVFilterContext *ctx, const char *gain, const char *g break; } - memcpy(s->kernel_buf, s->kernel_tmp_buf, (s->multi ? inlink->channels : 1) * s->rdft_len * sizeof(*s->kernel_buf)); + memcpy(s->kernel_buf, s->kernel_tmp_buf, (s->multi ? inlink->ch_layout.nb_channels : 1) * s->rdft_len * sizeof(*s->kernel_buf)); av_expr_free(gain_expr); if (dump_fp) fclose(dump_fp); @@ -754,7 +755,7 @@ static int config_input(AVFilterLink *inlink) if (!(s->rdft = av_rdft_init(rdft_bits, DFT_R2C)) || !(s->irdft = av_rdft_init(rdft_bits, IDFT_C2R))) return AVERROR(ENOMEM); - if (s->fft2 && !s->multi && inlink->channels > 1 && !(s->fft_ctx = av_fft_init(rdft_bits, 0))) + if (s->fft2 && !s->multi && inlink->ch_layout.nb_channels > 1 && !(s->fft_ctx = av_fft_init(rdft_bits, 0))) return AVERROR(ENOMEM); if (s->min_phase) { @@ -796,15 +797,15 @@ static int config_input(AVFilterLink *inlink) } s->analysis_buf = av_malloc_array(s->analysis_rdft_len, sizeof(*s->analysis_buf)); - s->kernel_tmp_buf = av_malloc_array(s->rdft_len * (s->multi ? inlink->channels : 1), sizeof(*s->kernel_tmp_buf)); - s->kernel_buf = av_malloc_array(s->rdft_len * (s->multi ? inlink->channels : 1), sizeof(*s->kernel_buf)); - s->conv_buf = av_calloc(2 * s->rdft_len * inlink->channels, sizeof(*s->conv_buf)); - s->conv_idx = av_calloc(inlink->channels, sizeof(*s->conv_idx)); + s->kernel_tmp_buf = av_malloc_array(s->rdft_len * (s->multi ? inlink->ch_layout.nb_channels : 1), sizeof(*s->kernel_tmp_buf)); + s->kernel_buf = av_malloc_array(s->rdft_len * (s->multi ? inlink->ch_layout.nb_channels : 1), sizeof(*s->kernel_buf)); + s->conv_buf = av_calloc(2 * s->rdft_len * inlink->ch_layout.nb_channels, sizeof(*s->conv_buf)); + s->conv_idx = av_calloc(inlink->ch_layout.nb_channels, sizeof(*s->conv_idx)); if (!s->analysis_buf || !s->kernel_tmp_buf || !s->kernel_buf || !s->conv_buf || !s->conv_idx) return AVERROR(ENOMEM); av_log(ctx, AV_LOG_DEBUG, "sample_rate = %d, channels = %d, analysis_rdft_len = %d, rdft_len = %d, fir_len = %d, nsamples_max = %d.\n", - inlink->sample_rate, inlink->channels, s->analysis_rdft_len, s->rdft_len, s->fir_len, s->nsamples_max); + inlink->sample_rate, inlink->ch_layout.nb_channels, s->analysis_rdft_len, s->rdft_len, s->fir_len, s->nsamples_max); if (s->fixed) inlink->min_samples = inlink->max_samples = s->nsamples_max; @@ -819,19 +820,19 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) int ch; if (!s->min_phase) { - for (ch = 0; ch + 1 < inlink->channels && s->fft_ctx; ch += 2) { + for (ch = 0; ch + 1 < inlink->ch_layout.nb_channels && s->fft_ctx; ch += 2) { fast_convolute2(s, s->kernel_buf, (FFTComplex *)(s->conv_buf + 2 * ch * s->rdft_len), s->conv_idx + ch, (float *) frame->extended_data[ch], (float *) frame->extended_data[ch+1], frame->nb_samples); } - for ( ; ch < inlink->channels; ch++) { + for ( ; ch < inlink->ch_layout.nb_channels; ch++) { fast_convolute(s, s->kernel_buf + (s->multi ? ch * s->rdft_len : 0), s->conv_buf + 2 * ch * s->rdft_len, s->conv_idx + ch, (float *) frame->extended_data[ch], frame->nb_samples); } } else { - for (ch = 0; ch < inlink->channels; ch++) { + for (ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { fast_convolute_nonlinear(s, s->kernel_buf + (s->multi ? ch * s->rdft_len : 0), s->conv_buf + 2 * ch * s->rdft_len, s->conv_idx + ch, (float *) frame->extended_data[ch], frame->nb_samples); @@ -861,7 +862,7 @@ static int request_frame(AVFilterLink *outlink) if (!frame) return AVERROR(ENOMEM); - av_samples_set_silence(frame->extended_data, 0, frame->nb_samples, outlink->channels, frame->format); + av_samples_set_silence(frame->extended_data, 0, frame->nb_samples, outlink->ch_layout.nb_channels, frame->format); frame->pts = s->next_pts; s->remaining -= frame->nb_samples; ret = filter_frame(ctx->inputs[0], frame); diff --git a/libavfilter/af_flanger.c b/libavfilter/af_flanger.c index ba8d033ce..452436a4b 100644 --- a/libavfilter/af_flanger.c +++ b/libavfilter/af_flanger.c @@ -95,7 +95,7 @@ static int config_input(AVFilterLink *inlink) s->max_samples = (s->delay_min + s->delay_depth) * inlink->sample_rate + 2.5; s->lfo_length = inlink->sample_rate / s->speed; - s->delay_last = av_calloc(inlink->channels, sizeof(*s->delay_last)); + s->delay_last = av_calloc(inlink->ch_layout.nb_channels, sizeof(*s->delay_last)); s->lfo = av_calloc(s->lfo_length, sizeof(*s->lfo)); if (!s->lfo || !s->delay_last) return AVERROR(ENOMEM); @@ -105,7 +105,7 @@ static int config_input(AVFilterLink *inlink) s->max_samples - 2., 3 * M_PI_2); return av_samples_alloc_array_and_samples(&s->delay_buffer, NULL, - inlink->channels, s->max_samples, + inlink->ch_layout.nb_channels, s->max_samples, inlink->format, 0); } @@ -131,7 +131,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) s->delay_buf_pos = (s->delay_buf_pos + s->max_samples - 1) % s->max_samples; - for (chan = 0; chan < inlink->channels; chan++) { + for (chan = 0; chan < inlink->ch_layout.nb_channels; chan++) { double *src = (double *)frame->extended_data[chan]; double *dst = (double *)out_frame->extended_data[chan]; double delayed_0, delayed_1; diff --git a/libavfilter/af_haas.c b/libavfilter/af_haas.c index 281ec276f..d283da726 100644 --- a/libavfilter/af_haas.c +++ b/libavfilter/af_haas.c @@ -87,7 +87,7 @@ static int query_formats(AVFilterContext *ctx) if ((ret = ff_add_format (&formats, AV_SAMPLE_FMT_DBL )) < 0 || (ret = ff_set_common_formats (ctx , formats )) < 0 || - (ret = ff_add_channel_layout (&layout , AV_CH_LAYOUT_STEREO)) < 0 || + (ret = ff_add_channel_layout (&layout , &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO)) < 0 || (ret = ff_set_common_channel_layouts (ctx , layout )) < 0) return ret; diff --git a/libavfilter/af_hdcd.c b/libavfilter/af_hdcd.c index 494642106..49bfa1bfa 100644 --- a/libavfilter/af_hdcd.c +++ b/libavfilter/af_hdcd.c @@ -1554,27 +1554,27 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) switch (inlink->format) { case AV_SAMPLE_FMT_S16P: for (n = 0; n < in->nb_samples; n++) - for (c = 0; c < in->channels; c++) { + for (c = 0; c < in->ch_layout.nb_channels; c++) { in_data = (int16_t*)in->extended_data[c]; - out_data[(n * in->channels) + c] = in_data[n]; + out_data[(n * in->ch_layout.nb_channels) + c] = in_data[n]; } break; case AV_SAMPLE_FMT_S16: in_data = (int16_t*)in->data[0]; - for (n = 0; n < in->nb_samples * in->channels; n++) + for (n = 0; n < in->nb_samples * in->ch_layout.nb_channels; n++) out_data[n] = in_data[n]; break; case AV_SAMPLE_FMT_S32P: for (n = 0; n < in->nb_samples; n++) - for (c = 0; c < in->channels; c++) { + for (c = 0; c < in->ch_layout.nb_channels; c++) { in_data32 = (int32_t*)in->extended_data[c]; - out_data[(n * in->channels) + c] = in_data32[n] >> a; + out_data[(n * in->ch_layout.nb_channels) + c] = in_data32[n] >> a; } break; case AV_SAMPLE_FMT_S32: in_data32 = (int32_t*)in->data[0]; - for (n = 0; n < in->nb_samples * in->channels; n++) + for (n = 0; n < in->nb_samples * in->ch_layout.nb_channels; n++) out_data[n] = in_data32[n] >> a; break; } @@ -1587,14 +1587,14 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) hdcd_detect_end(&s->detect, 2); } else { hdcd_detect_start(&s->detect); - for (c = 0; c < in->channels; c++) { - hdcd_process(s, &s->state[c], out_data + c, in->nb_samples, in->channels); + for (c = 0; c < in->ch_layout.nb_channels; c++) { + hdcd_process(s, &s->state[c], out_data + c, in->nb_samples, in->ch_layout.nb_channels); hdcd_detect_onech(&s->state[c], &s->detect); } - hdcd_detect_end(&s->detect, in->channels); + hdcd_detect_end(&s->detect, in->ch_layout.nb_channels); } - s->sample_count += in->nb_samples * in->channels; + s->sample_count += in->nb_samples * in->ch_layout.nb_channels; av_frame_free(&in); return ff_filter_frame(outlink, out); @@ -1627,10 +1627,10 @@ static int query_formats(AVFilterContext *ctx) }; int ret; - ret = ff_add_channel_layout(&layouts, AV_CH_LAYOUT_MONO); + ret = ff_add_channel_layout(&layouts, &(AVChannelLayout)AV_CHANNEL_LAYOUT_MONO); if (ret < 0) return ret; - ret = ff_add_channel_layout(&layouts, AV_CH_LAYOUT_STEREO); + ret = ff_add_channel_layout(&layouts, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO); if (ret < 0) return ret; @@ -1739,8 +1739,8 @@ static int config_input(AVFilterLink *inlink) { av_log(ctx, AV_LOG_VERBOSE, "CDT period: %dms (%u samples @44100Hz)\n", s->cdt_ms, s->state[0].sustain_reset ); - if (inlink->channels != 2 && s->process_stereo) { - av_log(ctx, AV_LOG_WARNING, "process_stereo disabled (channels = %d)\n", inlink->channels); + if (inlink->ch_layout.nb_channels != 2 && s->process_stereo) { + av_log(ctx, AV_LOG_WARNING, "process_stereo disabled (channels = %d)\n", inlink->ch_layout.nb_channels); s->process_stereo = 0; } av_log(ctx, AV_LOG_VERBOSE, "Process mode: %s\n", diff --git a/libavfilter/af_headphone.c b/libavfilter/af_headphone.c index b2030dbbb..edaae6217 100644 --- a/libavfilter/af_headphone.c +++ b/libavfilter/af_headphone.c @@ -82,16 +82,18 @@ typedef struct HeadphoneContext { int ir_len; int eof; } hrir_in[64]; - uint64_t mapping[64]; + AVChannelLayout map_channel_layout; + enum AVChannel mapping[64]; + uint8_t hrir_map[64]; } HeadphoneContext; -static int parse_channel_name(const char *arg, uint64_t *rchannel) +static int parse_channel_name(const char *arg, enum AVChannel *rchannel) { - uint64_t layout = av_get_channel_layout(arg); + int channel = av_channel_from_string(arg); - if (av_get_channel_layout_nb_channels(layout) != 1) + if (channel < 0 || channel >= 64) return AVERROR(EINVAL); - *rchannel = layout; + *rchannel = channel; return 0; } @@ -103,21 +105,22 @@ static void parse_map(AVFilterContext *ctx) p = s->map; while ((arg = av_strtok(p, "|", &tokenizer))) { - uint64_t out_channel; + enum AVChannel out_channel; p = NULL; if (parse_channel_name(arg, &out_channel)) { av_log(ctx, AV_LOG_WARNING, "Failed to parse \'%s\' as channel name.\n", arg); continue; } - if (used_channels & out_channel) { + if (used_channels & (1ULL << out_channel)) { av_log(ctx, AV_LOG_WARNING, "Ignoring duplicate channel '%s'.\n", arg); continue; } - used_channels |= out_channel; + used_channels |= (1ULL << out_channel); s->mapping[s->nb_irs] = out_channel; s->nb_irs++; } + av_channel_layout_from_mask(&s->map_channel_layout, used_channels); if (s->hrir_fmt == HRIR_MULTI) s->nb_hrir_inputs = 1; @@ -152,7 +155,7 @@ static int headphone_convolute(AVFilterContext *ctx, void *arg, int jobnr, int n const int air_len = s->air_len; const float *src = (const float *)in->data[0]; float *dst = (float *)out->data[0]; - const int in_channels = in->channels; + const int in_channels = in->ch_layout.nb_channels; const int buffer_length = s->buffer_length; const uint32_t modulo = (uint32_t)buffer_length - 1; float *buffer[64]; @@ -221,7 +224,7 @@ static int headphone_fast_convolute(AVFilterContext *ctx, void *arg, int jobnr, const int ir_len = s->ir_len; const float *src = (const float *)in->data[0]; float *dst = (float *)out->data[0]; - const int in_channels = in->channels; + const int in_channels = in->ch_layout.nb_channels; const int buffer_length = s->buffer_length; const uint32_t modulo = (uint32_t)buffer_length - 1; AVComplexFloat *fft_out = s->out_fft[jobnr]; @@ -262,7 +265,7 @@ static int headphone_fast_convolute(AVFilterContext *ctx, void *arg, int jobnr, } offset = i * n_fft; - hrtf_offset = hrtf + offset; + hrtf_offset = hrtf + s->hrir_map[i] * n_fft; memset(fft_in, 0, sizeof(AVComplexFloat) * n_fft); @@ -360,7 +363,8 @@ static int convert_coeffs(AVFilterContext *ctx, AVFilterLink *inlink) { struct HeadphoneContext *s = ctx->priv; const int ir_len = s->ir_len; - int nb_input_channels = ctx->inputs[0]->channels; + int nb_input_channels = ctx->inputs[0]->ch_layout.nb_channels; + const int nb_hrir_channels = s->nb_hrir_inputs == 1 ? ctx->inputs[1]->ch_layout.nb_channels : s->nb_hrir_inputs * 2; float gain_lin = expf((s->gain - 3 * nb_input_channels) / 20 * M_LN10); AVFrame *frame; int ret = 0; @@ -426,15 +430,15 @@ static int convert_coeffs(AVFilterContext *ctx, AVFilterLink *inlink) s->temp_src[0] = av_calloc(s->air_len, sizeof(float)); s->temp_src[1] = av_calloc(s->air_len, sizeof(float)); - s->data_ir[0] = av_calloc(nb_input_channels * s->air_len, sizeof(*s->data_ir[0])); - s->data_ir[1] = av_calloc(nb_input_channels * s->air_len, sizeof(*s->data_ir[1])); + s->data_ir[0] = av_calloc(nb_hrir_channels * s->air_len, sizeof(*s->data_ir[0])); + s->data_ir[1] = av_calloc(nb_hrir_channels * s->air_len, sizeof(*s->data_ir[1])); if (!s->data_ir[0] || !s->data_ir[1] || !s->temp_src[0] || !s->temp_src[1]) { ret = AVERROR(ENOMEM); goto fail; } } else { - s->data_hrtf[0] = av_calloc(n_fft, sizeof(*s->data_hrtf[0]) * nb_input_channels); - s->data_hrtf[1] = av_calloc(n_fft, sizeof(*s->data_hrtf[1]) * nb_input_channels); + s->data_hrtf[0] = av_calloc(n_fft, sizeof(*s->data_hrtf[0]) * nb_hrir_channels); + s->data_hrtf[1] = av_calloc(n_fft, sizeof(*s->data_hrtf[1]) * nb_hrir_channels); if (!s->data_hrtf[0] || !s->data_hrtf[1]) { ret = AVERROR(ENOMEM); goto fail; @@ -451,10 +455,12 @@ static int convert_coeffs(AVFilterContext *ctx, AVFilterLink *inlink) ptr = (float *)frame->extended_data[0]; if (s->hrir_fmt == HRIR_STEREO) { - int idx = av_get_channel_layout_channel_index(inlink->channel_layout, + int idx = av_channel_layout_index_from_channel(&s->map_channel_layout, s->mapping[i]); if (idx < 0) continue; + + s->hrir_map[i] = idx; if (s->type == TIME_DOMAIN) { float *data_ir_l = s->data_ir[0] + idx * s->air_len; float *data_ir_r = s->data_ir[1] + idx * s->air_len; @@ -478,14 +484,15 @@ static int convert_coeffs(AVFilterContext *ctx, AVFilterLink *inlink) s->tx_fn[0](s->fft[0], fft_out_r, fft_in_r, sizeof(float)); } } else { - int I, N = ctx->inputs[1]->channels; + int I, N = ctx->inputs[1]->ch_layout.nb_channels; for (k = 0; k < N / 2; k++) { - int idx = av_get_channel_layout_channel_index(inlink->channel_layout, + int idx = av_channel_layout_index_from_channel(&inlink->ch_layout, s->mapping[k]); if (idx < 0) continue; + s->hrir_map[k] = idx; I = k * 2; if (s->type == TIME_DOMAIN) { float *data_ir_l = s->data_ir[0] + idx * s->air_len; @@ -602,7 +609,7 @@ static int query_formats(AVFilterContext *ctx) if (ret) return ret; - ret = ff_add_channel_layout(&stereo_layout, AV_CH_LAYOUT_STEREO); + ret = ff_add_channel_layout(&stereo_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO); if (ret) return ret; ret = ff_channel_layouts_ref(stereo_layout, &ctx->outputs[0]->incfg.channel_layouts); @@ -632,13 +639,13 @@ static int config_input(AVFilterLink *inlink) AVFilterContext *ctx = inlink->dst; HeadphoneContext *s = ctx->priv; - if (s->nb_irs < inlink->channels) { - av_log(ctx, AV_LOG_ERROR, "Number of HRIRs must be >= %d.\n", inlink->channels); + if (s->nb_irs < inlink->ch_layout.nb_channels) { + av_log(ctx, AV_LOG_ERROR, "Number of HRIRs must be >= %d.\n", inlink->ch_layout.nb_channels); return AVERROR(EINVAL); } - s->lfe_channel = av_get_channel_layout_channel_index(inlink->channel_layout, - AV_CH_LOW_FREQUENCY); + s->lfe_channel = av_channel_layout_index_from_channel(&inlink->ch_layout, + AV_CHAN_LOW_FREQUENCY); return 0; } @@ -694,13 +701,13 @@ static int config_output(AVFilterLink *outlink) 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); + if (hrir_link->ch_layout.nb_channels < inlink->ch_layout.nb_channels * 2) { + av_log(ctx, AV_LOG_ERROR, "Number of channels in HRIR stream must be >= %d.\n", inlink->ch_layout.nb_channels * 2); return AVERROR(EINVAL); } } - s->gain_lfe = expf((s->gain - 3 * inlink->channels + s->lfe_gain) / 20 * M_LN10); + s->gain_lfe = expf((s->gain - 3 * inlink->ch_layout.nb_channels + s->lfe_gain) / 20 * M_LN10); return 0; } diff --git a/libavfilter/af_join.c b/libavfilter/af_join.c index 6cc21f465..dc075a8b2 100644 --- a/libavfilter/af_join.c +++ b/libavfilter/af_join.c @@ -24,6 +24,7 @@ * a single output */ +#include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/channel_layout.h" #include "libavutil/common.h" @@ -36,10 +37,10 @@ #include "internal.h" typedef struct ChannelMap { - int input; ///< input stream index - int in_channel_idx; ///< index of in_channel in the input stream data - uint64_t in_channel; ///< layout describing the input channel - uint64_t out_channel; ///< layout describing the output channel + int input; ///< input stream index + int in_channel_idx; ///< index of in_channel in the input stream data + enum AVChannel in_channel; + enum AVChannel out_channel; } ChannelMap; typedef struct JoinContext { @@ -48,11 +49,10 @@ typedef struct JoinContext { int inputs; char *map; char *channel_layout_str; - uint64_t channel_layout; + AVChannelLayout ch_layout; int64_t eof_pts; - int nb_channels; ChannelMap *channels; /** @@ -79,20 +79,21 @@ static const AVOption join_options[] = { { NULL } }; +#define MAP_SEPARATOR '|' + AVFILTER_DEFINE_CLASS(join); static int parse_maps(AVFilterContext *ctx) { JoinContext *s = ctx->priv; - char separator = '|'; char *cur = s->map; while (cur && *cur) { + ChannelMap *map; char *sep, *next, *p; - uint64_t in_channel = 0, out_channel = 0; - int input_idx, out_ch_idx, in_ch_idx; + int input_idx, out_ch_idx; - next = strchr(cur, separator); + next = strchr(cur, MAP_SEPARATOR); if (next) *next++ = 0; @@ -104,28 +105,16 @@ static int parse_maps(AVFilterContext *ctx) } *sep++ = 0; -#define PARSE_CHANNEL(str, var, inout) \ - if (!(var = av_get_channel_layout(str))) { \ - av_log(ctx, AV_LOG_ERROR, "Invalid " inout " channel: %s.\n", str);\ - return AVERROR(EINVAL); \ - } \ - if (av_get_channel_layout_nb_channels(var) != 1) { \ - av_log(ctx, AV_LOG_ERROR, "Channel map describes more than one " \ - inout " channel.\n"); \ - return AVERROR(EINVAL); \ - } - /* parse output channel */ - PARSE_CHANNEL(sep, out_channel, "output"); - if (!(out_channel & s->channel_layout)) { - av_log(ctx, AV_LOG_ERROR, "Output channel '%s' is not present in " - "requested channel layout.\n", sep); + out_ch_idx = av_channel_layout_index_from_string(&s->ch_layout, sep); + if (out_ch_idx < 0) { + av_log(ctx, AV_LOG_ERROR, "Invalid output channel: %s.\n", sep); return AVERROR(EINVAL); } - out_ch_idx = av_get_channel_layout_channel_index(s->channel_layout, - out_channel); - if (s->channels[out_ch_idx].input >= 0) { + map = &s->channels[out_ch_idx]; + + if (map->input >= 0) { av_log(ctx, AV_LOG_ERROR, "Multiple maps for output channel " "'%s'.\n", sep); return AVERROR(EINVAL); @@ -142,19 +131,21 @@ static int parse_maps(AVFilterContext *ctx) if (*cur) cur++; - in_ch_idx = strtol(cur, &p, 0); + map->input = input_idx; + map->in_channel = AV_CHAN_NONE; + map->in_channel_idx = strtol(cur, &p, 0); if (p == cur) { - /* channel specifier is not a number, - * try to parse as channel name */ - PARSE_CHANNEL(cur, in_channel, "input"); + /* channel specifier is not a number, handle as channel name */ + map->in_channel = av_channel_from_string(cur); + if (map->in_channel < 0) { + av_log(ctx, AV_LOG_ERROR, "Invalid input channel: %s.\n", cur); + return AVERROR(EINVAL); + } + } else if (map->in_channel_idx < 0) { + av_log(ctx, AV_LOG_ERROR, "Invalid input channel index: %d\n", map->in_channel_idx); + return AVERROR(EINVAL); } - s->channels[out_ch_idx].input = input_idx; - if (in_channel) - s->channels[out_ch_idx].in_channel = in_channel; - else - s->channels[out_ch_idx].in_channel_idx = in_ch_idx; - cur = next; } return 0; @@ -165,22 +156,37 @@ static av_cold int join_init(AVFilterContext *ctx) JoinContext *s = ctx->priv; int ret, 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", + ret = av_channel_layout_from_string(&s->ch_layout, s->channel_layout_str); + if (ret < 0) { +#if FF_API_OLD_CHANNEL_LAYOUT + uint64_t mask; +FF_DISABLE_DEPRECATION_WARNINGS + mask = av_get_channel_layout(s->channel_layout_str); + if (!mask) { +#endif + av_log(ctx, AV_LOG_ERROR, "Error parsing channel layout '%s'.\n", + s->channel_layout_str); + return AVERROR(EINVAL); +#if FF_API_OLD_CHANNEL_LAYOUT + } +FF_ENABLE_DEPRECATION_WARNINGS + av_log(ctx, AV_LOG_WARNING, "Channel layout '%s' uses a deprecated syntax.\n", s->channel_layout_str); - return AVERROR(EINVAL); + av_channel_layout_from_mask(&s->ch_layout, mask); +#endif } - s->nb_channels = av_get_channel_layout_nb_channels(s->channel_layout); - s->channels = av_calloc(s->nb_channels, sizeof(*s->channels)); - s->buffers = av_calloc(s->nb_channels, sizeof(*s->buffers)); + s->channels = av_calloc(s->ch_layout.nb_channels, sizeof(*s->channels)); + s->buffers = av_calloc(s->ch_layout.nb_channels, sizeof(*s->buffers)); s->input_frames = av_calloc(s->inputs, sizeof(*s->input_frames)); if (!s->channels || !s->buffers|| !s->input_frames) return AVERROR(ENOMEM); - for (i = 0; i < s->nb_channels; i++) { - s->channels[i].out_channel = av_channel_layout_extract_channel(s->channel_layout, i); - s->channels[i].input = -1; + for (i = 0; i < s->ch_layout.nb_channels; i++) { + s->channels[i].out_channel = av_channel_layout_channel_from_index(&s->ch_layout, i); + s->channels[i].input = -1; + s->channels[i].in_channel_idx = -1; + s->channels[i].in_channel = AV_CHAN_NONE; } if ((ret = parse_maps(ctx)) < 0) @@ -221,7 +227,7 @@ static int join_query_formats(AVFilterContext *ctx) AVFilterChannelLayouts *layouts = NULL; int i, ret; - if ((ret = ff_add_channel_layout(&layouts, s->channel_layout)) < 0 || + if ((ret = ff_add_channel_layout(&layouts, &s->ch_layout)) < 0 || (ret = ff_channel_layouts_ref(layouts, &ctx->outputs[0]->incfg.channel_layouts)) < 0) return ret; @@ -238,38 +244,55 @@ static int join_query_formats(AVFilterContext *ctx) return 0; } +typedef struct ChannelList { + enum AVChannel *ch; + int nb_ch; +} ChannelList; + +static enum AVChannel channel_list_pop(ChannelList *chl, int idx) +{ + enum AVChannel ret = chl->ch[idx]; + memmove(chl->ch + idx, chl->ch + idx + 1, + (chl->nb_ch - idx - 1) * sizeof(*chl->ch)); + chl->nb_ch--; + return ret; +} + +/* + * If ch is present in chl, remove it from the list and return it. + * Otherwise return AV_CHAN_NONE. + */ +static enum AVChannel channel_list_pop_ch(ChannelList *chl, enum AVChannel ch) +{ + for (int i = 0; i < chl->nb_ch; i++) + if (chl->ch[i] == ch) + return channel_list_pop(chl, i); + return AV_CHAN_NONE; +} + static void guess_map_matching(AVFilterContext *ctx, ChannelMap *ch, - uint64_t *inputs) + ChannelList *inputs) { int i; for (i = 0; i < ctx->nb_inputs; i++) { - AVFilterLink *link = ctx->inputs[i]; - - if (ch->out_channel & link->channel_layout && - !(ch->out_channel & inputs[i])) { + if (channel_list_pop_ch(&inputs[i], ch->out_channel) != AV_CHAN_NONE) { ch->input = i; ch->in_channel = ch->out_channel; - inputs[i] |= ch->out_channel; return; } } } static void guess_map_any(AVFilterContext *ctx, ChannelMap *ch, - uint64_t *inputs) + ChannelList *inputs) { int i; for (i = 0; i < ctx->nb_inputs; i++) { - AVFilterLink *link = ctx->inputs[i]; - - if ((inputs[i] & link->channel_layout) != link->channel_layout) { - uint64_t unused = link->channel_layout & ~inputs[i]; - + if (inputs[i].nb_ch) { ch->input = i; - ch->in_channel = av_channel_layout_extract_channel(unused, 0); - inputs[i] |= ch->in_channel; + ch->in_channel = channel_list_pop(&inputs[i], 0); return; } } @@ -279,81 +302,136 @@ static int join_config_output(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; JoinContext *s = ctx->priv; - uint64_t *inputs; // nth element tracks which channels are used from nth input + // unused channels from each input + ChannelList *inputs_unused; + char inbuf[64], outbuf[64]; int i, ret = 0; - /* initialize inputs to user-specified mappings */ - if (!(inputs = av_calloc(ctx->nb_inputs, sizeof(*inputs)))) + /* initialize unused channel list for each input */ + inputs_unused = av_calloc(ctx->nb_inputs, sizeof(*inputs_unused)); + if (!inputs_unused) return AVERROR(ENOMEM); - for (i = 0; i < s->nb_channels; i++) { + for (i = 0; i < ctx->nb_inputs; i++) { + AVFilterLink *inlink = ctx->inputs[i]; + AVChannelLayout *chl = &inlink->ch_layout; + ChannelList *iu = &inputs_unused[i]; + + iu->nb_ch = chl->nb_channels; + iu->ch = av_malloc_array(iu->nb_ch, sizeof(*iu->ch)); + if (!iu->ch) { + ret = AVERROR(ENOMEM); + goto fail; + } + + for (int ch_idx = 0; ch_idx < iu->nb_ch; ch_idx++) { + iu->ch[ch_idx] = av_channel_layout_channel_from_index(chl, ch_idx); + if (iu->ch[ch_idx] < 0) { + /* no channel ordering information in this input, + * so don't auto-map from it */ + iu->nb_ch = 0; + break; + } + } + } + + /* process user-specified maps */ + for (i = 0; i < s->ch_layout.nb_channels; i++) { ChannelMap *ch = &s->channels[i]; AVFilterLink *inlink; + AVChannelLayout *ichl; + ChannelList *iu; if (ch->input < 0) continue; inlink = ctx->inputs[ch->input]; + ichl = &inlink->ch_layout; + iu = &inputs_unused[ch->input]; - if (!ch->in_channel) - ch->in_channel = av_channel_layout_extract_channel(inlink->channel_layout, - ch->in_channel_idx); + /* get the index for the channels defined by name */ + if (ch->in_channel != AV_CHAN_NONE) { + ch->in_channel_idx = av_channel_layout_index_from_channel(ichl, ch->in_channel); + if (ch->in_channel_idx < 0) { + av_channel_name(inbuf, sizeof(inbuf), ch->in_channel); + av_log(ctx, AV_LOG_ERROR, "Requested channel %s is not present in " + "input stream #%d.\n", inbuf, + ch->input); + ret = AVERROR(EINVAL); + goto fail; + } + } - if (!(ch->in_channel & inlink->channel_layout)) { - av_log(ctx, AV_LOG_ERROR, "Requested channel %s is not present in " - "input stream #%d.\n", av_get_channel_name(ch->in_channel), - ch->input); + /* make sure channels specified by index actually exist */ + if (ch->in_channel_idx >= ichl->nb_channels) { + av_log(ctx, AV_LOG_ERROR, "Requested channel with index %d is not " + "present in input stream #%d.\n", ch->in_channel_idx, ch->input); ret = AVERROR(EINVAL); goto fail; } - inputs[ch->input] |= ch->in_channel; + channel_list_pop_ch(iu, av_channel_layout_channel_from_index(ichl, ch->in_channel_idx)); } /* guess channel maps when not explicitly defined */ /* first try unused matching channels */ - for (i = 0; i < s->nb_channels; i++) { + for (i = 0; i < s->ch_layout.nb_channels; i++) { ChannelMap *ch = &s->channels[i]; if (ch->input < 0) - guess_map_matching(ctx, ch, inputs); + guess_map_matching(ctx, ch, inputs_unused); } /* if the above failed, try to find _any_ unused input channel */ - for (i = 0; i < s->nb_channels; i++) { + for (i = 0; i < s->ch_layout.nb_channels; i++) { ChannelMap *ch = &s->channels[i]; if (ch->input < 0) - guess_map_any(ctx, ch, inputs); + guess_map_any(ctx, ch, inputs_unused); if (ch->input < 0) { + av_channel_name(outbuf, sizeof(outbuf), ch->out_channel); av_log(ctx, AV_LOG_ERROR, "Could not find input channel for " "output channel '%s'.\n", - av_get_channel_name(ch->out_channel)); + outbuf); + ret = AVERROR(EINVAL); goto fail; } - ch->in_channel_idx = av_get_channel_layout_channel_index(ctx->inputs[ch->input]->channel_layout, - ch->in_channel); + if (ch->in_channel != AV_CHAN_NONE) { + ch->in_channel_idx = av_channel_layout_index_from_channel( + &ctx->inputs[ch->input]->ch_layout, ch->in_channel); + } + + av_assert0(ch->in_channel_idx >= 0); } /* print mappings */ av_log(ctx, AV_LOG_VERBOSE, "mappings: "); - for (i = 0; i < s->nb_channels; i++) { + for (i = 0; i < s->ch_layout.nb_channels; i++) { ChannelMap *ch = &s->channels[i]; - av_log(ctx, AV_LOG_VERBOSE, "%d.%s => %s ", ch->input, - av_get_channel_name(ch->in_channel), - av_get_channel_name(ch->out_channel)); + AVFilterLink *inlink = ctx->inputs[ch->input]; + AVChannelLayout *ichl = &inlink->ch_layout; + enum AVChannel in_ch = av_channel_layout_channel_from_index( + ichl, ch->in_channel_idx); + + av_channel_name(inbuf, sizeof(inbuf), in_ch); + av_channel_name(outbuf, sizeof(outbuf), ch->out_channel); + av_log(ctx, AV_LOG_VERBOSE, "%d.%s(%d) => %s(%d) ", ch->input, + inbuf, ch->in_channel_idx, + outbuf, i); } av_log(ctx, AV_LOG_VERBOSE, "\n"); for (i = 0; i < ctx->nb_inputs; i++) { - if (!inputs[i]) + if (inputs_unused[i].nb_ch == ctx->inputs[i]->ch_layout.nb_channels) av_log(ctx, AV_LOG_WARNING, "No channels are used from input " "stream %d.\n", i); } fail: - av_freep(&inputs); + for (i = 0; i < ctx->nb_inputs; i++) + av_freep(&inputs_unused[i].ch); + av_freep(&inputs_unused); return ret; } @@ -382,8 +460,8 @@ static int try_push_frame(AVFilterContext *ctx) frame = av_frame_alloc(); if (!frame) return AVERROR(ENOMEM); - if (s->nb_channels > FF_ARRAY_ELEMS(frame->data)) { - frame->extended_data = av_calloc(s->nb_channels, + if (s->ch_layout.nb_channels > FF_ARRAY_ELEMS(frame->data)) { + frame->extended_data = av_calloc(s->ch_layout.nb_channels, sizeof(*frame->extended_data)); if (!frame->extended_data) { ret = AVERROR(ENOMEM); @@ -392,7 +470,7 @@ static int try_push_frame(AVFilterContext *ctx) } /* copy the data pointers */ - for (i = 0; i < s->nb_channels; i++) { + for (i = 0; i < s->ch_layout.nb_channels; i++) { ChannelMap *ch = &s->channels[i]; AVFrame *cur = s->input_frames[ch->input]; AVBufferRef *buf; @@ -442,15 +520,21 @@ static int try_push_frame(AVFilterContext *ctx) } frame->nb_samples = nb_samples; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS frame->channel_layout = outlink->channel_layout; - frame->channels = outlink->channels; + frame->channels = outlink->ch_layout.nb_channels; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + if ((ret = av_channel_layout_copy(&frame->ch_layout, &outlink->ch_layout)) < 0) + return ret; frame->sample_rate = outlink->sample_rate; frame->format = outlink->format; frame->pts = s->input_frames[0]->pts; frame->linesize[0] = linesize; if (frame->data != frame->extended_data) { memcpy(frame->data, frame->extended_data, sizeof(*frame->data) * - FFMIN(FF_ARRAY_ELEMS(frame->data), s->nb_channels)); + FFMIN(FF_ARRAY_ELEMS(frame->data), s->ch_layout.nb_channels)); } s->eof_pts = frame->pts + av_rescale_q(frame->nb_samples, @@ -502,7 +586,8 @@ static int activate(AVFilterContext *ctx) } } - nb_samples = s->input_frames[0]->nb_samples; + if (s->input_frames[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]) diff --git a/libavfilter/af_ladspa.c b/libavfilter/af_ladspa.c index ff16388a5..fc93d56af 100644 --- a/libavfilter/af_ladspa.c +++ b/libavfilter/af_ladspa.c @@ -29,11 +29,17 @@ #include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/channel_layout.h" +#include "libavutil/fifo.h" #include "libavutil/opt.h" #include "audio.h" #include "avfilter.h" #include "internal.h" +typedef struct MetaItem { + int64_t pts; + int nb_samples; +} MetaItem; + typedef struct LADSPAContext { const AVClass *class; char *dl_name; @@ -62,11 +68,15 @@ typedef struct LADSPAContext { int sample_rate; int nb_samples; + int64_t next_in_pts; + int64_t next_out_pts; int64_t pts; int64_t duration; int in_trim; int out_pad; int latency; + + AVFifo *fifo; } LADSPAContext; #define OFFSET(x) offsetof(LADSPAContext, x) @@ -164,8 +174,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) LADSPAContext *s = ctx->priv; AVFrame *out; int i, h, p, new_out_samples; + int64_t out_duration; + int64_t in_duration; + int64_t in_pts; + MetaItem meta; - av_assert0(in->channels == (s->nb_inputs * s->nb_handles)); + av_assert0(in->ch_layout.nb_channels == (s->nb_inputs * s->nb_handles)); if (!s->nb_outputs || (av_frame_is_writable(in) && s->nb_inputs == s->nb_outputs && @@ -181,7 +195,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) av_frame_copy_props(out, in); } - av_assert0(!s->nb_outputs || out->channels == (s->nb_outputs * s->nb_handles)); + av_assert0(!s->nb_outputs || out->ch_layout.nb_channels == (s->nb_outputs * s->nb_handles)); for (h = 0; h < s->nb_handles; h++) { for (i = 0; i < s->nb_inputs; i++) { @@ -205,6 +219,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) for (i = 0; i < s->nb_outputcontrols; i++) print_ctl_info(ctx, AV_LOG_VERBOSE, s, i, s->ocmap, s->octlv, 1); + meta = (MetaItem){ in->pts, in->nb_samples }; + av_fifo_write(s->fifo, &meta, 1); + if (out != in) av_frame_free(&in); @@ -221,12 +238,27 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) return 0; } else if (new_out_samples < out->nb_samples) { int offset = out->nb_samples - new_out_samples; - for (int ch = 0; ch < out->channels; ch++) + for (int ch = 0; ch < out->ch_layout.nb_channels; ch++) memmove(out->extended_data[ch], out->extended_data[ch] + sizeof(float) * offset, sizeof(float) * new_out_samples); out->nb_samples = new_out_samples; } + av_fifo_read(s->fifo, &meta, 1); + + out_duration = av_rescale_q(out->nb_samples, inlink->time_base, av_make_q(1, out->sample_rate)); + in_duration = av_rescale_q(meta.nb_samples, inlink->time_base, av_make_q(1, out->sample_rate)); + in_pts = meta.pts; + + if (s->next_out_pts != AV_NOPTS_VALUE && out->pts != s->next_out_pts && + s->next_in_pts != AV_NOPTS_VALUE && in_pts == s->next_in_pts) { + out->pts = s->next_out_pts; + } else { + out->pts = in_pts; + } + s->next_in_pts = in_pts + in_duration; + s->next_out_pts = out->pts + out_duration; + return ff_filter_frame(ctx->outputs[0], out); } @@ -247,6 +279,7 @@ static int request_frame(AVFilterLink *outlink) return AVERROR(ENOMEM); s->out_pad -= frame->nb_samples; + frame->pts = s->next_in_pts; return filter_frame(ctx->inputs[0], frame); } return ret; @@ -318,7 +351,7 @@ static int connect_ports(AVFilterContext *ctx, AVFilterLink *link) LADSPAContext *s = ctx->priv; int i, j; - s->nb_handles = s->nb_inputs == 1 && s->nb_outputs == 1 ? link->channels : 1; + s->nb_handles = s->nb_inputs == 1 && s->nb_outputs == 1 ? link->ch_layout.nb_channels : 1; s->handles = av_calloc(s->nb_handles, sizeof(*s->handles)); if (!s->handles) return AVERROR(ENOMEM); @@ -366,8 +399,13 @@ static int config_output(AVFilterLink *outlink) outlink->format = inlink->format; outlink->sample_rate = inlink->sample_rate; if (s->nb_inputs == s->nb_outputs) { + if ((ret = av_channel_layout_copy(&outlink->ch_layout, &inlink->ch_layout)) < 0) + return ret; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS outlink->channel_layout = inlink->channel_layout; - outlink->channels = inlink->channels; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } ret = 0; @@ -649,6 +687,13 @@ static av_cold int init(AVFilterContext *ctx) av_log(ctx, AV_LOG_DEBUG, "input controls: %lu output controls: %lu\n", s->nb_inputcontrols, s->nb_outputcontrols); + s->next_out_pts = AV_NOPTS_VALUE; + s->next_in_pts = AV_NOPTS_VALUE; + + s->fifo = av_fifo_alloc2(8, sizeof(MetaItem), AV_FIFO_FLAG_AUTO_GROW); + if (!s->fifo) + return AVERROR(ENOMEM); + return 0; } @@ -681,7 +726,7 @@ static int query_formats(AVFilterContext *ctx) return ret; } else if (s->nb_inputs == 2 && s->nb_outputs == 2) { layouts = NULL; - ret = ff_add_channel_layout(&layouts, AV_CH_LAYOUT_STEREO); + ret = ff_add_channel_layout(&layouts, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO); if (ret < 0) return ret; ret = ff_set_common_channel_layouts(ctx, layouts); @@ -692,10 +737,10 @@ static int query_formats(AVFilterContext *ctx) if (s->nb_inputs >= 1) { AVFilterLink *inlink = ctx->inputs[0]; - uint64_t inlayout = FF_COUNT2LAYOUT(s->nb_inputs); + AVChannelLayout inlayout = FF_COUNT2LAYOUT(s->nb_inputs); layouts = NULL; - ret = ff_add_channel_layout(&layouts, inlayout); + ret = ff_add_channel_layout(&layouts, &inlayout); if (ret < 0) return ret; ret = ff_channel_layouts_ref(layouts, &inlink->outcfg.channel_layouts); @@ -710,10 +755,10 @@ static int query_formats(AVFilterContext *ctx) } if (s->nb_outputs >= 1) { - uint64_t outlayout = FF_COUNT2LAYOUT(s->nb_outputs); + AVChannelLayout outlayout = FF_COUNT2LAYOUT(s->nb_outputs); layouts = NULL; - ret = ff_add_channel_layout(&layouts, outlayout); + ret = ff_add_channel_layout(&layouts, &outlayout); if (ret < 0) return ret; ret = ff_channel_layouts_ref(layouts, &outlink->incfg.channel_layouts); @@ -748,6 +793,8 @@ static av_cold void uninit(AVFilterContext *ctx) av_freep(&s->octlv); av_freep(&s->handles); av_freep(&s->ctl_needs_value); + + av_fifo_freep2(&s->fifo); } static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, diff --git a/libavfilter/af_loudnorm.c b/libavfilter/af_loudnorm.c index dbe7fba98..8d2379f14 100644 --- a/libavfilter/af_loudnorm.c +++ b/libavfilter/af_loudnorm.c @@ -101,8 +101,8 @@ typedef struct LoudNormContext { static const AVOption loudnorm_options[] = { { "I", "set integrated loudness target", OFFSET(target_i), AV_OPT_TYPE_DOUBLE, {.dbl = -24.}, -70., -5., FLAGS }, { "i", "set integrated loudness target", OFFSET(target_i), AV_OPT_TYPE_DOUBLE, {.dbl = -24.}, -70., -5., FLAGS }, - { "LRA", "set loudness range target", OFFSET(target_lra), AV_OPT_TYPE_DOUBLE, {.dbl = 7.}, 1., 20., FLAGS }, - { "lra", "set loudness range target", OFFSET(target_lra), AV_OPT_TYPE_DOUBLE, {.dbl = 7.}, 1., 20., FLAGS }, + { "LRA", "set loudness range target", OFFSET(target_lra), AV_OPT_TYPE_DOUBLE, {.dbl = 7.}, 1., 50., FLAGS }, + { "lra", "set loudness range target", OFFSET(target_lra), AV_OPT_TYPE_DOUBLE, {.dbl = 7.}, 1., 50., FLAGS }, { "TP", "set maximum true peak", OFFSET(target_tp), AV_OPT_TYPE_DOUBLE, {.dbl = -2.}, -9., 0., FLAGS }, { "tp", "set maximum true peak", OFFSET(target_tp), AV_OPT_TYPE_DOUBLE, {.dbl = -2.}, -9., 0., FLAGS }, { "measured_I", "measured IL of input file", OFFSET(measured_i), AV_OPT_TYPE_DOUBLE, {.dbl = 0.}, -99., 0., FLAGS }, @@ -446,7 +446,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) double offset, offset_tp, true_peak; ff_ebur128_loudness_global(s->r128_in, &global); - for (c = 0; c < inlink->channels; c++) { + for (c = 0; c < inlink->ch_layout.nb_channels; c++) { double tmp; ff_ebur128_sample_peak(s->r128_in, c, &tmp); if (c == 0 || tmp > true_peak) @@ -462,11 +462,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) switch (s->frame_type) { case FIRST_FRAME: for (n = 0; n < in->nb_samples; n++) { - for (c = 0; c < inlink->channels; c++) { + for (c = 0; c < inlink->ch_layout.nb_channels; c++) { buf[s->buf_index + c] = src[c]; } - src += inlink->channels; - s->buf_index += inlink->channels; + src += inlink->ch_layout.nb_channels; + s->buf_index += inlink->ch_layout.nb_channels; } ff_ebur128_loudness_shortterm(s->r128_in, &shortterm); @@ -486,19 +486,19 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) s->buf_index = s->limiter_buf_index = 0; - for (n = 0; n < (s->limiter_buf_size / inlink->channels); n++) { - for (c = 0; c < inlink->channels; c++) { + for (n = 0; n < (s->limiter_buf_size / inlink->ch_layout.nb_channels); n++) { + for (c = 0; c < inlink->ch_layout.nb_channels; c++) { limiter_buf[s->limiter_buf_index + c] = buf[s->buf_index + c] * s->delta[s->index] * s->offset; } - s->limiter_buf_index += inlink->channels; + s->limiter_buf_index += inlink->ch_layout.nb_channels; if (s->limiter_buf_index >= s->limiter_buf_size) s->limiter_buf_index -= s->limiter_buf_size; - s->buf_index += inlink->channels; + s->buf_index += inlink->ch_layout.nb_channels; } subframe_length = frame_size(inlink->sample_rate, 100); - true_peak_limiter(s, dst, subframe_length, inlink->channels); + true_peak_limiter(s, dst, subframe_length, inlink->ch_layout.nb_channels); ff_ebur128_add_frames_double(s->r128_out, dst, subframe_length); s->pts += @@ -514,29 +514,29 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) gain_next = gaussian_filter(s, s->index + 11 < 30 ? s->index + 11 : s->index + 11 - 30); for (n = 0; n < in->nb_samples; n++) { - for (c = 0; c < inlink->channels; c++) { + for (c = 0; c < inlink->ch_layout.nb_channels; c++) { buf[s->prev_buf_index + c] = src[c]; limiter_buf[s->limiter_buf_index + c] = buf[s->buf_index + c] * (gain + (((double) n / in->nb_samples) * (gain_next - gain))) * s->offset; } - src += inlink->channels; + src += inlink->ch_layout.nb_channels; - s->limiter_buf_index += inlink->channels; + s->limiter_buf_index += inlink->ch_layout.nb_channels; if (s->limiter_buf_index >= s->limiter_buf_size) s->limiter_buf_index -= s->limiter_buf_size; - s->prev_buf_index += inlink->channels; + s->prev_buf_index += inlink->ch_layout.nb_channels; if (s->prev_buf_index >= s->buf_size) s->prev_buf_index -= s->buf_size; - s->buf_index += inlink->channels; + s->buf_index += inlink->ch_layout.nb_channels; if (s->buf_index >= s->buf_size) s->buf_index -= s->buf_size; } - subframe_length = (frame_size(inlink->sample_rate, 100) - in->nb_samples) * inlink->channels; + subframe_length = (frame_size(inlink->sample_rate, 100) - in->nb_samples) * inlink->ch_layout.nb_channels; s->limiter_buf_index = s->limiter_buf_index + subframe_length < s->limiter_buf_size ? s->limiter_buf_index + subframe_length : s->limiter_buf_index + subframe_length - s->limiter_buf_size; - true_peak_limiter(s, dst, in->nb_samples, inlink->channels); + true_peak_limiter(s, dst, in->nb_samples, inlink->ch_layout.nb_channels); ff_ebur128_add_frames_double(s->r128_out, dst, in->nb_samples); ff_ebur128_loudness_range(s->r128_in, &lra); @@ -576,39 +576,39 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) s->limiter_buf_index = 0; src_index = 0; - for (n = 0; n < s->limiter_buf_size / inlink->channels; n++) { - for (c = 0; c < inlink->channels; c++) { + for (n = 0; n < s->limiter_buf_size / inlink->ch_layout.nb_channels; n++) { + for (c = 0; c < inlink->ch_layout.nb_channels; c++) { s->limiter_buf[s->limiter_buf_index + c] = src[src_index + c] * gain * s->offset; } - src_index += inlink->channels; + src_index += inlink->ch_layout.nb_channels; - s->limiter_buf_index += inlink->channels; + s->limiter_buf_index += inlink->ch_layout.nb_channels; if (s->limiter_buf_index >= s->limiter_buf_size) s->limiter_buf_index -= s->limiter_buf_size; } subframe_length = frame_size(inlink->sample_rate, 100); for (i = 0; i < in->nb_samples / subframe_length; i++) { - true_peak_limiter(s, dst, subframe_length, inlink->channels); + true_peak_limiter(s, dst, subframe_length, inlink->ch_layout.nb_channels); for (n = 0; n < subframe_length; n++) { - for (c = 0; c < inlink->channels; c++) { - if (src_index < (in->nb_samples * inlink->channels)) { + for (c = 0; c < inlink->ch_layout.nb_channels; c++) { + if (src_index < (in->nb_samples * inlink->ch_layout.nb_channels)) { limiter_buf[s->limiter_buf_index + c] = src[src_index + c] * gain * s->offset; } else { limiter_buf[s->limiter_buf_index + c] = 0.; } } - if (src_index < (in->nb_samples * inlink->channels)) - src_index += inlink->channels; + if (src_index < (in->nb_samples * inlink->ch_layout.nb_channels)) + src_index += inlink->ch_layout.nb_channels; - s->limiter_buf_index += inlink->channels; + s->limiter_buf_index += inlink->ch_layout.nb_channels; if (s->limiter_buf_index >= s->limiter_buf_size) s->limiter_buf_index -= s->limiter_buf_size; } - dst += (subframe_length * inlink->channels); + dst += (subframe_length * inlink->ch_layout.nb_channels); } dst = (double *)out->data[0]; @@ -617,11 +617,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) case LINEAR_MODE: for (n = 0; n < in->nb_samples; n++) { - for (c = 0; c < inlink->channels; c++) { + for (c = 0; c < inlink->ch_layout.nb_channels; c++) { dst[c] = src[c] * s->offset; } - src += inlink->channels; - dst += inlink->channels; + src += inlink->ch_layout.nb_channels; + dst += inlink->ch_layout.nb_channels; } dst = (double *)out->data[0]; @@ -650,7 +650,7 @@ static int request_frame(AVFilterLink *outlink) int nb_samples, n, c, offset; AVFrame *frame; - nb_samples = (s->buf_size / inlink->channels) - s->prev_nb_samples; + nb_samples = (s->buf_size / inlink->ch_layout.nb_channels) - s->prev_nb_samples; nb_samples -= (frame_size(inlink->sample_rate, 100) - s->prev_nb_samples); frame = ff_get_audio_buffer(outlink, nb_samples); @@ -661,16 +661,16 @@ static int request_frame(AVFilterLink *outlink) buf = s->buf; src = (double *)frame->data[0]; - offset = ((s->limiter_buf_size / inlink->channels) - s->prev_nb_samples) * inlink->channels; - offset -= (frame_size(inlink->sample_rate, 100) - s->prev_nb_samples) * inlink->channels; + offset = ((s->limiter_buf_size / inlink->ch_layout.nb_channels) - s->prev_nb_samples) * inlink->ch_layout.nb_channels; + offset -= (frame_size(inlink->sample_rate, 100) - s->prev_nb_samples) * inlink->ch_layout.nb_channels; s->buf_index = s->buf_index - offset < 0 ? s->buf_index - offset + s->buf_size : s->buf_index - offset; for (n = 0; n < nb_samples; n++) { - for (c = 0; c < inlink->channels; c++) { + for (c = 0; c < inlink->ch_layout.nb_channels; c++) { src[c] = buf[s->buf_index + c]; } - src += inlink->channels; - s->buf_index += inlink->channels; + src += inlink->ch_layout.nb_channels; + s->buf_index += inlink->ch_layout.nb_channels; if (s->buf_index >= s->buf_size) s->buf_index -= s->buf_size; } @@ -720,30 +720,30 @@ static int config_input(AVFilterLink *inlink) AVFilterContext *ctx = inlink->dst; LoudNormContext *s = ctx->priv; - s->r128_in = ff_ebur128_init(inlink->channels, inlink->sample_rate, 0, FF_EBUR128_MODE_I | FF_EBUR128_MODE_S | FF_EBUR128_MODE_LRA | FF_EBUR128_MODE_SAMPLE_PEAK); + s->r128_in = ff_ebur128_init(inlink->ch_layout.nb_channels, inlink->sample_rate, 0, FF_EBUR128_MODE_I | FF_EBUR128_MODE_S | FF_EBUR128_MODE_LRA | FF_EBUR128_MODE_SAMPLE_PEAK); if (!s->r128_in) return AVERROR(ENOMEM); - s->r128_out = ff_ebur128_init(inlink->channels, inlink->sample_rate, 0, FF_EBUR128_MODE_I | FF_EBUR128_MODE_S | FF_EBUR128_MODE_LRA | FF_EBUR128_MODE_SAMPLE_PEAK); + s->r128_out = ff_ebur128_init(inlink->ch_layout.nb_channels, inlink->sample_rate, 0, FF_EBUR128_MODE_I | FF_EBUR128_MODE_S | FF_EBUR128_MODE_LRA | FF_EBUR128_MODE_SAMPLE_PEAK); if (!s->r128_out) return AVERROR(ENOMEM); - if (inlink->channels == 1 && s->dual_mono) { + if (inlink->ch_layout.nb_channels == 1 && s->dual_mono) { ff_ebur128_set_channel(s->r128_in, 0, FF_EBUR128_DUAL_MONO); ff_ebur128_set_channel(s->r128_out, 0, FF_EBUR128_DUAL_MONO); } - s->buf_size = frame_size(inlink->sample_rate, 3000) * inlink->channels; + s->buf_size = frame_size(inlink->sample_rate, 3000) * inlink->ch_layout.nb_channels; s->buf = av_malloc_array(s->buf_size, sizeof(*s->buf)); if (!s->buf) return AVERROR(ENOMEM); - s->limiter_buf_size = frame_size(inlink->sample_rate, 210) * inlink->channels; + s->limiter_buf_size = frame_size(inlink->sample_rate, 210) * inlink->ch_layout.nb_channels; s->limiter_buf = av_malloc_array(s->buf_size, sizeof(*s->limiter_buf)); if (!s->limiter_buf) return AVERROR(ENOMEM); - s->prev_smp = av_malloc_array(inlink->channels, sizeof(*s->prev_smp)); + s->prev_smp = av_malloc_array(inlink->ch_layout.nb_channels, sizeof(*s->prev_smp)); if (!s->prev_smp) return AVERROR(ENOMEM); @@ -758,7 +758,7 @@ static int config_input(AVFilterLink *inlink) s->buf_index = s->prev_buf_index = s->limiter_buf_index = 0; - s->channels = inlink->channels; + s->channels = inlink->ch_layout.nb_channels; s->index = 1; s->limiter_state = OUT; s->offset = pow(10., s->offset / 20.); diff --git a/libavfilter/af_lv2.c b/libavfilter/af_lv2.c index 0f0c79798..3cdf16457 100644 --- a/libavfilter/af_lv2.c +++ b/libavfilter/af_lv2.c @@ -288,8 +288,14 @@ static int config_output(AVFilterLink *outlink) outlink->format = inlink->format; outlink->sample_rate = sample_rate = inlink->sample_rate; if (s->nb_inputs == s->nb_outputs) { + int ret; + if ((ret = av_channel_layout_copy(&outlink->ch_layout, &inlink->ch_layout)) < 0) + return ret; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS outlink->channel_layout = inlink->channel_layout; - outlink->channels = inlink->channels; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } } else { @@ -496,7 +502,7 @@ static int query_formats(AVFilterContext *ctx) if (s->nb_inputs == 2 && s->nb_outputs == 2) { layouts = NULL; - ret = ff_add_channel_layout(&layouts, AV_CH_LAYOUT_STEREO); + ret = ff_add_channel_layout(&layouts, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO); if (ret < 0) return ret; ret = ff_set_common_channel_layouts(ctx, layouts); @@ -505,10 +511,10 @@ static int query_formats(AVFilterContext *ctx) } else { if (s->nb_inputs >= 1) { AVFilterLink *inlink = ctx->inputs[0]; - uint64_t inlayout = FF_COUNT2LAYOUT(s->nb_inputs); + AVChannelLayout inlayout = FF_COUNT2LAYOUT(s->nb_inputs); layouts = NULL; - ret = ff_add_channel_layout(&layouts, inlayout); + ret = ff_add_channel_layout(&layouts, &inlayout); if (ret < 0) return ret; ret = ff_channel_layouts_ref(layouts, &inlink->outcfg.channel_layouts); @@ -523,10 +529,10 @@ static int query_formats(AVFilterContext *ctx) } if (s->nb_outputs >= 1) { - uint64_t outlayout = FF_COUNT2LAYOUT(s->nb_outputs); + AVChannelLayout outlayout = FF_COUNT2LAYOUT(s->nb_outputs); layouts = NULL; - ret = ff_add_channel_layout(&layouts, outlayout); + ret = ff_add_channel_layout(&layouts, &outlayout); if (ret < 0) return ret; ret = ff_channel_layouts_ref(layouts, &outlink->incfg.channel_layouts); @@ -538,6 +544,26 @@ static int query_formats(AVFilterContext *ctx) return 0; } +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + LV2Context *s = ctx->priv; + const LilvPort *port; + LilvNode *sym; + int index; + + sym = lilv_new_string(s->world, cmd); + 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", cmd); + } else { + index = lilv_port_get_index(s->plugin, port); + s->controls[index] = atof(args); + } + return 0; +} + static av_cold void uninit(AVFilterContext *ctx) { LV2Context *s = ctx->priv; @@ -578,6 +604,7 @@ const AVFilter ff_af_lv2 = { .priv_class = &lv2_class, .init = init, .uninit = uninit, + .process_command = process_command, .inputs = 0, FILTER_OUTPUTS(lv2_outputs), FILTER_QUERY_FUNC(query_formats), diff --git a/libavfilter/af_mcompand.c b/libavfilter/af_mcompand.c index 90cfda38c..1267cd9f3 100644 --- a/libavfilter/af_mcompand.c +++ b/libavfilter/af_mcompand.c @@ -302,7 +302,7 @@ static int crossover_setup(AVFilterLink *outlink, Crossover *p, double frequency square_quadratic(x + 3, p->coefs + 5); square_quadratic(x + 6, p->coefs + 10); - p->previous = av_calloc(outlink->channels, sizeof(*p->previous)); + p->previous = av_calloc(outlink->ch_layout.nb_channels, sizeof(*p->previous)); if (!p->previous) return AVERROR(ENOMEM); @@ -350,13 +350,13 @@ static int config_output(AVFilterLink *outlink) 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)); + s->bands[i].attack_rate = av_calloc(outlink->ch_layout.nb_channels, sizeof(double)); + s->bands[i].decay_rate = av_calloc(outlink->ch_layout.nb_channels, sizeof(double)); + s->bands[i].volume = av_calloc(outlink->ch_layout.nb_channels, sizeof(double)); if (!s->bands[i].attack_rate || !s->bands[i].decay_rate || !s->bands[i].volume) return AVERROR(ENOMEM); - for (k = 0; k < FFMIN(nb_attacks / 2, outlink->channels); k++) { + for (k = 0; k < FFMIN(nb_attacks / 2, outlink->ch_layout.nb_channels); k++) { char *tstr3 = av_strtok(p3, ",", &saveptr3); p3 = NULL; @@ -377,7 +377,7 @@ static int config_output(AVFilterLink *outlink) } } - for (ch = k; ch < outlink->channels; ch++) { + for (ch = k; ch < outlink->ch_layout.nb_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]; } @@ -440,7 +440,7 @@ static int config_output(AVFilterLink *outlink) sscanf(tstr2, "%lf", &initial_volume); initial_volume = pow(10.0, initial_volume / 20); - for (k = 0; k < outlink->channels; k++) { + for (k = 0; k < outlink->ch_layout.nb_channels; k++) { s->bands[i].volume[k] = initial_volume; } @@ -574,7 +574,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) s->band_samples = in->nb_samples; } - for (ch = 0; ch < outlink->channels; ch++) { + for (ch = 0; ch < outlink->ch_layout.nb_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++) { diff --git a/libavfilter/af_pan.c b/libavfilter/af_pan.c index a8a18960c..067f64680 100644 --- a/libavfilter/af_pan.c +++ b/libavfilter/af_pan.c @@ -42,7 +42,7 @@ typedef struct PanContext { const AVClass *class; char *args; - int64_t out_channel_layout; + AVChannelLayout out_channel_layout; double gain[MAX_CHANNELS][MAX_CHANNELS]; int64_t need_renorm; int need_renumber; @@ -65,23 +65,15 @@ static void skip_spaces(char **arg) static int parse_channel_name(char **arg, int *rchannel, int *rnamed) { char buf[8]; - int len, i, channel_id = 0; - int64_t layout, layout0; + int len, channel_id = 0; skip_spaces(arg); /* try to parse a channel name, e.g. "FL" */ if (sscanf(*arg, "%7[A-Z]%n", buf, &len)) { - layout0 = layout = av_get_channel_layout(buf); - /* channel_id <- first set bit in layout */ - for (i = 32; i > 0; i >>= 1) { - if (layout >= (int64_t)1 << i) { - channel_id += i; - layout >>= i; - } - } - /* reject layouts that are not a single channel */ - if (channel_id >= MAX_CHANNELS || layout0 != (int64_t)1 << channel_id) - return AVERROR(EINVAL); + channel_id = av_channel_from_string(buf); + if (channel_id < 0) + return channel_id; + *rchannel = channel_id; *rnamed = 1; *arg += len; @@ -137,17 +129,12 @@ static av_cold int init(AVFilterContext *ctx) goto fail; } if (named) { - if (!((pan->out_channel_layout >> out_ch_id) & 1)) { + if ((out_ch_id = av_channel_layout_index_from_channel(&pan->out_channel_layout, out_ch_id)) < 0) { av_log(ctx, AV_LOG_ERROR, "Channel \"%.8s\" does not exist in the chosen layout\n", arg0); ret = AVERROR(EINVAL); goto fail; } - /* get the channel number in the output channel layout: - * out_channel_layout & ((1 << out_ch_id) - 1) are all the - * channels that come before out_ch_id, - * so their count is the index of out_ch_id */ - out_ch_id = av_get_channel_layout_nb_channels(pan->out_channel_layout & (((int64_t)1 << out_ch_id) - 1)); } if (out_ch_id < 0 || out_ch_id >= pan->nb_output_channels) { av_log(ctx, AV_LOG_ERROR, @@ -269,9 +256,7 @@ static int query_formats(AVFilterContext *ctx) // outlink supports only requested output channel layout layouts = NULL; - if ((ret = ff_add_channel_layout(&layouts, - pan->out_channel_layout ? pan->out_channel_layout : - FF_COUNT2LAYOUT(pan->nb_output_channels))) < 0) + if ((ret = ff_add_channel_layout(&layouts, &pan->out_channel_layout)) < 0) return ret; return ff_channel_layouts_ref(layouts, &outlink->incfg.channel_layouts); } @@ -281,13 +266,13 @@ static int config_props(AVFilterLink *link) AVFilterContext *ctx = link->dst; PanContext *pan = ctx->priv; char buf[1024], *cur; - int i, j, k, r; + int i, j, k, r, ret; double t; if (pan->need_renumber) { // input channels were given by their name: renumber them for (i = j = 0; i < MAX_CHANNELS; i++) { - if ((link->channel_layout >> i) & 1) { + if (av_channel_layout_index_from_channel(&link->ch_layout, i) >= 0) { for (k = 0; k < pan->nb_output_channels; k++) pan->gain[k][j] = pan->gain[k][i]; j++; @@ -297,7 +282,7 @@ static int config_props(AVFilterLink *link) // sanity check; can't be done in query_formats since the inlink // channel layout is unknown at that time - if (link->channels > MAX_CHANNELS || + if (link->ch_layout.nb_channels > MAX_CHANNELS || pan->nb_output_channels > MAX_CHANNELS) { av_log(ctx, AV_LOG_ERROR, "af_pan supports a maximum of %d channels. " @@ -306,20 +291,12 @@ static int config_props(AVFilterLink *link) } // init libswresample context - pan->swr = swr_alloc_set_opts(pan->swr, - pan->out_channel_layout, link->format, link->sample_rate, - link->channel_layout, link->format, link->sample_rate, - 0, ctx); - if (!pan->swr) + ret = swr_alloc_set_opts2(&pan->swr, + &pan->out_channel_layout, link->format, link->sample_rate, + &link->ch_layout, link->format, link->sample_rate, + 0, ctx); + if (ret < 0) return AVERROR(ENOMEM); - if (!link->channel_layout) { - if (av_opt_set_int(pan->swr, "ich", link->channels, 0) < 0) - return AVERROR(EINVAL); - } - if (!pan->out_channel_layout) { - if (av_opt_set_int(pan->swr, "och", pan->nb_output_channels, 0) < 0) - return AVERROR(EINVAL); - } // gains are pure, init the channel mapping if (pan->pure_gains) { @@ -327,7 +304,7 @@ static int config_props(AVFilterLink *link) // get channel map from the pure gains for (i = 0; i < pan->nb_output_channels; i++) { int ch_id = -1; - for (j = 0; j < link->channels; j++) { + for (j = 0; j < link->ch_layout.nb_channels; j++) { if (pan->gain[i][j]) { ch_id = j; break; @@ -336,7 +313,6 @@ static int config_props(AVFilterLink *link) pan->channel_map[i] = ch_id; } - av_opt_set_int(pan->swr, "icl", pan->out_channel_layout, 0); av_opt_set_int(pan->swr, "uch", pan->nb_output_channels, 0); swr_set_channel_mapping(pan->swr, pan->channel_map); } else { @@ -345,7 +321,7 @@ static int config_props(AVFilterLink *link) if (!((pan->need_renorm >> i) & 1)) continue; t = 0; - for (j = 0; j < link->channels; j++) + for (j = 0; j < link->ch_layout.nb_channels; j++) t += fabs(pan->gain[i][j]); if (t > -1E-5 && t < 1E-5) { // t is almost 0 but not exactly, this is probably a mistake @@ -354,11 +330,9 @@ static int config_props(AVFilterLink *link) "Degenerate coefficients while renormalizing\n"); continue; } - for (j = 0; j < link->channels; j++) + for (j = 0; j < link->ch_layout.nb_channels; j++) pan->gain[i][j] /= t; } - av_opt_set_int(pan->swr, "icl", link->channel_layout, 0); - av_opt_set_int(pan->swr, "ocl", pan->out_channel_layout, 0); swr_set_matrix(pan->swr, pan->gain[0], pan->gain[1] - pan->gain[0]); } @@ -369,7 +343,7 @@ static int config_props(AVFilterLink *link) // summary for (i = 0; i < pan->nb_output_channels; i++) { cur = buf; - for (j = 0; j < link->channels; j++) { + for (j = 0; j < link->ch_layout.nb_channels; j++) { r = snprintf(cur, buf + sizeof(buf) - cur, "%s%.3g i%d", j ? " + " : "", pan->gain[i][j], j); cur += FFMIN(buf + sizeof(buf) - cur, r); @@ -405,8 +379,14 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) swr_convert(pan->swr, outsamples->extended_data, n, (void *)insamples->extended_data, n); av_frame_copy_props(outsamples, insamples); +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS outsamples->channel_layout = outlink->channel_layout; - outsamples->channels = outlink->channels; + outsamples->channels = outlink->ch_layout.nb_channels; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + if ((ret = av_channel_layout_copy(&outsamples->ch_layout, &outlink->ch_layout)) < 0) + return ret; ret = ff_filter_frame(outlink, outsamples); av_frame_free(&insamples); diff --git a/libavfilter/af_replaygain.c b/libavfilter/af_replaygain.c index e9bfc5676..53852ac8b 100644 --- a/libavfilter/af_replaygain.c +++ b/libavfilter/af_replaygain.c @@ -327,7 +327,7 @@ static int query_formats(AVFilterContext *ctx) if ((ret = ff_add_format (&formats, AV_SAMPLE_FMT_FLT )) < 0 || (ret = ff_set_common_formats (ctx , formats )) < 0 || - (ret = ff_add_channel_layout (&layout , AV_CH_LAYOUT_STEREO)) < 0 || + (ret = ff_add_channel_layout (&layout , &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO)) < 0 || (ret = ff_set_common_channel_layouts (ctx , layout )) < 0) return ret; diff --git a/libavfilter/af_rubberband.c b/libavfilter/af_rubberband.c index 4a42aa8a1..34a160566 100644 --- a/libavfilter/af_rubberband.c +++ b/libavfilter/af_rubberband.c @@ -135,7 +135,7 @@ static int config_input(AVFilterLink *inlink) if (s->rbs) rubberband_delete(s->rbs); - s->rbs = rubberband_new(inlink->sample_rate, inlink->channels, opts, 1. / s->tempo, s->pitch); + s->rbs = rubberband_new(inlink->sample_rate, inlink->ch_layout.nb_channels, opts, 1. / s->tempo, s->pitch); if (!s->rbs) return AVERROR(ENOMEM); diff --git a/libavfilter/af_sidechaincompress.c b/libavfilter/af_sidechaincompress.c index c0ce82066..4d060060e 100644 --- a/libavfilter/af_sidechaincompress.c +++ b/libavfilter/af_sidechaincompress.c @@ -24,6 +24,8 @@ * Audio (Sidechain) Compressor filter */ +#include "config_components.h" + #include "libavutil/audio_fifo.h" #include "libavutil/channel_layout.h" #include "libavutil/common.h" @@ -177,13 +179,13 @@ static void compressor(SidechainCompressContext *s, abs_sample = fabs(scsrc[0] * level_sc); if (s->link == 1) { - for (c = 1; c < sclink->channels; c++) + for (c = 1; c < sclink->ch_layout.nb_channels; c++) abs_sample = FFMAX(fabs(scsrc[c] * level_sc), abs_sample); } else { - for (c = 1; c < sclink->channels; c++) + for (c = 1; c < sclink->ch_layout.nb_channels; c++) abs_sample += fabs(scsrc[c] * level_sc); - abs_sample /= sclink->channels; + abs_sample /= sclink->ch_layout.nb_channels; } if (s->detection) @@ -206,12 +208,12 @@ static void compressor(SidechainCompressContext *s, s->compressed_knee_stop, s->detection, s->mode); - for (c = 0; c < inlink->channels; c++) + for (c = 0; c < inlink->ch_layout.nb_channels; c++) dst[c] = src[c] * level_in * (gain * makeup * mix + (1. - mix)); - src += inlink->channels; - dst += inlink->channels; - scsrc += sclink->channels; + src += inlink->ch_layout.nb_channels; + dst += inlink->ch_layout.nb_channels; + scsrc += sclink->ch_layout.nb_channels; } } @@ -325,8 +327,8 @@ static int config_output(AVFilterLink *outlink) outlink->time_base = ctx->inputs[0]->time_base; - s->fifo[0] = av_audio_fifo_alloc(ctx->inputs[0]->format, ctx->inputs[0]->channels, 1024); - s->fifo[1] = av_audio_fifo_alloc(ctx->inputs[1]->format, ctx->inputs[1]->channels, 1024); + s->fifo[0] = av_audio_fifo_alloc(ctx->inputs[0]->format, ctx->inputs[0]->ch_layout.nb_channels, 1024); + s->fifo[1] = av_audio_fifo_alloc(ctx->inputs[1]->format, ctx->inputs[1]->ch_layout.nb_channels, 1024); if (!s->fifo[0] || !s->fifo[1]) return AVERROR(ENOMEM); diff --git a/libavfilter/af_silencedetect.c b/libavfilter/af_silencedetect.c index 0ba76469d..6518283d9 100644 --- a/libavfilter/af_silencedetect.c +++ b/libavfilter/af_silencedetect.c @@ -136,12 +136,12 @@ static void silencedetect_##name(SilenceDetectContext *s, AVFrame *insamples, int nb_samples, int64_t nb_samples_notify, \ AVRational time_base) \ { \ - const int channels = insamples->channels; \ + const int channels = insamples->ch_layout.nb_channels; \ const type noise = s->noise; \ \ nb_samples /= channels; \ for (int i = 0; i < nb_samples; i++) { \ - for (int ch = 0; ch < insamples->channels; ch++) { \ + for (int ch = 0; ch < insamples->ch_layout.nb_channels; ch++) { \ const type *p = (const type *)insamples->extended_data[ch]; \ update(s, insamples, p[i] < noise && p[i] > -noise, \ channels * i + ch, \ @@ -166,7 +166,7 @@ static int config_input(AVFilterLink *inlink) SilenceDetectContext *s = ctx->priv; int c; - s->channels = inlink->channels; + s->channels = inlink->ch_layout.nb_channels; s->duration = av_rescale(s->duration, inlink->sample_rate, AV_TIME_BASE); s->independent_channels = s->mono ? s->channels : 1; s->nb_null_samples = av_calloc(s->independent_channels, @@ -210,7 +210,7 @@ static int config_input(AVFilterLink *inlink) static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) { SilenceDetectContext *s = inlink->dst->priv; - const int nb_channels = inlink->channels; + const int nb_channels = inlink->ch_layout.nb_channels; const int srate = inlink->sample_rate; const int nb_samples = insamples->nb_samples * nb_channels; const int64_t nb_samples_notify = s->duration * (s->mono ? 1 : nb_channels); diff --git a/libavfilter/af_silenceremove.c b/libavfilter/af_silenceremove.c index a02e1de78..a6db9be9d 100644 --- a/libavfilter/af_silenceremove.c +++ b/libavfilter/af_silenceremove.c @@ -136,10 +136,10 @@ static void copy_double(SilenceRemoveContext *s, AVFrame *out, AVFrame *in, int ch, int out_offset, int in_offset) { const double *srcp = (const double *)in->data[0]; - const double src = srcp[in->channels * in_offset + ch]; + const double src = srcp[in->ch_layout.nb_channels * in_offset + ch]; double *dstp = (double *)out->data[0]; - dstp[out->channels * out_offset + ch] = src; + dstp[out->ch_layout.nb_channels * out_offset + ch] = src; } static void copy_doublep(SilenceRemoveContext *s, AVFrame *out, AVFrame *in, @@ -156,10 +156,10 @@ static void copy_float(SilenceRemoveContext *s, AVFrame *out, AVFrame *in, int ch, int out_offset, int in_offset) { const float *srcp = (const float *)in->data[0]; - const float src = srcp[in->channels * in_offset + ch]; + const float src = srcp[in->ch_layout.nb_channels * in_offset + ch]; float *dstp = (float *)out->data[0]; - dstp[out->channels * out_offset + ch] = src; + dstp[out->ch_layout.nb_channels * out_offset + ch] = src; } static void copy_floatp(SilenceRemoveContext *s, AVFrame *out, AVFrame *in, @@ -176,8 +176,8 @@ static double compute_peak_double(SilenceRemoveContext *s, AVFrame *frame, int c { const double *samples = (const double *)frame->data[0]; const double *wsamples = (const double *)s->window->data[0]; - double sample = samples[frame->channels * offset + ch]; - double wsample = wsamples[frame->channels * s->window_offset + ch]; + double sample = samples[frame->ch_layout.nb_channels * offset + ch]; + double wsample = wsamples[frame->ch_layout.nb_channels * s->window_offset + ch]; double new_sum; new_sum = s->sum; @@ -192,8 +192,8 @@ static void update_peak_double(SilenceRemoveContext *s, AVFrame *frame, int ch, { const double *samples = (const double *)frame->data[0]; double *wsamples = (double *)s->window->data[0]; - double sample = samples[frame->channels * offset + ch]; - double *wsample = &wsamples[frame->channels * s->window_offset + ch]; + double sample = samples[frame->ch_layout.nb_channels * offset + ch]; + double *wsample = &wsamples[frame->ch_layout.nb_channels * s->window_offset + ch]; s->sum -= *wsample; s->sum = fmax(s->sum, 0.); @@ -205,8 +205,8 @@ static double compute_peak_float(SilenceRemoveContext *s, AVFrame *frame, int ch { const float *samples = (const float *)frame->data[0]; const float *wsamples = (const float *)s->window->data[0]; - float sample = samples[frame->channels * offset + ch]; - float wsample = wsamples[frame->channels * s->window_offset + ch]; + float sample = samples[frame->ch_layout.nb_channels * offset + ch]; + float wsample = wsamples[frame->ch_layout.nb_channels * s->window_offset + ch]; float new_sum; new_sum = s->sum; @@ -221,8 +221,8 @@ static void update_peak_float(SilenceRemoveContext *s, AVFrame *frame, int ch, i { const float *samples = (const float *)frame->data[0]; float *wsamples = (float *)s->window->data[0]; - float sample = samples[frame->channels * offset + ch]; - float *wsample = &wsamples[frame->channels * s->window_offset + ch]; + float sample = samples[frame->ch_layout.nb_channels * offset + ch]; + float *wsample = &wsamples[frame->ch_layout.nb_channels * s->window_offset + ch]; s->sum -= *wsample; s->sum = fmaxf(s->sum, 0.f); @@ -234,8 +234,8 @@ static double compute_rms_double(SilenceRemoveContext *s, AVFrame *frame, int ch { const double *samples = (const double *)frame->data[0]; const double *wsamples = (const double *)s->window->data[0]; - double sample = samples[frame->channels * offset + ch]; - double wsample = wsamples[frame->channels * s->window_offset + ch]; + double sample = samples[frame->ch_layout.nb_channels * offset + ch]; + double wsample = wsamples[frame->ch_layout.nb_channels * s->window_offset + ch]; double new_sum; new_sum = s->sum; @@ -251,8 +251,8 @@ static void update_rms_double(SilenceRemoveContext *s, AVFrame *frame, int ch, i { const double *samples = (const double *)frame->data[0]; double *wsamples = (double *)s->window->data[0]; - double sample = samples[frame->channels * offset + ch]; - double *wsample = &wsamples[frame->channels * s->window_offset + ch]; + double sample = samples[frame->ch_layout.nb_channels * offset + ch]; + double *wsample = &wsamples[frame->ch_layout.nb_channels * s->window_offset + ch]; s->sum -= *wsample; s->sum = fmax(s->sum, 0.); @@ -264,8 +264,8 @@ static double compute_rms_float(SilenceRemoveContext *s, AVFrame *frame, int ch, { const float *samples = (const float *)frame->data[0]; const float *wsamples = (const float *)s->window->data[0]; - float sample = samples[frame->channels * offset + ch]; - float wsample = wsamples[frame->channels * s->window_offset + ch]; + float sample = samples[frame->ch_layout.nb_channels * offset + ch]; + float wsample = wsamples[frame->ch_layout.nb_channels * s->window_offset + ch]; float new_sum; new_sum = s->sum; @@ -280,9 +280,9 @@ static double compute_rms_float(SilenceRemoveContext *s, AVFrame *frame, int ch, static void update_rms_float(SilenceRemoveContext *s, AVFrame *frame, int ch, int offset) { const float *samples = (const float *)frame->data[0]; - float sample = samples[frame->channels * offset + ch]; + float sample = samples[frame->ch_layout.nb_channels * offset + ch]; float *wsamples = (float *)s->window->data[0]; - float *wsample = &wsamples[frame->channels * s->window_offset + ch]; + float *wsample = &wsamples[frame->ch_layout.nb_channels * s->window_offset + ch]; s->sum -= *wsample; s->sum = fmaxf(s->sum, 0.f); @@ -423,7 +423,7 @@ static av_cold int init(AVFilterContext *ctx) static void clear_window(SilenceRemoveContext *s) { av_samples_set_silence(s->window->extended_data, 0, s->window_duration, - s->window->channels, s->window->format); + s->window->ch_layout.nb_channels, s->window->format); s->window_offset = 0; s->sum = 0; @@ -543,7 +543,7 @@ static int config_input(AVFilterLink *inlink) return AVERROR_BUG; } - s->fifo = av_audio_fifo_alloc(inlink->format, inlink->channels, 1024); + s->fifo = av_audio_fifo_alloc(inlink->format, inlink->ch_layout.nb_channels, 1024); if (!s->fifo) return AVERROR(ENOMEM); @@ -576,14 +576,14 @@ static void flush(SilenceRemoveContext *s, av_samples_copy(silence->extended_data, s->stop_silence_hold->extended_data, 0, s->stop_silence_offset, s->stop_silence_end - s->stop_silence_offset, - outlink->channels, outlink->format); + outlink->ch_layout.nb_channels, outlink->format); } if (s->stop_silence_offset > 0) { av_samples_copy(silence->extended_data, s->stop_silence_hold->extended_data, s->stop_silence_end - s->stop_silence_offset, 0, s->stop_silence_offset, - outlink->channels, outlink->format); + outlink->ch_layout.nb_channels, outlink->format); } s->stop_silence_offset = 0; @@ -617,18 +617,18 @@ silence_trim: for (i = 0; i < nbs; i++) { if (s->start_mode == T_ANY) { threshold = 0; - for (j = 0; j < outlink->channels; j++) { + for (j = 0; j < outlink->ch_layout.nb_channels; j++) { threshold |= s->compute(s, in, j, nb_samples_read) > s->start_threshold; } } else { threshold = 1; - for (j = 0; j < outlink->channels; j++) { + for (j = 0; j < outlink->ch_layout.nb_channels; j++) { threshold &= s->compute(s, in, j, nb_samples_read) > s->start_threshold; } } if (threshold) { - for (j = 0; j < outlink->channels; j++) { + for (j = 0; j < outlink->ch_layout.nb_channels; j++) { s->update(s, in, j, nb_samples_read); s->copy(s, s->start_holdoff, in, j, s->start_holdoff_end, nb_samples_read); } @@ -656,7 +656,7 @@ silence_trim: s->start_holdoff_end = 0; s->one_period++; - for (j = 0; j < outlink->channels; j++) { + for (j = 0; j < outlink->ch_layout.nb_channels; j++) { s->update(s, in, j, nb_samples_read); if (s->start_silence) s->copy(s, s->start_silence_hold, in, j, s->start_silence_offset, nb_samples_read); @@ -694,21 +694,21 @@ silence_trim_flush: av_samples_copy(out->extended_data, s->start_silence_hold->extended_data, 0, s->start_silence_offset, s->start_silence_end - s->start_silence_offset, - outlink->channels, outlink->format); + outlink->ch_layout.nb_channels, outlink->format); } if (s->start_silence_offset > 0) { av_samples_copy(out->extended_data, s->start_silence_hold->extended_data, s->start_silence_end - s->start_silence_offset, 0, s->start_silence_offset, - outlink->channels, outlink->format); + outlink->ch_layout.nb_channels, outlink->format); } } av_samples_copy(out->extended_data, s->start_holdoff->extended_data, s->start_silence_end, s->start_holdoff_offset, nbs, - outlink->channels, outlink->format); + outlink->ch_layout.nb_channels, outlink->format); s->start_holdoff_offset += nbs; @@ -741,12 +741,12 @@ silence_copy: for (i = 0; i < nbs; i++) { if (s->stop_mode == T_ANY) { threshold = 0; - for (j = 0; j < outlink->channels; j++) { + for (j = 0; j < outlink->ch_layout.nb_channels; j++) { threshold |= s->compute(s, in, j, nb_samples_read) > s->stop_threshold; } } else { threshold = 1; - for (j = 0; j < outlink->channels; j++) { + for (j = 0; j < outlink->ch_layout.nb_channels; j++) { threshold &= s->compute(s, in, j, nb_samples_read) > s->stop_threshold; } } @@ -757,7 +757,7 @@ silence_copy: s->one_period++; goto silence_copy_flush; } else if (threshold) { - for (j = 0; j < outlink->channels; j++) { + for (j = 0; j < outlink->ch_layout.nb_channels; j++) { s->update(s, in, j, nb_samples_read); s->copy(s, out, in, j, nb_samples_written, nb_samples_read); } @@ -769,7 +769,7 @@ silence_copy: nb_samples_written++; s->one_period++; } else if (!threshold) { - for (j = 0; j < outlink->channels; j++) { + for (j = 0; j < outlink->ch_layout.nb_channels; j++) { s->update(s, in, j, nb_samples_read); if (s->stop_silence) s->copy(s, s->stop_silence_hold, in, j, s->stop_silence_offset, nb_samples_read); @@ -827,7 +827,7 @@ silence_copy: av_samples_copy(out->extended_data, in->extended_data, nb_samples_written, nb_samples_read, nbs, - outlink->channels, outlink->format); + outlink->ch_layout.nb_channels, outlink->format); av_audio_fifo_write(s->fifo, (void **)out->extended_data, out->nb_samples); av_frame_free(&out); @@ -848,7 +848,7 @@ silence_copy_flush: av_samples_copy(out->extended_data, s->stop_holdoff->extended_data, 0, s->stop_holdoff_offset, nbs, - outlink->channels, outlink->format); + outlink->ch_layout.nb_channels, outlink->format); s->stop_holdoff_offset += nbs; @@ -909,7 +909,7 @@ static int request_frame(AVFilterLink *outlink) av_samples_copy(frame->extended_data, s->stop_holdoff->extended_data, 0, s->stop_holdoff_offset, nbs, - outlink->channels, outlink->format); + outlink->ch_layout.nb_channels, outlink->format); frame->pts = s->next_pts; s->next_pts += av_rescale_q(frame->nb_samples, diff --git a/libavfilter/af_sofalizer.c b/libavfilter/af_sofalizer.c index 20b717bdf..f9c5fa2f2 100644 --- a/libavfilter/af_sofalizer.c +++ b/libavfilter/af_sofalizer.c @@ -187,25 +187,18 @@ static int preload_sofa(AVFilterContext *ctx, char *filename, int *samplingrate) static int parse_channel_name(AVFilterContext *ctx, char **arg, int *rchannel) { - int len, i, channel_id = 0; - int64_t layout, layout0; + int len; + enum AVChannel channel_id = 0; char buf[8] = {0}; /* try to parse a channel name, e.g. "FL" */ if (av_sscanf(*arg, "%7[A-Z]%n", buf, &len)) { - layout0 = layout = av_get_channel_layout(buf); - /* channel_id <- first set bit in layout */ - for (i = 32; i > 0; i >>= 1) { - if (layout >= 1LL << i) { - channel_id += i; - layout >>= i; - } - } - /* reject layouts that are not a single channel */ - if (channel_id >= 64 || layout0 != 1LL << channel_id) { + channel_id = av_channel_from_string(buf); + if (channel_id < 0 || channel_id >= 64) { av_log(ctx, AV_LOG_WARNING, "Failed to parse \'%s\' as channel name.\n", buf); return AVERROR(EINVAL); } + *rchannel = channel_id; *arg += len; return 0; @@ -221,7 +214,7 @@ static int parse_channel_name(AVFilterContext *ctx, char **arg, int *rchannel) return AVERROR(EINVAL); } -static void parse_speaker_pos(AVFilterContext *ctx, int64_t in_channel_layout) +static void parse_speaker_pos(AVFilterContext *ctx) { SOFAlizerContext *s = ctx->priv; char *arg, *tokenizer, *p, *args = av_strdup(s->speakers_pos); @@ -256,10 +249,10 @@ static int get_speaker_pos(AVFilterContext *ctx, float *speaker_azim, float *speaker_elev) { struct SOFAlizerContext *s = ctx->priv; - uint64_t channels_layout = ctx->inputs[0]->channel_layout; + AVChannelLayout *channel_layout = &ctx->inputs[0]->ch_layout; float azim[64] = { 0 }; float elev[64] = { 0 }; - int m, ch, n_conv = ctx->inputs[0]->channels; /* get no. input channels */ + int ch, n_conv = ctx->inputs[0]->ch_layout.nb_channels; /* get no. input channels */ if (n_conv < 0 || n_conv > 64) return AVERROR(EINVAL); @@ -267,57 +260,53 @@ static int get_speaker_pos(AVFilterContext *ctx, s->lfe_channel = -1; if (s->speakers_pos) - parse_speaker_pos(ctx, channels_layout); + parse_speaker_pos(ctx); /* set speaker positions according to input channel configuration: */ - for (m = 0, ch = 0; ch < n_conv && m < 64; m++) { - uint64_t mask = channels_layout & (1ULL << m); + for (ch = 0; ch < n_conv; ch++) { + int chan = av_channel_layout_channel_from_index(channel_layout, ch); - switch (mask) { - case AV_CH_FRONT_LEFT: azim[ch] = 30; break; - case AV_CH_FRONT_RIGHT: azim[ch] = 330; break; - case AV_CH_FRONT_CENTER: azim[ch] = 0; break; - case AV_CH_LOW_FREQUENCY: - case AV_CH_LOW_FREQUENCY_2: s->lfe_channel = ch; break; - case AV_CH_BACK_LEFT: azim[ch] = 150; break; - case AV_CH_BACK_RIGHT: azim[ch] = 210; break; - case AV_CH_BACK_CENTER: azim[ch] = 180; break; - case AV_CH_SIDE_LEFT: azim[ch] = 90; break; - case AV_CH_SIDE_RIGHT: azim[ch] = 270; break; - case AV_CH_FRONT_LEFT_OF_CENTER: azim[ch] = 15; break; - case AV_CH_FRONT_RIGHT_OF_CENTER: azim[ch] = 345; break; - case AV_CH_TOP_CENTER: azim[ch] = 0; + switch (chan) { + case AV_CHAN_FRONT_LEFT: azim[ch] = 30; break; + case AV_CHAN_FRONT_RIGHT: azim[ch] = 330; break; + case AV_CHAN_FRONT_CENTER: azim[ch] = 0; break; + case AV_CHAN_LOW_FREQUENCY: + case AV_CHAN_LOW_FREQUENCY_2: s->lfe_channel = ch; break; + case AV_CHAN_BACK_LEFT: azim[ch] = 150; break; + case AV_CHAN_BACK_RIGHT: azim[ch] = 210; break; + case AV_CHAN_BACK_CENTER: azim[ch] = 180; break; + case AV_CHAN_SIDE_LEFT: azim[ch] = 90; break; + case AV_CHAN_SIDE_RIGHT: azim[ch] = 270; break; + case AV_CHAN_FRONT_LEFT_OF_CENTER: azim[ch] = 15; break; + case AV_CHAN_FRONT_RIGHT_OF_CENTER: azim[ch] = 345; break; + case AV_CHAN_TOP_CENTER: azim[ch] = 0; elev[ch] = 90; break; - case AV_CH_TOP_FRONT_LEFT: azim[ch] = 30; + case AV_CHAN_TOP_FRONT_LEFT: azim[ch] = 30; elev[ch] = 45; break; - case AV_CH_TOP_FRONT_CENTER: azim[ch] = 0; + case AV_CHAN_TOP_FRONT_CENTER: azim[ch] = 0; elev[ch] = 45; break; - case AV_CH_TOP_FRONT_RIGHT: azim[ch] = 330; + case AV_CHAN_TOP_FRONT_RIGHT: azim[ch] = 330; elev[ch] = 45; break; - case AV_CH_TOP_BACK_LEFT: azim[ch] = 150; + case AV_CHAN_TOP_BACK_LEFT: azim[ch] = 150; elev[ch] = 45; break; - case AV_CH_TOP_BACK_RIGHT: azim[ch] = 210; + case AV_CHAN_TOP_BACK_RIGHT: azim[ch] = 210; elev[ch] = 45; break; - case AV_CH_TOP_BACK_CENTER: azim[ch] = 180; + case AV_CHAN_TOP_BACK_CENTER: azim[ch] = 180; elev[ch] = 45; break; - case AV_CH_WIDE_LEFT: azim[ch] = 90; break; - case AV_CH_WIDE_RIGHT: azim[ch] = 270; break; - case AV_CH_SURROUND_DIRECT_LEFT: azim[ch] = 90; break; - case AV_CH_SURROUND_DIRECT_RIGHT: azim[ch] = 270; break; - case AV_CH_STEREO_LEFT: azim[ch] = 90; break; - case AV_CH_STEREO_RIGHT: azim[ch] = 270; break; - case 0: break; + case AV_CHAN_WIDE_LEFT: azim[ch] = 90; break; + case AV_CHAN_WIDE_RIGHT: azim[ch] = 270; break; + case AV_CHAN_SURROUND_DIRECT_LEFT: azim[ch] = 90; break; + case AV_CHAN_SURROUND_DIRECT_RIGHT: azim[ch] = 270; break; + case AV_CHAN_STEREO_LEFT: azim[ch] = 90; break; + case AV_CHAN_STEREO_RIGHT: azim[ch] = 270; break; default: return AVERROR(EINVAL); } - if (s->vspkrpos[m].set) { - azim[ch] = s->vspkrpos[m].azim; - elev[ch] = s->vspkrpos[m].elev; + if (s->vspkrpos[ch].set) { + azim[ch] = s->vspkrpos[ch].azim; + elev[ch] = s->vspkrpos[ch].elev; } - - if (mask) - ch++; } memcpy(speaker_azim, azim, n_conv * sizeof(float)); @@ -668,7 +657,7 @@ static int query_formats(AVFilterContext *ctx) return ret; layouts = NULL; - ret = ff_add_channel_layout(&layouts, AV_CH_LAYOUT_STEREO); + ret = ff_add_channel_layout(&layouts, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO); if (ret) return ret; @@ -733,7 +722,7 @@ static int load_data(AVFilterContext *ctx, int azim, int elev, float radius, int int n_fft; float delay_l; /* broadband delay for each IR */ float delay_r; - int nb_input_channels = ctx->inputs[0]->channels; /* no. input channels */ + int nb_input_channels = ctx->inputs[0]->ch_layout.nb_channels; /* no. input channels */ float gain_lin = expf((s->gain - 3 * nb_input_channels) / 20 * M_LN10); /* gain - 3dB/channel */ AVComplexFloat *data_hrtf_l = NULL; AVComplexFloat *data_hrtf_r = NULL; @@ -1016,16 +1005,16 @@ static int config_input(AVFilterLink *inlink) s->nb_samples = s->framesize; /* gain -3 dB per channel */ - s->gain_lfe = expf((s->gain - 3 * inlink->channels + s->lfe_gain) / 20 * M_LN10); + s->gain_lfe = expf((s->gain - 3 * inlink->ch_layout.nb_channels + s->lfe_gain) / 20 * M_LN10); - s->n_conv = inlink->channels; + s->n_conv = inlink->ch_layout.nb_channels; /* load IRs to data_ir[0] and data_ir[1] for required directions */ if ((ret = load_data(ctx, s->rotation, s->elevation, s->radius, inlink->sample_rate)) < 0) return ret; av_log(ctx, AV_LOG_DEBUG, "Samplerate: %d Channels to convolute: %d, Length of ringbuffer: %d x %d\n", - inlink->sample_rate, s->n_conv, inlink->channels, s->buffer_length); + inlink->sample_rate, s->n_conv, inlink->ch_layout.nb_channels, s->buffer_length); return 0; } diff --git a/libavfilter/af_speechnorm.c b/libavfilter/af_speechnorm.c index 212a926f3..c9bd8d5ca 100644 --- a/libavfilter/af_speechnorm.c +++ b/libavfilter/af_speechnorm.c @@ -68,7 +68,8 @@ typedef struct SpeechNormalizerContext { double threshold_value; double raise_amount; double fall_amount; - uint64_t channels; + char *ch_layout_str; + AVChannelLayout ch_layout; int invert; int link; @@ -103,8 +104,8 @@ static const AVOption speechnorm_options[] = { { "r", "set the expansion raising amount", OFFSET(raise_amount), AV_OPT_TYPE_DOUBLE, {.dbl=0.001}, 0.0, 1.0, FLAGS }, { "fall", "set the compression raising amount", OFFSET(fall_amount), AV_OPT_TYPE_DOUBLE, {.dbl=0.001}, 0.0, 1.0, FLAGS }, { "f", "set the compression raising amount", OFFSET(fall_amount), AV_OPT_TYPE_DOUBLE, {.dbl=0.001}, 0.0, 1.0, FLAGS }, - { "channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS }, - { "h", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS }, + { "channels", "set channels to filter", OFFSET(ch_layout_str), AV_OPT_TYPE_STRING, {.str="all"}, 0, 0, FLAGS }, + { "h", "set channels to filter", OFFSET(ch_layout_str), AV_OPT_TYPE_STRING, {.str="all"}, 0, 0, FLAGS }, { "invert", "set inverted filtering", OFFSET(invert), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, { "i", "set inverted filtering", OFFSET(invert), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, { "link", "set linked channels filtering", OFFSET(link), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, @@ -128,7 +129,7 @@ static int get_pi_samples(PeriodItem *pi, int start, int end, int remain) start = 0; if (pi[start].type == 0) break; - av_assert0(pi[start].size > 0); + av_assert1(pi[start].size > 0); sum += pi[start].size; } @@ -142,7 +143,7 @@ static int available_samples(AVFilterContext *ctx) int min_pi_nb_samples; min_pi_nb_samples = get_pi_samples(s->cc[0].pi, s->cc[0].pi_start, s->cc[0].pi_end, s->cc[0].pi_size); - for (int ch = 1; ch < inlink->channels && min_pi_nb_samples > 0; ch++) { + for (int ch = 1; ch < inlink->ch_layout.nb_channels && min_pi_nb_samples > 0; ch++) { ChannelContext *cc = &s->cc[ch]; min_pi_nb_samples = FFMIN(min_pi_nb_samples, get_pi_samples(cc->pi, cc->pi_start, cc->pi_end, cc->pi_size)); @@ -156,7 +157,7 @@ static void consume_pi(ChannelContext *cc, int nb_samples) if (cc->pi_size >= nb_samples) { cc->pi_size -= nb_samples; } else { - av_assert0(0); + av_assert1(0); } } @@ -178,16 +179,16 @@ static double next_gain(AVFilterContext *ctx, double pi_max_peak, int bypass, do static void next_pi(AVFilterContext *ctx, ChannelContext *cc, int bypass) { - av_assert0(cc->pi_size >= 0); + av_assert1(cc->pi_size >= 0); if (cc->pi_size == 0) { SpeechNormalizerContext *s = ctx->priv; int start = cc->pi_start; - av_assert0(cc->pi[start].size > 0); + av_assert1(cc->pi[start].size > 0); av_assert0(cc->pi[start].type > 0 || s->eof); cc->pi_size = cc->pi[start].size; cc->pi_max_peak = cc->pi[start].max_peak; - av_assert0(cc->pi_start != cc->pi_end || s->eof); + av_assert1(cc->pi_start != cc->pi_end || s->eof); start++; if (start >= MAX_ITEMS) start = 0; @@ -219,58 +220,71 @@ static double min_gain(AVFilterContext *ctx, ChannelContext *cc, int max_size) return min_gain; } -#define ANALYZE_CHANNEL(name, ptype, zero, min_peak) \ -static void analyze_channel_## name (AVFilterContext *ctx, ChannelContext *cc, \ - const uint8_t *srcp, int nb_samples) \ -{ \ - SpeechNormalizerContext *s = ctx->priv; \ - const ptype *src = (const ptype *)srcp; \ - int n = 0; \ - \ - if (cc->state < 0) \ - cc->state = src[0] >= zero; \ - \ - while (n < nb_samples) { \ - if ((cc->state != (src[n] >= zero)) || \ - (cc->pi[cc->pi_end].size > s->max_period)) { \ - ptype max_peak = cc->pi[cc->pi_end].max_peak; \ - int state = cc->state; \ - cc->state = src[n] >= zero; \ - av_assert0(cc->pi[cc->pi_end].size > 0); \ - if (max_peak >= min_peak || \ - cc->pi[cc->pi_end].size > s->max_period) { \ - cc->pi[cc->pi_end].type = 1; \ - cc->pi_end++; \ - if (cc->pi_end >= MAX_ITEMS) \ - cc->pi_end = 0; \ - if (cc->state != state) \ - cc->pi[cc->pi_end].max_peak = DBL_MIN; \ - else \ - cc->pi[cc->pi_end].max_peak = max_peak; \ - cc->pi[cc->pi_end].type = 0; \ - cc->pi[cc->pi_end].size = 0; \ - av_assert0(cc->pi_end != cc->pi_start); \ - } \ - } \ - \ - if (cc->state) { \ - while (src[n] >= zero) { \ - cc->pi[cc->pi_end].max_peak = FFMAX(cc->pi[cc->pi_end].max_peak, src[n]); \ - cc->pi[cc->pi_end].size++; \ - n++; \ - if (n >= nb_samples) \ - break; \ - } \ - } else { \ - while (src[n] < zero) { \ - cc->pi[cc->pi_end].max_peak = FFMAX(cc->pi[cc->pi_end].max_peak, -src[n]); \ - cc->pi[cc->pi_end].size++; \ - n++; \ - if (n >= nb_samples) \ - break; \ - } \ - } \ - } \ +#define ANALYZE_CHANNEL(name, ptype, zero, min_peak) \ +static void analyze_channel_## name (AVFilterContext *ctx, ChannelContext *cc, \ + const uint8_t *srcp, int nb_samples) \ +{ \ + SpeechNormalizerContext *s = ctx->priv; \ + const ptype *src = (const ptype *)srcp; \ + const int max_period = s->max_period; \ + PeriodItem *pi = (PeriodItem *)&cc->pi; \ + int pi_end = cc->pi_end; \ + int n = 0; \ + \ + if (cc->state < 0) \ + cc->state = src[0] >= zero; \ + \ + while (n < nb_samples) { \ + ptype new_max_peak; \ + int new_size; \ + \ + if ((cc->state != (src[n] >= zero)) || \ + (pi[pi_end].size > max_period)) { \ + ptype max_peak = pi[pi_end].max_peak; \ + int state = cc->state; \ + \ + cc->state = src[n] >= zero; \ + av_assert1(pi[pi_end].size > 0); \ + if (max_peak >= min_peak || \ + pi[pi_end].size > max_period) { \ + pi[pi_end].type = 1; \ + pi_end++; \ + if (pi_end >= MAX_ITEMS) \ + pi_end = 0; \ + if (cc->state != state) \ + pi[pi_end].max_peak = DBL_MIN; \ + else \ + pi[pi_end].max_peak = max_peak; \ + pi[pi_end].type = 0; \ + pi[pi_end].size = 0; \ + av_assert1(pi_end != cc->pi_start); \ + } \ + } \ + \ + new_max_peak = pi[pi_end].max_peak; \ + new_size = pi[pi_end].size; \ + if (cc->state) { \ + while (src[n] >= zero) { \ + new_max_peak = FFMAX(new_max_peak, src[n]); \ + new_size++; \ + n++; \ + if (n >= nb_samples) \ + break; \ + } \ + } else { \ + while (src[n] < zero) { \ + new_max_peak = FFMAX(new_max_peak, -src[n]); \ + new_size++; \ + n++; \ + if (n >= nb_samples) \ + break; \ + } \ + } \ + \ + pi[pi_end].max_peak = new_max_peak; \ + pi[pi_end].size = new_size; \ + } \ + cc->pi_end = pi_end; \ } ANALYZE_CHANNEL(dbl, double, 0.0, MIN_PEAK) @@ -283,11 +297,12 @@ static void filter_channels_## name (AVFilterContext *ctx, SpeechNormalizerContext *s = ctx->priv; \ AVFilterLink *inlink = ctx->inputs[0]; \ \ - for (int ch = 0; ch < inlink->channels; ch++) { \ + for (int ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { \ ChannelContext *cc = &s->cc[ch]; \ const ptype *src = (const ptype *)in->extended_data[ch]; \ ptype *dst = (ptype *)out->extended_data[ch]; \ - const int bypass = !(av_channel_layout_extract_channel(inlink->channel_layout, ch) & s->channels); \ + enum AVChannel channel = av_channel_layout_channel_from_index(&inlink->ch_layout, ch); \ + const int bypass = av_channel_layout_index_from_channel(&s->ch_layout, channel) < 0; \ int n = 0; \ \ while (n < nb_samples) { \ @@ -296,7 +311,7 @@ static void filter_channels_## name (AVFilterContext *ctx, \ next_pi(ctx, cc, bypass); \ size = FFMIN(nb_samples - n, cc->pi_size); \ - av_assert0(size > 0); \ + av_assert1(size > 0); \ gain = cc->gain_state; \ consume_pi(cc, size); \ for (int i = n; !ctx->is_disabled && i < n + size; i++) \ @@ -333,18 +348,19 @@ static void filter_link_channels_## name (AVFilterContext *ctx, int max_size = 1; \ ptype gain = s->max_expansion; \ \ - for (int ch = 0; ch < inlink->channels; ch++) { \ + for (int ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { \ ChannelContext *cc = &s->cc[ch]; \ \ - cc->bypass = !(av_channel_layout_extract_channel(inlink->channel_layout, ch) & s->channels); \ + enum AVChannel channel = av_channel_layout_channel_from_index(&inlink->ch_layout, ch); \ + cc->bypass = av_channel_layout_index_from_channel(&s->ch_layout, channel) < 0; \ \ next_pi(ctx, cc, cc->bypass); \ min_size = FFMIN(min_size, cc->pi_size); \ max_size = FFMAX(max_size, cc->pi_size); \ } \ \ - av_assert0(min_size > 0); \ - for (int ch = 0; ch < inlink->channels; ch++) { \ + av_assert1(min_size > 0); \ + for (int ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { \ ChannelContext *cc = &s->cc[ch]; \ \ if (cc->bypass) \ @@ -352,7 +368,7 @@ static void filter_link_channels_## name (AVFilterContext *ctx, gain = FFMIN(gain, min_gain(ctx, cc, max_size)); \ } \ \ - for (int ch = 0; ch < inlink->channels; ch++) { \ + for (int ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { \ ChannelContext *cc = &s->cc[ch]; \ const ptype *src = (const ptype *)in->extended_data[ch]; \ ptype *dst = (ptype *)out->extended_data[ch]; \ @@ -428,7 +444,7 @@ static int filter_frame(AVFilterContext *ctx) ff_bufqueue_add(ctx, &s->queue, in); - for (int ch = 0; ch < inlink->channels; ch++) { + for (int ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { ChannelContext *cc = &s->cc[ch]; s->analyze_channel(ctx, cc, in->extended_data[ch], in->nb_samples); @@ -446,6 +462,13 @@ static int activate(AVFilterContext *ctx) int ret, status; int64_t pts; + ret = av_channel_layout_copy(&s->ch_layout, &inlink->ch_layout); + if (ret < 0) + return ret; + if (strcmp(s->ch_layout_str, "all")) + av_channel_layout_from_string(&s->ch_layout, + s->ch_layout_str); + FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); ret = filter_frame(ctx); @@ -486,11 +509,11 @@ static int config_input(AVFilterLink *inlink) s->max_period = inlink->sample_rate / 10; s->prev_gain = 1.; - s->cc = av_calloc(inlink->channels, sizeof(*s->cc)); + s->cc = av_calloc(inlink->ch_layout.nb_channels, sizeof(*s->cc)); if (!s->cc) return AVERROR(ENOMEM); - for (int ch = 0; ch < inlink->channels; ch++) { + for (int ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { ChannelContext *cc = &s->cc[ch]; cc->state = -1; @@ -509,7 +532,7 @@ static int config_input(AVFilterLink *inlink) s->filter_channels[1] = filter_link_channels_dbl; break; default: - av_assert0(0); + av_assert1(0); } return 0; @@ -536,6 +559,7 @@ static av_cold void uninit(AVFilterContext *ctx) SpeechNormalizerContext *s = ctx->priv; ff_bufqueue_discard_all(&s->queue); + av_channel_layout_uninit(&s->ch_layout); av_freep(&s->cc); } diff --git a/libavfilter/af_stereotools.c b/libavfilter/af_stereotools.c index 27ec4a2e4..eedc7c68b 100644 --- a/libavfilter/af_stereotools.c +++ b/libavfilter/af_stereotools.c @@ -107,7 +107,7 @@ static int query_formats(AVFilterContext *ctx) if ((ret = ff_add_format (&formats, AV_SAMPLE_FMT_DBL )) < 0 || (ret = ff_set_common_formats (ctx , formats )) < 0 || - (ret = ff_add_channel_layout (&layout , AV_CH_LAYOUT_STEREO)) < 0 || + (ret = ff_add_channel_layout (&layout , &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO)) < 0 || (ret = ff_set_common_channel_layouts (ctx , layout )) < 0) return ret; diff --git a/libavfilter/af_stereowiden.c b/libavfilter/af_stereowiden.c index 7cce1a8f2..a91ea0395 100644 --- a/libavfilter/af_stereowiden.c +++ b/libavfilter/af_stereowiden.c @@ -60,7 +60,7 @@ static int query_formats(AVFilterContext *ctx) if ((ret = ff_add_format (&formats, AV_SAMPLE_FMT_FLT )) < 0 || (ret = ff_set_common_formats (ctx , formats )) < 0 || - (ret = ff_add_channel_layout (&layout , AV_CH_LAYOUT_STEREO)) < 0 || + (ret = ff_add_channel_layout (&layout , &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO)) < 0 || (ret = ff_set_common_channel_layouts (ctx , layout )) < 0) return ret; diff --git a/libavfilter/af_superequalizer.c b/libavfilter/af_superequalizer.c index aa73e9203..99c08f34d 100644 --- a/libavfilter/af_superequalizer.c +++ b/libavfilter/af_superequalizer.c @@ -20,8 +20,7 @@ */ #include "libavutil/opt.h" - -#include "libavcodec/avfft.h" +#include "libavutil/tx.h" #include "audio.h" #include "avfilter.h" @@ -46,11 +45,12 @@ typedef struct SuperEqualizerContext { float aa; float iza; float *ires, *irest; - float *fsamples; + float *fsamples, *fsamples_out; int winlen, tabsize; AVFrame *in, *out; - RDFTContext *rdft, *irdft; + AVTXContext *rdft, *irdft; + av_tx_fn tx_fn, itx_fn; } SuperEqualizerContext; static const float bands[] = { @@ -134,20 +134,27 @@ static void process_param(float *bc, EqParameter *param, float fs) static int equ_init(SuperEqualizerContext *s, int wb) { - int i,j; + float scale = 1.f, iscale = 1.f; + int i, j, ret; - s->rdft = av_rdft_init(wb, DFT_R2C); - s->irdft = av_rdft_init(wb, IDFT_C2R); - if (!s->rdft || !s->irdft) - return AVERROR(ENOMEM); + ret = av_tx_init(&s->rdft, &s->tx_fn, AV_TX_FLOAT_RDFT, 0, 1 << wb, &scale, 0); + if (ret < 0) + return ret; + + ret = av_tx_init(&s->irdft, &s->itx_fn, AV_TX_FLOAT_RDFT, 1, 1 << wb, &iscale, 0); + if (ret < 0) + return ret; s->aa = 96; s->winlen = (1 << (wb-1))-1; s->tabsize = 1 << wb; - s->ires = av_calloc(s->tabsize, sizeof(float)); + s->ires = av_calloc(s->tabsize + 2, sizeof(float)); s->irest = av_calloc(s->tabsize, sizeof(float)); s->fsamples = av_calloc(s->tabsize, sizeof(float)); + s->fsamples_out = av_calloc(s->tabsize + 2, sizeof(float)); + if (!s->ires || !s->irest || !s->fsamples || !s->fsamples_out) + return AVERROR(ENOMEM); for (i = 0; i <= M; i++) { s->fact[i] = 1; @@ -164,7 +171,6 @@ static void make_fir(SuperEqualizerContext *s, float *lbc, float *rbc, EqParamet { const int winlen = s->winlen; const int tabsize = s->tabsize; - float *nires; int i; if (fs <= 0) @@ -176,10 +182,7 @@ static void make_fir(SuperEqualizerContext *s, float *lbc, float *rbc, EqParamet for (; i < tabsize; i++) s->irest[i] = 0; - av_rdft_calc(s->rdft, s->irest); - nires = s->ires; - for (i = 0; i < tabsize; i++) - nires[i] = s->irest[i]; + s->tx_fn(s->rdft, s->ires, s->irest, sizeof(float)); } static int filter_frame(AVFilterLink *inlink, AVFrame *in) @@ -188,10 +191,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) SuperEqualizerContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; const float *ires = s->ires; + float *fsamples_out = s->fsamples_out; float *fsamples = s->fsamples; int ch, i; - AVFrame *out = ff_get_audio_buffer(outlink, s->winlen); + AVFrame *out = ff_get_audio_buffer(outlink, in->nb_samples); float *src, *dst, *ptr; if (!out) { @@ -199,7 +203,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) return AVERROR(ENOMEM); } - for (ch = 0; ch < in->channels; ch++) { + for (ch = 0; ch < in->ch_layout.nb_channels; ch++) { ptr = (float *)out->extended_data[ch]; dst = (float *)s->out->extended_data[ch]; src = (float *)in->extended_data[ch]; @@ -209,27 +213,25 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) for (; i < s->tabsize; i++) fsamples[i] = 0; - av_rdft_calc(s->rdft, fsamples); + s->tx_fn(s->rdft, fsamples_out, fsamples, sizeof(float)); - fsamples[0] = ires[0] * fsamples[0]; - fsamples[1] = ires[1] * fsamples[1]; - for (i = 1; i < s->tabsize / 2; i++) { + for (i = 0; i <= s->tabsize / 2; i++) { float re, im; - re = ires[i*2 ] * fsamples[i*2] - ires[i*2+1] * fsamples[i*2+1]; - im = ires[i*2+1] * fsamples[i*2] + ires[i*2 ] * fsamples[i*2+1]; + re = ires[i*2 ] * fsamples_out[i*2] - ires[i*2+1] * fsamples_out[i*2+1]; + im = ires[i*2+1] * fsamples_out[i*2] + ires[i*2 ] * fsamples_out[i*2+1]; - fsamples[i*2 ] = re; - fsamples[i*2+1] = im; + fsamples_out[i*2 ] = re; + fsamples_out[i*2+1] = im; } - av_rdft_calc(s->irdft, fsamples); + s->itx_fn(s->irdft, fsamples, fsamples_out, sizeof(float)); for (i = 0; i < s->winlen; i++) - dst[i] += fsamples[i] / s->tabsize * 2; + dst[i] += fsamples[i] / s->tabsize; for (i = s->winlen; i < s->tabsize; i++) - dst[i] = fsamples[i] / s->tabsize * 2; - for (i = 0; i < s->winlen; i++) + dst[i] = fsamples[i] / s->tabsize; + for (i = 0; i < out->nb_samples; i++) ptr[i] = dst[i]; for (i = 0; i < s->winlen; i++) dst[i] = dst[i+s->winlen]; @@ -300,8 +302,9 @@ static av_cold void uninit(AVFilterContext *ctx) av_freep(&s->irest); av_freep(&s->ires); av_freep(&s->fsamples); - av_rdft_end(s->rdft); - av_rdft_end(s->irdft); + av_freep(&s->fsamples_out); + av_tx_uninit(&s->rdft); + av_tx_uninit(&s->irdft); } static const AVFilterPad superequalizer_inputs[] = { diff --git a/libavfilter/af_surround.c b/libavfilter/af_surround.c index ccd85148e..858fed609 100644 --- a/libavfilter/af_surround.c +++ b/libavfilter/af_surround.c @@ -19,10 +19,9 @@ */ #include "libavutil/avassert.h" -#include "libavutil/audio_fifo.h" #include "libavutil/channel_layout.h" #include "libavutil/opt.h" -#include "libavcodec/avfft.h" +#include "libavutil/tx.h" #include "avfilter.h" #include "audio.h" #include "filters.h" @@ -92,24 +91,24 @@ typedef struct AudioSurroundContext { float lowcut; float highcut; - uint64_t out_channel_layout; - uint64_t in_channel_layout; + AVChannelLayout out_channel_layout; + AVChannelLayout in_channel_layout; int nb_in_channels; int nb_out_channels; + AVFrame *input_in; AVFrame *input; AVFrame *output; + AVFrame *output_out; AVFrame *overlap_buffer; + AVFrame *window; int buf_size; int hop_size; - AVAudioFifo *fifo; - RDFTContext **rdft, **irdft; + AVTXContext **rdft, **irdft; + av_tx_fn tx_fn, itx_fn; float *window_func_lut; - int64_t pts; - int eof; - void (*filter)(AVFilterContext *ctx); void (*upmix_stereo)(AVFilterContext *ctx, float l_phase, @@ -171,7 +170,7 @@ static int query_formats(AVFilterContext *ctx) return ret; layouts = NULL; - ret = ff_add_channel_layout(&layouts, s->out_channel_layout); + ret = ff_add_channel_layout(&layouts, &s->out_channel_layout); if (ret) return ret; @@ -180,7 +179,7 @@ static int query_formats(AVFilterContext *ctx) return ret; layouts = NULL; - ret = ff_add_channel_layout(&layouts, s->in_channel_layout); + ret = ff_add_channel_layout(&layouts, &s->in_channel_layout); if (ret) return ret; @@ -197,13 +196,15 @@ static int config_input(AVFilterLink *inlink) AudioSurroundContext *s = ctx->priv; int ch; - s->rdft = av_calloc(inlink->channels, sizeof(*s->rdft)); + s->rdft = av_calloc(inlink->ch_layout.nb_channels, sizeof(*s->rdft)); if (!s->rdft) return AVERROR(ENOMEM); - s->nb_in_channels = inlink->channels; + s->nb_in_channels = inlink->ch_layout.nb_channels; - for (ch = 0; ch < inlink->channels; ch++) { - s->rdft[ch] = av_rdft_init(ff_log2(s->buf_size), DFT_R2C); + for (ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { + float scale = 1.f; + + av_tx_init(&s->rdft[ch], &s->tx_fn, AV_TX_FLOAT_RDFT, 0, s->buf_size, &scale, 0); if (!s->rdft[ch]) return AVERROR(ENOMEM); } @@ -212,40 +213,44 @@ static int config_input(AVFilterLink *inlink) return AVERROR(ENOMEM); for (ch = 0; ch < s->nb_in_channels; ch++) s->input_levels[ch] = s->level_in; - ch = av_get_channel_layout_channel_index(inlink->channel_layout, AV_CH_FRONT_CENTER); + ch = av_channel_layout_index_from_channel(&inlink->ch_layout, AV_CHAN_FRONT_CENTER); if (ch >= 0) s->input_levels[ch] *= s->fc_in; - ch = av_get_channel_layout_channel_index(inlink->channel_layout, AV_CH_FRONT_LEFT); + ch = av_channel_layout_index_from_channel(&inlink->ch_layout, AV_CHAN_FRONT_LEFT); if (ch >= 0) s->input_levels[ch] *= s->fl_in; - ch = av_get_channel_layout_channel_index(inlink->channel_layout, AV_CH_FRONT_RIGHT); + ch = av_channel_layout_index_from_channel(&inlink->ch_layout, AV_CHAN_FRONT_RIGHT); if (ch >= 0) s->input_levels[ch] *= s->fr_in; - ch = av_get_channel_layout_channel_index(inlink->channel_layout, AV_CH_SIDE_LEFT); + ch = av_channel_layout_index_from_channel(&inlink->ch_layout, AV_CHAN_SIDE_LEFT); if (ch >= 0) s->input_levels[ch] *= s->sl_in; - ch = av_get_channel_layout_channel_index(inlink->channel_layout, AV_CH_SIDE_RIGHT); + ch = av_channel_layout_index_from_channel(&inlink->ch_layout, AV_CHAN_SIDE_RIGHT); if (ch >= 0) s->input_levels[ch] *= s->sr_in; - ch = av_get_channel_layout_channel_index(inlink->channel_layout, AV_CH_BACK_LEFT); + ch = av_channel_layout_index_from_channel(&inlink->ch_layout, AV_CHAN_BACK_LEFT); if (ch >= 0) s->input_levels[ch] *= s->bl_in; - ch = av_get_channel_layout_channel_index(inlink->channel_layout, AV_CH_BACK_RIGHT); + ch = av_channel_layout_index_from_channel(&inlink->ch_layout, AV_CHAN_BACK_RIGHT); if (ch >= 0) s->input_levels[ch] *= s->br_in; - ch = av_get_channel_layout_channel_index(inlink->channel_layout, AV_CH_BACK_CENTER); + ch = av_channel_layout_index_from_channel(&inlink->ch_layout, AV_CHAN_BACK_CENTER); if (ch >= 0) s->input_levels[ch] *= s->bc_in; - ch = av_get_channel_layout_channel_index(inlink->channel_layout, AV_CH_LOW_FREQUENCY); + ch = av_channel_layout_index_from_channel(&inlink->ch_layout, AV_CHAN_LOW_FREQUENCY); if (ch >= 0) s->input_levels[ch] *= s->lfe_in; - s->input = ff_get_audio_buffer(inlink, s->buf_size * 2); - if (!s->input) + s->window = ff_get_audio_buffer(inlink, s->buf_size * 2); + if (!s->window) return AVERROR(ENOMEM); - s->fifo = av_audio_fifo_alloc(inlink->format, inlink->channels, s->buf_size); - if (!s->fifo) + s->input_in = ff_get_audio_buffer(inlink, s->buf_size * 2); + if (!s->input_in) + return AVERROR(ENOMEM); + + s->input = ff_get_audio_buffer(inlink, s->buf_size + 2); + if (!s->input) return AVERROR(ENOMEM); s->lowcut = 1.f * s->lowcutf / (inlink->sample_rate * 0.5) * (s->buf_size / 2); @@ -260,13 +265,15 @@ static int config_output(AVFilterLink *outlink) AudioSurroundContext *s = ctx->priv; int ch; - s->irdft = av_calloc(outlink->channels, sizeof(*s->irdft)); + s->irdft = av_calloc(outlink->ch_layout.nb_channels, sizeof(*s->irdft)); if (!s->irdft) return AVERROR(ENOMEM); - s->nb_out_channels = outlink->channels; + s->nb_out_channels = outlink->ch_layout.nb_channels; - for (ch = 0; ch < outlink->channels; ch++) { - s->irdft[ch] = av_rdft_init(ff_log2(s->buf_size), IDFT_C2R); + for (ch = 0; ch < outlink->ch_layout.nb_channels; ch++) { + float iscale = 1.f; + + av_tx_init(&s->irdft[ch], &s->itx_fn, AV_TX_FLOAT_RDFT, 1, s->buf_size, &iscale, 0); if (!s->irdft[ch]) return AVERROR(ENOMEM); } @@ -275,37 +282,38 @@ static int config_output(AVFilterLink *outlink) return AVERROR(ENOMEM); for (ch = 0; ch < s->nb_out_channels; ch++) s->output_levels[ch] = s->level_out; - ch = av_get_channel_layout_channel_index(outlink->channel_layout, AV_CH_FRONT_CENTER); + ch = av_channel_layout_index_from_channel(&outlink->ch_layout, AV_CHAN_FRONT_CENTER); if (ch >= 0) s->output_levels[ch] *= s->fc_out; - ch = av_get_channel_layout_channel_index(outlink->channel_layout, AV_CH_FRONT_LEFT); + ch = av_channel_layout_index_from_channel(&outlink->ch_layout, AV_CHAN_FRONT_LEFT); if (ch >= 0) s->output_levels[ch] *= s->fl_out; - ch = av_get_channel_layout_channel_index(outlink->channel_layout, AV_CH_FRONT_RIGHT); + ch = av_channel_layout_index_from_channel(&outlink->ch_layout, AV_CHAN_FRONT_RIGHT); if (ch >= 0) s->output_levels[ch] *= s->fr_out; - ch = av_get_channel_layout_channel_index(outlink->channel_layout, AV_CH_SIDE_LEFT); + ch = av_channel_layout_index_from_channel(&outlink->ch_layout, AV_CHAN_SIDE_LEFT); if (ch >= 0) s->output_levels[ch] *= s->sl_out; - ch = av_get_channel_layout_channel_index(outlink->channel_layout, AV_CH_SIDE_RIGHT); + ch = av_channel_layout_index_from_channel(&outlink->ch_layout, AV_CHAN_SIDE_RIGHT); if (ch >= 0) s->output_levels[ch] *= s->sr_out; - ch = av_get_channel_layout_channel_index(outlink->channel_layout, AV_CH_BACK_LEFT); + ch = av_channel_layout_index_from_channel(&outlink->ch_layout, AV_CHAN_BACK_LEFT); if (ch >= 0) s->output_levels[ch] *= s->bl_out; - ch = av_get_channel_layout_channel_index(outlink->channel_layout, AV_CH_BACK_RIGHT); + ch = av_channel_layout_index_from_channel(&outlink->ch_layout, AV_CHAN_BACK_RIGHT); if (ch >= 0) s->output_levels[ch] *= s->br_out; - ch = av_get_channel_layout_channel_index(outlink->channel_layout, AV_CH_BACK_CENTER); + ch = av_channel_layout_index_from_channel(&outlink->ch_layout, AV_CHAN_BACK_CENTER); if (ch >= 0) s->output_levels[ch] *= s->bc_out; - ch = av_get_channel_layout_channel_index(outlink->channel_layout, AV_CH_LOW_FREQUENCY); + ch = av_channel_layout_index_from_channel(&outlink->ch_layout, AV_CHAN_LOW_FREQUENCY); if (ch >= 0) s->output_levels[ch] *= s->lfe_out; - s->output = ff_get_audio_buffer(outlink, s->buf_size * 2); + s->output_out = ff_get_audio_buffer(outlink, s->buf_size + 2); + s->output = ff_get_audio_buffer(outlink, s->buf_size + 2); s->overlap_buffer = ff_get_audio_buffer(outlink, s->buf_size * 2); - if (!s->overlap_buffer || !s->output) + if (!s->overlap_buffer || !s->output || !s->output_out) return AVERROR(ENOMEM); return 0; @@ -327,16 +335,16 @@ static void stereo_transform(float *x, float *y, float angle) else a = M_PI + 2 * (-2 * M_PI + reference) * (M_PI - fabsf(a)) * FFDIFFSIGN(a, 0) / (3 * M_PI); - *x = av_clipf(sinf(a) * r, -1, 1); - *y = av_clipf(cosf(a) * r, -1, 1); + *x = av_clipf(sinf(a) * r, -1.f, 1.f); + *y = av_clipf(cosf(a) * r, -1.f, 1.f); } static void stereo_position(float a, float p, float *x, float *y) { av_assert2(a >= -1.f && a <= 1.f); av_assert2(p >= 0.f && p <= M_PI); - *x = av_clipf(a+a*FFMAX(0, p*p-M_PI_2), -1, 1); - *y = av_clipf(cosf(a*M_PI_2+M_PI)*cosf(M_PI_2-p/M_PI)*M_LN10+1, -1, 1); + *x = av_clipf(a+a*FFMAX(0, p*p-M_PI_2), -1.f, 1.f); + *y = av_clipf(cosf(a*M_PI_2+M_PI)*cosf(M_PI_2-p/M_PI)*M_LN10+1, -1.f, 1.f); } static inline void get_lfe(int output_lfe, int n, float lowcut, float highcut, @@ -1099,7 +1107,7 @@ static void filter_stereo(AVFilterContext *ctx) srcl = (float *)s->input->extended_data[0]; srcr = (float *)s->input->extended_data[1]; - for (n = 0; n < s->buf_size; n++) { + for (n = 0; n < s->buf_size / 2 + 1; n++) { float l_re = srcl[2 * n], r_re = srcr[2 * n]; float l_im = srcl[2 * n + 1], r_im = srcr[2 * n + 1]; float c_phase = atan2f(l_im + r_im, l_re + r_re); @@ -1133,7 +1141,7 @@ static void filter_surround(AVFilterContext *ctx) srcr = (float *)s->input->extended_data[1]; srcc = (float *)s->input->extended_data[2]; - for (n = 0; n < s->buf_size; n++) { + for (n = 0; n < s->buf_size / 2 + 1; n++) { float l_re = srcl[2 * n], r_re = srcr[2 * n]; float l_im = srcl[2 * n + 1], r_im = srcr[2 * n + 1]; float c_re = srcc[2 * n], c_im = srcc[2 * n + 1]; @@ -1169,7 +1177,7 @@ static void filter_2_1(AVFilterContext *ctx) srcr = (float *)s->input->extended_data[1]; srclfe = (float *)s->input->extended_data[2]; - for (n = 0; n < s->buf_size; n++) { + for (n = 0; n < s->buf_size / 2 + 1; n++) { float l_re = srcl[2 * n], r_re = srcr[2 * n]; float l_im = srcl[2 * n + 1], r_im = srcr[2 * n + 1]; float lfe_re = srclfe[2 * n], lfe_im = srclfe[2 * n + 1]; @@ -1206,7 +1214,7 @@ static void filter_5_0_side(AVFilterContext *ctx) srcsl = (float *)s->input->extended_data[3]; srcsr = (float *)s->input->extended_data[4]; - for (n = 0; n < s->buf_size; n++) { + for (n = 0; n < s->buf_size / 2 + 1; 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]; @@ -1264,7 +1272,7 @@ static void filter_5_1_side(AVFilterContext *ctx) srcsl = (float *)s->input->extended_data[4]; srcsr = (float *)s->input->extended_data[5]; - for (n = 0; n < s->buf_size; n++) { + for (n = 0; n < s->buf_size / 2 + 1; 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]; @@ -1323,7 +1331,7 @@ static void filter_5_1_back(AVFilterContext *ctx) srcbl = (float *)s->input->extended_data[4]; srcbr = (float *)s->input->extended_data[5]; - for (n = 0; n < s->buf_size; n++) { + for (n = 0; n < s->buf_size / 2 + 1; 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]; @@ -1373,15 +1381,16 @@ static av_cold int init(AVFilterContext *ctx) { AudioSurroundContext *s = ctx->priv; float overlap; - int i; + int64_t in_channel_layout, out_channel_layout; + int i, ret; - if (!(s->out_channel_layout = av_get_channel_layout(s->out_channel_layout_str))) { + if ((ret = av_channel_layout_from_string(&s->out_channel_layout, s->out_channel_layout_str)) < 0) { av_log(ctx, AV_LOG_ERROR, "Error parsing output channel layout '%s'.\n", s->out_channel_layout_str); - return AVERROR(EINVAL); + return ret; } - if (!(s->in_channel_layout = av_get_channel_layout(s->in_channel_layout_str))) { + if ((ret = av_channel_layout_from_string(&s->in_channel_layout, s->in_channel_layout_str)) < 0) { av_log(ctx, AV_LOG_ERROR, "Error parsing input channel layout '%s'.\n", s->in_channel_layout_str); return AVERROR(EINVAL); @@ -1393,10 +1402,15 @@ static av_cold int init(AVFilterContext *ctx) return AVERROR(EINVAL); } - switch (s->in_channel_layout) { + in_channel_layout = s->in_channel_layout.order == AV_CHANNEL_ORDER_NATIVE ? + s->in_channel_layout.u.mask : 0; + out_channel_layout = s->out_channel_layout.order == AV_CHANNEL_ORDER_NATIVE ? + s->out_channel_layout.u.mask : 0; + + switch (in_channel_layout) { case AV_CH_LAYOUT_STEREO: s->filter = filter_stereo; - switch (s->out_channel_layout) { + switch (out_channel_layout) { case AV_CH_LAYOUT_MONO: s->upmix_stereo = upmix_1_0; break; @@ -1442,7 +1456,7 @@ static av_cold int init(AVFilterContext *ctx) break; case AV_CH_LAYOUT_2POINT1: s->filter = filter_2_1; - switch (s->out_channel_layout) { + switch (out_channel_layout) { case AV_CH_LAYOUT_5POINT1_BACK: s->upmix_2_1 = upmix_5_1_back_2_1; break; @@ -1452,7 +1466,7 @@ static av_cold int init(AVFilterContext *ctx) break; case AV_CH_LAYOUT_SURROUND: s->filter = filter_surround; - switch (s->out_channel_layout) { + switch (out_channel_layout) { case AV_CH_LAYOUT_3POINT1: s->upmix_3_0 = upmix_3_1_surround; break; @@ -1465,7 +1479,7 @@ static av_cold int init(AVFilterContext *ctx) break; case AV_CH_LAYOUT_5POINT0: s->filter = filter_5_0_side; - switch (s->out_channel_layout) { + switch (out_channel_layout) { case AV_CH_LAYOUT_7POINT1: s->upmix_5_0 = upmix_7_1_5_0_side; break; @@ -1475,7 +1489,7 @@ static av_cold int init(AVFilterContext *ctx) break; case AV_CH_LAYOUT_5POINT1: s->filter = filter_5_1_side; - switch (s->out_channel_layout) { + switch (out_channel_layout) { case AV_CH_LAYOUT_7POINT1: s->upmix_5_1 = upmix_7_1_5_1; break; @@ -1485,7 +1499,7 @@ static av_cold int init(AVFilterContext *ctx) break; case AV_CH_LAYOUT_5POINT1_BACK: s->filter = filter_5_1_back; - switch (s->out_channel_layout) { + switch (out_channel_layout) { case AV_CH_LAYOUT_7POINT1: s->upmix_5_1 = upmix_7_1_5_1; break; @@ -1501,7 +1515,6 @@ fail: } s->buf_size = 1 << av_log2(s->win_size); - s->pts = AV_NOPTS_VALUE; s->window_func_lut = av_calloc(s->buf_size, sizeof(*s->window_func_lut)); if (!s->window_func_lut) @@ -1528,18 +1541,21 @@ fail: static int fft_channel(AVFilterContext *ctx, void *arg, int ch, int nb_jobs) { AudioSurroundContext *s = ctx->priv; + float *src = (float *)s->input_in->extended_data[ch]; + float *win = (float *)s->window->extended_data[ch]; + const int offset = s->buf_size - s->hop_size; const float level_in = s->input_levels[ch]; - float *dst; - int n; + AVFrame *in = arg; - memset(s->input->extended_data[ch] + s->buf_size * sizeof(float), 0, s->buf_size * sizeof(float)); + memmove(src, &src[s->hop_size], offset * sizeof(float)); + memcpy(&src[offset], in->extended_data[ch], in->nb_samples * sizeof(float)); + memset(&src[offset + in->nb_samples], 0, (s->hop_size - in->nb_samples) * sizeof(float)); - dst = (float *)s->input->extended_data[ch]; - for (n = 0; n < s->buf_size; n++) { - dst[n] *= s->window_func_lut[n] * level_in; + for (int n = 0; n < s->buf_size; n++) { + win[n] = src[n] * s->window_func_lut[n] * level_in; } - av_rdft_calc(s->rdft[ch], (float *)s->input->extended_data[ch]); + s->tx_fn(s->rdft[ch], (float *)s->input->extended_data[ch], win, sizeof(float)); return 0; } @@ -1552,10 +1568,9 @@ static int ifft_channel(AVFilterContext *ctx, void *arg, int ch, int nb_jobs) float *dst, *ptr; int n; - av_rdft_calc(s->irdft[ch], (float *)s->output->extended_data[ch]); - - dst = (float *)s->output->extended_data[ch]; + dst = (float *)s->output_out->extended_data[ch]; ptr = (float *)s->overlap_buffer->extended_data[ch]; + s->itx_fn(s->irdft[ch], dst, (float *)s->output->extended_data[ch], sizeof(float)); memmove(s->overlap_buffer->extended_data[ch], s->overlap_buffer->extended_data[ch] + s->hop_size * sizeof(float), @@ -1574,19 +1589,14 @@ static int ifft_channel(AVFilterContext *ctx, void *arg, int ch, int nb_jobs) return 0; } -static int filter_frame(AVFilterLink *inlink) +static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; AudioSurroundContext *s = ctx->priv; AVFrame *out; - int ret; - ret = av_audio_fifo_peek(s->fifo, (void **)s->input->extended_data, s->buf_size); - if (ret < 0) - return ret; - - ff_filter_execute(ctx, fft_channel, NULL, NULL, inlink->channels); + ff_filter_execute(ctx, fft_channel, in, NULL, inlink->ch_layout.nb_channels); s->filter(ctx); @@ -1594,13 +1604,12 @@ static int filter_frame(AVFilterLink *inlink) if (!out) return AVERROR(ENOMEM); - ff_filter_execute(ctx, ifft_channel, out, NULL, outlink->channels); + ff_filter_execute(ctx, ifft_channel, out, NULL, outlink->ch_layout.nb_channels); - out->pts = s->pts; - if (s->pts != AV_NOPTS_VALUE) - s->pts += av_rescale_q(out->nb_samples, (AVRational){1, outlink->sample_rate}, outlink->time_base); - av_audio_fifo_drain(s->fifo, FFMIN(av_audio_fifo_size(s->fifo), s->hop_size)); + out->pts = in->pts; + out->nb_samples = in->nb_samples; + av_frame_free(&in); return ff_filter_frame(outlink, out); } @@ -1615,48 +1624,26 @@ static int activate(AVFilterContext *ctx) FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); - if (!s->eof && av_audio_fifo_size(s->fifo) < s->buf_size) { - ret = ff_inlink_consume_frame(inlink, &in); - if (ret < 0) - return ret; - - if (ret > 0) { - 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; - } - } - - if ((av_audio_fifo_size(s->fifo) >= s->buf_size) || - (av_audio_fifo_size(s->fifo) > 0 && s->eof)) { - ret = filter_frame(inlink); - if (av_audio_fifo_size(s->fifo) >= s->buf_size) - ff_filter_set_ready(ctx, 100); + ret = ff_inlink_consume_samples(inlink, s->hop_size, s->hop_size, &in); + if (ret < 0) return ret; - } - if (!s->eof && ff_inlink_acknowledge_status(inlink, &status, &pts)) { - if (status == AVERROR_EOF) { - s->eof = 1; - if (av_audio_fifo_size(s->fifo) >= 0) { - ff_filter_set_ready(ctx, 100); - return 0; - } - } - } + if (ret > 0) + ret = filter_frame(inlink, in); + if (ret < 0) + return ret; - if (s->eof && av_audio_fifo_size(s->fifo) <= 0) { - ff_outlink_set_status(outlink, AVERROR_EOF, s->pts); + if (ff_inlink_queued_samples(inlink) >= s->hop_size) { + ff_filter_set_ready(ctx, 10); return 0; } - if (!s->eof) - FF_FILTER_FORWARD_WANTED(outlink, inlink); + if (ff_inlink_acknowledge_status(inlink, &status, &pts)) { + ff_outlink_set_status(outlink, status, pts); + return 0; + } + + FF_FILTER_FORWARD_WANTED(outlink, inlink); return FFERROR_NOT_READY; } @@ -1664,23 +1651,22 @@ static int activate(AVFilterContext *ctx) static av_cold void uninit(AVFilterContext *ctx) { AudioSurroundContext *s = ctx->priv; - int ch; + av_frame_free(&s->window); + av_frame_free(&s->input_in); av_frame_free(&s->input); av_frame_free(&s->output); + av_frame_free(&s->output_out); av_frame_free(&s->overlap_buffer); - for (ch = 0; ch < s->nb_in_channels; ch++) { - av_rdft_end(s->rdft[ch]); - } - for (ch = 0; ch < s->nb_out_channels; ch++) { - av_rdft_end(s->irdft[ch]); - } + for (int ch = 0; ch < s->nb_in_channels; ch++) + av_tx_uninit(&s->rdft[ch]); + for (int ch = 0; ch < s->nb_out_channels; ch++) + av_tx_uninit(&s->irdft[ch]); av_freep(&s->input_levels); av_freep(&s->output_levels); av_freep(&s->rdft); av_freep(&s->irdft); - av_audio_fifo_free(s->fifo); av_freep(&s->window_func_lut); } @@ -1719,22 +1705,22 @@ static const AVOption surround_options[] = { { "lfe_out", "set lfe channel output level", OFFSET(lfe_out), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 10, FLAGS }, { "allx", "set all channel's x spread", OFFSET(all_x), AV_OPT_TYPE_FLOAT, {.dbl=-1}, -1, 15, FLAGS }, { "ally", "set all channel's y spread", OFFSET(all_y), AV_OPT_TYPE_FLOAT, {.dbl=-1}, -1, 15, FLAGS }, - { "fcx", "set front center channel x spread", OFFSET(fc_x), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 15, FLAGS }, - { "flx", "set front left channel x spread", OFFSET(fl_x), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 15, FLAGS }, - { "frx", "set front right channel x spread", OFFSET(fr_x), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 15, FLAGS }, - { "blx", "set back left channel x spread", OFFSET(bl_x), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 15, FLAGS }, - { "brx", "set back right channel x spread", OFFSET(br_x), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 15, FLAGS }, - { "slx", "set side left channel x spread", OFFSET(sl_x), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 15, FLAGS }, - { "srx", "set side right channel x spread", OFFSET(sr_x), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 15, FLAGS }, - { "bcx", "set back center channel x spread", OFFSET(bc_x), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 15, FLAGS }, - { "fcy", "set front center channel y spread", OFFSET(fc_y), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 15, FLAGS }, - { "fly", "set front left channel y spread", OFFSET(fl_y), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 15, FLAGS }, - { "fry", "set front right channel y spread", OFFSET(fr_y), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 15, FLAGS }, - { "bly", "set back left channel y spread", OFFSET(bl_y), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 15, FLAGS }, - { "bry", "set back right channel y spread", OFFSET(br_y), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 15, FLAGS }, - { "sly", "set side left channel y spread", OFFSET(sl_y), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 15, FLAGS }, - { "sry", "set side right channel y spread", OFFSET(sr_y), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 15, FLAGS }, - { "bcy", "set back center channel y spread", OFFSET(bc_y), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 15, FLAGS }, + { "fcx", "set front center channel x spread", OFFSET(fc_x), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, .06, 15, FLAGS }, + { "flx", "set front left channel x spread", OFFSET(fl_x), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, .06, 15, FLAGS }, + { "frx", "set front right channel x spread", OFFSET(fr_x), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, .06, 15, FLAGS }, + { "blx", "set back left channel x spread", OFFSET(bl_x), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, .06, 15, FLAGS }, + { "brx", "set back right channel x spread", OFFSET(br_x), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, .06, 15, FLAGS }, + { "slx", "set side left channel x spread", OFFSET(sl_x), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, .06, 15, FLAGS }, + { "srx", "set side right channel x spread", OFFSET(sr_x), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, .06, 15, FLAGS }, + { "bcx", "set back center channel x spread", OFFSET(bc_x), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, .06, 15, FLAGS }, + { "fcy", "set front center channel y spread", OFFSET(fc_y), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, .06, 15, FLAGS }, + { "fly", "set front left channel y spread", OFFSET(fl_y), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, .06, 15, FLAGS }, + { "fry", "set front right channel y spread", OFFSET(fr_y), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, .06, 15, FLAGS }, + { "bly", "set back left channel y spread", OFFSET(bl_y), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, .06, 15, FLAGS }, + { "bry", "set back right channel y spread", OFFSET(br_y), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, .06, 15, FLAGS }, + { "sly", "set side left channel y spread", OFFSET(sl_y), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, .06, 15, FLAGS }, + { "sry", "set side right channel y spread", OFFSET(sr_y), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, .06, 15, FLAGS }, + { "bcy", "set back center channel y spread", OFFSET(bc_y), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, .06, 15, FLAGS }, { "win_size", "set window size", OFFSET(win_size), AV_OPT_TYPE_INT, {.i64 = 4096}, 1024, 65536, FLAGS }, WIN_FUNC_OPTION("win_func", OFFSET(win_func), FLAGS, WFUNC_HANNING), { "overlap", "set window overlap", OFFSET(overlap), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, 0, 1, FLAGS }, diff --git a/libavfilter/af_tremolo.c b/libavfilter/af_tremolo.c index b34a7b79f..3e3e2be6f 100644 --- a/libavfilter/af_tremolo.c +++ b/libavfilter/af_tremolo.c @@ -49,7 +49,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) AVFilterLink *outlink = ctx->outputs[0]; TremoloContext *s = ctx->priv; const double *src = (const double *)in->data[0]; - const int channels = inlink->channels; + const int channels = inlink->ch_layout.nb_channels; const int nb_samples = in->nb_samples; AVFrame *out; double *dst; @@ -137,4 +137,5 @@ const AVFilter ff_af_tremolo = { FILTER_INPUTS(avfilter_af_tremolo_inputs), FILTER_OUTPUTS(avfilter_af_tremolo_outputs), FILTER_SINGLE_SAMPLEFMT(AV_SAMPLE_FMT_DBL), + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, }; diff --git a/libavfilter/af_vibrato.c b/libavfilter/af_vibrato.c index 2cf136427..807d2b599 100644 --- a/libavfilter/af_vibrato.c +++ b/libavfilter/af_vibrato.c @@ -71,7 +71,6 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) av_frame_copy_props(out, in); } - for (n = 0; n < in->nb_samples; n++) { double integer, decimal; decimal = modf(s->depth * s->wave_table[s->wave_table_index], &integer); @@ -80,7 +79,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) if (s->wave_table_index >= s->wave_table_size) s->wave_table_index -= s->wave_table_size; - for (c = 0; c < inlink->channels; c++) { + for (c = 0; c < inlink->ch_layout.nb_channels; c++) { int samp1_index, samp2_index; double *buf; double this_samp; @@ -128,10 +127,10 @@ static int config_input(AVFilterLink *inlink) AVFilterContext *ctx = inlink->dst; VibratoContext *s = ctx->priv; - s->buf = av_calloc(inlink->channels, sizeof(*s->buf)); + s->buf = av_calloc(inlink->ch_layout.nb_channels, sizeof(*s->buf)); if (!s->buf) return AVERROR(ENOMEM); - s->channels = inlink->channels; + s->channels = inlink->ch_layout.nb_channels; s->buf_size = lrint(inlink->sample_rate * 0.005 + 0.5); for (c = 0; c < s->channels; c++) { s->buf[c] = av_malloc_array(s->buf_size, sizeof(*s->buf[c])); @@ -175,4 +174,5 @@ const AVFilter ff_af_vibrato = { FILTER_INPUTS(avfilter_af_vibrato_inputs), FILTER_OUTPUTS(avfilter_af_vibrato_outputs), FILTER_SINGLE_SAMPLEFMT(AV_SAMPLE_FMT_DBLP), + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, }; diff --git a/libavfilter/af_virtualbass.c b/libavfilter/af_virtualbass.c new file mode 100644 index 000000000..950159096 --- /dev/null +++ b/libavfilter/af_virtualbass.c @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2022 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 "audio.h" +#include "avfilter.h" +#include "filters.h" +#include "internal.h" + +#include + +typedef struct AudioVirtualBassContext { + const AVClass *class; + + double cutoff; + double strength; + + double a[3], m[3], cf[2]; +} AudioVirtualBassContext; + +#define OFFSET(x) offsetof(AudioVirtualBassContext, x) +#define TFLAGS AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_RUNTIME_PARAM +#define FLAGS AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM + +static const AVOption virtualbass_options[] = { + { "cutoff", "set virtual bass cutoff", OFFSET(cutoff), AV_OPT_TYPE_DOUBLE, {.dbl=250},100,500, FLAGS }, + { "strength", "set virtual bass strength", OFFSET(strength), AV_OPT_TYPE_DOUBLE, {.dbl=3}, 0.5, 3, TFLAGS }, + {NULL} +}; + +AVFILTER_DEFINE_CLASS(virtualbass); + +static int query_formats(AVFilterContext *ctx) +{ + AVFilterChannelLayouts *in_layout = NULL, *out_layout = NULL; + AVFilterFormats *formats = NULL; + int ret; + + if ((ret = ff_add_format (&formats, AV_SAMPLE_FMT_DBLP )) < 0 || + (ret = ff_set_common_formats (ctx, formats )) < 0 || + (ret = ff_add_channel_layout (&in_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO)) < 0 || + (ret = ff_channel_layouts_ref(in_layout, &ctx->inputs[0]->outcfg.channel_layouts)) < 0 || + (ret = ff_add_channel_layout (&out_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_2POINT1)) < 0 || + (ret = ff_channel_layouts_ref(out_layout, &ctx->outputs[0]->incfg.channel_layouts)) < 0) + return ret; + + return ff_set_common_all_samplerates(ctx); +} + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + AudioVirtualBassContext *s = ctx->priv; + const double Q = 0.707; + double g, k; + + g = tan(M_PI * s->cutoff / inlink->sample_rate); + k = 1. / Q; + s->a[0] = 1. / (1. + g * (g + k)); + s->a[1] = g * s->a[0]; + s->a[2] = g * s->a[1]; + s->m[0] = 0.; + s->m[1] = 0.; + s->m[2] = 1.; + + return 0; +} + +#define SQR(x) ((x) * (x)) + +static double vb_fun(double x) +{ + double y = 2.5 * atan(0.9 * x) + 2.5 * sqrt(1. - SQR(0.9 * x)) - 2.5; + + return y < 0. ? sin(y) : y; +} + +static void vb_stereo(AVFilterContext *ctx, AVFrame *out, AVFrame *in) +{ + AudioVirtualBassContext *s = ctx->priv; + const double *lsrc = (const double *)in->extended_data[0]; + const double *rsrc = (const double *)in->extended_data[1]; + double *ldst = (double *)out->extended_data[0]; + double *rdst = (double *)out->extended_data[1]; + double *lfe = (double *)out->extended_data[2]; + const double st = M_PI / s->strength; + const double a0 = s->a[0]; + const double a1 = s->a[1]; + const double a2 = s->a[2]; + const double m0 = s->m[0]; + const double m1 = s->m[1]; + const double m2 = s->m[2]; + double b0 = s->cf[0]; + double b1 = s->cf[1]; + + memcpy(ldst, lsrc, in->nb_samples * sizeof(double)); + memcpy(rdst, rsrc, in->nb_samples * sizeof(double)); + + for (int n = 0; n < in->nb_samples; n++) { + const double center = (lsrc[n] + rsrc[n]) * 0.5; + const double v0 = center; + const double v3 = v0 - b1; + const double v1 = a0 * b0 + a1 * v3; + const double v2 = b1 + a1 * b0 + a2 * v3; + double b, vb; + + b0 = 2. * v1 - b0; + b1 = 2. * v2 - b1; + + b = m0 * v0 + m1 * v1 + m2 * v2; + vb = sin(vb_fun(b) * st); + + lfe[n] = vb; + } + + s->cf[0] = b0; + s->cf[1] = b1; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + AVFrame *out; + + out = ff_get_audio_buffer(outlink, in->nb_samples); + if (!out) { + av_frame_free(&in); + return AVERROR(ENOMEM); + } + + vb_stereo(ctx, out, in); + + out->pts = in->pts; + 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, + }, +}; + +static const AVFilterPad outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + }, +}; + +const AVFilter ff_af_virtualbass = { + .name = "virtualbass", + .description = NULL_IF_CONFIG_SMALL("Audio Virtual Bass."), + .priv_size = sizeof(AudioVirtualBassContext), + .priv_class = &virtualbass_class, + FILTER_INPUTS(inputs), + FILTER_OUTPUTS(outputs), + FILTER_QUERY_FUNC(query_formats), + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, + .process_command = ff_filter_process_command, +}; diff --git a/libavfilter/af_volume.c b/libavfilter/af_volume.c index 76ccddc31..f6e183df8 100644 --- a/libavfilter/af_volume.c +++ b/libavfilter/af_volume.c @@ -238,8 +238,9 @@ static av_cold void volume_init(VolumeContext *vol) break; } - if (ARCH_X86) - ff_volume_init_x86(vol); +#if ARCH_X86 + ff_volume_init_x86(vol); +#endif } static int set_volume(AVFilterContext *ctx) @@ -281,7 +282,7 @@ static int config_output(AVFilterLink *outlink) AVFilterLink *inlink = ctx->inputs[0]; vol->sample_fmt = inlink->format; - vol->channels = inlink->channels; + vol->channels = inlink->ch_layout.nb_channels; vol->planes = av_sample_fmt_is_planar(inlink->format) ? vol->channels : 1; vol->var_values[VAR_N] = @@ -294,7 +295,7 @@ static int config_output(AVFilterLink *outlink) vol->var_values[VAR_T] = vol->var_values[VAR_VOLUME] = NAN; - vol->var_values[VAR_NB_CHANNELS] = inlink->channels; + vol->var_values[VAR_NB_CHANNELS] = inlink->ch_layout.nb_channels; vol->var_values[VAR_TB] = av_q2d(inlink->time_base); vol->var_values[VAR_SAMPLE_RATE] = inlink->sample_rate; diff --git a/libavfilter/af_volume.h b/libavfilter/af_volume.h index af46e34ff..c97902969 100644 --- a/libavfilter/af_volume.h +++ b/libavfilter/af_volume.h @@ -24,10 +24,10 @@ #ifndef AVFILTER_VOLUME_H #define AVFILTER_VOLUME_H -#include "libavutil/common.h" +#include #include "libavutil/eval.h" #include "libavutil/float_dsp.h" -#include "libavutil/opt.h" +#include "libavutil/log.h" #include "libavutil/samplefmt.h" enum PrecisionType { diff --git a/libavfilter/af_volumedetect.c b/libavfilter/af_volumedetect.c index 486fccc4e..ebfad6914 100644 --- a/libavfilter/af_volumedetect.c +++ b/libavfilter/af_volumedetect.c @@ -38,7 +38,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *samples) AVFilterContext *ctx = inlink->dst; VolDetectContext *vd = ctx->priv; int nb_samples = samples->nb_samples; - int nb_channels = samples->channels; + int nb_channels = samples->ch_layout.nb_channels; int nb_planes = nb_channels; int plane, i; int16_t *pcm; diff --git a/libavfilter/afir_template.c b/libavfilter/afir_template.c new file mode 100644 index 000000000..6cb3eb220 --- /dev/null +++ b/libavfilter/afir_template.c @@ -0,0 +1,392 @@ +/* + * 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 "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "audio.h" + +#undef ctype +#undef ftype +#undef SQRT +#undef SAMPLE_FORMAT +#if DEPTH == 32 +#define SAMPLE_FORMAT float +#define SQRT sqrtf +#define ctype AVComplexFloat +#define ftype float +#else +#define SAMPLE_FORMAT double +#define SQRT sqrt +#define ctype AVComplexDouble +#define ftype double +#endif + +#define fn3(a,b) a##_##b +#define fn2(a,b) fn3(a,b) +#define fn(a) fn2(a, SAMPLE_FORMAT) + +static void fn(draw_response)(AVFilterContext *ctx, AVFrame *out) +{ + AudioFIRContext *s = ctx->priv; + ftype *mag, *phase, *delay, min = FLT_MAX, max = FLT_MIN; + ftype min_delay = FLT_MAX, max_delay = FLT_MIN; + int prev_ymag = -1, prev_yphase = -1, prev_ydelay = -1; + char text[32]; + int channel, i, x; + + memset(out->data[0], 0, s->h * out->linesize[0]); + + phase = av_malloc_array(s->w, sizeof(*phase)); + mag = av_malloc_array(s->w, sizeof(*mag)); + delay = av_malloc_array(s->w, sizeof(*delay)); + if (!mag || !phase || !delay) + goto end; + + channel = av_clip(s->ir_channel, 0, s->ir[s->selir]->ch_layout.nb_channels - 1); + for (i = 0; i < s->w; i++) { + const ftype *src = (const ftype *)s->ir[s->selir]->extended_data[channel]; + double w = i * M_PI / (s->w - 1); + double div, real_num = 0., imag_num = 0., real = 0., imag = 0.; + + for (x = 0; x < s->nb_taps; x++) { + real += cos(-x * w) * src[x]; + imag += sin(-x * w) * src[x]; + real_num += cos(-x * w) * src[x] * x; + imag_num += sin(-x * w) * src[x] * x; + } + + mag[i] = hypot(real, imag); + phase[i] = atan2(imag, real); + div = real * real + imag * imag; + delay[i] = (real_num * real + imag_num * imag) / div; + min = fminf(min, mag[i]); + max = fmaxf(max, mag[i]); + min_delay = fminf(min_delay, delay[i]); + max_delay = fmaxf(max_delay, delay[i]); + } + + for (i = 0; i < s->w; i++) { + int ymag = mag[i] / max * (s->h - 1); + int ydelay = (delay[i] - min_delay) / (max_delay - min_delay) * (s->h - 1); + int yphase = (0.5 * (1. + phase[i] / M_PI)) * (s->h - 1); + + ymag = s->h - 1 - av_clip(ymag, 0, s->h - 1); + yphase = s->h - 1 - av_clip(yphase, 0, s->h - 1); + ydelay = s->h - 1 - av_clip(ydelay, 0, s->h - 1); + + if (prev_ymag < 0) + prev_ymag = ymag; + if (prev_yphase < 0) + prev_yphase = yphase; + if (prev_ydelay < 0) + prev_ydelay = ydelay; + + draw_line(out, i, ymag, FFMAX(i - 1, 0), prev_ymag, 0xFFFF00FF); + draw_line(out, i, yphase, FFMAX(i - 1, 0), prev_yphase, 0xFF00FF00); + draw_line(out, i, ydelay, FFMAX(i - 1, 0), prev_ydelay, 0xFF00FFFF); + + prev_ymag = ymag; + prev_yphase = yphase; + prev_ydelay = ydelay; + } + + if (s->w > 400 && s->h > 100) { + drawtext(out, 2, 2, "Max Magnitude:", 0xDDDDDDDD); + snprintf(text, sizeof(text), "%.2f", max); + drawtext(out, 15 * 8 + 2, 2, text, 0xDDDDDDDD); + + drawtext(out, 2, 12, "Min Magnitude:", 0xDDDDDDDD); + snprintf(text, sizeof(text), "%.2f", min); + drawtext(out, 15 * 8 + 2, 12, text, 0xDDDDDDDD); + + drawtext(out, 2, 22, "Max Delay:", 0xDDDDDDDD); + snprintf(text, sizeof(text), "%.2f", max_delay); + drawtext(out, 11 * 8 + 2, 22, text, 0xDDDDDDDD); + + drawtext(out, 2, 32, "Min Delay:", 0xDDDDDDDD); + snprintf(text, sizeof(text), "%.2f", min_delay); + drawtext(out, 11 * 8 + 2, 32, text, 0xDDDDDDDD); + } + +end: + av_free(delay); + av_free(phase); + av_free(mag); +} + +static void fn(convert_channels)(AVFilterContext *ctx, AudioFIRContext *s) +{ + for (int ch = 0; ch < ctx->inputs[1 + s->selir]->ch_layout.nb_channels; ch++) { + ftype *time = (ftype *)s->ir[s->selir]->extended_data[!s->one2many * ch]; + int toffset = 0; + + for (int i = FFMAX(1, s->length * s->nb_taps); i < s->nb_taps; i++) + time[i] = 0; + + av_log(ctx, AV_LOG_DEBUG, "channel: %d\n", ch); + + for (int segment = 0; segment < s->nb_segments; segment++) { + AudioFIRSegment *seg = &s->seg[segment]; + ftype *blockin = (ftype *)seg->blockin->extended_data[ch]; + ftype *blockout = (ftype *)seg->blockout->extended_data[ch]; + ctype *coeff = (ctype *)seg->coeff->extended_data[ch]; + + av_log(ctx, AV_LOG_DEBUG, "segment: %d\n", segment); + + for (int i = 0; i < seg->nb_partitions; i++) { + const int coffset = i * seg->coeff_size; + const int remaining = s->nb_taps - toffset; + const int size = remaining >= seg->part_size ? seg->part_size : remaining; + + if (size < 8) { + for (int n = 0; n < size; n++) + coeff[coffset + n].re = time[toffset + n]; + + toffset += size; + continue; + } + + memset(blockin, 0, sizeof(*blockin) * seg->fft_length); + memcpy(blockin, time + toffset, size * sizeof(*blockin)); + + seg->tx_fn(seg->tx[0], blockout, blockin, sizeof(ftype)); + + for (int n = 0; n < seg->part_size + 1; n++) { + coeff[coffset + n].re = blockout[2 * n]; + coeff[coffset + n].im = blockout[2 * n + 1]; + } + + toffset += size; + } + + av_log(ctx, AV_LOG_DEBUG, "nb_partitions: %d\n", seg->nb_partitions); + av_log(ctx, AV_LOG_DEBUG, "partition size: %d\n", seg->part_size); + av_log(ctx, AV_LOG_DEBUG, "block size: %d\n", seg->block_size); + av_log(ctx, AV_LOG_DEBUG, "fft_length: %d\n", seg->fft_length); + av_log(ctx, AV_LOG_DEBUG, "coeff_size: %d\n", seg->coeff_size); + av_log(ctx, AV_LOG_DEBUG, "input_size: %d\n", seg->input_size); + av_log(ctx, AV_LOG_DEBUG, "input_offset: %d\n", seg->input_offset); + } + } +} + +static int fn(get_power)(AVFilterContext *ctx, AudioFIRContext *s, int cur_nb_taps) +{ + ftype power = 0; + int ch; + + switch (s->gtype) { + case -1: + /* nothing to do */ + break; + case 0: + for (ch = 0; ch < ctx->inputs[1 + s->selir]->ch_layout.nb_channels; ch++) { + ftype *time = (ftype *)s->ir[s->selir]->extended_data[!s->one2many * ch]; + + for (int i = 0; i < cur_nb_taps; i++) + power += FFABS(time[i]); + } + s->gain = ctx->inputs[1 + s->selir]->ch_layout.nb_channels / power; + break; + case 1: + for (ch = 0; ch < ctx->inputs[1 + s->selir]->ch_layout.nb_channels; ch++) { + ftype *time = (ftype *)s->ir[s->selir]->extended_data[!s->one2many * ch]; + + for (int i = 0; i < cur_nb_taps; i++) + power += time[i]; + } + s->gain = ctx->inputs[1 + s->selir]->ch_layout.nb_channels / power; + break; + case 2: + for (ch = 0; ch < ctx->inputs[1 + s->selir]->ch_layout.nb_channels; ch++) { + ftype *time = (ftype *)s->ir[s->selir]->extended_data[!s->one2many * ch]; + + for (int i = 0; i < cur_nb_taps; i++) + power += time[i] * time[i]; + } + s->gain = SQRT(ch / power); + break; + default: + return AVERROR_BUG; + } + + s->gain = FFMIN(s->gain * s->ir_gain, 1.); + + av_log(ctx, AV_LOG_DEBUG, "power %f, gain %f\n", power, s->gain); + + for (int ch = 0; ch < ctx->inputs[1 + s->selir]->ch_layout.nb_channels; ch++) { + ftype *time = (ftype *)s->ir[s->selir]->extended_data[!s->one2many * ch]; + +#if DEPTH == 32 + s->fdsp->vector_fmul_scalar(time, time, s->gain, FFALIGN(cur_nb_taps, 4)); +#else + s->fdsp->vector_dmul_scalar(time, time, s->gain, FFALIGN(cur_nb_taps, 8)); +#endif + } + + return 0; +} + +static void fn(direct)(const ftype *in, const ctype *ir, int len, ftype *out) +{ + for (int n = 0; n < len; n++) + for (int m = 0; m <= n; m++) + out[n] += ir[m].re * in[n - m]; +} + +static void fn(fir_fadd)(AudioFIRContext *s, ftype *dst, const ftype *src, int nb_samples) +{ + if ((nb_samples & 15) == 0 && nb_samples >= 16) { +#if DEPTH == 32 + s->fdsp->vector_fmac_scalar(dst, src, 1.f, nb_samples); +#else + s->fdsp->vector_dmac_scalar(dst, src, 1.0, nb_samples); +#endif + } else { + for (int n = 0; n < nb_samples; n++) + dst[n] += src[n]; + } +} + +static int fn(fir_quantum)(AVFilterContext *ctx, AVFrame *out, int ch, int offset) +{ + AudioFIRContext *s = ctx->priv; + const ftype *in = (const ftype *)s->in->extended_data[ch] + offset; + ftype *blockin, *blockout, *buf, *ptr = (ftype *)out->extended_data[ch] + offset; + const int nb_samples = FFMIN(s->min_part_size, out->nb_samples - offset); + int n, i, j; + + for (int segment = 0; segment < s->nb_segments; segment++) { + AudioFIRSegment *seg = &s->seg[segment]; + ftype *src = (ftype *)seg->input->extended_data[ch]; + ftype *dst = (ftype *)seg->output->extended_data[ch]; + ftype *sumin = (ftype *)seg->sumin->extended_data[ch]; + ftype *sumout = (ftype *)seg->sumout->extended_data[ch]; + + if (s->min_part_size >= 8) { +#if DEPTH == 32 + s->fdsp->vector_fmul_scalar(src + seg->input_offset, in, s->dry_gain, FFALIGN(nb_samples, 4)); +#else + s->fdsp->vector_dmul_scalar(src + seg->input_offset, in, s->dry_gain, FFALIGN(nb_samples, 8)); +#endif + emms_c(); + } else { + for (n = 0; n < nb_samples; n++) + src[seg->input_offset + n] = in[n] * s->dry_gain; + } + + seg->output_offset[ch] += s->min_part_size; + if (seg->output_offset[ch] == seg->part_size) { + seg->output_offset[ch] = 0; + } else { + memmove(src, src + s->min_part_size, (seg->input_size - s->min_part_size) * sizeof(*src)); + + dst += seg->output_offset[ch]; + fn(fir_fadd)(s, ptr, dst, nb_samples); + continue; + } + + if (seg->part_size < 8) { + memset(dst, 0, sizeof(*dst) * seg->part_size * seg->nb_partitions); + + j = seg->part_index[ch]; + + for (i = 0; i < seg->nb_partitions; i++) { + const int coffset = j * seg->coeff_size; + const ctype *coeff = (const ctype *)seg->coeff->extended_data[ch * !s->one2many] + coffset; + + fn(direct)(src, coeff, nb_samples, dst); + + if (j == 0) + j = seg->nb_partitions; + j--; + } + + seg->part_index[ch] = (seg->part_index[ch] + 1) % seg->nb_partitions; + + memmove(src, src + s->min_part_size, (seg->input_size - s->min_part_size) * sizeof(*src)); + + for (n = 0; n < nb_samples; n++) { + ptr[n] += dst[n]; + } + continue; + } + + memset(sumin, 0, sizeof(*sumin) * seg->fft_length); + blockin = (ftype *)seg->blockin->extended_data[ch] + seg->part_index[ch] * seg->block_size; + blockout = (ftype *)seg->blockout->extended_data[ch] + seg->part_index[ch] * seg->block_size; + memset(blockin + seg->part_size, 0, sizeof(*blockin) * (seg->fft_length - seg->part_size)); + + memcpy(blockin, src, sizeof(*src) * seg->part_size); + + seg->tx_fn(seg->tx[ch], blockout, blockin, sizeof(ftype)); + + j = seg->part_index[ch]; + + for (i = 0; i < seg->nb_partitions; i++) { + const int coffset = j * seg->coeff_size; + const ftype *blockout = (const ftype *)seg->blockout->extended_data[ch] + i * seg->block_size; + const ctype *coeff = (const ctype *)seg->coeff->extended_data[ch * !s->one2many] + coffset; + +#if DEPTH == 32 + s->afirdsp.fcmul_add(sumin, blockout, (const ftype *)coeff, seg->part_size); +#else + s->afirdsp.dcmul_add(sumin, blockout, (const ftype *)coeff, seg->part_size); +#endif + + if (j == 0) + j = seg->nb_partitions; + j--; + } + + seg->itx_fn(seg->itx[ch], sumout, sumin, sizeof(ftype)); + + buf = (ftype *)seg->buffer->extended_data[ch]; + fn(fir_fadd)(s, buf, sumout, seg->part_size); + + memcpy(dst, buf, seg->part_size * sizeof(*dst)); + + buf = (ftype *)seg->buffer->extended_data[ch]; + memcpy(buf, sumout + seg->part_size, seg->part_size * sizeof(*buf)); + + seg->part_index[ch] = (seg->part_index[ch] + 1) % seg->nb_partitions; + + memmove(src, src + s->min_part_size, (seg->input_size - s->min_part_size) * sizeof(*src)); + + fn(fir_fadd)(s, ptr, dst, nb_samples); + } + + if (s->min_part_size >= 8) { +#if DEPTH == 32 + s->fdsp->vector_fmul_scalar(ptr, ptr, s->wet_gain, FFALIGN(nb_samples, 4)); +#else + s->fdsp->vector_dmul_scalar(ptr, ptr, s->wet_gain, FFALIGN(nb_samples, 8)); +#endif + emms_c(); + } else { + for (n = 0; n < nb_samples; n++) + ptr[n] *= s->wet_gain; + } + + return 0; +} + + diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index caa755320..5ebacfde2 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -19,9 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/thread.h" #include "avfilter.h" -#include "config.h" extern const AVFilter ff_af_abench; extern const AVFilter ff_af_acompressor; @@ -117,6 +115,7 @@ extern const AVFilter ff_af_crossfeed; extern const AVFilter ff_af_crystalizer; extern const AVFilter ff_af_dcshift; extern const AVFilter ff_af_deesser; +extern const AVFilter ff_af_dialoguenhance; extern const AVFilter ff_af_drmeter; extern const AVFilter ff_af_dynaudnorm; extern const AVFilter ff_af_earwax; @@ -150,9 +149,11 @@ extern const AVFilter ff_af_stereotools; extern const AVFilter ff_af_stereowiden; extern const AVFilter ff_af_superequalizer; extern const AVFilter ff_af_surround; +extern const AVFilter ff_af_tiltshelf; extern const AVFilter ff_af_treble; extern const AVFilter ff_af_tremolo; extern const AVFilter ff_af_vibrato; +extern const AVFilter ff_af_virtualbass; extern const AVFilter ff_af_volume; extern const AVFilter ff_af_volumedetect; @@ -183,6 +184,9 @@ extern const AVFilter ff_vf_bitplanenoise; extern const AVFilter ff_vf_blackdetect; extern const AVFilter ff_vf_blackframe; extern const AVFilter ff_vf_blend; +extern const AVFilter ff_vf_blend_vulkan; +extern const AVFilter ff_vf_blockdetect; +extern const AVFilter ff_vf_blurdetect; extern const AVFilter ff_vf_bm3d; extern const AVFilter ff_vf_boxblur; extern const AVFilter ff_vf_boxblur_opencl; @@ -191,6 +195,7 @@ extern const AVFilter ff_vf_cas; extern const AVFilter ff_vf_chromaber_vulkan; extern const AVFilter ff_vf_chromahold; extern const AVFilter ff_vf_chromakey; +extern const AVFilter ff_vf_chromakey_cuda; extern const AVFilter ff_vf_chromanr; extern const AVFilter ff_vf_chromashift; extern const AVFilter ff_vf_ciescope; @@ -204,6 +209,7 @@ extern const AVFilter ff_vf_colorkey; extern const AVFilter ff_vf_colorkey_opencl; extern const AVFilter ff_vf_colorhold; extern const AVFilter ff_vf_colorlevels; +extern const AVFilter ff_vf_colormap; extern const AVFilter ff_vf_colormatrix; extern const AVFilter ff_vf_colorspace; extern const AVFilter ff_vf_colortemperature; @@ -259,6 +265,7 @@ extern const AVFilter ff_vf_estdif; extern const AVFilter ff_vf_exposure; extern const AVFilter ff_vf_extractplanes; extern const AVFilter ff_vf_fade; +extern const AVFilter ff_vf_feedback; extern const AVFilter ff_vf_fftdnoiz; extern const AVFilter ff_vf_fftfilt; extern const AVFilter ff_vf_field; @@ -303,6 +310,8 @@ extern const AVFilter ff_vf_hwmap; extern const AVFilter ff_vf_hwupload; extern const AVFilter ff_vf_hwupload_cuda; extern const AVFilter ff_vf_hysteresis; +extern const AVFilter ff_vf_iccdetect; +extern const AVFilter ff_vf_iccgen; extern const AVFilter ff_vf_identity; extern const AVFilter ff_vf_idet; extern const AVFilter ff_vf_il; @@ -345,6 +354,7 @@ extern const AVFilter ff_vf_monochrome; extern const AVFilter ff_vf_morpho; extern const AVFilter ff_vf_mpdecimate; extern const AVFilter ff_vf_msad; +extern const AVFilter ff_vf_multiply; extern const AVFilter ff_vf_negate; extern const AVFilter ff_vf_nlmeans; extern const AVFilter ff_vf_nlmeans_opencl; @@ -359,6 +369,7 @@ extern const AVFilter ff_vf_oscilloscope; extern const AVFilter ff_vf_overlay; extern const AVFilter ff_vf_overlay_opencl; extern const AVFilter ff_vf_overlay_qsv; +extern const AVFilter ff_vf_overlay_vaapi; extern const AVFilter ff_vf_overlay_vulkan; extern const AVFilter ff_vf_overlay_cuda; extern const AVFilter ff_vf_owdenoise; @@ -371,6 +382,7 @@ extern const AVFilter ff_vf_perspective; extern const AVFilter ff_vf_phase; extern const AVFilter ff_vf_photosensitivity; extern const AVFilter ff_vf_pixdesctest; +extern const AVFilter ff_vf_pixelize; extern const AVFilter ff_vf_pixscope; extern const AVFilter ff_vf_pp; extern const AVFilter ff_vf_pp7; @@ -388,6 +400,7 @@ extern const AVFilter ff_vf_readeia608; extern const AVFilter ff_vf_readvitc; extern const AVFilter ff_vf_realtime; extern const AVFilter ff_vf_remap; +extern const AVFilter ff_vf_remap_opencl; extern const AVFilter ff_vf_removegrain; extern const AVFilter ff_vf_removelogo; extern const AVFilter ff_vf_repeatfields; @@ -431,6 +444,7 @@ extern const AVFilter ff_vf_shuffleplanes; extern const AVFilter ff_vf_sidedata; extern const AVFilter ff_vf_signalstats; extern const AVFilter ff_vf_signature; +extern const AVFilter ff_vf_siti; extern const AVFilter ff_vf_smartblur; extern const AVFilter ff_vf_sobel; extern const AVFilter ff_vf_sobel_opencl; @@ -507,6 +521,7 @@ extern const AVFilter ff_vsrc_allrgb; extern const AVFilter ff_vsrc_allyuv; extern const AVFilter ff_vsrc_cellauto; extern const AVFilter ff_vsrc_color; +extern const AVFilter ff_vsrc_colorchart; extern const AVFilter ff_vsrc_colorspectrum; extern const AVFilter ff_vsrc_coreimagesrc; extern const AVFilter ff_vsrc_frei0r_src; @@ -548,6 +563,7 @@ extern const AVFilter ff_avf_showwavespic; extern const AVFilter ff_vaf_spectrumsynth; /* multimedia sources */ +extern const AVFilter ff_avsrc_avsynctest; extern const AVFilter ff_avsrc_amovie; extern const AVFilter ff_avsrc_movie; diff --git a/libavfilter/asrc_afirsrc.c b/libavfilter/asrc_afirsrc.c index 3612610e7..615242e0f 100644 --- a/libavfilter/asrc_afirsrc.c +++ b/libavfilter/asrc_afirsrc.c @@ -109,7 +109,7 @@ static av_cold void uninit(AVFilterContext *ctx) static av_cold int query_formats(AVFilterContext *ctx) { AudioFIRSourceContext *s = ctx->priv; - static const int64_t chlayouts[] = { AV_CH_LAYOUT_MONO, -1 }; + static const AVChannelLayout chlayouts[] = { AV_CHANNEL_LAYOUT_MONO, { 0 } }; int sample_rates[] = { s->sample_rate, -1 }; static const enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_FLT, diff --git a/libavfilter/asrc_anoisesrc.c b/libavfilter/asrc_anoisesrc.c index 8c834492f..96a8fd63e 100644 --- a/libavfilter/asrc_anoisesrc.c +++ b/libavfilter/asrc_anoisesrc.c @@ -84,7 +84,7 @@ AVFILTER_DEFINE_CLASS(anoisesrc); static av_cold int query_formats(AVFilterContext *ctx) { ANoiseSrcContext *s = ctx->priv; - static const int64_t chlayouts[] = { AV_CH_LAYOUT_MONO, -1 }; + static const AVChannelLayout chlayouts[] = { AV_CHANNEL_LAYOUT_MONO, { 0 } }; int sample_rates[] = { s->sample_rate, -1 }; static const enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_DBL, diff --git a/libavfilter/asrc_anullsrc.c b/libavfilter/asrc_anullsrc.c index 7ee2fa5a5..c071d8aa1 100644 --- a/libavfilter/asrc_anullsrc.c +++ b/libavfilter/asrc_anullsrc.c @@ -38,7 +38,7 @@ typedef struct ANullContext { const AVClass *class; char *channel_layout_str; - uint64_t channel_layout; + AVChannelLayout ch_layout; char *sample_rate_str; int sample_rate; int64_t duration; @@ -72,7 +72,7 @@ static av_cold int init(AVFilterContext *ctx) null->sample_rate_str, ctx)) < 0) return ret; - if ((ret = ff_parse_channel_layout(&null->channel_layout, NULL, + if ((ret = ff_parse_channel_layout(&null->ch_layout, NULL, null->channel_layout_str, ctx)) < 0) return ret; @@ -82,7 +82,7 @@ static av_cold int init(AVFilterContext *ctx) static int query_formats(AVFilterContext *ctx) { ANullContext *null = ctx->priv; - int64_t chlayouts[] = { null->channel_layout, -1 }; + const AVChannelLayout chlayouts[] = { null->ch_layout, { 0 } }; int sample_rates[] = { null->sample_rate, -1 }; int ret; @@ -128,6 +128,12 @@ static int activate(AVFilterContext *ctx) return FFERROR_NOT_READY; } +static av_cold void uninit(AVFilterContext *ctx) +{ + ANullContext *s = ctx->priv; + av_channel_layout_uninit(&s->ch_layout); +} + static const AVFilterPad avfilter_asrc_anullsrc_outputs[] = { { .name = "default", @@ -140,6 +146,7 @@ const AVFilter ff_asrc_anullsrc = { .name = "anullsrc", .description = NULL_IF_CONFIG_SMALL("Null audio source, return empty audio frames."), .init = init, + .uninit = uninit, .priv_size = sizeof(ANullContext), .inputs = NULL, FILTER_OUTPUTS(avfilter_asrc_anullsrc_outputs), diff --git a/libavfilter/asrc_flite.c b/libavfilter/asrc_flite.c index 17e7a5b9b..5fab8086b 100644 --- a/libavfilter/asrc_flite.c +++ b/libavfilter/asrc_flite.c @@ -225,11 +225,13 @@ static int query_formats(AVFilterContext *ctx) int ret; AVFilterChannelLayouts *chlayouts = NULL; - int64_t chlayout = av_get_default_channel_layout(flite->wave->num_channels); AVFilterFormats *sample_formats = NULL; AVFilterFormats *sample_rates = NULL; + AVChannelLayout chlayout = { 0 }; - if ((ret = ff_add_channel_layout (&chlayouts , chlayout )) < 0 || + av_channel_layout_default(&chlayout, flite->wave->num_channels); + + if ((ret = ff_add_channel_layout (&chlayouts , &chlayout )) < 0 || (ret = ff_set_common_channel_layouts (ctx , chlayouts )) < 0 || (ret = ff_add_format (&sample_formats, AV_SAMPLE_FMT_S16 )) < 0 || (ret = ff_set_common_formats (ctx , sample_formats )) < 0 || diff --git a/libavfilter/asrc_hilbert.c b/libavfilter/asrc_hilbert.c index 82996c736..c8e843546 100644 --- a/libavfilter/asrc_hilbert.c +++ b/libavfilter/asrc_hilbert.c @@ -77,7 +77,7 @@ static av_cold void uninit(AVFilterContext *ctx) static av_cold int query_formats(AVFilterContext *ctx) { HilbertContext *s = ctx->priv; - static const int64_t chlayouts[] = { AV_CH_LAYOUT_MONO, -1 }; + static const AVChannelLayout chlayouts[] = { AV_CHANNEL_LAYOUT_MONO, { 0 } }; int sample_rates[] = { s->sample_rate, -1 }; static const enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_FLT, diff --git a/libavfilter/asrc_sinc.c b/libavfilter/asrc_sinc.c index aaa81291a..db6f70eb2 100644 --- a/libavfilter/asrc_sinc.c +++ b/libavfilter/asrc_sinc.c @@ -22,8 +22,7 @@ #include "libavutil/avassert.h" #include "libavutil/channel_layout.h" #include "libavutil/opt.h" - -#include "libavcodec/avfft.h" +#include "libavutil/tx.h" #include "audio.h" #include "avfilter.h" @@ -42,7 +41,8 @@ typedef struct SincContext { float *coeffs; int64_t pts; - RDFTContext *rdft, *irdft; + AVTXContext *tx, *itx; + av_tx_fn tx_fn, itx_fn; } SincContext; static int activate(AVFilterContext *ctx) @@ -76,7 +76,7 @@ static int activate(AVFilterContext *ctx) static int query_formats(AVFilterContext *ctx) { SincContext *s = ctx->priv; - static const int64_t chlayouts[] = { AV_CH_LAYOUT_MONO, -1 }; + static const AVChannelLayout chlayouts[] = { AV_CHANNEL_LAYOUT_MONO, { 0 } }; int sample_rates[] = { s->sample_rate, -1 }; static const enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_NONE }; @@ -113,6 +113,9 @@ static float *make_lpf(int num_taps, float Fc, float beta, float rho, float *h = av_calloc(num_taps, sizeof(*h)), sum = 0; float mult = scale / bessel_I_0(beta), mult1 = 1.f / (.5f * m + rho); + if (!h) + return NULL; + av_assert0(Fc >= 0 && Fc <= 1); for (i = 0; i <= m / 2; i++) { @@ -200,8 +203,6 @@ static void invert(float *h, int n) h[(n - 1) / 2] += 1; } -#define PACK(h, n) h[1] = h[n] -#define UNPACK(h, n) h[n] = h[1], h[n + 1] = h[1] = 0; #define SQR(a) ((a) * (a)) static float safe_log(float x) @@ -216,7 +217,7 @@ static int fir_to_phase(SincContext *s, float **h, int *len, int *post_len, floa { float *pi_wraps, *work, phase1 = (phase > 50.f ? 100.f - phase : phase) / 50.f; int i, work_len, begin, end, imp_peak = 0, peak = 0; - float imp_sum = 0, peak_imp_sum = 0; + float imp_sum = 0, peak_imp_sum = 0, scale = 1.f; float prev_angle2 = 0, cum_2pi = 0, prev_angle1 = 0, cum_1pi = 0; for (i = *len, work_len = 2 * 2 * 8; i > 1; work_len <<= 1, i >>= 1); @@ -229,18 +230,16 @@ static int fir_to_phase(SincContext *s, float **h, int *len, int *post_len, floa memcpy(work, *h, *len * sizeof(*work)); - av_rdft_end(s->rdft); - av_rdft_end(s->irdft); - s->rdft = s->irdft = NULL; - s->rdft = av_rdft_init(av_log2(work_len), DFT_R2C); - s->irdft = av_rdft_init(av_log2(work_len), IDFT_C2R); - if (!s->rdft || !s->irdft) { + av_tx_uninit(&s->tx); + av_tx_uninit(&s->itx); + av_tx_init(&s->tx, &s->tx_fn, AV_TX_FLOAT_RDFT, 0, work_len, &scale, AV_TX_INPLACE); + av_tx_init(&s->itx, &s->itx_fn, AV_TX_FLOAT_RDFT, 1, work_len, &scale, AV_TX_INPLACE); + if (!s->tx || !s->itx) { av_free(work); return AVERROR(ENOMEM); } - av_rdft_calc(s->rdft, work); /* Cepstral: */ - UNPACK(work, work_len); + s->tx_fn(s->tx, work, work, sizeof(float)); /* Cepstral: */ for (i = 0; i <= work_len; i += 2) { float angle = atan2f(work[i + 1], work[i]); @@ -262,8 +261,7 @@ static int fir_to_phase(SincContext *s, float **h, int *len, int *post_len, floa work[i + 1] = 0; } - PACK(work, work_len); - av_rdft_calc(s->irdft, work); + s->itx_fn(s->itx, work, work, sizeof(float)); for (i = 0; i < work_len; i++) work[i] *= 2.f / work_len; @@ -272,7 +270,7 @@ static int fir_to_phase(SincContext *s, float **h, int *len, int *post_len, floa work[i] *= 2; work[i + work_len / 2] = 0; } - av_rdft_calc(s->rdft, work); + s->tx_fn(s->tx, work, work, sizeof(float)); for (i = 2; i < work_len; i += 2) /* Interpolate between linear & min phase */ work[i + 1] = phase1 * i / work_len * pi_wraps[work_len >> 1] + (1 - phase1) * (work[i + 1] + pi_wraps[i >> 1]) - pi_wraps[i >> 1]; @@ -286,7 +284,7 @@ static int fir_to_phase(SincContext *s, float **h, int *len, int *post_len, floa work[i + 1] = x * sinf(work[i + 1]); } - av_rdft_calc(s->irdft, work); + s->itx_fn(s->itx, work, work, sizeof(float)); for (i = 0; i < work_len; i++) work[i] *= 2.f / work_len; @@ -390,9 +388,8 @@ static int config_output(AVFilterLink *outlink) s->coeffs[i] = h[longer][i]; av_free(h[longer]); - av_rdft_end(s->rdft); - av_rdft_end(s->irdft); - s->rdft = s->irdft = NULL; + av_tx_uninit(&s->tx); + av_tx_uninit(&s->itx); return 0; } @@ -402,9 +399,8 @@ static av_cold void uninit(AVFilterContext *ctx) SincContext *s = ctx->priv; av_freep(&s->coeffs); - av_rdft_end(s->rdft); - av_rdft_end(s->irdft); - s->rdft = s->irdft = NULL; + av_tx_uninit(&s->tx); + av_tx_uninit(&s->itx); } static const AVFilterPad sinc_outputs[] = { diff --git a/libavfilter/asrc_sine.c b/libavfilter/asrc_sine.c index c8995ae2c..c0d8d2265 100644 --- a/libavfilter/asrc_sine.c +++ b/libavfilter/asrc_sine.c @@ -180,7 +180,7 @@ static av_cold void uninit(AVFilterContext *ctx) static av_cold int query_formats(AVFilterContext *ctx) { SineContext *sine = ctx->priv; - static const int64_t chlayouts[] = { AV_CH_LAYOUT_MONO, -1 }; + static const AVChannelLayout chlayouts[] = { AV_CHANNEL_LAYOUT_MONO, { 0 } }; int sample_rates[] = { sine->sample_rate, -1 }; static const enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE }; diff --git a/libavfilter/audio.c b/libavfilter/audio.c index cebc9709d..499504724 100644 --- a/libavfilter/audio.c +++ b/libavfilter/audio.c @@ -22,15 +22,13 @@ #include "libavutil/avassert.h" #include "libavutil/channel_layout.h" #include "libavutil/common.h" +#include "libavutil/cpu.h" #include "audio.h" #include "avfilter.h" #include "framepool.h" #include "internal.h" -#define BUFFER_ALIGN 0 - - AVFrame *ff_null_get_audio_buffer(AVFilterLink *link, int nb_samples) { return ff_get_audio_buffer(link->dst->outputs[0], nb_samples); @@ -39,14 +37,19 @@ AVFrame *ff_null_get_audio_buffer(AVFilterLink *link, int nb_samples) AVFrame *ff_default_get_audio_buffer(AVFilterLink *link, int nb_samples) { AVFrame *frame = NULL; - int channels = link->channels; + int channels = link->ch_layout.nb_channels; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS int channel_layout_nb_channels = av_get_channel_layout_nb_channels(link->channel_layout); + int align = av_cpu_max_align(); av_assert0(channels == channel_layout_nb_channels || !channel_layout_nb_channels); +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (!link->frame_pool) { link->frame_pool = ff_frame_pool_audio_init(av_buffer_allocz, channels, - nb_samples, link->format, BUFFER_ALIGN); + nb_samples, link->format, align); if (!link->frame_pool) return NULL; } else { @@ -62,11 +65,11 @@ AVFrame *ff_default_get_audio_buffer(AVFilterLink *link, int nb_samples) } if (pool_channels != channels || pool_nb_samples < nb_samples || - pool_format != link->format || pool_align != BUFFER_ALIGN) { + pool_format != link->format || pool_align != align) { ff_frame_pool_uninit((FFFramePool **)&link->frame_pool); link->frame_pool = ff_frame_pool_audio_init(av_buffer_allocz, channels, - nb_samples, link->format, BUFFER_ALIGN); + nb_samples, link->format, align); if (!link->frame_pool) return NULL; } @@ -77,7 +80,16 @@ AVFrame *ff_default_get_audio_buffer(AVFilterLink *link, int nb_samples) return NULL; frame->nb_samples = nb_samples; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS frame->channel_layout = link->channel_layout; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + if (link->ch_layout.order != AV_CHANNEL_ORDER_UNSPEC && + av_channel_layout_copy(&frame->ch_layout, &link->ch_layout) < 0) { + av_frame_free(&frame); + return NULL; + } frame->sample_rate = link->sample_rate; av_samples_set_silence(frame->extended_data, 0, nb_samples, channels, link->format); diff --git a/libavfilter/avf_abitscope.c b/libavfilter/avf_abitscope.c index f74a6eacb..58e2bdaf6 100644 --- a/libavfilter/avf_abitscope.c +++ b/libavfilter/avf_abitscope.c @@ -34,13 +34,17 @@ typedef struct AudioBitScopeContext { int w, h; AVRational frame_rate; char *colors; + int mode; int nb_channels; int nb_samples; int depth; + int current_vpos; uint8_t *fg; uint64_t counter[64]; + + AVFrame *outpicref; } AudioBitScopeContext; #define OFFSET(x) offsetof(AudioBitScopeContext, x) @@ -52,6 +56,10 @@ static const AVOption abitscope_options[] = { { "size", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="1024x256"}, 0, 0, FLAGS }, { "s", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="1024x256"}, 0, 0, FLAGS }, { "colors", "set channels colors", OFFSET(colors), AV_OPT_TYPE_STRING, {.str = "red|green|blue|yellow|orange|lime|pink|magenta|brown" }, 0, 0, FLAGS }, + { "mode", "set output mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 1, FLAGS, "mode" }, + { "m", "set output mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 1, FLAGS, "mode" }, + { "bars", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, 0, 0, FLAGS, "mode" }, + { "trace", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 0, FLAGS, "mode" }, { NULL } }; @@ -63,7 +71,10 @@ static int query_formats(AVFilterContext *ctx) AVFilterChannelLayouts *layouts; AVFilterLink *inlink = ctx->inputs[0]; AVFilterLink *outlink = ctx->outputs[0]; - static const enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_NONE }; + static const enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S32P, + AV_SAMPLE_FMT_U8P, AV_SAMPLE_FMT_S64P, + AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_DBLP, + AV_SAMPLE_FMT_NONE }; static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_RGBA, AV_PIX_FMT_NONE }; int ret; @@ -96,7 +107,7 @@ static int config_input(AVFilterLink *inlink) char *colors, *saveptr = NULL; s->nb_samples = FFMAX(1, av_rescale(inlink->sample_rate, s->frame_rate.den, s->frame_rate.num)); - s->nb_channels = inlink->channels; + s->nb_channels = inlink->ch_layout.nb_channels; s->depth = inlink->format == AV_SAMPLE_FMT_S16P ? 16 : 32; s->fg = av_malloc_array(s->nb_channels, 4 * sizeof(*s->fg)); @@ -136,15 +147,64 @@ static int config_output(AVFilterLink *outlink) return 0; } -static void count_bits(AudioBitScopeContext *s, uint32_t sample, int max) -{ - int i; +#define BARS(type, depth, one) \ + for (int ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { \ + const type *in = (const type *)insamples->extended_data[ch]; \ + const int w = outpicref->width / inlink->ch_layout.nb_channels; \ + const int h = outpicref->height / depth; \ + const uint32_t color = AV_RN32(&s->fg[4 * ch]); \ + \ + memset(s->counter, 0, sizeof(s->counter)); \ + for (int i = 0; i < insamples->nb_samples; i++) { \ + for (int j = 0; j < depth; j++) { \ + if (in[i] & (one << j)) \ + s->counter[j]++; \ + } \ + } \ + \ + for (int b = 0; b < depth; b++) { \ + for (int j = 1; j < h - 1; j++) { \ + uint8_t *dst = outpicref->data[0] + (b * h + j) * outpicref->linesize[0] + w * ch * 4; \ + const int ww = (s->counter[depth - b - 1] / (float)insamples->nb_samples) * (w - 1); \ + \ + for (int i = 0; i < ww; i++) { \ + AV_WN32(&dst[i * 4], color); \ + } \ + } \ + } \ + } - for (i = 0; i < max; i++) { - if (sample & (1U << i)) - s->counter[i]++; +#define DO_TRACE(type, depth, one) \ + for (int ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { \ + const int w = outpicref->width / inlink->ch_layout.nb_channels; \ + const type *in = (const type *)insamples->extended_data[ch]; \ + const int wb = w / depth; \ + int wv; \ + \ + memset(s->counter, 0, sizeof(s->counter)); \ + for (int i = 0; i < insamples->nb_samples; i++) { \ + for (int j = 0; j < depth; j++) { \ + if (in[i] & (one << j)) \ + s->counter[j]++; \ + } \ + } \ + \ + for (int b = 0; b < depth; b++) { \ + uint8_t colors[4]; \ + uint32_t color; \ + uint8_t *dst = outpicref->data[0] + w * ch * 4 + wb * b * 4 + \ + s->current_vpos * outpicref->linesize[0]; \ + wv = (s->counter[depth - b - 1] * 255) / insamples->nb_samples; \ + colors[0] = (wv * s->fg[ch * 4 + 0] + 127) / 255; \ + colors[1] = (wv * s->fg[ch * 4 + 1] + 127) / 255; \ + colors[2] = (wv * s->fg[ch * 4 + 2] + 127) / 255; \ + colors[3] = (wv * s->fg[ch * 4 + 3] + 127) / 255; \ + color = AV_RN32(colors); \ + \ + for (int x = 0; x < wb; x++) \ + AV_WN32(&dst[x * 4], color); \ + } \ } -} static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) { @@ -152,69 +212,50 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) AVFilterLink *outlink = ctx->outputs[0]; AudioBitScopeContext *s = ctx->priv; AVFrame *outpicref; - int ch, i, j, b; - outpicref = ff_get_video_buffer(outlink, outlink->w, outlink->h); - if (!outpicref) { - av_frame_free(&insamples); - return AVERROR(ENOMEM); + if (s->mode == 0 || !s->outpicref) { + outpicref = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!outpicref) { + av_frame_free(&insamples); + return AVERROR(ENOMEM); + } + + for (int i = 0; i < outlink->h; i++) + memset(outpicref->data[0] + i * outpicref->linesize[0], 0, outlink->w * 4); + if (!s->outpicref && s->mode == 1) + s->outpicref = outpicref; } - for (i = 0; i < outlink->h; i++) - memset(outpicref->data[0] + i * outpicref->linesize[0], 0, outlink->w * 4); + if (s->mode == 1) { + av_frame_make_writable(s->outpicref); + outpicref = av_frame_clone(s->outpicref); + if (!outpicref) + return AVERROR(ENOMEM); + } outpicref->pts = insamples->pts; outpicref->sample_aspect_ratio = (AVRational){1,1}; switch (insamples->format) { - case AV_SAMPLE_FMT_S16P: - for (ch = 0; ch < inlink->channels; ch++) { - uint16_t *in = (uint16_t *)insamples->extended_data[ch]; - int w = outpicref->width / inlink->channels; - int h = outpicref->height / 16; - uint32_t color = AV_RN32(&s->fg[4 * ch]); - - memset(s->counter, 0, sizeof(s->counter)); - for (i = 0; i < insamples->nb_samples; i++) - count_bits(s, in[i], 16); - - for (b = 0; b < 16; b++) { - for (j = 1; j < h - 1; j++) { - uint8_t *dst = outpicref->data[0] + (b * h + j) * outpicref->linesize[0] + w * ch * 4; - int ww = (s->counter[16 - b - 1] / (float)insamples->nb_samples) * (w - 1); - - for (i = 0; i < ww; i++) { - AV_WN32(&dst[i * 4], color); - } - } - } - } + case AV_SAMPLE_FMT_U8P: + if (s->mode == 0) { BARS(uint8_t, 8, 1) } else { DO_TRACE(uint8_t, 8, 1) } break; + case AV_SAMPLE_FMT_S16P: + if (s->mode == 0) { BARS(uint16_t, 16, 1) } else { DO_TRACE(uint16_t, 16, 1) } + break; + case AV_SAMPLE_FMT_FLTP: case AV_SAMPLE_FMT_S32P: - for (ch = 0; ch < inlink->channels; ch++) { - uint32_t *in = (uint32_t *)insamples->extended_data[ch]; - int w = outpicref->width / inlink->channels; - int h = outpicref->height / 32; - uint32_t color = AV_RN32(&s->fg[4 * ch]); - - memset(s->counter, 0, sizeof(s->counter)); - for (i = 0; i < insamples->nb_samples; i++) - count_bits(s, in[i], 32); - - for (b = 0; b < 32; b++) { - for (j = 1; j < h - 1; j++) { - uint8_t *dst = outpicref->data[0] + (b * h + j) * outpicref->linesize[0] + w * ch * 4; - int ww = (s->counter[32 - b - 1] / (float)insamples->nb_samples) * (w - 1); - - for (i = 0; i < ww; i++) { - AV_WN32(&dst[i * 4], color); - } - } - } - } + if (s->mode == 0) { BARS(uint32_t, 32, 1U) } else { DO_TRACE(uint32_t, 32, 1U) } + break; + case AV_SAMPLE_FMT_DBLP: + case AV_SAMPLE_FMT_S64P: + if (s->mode == 0) { BARS(uint64_t, 64, 1ULL) } else { DO_TRACE(uint64_t, 64, 1ULL) } break; } + s->current_vpos++; + if (s->current_vpos >= outlink->h) + s->current_vpos = 0; av_frame_free(&insamples); return ff_filter_frame(outlink, outpicref); @@ -242,6 +283,13 @@ static int activate(AVFilterContext *ctx) return FFERROR_NOT_READY; } +static av_cold void uninit(AVFilterContext *ctx) +{ + AudioBitScopeContext *s = ctx->priv; + + av_frame_free(&s->outpicref); +} + static const AVFilterPad inputs[] = { { .name = "default", @@ -265,6 +313,7 @@ const AVFilter ff_avf_abitscope = { FILTER_INPUTS(inputs), FILTER_OUTPUTS(outputs), FILTER_QUERY_FUNC(query_formats), + .uninit = uninit, .activate = activate, .priv_class = &abitscope_class, }; diff --git a/libavfilter/avf_ahistogram.c b/libavfilter/avf_ahistogram.c index 258b06287..d14e0bcfa 100644 --- a/libavfilter/avf_ahistogram.c +++ b/libavfilter/avf_ahistogram.c @@ -32,7 +32,7 @@ enum DisplayScale { LINEAR, SQRT, CBRT, LOG, RLOG, NB_SCALES }; enum AmplitudeScale { ALINEAR, ALOG, NB_ASCALES }; enum SlideMode { REPLACE, SCROLL, NB_SLIDES }; enum DisplayMode { SINGLE, SEPARATE, NB_DMODES }; -enum HistogramMode { ACCUMULATE, CURRENT, NB_HMODES }; +enum HistogramMode { ABS, SIGN, NB_HMODES }; typedef struct AudioHistogramContext { const AVClass *class; @@ -49,6 +49,7 @@ typedef struct AudioHistogramContext { int ypos; int slide; int dmode; + int hmode; int dchannels; int count; int frame_count; @@ -56,6 +57,8 @@ typedef struct AudioHistogramContext { AVFrame *in[101]; int first; int nb_samples; + + int (*get_bin)(float in, int w); } AudioHistogramContext; #define OFFSET(x) offsetof(AudioHistogramContext, x) @@ -83,6 +86,9 @@ static const AVOption ahistogram_options[] = { { "slide", "set sonogram sliding", OFFSET(slide), AV_OPT_TYPE_INT, {.i64=REPLACE}, 0, NB_SLIDES-1, FLAGS, "slide" }, { "replace", "replace old rows with new", 0, AV_OPT_TYPE_CONST, {.i64=REPLACE}, 0, 0, FLAGS, "slide" }, { "scroll", "scroll from top to bottom", 0, AV_OPT_TYPE_CONST, {.i64=SCROLL}, 0, 0, FLAGS, "slide" }, + { "hmode", "set histograms mode", OFFSET(hmode), AV_OPT_TYPE_INT, {.i64=ABS}, 0, NB_HMODES-1, FLAGS, "hmode" }, + { "abs", "use absolute samples", 0, AV_OPT_TYPE_CONST, {.i64=ABS}, 0, 0, FLAGS, "hmode" }, + { "sign", "use unchanged samples", 0, AV_OPT_TYPE_CONST, {.i64=SIGN},0, 0, FLAGS, "hmode" }, { NULL } }; @@ -121,7 +127,7 @@ static int config_input(AVFilterLink *inlink) AudioHistogramContext *s = ctx->priv; s->nb_samples = FFMAX(1, av_rescale(inlink->sample_rate, s->frame_rate.den, s->frame_rate.num)); - s->dchannels = s->dmode == SINGLE ? 1 : inlink->channels; + s->dchannels = s->dmode == SINGLE ? 1 : inlink->ch_layout.nb_channels; s->shistogram = av_calloc(s->w, s->dchannels * sizeof(*s->shistogram)); if (!s->shistogram) return AVERROR(ENOMEM); @@ -133,6 +139,26 @@ static int config_input(AVFilterLink *inlink) return 0; } +static int get_lin_bin_abs(float in, int w) +{ + return lrintf(av_clipf(fabsf(in), 0.f, 1.f) * (w - 1)); +} + +static int get_lin_bin_sign(float in, int w) +{ + return lrintf((1.f + av_clipf(in, -1.f, 1.f)) * 0.5f * (w - 1)); +} + +static int get_log_bin_abs(float in, int w) +{ + return lrintf(av_clipf(1.f + log10f(fabsf(in)) / 6.f, 0.f, 1.f) * (w - 1)); +} + +static int get_log_bin_sign(float in, int w) +{ + return (w / 2) + FFSIGN(in) * lrintf(av_clipf(1.f + log10f(fabsf(in)) / 6.f, 0.f, 1.f) * (w / 2)); +} + static int config_output(AVFilterLink *outlink) { AudioHistogramContext *s = outlink->src->priv; @@ -141,10 +167,32 @@ static int config_output(AVFilterLink *outlink) outlink->h = s->h; outlink->sample_aspect_ratio = (AVRational){1,1}; outlink->frame_rate = s->frame_rate; + outlink->time_base = av_inv_q(outlink->frame_rate); s->histogram_h = s->h * s->phisto; s->ypos = s->h * s->phisto; + switch (s->ascale) { + case ALINEAR: + switch (s->hmode) { + case ABS: s->get_bin = get_lin_bin_abs; break; + case SIGN: s->get_bin = get_lin_bin_sign; break; + default: + return AVERROR_BUG; + } + break; + case ALOG: + switch (s->hmode) { + case ABS: s->get_bin = get_log_bin_abs; break; + case SIGN: s->get_bin = get_log_bin_sign; break; + default: + return AVERROR_BUG; + } + break; + default: + return AVERROR_BUG; + } + if (s->dmode == SEPARATE) { s->combine_buffer = av_malloc_array(outlink->w * 3, sizeof(*s->combine_buffer)); if (!s->combine_buffer) @@ -181,6 +229,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) } } + av_frame_make_writable(s->out); if (s->dmode == SEPARATE) { for (y = 0; y < w; y++) { s->combine_buffer[3 * y ] = 0; @@ -195,18 +244,18 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) memset(s->out->data[2] + n * s->out->linesize[0], 127, w); memset(s->out->data[3] + n * s->out->linesize[0], 0, w); } - s->out->pts = in->pts; + s->out->pts = av_rescale_q(in->pts, inlink->time_base, outlink->time_base); s->first = s->frame_count; switch (s->ascale) { case ALINEAR: - for (c = 0; c < inlink->channels; c++) { + for (c = 0; c < inlink->ch_layout.nb_channels; c++) { const float *src = (const float *)in->extended_data[c]; uint64_t *achistogram = &s->achistogram[(s->dmode == SINGLE ? 0: c) * w]; for (n = 0; n < in->nb_samples; n++) { - bin = lrint(av_clipf(fabsf(src[n]), 0, 1) * (w - 1)); + bin = s->get_bin(src[n], w); achistogram[bin]++; } @@ -216,7 +265,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) const float *src2 = (const float *)s->in[s->first]->extended_data[c]; for (n = 0; n < in->nb_samples; n++) { - bin = lrint(av_clipf(fabsf(src2[n]), 0, 1) * (w - 1)); + bin = s->get_bin(src2[n], w); shistogram[bin]++; } @@ -224,12 +273,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) } break; case ALOG: - for (c = 0; c < inlink->channels; c++) { + for (c = 0; c < inlink->ch_layout.nb_channels; c++) { const float *src = (const float *)in->extended_data[c]; uint64_t *achistogram = &s->achistogram[(s->dmode == SINGLE ? 0: c) * w]; for (n = 0; n < in->nb_samples; n++) { - bin = lrint(av_clipf(1 + log10(fabsf(src[n])) / 6, 0, 1) * (w - 1)); + bin = s->get_bin(src[n], w); achistogram[bin]++; } @@ -239,7 +288,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) const float *src2 = (const float *)s->in[s->first]->extended_data[c]; for (n = 0; n < in->nb_samples; n++) { - bin = lrint(av_clipf(1 + log10(fabsf(src2[n])) / 6, 0, 1) * (w - 1)); + bin = s->get_bin(src2[n], w); shistogram[bin]++; } @@ -264,7 +313,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) float yf, uf, vf; if (s->dmode == SEPARATE) { - yf = 256.0f / s->dchannels; + yf = 255.0f / s->dchannels; uf = yf * M_PI; vf = yf * M_PI; uf *= 0.5 * sin((2 * M_PI * c) / s->dchannels); @@ -311,7 +360,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) if (s->h - H > 0) { h = aa * 255; - s->out->data[0][s->ypos * s->out->linesize[0] + n] = h; + s->out->data[0][s->ypos * s->out->linesize[0] + n] = av_clip_uint8(h); s->out->data[1][s->ypos * s->out->linesize[1] + n] = 127; s->out->data[2][s->ypos * s->out->linesize[2] + n] = 127; s->out->data[3][s->ypos * s->out->linesize[3] + n] = 255; @@ -325,9 +374,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) if (s->out->data[0][y * s->out->linesize[0] + n] != old) break; old = s->out->data[0][y * s->out->linesize[0] + n]; - s->out->data[0][y * s->out->linesize[0] + n] = yf; - s->out->data[1][y * s->out->linesize[1] + n] = 128+uf; - s->out->data[2][y * s->out->linesize[2] + n] = 128+vf; + s->out->data[0][y * s->out->linesize[0] + n] = av_clip_uint8(yf); + s->out->data[1][y * s->out->linesize[1] + n] = av_clip_uint8(128.f+uf); + s->out->data[2][y * s->out->linesize[2] + n] = av_clip_uint8(128.f+vf); s->out->data[3][y * s->out->linesize[3] + n] = 255; } @@ -352,7 +401,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) if (s->slide == SCROLL) { for (p = 0; p < 4; p++) { - for (y = s->h; y >= H + 1; y--) { + for (y = s->h - 1; y >= H + 1; y--) { memmove(s->out->data[p] + (y ) * s->out->linesize[p], s->out->data[p] + (y-1) * s->out->linesize[p], w); } @@ -387,6 +436,11 @@ static int activate(AVFilterContext *ctx) if (ret > 0) return filter_frame(inlink, in); + if (ff_inlink_queued_samples(inlink) >= s->nb_samples) { + ff_filter_set_ready(ctx, 10); + return 0; + } + FF_FILTER_FORWARD_STATUS(inlink, outlink); FF_FILTER_FORWARD_WANTED(outlink, inlink); diff --git a/libavfilter/avf_aphasemeter.c b/libavfilter/avf_aphasemeter.c index d9302cf86..3501e6282 100644 --- a/libavfilter/avf_aphasemeter.c +++ b/libavfilter/avf_aphasemeter.c @@ -101,7 +101,7 @@ static int query_formats(AVFilterContext *ctx) formats = ff_make_format_list(sample_fmts); if ((ret = ff_formats_ref (formats, &inlink->outcfg.formats )) < 0 || (ret = ff_formats_ref (formats, &outlink->incfg.formats )) < 0 || - (ret = ff_add_channel_layout (&layout, AV_CH_LAYOUT_STEREO )) < 0 || + (ret = ff_add_channel_layout (&layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO )) < 0 || (ret = ff_channel_layouts_ref (layout , &inlink->outcfg.channel_layouts)) < 0 || (ret = ff_channel_layouts_ref (layout , &outlink->incfg.channel_layouts)) < 0) return ret; @@ -266,6 +266,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) memset(out->data[0] + i * out->linesize[0], 0, outlink->w * 4); } else if (s->do_video) { out = s->out; + av_frame_make_writable(s->out); for (i = outlink->h - 1; i >= 10; i--) memmove(out->data[0] + (i ) * out->linesize[0], out->data[0] + (i-1) * out->linesize[0], diff --git a/libavfilter/avf_avectorscope.c b/libavfilter/avf_avectorscope.c index ba392153f..fe381a631 100644 --- a/libavfilter/avf_avectorscope.c +++ b/libavfilter/avf_avectorscope.c @@ -207,7 +207,7 @@ static int query_formats(AVFilterContext *ctx) formats = ff_make_format_list(sample_fmts); if ((ret = ff_formats_ref (formats, &inlink->outcfg.formats )) < 0 || - (ret = ff_add_channel_layout (&layout, AV_CH_LAYOUT_STEREO )) < 0 || + (ret = ff_add_channel_layout (&layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO)) < 0 || (ret = ff_channel_layouts_ref (layout , &inlink->outcfg.channel_layouts)) < 0) return ret; @@ -240,6 +240,7 @@ static int config_output(AVFilterLink *outlink) outlink->h = s->h; outlink->sample_aspect_ratio = (AVRational){1,1}; outlink->frame_rate = s->frame_rate; + outlink->time_base = av_inv_q(outlink->frame_rate); s->prev_x = s->hw = s->w / 2; s->prev_y = s->hh = s->mode == POLAR ? s->h - 1 : s->h / 2; @@ -273,8 +274,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) for (i = 0; i < outlink->h; i++) memset(s->outpicref->data[0] + i * s->outpicref->linesize[0], 0, outlink->w * 4); } - s->outpicref->pts = insamples->pts; + s->outpicref->pts = av_rescale_q(insamples->pts, inlink->time_base, outlink->time_base); + av_frame_make_writable(s->outpicref); ff_filter_execute(ctx, fade, NULL, NULL, FFMIN(outlink->h, ff_filter_get_nb_threads(ctx))); if (zoom < 1) { @@ -412,6 +414,11 @@ static int activate(AVFilterContext *ctx) if (ret > 0) return filter_frame(inlink, in); + if (ff_inlink_queued_samples(inlink) >= s->nb_samples) { + ff_filter_set_ready(ctx, 10); + return 0; + } + FF_FILTER_FORWARD_STATUS(inlink, outlink); FF_FILTER_FORWARD_WANTED(outlink, inlink); diff --git a/libavfilter/avf_concat.c b/libavfilter/avf_concat.c index 84c2a5209..c85c17b51 100644 --- a/libavfilter/avf_concat.c +++ b/libavfilter/avf_concat.c @@ -263,7 +263,7 @@ static int send_silence(AVFilterContext *ctx, unsigned in_no, unsigned out_no, if (!buf) return AVERROR(ENOMEM); av_samples_set_silence(buf->extended_data, 0, frame_nb_samples, - outlink->channels, outlink->format); + outlink->ch_layout.nb_channels, outlink->format); buf->pts = base_pts + av_rescale_q(sent, rate_tb, outlink->time_base); ret = ff_filter_frame(outlink, buf); if (ret < 0) diff --git a/libavfilter/avf_showcqt.c b/libavfilter/avf_showcqt.c index 6f63574a8..33c482bd4 100644 --- a/libavfilter/avf_showcqt.c +++ b/libavfilter/avf_showcqt.c @@ -1325,7 +1325,8 @@ static int query_formats(AVFilterContext *ctx) AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_RGB24, AV_PIX_FMT_NONE }; - static const int64_t channel_layouts[] = { AV_CH_LAYOUT_STEREO, AV_CH_LAYOUT_STEREO_DOWNMIX, -1 }; + static const AVChannelLayout channel_layouts[] = { AV_CHANNEL_LAYOUT_STEREO, + AV_CHANNEL_LAYOUT_STEREO_DOWNMIX, { 0 } }; int ret; /* set input audio formats */ @@ -1333,7 +1334,7 @@ static int query_formats(AVFilterContext *ctx) if ((ret = ff_formats_ref(formats, &inlink->outcfg.formats)) < 0) return ret; - layouts = ff_make_format64_list(channel_layouts); + layouts = ff_make_channel_layout_list(channel_layouts); if ((ret = ff_channel_layouts_ref(layouts, &inlink->outcfg.channel_layouts)) < 0) return ret; @@ -1417,8 +1418,9 @@ static int config_output(AVFilterLink *outlink) s->update_sono = update_sono_yuv; } - if (ARCH_X86) - ff_showcqt_init_x86(s); +#if ARCH_X86 + ff_showcqt_init_x86(s); +#endif if ((ret = init_cqt(s)) < 0) return ret; diff --git a/libavfilter/avf_showfreqs.c b/libavfilter/avf_showfreqs.c index 08dbce53c..86a67c732 100644 --- a/libavfilter/avf_showfreqs.c +++ b/libavfilter/avf_showfreqs.c @@ -22,7 +22,6 @@ #include #include "libavutil/tx.h" -#include "libavutil/audio_fifo.h" #include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/channel_layout.h" @@ -52,22 +51,28 @@ typedef struct ShowFreqsContext { int ascale, fscale; int avg; int win_func; + char *ch_layout_str; + uint8_t *bypass; + AVChannelLayout ch_layout; AVTXContext *fft; av_tx_fn tx_fn; AVComplexFloat **fft_input; AVComplexFloat **fft_data; + AVFrame *window; float **avg_data; float *window_func_lut; float overlap; float minamp; int hop_size; int nb_channels; + int nb_draw_channels; int nb_freq; int win_size; float scale; char *colors; - AVAudioFifo *fifo; int64_t pts; + int64_t old_pts; + AVRational frame_rate; } ShowFreqsContext; #define OFFSET(x) offsetof(ShowFreqsContext, x) @@ -76,6 +81,8 @@ typedef struct ShowFreqsContext { static const AVOption showfreqs_options[] = { { "size", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "1024x512"}, 0, 0, FLAGS }, { "s", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "1024x512"}, 0, 0, FLAGS }, + { "rate", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, FLAGS }, + { "r", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, FLAGS }, { "mode", "set display mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=BAR}, 0, NB_MODES-1, FLAGS, "mode" }, { "line", "show lines", 0, AV_OPT_TYPE_CONST, {.i64=LINE}, 0, 0, FLAGS, "mode" }, { "bar", "show bars", 0, AV_OPT_TYPE_CONST, {.i64=BAR}, 0, 0, FLAGS, "mode" }, @@ -102,6 +109,7 @@ static const AVOption showfreqs_options[] = { { "magnitude", "show magnitude", 0, AV_OPT_TYPE_CONST, {.i64=MAGNITUDE}, 0, 0, FLAGS, "data" }, { "phase", "show phase", 0, AV_OPT_TYPE_CONST, {.i64=PHASE}, 0, 0, FLAGS, "data" }, { "delay", "show group delay",0, AV_OPT_TYPE_CONST, {.i64=DELAY}, 0, 0, FLAGS, "data" }, + { "channels", "set channels to draw", OFFSET(ch_layout_str), AV_OPT_TYPE_STRING, {.str="all"}, 0, 0, FLAGS }, { NULL } }; @@ -122,7 +130,7 @@ static int query_formats(AVFilterContext *ctx) if ((ret = ff_formats_ref(formats, &inlink->outcfg.formats)) < 0) return ret; - layouts = ff_all_channel_layouts(); + layouts = ff_all_channel_counts(); if ((ret = ff_channel_layouts_ref(layouts, &inlink->outcfg.channel_layouts)) < 0) return ret; @@ -138,15 +146,6 @@ static int query_formats(AVFilterContext *ctx) return 0; } -static av_cold int init(AVFilterContext *ctx) -{ - ShowFreqsContext *s = ctx->priv; - - s->pts = AV_NOPTS_VALUE; - - return 0; -} - static int config_output(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; @@ -155,9 +154,9 @@ static int config_output(AVFilterLink *outlink) float overlap, scale; int i, ret; + s->old_pts = AV_NOPTS_VALUE; s->nb_freq = s->fft_size / 2; s->win_size = s->fft_size; - av_audio_fifo_free(s->fifo); av_tx_uninit(&s->fft); ret = av_tx_init(&s->fft, &s->tx_fn, AV_TX_FLOAT_FFT, 0, s->fft_size, &scale, 0); if (ret < 0) { @@ -174,11 +173,15 @@ static int config_output(AVFilterLink *outlink) av_freep(&s->fft_data[i]); av_freep(&s->avg_data[i]); } + av_freep(&s->bypass); av_freep(&s->fft_input); av_freep(&s->fft_data); av_freep(&s->avg_data); - s->nb_channels = inlink->channels; + s->nb_channels = inlink->ch_layout.nb_channels; + s->bypass = av_calloc(s->nb_channels, sizeof(*s->bypass)); + if (!s->bypass) + return AVERROR(ENOMEM); s->fft_input = av_calloc(s->nb_channels, sizeof(*s->fft_input)); if (!s->fft_input) return AVERROR(ENOMEM); @@ -214,14 +217,36 @@ static int config_output(AVFilterLink *outlink) s->scale += s->window_func_lut[i] * s->window_func_lut[i]; } - outlink->frame_rate = av_make_q(inlink->sample_rate, s->win_size * (1.-s->overlap)); + s->window = ff_get_audio_buffer(inlink, s->win_size * 2); + if (!s->window) + return AVERROR(ENOMEM); + + outlink->frame_rate = s->frame_rate; + outlink->time_base = av_inv_q(outlink->frame_rate); outlink->sample_aspect_ratio = (AVRational){1,1}; outlink->w = s->w; outlink->h = s->h; - s->fifo = av_audio_fifo_alloc(inlink->format, inlink->channels, s->win_size); - if (!s->fifo) - return AVERROR(ENOMEM); + ret = av_channel_layout_copy(&s->ch_layout, &inlink->ch_layout); + if (ret < 0) + return ret; + s->nb_draw_channels = s->nb_channels; + + if (strcmp(s->ch_layout_str, "all")) { + int nb_draw_channels = 0; + av_channel_layout_from_string(&s->ch_layout, + s->ch_layout_str); + + for (int ch = 0; ch < s->nb_channels; ch++) { + const enum AVChannel channel = av_channel_layout_channel_from_index(&inlink->ch_layout, ch); + + s->bypass[ch] = av_channel_layout_index_from_channel(&s->ch_layout, channel) < 0; + nb_draw_channels += s->bypass[ch] == 0; + } + + s->nb_draw_channels = nb_draw_channels; + } + return 0; } @@ -298,8 +323,8 @@ static inline void plot_freq(ShowFreqsContext *s, int ch, y = a * outlink->h - 1; break; case SEPARATE: - end = (outlink->h / s->nb_channels) * (ch + 1); - y = (outlink->h / s->nb_channels) * ch + a * (outlink->h / s->nb_channels) - 1; + end = (outlink->h / s->nb_draw_channels) * (ch + 1); + y = (outlink->h / s->nb_draw_channels) * ch + a * (outlink->h / s->nb_draw_channels) - 1; break; default: av_assert0(0); @@ -309,13 +334,13 @@ static inline void plot_freq(ShowFreqsContext *s, int ch, switch (s->avg) { case 0: - y = s->avg_data[ch][f] = !outlink->frame_count_in ? y : FFMIN(avg, y); + y = s->avg_data[ch][f] = !outlink->frame_count_in ? y : FFMIN(0, y); break; case 1: break; default: - s->avg_data[ch][f] = avg + y * (y - avg) / (FFMIN(outlink->frame_count_in + 1, s->avg) * y); - y = s->avg_data[ch][f]; + s->avg_data[ch][f] = avg + y * (y - avg) / (FFMIN(outlink->frame_count_in + 1, s->avg) * (float)y); + y = av_clip(s->avg_data[ch][f], 0, outlink->h - 1); break; } @@ -349,53 +374,61 @@ static inline void plot_freq(ShowFreqsContext *s, int ch, } } -static int plot_freqs(AVFilterLink *inlink, AVFrame *in) +static int plot_freqs(AVFilterLink *inlink, int64_t pts) { AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; ShowFreqsContext *s = ctx->priv; + AVFrame *in = s->window; const int win_size = s->win_size; char *colors, *color, *saveptr = NULL; AVFrame *out; int ch, n; - out = ff_get_video_buffer(outlink, outlink->w, outlink->h); - if (!out) - return AVERROR(ENOMEM); - - for (n = 0; n < outlink->h; n++) - memset(out->data[0] + out->linesize[0] * n, 0, outlink->w * 4); - /* fill FFT input with the number of samples available */ for (ch = 0; ch < s->nb_channels; ch++) { const float *p = (float *)in->extended_data[ch]; - for (n = 0; n < in->nb_samples; n++) { + if (s->bypass[ch]) + continue; + + for (n = 0; n < win_size; n++) { s->fft_input[ch][n].re = p[n] * s->window_func_lut[n]; s->fft_input[ch][n].im = 0; } - for (; n < win_size; n++) { - s->fft_input[ch][n].re = 0; - s->fft_input[ch][n].im = 0; - } } /* run FFT on each samples set */ for (ch = 0; ch < s->nb_channels; ch++) { + if (s->bypass[ch]) + continue; + s->tx_fn(s->fft, s->fft_data[ch], s->fft_input[ch], sizeof(float)); } + s->pts = av_rescale_q(pts, inlink->time_base, outlink->time_base); + if (s->old_pts >= s->pts) + return 0; + s->old_pts = s->pts; + #define RE(x, ch) s->fft_data[ch][x].re #define IM(x, ch) s->fft_data[ch][x].im #define M(a, b) (sqrt((a) * (a) + (b) * (b))) #define P(a, b) (atan2((b), (a))) colors = av_strdup(s->colors); - if (!colors) { - av_frame_free(&out); + if (!colors) + return AVERROR(ENOMEM); + + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) { + av_free(colors); return AVERROR(ENOMEM); } + for (n = 0; n < outlink->h; n++) + memset(out->data[0] + out->linesize[0] * n, 0, outlink->w * 4); + for (ch = 0; ch < s->nb_channels; ch++) { uint8_t fg[4] = { 0xff, 0xff, 0xff, 0xff }; int prev_y = -1, f; @@ -405,31 +438,26 @@ static int plot_freqs(AVFilterLink *inlink, AVFrame *in) if (color) av_parse_color(fg, color, -1, ctx); + if (s->bypass[ch]) + continue; + switch (s->data_mode) { case MAGNITUDE: - a = av_clipd(M(RE(0, ch), 0) / s->scale, 0, 1); - plot_freq(s, ch, a, 0, fg, &prev_y, out, outlink); - - for (f = 1; f < s->nb_freq; f++) { + for (f = 0; f < s->nb_freq; f++) { a = av_clipd(M(RE(f, ch), IM(f, ch)) / s->scale, 0, 1); plot_freq(s, ch, a, f, fg, &prev_y, out, outlink); } break; case PHASE: - a = av_clipd((M_PI + P(RE(0, ch), 0)) / (2. * M_PI), 0, 1); - plot_freq(s, ch, a, 0, fg, &prev_y, out, outlink); - - for (f = 1; f < s->nb_freq; f++) { + for (f = 0; f < s->nb_freq; f++) { a = av_clipd((M_PI + P(RE(f, ch), IM(f, ch))) / (2. * M_PI), 0, 1); plot_freq(s, ch, a, f, fg, &prev_y, out, outlink); } break; case DELAY: - plot_freq(s, ch, 0, 0, fg, &prev_y, out, outlink); - - for (f = 1; f < s->nb_freq; f++) { + for (f = 0; f < s->nb_freq; f++) { a = av_clipd((M_PI - P(IM(f, ch) * RE(f-1, ch) - IM(f-1, ch) * RE(f, ch), RE(f, ch) * RE(f-1, ch) + IM(f, ch) * IM(f-1, ch))) / (2. * M_PI), 0, 1); @@ -440,37 +468,29 @@ static int plot_freqs(AVFilterLink *inlink, AVFrame *in) } av_free(colors); - out->pts = in->pts; + out->pts = s->pts; out->sample_aspect_ratio = (AVRational){1,1}; return ff_filter_frame(outlink, out); } -static int filter_frame(AVFilterLink *inlink) +static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; ShowFreqsContext *s = ctx->priv; - AVFrame *fin = NULL; - int ret = 0; + const int offset = s->win_size - s->hop_size; + int64_t pts = in->pts; - fin = ff_get_audio_buffer(inlink, s->win_size); - if (!fin) { - ret = AVERROR(ENOMEM); - goto fail; + for (int ch = 0; ch < in->ch_layout.nb_channels; ch++) { + float *dst = (float *)s->window->extended_data[ch]; + + memmove(dst, &dst[s->hop_size], offset * sizeof(float)); + memcpy(&dst[offset], in->extended_data[ch], in->nb_samples * sizeof(float)); + memset(&dst[offset + in->nb_samples], 0, (s->hop_size - in->nb_samples) * sizeof(float)); } - fin->pts = s->pts; - s->pts += s->hop_size; - ret = av_audio_fifo_peek(s->fifo, (void **)fin->extended_data, s->win_size); - if (ret < 0) - goto fail; + av_frame_free(&in); - ret = plot_freqs(inlink, fin); - av_frame_free(&fin); - av_audio_fifo_drain(s->fifo, s->hop_size); - -fail: - av_frame_free(&fin); - return ret; + return plot_freqs(inlink, pts); } static int activate(AVFilterContext *ctx) @@ -478,26 +498,23 @@ static int activate(AVFilterContext *ctx) AVFilterLink *inlink = ctx->inputs[0]; AVFilterLink *outlink = ctx->outputs[0]; ShowFreqsContext *s = ctx->priv; - AVFrame *in = NULL; - int ret = 0; + AVFrame *in; + int ret; FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); - if (av_audio_fifo_size(s->fifo) < s->win_size) - ret = ff_inlink_consume_samples(inlink, s->win_size, s->win_size, &in); + ret = ff_inlink_consume_samples(inlink, s->hop_size, s->hop_size, &in); if (ret < 0) return ret; - if (ret > 0) { - av_audio_fifo_write(s->fifo, (void **)in->extended_data, in->nb_samples); - if (s->pts == AV_NOPTS_VALUE) - s->pts = in->pts; - av_frame_free(&in); - } - if (av_audio_fifo_size(s->fifo) >= s->win_size) { - ret = filter_frame(inlink); - if (ret <= 0) - return ret; + if (ret > 0) + ret = filter_frame(inlink, in); + if (ret < 0) + return ret; + + if (ff_inlink_queued_samples(inlink) >= s->hop_size) { + ff_filter_set_ready(ctx, 10); + return 0; } FF_FILTER_FORWARD_STATUS(inlink, outlink); @@ -511,6 +528,7 @@ static av_cold void uninit(AVFilterContext *ctx) ShowFreqsContext *s = ctx->priv; int i; + av_channel_layout_uninit(&s->ch_layout); av_tx_uninit(&s->fft); for (i = 0; i < s->nb_channels; i++) { if (s->fft_input) @@ -520,11 +538,12 @@ static av_cold void uninit(AVFilterContext *ctx) if (s->avg_data) av_freep(&s->avg_data[i]); } + av_freep(&s->bypass); av_freep(&s->fft_input); av_freep(&s->fft_data); av_freep(&s->avg_data); av_freep(&s->window_func_lut); - av_audio_fifo_free(s->fifo); + av_frame_free(&s->window); } static const AVFilterPad showfreqs_inputs[] = { @@ -545,7 +564,6 @@ static const AVFilterPad showfreqs_outputs[] = { const AVFilter ff_avf_showfreqs = { .name = "showfreqs", .description = NULL_IF_CONFIG_SMALL("Convert input audio to a frequencies video output."), - .init = init, .uninit = uninit, .priv_size = sizeof(ShowFreqsContext), .activate = activate, diff --git a/libavfilter/avf_showspatial.c b/libavfilter/avf_showspatial.c index 64e520483..780762854 100644 --- a/libavfilter/avf_showspatial.c +++ b/libavfilter/avf_showspatial.c @@ -94,7 +94,7 @@ static int query_formats(AVFilterContext *ctx) formats = ff_make_format_list(sample_fmts); if ((ret = ff_formats_ref (formats, &inlink->outcfg.formats )) < 0 || - (ret = ff_add_channel_layout (&layout, AV_CH_LAYOUT_STEREO )) < 0 || + (ret = ff_add_channel_layout (&layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO)) < 0 || (ret = ff_channel_layouts_ref (layout , &inlink->outcfg.channel_layouts)) < 0) return ret; @@ -190,7 +190,7 @@ static int config_output(AVFilterLink *outlink) outlink->time_base = av_inv_q(outlink->frame_rate); av_audio_fifo_free(s->fifo); - s->fifo = av_audio_fifo_alloc(inlink->format, inlink->channels, s->win_size); + s->fifo = av_audio_fifo_alloc(inlink->format, inlink->ch_layout.nb_channels, s->win_size); if (!s->fifo) return AVERROR(ENOMEM); return 0; diff --git a/libavfilter/avf_showspectrum.c b/libavfilter/avf_showspectrum.c index 74d2dd758..b11147111 100644 --- a/libavfilter/avf_showspectrum.c +++ b/libavfilter/avf_showspectrum.c @@ -26,11 +26,12 @@ * (by Michael Niedermayer) and lavfi/avf_showwaves (by Stefano Sabatini). */ +#include "config_components.h" + #include #include #include "libavutil/tx.h" -#include "libavutil/audio_fifo.h" #include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/channel_layout.h" @@ -53,6 +54,8 @@ enum ColorMode { CHANNEL, INTENSITY, RAINBOW, MORELAND, NEBULAE, FIRE, FIERY, enum SlideMode { REPLACE, SCROLL, FULLFRAME, RSCROLL, LREPLACE, NB_SLIDES }; enum Orientation { VERTICAL, HORIZONTAL, NB_ORIENTATIONS }; +#define DEFAULT_LENGTH 300 + typedef struct ShowSpectrumContext { const AVClass *class; int w, h; @@ -60,6 +63,7 @@ typedef struct ShowSpectrumContext { AVRational auto_frame_rate; AVRational frame_rate; AVFrame *outpicref; + AVFrame *in_frame; int nb_display_channels; int orientation; int channel_width; @@ -91,20 +95,26 @@ typedef struct ShowSpectrumContext { double win_scale; float overlap; float gain; - int consumed; int hop_size; - float *combine_buffer; ///< color combining buffer (3 * h items) - float **color_buffer; ///< color buffer (3 * h * ch items) - AVAudioFifo *fifo; + float *combine_buffer; ///< color combining buffer (4 * h items) + float **color_buffer; ///< color buffer (4 * h * ch items) int64_t pts; int64_t old_pts; + int64_t in_pts; int old_len; int single_pic; int legend; int start_x, start_y; float drange, limit; float dmin, dmax; + uint64_t samples; int (*plot_channel)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); + + float opacity_factor; + + AVFrame **frames; + unsigned int nb_frames; + unsigned int frames_size; } ShowSpectrumContext; #define OFFSET(x) offsetof(ShowSpectrumContext, x) @@ -166,6 +176,7 @@ static const AVOption showspectrum_options[] = { { "legend", "draw legend", OFFSET(legend), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS }, { "drange", "set dynamic range in dBFS", OFFSET(drange), AV_OPT_TYPE_FLOAT, {.dbl = 120}, 10, 200, FLAGS }, { "limit", "set upper limit in dBFS", OFFSET(limit), AV_OPT_TYPE_FLOAT, {.dbl = 0}, -100, 100, FLAGS }, + { "opacity", "set opacity strength", OFFSET(opacity_factor), AV_OPT_TYPE_FLOAT, {.dbl = 1}, 0, 10, FLAGS }, { NULL } }; @@ -330,12 +341,19 @@ static av_cold void uninit(AVFilterContext *ctx) } av_freep(&s->magnitudes); av_frame_free(&s->outpicref); - av_audio_fifo_free(s->fifo); + av_frame_free(&s->in_frame); if (s->phases) { for (i = 0; i < s->nb_display_channels; i++) av_freep(&s->phases[i]); } av_freep(&s->phases); + + while (s->nb_frames > 0) { + av_frame_free(&s->frames[s->nb_frames - 1]); + s->nb_frames--; + } + + av_freep(&s->frames); } static int query_formats(AVFilterContext *ctx) @@ -345,7 +363,7 @@ static int query_formats(AVFilterContext *ctx) AVFilterLink *inlink = ctx->inputs[0]; AVFilterLink *outlink = ctx->outputs[0]; static const enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }; - static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_NONE }; + static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVA444P, AV_PIX_FMT_NONE }; int ret; /* set input audio formats */ @@ -353,7 +371,7 @@ static int query_formats(AVFilterContext *ctx) if ((ret = ff_formats_ref(formats, &inlink->outcfg.formats)) < 0) return ret; - layouts = ff_all_channel_layouts(); + layouts = ff_all_channel_counts(); if ((ret = ff_channel_layouts_ref(layouts, &inlink->outcfg.channel_layouts)) < 0) return ret; @@ -380,6 +398,13 @@ static int run_channel_fft(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo /* fill FFT input with the number of samples available */ const float *p = (float *)fin->extended_data[ch]; + float *in_frame = (float *)s->in_frame->extended_data[ch]; + + memmove(in_frame, in_frame + s->hop_size, (s->fft_size - s->hop_size) * sizeof(float)); + memcpy(in_frame + s->fft_size - s->hop_size, p, fin->nb_samples * sizeof(float)); + + for (int i = fin->nb_samples; i < s->hop_size; i++) + in_frame[i + s->fft_size - s->hop_size] = 0.f; if (s->stop) { float theta, phi, psi, a, b, S, c; @@ -391,7 +416,7 @@ static int run_channel_fft(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo int M = s->win_size / 2; for (n = 0; n < s->win_size; n++) { - s->fft_data[ch][n].re = p[n] * window_func_lut[n]; + s->fft_data[ch][n].re = in_frame[n] * window_func_lut[n]; s->fft_data[ch][n].im = 0; } @@ -458,7 +483,7 @@ static int run_channel_fft(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo } } else { for (n = 0; n < s->win_size; n++) { - s->fft_in[ch][n].re = p[n] * window_func_lut[n]; + s->fft_in[ch][n].re = in_frame[n] * window_func_lut[n]; s->fft_in[ch][n].im = 0; } @@ -473,11 +498,10 @@ static void drawtext(AVFrame *pic, int x, int y, const char *txt, int o) { const uint8_t *font; int font_height; - int i; font = avpriv_cga_font, font_height = 8; - for (i = 0; txt[i]; i++) { + for (int i = 0; txt[i]; i++) { int char_y, mask; if (o) { @@ -501,6 +525,28 @@ static void drawtext(AVFrame *pic, int x, int y, const char *txt, int o) } } } + + for (int i = 0; txt[i] && pic->data[3]; i++) { + int char_y, mask; + + if (o) { + for (char_y = font_height - 1; char_y >= 0; char_y--) { + uint8_t *p = pic->data[3] + (y + i * 10) * pic->linesize[3] + x; + for (mask = 0x80; mask; mask >>= 1) { + for (int k = 0; k < 8; k++) + p[k] = 255; + p += pic->linesize[3]; + } + } + } else { + uint8_t *p = pic->data[3] + y*pic->linesize[3] + (x + i*8); + for (char_y = 0; char_y < font_height; char_y++) { + for (mask = 0x80; mask; mask >>= 1) + *p++ = 255; + p += pic->linesize[3] - 8; + } + } + } } static void color_range(ShowSpectrumContext *s, int ch, @@ -569,6 +615,8 @@ static void pick_color(ShowSpectrumContext *s, float yf, float uf, float vf, float a, float *out) { + const float af = s->opacity_factor * 255.f; + if (s->color_mode > CHANNEL) { const int cm = s->color_mode; float y, u, v; @@ -602,10 +650,12 @@ static void pick_color(ShowSpectrumContext *s, out[0] = y * yf; out[1] = u * uf; out[2] = v * vf; + out[3] = a * af; } else { out[0] = a * yf; out[1] = a * uf; out[2] = a * vf; + out[3] = a * af; } } @@ -726,7 +776,7 @@ static float get_iscale(AVFilterContext *ctx, int scale, float a) return a; } -static int draw_legend(AVFilterContext *ctx, int samples) +static int draw_legend(AVFilterContext *ctx, uint64_t samples) { ShowSpectrumContext *s = ctx->priv; AVFilterLink *inlink = ctx->inputs[0]; @@ -738,8 +788,7 @@ static int draw_legend(AVFilterContext *ctx, int samples) uint8_t *dst; char chlayout_str[128]; - av_get_channel_layout_string(chlayout_str, sizeof(chlayout_str), inlink->channels, - inlink->channel_layout); + av_channel_layout_describe(&inlink->ch_layout, chlayout_str, sizeof(chlayout_str)); text = av_asprintf("%d Hz | %s", inlink->sample_rate, chlayout_str); if (!text) @@ -886,23 +935,26 @@ static int draw_legend(AVFilterContext *ctx, int samples) int h = multi ? s->h / s->nb_display_channels : s->h; for (y = 0; y < h; y++) { - float out[3] = { 0., 127.5, 127.5}; + float out[4] = { 0., 127.5, 127.5, 0.f}; int chn; for (chn = 0; chn < (s->mode == SEPARATE ? 1 : s->nb_display_channels); chn++) { float yf, uf, vf; int channel = (multi) ? s->nb_display_channels - ch - 1 : chn; - float lout[3]; + float lout[4]; color_range(s, channel, &yf, &uf, &vf); pick_color(s, yf, uf, vf, y / (float)h, lout); out[0] += lout[0]; out[1] += lout[1]; out[2] += lout[2]; + out[3] += lout[3]; } memset(s->outpicref->data[0]+(s->start_y + h * (ch + 1) - y - 1) * s->outpicref->linesize[0] + s->w + s->start_x + 20, av_clip_uint8(out[0]), 10); memset(s->outpicref->data[1]+(s->start_y + h * (ch + 1) - y - 1) * s->outpicref->linesize[1] + s->w + s->start_x + 20, av_clip_uint8(out[1]), 10); memset(s->outpicref->data[2]+(s->start_y + h * (ch + 1) - y - 1) * s->outpicref->linesize[2] + s->w + s->start_x + 20, av_clip_uint8(out[2]), 10); + if (s->outpicref->data[3]) + memset(s->outpicref->data[3]+(s->start_y + h * (ch + 1) - y - 1) * s->outpicref->linesize[3] + s->w + s->start_x + 20, av_clip_uint8(out[3]), 10); } for (y = 0; ch == 0 && y < h + 5; y += 25) { @@ -964,7 +1016,7 @@ static int plot_channel_lin(AVFilterContext *ctx, void *arg, int jobnr, int nb_j /* draw the channel */ for (y = 0; y < h; y++) { int row = (s->mode == COMBINED) ? y : ch * h + y; - float *out = &s->color_buffer[ch][3 * row]; + float *out = &s->color_buffer[ch][4 * row]; float a = get_value(ctx, ch, y); pick_color(s, yf, uf, vf, a, out); @@ -995,7 +1047,7 @@ static int plot_channel_log(AVFilterContext *ctx, void *arg, int jobnr, int nb_j a1 = get_value(ctx, ch, av_clip(pos+1, 0, h-1)); { int row = (s->mode == COMBINED) ? yy : ch * h + yy; - float *out = &s->color_buffer[ch][3 * row]; + float *out = &s->color_buffer[ch][4 * row]; pick_color(s, yf, uf, vf, delta * a1 + (1.f - delta) * a0, out); } @@ -1012,6 +1064,7 @@ static int config_output(AVFilterLink *outlink) int i, fft_size, h, w, ret; float overlap; + s->old_pts = AV_NOPTS_VALUE; s->dmax = expf(s->limit * M_LN10 / 20.f); s->dmin = expf((s->limit - s->drange) * M_LN10 / 20.f); @@ -1041,8 +1094,8 @@ static int config_output(AVFilterLink *outlink) outlink->h += s->start_y * 2; } - h = (s->mode == COMBINED || s->orientation == HORIZONTAL) ? s->h : s->h / inlink->channels; - w = (s->mode == COMBINED || s->orientation == VERTICAL) ? s->w : s->w / inlink->channels; + h = (s->mode == COMBINED || s->orientation == HORIZONTAL) ? s->h : s->h / inlink->ch_layout.nb_channels; + w = (s->mode == COMBINED || s->orientation == VERTICAL) ? s->w : s->w / inlink->ch_layout.nb_channels; s->channel_height = h; s->channel_width = w; @@ -1058,14 +1111,14 @@ static int config_output(AVFilterLink *outlink) s->buf_size = FFALIGN(s->win_size << (!!s->stop), av_cpu_max_align()); if (!s->fft) { - s->fft = av_calloc(inlink->channels, sizeof(*s->fft)); + s->fft = av_calloc(inlink->ch_layout.nb_channels, sizeof(*s->fft)); if (!s->fft) return AVERROR(ENOMEM); } if (s->stop) { if (!s->ifft) { - s->ifft = av_calloc(inlink->channels, sizeof(*s->ifft)); + s->ifft = av_calloc(inlink->ch_layout.nb_channels, sizeof(*s->ifft)); if (!s->ifft) return AVERROR(ENOMEM); } @@ -1091,7 +1144,7 @@ static int config_output(AVFilterLink *outlink) } av_freep(&s->fft_data); - s->nb_display_channels = inlink->channels; + s->nb_display_channels = inlink->ch_layout.nb_channels; for (i = 0; i < s->nb_display_channels; i++) { float scale; @@ -1134,7 +1187,7 @@ static int config_output(AVFilterLink *outlink) if (!s->color_buffer) return AVERROR(ENOMEM); for (i = 0; i < s->nb_display_channels; i++) { - s->color_buffer[i] = av_calloc(s->orientation == VERTICAL ? s->h * 3 : s->w * 3, sizeof(**s->color_buffer)); + s->color_buffer[i] = av_calloc(s->orientation == VERTICAL ? s->h * 4 : s->w * 4, sizeof(**s->color_buffer)); if (!s->color_buffer[i]) return AVERROR(ENOMEM); } @@ -1193,6 +1246,8 @@ static int config_output(AVFilterLink *outlink) memset(outpicref->data[0] + i * outpicref->linesize[0], 0, outlink->w); memset(outpicref->data[1] + i * outpicref->linesize[1], 128, outlink->w); memset(outpicref->data[2] + i * outpicref->linesize[2], 128, outlink->w); + if (outpicref->data[3]) + memset(outpicref->data[3] + i * outpicref->linesize[3], 0, outlink->w); } outpicref->color_range = AVCOL_RANGE_JPEG; @@ -1220,6 +1275,8 @@ static int config_output(AVFilterLink *outlink) int ret = av_parse_video_rate(&s->frame_rate, s->rate_str); if (ret < 0) return ret; + } else if (s->single_pic) { + s->frame_rate = av_make_q(1, 1); } else { s->frame_rate = s->auto_frame_rate; } @@ -1228,21 +1285,26 @@ static int config_output(AVFilterLink *outlink) if (s->orientation == VERTICAL) { s->combine_buffer = - av_realloc_f(s->combine_buffer, s->h * 3, + av_realloc_f(s->combine_buffer, s->h * 4, sizeof(*s->combine_buffer)); } else { s->combine_buffer = - av_realloc_f(s->combine_buffer, s->w * 3, + av_realloc_f(s->combine_buffer, s->w * 4, sizeof(*s->combine_buffer)); } av_log(ctx, AV_LOG_VERBOSE, "s:%dx%d FFT window size:%d\n", s->w, s->h, s->win_size); - av_audio_fifo_free(s->fifo); - s->fifo = av_audio_fifo_alloc(inlink->format, inlink->channels, s->win_size); - if (!s->fifo) + s->in_frame = ff_get_audio_buffer(inlink, s->win_size); + if (!s->in_frame) return AVERROR(ENOMEM); + + s->frames = av_fast_realloc(NULL, &s->frames_size, + DEFAULT_LENGTH * sizeof(*(s->frames))); + if (!s->frames) + return AVERROR(ENOMEM); + return 0; } @@ -1351,9 +1413,10 @@ static void clear_combine_buffer(ShowSpectrumContext *s, int size) int y; for (y = 0; y < size; y++) { - s->combine_buffer[3 * y ] = 0; - s->combine_buffer[3 * y + 1] = 127.5; - s->combine_buffer[3 * y + 2] = 127.5; + s->combine_buffer[4 * y ] = 0; + s->combine_buffer[4 * y + 1] = 127.5; + s->combine_buffer[4 * y + 2] = 127.5; + s->combine_buffer[4 * y + 3] = 0; } } @@ -1364,6 +1427,7 @@ static int plot_spectrum_column(AVFilterLink *inlink, AVFrame *insamples) ShowSpectrumContext *s = ctx->priv; AVFrame *outpicref = s->outpicref; int ret, plane, x, y, z = s->orientation == VERTICAL ? s->h : s->w; + const int alpha = outpicref->data[3] != NULL; /* fill a new spectrum column */ /* initialize buffer for combining to black */ @@ -1371,7 +1435,7 @@ static int plot_spectrum_column(AVFilterLink *inlink, AVFrame *insamples) ff_filter_execute(ctx, s->plot_channel, NULL, NULL, s->nb_display_channels); - for (y = 0; y < z * 3; y++) { + for (y = 0; y < z * 4; y++) { for (x = 0; x < s->nb_display_channels; x++) { s->combine_buffer[y] += s->color_buffer[x][y]; } @@ -1381,7 +1445,7 @@ static int plot_spectrum_column(AVFilterLink *inlink, AVFrame *insamples) /* copy to output */ if (s->orientation == VERTICAL) { if (s->sliding == SCROLL) { - for (plane = 0; plane < 3; plane++) { + for (plane = 0; plane < 3 + alpha; plane++) { for (y = 0; y < s->h; y++) { uint8_t *p = outpicref->data[plane] + s->start_x + (y + s->start_y) * outpicref->linesize[plane]; @@ -1390,7 +1454,7 @@ static int plot_spectrum_column(AVFilterLink *inlink, AVFrame *insamples) } s->xpos = s->w - 1; } else if (s->sliding == RSCROLL) { - for (plane = 0; plane < 3; plane++) { + for (plane = 0; plane < 3 + alpha; plane++) { for (y = 0; y < s->h; y++) { uint8_t *p = outpicref->data[plane] + s->start_x + (y + s->start_y) * outpicref->linesize[plane]; @@ -1404,13 +1468,22 @@ static int plot_spectrum_column(AVFilterLink *inlink, AVFrame *insamples) (outlink->h - 1 - s->start_y) * outpicref->linesize[plane] + s->xpos; for (y = 0; y < s->h; y++) { - *p = lrintf(av_clipf(s->combine_buffer[3 * y + plane], 0, 255)); + *p = lrintf(av_clipf(s->combine_buffer[4 * y + plane], 0, 255)); p -= outpicref->linesize[plane]; } } + if (alpha) { + uint8_t *p = outpicref->data[3] + s->start_x + + (outlink->h - 1 - s->start_y) * outpicref->linesize[3] + + s->xpos; + for (y = 0; y < s->h; y++) { + *p = lrintf(av_clipf(s->combine_buffer[4 * y + 3], 0, 255)); + p -= outpicref->linesize[3]; + } + } } else { if (s->sliding == SCROLL) { - for (plane = 0; plane < 3; plane++) { + for (plane = 0; plane < 3 + alpha; plane++) { for (y = 1; y < s->h; y++) { memmove(outpicref->data[plane] + (y-1 + s->start_y) * outpicref->linesize[plane] + s->start_x, outpicref->data[plane] + (y + s->start_y) * outpicref->linesize[plane] + s->start_x, @@ -1419,7 +1492,7 @@ static int plot_spectrum_column(AVFilterLink *inlink, AVFrame *insamples) } s->xpos = s->h - 1; } else if (s->sliding == RSCROLL) { - for (plane = 0; plane < 3; plane++) { + for (plane = 0; plane < 3 + alpha; plane++) { for (y = s->h - 1; y >= 1; y--) { memmove(outpicref->data[plane] + (y + s->start_y) * outpicref->linesize[plane] + s->start_x, outpicref->data[plane] + (y-1 + s->start_y) * outpicref->linesize[plane] + s->start_x, @@ -1432,14 +1505,22 @@ static int plot_spectrum_column(AVFilterLink *inlink, AVFrame *insamples) uint8_t *p = outpicref->data[plane] + s->start_x + (s->xpos + s->start_y) * outpicref->linesize[plane]; for (x = 0; x < s->w; x++) { - *p = lrintf(av_clipf(s->combine_buffer[3 * x + plane], 0, 255)); + *p = lrintf(av_clipf(s->combine_buffer[4 * x + plane], 0, 255)); + p++; + } + } + if (alpha) { + uint8_t *p = outpicref->data[3] + s->start_x + + (s->xpos + s->start_y) * outpicref->linesize[3]; + for (x = 0; x < s->w; x++) { + *p = lrintf(av_clipf(s->combine_buffer[4 * x + 3], 0, 255)); p++; } } } if (s->sliding != FULLFRAME || s->xpos == 0) - outpicref->pts = av_rescale_q(insamples->pts, inlink->time_base, outlink->time_base); + s->pts = outpicref->pts = av_rescale_q(s->in_pts, inlink->time_base, outlink->time_base); if (s->sliding == LREPLACE) { s->xpos--; @@ -1456,7 +1537,7 @@ static int plot_spectrum_column(AVFilterLink *inlink, AVFrame *insamples) } if (!s->single_pic && (s->sliding != FULLFRAME || s->xpos == 0)) { - if (s->old_pts < outpicref->pts) { + if (s->old_pts < outpicref->pts || s->sliding == FULLFRAME) { AVFrame *clone; if (s->legend) { @@ -1507,80 +1588,60 @@ static int activate(AVFilterContext *ctx) AVFilterLink *inlink = ctx->inputs[0]; AVFilterLink *outlink = ctx->outputs[0]; ShowSpectrumContext *s = ctx->priv; - int ret; + int ret, status; + int64_t pts; FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); - if (av_audio_fifo_size(s->fifo) < s->win_size) { - AVFrame *frame = NULL; + if (s->outpicref) { + AVFrame *fin; - ret = ff_inlink_consume_frame(inlink, &frame); + ret = ff_inlink_consume_samples(inlink, s->hop_size, s->hop_size, &fin); if (ret < 0) return ret; if (ret > 0) { - s->pts = frame->pts; - s->consumed = 0; + ff_filter_execute(ctx, run_channel_fft, fin, NULL, s->nb_display_channels); - av_audio_fifo_write(s->fifo, (void **)frame->extended_data, frame->nb_samples); - av_frame_free(&frame); - } - } + if (s->data == D_MAGNITUDE) + ff_filter_execute(ctx, calc_channel_magnitudes, NULL, NULL, s->nb_display_channels); - if (s->outpicref && (av_audio_fifo_size(s->fifo) >= s->win_size || - ff_outlink_get_status(inlink))) { - AVFrame *fin = ff_get_audio_buffer(inlink, s->win_size); - if (!fin) - return AVERROR(ENOMEM); + if (s->data == D_PHASE) + ff_filter_execute(ctx, calc_channel_phases, NULL, NULL, s->nb_display_channels); - fin->pts = s->pts + s->consumed; - s->consumed += s->hop_size; - ret = av_audio_fifo_peek(s->fifo, (void **)fin->extended_data, - FFMIN(s->win_size, av_audio_fifo_size(s->fifo))); - if (ret < 0) { + if (s->data == D_UPHASE) + ff_filter_execute(ctx, calc_channel_uphases, NULL, NULL, s->nb_display_channels); + + if (s->sliding != FULLFRAME || s->xpos == 0) + s->in_pts = fin->pts; + ret = plot_spectrum_column(inlink, fin); av_frame_free(&fin); - return ret; + if (ret <= 0) + return ret; } - - av_assert0(fin->nb_samples == s->win_size); - - ff_filter_execute(ctx, run_channel_fft, fin, NULL, s->nb_display_channels); - - if (s->data == D_MAGNITUDE) - ff_filter_execute(ctx, calc_channel_magnitudes, NULL, NULL, s->nb_display_channels); - - if (s->data == D_PHASE) - ff_filter_execute(ctx, calc_channel_phases, NULL, NULL, s->nb_display_channels); - - if (s->data == D_UPHASE) - ff_filter_execute(ctx, calc_channel_uphases, NULL, NULL, s->nb_display_channels); - - ret = plot_spectrum_column(inlink, fin); - - av_frame_free(&fin); - av_audio_fifo_drain(s->fifo, s->hop_size); - if (ret <= 0 && !ff_outlink_get_status(inlink)) - return ret; } if (ff_outlink_get_status(inlink) == AVERROR_EOF && s->sliding == FULLFRAME && s->xpos > 0 && s->outpicref) { - int64_t pts; if (s->orientation == VERTICAL) { for (int i = 0; i < outlink->h; i++) { memset(s->outpicref->data[0] + i * s->outpicref->linesize[0] + s->xpos, 0, outlink->w - s->xpos); memset(s->outpicref->data[1] + i * s->outpicref->linesize[1] + s->xpos, 128, outlink->w - s->xpos); memset(s->outpicref->data[2] + i * s->outpicref->linesize[2] + s->xpos, 128, outlink->w - s->xpos); + if (s->outpicref->data[3]) + memset(s->outpicref->data[3] + i * s->outpicref->linesize[3] + s->xpos, 0, outlink->w - s->xpos); } } else { for (int i = s->xpos; i < outlink->h; i++) { memset(s->outpicref->data[0] + i * s->outpicref->linesize[0], 0, outlink->w); memset(s->outpicref->data[1] + i * s->outpicref->linesize[1], 128, outlink->w); memset(s->outpicref->data[2] + i * s->outpicref->linesize[2], 128, outlink->w); + if (s->outpicref->data[3]) + memset(s->outpicref->data[3] + i * s->outpicref->linesize[3], 0, outlink->w); } } - s->outpicref->pts += av_rescale_q(s->consumed, inlink->time_base, outlink->time_base); + s->outpicref->pts = av_rescale_q(s->in_pts, inlink->time_base, outlink->time_base); pts = s->outpicref->pts; ret = ff_filter_frame(outlink, s->outpicref); s->outpicref = NULL; @@ -1588,17 +1649,19 @@ static int activate(AVFilterContext *ctx) return 0; } - FF_FILTER_FORWARD_STATUS(inlink, outlink); - if (av_audio_fifo_size(s->fifo) >= s->win_size || - ff_inlink_queued_frames(inlink) > 0 || - ff_outlink_get_status(inlink) == AVERROR_EOF) { + if (ff_inlink_acknowledge_status(inlink, &status, &pts)) { + if (status == AVERROR_EOF) { + ff_outlink_set_status(outlink, status, s->pts); + return 0; + } + } + + if (ff_inlink_queued_samples(inlink) >= s->hop_size) { ff_filter_set_ready(ctx, 10); return 0; } - if (ff_outlink_frame_wanted(outlink) && av_audio_fifo_size(s->fifo) < s->win_size && - ff_inlink_queued_frames(inlink) == 0 && - ff_outlink_get_status(inlink) != AVERROR_EOF) { + if (ff_outlink_frame_wanted(outlink)) { ff_inlink_request_frame(inlink); return 0; } @@ -1681,6 +1744,7 @@ static const AVOption showspectrumpic_options[] = { { "stop", "stop frequency", OFFSET(stop), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT32_MAX, FLAGS }, { "drange", "set dynamic range in dBFS", OFFSET(drange), AV_OPT_TYPE_FLOAT, {.dbl = 120}, 10, 200, FLAGS }, { "limit", "set upper limit in dBFS", OFFSET(limit), AV_OPT_TYPE_FLOAT, {.dbl = 0}, -100, 100, FLAGS }, + { "opacity", "set opacity strength", OFFSET(opacity_factor), AV_OPT_TYPE_FLOAT, {.dbl = 1}, 0, 10, FLAGS }, { NULL } }; @@ -1691,39 +1755,53 @@ static int showspectrumpic_request_frame(AVFilterLink *outlink) AVFilterContext *ctx = outlink->src; ShowSpectrumContext *s = ctx->priv; AVFilterLink *inlink = ctx->inputs[0]; - int ret, samples; + int ret; ret = ff_request_frame(inlink); - samples = av_audio_fifo_size(s->fifo); - if (ret == AVERROR_EOF && s->outpicref && samples > 0) { + if (ret == AVERROR_EOF && s->outpicref && s->samples > 0) { int consumed = 0; int x = 0, sz = s->orientation == VERTICAL ? s->w : s->h; + unsigned int nb_frame = 0; int ch, spf, spb; + int src_offset = 0; AVFrame *fin; - spf = s->win_size * (samples / ((s->win_size * sz) * ceil(samples / (float)(s->win_size * sz)))); + spf = s->win_size * (s->samples / ((s->win_size * sz) * ceil(s->samples / (float)(s->win_size * sz)))); spf = FFMAX(1, spf); - spb = (samples / (spf * sz)) * spf; + spb = (s->samples / (spf * sz)) * spf; - fin = ff_get_audio_buffer(inlink, s->win_size); + fin = ff_get_audio_buffer(inlink, spf); if (!fin) return AVERROR(ENOMEM); while (x < sz) { - ret = av_audio_fifo_peek(s->fifo, (void **)fin->extended_data, s->win_size); - if (ret < 0) { - av_frame_free(&fin); - return ret; - } + int acc_samples = 0; + int dst_offset = 0; - av_audio_fifo_drain(s->fifo, spf); + while (nb_frame <= s->nb_frames) { + AVFrame *cur_frame = s->frames[nb_frame]; + int cur_frame_samples = cur_frame->nb_samples; + int nb_samples = 0; - if (ret < s->win_size) { - for (ch = 0; ch < s->nb_display_channels; ch++) { - memset(fin->extended_data[ch] + ret * sizeof(float), 0, - (s->win_size - ret) * sizeof(float)); + if (acc_samples < spf) { + nb_samples = FFMIN(spf - acc_samples, cur_frame_samples - src_offset); + acc_samples += nb_samples; + av_samples_copy(fin->extended_data, cur_frame->extended_data, + dst_offset, src_offset, nb_samples, + cur_frame->ch_layout.nb_channels, AV_SAMPLE_FMT_FLTP); } + + src_offset += nb_samples; + dst_offset += nb_samples; + if (cur_frame_samples <= src_offset) { + av_frame_free(&s->frames[nb_frame]); + nb_frame++; + src_offset = 0; + } + + if (acc_samples == spf) + break; } ff_filter_execute(ctx, run_channel_fft, fin, NULL, s->nb_display_channels); @@ -1746,7 +1824,7 @@ static int showspectrumpic_request_frame(AVFilterLink *outlink) s->outpicref->pts = 0; if (s->legend) - draw_legend(ctx, samples); + draw_legend(ctx, s->samples); ret = ff_filter_frame(outlink, s->outpicref); s->outpicref = NULL; @@ -1759,11 +1837,20 @@ static int showspectrumpic_filter_frame(AVFilterLink *inlink, AVFrame *insamples { AVFilterContext *ctx = inlink->dst; ShowSpectrumContext *s = ctx->priv; - int ret; + void *ptr; - ret = av_audio_fifo_write(s->fifo, (void **)insamples->extended_data, insamples->nb_samples); - av_frame_free(&insamples); - return ret; + if (s->nb_frames + 1ULL > s->frames_size / sizeof(*(s->frames))) { + ptr = av_fast_realloc(s->frames, &s->frames_size, s->frames_size * 2); + if (!ptr) + return AVERROR(ENOMEM); + s->frames = ptr; + } + + s->frames[s->nb_frames] = insamples; + s->samples += insamples->nb_samples; + s->nb_frames++; + + return 0; } static const AVFilterPad showspectrumpic_inputs[] = { diff --git a/libavfilter/avf_showvolume.c b/libavfilter/avf_showvolume.c index 401b65ca6..854d10be7 100644 --- a/libavfilter/avf_showvolume.c +++ b/libavfilter/avf_showvolume.c @@ -166,15 +166,15 @@ static int config_input(AVFilterLink *inlink) ShowVolumeContext *s = ctx->priv; s->nb_samples = FFMAX(1, av_rescale(inlink->sample_rate, s->frame_rate.den, s->frame_rate.num)); - s->values = av_calloc(inlink->channels * VAR_VARS_NB, sizeof(double)); + s->values = av_calloc(inlink->ch_layout.nb_channels * VAR_VARS_NB, sizeof(double)); if (!s->values) return AVERROR(ENOMEM); - s->color_lut = av_calloc(s->w, sizeof(*s->color_lut) * inlink->channels); + s->color_lut = av_calloc(s->w, sizeof(*s->color_lut) * inlink->ch_layout.nb_channels); if (!s->color_lut) return AVERROR(ENOMEM); - s->max = av_calloc(inlink->channels, sizeof(*s->max)); + s->max = av_calloc(inlink->ch_layout.nb_channels, sizeof(*s->max)); if (!s->max) return AVERROR(ENOMEM); @@ -188,8 +188,11 @@ static int config_input(AVFilterLink *inlink) 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)); + s->max_persistent = av_calloc(inlink->ch_layout.nb_channels * s->persistent_max_frames, sizeof(*s->max_persistent)); + s->nb_frames_max_display = av_calloc(inlink->ch_layout.nb_channels * s->persistent_max_frames, sizeof(*s->nb_frames_max_display)); + if (!s->max_persistent || + !s->nb_frames_max_display) + return AVERROR(ENOMEM); } return 0; } @@ -202,16 +205,17 @@ static int config_output(AVFilterLink *outlink) if (s->orientation) { outlink->h = s->w; - outlink->w = s->h * inlink->channels + (inlink->channels - 1) * s->b; + outlink->w = s->h * inlink->ch_layout.nb_channels + (inlink->ch_layout.nb_channels - 1) * s->b; } else { outlink->w = s->w; - outlink->h = s->h * inlink->channels + (inlink->channels - 1) * s->b; + outlink->h = s->h * inlink->ch_layout.nb_channels + (inlink->ch_layout.nb_channels - 1) * s->b; } outlink->sample_aspect_ratio = (AVRational){1,1}; outlink->frame_rate = s->frame_rate; + outlink->time_base = av_inv_q(outlink->frame_rate); - for (ch = 0; ch < inlink->channels; ch++) { + for (ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { int i; for (i = 0; i < s->w; i++) { @@ -322,6 +326,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) ShowVolumeContext *s = ctx->priv; const int step = s->step; int c, j, k, max_draw; + char channel_name[64]; AVFrame *out; if (!s->out || s->out->width != outlink->w || @@ -334,7 +339,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) } clear_picture(s, outlink); } - s->out->pts = insamples->pts; + s->out->pts = av_rescale_q(insamples->pts, inlink->time_base, outlink->time_base); if ((s->f < 1.) && (s->f > 0.)) { for (j = 0; j < outlink->h; j++) { @@ -353,7 +358,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) } if (s->orientation) { /* vertical */ - for (c = 0; c < inlink->channels; c++) { + for (c = 0; c < inlink->ch_layout.nb_channels; c++) { float *src = (float *)insamples->extended_data[c]; uint32_t *lut = s->color_lut + s->w * c; float max; @@ -375,8 +380,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) } if (s->h >= 8 && s->draw_text) { - const char *channel_name = av_get_channel_name(av_channel_layout_extract_channel(insamples->channel_layout, c)); - if (!channel_name) + int ret = av_channel_name(channel_name, sizeof(channel_name), av_channel_layout_channel_from_index(&insamples->ch_layout, c)); + if (ret < 0) continue; drawtext(s->out, c * (s->h + s->b) + (s->h - 10) / 2, outlink->h - 35, channel_name, 1); } @@ -388,7 +393,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) } } } else { /* horizontal */ - for (c = 0; c < inlink->channels; c++) { + for (c = 0; c < inlink->ch_layout.nb_channels; c++) { float *src = (float *)insamples->extended_data[c]; uint32_t *lut = s->color_lut + s->w * c; float max; @@ -411,8 +416,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) } if (s->h >= 8 && s->draw_text) { - const char *channel_name = av_get_channel_name(av_channel_layout_extract_channel(insamples->channel_layout, c)); - if (!channel_name) + int ret = av_channel_name(channel_name, sizeof(channel_name), av_channel_layout_channel_from_index(&insamples->ch_layout, c)); + if (ret < 0) continue; drawtext(s->out, 2, c * (s->h + s->b) + (s->h - 8) / 2, channel_name, 0); } @@ -432,7 +437,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) av_frame_make_writable(out); /* draw volume level */ - for (c = 0; c < inlink->channels && s->h >= 8 && s->draw_volume; c++) { + for (c = 0; c < inlink->ch_layout.nb_channels && s->h >= 8 && s->draw_volume; c++) { char buf[16]; if (s->orientation) { /* vertical */ @@ -463,6 +468,11 @@ static int activate(AVFilterContext *ctx) if (ret > 0) return filter_frame(inlink, in); + if (ff_inlink_queued_samples(inlink) >= s->nb_samples) { + ff_filter_set_ready(ctx, 10); + return 0; + } + FF_FILTER_FORWARD_STATUS(inlink, outlink); FF_FILTER_FORWARD_WANTED(outlink, inlink); @@ -478,6 +488,8 @@ static av_cold void uninit(AVFilterContext *ctx) av_freep(&s->values); av_freep(&s->color_lut); av_freep(&s->max); + av_freep(&s->max_persistent); + av_freep(&s->nb_frames_max_display); } static const AVFilterPad showvolume_inputs[] = { diff --git a/libavfilter/avf_showwaves.c b/libavfilter/avf_showwaves.c index 853f6bbdc..76399ab13 100644 --- a/libavfilter/avf_showwaves.c +++ b/libavfilter/avf_showwaves.c @@ -23,6 +23,8 @@ * audio to video multimedia filter */ +#include "config_components.h" + #include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/channel_layout.h" @@ -415,7 +417,7 @@ static int config_output(AVFilterLink *outlink) AVFilterContext *ctx = outlink->src; AVFilterLink *inlink = ctx->inputs[0]; ShowWavesContext *showwaves = ctx->priv; - int nb_channels = inlink->channels; + int nb_channels = inlink->ch_layout.nb_channels; char *colors, *saveptr = NULL; uint8_t x; int ch; @@ -435,8 +437,11 @@ static int config_output(AVFilterLink *outlink) outlink->h = showwaves->h; outlink->sample_aspect_ratio = (AVRational){1,1}; - outlink->frame_rate = av_div_q((AVRational){inlink->sample_rate,showwaves->n}, - (AVRational){showwaves->w,1}); + if (showwaves->single_pic) + outlink->frame_rate = av_make_q(1, 1); + else + outlink->frame_rate = av_div_q((AVRational){inlink->sample_rate,showwaves->n}, + (AVRational){showwaves->w,1}); av_log(ctx, AV_LOG_VERBOSE, "s:%dx%d r:%f n:%d\n", showwaves->w, showwaves->h, av_q2d(outlink->frame_rate), showwaves->n); @@ -551,7 +556,7 @@ inline static int push_frame(AVFilterLink *outlink) AVFilterContext *ctx = outlink->src; AVFilterLink *inlink = ctx->inputs[0]; ShowWavesContext *showwaves = outlink->src->priv; - int nb_channels = inlink->channels; + int nb_channels = inlink->ch_layout.nb_channels; int ret, i; ret = ff_filter_frame(outlink, showwaves->outpicref); @@ -572,7 +577,7 @@ static int push_single_pic(AVFilterLink *outlink) int64_t last_column_samples = column_max_samples + remaining_samples; AVFrame *out = showwaves->outpicref; struct frame_node *node; - const int nb_channels = inlink->channels; + const int nb_channels = inlink->ch_layout.nb_channels; const int ch_height = showwaves->split_channels ? outlink->h / nb_channels : outlink->h; const int linesize = out->linesize[0]; const int pixstep = showwaves->pixstep; @@ -661,7 +666,7 @@ static int alloc_out_frame(ShowWavesContext *showwaves, const int16_t *p, return AVERROR(ENOMEM); out->width = outlink->w; out->height = outlink->h; - out->pts = in->pts + av_rescale_q((p - (int16_t *)in->data[0]) / inlink->channels, + out->pts = in->pts + av_rescale_q((p - (int16_t *)in->data[0]) / inlink->ch_layout.nb_channels, av_make_q(1, inlink->sample_rate), outlink->time_base); for (j = 0; j < outlink->h; j++) @@ -692,7 +697,7 @@ static int showwaves_filter_frame(AVFilterLink *inlink, AVFrame *insamples) const int nb_samples = insamples->nb_samples; AVFrame *outpicref = showwaves->outpicref; int16_t *p = (int16_t *)insamples->data[0]; - int nb_channels = inlink->channels; + int nb_channels = inlink->ch_layout.nb_channels; int i, j, ret = 0; const int pixstep = showwaves->pixstep; const int n = showwaves->n; @@ -820,7 +825,7 @@ static int showwavespic_config_input(AVFilterLink *inlink) ShowWavesContext *showwaves = ctx->priv; if (showwaves->single_pic) { - showwaves->sum = av_calloc(inlink->channels, sizeof(*showwaves->sum)); + showwaves->sum = av_calloc(inlink->ch_layout.nb_channels, sizeof(*showwaves->sum)); if (!showwaves->sum) return AVERROR(ENOMEM); } diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index 7362bcdab..965f5d0f6 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -32,7 +32,6 @@ #include "libavutil/pixdesc.h" #include "libavutil/rational.h" #include "libavutil/samplefmt.h" -#include "libavutil/thread.h" #define FF_INTERNAL_FIELDS 1 #include "framequeue.h" @@ -44,9 +43,6 @@ #include "framepool.h" #include "internal.h" -#include "libavutil/ffversion.h" -const char av_filter_ffversion[] = "FFmpeg version " FFMPEG_VERSION; - static void tlog_ref(void *ctx, AVFrame *ref, int end) { ff_tlog(ctx, @@ -74,23 +70,6 @@ static void tlog_ref(void *ctx, AVFrame *ref, int end) ff_tlog(ctx, "]%s", end ? "\n" : ""); } -unsigned avfilter_version(void) -{ - av_assert0(LIBAVFILTER_VERSION_MICRO >= 100); - return LIBAVFILTER_VERSION_INT; -} - -const char *avfilter_configuration(void) -{ - return FFMPEG_CONFIGURATION; -} - -const char *avfilter_license(void) -{ -#define LICENSE_PREFIX "libavfilter license: " - return &LICENSE_PREFIX FFMPEG_LICENSE[sizeof(LICENSE_PREFIX) - 1]; -} - void ff_command_queue_pop(AVFilterContext *filter) { AVFilterCommand *c= filter->command_queue; @@ -204,6 +183,7 @@ void avfilter_link_free(AVFilterLink **link) ff_framequeue_free(&(*link)->fifo); ff_frame_pool_uninit((FFFramePool**)&(*link)->frame_pool); + av_channel_layout_uninit(&(*link)->ch_layout); av_freep(link); } @@ -405,7 +385,7 @@ void ff_tlog_link(void *ctx, AVFilterLink *link, int end) end ? "\n" : ""); } else { char buf[128]; - av_get_channel_layout_string(buf, sizeof(buf), -1, link->channel_layout); + av_channel_layout_describe(&link->ch_layout, buf, sizeof(buf)); ff_tlog(ctx, "link[%p r:%d cl:%s fmt:%s %s->%s]%s", @@ -860,16 +840,17 @@ static int process_options(AVFilterContext *ctx, AVDictionary **options, return ret; } } else { - av_dict_set(options, key, value, 0); - if ((ret = av_opt_set(ctx->priv, key, value, AV_OPT_SEARCH_CHILDREN)) < 0) { - if (!av_opt_find(ctx->priv, key, NULL, 0, AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ)) { - if (ret == AVERROR_OPTION_NOT_FOUND) - av_log(ctx, AV_LOG_ERROR, "Option '%s' not found\n", key); - av_free(value); - av_free(parsed_key); - return ret; - } + o = av_opt_find(ctx->priv, key, NULL, 0, + AV_OPT_SEARCH_CHILDREN | AV_OPT_SEARCH_FAKE_OBJ); + if (!o) { + av_log(ctx, AV_LOG_ERROR, "Option '%s' not found\n", key); + av_free(value); + av_free(parsed_key); + return AVERROR_OPTION_NOT_FOUND; } + av_dict_set(options, key, value, + (o->type == AV_OPT_TYPE_FLAGS && + (value[0] == '-' || value[0] == '+')) ? AV_DICT_APPEND : 0); } av_free(value); @@ -1036,11 +1017,7 @@ int ff_filter_frame(AVFilterLink *link, AVFrame *frame) av_log(link->dst, AV_LOG_ERROR, "Format change is not supported\n"); goto error; } - if (frame->channels != link->channels) { - av_log(link->dst, AV_LOG_ERROR, "Channel count change is not supported\n"); - goto error; - } - if (frame->channel_layout != link->channel_layout) { + if (av_channel_layout_compare(&frame->ch_layout, &link->ch_layout)) { av_log(link->dst, AV_LOG_ERROR, "Channel layout change is not supported\n"); goto error; } @@ -1117,7 +1094,7 @@ static int take_samples(AVFilterLink *link, unsigned min, unsigned max, for (i = 0; i < nb_frames; i++) { frame = ff_framequeue_take(&link->fifo); av_samples_copy(buf->extended_data, frame->extended_data, p, 0, - frame->nb_samples, link->channels, link->format); + frame->nb_samples, link->ch_layout.nb_channels, link->format); p += frame->nb_samples; av_frame_free(&frame); } @@ -1125,7 +1102,7 @@ static int take_samples(AVFilterLink *link, unsigned min, unsigned max, unsigned n = nb_samples - p; frame = ff_framequeue_peek(&link->fifo, 0); av_samples_copy(buf->extended_data, frame->extended_data, p, 0, n, - link->channels, link->format); + link->ch_layout.nb_channels, link->format); ff_framequeue_skip_samples(&link->fifo, n, link->time_base); } @@ -1559,6 +1536,14 @@ int ff_outlink_get_status(AVFilterLink *link) return link->status_in; } +int ff_inoutlink_check_flow(AVFilterLink *inlink, AVFilterLink *outlink) +{ + return ff_outlink_frame_wanted(outlink) || + ff_inlink_check_available_frame(inlink) || + inlink->status_out; +} + + const AVClass *avfilter_get_class(void) { return &avfilter_class; diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h index b105dc315..2e8197c9a 100644 --- a/libavfilter/avfilter.h +++ b/libavfilter/avfilter.h @@ -47,7 +47,13 @@ #include "libavutil/pixfmt.h" #include "libavutil/rational.h" +#include "libavfilter/version_major.h" +#ifndef HAVE_AV_CONFIG_H +/* When included as part of the ffmpeg build, only include the major version + * to avoid unnecessary rebuilds. When included externally, keep including + * the full version information. */ #include "libavfilter/version.h" +#endif /** * Return the LIBAVFILTER_VERSION_INT constant. @@ -543,7 +549,14 @@ struct AVFilterLink { int h; ///< agreed upon image height AVRational sample_aspect_ratio; ///< agreed upon sample aspect ratio /* These parameters apply only to audio */ - uint64_t channel_layout; ///< channel layout of current buffer (see libavutil/channel_layout.h) +#if FF_API_OLD_CHANNEL_LAYOUT + /** + * channel layout of current buffer (see libavutil/channel_layout.h) + * @deprecated use ch_layout + */ + attribute_deprecated + uint64_t channel_layout; +#endif int sample_rate; ///< samples per second int format; ///< agreed upon media format @@ -557,6 +570,8 @@ struct AVFilterLink { */ AVRational time_base; + AVChannelLayout ch_layout; ///< channel layout of current buffer (see libavutil/channel_layout.h) + /***************************************************************** * 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 @@ -632,11 +647,6 @@ struct AVFilterLink { */ int max_samples; - /** - * Number of channels. - */ - int channels; - /** * Number of past frames sent through the link. */ diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c index b8b432e98..b7dbfc063 100644 --- a/libavfilter/avfiltergraph.c +++ b/libavfilter/avfiltergraph.c @@ -25,11 +25,9 @@ #include #include "libavutil/avassert.h" -#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" @@ -639,6 +637,8 @@ static int pick_format(AVFilterLink *link, AVFilterLink *ref) link->format = link->incfg.formats->formats[0]; if (link->type == AVMEDIA_TYPE_AUDIO) { + int ret; + if (!link->incfg.samplerates->nb_formats) { av_log(link->src, AV_LOG_ERROR, "Cannot select sample rate for" " the link between filters %s and %s.\n", link->src->name, @@ -659,11 +659,15 @@ static int pick_format(AVFilterLink *link, AVFilterLink *ref) return AVERROR(EINVAL); } link->incfg.channel_layouts->nb_channel_layouts = 1; - link->channel_layout = link->incfg.channel_layouts->channel_layouts[0]; - if ((link->channels = FF_LAYOUT2COUNT(link->channel_layout))) - link->channel_layout = 0; - else - link->channels = av_get_channel_layout_nb_channels(link->channel_layout); + ret = av_channel_layout_copy(&link->ch_layout, &link->incfg.channel_layouts->channel_layouts[0]); + if (ret < 0) + return ret; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + link->channel_layout = link->ch_layout.order == AV_CHANNEL_ORDER_NATIVE ? + link->ch_layout.u.mask : 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } ff_formats_unref(&link->incfg.formats); @@ -725,12 +729,12 @@ static int reduce_formats_on_filter(AVFilterContext *filter) /* reduce channel layouts */ for (i = 0; i < filter->nb_inputs; i++) { AVFilterLink *inlink = filter->inputs[i]; - uint64_t fmt; + AVChannelLayout fmt = { 0 }; if (!inlink->outcfg.channel_layouts || inlink->outcfg.channel_layouts->nb_channel_layouts != 1) continue; - fmt = inlink->outcfg.channel_layouts->channel_layouts[0]; + av_channel_layout_copy(&fmt, &inlink->outcfg.channel_layouts->channel_layouts[0]); for (j = 0; j < filter->nb_outputs; j++) { AVFilterLink *outlink = filter->outputs[j]; @@ -741,23 +745,24 @@ static int reduce_formats_on_filter(AVFilterContext *filter) continue; if (fmts->all_layouts && - (!FF_LAYOUT2COUNT(fmt) || fmts->all_counts)) { + (KNOWN(&fmt) || fmts->all_counts)) { /* Turn the infinite list into a singleton */ fmts->all_layouts = fmts->all_counts = 0; - if (ff_add_channel_layout(&outlink->incfg.channel_layouts, fmt) < 0) + if (ff_add_channel_layout(&outlink->incfg.channel_layouts, &fmt) < 0) ret = 1; break; } for (k = 0; k < outlink->incfg.channel_layouts->nb_channel_layouts; k++) { - if (fmts->channel_layouts[k] == fmt) { - fmts->channel_layouts[0] = fmt; + if (!av_channel_layout_compare(&fmts->channel_layouts[k], &fmt)) { + av_channel_layout_copy(&fmts->channel_layouts[0], &fmt); fmts->nb_channel_layouts = 1; ret = 1; break; } } } + av_channel_layout_uninit(&fmt); } return ret; @@ -887,26 +892,31 @@ static void swap_channel_layouts_on_filter(AVFilterContext *filter) continue; for (j = 0; j < outlink->incfg.channel_layouts->nb_channel_layouts; j++) { - uint64_t in_chlayout = link->outcfg.channel_layouts->channel_layouts[0]; - uint64_t out_chlayout = outlink->incfg.channel_layouts->channel_layouts[j]; - int in_channels = av_get_channel_layout_nb_channels(in_chlayout); - int out_channels = av_get_channel_layout_nb_channels(out_chlayout); - int count_diff = out_channels - in_channels; + AVChannelLayout in_chlayout = { 0 }, out_chlayout = { 0 }; + int in_channels; + int out_channels; + int count_diff; int matched_channels, extra_channels; int score = 100000; - if (FF_LAYOUT2COUNT(in_chlayout) || FF_LAYOUT2COUNT(out_chlayout)) { + av_channel_layout_copy(&in_chlayout, &link->outcfg.channel_layouts->channel_layouts[0]); + av_channel_layout_copy(&out_chlayout, &outlink->incfg.channel_layouts->channel_layouts[j]); + in_channels = in_chlayout.nb_channels; + out_channels = out_chlayout.nb_channels; + count_diff = out_channels - in_channels; + if (!KNOWN(&in_chlayout) || !KNOWN(&out_chlayout)) { /* Compute score in case the input or output layout encodes a channel count; in this case the score is not altered by the computation afterwards, as in_chlayout and out_chlayout have both been set to 0 */ - if (FF_LAYOUT2COUNT(in_chlayout)) - in_channels = FF_LAYOUT2COUNT(in_chlayout); - if (FF_LAYOUT2COUNT(out_chlayout)) - out_channels = FF_LAYOUT2COUNT(out_chlayout); + if (!KNOWN(&in_chlayout)) + in_channels = FF_LAYOUT2COUNT(&in_chlayout); + if (!KNOWN(&out_chlayout)) + out_channels = FF_LAYOUT2COUNT(&out_chlayout); score -= 10000 + FFABS(out_channels - in_channels) + (in_channels > out_channels ? 10000 : 0); - in_chlayout = out_chlayout = 0; + av_channel_layout_uninit(&in_chlayout); + av_channel_layout_uninit(&out_chlayout); /* Let the remaining computation run, even if the score value is not altered */ } @@ -915,27 +925,27 @@ static void swap_channel_layouts_on_filter(AVFilterContext *filter) for (k = 0; k < FF_ARRAY_ELEMS(ch_subst); k++) { uint64_t cmp0 = ch_subst[k][0]; uint64_t cmp1 = ch_subst[k][1]; - if (( in_chlayout & cmp0) && (!(out_chlayout & cmp0)) && - (out_chlayout & cmp1) && (!( in_chlayout & cmp1))) { - in_chlayout &= ~cmp0; - out_chlayout &= ~cmp1; + if ( av_channel_layout_subset(& in_chlayout, cmp0) && + !av_channel_layout_subset(&out_chlayout, cmp0) && + av_channel_layout_subset(&out_chlayout, cmp1) && + !av_channel_layout_subset(& in_chlayout, cmp1)) { + av_channel_layout_from_mask(&in_chlayout, av_channel_layout_subset(& in_chlayout, ~cmp0)); + av_channel_layout_from_mask(&out_chlayout, av_channel_layout_subset(&out_chlayout, ~cmp1)); /* add score for channel match, minus a deduction for having to do the substitution */ - score += 10 * av_get_channel_layout_nb_channels(cmp1) - 2; + score += 10 * av_popcount64(cmp1) - 2; } } /* no penalty for LFE channel mismatch */ - if ( (in_chlayout & AV_CH_LOW_FREQUENCY) && - (out_chlayout & AV_CH_LOW_FREQUENCY)) + if (av_channel_layout_channel_from_index(&in_chlayout, AV_CHAN_LOW_FREQUENCY) >= 0 && + av_channel_layout_channel_from_index(&out_chlayout, AV_CHAN_LOW_FREQUENCY) >= 0) score += 10; - in_chlayout &= ~AV_CH_LOW_FREQUENCY; - out_chlayout &= ~AV_CH_LOW_FREQUENCY; + av_channel_layout_from_mask(&in_chlayout, av_channel_layout_subset(&in_chlayout, ~AV_CH_LOW_FREQUENCY)); + av_channel_layout_from_mask(&out_chlayout, av_channel_layout_subset(&out_chlayout, ~AV_CH_LOW_FREQUENCY)); - matched_channels = av_get_channel_layout_nb_channels(in_chlayout & - out_chlayout); - extra_channels = av_get_channel_layout_nb_channels(out_chlayout & - (~in_chlayout)); + matched_channels = av_popcount64(in_chlayout.u.mask & out_chlayout.u.mask); + extra_channels = av_popcount64(out_chlayout.u.mask & (~in_chlayout.u.mask)); score += 10 * matched_channels - 5 * extra_channels; if (score > best_score || @@ -946,7 +956,7 @@ static void swap_channel_layouts_on_filter(AVFilterContext *filter) } } av_assert0(best_idx >= 0); - FFSWAP(uint64_t, outlink->incfg.channel_layouts->channel_layouts[0], + FFSWAP(AVChannelLayout, outlink->incfg.channel_layouts->channel_layouts[0], outlink->incfg.channel_layouts->channel_layouts[best_idx]); } diff --git a/libavfilter/blend.h b/libavfilter/blend.h index ff417650c..b046e062b 100644 --- a/libavfilter/blend.h +++ b/libavfilter/blend.h @@ -81,7 +81,6 @@ typedef struct FilterParams { struct FilterParams *param, double *values, int starty); } FilterParams; -void ff_blend_init(FilterParams *param, int depth); void ff_blend_init_x86(FilterParams *param, int depth); #endif /* AVFILTER_BLEND_H */ diff --git a/libavfilter/blend_modes.c b/libavfilter/blend_modes.c index 64cd6e8a5..0ff96a5b0 100644 --- a/libavfilter/blend_modes.c +++ b/libavfilter/blend_modes.c @@ -56,6 +56,7 @@ #undef INT2FLOAT #undef FLOAT2INT #undef MDIV +#undef LRINTF #if DEPTH < 32 #define MULTIPLY(x, a, b) ((x) * (((a) * (b)) / MAX)) @@ -66,6 +67,7 @@ #define INT2FLOAT(x) (x) #define FLOAT2INT(x) (x) #define MDIV (0.125f * (1 << DEPTH)) +#define LRINTF(x) lrintf(x) #else #define MULTIPLY(x, a, b) ((x) * (((a) * (b)) / 1.0)) #define SCREEN(x, a, b) (1.0 - (x) * ((1.0 - (a)) * (1.0 - (b)) / 1.0)) @@ -75,6 +77,7 @@ #define INT2FLOAT(x) av_int2float(x) #define FLOAT2INT(x) av_float2int(x) #define MDIV 0.125f +#define LRINTF(x) (x) #endif #define A top[j] @@ -147,5 +150,5 @@ fn(geometric, GEOMETRIC(A, B)) fn(harmonic, A == 0 && B == 0 ? 0 : 2LL * A * B / (A + B)) fn(bleach, (MAX - B) + (MAX - A) - MAX) fn(stain, 2 * MAX - A - B) -fn(interpolate,lrintf(MAX * (2 - cosf(A * M_PI / MAX) - cosf(B * M_PI / MAX)) * 0.25f)) +fn(interpolate,LRINTF(MAX * (2 - cosf(A * M_PI / MAX) - cosf(B * M_PI / MAX)) * 0.25f)) fn(hardoverlay,A == MAX ? MAX : FFMIN(MAX, MAX * B / (2 * MAX - 2 * A) * (A > HALF) + 2 * A * B / MAX * (A <= HALF))) diff --git a/libavfilter/buffersink.c b/libavfilter/buffersink.c index c0215669e..e269cf72d 100644 --- a/libavfilter/buffersink.c +++ b/libavfilter/buffersink.c @@ -24,6 +24,7 @@ */ #include "libavutil/avassert.h" +#include "libavutil/avstring.h" #include "libavutil/channel_layout.h" #include "libavutil/common.h" #include "libavutil/internal.h" @@ -49,10 +50,13 @@ typedef struct BufferSinkContext { /* only used for audio */ enum AVSampleFormat *sample_fmts; ///< list of accepted sample formats int sample_fmts_size; +#if FF_API_OLD_CHANNEL_LAYOUT int64_t *channel_layouts; ///< list of accepted channel layouts int channel_layouts_size; int *channel_counts; ///< list of accepted channel counts int channel_counts_size; +#endif + char *channel_layouts_str; ///< list of accepted channel layouts int all_channel_counts; int *sample_rates; ///< list of accepted sample rates int sample_rates_size; @@ -62,6 +66,7 @@ typedef struct BufferSinkContext { #define NB_ITEMS(list) (list ## _size / sizeof(*list)) +#if FF_API_OLD_CHANNEL_LAYOUT static void cleanup_redundant_layouts(AVFilterContext *ctx) { BufferSinkContext *buf = ctx->priv; @@ -74,7 +79,7 @@ static void cleanup_redundant_layouts(AVFilterContext *ctx) if (buf->channel_counts[i] < 64) counts |= (uint64_t)1 << buf->channel_counts[i]; for (i = lc = 0; i < nb_layouts; i++) { - n = av_get_channel_layout_nb_channels(buf->channel_layouts[i]); + n = av_popcount64(buf->channel_layouts[i]); if (n < 64 && (counts & ((uint64_t)1 << n))) av_log(ctx, AV_LOG_WARNING, "Removing channel layout 0x%"PRIx64", redundant with %d channels\n", @@ -84,6 +89,7 @@ static void cleanup_redundant_layouts(AVFilterContext *ctx) } buf->channel_layouts_size = lc * sizeof(*buf->channel_layouts); } +#endif int attribute_align_arg av_buffersink_get_frame(AVFilterContext *ctx, AVFrame *frame) { @@ -217,12 +223,34 @@ MAKE_AVFILTERLINK_ACCESSOR(int , w ) MAKE_AVFILTERLINK_ACCESSOR(int , h ) MAKE_AVFILTERLINK_ACCESSOR(AVRational , sample_aspect_ratio) -MAKE_AVFILTERLINK_ACCESSOR(int , channels ) +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS MAKE_AVFILTERLINK_ACCESSOR(uint64_t , channel_layout ) +FF_ENABLE_DEPRECATION_WARNINGS +#endif MAKE_AVFILTERLINK_ACCESSOR(int , sample_rate ) MAKE_AVFILTERLINK_ACCESSOR(AVBufferRef * , hw_frames_ctx ) +int av_buffersink_get_channels(const AVFilterContext *ctx) +{ + av_assert0(ctx->filter->activate == activate); + return ctx->inputs[0]->ch_layout.nb_channels; +} + +int av_buffersink_get_ch_layout(const AVFilterContext *ctx, AVChannelLayout *out) +{ + AVChannelLayout ch_layout = { 0 }; + int ret; + + av_assert0(ctx->filter->activate == activate); + ret = av_channel_layout_copy(&ch_layout, &ctx->inputs[0]->ch_layout); + if (ret < 0) + return ret; + *out = ch_layout; + return 0; +} + #define CHECK_LIST_SIZE(field) \ if (buf->field ## _size % sizeof(*buf->field)) { \ av_log(ctx, AV_LOG_ERROR, "Invalid size for " #field ": %d, " \ @@ -256,14 +284,17 @@ static int asink_query_formats(AVFilterContext *ctx) { BufferSinkContext *buf = ctx->priv; AVFilterFormats *formats = NULL; + AVChannelLayout layout = { 0 }; AVFilterChannelLayouts *layouts = NULL; unsigned i; int ret; CHECK_LIST_SIZE(sample_fmts) CHECK_LIST_SIZE(sample_rates) +#if FF_API_OLD_CHANNEL_LAYOUT CHECK_LIST_SIZE(channel_layouts) CHECK_LIST_SIZE(channel_counts) +#endif if (buf->sample_fmts_size) { for (i = 0; i < NB_ITEMS(buf->sample_fmts); i++) @@ -273,15 +304,51 @@ static int asink_query_formats(AVFilterContext *ctx) return ret; } - if (buf->channel_layouts_size || buf->channel_counts_size || - buf->all_channel_counts) { + if ( +#if FF_API_OLD_CHANNEL_LAYOUT + buf->channel_layouts_size || buf->channel_counts_size || +#endif + buf->channel_layouts_str || buf->all_channel_counts) { +#if FF_API_OLD_CHANNEL_LAYOUT cleanup_redundant_layouts(ctx); for (i = 0; i < NB_ITEMS(buf->channel_layouts); i++) - if ((ret = ff_add_channel_layout(&layouts, buf->channel_layouts[i])) < 0) + if ((ret = av_channel_layout_from_mask(&layout, buf->channel_layouts[i])) < 0 || + (ret = ff_add_channel_layout(&layouts, &layout) < 0)) return ret; - for (i = 0; i < NB_ITEMS(buf->channel_counts); i++) - if ((ret = ff_add_channel_layout(&layouts, FF_COUNT2LAYOUT(buf->channel_counts[i]))) < 0) + for (i = 0; i < NB_ITEMS(buf->channel_counts); i++) { + layout = FF_COUNT2LAYOUT(buf->channel_counts[i]); + if ((ret = ff_add_channel_layout(&layouts, &layout)) < 0) return ret; + } +#endif + if (buf->channel_layouts_str) { + const char *cur = buf->channel_layouts_str; + +#if FF_API_OLD_CHANNEL_LAYOUT + if (layouts) + av_log(ctx, AV_LOG_WARNING, + "Conflicting ch_layouts and list of channel_counts/channel_layouts. Ignoring the former\n"); + else +#endif + while (cur) { + char *next = strchr(cur, '|'); + if (next) + *next++ = 0; + + ret = av_channel_layout_from_string(&layout, cur); + if (ret < 0) { + av_log(ctx, AV_LOG_ERROR, "Error parsing channel layout: %s.\n", cur); + return ret; + } + ret = ff_add_channel_layout(&layouts, &layout); + av_channel_layout_uninit(&layout); + if (ret < 0) + return ret; + + cur = next; + } + } + if (buf->all_channel_counts) { if (layouts) av_log(ctx, AV_LOG_WARNING, @@ -316,8 +383,14 @@ static const AVOption buffersink_options[] = { static const AVOption abuffersink_options[] = { { "sample_fmts", "set the supported sample formats", OFFSET(sample_fmts), AV_OPT_TYPE_BINARY, .flags = FLAGS }, { "sample_rates", "set the supported sample rates", OFFSET(sample_rates), AV_OPT_TYPE_BINARY, .flags = FLAGS }, - { "channel_layouts", "set the supported channel layouts", OFFSET(channel_layouts), AV_OPT_TYPE_BINARY, .flags = FLAGS }, - { "channel_counts", "set the supported channel counts", OFFSET(channel_counts), AV_OPT_TYPE_BINARY, .flags = FLAGS }, +#if FF_API_OLD_CHANNEL_LAYOUT + { "channel_layouts", "set the supported channel layouts (deprecated, use ch_layouts)", + OFFSET(channel_layouts), AV_OPT_TYPE_BINARY, .flags = FLAGS | AV_OPT_FLAG_DEPRECATED }, + { "channel_counts", "set the supported channel counts (deprecated, use ch_layouts)", + OFFSET(channel_counts), AV_OPT_TYPE_BINARY, .flags = FLAGS | AV_OPT_FLAG_DEPRECATED }, +#endif + { "ch_layouts", "set a '|'-separated list of supported channel layouts", + OFFSET(channel_layouts_str), AV_OPT_TYPE_STRING, .flags = FLAGS }, { "all_channel_counts", "accept all channel counts", OFFSET(all_channel_counts), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS }, { NULL }, }; diff --git a/libavfilter/buffersink.h b/libavfilter/buffersink.h index 69ed0f29a..01e7c747d 100644 --- a/libavfilter/buffersink.h +++ b/libavfilter/buffersink.h @@ -46,27 +46,26 @@ * - av_buffersink_get_h(), * - av_buffersink_get_sample_aspect_ratio(), * - av_buffersink_get_channels(), - * - av_buffersink_get_channel_layout(), + * - av_buffersink_get_ch_layout(), * - av_buffersink_get_sample_rate(). * + * The layout returned by av_buffersink_get_ch_layout() must de uninitialized + * by the caller. + * * The format can be constrained by setting options, using av_opt_set() and * related functions with the AV_OPT_SEARCH_CHILDREN flag. * - pix_fmts (int list), * - sample_fmts (int list), * - sample_rates (int list), - * - channel_layouts (int64_t), + * - ch_layouts (string), * - channel_counts (int list), * - all_channel_counts (bool). * Most of these options are of type binary, and should be set using * av_opt_set_int_list() or av_opt_set_bin(). If they are not set, all * corresponding formats are accepted. * - * As a special case, if neither channel_layouts nor channel_counts is set, - * all valid channel layouts are accepted, but channel counts without a - * layout are not, unless all_channel_counts is set. - * Also, channel_layouts must not contain a channel layout already accepted - * by a value in channel_counts; for example, if channel_counts contains 2, - * then channel_layouts must not contain stereo. + * As a special case, if ch_layouts is not set, all valid channel layouts are + * accepted except for UNSPEC layouts, unless all_channel_counts is set. */ /** @@ -156,7 +155,12 @@ int av_buffersink_get_h (const AVFilterContext *c AVRational av_buffersink_get_sample_aspect_ratio (const AVFilterContext *ctx); int av_buffersink_get_channels (const AVFilterContext *ctx); +#if FF_API_OLD_CHANNEL_LAYOUT +attribute_deprecated uint64_t av_buffersink_get_channel_layout (const AVFilterContext *ctx); +#endif +int av_buffersink_get_ch_layout (const AVFilterContext *ctx, + AVChannelLayout *ch_layout); int av_buffersink_get_sample_rate (const AVFilterContext *ctx); AVBufferRef * av_buffersink_get_hw_frames_ctx (const AVFilterContext *ctx); diff --git a/libavfilter/buffersrc.c b/libavfilter/buffersrc.c index b0611872f..a3190468b 100644 --- a/libavfilter/buffersrc.c +++ b/libavfilter/buffersrc.c @@ -60,8 +60,8 @@ typedef struct BufferSourceContext { int sample_rate; enum AVSampleFormat sample_fmt; int channels; - uint64_t channel_layout; char *channel_layout_str; + AVChannelLayout ch_layout; int eof; } BufferSourceContext; @@ -73,12 +73,12 @@ typedef struct BufferSourceContext { av_log(s, AV_LOG_WARNING, "Changing video frame properties on the fly is not supported by all filters.\n");\ } -#define CHECK_AUDIO_PARAM_CHANGE(s, c, srate, ch_layout, ch_count, format, pts)\ +#define CHECK_AUDIO_PARAM_CHANGE(s, c, srate, layout, format, pts)\ if (c->sample_fmt != format || c->sample_rate != srate ||\ - c->channel_layout != ch_layout || c->channels != ch_count) {\ + av_channel_layout_compare(&c->ch_layout, &layout) || c->channels != layout.nb_channels) {\ av_log(s, AV_LOG_INFO, "filter context - fmt: %s r: %d layout: %"PRIX64" ch: %d, incoming frame - fmt: %s r: %d layout: %"PRIX64" ch: %d pts_time: %s\n",\ - av_get_sample_fmt_name(c->sample_fmt), c->sample_rate, c->channel_layout, c->channels,\ - av_get_sample_fmt_name(format), srate, ch_layout, ch_count, av_ts2timestr(pts, &s->outputs[0]->time_base));\ + av_get_sample_fmt_name(c->sample_fmt), c->sample_rate, c->ch_layout.order == AV_CHANNEL_ORDER_NATIVE ? c->ch_layout.u.mask : 0, c->channels,\ + av_get_sample_fmt_name(format), srate, layout.order == AV_CHANNEL_ORDER_NATIVE ? layout.u.mask : 0, layout.nb_channels, av_ts2timestr(pts, &s->outputs[0]->time_base));\ av_log(s, AV_LOG_ERROR, "Changing audio frame properties on the fly is not supported.\n");\ return AVERROR(EINVAL);\ } @@ -127,8 +127,21 @@ int av_buffersrc_parameters_set(AVFilterContext *ctx, AVBufferSrcParameters *par } if (param->sample_rate > 0) s->sample_rate = param->sample_rate; - if (param->channel_layout) - s->channel_layout = param->channel_layout; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + // if the old/new fields are set inconsistently, prefer the old ones + if (param->channel_layout && (param->ch_layout.order != AV_CHANNEL_ORDER_NATIVE || + param->ch_layout.u.mask != param->channel_layout)) { + av_channel_layout_uninit(&s->ch_layout); + av_channel_layout_from_mask(&s->ch_layout, param->channel_layout); +FF_ENABLE_DEPRECATION_WARNINGS + } else +#endif + if (param->ch_layout.nb_channels) { + int ret = av_channel_layout_copy(&s->ch_layout, ¶m->ch_layout); + if (ret < 0) + return ret; + } break; default: return AVERROR_BUG; @@ -168,11 +181,15 @@ int attribute_align_arg av_buffersrc_add_frame_flags(AVFilterContext *ctx, AVFra AVFrame *copy; int refcounted, ret; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS if (frame && frame->channel_layout && av_get_channel_layout_nb_channels(frame->channel_layout) != frame->channels) { av_log(ctx, AV_LOG_ERROR, "Layout indicates a different number of channels than actually present\n"); return AVERROR(EINVAL); } +FF_ENABLE_DEPRECATION_WARNINGS +#endif s->nb_failed_requests = 0; @@ -192,10 +209,20 @@ int attribute_align_arg av_buffersrc_add_frame_flags(AVFilterContext *ctx, AVFra break; case AVMEDIA_TYPE_AUDIO: /* For layouts unknown on input but known on link after negotiation. */ +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS if (!frame->channel_layout) - frame->channel_layout = s->channel_layout; - CHECK_AUDIO_PARAM_CHANGE(ctx, s, frame->sample_rate, frame->channel_layout, - frame->channels, frame->format, frame->pts); + frame->channel_layout = s->ch_layout.order == AV_CHANNEL_ORDER_NATIVE ? + s->ch_layout.u.mask : 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + if (frame->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) { + ret = av_channel_layout_copy(&frame->ch_layout, &s->ch_layout); + if (ret < 0) + return ret; + } + CHECK_AUDIO_PARAM_CHANGE(ctx, s, frame->sample_rate, frame->ch_layout, + frame->format, frame->pts); break; default: return AVERROR(EINVAL); @@ -301,6 +328,7 @@ AVFILTER_DEFINE_CLASS(abuffer); static av_cold int init_audio(AVFilterContext *ctx) { BufferSourceContext *s = ctx->priv; + char buf[128]; int ret = 0; if (s->sample_fmt == AV_SAMPLE_FMT_NONE) { @@ -308,24 +336,39 @@ static av_cold int init_audio(AVFilterContext *ctx) return AVERROR(EINVAL); } - if (s->channel_layout_str || s->channel_layout) { + if (s->channel_layout_str || s->ch_layout.nb_channels) { int n; - if (!s->channel_layout) { - s->channel_layout = av_get_channel_layout(s->channel_layout_str); - if (!s->channel_layout) { - av_log(ctx, AV_LOG_ERROR, "Invalid channel layout %s.\n", + if (!s->ch_layout.nb_channels) { + ret = av_channel_layout_from_string(&s->ch_layout, s->channel_layout_str); + if (ret < 0) { +#if FF_API_OLD_CHANNEL_LAYOUT + uint64_t mask; +FF_DISABLE_DEPRECATION_WARNINGS + mask = av_get_channel_layout(s->channel_layout_str); + if (!mask) { +#endif + av_log(ctx, AV_LOG_ERROR, "Invalid channel layout %s.\n", + s->channel_layout_str); + return AVERROR(EINVAL); +#if FF_API_OLD_CHANNEL_LAYOUT + } +FF_ENABLE_DEPRECATION_WARNINGS + av_log(ctx, AV_LOG_WARNING, "Channel layout '%s' uses a deprecated syntax.\n", s->channel_layout_str); - return AVERROR(EINVAL); + av_channel_layout_from_mask(&s->ch_layout, mask); +#endif } } - n = av_get_channel_layout_nb_channels(s->channel_layout); + + n = s->ch_layout.nb_channels; + av_channel_layout_describe(&s->ch_layout, buf, sizeof(buf)); if (s->channels) { if (n != s->channels) { av_log(ctx, AV_LOG_ERROR, "Mismatching channel count %d and layout '%s' " "(%d channels)\n", - s->channels, s->channel_layout_str, n); + s->channels, buf, n); return AVERROR(EINVAL); } } @@ -334,6 +377,9 @@ static av_cold int init_audio(AVFilterContext *ctx) av_log(ctx, AV_LOG_ERROR, "Neither number of channels nor " "channel layout specified\n"); return AVERROR(EINVAL); + } else { + s->ch_layout = FF_COUNT2LAYOUT(s->channels); + av_channel_layout_describe(&s->ch_layout, buf, sizeof(buf)); } if (!s->time_base.num) @@ -342,7 +388,7 @@ static av_cold int init_audio(AVFilterContext *ctx) av_log(ctx, AV_LOG_VERBOSE, "tb:%d/%d samplefmt:%s samplerate:%d chlayout:%s\n", s->time_base.num, s->time_base.den, av_get_sample_fmt_name(s->sample_fmt), - s->sample_rate, s->channel_layout_str); + s->sample_rate, buf); return ret; } @@ -351,6 +397,7 @@ static av_cold void uninit(AVFilterContext *ctx) { BufferSourceContext *s = ctx->priv; av_buffer_unref(&s->hw_frames_ctx); + av_channel_layout_uninit(&s->ch_layout); } static int query_formats(AVFilterContext *ctx) @@ -374,9 +421,7 @@ static int query_formats(AVFilterContext *ctx) (ret = ff_set_common_samplerates (ctx , samplerates )) < 0) return ret; - if ((ret = ff_add_channel_layout(&channel_layouts, - c->channel_layout ? c->channel_layout : - FF_COUNT2LAYOUT(c->channels))) < 0) + if ((ret = ff_add_channel_layout(&channel_layouts, &c->ch_layout)) < 0) return ret; if ((ret = ff_set_common_channel_layouts(ctx, channel_layouts)) < 0) return ret; @@ -405,8 +450,11 @@ static int config_props(AVFilterLink *link) } break; case AVMEDIA_TYPE_AUDIO: - if (!c->channel_layout) - c->channel_layout = link->channel_layout; + if (!c->ch_layout.nb_channels) { + int ret = av_channel_layout_copy(&c->ch_layout, &link->ch_layout); + if (ret < 0) + return ret; + } break; default: return AVERROR(EINVAL); diff --git a/libavfilter/buffersrc.h b/libavfilter/buffersrc.h index 08fbd18a4..3b248b37c 100644 --- a/libavfilter/buffersrc.h +++ b/libavfilter/buffersrc.h @@ -110,10 +110,19 @@ typedef struct AVBufferSrcParameters { */ int sample_rate; +#if FF_API_OLD_CHANNEL_LAYOUT + /** + * Audio only, the audio channel layout + * @deprecated use ch_layout + */ + attribute_deprecated + uint64_t channel_layout; +#endif + /** * Audio only, the audio channel layout */ - uint64_t channel_layout; + AVChannelLayout ch_layout; } AVBufferSrcParameters; /** diff --git a/libavfilter/colorchannelmixer_template.c b/libavfilter/colorchannelmixer_template.c new file mode 100644 index 000000000..bef57476a --- /dev/null +++ b/libavfilter/colorchannelmixer_template.c @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2013 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 + +#undef pixel +#undef cpixel +#undef ROUND +#if DEPTH == 8 +#define pixel uint8_t +#define cpixel int +#define ROUND lrintf +#elif DEPTH == 16 +#define pixel uint16_t +#define cpixel int +#define ROUND lrintf +#else +#define NOP(x) (x) +#define pixel float +#define cpixel float +#define ROUND NOP +#endif + +#undef fn +#undef fn2 +#undef fn3 +#define fn3(a,b) a##_##b +#define fn2(a,b) fn3(a,b) +#define fn(a) fn2(a, DEPTH) + +static av_always_inline int fn(filter_slice_rgba_planar)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs, + int have_alpha, int depth, int pc) +{ + ColorChannelMixerContext *s = ctx->priv; + ThreadData *td = arg; + AVFrame *in = td->in; + AVFrame *out = td->out; + const float pa = s->preserve_amount; + const float max = (1 << depth) - 1; + const int slice_start = (out->height * jobnr) / nb_jobs; + const int slice_end = (out->height * (jobnr+1)) / nb_jobs; + const pixel *srcg = (const pixel *)(in->data[0] + slice_start * in->linesize[0]); + const pixel *srcb = (const pixel *)(in->data[1] + slice_start * in->linesize[1]); + const pixel *srcr = (const pixel *)(in->data[2] + slice_start * in->linesize[2]); + const pixel *srca = (const pixel *)(in->data[3] + slice_start * in->linesize[3]); + pixel *dstg = (pixel *)(out->data[0] + slice_start * out->linesize[0]); + pixel *dstb = (pixel *)(out->data[1] + slice_start * out->linesize[1]); + pixel *dstr = (pixel *)(out->data[2] + slice_start * out->linesize[2]); + pixel *dsta = (pixel *)(out->data[3] + slice_start * out->linesize[3]); + + for (int i = slice_start; i < slice_end; i++) { + for (int j = 0; j < out->width; j++) { + const pixel rin = srcr[j]; + const pixel gin = srcg[j]; + const pixel bin = srcb[j]; + const pixel ain = have_alpha ? srca[j] : 0; + cpixel rout, gout, bout; + +#if DEPTH == 32 + rout = s->rr * rin + + s->rg * gin + + s->rb * bin + + (have_alpha == 1 ? s->ra * ain : 0); + gout = s->gr * rin + + s->gg * gin + + s->gb * bin + + (have_alpha == 1 ? s->ga * ain : 0); + bout = s->br * rin + + s->bg * gin + + s->bb * bin + + (have_alpha == 1 ? s->ba * ain : 0); +#else + rout = s->lut[R][R][rin] + + s->lut[R][G][gin] + + s->lut[R][B][bin] + + (have_alpha == 1 ? s->lut[R][A][ain] : 0); + gout = s->lut[G][R][rin] + + s->lut[G][G][gin] + + s->lut[G][B][bin] + + (have_alpha == 1 ? s->lut[G][A][ain] : 0); + bout = s->lut[B][R][rin] + + s->lut[B][G][gin] + + s->lut[B][B][bin] + + (have_alpha == 1 ? s->lut[B][A][ain] : 0); +#endif + + if (pc) { + float frout, fgout, fbout, lin, lout; + +#if DEPTH < 32 + frout = av_clipf(rout, 0.f, max); + fgout = av_clipf(gout, 0.f, max); + fbout = av_clipf(bout, 0.f, max); +#else + frout = rout; + fgout = gout; + fbout = bout; +#endif + + preserve_color(s->preserve_color, rin, gin, bin, + rout, gout, bout, max, &lin, &lout); + preservel(&frout, &fgout, &fbout, lin, lout, max); + + rout = ROUND(lerpf(rout, frout, pa)); + gout = ROUND(lerpf(gout, fgout, pa)); + bout = ROUND(lerpf(bout, fbout, pa)); + } + +#if DEPTH < 32 + dstr[j] = av_clip_uintp2(rout, depth); + dstg[j] = av_clip_uintp2(gout, depth); + dstb[j] = av_clip_uintp2(bout, depth); +#else + dstr[j] = rout; + dstg[j] = gout; + dstb[j] = bout; +#endif + + if (have_alpha == 1) { +#if DEPTH < 32 + dsta[j] = av_clip_uintp2(s->lut[A][R][rin] + + s->lut[A][G][gin] + + s->lut[A][B][bin] + + s->lut[A][A][ain], depth); +#else + dsta[j] = s->ar * rin + + s->ag * gin + + s->ab * bin + + s->aa * ain; +#endif + } + } + + srcg += in->linesize[0] / sizeof(pixel); + srcb += in->linesize[1] / sizeof(pixel); + srcr += in->linesize[2] / sizeof(pixel); + srca += in->linesize[3] / sizeof(pixel); + dstg += out->linesize[0] / sizeof(pixel); + dstb += out->linesize[1] / sizeof(pixel); + dstr += out->linesize[2] / sizeof(pixel); + dsta += out->linesize[3] / sizeof(pixel); + } + + return 0; +} + +#if DEPTH < 32 + +static av_always_inline int fn(filter_slice_rgba_packed)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs, + int have_alpha, int step, int pc, int depth) +{ + ColorChannelMixerContext *s = ctx->priv; + ThreadData *td = arg; + AVFrame *in = td->in; + AVFrame *out = td->out; + const float pa = s->preserve_amount; + const float max = (1 << depth) - 1; + const int slice_start = (out->height * jobnr) / nb_jobs; + const int slice_end = (out->height * (jobnr+1)) / nb_jobs; + const uint8_t roffset = s->rgba_map[R]; + const uint8_t goffset = s->rgba_map[G]; + const uint8_t boffset = s->rgba_map[B]; + const uint8_t aoffset = s->rgba_map[A]; + const uint8_t *srcrow = in->data[0] + slice_start * in->linesize[0]; + uint8_t *dstrow = out->data[0] + slice_start * out->linesize[0]; + int i, j; + + for (i = slice_start; i < slice_end; i++) { + const pixel *src = (const pixel *)srcrow; + pixel *dst = (pixel *)dstrow; + + for (j = 0; j < out->width * step; j += step) { + const pixel rin = src[j + roffset]; + const pixel gin = src[j + goffset]; + const pixel bin = src[j + boffset]; + const pixel ain = src[j + aoffset]; + int rout, gout, bout; + + rout = s->lut[R][R][rin] + + s->lut[R][G][gin] + + s->lut[R][B][bin] + + (have_alpha == 1 ? s->lut[R][A][ain] : 0); + gout = s->lut[G][R][rin] + + s->lut[G][G][gin] + + s->lut[G][B][bin] + + (have_alpha == 1 ? s->lut[G][A][ain] : 0); + bout = s->lut[B][R][rin] + + s->lut[B][G][gin] + + s->lut[B][B][bin] + + (have_alpha == 1 ? s->lut[B][A][ain] : 0); + + if (pc) { + float frout = av_clipf(rout, 0.f, max); + float fgout = av_clipf(gout, 0.f, max); + float fbout = av_clipf(bout, 0.f, max); + float lin, lout; + + preserve_color(s->preserve_color, rin, gin, bin, + rout, gout, bout, max, &lin, &lout); + preservel(&frout, &fgout, &fbout, lin, lout, max); + + rout = lrintf(lerpf(rout, frout, pa)); + gout = lrintf(lerpf(gout, fgout, pa)); + bout = lrintf(lerpf(bout, fbout, pa)); + } + + dst[j + roffset] = av_clip_uintp2(rout, depth); + dst[j + goffset] = av_clip_uintp2(gout, depth); + dst[j + boffset] = av_clip_uintp2(bout, depth); + + if (have_alpha == 1) { + dst[j + aoffset] = av_clip_uintp2(s->lut[A][R][rin] + + s->lut[A][G][gin] + + s->lut[A][B][bin] + + s->lut[A][A][ain], depth); + } + } + + srcrow += in->linesize[0]; + dstrow += out->linesize[0]; + } + + return 0; +} + +#endif diff --git a/libavfilter/colorspace.c b/libavfilter/colorspace.c index 19616e4f1..f0bd14be1 100644 --- a/libavfilter/colorspace.c +++ b/libavfilter/colorspace.c @@ -62,27 +62,42 @@ void ff_matrix_mul_3x3(double dst[3][3], src2[m][1] * src1[1][n] + src2[m][2] * src1[2][n]; } + +void ff_matrix_mul_3x3_vec(double dst[3], const double vec[3], const double mat[3][3]) +{ + int m; + + for (m = 0; m < 3; m++) + dst[m] = vec[0] * mat[m][0] + + vec[1] * mat[m][1] + + vec[2] * mat[m][2]; +} + /* * see e.g. http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html */ -void ff_fill_rgb2xyz_table(const struct PrimaryCoefficients *coeffs, - const struct WhitepointCoefficients *wp, +void ff_fill_rgb2xyz_table(const AVPrimaryCoefficients *coeffs, + const AVWhitepointCoefficients *wp, double rgb2xyz[3][3]) { double i[3][3], sr, sg, sb, zw; + double xr = av_q2d(coeffs->r.x), yr = av_q2d(coeffs->r.y); + double xg = av_q2d(coeffs->g.x), yg = av_q2d(coeffs->g.y); + double xb = av_q2d(coeffs->b.x), yb = av_q2d(coeffs->b.y); + double xw = av_q2d(wp->x), yw = av_q2d(wp->y); - rgb2xyz[0][0] = coeffs->xr / coeffs->yr; - rgb2xyz[0][1] = coeffs->xg / coeffs->yg; - rgb2xyz[0][2] = coeffs->xb / coeffs->yb; + rgb2xyz[0][0] = xr / yr; + rgb2xyz[0][1] = xg / yg; + rgb2xyz[0][2] = xb / yb; rgb2xyz[1][0] = rgb2xyz[1][1] = rgb2xyz[1][2] = 1.0; - rgb2xyz[2][0] = (1.0 - coeffs->xr - coeffs->yr) / coeffs->yr; - rgb2xyz[2][1] = (1.0 - coeffs->xg - coeffs->yg) / coeffs->yg; - rgb2xyz[2][2] = (1.0 - coeffs->xb - coeffs->yb) / coeffs->yb; + rgb2xyz[2][0] = (1.0 - xr - yr) / yr; + rgb2xyz[2][1] = (1.0 - xg - yg) / yg; + rgb2xyz[2][2] = (1.0 - xb - yb) / yb; ff_matrix_invert_3x3(rgb2xyz, i); - zw = 1.0 - wp->xw - wp->yw; - sr = i[0][0] * wp->xw + i[0][1] * wp->yw + i[0][2] * zw; - sg = i[1][0] * wp->xw + i[1][1] * wp->yw + i[1][2] * zw; - sb = i[2][0] * wp->xw + i[2][1] * wp->yw + i[2][2] * zw; + zw = 1.0 - xw - yw; + sr = i[0][0] * xw + i[0][1] * yw + i[0][2] * zw; + sg = i[1][0] * xw + i[1][1] * yw + i[1][2] * zw; + sb = i[2][0] * xw + i[2][1] * yw + i[2][2] * zw; rgb2xyz[0][0] *= sr; rgb2xyz[0][1] *= sg; rgb2xyz[0][2] *= sb; @@ -107,62 +122,32 @@ static const double gbr_matrix[3][3] = { 0.5, -0.5, 0 }, }; -/* - * All constants explained in e.g. https://linuxtv.org/downloads/v4l-dvb-apis/ch02s06.html - * The older ones (bt470bg/m) are also explained in their respective ITU docs - * (e.g. https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.470-5-199802-S!!PDF-E.pdf) - * whereas the newer ones can typically be copied directly from wikipedia :) - */ -static const struct LumaCoefficients luma_coefficients[AVCOL_SPC_NB] = { - [AVCOL_SPC_FCC] = { 0.30, 0.59, 0.11 }, - [AVCOL_SPC_BT470BG] = { 0.299, 0.587, 0.114 }, - [AVCOL_SPC_SMPTE170M] = { 0.299, 0.587, 0.114 }, - [AVCOL_SPC_BT709] = { 0.2126, 0.7152, 0.0722 }, - [AVCOL_SPC_SMPTE240M] = { 0.212, 0.701, 0.087 }, - [AVCOL_SPC_YCOCG] = { 0.25, 0.5, 0.25 }, - [AVCOL_SPC_RGB] = { 1, 1, 1 }, - [AVCOL_SPC_BT2020_NCL] = { 0.2627, 0.6780, 0.0593 }, - [AVCOL_SPC_BT2020_CL] = { 0.2627, 0.6780, 0.0593 }, -}; - -const struct LumaCoefficients *ff_get_luma_coefficients(enum AVColorSpace csp) -{ - const struct LumaCoefficients *coeffs; - - if (csp >= AVCOL_SPC_NB) - return NULL; - coeffs = &luma_coefficients[csp]; - if (!coeffs->cr) - return NULL; - - return coeffs; -} - -void ff_fill_rgb2yuv_table(const struct LumaCoefficients *coeffs, +void ff_fill_rgb2yuv_table(const AVLumaCoefficients *coeffs, double rgb2yuv[3][3]) { double bscale, rscale; + double cr = av_q2d(coeffs->cr), cg = av_q2d(coeffs->cg), cb = av_q2d(coeffs->cb); // special ycgco matrix - if (coeffs->cr == 0.25 && coeffs->cg == 0.5 && coeffs->cb == 0.25) { + if (cr == 0.25 && cg == 0.5 && cb == 0.25) { memcpy(rgb2yuv, ycgco_matrix, sizeof(double) * 9); return; - } else if (coeffs->cr == 1 && coeffs->cg == 1 && coeffs->cb == 1) { + } else if (cr == 1 && cg == 1 && cb == 1) { memcpy(rgb2yuv, gbr_matrix, sizeof(double) * 9); return; } - rgb2yuv[0][0] = coeffs->cr; - rgb2yuv[0][1] = coeffs->cg; - rgb2yuv[0][2] = coeffs->cb; - bscale = 0.5 / (coeffs->cb - 1.0); - rscale = 0.5 / (coeffs->cr - 1.0); - rgb2yuv[1][0] = bscale * coeffs->cr; - rgb2yuv[1][1] = bscale * coeffs->cg; + rgb2yuv[0][0] = cr; + rgb2yuv[0][1] = cg; + rgb2yuv[0][2] = cb; + bscale = 0.5 / (cb - 1.0); + rscale = 0.5 / (cr - 1.0); + rgb2yuv[1][0] = bscale * cr; + rgb2yuv[1][1] = bscale * cg; rgb2yuv[1][2] = 0.5; rgb2yuv[2][0] = 0.5; - rgb2yuv[2][1] = rscale * coeffs->cg; - rgb2yuv[2][2] = rscale * coeffs->cb; + rgb2yuv[2][1] = rscale * cg; + rgb2yuv[2][2] = rscale * cb; } double ff_determine_signal_peak(AVFrame *in) diff --git a/libavfilter/colorspace.h b/libavfilter/colorspace.h index 459a5df60..4d98b1da2 100644 --- a/libavfilter/colorspace.h +++ b/libavfilter/colorspace.h @@ -20,34 +20,21 @@ #ifndef AVFILTER_COLORSPACE_H #define AVFILTER_COLORSPACE_H -#include "libavutil/common.h" +#include "libavutil/csp.h" #include "libavutil/frame.h" +#include "libavutil/pixfmt.h" #define REFERENCE_WHITE 100.0f -struct LumaCoefficients { - double cr, cg, cb; -}; - -struct PrimaryCoefficients { - double xr, yr, xg, yg, xb, yb; -}; - -struct WhitepointCoefficients { - double xw, yw; -}; - void ff_matrix_invert_3x3(const double in[3][3], double out[3][3]); void ff_matrix_mul_3x3(double dst[3][3], const double src1[3][3], const double src2[3][3]); -void ff_fill_rgb2xyz_table(const struct PrimaryCoefficients *coeffs, - const struct WhitepointCoefficients *wp, +void ff_matrix_mul_3x3_vec(double dst[3], const double vec[3], const double mat[3][3]); +void ff_fill_rgb2xyz_table(const AVPrimaryCoefficients *coeffs, + const AVWhitepointCoefficients *wp, double rgb2xyz[3][3]); - -const struct LumaCoefficients *ff_get_luma_coefficients(enum AVColorSpace csp); -void ff_fill_rgb2yuv_table(const struct LumaCoefficients *coeffs, +void ff_fill_rgb2yuv_table(const AVLumaCoefficients *coeffs, double rgb2yuv[3][3]); - double ff_determine_signal_peak(AVFrame *in); void ff_update_hdr_metadata(AVFrame *in, double peak); diff --git a/libavfilter/colorspacedsp.c b/libavfilter/colorspacedsp.c index b8ba5c06e..72207ffaf 100644 --- a/libavfilter/colorspacedsp.c +++ b/libavfilter/colorspacedsp.c @@ -18,6 +18,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/common.h" #include "colorspacedsp.h" /* @@ -142,6 +143,7 @@ void ff_colorspacedsp_init(ColorSpaceDSPContext *dsp) dsp->multiply3x3 = multiply3x3_c; - if (ARCH_X86) - ff_colorspacedsp_x86_init(dsp); +#if ARCH_X86 + ff_colorspacedsp_x86_init(dsp); +#endif } diff --git a/libavfilter/dnn/dnn_backend_common.c b/libavfilter/dnn/dnn_backend_common.c index 6a9c4cc87..91a4a3c4b 100644 --- a/libavfilter/dnn/dnn_backend_common.c +++ b/libavfilter/dnn/dnn_backend_common.c @@ -47,19 +47,19 @@ int ff_check_exec_params(void *ctx, DNNBackendType backend, DNNFunctionType func // currently, the filter does not need multiple outputs, // so we just pending the support until we really need it. avpriv_report_missing_feature(ctx, "multiple outputs"); - return AVERROR(EINVAL); + return AVERROR(ENOSYS); } return 0; } -DNNReturnType ff_dnn_fill_task(TaskItem *task, DNNExecBaseParams *exec_params, void *backend_model, int async, int do_ioproc) { +int ff_dnn_fill_task(TaskItem *task, DNNExecBaseParams *exec_params, void *backend_model, int async, int do_ioproc) { if (task == NULL || exec_params == NULL || backend_model == NULL) - return DNN_ERROR; + return AVERROR(EINVAL); if (do_ioproc != 0 && do_ioproc != 1) - return DNN_ERROR; + return AVERROR(EINVAL); if (async != 0 && async != 1) - return DNN_ERROR; + return AVERROR(EINVAL); task->do_ioproc = do_ioproc; task->async = async; @@ -70,7 +70,7 @@ DNNReturnType ff_dnn_fill_task(TaskItem *task, DNNExecBaseParams *exec_params, v task->nb_output = exec_params->nb_output; task->output_names = exec_params->output_names; - return DNN_SUCCESS; + return 0; } /** @@ -82,60 +82,61 @@ static void *async_thread_routine(void *args) DNNAsyncExecModule *async_module = args; void *request = async_module->args; - if (async_module->start_inference(request) != DNN_SUCCESS) { + if (async_module->start_inference(request) != 0) { return DNN_ASYNC_FAIL; } async_module->callback(request); return DNN_ASYNC_SUCCESS; } -DNNReturnType ff_dnn_async_module_cleanup(DNNAsyncExecModule *async_module) +int ff_dnn_async_module_cleanup(DNNAsyncExecModule *async_module) { void *status = 0; if (!async_module) { - return DNN_ERROR; + return AVERROR(EINVAL); } #if HAVE_PTHREAD_CANCEL pthread_join(async_module->thread_id, &status); if (status == DNN_ASYNC_FAIL) { av_log(NULL, AV_LOG_ERROR, "Last Inference Failed.\n"); - return DNN_ERROR; + return DNN_GENERIC_ERROR; } #endif async_module->start_inference = NULL; async_module->callback = NULL; async_module->args = NULL; - return DNN_SUCCESS; + return 0; } -DNNReturnType ff_dnn_start_inference_async(void *ctx, DNNAsyncExecModule *async_module) +int ff_dnn_start_inference_async(void *ctx, DNNAsyncExecModule *async_module) { int ret; void *status = 0; if (!async_module) { av_log(ctx, AV_LOG_ERROR, "async_module is null when starting async inference.\n"); - return DNN_ERROR; + return AVERROR(EINVAL); } #if HAVE_PTHREAD_CANCEL pthread_join(async_module->thread_id, &status); if (status == DNN_ASYNC_FAIL) { av_log(ctx, AV_LOG_ERROR, "Unable to start inference as previous inference failed.\n"); - return DNN_ERROR; + return DNN_GENERIC_ERROR; } ret = pthread_create(&async_module->thread_id, NULL, async_thread_routine, async_module); if (ret != 0) { av_log(ctx, AV_LOG_ERROR, "Unable to start async inference.\n"); - return DNN_ERROR; + return ret; } #else - if (async_module->start_inference(async_module->args) != DNN_SUCCESS) { - return DNN_ERROR; + ret = async_module->start_inference(async_module->args); + if (ret != 0) { + return ret; } async_module->callback(async_module->args); #endif - return DNN_SUCCESS; + return 0; } DNNAsyncStatusType ff_dnn_get_result_common(Queue *task_queue, AVFrame **in, AVFrame **out) @@ -158,7 +159,7 @@ DNNAsyncStatusType ff_dnn_get_result_common(Queue *task_queue, AVFrame **in, AVF return DAST_SUCCESS; } -DNNReturnType ff_dnn_fill_gettingoutput_task(TaskItem *task, DNNExecBaseParams *exec_params, void *backend_model, int input_height, int input_width, void *ctx) +int ff_dnn_fill_gettingoutput_task(TaskItem *task, DNNExecBaseParams *exec_params, void *backend_model, int input_height, int input_width, void *ctx) { AVFrame *in_frame = NULL; AVFrame *out_frame = NULL; @@ -166,14 +167,14 @@ DNNReturnType ff_dnn_fill_gettingoutput_task(TaskItem *task, DNNExecBaseParams * in_frame = av_frame_alloc(); if (!in_frame) { av_log(ctx, AV_LOG_ERROR, "Failed to allocate memory for input frame\n"); - return DNN_ERROR; + return AVERROR(ENOMEM); } out_frame = av_frame_alloc(); if (!out_frame) { av_frame_free(&in_frame); av_log(ctx, AV_LOG_ERROR, "Failed to allocate memory for output frame\n"); - return DNN_ERROR; + return AVERROR(ENOMEM); } in_frame->width = input_width; diff --git a/libavfilter/dnn/dnn_backend_common.h b/libavfilter/dnn/dnn_backend_common.h index 6b6a5e21a..42c67c704 100644 --- a/libavfilter/dnn/dnn_backend_common.h +++ b/libavfilter/dnn/dnn_backend_common.h @@ -60,7 +60,7 @@ typedef struct DNNAsyncExecModule { * Synchronous inference function for the backend * with corresponding request item as the argument. */ - DNNReturnType (*start_inference)(void *request); + int (*start_inference)(void *request); /** * Completion Callback for the backend. @@ -92,20 +92,18 @@ int ff_check_exec_params(void *ctx, DNNBackendType backend, DNNFunctionType func * @param async flag for async execution. Must be 0 or 1 * @param do_ioproc flag for IO processing. Must be 0 or 1 * - * @retval DNN_SUCCESS if successful - * @retval DNN_ERROR if flags are invalid or any parameter is NULL + * @returns 0 if successful or error code otherwise. */ -DNNReturnType ff_dnn_fill_task(TaskItem *task, DNNExecBaseParams *exec_params, void *backend_model, int async, int do_ioproc); +int ff_dnn_fill_task(TaskItem *task, DNNExecBaseParams *exec_params, void *backend_model, int async, int do_ioproc); /** * Join the Async Execution thread and set module pointers to NULL. * * @param async_module pointer to DNNAsyncExecModule module * - * @retval DNN_SUCCESS if successful - * @retval DNN_ERROR if async_module is NULL + * @returns 0 if successful or error code otherwise. */ -DNNReturnType ff_dnn_async_module_cleanup(DNNAsyncExecModule *async_module); +int ff_dnn_async_module_cleanup(DNNAsyncExecModule *async_module); /** * Start asynchronous inference routine for the TensorFlow @@ -119,10 +117,9 @@ DNNReturnType ff_dnn_async_module_cleanup(DNNAsyncExecModule *async_module); * @param ctx pointer to the backend context * @param async_module pointer to DNNAsyncExecModule module * - * @retval DNN_SUCCESS on the start of async inference. - * @retval DNN_ERROR in case async inference cannot be started + * @returns 0 on the start of async inference or error code otherwise. */ -DNNReturnType ff_dnn_start_inference_async(void *ctx, DNNAsyncExecModule *async_module); +int ff_dnn_start_inference_async(void *ctx, DNNAsyncExecModule *async_module); /** * Extract input and output frame from the Task Queue after @@ -149,9 +146,8 @@ DNNAsyncStatusType ff_dnn_get_result_common(Queue *task_queue, AVFrame **in, AVF * @param input_width width of input frame * @param ctx pointer to the backend context * - * @retval DNN_SUCCESS if successful - * @retval DNN_ERROR if allocation fails + * @returns 0 if successful or error code otherwise. */ -DNNReturnType ff_dnn_fill_gettingoutput_task(TaskItem *task, DNNExecBaseParams *exec_params, void *backend_model, int input_height, int input_width, void *ctx); +int ff_dnn_fill_gettingoutput_task(TaskItem *task, DNNExecBaseParams *exec_params, void *backend_model, int input_height, int input_width, void *ctx); #endif diff --git a/libavfilter/dnn/dnn_backend_native.c b/libavfilter/dnn/dnn_backend_native.c index 13436c048..b53799f04 100644 --- a/libavfilter/dnn/dnn_backend_native.c +++ b/libavfilter/dnn/dnn_backend_native.c @@ -46,9 +46,9 @@ static const AVClass dnn_native_class = { .category = AV_CLASS_CATEGORY_FILTER, }; -static DNNReturnType execute_model_native(Queue *lltask_queue); +static int execute_model_native(Queue *lltask_queue); -static DNNReturnType extract_lltask_from_task(TaskItem *task, Queue *lltask_queue) +static int extract_lltask_from_task(TaskItem *task, Queue *lltask_queue) { NativeModel *native_model = task->model; NativeContext *ctx = &native_model->ctx; @@ -56,7 +56,7 @@ static DNNReturnType extract_lltask_from_task(TaskItem *task, Queue *lltask_queu if (!lltask) { av_log(ctx, AV_LOG_ERROR, "Unable to allocate space for LastLevelTaskItem\n"); - return DNN_ERROR; + return AVERROR(ENOMEM); } task->inference_todo = 1; task->inference_done = 0; @@ -65,12 +65,12 @@ static DNNReturnType extract_lltask_from_task(TaskItem *task, Queue *lltask_queu if (ff_queue_push_back(lltask_queue, lltask) < 0) { av_log(ctx, AV_LOG_ERROR, "Failed to push back lltask_queue.\n"); av_freep(&lltask); - return DNN_ERROR; + return AVERROR(ENOMEM); } - return DNN_SUCCESS; + return 0; } -static DNNReturnType get_input_native(void *model, DNNData *input, const char *input_name) +static int get_input_native(void *model, DNNData *input, const char *input_name) { NativeModel *native_model = model; NativeContext *ctx = &native_model->ctx; @@ -80,26 +80,26 @@ static DNNReturnType get_input_native(void *model, DNNData *input, const char *i if (strcmp(oprd->name, input_name) == 0) { if (oprd->type != DOT_INPUT) { av_log(ctx, AV_LOG_ERROR, "Found \"%s\" in model, but it is not input node\n", input_name); - return DNN_ERROR; + return AVERROR(EINVAL); } input->dt = oprd->data_type; av_assert0(oprd->dims[0] == 1); input->height = oprd->dims[1]; input->width = oprd->dims[2]; input->channels = oprd->dims[3]; - return DNN_SUCCESS; + return 0; } } // do not find the input operand av_log(ctx, AV_LOG_ERROR, "Could not find \"%s\" in model\n", input_name); - return DNN_ERROR; + return AVERROR(EINVAL); } -static DNNReturnType get_output_native(void *model, const char *input_name, int input_width, int input_height, +static int get_output_native(void *model, const char *input_name, int input_width, int input_height, const char *output_name, int *output_width, int *output_height) { - DNNReturnType ret = 0; + int ret = 0; NativeModel *native_model = model; NativeContext *ctx = &native_model->ctx; TaskItem task; @@ -111,14 +111,14 @@ static DNNReturnType get_output_native(void *model, const char *input_name, int .out_frame = NULL, }; - if (ff_dnn_fill_gettingoutput_task(&task, &exec_params, native_model, input_height, input_width, ctx) != DNN_SUCCESS) { - ret = DNN_ERROR; + ret = ff_dnn_fill_gettingoutput_task(&task, &exec_params, native_model, input_height, input_width, ctx); + if (ret != 0) { goto err; } - if (extract_lltask_from_task(&task, native_model->lltask_queue) != DNN_SUCCESS) { + ret = extract_lltask_from_task(&task, native_model->lltask_queue); + if (ret != 0) { av_log(ctx, AV_LOG_ERROR, "unable to extract last level task from task.\n"); - ret = DNN_ERROR; goto err; } @@ -297,7 +297,7 @@ fail: return NULL; } -static DNNReturnType execute_model_native(Queue *lltask_queue) +static int execute_model_native(Queue *lltask_queue) { NativeModel *native_model = NULL; NativeContext *ctx = NULL; @@ -306,12 +306,12 @@ static DNNReturnType execute_model_native(Queue *lltask_queue) DnnOperand *oprd = NULL; LastLevelTaskItem *lltask = NULL; TaskItem *task = NULL; - DNNReturnType ret = 0; + int ret = 0; lltask = ff_queue_pop_front(lltask_queue); if (!lltask) { av_log(NULL, AV_LOG_ERROR, "Failed to get LastLevelTaskItem\n"); - ret = DNN_ERROR; + ret = AVERROR(EINVAL); goto err; } task = lltask->task; @@ -320,7 +320,7 @@ static DNNReturnType execute_model_native(Queue *lltask_queue) if (native_model->layers_num <= 0 || native_model->operands_num <= 0) { av_log(ctx, AV_LOG_ERROR, "No operands or layers in model\n"); - ret = DNN_ERROR; + ret = AVERROR(EINVAL); goto err; } @@ -329,7 +329,7 @@ static DNNReturnType execute_model_native(Queue *lltask_queue) if (strcmp(oprd->name, task->input_name) == 0) { if (oprd->type != DOT_INPUT) { av_log(ctx, AV_LOG_ERROR, "Found \"%s\" in model, but it is not input node\n", task->input_name); - ret = DNN_ERROR; + ret = AVERROR(EINVAL); goto err; } break; @@ -338,7 +338,7 @@ static DNNReturnType execute_model_native(Queue *lltask_queue) } if (!oprd) { av_log(ctx, AV_LOG_ERROR, "Could not find \"%s\" in model\n", task->input_name); - ret = DNN_ERROR; + ret = AVERROR(EINVAL); goto err; } @@ -349,13 +349,13 @@ static DNNReturnType execute_model_native(Queue *lltask_queue) oprd->length = ff_calculate_operand_data_length(oprd); if (oprd->length <= 0) { av_log(ctx, AV_LOG_ERROR, "The input data length overflow\n"); - ret = DNN_ERROR; + ret = AVERROR(EINVAL); goto err; } oprd->data = av_malloc(oprd->length); if (!oprd->data) { av_log(ctx, AV_LOG_ERROR, "Failed to malloc memory for input data\n"); - ret = DNN_ERROR; + ret = AVERROR(ENOMEM); goto err; } @@ -376,19 +376,19 @@ static DNNReturnType execute_model_native(Queue *lltask_queue) // currently, the filter does not need multiple outputs, // so we just pending the support until we really need it. avpriv_report_missing_feature(ctx, "multiple outputs"); - ret = DNN_ERROR; + ret = AVERROR(ENOSYS); goto err; } for (layer = 0; layer < native_model->layers_num; ++layer){ DNNLayerType layer_type = native_model->layers[layer].type; - if (ff_layer_funcs[layer_type].pf_exec(native_model->operands, - native_model->layers[layer].input_operand_indexes, - native_model->layers[layer].output_operand_index, - native_model->layers[layer].params, - &native_model->ctx) == DNN_ERROR) { + ret = ff_layer_funcs[layer_type].pf_exec(native_model->operands, + native_model->layers[layer].input_operand_indexes, + native_model->layers[layer].output_operand_index, + native_model->layers[layer].params, + &native_model->ctx); + if (ret != 0) { av_log(ctx, AV_LOG_ERROR, "Failed to execute model\n"); - ret = DNN_ERROR; goto err; } } @@ -405,7 +405,7 @@ static DNNReturnType execute_model_native(Queue *lltask_queue) if (oprd == NULL) { av_log(ctx, AV_LOG_ERROR, "Could not find output in model\n"); - ret = DNN_ERROR; + ret = AVERROR(EINVAL); goto err; } @@ -432,48 +432,52 @@ err: return ret; } -DNNReturnType ff_dnn_execute_model_native(const DNNModel *model, DNNExecBaseParams *exec_params) +int ff_dnn_execute_model_native(const DNNModel *model, DNNExecBaseParams *exec_params) { NativeModel *native_model = model->model; NativeContext *ctx = &native_model->ctx; TaskItem *task; + int ret = 0; - if (ff_check_exec_params(ctx, DNN_NATIVE, model->func_type, exec_params) != 0) { - return DNN_ERROR; + ret = ff_check_exec_params(ctx, DNN_NATIVE, model->func_type, exec_params); + if (ret != 0) { + return ret; } task = av_malloc(sizeof(*task)); if (!task) { av_log(ctx, AV_LOG_ERROR, "unable to alloc memory for task item.\n"); - return DNN_ERROR; + return AVERROR(ENOMEM); } - if (ff_dnn_fill_task(task, exec_params, native_model, ctx->options.async, 1) != DNN_SUCCESS) { + ret = ff_dnn_fill_task(task, exec_params, native_model, ctx->options.async, 1); + if (ret != 0) { av_freep(&task); - return DNN_ERROR; + return ret; } if (ff_queue_push_back(native_model->task_queue, task) < 0) { av_freep(&task); av_log(ctx, AV_LOG_ERROR, "unable to push back task_queue.\n"); - return DNN_ERROR; + return AVERROR(ENOMEM); } - if (extract_lltask_from_task(task, native_model->lltask_queue) != DNN_SUCCESS) { + ret = extract_lltask_from_task(task, native_model->lltask_queue); + if (ret != 0) { av_log(ctx, AV_LOG_ERROR, "unable to extract last level task from task.\n"); - return DNN_ERROR; + return ret; } return execute_model_native(native_model->lltask_queue); } -DNNReturnType ff_dnn_flush_native(const DNNModel *model) +int ff_dnn_flush_native(const DNNModel *model) { NativeModel *native_model = model->model; if (ff_queue_size(native_model->lltask_queue) == 0) { // no pending task need to flush - return DNN_SUCCESS; + return 0; } // for now, use sync node with flush operation diff --git a/libavfilter/dnn/dnn_backend_native.h b/libavfilter/dnn/dnn_backend_native.h index e8017ee4b..75bd9a44f 100644 --- a/libavfilter/dnn/dnn_backend_native.h +++ b/libavfilter/dnn/dnn_backend_native.h @@ -134,11 +134,11 @@ typedef struct NativeModel{ DNNModel *ff_dnn_load_model_native(const char *model_filename, DNNFunctionType func_type, const char *options, AVFilterContext *filter_ctx); -DNNReturnType ff_dnn_execute_model_native(const DNNModel *model, DNNExecBaseParams *exec_params); +int ff_dnn_execute_model_native(const DNNModel *model, DNNExecBaseParams *exec_params); DNNAsyncStatusType ff_dnn_get_result_native(const DNNModel *model, AVFrame **in, AVFrame **out); -DNNReturnType ff_dnn_flush_native(const DNNModel *model); +int ff_dnn_flush_native(const DNNModel *model); void ff_dnn_free_model_native(DNNModel **model); diff --git a/libavfilter/dnn/dnn_backend_native_layer_avgpool.c b/libavfilter/dnn/dnn_backend_native_layer_avgpool.c index 89f178752..d6fcac8a3 100644 --- a/libavfilter/dnn/dnn_backend_native_layer_avgpool.c +++ b/libavfilter/dnn/dnn_backend_native_layer_avgpool.c @@ -109,12 +109,12 @@ int ff_dnn_execute_layer_avg_pool(DnnOperand *operands, const int32_t *input_ope output_operand->length = ff_calculate_operand_data_length(output_operand); if (output_operand->length <= 0) { av_log(ctx, AV_LOG_ERROR, "The output data length overflow\n"); - return DNN_ERROR; + return AVERROR(EINVAL); } output_operand->data = av_realloc(output_operand->data, output_operand->length); if (!output_operand->data) { av_log(ctx, AV_LOG_ERROR, "Failed to reallocate memory for output\n"); - return DNN_ERROR; + return AVERROR(ENOMEM); } output = output_operand->data; diff --git a/libavfilter/dnn/dnn_backend_native_layer_avgpool.h b/libavfilter/dnn/dnn_backend_native_layer_avgpool.h index d8972487d..118a16009 100644 --- a/libavfilter/dnn/dnn_backend_native_layer_avgpool.h +++ b/libavfilter/dnn/dnn_backend_native_layer_avgpool.h @@ -60,7 +60,8 @@ int ff_dnn_load_layer_avg_pool(Layer *layer, AVIOContext *model_file_context, in * @param parameters average pooling parameters * @param ctx pointer to Native model context for logging * @retval 0 if the execution succeeds - * @retval DNN_ERROR if the execution fails + * @retval AVERROR(ENOMEM) if memory allocation fails + * @retval AVERROR(EINVAL) for invalid arguments */ int ff_dnn_execute_layer_avg_pool(DnnOperand *operands, const int32_t *input_operand_indexes, int32_t output_operand_index, const void *parameters, NativeContext *ctx); diff --git a/libavfilter/dnn/dnn_backend_native_layer_conv2d.c b/libavfilter/dnn/dnn_backend_native_layer_conv2d.c index 7a60aa6a4..2ac37d885 100644 --- a/libavfilter/dnn/dnn_backend_native_layer_conv2d.c +++ b/libavfilter/dnn/dnn_backend_native_layer_conv2d.c @@ -190,7 +190,7 @@ int ff_dnn_execute_layer_conv2d(DnnOperand *operands, const int32_t *input_opera #if HAVE_PTHREAD_CANCEL int thread_num = (ctx->options.conv2d_threads <= 0 || ctx->options.conv2d_threads > av_cpu_count()) ? (av_cpu_count() + 1) : (ctx->options.conv2d_threads); - int ret = DNN_SUCCESS, thread_stride; + int ret = 0, thread_stride; ThreadParam *thread_param; #else ThreadParam thread_param = { 0 }; @@ -211,12 +211,12 @@ int ff_dnn_execute_layer_conv2d(DnnOperand *operands, const int32_t *input_opera output_operand->length = ff_calculate_operand_data_length(output_operand); if (output_operand->length <= 0) { av_log(ctx, AV_LOG_ERROR, "The output data length overflow\n"); - return DNN_ERROR; + return AVERROR(EINVAL); } tmp = av_realloc(output_operand->data, output_operand->length); if (!tmp) { av_log(ctx, AV_LOG_ERROR, "Failed to reallocate memory for output\n"); - return DNN_ERROR; + return AVERROR(ENOMEM); } output_operand->data = tmp; thread_common_param.output_data = output_operand->data; @@ -229,17 +229,19 @@ int ff_dnn_execute_layer_conv2d(DnnOperand *operands, const int32_t *input_opera #if HAVE_PTHREAD_CANCEL thread_param = av_malloc_array(thread_num, sizeof(*thread_param)); if (!thread_param) - return DNN_ERROR; + return AVERROR(ENOMEM); thread_stride = (height - pad_size * 2) / thread_num; //create threads for (int i = 0; i < thread_num; i++){ + int thread_ret = 0; thread_param[i].thread_common_param = &thread_common_param; thread_param[i].thread_start = thread_stride * i + pad_size; thread_param[i].thread_end = (i == thread_num - 1) ? (height - pad_size) : (thread_param[i].thread_start + thread_stride); - if (pthread_create(&thread_param[i].thread, NULL, - dnn_execute_layer_conv2d_thread, &thread_param[i])) { + thread_ret = pthread_create(&thread_param[i].thread, NULL, + dnn_execute_layer_conv2d_thread, &thread_param[i]); + if (thread_ret) { thread_num = i; - ret = DNN_ERROR; + ret = AVERROR(thread_ret); break; } } @@ -258,6 +260,6 @@ int ff_dnn_execute_layer_conv2d(DnnOperand *operands, const int32_t *input_opera thread_param.thread_end = height - pad_size; dnn_execute_layer_conv2d_thread(&thread_param); - return DNN_SUCCESS; + return 0; #endif } diff --git a/libavfilter/dnn/dnn_backend_native_layer_conv2d.h b/libavfilter/dnn/dnn_backend_native_layer_conv2d.h index 446f48f60..f754a9ba1 100644 --- a/libavfilter/dnn/dnn_backend_native_layer_conv2d.h +++ b/libavfilter/dnn/dnn_backend_native_layer_conv2d.h @@ -60,7 +60,8 @@ int ff_dnn_load_layer_conv2d(Layer *layer, AVIOContext *model_file_context, int * @param parameters convolution parameters * @param ctx pointer to Native model context for logging * @retval 0 if the execution succeeds - * @retval DNN_ERROR if the execution fails + * @retval AVERROR(ENOMEM) if memory allocation fails + * @retval AVERROR(EINVAL) for invalid arguments */ int ff_dnn_execute_layer_conv2d(DnnOperand *operands, const int32_t *input_operand_indexes, int32_t output_operand_index, const void *parameters, NativeContext *ctx); diff --git a/libavfilter/dnn/dnn_backend_native_layer_dense.c b/libavfilter/dnn/dnn_backend_native_layer_dense.c index 117590d7b..dff342c1f 100644 --- a/libavfilter/dnn/dnn_backend_native_layer_dense.c +++ b/libavfilter/dnn/dnn_backend_native_layer_dense.c @@ -104,12 +104,12 @@ int ff_dnn_execute_layer_dense(DnnOperand *operands, const int32_t *input_operan output_operand->length = ff_calculate_operand_data_length(output_operand); if (output_operand->length <= 0) { av_log(ctx, AV_LOG_ERROR, "The output data length overflow\n"); - return DNN_ERROR; + return AVERROR(EINVAL); } output_operand->data = av_realloc(output_operand->data, output_operand->length); if (!output_operand->data) { av_log(ctx, AV_LOG_ERROR, "Failed to reallocate memory for output\n"); - return DNN_ERROR; + return AVERROR(ENOMEM); } output = output_operand->data; diff --git a/libavfilter/dnn/dnn_backend_native_layer_dense.h b/libavfilter/dnn/dnn_backend_native_layer_dense.h index 0488b03cc..607fc3e68 100644 --- a/libavfilter/dnn/dnn_backend_native_layer_dense.h +++ b/libavfilter/dnn/dnn_backend_native_layer_dense.h @@ -57,7 +57,8 @@ int ff_dnn_load_layer_dense(Layer *layer, AVIOContext *model_file_context, int f * @param parameters dense layer parameters * @param ctx pointer to Native model context for logging * @retval 0 if the execution succeeds - * @retval DNN_ERROR if the execution fails + * @retval AVERROR(ENOMEM) if memory allocation fails + * @retval AVERROR(EINVAL) for invalid arguments */ int ff_dnn_execute_layer_dense(DnnOperand *operands, const int32_t *input_operand_indexes, int32_t output_operand_index, const void *parameters, NativeContext *ctx); diff --git a/libavfilter/dnn/dnn_backend_native_layer_depth2space.c b/libavfilter/dnn/dnn_backend_native_layer_depth2space.c index 30ced43cd..358ac3bca 100644 --- a/libavfilter/dnn/dnn_backend_native_layer_depth2space.c +++ b/libavfilter/dnn/dnn_backend_native_layer_depth2space.c @@ -76,12 +76,12 @@ int ff_dnn_execute_layer_depth2space(DnnOperand *operands, const int32_t *input_ output_operand->length = ff_calculate_operand_data_length(output_operand); if (output_operand->length <= 0) { av_log(ctx, AV_LOG_ERROR, "The output data length overflow\n"); - return DNN_ERROR; + return AVERROR(EINVAL); } output_operand->data = av_realloc(output_operand->data, output_operand->length); if (!output_operand->data) { av_log(ctx, AV_LOG_ERROR, "Failed to reallocate memory for output\n"); - return DNN_ERROR; + return AVERROR(ENOMEM); } output = output_operand->data; diff --git a/libavfilter/dnn/dnn_backend_native_layer_depth2space.h b/libavfilter/dnn/dnn_backend_native_layer_depth2space.h index 2792a33eb..aaf2df4c1 100644 --- a/libavfilter/dnn/dnn_backend_native_layer_depth2space.h +++ b/libavfilter/dnn/dnn_backend_native_layer_depth2space.h @@ -63,7 +63,8 @@ int ff_dnn_load_layer_depth2space(Layer *layer, AVIOContext *model_file_context, * @param parameters depth to space layer parameters * @param ctx pointer to Native model context for logging * @retval 0 if the execution succeeds - * @retval DNN_ERROR if the execution fails + * @retval AVERROR(ENOMEM) if memory allocation fails + * @retval AVERROR(EINVAL) for invalid arguments */ int ff_dnn_execute_layer_depth2space(DnnOperand *operands, const int32_t *input_operand_indexes, int32_t output_operand_index, const void *parameters, NativeContext *ctx); diff --git a/libavfilter/dnn/dnn_backend_native_layer_mathbinary.c b/libavfilter/dnn/dnn_backend_native_layer_mathbinary.c index 81901c56d..1a3fa3f13 100644 --- a/libavfilter/dnn/dnn_backend_native_layer_mathbinary.c +++ b/libavfilter/dnn/dnn_backend_native_layer_mathbinary.c @@ -159,12 +159,12 @@ int ff_dnn_execute_layer_math_binary(DnnOperand *operands, const int32_t *input_ output->length = ff_calculate_operand_data_length(output); if (output->length <= 0) { av_log(ctx, AV_LOG_ERROR, "The output data length overflow\n"); - return DNN_ERROR; + return AVERROR(EINVAL); } output->data = av_realloc(output->data, output->length); if (!output->data) { av_log(ctx, AV_LOG_ERROR, "Failed to reallocate memory for output\n"); - return DNN_ERROR; + return AVERROR(ENOMEM); } switch (params->bin_op) { @@ -188,6 +188,6 @@ int ff_dnn_execute_layer_math_binary(DnnOperand *operands, const int32_t *input_ return 0; default: av_log(ctx, AV_LOG_ERROR, "Unmatch math binary operator\n"); - return DNN_ERROR; + return AVERROR(EINVAL); } } diff --git a/libavfilter/dnn/dnn_backend_native_layer_mathunary.c b/libavfilter/dnn/dnn_backend_native_layer_mathunary.c index b8694910d..e3c5106e5 100644 --- a/libavfilter/dnn/dnn_backend_native_layer_mathunary.c +++ b/libavfilter/dnn/dnn_backend_native_layer_mathunary.c @@ -68,12 +68,12 @@ int ff_dnn_execute_layer_math_unary(DnnOperand *operands, const int32_t *input_o output->length = ff_calculate_operand_data_length(output); if (output->length <= 0) { av_log(ctx, AV_LOG_ERROR, "The output data length overflow\n"); - return DNN_ERROR; + return AVERROR(EINVAL); } output->data = av_realloc(output->data, output->length); if (!output->data) { av_log(ctx, AV_LOG_ERROR, "Failed to reallocate memory for output\n"); - return DNN_ERROR; + return AVERROR(ENOMEM); } dims_count = ff_calculate_operand_dims_count(output); @@ -151,6 +151,6 @@ int ff_dnn_execute_layer_math_unary(DnnOperand *operands, const int32_t *input_o return 0; default: av_log(ctx, AV_LOG_ERROR, "Unmatch math unary operator\n"); - return DNN_ERROR; + return AVERROR(EINVAL); } } diff --git a/libavfilter/dnn/dnn_backend_native_layer_mathunary.h b/libavfilter/dnn/dnn_backend_native_layer_mathunary.h index ed7994789..806e73b29 100644 --- a/libavfilter/dnn/dnn_backend_native_layer_mathunary.h +++ b/libavfilter/dnn/dnn_backend_native_layer_mathunary.h @@ -83,7 +83,8 @@ int ff_dnn_load_layer_math_unary(Layer *layer, AVIOContext *model_file_context, * @param parameters unary math layer parameters * @param ctx pointer to Native model context for logging * @retval 0 if the execution succeeds - * @retval DNN_ERROR if the execution fails + * @retval AVERROR(ENOMEM) if memory allocation fails + * @retval AVERROR(EINVAL) for invalid arguments */ int ff_dnn_execute_layer_math_unary(DnnOperand *operands, const int32_t *input_operand_indexes, int32_t output_operand_index, const void *parameters, NativeContext *ctx); diff --git a/libavfilter/dnn/dnn_backend_native_layer_maximum.c b/libavfilter/dnn/dnn_backend_native_layer_maximum.c index a38759eee..667efaa3b 100644 --- a/libavfilter/dnn/dnn_backend_native_layer_maximum.c +++ b/libavfilter/dnn/dnn_backend_native_layer_maximum.c @@ -65,12 +65,12 @@ int ff_dnn_execute_layer_maximum(DnnOperand *operands, const int32_t *input_oper output->length = ff_calculate_operand_data_length(output); if (output->length <= 0) { av_log(ctx, AV_LOG_ERROR, "The output data length overflow\n"); - return DNN_ERROR; + return AVERROR(EINVAL); } output->data = av_realloc(output->data, output->length); if (!output->data) { av_log(ctx, AV_LOG_ERROR, "Failed to reallocate memory for output\n"); - return DNN_ERROR; + return AVERROR(ENOMEM); } dims_count = ff_calculate_operand_dims_count(output); diff --git a/libavfilter/dnn/dnn_backend_native_layer_pad.c b/libavfilter/dnn/dnn_backend_native_layer_pad.c index a60451a8d..e274fe12c 100644 --- a/libavfilter/dnn/dnn_backend_native_layer_pad.c +++ b/libavfilter/dnn/dnn_backend_native_layer_pad.c @@ -113,12 +113,12 @@ int ff_dnn_execute_layer_pad(DnnOperand *operands, const int32_t *input_operand_ output_operand->length = ff_calculate_operand_data_length(output_operand); if (output_operand->length <= 0) { av_log(ctx, AV_LOG_ERROR, "The output data length overflow\n"); - return DNN_ERROR; + return AVERROR(EINVAL); } output_operand->data = av_realloc(output_operand->data, output_operand->length); if (!output_operand->data) { av_log(ctx, AV_LOG_ERROR, "Failed to reallocate memory for output\n"); - return DNN_ERROR; + return AVERROR(ENOMEM); } output = output_operand->data; diff --git a/libavfilter/dnn/dnn_backend_openvino.c b/libavfilter/dnn/dnn_backend_openvino.c index f5b1454d2..cf012aca4 100644 --- a/libavfilter/dnn/dnn_backend_openvino.c +++ b/libavfilter/dnn/dnn_backend_openvino.c @@ -112,7 +112,7 @@ static int get_datatype_size(DNNDataType dt) } } -static DNNReturnType fill_model_input_ov(OVModel *ov_model, OVRequestItem *request) +static int fill_model_input_ov(OVModel *ov_model, OVRequestItem *request) { dimensions_t dims; precision_e precision; @@ -131,7 +131,7 @@ static DNNReturnType fill_model_input_ov(OVModel *ov_model, OVRequestItem *reque status = ie_infer_request_get_blob(request->infer_request, task->input_name, &input_blob); if (status != OK) { av_log(ctx, AV_LOG_ERROR, "Failed to get input blob with name %s\n", task->input_name); - return DNN_ERROR; + return DNN_GENERIC_ERROR; } status |= ie_blob_get_dims(input_blob, &dims); @@ -139,14 +139,14 @@ static DNNReturnType fill_model_input_ov(OVModel *ov_model, OVRequestItem *reque if (status != OK) { ie_blob_free(&input_blob); av_log(ctx, AV_LOG_ERROR, "Failed to get input blob dims/precision\n"); - return DNN_ERROR; + return DNN_GENERIC_ERROR; } status = ie_blob_get_buffer(input_blob, &blob_buffer); if (status != OK) { ie_blob_free(&input_blob); av_log(ctx, AV_LOG_ERROR, "Failed to get input blob buffer\n"); - return DNN_ERROR; + return DNN_GENERIC_ERROR; } input.height = dims.dims[2]; @@ -191,7 +191,7 @@ static DNNReturnType fill_model_input_ov(OVModel *ov_model, OVRequestItem *reque } ie_blob_free(&input_blob); - return DNN_SUCCESS; + return 0; } static void infer_completion_callback(void *args) @@ -301,8 +301,9 @@ static void infer_completion_callback(void *args) } } -static DNNReturnType init_model_ov(OVModel *ov_model, const char *input_name, const char *output_name) +static int init_model_ov(OVModel *ov_model, const char *input_name, const char *output_name) { + int ret = 0; OVContext *ctx = &ov_model->ctx; IEStatusCode status; ie_available_devices_t a_dev; @@ -317,14 +318,18 @@ static DNNReturnType init_model_ov(OVModel *ov_model, const char *input_name, co if (ctx->options.batch_size > 1) { input_shapes_t input_shapes; status = ie_network_get_input_shapes(ov_model->network, &input_shapes); - if (status != OK) + if (status != OK) { + ret = DNN_GENERIC_ERROR; goto err; + } for (int i = 0; i < input_shapes.shape_num; i++) input_shapes.shapes[i].shape.dims[0] = ctx->options.batch_size; status = ie_network_reshape(ov_model->network, input_shapes); ie_network_input_shapes_free(&input_shapes); - if (status != OK) + if (status != OK) { + ret = DNN_GENERIC_ERROR; goto err; + } } // The order of dims in the openvino is fixed and it is always NCHW for 4-D data. @@ -332,11 +337,13 @@ static DNNReturnType init_model_ov(OVModel *ov_model, const char *input_name, co status = ie_network_set_input_layout(ov_model->network, input_name, NHWC); if (status != OK) { av_log(ctx, AV_LOG_ERROR, "Failed to set layout as NHWC for input %s\n", input_name); + ret = DNN_GENERIC_ERROR; goto err; } status = ie_network_set_output_layout(ov_model->network, output_name, NHWC); if (status != OK) { av_log(ctx, AV_LOG_ERROR, "Failed to set layout as NHWC for output %s\n", output_name); + ret = DNN_GENERIC_ERROR; goto err; } @@ -350,6 +357,7 @@ static DNNReturnType init_model_ov(OVModel *ov_model, const char *input_name, co status = ie_network_set_input_precision(ov_model->network, input_name, U8); if (status != OK) { av_log(ctx, AV_LOG_ERROR, "Failed to set input precision as U8 for %s\n", input_name); + ret = DNN_GENERIC_ERROR; goto err; } } @@ -360,6 +368,7 @@ static DNNReturnType init_model_ov(OVModel *ov_model, const char *input_name, co status = ie_core_get_available_devices(ov_model->core, &a_dev); if (status != OK) { av_log(ctx, AV_LOG_ERROR, "Failed to get available devices\n"); + ret = DNN_GENERIC_ERROR; goto err; } for (int i = 0; i < a_dev.num_devices; i++) { @@ -367,6 +376,7 @@ static DNNReturnType init_model_ov(OVModel *ov_model, const char *input_name, co } av_log(ctx, AV_LOG_ERROR,"device %s may not be supported, all available devices are: \"%s\"\n", ctx->options.device_type, all_dev_names); + ret = AVERROR(ENODEV); goto err; } @@ -378,12 +388,14 @@ static DNNReturnType init_model_ov(OVModel *ov_model, const char *input_name, co ov_model->request_queue = ff_safe_queue_create(); if (!ov_model->request_queue) { + ret = AVERROR(ENOMEM); goto err; } for (int i = 0; i < ctx->options.nireq; i++) { OVRequestItem *item = av_mallocz(sizeof(*item)); if (!item) { + ret = AVERROR(ENOMEM); goto err; } @@ -391,16 +403,19 @@ static DNNReturnType init_model_ov(OVModel *ov_model, const char *input_name, co item->callback.args = item; if (ff_safe_queue_push_back(ov_model->request_queue, item) < 0) { av_freep(&item); + ret = AVERROR(ENOMEM); goto err; } status = ie_exec_network_create_infer_request(ov_model->exe_network, &item->infer_request); if (status != OK) { + ret = DNN_GENERIC_ERROR; goto err; } item->lltasks = av_malloc_array(ctx->options.batch_size, sizeof(*item->lltasks)); if (!item->lltasks) { + ret = AVERROR(ENOMEM); goto err; } item->lltask_count = 0; @@ -408,26 +423,28 @@ static DNNReturnType init_model_ov(OVModel *ov_model, const char *input_name, co ov_model->task_queue = ff_queue_create(); if (!ov_model->task_queue) { + ret = AVERROR(ENOMEM); goto err; } ov_model->lltask_queue = ff_queue_create(); if (!ov_model->lltask_queue) { + ret = AVERROR(ENOMEM); goto err; } - return DNN_SUCCESS; + return 0; err: ff_dnn_free_model_ov(&ov_model->model); - return DNN_ERROR; + return ret; } -static DNNReturnType execute_model_ov(OVRequestItem *request, Queue *inferenceq) +static int execute_model_ov(OVRequestItem *request, Queue *inferenceq) { IEStatusCode status; - DNNReturnType ret; LastLevelTaskItem *lltask; + int ret = 0; TaskItem *task; OVContext *ctx; OVModel *ov_model; @@ -435,7 +452,7 @@ static DNNReturnType execute_model_ov(OVRequestItem *request, Queue *inferenceq) if (ff_queue_size(inferenceq) == 0) { ie_infer_request_free(&request->infer_request); av_freep(&request); - return DNN_SUCCESS; + return 0; } lltask = ff_queue_peek_front(inferenceq); @@ -445,42 +462,45 @@ static DNNReturnType execute_model_ov(OVRequestItem *request, Queue *inferenceq) if (task->async) { ret = fill_model_input_ov(ov_model, request); - if (ret != DNN_SUCCESS) { + if (ret != 0) { goto err; } status = ie_infer_set_completion_callback(request->infer_request, &request->callback); if (status != OK) { av_log(ctx, AV_LOG_ERROR, "Failed to set completion callback for inference\n"); + ret = DNN_GENERIC_ERROR; goto err; } status = ie_infer_request_infer_async(request->infer_request); if (status != OK) { av_log(ctx, AV_LOG_ERROR, "Failed to start async inference\n"); + ret = DNN_GENERIC_ERROR; goto err; } - return DNN_SUCCESS; + return 0; } else { ret = fill_model_input_ov(ov_model, request); - if (ret != DNN_SUCCESS) { + if (ret != 0) { goto err; } status = ie_infer_request_infer(request->infer_request); if (status != OK) { av_log(ctx, AV_LOG_ERROR, "Failed to start synchronous model inference\n"); + ret = DNN_GENERIC_ERROR; goto err; } infer_completion_callback(request); - return (task->inference_done == task->inference_todo) ? DNN_SUCCESS : DNN_ERROR; + return (task->inference_done == task->inference_todo) ? 0 : DNN_GENERIC_ERROR; } err: if (ff_safe_queue_push_back(ov_model->request_queue, request) < 0) { ie_infer_request_free(&request->infer_request); av_freep(&request); } - return DNN_ERROR; + return ret; } -static DNNReturnType get_input_ov(void *model, DNNData *input, const char *input_name) +static int get_input_ov(void *model, DNNData *input, const char *input_name) { OVModel *ov_model = model; OVContext *ctx = &ov_model->ctx; @@ -495,14 +515,14 @@ static DNNReturnType get_input_ov(void *model, DNNData *input, const char *input status = ie_network_get_inputs_number(ov_model->network, &model_input_count); if (status != OK) { av_log(ctx, AV_LOG_ERROR, "Failed to get input count\n"); - return DNN_ERROR; + return DNN_GENERIC_ERROR; } for (size_t i = 0; i < model_input_count; i++) { status = ie_network_get_input_name(ov_model->network, i, &model_input_name); if (status != OK) { av_log(ctx, AV_LOG_ERROR, "Failed to get No.%d input's name\n", (int)i); - return DNN_ERROR; + return DNN_GENERIC_ERROR; } if (strcmp(model_input_name, input_name) == 0) { ie_network_name_free(&model_input_name); @@ -510,14 +530,14 @@ static DNNReturnType get_input_ov(void *model, DNNData *input, const char *input status |= ie_network_get_input_precision(ov_model->network, input_name, &precision); if (status != OK) { av_log(ctx, AV_LOG_ERROR, "Failed to get No.%d input's dims or precision\n", (int)i); - return DNN_ERROR; + return DNN_GENERIC_ERROR; } input->channels = dims.dims[1]; input->height = input_resizable ? -1 : dims.dims[2]; input->width = input_resizable ? -1 : dims.dims[3]; input->dt = precision_to_datatype(precision); - return DNN_SUCCESS; + return 0; } else { //incorrect input name APPEND_STRING(all_input_names, model_input_name) @@ -527,7 +547,7 @@ static DNNReturnType get_input_ov(void *model, DNNData *input, const char *input } av_log(ctx, AV_LOG_ERROR, "Could not find \"%s\" in model, all input(s) are: \"%s\"\n", input_name, all_input_names); - return DNN_ERROR; + return AVERROR(EINVAL); } static int contain_valid_detection_bbox(AVFrame *frame) @@ -567,7 +587,7 @@ static int contain_valid_detection_bbox(AVFrame *frame) return 1; } -static DNNReturnType extract_lltask_from_task(DNNFunctionType func_type, TaskItem *task, Queue *lltask_queue, DNNExecBaseParams *exec_params) +static int extract_lltask_from_task(DNNFunctionType func_type, TaskItem *task, Queue *lltask_queue, DNNExecBaseParams *exec_params) { switch (func_type) { case DFT_PROCESS_FRAME: @@ -575,16 +595,16 @@ static DNNReturnType extract_lltask_from_task(DNNFunctionType func_type, TaskIte { LastLevelTaskItem *lltask = av_malloc(sizeof(*lltask)); if (!lltask) { - return DNN_ERROR; + return AVERROR(ENOMEM); } task->inference_todo = 1; task->inference_done = 0; lltask->task = task; if (ff_queue_push_back(lltask_queue, lltask) < 0) { av_freep(&lltask); - return DNN_ERROR; + return AVERROR(ENOMEM); } - return DNN_SUCCESS; + return 0; } case DFT_ANALYTICS_CLASSIFY: { @@ -597,7 +617,7 @@ static DNNReturnType extract_lltask_from_task(DNNFunctionType func_type, TaskIte task->inference_done = 0; if (!contain_valid_detection_bbox(frame)) { - return DNN_SUCCESS; + return 0; } sd = av_frame_get_side_data(frame, AV_FRAME_DATA_DETECTION_BBOXES); @@ -615,28 +635,28 @@ static DNNReturnType extract_lltask_from_task(DNNFunctionType func_type, TaskIte lltask = av_malloc(sizeof(*lltask)); if (!lltask) { - return DNN_ERROR; + return AVERROR(ENOMEM); } task->inference_todo++; lltask->task = task; lltask->bbox_index = i; if (ff_queue_push_back(lltask_queue, lltask) < 0) { av_freep(&lltask); - return DNN_ERROR; + return AVERROR(ENOMEM); } } - return DNN_SUCCESS; + return 0; } default: av_assert0(!"should not reach here"); - return DNN_ERROR; + return AVERROR(EINVAL); } } -static DNNReturnType get_output_ov(void *model, const char *input_name, int input_width, int input_height, +static int get_output_ov(void *model, const char *input_name, int input_width, int input_height, const char *output_name, int *output_width, int *output_height) { - DNNReturnType ret; + int ret; OVModel *ov_model = model; OVContext *ctx = &ov_model->ctx; TaskItem task; @@ -653,7 +673,7 @@ static DNNReturnType get_output_ov(void *model, const char *input_name, int inpu if (ov_model->model->func_type != DFT_PROCESS_FRAME) { av_log(ctx, AV_LOG_ERROR, "Get output dim only when processing frame.\n"); - return DNN_ERROR; + return AVERROR(EINVAL); } if (ctx->options.input_resizable) { @@ -664,31 +684,33 @@ static DNNReturnType get_output_ov(void *model, const char *input_name, int inpu ie_network_input_shapes_free(&input_shapes); if (status != OK) { av_log(ctx, AV_LOG_ERROR, "Failed to reshape input size for %s\n", input_name); - return DNN_ERROR; + return DNN_GENERIC_ERROR; } } if (!ov_model->exe_network) { - if (init_model_ov(ov_model, input_name, output_name) != DNN_SUCCESS) { + ret = init_model_ov(ov_model, input_name, output_name); + if (ret != 0) { av_log(ctx, AV_LOG_ERROR, "Failed init OpenVINO exectuable network or inference request\n"); - return DNN_ERROR; + return ret; } } - if (ff_dnn_fill_gettingoutput_task(&task, &exec_params, ov_model, input_height, input_width, ctx) != DNN_SUCCESS) { - return DNN_ERROR; + ret = ff_dnn_fill_gettingoutput_task(&task, &exec_params, ov_model, input_height, input_width, ctx); + if (ret != 0) { + goto err; } - if (extract_lltask_from_task(ov_model->model->func_type, &task, ov_model->lltask_queue, NULL) != DNN_SUCCESS) { - av_log(ctx, AV_LOG_ERROR, "unable to extract last level task from task.\n"); - ret = DNN_ERROR; + ret = extract_lltask_from_task(ov_model->model->func_type, &task, ov_model->lltask_queue, NULL); + if (ret != 0) { + av_log(ctx, AV_LOG_ERROR, "unable to extract inference from task.\n"); goto err; } request = ff_safe_queue_pop_front(ov_model->request_queue); if (!request) { av_log(ctx, AV_LOG_ERROR, "unable to get infer request.\n"); - ret = DNN_ERROR; + ret = AVERROR(EINVAL); goto err; } @@ -758,45 +780,49 @@ err: return NULL; } -DNNReturnType ff_dnn_execute_model_ov(const DNNModel *model, DNNExecBaseParams *exec_params) +int ff_dnn_execute_model_ov(const DNNModel *model, DNNExecBaseParams *exec_params) { OVModel *ov_model = model->model; OVContext *ctx = &ov_model->ctx; OVRequestItem *request; TaskItem *task; - DNNReturnType ret; + int ret; - if (ff_check_exec_params(ctx, DNN_OV, model->func_type, exec_params) != 0) { - return DNN_ERROR; + ret = ff_check_exec_params(ctx, DNN_OV, model->func_type, exec_params); + if (ret != 0) { + return ret; } if (!ov_model->exe_network) { - if (init_model_ov(ov_model, exec_params->input_name, exec_params->output_names[0]) != DNN_SUCCESS) { + ret = init_model_ov(ov_model, exec_params->input_name, exec_params->output_names[0]); + if (ret != 0) { av_log(ctx, AV_LOG_ERROR, "Failed init OpenVINO exectuable network or inference request\n"); - return DNN_ERROR; + return ret; } } task = av_malloc(sizeof(*task)); if (!task) { av_log(ctx, AV_LOG_ERROR, "unable to alloc memory for task item.\n"); - return DNN_ERROR; + return AVERROR(ENOMEM); } - if (ff_dnn_fill_task(task, exec_params, ov_model, ctx->options.async, 1) != DNN_SUCCESS) { + ret = ff_dnn_fill_task(task, exec_params, ov_model, ctx->options.async, 1); + if (ret != 0) { av_freep(&task); - return DNN_ERROR; + return ret; } if (ff_queue_push_back(ov_model->task_queue, task) < 0) { av_freep(&task); av_log(ctx, AV_LOG_ERROR, "unable to push back task_queue.\n"); - return DNN_ERROR; + return AVERROR(ENOMEM); } - if (extract_lltask_from_task(model->func_type, task, ov_model->lltask_queue, exec_params) != DNN_SUCCESS) { + ret = extract_lltask_from_task(model->func_type, task, ov_model->lltask_queue, exec_params); + if (ret != 0) { av_log(ctx, AV_LOG_ERROR, "unable to extract inference from task.\n"); - return DNN_ERROR; + return ret; } if (ctx->options.async) { @@ -804,34 +830,34 @@ DNNReturnType ff_dnn_execute_model_ov(const DNNModel *model, DNNExecBaseParams * request = ff_safe_queue_pop_front(ov_model->request_queue); if (!request) { av_log(ctx, AV_LOG_ERROR, "unable to get infer request.\n"); - return DNN_ERROR; + return AVERROR(EINVAL); } ret = execute_model_ov(request, ov_model->lltask_queue); - if (ret != DNN_SUCCESS) { + if (ret != 0) { return ret; } } - return DNN_SUCCESS; + return 0; } else { if (model->func_type == DFT_ANALYTICS_CLASSIFY) { // Classification filter has not been completely // tested with the sync mode. So, do not support now. avpriv_report_missing_feature(ctx, "classify for sync execution"); - return DNN_ERROR; + return AVERROR(ENOSYS); } if (ctx->options.batch_size > 1) { avpriv_report_missing_feature(ctx, "batch mode for sync execution"); - return DNN_ERROR; + return AVERROR(ENOSYS); } request = ff_safe_queue_pop_front(ov_model->request_queue); if (!request) { av_log(ctx, AV_LOG_ERROR, "unable to get infer request.\n"); - return DNN_ERROR; + return AVERROR(EINVAL); } return execute_model_ov(request, ov_model->lltask_queue); } @@ -843,42 +869,42 @@ DNNAsyncStatusType ff_dnn_get_result_ov(const DNNModel *model, AVFrame **in, AVF return ff_dnn_get_result_common(ov_model->task_queue, in, out); } -DNNReturnType ff_dnn_flush_ov(const DNNModel *model) +int ff_dnn_flush_ov(const DNNModel *model) { OVModel *ov_model = model->model; OVContext *ctx = &ov_model->ctx; OVRequestItem *request; IEStatusCode status; - DNNReturnType ret; + int ret; if (ff_queue_size(ov_model->lltask_queue) == 0) { // no pending task need to flush - return DNN_SUCCESS; + return 0; } request = ff_safe_queue_pop_front(ov_model->request_queue); if (!request) { av_log(ctx, AV_LOG_ERROR, "unable to get infer request.\n"); - return DNN_ERROR; + return AVERROR(EINVAL); } ret = fill_model_input_ov(ov_model, request); - if (ret != DNN_SUCCESS) { + if (ret != 0) { av_log(ctx, AV_LOG_ERROR, "Failed to fill model input.\n"); return ret; } status = ie_infer_set_completion_callback(request->infer_request, &request->callback); if (status != OK) { av_log(ctx, AV_LOG_ERROR, "Failed to set completion callback for inference\n"); - return DNN_ERROR; + return DNN_GENERIC_ERROR; } status = ie_infer_request_infer_async(request->infer_request); if (status != OK) { av_log(ctx, AV_LOG_ERROR, "Failed to start async inference\n"); - return DNN_ERROR; + return DNN_GENERIC_ERROR; } - return DNN_SUCCESS; + return 0; } void ff_dnn_free_model_ov(DNNModel **model) diff --git a/libavfilter/dnn/dnn_backend_openvino.h b/libavfilter/dnn/dnn_backend_openvino.h index 0bbca0c05..304bc96b9 100644 --- a/libavfilter/dnn/dnn_backend_openvino.h +++ b/libavfilter/dnn/dnn_backend_openvino.h @@ -31,9 +31,9 @@ DNNModel *ff_dnn_load_model_ov(const char *model_filename, DNNFunctionType func_type, const char *options, AVFilterContext *filter_ctx); -DNNReturnType ff_dnn_execute_model_ov(const DNNModel *model, DNNExecBaseParams *exec_params); +int ff_dnn_execute_model_ov(const DNNModel *model, DNNExecBaseParams *exec_params); DNNAsyncStatusType ff_dnn_get_result_ov(const DNNModel *model, AVFrame **in, AVFrame **out); -DNNReturnType ff_dnn_flush_ov(const DNNModel *model); +int ff_dnn_flush_ov(const DNNModel *model); void ff_dnn_free_model_ov(DNNModel **model); diff --git a/libavfilter/dnn/dnn_backend_tf.c b/libavfilter/dnn/dnn_backend_tf.c index 7dd48fb61..3b5084b67 100644 --- a/libavfilter/dnn/dnn_backend_tf.c +++ b/libavfilter/dnn/dnn_backend_tf.c @@ -90,7 +90,7 @@ static const AVOption dnn_tensorflow_options[] = { AVFILTER_DEFINE_CLASS(dnn_tensorflow); -static DNNReturnType execute_model_tf(TFRequestItem *request, Queue *lltask_queue); +static int execute_model_tf(TFRequestItem *request, Queue *lltask_queue); static void infer_completion_callback(void *args); static inline void destroy_request_item(TFRequestItem **arg); @@ -151,10 +151,11 @@ static TFInferRequest *tf_create_inference_request(void) * Start synchronous inference for the TensorFlow model. * * @param request pointer to the TFRequestItem for inference - * @retval DNN_SUCCESS if execution is successful - * @retval DNN_ERROR if execution fails + * @retval 0 if execution is successful + * @retval AVERROR(EINVAL) if request is NULL + * @retval DNN_GENERIC_ERROR if execution fails */ -static DNNReturnType tf_start_inference(void *args) +static int tf_start_inference(void *args) { TFRequestItem *request = args; TFInferRequest *infer_request = request->infer_request; @@ -164,7 +165,7 @@ static DNNReturnType tf_start_inference(void *args) if (!request) { av_log(&tf_model->ctx, AV_LOG_ERROR, "TFRequestItem is NULL\n"); - return DNN_ERROR; + return AVERROR(EINVAL); } TF_SessionRun(tf_model->session, NULL, @@ -178,9 +179,9 @@ static DNNReturnType tf_start_inference(void *args) if (ff_safe_queue_push_back(tf_model->request_queue, request) < 0) { destroy_request_item(&request); } - return DNN_ERROR; + return DNN_GENERIC_ERROR; } - return DNN_SUCCESS; + return 0; } /** @@ -202,14 +203,14 @@ static inline void destroy_request_item(TFRequestItem **arg) { av_freep(arg); } -static DNNReturnType extract_lltask_from_task(TaskItem *task, Queue *lltask_queue) +static int extract_lltask_from_task(TaskItem *task, Queue *lltask_queue) { TFModel *tf_model = task->model; TFContext *ctx = &tf_model->ctx; LastLevelTaskItem *lltask = av_malloc(sizeof(*lltask)); if (!lltask) { av_log(ctx, AV_LOG_ERROR, "Unable to allocate space for LastLevelTaskItem\n"); - return DNN_ERROR; + return AVERROR(ENOMEM); } task->inference_todo = 1; task->inference_done = 0; @@ -217,9 +218,9 @@ static DNNReturnType extract_lltask_from_task(TaskItem *task, Queue *lltask_queu if (ff_queue_push_back(lltask_queue, lltask) < 0) { av_log(ctx, AV_LOG_ERROR, "Failed to push back lltask_queue.\n"); av_freep(&lltask); - return DNN_ERROR; + return AVERROR(ENOMEM); } - return DNN_SUCCESS; + return 0; } static TF_Buffer *read_graph(const char *model_filename) @@ -277,7 +278,7 @@ static TF_Tensor *allocate_input_tensor(const DNNData *input) input_dims[1] * input_dims[2] * input_dims[3] * size); } -static DNNReturnType get_input_tf(void *model, DNNData *input, const char *input_name) +static int get_input_tf(void *model, DNNData *input, const char *input_name) { TFModel *tf_model = model; TFContext *ctx = &tf_model->ctx; @@ -288,7 +289,7 @@ static DNNReturnType get_input_tf(void *model, DNNData *input, const char *input tf_output.oper = TF_GraphOperationByName(tf_model->graph, input_name); if (!tf_output.oper) { av_log(ctx, AV_LOG_ERROR, "Could not find \"%s\" in model\n", input_name); - return DNN_ERROR; + return AVERROR(EINVAL); } tf_output.index = 0; @@ -300,7 +301,7 @@ static DNNReturnType get_input_tf(void *model, DNNData *input, const char *input if (TF_GetCode(status) != TF_OK){ TF_DeleteStatus(status); av_log(ctx, AV_LOG_ERROR, "Failed to get input tensor shape: number of dimension incorrect\n"); - return DNN_ERROR; + return DNN_GENERIC_ERROR; } TF_DeleteStatus(status); @@ -310,13 +311,13 @@ static DNNReturnType get_input_tf(void *model, DNNData *input, const char *input input->width = dims[2]; input->channels = dims[3]; - return DNN_SUCCESS; + return 0; } -static DNNReturnType get_output_tf(void *model, const char *input_name, int input_width, int input_height, +static int get_output_tf(void *model, const char *input_name, int input_width, int input_height, const char *output_name, int *output_width, int *output_height) { - DNNReturnType ret; + int ret; TFModel *tf_model = model; TFContext *ctx = &tf_model->ctx; TaskItem task; @@ -329,20 +330,21 @@ static DNNReturnType get_output_tf(void *model, const char *input_name, int inpu .out_frame = NULL, }; - if (ff_dnn_fill_gettingoutput_task(&task, &exec_params, tf_model, input_height, input_width, ctx) != DNN_SUCCESS) { + ret = ff_dnn_fill_gettingoutput_task(&task, &exec_params, tf_model, input_height, input_width, ctx); + if (ret != 0) { goto err; } - if (extract_lltask_from_task(&task, tf_model->lltask_queue) != DNN_SUCCESS) { + ret = extract_lltask_from_task(&task, tf_model->lltask_queue); + if (ret != 0) { av_log(ctx, AV_LOG_ERROR, "unable to extract inference from task.\n"); - ret = DNN_ERROR; goto err; } request = ff_safe_queue_pop_front(tf_model->request_queue); if (!request) { av_log(ctx, AV_LOG_ERROR, "unable to get infer request.\n"); - ret = DNN_ERROR; + ret = AVERROR(EINVAL); goto err; } @@ -386,7 +388,7 @@ static int hex_to_data(uint8_t *data, const char *p) return len; } -static DNNReturnType load_tf_model(TFModel *tf_model, const char *model_filename) +static int load_tf_model(TFModel *tf_model, const char *model_filename) { TFContext *ctx = &tf_model->ctx; TF_Buffer *graph_def; @@ -407,7 +409,7 @@ static DNNReturnType load_tf_model(TFModel *tf_model, const char *model_filename */ if (strncmp(tf_model->ctx.options.sess_config, "0x", 2) != 0) { av_log(ctx, AV_LOG_ERROR, "sess_config should start with '0x'\n"); - return DNN_ERROR; + return AVERROR(EINVAL); } config = tf_model->ctx.options.sess_config + 2; sess_config_length = hex_to_data(NULL, config); @@ -415,11 +417,11 @@ static DNNReturnType load_tf_model(TFModel *tf_model, const char *model_filename sess_config = av_mallocz(sess_config_length + AV_INPUT_BUFFER_PADDING_SIZE); if (!sess_config) { av_log(ctx, AV_LOG_ERROR, "failed to allocate memory\n"); - return DNN_ERROR; + return AVERROR(ENOMEM); } if (hex_to_data(sess_config, config) < 0) { av_log(ctx, AV_LOG_ERROR, "failed to convert hex to data\n"); - return DNN_ERROR; + return AVERROR(EINVAL); } } @@ -427,7 +429,7 @@ static DNNReturnType load_tf_model(TFModel *tf_model, const char *model_filename if (!graph_def){ av_log(ctx, AV_LOG_ERROR, "Failed to read model \"%s\" graph\n", model_filename); av_freep(&sess_config); - return DNN_ERROR; + return AVERROR(EINVAL); } tf_model->graph = TF_NewGraph(); tf_model->status = TF_NewStatus(); @@ -440,7 +442,7 @@ static DNNReturnType load_tf_model(TFModel *tf_model, const char *model_filename TF_DeleteStatus(tf_model->status); av_log(ctx, AV_LOG_ERROR, "Failed to import serialized graph to model graph\n"); av_freep(&sess_config); - return DNN_ERROR; + return DNN_GENERIC_ERROR; } init_op = TF_GraphOperationByName(tf_model->graph, "init"); @@ -455,7 +457,7 @@ static DNNReturnType load_tf_model(TFModel *tf_model, const char *model_filename TF_DeleteSessionOptions(sess_opts); av_log(ctx, AV_LOG_ERROR, "Failed to set config for sess options with %s\n", tf_model->ctx.options.sess_config); - return DNN_ERROR; + return DNN_GENERIC_ERROR; } } @@ -466,7 +468,7 @@ static DNNReturnType load_tf_model(TFModel *tf_model, const char *model_filename TF_DeleteGraph(tf_model->graph); TF_DeleteStatus(tf_model->status); av_log(ctx, AV_LOG_ERROR, "Failed to create new session with model graph\n"); - return DNN_ERROR; + return DNN_GENERIC_ERROR; } // Run initialization operation with name "init" if it is present in graph @@ -481,16 +483,16 @@ static DNNReturnType load_tf_model(TFModel *tf_model, const char *model_filename TF_DeleteGraph(tf_model->graph); TF_DeleteStatus(tf_model->status); av_log(ctx, AV_LOG_ERROR, "Failed to run session when initializing\n"); - return DNN_ERROR; + return DNN_GENERIC_ERROR; } } - return DNN_SUCCESS; + return 0; } #define NAME_BUFFER_SIZE 256 -static DNNReturnType add_conv_layer(TFModel *tf_model, TF_Operation *transpose_op, TF_Operation **cur_op, +static int add_conv_layer(TFModel *tf_model, TF_Operation *transpose_op, TF_Operation **cur_op, ConvolutionalParams* params, const int layer) { TFContext *ctx = &tf_model->ctx; @@ -594,7 +596,7 @@ static DNNReturnType add_conv_layer(TFModel *tf_model, TF_Operation *transpose_o break; default: avpriv_report_missing_feature(ctx, "convolutional activation function %d", params->activation); - return DNN_ERROR; + return AVERROR(ENOSYS); } input.oper = *cur_op; TF_AddInput(op_desc, input); @@ -604,15 +606,15 @@ static DNNReturnType add_conv_layer(TFModel *tf_model, TF_Operation *transpose_o goto err; } - return DNN_SUCCESS; + return 0; err: TF_DeleteTensor(kernel_tensor); TF_DeleteTensor(biases_tensor); av_log(ctx, AV_LOG_ERROR, "Failed to add conv layer %d\n", layer); - return DNN_ERROR; + return DNN_GENERIC_ERROR; } -static DNNReturnType add_depth_to_space_layer(TFModel *tf_model, TF_Operation **cur_op, +static int add_depth_to_space_layer(TFModel *tf_model, TF_Operation **cur_op, DepthToSpaceParams *params, const int layer) { TFContext *ctx = &tf_model->ctx; @@ -630,13 +632,13 @@ static DNNReturnType add_depth_to_space_layer(TFModel *tf_model, TF_Operation ** *cur_op = TF_FinishOperation(op_desc, tf_model->status); if (TF_GetCode(tf_model->status) != TF_OK){ av_log(ctx, AV_LOG_ERROR, "Failed to add depth_to_space to layer %d\n", layer); - return DNN_ERROR; + return DNN_GENERIC_ERROR; } - return DNN_SUCCESS; + return 0; } -static DNNReturnType add_pad_layer(TFModel *tf_model, TF_Operation **cur_op, +static int add_pad_layer(TFModel *tf_model, TF_Operation **cur_op, LayerPadParams *params, const int layer) { TFContext *ctx = &tf_model->ctx; @@ -666,13 +668,13 @@ static DNNReturnType add_pad_layer(TFModel *tf_model, TF_Operation **cur_op, if (TF_GetCode(tf_model->status) != TF_OK){ TF_DeleteTensor(tensor); av_log(ctx, AV_LOG_ERROR, "Failed to set value for pad of layer %d\n", layer); - return DNN_ERROR; + return DNN_GENERIC_ERROR; } op = TF_FinishOperation(op_desc, tf_model->status); if (TF_GetCode(tf_model->status) != TF_OK){ TF_DeleteTensor(tensor); av_log(ctx, AV_LOG_ERROR, "Failed to add pad to layer %d\n", layer); - return DNN_ERROR; + return DNN_GENERIC_ERROR; } op_desc = TF_NewOperation(tf_model->graph, "MirrorPad", "mirror_pad"); @@ -688,13 +690,13 @@ static DNNReturnType add_pad_layer(TFModel *tf_model, TF_Operation **cur_op, if (TF_GetCode(tf_model->status) != TF_OK){ TF_DeleteTensor(tensor); av_log(ctx, AV_LOG_ERROR, "Failed to add mirror_pad to layer %d\n", layer); - return DNN_ERROR; + return DNN_GENERIC_ERROR; } - return DNN_SUCCESS; + return 0; } -static DNNReturnType add_maximum_layer(TFModel *tf_model, TF_Operation **cur_op, +static int add_maximum_layer(TFModel *tf_model, TF_Operation **cur_op, DnnLayerMaximumParams *params, const int layer) { TFContext *ctx = &tf_model->ctx; @@ -716,13 +718,13 @@ static DNNReturnType add_maximum_layer(TFModel *tf_model, TF_Operation **cur_op, if (TF_GetCode(tf_model->status) != TF_OK){ TF_DeleteTensor(tensor); av_log(ctx, AV_LOG_ERROR, "Failed to set value for maximum/y of layer %d", layer); - return DNN_ERROR; + return DNN_GENERIC_ERROR; } op = TF_FinishOperation(op_desc, tf_model->status); if (TF_GetCode(tf_model->status) != TF_OK){ TF_DeleteTensor(tensor); av_log(ctx, AV_LOG_ERROR, "Failed to add maximum/y to layer %d\n", layer); - return DNN_ERROR; + return DNN_GENERIC_ERROR; } snprintf(name_buffer, NAME_BUFFER_SIZE, "maximum%d", layer); @@ -737,13 +739,13 @@ static DNNReturnType add_maximum_layer(TFModel *tf_model, TF_Operation **cur_op, if (TF_GetCode(tf_model->status) != TF_OK){ TF_DeleteTensor(tensor); av_log(ctx, AV_LOG_ERROR, "Failed to add maximum to layer %d\n", layer); - return DNN_ERROR; + return DNN_GENERIC_ERROR; } - return DNN_SUCCESS; + return 0; } -static DNNReturnType load_native_model(TFModel *tf_model, const char *model_filename) +static int load_native_model(TFModel *tf_model, const char *model_filename) { TFContext *ctx = &tf_model->ctx; int32_t layer; @@ -755,14 +757,14 @@ static DNNReturnType load_native_model(TFModel *tf_model, const char *model_file int32_t *transpose_perm; int64_t transpose_perm_shape[] = {4}; int64_t input_shape[] = {1, -1, -1, -1}; - DNNReturnType layer_add_res; + int layer_add_res; DNNModel *model = NULL; NativeModel *native_model; model = ff_dnn_load_model_native(model_filename, DFT_PROCESS_FRAME, NULL, NULL); if (!model){ av_log(ctx, AV_LOG_ERROR, "Failed to load native model\n"); - return DNN_ERROR; + return AVERROR(EINVAL); } native_model = model->model; @@ -775,7 +777,7 @@ static DNNReturnType load_native_model(TFModel *tf_model, const char *model_file TF_DeleteGraph(tf_model->graph); \ TF_DeleteStatus(tf_model->status); \ av_log(ctx, AV_LOG_ERROR, "Failed to set value or add operator to layer\n"); \ - return DNN_ERROR; \ + return DNN_GENERIC_ERROR; \ } op_desc = TF_NewOperation(tf_model->graph, "Placeholder", "x"); @@ -806,7 +808,7 @@ static DNNReturnType load_native_model(TFModel *tf_model, const char *model_file for (layer = 0; layer < native_model->layers_num; ++layer){ switch (native_model->layers[layer].type){ case DLT_INPUT: - layer_add_res = DNN_SUCCESS; + layer_add_res = 0; break; case DLT_CONV2D: layer_add_res = add_conv_layer(tf_model, transpose_op, &op, @@ -828,7 +830,7 @@ static DNNReturnType load_native_model(TFModel *tf_model, const char *model_file CLEANUP_ON_ERROR(tf_model); } - if (layer_add_res != DNN_SUCCESS){ + if (layer_add_res != 0){ CLEANUP_ON_ERROR(tf_model); } } @@ -844,7 +846,7 @@ static DNNReturnType load_native_model(TFModel *tf_model, const char *model_file ff_dnn_free_model_native(&model); - return DNN_SUCCESS; + return 0; } DNNModel *ff_dnn_load_model_tf(const char *model_filename, DNNFunctionType func_type, const char *options, AVFilterContext *filter_ctx) @@ -874,8 +876,8 @@ DNNModel *ff_dnn_load_model_tf(const char *model_filename, DNNFunctionType func_ goto err; } - if (load_tf_model(tf_model, model_filename) != DNN_SUCCESS){ - if (load_native_model(tf_model, model_filename) != DNN_SUCCESS){ + if (load_tf_model(tf_model, model_filename) != 0){ + if (load_native_model(tf_model, model_filename) != 0){ goto err; } } @@ -942,19 +944,21 @@ err: return NULL; } -static DNNReturnType fill_model_input_tf(TFModel *tf_model, TFRequestItem *request) { +static int fill_model_input_tf(TFModel *tf_model, TFRequestItem *request) { DNNData input; LastLevelTaskItem *lltask; TaskItem *task; TFInferRequest *infer_request; TFContext *ctx = &tf_model->ctx; + int ret = 0; lltask = ff_queue_pop_front(tf_model->lltask_queue); av_assert0(lltask); task = lltask->task; request->lltask = lltask; - if (get_input_tf(tf_model, &input, task->input_name) != DNN_SUCCESS) { + ret = get_input_tf(tf_model, &input, task->input_name); + if (ret != 0) { goto err; } @@ -965,12 +969,14 @@ static DNNReturnType fill_model_input_tf(TFModel *tf_model, TFRequestItem *reque infer_request->tf_input = av_malloc(sizeof(TF_Output)); if (!infer_request->tf_input) { av_log(ctx, AV_LOG_ERROR, "Failed to allocate memory for input tensor\n"); + ret = AVERROR(ENOMEM); goto err; } infer_request->tf_input->oper = TF_GraphOperationByName(tf_model->graph, task->input_name); if (!infer_request->tf_input->oper){ av_log(ctx, AV_LOG_ERROR, "Could not find \"%s\" in model\n", task->input_name); + ret = DNN_GENERIC_ERROR; goto err; } infer_request->tf_input->index = 0; @@ -978,6 +984,7 @@ static DNNReturnType fill_model_input_tf(TFModel *tf_model, TFRequestItem *reque infer_request->input_tensor = allocate_input_tensor(&input); if (!infer_request->input_tensor){ av_log(ctx, AV_LOG_ERROR, "Failed to allocate memory for input tensor\n"); + ret = AVERROR(ENOMEM); goto err; } input.data = (float *)TF_TensorData(infer_request->input_tensor); @@ -1003,12 +1010,14 @@ static DNNReturnType fill_model_input_tf(TFModel *tf_model, TFRequestItem *reque infer_request->tf_outputs = av_malloc_array(task->nb_output, sizeof(TF_Output)); if (infer_request->tf_outputs == NULL) { av_log(ctx, AV_LOG_ERROR, "Failed to allocate memory for *tf_outputs\n"); + ret = AVERROR(ENOMEM); goto err; } infer_request->output_tensors = av_calloc(task->nb_output, sizeof(*infer_request->output_tensors)); if (!infer_request->output_tensors) { av_log(ctx, AV_LOG_ERROR, "Failed to allocate memory for output tensor\n"); + ret = AVERROR(ENOMEM); goto err; } @@ -1017,15 +1026,16 @@ static DNNReturnType fill_model_input_tf(TFModel *tf_model, TFRequestItem *reque infer_request->tf_outputs[i].oper = TF_GraphOperationByName(tf_model->graph, task->output_names[i]); if (!infer_request->tf_outputs[i].oper) { av_log(ctx, AV_LOG_ERROR, "Could not find output \"%s\" in model\n", task->output_names[i]); + ret = DNN_GENERIC_ERROR; goto err; } infer_request->tf_outputs[i].index = 0; } - return DNN_SUCCESS; + return 0; err: tf_free_request(infer_request); - return DNN_ERROR; + return ret; } static void infer_completion_callback(void *args) { @@ -1086,16 +1096,17 @@ err: } } -static DNNReturnType execute_model_tf(TFRequestItem *request, Queue *lltask_queue) +static int execute_model_tf(TFRequestItem *request, Queue *lltask_queue) { TFModel *tf_model; TFContext *ctx; LastLevelTaskItem *lltask; TaskItem *task; + int ret = 0; if (ff_queue_size(lltask_queue) == 0) { destroy_request_item(&request); - return DNN_SUCCESS; + return 0; } lltask = ff_queue_peek_front(lltask_queue); @@ -1103,67 +1114,74 @@ static DNNReturnType execute_model_tf(TFRequestItem *request, Queue *lltask_queu tf_model = task->model; ctx = &tf_model->ctx; - if (fill_model_input_tf(tf_model, request) != DNN_SUCCESS) { + ret = fill_model_input_tf(tf_model, request); + if (ret != 0) { goto err; } if (task->async) { - if (ff_dnn_start_inference_async(ctx, &request->exec_module) != DNN_SUCCESS) { + if (ff_dnn_start_inference_async(ctx, &request->exec_module) != 0) { goto err; } - return DNN_SUCCESS; - } else { - if (tf_start_inference(request) != DNN_SUCCESS) { + return 0; + } + else { + ret = tf_start_inference(request); + if (ret != 0) { goto err; } infer_completion_callback(request); - return (task->inference_done == task->inference_todo) ? DNN_SUCCESS : DNN_ERROR; + return (task->inference_done == task->inference_todo) ? 0 : DNN_GENERIC_ERROR; } err: tf_free_request(request->infer_request); if (ff_safe_queue_push_back(tf_model->request_queue, request) < 0) { destroy_request_item(&request); } - return DNN_ERROR; + return ret; } -DNNReturnType ff_dnn_execute_model_tf(const DNNModel *model, DNNExecBaseParams *exec_params) +int ff_dnn_execute_model_tf(const DNNModel *model, DNNExecBaseParams *exec_params) { TFModel *tf_model = model->model; TFContext *ctx = &tf_model->ctx; TaskItem *task; TFRequestItem *request; + int ret = 0; - if (ff_check_exec_params(ctx, DNN_TF, model->func_type, exec_params) != 0) { - return DNN_ERROR; + ret = ff_check_exec_params(ctx, DNN_TF, model->func_type, exec_params); + if (ret != 0) { + return ret; } task = av_malloc(sizeof(*task)); if (!task) { av_log(ctx, AV_LOG_ERROR, "unable to alloc memory for task item.\n"); - return DNN_ERROR; + return AVERROR(ENOMEM); } - if (ff_dnn_fill_task(task, exec_params, tf_model, ctx->options.async, 1) != DNN_SUCCESS) { + ret = ff_dnn_fill_task(task, exec_params, tf_model, ctx->options.async, 1); + if (ret != 0) { av_freep(&task); - return DNN_ERROR; + return ret; } if (ff_queue_push_back(tf_model->task_queue, task) < 0) { av_freep(&task); av_log(ctx, AV_LOG_ERROR, "unable to push back task_queue.\n"); - return DNN_ERROR; + return AVERROR(ENOMEM); } - if (extract_lltask_from_task(task, tf_model->lltask_queue) != DNN_SUCCESS) { + ret = extract_lltask_from_task(task, tf_model->lltask_queue); + if (ret != 0) { av_log(ctx, AV_LOG_ERROR, "unable to extract last level task from task.\n"); - return DNN_ERROR; + return ret; } request = ff_safe_queue_pop_front(tf_model->request_queue); if (!request) { av_log(ctx, AV_LOG_ERROR, "unable to get infer request.\n"); - return DNN_ERROR; + return AVERROR(EINVAL); } return execute_model_tf(request, tf_model->lltask_queue); } @@ -1174,26 +1192,26 @@ DNNAsyncStatusType ff_dnn_get_result_tf(const DNNModel *model, AVFrame **in, AVF return ff_dnn_get_result_common(tf_model->task_queue, in, out); } -DNNReturnType ff_dnn_flush_tf(const DNNModel *model) +int ff_dnn_flush_tf(const DNNModel *model) { TFModel *tf_model = model->model; TFContext *ctx = &tf_model->ctx; TFRequestItem *request; - DNNReturnType ret; + int ret; if (ff_queue_size(tf_model->lltask_queue) == 0) { // no pending task need to flush - return DNN_SUCCESS; + return 0; } request = ff_safe_queue_pop_front(tf_model->request_queue); if (!request) { av_log(ctx, AV_LOG_ERROR, "unable to get infer request.\n"); - return DNN_ERROR; + return AVERROR(EINVAL); } ret = fill_model_input_tf(tf_model, request); - if (ret != DNN_SUCCESS) { + if (ret != 0) { av_log(ctx, AV_LOG_ERROR, "Failed to fill model input.\n"); if (ff_safe_queue_push_back(tf_model->request_queue, request) < 0) { destroy_request_item(&request); diff --git a/libavfilter/dnn/dnn_backend_tf.h b/libavfilter/dnn/dnn_backend_tf.h index f14ea8c47..0b63a4b6d 100644 --- a/libavfilter/dnn/dnn_backend_tf.h +++ b/libavfilter/dnn/dnn_backend_tf.h @@ -31,9 +31,9 @@ DNNModel *ff_dnn_load_model_tf(const char *model_filename, DNNFunctionType func_type, const char *options, AVFilterContext *filter_ctx); -DNNReturnType ff_dnn_execute_model_tf(const DNNModel *model, DNNExecBaseParams *exec_params); +int ff_dnn_execute_model_tf(const DNNModel *model, DNNExecBaseParams *exec_params); DNNAsyncStatusType ff_dnn_get_result_tf(const DNNModel *model, AVFrame **in, AVFrame **out); -DNNReturnType ff_dnn_flush_tf(const DNNModel *model); +int ff_dnn_flush_tf(const DNNModel *model); void ff_dnn_free_model_tf(DNNModel **model); diff --git a/libavfilter/dnn/dnn_io_proc.c b/libavfilter/dnn/dnn_io_proc.c index f55424d97..7961bf6b9 100644 --- a/libavfilter/dnn/dnn_io_proc.c +++ b/libavfilter/dnn/dnn_io_proc.c @@ -24,16 +24,16 @@ #include "libavutil/avassert.h" #include "libavutil/detection_bbox.h" -DNNReturnType ff_proc_from_dnn_to_frame(AVFrame *frame, DNNData *output, void *log_ctx) +int ff_proc_from_dnn_to_frame(AVFrame *frame, DNNData *output, void *log_ctx) { struct SwsContext *sws_ctx; int bytewidth = av_image_get_linesize(frame->format, frame->width, 0); if (bytewidth < 0) { - return DNN_ERROR; + return AVERROR(EINVAL); } if (output->dt != DNN_FLOAT) { avpriv_report_missing_feature(log_ctx, "data type rather than DNN_FLOAT"); - return DNN_ERROR; + return AVERROR(ENOSYS); } switch (frame->format) { @@ -51,18 +51,18 @@ DNNReturnType ff_proc_from_dnn_to_frame(AVFrame *frame, DNNData *output, void *l "fmt:%s s:%dx%d -> fmt:%s s:%dx%d\n", av_get_pix_fmt_name(AV_PIX_FMT_GRAYF32), frame->width * 3, frame->height, av_get_pix_fmt_name(AV_PIX_FMT_GRAY8), frame->width * 3, frame->height); - return DNN_ERROR; + return AVERROR(EINVAL); } sws_scale(sws_ctx, (const uint8_t *[4]){(const uint8_t *)output->data, 0, 0, 0}, (const int[4]){frame->width * 3 * sizeof(float), 0, 0, 0}, 0, frame->height, (uint8_t * const*)frame->data, frame->linesize); sws_freeContext(sws_ctx); - return DNN_SUCCESS; + return 0; case AV_PIX_FMT_GRAYF32: av_image_copy_plane(frame->data[0], frame->linesize[0], output->data, bytewidth, bytewidth, frame->height); - return DNN_SUCCESS; + return 0; case AV_PIX_FMT_YUV420P: case AV_PIX_FMT_YUV422P: case AV_PIX_FMT_YUV444P: @@ -82,31 +82,31 @@ DNNReturnType ff_proc_from_dnn_to_frame(AVFrame *frame, DNNData *output, void *l "fmt:%s s:%dx%d -> fmt:%s s:%dx%d\n", av_get_pix_fmt_name(AV_PIX_FMT_GRAYF32), frame->width, frame->height, av_get_pix_fmt_name(AV_PIX_FMT_GRAY8), frame->width, frame->height); - return DNN_ERROR; + return AVERROR(EINVAL); } sws_scale(sws_ctx, (const uint8_t *[4]){(const uint8_t *)output->data, 0, 0, 0}, (const int[4]){frame->width * sizeof(float), 0, 0, 0}, 0, frame->height, (uint8_t * const*)frame->data, frame->linesize); sws_freeContext(sws_ctx); - return DNN_SUCCESS; + return 0; default: avpriv_report_missing_feature(log_ctx, "%s", av_get_pix_fmt_name(frame->format)); - return DNN_ERROR; + return AVERROR(ENOSYS); } - return DNN_SUCCESS; + return 0; } -DNNReturnType ff_proc_from_frame_to_dnn(AVFrame *frame, DNNData *input, void *log_ctx) +int ff_proc_from_frame_to_dnn(AVFrame *frame, DNNData *input, void *log_ctx) { struct SwsContext *sws_ctx; int bytewidth = av_image_get_linesize(frame->format, frame->width, 0); if (bytewidth < 0) { - return DNN_ERROR; + return AVERROR(EINVAL); } if (input->dt != DNN_FLOAT) { avpriv_report_missing_feature(log_ctx, "data type rather than DNN_FLOAT"); - return DNN_ERROR; + return AVERROR(ENOSYS); } switch (frame->format) { @@ -124,7 +124,7 @@ DNNReturnType ff_proc_from_frame_to_dnn(AVFrame *frame, DNNData *input, void *lo "fmt:%s s:%dx%d -> fmt:%s s:%dx%d\n", av_get_pix_fmt_name(AV_PIX_FMT_GRAY8), frame->width * 3, frame->height, av_get_pix_fmt_name(AV_PIX_FMT_GRAYF32),frame->width * 3, frame->height); - return DNN_ERROR; + return AVERROR(EINVAL); } sws_scale(sws_ctx, (const uint8_t **)frame->data, frame->linesize, 0, frame->height, @@ -156,7 +156,7 @@ DNNReturnType ff_proc_from_frame_to_dnn(AVFrame *frame, DNNData *input, void *lo "fmt:%s s:%dx%d -> fmt:%s s:%dx%d\n", av_get_pix_fmt_name(AV_PIX_FMT_GRAY8), frame->width, frame->height, av_get_pix_fmt_name(AV_PIX_FMT_GRAYF32),frame->width, frame->height); - return DNN_ERROR; + return AVERROR(EINVAL); } sws_scale(sws_ctx, (const uint8_t **)frame->data, frame->linesize, 0, frame->height, @@ -166,10 +166,10 @@ DNNReturnType ff_proc_from_frame_to_dnn(AVFrame *frame, DNNData *input, void *lo break; default: avpriv_report_missing_feature(log_ctx, "%s", av_get_pix_fmt_name(frame->format)); - return DNN_ERROR; + return AVERROR(ENOSYS); } - return DNN_SUCCESS; + return 0; } static enum AVPixelFormat get_pixel_format(DNNData *data) @@ -190,13 +190,14 @@ static enum AVPixelFormat get_pixel_format(DNNData *data) return AV_PIX_FMT_BGR24; } -DNNReturnType ff_frame_to_dnn_classify(AVFrame *frame, DNNData *input, uint32_t bbox_index, void *log_ctx) +int ff_frame_to_dnn_classify(AVFrame *frame, DNNData *input, uint32_t bbox_index, void *log_ctx) { const AVPixFmtDescriptor *desc; int offsetx[4], offsety[4]; uint8_t *bbox_data[4]; struct SwsContext *sws_ctx; int linesizes[4]; + int ret = 0; enum AVPixelFormat fmt; int left, top, width, height; const AVDetectionBBoxHeader *header; @@ -221,13 +222,14 @@ DNNReturnType ff_frame_to_dnn_classify(AVFrame *frame, DNNData *input, uint32_t "fmt:%s s:%dx%d -> fmt:%s s:%dx%d\n", av_get_pix_fmt_name(frame->format), width, height, av_get_pix_fmt_name(fmt), input->width, input->height); - return DNN_ERROR; + return AVERROR(EINVAL); } - if (av_image_fill_linesizes(linesizes, fmt, input->width) < 0) { + ret = av_image_fill_linesizes(linesizes, fmt, input->width); + if (ret < 0) { av_log(log_ctx, AV_LOG_ERROR, "unable to get linesizes with av_image_fill_linesizes"); sws_freeContext(sws_ctx); - return DNN_ERROR; + return ret; } desc = av_pix_fmt_desc_get(frame->format); @@ -246,13 +248,14 @@ DNNReturnType ff_frame_to_dnn_classify(AVFrame *frame, DNNData *input, uint32_t sws_freeContext(sws_ctx); - return DNN_SUCCESS; + return ret; } -DNNReturnType ff_frame_to_dnn_detect(AVFrame *frame, DNNData *input, void *log_ctx) +int ff_frame_to_dnn_detect(AVFrame *frame, DNNData *input, void *log_ctx) { struct SwsContext *sws_ctx; int linesizes[4]; + int ret = 0; enum AVPixelFormat fmt = get_pixel_format(input); sws_ctx = sws_getContext(frame->width, frame->height, frame->format, input->width, input->height, fmt, @@ -262,18 +265,19 @@ DNNReturnType ff_frame_to_dnn_detect(AVFrame *frame, DNNData *input, void *log_c "fmt:%s s:%dx%d -> fmt:%s s:%dx%d\n", av_get_pix_fmt_name(frame->format), frame->width, frame->height, av_get_pix_fmt_name(fmt), input->width, input->height); - return DNN_ERROR; + return AVERROR(EINVAL); } - if (av_image_fill_linesizes(linesizes, fmt, input->width) < 0) { + ret = av_image_fill_linesizes(linesizes, fmt, input->width); + if (ret < 0) { av_log(log_ctx, AV_LOG_ERROR, "unable to get linesizes with av_image_fill_linesizes"); sws_freeContext(sws_ctx); - return DNN_ERROR; + return ret; } sws_scale(sws_ctx, (const uint8_t *const *)frame->data, frame->linesize, 0, frame->height, (uint8_t *const [4]){input->data, 0, 0, 0}, linesizes); sws_freeContext(sws_ctx); - return DNN_SUCCESS; + return ret; } diff --git a/libavfilter/dnn/dnn_io_proc.h b/libavfilter/dnn/dnn_io_proc.h index daef01ace..a3dd94675 100644 --- a/libavfilter/dnn/dnn_io_proc.h +++ b/libavfilter/dnn/dnn_io_proc.h @@ -30,9 +30,9 @@ #include "../dnn_interface.h" #include "libavutil/frame.h" -DNNReturnType ff_proc_from_frame_to_dnn(AVFrame *frame, DNNData *input, void *log_ctx); -DNNReturnType ff_proc_from_dnn_to_frame(AVFrame *frame, DNNData *output, void *log_ctx); -DNNReturnType ff_frame_to_dnn_detect(AVFrame *frame, DNNData *input, void *log_ctx); -DNNReturnType ff_frame_to_dnn_classify(AVFrame *frame, DNNData *input, uint32_t bbox_index, void *log_ctx); +int ff_proc_from_frame_to_dnn(AVFrame *frame, DNNData *input, void *log_ctx); +int ff_proc_from_dnn_to_frame(AVFrame *frame, DNNData *output, void *log_ctx); +int ff_frame_to_dnn_detect(AVFrame *frame, DNNData *input, void *log_ctx); +int ff_frame_to_dnn_classify(AVFrame *frame, DNNData *input, uint32_t bbox_index, void *log_ctx); #endif diff --git a/libavfilter/dnn_filter_common.c b/libavfilter/dnn_filter_common.c index 3c7a962b3..5083e3de1 100644 --- a/libavfilter/dnn_filter_common.c +++ b/libavfilter/dnn_filter_common.c @@ -106,18 +106,18 @@ int ff_dnn_set_classify_post_proc(DnnContext *ctx, ClassifyPostProc post_proc) return 0; } -DNNReturnType ff_dnn_get_input(DnnContext *ctx, DNNData *input) +int ff_dnn_get_input(DnnContext *ctx, DNNData *input) { return ctx->model->get_input(ctx->model->model, input, ctx->model_inputname); } -DNNReturnType ff_dnn_get_output(DnnContext *ctx, int input_width, int input_height, int *output_width, int *output_height) +int ff_dnn_get_output(DnnContext *ctx, int input_width, int input_height, int *output_width, int *output_height) { return ctx->model->get_output(ctx->model->model, ctx->model_inputname, input_width, input_height, (const char *)ctx->model_outputnames[0], output_width, output_height); } -DNNReturnType ff_dnn_execute_model(DnnContext *ctx, AVFrame *in_frame, AVFrame *out_frame) +int ff_dnn_execute_model(DnnContext *ctx, AVFrame *in_frame, AVFrame *out_frame) { DNNExecBaseParams exec_params = { .input_name = ctx->model_inputname, @@ -129,7 +129,7 @@ DNNReturnType ff_dnn_execute_model(DnnContext *ctx, AVFrame *in_frame, AVFrame * return (ctx->dnn_module->execute_model)(ctx->model, &exec_params); } -DNNReturnType ff_dnn_execute_model_classification(DnnContext *ctx, AVFrame *in_frame, AVFrame *out_frame, const char *target) +int ff_dnn_execute_model_classification(DnnContext *ctx, AVFrame *in_frame, AVFrame *out_frame, const char *target) { DNNExecClassificationParams class_params = { { @@ -149,7 +149,7 @@ DNNAsyncStatusType ff_dnn_get_result(DnnContext *ctx, AVFrame **in_frame, AVFram return (ctx->dnn_module->get_result)(ctx->model, in_frame, out_frame); } -DNNReturnType ff_dnn_flush(DnnContext *ctx) +int ff_dnn_flush(DnnContext *ctx) { return (ctx->dnn_module->flush)(ctx->model); } diff --git a/libavfilter/dnn_filter_common.h b/libavfilter/dnn_filter_common.h index 635ae631c..bcdf37c81 100644 --- a/libavfilter/dnn_filter_common.h +++ b/libavfilter/dnn_filter_common.h @@ -53,12 +53,12 @@ int ff_dnn_init(DnnContext *ctx, DNNFunctionType func_type, AVFilterContext *fil int ff_dnn_set_frame_proc(DnnContext *ctx, FramePrePostProc pre_proc, FramePrePostProc post_proc); int ff_dnn_set_detect_post_proc(DnnContext *ctx, DetectPostProc post_proc); int ff_dnn_set_classify_post_proc(DnnContext *ctx, ClassifyPostProc post_proc); -DNNReturnType ff_dnn_get_input(DnnContext *ctx, DNNData *input); -DNNReturnType ff_dnn_get_output(DnnContext *ctx, int input_width, int input_height, int *output_width, int *output_height); -DNNReturnType ff_dnn_execute_model(DnnContext *ctx, AVFrame *in_frame, AVFrame *out_frame); -DNNReturnType ff_dnn_execute_model_classification(DnnContext *ctx, AVFrame *in_frame, AVFrame *out_frame, const char *target); +int ff_dnn_get_input(DnnContext *ctx, DNNData *input); +int ff_dnn_get_output(DnnContext *ctx, int input_width, int input_height, int *output_width, int *output_height); +int ff_dnn_execute_model(DnnContext *ctx, AVFrame *in_frame, AVFrame *out_frame); +int ff_dnn_execute_model_classification(DnnContext *ctx, AVFrame *in_frame, AVFrame *out_frame, const char *target); DNNAsyncStatusType ff_dnn_get_result(DnnContext *ctx, AVFrame **in_frame, AVFrame **out_frame); -DNNReturnType ff_dnn_flush(DnnContext *ctx); +int ff_dnn_flush(DnnContext *ctx); void ff_dnn_uninit(DnnContext *ctx); #endif diff --git a/libavfilter/dnn_interface.h b/libavfilter/dnn_interface.h index 37e89d978..ef8d7ae66 100644 --- a/libavfilter/dnn_interface.h +++ b/libavfilter/dnn_interface.h @@ -30,7 +30,7 @@ #include "libavutil/frame.h" #include "avfilter.h" -typedef enum {DNN_SUCCESS, DNN_ERROR} DNNReturnType; +#define DNN_GENERIC_ERROR FFERRTAG('D','N','N','!') typedef enum {DNN_NATIVE, DNN_TF, DNN_OV} DNNBackendType; @@ -92,9 +92,9 @@ typedef struct DNNModel{ DNNFunctionType func_type; // Gets model input information // Just reuse struct DNNData here, actually the DNNData.data field is not needed. - DNNReturnType (*get_input)(void *model, DNNData *input, const char *input_name); + int (*get_input)(void *model, DNNData *input, const char *input_name); // Gets model output width/height with given input w/h - DNNReturnType (*get_output)(void *model, const char *input_name, int input_width, int input_height, + int (*get_output)(void *model, const char *input_name, int input_width, int input_height, const char *output_name, int *output_width, int *output_height); // set the pre process to transfer data from AVFrame to DNNData // the default implementation within DNN is used if it is not provided by the filter @@ -112,12 +112,12 @@ typedef struct DNNModel{ typedef struct DNNModule{ // Loads model and parameters from given file. Returns NULL if it is not possible. DNNModel *(*load_model)(const char *model_filename, DNNFunctionType func_type, const char *options, AVFilterContext *filter_ctx); - // Executes model with specified input and output. Returns DNN_ERROR otherwise. - DNNReturnType (*execute_model)(const DNNModel *model, DNNExecBaseParams *exec_params); + // Executes model with specified input and output. Returns the error code otherwise. + int (*execute_model)(const DNNModel *model, DNNExecBaseParams *exec_params); // Retrieve inference result. DNNAsyncStatusType (*get_result)(const DNNModel *model, AVFrame **in, AVFrame **out); // Flush all the pending tasks. - DNNReturnType (*flush)(const DNNModel *model); + int (*flush)(const DNNModel *model); // Frees memory allocated for model. void (*free_model)(DNNModel **model); } DNNModule; diff --git a/libavfilter/drawutils.c b/libavfilter/drawutils.c index 65ed61aa9..b4083b9a9 100644 --- a/libavfilter/drawutils.c +++ b/libavfilter/drawutils.c @@ -23,9 +23,10 @@ #include "libavutil/avassert.h" #include "libavutil/avutil.h" -#include "libavutil/colorspace.h" +#include "libavutil/csp.h" #include "libavutil/intreadwrite.h" #include "libavutil/pixdesc.h" +#include "colorspace.h" #include "drawutils.h" #include "formats.h" @@ -76,13 +77,14 @@ int ff_fill_rgba_map(uint8_t *rgba_map, enum AVPixelFormat pix_fmt) return 0; } -int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags) +int ff_draw_init2(FFDrawContext *draw, enum AVPixelFormat format, enum AVColorSpace csp, + enum AVColorRange range, unsigned flags) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(format); + const AVLumaCoefficients *luma = NULL; const AVComponentDescriptor *c; unsigned i, nb_planes = 0; int pixelstep[MAX_PLANES] = { 0 }; - int full_range = 0; int depthb = 0; if (!desc || !desc->name) @@ -91,9 +93,17 @@ int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags) return AVERROR(ENOSYS); if (desc->flags & ~(AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_ALPHA)) return AVERROR(ENOSYS); - if (format == AV_PIX_FMT_YUVJ420P || format == AV_PIX_FMT_YUVJ422P || format == AV_PIX_FMT_YUVJ444P || - format == AV_PIX_FMT_YUVJ411P || format == AV_PIX_FMT_YUVJ440P) - full_range = 1; + if (csp == AVCOL_SPC_UNSPECIFIED) + csp = (desc->flags & AV_PIX_FMT_FLAG_RGB) ? AVCOL_SPC_RGB : AVCOL_SPC_SMPTE170M; + if (!(desc->flags & AV_PIX_FMT_FLAG_RGB) && !(luma = av_csp_luma_coeffs_from_avcsp(csp))) + return AVERROR(EINVAL); + if (range == AVCOL_RANGE_UNSPECIFIED) + range = (format == AV_PIX_FMT_YUVJ420P || format == AV_PIX_FMT_YUVJ422P || + format == AV_PIX_FMT_YUVJ444P || format == AV_PIX_FMT_YUVJ411P || + format == AV_PIX_FMT_YUVJ440P || csp == AVCOL_SPC_RGB) + ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG; + if (range != AVCOL_RANGE_JPEG && range != AVCOL_RANGE_MPEG) + return AVERROR(EINVAL); for (i = 0; i < desc->nb_components; i++) { int db; c = &desc->comp[i]; @@ -130,18 +140,27 @@ int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags) draw->desc = desc; draw->format = format; draw->nb_planes = nb_planes; + draw->range = range; + draw->csp = csp; draw->flags = flags; - draw->full_range = full_range; + if (luma) + ff_fill_rgb2yuv_table(luma, draw->rgb2yuv); memcpy(draw->pixelstep, pixelstep, sizeof(draw->pixelstep)); draw->hsub[1] = draw->hsub[2] = draw->hsub_max = desc->log2_chroma_w; draw->vsub[1] = draw->vsub[2] = draw->vsub_max = desc->log2_chroma_h; return 0; } +int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags) +{ + return ff_draw_init2(draw, format, AVCOL_SPC_UNSPECIFIED, AVCOL_RANGE_UNSPECIFIED, flags); +} + void ff_draw_color(FFDrawContext *draw, FFDrawColor *color, const uint8_t rgba[4]) { unsigned i; - uint8_t tmp8[4]; + double yuvad[4]; + double rgbad[4]; const AVPixFmtDescriptor *desc = draw->desc; if (rgba != color->rgba) @@ -149,35 +168,36 @@ void ff_draw_color(FFDrawContext *draw, FFDrawColor *color, const uint8_t rgba[4 memset(color->comp, 0, sizeof(color->comp)); - if (draw->desc->flags & AV_PIX_FMT_FLAG_RGB) { - memcpy(tmp8, rgba, sizeof(tmp8)); - } else if (draw->nb_planes >= 2) { - /* assume YUV */ - tmp8[0] = draw->full_range ? RGB_TO_Y_JPEG(rgba[0], rgba[1], rgba[2]) : RGB_TO_Y_CCIR(rgba[0], rgba[1], rgba[2]); - tmp8[1] = draw->full_range ? RGB_TO_U_JPEG(rgba[0], rgba[1], rgba[2]) : RGB_TO_U_CCIR(rgba[0], rgba[1], rgba[2], 0); - tmp8[2] = draw->full_range ? RGB_TO_V_JPEG(rgba[0], rgba[1], rgba[2]) : RGB_TO_V_CCIR(rgba[0], rgba[1], rgba[2], 0); - tmp8[3] = rgba[3]; - } else if (draw->format == AV_PIX_FMT_GRAY8 || draw->format == AV_PIX_FMT_GRAY8A || - draw->format == AV_PIX_FMT_GRAY16LE || draw->format == AV_PIX_FMT_YA16LE || - draw->format == AV_PIX_FMT_GRAY9LE || - draw->format == AV_PIX_FMT_GRAY10LE || - draw->format == AV_PIX_FMT_GRAY12LE || - draw->format == AV_PIX_FMT_GRAY14LE) { - tmp8[0] = RGB_TO_Y_CCIR(rgba[0], rgba[1], rgba[2]); - tmp8[1] = rgba[3]; - } else { - av_log(NULL, AV_LOG_WARNING, - "Color conversion not implemented for %s\n", draw->desc->name); - memset(color, 128, sizeof(*color)); - return; + for (int i = 0; i < 4; i++) + rgbad[i] = color->rgba[i] / 255.; + + if (draw->desc->flags & AV_PIX_FMT_FLAG_RGB) + memcpy(yuvad, rgbad, sizeof(double) * 3); + else + ff_matrix_mul_3x3_vec(yuvad, rgbad, draw->rgb2yuv); + + yuvad[3] = rgbad[3]; + + for (int i = 0; i < 3; i++) { + int chroma = (!(draw->desc->flags & AV_PIX_FMT_FLAG_RGB) && i > 0); + if (draw->range == AVCOL_RANGE_MPEG) { + yuvad[i] *= (chroma ? 224. : 219.) / 255.; + yuvad[i] += (chroma ? 128. : 16.) / 255.; + } else if (chroma) { + yuvad[i] += 0.5; + } } + // Ensure we place the alpha appropriately for gray formats + if (desc->nb_components <= 2) + yuvad[1] = yuvad[3]; + for (i = 0; i < desc->nb_components; i++) { + unsigned val = yuvad[i] * ((1 << (draw->desc->comp[i].depth + draw->desc->comp[i].shift)) - 1) + 0.5; if (desc->comp[i].depth > 8) - color->comp[desc->comp[i].plane].u16[desc->comp[i].offset / 2] = tmp8[i] << - (draw->desc->comp[i].depth + draw->desc->comp[i].shift - 8); + color->comp[desc->comp[i].plane].u16[desc->comp[i].offset / 2] = val; else - color->comp[desc->comp[i].plane].u8[desc->comp[i].offset] = tmp8[i]; + color->comp[desc->comp[i].plane].u8[desc->comp[i].offset] = val; } } diff --git a/libavfilter/drawutils.h b/libavfilter/drawutils.h index 396688514..90df55107 100644 --- a/libavfilter/drawutils.h +++ b/libavfilter/drawutils.h @@ -41,8 +41,10 @@ typedef struct FFDrawContext { uint8_t vsub[MAX_PLANES]; /*< vertical subsampling */ uint8_t hsub_max; uint8_t vsub_max; - int full_range; + enum AVColorRange range; unsigned flags; + enum AVColorSpace csp; + double rgb2yuv[3][3]; } FFDrawContext; typedef struct FFDrawColor { @@ -64,13 +66,29 @@ typedef struct FFDrawColor { * * Only a limited number of pixel formats are supported, if format is not * supported the function will return an error. - * flags is combination of FF_DRAW_* flags. - * @return 0 for success, < 0 for error + * @param format pixel format of the frames that will be drawn onto + * @param csp color space of the frames that will be drawn onto, + * defaulting to BT601 or RGB depending on the specified format + * when AVCOL_SPC_UNSPECIFIED is passed. + * @param range sample value range of the frames that will be drawn onto, + * defaulting to TV-range unless using a legacy J format + * when AVCOL_RANGE_UNSPECIFIED is passed. + * @param flags combination of FF_DRAW_* flags. + * @return 0 for success, < 0 for error + */ +int ff_draw_init2(FFDrawContext *draw, enum AVPixelFormat format, enum AVColorSpace csp, + enum AVColorRange range, unsigned flags); + +/* + * Legacy wrapper for ff_draw_init2. */ int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags); + + /** - * Prepare a color. + * Prepare a color. The rgba value passed is always 8-bit full-range in the RGB space + * corresponding to the space set at initialization. */ void ff_draw_color(FFDrawContext *draw, FFDrawColor *color, const uint8_t rgba[4]); diff --git a/libavfilter/ebur128.c b/libavfilter/ebur128.c index 1a85a9036..062099e20 100644 --- a/libavfilter/ebur128.c +++ b/libavfilter/ebur128.c @@ -47,7 +47,8 @@ #include #include /* You may have to define _USE_MATH_DEFINES if you use MSVC */ -#include "libavutil/common.h" +#include "libavutil/error.h" +#include "libavutil/macros.h" #include "libavutil/mem.h" #include "libavutil/mem_internal.h" #include "libavutil/thread.h" diff --git a/libavfilter/edge_common.c b/libavfilter/edge_common.c new file mode 100644 index 000000000..d72e8521c --- /dev/null +++ b/libavfilter/edge_common.c @@ -0,0 +1,181 @@ +/* + * 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 "edge_common.h" + +// Internal helper for ff_sobel() +static int get_rounded_direction(int gx, int gy) +{ + /* reference angles: + * tan( pi/8) = sqrt(2)-1 + * tan(3pi/8) = sqrt(2)+1 + * Gy/Gx is the tangent of the angle (theta), so Gy/Gx is compared against + * , or more simply Gy against *Gx + * + * Gx and Gy bounds = [-1020;1020], using 16-bit arithmetic: + * round((sqrt(2)-1) * (1<<16)) = 27146 + * round((sqrt(2)+1) * (1<<16)) = 158218 + */ + if (gx) { + int tanpi8gx, tan3pi8gx; + + if (gx < 0) + gx = -gx, gy = -gy; + gy *= (1 << 16); + tanpi8gx = 27146 * gx; + tan3pi8gx = 158218 * gx; + if (gy > -tan3pi8gx && gy < -tanpi8gx) return DIRECTION_45UP; + if (gy > -tanpi8gx && gy < tanpi8gx) return DIRECTION_HORIZONTAL; + if (gy > tanpi8gx && gy < tan3pi8gx) return DIRECTION_45DOWN; + } + return DIRECTION_VERTICAL; +} + +// Simple sobel operator to get rounded gradients +void ff_sobel(int w, int h, + uint16_t *dst, int dst_linesize, + int8_t *dir, int dir_linesize, + const uint8_t *src, int src_linesize) +{ + int i, j; + + for (j = 1; j < h - 1; j++) { + dst += dst_linesize; + dir += dir_linesize; + src += src_linesize; + for (i = 1; i < w - 1; i++) { + const int gx = + -1*src[-src_linesize + i-1] + 1*src[-src_linesize + i+1] + -2*src[ i-1] + 2*src[ i+1] + -1*src[ src_linesize + i-1] + 1*src[ src_linesize + i+1]; + const int gy = + -1*src[-src_linesize + i-1] + 1*src[ src_linesize + i-1] + -2*src[-src_linesize + i ] + 2*src[ src_linesize + i ] + -1*src[-src_linesize + i+1] + 1*src[ src_linesize + i+1]; + + dst[i] = FFABS(gx) + FFABS(gy); + dir[i] = get_rounded_direction(gx, gy); + } + } +} + +// Filters rounded gradients to drop all non-maxima +// Expects gradients generated by ff_sobel() +// Expects zero's destination buffer +void ff_non_maximum_suppression(int w, int h, + uint8_t *dst, int dst_linesize, + const int8_t *dir, int dir_linesize, + const uint16_t *src, int src_linesize) +{ + int i, j; + +#define COPY_MAXIMA(ay, ax, by, bx) do { \ + if (src[i] > src[(ay)*src_linesize + i+(ax)] && \ + src[i] > src[(by)*src_linesize + i+(bx)]) \ + dst[i] = av_clip_uint8(src[i]); \ +} while (0) + + for (j = 1; j < h - 1; j++) { + dst += dst_linesize; + dir += dir_linesize; + src += src_linesize; + for (i = 1; i < w - 1; i++) { + switch (dir[i]) { + case DIRECTION_45UP: COPY_MAXIMA( 1, -1, -1, 1); break; + case DIRECTION_45DOWN: COPY_MAXIMA(-1, -1, 1, 1); break; + case DIRECTION_HORIZONTAL: COPY_MAXIMA( 0, -1, 0, 1); break; + case DIRECTION_VERTICAL: COPY_MAXIMA(-1, 0, 1, 0); break; + } + } + } +} + +// Filter to keep all pixels > high, and keep all pixels > low where all surrounding pixels > high +void ff_double_threshold(int low, int high, int w, int h, + uint8_t *dst, int dst_linesize, + const uint8_t *src, int src_linesize) +{ + int i, j; + + for (j = 0; j < h; j++) { + for (i = 0; i < w; i++) { + if (src[i] > high) { + dst[i] = src[i]; + continue; + } + + if (!(!i || i == w - 1 || !j || j == h - 1) && + src[i] > low && + (src[-src_linesize + i-1] > high || + src[-src_linesize + i ] > high || + src[-src_linesize + i+1] > high || + src[ i-1] > high || + src[ i+1] > high || + src[ src_linesize + i-1] > high || + src[ src_linesize + i ] > high || + src[ src_linesize + i+1] > high)) + dst[i] = src[i]; + else + dst[i] = 0; + } + dst += dst_linesize; + src += src_linesize; + } +} + +// Applies gaussian blur, using 5x5 kernels, sigma = 1.4 +void ff_gaussian_blur(int w, int h, + uint8_t *dst, int dst_linesize, + const uint8_t *src, int src_linesize) +{ + int i, j; + + memcpy(dst, src, w); dst += dst_linesize; src += src_linesize; + memcpy(dst, src, w); dst += dst_linesize; src += src_linesize; + for (j = 2; j < h - 2; j++) { + dst[0] = src[0]; + dst[1] = src[1]; + for (i = 2; i < w - 2; i++) { + /* Gaussian mask of size 5x5 with sigma = 1.4 */ + dst[i] = ((src[-2*src_linesize + i-2] + src[2*src_linesize + i-2]) * 2 + + (src[-2*src_linesize + i-1] + src[2*src_linesize + i-1]) * 4 + + (src[-2*src_linesize + i ] + src[2*src_linesize + i ]) * 5 + + (src[-2*src_linesize + i+1] + src[2*src_linesize + i+1]) * 4 + + (src[-2*src_linesize + i+2] + src[2*src_linesize + i+2]) * 2 + + + (src[ -src_linesize + i-2] + src[ src_linesize + i-2]) * 4 + + (src[ -src_linesize + i-1] + src[ src_linesize + i-1]) * 9 + + (src[ -src_linesize + i ] + src[ src_linesize + i ]) * 12 + + (src[ -src_linesize + i+1] + src[ src_linesize + i+1]) * 9 + + (src[ -src_linesize + i+2] + src[ src_linesize + i+2]) * 4 + + + src[i-2] * 5 + + src[i-1] * 12 + + src[i ] * 15 + + src[i+1] * 12 + + src[i+2] * 5) / 159; + } + dst[i ] = src[i ]; + dst[i + 1] = src[i + 1]; + + dst += dst_linesize; + src += src_linesize; + } + memcpy(dst, src, w); dst += dst_linesize; src += src_linesize; + memcpy(dst, src, w); +} diff --git a/libavfilter/edge_common.h b/libavfilter/edge_common.h new file mode 100644 index 000000000..87c143f2b --- /dev/null +++ b/libavfilter/edge_common.h @@ -0,0 +1,107 @@ +/* + * 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 + * common functions for edge detection + */ + +#ifndef AVFILTER_EDGE_COMMON_H +#define AVFILTER_EDGE_COMMON_H + +#include "avfilter.h" + +/** + * @brief Rounded directions used in av_image_sobel() + */ +enum AVRoundedDirection { + DIRECTION_45UP, + DIRECTION_45DOWN, + DIRECTION_HORIZONTAL, + DIRECTION_VERTICAL, +}; + +/** + * Simple sobel operator to get rounded gradients + * + * @param w the width of the image in pixels + * @param h the height of the image in pixels + * @param dst data pointers to magnitude image + * @param dst_linesize linesizes for the magnitude image + * @param dir data pointers to direction image + * @param dir_linesize linesizes for the direction image + * @param src data pointers to source image + * @param src_linesize linesizes for the source image + */ +void ff_sobel(int w, int h, + uint16_t *dst, int dst_linesize, + int8_t *dir, int dir_linesize, + const uint8_t *src, int src_linesize); + +/** + * Filters rounded gradients to drop all non-maxima pixels in the magnitude image + * Expects gradients generated by av_image_sobel() + * Expects zero's in the destination buffer dst + * + * @param w the width of the image in pixels + * @param h the height of the image in pixels + * @param dst data pointers to magnitude image + * @param dst_linesize linesizes for the magnitude image + * @param dir data pointers to direction image + * @param dir_linesize linesizes for the direction image + * @param src data pointers to source image + * @param src_linesize linesizes for the source image + */ +void ff_non_maximum_suppression(int w, int h, + uint8_t *dst, int dst_linesize, + const int8_t *dir, int dir_linesize, + const uint16_t *src, int src_linesize); + +/** + * Filters all pixels in src to keep all pixels > high, + * and keep all pixels > low where all surrounding pixels > high + * + * @param low the low threshold value + * @param high the hegh threshold value + * @param w the width of the image in pixels + * @param h the height of the image in pixels + * @param dst data pointers to destination image + * @param dst_linesize linesizes for the destination image + * @param src data pointers to source image + * @param src_linesize linesizes for the source image + */ +void ff_double_threshold(int low, int high, int w, int h, + uint8_t *dst, int dst_linesize, + const uint8_t *src, int src_linesize); + +/** + * Applies gaussian blur. + * 5x5 kernels, sigma = 1.4 + * + * @param w the width of the image in pixels + * @param h the height of the image in pixels + * @param dst data pointers to destination image + * @param dst_linesize linesizes for the destination image + * @param src data pointers to source image + * @param src_linesize linesizes for the source image + */ +void ff_gaussian_blur(int w, int h, + uint8_t *dst, int dst_linesize, + const uint8_t *src, int src_linesize); + +#endif diff --git a/libavfilter/f_bench.c b/libavfilter/f_bench.c index 109a530d7..9b55194db 100644 --- a/libavfilter/f_bench.c +++ b/libavfilter/f_bench.c @@ -16,6 +16,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/opt.h" #include "libavutil/time.h" #include "avfilter.h" diff --git a/libavfilter/f_cue.c b/libavfilter/f_cue.c index d90fe54b9..9a1b7c03b 100644 --- a/libavfilter/f_cue.c +++ b/libavfilter/f_cue.c @@ -18,6 +18,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/opt.h" #include "libavutil/time.h" #include "avfilter.h" diff --git a/libavfilter/f_drawgraph.c b/libavfilter/f_drawgraph.c index b6fcb3b75..000255fc5 100644 --- a/libavfilter/f_drawgraph.c +++ b/libavfilter/f_drawgraph.c @@ -18,6 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "float.h" #include "libavutil/avstring.h" diff --git a/libavfilter/f_ebur128.c b/libavfilter/f_ebur128.c index 88d6a1fe4..195c9a863 100644 --- a/libavfilter/f_ebur128.c +++ b/libavfilter/f_ebur128.c @@ -39,11 +39,10 @@ #include "libswresample/swresample.h" #include "audio.h" #include "avfilter.h" +#include "filters.h" #include "formats.h" #include "internal.h" -#define MAX_CHANNELS 63 - #define ABS_THRES -70 ///< silence gate: we discard anything below this absolute (LUFS) threshold #define ABS_UP_THRES 10 ///< upper loud limit to consider (ABS_THRES being the minimum) #define HIST_GRAIN 100 ///< defines histogram precision @@ -57,16 +56,16 @@ * infinitely over the time and is thus more scalable. */ struct hist_entry { - int count; ///< how many times the corresponding value occurred + unsigned count; ///< how many times the corresponding value occurred double energy; ///< E = 10^((L + 0.691) / 10) double loudness; ///< L = -0.691 + 10 * log10(E) }; struct integrator { - double *cache[MAX_CHANNELS]; ///< window of filtered samples (N ms) + double **cache; ///< window of filtered samples (N ms) int cache_pos; ///< focus on the last added bin in the cache array int cache_size; - double sum[MAX_CHANNELS]; ///< sum of the last N ms filtered samples (cache content) + double *sum; ///< sum of the last N ms filtered samples (cache content) int filled; ///< 1 if the cache is completely filled, 0 otherwise double rel_threshold; ///< relative threshold double sum_kept_powers; ///< sum of the powers (weighted sums) above absolute threshold @@ -108,12 +107,15 @@ typedef struct EBUR128Context { int nb_channels; ///< number of channels in the input double *ch_weighting; ///< channel weighting mapping int sample_count; ///< sample count used for refresh frequency, reset at refresh + int nb_samples; ///< number of samples to consume per single input frame + int idx_insample; ///< current sample position of processed samples in single input frame + AVFrame *insamples; ///< input samples reference, updated regularly /* Filter caches. * The mult by 3 in the following is for X[i], X[i-1] and X[i-2] */ - double x[MAX_CHANNELS * 3]; ///< 3 input samples cache for each channel - double y[MAX_CHANNELS * 3]; ///< 3 pre-filter samples cache for each channel - double z[MAX_CHANNELS * 3]; ///< 3 RLB-filter samples cache for each channel + double *x; ///< 3 input samples cache for each channel + double *y; ///< 3 pre-filter samples cache for each channel + double *z; ///< 3 RLB-filter samples cache for each channel double pre_b[3]; ///< pre-filter numerator coefficients double pre_a[3]; ///< pre-filter denominator coefficients double rlb_b[3]; ///< rlb-filter numerator coefficients @@ -281,6 +283,7 @@ static int config_video_output(AVFilterLink *outlink) int i, x, y; uint8_t *p; AVFilterContext *ctx = outlink->src; + AVFilterLink *inlink = ctx->inputs[0]; EBUR128Context *ebur128 = ctx->priv; AVFrame *outpicref; @@ -293,6 +296,8 @@ static int config_video_output(AVFilterLink *outlink) outlink->w = ebur128->w; outlink->h = ebur128->h; outlink->sample_aspect_ratio = (AVRational){1,1}; + outlink->time_base = inlink->time_base; + outlink->frame_rate = av_make_q(10, 1); #define PAD 8 @@ -412,8 +417,7 @@ static int config_audio_input(AVFilterLink *inlink) * can be more complex to integrate in the one-sample loop of * filter_frame()). */ if (ebur128->metadata || (ebur128->peak_mode & PEAK_MODE_TRUE_PEAKS)) - inlink->min_samples = - inlink->max_samples = inlink->sample_rate / 10; + ebur128->nb_samples = inlink->sample_rate / 10; return 0; } @@ -422,7 +426,7 @@ static int config_audio_output(AVFilterLink *outlink) int i; AVFilterContext *ctx = outlink->src; EBUR128Context *ebur128 = ctx->priv; - const int nb_channels = av_get_channel_layout_nb_channels(outlink->channel_layout); + const int nb_channels = outlink->ch_layout.nb_channels; #define BACK_MASK (AV_CH_BACK_LEFT |AV_CH_BACK_CENTER |AV_CH_BACK_RIGHT| \ AV_CH_TOP_BACK_LEFT|AV_CH_TOP_BACK_CENTER|AV_CH_TOP_BACK_RIGHT| \ @@ -430,19 +434,30 @@ static int config_audio_output(AVFilterLink *outlink) AV_CH_SURROUND_DIRECT_LEFT |AV_CH_SURROUND_DIRECT_RIGHT) ebur128->nb_channels = nb_channels; + ebur128->x = av_calloc(nb_channels, 3 * sizeof(*ebur128->x)); + ebur128->y = av_calloc(nb_channels, 3 * sizeof(*ebur128->y)); + ebur128->z = av_calloc(nb_channels, 3 * sizeof(*ebur128->z)); ebur128->ch_weighting = av_calloc(nb_channels, sizeof(*ebur128->ch_weighting)); - if (!ebur128->ch_weighting) + if (!ebur128->ch_weighting || !ebur128->x || !ebur128->y || !ebur128->z) return AVERROR(ENOMEM); #define I400_BINS(x) ((x) * 4 / 10) #define I3000_BINS(x) ((x) * 3) + ebur128->i400.sum = av_calloc(nb_channels, sizeof(*ebur128->i400.sum)); + ebur128->i3000.sum = av_calloc(nb_channels, sizeof(*ebur128->i3000.sum)); + ebur128->i400.cache = av_calloc(nb_channels, sizeof(*ebur128->i400.cache)); + ebur128->i3000.cache = av_calloc(nb_channels, sizeof(*ebur128->i3000.cache)); + if (!ebur128->i400.sum || !ebur128->i3000.sum || + !ebur128->i400.cache || !ebur128->i3000.cache) + return AVERROR(ENOMEM); + for (i = 0; i < nb_channels; i++) { /* channel weighting */ - const uint64_t chl = av_channel_layout_extract_channel(outlink->channel_layout, i); - if (chl & (AV_CH_LOW_FREQUENCY|AV_CH_LOW_FREQUENCY_2)) { + const enum AVChannel chl = av_channel_layout_channel_from_index(&outlink->ch_layout, i); + if (chl == AV_CHAN_LOW_FREQUENCY || chl == AV_CHAN_LOW_FREQUENCY_2) { ebur128->ch_weighting[i] = 0; - } else if (chl & BACK_MASK) { + } else if (chl < 64 && (1ULL << chl) & BACK_MASK) { ebur128->ch_weighting[i] = 1.41; } else { ebur128->ch_weighting[i] = 1.0; @@ -472,11 +487,11 @@ static int config_audio_output(AVFilterLink *outlink) !ebur128->true_peaks_per_frame || !ebur128->swr_ctx) return AVERROR(ENOMEM); - av_opt_set_int(ebur128->swr_ctx, "in_channel_layout", outlink->channel_layout, 0); + av_opt_set_chlayout(ebur128->swr_ctx, "in_chlayout", &outlink->ch_layout, 0); av_opt_set_int(ebur128->swr_ctx, "in_sample_rate", outlink->sample_rate, 0); av_opt_set_sample_fmt(ebur128->swr_ctx, "in_sample_fmt", outlink->format, 0); - av_opt_set_int(ebur128->swr_ctx, "out_channel_layout", outlink->channel_layout, 0); + av_opt_set_chlayout(ebur128->swr_ctx, "out_chlayout", &outlink->ch_layout, 0); av_opt_set_int(ebur128->swr_ctx, "out_sample_rate", 192000, 0); av_opt_set_sample_fmt(ebur128->swr_ctx, "out_sample_fmt", outlink->format, 0); @@ -609,7 +624,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) AVFrame *pic = ebur128->outpicref; #if CONFIG_SWRESAMPLE - if (ebur128->peak_mode & PEAK_MODE_TRUE_PEAKS) { + if (ebur128->peak_mode & PEAK_MODE_TRUE_PEAKS && ebur128->idx_insample == 0) { const double *swr_samples = ebur128->swr_buf; int ret = swr_convert(ebur128->swr_ctx, (uint8_t**)&ebur128->swr_buf, 19200, (const uint8_t **)insamples->data, nb_samples); @@ -628,7 +643,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) } #endif - for (idx_insample = 0; idx_insample < nb_samples; idx_insample++) { + for (idx_insample = ebur128->idx_insample; idx_insample < nb_samples; idx_insample++) { const int bin_id_400 = ebur128->i400.cache_pos; const int bin_id_3000 = ebur128->i3000.cache_pos; @@ -648,9 +663,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) double bin; if (ebur128->peak_mode & PEAK_MODE_SAMPLES_PEAKS) - ebur128->sample_peaks[ch] = FFMAX(ebur128->sample_peaks[ch], fabs(*samples)); + ebur128->sample_peaks[ch] = FFMAX(ebur128->sample_peaks[ch], fabs(samples[idx_insample * nb_channels + ch])); - ebur128->x[ch * 3] = *samples++; // set X[i] + ebur128->x[ch * 3] = samples[idx_insample * nb_channels + ch]; // set X[i] if (!ebur128->ch_weighting[ch]) continue; @@ -713,15 +728,15 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) #define I_GATE_THRES -10 // initially defined to -8 LU in the first EBU standard if (loudness_400 >= ABS_THRES) { - double integrated_sum = 0; - int nb_integrated = 0; + double integrated_sum = 0.0; + uint64_t nb_integrated = 0; int gate_hist_pos = gate_update(&ebur128->i400, power_400, loudness_400, I_GATE_THRES); /* compute integrated loudness by summing the histogram values * above the relative threshold */ for (i = gate_hist_pos; i < HIST_SIZE; i++) { - const int nb_v = ebur128->i400.histogram[i].count; + const unsigned nb_v = ebur128->i400.histogram[i].count; nb_integrated += nb_v; integrated_sum += nb_v * ebur128->i400.histogram[i].energy; } @@ -742,18 +757,18 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) /* XXX: example code in EBU 3342 is ">=" but formula in BS.1770 * specs is ">" */ if (loudness_3000 >= ABS_THRES) { - int nb_powers = 0; + uint64_t nb_powers = 0; int gate_hist_pos = gate_update(&ebur128->i3000, power_3000, loudness_3000, LRA_GATE_THRES); for (i = gate_hist_pos; i < HIST_SIZE; i++) nb_powers += ebur128->i3000.histogram[i].count; if (nb_powers) { - int n, nb_pow; + uint64_t n, nb_pow; /* get lower loudness to consider */ n = 0; - nb_pow = LRA_LOWER_PRC * nb_powers / 100. + 0.5; + nb_pow = LRA_LOWER_PRC * nb_powers * 0.01 + 0.5; for (i = gate_hist_pos; i < HIST_SIZE; i++) { n += ebur128->i3000.histogram[i].count; if (n >= nb_pow) { @@ -764,9 +779,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) /* get higher loudness to consider */ n = nb_powers; - nb_pow = LRA_HIGHER_PRC * nb_powers / 100. + 0.5; + nb_pow = LRA_HIGHER_PRC * nb_powers * 0.01 + 0.5; for (i = HIST_SIZE - 1; i >= 0; i--) { - n -= ebur128->i3000.histogram[i].count; + n -= FFMIN(n, ebur128->i3000.histogram[i].count); if (n < nb_pow) { ebur128->lra_high = ebur128->i3000.histogram[i].loudness; break; @@ -789,7 +804,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) /* push one video frame */ if (ebur128->do_video) { AVFrame *clone; - int x, y, ret; + int x, y; uint8_t *p; double gauge_value; int y_loudness_lu_graph, y_loudness_lu_gauge; @@ -803,6 +818,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) y_loudness_lu_graph = lu_to_y(ebur128, loudness_3000 - ebur128->target); y_loudness_lu_gauge = lu_to_y(ebur128, gauge_value); + av_frame_make_writable(pic); /* draw the graph using the short-term loudness */ p = pic->data[0] + ebur128->graph.y*pic->linesize[0] + ebur128->graph.x*3; for (y = 0; y < ebur128->graph.h; y++) { @@ -841,9 +857,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) clone = av_frame_clone(pic); if (!clone) return AVERROR(ENOMEM); - ret = ff_filter_frame(outlink, clone); - if (ret < 0) - return ret; + ebur128->idx_insample = idx_insample + 1; + ff_filter_set_ready(ctx, 100); + return ff_filter_frame(outlink, clone); } if (ebur128->metadata) { /* happens only once per filter_frame call */ @@ -857,12 +873,17 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) #define SET_META_PEAK(name, ptype) do { \ if (ebur128->peak_mode & PEAK_MODE_ ## ptype ## _PEAKS) { \ + double max_peak = 0.0; \ char key[64]; \ for (ch = 0; ch < nb_channels; ch++) { \ snprintf(key, sizeof(key), \ META_PREFIX AV_STRINGIFY(name) "_peaks_ch%d", ch); \ + max_peak = fmax(max_peak, ebur128->name##_peaks[ch]); \ SET_META(key, ebur128->name##_peaks[ch]); \ } \ + snprintf(key, sizeof(key), \ + META_PREFIX AV_STRINGIFY(name) "_peak"); \ + SET_META(key, max_peak); \ } \ } while (0) @@ -902,12 +923,53 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) PRINT_PEAKS("FTPK", ebur128->true_peaks_per_frame, TRUE); PRINT_PEAKS("TPK", ebur128->true_peaks, TRUE); av_log(ctx, ebur128->loglevel, "\n"); + } } + ebur128->idx_insample = 0; + ebur128->insamples = NULL; + return ff_filter_frame(ctx->outputs[ebur128->do_video], insamples); } +static int activate(AVFilterContext *ctx) +{ + AVFilterLink *inlink = ctx->inputs[0]; + EBUR128Context *ebur128 = ctx->priv; + AVFilterLink *voutlink = ctx->outputs[0]; + AVFilterLink *outlink = ctx->outputs[ebur128->do_video]; + int ret; + + FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); + if (ebur128->do_video) + FF_FILTER_FORWARD_STATUS_BACK(voutlink, inlink); + + if (!ebur128->insamples) { + AVFrame *in; + + if (ebur128->nb_samples > 0) { + ret = ff_inlink_consume_samples(inlink, ebur128->nb_samples, ebur128->nb_samples, &in); + } else { + ret = ff_inlink_consume_frame(inlink, &in); + } + if (ret < 0) + return ret; + if (ret > 0) + ebur128->insamples = in; + } + + if (ebur128->insamples) + ret = filter_frame(inlink, ebur128->insamples); + + FF_FILTER_FORWARD_STATUS_ALL(inlink, ctx); + FF_FILTER_FORWARD_WANTED(outlink, inlink); + if (ebur128->do_video) + FF_FILTER_FORWARD_WANTED(voutlink, inlink); + + return ret; +} + static int query_formats(AVFilterContext *ctx) { EBUR128Context *ebur128 = ctx->priv; @@ -993,16 +1055,25 @@ static av_cold void uninit(AVFilterContext *ctx) av_log(ctx, AV_LOG_INFO, "\n"); av_freep(&ebur128->y_line_ref); + av_freep(&ebur128->x); + av_freep(&ebur128->y); + av_freep(&ebur128->z); av_freep(&ebur128->ch_weighting); av_freep(&ebur128->true_peaks); av_freep(&ebur128->sample_peaks); av_freep(&ebur128->true_peaks_per_frame); + av_freep(&ebur128->i400.sum); + av_freep(&ebur128->i3000.sum); av_freep(&ebur128->i400.histogram); av_freep(&ebur128->i3000.histogram); for (i = 0; i < ebur128->nb_channels; i++) { - av_freep(&ebur128->i400.cache[i]); - av_freep(&ebur128->i3000.cache[i]); + if (ebur128->i400.cache) + av_freep(&ebur128->i400.cache[i]); + if (ebur128->i3000.cache) + av_freep(&ebur128->i3000.cache[i]); } + av_freep(&ebur128->i400.cache); + av_freep(&ebur128->i3000.cache); av_frame_free(&ebur128->outpicref); #if CONFIG_SWRESAMPLE av_freep(&ebur128->swr_buf); @@ -1014,7 +1085,6 @@ static const AVFilterPad ebur128_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_AUDIO, - .filter_frame = filter_frame, .config_props = config_audio_input, }, }; @@ -1025,6 +1095,7 @@ const AVFilter ff_af_ebur128 = { .priv_size = sizeof(EBUR128Context), .init = init, .uninit = uninit, + .activate = activate, FILTER_INPUTS(ebur128_inputs), .outputs = NULL, FILTER_QUERY_FUNC(query_formats), diff --git a/libavfilter/f_graphmonitor.c b/libavfilter/f_graphmonitor.c index 51d0a568e..016a707a2 100644 --- a/libavfilter/f_graphmonitor.c +++ b/libavfilter/f_graphmonitor.c @@ -18,6 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "float.h" #include "libavutil/pixdesc.h" @@ -32,6 +34,10 @@ #include "internal.h" #include "video.h" +typedef struct CacheItem { + int64_t previous_pts_us; +} CacheItem; + typedef struct GraphMonitorContext { const AVClass *class; @@ -49,6 +55,10 @@ typedef struct GraphMonitorContext { uint8_t green[4]; uint8_t blue[4]; uint8_t bg[4]; + + CacheItem *cache; + unsigned int cache_size; + unsigned int cache_index; } GraphMonitorContext; enum { @@ -64,6 +74,10 @@ enum { MODE_EOF = 1 << 9, MODE_SCIN = 1 << 10, MODE_SCOUT = 1 << 11, + MODE_PTS_DELTA = 1 << 12, + MODE_TIME_DELTA = 1 << 13, + MODE_FC_DELTA = 1 << 14, + MODE_SC_DELTA = 1 << 15, }; #define OFFSET(x) offsetof(GraphMonitorContext, x) @@ -83,8 +97,11 @@ static const AVOption graphmonitor_options[] = { { "queue", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_QUEUE}, 0, 0, VF, "flags" }, { "frame_count_in", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_FCOUT}, 0, 0, VF, "flags" }, { "frame_count_out", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_FCIN}, 0, 0, VF, "flags" }, + { "frame_count_delta",NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_FC_DELTA},0, 0, VF, "flags" }, { "pts", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_PTS}, 0, 0, VF, "flags" }, + { "pts_delta", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_PTS_DELTA},0,0, VF, "flags" }, { "time", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_TIME}, 0, 0, VF, "flags" }, + { "time_delta", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_TIME_DELTA},0,0,VF, "flags" }, { "timebase", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_TB}, 0, 0, VF, "flags" }, { "format", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_FMT}, 0, 0, VF, "flags" }, { "size", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_SIZE}, 0, 0, VF, "flags" }, @@ -92,11 +109,24 @@ static const AVOption graphmonitor_options[] = { { "eof", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_EOF}, 0, 0, VF, "flags" }, { "sample_count_in", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_SCOUT}, 0, 0, VF, "flags" }, { "sample_count_out", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_SCIN}, 0, 0, VF, "flags" }, + { "sample_count_delta",NULL,0, AV_OPT_TYPE_CONST, {.i64=MODE_SC_DELTA},0, 0, VF, "flags" }, { "rate", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, VF }, { "r", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, VF }, { NULL } }; +static av_cold int init(AVFilterContext *ctx) +{ + GraphMonitorContext *s = ctx->priv; + + s->cache = av_fast_realloc(NULL, &s->cache_size, + 8192 * sizeof(*(s->cache))); + if (!s->cache) + return AVERROR(ENOMEM); + + return 0; +} + static int query_formats(AVFilterContext *ctx) { AVFilterLink *outlink = ctx->outputs[0]; @@ -173,12 +203,14 @@ static int filter_have_queued(AVFilterContext *filter) return 0; } -static void draw_items(AVFilterContext *ctx, AVFrame *out, - int xpos, int ypos, - AVFilterLink *l, - size_t frames) +static int draw_items(AVFilterContext *ctx, AVFrame *out, + int xpos, int ypos, + AVFilterLink *l, + size_t frames) { GraphMonitorContext *s = ctx->priv; + int64_t previous_pts_us = s->cache[s->cache_index].previous_pts_us; + int64_t current_pts_us = l->current_pts_us; char buffer[1024] = { 0 }; if (s->flags & MODE_FMT) { @@ -196,7 +228,7 @@ static void draw_items(AVFilterContext *ctx, AVFrame *out, if (l->type == AVMEDIA_TYPE_VIDEO) { snprintf(buffer, sizeof(buffer)-1, " | size: %dx%d", l->w, l->h); } else if (l->type == AVMEDIA_TYPE_AUDIO) { - snprintf(buffer, sizeof(buffer)-1, " | channels: %d", l->channels); + snprintf(buffer, sizeof(buffer)-1, " | channels: %d", l->ch_layout.nb_channels); } drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; @@ -233,6 +265,11 @@ static void draw_items(AVFilterContext *ctx, AVFrame *out, drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } + if (s->flags & MODE_FC_DELTA) { + snprintf(buffer, sizeof(buffer)-1, " | delta: %"PRId64, l->frame_count_in - l->frame_count_out); + drawtext(out, xpos, ypos, buffer, s->white); + xpos += strlen(buffer) * 8; + } if (s->flags & MODE_SCIN) { snprintf(buffer, sizeof(buffer)-1, " | sin: %"PRId64, l->sample_count_in); drawtext(out, xpos, ypos, buffer, s->white); @@ -243,13 +280,28 @@ static void draw_items(AVFilterContext *ctx, AVFrame *out, drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } + if (s->flags & MODE_SC_DELTA) { + snprintf(buffer, sizeof(buffer)-1, " | sdelta: %"PRId64, l->sample_count_in - l->sample_count_out); + drawtext(out, xpos, ypos, buffer, s->white); + xpos += strlen(buffer) * 8; + } if (s->flags & MODE_PTS) { - snprintf(buffer, sizeof(buffer)-1, " | pts: %s", av_ts2str(l->current_pts_us)); + snprintf(buffer, sizeof(buffer)-1, " | pts: %s", av_ts2str(current_pts_us)); + drawtext(out, xpos, ypos, buffer, s->white); + xpos += strlen(buffer) * 8; + } + if (s->flags & MODE_PTS_DELTA) { + snprintf(buffer, sizeof(buffer)-1, " | pts_delta: %s", av_ts2str(current_pts_us - previous_pts_us)); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } if (s->flags & MODE_TIME) { - snprintf(buffer, sizeof(buffer)-1, " | time: %s", av_ts2timestr(l->current_pts_us, &AV_TIME_BASE_Q)); + snprintf(buffer, sizeof(buffer)-1, " | time: %s", av_ts2timestr(current_pts_us, &AV_TIME_BASE_Q)); + drawtext(out, xpos, ypos, buffer, s->white); + xpos += strlen(buffer) * 8; + } + if (s->flags & MODE_TIME_DELTA) { + snprintf(buffer, sizeof(buffer)-1, " | time_delta: %s", av_ts2timestr(current_pts_us - previous_pts_us, &AV_TIME_BASE_Q)); drawtext(out, xpos, ypos, buffer, s->white); xpos += strlen(buffer) * 8; } @@ -258,6 +310,19 @@ static void draw_items(AVFilterContext *ctx, AVFrame *out, drawtext(out, xpos, ypos, buffer, s->blue); xpos += strlen(buffer) * 8; } + + s->cache[s->cache_index].previous_pts_us = l->current_pts_us; + + if (s->cache_index + 1 >= s->cache_size / sizeof(*(s->cache))) { + void *ptr = av_fast_realloc(s->cache, &s->cache_size, s->cache_size * 2); + + if (!ptr) + return AVERROR(ENOMEM); + s->cache = ptr; + } + s->cache_index++; + + return 0; } static int create_frame(AVFilterContext *ctx, int64_t pts) @@ -265,7 +330,7 @@ static int create_frame(AVFilterContext *ctx, int64_t pts) GraphMonitorContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; AVFrame *out; - int xpos, ypos = 0; + int ret, xpos, ypos = 0; out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) @@ -273,6 +338,8 @@ static int create_frame(AVFilterContext *ctx, int64_t pts) clear_image(s, out, outlink); + s->cache_index = 0; + for (int i = 0; i < ctx->graph->nb_filters; i++) { AVFilterContext *filter = ctx->graph->filters[i]; char buffer[1024] = { 0 }; @@ -298,7 +365,9 @@ static int create_frame(AVFilterContext *ctx, int64_t pts) xpos += strlen(buffer) * 8; drawtext(out, xpos, ypos, l->src->name, s->white); xpos += strlen(l->src->name) * 8 + 10; - draw_items(ctx, out, xpos, ypos, l, frames); + ret = draw_items(ctx, out, xpos, ypos, l, frames); + if (ret < 0) + goto error; ypos += 10; } @@ -316,7 +385,9 @@ static int create_frame(AVFilterContext *ctx, int64_t pts) xpos += strlen(buffer) * 8; drawtext(out, xpos, ypos, l->dst->name, s->white); xpos += strlen(l->dst->name) * 8 + 10; - draw_items(ctx, out, xpos, ypos, l, frames); + ret = draw_items(ctx, out, xpos, ypos, l, frames); + if (ret < 0) + goto error; ypos += 10; } ypos += 5; @@ -325,6 +396,9 @@ static int create_frame(AVFilterContext *ctx, int64_t pts) out->pts = pts; s->pts = pts + 1; return ff_filter_frame(outlink, out); +error: + av_frame_free(&out); + return ret; } static int activate(AVFilterContext *ctx) @@ -386,6 +460,14 @@ static int config_output(AVFilterLink *outlink) return 0; } +static av_cold void uninit(AVFilterContext *ctx) +{ + GraphMonitorContext *s = ctx->priv; + + av_freep(&s->cache); + s->cache_size = s->cache_index = 0; +} + AVFILTER_DEFINE_CLASS_EXT(graphmonitor, "(a)graphmonitor", graphmonitor_options); #if CONFIG_GRAPHMONITOR_FILTER @@ -410,6 +492,8 @@ const AVFilter ff_vf_graphmonitor = { .description = NULL_IF_CONFIG_SMALL("Show various filtergraph stats."), .priv_size = sizeof(GraphMonitorContext), .priv_class = &graphmonitor_class, + .init = init, + .uninit = uninit, .activate = activate, FILTER_INPUTS(graphmonitor_inputs), FILTER_OUTPUTS(graphmonitor_outputs), @@ -440,6 +524,8 @@ const AVFilter ff_avf_agraphmonitor = { .description = NULL_IF_CONFIG_SMALL("Show various filtergraph stats."), .priv_class = &graphmonitor_class, .priv_size = sizeof(GraphMonitorContext), + .init = init, + .uninit = uninit, .activate = activate, FILTER_INPUTS(agraphmonitor_inputs), FILTER_OUTPUTS(agraphmonitor_outputs), diff --git a/libavfilter/f_interleave.c b/libavfilter/f_interleave.c index b60e89762..74597a0ec 100644 --- a/libavfilter/f_interleave.c +++ b/libavfilter/f_interleave.c @@ -23,6 +23,8 @@ * audio and video interleaver */ +#include "config_components.h" + #include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/opt.h" diff --git a/libavfilter/f_latency.c b/libavfilter/f_latency.c index 6f16d6677..f04fd726f 100644 --- a/libavfilter/f_latency.c +++ b/libavfilter/f_latency.c @@ -18,6 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/opt.h" #include "avfilter.h" #include "filters.h" diff --git a/libavfilter/f_loop.c b/libavfilter/f_loop.c index f8ae4a6a3..672aa4c8f 100644 --- a/libavfilter/f_loop.c +++ b/libavfilter/f_loop.c @@ -18,6 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/audio_fifo.h" #include "libavutil/fifo.h" #include "libavutil/internal.h" @@ -70,8 +72,8 @@ static int aconfig_input(AVFilterLink *inlink) AVFilterContext *ctx = inlink->dst; LoopContext *s = ctx->priv; - s->fifo = av_audio_fifo_alloc(inlink->format, inlink->channels, 8192); - s->left = av_audio_fifo_alloc(inlink->format, inlink->channels, 8192); + s->fifo = av_audio_fifo_alloc(inlink->format, inlink->ch_layout.nb_channels, 8192); + s->left = av_audio_fifo_alloc(inlink->format, inlink->ch_layout.nb_channels, 8192); if (!s->fifo || !s->left) return AVERROR(ENOMEM); diff --git a/libavfilter/f_metadata.c b/libavfilter/f_metadata.c index 5f5091e9b..82491f2bb 100644 --- a/libavfilter/f_metadata.c +++ b/libavfilter/f_metadata.c @@ -23,6 +23,8 @@ * filter for manipulating frame metadata */ +#include "config_components.h" + #include #include "libavutil/avassert.h" diff --git a/libavfilter/f_perms.c b/libavfilter/f_perms.c index 6e75b2517..e26a15fd0 100644 --- a/libavfilter/f_perms.c +++ b/libavfilter/f_perms.c @@ -18,6 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/lfg.h" #include "libavutil/opt.h" #include "libavutil/random_seed.h" @@ -42,14 +44,15 @@ typedef struct PermsContext { #define OFFSET(x) offsetof(PermsContext, x) #define FLAGS AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_VIDEO_PARAM +#define TFLAGS AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_RUNTIME_PARAM static const AVOption options[] = { - { "mode", "select permissions mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64 = MODE_NONE}, MODE_NONE, NB_MODES-1, FLAGS, "mode" }, - { "none", "do nothing", 0, AV_OPT_TYPE_CONST, {.i64 = MODE_NONE}, INT_MIN, INT_MAX, FLAGS, "mode" }, - { "ro", "set all output frames read-only", 0, AV_OPT_TYPE_CONST, {.i64 = MODE_RO}, INT_MIN, INT_MAX, FLAGS, "mode" }, - { "rw", "set all output frames writable", 0, AV_OPT_TYPE_CONST, {.i64 = MODE_RW}, INT_MIN, INT_MAX, FLAGS, "mode" }, - { "toggle", "switch permissions", 0, AV_OPT_TYPE_CONST, {.i64 = MODE_TOGGLE}, INT_MIN, INT_MAX, FLAGS, "mode" }, - { "random", "set permissions randomly", 0, AV_OPT_TYPE_CONST, {.i64 = MODE_RANDOM}, INT_MIN, INT_MAX, FLAGS, "mode" }, + { "mode", "select permissions mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64 = MODE_NONE}, MODE_NONE, NB_MODES-1, TFLAGS, "mode" }, + { "none", "do nothing", 0, AV_OPT_TYPE_CONST, {.i64 = MODE_NONE}, 0, 0, TFLAGS, "mode" }, + { "ro", "set all output frames read-only", 0, AV_OPT_TYPE_CONST, {.i64 = MODE_RO}, 0, 0, TFLAGS, "mode" }, + { "rw", "set all output frames writable", 0, AV_OPT_TYPE_CONST, {.i64 = MODE_RW}, 0, 0, TFLAGS, "mode" }, + { "toggle", "switch permissions", 0, AV_OPT_TYPE_CONST, {.i64 = MODE_TOGGLE}, 0, 0, TFLAGS, "mode" }, + { "random", "set permissions randomly", 0, AV_OPT_TYPE_CONST, {.i64 = MODE_RANDOM}, 0, 0, TFLAGS, "mode" }, { "seed", "set the seed for the random mode", OFFSET(random_seed), AV_OPT_TYPE_INT64, {.i64 = -1}, -1, UINT32_MAX, FLAGS }, { NULL } }; @@ -57,16 +60,13 @@ static const AVOption options[] = { static av_cold int init(AVFilterContext *ctx) { PermsContext *s = ctx->priv; + uint32_t seed; - if (s->mode == MODE_RANDOM) { - uint32_t seed; - - if (s->random_seed == -1) - s->random_seed = av_get_random_seed(); - seed = s->random_seed; - av_log(ctx, AV_LOG_INFO, "random seed: 0x%08"PRIx32"\n", seed); - av_lfg_init(&s->lfg, seed); - } + if (s->random_seed == -1) + s->random_seed = av_get_random_seed(); + seed = s->random_seed; + av_log(ctx, AV_LOG_INFO, "random seed: 0x%08"PRIx32"\n", seed); + av_lfg_init(&s->lfg, seed); return 0; } @@ -140,6 +140,7 @@ const AVFilter ff_af_aperms = { FILTER_OUTPUTS(aperms_outputs), .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_METADATA_ONLY, + .process_command = ff_filter_process_command, }; #endif /* CONFIG_APERMS_FILTER */ @@ -170,5 +171,6 @@ const AVFilter ff_vf_perms = { .priv_class = &perms_class, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_METADATA_ONLY, + .process_command = ff_filter_process_command, }; #endif /* CONFIG_PERMS_FILTER */ diff --git a/libavfilter/f_realtime.c b/libavfilter/f_realtime.c index 9a60ded0c..ef713474e 100644 --- a/libavfilter/f_realtime.c +++ b/libavfilter/f_realtime.c @@ -18,6 +18,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/opt.h" #include "libavutil/time.h" #include "avfilter.h" @@ -64,7 +66,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) } #define OFFSET(x) offsetof(RealtimeContext, x) -#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_RUNTIME_PARAM static const AVOption options[] = { { "limit", "sleep time limit", OFFSET(limit), AV_OPT_TYPE_DURATION, { .i64 = 2000000 }, 0, INT64_MAX, FLAGS }, { "speed", "speed factor", OFFSET(speed), AV_OPT_TYPE_DOUBLE, { .dbl = 1.0 }, DBL_MIN, DBL_MAX, FLAGS }, @@ -98,6 +100,7 @@ const AVFilter ff_vf_realtime = { .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(avfilter_vf_realtime_inputs), FILTER_OUTPUTS(avfilter_vf_realtime_outputs), + .process_command = ff_filter_process_command, }; #endif /* CONFIG_REALTIME_FILTER */ @@ -126,5 +129,6 @@ const AVFilter ff_af_arealtime = { .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(arealtime_inputs), FILTER_OUTPUTS(arealtime_outputs), + .process_command = ff_filter_process_command, }; #endif /* CONFIG_AREALTIME_FILTER */ diff --git a/libavfilter/f_reverse.c b/libavfilter/f_reverse.c index f7a7e716f..2c99557c7 100644 --- a/libavfilter/f_reverse.c +++ b/libavfilter/f_reverse.c @@ -18,6 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/opt.h" #include "avfilter.h" #include "formats.h" @@ -148,7 +150,7 @@ const AVFilter ff_vf_reverse = { static void reverse_samples_planar(AVFrame *out) { - for (int p = 0; p < out->channels; p++) { + for (int p = 0; p < out->ch_layout.nb_channels; p++) { switch (out->format) { case AV_SAMPLE_FMT_U8P: { uint8_t *dst = (uint8_t *)out->extended_data[p]; @@ -192,7 +194,7 @@ static void reverse_samples_planar(AVFrame *out) static void reverse_samples_packed(AVFrame *out) { - const int channels = out->channels; + const int channels = out->ch_layout.nb_channels; switch (out->format) { case AV_SAMPLE_FMT_U8: { diff --git a/libavfilter/f_segment.c b/libavfilter/f_segment.c index 5f4463480..03a071a05 100644 --- a/libavfilter/f_segment.c +++ b/libavfilter/f_segment.c @@ -16,6 +16,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include #include "libavutil/avstring.h" @@ -41,6 +43,7 @@ typedef struct SegmentContext { int current_point; int nb_points; + int64_t last_pts; int64_t *points; } SegmentContext; @@ -186,7 +189,7 @@ static int activate(AVFilterContext *ctx) SegmentContext *s = ctx->priv; AVFrame *frame = NULL; int ret, status; - int max_samples; + int64_t max_samples; int64_t diff; int64_t pts; @@ -200,18 +203,30 @@ static int activate(AVFilterContext *ctx) break; case AVMEDIA_TYPE_AUDIO: diff = s->points[s->current_point] - inlink->sample_count_out; + while (diff <= 0) { + ff_outlink_set_status(ctx->outputs[s->current_point], AVERROR_EOF, s->last_pts); + s->current_point++; + if (s->current_point >= s->nb_points) + return AVERROR(EINVAL); + + diff = s->points[s->current_point] - inlink->sample_count_out; + } if (s->use_timestamps) { max_samples = av_rescale_q(diff, av_make_q(1, inlink->sample_rate), inlink->time_base); } else { max_samples = FFMAX(1, FFMIN(diff, INT_MAX)); } - ret = ff_inlink_consume_samples(inlink, 1, max_samples, &frame); + if (max_samples <= 0 || max_samples > INT_MAX) + ret = ff_inlink_consume_frame(inlink, &frame); + else + ret = ff_inlink_consume_samples(inlink, 1, max_samples, &frame); break; default: return AVERROR_BUG; } if (ret > 0) { + s->last_pts = frame->pts; while (current_segment_finished(ctx, frame)) { ff_outlink_set_status(ctx->outputs[s->current_point], AVERROR_EOF, frame->pts); s->current_point++; diff --git a/libavfilter/f_select.c b/libavfilter/f_select.c index b61d88f4f..1cfe2d59e 100644 --- a/libavfilter/f_select.c +++ b/libavfilter/f_select.c @@ -23,6 +23,8 @@ * filter for selecting which frame passes in the filterchain */ +#include "config_components.h" + #include "libavutil/avstring.h" #include "libavutil/eval.h" #include "libavutil/fifo.h" diff --git a/libavfilter/f_sendcmd.c b/libavfilter/f_sendcmd.c index 7261a05aa..857b84131 100644 --- a/libavfilter/f_sendcmd.c +++ b/libavfilter/f_sendcmd.c @@ -23,6 +23,8 @@ * send commands filter */ +#include "config_components.h" + #include "libavutil/avstring.h" #include "libavutil/bprint.h" #include "libavutil/eval.h" @@ -46,6 +48,8 @@ static const char *const var_names[] = { "TS", /* interval start time in seconds */ "TE", /* interval end time in seconds */ "TI", /* interval interpolated value: TI = (T - TS) / (TE - TS) */ + "W", /* width for video frames */ + "H", /* height for video frames */ NULL }; @@ -57,6 +61,8 @@ enum var_name { VAR_TS, VAR_TE, VAR_TI, + VAR_W, + VAR_H, VAR_VARS_NB }; @@ -531,6 +537,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *ref) var_values[VAR_TS] = start; var_values[VAR_TE] = end; var_values[VAR_TI] = (current - start) / (end - start); + var_values[VAR_W] = ref->width; + var_values[VAR_H] = ref->height; if ((ret = av_expr_parse_and_eval(&res, cmd->arg, var_names, var_values, NULL, NULL, NULL, NULL, NULL, 0, NULL)) < 0) { diff --git a/libavfilter/f_sidedata.c b/libavfilter/f_sidedata.c index 8eccd4a06..82bbaa0e7 100644 --- a/libavfilter/f_sidedata.c +++ b/libavfilter/f_sidedata.c @@ -21,6 +21,8 @@ * filter for manipulating frame side data */ +#include "config_components.h" + #include "libavutil/avassert.h" #include "libavutil/internal.h" #include "libavutil/frame.h" diff --git a/libavfilter/f_streamselect.c b/libavfilter/f_streamselect.c index 3708d2b25..1328a842f 100644 --- a/libavfilter/f_streamselect.c +++ b/libavfilter/f_streamselect.c @@ -118,8 +118,12 @@ static int config_output(AVFilterLink *outlink) break; case AVMEDIA_TYPE_AUDIO: outlink->sample_rate = inlink->sample_rate; - outlink->channels = inlink->channels; + outlink->ch_layout.nb_channels = inlink->ch_layout.nb_channels; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS outlink->channel_layout = inlink->channel_layout; +FF_ENABLE_DEPRECATION_WARNINGS +#endif break; } diff --git a/libavfilter/f_zmq.c b/libavfilter/f_zmq.c index 3bd195f0b..156670dad 100644 --- a/libavfilter/f_zmq.c +++ b/libavfilter/f_zmq.c @@ -23,6 +23,8 @@ * receive commands through libzeromq and broker them to filters */ +#include "config_components.h" + #include #include "libavutil/avstring.h" #include "libavutil/bprint.h" diff --git a/libavfilter/fflcms2.c b/libavfilter/fflcms2.c new file mode 100644 index 000000000..fd370fb31 --- /dev/null +++ b/libavfilter/fflcms2.c @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2022 Niklas Haas + * 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/color_utils.h" +#include "libavutil/csp.h" + +#include "fflcms2.h" + +static void log_cb(cmsContext ctx, cmsUInt32Number error, const char *str) +{ + FFIccContext *s = cmsGetContextUserData(ctx); + av_log(s->avctx, AV_LOG_ERROR, "lcms2: [%"PRIu32"] %s\n", error, str); +} + +int ff_icc_context_init(FFIccContext *s, void *avctx) +{ + memset(s, 0, sizeof(*s)); + s->avctx = avctx; + s->ctx = cmsCreateContext(NULL, s); + if (!s->ctx) + return AVERROR(ENOMEM); + + cmsSetLogErrorHandlerTHR(s->ctx, log_cb); + return 0; +} + +void ff_icc_context_uninit(FFIccContext *s) +{ + for (int i = 0; i < FF_ARRAY_ELEMS(s->curves); i++) + cmsFreeToneCurve(s->curves[i]); + cmsDeleteContext(s->ctx); + memset(s, 0, sizeof(*s)); +} + +static int get_curve(FFIccContext *s, enum AVColorTransferCharacteristic trc, + cmsToneCurve **out_curve) +{ + if (trc >= AVCOL_TRC_NB) + return AVERROR_INVALIDDATA; + + if (s->curves[trc]) + goto done; + + switch (trc) { + case AVCOL_TRC_LINEAR: + s->curves[trc] = cmsBuildGamma(s->ctx, 1.0); + break; + case AVCOL_TRC_GAMMA22: + s->curves[trc] = cmsBuildGamma(s->ctx, 2.2); + break; + case AVCOL_TRC_GAMMA28: + s->curves[trc] = cmsBuildGamma(s->ctx, 2.8); + break; + case AVCOL_TRC_BT709: + case AVCOL_TRC_SMPTE170M: + case AVCOL_TRC_BT2020_10: + case AVCOL_TRC_BT2020_12: + s->curves[trc] = cmsBuildParametricToneCurve(s->ctx, 4, (double[5]) { + /* γ = */ 1/0.45, + /* a = */ 1/1.099296826809442, + /* b = */ 1 - 1/1.099296826809442, + /* c = */ 1/4.5, + /* d = */ 4.5 * 0.018053968510807, + }); + break; + case AVCOL_TRC_SMPTE240M: + s->curves[trc] = cmsBuildParametricToneCurve(s->ctx, 4, (double[5]) { + /* γ = */ 1/0.45, + /* a = */ 1/1.1115, + /* b = */ 1 - 1/1.1115, + /* c = */ 1/4.0, + /* d = */ 4.0 * 0.0228, + }); + break; + case AVCOL_TRC_LOG: + s->curves[trc] = cmsBuildParametricToneCurve(s->ctx, 8, (double[5]) { + /* a = */ 1.0, + /* b = */ 10.0, + /* c = */ 2.0, + /* d = */ -1.0, + /* e = */ 0.0 + }); + break; + case AVCOL_TRC_LOG_SQRT: + s->curves[trc] = cmsBuildParametricToneCurve(s->ctx, 8, (double[5]) { + /* a = */ 1.0, + /* b = */ 10.0, + /* c = */ 2.5, + /* d = */ -1.0, + /* e = */ 0.0 + }); + break; + case AVCOL_TRC_IEC61966_2_1: + s->curves[trc] = cmsBuildParametricToneCurve(s->ctx, 4, (double[5]) { + /* γ = */ 2.4, + /* a = */ 1/1.055, + /* b = */ 1 - 1/1.055, + /* c = */ 1/12.92, + /* d = */ 12.92 * 0.0031308, + }); + break; + case AVCOL_TRC_SMPTE428: + s->curves[trc] = cmsBuildParametricToneCurve(s->ctx, 2, (double[3]) { + /* γ = */ 2.6, + /* a = */ pow(52.37/48.0, 1/2.6), + /* b = */ 0.0 + }); + break; + + /* Can't be represented using the existing parametric tone curves. + * FIXME: use cmsBuildTabulatedToneCurveFloat instead */ + case AVCOL_TRC_IEC61966_2_4: + case AVCOL_TRC_BT1361_ECG: + case AVCOL_TRC_SMPTE2084: + case AVCOL_TRC_ARIB_STD_B67: + return AVERROR_PATCHWELCOME; + + default: + return AVERROR_INVALIDDATA; + } + + if (!s->curves[trc]) + return AVERROR(ENOMEM); + +done: + *out_curve = s->curves[trc]; + return 0; +} + +int ff_icc_profile_generate(FFIccContext *s, + enum AVColorPrimaries color_prim, + enum AVColorTransferCharacteristic color_trc, + cmsHPROFILE *out_profile) +{ + cmsToneCurve *tonecurve; + const AVColorPrimariesDesc *prim; + int ret; + + if (!(prim = av_csp_primaries_desc_from_id(color_prim))) + return AVERROR_INVALIDDATA; + if ((ret = get_curve(s, color_trc, &tonecurve)) < 0) + return ret; + + *out_profile = cmsCreateRGBProfileTHR(s->ctx, + &(cmsCIExyY) { av_q2d(prim->wp.x), av_q2d(prim->wp.y), 1.0 }, + &(cmsCIExyYTRIPLE) { + .Red = { av_q2d(prim->prim.r.x), av_q2d(prim->prim.r.y), 1.0 }, + .Green = { av_q2d(prim->prim.g.x), av_q2d(prim->prim.g.y), 1.0 }, + .Blue = { av_q2d(prim->prim.b.x), av_q2d(prim->prim.b.y), 1.0 }, + }, + (cmsToneCurve *[3]) { tonecurve, tonecurve, tonecurve } + ); + + return *out_profile == NULL ? AVERROR(ENOMEM) : 0; +} + +int ff_icc_profile_attach(FFIccContext *s, cmsHPROFILE profile, AVFrame *frame) +{ + cmsUInt32Number size; + AVBufferRef *buf; + + if (!cmsSaveProfileToMem(profile, NULL, &size)) + return AVERROR_EXTERNAL; + + buf = av_buffer_alloc(size); + if (!buf) + return AVERROR(ENOMEM); + + if (!cmsSaveProfileToMem(profile, buf->data, &size) || size != buf->size) { + av_buffer_unref(&buf); + return AVERROR_EXTERNAL; + } + + if (!av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_ICC_PROFILE, buf)) { + av_buffer_unref(&buf); + return AVERROR(ENOMEM); + } + + return 0; +} + +static av_always_inline void XYZ_xy(cmsCIEXYZ XYZ, AVCIExy *xy) +{ + double k = 1.0 / (XYZ.X + XYZ.Y + XYZ.Z); + xy->x = av_d2q(k * XYZ.X, 100000); + xy->y = av_d2q(k * XYZ.Y, 100000); +} + +int ff_icc_profile_read_primaries(FFIccContext *s, cmsHPROFILE profile, + AVColorPrimariesDesc *out_primaries) +{ + static const uint8_t testprimaries[4][3] = { + { 0xFF, 0, 0 }, /* red */ + { 0, 0xFF, 0 }, /* green */ + { 0, 0, 0xFF }, /* blue */ + { 0xFF, 0xFF, 0xFF }, /* white */ + }; + + AVWhitepointCoefficients *wp = &out_primaries->wp; + AVPrimaryCoefficients *prim = &out_primaries->prim; + cmsFloat64Number prev_adapt; + cmsHPROFILE xyz; + cmsHTRANSFORM tf; + cmsCIEXYZ dst[4]; + + xyz = cmsCreateXYZProfileTHR(s->ctx); + if (!xyz) + return AVERROR(ENOMEM); + + /* We need to use an unadapted observer to get the raw values */ + prev_adapt = cmsSetAdaptationStateTHR(s->ctx, 0.0); + tf = cmsCreateTransformTHR(s->ctx, profile, TYPE_RGB_8, xyz, TYPE_XYZ_DBL, + INTENT_ABSOLUTE_COLORIMETRIC, + /* Note: These flags mostly don't do anything + * anyway, but specify them regardless */ + cmsFLAGS_NOCACHE | + cmsFLAGS_NOOPTIMIZE | + cmsFLAGS_LOWRESPRECALC | + cmsFLAGS_GRIDPOINTS(2)); + cmsSetAdaptationStateTHR(s->ctx, prev_adapt); + cmsCloseProfile(xyz); + if (!tf) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid ICC profile (e.g. CMYK)\n"); + return AVERROR_INVALIDDATA; + } + + cmsDoTransform(tf, testprimaries, dst, 4); + cmsDeleteTransform(tf); + XYZ_xy(dst[0], &prim->r); + XYZ_xy(dst[1], &prim->g); + XYZ_xy(dst[2], &prim->b); + XYZ_xy(dst[3], wp); + return 0; +} + +int ff_icc_profile_detect_transfer(FFIccContext *s, cmsHPROFILE profile, + enum AVColorTransferCharacteristic *out_trc) +{ + /* 8-bit linear grayscale ramp */ + static const uint8_t testramp[16][3] = { + { 1, 1, 1}, /* avoid exact zero due to log100 etc. */ + { 17, 17, 17}, + { 34, 34, 34}, + { 51, 51, 51}, + { 68, 68, 68}, + { 85, 85, 85}, + { 02, 02, 02}, + {119, 119, 119}, + {136, 136, 136}, + {153, 153, 153}, + {170, 170, 170}, + {187, 187, 187}, + {204, 204, 204}, + {221, 221, 221}, + {238, 238, 238}, + {255, 255, 255}, + }; + + double dst[FF_ARRAY_ELEMS(testramp)]; + + for (enum AVColorTransferCharacteristic trc = 0; trc < AVCOL_TRC_NB; trc++) { + cmsToneCurve *tonecurve; + cmsHPROFILE ref; + cmsHTRANSFORM tf; + double delta = 0.0; + if (get_curve(s, trc, &tonecurve) < 0) + continue; + + ref = cmsCreateGrayProfileTHR(s->ctx, cmsD50_xyY(), tonecurve); + if (!ref) + return AVERROR(ENOMEM); + + tf = cmsCreateTransformTHR(s->ctx, profile, TYPE_RGB_8, ref, TYPE_GRAY_DBL, + INTENT_RELATIVE_COLORIMETRIC, + cmsFLAGS_NOCACHE | cmsFLAGS_NOOPTIMIZE); + cmsCloseProfile(ref); + if (!tf) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid ICC profile (e.g. CMYK)\n"); + return AVERROR_INVALIDDATA; + } + + cmsDoTransform(tf, testramp, dst, FF_ARRAY_ELEMS(dst)); + cmsDeleteTransform(tf); + + for (int i = 0; i < FF_ARRAY_ELEMS(dst); i++) + delta += fabs(testramp[i][0] / 255.0 - dst[i]); + if (delta < 0.01) { + *out_trc = trc; + return 0; + } + } + + *out_trc = AVCOL_TRC_UNSPECIFIED; + return 0; +} diff --git a/libavfilter/fflcms2.h b/libavfilter/fflcms2.h new file mode 100644 index 000000000..0d238c679 --- /dev/null +++ b/libavfilter/fflcms2.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2022 Niklas Haas + * 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 + * Various functions for dealing with ICC profiles + */ + +#ifndef AVFILTER_FFLCMS2_H +#define AVFILTER_FFLCMS2_H + +#include "libavutil/csp.h" +#include "libavutil/frame.h" +#include "libavutil/pixfmt.h" + +#include + +typedef struct FFIccContext { + void *avctx; + cmsContext ctx; + cmsToneCurve *curves[AVCOL_TRC_NB]; /* tone curve cache */ +} FFIccContext; + +/** + * Initializes an FFIccContext. This must be done prior to using it. + * + * Returns 0 on success, or a negative error code. + */ +int ff_icc_context_init(FFIccContext *s, void *avctx); +void ff_icc_context_uninit(FFIccContext *s); + +/** + * Generate an ICC profile for a given combination of color primaries and + * transfer function. Both values must be set to valid entries (not + * "undefined") for this function to work. + * + * Returns 0 on success, or a negative error code. + */ +int ff_icc_profile_generate(FFIccContext *s, + enum AVColorPrimaries color_prim, + enum AVColorTransferCharacteristic color_trc, + cmsHPROFILE *out_profile); + +/** + * Attach an ICC profile to a frame. Helper wrapper around cmsSaveProfileToMem + * and av_frame_new_side_data_from_buf. + * + * Returns 0 on success, or a negative error code. + */ +int ff_icc_profile_attach(FFIccContext *s, cmsHPROFILE profile, AVFrame *frame); + +/** + * Read the color primaries and white point coefficients encoded by an ICC + * profile, and return the raw values in `out_primaries`. + * + * Returns 0 on success, or a negative error code. + */ +int ff_icc_profile_read_primaries(FFIccContext *s, cmsHPROFILE profile, + AVColorPrimariesDesc *out_primaries); + +/** + * Attempt detecting the transfer characteristic that best approximates the + * transfer function encoded by an ICC profile. Sets `out_trc` to + * AVCOL_TRC_UNSPECIFIED if no clear match can be identified. + * + * Returns 0 on success (including no match), or a negative error code. + */ +int ff_icc_profile_detect_transfer(FFIccContext *s, cmsHPROFILE profile, + enum AVColorTransferCharacteristic *out_trc); + +#endif /* AVFILTER_FFLCMS2_H */ diff --git a/libavfilter/file_open.c b/libavfilter/file_open.c new file mode 100644 index 000000000..494a5d37a --- /dev/null +++ b/libavfilter/file_open.c @@ -0,0 +1 @@ +#include "libavutil/file_open.c" diff --git a/libavfilter/filters.h b/libavfilter/filters.h index 115775540..86bc49d45 100644 --- a/libavfilter/filters.h +++ b/libavfilter/filters.h @@ -258,4 +258,12 @@ static inline void ff_outlink_set_status(AVFilterLink *link, int status, int64_t } \ } while (0) +/** + * Check for flow control between input and output. + * This is necessary for filters that may produce several output frames for + * a single input event, otherwise they may produce them all at once, + * causing excessive memory consumption. + */ +int ff_inoutlink_check_flow(AVFilterLink *inlink, AVFilterLink *outlink); + #endif /* AVFILTER_FILTERS_H */ diff --git a/libavfilter/formats.c b/libavfilter/formats.c index ba62f7324..e8c2888c0 100644 --- a/libavfilter/formats.c +++ b/libavfilter/formats.c @@ -28,8 +28,6 @@ #include "internal.h" #include "formats.h" -#define KNOWN(l) (!FF_LAYOUT2COUNT(l)) /* for readability */ - /** * Add all refs from a to ret and destroy a. */ @@ -215,7 +213,7 @@ static int merge_channel_layouts(void *va, void *vb) { AVFilterChannelLayouts *a = va; AVFilterChannelLayouts *b = vb; - uint64_t *channel_layouts; + AVChannelLayout *channel_layouts; unsigned a_all = a->all_layouts + a->all_counts; unsigned b_all = b->all_layouts + b->all_counts; int ret_max, ret_nb = 0, i, j, round; @@ -233,8 +231,8 @@ static int merge_channel_layouts(void *va, void *vb) if (a_all == 1 && !b_all) { /* keep only known layouts in b; works also for b_all = 1 */ for (i = j = 0; i < b->nb_channel_layouts; i++) - if (KNOWN(b->channel_layouts[i])) - b->channel_layouts[j++] = b->channel_layouts[i]; + if (KNOWN(&b->channel_layouts[i]) && i != j++) + av_channel_layout_copy(&b->channel_layouts[j], &b->channel_layouts[i]); /* Not optimal: the unknown layouts of b may become known after another merge. */ if (!j) @@ -246,17 +244,18 @@ static int merge_channel_layouts(void *va, void *vb) } ret_max = a->nb_channel_layouts + b->nb_channel_layouts; - if (!(channel_layouts = av_malloc_array(ret_max, sizeof(*channel_layouts)))) + if (!(channel_layouts = av_calloc(ret_max, sizeof(*channel_layouts)))) return AVERROR(ENOMEM); /* a[known] intersect b[known] */ for (i = 0; i < a->nb_channel_layouts; i++) { - if (!KNOWN(a->channel_layouts[i])) + if (!KNOWN(&a->channel_layouts[i])) continue; for (j = 0; j < b->nb_channel_layouts; j++) { - if (a->channel_layouts[i] == b->channel_layouts[j]) { - channel_layouts[ret_nb++] = a->channel_layouts[i]; - a->channel_layouts[i] = b->channel_layouts[j] = 0; + if (!av_channel_layout_compare(&a->channel_layouts[i], &b->channel_layouts[j])) { + av_channel_layout_copy(&channel_layouts[ret_nb++], &a->channel_layouts[i]); + av_channel_layout_uninit(&a->channel_layouts[i]); + av_channel_layout_uninit(&b->channel_layouts[j]); break; } } @@ -265,24 +264,24 @@ static int merge_channel_layouts(void *va, void *vb) 2nd round: a[generic] intersect b[known] */ for (round = 0; round < 2; round++) { for (i = 0; i < a->nb_channel_layouts; i++) { - uint64_t fmt = a->channel_layouts[i], bfmt; - if (!fmt || !KNOWN(fmt)) + AVChannelLayout *fmt = &a->channel_layouts[i], bfmt = { 0 }; + if (!av_channel_layout_check(fmt) || !KNOWN(fmt)) continue; - bfmt = FF_COUNT2LAYOUT(av_get_channel_layout_nb_channels(fmt)); + bfmt = FF_COUNT2LAYOUT(fmt->nb_channels); for (j = 0; j < b->nb_channel_layouts; j++) - if (b->channel_layouts[j] == bfmt) - channel_layouts[ret_nb++] = a->channel_layouts[i]; + if (!av_channel_layout_compare(&b->channel_layouts[j], &bfmt)) + av_channel_layout_copy(&channel_layouts[ret_nb++], fmt); } /* 1st round: swap to prepare 2nd round; 2nd round: put it back */ FFSWAP(AVFilterChannelLayouts *, a, b); } /* a[generic] intersect b[generic] */ for (i = 0; i < a->nb_channel_layouts; i++) { - if (KNOWN(a->channel_layouts[i])) + if (KNOWN(&a->channel_layouts[i])) continue; for (j = 0; j < b->nb_channel_layouts; j++) - if (a->channel_layouts[i] == b->channel_layouts[j]) - channel_layouts[ret_nb++] = a->channel_layouts[i]; + if (!av_channel_layout_compare(&a->channel_layouts[i], &b->channel_layouts[j])) + av_channel_layout_copy(&channel_layouts[ret_nb++], &a->channel_layouts[i]); } if (!ret_nb) { @@ -388,15 +387,40 @@ AVFilterFormats *ff_make_format_list(const int *fmts) return formats; } -AVFilterChannelLayouts *ff_make_format64_list(const int64_t *fmts) +AVFilterChannelLayouts *ff_make_channel_layout_list(const AVChannelLayout *fmts) { - MAKE_FORMAT_LIST(AVFilterChannelLayouts, - channel_layouts, nb_channel_layouts); - if (count) - memcpy(formats->channel_layouts, fmts, - sizeof(*formats->channel_layouts) * count); + AVFilterChannelLayouts *ch_layouts; + int count = 0; + if (fmts) + for (count = 0; fmts[count].nb_channels; count++) + ; + ch_layouts = av_mallocz(sizeof(*ch_layouts)); + if (!ch_layouts) + return NULL; + ch_layouts->nb_channel_layouts = count; + if (count) { + ch_layouts->channel_layouts = + av_calloc(count, sizeof(*ch_layouts->channel_layouts)); + if (!ch_layouts->channel_layouts) { + av_freep(&ch_layouts); + return NULL; + } + for (int i = 0; i < count; i++) { + int ret = av_channel_layout_copy(&ch_layouts->channel_layouts[i], &fmts[i]); + if (ret < 0) + goto fail; + } + } - return formats; + return ch_layouts; + +fail: + for (int i = 0; i < count; i++) + av_channel_layout_uninit(&ch_layouts->channel_layouts[i]); + av_free(ch_layouts->channel_layouts); + av_freep(&ch_layouts); + + return NULL; } #define ADD_FORMAT(f, fmt, unref_fn, type, list, nb) \ @@ -415,6 +439,11 @@ do { \ } \ \ (*f)->list = fmts; \ + ASSIGN_FMT(f, fmt, list, nb); \ +} while (0) + +#define ASSIGN_FMT(f, fmt, list, nb) \ +do { \ (*f)->list[(*f)->nb++] = fmt; \ } while (0) @@ -424,10 +453,22 @@ int ff_add_format(AVFilterFormats **avff, int64_t fmt) return 0; } -int ff_add_channel_layout(AVFilterChannelLayouts **l, uint64_t channel_layout) +#undef ASSIGN_FMT +#define ASSIGN_FMT(f, fmt, list, nb) \ +do { \ + int ret; \ + memset((*f)->list + (*f)->nb, 0, sizeof(*(*f)->list)); \ + ret = av_channel_layout_copy(&(*f)->list[(*f)->nb], fmt); \ + if (ret < 0) \ + return ret; \ + (*f)->nb++; \ +} while (0) + +int ff_add_channel_layout(AVFilterChannelLayouts **l, + const AVChannelLayout *channel_layout) { av_assert1(!(*l && (*l)->all_layouts)); - ADD_FORMAT(l, channel_layout, ff_channel_layouts_unref, uint64_t, channel_layouts, nb_channel_layouts); + ADD_FORMAT(l, channel_layout, ff_channel_layouts_unref, AVChannelLayout, channel_layouts, nb_channel_layouts); return 0; } @@ -583,6 +624,7 @@ do { \ --(*ref)->refcount; \ } \ if (!(*ref)->refcount) { \ + FREE_LIST(ref, list); \ av_free((*ref)->list); \ av_free((*ref)->refs); \ av_free(*ref); \ @@ -590,11 +632,19 @@ do { \ *ref = NULL; \ } while (0) +#define FREE_LIST(ref, list) do { } while(0) void ff_formats_unref(AVFilterFormats **ref) { FORMATS_UNREF(ref, formats); } +#undef FREE_LIST +#define FREE_LIST(ref, list) \ + do { \ + for (int i = 0; i < (*ref)->nb_channel_layouts; i++) \ + av_channel_layout_uninit(&(*ref)->list[i]); \ + } while(0) + void ff_channel_layouts_unref(AVFilterChannelLayouts **ref) { FORMATS_UNREF(ref, channel_layouts); @@ -664,9 +714,9 @@ int ff_set_common_channel_layouts(AVFilterContext *ctx, } int ff_set_common_channel_layouts_from_list(AVFilterContext *ctx, - const int64_t *fmts) + const AVChannelLayout *fmts) { - return ff_set_common_channel_layouts(ctx, ff_make_format64_list(fmts)); + return ff_set_common_channel_layouts(ctx, ff_make_channel_layout_list(fmts)); } int ff_set_common_all_channel_counts(AVFilterContext *ctx) @@ -787,23 +837,41 @@ int ff_parse_sample_rate(int *ret, const char *arg, void *log_ctx) return 0; } -int ff_parse_channel_layout(int64_t *ret, int *nret, const char *arg, +int ff_parse_channel_layout(AVChannelLayout *ret, int *nret, const char *arg, void *log_ctx) { - int64_t chlayout; - int nb_channels; + AVChannelLayout chlayout = { 0 }; + int res; - if (av_get_extended_channel_layout(arg, &chlayout, &nb_channels) < 0) { - av_log(log_ctx, AV_LOG_ERROR, "Invalid channel layout '%s'\n", arg); - return AVERROR(EINVAL); + res = av_channel_layout_from_string(&chlayout, arg); + if (res < 0) { +#if FF_API_OLD_CHANNEL_LAYOUT + int64_t mask; + int nb_channels; +FF_DISABLE_DEPRECATION_WARNINGS + if (av_get_extended_channel_layout(arg, &mask, &nb_channels) < 0) { +#endif + av_log(log_ctx, AV_LOG_ERROR, "Invalid channel layout '%s'\n", arg); + return AVERROR(EINVAL); +#if FF_API_OLD_CHANNEL_LAYOUT + } +FF_ENABLE_DEPRECATION_WARNINGS + av_log(log_ctx, AV_LOG_WARNING, "Channel layout '%s' uses a deprecated syntax.\n", + arg); + if (mask) + av_channel_layout_from_mask(&chlayout, mask); + else + chlayout = (AVChannelLayout) { .order = AV_CHANNEL_ORDER_UNSPEC, .nb_channels = nb_channels }; +#endif } - if (!chlayout && !nret) { + + if (chlayout.order == AV_CHANNEL_ORDER_UNSPEC && !nret) { av_log(log_ctx, AV_LOG_ERROR, "Unknown channel layout '%s' is not supported.\n", arg); return AVERROR(EINVAL); } *ret = chlayout; if (nret) - *nret = nb_channels; + *nret = chlayout.nb_channels; return 0; } @@ -846,11 +914,11 @@ int ff_formats_check_sample_rates(void *log, const AVFilterFormats *fmts) return check_list(log, "sample rate", fmts); } -static int layouts_compatible(uint64_t a, uint64_t b) +static int layouts_compatible(const AVChannelLayout *a, const AVChannelLayout *b) { - return a == b || - (KNOWN(a) && !KNOWN(b) && av_get_channel_layout_nb_channels(a) == FF_LAYOUT2COUNT(b)) || - (KNOWN(b) && !KNOWN(a) && av_get_channel_layout_nb_channels(b) == FF_LAYOUT2COUNT(a)); + return !av_channel_layout_compare(a, b) || + (KNOWN(a) && !KNOWN(b) && a->nb_channels == b->nb_channels) || + (KNOWN(b) && !KNOWN(a) && b->nb_channels == a->nb_channels); } int ff_formats_check_channel_layouts(void *log, const AVFilterChannelLayouts *fmts) @@ -869,7 +937,7 @@ int ff_formats_check_channel_layouts(void *log, const AVFilterChannelLayouts *fm } for (i = 0; i < fmts->nb_channel_layouts; i++) { for (j = i + 1; j < fmts->nb_channel_layouts; j++) { - if (layouts_compatible(fmts->channel_layouts[i], fmts->channel_layouts[j])) { + if (layouts_compatible(&fmts->channel_layouts[i], &fmts->channel_layouts[j])) { av_log(log, AV_LOG_ERROR, "Duplicated or redundant channel layout\n"); return AVERROR(EINVAL); } diff --git a/libavfilter/formats.h b/libavfilter/formats.h index a884d1521..22224dce2 100644 --- a/libavfilter/formats.h +++ b/libavfilter/formats.h @@ -83,7 +83,7 @@ struct AVFilterFormats { * (e.g. AV_CH_LAYOUT_STEREO and FF_COUNT2LAYOUT(2). */ struct AVFilterChannelLayouts { - uint64_t *channel_layouts; ///< list of channel layouts + AVChannelLayout *channel_layouts; ///< list of channel layouts int nb_channel_layouts; ///< number of channel layouts char all_layouts; ///< accept any known channel layout char all_counts; ///< accept any channel layout or count @@ -99,14 +99,16 @@ struct AVFilterChannelLayouts { * The result is only valid inside AVFilterChannelLayouts and immediately * related functions. */ -#define FF_COUNT2LAYOUT(c) (0x8000000000000000ULL | (c)) +#define FF_COUNT2LAYOUT(c) ((AVChannelLayout) { .order = AV_CHANNEL_ORDER_UNSPEC, .nb_channels = c }) /** * Decode a channel count encoded as a channel layout. * Return 0 if the channel layout was a real one. */ -#define FF_LAYOUT2COUNT(l) (((l) & 0x8000000000000000ULL) ? \ - (int)((l) & 0x7FFFFFFF) : 0) +#define FF_LAYOUT2COUNT(l) (((l)->order == AV_CHANNEL_ORDER_UNSPEC) ? \ + (l)->nb_channels : 0) + +#define KNOWN(l) (!FF_LAYOUT2COUNT(l)) /* for readability */ /** * Construct an empty AVFilterChannelLayouts/AVFilterFormats struct -- @@ -126,7 +128,7 @@ av_warn_unused_result AVFilterChannelLayouts *ff_all_channel_counts(void); av_warn_unused_result -AVFilterChannelLayouts *ff_make_format64_list(const int64_t *fmts); +AVFilterChannelLayouts *ff_make_channel_layout_list(const AVChannelLayout *fmts); /** * Helpers for query_formats() which set all free audio links to the same list @@ -137,11 +139,11 @@ av_warn_unused_result int ff_set_common_channel_layouts(AVFilterContext *ctx, AVFilterChannelLayouts *layouts); /** - * Equivalent to ff_set_common_channel_layouts(ctx, ff_make_format64_list(fmts)) + * Equivalent to ff_set_common_channel_layouts(ctx, ff_make_channel_layout_list(fmts)) */ av_warn_unused_result int ff_set_common_channel_layouts_from_list(AVFilterContext *ctx, - const int64_t *fmts); + const AVChannelLayout *fmts); /** * Equivalent to ff_set_common_channel_layouts(ctx, ff_all_channel_counts()) */ @@ -178,7 +180,8 @@ av_warn_unused_result int ff_set_common_formats_from_list(AVFilterContext *ctx, const int *fmts); av_warn_unused_result -int ff_add_channel_layout(AVFilterChannelLayouts **l, uint64_t channel_layout); +int ff_add_channel_layout(AVFilterChannelLayouts **l, + const AVChannelLayout *channel_layout); /** * Add *ref as a new reference to f. diff --git a/libavfilter/framepool.c b/libavfilter/framepool.c index 7c63807df..040458905 100644 --- a/libavfilter/framepool.c +++ b/libavfilter/framepool.c @@ -56,10 +56,8 @@ FFFramePool *ff_frame_pool_video_init(AVBufferRef* (*alloc)(size_t size), { int i, ret; FFFramePool *pool; - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(format); - - if (!desc) - return NULL; + ptrdiff_t linesizes[4]; + size_t sizes[4]; pool = av_mallocz(sizeof(FFFramePool)); if (!pool) @@ -76,35 +74,33 @@ FFFramePool *ff_frame_pool_video_init(AVBufferRef* (*alloc)(size_t size), } if (!pool->linesize[0]) { - for(i = 1; i <= align; i += i) { - ret = av_image_fill_linesizes(pool->linesize, pool->format, - FFALIGN(pool->width, i)); - if (ret < 0) { - goto fail; - } - if (!(pool->linesize[0] & (pool->align - 1))) - break; + ret = av_image_fill_linesizes(pool->linesize, pool->format, + FFALIGN(pool->width, align)); + if (ret < 0) { + goto fail; } for (i = 0; i < 4 && pool->linesize[i]; i++) { pool->linesize[i] = FFALIGN(pool->linesize[i], pool->align); + if ((pool->linesize[i] & (pool->align - 1))) + goto fail; } } - for (i = 0; i < 4 && pool->linesize[i]; i++) { - int h = FFALIGN(pool->height, 32); - if (i == 1 || i == 2) - h = AV_CEIL_RSHIFT(h, desc->log2_chroma_h); + for (i = 0; i < 4; i++) + linesizes[i] = pool->linesize[i]; - pool->pools[i] = av_buffer_pool_init(pool->linesize[i] * h + 16 + 16 - 1, - alloc); - if (!pool->pools[i]) - goto fail; + if (av_image_fill_plane_sizes(sizes, pool->format, + pool->height, + linesizes) < 0) { + goto fail; } - if (desc->flags & AV_PIX_FMT_FLAG_PAL) { - pool->pools[1] = av_buffer_pool_init(AVPALETTE_SIZE, alloc); - if (!pool->pools[1]) + for (i = 0; i < 4 && sizes[i]; i++) { + if (sizes[i] > SIZE_MAX - align) + goto fail; + pool->pools[i] = av_buffer_pool_init(sizes[i] + align, alloc); + if (!pool->pools[i]) goto fail; } @@ -238,7 +234,12 @@ AVFrame *ff_frame_pool_get(FFFramePool *pool) break; case AVMEDIA_TYPE_AUDIO: frame->nb_samples = pool->nb_samples; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS frame->channels = pool->channels; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + frame->ch_layout.nb_channels = pool->channels; frame->format = pool->format; frame->linesize[0] = pool->linesize[0]; diff --git a/libavfilter/framequeue.c b/libavfilter/framequeue.c index fed111897..383c195b8 100644 --- a/libavfilter/framequeue.c +++ b/libavfilter/framequeue.c @@ -134,10 +134,10 @@ void ff_framequeue_skip_samples(FFFrameQueue *fq, size_t samples, AVRational tim b = bucket(fq, 0); av_assert1(samples < b->frame->nb_samples); planar = av_sample_fmt_is_planar(b->frame->format); - planes = planar ? b->frame->channels : 1; + planes = planar ? b->frame->ch_layout.nb_channels : 1; bytes = samples * av_get_bytes_per_sample(b->frame->format); if (!planar) - bytes *= b->frame->channels; + bytes *= b->frame->ch_layout.nb_channels; if (b->frame->pts != AV_NOPTS_VALUE) b->frame->pts += av_rescale_q(samples, av_make_q(1, b->frame->sample_rate), time_base); b->frame->nb_samples -= samples; diff --git a/libavfilter/gblur.h b/libavfilter/gblur.h index 3a66984b0..83f43c2c1 100644 --- a/libavfilter/gblur.h +++ b/libavfilter/gblur.h @@ -57,6 +57,5 @@ typedef struct GBlurContext { void (*postscale_slice)(float *buffer, int length, float postscale, float min, float max); } GBlurContext; -void ff_gblur_init(GBlurContext *s); void ff_gblur_init_x86(GBlurContext *s); #endif diff --git a/libavfilter/graphdump.c b/libavfilter/graphdump.c index cf8914b55..80f7bf6c9 100644 --- a/libavfilter/graphdump.c +++ b/libavfilter/graphdump.c @@ -30,6 +30,7 @@ static int print_link_prop(AVBPrint *buf, AVFilterLink *link) { const char *format; + char layout[128]; AVBPrint dummy_buffer; if (!buf) { @@ -49,7 +50,8 @@ static int print_link_prop(AVBPrint *buf, AVFilterLink *link) format = av_x_if_null(av_get_sample_fmt_name(link->format), "?"); av_bprintf(buf, "[%dHz %s:", (int)link->sample_rate, format); - av_bprint_channel_layout(buf, link->channels, link->channel_layout); + av_channel_layout_describe(&link->ch_layout, layout, sizeof(layout)); + av_bprintf(buf, "%s", layout); av_bprint_chars(buf, ']', 1); break; diff --git a/libavfilter/hflip.h b/libavfilter/hflip.h index a40b98470..8532dc0f4 100644 --- a/libavfilter/hflip.h +++ b/libavfilter/hflip.h @@ -34,7 +34,6 @@ 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/internal.h b/libavfilter/internal.h index 1099b82b4..0f8da367d 100644 --- a/libavfilter/internal.h +++ b/libavfilter/internal.h @@ -28,7 +28,6 @@ #include "avfilter.h" #include "formats.h" #include "framequeue.h" -#include "version.h" #include "video.h" typedef struct AVFilterCommand { @@ -237,7 +236,7 @@ int ff_parse_sample_rate(int *ret, const char *arg, void *log_ctx); * @return >= 0 in case of success, a negative AVERROR code on error */ av_warn_unused_result -int ff_parse_channel_layout(int64_t *ret, int *nret, const char *arg, +int ff_parse_channel_layout(AVChannelLayout *ret, int *nret, const char *arg, void *log_ctx); void ff_update_link_current_pts(AVFilterLink *link, int64_t pts); diff --git a/libavfilter/lut3d.h b/libavfilter/lut3d.h index bc32eac91..14e3c7fea 100644 --- a/libavfilter/lut3d.h +++ b/libavfilter/lut3d.h @@ -21,6 +21,8 @@ #ifndef AVFILTER_LUT3D_H #define AVFILTER_LUT3D_H +#include "config_components.h" + #include "libavutil/pixdesc.h" #include "framesync.h" #include "avfilter.h" @@ -64,6 +66,8 @@ typedef struct LUT3DContext { avfilter_action_func *interp; Lut3DPreLut prelut; #if CONFIG_HALDCLUT_FILTER + int clut; + int got_clut; uint8_t clut_rgba_map[4]; int clut_step; int clut_bits; diff --git a/libavfilter/maskedmerge.h b/libavfilter/maskedmerge.h index 8e2b1cf67..c1cf8027e 100644 --- a/libavfilter/maskedmerge.h +++ b/libavfilter/maskedmerge.h @@ -30,7 +30,7 @@ typedef struct MaskedMergeContext { int linesize[4]; int nb_planes; int planes; - int half, depth; + int half, depth, max; FFFrameSync fs; void (*maskedmerge)(const uint8_t *bsrc, const uint8_t *osrc, diff --git a/libavfilter/motion_estimation.c b/libavfilter/motion_estimation.c index 0f9ba2178..2bf5ce615 100644 --- a/libavfilter/motion_estimation.c +++ b/libavfilter/motion_estimation.c @@ -18,6 +18,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/common.h" #include "motion_estimation.h" static const int8_t sqr1[8][2] = {{ 0,-1}, { 0, 1}, {-1, 0}, { 1, 0}, {-1,-1}, {-1, 1}, { 1,-1}, { 1, 1}}; diff --git a/libavfilter/motion_estimation.h b/libavfilter/motion_estimation.h index 6ae29dd9e..be627ec3b 100644 --- a/libavfilter/motion_estimation.h +++ b/libavfilter/motion_estimation.h @@ -21,7 +21,7 @@ #ifndef AVFILTER_MOTION_ESTIMATION_H #define AVFILTER_MOTION_ESTIMATION_H -#include "libavutil/avutil.h" +#include #define AV_ME_METHOD_ESA 1 #define AV_ME_METHOD_TSS 2 diff --git a/libavfilter/opencl.c b/libavfilter/opencl.c index 70d5edb78..c8e7e6e1a 100644 --- a/libavfilter/opencl.c +++ b/libavfilter/opencl.c @@ -210,7 +210,7 @@ int ff_opencl_filter_load_program_from_file(AVFilterContext *avctx, const char *src_const; int err; - file = av_fopen_utf8(filename, "r"); + file = avpriv_fopen_utf8(filename, "r"); if (!file) { av_log(avctx, AV_LOG_ERROR, "Unable to open program " "source file \"%s\".\n", filename); diff --git a/libavfilter/opencl/remap.cl b/libavfilter/opencl/remap.cl new file mode 100644 index 000000000..fba82d134 --- /dev/null +++ b/libavfilter/opencl/remap.cl @@ -0,0 +1,73 @@ +/* + * 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 + */ + +const sampler_t linear_sampler = (CLK_NORMALIZED_COORDS_FALSE | + CLK_FILTER_LINEAR); + +const sampler_t nearest_sampler = (CLK_NORMALIZED_COORDS_FALSE | + CLK_FILTER_NEAREST); + +__kernel void remap_near(__write_only image2d_t dst, + __read_only image2d_t src, + __read_only image2d_t xmapi, + __read_only image2d_t ymapi, + float4 fill_color) +{ + int2 p = (int2)(get_global_id(0), get_global_id(1)); + int2 dimi = get_image_dim(src); + float2 dimf = (float2)(dimi.x, dimi.y); + float4 val; + int2 mi; + float m; + + float4 xmap = read_imagef(xmapi, nearest_sampler, p); + float4 ymap = read_imagef(ymapi, nearest_sampler, p); + float2 pos = (float2)(xmap.x, ymap.x); + pos.xy = pos.xy * 65535.f; + + mi = ((pos >= (float2)(0.f, 0.f)) * (pos < dimf) * (p <= dimi)); + m = mi.x && mi.y; + val = mix(fill_color, read_imagef(src, nearest_sampler, pos), m); + + write_imagef(dst, p, val); +} + +__kernel void remap_linear(__write_only image2d_t dst, + __read_only image2d_t src, + __read_only image2d_t xmapi, + __read_only image2d_t ymapi, + float4 fill_color) +{ + int2 p = (int2)(get_global_id(0), get_global_id(1)); + int2 dimi = get_image_dim(src); + float2 dimf = (float2)(dimi.x, dimi.y); + float4 val; + int2 mi; + float m; + + float4 xmap = read_imagef(xmapi, nearest_sampler, p); + float4 ymap = read_imagef(ymapi, nearest_sampler, p); + float2 pos = (float2)(xmap.x, ymap.x); + pos.xy = pos.xy * 65535.f; + + mi = ((pos >= (float2)(0.f, 0.f)) * (pos < dimf) * (p <= dimi)); + m = mi.x && mi.y; + val = mix(fill_color, read_imagef(src, linear_sampler, pos), m); + + write_imagef(dst, p, val); +} diff --git a/libavfilter/opencl_source.h b/libavfilter/opencl_source.h index 7e8133090..9eac2dc51 100644 --- a/libavfilter/opencl_source.h +++ b/libavfilter/opencl_source.h @@ -28,6 +28,7 @@ extern const char *ff_opencl_source_neighbor; extern const char *ff_opencl_source_nlmeans; extern const char *ff_opencl_source_overlay; extern const char *ff_opencl_source_pad; +extern const char *ff_opencl_source_remap; extern const char *ff_opencl_source_tonemap; extern const char *ff_opencl_source_transpose; extern const char *ff_opencl_source_unsharp; diff --git a/libavfilter/pthread.c b/libavfilter/pthread.c index 34fc69950..1a063d3cc 100644 --- a/libavfilter/pthread.c +++ b/libavfilter/pthread.c @@ -21,11 +21,11 @@ * Libavfilter multithreading support */ -#include "config.h" +#include -#include "libavutil/common.h" +#include "libavutil/error.h" +#include "libavutil/macros.h" #include "libavutil/mem.h" -#include "libavutil/thread.h" #include "libavutil/slicethread.h" #include "avfilter.h" diff --git a/libavfilter/qp_table.c b/libavfilter/qp_table.c index 33812b708..8137dc019 100644 --- a/libavfilter/qp_table.c +++ b/libavfilter/qp_table.c @@ -18,9 +18,6 @@ #include -// for FF_QSCALE_TYPE_* -#include "libavcodec/internal.h" - #include "libavutil/frame.h" #include "libavutil/mem.h" #include "libavutil/video_enc_params.h" @@ -28,7 +25,7 @@ #include "qp_table.h" int ff_qp_table_extract(AVFrame *frame, int8_t **table, int *table_w, int *table_h, - int *qscale_type) + enum AVVideoEncParamsType *qscale_type) { AVFrameSideData *sd; AVVideoEncParams *par; @@ -55,7 +52,7 @@ int ff_qp_table_extract(AVFrame *frame, int8_t **table, int *table_w, int *table if (table_h) *table_h = mb_h; if (qscale_type) - *qscale_type = FF_QSCALE_TYPE_MPEG2; + *qscale_type = par->type; if (par->nb_blocks == 0) { memset(*table, par->qp, nb_mb); diff --git a/libavfilter/qp_table.h b/libavfilter/qp_table.h index 4758ee853..4407bacb0 100644 --- a/libavfilter/qp_table.h +++ b/libavfilter/qp_table.h @@ -22,27 +22,24 @@ #include #include "libavutil/frame.h" -#include "libavcodec/internal.h" +#include "libavutil/video_enc_params.h" /** * Extract a libpostproc-compatible QP table - an 8-bit QP value per 16x16 * macroblock, stored in raster order - from AVVideoEncParams side data. */ int ff_qp_table_extract(AVFrame *frame, int8_t **table, int *table_w, int *table_h, - int *qscale_type); + enum AVVideoEncParamsType *qscale_type); /** * Normalize the qscale factor - * FIXME the H264 qscale is a log based scale, mpeg1/2 is not, the code below - * cannot be optimal + * FIXME Add support for other values of enum AVVideoEncParamsType + * besides AV_VIDEO_ENC_PARAMS_MPEG2. */ -static inline int ff_norm_qscale(int qscale, int type) +static inline int ff_norm_qscale(int qscale, enum AVVideoEncParamsType type) { switch (type) { - case FF_QSCALE_TYPE_MPEG1: return qscale; - case FF_QSCALE_TYPE_MPEG2: return qscale >> 1; - case FF_QSCALE_TYPE_H264: return qscale >> 2; - case FF_QSCALE_TYPE_VP56: return (63 - qscale + 2) >> 2; + case AV_VIDEO_ENC_PARAMS_MPEG2: return qscale >> 1; } return qscale; } diff --git a/libavfilter/qsvvpp.c b/libavfilter/qsvvpp.c index d1218355c..954f88263 100644 --- a/libavfilter/qsvvpp.c +++ b/libavfilter/qsvvpp.c @@ -40,6 +40,11 @@ static const AVRational default_tb = { 1, 90000 }; +typedef struct QSVAsyncFrame { + mfxSyncPoint sync; + QSVFrame *frame; +} QSVAsyncFrame; + static const struct { int mfx_iopattern; const char *desc; @@ -642,16 +647,6 @@ static int init_vpp_session(AVFilterContext *avctx, QSVVPPContext *s) return 0; } -static unsigned int qsv_fifo_item_size(void) -{ - return sizeof(mfxSyncPoint) + sizeof(QSVFrame*); -} - -static unsigned int qsv_fifo_size(const AVFifoBuffer* fifo) -{ - return av_fifo_size(fifo)/qsv_fifo_item_size(); -} - int ff_qsvvpp_create(AVFilterContext *avctx, QSVVPPContext **vpp, QSVVPPParam *param) { int i; @@ -727,7 +722,7 @@ int ff_qsvvpp_create(AVFilterContext *avctx, QSVVPPContext **vpp, QSVVPPParam *p s->got_frame = 0; /** keep fifo size at least 1. Even when async_depth is 0, fifo is used. */ - s->async_fifo = av_fifo_alloc((param->async_depth + 1) * qsv_fifo_item_size()); + s->async_fifo = av_fifo_alloc2(param->async_depth + 1, sizeof(QSVAsyncFrame), 0); s->async_depth = param->async_depth; if (!s->async_fifo) { ret = AVERROR(ENOMEM); @@ -789,7 +784,7 @@ int ff_qsvvpp_free(QSVVPPContext **vpp) av_freep(&s->surface_ptrs_out); av_freep(&s->ext_buffers); av_freep(&s->frame_infos); - av_fifo_free(s->async_fifo); + av_fifo_freep2(&s->async_fifo); av_freep(vpp); return 0; @@ -799,24 +794,23 @@ int ff_qsvvpp_filter_frame(QSVVPPContext *s, AVFilterLink *inlink, AVFrame *picr { AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; + QSVAsyncFrame aframe; mfxSyncPoint sync; - QSVFrame *in_frame, *out_frame, *tmp; + QSVFrame *in_frame, *out_frame; int ret, filter_ret; - while (s->eof && qsv_fifo_size(s->async_fifo)) { - av_fifo_generic_read(s->async_fifo, &tmp, sizeof(tmp), NULL); - av_fifo_generic_read(s->async_fifo, &sync, sizeof(sync), NULL); - if (MFXVideoCORE_SyncOperation(s->session, sync, 1000) < 0) + while (s->eof && av_fifo_read(s->async_fifo, &aframe, 1) >= 0) { + if (MFXVideoCORE_SyncOperation(s->session, aframe.sync, 1000) < 0) av_log(ctx, AV_LOG_WARNING, "Sync failed.\n"); - filter_ret = s->filter_frame(outlink, tmp->frame); + filter_ret = s->filter_frame(outlink, aframe.frame->frame); if (filter_ret < 0) { - av_frame_free(&tmp->frame); + av_frame_free(&aframe.frame->frame); return filter_ret; } - tmp->queued--; + aframe.frame->queued--; s->got_frame = 1; - tmp->frame = NULL; + aframe.frame->frame = NULL; }; if (!picref) @@ -853,27 +847,25 @@ int ff_qsvvpp_filter_frame(QSVVPPContext *s, AVFilterLink *inlink, AVFrame *picr default_tb, outlink->time_base); out_frame->queued++; - av_fifo_generic_write(s->async_fifo, &out_frame, sizeof(out_frame), NULL); - av_fifo_generic_write(s->async_fifo, &sync, sizeof(sync), NULL); + aframe = (QSVAsyncFrame){ sync, out_frame }; + av_fifo_write(s->async_fifo, &aframe, 1); - - if (qsv_fifo_size(s->async_fifo) > s->async_depth) { - av_fifo_generic_read(s->async_fifo, &tmp, sizeof(tmp), NULL); - av_fifo_generic_read(s->async_fifo, &sync, sizeof(sync), NULL); + if (av_fifo_can_read(s->async_fifo) > s->async_depth) { + av_fifo_read(s->async_fifo, &aframe, 1); do { - ret = MFXVideoCORE_SyncOperation(s->session, sync, 1000); + ret = MFXVideoCORE_SyncOperation(s->session, aframe.sync, 1000); } while (ret == MFX_WRN_IN_EXECUTION); - filter_ret = s->filter_frame(outlink, tmp->frame); + filter_ret = s->filter_frame(outlink, aframe.frame->frame); if (filter_ret < 0) { - av_frame_free(&tmp->frame); + av_frame_free(&aframe.frame->frame); return filter_ret; } - tmp->queued--; + aframe.frame->queued--; s->got_frame = 1; - tmp->frame = NULL; + aframe.frame->frame = NULL; } } while(ret == MFX_ERR_MORE_SURFACE); diff --git a/libavfilter/qsvvpp.h b/libavfilter/qsvvpp.h index e0f4c8f5b..4fe07ab1f 100644 --- a/libavfilter/qsvvpp.h +++ b/libavfilter/qsvvpp.h @@ -73,7 +73,7 @@ typedef struct QSVVPPContext { int async_depth; int eof; /** order with frame_out, sync */ - AVFifoBuffer *async_fifo; + AVFifo *async_fifo; } QSVVPPContext; typedef struct QSVVPPCrop { diff --git a/libavfilter/scene_sad.c b/libavfilter/scene_sad.c index 73d3eacbf..caf911eb5 100644 --- a/libavfilter/scene_sad.c +++ b/libavfilter/scene_sad.c @@ -59,8 +59,9 @@ void ff_scene_sad_c(SCENE_SAD_PARAMS) ff_scene_sad_fn ff_scene_sad_get_fn(int depth) { ff_scene_sad_fn sad = NULL; - if (ARCH_X86) - sad = ff_scene_sad_get_fn_x86(depth); +#if ARCH_X86 + sad = ff_scene_sad_get_fn_x86(depth); +#endif if (!sad) { if (depth == 8) sad = ff_scene_sad_c; diff --git a/libavfilter/setpts.c b/libavfilter/setpts.c index 054feb05f..171fae88c 100644 --- a/libavfilter/setpts.c +++ b/libavfilter/setpts.c @@ -24,6 +24,8 @@ * video presentation timestamp (PTS) modification filter */ +#include "config_components.h" + #include #include "libavutil/eval.h" diff --git a/libavfilter/settb.c b/libavfilter/settb.c index 67d310afb..5f589004f 100644 --- a/libavfilter/settb.c +++ b/libavfilter/settb.c @@ -23,6 +23,8 @@ * Set timebase for the output link. */ +#include "config_components.h" + #include #include diff --git a/libavfilter/split.c b/libavfilter/split.c index 6b9b65670..98b51f976 100644 --- a/libavfilter/split.c +++ b/libavfilter/split.c @@ -63,28 +63,62 @@ static av_cold int split_init(AVFilterContext *ctx) return 0; } -static int filter_frame(AVFilterLink *inlink, AVFrame *frame) +static int activate(AVFilterContext *ctx) { - AVFilterContext *ctx = inlink->dst; - int i, ret = AVERROR_EOF; + AVFilterLink *inlink = ctx->inputs[0]; + AVFrame *in; + int status, ret; + int64_t pts; - for (i = 0; i < ctx->nb_outputs; i++) { - AVFrame *buf_out; + for (int i = 0; i < ctx->nb_outputs; i++) { + FF_FILTER_FORWARD_STATUS_BACK_ALL(ctx->outputs[i], ctx); + } - if (ff_outlink_get_status(ctx->outputs[i])) - continue; - buf_out = av_frame_clone(frame); - if (!buf_out) { - ret = AVERROR(ENOMEM); - break; + ret = ff_inlink_consume_frame(inlink, &in); + if (ret < 0) + return ret; + if (ret > 0) { + for (int i = 0; i < ctx->nb_outputs; i++) { + AVFrame *buf_out; + + if (ff_outlink_get_status(ctx->outputs[i])) + continue; + buf_out = av_frame_clone(in); + if (!buf_out) { + ret = AVERROR(ENOMEM); + break; + } + + ret = ff_filter_frame(ctx->outputs[i], buf_out); + if (ret < 0) + break; } - ret = ff_filter_frame(ctx->outputs[i], buf_out); + av_frame_free(&in); if (ret < 0) - break; + return ret; } - av_frame_free(&frame); - return ret; + + if (ff_inlink_acknowledge_status(inlink, &status, &pts)) { + for (int i = 0; i < ctx->nb_outputs; i++) { + if (ff_outlink_get_status(ctx->outputs[i])) + continue; + ff_outlink_set_status(ctx->outputs[i], status, pts); + } + return 0; + } + + for (int i = 0; i < ctx->nb_outputs; i++) { + if (ff_outlink_get_status(ctx->outputs[i])) + continue; + + if (ff_outlink_frame_wanted(ctx->outputs[i])) { + ff_inlink_request_frame(inlink); + return 0; + } + } + + return FFERROR_NOT_READY; } #define OFFSET(x) offsetof(SplitContext, x) @@ -100,7 +134,6 @@ static const AVFilterPad avfilter_vf_split_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .filter_frame = filter_frame, }, }; @@ -110,6 +143,7 @@ const AVFilter ff_vf_split = { .priv_size = sizeof(SplitContext), .priv_class = &split_class, .init = split_init, + .activate = activate, FILTER_INPUTS(avfilter_vf_split_inputs), .outputs = NULL, .flags = AVFILTER_FLAG_DYNAMIC_OUTPUTS | AVFILTER_FLAG_METADATA_ONLY, @@ -119,7 +153,6 @@ static const AVFilterPad avfilter_af_asplit_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_AUDIO, - .filter_frame = filter_frame, }, }; @@ -129,6 +162,7 @@ const AVFilter ff_af_asplit = { .priv_class = &split_class, .priv_size = sizeof(SplitContext), .init = split_init, + .activate = activate, FILTER_INPUTS(avfilter_af_asplit_inputs), .outputs = NULL, .flags = AVFILTER_FLAG_DYNAMIC_OUTPUTS | AVFILTER_FLAG_METADATA_ONLY, diff --git a/libavfilter/src_avsynctest.c b/libavfilter/src_avsynctest.c new file mode 100644 index 000000000..c78e517ac --- /dev/null +++ b/libavfilter/src_avsynctest.c @@ -0,0 +1,402 @@ +/* + * Copyright (c) 2017-2022 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/common.h" +#include "libavutil/channel_layout.h" +#include "libavutil/ffmath.h" +#include "libavutil/opt.h" +#include "libavutil/imgutils.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/parseutils.h" +#include "libavutil/timestamp.h" +#include "libavutil/xga_font_data.h" +#include "avfilter.h" +#include "drawutils.h" +#include "filters.h" +#include "formats.h" +#include "internal.h" +#include "audio.h" +#include "video.h" + +typedef struct AVSyncTestContext { + const AVClass *class; + + int w, h; + AVRational frame_rate; + int sample_rate; + int64_t duration; + int64_t apts, vpts; + float amplitude; + int period; + int delay; + int cycle; + + int beep; + int beep_duration; + int flash; + int dir; + AVRational vdelay, delay_max, delay_min; + AVRational delay_range; + int64_t prev_intpart; + + uint8_t rgba[3][4]; + FFDrawContext draw; + FFDrawColor fg; + FFDrawColor bg; + FFDrawColor ag; +} AVSyncTestContext; + +#define OFFSET(x) offsetof(AVSyncTestContext, x) +#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define V AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM + +static const AVOption avsynctest_options[] = { + {"size", "set frame size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="hd720"}, 0, 0, V }, + {"s", "set frame size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="hd720"}, 0, 0, V }, + {"framerate", "set frame rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="30"}, 0,INT_MAX, V }, + {"fr", "set frame rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="30"}, 0,INT_MAX, V }, + {"samplerate", "set sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64=44100},8000,384000, A }, + {"sr", "set sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64=44100},8000,384000, A }, + {"amplitude", "set beep amplitude", OFFSET(amplitude), AV_OPT_TYPE_FLOAT, {.dbl=.7}, 0., 1., A }, + {"a", "set beep amplitude", OFFSET(amplitude), AV_OPT_TYPE_FLOAT, {.dbl=.7}, 0., 1., A }, + {"period", "set beep period", OFFSET(period), AV_OPT_TYPE_INT, {.i64=3}, 1, 99., A }, + {"p", "set beep period", OFFSET(period), AV_OPT_TYPE_INT, {.i64=3}, 1, 99., A }, + {"delay", "set flash delay", OFFSET(delay), AV_OPT_TYPE_INT, {.i64=0}, -30, 30, V }, + {"dl", "set flash delay", OFFSET(delay), AV_OPT_TYPE_INT, {.i64=0}, -30, 30, V }, + {"cycle", "set delay cycle", OFFSET(cycle), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, V }, + {"c", "set delay cycle", OFFSET(cycle), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, V }, + {"duration", "set duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64=0}, 0, INT64_MAX, V|A }, + {"d", "set duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64=0}, 0, INT64_MAX, V|A }, + {"fg", "set foreground color", OFFSET(rgba[0]), AV_OPT_TYPE_COLOR, {.str="white"}, 0, 0, V }, + {"bg", "set background color", OFFSET(rgba[1]), AV_OPT_TYPE_COLOR, {.str="black"}, 0, 0, V }, + {"ag", "set additional color", OFFSET(rgba[2]), AV_OPT_TYPE_COLOR, {.str="gray"}, 0, 0, V }, + {NULL}, +}; + +AVFILTER_DEFINE_CLASS(avsynctest); + +static av_cold int query_formats(AVFilterContext *ctx) +{ + AVSyncTestContext *s = ctx->priv; + AVFilterChannelLayouts *chlayout = NULL; + int sample_rates[] = { s->sample_rate, -1 }; + static const enum AVSampleFormat sample_fmts[] = { + AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE + }; + AVFilterFormats *formats; + int ret; + + formats = ff_make_format_list(sample_fmts); + if (!formats) + return AVERROR(ENOMEM); + if ((ret = ff_formats_ref(formats, &ctx->outputs[0]->incfg.formats)) < 0) + return ret; + + formats = ff_draw_supported_pixel_formats(0); + if (!formats) + return AVERROR(ENOMEM); + if ((ret = ff_formats_ref(formats, &ctx->outputs[1]->incfg.formats)) < 0) + return ret; + + if ((ret = ff_add_channel_layout(&chlayout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_MONO)) < 0) + return ret; + ret = ff_set_common_channel_layouts(ctx, chlayout); + 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 aconfig_props(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + AVSyncTestContext *s = ctx->priv; + + outlink->sample_rate = s->sample_rate; + outlink->time_base = (AVRational){1, s->sample_rate}; + + s->beep_duration = av_rescale(s->sample_rate, s->frame_rate.den, s->frame_rate.num); + s->duration = av_rescale(s->duration, s->sample_rate, AV_TIME_BASE); + + return 0; +} + +static av_cold int config_props(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + AVSyncTestContext *s = ctx->priv; + + outlink->w = s->w; + outlink->h = s->h; + outlink->time_base = av_inv_q(s->frame_rate); + outlink->frame_rate = s->frame_rate; + outlink->sample_aspect_ratio = (AVRational) {1, 1}; + s->delay_min = av_mul_q(s->frame_rate, av_make_q(-1, 2)); + s->delay_max = av_mul_q(s->delay_min, av_make_q(-1, 1)); + s->delay_range = av_sub_q(s->delay_max, s->delay_min); + s->vdelay = av_make_q(s->delay, 1); + s->dir = 1; + s->prev_intpart = INT64_MIN; + + ff_draw_init(&s->draw, outlink->format, 0); + + ff_draw_color(&s->draw, &s->fg, s->rgba[0]); + ff_draw_color(&s->draw, &s->bg, s->rgba[1]); + ff_draw_color(&s->draw, &s->ag, s->rgba[2] ); + + return 0; +} + +#define FPI 0x8000 + +static int32_t sin32(int32_t x, int shift) +{ + const double pi = M_PI; + const int32_t a = ((2.0 * pi) * (1 << 24)); + const int32_t b = (1 << 7) * (12.0 / pi - 1.0 - pi) * (1 << 24); + const int32_t c = (1 << 9) * 3.0 * (2.0 + pi - 16.0 / pi) * (1 << 24); + int64_t x2, result; + int32_t t1, t2; + + x &= 2 * FPI - 1; + + if (x >= (3 * FPI / 2)) + x = x - 2 * FPI; + else if (x > FPI / 2) + x = FPI - x; + + x2 = x * x; + t1 = (x2 * c) >> 32; + t2 = ((b + t1) * x2) >> 32; + x = x << 8; + + result = a + t2; + result *= x; + result += (1U << 31); + result >>= (32 - shift); + + return result; +} + +static int audio_frame(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + AVSyncTestContext *s = ctx->priv; + const int a = lrintf(s->amplitude * 15); + int64_t duration[2]; + int64_t delta; + AVFrame *out; + int32_t *dst; + + delta = av_rescale_q(s->vpts, av_make_q(s->sample_rate, 1), s->frame_rate) - s->apts; + if (delta < 0) + return 1; + + duration[0] = av_rescale_rnd(s->sample_rate, s->frame_rate.den, s->frame_rate.num, AV_ROUND_DOWN); + duration[1] = av_rescale_rnd(s->sample_rate, s->frame_rate.den, s->frame_rate.num, AV_ROUND_UP); + + delta = duration[delta > 0]; + out = ff_get_audio_buffer(outlink, delta); + if (!out) + return AVERROR(ENOMEM); + + out->pts = s->apts; + dst = (int32_t *)out->data[0]; + + for (int i = 0; i < delta; i++) { + if (((s->apts + i) % (s->period * s->sample_rate)) == 0) + s->beep = 1; + if (s->beep) { + dst[i] = sin32(av_rescale_q(800LL * 2LL * FPI, outlink->time_base, av_make_q(1, s->apts + i)), a); + s->beep++; + } else { + dst[i] = 0; + } + if (s->beep >= s->beep_duration) { + s->beep = 0; + } + } + s->apts += out->nb_samples; + + return ff_filter_frame(outlink, out); +} + +static void draw_text(FFDrawContext *draw, AVFrame *out, FFDrawColor *color, + int x0, int y0, const uint8_t *text) +{ + int x = x0; + + for (; *text; text++) { + if (*text == '\n') { + x = x0; + y0 += 8; + continue; + } + ff_blend_mask(draw, color, out->data, out->linesize, + out->width, out->height, + avpriv_cga_font + *text * 8, 1, 8, 8, 0, 0, x, y0); + x += 8; + } +} + +static int offset(int x, int num, int den) +{ + return av_rescale_rnd(x, num, den, AV_ROUND_UP); +} + +static int video_frame(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + AVSyncTestContext *s = ctx->priv; + const int w = outlink->w; + const int h = outlink->h; + const int step = av_rescale_rnd(w, s->delay_range.den, s->delay_range.num, AV_ROUND_DOWN); + char text[128]; + int new_offset; + int64_t delta, temp, intpart; + AVFrame *out; + + delta = av_rescale_q(s->apts, s->frame_rate, av_make_q(s->sample_rate, 1)) - s->vpts; + if (delta < 0) + return 1; + + out = ff_get_video_buffer(outlink, w, h); + if (!out) + return AVERROR(ENOMEM); + + ff_fill_rectangle(&s->draw, &s->bg, out->data, out->linesize, 0, 0, w, h); + + snprintf(text, sizeof(text), "FRN: %"PRId64"", s->vpts); + draw_text(&s->draw, out, &s->fg, offset(w, 1, 10), offset(h, 1, 10), text); + + snprintf(text, sizeof(text), "SEC: %s", av_ts2timestr(s->vpts, &outlink->time_base)); + draw_text(&s->draw, out, &s->fg, offset(w, 1, 10), offset(h, 9, 10), text); + + snprintf(text, sizeof(text), "DLY: %d", s->vdelay.num); + draw_text(&s->draw, out, &s->fg, offset(w, 9, 10) - strlen(text) * 8, offset(h, 9, 10), text); + + snprintf(text, sizeof(text), "FPS: %d/%d", s->frame_rate.num, s->frame_rate.den); + draw_text(&s->draw, out, &s->fg, offset(w, 9, 10) - strlen(text) * 8, offset(h, 1, 10), text); + + snprintf(text, sizeof(text), "P: %d", s->period); + draw_text(&s->draw, out, &s->ag, offset(w, 1, 2) - strlen(text) * 4, offset(h, 9, 10), text); + + snprintf(text, sizeof(text), "SR: %d", s->sample_rate); + draw_text(&s->draw, out, &s->ag, offset(w, 1, 2) - strlen(text) * 4, offset(h, 1, 10), text); + + snprintf(text, sizeof(text), "A: %1.2f", s->amplitude); + draw_text(&s->draw, out, &s->ag, offset(w, 1, 10), offset(h, 1, 2), text); + + snprintf(text, sizeof(text), "WxH: %dx%d", w, h); + draw_text(&s->draw, out, &s->ag, offset(w, 9, 10) - strlen(text) * 8, offset(h, 1, 2), text); + + temp = s->vpts + s->vdelay.num; + intpart = av_rescale_rnd(temp, outlink->time_base.num, outlink->time_base.den, AV_ROUND_NEAR_INF); + intpart = temp - av_rescale_rnd(intpart, outlink->time_base.den, outlink->time_base.num, AV_ROUND_NEAR_INF); + + new_offset = offset(w, 1, 2); + ff_fill_rectangle(&s->draw, &s->fg, out->data, out->linesize, + av_clip(new_offset + step * intpart, 0, w - 2), + offset(h, 141, 200), offset(step, 2, 3), offset(h, 1, 25)); + + if (intpart == 0 && s->prev_intpart != intpart) { + if (s->flash >= s->period) { + int result; + + if (s->cycle) + s->vdelay = av_add_q(s->vdelay, av_make_q(s->dir, 1)); + result = av_cmp_q(s->vdelay, s->delay_max); + if (result >= 0) + s->dir = -1; + result = av_cmp_q(s->vdelay, s->delay_min); + if (result <= 0) + s->dir = 1; + ff_fill_rectangle(&s->draw, &s->fg, out->data, out->linesize, + offset(w, 1, 3), offset(h, 1, 3), offset(w, 1, 3), offset(h, 1, 4)); + s->flash = 0; + } + s->flash++; + } + s->prev_intpart = intpart; + + for (int i = av_rescale(s->delay_min.num, 1, s->delay_min.den); + i < av_rescale(s->delay_max.num, 1, s->delay_max.den); i++) { + ff_fill_rectangle(&s->draw, &s->fg, out->data, out->linesize, + av_clip(new_offset + step * i, 0, w - 2), + offset(h, 7, 10), 1, offset(h, 1, 20)); + } + + out->pts = s->vpts++; + + return ff_filter_frame(outlink, out); +} + +static int activate(AVFilterContext *ctx) +{ + AVSyncTestContext *s = ctx->priv; + AVFilterLink *aoutlink = ctx->outputs[0]; + AVFilterLink *voutlink = ctx->outputs[1]; + int ret = FFERROR_NOT_READY; + + if (!ff_outlink_frame_wanted(aoutlink) && + !ff_outlink_frame_wanted(voutlink)) + return ret; + + if (s->duration > 0 && s->apts >= s->duration) { + ff_outlink_set_status(aoutlink, AVERROR_EOF, s->apts); + ff_outlink_set_status(voutlink, AVERROR_EOF, s->vpts); + return 0; + } + + ret = audio_frame(aoutlink); + if (ret < 0) + return ret; + ret = video_frame(voutlink); + + return ret; +} + +static const AVFilterPad avsynctest_outputs[] = { + { + .name = "audio", + .type = AVMEDIA_TYPE_AUDIO, + .config_props = aconfig_props, + }, + { + .name = "video", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_props, + }, +}; + +const AVFilter ff_avsrc_avsynctest = { + .name = "avsynctest", + .description = NULL_IF_CONFIG_SMALL("Generate an Audio Video Sync Test."), + .priv_size = sizeof(AVSyncTestContext), + .priv_class = &avsynctest_class, + .inputs = NULL, + .activate = activate, + FILTER_OUTPUTS(avsynctest_outputs), + FILTER_QUERY_FUNC(query_formats), +}; diff --git a/libavfilter/src_movie.c b/libavfilter/src_movie.c index b89a68088..711854c23 100644 --- a/libavfilter/src_movie.c +++ b/libavfilter/src_movie.c @@ -27,6 +27,8 @@ * @todo support a PTS correction mechanism */ +#include "config_components.h" + #include #include @@ -189,23 +191,24 @@ static int guess_channel_layout(MovieStream *st, int st_index, void *log_ctx) { AVCodecParameters *dec_par = st->st->codecpar; char buf[256]; - int64_t chl = av_get_default_channel_layout(dec_par->channels); + AVChannelLayout chl = { 0 }; - if (!chl) { + av_channel_layout_default(&chl, dec_par->ch_layout.nb_channels); + + if (!KNOWN(&chl)) { av_log(log_ctx, AV_LOG_ERROR, "Channel layout is not set in stream %d, and could not " "be guessed from the number of channels (%d)\n", - st_index, dec_par->channels); + st_index, dec_par->ch_layout.nb_channels); return AVERROR(EINVAL); } - av_get_channel_layout_string(buf, sizeof(buf), dec_par->channels, chl); + av_channel_layout_describe(&chl, buf, sizeof(buf)); av_log(log_ctx, AV_LOG_WARNING, "Channel layout is not set in output stream %d, " "guessed channel layout is '%s'\n", st_index, buf); - dec_par->channel_layout = chl; - return 0; + return av_channel_layout_copy(&dec_par->ch_layout, &chl); } static av_cold int movie_common_init(AVFilterContext *ctx) @@ -315,7 +318,7 @@ static av_cold int movie_common_init(AVFilterContext *ctx) if ((ret = ff_append_outpad_free_name(ctx, &pad)) < 0) return ret; if ( movie->st[i].st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && - !movie->st[i].st->codecpar->channel_layout) { + !KNOWN(&movie->st[i].st->codecpar->ch_layout)) { ret = guess_channel_layout(&movie->st[i], i, ctx); if (ret < 0) return ret; @@ -351,7 +354,7 @@ static int movie_query_formats(AVFilterContext *ctx) { MovieContext *movie = ctx->priv; int list[] = { 0, -1 }; - int64_t list64[] = { 0, -1 }; + AVChannelLayout list64[] = { { 0 }, { 0 } }; int i, ret; for (i = 0; i < ctx->nb_outputs; i++) { @@ -372,8 +375,8 @@ static int movie_query_formats(AVFilterContext *ctx) list[0] = c->sample_rate; if ((ret = ff_formats_ref(ff_make_format_list(list), &outlink->incfg.samplerates)) < 0) return ret; - list64[0] = c->channel_layout; - if ((ret = ff_channel_layouts_ref(ff_make_format64_list(list64), + list64[0] = c->ch_layout; + if ((ret = ff_channel_layouts_ref(ff_make_channel_layout_list(list64), &outlink->incfg.channel_layouts)) < 0) return ret; break; diff --git a/libavfilter/tests/filtfmts.c b/libavfilter/tests/filtfmts.c index d79348034..909c1e8dc 100644 --- a/libavfilter/tests/filtfmts.c +++ b/libavfilter/tests/filtfmts.c @@ -59,8 +59,7 @@ static void print_formats_internal(AVFilterLink **links, const AVFilterPad *pads for (unsigned j = 0; layouts && j < layouts->nb_channel_layouts; j++) { char buf[256]; - av_get_channel_layout_string(buf, sizeof(buf), -1, - layouts->channel_layouts[j]); + av_channel_layout_describe(&layouts->channel_layouts[j], buf, sizeof(buf)); printf("%s[%u] %s: chlayout:%s\n", inout_string, i, pad_name, buf); } diff --git a/libavfilter/tests/formats.c b/libavfilter/tests/formats.c index c1e30e73e..2bdceb0d2 100644 --- a/libavfilter/tests/formats.c +++ b/libavfilter/tests/formats.c @@ -97,6 +97,7 @@ const int64_t avfilter_all_channel_layouts[] = { int main(void) { + AVChannelLayout layout = { 0 }; const int64_t *cl; char buf[512]; int i; @@ -124,17 +125,19 @@ int main(void) }; for (cl = avfilter_all_channel_layouts; *cl != -1; cl++) { - av_get_channel_layout_string(buf, sizeof(buf), -1, *cl); + av_channel_layout_from_mask(&layout, *cl); + av_channel_layout_describe(&layout, buf, sizeof(buf)); printf("%s\n", buf); + av_channel_layout_uninit(&layout); } for ( i = 0; i #include "config.h" +#include "config_components.h" #include "libavutil/channel_layout.h" #include "libavutil/common.h" @@ -309,7 +310,7 @@ static int atrim_filter_frame(AVFilterLink *inlink, AVFrame *frame) av_frame_copy_props(out, frame); av_samples_copy(out->extended_data, frame->extended_data, 0, start_sample, - out->nb_samples, inlink->channels, + out->nb_samples, inlink->ch_layout.nb_channels, frame->format); if (out->pts != AV_NOPTS_VALUE) out->pts += av_rescale_q(start_sample, (AVRational){ 1, out->sample_rate }, diff --git a/libavfilter/unsharp.h b/libavfilter/unsharp.h index 253e32dd1..0da6f0503 100644 --- a/libavfilter/unsharp.h +++ b/libavfilter/unsharp.h @@ -44,14 +44,17 @@ typedef struct UnsharpFilterParam { typedef struct UnsharpContext { const AVClass *class; int lmsize_x, lmsize_y, cmsize_x, cmsize_y; + int amsize_x, amsize_y; float lamount, camount; + float aamount; UnsharpFilterParam luma; ///< luma parameters (width, height, amount) UnsharpFilterParam chroma; ///< chroma parameters (width, height, amount) + UnsharpFilterParam alpha; ///< alpha parameters (width, height, amount) int hsub, vsub; + int nb_planes; int bitdepth; int bps; int nb_threads; - int opencl; int (* apply_unsharp)(AVFilterContext *ctx, AVFrame *in, AVFrame *out); int (* unsharp_slice)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); } UnsharpContext; diff --git a/libavfilter/vaf_spectrumsynth.c b/libavfilter/vaf_spectrumsynth.c index 674e9953b..e0baf855a 100644 --- a/libavfilter/vaf_spectrumsynth.c +++ b/libavfilter/vaf_spectrumsynth.c @@ -112,7 +112,7 @@ static int query_formats(AVFilterContext *ctx) formats = ff_make_format_list(sample_fmts); if ((ret = ff_formats_ref (formats, &outlink->incfg.formats )) < 0 || - (ret = ff_add_channel_layout (&layout, FF_COUNT2LAYOUT(s->channels))) < 0 || + (ret = ff_add_channel_layout (&layout, &FF_COUNT2LAYOUT(s->channels))) < 0 || (ret = ff_channel_layouts_ref (layout , &outlink->incfg.channel_layouts)) < 0) return ret; diff --git a/libavfilter/version.c b/libavfilter/version.c new file mode 100644 index 000000000..db1a2511e --- /dev/null +++ b/libavfilter/version.c @@ -0,0 +1,44 @@ +/* + * Version functions. + * + * 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/avassert.h" +#include "avfilter.h" +#include "version.h" + +#include "libavutil/ffversion.h" +const char av_filter_ffversion[] = "FFmpeg version " FFMPEG_VERSION; + +unsigned avfilter_version(void) +{ + av_assert0(LIBAVFILTER_VERSION_MICRO >= 100); + return LIBAVFILTER_VERSION_INT; +} + +const char *avfilter_configuration(void) +{ + return FFMPEG_CONFIGURATION; +} + +const char *avfilter_license(void) +{ +#define LICENSE_PREFIX "libavfilter license: " + return &LICENSE_PREFIX FFMPEG_LICENSE[sizeof(LICENSE_PREFIX) - 1]; +} diff --git a/libavfilter/version.h b/libavfilter/version.h index 1a1d7ee1c..ceead918e 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -29,8 +29,9 @@ #include "libavutil/version.h" -#define LIBAVFILTER_VERSION_MAJOR 8 -#define LIBAVFILTER_VERSION_MINOR 24 +#include "version_major.h" + +#define LIBAVFILTER_VERSION_MINOR 44 #define LIBAVFILTER_VERSION_MICRO 100 @@ -44,14 +45,4 @@ #define LIBAVFILTER_IDENT "Lavfi" AV_STRINGIFY(LIBAVFILTER_VERSION) -/** - * FF_API_* defines may be placed below to indicate public API that will be - * 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. - */ - -#define FF_API_SWS_PARAM_OPTION (LIBAVFILTER_VERSION_MAJOR < 9) -#define FF_API_BUFFERSINK_ALLOC (LIBAVFILTER_VERSION_MAJOR < 9) -#define FF_API_PAD_COUNT (LIBAVFILTER_VERSION_MAJOR < 9) - #endif /* AVFILTER_VERSION_H */ diff --git a/libavfilter/version_major.h b/libavfilter/version_major.h new file mode 100644 index 000000000..de0cf6e97 --- /dev/null +++ b/libavfilter/version_major.h @@ -0,0 +1,42 @@ +/* + * Version macros. + * + * 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_VERSION_MAJOR_H +#define AVFILTER_VERSION_MAJOR_H + +/** + * @file + * @ingroup lavfi + * Libavfilter version macros + */ + +#define LIBAVFILTER_VERSION_MAJOR 8 + +/** + * FF_API_* defines may be placed below to indicate public API that will be + * 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. + */ + +#define FF_API_SWS_PARAM_OPTION (LIBAVFILTER_VERSION_MAJOR < 9) +#define FF_API_BUFFERSINK_ALLOC (LIBAVFILTER_VERSION_MAJOR < 9) +#define FF_API_PAD_COUNT (LIBAVFILTER_VERSION_MAJOR < 9) + +#endif /* AVFILTER_VERSION_MAJOR_H */ diff --git a/libavfilter/vf_amplify.c b/libavfilter/vf_amplify.c index 10f153be4..0891d2641 100644 --- a/libavfilter/vf_amplify.c +++ b/libavfilter/vf_amplify.c @@ -37,8 +37,8 @@ typedef struct AmplifyContext { float tolerance; int planes; - int llimit; - int hlimit; + float llimit; + float hlimit; int nb_inputs; int nb_frames; @@ -53,7 +53,7 @@ typedef struct AmplifyContext { static const enum AVPixelFormat pixel_fmts[] = { AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY9, AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12, AV_PIX_FMT_GRAY14, - AV_PIX_FMT_GRAY16, + AV_PIX_FMT_GRAY16, AV_PIX_FMT_GRAYF32, AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV444P, @@ -74,6 +74,7 @@ static const enum AVPixelFormat pixel_fmts[] = { AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, + AV_PIX_FMT_GBRPF32, AV_PIX_FMT_GBRAPF32, AV_PIX_FMT_NONE }; @@ -94,6 +95,53 @@ typedef struct ThreadData { AVFrame **in, *out; } ThreadData; +#define AMPLIFY_SLICE(type, stype, clip) \ + const stype limit[2] = { s->llimit, s->hlimit }; \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + const int slice_start = (s->height[p] * jobnr) / nb_jobs; \ + const int slice_end = (s->height[p] * (jobnr+1)) / nb_jobs; \ + type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ + ptrdiff_t dst_linesize = out->linesize[p] / sizeof(type); \ + \ + if (!((1 << p) & s->planes)) { \ + av_image_copy_plane((uint8_t *)dst, out->linesize[p], \ + in[radius]->data[p] + slice_start * in[radius]->linesize[p], \ + in[radius]->linesize[p], \ + s->linesize[p], slice_end - slice_start); \ + continue; \ + } \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + for (int x = 0; x < s->linesize[p] / sizeof(type); x++) { \ + stype src = *(type *)(in[radius]->data[p] + y * in[radius]->linesize[p] + x * sizeof(type));\ + float diff, abs_diff, avg; \ + stype sum = 0; \ + \ + for (int i = 0; i < nb_inputs; i++) { \ + sum += *(type *)(in[i]->data[p] + y * in[i]->linesize[p] + x * sizeof(type));\ + } \ + \ + avg = sum * scale; \ + diff = src - avg; \ + abs_diff = fabsf(diff); \ + \ + if (abs_diff < threshold && abs_diff > tolerance) { \ + float amp = copysignf(fminf(abs_diff * factor, limit[diff >= 0]), diff); \ + dst[x] = clip(src + amp, depth); \ + } else { \ + dst[x] = src; \ + } \ + } \ + \ + dst += dst_linesize; \ + } \ + } + +#define CLIP8(x, depth) av_clip_uint8(lrintf(x)) +#define CLIP16(x, depth) av_clip_uintp2_c(lrintf(x), depth) +#define NOP(x, depth) (x) + static int amplify_frame(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { AmplifyContext *s = ctx->priv; @@ -104,97 +152,16 @@ static int amplify_frame(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs const int nb_inputs = s->nb_inputs; const float threshold = s->threshold; const float tolerance = s->tolerance; + const float scale = 1.f / nb_inputs; const float factor = s->factor; - const int llimit = s->llimit; - const int hlimit = s->hlimit; const int depth = s->depth; - int i, p, x, y; if (s->depth <= 8) { - for (p = 0; p < s->nb_planes; p++) { - const int slice_start = (s->height[p] * jobnr) / nb_jobs; - const int slice_end = (s->height[p] * (jobnr+1)) / nb_jobs; - uint8_t *dst = out->data[p] + slice_start * out->linesize[p]; - - if (!((1 << p) & s->planes)) { - av_image_copy_plane(dst, out->linesize[p], - in[radius]->data[p] + slice_start * in[radius]->linesize[p], - in[radius]->linesize[p], - s->linesize[p], slice_end - slice_start); - continue; - } - - for (y = slice_start; y < slice_end; y++) { - for (x = 0; x < s->linesize[p]; x++) { - int src = in[radius]->data[p][y * in[radius]->linesize[p] + x]; - float diff, avg; - int sum = 0; - - for (i = 0; i < nb_inputs; i++) { - sum += in[i]->data[p][y * in[i]->linesize[p] + x]; - } - - avg = sum / (float)nb_inputs; - diff = src - avg; - if (fabsf(diff) < threshold && fabsf(diff) > tolerance) { - int amp; - if (diff < 0) { - amp = -FFMIN(FFABS(diff * factor), llimit); - } else { - amp = FFMIN(FFABS(diff * factor), hlimit); - } - dst[x] = av_clip_uint8(src + amp); - } else { - dst[x] = src; - } - } - - dst += out->linesize[p]; - } - } + AMPLIFY_SLICE(uint8_t, int, CLIP8) + } else if (s->depth <= 16) { + AMPLIFY_SLICE(uint16_t, int, CLIP16) } else { - for (p = 0; p < s->nb_planes; p++) { - const int slice_start = (s->height[p] * jobnr) / nb_jobs; - const int slice_end = (s->height[p] * (jobnr+1)) / nb_jobs; - uint16_t *dst = (uint16_t *)(out->data[p] + slice_start * out->linesize[p]); - - if (!((1 << p) & s->planes)) { - av_image_copy_plane((uint8_t *)dst, out->linesize[p], - in[radius]->data[p] + slice_start * in[radius]->linesize[p], - in[radius]->linesize[p], - s->linesize[p], slice_end - slice_start); - continue; - } - - for (y = slice_start; y < slice_end; y++) { - for (x = 0; x < s->linesize[p] / 2; x++) { - int src = AV_RN16(in[radius]->data[p] + y * in[radius]->linesize[p] + x * 2); - float diff, avg; - int sum = 0; - - for (i = 0; i < nb_inputs; i++) { - sum += AV_RN16(in[i]->data[p] + y * in[i]->linesize[p] + x * 2); - } - - avg = sum / (float)nb_inputs; - diff = src - avg; - - if (fabsf(diff) < threshold && fabsf(diff) > tolerance) { - int amp; - if (diff < 0) { - amp = -FFMIN(FFABS(diff * factor), llimit); - } else { - amp = FFMIN(FFABS(diff * factor), hlimit); - } - dst[x] = av_clip_uintp2_c(src + amp, depth); - } else { - dst[x] = src; - } - } - - dst += out->linesize[p] / 2; - } - } + AMPLIFY_SLICE(float, float, NOP) } return 0; @@ -281,8 +248,8 @@ static const AVOption amplify_options[] = { { "factor", "set factor", OFFSET(factor), AV_OPT_TYPE_FLOAT, {.dbl=2}, 0, UINT16_MAX, .flags = VFT }, { "threshold", "set threshold", OFFSET(threshold), AV_OPT_TYPE_FLOAT, {.dbl=10}, 0, UINT16_MAX, .flags = VFT }, { "tolerance", "set tolerance", OFFSET(tolerance), AV_OPT_TYPE_FLOAT, {.dbl=0}, 0, UINT16_MAX, .flags = VFT }, - { "low", "set low limit for amplification", OFFSET(llimit), AV_OPT_TYPE_INT, {.i64=UINT16_MAX}, 0, UINT16_MAX, .flags = VFT }, - { "high", "set high limit for amplification", OFFSET(hlimit), AV_OPT_TYPE_INT, {.i64=UINT16_MAX}, 0, UINT16_MAX, .flags = VFT }, + { "low", "set low limit for amplification", OFFSET(llimit), AV_OPT_TYPE_FLOAT, {.dbl=UINT16_MAX}, 0, UINT16_MAX, .flags = VFT }, + { "high", "set high limit for amplification", OFFSET(hlimit), AV_OPT_TYPE_FLOAT, {.dbl=UINT16_MAX}, 0, UINT16_MAX, .flags = VFT }, { "planes", "set what planes to filter", OFFSET(planes), AV_OPT_TYPE_FLAGS, {.i64=7}, 0, 15, VFT }, { NULL }, }; diff --git a/libavfilter/vf_aspect.c b/libavfilter/vf_aspect.c index 2d1eaa954..0a10a5a17 100644 --- a/libavfilter/vf_aspect.c +++ b/libavfilter/vf_aspect.c @@ -23,6 +23,8 @@ * aspect ratio modification video filters */ +#include "config_components.h" + #include #include "libavutil/common.h" diff --git a/libavfilter/vf_atadenoise.c b/libavfilter/vf_atadenoise.c index 196d35465..2178c62fa 100644 --- a/libavfilter/vf_atadenoise.c +++ b/libavfilter/vf_atadenoise.c @@ -52,6 +52,7 @@ typedef struct ATADenoiseContext { int nb_planes; int planewidth[4]; int planeheight[4]; + int linesizes[4]; struct FFBufQueue q; void *data[4][SIZE]; @@ -153,7 +154,6 @@ static void fweight_row##name(const uint8_t *ssrc, uint8_t *ddst, \ unsigned ldiff, rdiff; \ float sum = srcx; \ float wsum = 1.f; \ - int l = 0, r = 0; \ int srcjx, srcix; \ \ for (int j = mid - 1, i = mid + 1; j >= 0 && i < size; j--, i++) { \ @@ -164,7 +164,6 @@ static void fweight_row##name(const uint8_t *ssrc, uint8_t *ddst, \ if (ldiff > thra || \ lsumdiff > thrb) \ break; \ - l++; \ sum += srcjx * weights[j]; \ wsum += weights[j]; \ \ @@ -175,7 +174,6 @@ static void fweight_row##name(const uint8_t *ssrc, uint8_t *ddst, \ if (rdiff > thra || \ rsumdiff > thrb) \ break; \ - r++; \ sum += srcix * weights[i]; \ wsum += weights[i]; \ } \ @@ -204,7 +202,6 @@ static void fweight_row##name##_serial(const uint8_t *ssrc, uint8_t *ddst, \ unsigned ldiff, rdiff; \ float sum = srcx; \ float wsum = 1.f; \ - int l = 0, r = 0; \ int srcjx, srcix; \ \ for (int j = mid - 1; j >= 0; j--) { \ @@ -215,7 +212,6 @@ static void fweight_row##name##_serial(const uint8_t *ssrc, uint8_t *ddst, \ if (ldiff > thra || \ lsumdiff > thrb) \ break; \ - l++; \ sum += srcjx * weights[j]; \ wsum += weights[j]; \ } \ @@ -228,7 +224,6 @@ static void fweight_row##name##_serial(const uint8_t *ssrc, uint8_t *ddst, \ if (rdiff > thra || \ rsumdiff > thrb) \ break; \ - r++; \ sum += srcix * weights[i]; \ wsum += weights[i]; \ } \ @@ -363,7 +358,7 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) if (!((1 << p) & s->planes)) { av_image_copy_plane(dst, out->linesize[p], src, in->linesize[p], - w, slice_end - slice_start); + s->linesizes[p], slice_end - slice_start); continue; } @@ -389,7 +384,7 @@ static int config_input(AVFilterLink *inlink) const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); AVFilterContext *ctx = inlink->dst; ATADenoiseContext *s = ctx->priv; - int depth; + int depth, ret; s->nb_planes = desc->nb_components; @@ -401,6 +396,9 @@ static int config_input(AVFilterLink *inlink) depth = desc->comp[0].depth; s->filter_slice = filter_slice; + if ((ret = av_image_fill_linesizes(s->linesizes, inlink->format, inlink->w)) < 0) + return ret; + for (int p = 0; p < s->nb_planes; p++) { if (depth == 8 && s->sigma[p] == INT16_MAX) s->dsp.filter_row[p] = s->algorithm == PARALLEL ? filter_row8 : filter_row8_serial; @@ -429,8 +427,9 @@ static int config_input(AVFilterLink *inlink) } } - if (ARCH_X86) - ff_atadenoise_init_x86(&s->dsp, depth, s->algorithm, s->sigma); +#if ARCH_X86 + ff_atadenoise_init_x86(&s->dsp, depth, s->algorithm, s->sigma); +#endif return 0; } diff --git a/libavfilter/vf_avgblur.c b/libavfilter/vf_avgblur.c index e44b9f63c..bd4471cb8 100644 --- a/libavfilter/vf_avgblur.c +++ b/libavfilter/vf_avgblur.c @@ -187,12 +187,21 @@ static void build_lut(AVFilterContext *ctx, int max) } } +static av_cold void uninit(AVFilterContext *ctx) +{ + AverageBlurContext *s = ctx->priv; + + av_freep(&s->buffer); +} + static int config_input(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); AverageBlurContext *s = ctx->priv; + uninit(ctx); + s->depth = desc->comp[0].depth; s->max = 1 << s->depth; s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w); @@ -316,13 +325,6 @@ static int process_command(AVFilterContext *ctx, const char *cmd, const char *ar return 0; } -static av_cold void uninit(AVFilterContext *ctx) -{ - AverageBlurContext *s = ctx->priv; - - av_freep(&s->buffer); -} - static const AVFilterPad avgblur_inputs[] = { { .name = "default", diff --git a/libavfilter/vf_avgblur_opencl.c b/libavfilter/vf_avgblur_opencl.c index 53cd1b8f4..7c0578b69 100644 --- a/libavfilter/vf_avgblur_opencl.c +++ b/libavfilter/vf_avgblur_opencl.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/common.h" #include "libavutil/imgutils.h" #include "libavutil/opt.h" diff --git a/libavfilter/vf_blend.c b/libavfilter/vf_blend.c index 2d433e439..dfe2b8b17 100644 --- a/libavfilter/vf_blend.c +++ b/libavfilter/vf_blend.c @@ -18,48 +18,21 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/imgutils.h" -#include "libavutil/intfloat.h" +#include "config_components.h" + #include "libavutil/eval.h" #include "libavutil/opt.h" #include "libavutil/pixfmt.h" #include "avfilter.h" -#include "formats.h" #include "framesync.h" #include "internal.h" +#include "vf_blend_init.h" #include "video.h" #include "blend.h" #define TOP 0 #define BOTTOM 1 -#define DEPTH 8 -#include "blend_modes.c" - -#undef DEPTH -#define DEPTH 9 -#include "blend_modes.c" - -#undef DEPTH -#define DEPTH 10 -#include "blend_modes.c" - -#undef DEPTH -#define DEPTH 12 -#include "blend_modes.c" - -#undef DEPTH -#define DEPTH 14 -#include "blend_modes.c" - -#undef DEPTH -#define DEPTH 16 -#include "blend_modes.c" - -#undef DEPTH -#define DEPTH 32 -#include "blend_modes.c" - typedef struct BlendContext { const AVClass *class; FFFrameSync fs; @@ -153,58 +126,6 @@ static const AVOption blend_options[] = { FRAMESYNC_DEFINE_CLASS(blend, BlendContext, fs); -#define COPY(src, depth) \ -static void blend_copy ## src##_##depth(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, \ - FilterParams *param, double *values, int starty) \ -{ \ - av_image_copy_plane(dst, dst_linesize, src, src ## _linesize, \ - width * depth / 8, height); \ -} - -COPY(top, 8) -COPY(bottom, 8) - -COPY(top, 16) -COPY(bottom, 16) - -COPY(top, 32) -COPY(bottom, 32) - -#undef COPY - -#define BLEND_NORMAL(name, type) \ -static void blend_normal_##name(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, \ - FilterParams *param, double *values, int starty) \ -{ \ - const type *top = (type*)_top; \ - const type *bottom = (type*)_bottom; \ - type *dst = (type*)_dst; \ - const float opacity = param->opacity; \ - \ - dst_linesize /= sizeof(type); \ - top_linesize /= sizeof(type); \ - bottom_linesize /= sizeof(type); \ - \ - for (int i = 0; i < height; i++) { \ - for (int j = 0; j < width; j++) { \ - dst[j] = top[j] * opacity + bottom[j] * (1.f - opacity); \ - } \ - dst += dst_linesize; \ - top += top_linesize; \ - bottom += bottom_linesize; \ - } \ -} - -BLEND_NORMAL(8bit, uint8_t) -BLEND_NORMAL(16bit, uint16_t) -BLEND_NORMAL(32bit, float) - #define DEFINE_BLEND_EXPR(type, name, div) \ static void blend_expr_## name(const uint8_t *_top, ptrdiff_t top_linesize, \ const uint8_t *_bottom, ptrdiff_t bottom_linesize, \ @@ -363,99 +284,6 @@ static av_cold void uninit(AVFilterContext *ctx) av_expr_free(s->params[i].e); } -#define DEFINE_INIT_BLEND_FUNC(depth, nbits) \ -static av_cold void init_blend_func_##depth##_##nbits##bit(FilterParams *param) \ -{ \ - switch (param->mode) { \ - case BLEND_ADDITION: param->blend = blend_addition_##depth##bit; break; \ - case BLEND_GRAINMERGE: param->blend = blend_grainmerge_##depth##bit; break; \ - case BLEND_AND: param->blend = blend_and_##depth##bit; break; \ - case BLEND_AVERAGE: param->blend = blend_average_##depth##bit; break; \ - case BLEND_BURN: param->blend = blend_burn_##depth##bit; break; \ - case BLEND_DARKEN: param->blend = blend_darken_##depth##bit; break; \ - case BLEND_DIFFERENCE: param->blend = blend_difference_##depth##bit; break; \ - case BLEND_GRAINEXTRACT: param->blend = blend_grainextract_##depth##bit; break; \ - case BLEND_DIVIDE: param->blend = blend_divide_##depth##bit; break; \ - case BLEND_DODGE: param->blend = blend_dodge_##depth##bit; break; \ - case BLEND_EXCLUSION: param->blend = blend_exclusion_##depth##bit; break; \ - case BLEND_EXTREMITY: param->blend = blend_extremity_##depth##bit; break; \ - case BLEND_FREEZE: param->blend = blend_freeze_##depth##bit; break; \ - case BLEND_GLOW: param->blend = blend_glow_##depth##bit; break; \ - case BLEND_HARDLIGHT: param->blend = blend_hardlight_##depth##bit; break; \ - case BLEND_HARDMIX: param->blend = blend_hardmix_##depth##bit; break; \ - case BLEND_HEAT: param->blend = blend_heat_##depth##bit; break; \ - case BLEND_LIGHTEN: param->blend = blend_lighten_##depth##bit; break; \ - case BLEND_LINEARLIGHT: param->blend = blend_linearlight_##depth##bit; break; \ - case BLEND_MULTIPLY: param->blend = blend_multiply_##depth##bit; break; \ - case BLEND_MULTIPLY128: param->blend = blend_multiply128_##depth##bit; break; \ - case BLEND_NEGATION: param->blend = blend_negation_##depth##bit; break; \ - case BLEND_NORMAL: param->blend = blend_normal_##nbits##bit; break; \ - case BLEND_OR: param->blend = blend_or_##depth##bit; break; \ - case BLEND_OVERLAY: param->blend = blend_overlay_##depth##bit; break; \ - case BLEND_PHOENIX: param->blend = blend_phoenix_##depth##bit; break; \ - case BLEND_PINLIGHT: param->blend = blend_pinlight_##depth##bit; break; \ - case BLEND_REFLECT: param->blend = blend_reflect_##depth##bit; break; \ - case BLEND_SCREEN: param->blend = blend_screen_##depth##bit; break; \ - case BLEND_SOFTLIGHT: param->blend = blend_softlight_##depth##bit; break; \ - case BLEND_SUBTRACT: param->blend = blend_subtract_##depth##bit; break; \ - case BLEND_VIVIDLIGHT: param->blend = blend_vividlight_##depth##bit; break; \ - case BLEND_XOR: param->blend = blend_xor_##depth##bit; break; \ - case BLEND_SOFTDIFFERENCE:param->blend=blend_softdifference_##depth##bit;break; \ - case BLEND_GEOMETRIC: param->blend = blend_geometric_##depth##bit; break; \ - case BLEND_HARMONIC: param->blend = blend_harmonic_##depth##bit; break; \ - case BLEND_BLEACH: param->blend = blend_bleach_##depth##bit; break; \ - case BLEND_STAIN: param->blend = blend_stain_##depth##bit; break; \ - case BLEND_INTERPOLATE: param->blend = blend_interpolate_##depth##bit; break; \ - case BLEND_HARDOVERLAY: param->blend = blend_hardoverlay_##depth##bit; break; \ - } \ -} -DEFINE_INIT_BLEND_FUNC(8, 8) -DEFINE_INIT_BLEND_FUNC(9, 16) -DEFINE_INIT_BLEND_FUNC(10, 16) -DEFINE_INIT_BLEND_FUNC(12, 16) -DEFINE_INIT_BLEND_FUNC(14, 16) -DEFINE_INIT_BLEND_FUNC(16, 16) -DEFINE_INIT_BLEND_FUNC(32, 32) - -void ff_blend_init(FilterParams *param, int depth) -{ - switch (depth) { - case 8: - init_blend_func_8_8bit(param); - break; - case 9: - init_blend_func_9_16bit(param); - break; - case 10: - init_blend_func_10_16bit(param); - break; - case 12: - init_blend_func_12_16bit(param); - break; - case 14: - init_blend_func_14_16bit(param); - break; - case 16: - init_blend_func_16_16bit(param); - break; - case 32: - init_blend_func_32_32bit(param); - break; - } - - if (param->opacity == 0 && param->mode != BLEND_NORMAL) { - param->blend = depth > 8 ? depth > 16 ? blend_copytop_32 : blend_copytop_16 : blend_copytop_8; - } else if (param->mode == BLEND_NORMAL) { - if (param->opacity == 1) - param->blend = depth > 8 ? depth > 16 ? blend_copytop_32 : blend_copytop_16 : blend_copytop_8; - else if (param->opacity == 0) - param->blend = depth > 8 ? depth > 16 ? blend_copybottom_32 : blend_copybottom_16 : blend_copybottom_8; - } - - if (ARCH_X86) - ff_blend_init_x86(param, depth); -} - static int config_params(AVFilterContext *ctx) { BlendContext *s = ctx->priv; diff --git a/libavfilter/vf_blend_init.h b/libavfilter/vf_blend_init.h new file mode 100644 index 000000000..f531338a5 --- /dev/null +++ b/libavfilter/vf_blend_init.h @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2013 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_BLEND_INIT_H +#define AVFILTER_BLEND_INIT_H + +#include "config.h" +#include "libavutil/attributes.h" +#include "libavutil/imgutils.h" +#include "blend.h" + +#define DEPTH 8 +#include "blend_modes.c" + +#undef DEPTH +#define DEPTH 9 +#include "blend_modes.c" + +#undef DEPTH +#define DEPTH 10 +#include "blend_modes.c" + +#undef DEPTH +#define DEPTH 12 +#include "blend_modes.c" + +#undef DEPTH +#define DEPTH 14 +#include "blend_modes.c" + +#undef DEPTH +#define DEPTH 16 +#include "blend_modes.c" + +#undef DEPTH +#define DEPTH 32 +#include "blend_modes.c" + +#define COPY(src, depth) \ +static void blend_copy ## src##_##depth(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, \ + FilterParams *param, double *values, int starty) \ +{ \ + av_image_copy_plane(dst, dst_linesize, src, src ## _linesize, \ + width * depth / 8, height); \ +} + +COPY(top, 8) +COPY(bottom, 8) + +COPY(top, 16) +COPY(bottom, 16) + +COPY(top, 32) +COPY(bottom, 32) + +#undef COPY + +#define BLEND_NORMAL(name, type) \ +static void blend_normal_##name(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, \ + FilterParams *param, double *values, int starty) \ +{ \ + const type *top = (type*)_top; \ + const type *bottom = (type*)_bottom; \ + type *dst = (type*)_dst; \ + const float opacity = param->opacity; \ + \ + dst_linesize /= sizeof(type); \ + top_linesize /= sizeof(type); \ + bottom_linesize /= sizeof(type); \ + \ + for (int i = 0; i < height; i++) { \ + for (int j = 0; j < width; j++) { \ + dst[j] = top[j] * opacity + bottom[j] * (1.f - opacity); \ + } \ + dst += dst_linesize; \ + top += top_linesize; \ + bottom += bottom_linesize; \ + } \ +} + +BLEND_NORMAL(8bit, uint8_t) +BLEND_NORMAL(16bit, uint16_t) +BLEND_NORMAL(32bit, float) + +#define DEFINE_INIT_BLEND_FUNC(depth, nbits) \ +static av_cold void init_blend_func_##depth##_##nbits##bit(FilterParams *param) \ +{ \ + switch (param->mode) { \ + case BLEND_ADDITION: param->blend = blend_addition_##depth##bit; break; \ + case BLEND_GRAINMERGE: param->blend = blend_grainmerge_##depth##bit; break; \ + case BLEND_AND: param->blend = blend_and_##depth##bit; break; \ + case BLEND_AVERAGE: param->blend = blend_average_##depth##bit; break; \ + case BLEND_BURN: param->blend = blend_burn_##depth##bit; break; \ + case BLEND_DARKEN: param->blend = blend_darken_##depth##bit; break; \ + case BLEND_DIFFERENCE: param->blend = blend_difference_##depth##bit; break; \ + case BLEND_GRAINEXTRACT: param->blend = blend_grainextract_##depth##bit; break; \ + case BLEND_DIVIDE: param->blend = blend_divide_##depth##bit; break; \ + case BLEND_DODGE: param->blend = blend_dodge_##depth##bit; break; \ + case BLEND_EXCLUSION: param->blend = blend_exclusion_##depth##bit; break; \ + case BLEND_EXTREMITY: param->blend = blend_extremity_##depth##bit; break; \ + case BLEND_FREEZE: param->blend = blend_freeze_##depth##bit; break; \ + case BLEND_GLOW: param->blend = blend_glow_##depth##bit; break; \ + case BLEND_HARDLIGHT: param->blend = blend_hardlight_##depth##bit; break; \ + case BLEND_HARDMIX: param->blend = blend_hardmix_##depth##bit; break; \ + case BLEND_HEAT: param->blend = blend_heat_##depth##bit; break; \ + case BLEND_LIGHTEN: param->blend = blend_lighten_##depth##bit; break; \ + case BLEND_LINEARLIGHT: param->blend = blend_linearlight_##depth##bit; break; \ + case BLEND_MULTIPLY: param->blend = blend_multiply_##depth##bit; break; \ + case BLEND_MULTIPLY128: param->blend = blend_multiply128_##depth##bit; break; \ + case BLEND_NEGATION: param->blend = blend_negation_##depth##bit; break; \ + case BLEND_NORMAL: param->blend = blend_normal_##nbits##bit; break; \ + case BLEND_OR: param->blend = blend_or_##depth##bit; break; \ + case BLEND_OVERLAY: param->blend = blend_overlay_##depth##bit; break; \ + case BLEND_PHOENIX: param->blend = blend_phoenix_##depth##bit; break; \ + case BLEND_PINLIGHT: param->blend = blend_pinlight_##depth##bit; break; \ + case BLEND_REFLECT: param->blend = blend_reflect_##depth##bit; break; \ + case BLEND_SCREEN: param->blend = blend_screen_##depth##bit; break; \ + case BLEND_SOFTLIGHT: param->blend = blend_softlight_##depth##bit; break; \ + case BLEND_SUBTRACT: param->blend = blend_subtract_##depth##bit; break; \ + case BLEND_VIVIDLIGHT: param->blend = blend_vividlight_##depth##bit; break; \ + case BLEND_XOR: param->blend = blend_xor_##depth##bit; break; \ + case BLEND_SOFTDIFFERENCE:param->blend=blend_softdifference_##depth##bit;break; \ + case BLEND_GEOMETRIC: param->blend = blend_geometric_##depth##bit; break; \ + case BLEND_HARMONIC: param->blend = blend_harmonic_##depth##bit; break; \ + case BLEND_BLEACH: param->blend = blend_bleach_##depth##bit; break; \ + case BLEND_STAIN: param->blend = blend_stain_##depth##bit; break; \ + case BLEND_INTERPOLATE: param->blend = blend_interpolate_##depth##bit; break; \ + case BLEND_HARDOVERLAY: param->blend = blend_hardoverlay_##depth##bit; break; \ + } \ +} +DEFINE_INIT_BLEND_FUNC(8, 8) +DEFINE_INIT_BLEND_FUNC(9, 16) +DEFINE_INIT_BLEND_FUNC(10, 16) +DEFINE_INIT_BLEND_FUNC(12, 16) +DEFINE_INIT_BLEND_FUNC(14, 16) +DEFINE_INIT_BLEND_FUNC(16, 16) +DEFINE_INIT_BLEND_FUNC(32, 32) + +static av_unused void ff_blend_init(FilterParams *param, int depth) +{ + switch (depth) { + case 8: + init_blend_func_8_8bit(param); + break; + case 9: + init_blend_func_9_16bit(param); + break; + case 10: + init_blend_func_10_16bit(param); + break; + case 12: + init_blend_func_12_16bit(param); + break; + case 14: + init_blend_func_14_16bit(param); + break; + case 16: + init_blend_func_16_16bit(param); + break; + case 32: + init_blend_func_32_32bit(param); + break; + } + + if (param->opacity == 0 && param->mode != BLEND_NORMAL) { + param->blend = depth > 8 ? depth > 16 ? blend_copytop_32 : blend_copytop_16 : blend_copytop_8; + } else if (param->mode == BLEND_NORMAL) { + if (param->opacity == 1) + param->blend = depth > 8 ? depth > 16 ? blend_copytop_32 : blend_copytop_16 : blend_copytop_8; + else if (param->opacity == 0) + param->blend = depth > 8 ? depth > 16 ? blend_copybottom_32 : blend_copybottom_16 : blend_copybottom_8; + } + +#if ARCH_X86 + ff_blend_init_x86(param, depth); +#endif +} + +#endif /* AVFILTER_BLEND_INIT_H */ diff --git a/libavfilter/vf_blend_vulkan.c b/libavfilter/vf_blend_vulkan.c new file mode 100644 index 000000000..fcc21cbc8 --- /dev/null +++ b/libavfilter/vf_blend_vulkan.c @@ -0,0 +1,504 @@ +/* + * copyright (c) 2021-2022 Wu Jianhua + * The blend modes are based on the blend.c. + * + * 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/random_seed.h" +#include "libavutil/opt.h" +#include "vulkan_filter.h" +#include "internal.h" +#include "framesync.h" +#include "blend.h" + +#define CGS 32 + +#define IN_TOP 0 +#define IN_BOTTOM 1 + +typedef struct FilterParamsVulkan { + const char *blend; + const char *blend_func; + double opacity; + enum BlendMode mode; +} FilterParamsVulkan; + +typedef struct BlendVulkanContext { + FFVulkanContext vkctx; + FFVkQueueFamilyCtx qf; + FFVkExecContext *exec; + FFVulkanPipeline *pl; + FFFrameSync fs; + + VkDescriptorImageInfo top_images[3]; + VkDescriptorImageInfo bottom_images[3]; + VkDescriptorImageInfo output_images[3]; + + FilterParamsVulkan params[4]; + double all_opacity; + enum BlendMode all_mode; + + int initialized; +} BlendVulkanContext; + +#define DEFINE_BLEND_MODE(MODE, EXPR) \ +static const char blend_##MODE[] = "blend_"#MODE; \ +static const char blend_##MODE##_func[] = { \ + C(0, vec4 blend_##MODE(vec4 top, vec4 bottom, float opacity) { ) \ + C(1, vec4 dst = EXPR; ) \ + C(1, return dst; ) \ + C(0, } ) \ +}; + +#define A top +#define B bottom + +#define FN(EXPR) A + ((EXPR) - A) * opacity + +DEFINE_BLEND_MODE(NORMAL, A * opacity + B * (1.0f - opacity)) +DEFINE_BLEND_MODE(MULTIPLY, FN(1.0f * A * B / 1.0f)) + +static inline void init_blend_func(FilterParamsVulkan *param) +{ +#define CASE(MODE) case BLEND_##MODE: \ + param->blend = blend_##MODE;\ + param->blend_func = blend_##MODE##_func; \ + break; + + switch (param->mode) { + CASE(NORMAL) + CASE(MULTIPLY) + default: param->blend = NULL; break; + } + +#undef CASE +} + +static int config_params(AVFilterContext *avctx) +{ + BlendVulkanContext *s = avctx->priv; + + for (int plane = 0; plane < FF_ARRAY_ELEMS(s->params); plane++) { + FilterParamsVulkan *param = &s->params[plane]; + + if (s->all_mode >= 0) + param->mode = s->all_mode; + if (s->all_opacity < 1) + param->opacity = s->all_opacity; + + init_blend_func(param); + if (!param->blend) { + av_log(avctx, AV_LOG_ERROR, + "Currently the blend mode specified is not supported yet.\n"); + return AVERROR(EINVAL); + } + } + + return 0; +} + +static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, + char *res, int res_len, int flags) +{ + int ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + return config_params(ctx); +} + +static av_cold int init_filter(AVFilterContext *avctx) +{ + int err = 0; + FFVkSampler *sampler; + FFVkSPIRVShader *shd; + BlendVulkanContext *s = avctx->priv; + FFVulkanContext *vkctx = &s->vkctx; + const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); + + ff_vk_qf_init(vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0); + + sampler = ff_vk_init_sampler(vkctx, 1, VK_FILTER_LINEAR); + if (!sampler) + return AVERROR_EXTERNAL; + + s->pl = ff_vk_create_pipeline(vkctx, &s->qf); + if (!s->pl) + return AVERROR(ENOMEM); + + { + FFVulkanDescriptorSetBinding image_descs[] = { + { + .name = "top_images", + .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .dimensions = 2, + .elems = planes, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .updater = s->top_images, + .sampler = sampler, + }, + { + .name = "bottom_images", + .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .dimensions = 2, + .elems = planes, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .updater = s->bottom_images, + .sampler = sampler, + }, + { + .name = "output_images", + .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format), + .mem_quali = "writeonly", + .dimensions = 2, + .elems = planes, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .updater = s->output_images, + }, + }; + + shd = ff_vk_init_shader(s->pl, "blend_compute", image_descs[0].stages); + if (!shd) + return AVERROR(ENOMEM); + + ff_vk_set_compute_shader_sizes(shd, (int [3]){ CGS, CGS, 1 }); + RET(ff_vk_add_descriptor_set(vkctx, s->pl, shd, image_descs, FF_ARRAY_ELEMS(image_descs), 0)); + + for (int i = 0, j = 0; i < planes; i++) { + for (j = 0; j < i; j++) + if (s->params[i].blend_func == s->params[j].blend_func) + break; + /* note: the bracket is needed, for GLSLD is a macro with multiple statements. */ + if (j == i) { + GLSLD(s->params[i].blend_func); + } + } + + GLSLC(0, void main() ); + GLSLC(0, { ); + GLSLC(1, ivec2 size; ); + GLSLC(1, const ivec2 pos = ivec2(gl_GlobalInvocationID.xy); ); + for (int i = 0; i < planes; i++) { + GLSLC(0, ); + GLSLF(1, size = imageSize(output_images[%i]); ,i); + GLSLC(1, if (IS_WITHIN(pos, size)) { ); + GLSLF(2, const vec4 top = texture(top_images[%i], pos); ,i); + GLSLF(2, const vec4 bottom = texture(bottom_images[%i], pos); ,i); + GLSLF(2, const float opacity = %f; ,s->params[i].opacity); + GLSLF(2, vec4 dst = %s(top, bottom, opacity); ,s->params[i].blend); + GLSLC(0, ); + GLSLF(2, imageStore(output_images[%i], pos, dst); ,i); + GLSLC(1, } ); + } + GLSLC(0, } ); + + RET(ff_vk_compile_shader(vkctx, shd, "main")); + RET(ff_vk_init_pipeline_layout(vkctx, s->pl)); + RET(ff_vk_init_compute_pipeline(vkctx, s->pl)); + } + + RET(ff_vk_create_exec_ctx(vkctx, &s->exec, &s->qf)); + + s->initialized = 1; + +fail: + return err; +} + +static int process_frames(AVFilterContext *avctx, AVFrame *out_frame, AVFrame *top_frame, AVFrame *bottom_frame) +{ + int err = 0; + VkCommandBuffer cmd_buf; + BlendVulkanContext *s = avctx->priv; + FFVulkanContext *vkctx = &s->vkctx; + FFVulkanFunctions *vk = &s->vkctx.vkfn; + const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); + + AVVkFrame *out = (AVVkFrame *)out_frame->data[0]; + AVVkFrame *top = (AVVkFrame *)top_frame->data[0]; + AVVkFrame *bottom = (AVVkFrame *)bottom_frame->data[0]; + + AVHWFramesContext *top_fc = (AVHWFramesContext*)top_frame->hw_frames_ctx->data; + AVHWFramesContext *bottom_fc = (AVHWFramesContext*)bottom_frame->hw_frames_ctx->data; + + const VkFormat *top_formats = av_vkfmt_from_pixfmt(top_fc->sw_format); + const VkFormat *bottom_formats = av_vkfmt_from_pixfmt(bottom_fc->sw_format); + const VkFormat *output_formats = av_vkfmt_from_pixfmt(s->vkctx.output_format); + + ff_vk_start_exec_recording(vkctx, s->exec); + cmd_buf = ff_vk_get_exec_buf(s->exec); + + for (int i = 0; i < planes; i++) { + RET(ff_vk_create_imageview(vkctx, s->exec, + &s->top_images[i].imageView, top->img[i], + top_formats[i], + ff_comp_identity_map)); + + RET(ff_vk_create_imageview(vkctx, s->exec, + &s->bottom_images[i].imageView, bottom->img[i], + bottom_formats[i], + ff_comp_identity_map)); + + RET(ff_vk_create_imageview(vkctx, s->exec, + &s->output_images[i].imageView, out->img[i], + output_formats[i], + ff_comp_identity_map)); + + s->top_images[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + s->bottom_images[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + s->output_images[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL; + } + + ff_vk_update_descriptor_set(vkctx, s->pl, 0); + + for (int i = 0; i < planes; i++) { + VkImageMemoryBarrier barriers[] = { + { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .srcAccessMask = 0, + .dstAccessMask = VK_ACCESS_SHADER_READ_BIT, + .oldLayout = top->layout[i], + .newLayout = s->top_images[i].imageLayout, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = top->img[i], + .subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .subresourceRange.levelCount = 1, + .subresourceRange.layerCount = 1, + }, + { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .srcAccessMask = 0, + .dstAccessMask = VK_ACCESS_SHADER_READ_BIT, + .oldLayout = bottom->layout[i], + .newLayout = s->bottom_images[i].imageLayout, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = bottom->img[i], + .subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .subresourceRange.levelCount = 1, + .subresourceRange.layerCount = 1, + }, + { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .srcAccessMask = 0, + .dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT, + .oldLayout = out->layout[i], + .newLayout = s->output_images[i].imageLayout, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = out->img[i], + .subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .subresourceRange.levelCount = 1, + .subresourceRange.layerCount = 1, + }, + }; + + vk->CmdPipelineBarrier(cmd_buf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, + 0, NULL, 0, NULL, FF_ARRAY_ELEMS(barriers), barriers); + + top->layout[i] = barriers[0].newLayout; + top->access[i] = barriers[0].dstAccessMask; + + bottom->layout[i] = barriers[1].newLayout; + bottom->access[i] = barriers[1].dstAccessMask; + + out->layout[i] = barriers[2].newLayout; + out->access[i] = barriers[2].dstAccessMask; + } + + ff_vk_bind_pipeline_exec(vkctx, s->exec, s->pl); + vk->CmdDispatch(cmd_buf, FFALIGN(s->vkctx.output_width, CGS) / CGS, + FFALIGN(s->vkctx.output_height, CGS) / CGS, 1); + + ff_vk_add_exec_dep(vkctx, s->exec, top_frame, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + ff_vk_add_exec_dep(vkctx, s->exec, bottom_frame, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + ff_vk_add_exec_dep(vkctx, s->exec, out_frame, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + + err = ff_vk_submit_exec_queue(vkctx, s->exec); + if (err) + return err; + + ff_vk_qf_rotate(&s->qf); + + return 0; + +fail: + ff_vk_discard_exec_deps(s->exec); + return err; +} + +static int blend_frame(FFFrameSync *fs) +{ + int err; + AVFilterContext *avctx = fs->parent; + BlendVulkanContext *s = avctx->priv; + AVFilterLink *outlink = avctx->outputs[0]; + AVFrame *top, *bottom, *out; + + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) { + err = AVERROR(ENOMEM); + goto fail; + } + + RET(ff_framesync_get_frame(fs, IN_TOP, &top, 0)); + RET(ff_framesync_get_frame(fs, IN_BOTTOM, &bottom, 0)); + + RET(av_frame_copy_props(out, top)); + + if (!s->initialized) { + AVHWFramesContext *top_fc = (AVHWFramesContext*)top->hw_frames_ctx->data; + AVHWFramesContext *bottom_fc = (AVHWFramesContext*)bottom->hw_frames_ctx->data; + if (top_fc->sw_format != bottom_fc->sw_format) { + av_log(avctx, AV_LOG_ERROR, + "Currently the sw format of the bottom video need to match the top!\n"); + return AVERROR(EINVAL); + } + RET(init_filter(avctx)); + } + + RET(process_frames(avctx, out, top, bottom)); + + return ff_filter_frame(outlink, out); + +fail: + av_frame_free(&out); + return err; +} + +static av_cold int init(AVFilterContext *avctx) +{ + BlendVulkanContext *s = avctx->priv; + + s->fs.on_event = blend_frame; + + return ff_vk_filter_init(avctx); +} + +static av_cold void uninit(AVFilterContext *avctx) +{ + BlendVulkanContext *s = avctx->priv; + + ff_framesync_uninit(&s->fs); + + ff_vk_uninit(&s->vkctx); + + s->initialized = 0; +} + +static int config_props_output(AVFilterLink *outlink) +{ + int err; + AVFilterContext *avctx = outlink->src; + BlendVulkanContext *s = avctx->priv; + AVFilterLink *toplink = avctx->inputs[IN_TOP]; + AVFilterLink *bottomlink = avctx->inputs[IN_BOTTOM]; + + if (toplink->w != bottomlink->w || toplink->h != bottomlink->h) { + av_log(avctx, AV_LOG_ERROR, "First input link %s parameters " + "(size %dx%d) do not match the corresponding " + "second input link %s parameters (size %dx%d)\n", + avctx->input_pads[IN_TOP].name, toplink->w, toplink->h, + avctx->input_pads[IN_BOTTOM].name, bottomlink->w, bottomlink->h); + return AVERROR(EINVAL); + } + + outlink->sample_aspect_ratio = toplink->sample_aspect_ratio; + outlink->frame_rate = toplink->frame_rate; + + RET(ff_vk_filter_config_output(outlink)); + + RET(ff_framesync_init_dualinput(&s->fs, avctx)); + + RET(ff_framesync_configure(&s->fs)); + outlink->time_base = s->fs.time_base; + + RET(config_params(avctx)); + +fail: + return err; +} + +static int activate(AVFilterContext *avctx) +{ + BlendVulkanContext *s = avctx->priv; + return ff_framesync_activate(&s->fs); +} + +#define OFFSET(x) offsetof(BlendVulkanContext, x) +#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) + +static const AVOption blend_vulkan_options[] = { + { "c0_mode", "set component #0 blend mode", OFFSET(params[0].mode), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, BLEND_NB - 1, FLAGS, "mode" }, + { "c1_mode", "set component #1 blend mode", OFFSET(params[1].mode), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, BLEND_NB - 1, FLAGS, "mode" }, + { "c2_mode", "set component #2 blend mode", OFFSET(params[2].mode), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, BLEND_NB - 1, FLAGS, "mode" }, + { "c3_mode", "set component #3 blend mode", OFFSET(params[3].mode), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, BLEND_NB - 1, FLAGS, "mode" }, + { "all_mode", "set blend mode for all components", OFFSET(all_mode), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, BLEND_NB - 1, FLAGS, "mode" }, + { "normal", "", 0, AV_OPT_TYPE_CONST, { .i64 = BLEND_NORMAL }, 0, 0, FLAGS, "mode" }, + { "multiply", "", 0, AV_OPT_TYPE_CONST, { .i64 = BLEND_MULTIPLY }, 0, 0, FLAGS, "mode" }, + + { "c0_opacity", "set color component #0 opacity", OFFSET(params[0].opacity), AV_OPT_TYPE_DOUBLE, { .dbl = 1 }, 0, 1, FLAGS }, + { "c1_opacity", "set color component #1 opacity", OFFSET(params[1].opacity), AV_OPT_TYPE_DOUBLE, { .dbl = 1 }, 0, 1, FLAGS }, + { "c2_opacity", "set color component #2 opacity", OFFSET(params[2].opacity), AV_OPT_TYPE_DOUBLE, { .dbl = 1 }, 0, 1, FLAGS }, + { "c3_opacity", "set color component #3 opacity", OFFSET(params[3].opacity), AV_OPT_TYPE_DOUBLE, { .dbl = 1 }, 0, 1, FLAGS }, + { "all_opacity", "set opacity for all color components", OFFSET(all_opacity), AV_OPT_TYPE_DOUBLE, { .dbl = 1 }, 0, 1, FLAGS }, + + { NULL } +}; + +AVFILTER_DEFINE_CLASS(blend_vulkan); + +static const AVFilterPad blend_vulkan_inputs[] = { + { + .name = "top", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &ff_vk_filter_config_input, + }, + { + .name = "bottom", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &ff_vk_filter_config_input, + }, +}; + + +static const AVFilterPad blend_vulkan_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &config_props_output, + } +}; + +const AVFilter ff_vf_blend_vulkan = { + .name = "blend_vulkan", + .description = NULL_IF_CONFIG_SMALL("Blend two video frames in Vulkan"), + .priv_size = sizeof(BlendVulkanContext), + .init = &init, + .uninit = &uninit, + .activate = &activate, + FILTER_INPUTS(blend_vulkan_inputs), + FILTER_OUTPUTS(blend_vulkan_outputs), + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN), + .priv_class = &blend_vulkan_class, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, + .process_command = &process_command, +}; diff --git a/libavfilter/vf_blockdetect.c b/libavfilter/vf_blockdetect.c new file mode 100644 index 000000000..27283590b --- /dev/null +++ b/libavfilter/vf_blockdetect.c @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2021 Thilo Borgmann + * + * 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 + * No-reference blockdetect filter + * + * Implementing: + * Remco Muijs and Ihor Kirenko: "A no-reference blocking artifact measure for adaptive video processing." 2005 13th European signal processing conference. IEEE, 2005. + * http://www.eurasip.org/Proceedings/Eusipco/Eusipco2005/defevent/papers/cr1042.pdf + * + * @author Thilo Borgmann + */ + +#include "libavutil/imgutils.h" +#include "libavutil/opt.h" +#include "internal.h" + +typedef struct BLKContext { + const AVClass *class; + + int hsub, vsub; + int nb_planes; + + int period_min; // minimum period to search for + int period_max; // maximum period to search for + int planes; // number of planes to filter + + double block_total; + uint64_t nb_frames; + + float *gradients; +} BLKContext; + +#define OFFSET(x) offsetof(BLKContext, x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +static const AVOption blockdetect_options[] = { + { "period_min", "Minimum period to search for", OFFSET(period_min), AV_OPT_TYPE_INT, {.i64=3}, 2, 32, FLAGS}, + { "period_max", "Maximum period to search for", OFFSET(period_max), AV_OPT_TYPE_INT, {.i64=24}, 2, 64, FLAGS}, + { "planes", "set planes to filter", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=1}, 0, 15, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(blockdetect); + +static int blockdetect_config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + BLKContext *s = ctx->priv; + const int bufsize = inlink->w * inlink->h; + const AVPixFmtDescriptor *pix_desc; + + pix_desc = av_pix_fmt_desc_get(inlink->format); + s->hsub = pix_desc->log2_chroma_w; + s->vsub = pix_desc->log2_chroma_h; + s->nb_planes = av_pix_fmt_count_planes(inlink->format); + + s->gradients = av_calloc(bufsize, sizeof(*s->gradients)); + + if (!s->gradients) + return AVERROR(ENOMEM); + + return 0; +} + +static float calculate_blockiness(BLKContext *s, int w, int h, + float *grad, int grad_linesize, + uint8_t* src, int src_linesize) +{ + float block = 0.0f; + float nonblock = 0.0f; + int block_count = 0; + int nonblock_count = 0; + float ret = 0; + + // Calculate BS in horizontal and vertical directions according to (1)(2)(3). + // Also try to find integer pixel periods (grids) even for scaled images. + // In case of fractional periods, FFMAX of current and neighbor pixels + // can help improve the correlation with MQS. + // Skip linear correction term (4)(5), as it appears only valid for their own test samples. + + // horizontal blockiness (fixed width) + for (int j = 1; j < h; j++) { + for (int i = 3; i < w - 4; i++) { + float temp = 0.0f; + grad[j * grad_linesize + i] = + abs(src[j * src_linesize + i + 0] - src[j * src_linesize + i + 1]); + temp += abs(src[j * src_linesize + i + 1] - src[j * src_linesize + i + 2]); + temp += abs(src[j * src_linesize + i + 2] - src[j * src_linesize + i + 3]); + temp += abs(src[j * src_linesize + i + 3] - src[j * src_linesize + i + 4]); + temp += abs(src[j * src_linesize + i - 0] - src[j * src_linesize + i - 1]); + temp += abs(src[j * src_linesize + i - 1] - src[j * src_linesize + i - 2]); + temp += abs(src[j * src_linesize + i - 2] - src[j * src_linesize + i - 3]); + temp = FFMAX(1, temp); + grad[j * grad_linesize + i] /= temp; + + // use first row to store acculated results + grad[i] += grad[j * grad_linesize + i]; + } + } + + // find horizontal period + for (int period = s->period_min; period < s->period_max + 1; period++) { + float temp; + block = 0; + nonblock = 0; + block_count = 0; + nonblock_count = 0; + for (int i = 3; i < w - 4; i++) { + if ((i % period) == (period - 1)) { + block += FFMAX(FFMAX(grad[i + 0], grad[i + 1]), grad[i - 1]); + block_count++; + } else { + nonblock += grad[i]; + nonblock_count++; + } + } + if (block_count && nonblock_count) { + temp = (block / block_count) / (nonblock / nonblock_count); + ret = FFMAX(ret, temp); + } + } + + // vertical blockiness (fixed height) + block_count = 0; + for (int j = 3; j < h - 4; j++) { + for (int i = 1; i < w; i++) { + float temp = 0.0f; + grad[j * grad_linesize + i] = + abs(src[(j + 0) * src_linesize + i] - src[(j + 1) * src_linesize + i]); + temp += abs(src[(j + 1) * src_linesize + i] - src[(j + 2) * src_linesize + i]); + temp += abs(src[(j + 2) * src_linesize + i] - src[(j + 3) * src_linesize + i]); + temp += abs(src[(j + 3) * src_linesize + i] - src[(j + 4) * src_linesize + i]); + temp += abs(src[(j - 0) * src_linesize + i] - src[(j - 1) * src_linesize + i]); + temp += abs(src[(j - 1) * src_linesize + i] - src[(j - 2) * src_linesize + i]); + temp += abs(src[(j - 2) * src_linesize + i] - src[(j - 3) * src_linesize + i]); + temp = FFMAX(1, temp); + grad[j * grad_linesize + i] /= temp; + + // use first column to store accumulated results + grad[j * grad_linesize] += grad[j * grad_linesize + i]; + } + } + + // find vertical period + for (int period = s->period_min; period < s->period_max + 1; period++) { + float temp; + block = 0; + nonblock = 0; + block_count = 0; + nonblock_count = 0; + for (int j = 3; j < h - 4; j++) { + if ((j % period) == (period - 1)) { + block += FFMAX(FFMAX(grad[(j + 0) * grad_linesize], + grad[(j + 1) * grad_linesize]), + grad[(j - 1) * grad_linesize]); + block_count++; + } else { + nonblock += grad[j * grad_linesize]; + nonblock_count++; + } + } + if (block_count && nonblock_count) { + temp = (block / block_count) / (nonblock / nonblock_count); + ret = FFMAX(ret, temp); + } + } + + // return highest value of horz||vert + return ret; +} + +static void set_meta(AVDictionary **metadata, const char *key, float d) +{ + char value[128]; + snprintf(value, sizeof(value), "%f", d); + av_dict_set(metadata, key, value, 0); +} + +static int blockdetect_filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + BLKContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + + const int inw = inlink->w; + const int inh = inlink->h; + + float *gradients = s->gradients; + + float block = 0.0f; + int nplanes = 0; + AVDictionary **metadata; + metadata = &in->metadata; + + for (int plane = 0; plane < s->nb_planes; plane++) { + int hsub = plane == 1 || plane == 2 ? s->hsub : 0; + int vsub = plane == 1 || plane == 2 ? s->vsub : 0; + int w = AV_CEIL_RSHIFT(inw, hsub); + int h = AV_CEIL_RSHIFT(inh, vsub); + + if (!((1 << plane) & s->planes)) + continue; + + nplanes++; + + block += calculate_blockiness(s, w, h, gradients, w, in->data[plane], in->linesize[plane]); + } + + if (nplanes) + block /= nplanes; + + s->block_total += block; + + // write stats + av_log(ctx, AV_LOG_VERBOSE, "block: %.7f\n", block); + + set_meta(metadata, "lavfi.block", block); + + s->nb_frames = inlink->frame_count_in; + + return ff_filter_frame(outlink, in); +} + +static av_cold void blockdetect_uninit(AVFilterContext *ctx) +{ + BLKContext *s = ctx->priv; + + if (s->nb_frames > 0) { + av_log(ctx, AV_LOG_INFO, "block mean: %.7f\n", + s->block_total / s->nb_frames); + } + + av_freep(&s->gradients); +} + +static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_GRAY8, + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, + AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV440P, + AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P, + AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ411P, AV_PIX_FMT_YUVJ420P, + AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P, + AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA420P, + AV_PIX_FMT_NONE +}; + +static const AVFilterPad blockdetect_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = blockdetect_config_input, + .filter_frame = blockdetect_filter_frame, + }, +}; + +static const AVFilterPad blockdetect_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, +}; + +const AVFilter ff_vf_blockdetect = { + .name = "blockdetect", + .description = NULL_IF_CONFIG_SMALL("Blockdetect filter."), + .priv_size = sizeof(BLKContext), + .uninit = blockdetect_uninit, + FILTER_PIXFMTS_ARRAY(pix_fmts), + FILTER_INPUTS(blockdetect_inputs), + FILTER_OUTPUTS(blockdetect_outputs), + .priv_class = &blockdetect_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, +}; diff --git a/libavfilter/vf_blurdetect.c b/libavfilter/vf_blurdetect.c new file mode 100644 index 000000000..0e08ba96d --- /dev/null +++ b/libavfilter/vf_blurdetect.c @@ -0,0 +1,377 @@ +/* + * Copyright (c) 2021 Thilo Borgmann + * + * 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 + * No-reference blurdetect filter + * + * Implementing: + * Marziliano, Pina, et al. "A no-reference perceptual blur metric." Proceedings. + * International conference on image processing. Vol. 3. IEEE, 2002. + * https://infoscience.epfl.ch/record/111802/files/14%20A%20no-reference%20perceptual%20blur%20metric.pdf + * + * @author Thilo Borgmann + */ + +#include "libavutil/imgutils.h" +#include "libavutil/opt.h" +#include "libavutil/qsort.h" +#include "internal.h" +#include "edge_common.h" + +static int comp(const float *a,const float *b) +{ + return FFDIFFSIGN(*a, *b); +} + +typedef struct BLRContext { + const AVClass *class; + + int hsub, vsub; + int nb_planes; + + float low, high; + uint8_t low_u8, high_u8; + int radius; // radius during local maxima detection + int block_pct; // percentage of "sharpest" blocks in the image to use for bluriness calculation + int block_width; // width for block abbreviation + int block_height; // height for block abbreviation + int planes; // number of planes to filter + + double blur_total; + uint64_t nb_frames; + + float *blks; + uint8_t *filterbuf; + uint8_t *tmpbuf; + uint16_t *gradients; + int8_t *directions; +} BLRContext; + +#define OFFSET(x) offsetof(BLRContext, x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +static const AVOption blurdetect_options[] = { + { "high", "set high threshold", OFFSET(high), AV_OPT_TYPE_FLOAT, {.dbl=30/255.}, 0, 1, FLAGS }, + { "low", "set low threshold", OFFSET(low), AV_OPT_TYPE_FLOAT, {.dbl=15/255.}, 0, 1, FLAGS }, + { "radius", "search radius for maxima detection", OFFSET(radius), AV_OPT_TYPE_INT, {.i64=50}, 1, 100, FLAGS }, + { "block_pct", "block pooling threshold when calculating blurriness", OFFSET(block_pct), AV_OPT_TYPE_INT, {.i64=80}, 1, 100, FLAGS }, + { "block_width", "block size for block-based abbreviation of blurriness", OFFSET(block_width), AV_OPT_TYPE_INT, {.i64=-1}, -1, INT_MAX, FLAGS }, + { "block_height", "block size for block-based abbreviation of blurriness", OFFSET(block_height), AV_OPT_TYPE_INT, {.i64=-1}, -1, INT_MAX, FLAGS }, + { "planes", "set planes to filter", OFFSET(planes), AV_OPT_TYPE_INT, {.i64=1}, 0, 15, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(blurdetect); + +static av_cold int blurdetect_init(AVFilterContext *ctx) +{ + BLRContext *s = ctx->priv; + + s->low_u8 = s->low * 255. + .5; + s->high_u8 = s->high * 255. + .5; + + return 0; +} + +static int blurdetect_config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + BLRContext *s = ctx->priv; + const int bufsize = inlink->w * inlink->h; + const AVPixFmtDescriptor *pix_desc; + + pix_desc = av_pix_fmt_desc_get(inlink->format); + s->hsub = pix_desc->log2_chroma_w; + s->vsub = pix_desc->log2_chroma_h; + s->nb_planes = av_pix_fmt_count_planes(inlink->format); + + if (s->block_width < 1 || s->block_height < 1) { + s->block_width = inlink->w; + s->block_height = inlink->h; + } + + s->tmpbuf = av_malloc(bufsize); + s->filterbuf = av_malloc(bufsize); + s->gradients = av_calloc(bufsize, sizeof(*s->gradients)); + s->directions = av_malloc(bufsize); + s->blks = av_calloc((inlink->w / s->block_width) * (inlink->h / s->block_height), + sizeof(*s->blks)); + + if (!s->tmpbuf || !s->filterbuf || !s->gradients || !s->directions || !s->blks) + return AVERROR(ENOMEM); + + return 0; +} + +// edge width is defined as the distance between surrounding maxima of the edge pixel +static float edge_width(BLRContext *blr, int i, int j, int8_t dir, int w, int h, + int edge, const uint8_t *src, int src_linesize) +{ + float width = 0; + int dX, dY; + int sign; + int tmp; + int p1; + int p2; + int k, x, y; + int radius = blr->radius; + + switch(dir) { + case DIRECTION_HORIZONTAL: dX = 1; dY = 0; break; + case DIRECTION_VERTICAL: dX = 0; dY = 1; break; + case DIRECTION_45UP: dX = 1; dY = -1; break; + case DIRECTION_45DOWN: dX = 1; dY = 1; break; + default: dX = 1; dY = 1; break; + } + + // determines if search in direction dX/dY is looking for a maximum or minimum + sign = src[j * src_linesize + i] > src[(j - dY) * src_linesize + i - dX] ? 1 : -1; + + // search in -(dX/dY) direction + for (k = 0; k < radius; k++) { + x = i - k*dX; + y = j - k*dY; + p1 = y * src_linesize + x; + x -= dX; + y -= dY; + p2 = y * src_linesize + x; + if (x < 0 || x >= w || y < 0 || y >= h) + return 0; + + tmp = (src[p1] - src[p2]) * sign; + + if (tmp <= 0) // local maximum found + break; + } + width += k; + + // search in +(dX/dY) direction + for (k = 0; k < radius; k++) { + x = i + k * dX; + y = j + k * dY; + p1 = y * src_linesize + x; + x += dX; + y += dY; + p2 = y * src_linesize + x; + if (x < 0 || x >= w || y < 0 || y >= h) + return 0; + + tmp = (src[p1] - src[p2]) * sign; + + if (tmp >= 0) // local maximum found + break; + } + width += k; + + // for 45 degree directions approximate edge width in pixel units: 0.7 ~= sqrt(2)/2 + if (dir == DIRECTION_45UP || dir == DIRECTION_45DOWN) + width *= 0.7; + + return width; +} + +static float calculate_blur(BLRContext *s, int w, int h, int hsub, int vsub, + int8_t* dir, int dir_linesize, + uint8_t* dst, int dst_linesize, + uint8_t* src, int src_linesize) +{ + float total_width = 0.0; + int block_count; + double block_total_width; + + int i, j; + int blkcnt = 0; + + float *blks = s->blks; + float block_pool_threshold = s->block_pct / 100.0; + + int block_width = AV_CEIL_RSHIFT(s->block_width, hsub); + int block_height = AV_CEIL_RSHIFT(s->block_height, vsub); + int brows = h / block_height; + int bcols = w / block_width; + + for (int blkj = 0; blkj < brows; blkj++) { + for (int blki = 0; blki < bcols; blki++) { + block_total_width = 0.0; + block_count = 0; + for (int inj = 0; inj < block_height; inj++) { + for (int ini = 0; ini < block_width; ini++) { + i = blki * block_width + ini; + j = blkj * block_height + inj; + + if (dst[j * dst_linesize + i] > 0) { + float width = edge_width(s, i, j, dir[j*dir_linesize+i], + w, h, dst[j*dst_linesize+i], + src, src_linesize); + if (width > 0.001) { // throw away zeros + block_count++; + block_total_width += width; + } + } + } + } + // if not enough edge pixels in a block, consider it smooth + if (block_total_width >= 2 && block_count) { + blks[blkcnt] = block_total_width / block_count; + blkcnt++; + } + } + } + + // simple block pooling by sorting and keeping the sharper blocks + AV_QSORT(blks, blkcnt, float, comp); + blkcnt = ceil(blkcnt * block_pool_threshold); + for (int i = 0; i < blkcnt; i++) { + total_width += blks[i]; + } + + return total_width / blkcnt; +} + +static void set_meta(AVDictionary **metadata, const char *key, float d) +{ + char value[128]; + snprintf(value, sizeof(value), "%f", d); + av_dict_set(metadata, key, value, 0); +} + +static int blurdetect_filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + BLRContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + + const int inw = inlink->w; + const int inh = inlink->h; + + uint8_t *tmpbuf = s->tmpbuf; + uint8_t *filterbuf = s->filterbuf; + uint16_t *gradients = s->gradients; + int8_t *directions = s->directions; + + float blur = 0.0f; + int nplanes = 0; + AVDictionary **metadata; + metadata = &in->metadata; + + for (int plane = 0; plane < s->nb_planes; plane++) { + int hsub = plane == 1 || plane == 2 ? s->hsub : 0; + int vsub = plane == 1 || plane == 2 ? s->vsub : 0; + int w = AV_CEIL_RSHIFT(inw, hsub); + int h = AV_CEIL_RSHIFT(inh, vsub); + + if (!((1 << plane) & s->planes)) + continue; + + nplanes++; + + // gaussian filter to reduce noise + ff_gaussian_blur(w, h, + filterbuf, w, + in->data[plane], in->linesize[plane]); + + // compute the 16-bits gradients and directions for the next step + ff_sobel(w, h, gradients, w, directions, w, filterbuf, w); + + // non_maximum_suppression() will actually keep & clip what's necessary and + // ignore the rest, so we need a clean output buffer + memset(tmpbuf, 0, inw * inh); + ff_non_maximum_suppression(w, h, tmpbuf, w, directions, w, gradients, w); + + + // keep high values, or low values surrounded by high values + ff_double_threshold(s->low_u8, s->high_u8, w, h, + tmpbuf, w, tmpbuf, w); + + blur += calculate_blur(s, w, h, hsub, vsub, directions, w, + tmpbuf, w, filterbuf, w); + } + + if (nplanes) + blur /= nplanes; + + s->blur_total += blur; + + // write stats + av_log(ctx, AV_LOG_VERBOSE, "blur: %.7f\n", blur); + + set_meta(metadata, "lavfi.blur", blur); + + s->nb_frames = inlink->frame_count_in; + + return ff_filter_frame(outlink, in); +} + +static av_cold void blurdetect_uninit(AVFilterContext *ctx) +{ + BLRContext *s = ctx->priv; + + if (s->nb_frames > 0) { + av_log(ctx, AV_LOG_INFO, "blur mean: %.7f\n", + s->blur_total / s->nb_frames); + } + + av_freep(&s->tmpbuf); + av_freep(&s->filterbuf); + av_freep(&s->gradients); + av_freep(&s->directions); + av_freep(&s->blks); +} + +static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_GRAY8, + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, + AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV440P, + AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P, + AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ411P, AV_PIX_FMT_YUVJ420P, + AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P, + AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA420P, + AV_PIX_FMT_NONE +}; + +static const AVFilterPad blurdetect_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = blurdetect_config_input, + .filter_frame = blurdetect_filter_frame, + }, +}; + +static const AVFilterPad blurdetect_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, +}; + +const AVFilter ff_vf_blurdetect = { + .name = "blurdetect", + .description = NULL_IF_CONFIG_SMALL("Blurdetect filter."), + .priv_size = sizeof(BLRContext), + .init = blurdetect_init, + .uninit = blurdetect_uninit, + FILTER_PIXFMTS_ARRAY(pix_fmts), + FILTER_INPUTS(blurdetect_inputs), + FILTER_OUTPUTS(blurdetect_outputs), + .priv_class = &blurdetect_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, +}; diff --git a/libavfilter/vf_bwdif.c b/libavfilter/vf_bwdif.c index c3b7abc1b..65c617ebb 100644 --- a/libavfilter/vf_bwdif.c +++ b/libavfilter/vf_bwdif.c @@ -350,8 +350,9 @@ static int config_props(AVFilterLink *link) s->filter_edge = filter_edge; } - if (ARCH_X86) - ff_bwdif_init_x86(s); +#if ARCH_X86 + ff_bwdif_init_x86(s); +#endif return 0; } diff --git a/libavfilter/vf_cas.c b/libavfilter/vf_cas.c index 305aec9bd..c45529cef 100644 --- a/libavfilter/vf_cas.c +++ b/libavfilter/vf_cas.c @@ -65,7 +65,7 @@ static int cas_slice8(AVFilterContext *avctx, void *arg, int jobnr, int nb_jobs) const uint8_t *src = in->data[p]; if (!((1 << p) & s->planes)) { - av_image_copy_plane(dst, linesize, src + slice_start * linesize, in_linesize, + av_image_copy_plane(dst, linesize, src + slice_start * in_linesize, in_linesize, w, slice_end - slice_start); continue; } @@ -128,12 +128,12 @@ static int cas_slice16(AVFilterContext *avctx, void *arg, int jobnr, int nb_jobs const int w1 = w - 1; const int h = s->planeheight[p]; const int h1 = h - 1; - uint16_t *dst = (uint16_t *)out->data[p] + slice_start * linesize; + uint16_t *dst = ((uint16_t *)out->data[p]) + slice_start * linesize; const uint16_t *src = (const uint16_t *)in->data[p]; if (!((1 << p) & s->planes)) { - av_image_copy_plane((uint8_t *)dst, linesize, (uint8_t *)(src + slice_start * linesize), - in_linesize, w * 2, slice_end - slice_start); + av_image_copy_plane((uint8_t *)dst, linesize * 2, (uint8_t *)(src + slice_start * in_linesize), + in_linesize * 2, w * 2, slice_end - slice_start); continue; } diff --git a/libavfilter/vf_chromakey_cuda.c b/libavfilter/vf_chromakey_cuda.c new file mode 100644 index 000000000..113484279 --- /dev/null +++ b/libavfilter/vf_chromakey_cuda.c @@ -0,0 +1,498 @@ +/* + * Copyright (c) 2022 Mohamed Khaled + * + * 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 "libavutil/avstring.h" +#include "libavutil/common.h" +#include "libavutil/hwcontext.h" +#include "libavutil/hwcontext_cuda_internal.h" +#include "libavutil/cuda_check.h" +#include "libavutil/internal.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" + +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "video.h" +#include "cuda/load_helper.h" + +static const enum AVPixelFormat supported_formats[] = { + AV_PIX_FMT_YUV420P, + AV_PIX_FMT_NV12, + AV_PIX_FMT_YUVA420P +}; + +#define DIV_UP(a, b) (((a) + (b)-1) / (b)) +#define BLOCKX 32 +#define BLOCKY 16 +#define CHECK_CU(x) FF_CUDA_CHECK_DL(ctx, s->hwctx->internal->cuda_dl, x) + +typedef struct ChromakeyCUDAContext { + const AVClass *class; + + AVCUDADeviceContext *hwctx; + + enum AVPixelFormat in_fmt, out_fmt; + const AVPixFmtDescriptor *in_desc, *out_desc; + int in_planes, out_planes; + int in_plane_depths[4]; + int in_plane_channels[4]; + + uint8_t chromakey_rgba[4]; + uint16_t chromakey_uv[2]; + int is_yuv; + float similarity; + float blend; + + AVBufferRef *frames_ctx; + AVFrame *frame; + AVFrame *tmp_frame; + + CUcontext cu_ctx; + CUmodule cu_module; + CUfunction cu_func; + CUfunction cu_func_uv; + CUstream cu_stream; +} ChromakeyCUDAContext; + +static av_cold int cudachromakey_init(AVFilterContext *ctx) +{ + ChromakeyCUDAContext *s = ctx->priv; + + s->frame = av_frame_alloc(); + if (!s->frame) + return AVERROR(ENOMEM); + + s->tmp_frame = av_frame_alloc(); + if (!s->tmp_frame) + return AVERROR(ENOMEM); + + return 0; +} + +static av_cold void cudachromakey_uninit(AVFilterContext *ctx) +{ + ChromakeyCUDAContext *s = ctx->priv; + + if (s->hwctx && s->cu_module) + { + CudaFunctions *cu = s->hwctx->internal->cuda_dl; + CUcontext context; + + CHECK_CU(cu->cuCtxPushCurrent(s->hwctx->cuda_ctx)); + CHECK_CU(cu->cuModuleUnload(s->cu_module)); + s->cu_module = NULL; + CHECK_CU(cu->cuCtxPopCurrent(&context)); + } + + av_frame_free(&s->frame); + av_buffer_unref(&s->frames_ctx); + av_frame_free(&s->tmp_frame); +} + +static av_cold int init_hwframe_ctx(ChromakeyCUDAContext *s, AVBufferRef *device_ctx, int width, int height) +{ + AVBufferRef *out_ref = NULL; + AVHWFramesContext *out_ctx; + int ret; + + out_ref = av_hwframe_ctx_alloc(device_ctx); + if (!out_ref) + return AVERROR(ENOMEM); + out_ctx = (AVHWFramesContext *)out_ref->data; + + out_ctx->format = AV_PIX_FMT_CUDA; + out_ctx->sw_format = s->out_fmt; + out_ctx->width = width; + out_ctx->height = height; + + ret = av_hwframe_ctx_init(out_ref); + if (ret < 0) + goto fail; + + av_frame_unref(s->frame); + ret = av_hwframe_get_buffer(out_ref, s->frame, 0); + if (ret < 0) + goto fail; + + av_buffer_unref(&s->frames_ctx); + s->frames_ctx = out_ref; + + return 0; +fail: + av_buffer_unref(&out_ref); + return ret; +} + +static int format_is_supported(enum AVPixelFormat fmt) +{ + int i; + + for (i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++) + if (supported_formats[i] == fmt) + return 1; + return 0; +} + +static av_cold void set_format_info(AVFilterContext *ctx, enum AVPixelFormat in_format, enum AVPixelFormat out_format) +{ + ChromakeyCUDAContext *s = ctx->priv; + int i, p, d; + + s->in_fmt = in_format; + s->out_fmt = out_format; + + s->in_desc = av_pix_fmt_desc_get(s->in_fmt); + s->out_desc = av_pix_fmt_desc_get(s->out_fmt); + s->in_planes = av_pix_fmt_count_planes(s->in_fmt); + s->out_planes = av_pix_fmt_count_planes(s->out_fmt); + + // find maximum step of each component of each plane + // For our subset of formats, this should accurately tell us how many channels CUDA needs + // i.e. 1 for Y plane, 2 for UV plane of NV12, 4 for single plane of RGB0 formats + + for (i = 0; i < s->in_desc->nb_components; i++) + { + d = (s->in_desc->comp[i].depth + 7) / 8; + p = s->in_desc->comp[i].plane; + s->in_plane_channels[p] = FFMAX(s->in_plane_channels[p], s->in_desc->comp[i].step / d); + + s->in_plane_depths[p] = s->in_desc->comp[i].depth; + } +} + +static av_cold int init_processing_chain(AVFilterContext *ctx, int width, int height) +{ + ChromakeyCUDAContext *s = ctx->priv; + AVHWFramesContext *in_frames_ctx; + int ret; + + /* check that we have a hw context */ + if (!ctx->inputs[0]->hw_frames_ctx) + { + av_log(ctx, AV_LOG_ERROR, "No hw context provided on input\n"); + return AVERROR(EINVAL); + } + in_frames_ctx = (AVHWFramesContext *)ctx->inputs[0]->hw_frames_ctx->data; + + if (!format_is_supported(in_frames_ctx->sw_format)) + { + av_log(ctx, AV_LOG_ERROR, "Unsupported format: %s\n", av_get_pix_fmt_name(in_frames_ctx->sw_format)); + return AVERROR(ENOSYS); + } + + set_format_info(ctx, in_frames_ctx->sw_format, AV_PIX_FMT_YUVA420P); + + ret = init_hwframe_ctx(s, in_frames_ctx->device_ref, width, height); + if (ret < 0) + return ret; + + ctx->outputs[0]->hw_frames_ctx = av_buffer_ref(s->frames_ctx); + if (!ctx->outputs[0]->hw_frames_ctx) + return AVERROR(ENOMEM); + + return 0; +} + +static av_cold int cudachromakey_load_functions(AVFilterContext *ctx) +{ + ChromakeyCUDAContext *s = ctx->priv; + CUcontext context, cuda_ctx = s->hwctx->cuda_ctx; + CudaFunctions *cu = s->hwctx->internal->cuda_dl; + int ret; + + extern const unsigned char ff_vf_chromakey_cuda_ptx_data[]; + extern const unsigned int ff_vf_chromakey_cuda_ptx_len; + + ret = CHECK_CU(cu->cuCtxPushCurrent(cuda_ctx)); + if (ret < 0) + return ret; + + ret = ff_cuda_load_module(ctx, s->hwctx, &s->cu_module, + ff_vf_chromakey_cuda_ptx_data, ff_vf_chromakey_cuda_ptx_len); + if (ret < 0) + goto fail; + + ret = CHECK_CU(cu->cuModuleGetFunction(&s->cu_func, s->cu_module, "Process_uchar")); + if (ret < 0) + { + av_log(ctx, AV_LOG_FATAL, "Failed loading Process_uchar\n"); + goto fail; + } + + ret = CHECK_CU(cu->cuModuleGetFunction(&s->cu_func_uv, s->cu_module, "Process_uchar2")); + if (ret < 0) + { + av_log(ctx, AV_LOG_FATAL, "Failed loading Process_uchar2\n"); + goto fail; + } + +fail: + CHECK_CU(cu->cuCtxPopCurrent(&context)); + + return ret; +} + +#define FIXNUM(x) lrint((x) * (1 << 10)) +#define RGB_TO_U(rgb) (((-FIXNUM(0.16874) * rgb[0] - FIXNUM(0.33126) * rgb[1] + FIXNUM(0.50000) * rgb[2] + (1 << 9) - 1) >> 10) + 128) +#define RGB_TO_V(rgb) (((FIXNUM(0.50000) * rgb[0] - FIXNUM(0.41869) * rgb[1] - FIXNUM(0.08131) * rgb[2] + (1 << 9) - 1) >> 10) + 128) + +static av_cold int cudachromakey_config_props(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + AVFilterLink *inlink = outlink->src->inputs[0]; + ChromakeyCUDAContext *s = ctx->priv; + AVHWFramesContext *frames_ctx = (AVHWFramesContext *)inlink->hw_frames_ctx->data; + AVCUDADeviceContext *device_hwctx = frames_ctx->device_ctx->hwctx; + int ret; + + s->hwctx = device_hwctx; + s->cu_stream = s->hwctx->stream; + + if (s->is_yuv) { + s->chromakey_uv[0] = s->chromakey_rgba[1]; + s->chromakey_uv[1] = s->chromakey_rgba[2]; + } else { + s->chromakey_uv[0] = RGB_TO_U(s->chromakey_rgba); + s->chromakey_uv[1] = RGB_TO_V(s->chromakey_rgba); + } + + ret = init_processing_chain(ctx, inlink->w, inlink->h); + if (ret < 0) + return ret; + + outlink->sample_aspect_ratio = inlink->sample_aspect_ratio; + + ret = cudachromakey_load_functions(ctx); + if (ret < 0) + return ret; + + return 0; +} + +static int call_cuda_kernel(AVFilterContext *ctx, CUfunction func, + CUtexObject src_tex[3], AVFrame *out_frame, + int width, int height, int pitch, + int width_uv, int height_uv, int pitch_uv, + float u_key, float v_key, float similarity, + float blend) +{ + ChromakeyCUDAContext *s = ctx->priv; + CudaFunctions *cu = s->hwctx->internal->cuda_dl; + + CUdeviceptr dst_devptr[4] = { + (CUdeviceptr)out_frame->data[0], (CUdeviceptr)out_frame->data[1], + (CUdeviceptr)out_frame->data[2], (CUdeviceptr)out_frame->data[3] + }; + + void *args_uchar[] = { + &src_tex[0], &src_tex[1], &src_tex[2], + &dst_devptr[0], &dst_devptr[1], &dst_devptr[2], &dst_devptr[3], + &width, &height, &pitch, + &width_uv, &height_uv, &pitch_uv, + &u_key, &v_key, &similarity, &blend + }; + + return CHECK_CU(cu->cuLaunchKernel(func, + DIV_UP(width, BLOCKX), DIV_UP(height, BLOCKY), 1, + BLOCKX, BLOCKY, 1, 0, s->cu_stream, args_uchar, NULL)); +} + +static int cudachromakey_process_internal(AVFilterContext *ctx, + AVFrame *out, AVFrame *in) +{ + ChromakeyCUDAContext *s = ctx->priv; + CudaFunctions *cu = s->hwctx->internal->cuda_dl; + CUcontext context, cuda_ctx = s->hwctx->cuda_ctx; + int i, ret; + + CUtexObject tex[3] = {0, 0, 0}; + + ret = CHECK_CU(cu->cuCtxPushCurrent(cuda_ctx)); + if (ret < 0) + return ret; + + for (i = 0; i < s->in_planes; i++) + { + CUDA_TEXTURE_DESC tex_desc = { + .filterMode = CU_TR_FILTER_MODE_LINEAR, + .flags = 0, // CU_TRSF_READ_AS_INTEGER to get raw ints instead of normalized floats from tex2D + }; + + CUDA_RESOURCE_DESC res_desc = { + .resType = CU_RESOURCE_TYPE_PITCH2D, + .res.pitch2D.format = CU_AD_FORMAT_UNSIGNED_INT8, + .res.pitch2D.numChannels = s->in_plane_channels[i], + .res.pitch2D.pitchInBytes = in->linesize[i], + .res.pitch2D.devPtr = (CUdeviceptr)in->data[i], + }; + + if (i == 1 || i == 2) + { + res_desc.res.pitch2D.width = AV_CEIL_RSHIFT(in->width, s->in_desc->log2_chroma_w); + res_desc.res.pitch2D.height = AV_CEIL_RSHIFT(in->height, s->in_desc->log2_chroma_h); + } + else + { + res_desc.res.pitch2D.width = in->width; + res_desc.res.pitch2D.height = in->height; + } + + ret = CHECK_CU(cu->cuTexObjectCreate(&tex[i], &res_desc, &tex_desc, NULL)); + if (ret < 0) + goto exit; + } + + ret = call_cuda_kernel(ctx, (s->in_plane_channels[1] > 1) ? s->cu_func_uv : s->cu_func, + tex, out, + out->width, out->height, out->linesize[0], + AV_CEIL_RSHIFT(out->width, s->out_desc->log2_chroma_w), + AV_CEIL_RSHIFT(out->height, s->out_desc->log2_chroma_h), + out->linesize[1], + s->chromakey_uv[0], s->chromakey_uv[1], + s->similarity, s->blend); + if (ret < 0) + goto exit; + +exit: + for (i = 0; i < s->in_planes; i++) + if (tex[i]) + CHECK_CU(cu->cuTexObjectDestroy(tex[i])); + + CHECK_CU(cu->cuCtxPopCurrent(&context)); + + return ret; +} + +static int cudachromakey_process(AVFilterContext *ctx, AVFrame *out, AVFrame *in) +{ + ChromakeyCUDAContext *s = ctx->priv; + AVFrame *src = in; + int ret; + + ret = cudachromakey_process_internal(ctx, s->frame, src); + if (ret < 0) + return ret; + + src = s->frame; + ret = av_hwframe_get_buffer(src->hw_frames_ctx, s->tmp_frame, 0); + if (ret < 0) + return ret; + + av_frame_move_ref(out, s->frame); + av_frame_move_ref(s->frame, s->tmp_frame); + + ret = av_frame_copy_props(out, in); + if (ret < 0) + return ret; + + return 0; +} + +static int cudachromakey_filter_frame(AVFilterLink *link, AVFrame *in) +{ + AVFilterContext *ctx = link->dst; + ChromakeyCUDAContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + CudaFunctions *cu = s->hwctx->internal->cuda_dl; + + AVFrame *out = NULL; + CUcontext context; + int ret = 0; + + out = av_frame_alloc(); + if (!out) + { + ret = AVERROR(ENOMEM); + goto fail; + } + + ret = CHECK_CU(cu->cuCtxPushCurrent(s->hwctx->cuda_ctx)); + if (ret < 0) + goto fail; + + ret = cudachromakey_process(ctx, out, in); + + CHECK_CU(cu->cuCtxPopCurrent(&context)); + if (ret < 0) + goto fail; + + av_frame_free(&in); + return ff_filter_frame(outlink, out); +fail: + av_frame_free(&in); + av_frame_free(&out); + return ret; +} + +#define OFFSET(x) offsetof(ChromakeyCUDAContext, x) +#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) +static const AVOption options[] = { + {"color", "set the chromakey key color", OFFSET(chromakey_rgba), AV_OPT_TYPE_COLOR, {.str = "black"}, 0, 0, FLAGS}, + {"similarity", "set the chromakey similarity value", OFFSET(similarity), AV_OPT_TYPE_FLOAT, {.dbl = 0.01}, 0.01, 1.0, FLAGS}, + {"blend", "set the chromakey key blend value", OFFSET(blend), AV_OPT_TYPE_FLOAT, {.dbl = 0.0}, 0.0, 1.0, FLAGS}, + {"yuv", "color parameter is in yuv instead of rgb", OFFSET(is_yuv), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS}, + {NULL}, +}; + +static const AVClass cudachromakey_class = { + .class_name = "cudachromakey", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const AVFilterPad cudachromakey_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = cudachromakey_filter_frame, + }, +}; + +static const AVFilterPad cudachromakey_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = cudachromakey_config_props, + }, +}; + +const AVFilter ff_vf_chromakey_cuda = { + .name = "chromakey_cuda", + .description = NULL_IF_CONFIG_SMALL("GPU accelerated chromakey filter"), + + .init = cudachromakey_init, + .uninit = cudachromakey_uninit, + + .priv_size = sizeof(ChromakeyCUDAContext), + .priv_class = &cudachromakey_class, + + FILTER_INPUTS(cudachromakey_inputs), + FILTER_OUTPUTS(cudachromakey_outputs), + + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_CUDA), + + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; diff --git a/libavfilter/vf_chromakey_cuda.cu b/libavfilter/vf_chromakey_cuda.cu new file mode 100644 index 000000000..25a10786a --- /dev/null +++ b/libavfilter/vf_chromakey_cuda.cu @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2022 Mohamed Khaled + * + * 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 "cuda/vector_helpers.cuh" + +extern "C" +{ + +/** + * @brief function contains the main logic of chroma keying, and changes the alpahc channel with the suitable value + * + * @param src_tex texture U or texture UV , decided based on the passed is_uchar2 flag + * @param src_tex_V texture V , used only if is_uchar2 flag is false + * @param dst_A alpha channel destination + * @param width_uv width of uv channels + * @param height_uv height of uv channels + * @param width width of alpha channel + * @param height height of alpha channel + * @param pitch pitch of alpha channel + * @param x current x coordinate of pixel + * @param y current y coordinate of pixel + * @param chromakey_uv uv values for chroma keying + * @param similarity similarity of keying + * @param blend blend of keying + */ +__device__ static inline void change_alpha_channel( + cudaTextureObject_t src_tex, cudaTextureObject_t src_tex_V, uchar *dst_A, + int width_uv, int height_uv, + int width, int height, int pitch, + int x, int y, + float2 chromakey_uv, float similarity, float blend) +{ + int window_size = 3; + int start_r = x - window_size / 2; + int start_c = y - window_size / 2; + int resize_ratio = width / width_uv; + int counter = 0; + float diff = 0.0f; + float du, dv; + uchar alpha_value; + + // loop over the eight neighbourhood of the current pixel(x,y) + for (uchar i = 0; i < window_size; i++) + { + for (uchar j = 0; j < window_size; j++) + { + float u_value, v_value; + int r = start_r + i; + int c = start_c + j; + + if (r < 0 || r >= width_uv || c < 0 || c >= height_uv) + continue; + + if (!src_tex_V) { + float2 temp_uv = tex2D(src_tex, r, c); + u_value = temp_uv.x; + v_value = temp_uv.y; + } else { + u_value = tex2D(src_tex, r, c); + v_value = tex2D(src_tex_V, r, c); + } + + du = (u_value * 255.0f) - chromakey_uv.x; + dv = (v_value * 255.0f) - chromakey_uv.y; + diff += sqrtf((du * du + dv * dv) / (255.0f * 255.0f * 2.f)); + + counter++; + } + } + + if (counter > 0) + diff = diff / counter; + else + diff /= 9.0f; + + if (blend>0.0001f) + alpha_value = __saturatef((diff - similarity) / blend) * 255; + else + alpha_value = (diff < similarity) ? 0 : 255; + + //write the value in the alpha channel with regarding the ratio of (alpha_size : uv_size) + for (uchar k = 0; k < resize_ratio; k++) + { + for (uchar l = 0; l < resize_ratio; l++) + { + int x_resize = x * resize_ratio + k; + int y_resize = y * resize_ratio + l; + int a_channel_resize = y_resize * pitch + x_resize; + + if (y_resize >= height || x_resize >= width) + continue; + + dst_A[a_channel_resize] = alpha_value; + } + } +} + +__global__ void Process_uchar( + cudaTextureObject_t src_tex_Y, cudaTextureObject_t src_tex_U, cudaTextureObject_t src_tex_V, + uchar *dst_Y, uchar *dst_U, uchar *dst_V, uchar *dst_A, + int width, int height, int pitch, + int width_uv, int height_uv, int pitch_uv, + float u_key, float v_key, float similarity, float blend) +{ + int x = blockIdx.x * blockDim.x + threadIdx.x; + int y = blockIdx.y * blockDim.y + threadIdx.y; + + if (y >= height || x >= width) + return; + + dst_Y[y * pitch + x] = tex2D(src_tex_Y, x, y)*255; + + if (y >= height_uv || x >= width_uv) + return; + + int uv_index = y * pitch_uv + x; + dst_U[uv_index] = tex2D(src_tex_U, x, y) * 255; + dst_V[uv_index] = tex2D(src_tex_V, x, y) * 255; + + change_alpha_channel(src_tex_U, src_tex_V, dst_A, + width_uv, height_uv, + width, height, pitch, + x, y, + make_float2(u_key, v_key), similarity, blend); +} + +__global__ void Process_uchar2( + cudaTextureObject_t src_tex_Y, cudaTextureObject_t src_tex_UV, cudaTextureObject_t unused1, + uchar *dst_Y, uchar *dst_U, uchar *dst_V, uchar *dst_A, + int width, int height, int pitch, + int width_uv, int height_uv,int pitch_uv, + float u_key, float v_key, float similarity, float blend) +{ + int x = blockIdx.x * blockDim.x + threadIdx.x; // x coordinate of current pixel + int y = blockIdx.y * blockDim.y + threadIdx.y; // y coordinate of current pixel + + if (y >= height || x >= width) + return; + + dst_Y[y * pitch + x] = tex2D(src_tex_Y, x, y) * 255; + + if (y >= height_uv || x >= width_uv) + return; + + int uv_index = y * pitch_uv + x; + float2 uv_temp = tex2D(src_tex_UV, x, y); + dst_U[uv_index] = uv_temp.x * 255; + dst_V[uv_index] = uv_temp.y * 255; + + change_alpha_channel(src_tex_UV, (cudaTextureObject_t)nullptr, + dst_A, width_uv, height_uv, + width, height, pitch, + x, y, + make_float2(u_key, v_key), similarity, blend); +} + +} diff --git a/libavfilter/vf_chromanr.c b/libavfilter/vf_chromanr.c index 63ec8ff07..385a26c8a 100644 --- a/libavfilter/vf_chromanr.c +++ b/libavfilter/vf_chromanr.c @@ -161,8 +161,8 @@ static int distance ## _slice##name(AVFilterContext *ctx, void *arg, } \ } \ \ - out_uptr[x] = su / cn; \ - out_vptr[x] = sv / cn; \ + out_uptr[x] = (su + (cn >> 1)) / cn; \ + out_vptr[x] = (sv + (cn >> 1)) / cn; \ } \ \ out_uptr += out_ulinesize / sizeof(type); \ diff --git a/libavfilter/vf_chromashift.c b/libavfilter/vf_chromashift.c index 0d197b134..2ddfa6172 100644 --- a/libavfilter/vf_chromashift.c +++ b/libavfilter/vf_chromashift.c @@ -49,7 +49,7 @@ typedef struct ChromaShiftContext { AVFrame *in; int is_rgbashift; - int (*filter_slice)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); + int (*filter_slice[2])(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); } ChromaShiftContext; #define DEFINE_SMEAR(depth, type, div) \ @@ -326,7 +326,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) in->data[0], in->linesize[0], s->linesize[0], s->height[0]); } - ff_filter_execute(ctx, s->filter_slice, out, NULL, + ff_filter_execute(ctx, s->filter_slice[s->edge], out, NULL, FFMIN3(s->height[1], s->height[2], ff_filter_get_nb_threads(ctx))); @@ -345,15 +345,11 @@ static int config_input(AVFilterLink *inlink) s->depth = desc->comp[0].depth; s->nb_planes = desc->nb_components; if (s->is_rgbashift) { - if (s->edge) - s->filter_slice = s->depth > 8 ? rgbawrap_slice16 : rgbawrap_slice8; - else - s->filter_slice = s->depth > 8 ? rgbasmear_slice16 : rgbasmear_slice8; + s->filter_slice[1] = s->depth > 8 ? rgbawrap_slice16 : rgbawrap_slice8; + s->filter_slice[0] = s->depth > 8 ? rgbasmear_slice16 : rgbasmear_slice8; } else { - if (s->edge) - s->filter_slice = s->depth > 8 ? wrap_slice16 : wrap_slice8; - else - s->filter_slice = s->depth > 8 ? smear_slice16 : smear_slice8; + s->filter_slice[1] = s->depth > 8 ? wrap_slice16 : wrap_slice8; + s->filter_slice[0] = s->depth > 8 ? smear_slice16 : smear_slice8; } s->height[1] = s->height[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h); s->height[0] = s->height[3] = inlink->h; @@ -363,18 +359,6 @@ static int config_input(AVFilterLink *inlink) return av_image_fill_linesizes(s->linesize, inlink->format, inlink->w); } -static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, - char *res, int res_len, int flags) -{ - int ret; - - ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); - if (ret < 0) - return ret; - - return config_input(ctx->inputs[0]); -} - #define OFFSET(x) offsetof(ChromaShiftContext, x) #define VFR AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_RUNTIME_PARAM @@ -431,7 +415,7 @@ const AVFilter ff_vf_chromashift = { FILTER_INPUTS(inputs), FILTER_PIXFMTS_ARRAY(yuv_pix_fmts), .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, - .process_command = process_command, + .process_command = ff_filter_process_command, }; static const enum AVPixelFormat rgb_pix_fmts[] = { @@ -468,5 +452,5 @@ const AVFilter ff_vf_rgbashift = { FILTER_INPUTS(inputs), FILTER_PIXFMTS_ARRAY(rgb_pix_fmts), .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, - .process_command = process_command, + .process_command = ff_filter_process_command, }; diff --git a/libavfilter/vf_ciescope.c b/libavfilter/vf_ciescope.c index fcb28d2b5..a0caaa76e 100644 --- a/libavfilter/vf_ciescope.c +++ b/libavfilter/vf_ciescope.c @@ -61,13 +61,16 @@ typedef struct CiescopeContext { float intensity; float contrast; int background; + int fill; - double log2lin[65536]; - double igamma; - double i[3][3]; - double m[3][3]; + float log2lin[65536]; + float igamma; + float i[3][3]; + float m[3][3]; AVFrame *f; - void (*filter)(AVFilterContext *ctx, AVFrame *in, double *cx, double *cy, int x, int y); + void (*filter)(AVFilterContext *ctx, const uint8_t *ptr, + ptrdiff_t linesize, + float *cx, float *cy, int x, int y); } CiescopeContext; #define OFFSET(x) offsetof(CiescopeContext, x) @@ -116,6 +119,7 @@ static const AVOption ciescope_options[] = { { "corrgamma", NULL, OFFSET(correct_gamma), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS }, { "showwhite", NULL, OFFSET(show_white), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, { "gamma", NULL, OFFSET(igamma), AV_OPT_TYPE_DOUBLE, {.dbl=2.6}, 0.1, 6, FLAGS }, + { "fill", "fill with CIE colors", OFFSET(fill), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS }, { NULL } }; @@ -163,11 +167,11 @@ static int config_output(AVFilterLink *outlink) point. */ struct ColorSystem { - double xRed, yRed, /* Red primary illuminant */ - xGreen, yGreen, /* Green primary illuminant */ - xBlue, yBlue, /* Blue primary illuminant */ - xWhite, yWhite, /* White point */ - gamma; /* gamma of nonlinear correction */ + float xRed, yRed, /* Red primary illuminant */ + xGreen, yGreen, /* Green primary illuminant */ + xBlue, yBlue, /* Blue primary illuminant */ + xWhite, yWhite, /* White point */ + gamma; /* gamma of nonlinear correction */ }; static float const spectral_chromaticity[][3] = { @@ -712,23 +716,23 @@ static struct ColorSystem CustomSystem = { */ static void -uv_to_xy(double const u, - double const v, - double * const xc, - double * const yc) +uv_to_xy(float const u, + float const v, + float *const xc, + float *const yc) { /* Given 1970 coordinates u, v, determine 1931 chromaticities x, y */ - *xc = 3*u / (2*u - 8*v + 4); - *yc = 2*v / (2*u - 8*v + 4); + *xc = 3.f*u / (2.f*u - 8.f*v + 4.f); + *yc = 2.f*v / (2.f*u - 8.f*v + 4.f); } static void -upvp_to_xy(double const up, - double const vp, - double * const xc, - double * const yc) +upvp_to_xy(float const up, + float const vp, + float * const xc, + float * const yc) { /* Given 1976 coordinates u', v', determine 1931 chromaticities x, y @@ -738,48 +742,50 @@ upvp_to_xy(double const up, } static void -xy_to_upvp(double xc, - double yc, - double * const up, - double * const vp) +xy_to_upvp(float xc, + float yc, + float * const up, + float * const vp) { /* Given 1931 chromaticities x, y, determine 1976 coordinates u', v' */ - *up = 4*xc / (- 2*xc + 12*yc + 3); - *vp = 9*yc / (- 2*xc + 12*yc + 3); + const float scale = 1.f / (-2.f*xc + 12.f*yc + 3.f); + *up = 4.f*xc * scale; + *vp = 9.f*yc * scale; } static void -xy_to_uv(double xc, - double yc, - double * const u, - double * const v) +xy_to_uv(float xc, + float yc, + float * const u, + float * const v) { /* Given 1931 chromaticities x, y, determine 1960 coordinates u, v */ - *u = 4*xc / (- 2*xc + 12*yc + 3); - *v = 6*yc / (- 2*xc + 12*yc + 3); + const float scale = 1.f / (-2.f*xc + 12.f*yc + 3.f); + *u = 4.f*xc * scale; + *v = 6.f*yc * scale; } static void -xyz_to_rgb(const double m[3][3], - double xc, double yc, double zc, - double * const r, double * const g, double * const b) +xyz_to_rgb(const float m[3][3], + float xc, float yc, float zc, + float * const r, float * const g, float * const b) { *r = m[0][0]*xc + m[0][1]*yc + m[0][2]*zc; *g = m[1][0]*xc + m[1][1]*yc + m[1][2]*zc; *b = m[2][0]*xc + m[2][1]*yc + m[2][2]*zc; } -static void invert_matrix3x3(double in[3][3], double out[3][3]) +static void invert_matrix3x3(float in[3][3], float out[3][3]) { - double m00 = in[0][0], m01 = in[0][1], m02 = in[0][2], + float m00 = in[0][0], m01 = in[0][1], m02 = in[0][2], m10 = in[1][0], m11 = in[1][1], m12 = in[1][2], m20 = in[2][0], m21 = in[2][1], m22 = in[2][2]; int i, j; - double det; + float det; out[0][0] = (m11 * m22 - m21 * m12); out[0][1] = -(m01 * m22 - m21 * m02); @@ -800,9 +806,9 @@ static void invert_matrix3x3(double in[3][3], double out[3][3]) } } -static void get_rgb2xyz_matrix(struct ColorSystem system, double m[3][3]) +static void get_rgb2xyz_matrix(struct ColorSystem system, float m[3][3]) { - double S[3], X[4], Z[4]; + float S[3], X[4], Z[4]; int i; X[0] = system.xRed / system.yRed; @@ -834,31 +840,32 @@ static void get_rgb2xyz_matrix(struct ColorSystem system, double m[3][3]) } static void -rgb_to_xy(double rc, - double gc, - double bc, - double * const x, - double * const y, - double * const z, - const double m[3][3]) +rgb_to_xy(float rc, + float gc, + float bc, + float * const x, + float * const y, + float * const z, + const float m[3][3]) { - double sum; + float scale; *x = m[0][0] * rc + m[0][1] * gc + m[0][2] * bc; *y = m[1][0] * rc + m[1][1] * gc + m[1][2] * bc; *z = m[2][0] * rc + m[2][1] * gc + m[2][2] * bc; - sum = *x + *y + *z; - if (sum == 0) - sum = 1; - *x = *x / sum; - *y = *y / sum; + scale = *x + *y + *z; + if (scale == 0.f) + scale = 1.f; + scale = 1.f / scale; + *x = *x * scale; + *y = *y * scale; } static int -constrain_rgb(double * const r, - double * const g, - double * const b) +constrain_rgb(float * const r, + float * const g, + float * const b) { /*---------------------------------------------------------------------------- If the requested RGB shade contains a negative weight for one of @@ -866,7 +873,7 @@ constrain_rgb(double * const r, the given triple of primaries. Desaturate it by adding white, equal quantities of R, G, and B, enough to make RGB all positive. -----------------------------------------------------------------------------*/ - double w; + float w; /* Amount of white needed is w = - min(0, *r, *g, *b) */ w = (0 < *r) ? 0 : *r; @@ -886,7 +893,7 @@ constrain_rgb(double * const r, static void gamma_correct(const struct ColorSystem * const cs, - double * const c) + float * const c) { /*---------------------------------------------------------------------------- Transform linear RGB values to nonlinear RGB values. @@ -899,8 +906,8 @@ gamma_correct(const struct ColorSystem * const cs, http://www.inforamp.net/~poynton/ColorFAQ.html http://www.inforamp.net/~poynton/GammaFAQ.html -----------------------------------------------------------------------------*/ - double gamma; - double cc; + float gamma; + float cc; gamma = cs->gamma; @@ -922,9 +929,9 @@ gamma_correct(const struct ColorSystem * const cs, static void gamma_correct_rgb(const struct ColorSystem * const cs, - double * const r, - double * const g, - double * const b) + float * const r, + float * const g, + float * const b) { gamma_correct(cs, r); gamma_correct(cs, g); @@ -938,24 +945,24 @@ gamma_correct_rgb(const struct ColorSystem * const cs, #define Sz(x) (((x) * (int)FFMIN(w, h)) / 512) static void -monochrome_color_location(double waveLength, int w, int h, +monochrome_color_location(float waveLength, int w, int h, int cie, int *xP, int *yP) { const int ix = waveLength - 360; - const double pX = spectral_chromaticity[ix][0]; - const double pY = spectral_chromaticity[ix][1]; - const double pZ = spectral_chromaticity[ix][2]; - const double px = pX / (pX + pY + pZ); - const double py = pY / (pX + pY + pZ); + const float pX = spectral_chromaticity[ix][0]; + const float pY = spectral_chromaticity[ix][1]; + const float pZ = spectral_chromaticity[ix][2]; + const float px = pX / (pX + pY + pZ); + const float py = pY / (pX + pY + pZ); if (cie == LUV) { - double up, vp; + float up, vp; xy_to_upvp(px, py, &up, &vp); *xP = up * (w - 1); *yP = (h - 1) - vp * (h - 1); } else if (cie == UCS) { - double u, v; + float u, v; xy_to_uv(px, py, &u, &v); *xP = u * (w - 1); @@ -1099,7 +1106,7 @@ fill_in_tongue(uint16_t* const pixels, int const h, uint16_t const maxval, const struct ColorSystem * const cs, - double const m[3][3], + float const m[3][3], int const cie, int const correct_gamma, float const contrast) @@ -1122,24 +1129,24 @@ fill_in_tongue(uint16_t* const pixels, int x; for (x = leftEdge; x <= rightEdge; ++x) { - double cx, cy, cz, jr, jg, jb, jmax; + float cx, cy, cz, jr, jg, jb, jmax; int r, g, b, mx = maxval; if (cie == LUV) { - double up, vp; - up = ((double) x) / (w - 1); - vp = 1.0 - ((double) y) / (h - 1); + float up, vp; + up = ((float) x) / (w - 1); + vp = 1.0 - ((float) y) / (h - 1); upvp_to_xy(up, vp, &cx, &cy); cz = 1.0 - (cx + cy); } else if (cie == UCS) { - double u, v; - u = ((double) x) / (w - 1); - v = 1.0 - ((double) y) / (h - 1); + float u, v; + u = ((float) x) / (w - 1); + v = 1.0 - ((float) y) / (h - 1); uv_to_xy(u, v, &cx, &cy); cz = 1.0 - (cx + cy); } else if (cie == XYY) { - cx = ((double) x) / (w - 1); - cy = 1.0 - ((double) y) / (h - 1); + cx = ((float) x) / (w - 1); + cy = 1.0 - ((float) y) / (h - 1); cz = 1.0 - (cx + cy); } else { av_assert0(0); @@ -1189,12 +1196,12 @@ plot_white_point(uint16_t* pixels, int wx, wy; if (cie == LUV) { - double wup, wvp; + float wup, wvp; xy_to_upvp(cs->xWhite, cs->yWhite, &wup, &wvp); wx = (w - 1) * wup; wy = (h - 1) - ((int) ((h - 1) * wvp)); } else if (cie == UCS) { - double wu, wv; + float wu, wv; xy_to_uv(cs->xWhite, cs->yWhite, &wu, &wv); wx = (w - 1) * wu; wy = (h - 1) - ((int) ((h - 1) * wv)); @@ -1234,68 +1241,83 @@ static int draw_background(AVFilterContext *ctx) tongue_outline(pixels, s->f->linesize[0] / 2, w, h, 65535, s->cie); - fill_in_tongue(pixels, s->f->linesize[0] / 2, w, h, 65535, cs, (const double (*)[3])s->i, s->cie, - s->correct_gamma, s->contrast); + if (s->fill) + fill_in_tongue(pixels, s->f->linesize[0] / 2, w, h, 65535, cs, (const float (*)[3])s->i, s->cie, + s->correct_gamma, s->contrast); return 0; } -static void filter_rgb48(AVFilterContext *ctx, AVFrame *in, double *cx, double *cy, int x, int y) +static void filter_rgb48(AVFilterContext *ctx, const uint8_t *ptr, + ptrdiff_t linesize, + float *cx, float *cy, int x, int y) { CiescopeContext *s = ctx->priv; - const uint16_t* src = (const uint16_t*)(in->data[0] + in->linesize[0] * y + x * 6); - double r = src[0] / 65535.; - double g = src[1] / 65535.; - double b = src[2] / 65535.; - double cz; + const float scale = 1. / 65535.; + const uint16_t *src = (const uint16_t*)(ptr + linesize * y + x * 6); + float r = src[0] * scale; + float g = src[1] * scale; + float b = src[2] * scale; + float cz; - rgb_to_xy(r, g, b, cx, cy, &cz, (const double (*)[3])s->m); + rgb_to_xy(r, g, b, cx, cy, &cz, (const float (*)[3])s->m); } -static void filter_rgba64(AVFilterContext *ctx, AVFrame *in, double *cx, double *cy, int x, int y) +static void filter_rgba64(AVFilterContext *ctx, const uint8_t *ptr, + ptrdiff_t linesize, + float *cx, float *cy, int x, int y) { CiescopeContext *s = ctx->priv; - const uint16_t* src = (const uint16_t*)(in->data[0] + in->linesize[0] * y + x * 8); - double r = src[0] / 65535.; - double g = src[1] / 65535.; - double b = src[2] / 65535.; - double cz; + const float scale = 1. / 65535.; + const uint16_t *src = (const uint16_t*)(ptr + linesize * y + x * 8); + float r = src[0] * scale; + float g = src[1] * scale; + float b = src[2] * scale; + float cz; - rgb_to_xy(r, g, b, cx, cy, &cz, (const double (*)[3])s->m); + rgb_to_xy(r, g, b, cx, cy, &cz, (const float (*)[3])s->m); } -static void filter_rgb24(AVFilterContext *ctx, AVFrame *in, double *cx, double *cy, int x, int y) +static void filter_rgb24(AVFilterContext *ctx, const uint8_t *ptr, + ptrdiff_t linesize, + float *cx, float *cy, int x, int y) { CiescopeContext *s = ctx->priv; - const uint8_t* src = in->data[0] + in->linesize[0] * y + x * 3; - double r = src[0] / 255.; - double g = src[1] / 255.; - double b = src[2] / 255.; - double cz; + const float scale = 1. / 255.; + const uint8_t *src = ptr + linesize * y + x * 3; + float r = src[0] * scale; + float g = src[1] * scale; + float b = src[2] * scale; + float cz; - rgb_to_xy(r, g, b, cx, cy, &cz, (const double (*)[3])s->m); + rgb_to_xy(r, g, b, cx, cy, &cz, (const float (*)[3])s->m); } -static void filter_rgba(AVFilterContext *ctx, AVFrame *in, double *cx, double *cy, int x, int y) +static void filter_rgba(AVFilterContext *ctx, const uint8_t *ptr, + ptrdiff_t linesize, + float *cx, float *cy, int x, int y) { CiescopeContext *s = ctx->priv; - const uint8_t* src = in->data[0] + in->linesize[0] * y + x * 4; - double r = src[0] / 255.; - double g = src[1] / 255.; - double b = src[2] / 255.; - double cz; + const float scale = 1. / 255.; + const uint8_t *src = ptr + linesize * y + x * 4; + float r = src[0] * scale; + float g = src[1] * scale; + float b = src[2] * scale; + float cz; - rgb_to_xy(r, g, b, cx, cy, &cz, (const double (*)[3])s->m); + rgb_to_xy(r, g, b, cx, cy, &cz, (const float (*)[3])s->m); } -static void filter_xyz(AVFilterContext *ctx, AVFrame *in, double *cx, double *cy, int x, int y) +static void filter_xyz(AVFilterContext *ctx, const uint8_t *ptr, + ptrdiff_t linesize, + float *cx, float *cy, int x, int y) { CiescopeContext *s = ctx->priv; - const uint16_t* src = (uint16_t *)(in->data[0] + in->linesize[0] * y + x * 6); - double lx = s->log2lin[src[0]]; - double ly = s->log2lin[src[1]]; - double lz = s->log2lin[src[2]]; - double sum = lx + ly + lz; + const uint16_t* src = (uint16_t *)(ptr + linesize * y + x * 6); + float lx = s->log2lin[src[0]]; + float ly = s->log2lin[src[1]]; + float lz = s->log2lin[src[2]]; + float sum = lx + ly + lz; if (sum == 0) sum = 1; @@ -1315,7 +1337,7 @@ static void plot_gamuts(uint16_t *pixels, int linesize, int w, int h, if (!((1 << i) & gamuts)) continue; if (cie == LUV) { - double wup, wvp; + float wup, wvp; xy_to_upvp(cs->xRed, cs->yRed, &wup, &wvp); rx = (w - 1) * wup; ry = (h - 1) - ((int) ((h - 1) * wvp)); @@ -1326,7 +1348,7 @@ static void plot_gamuts(uint16_t *pixels, int linesize, int w, int h, bx = (w - 1) * wup; by = (h - 1) - ((int) ((h - 1) * wvp)); } else if (cie == UCS) { - double wu, wv; + float wu, wv; xy_to_uv(cs->xRed, cs->yRed, &wu, &wv); rx = (w - 1) * wu; ry = (h - 1) - ((int) ((h - 1) * wv)); @@ -1384,37 +1406,48 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) } for (y = 0; y < in->height; y++) { - for (x = 0; x < in->width; x++) { - double cx, cy; - uint16_t *dst; - int wx, wy; + const uint8_t *src = in->data[0]; + const ptrdiff_t src_linesize = in->linesize[0]; + uint16_t *dst = (uint16_t *)out->data[0]; + const ptrdiff_t linesize = out->linesize[0] / 2; + const int w_1 = w - 1; + const int h_1 = h - 1; - s->filter(ctx, in, &cx, &cy, x, y); + for (x = 0; x < in->width; x++) { + float cx, cy; + int wx, wy, pos; + int r, g, b; + + s->filter(ctx, src, src_linesize, &cx, &cy, x, y); if (s->cie == LUV) { - double up, vp; + float up, vp; xy_to_upvp(cx, cy, &up, &vp); cx = up; cy = vp; } else if (s->cie == UCS) { - double u, v; + float u, v; xy_to_uv(cx, cy, &u, &v); cx = u; cy = v; } - wx = (w - 1) * cx; - wy = (h - 1) - ((h - 1) * cy); + wx = w_1 * cx; + wy = h_1 - h_1 * cy; if (wx < 0 || wx >= w || wy < 0 || wy >= h) continue; - dst = (uint16_t *)(out->data[0] + wy * out->linesize[0] + wx * 8 + 0); - dst[0] = FFMIN(dst[0] + i, 65535); - dst[1] = FFMIN(dst[1] + i, 65535); - dst[2] = FFMIN(dst[2] + i, 65535); - dst[3] = 65535; + pos = wy * linesize + wx * 4; + r = dst[pos + 0] + i; + g = dst[pos + 1] + i; + b = dst[pos + 2] + i; + + dst[pos + 0] = FFMIN(r, 65535); + dst[pos + 1] = FFMIN(g, 65535); + dst[pos + 2] = FFMIN(b, 65535); + dst[pos + 3] = 65535; } } diff --git a/libavfilter/vf_codecview.c b/libavfilter/vf_codecview.c index aac038ede..cddb3e536 100644 --- a/libavfilter/vf_codecview.c +++ b/libavfilter/vf_codecview.c @@ -227,7 +227,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) AVFilterLink *outlink = ctx->outputs[0]; if (s->qp) { - int qstride, qp_type, ret; + enum AVVideoEncParamsType qp_type; + int qstride, ret; int8_t *qp_table; ret = ff_qp_table_extract(frame, &qp_table, &qstride, NULL, &qp_type); diff --git a/libavfilter/vf_colorchannelmixer.c b/libavfilter/vf_colorchannelmixer.c index dfbc082b3..88dd7451d 100644 --- a/libavfilter/vf_colorchannelmixer.c +++ b/libavfilter/vf_colorchannelmixer.c @@ -56,6 +56,31 @@ typedef struct ColorChannelMixerContext { int (*filter_slice[2])(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); } ColorChannelMixerContext; +static float lerpf(float v0, float v1, float f) +{ + return v0 + (v1 - v0) * f; +} + +static void preservel(float *r, float *g, float *b, float lin, float lout, float max) +{ + if (lout <= 0.f) + lout = 1.f / (max * 2.f); + *r *= lin / lout; + *g *= lin / lout; + *b *= lin / lout; +} + +#define DEPTH 8 +#include "colorchannelmixer_template.c" + +#undef DEPTH +#define DEPTH 16 +#include "colorchannelmixer_template.c" + +#undef DEPTH +#define DEPTH 32 +#include "colorchannelmixer_template.c" + #define OFFSET(x) offsetof(ColorChannelMixerContext, x) #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM @@ -104,487 +129,178 @@ static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP16, + AV_PIX_FMT_GBRPF32, AV_PIX_FMT_GBRAPF32, AV_PIX_FMT_NONE }; -static float lerpf(float v0, float v1, float f) -{ - return v0 + (v1 - v0) * f; -} - -static void preservel(float *r, float *g, float *b, float lin, float lout, float max) -{ - if (lout <= 0.f) - lout = 1.f / (max * 2.f); - *r *= lin / lout; - *g *= lin / lout; - *b *= lin / lout; -} - -static av_always_inline int filter_slice_rgba_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs, - int have_alpha, int pc) -{ - ColorChannelMixerContext *s = ctx->priv; - ThreadData *td = arg; - AVFrame *in = td->in; - AVFrame *out = td->out; - const float pa = s->preserve_amount; - const int slice_start = (out->height * jobnr) / nb_jobs; - const int slice_end = (out->height * (jobnr+1)) / nb_jobs; - const uint8_t *srcg = in->data[0] + slice_start * in->linesize[0]; - const uint8_t *srcb = in->data[1] + slice_start * in->linesize[1]; - const uint8_t *srcr = in->data[2] + slice_start * in->linesize[2]; - const uint8_t *srca = in->data[3] + slice_start * in->linesize[3]; - uint8_t *dstg = out->data[0] + slice_start * out->linesize[0]; - uint8_t *dstb = out->data[1] + slice_start * out->linesize[1]; - uint8_t *dstr = out->data[2] + slice_start * out->linesize[2]; - uint8_t *dsta = out->data[3] + slice_start * out->linesize[3]; - int i, j; - - for (i = slice_start; i < slice_end; i++) { - for (j = 0; j < out->width; j++) { - const uint8_t rin = srcr[j]; - const uint8_t gin = srcg[j]; - const uint8_t bin = srcb[j]; - const uint8_t ain = have_alpha ? srca[j] : 0; - int rout, gout, bout; - - rout = s->lut[R][R][rin] + - s->lut[R][G][gin] + - s->lut[R][B][bin] + - (have_alpha == 1 ? s->lut[R][A][ain] : 0); - gout = s->lut[G][R][rin] + - s->lut[G][G][gin] + - s->lut[G][B][bin] + - (have_alpha == 1 ? s->lut[G][A][ain] : 0); - bout = s->lut[B][R][rin] + - s->lut[B][G][gin] + - s->lut[B][B][bin] + - (have_alpha == 1 ? s->lut[B][A][ain] : 0); - - if (pc) { - float frout = av_clipf(rout, 0.f, 255.f); - float fgout = av_clipf(gout, 0.f, 255.f); - float fbout = av_clipf(bout, 0.f, 255.f); - float lin, lout; - - preserve_color(s->preserve_color, rin, gin, bin, - rout, gout, bout, 255.f, &lin, &lout); - preservel(&frout, &fgout, &fbout, lin, lout, 255.f); - - rout = lrintf(lerpf(rout, frout, pa)); - gout = lrintf(lerpf(gout, fgout, pa)); - bout = lrintf(lerpf(bout, fbout, pa)); - } - - dstr[j] = av_clip_uint8(rout); - dstg[j] = av_clip_uint8(gout); - dstb[j] = av_clip_uint8(bout); - - if (have_alpha == 1) { - dsta[j] = av_clip_uint8(s->lut[A][R][rin] + - s->lut[A][G][gin] + - s->lut[A][B][bin] + - s->lut[A][A][ain]); - } - } - - srcg += in->linesize[0]; - srcb += in->linesize[1]; - srcr += in->linesize[2]; - srca += in->linesize[3]; - dstg += out->linesize[0]; - dstb += out->linesize[1]; - dstr += out->linesize[2]; - dsta += out->linesize[3]; - } - - return 0; -} - -static av_always_inline int filter_slice_rgba16_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs, - int have_alpha, int depth, int pc) -{ - ColorChannelMixerContext *s = ctx->priv; - ThreadData *td = arg; - AVFrame *in = td->in; - AVFrame *out = td->out; - const float pa = s->preserve_amount; - const float max = (1 << depth) - 1; - const int slice_start = (out->height * jobnr) / nb_jobs; - const int slice_end = (out->height * (jobnr+1)) / nb_jobs; - const uint16_t *srcg = (const uint16_t *)(in->data[0] + slice_start * in->linesize[0]); - const uint16_t *srcb = (const uint16_t *)(in->data[1] + slice_start * in->linesize[1]); - const uint16_t *srcr = (const uint16_t *)(in->data[2] + slice_start * in->linesize[2]); - const uint16_t *srca = (const uint16_t *)(in->data[3] + slice_start * in->linesize[3]); - uint16_t *dstg = (uint16_t *)(out->data[0] + slice_start * out->linesize[0]); - uint16_t *dstb = (uint16_t *)(out->data[1] + slice_start * out->linesize[1]); - uint16_t *dstr = (uint16_t *)(out->data[2] + slice_start * out->linesize[2]); - uint16_t *dsta = (uint16_t *)(out->data[3] + slice_start * out->linesize[3]); - int i, j; - - for (i = slice_start; i < slice_end; i++) { - for (j = 0; j < out->width; j++) { - const uint16_t rin = srcr[j]; - const uint16_t gin = srcg[j]; - const uint16_t bin = srcb[j]; - const uint16_t ain = have_alpha ? srca[j] : 0; - int rout, gout, bout; - - rout = s->lut[R][R][rin] + - s->lut[R][G][gin] + - s->lut[R][B][bin] + - (have_alpha == 1 ? s->lut[R][A][ain] : 0); - gout = s->lut[G][R][rin] + - s->lut[G][G][gin] + - s->lut[G][B][bin] + - (have_alpha == 1 ? s->lut[G][A][ain] : 0); - bout = s->lut[B][R][rin] + - s->lut[B][G][gin] + - s->lut[B][B][bin] + - (have_alpha == 1 ? s->lut[B][A][ain] : 0); - - if (pc) { - float frout = av_clipf(rout, 0.f, max); - float fgout = av_clipf(gout, 0.f, max); - float fbout = av_clipf(bout, 0.f, max); - float lin, lout; - - preserve_color(s->preserve_color, rin, gin, bin, - rout, gout, bout, max, &lin, &lout); - preservel(&frout, &fgout, &fbout, lin, lout, max); - - rout = lrintf(lerpf(rout, frout, pa)); - gout = lrintf(lerpf(gout, fgout, pa)); - bout = lrintf(lerpf(bout, fbout, pa)); - } - - dstr[j] = av_clip_uintp2(rout, depth); - dstg[j] = av_clip_uintp2(gout, depth); - dstb[j] = av_clip_uintp2(bout, depth); - - if (have_alpha == 1) { - dsta[j] = av_clip_uintp2(s->lut[A][R][rin] + - s->lut[A][G][gin] + - s->lut[A][B][bin] + - s->lut[A][A][ain], depth); - } - } - - srcg += in->linesize[0] / 2; - srcb += in->linesize[1] / 2; - srcr += in->linesize[2] / 2; - srca += in->linesize[3] / 2; - dstg += out->linesize[0] / 2; - dstb += out->linesize[1] / 2; - dstr += out->linesize[2] / 2; - dsta += out->linesize[3] / 2; - } - - return 0; -} - static int filter_slice_gbrp(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba_planar(ctx, arg, jobnr, nb_jobs, 0, 0); + return filter_slice_rgba_planar_8(ctx, arg, jobnr, nb_jobs, 0, 8, 0); } static int filter_slice_gbrap(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba_planar(ctx, arg, jobnr, nb_jobs, 1, 0); + return filter_slice_rgba_planar_8(ctx, arg, jobnr, nb_jobs, 1, 8, 0); } static int filter_slice_gbrp_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba_planar(ctx, arg, jobnr, nb_jobs, 0, 1); + return filter_slice_rgba_planar_8(ctx, arg, jobnr, nb_jobs, 0, 8, 1); } static int filter_slice_gbrap_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba_planar(ctx, arg, jobnr, nb_jobs, 1, 1); + return filter_slice_rgba_planar_8(ctx, arg, jobnr, nb_jobs, 1, 8, 1); } static int filter_slice_gbrp9(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 9, 0); + return filter_slice_rgba_planar_16(ctx, arg, jobnr, nb_jobs, 0, 9, 0); } static int filter_slice_gbrp10(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 10, 0); + return filter_slice_rgba_planar_16(ctx, arg, jobnr, nb_jobs, 0, 10, 0); } static int filter_slice_gbrap10(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 1, 10, 0); + return filter_slice_rgba_planar_16(ctx, arg, jobnr, nb_jobs, 1, 10, 0); } static int filter_slice_gbrp12(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 12, 0); + return filter_slice_rgba_planar_16(ctx, arg, jobnr, nb_jobs, 0, 12, 0); } static int filter_slice_gbrap12(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 1, 12, 0); + return filter_slice_rgba_planar_16(ctx, arg, jobnr, nb_jobs, 1, 12, 0); } static int filter_slice_gbrp14(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 14, 0); + return filter_slice_rgba_planar_16(ctx, arg, jobnr, nb_jobs, 0, 14, 0); } static int filter_slice_gbrp16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 16, 0); + return filter_slice_rgba_planar_16(ctx, arg, jobnr, nb_jobs, 0, 16, 0); } static int filter_slice_gbrap16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 1, 16, 0); + return filter_slice_rgba_planar_16(ctx, arg, jobnr, nb_jobs, 1, 16, 0); } static int filter_slice_gbrp9_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 9, 1); + return filter_slice_rgba_planar_16(ctx, arg, jobnr, nb_jobs, 0, 9, 1); } static int filter_slice_gbrp10_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 10, 1); + return filter_slice_rgba_planar_16(ctx, arg, jobnr, nb_jobs, 0, 10, 1); } static int filter_slice_gbrap10_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 1, 10, 1); + return filter_slice_rgba_planar_16(ctx, arg, jobnr, nb_jobs, 1, 10, 1); } static int filter_slice_gbrp12_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 12, 1); + return filter_slice_rgba_planar_16(ctx, arg, jobnr, nb_jobs, 0, 12, 1); } static int filter_slice_gbrap12_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 1, 12, 1); + return filter_slice_rgba_planar_16(ctx, arg, jobnr, nb_jobs, 1, 12, 1); } static int filter_slice_gbrp14_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 14, 1); + return filter_slice_rgba_planar_16(ctx, arg, jobnr, nb_jobs, 0, 14, 1); } static int filter_slice_gbrp16_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 0, 16, 1); + return filter_slice_rgba_planar_16(ctx, arg, jobnr, nb_jobs, 0, 16, 1); } static int filter_slice_gbrap16_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba16_planar(ctx, arg, jobnr, nb_jobs, 1, 16, 1); -} - -static av_always_inline int filter_slice_rgba_packed(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs, - int have_alpha, int step, int pc) -{ - ColorChannelMixerContext *s = ctx->priv; - ThreadData *td = arg; - AVFrame *in = td->in; - AVFrame *out = td->out; - const float pa = s->preserve_amount; - const int slice_start = (out->height * jobnr) / nb_jobs; - const int slice_end = (out->height * (jobnr+1)) / nb_jobs; - const uint8_t roffset = s->rgba_map[R]; - const uint8_t goffset = s->rgba_map[G]; - const uint8_t boffset = s->rgba_map[B]; - const uint8_t aoffset = s->rgba_map[A]; - const uint8_t *srcrow = in->data[0] + slice_start * in->linesize[0]; - uint8_t *dstrow = out->data[0] + slice_start * out->linesize[0]; - int i, j; - - for (i = slice_start; i < slice_end; i++) { - const uint8_t *src = srcrow; - uint8_t *dst = dstrow; - - for (j = 0; j < out->width * step; j += step) { - const uint8_t rin = src[j + roffset]; - const uint8_t gin = src[j + goffset]; - const uint8_t bin = src[j + boffset]; - const uint8_t ain = src[j + aoffset]; - int rout, gout, bout; - - rout = s->lut[R][R][rin] + - s->lut[R][G][gin] + - s->lut[R][B][bin] + - (have_alpha == 1 ? s->lut[R][A][ain] : 0); - gout = s->lut[G][R][rin] + - s->lut[G][G][gin] + - s->lut[G][B][bin] + - (have_alpha == 1 ? s->lut[G][A][ain] : 0); - bout = s->lut[B][R][rin] + - s->lut[B][G][gin] + - s->lut[B][B][bin] + - (have_alpha == 1 ? s->lut[B][A][ain] : 0); - - if (pc) { - float frout = av_clipf(rout, 0.f, 255.f); - float fgout = av_clipf(gout, 0.f, 255.f); - float fbout = av_clipf(bout, 0.f, 255.f); - float lin, lout; - - preserve_color(s->preserve_color, rin, gin, bin, - rout, gout, bout, 255.f, &lin, &lout); - preservel(&frout, &fgout, &fbout, lin, lout, 255.f); - - rout = lrintf(lerpf(rout, frout, pa)); - gout = lrintf(lerpf(gout, fgout, pa)); - bout = lrintf(lerpf(bout, fbout, pa)); - } - - dst[j + roffset] = av_clip_uint8(rout); - dst[j + goffset] = av_clip_uint8(gout); - dst[j + boffset] = av_clip_uint8(bout); - - if (have_alpha == 1) { - dst[j + aoffset] = av_clip_uint8(s->lut[A][R][rin] + - s->lut[A][G][gin] + - s->lut[A][B][bin] + - s->lut[A][A][ain]); - } else if (have_alpha == -1 && in != out) - dst[j + aoffset] = 0; - } - - srcrow += in->linesize[0]; - dstrow += out->linesize[0]; - } - - return 0; -} - -static av_always_inline int filter_slice_rgba16_packed(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs, - int have_alpha, int step, int pc) -{ - ColorChannelMixerContext *s = ctx->priv; - ThreadData *td = arg; - AVFrame *in = td->in; - AVFrame *out = td->out; - const float pa = s->preserve_amount; - const int slice_start = (out->height * jobnr) / nb_jobs; - const int slice_end = (out->height * (jobnr+1)) / nb_jobs; - const uint8_t roffset = s->rgba_map[R]; - const uint8_t goffset = s->rgba_map[G]; - const uint8_t boffset = s->rgba_map[B]; - const uint8_t aoffset = s->rgba_map[A]; - const uint8_t *srcrow = in->data[0] + slice_start * in->linesize[0]; - uint8_t *dstrow = out->data[0] + slice_start * out->linesize[0]; - int i, j; - - for (i = slice_start; i < slice_end; i++) { - const uint16_t *src = (const uint16_t *)srcrow; - uint16_t *dst = (uint16_t *)dstrow; - - for (j = 0; j < out->width * step; j += step) { - const uint16_t rin = src[j + roffset]; - const uint16_t gin = src[j + goffset]; - const uint16_t bin = src[j + boffset]; - const uint16_t ain = src[j + aoffset]; - int rout, gout, bout; - - rout = s->lut[R][R][rin] + - s->lut[R][G][gin] + - s->lut[R][B][bin] + - (have_alpha == 1 ? s->lut[R][A][ain] : 0); - gout = s->lut[G][R][rin] + - s->lut[G][G][gin] + - s->lut[G][B][bin] + - (have_alpha == 1 ? s->lut[G][A][ain] : 0); - bout = s->lut[B][R][rin] + - s->lut[B][G][gin] + - s->lut[B][B][bin] + - (have_alpha == 1 ? s->lut[B][A][ain] : 0); - - if (pc) { - float frout = av_clipf(rout, 0.f, 65535.f); - float fgout = av_clipf(gout, 0.f, 65535.f); - float fbout = av_clipf(bout, 0.f, 65535.f); - float lin, lout; - - preserve_color(s->preserve_color, rin, gin, bin, - rout, gout, bout, 65535.f, &lin, &lout); - preservel(&frout, &fgout, &fbout, lin, lout, 65535.f); - - rout = lrintf(lerpf(rout, frout, pa)); - gout = lrintf(lerpf(gout, fgout, pa)); - bout = lrintf(lerpf(bout, fbout, pa)); - } - - dst[j + roffset] = av_clip_uint16(rout); - dst[j + goffset] = av_clip_uint16(gout); - dst[j + boffset] = av_clip_uint16(bout); - - if (have_alpha == 1) { - dst[j + aoffset] = av_clip_uint16(s->lut[A][R][rin] + - s->lut[A][G][gin] + - s->lut[A][B][bin] + - s->lut[A][A][ain]); - } - } - - srcrow += in->linesize[0]; - dstrow += out->linesize[0]; - } - - return 0; + return filter_slice_rgba_planar_16(ctx, arg, jobnr, nb_jobs, 1, 16, 1); } static int filter_slice_rgba64(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba16_packed(ctx, arg, jobnr, nb_jobs, 1, 4, 0); + return filter_slice_rgba_packed_16(ctx, arg, jobnr, nb_jobs, 1, 4, 0, 16); } static int filter_slice_rgb48(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba16_packed(ctx, arg, jobnr, nb_jobs, 0, 3, 0); + return filter_slice_rgba_packed_16(ctx, arg, jobnr, nb_jobs, 0, 3, 0, 16); } static int filter_slice_rgba64_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba16_packed(ctx, arg, jobnr, nb_jobs, 1, 4, 1); + return filter_slice_rgba_packed_16(ctx, arg, jobnr, nb_jobs, 1, 4, 1, 16); } static int filter_slice_rgb48_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba16_packed(ctx, arg, jobnr, nb_jobs, 0, 3, 1); + return filter_slice_rgba_packed_16(ctx, arg, jobnr, nb_jobs, 0, 3, 1, 16); } static int filter_slice_rgba(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba_packed(ctx, arg, jobnr, nb_jobs, 1, 4, 0); + return filter_slice_rgba_packed_8(ctx, arg, jobnr, nb_jobs, 1, 4, 0, 8); } static int filter_slice_rgb24(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba_packed(ctx, arg, jobnr, nb_jobs, 0, 3, 0); + return filter_slice_rgba_packed_8(ctx, arg, jobnr, nb_jobs, 0, 3, 0, 8); } static int filter_slice_rgb0(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba_packed(ctx, arg, jobnr, nb_jobs, -1, 4, 0); + return filter_slice_rgba_packed_8(ctx, arg, jobnr, nb_jobs, -1, 4, 0, 8); } static int filter_slice_rgba_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba_packed(ctx, arg, jobnr, nb_jobs, 1, 4, 1); + return filter_slice_rgba_packed_8(ctx, arg, jobnr, nb_jobs, 1, 4, 1, 8); } static int filter_slice_rgb24_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba_packed(ctx, arg, jobnr, nb_jobs, 0, 3, 1); + return filter_slice_rgba_packed_8(ctx, arg, jobnr, nb_jobs, 0, 3, 1, 8); } static int filter_slice_rgb0_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - return filter_slice_rgba_packed(ctx, arg, jobnr, nb_jobs, -1, 4, 1); + return filter_slice_rgba_packed_8(ctx, arg, jobnr, nb_jobs, -1, 4, 1, 8); +} + +static int filter_slice_gbrp32(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + return filter_slice_rgba_planar_32(ctx, arg, jobnr, nb_jobs, 0, 1, 0); +} + +static int filter_slice_gbrap32(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + return filter_slice_rgba_planar_32(ctx, arg, jobnr, nb_jobs, 1, 1, 0); +} + +static int filter_slice_gbrp32_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + return filter_slice_rgba_planar_32(ctx, arg, jobnr, nb_jobs, 0, 1, 1); +} + +static int filter_slice_gbrap32_pl(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + return filter_slice_rgba_planar_32(ctx, arg, jobnr, nb_jobs, 1, 1, 1); } static int config_output(AVFilterLink *outlink) @@ -700,6 +416,14 @@ static int config_output(AVFilterLink *outlink) s->filter_slice[0] = filter_slice_gbrap16; s->filter_slice[1] = filter_slice_gbrap16_pl; break; + case AV_PIX_FMT_GBRPF32: + s->filter_slice[0] = filter_slice_gbrp32; + s->filter_slice[1] = filter_slice_gbrp32_pl; + break; + case AV_PIX_FMT_GBRAPF32: + s->filter_slice[0] = filter_slice_gbrap32; + s->filter_slice[1] = filter_slice_gbrap32_pl; + break; } return 0; diff --git a/libavfilter/vf_colorconstancy.c b/libavfilter/vf_colorconstancy.c index ba6359462..db7e20df5 100644 --- a/libavfilter/vf_colorconstancy.c +++ b/libavfilter/vf_colorconstancy.c @@ -28,6 +28,8 @@ * J. van de Weijer, Th. Gevers, A. Gijsenij "Edge-Based Color Constancy". */ +#include "config_components.h" + #include "libavutil/imgutils.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" diff --git a/libavfilter/vf_colorkey.c b/libavfilter/vf_colorkey.c index ed43722c0..cd4987e26 100644 --- a/libavfilter/vf_colorkey.c +++ b/libavfilter/vf_colorkey.c @@ -18,9 +18,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/opt.h" #include "libavutil/imgutils.h" #include "avfilter.h" +#include "drawutils.h" #include "formats.h" #include "internal.h" #include "video.h" @@ -29,105 +32,120 @@ typedef struct ColorkeyContext { const AVClass *class; /* color offsets rgba */ - int co[4]; + uint8_t co[4]; uint8_t colorkey_rgba[4]; float similarity; float blend; + double scale; + int depth; + int max; int (*do_slice)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); } ColorkeyContext; -static uint8_t do_colorkey_pixel(ColorkeyContext *ctx, uint8_t r, uint8_t g, uint8_t b) +static int do_colorkey_pixel(const uint8_t *colorkey_rgba, int r, int g, int b, + float similarity, float iblend, int max, double scale) { - int dr = (int)r - ctx->colorkey_rgba[0]; - int dg = (int)g - ctx->colorkey_rgba[1]; - int db = (int)b - ctx->colorkey_rgba[2]; + double dr, dg, db, diff; - double diff = sqrt((dr * dr + dg * dg + db * db) / (255.0 * 255.0 * 3.0)); + dr = r * scale - colorkey_rgba[0]; + dg = g * scale - colorkey_rgba[1]; + db = b * scale - colorkey_rgba[2]; - if (ctx->blend > 0.0001) { - return av_clipd((diff - ctx->similarity) / ctx->blend, 0.0, 1.0) * 255.0; + diff = sqrt((dr * dr + dg * dg + db * db) / (255.0 * 255.0 * 3.0)); + + if (iblend < 10000.0) { + return av_clipd((diff - similarity) * iblend, 0.0, 1.0) * max; } else { - return (diff > ctx->similarity) ? 255 : 0; + return (diff > similarity) ? max : 0; } } -static int do_colorkey_slice(AVFilterContext *avctx, void *arg, int jobnr, int nb_jobs) -{ - AVFrame *frame = arg; - - const int slice_start = (frame->height * jobnr) / nb_jobs; - const int slice_end = (frame->height * (jobnr + 1)) / nb_jobs; - - ColorkeyContext *ctx = avctx->priv; - - int o, x, y; - - for (y = slice_start; y < slice_end; ++y) { - for (x = 0; x < frame->width; ++x) { - o = frame->linesize[0] * y + x * 4; - - frame->data[0][o + ctx->co[3]] = - do_colorkey_pixel(ctx, - frame->data[0][o + ctx->co[0]], - frame->data[0][o + ctx->co[1]], - frame->data[0][o + ctx->co[2]]); - } - } - - return 0; +#define COLORKEY_SLICE(name, type) \ +static int do_colorkey_slice##name(AVFilterContext *avctx, \ + void *arg, \ + int jobnr, int nb_jobs) \ +{ \ + AVFrame *frame = arg; \ + const int slice_start = (frame->height * jobnr) / nb_jobs; \ + const int slice_end = (frame->height * (jobnr + 1)) / nb_jobs; \ + ColorkeyContext *ctx = avctx->priv; \ + const float similarity = ctx->similarity; \ + const float iblend = 1.f / ctx->blend; \ + const uint8_t *colorkey_rgba = ctx->colorkey_rgba; \ + const uint8_t *co = ctx->co; \ + const double scale = ctx->scale; \ + const int max = ctx->max; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + type *dst = (type *)(frame->data[0] + y * frame->linesize[0]);\ + \ + for (int x = 0; x < frame->width; x++) { \ + const int o = x * 4; \ + \ + dst[o + co[3]] = do_colorkey_pixel(colorkey_rgba, \ + dst[o + co[0]], \ + dst[o + co[1]], \ + dst[o + co[2]], \ + similarity, iblend, max, scale); \ + } \ + } \ + \ + return 0; \ } -static int do_colorhold_slice(AVFilterContext *avctx, void *arg, int jobnr, int nb_jobs) -{ - AVFrame *frame = arg; +COLORKEY_SLICE(8, uint8_t) +COLORKEY_SLICE(16, uint16_t) - const int slice_start = (frame->height * jobnr) / nb_jobs; - const int slice_end = (frame->height * (jobnr + 1)) / nb_jobs; - - ColorkeyContext *ctx = avctx->priv; - - int x, y; - - for (y = slice_start; y < slice_end; ++y) { - for (x = 0; x < frame->width; ++x) { - int o, t, r, g, b; - - o = frame->linesize[0] * y + x * 4; - r = frame->data[0][o + ctx->co[0]]; - g = frame->data[0][o + ctx->co[1]]; - b = frame->data[0][o + ctx->co[2]]; - - t = do_colorkey_pixel(ctx, r, g, b); - - if (t > 0) { - int a = (r + g + b) / 3; - int rt = 255 - t; - - frame->data[0][o + ctx->co[0]] = (a * t + r * rt + 127) >> 8; - frame->data[0][o + ctx->co[1]] = (a * t + g * rt + 127) >> 8; - frame->data[0][o + ctx->co[2]] = (a * t + b * rt + 127) >> 8; - } - } - } - - return 0; +#define COLORHOLD_SLICE(name, type, htype) \ +static int do_colorhold_slice##name(AVFilterContext *avctx, void *arg, \ + int jobnr, int nb_jobs) \ +{ \ + AVFrame *frame = arg; \ + const int slice_start = (frame->height * jobnr) / nb_jobs; \ + const int slice_end = (frame->height * (jobnr + 1)) / nb_jobs; \ + ColorkeyContext *ctx = avctx->priv; \ + const int depth = ctx->depth; \ + const int max = ctx->max; \ + const int half = max / 2; \ + const uint8_t *co = ctx->co; \ + const uint8_t *colorkey_rgba = ctx->colorkey_rgba; \ + const float similarity = ctx->similarity; \ + const float iblend = 1.f / ctx->blend; \ + const double scale = ctx->scale; \ + \ + for (int y = slice_start; y < slice_end; ++y) { \ + type *dst = (type *)(frame->data[0] + y * frame->linesize[0]); \ + \ + for (int x = 0; x < frame->width; ++x) { \ + int o, t, r, g, b; \ + \ + o = x * 4; \ + r = dst[o + co[0]]; \ + g = dst[o + co[1]]; \ + b = dst[o + co[2]]; \ + \ + t = do_colorkey_pixel(colorkey_rgba, r, g, b, \ + similarity, iblend, max, scale); \ + \ + if (t > 0) { \ + htype a = (r + g + b) / 3; \ + htype rt = max - t; \ + \ + dst[o + co[0]] = (a * t + r * rt + half) >> depth; \ + dst[o + co[1]] = (a * t + g * rt + half) >> depth; \ + dst[o + co[2]] = (a * t + b * rt + half) >> depth; \ + } \ + } \ + } \ + \ + return 0; \ } -static av_cold int init_filter(AVFilterContext *avctx) -{ - ColorkeyContext *ctx = avctx->priv; - - if (!strcmp(avctx->filter->name, "colorkey")) { - ctx->do_slice = do_colorkey_slice; - } else { - ctx->do_slice = do_colorhold_slice; - } - - return 0; -} +COLORHOLD_SLICE(8, uint8_t, int) +COLORHOLD_SLICE(16, uint16_t, int64_t) static int filter_frame(AVFilterLink *link, AVFrame *frame) { @@ -146,15 +164,21 @@ static av_cold int config_output(AVFilterLink *outlink) { AVFilterContext *avctx = outlink->src; ColorkeyContext *ctx = avctx->priv; - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(outlink->format); - int i; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->inputs[0]->format); + ctx->depth = desc->comp[0].depth; + ctx->max = (1 << ctx->depth) - 1; + ctx->scale = 255.0 / ctx->max; outlink->w = avctx->inputs[0]->w; outlink->h = avctx->inputs[0]->h; outlink->time_base = avctx->inputs[0]->time_base; + ff_fill_rgba_map(ctx->co, outlink->format); - for (i = 0; i < 4; ++i) - ctx->co[i] = desc->comp[i].offset; + if (!strcmp(avctx->filter->name, "colorkey")) { + ctx->do_slice = ctx->max == 255 ? do_colorkey_slice8 : do_colorkey_slice16; + } else { + ctx->do_slice = ctx->max == 255 ? do_colorhold_slice8 : do_colorhold_slice16; + } return 0; } @@ -164,6 +188,8 @@ static const enum AVPixelFormat pixel_fmts[] = { AV_PIX_FMT_RGBA, AV_PIX_FMT_ABGR, AV_PIX_FMT_BGRA, + AV_PIX_FMT_RGBA64, + AV_PIX_FMT_BGRA64, AV_PIX_FMT_NONE }; @@ -203,7 +229,6 @@ const AVFilter ff_vf_colorkey = { .description = NULL_IF_CONFIG_SMALL("Turns a certain color into transparency. Operates on RGB colors."), .priv_size = sizeof(ColorkeyContext), .priv_class = &colorkey_class, - .init = init_filter, FILTER_INPUTS(colorkey_inputs), FILTER_OUTPUTS(colorkey_outputs), FILTER_PIXFMTS_ARRAY(pixel_fmts), @@ -228,7 +253,6 @@ const AVFilter ff_vf_colorhold = { .description = NULL_IF_CONFIG_SMALL("Turns a certain color range into gray. Operates on RGB colors."), .priv_size = sizeof(ColorkeyContext), .priv_class = &colorhold_class, - .init = init_filter, FILTER_INPUTS(colorkey_inputs), FILTER_OUTPUTS(colorkey_outputs), FILTER_PIXFMTS_ARRAY(pixel_fmts), diff --git a/libavfilter/vf_colorlevels.c b/libavfilter/vf_colorlevels.c index c089740b0..76adfbd8c 100644 --- a/libavfilter/vf_colorlevels.c +++ b/libavfilter/vf_colorlevels.c @@ -44,6 +44,9 @@ typedef struct ColorLevelsContext { int preserve_color; int nb_comp; + int depth; + int max; + int planar; int bpp; int step; uint8_t rgba_map[4]; @@ -85,8 +88,8 @@ static const AVOption colorlevels_options[] = { AVFILTER_DEFINE_CLASS(colorlevels); typedef struct ThreadData { - const uint8_t *srcrow; - uint8_t *dstrow; + const uint8_t *srcrow[4]; + uint8_t *dstrow[4]; int dst_linesize; int src_linesize; @@ -98,8 +101,7 @@ typedef struct ThreadData { int omin[4]; } ThreadData; -#define DO_COMMON(type, clip, preserve) \ - ColorLevelsContext *s = ctx->priv; \ +#define DO_COMMON(type, clip, preserve, planar) \ const ThreadData *td = arg; \ const int linesize = s->linesize; \ const int step = s->step; \ @@ -108,12 +110,14 @@ typedef struct ThreadData { const int slice_end = (process_h * (jobnr+1)) / nb_jobs; \ const int src_linesize = td->src_linesize / sizeof(type); \ const int dst_linesize = td->dst_linesize / sizeof(type); \ - const type *srcrow = (const type *)td->srcrow + src_linesize * slice_start; \ - type *dstrow = (type *)td->dstrow + dst_linesize * slice_start; \ - const uint8_t offset_r = s->rgba_map[R]; \ - const uint8_t offset_g = s->rgba_map[G]; \ - const uint8_t offset_b = s->rgba_map[B]; \ - const uint8_t offset_a = s->rgba_map[A]; \ + const type *src_r = (const type *)(td->srcrow[R]) + src_linesize * slice_start; \ + const type *src_g = (const type *)(td->srcrow[G]) + src_linesize * slice_start; \ + const type *src_b = (const type *)(td->srcrow[B]) + src_linesize * slice_start; \ + const type *src_a = (const type *)(td->srcrow[A]) + src_linesize * slice_start; \ + type *dst_r = (type *)(td->dstrow[R]) + src_linesize * slice_start; \ + type *dst_g = (type *)(td->dstrow[G]) + src_linesize * slice_start; \ + type *dst_b = (type *)(td->dstrow[B]) + src_linesize * slice_start; \ + type *dst_a = (type *)(td->dstrow[A]) + src_linesize * slice_start; \ const int imin_r = td->imin[R]; \ const int imin_g = td->imin[G]; \ const int imin_b = td->imin[B]; \ @@ -126,14 +130,6 @@ typedef struct ThreadData { const float coeff_g = td->coeff[G]; \ const float coeff_b = td->coeff[B]; \ const float coeff_a = td->coeff[A]; \ - const type *src_r = srcrow + offset_r; \ - const type *src_g = srcrow + offset_g; \ - const type *src_b = srcrow + offset_b; \ - const type *src_a = srcrow + offset_a; \ - type *dst_r = dstrow + offset_r; \ - type *dst_g = dstrow + offset_g; \ - type *dst_b = dstrow + offset_b; \ - type *dst_a = dstrow + offset_a; \ \ for (int y = slice_start; y < slice_end; y++) { \ for (int x = 0; x < linesize; x += step) { \ @@ -142,7 +138,7 @@ typedef struct ThreadData { ig = src_g[x]; \ ib = src_b[x]; \ if (preserve) { \ - float ratio, icolor, ocolor, max = (1<<(8*sizeof(type)))-1; \ + float ratio, icolor, ocolor, max = s->max; \ \ or = (ir - imin_r) * coeff_r + omin_r; \ og = (ig - imin_g) * coeff_g + omin_g; \ @@ -158,18 +154,18 @@ typedef struct ThreadData { ob *= ratio; \ } \ \ - dst_r[x] = clip(or); \ - dst_g[x] = clip(og); \ - dst_b[x] = clip(ob); \ + dst_r[x] = clip(or, depth); \ + dst_g[x] = clip(og, depth); \ + dst_b[x] = clip(ob, depth); \ } else { \ - dst_r[x] = clip((ir - imin_r) * coeff_r + omin_r); \ - dst_g[x] = clip((ig - imin_g) * coeff_g + omin_g); \ - dst_b[x] = clip((ib - imin_b) * coeff_b + omin_b); \ + dst_r[x] = clip((ir - imin_r) * coeff_r + omin_r, depth); \ + dst_g[x] = clip((ig - imin_g) * coeff_g + omin_g, depth); \ + dst_b[x] = clip((ib - imin_b) * coeff_b + omin_b, depth); \ } \ } \ \ for (int x = 0; x < linesize && s->nb_comp == 4; x += step) \ - dst_a[x] = clip((src_a[x] - imin_a) * coeff_a + omin_a); \ + dst_a[x] = clip((src_a[x] - imin_a) * coeff_a + omin_a, depth); \ \ src_r += src_linesize; \ src_g += src_linesize; \ @@ -182,31 +178,126 @@ typedef struct ThreadData { dst_a += dst_linesize; \ } +#define CLIP8(x, depth) av_clip_uint8(x) +#define CLIP16(x, depth) av_clip_uint16(x) + static int colorlevels_slice_8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - DO_COMMON(uint8_t, av_clip_uint8, 0) - + ColorLevelsContext *s = ctx->priv; + DO_COMMON(uint8_t, CLIP8, 0, 0) return 0; } static int colorlevels_slice_16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - DO_COMMON(uint16_t, av_clip_uint16, 0) - + ColorLevelsContext *s = ctx->priv;\ + DO_COMMON(uint16_t, CLIP16, 0, 0) return 0; } static int colorlevels_preserve_slice_8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - DO_COMMON(uint8_t, av_clip_uint8, 1) - + ColorLevelsContext *s = ctx->priv; + DO_COMMON(uint8_t, CLIP8, 1, 0) return 0; } static int colorlevels_preserve_slice_16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { - DO_COMMON(uint16_t, av_clip_uint16, 1) + ColorLevelsContext *s = ctx->priv; + DO_COMMON(uint16_t, CLIP16, 1, 0) + return 0; +} +static int colorlevels_slice_8_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ColorLevelsContext *s = ctx->priv; + DO_COMMON(uint8_t, CLIP8, 0, 1) + return 0; +} + +static int colorlevels_slice_9_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ColorLevelsContext *s = ctx->priv; + const int depth = 9; + DO_COMMON(uint16_t, av_clip_uintp2, 0, 1) + return 0; +} + +static int colorlevels_slice_10_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ColorLevelsContext *s = ctx->priv; + const int depth = 10; + DO_COMMON(uint16_t, av_clip_uintp2, 0, 1) + return 0; +} + +static int colorlevels_slice_12_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ColorLevelsContext *s = ctx->priv; + const int depth = 12; + DO_COMMON(uint16_t, av_clip_uintp2, 0, 1) + return 0; +} + +static int colorlevels_slice_14_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ColorLevelsContext *s = ctx->priv; + const int depth = 14; + DO_COMMON(uint16_t, av_clip_uintp2, 0, 1) + return 0; +} + +static int colorlevels_slice_16_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ColorLevelsContext *s = ctx->priv; + DO_COMMON(uint16_t, CLIP16, 0, 1) + return 0; +} + +static int colorlevels_preserve_slice_8_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ColorLevelsContext *s = ctx->priv; + DO_COMMON(uint8_t, CLIP8, 1, 1) + return 0; +} + +static int colorlevels_preserve_slice_9_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ColorLevelsContext *s = ctx->priv; + const int depth = 9; + DO_COMMON(uint16_t, av_clip_uintp2, 1, 1) + return 0; +} + +static int colorlevels_preserve_slice_10_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ColorLevelsContext *s = ctx->priv; + const int depth = 10; + DO_COMMON(uint16_t, av_clip_uintp2, 1, 1) + return 0; +} + +static int colorlevels_preserve_slice_12_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ColorLevelsContext *s = ctx->priv; + const int depth = 12; + DO_COMMON(uint16_t, av_clip_uintp2, 1, 1) + return 0; +} + +static int colorlevels_preserve_slice_14_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ColorLevelsContext *s = ctx->priv; + const int depth = 14; + DO_COMMON(uint16_t, av_clip_uintp2, 1, 1) + return 0; +} + +static int colorlevels_preserve_slice_16_planar(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ColorLevelsContext *s = ctx->priv; + DO_COMMON(uint16_t, CLIP16, 1, 1) return 0; } @@ -217,16 +308,48 @@ static int config_input(AVFilterLink *inlink) const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); s->nb_comp = desc->nb_components; - s->bpp = desc->comp[0].depth >> 3; - s->step = av_get_padded_bits_per_pixel(desc) >> (3 + (s->bpp == 2)); + s->planar = desc->flags & AV_PIX_FMT_FLAG_PLANAR; + s->depth = desc->comp[0].depth; + s->max = (1 << s->depth) - 1; + s->bpp = (desc->comp[0].depth + 7) >> 3; + s->step = s->planar ? 1 : av_get_padded_bits_per_pixel(desc) >> (3 + (s->bpp == 2)); s->linesize = inlink->w * s->step; ff_fill_rgba_map(s->rgba_map, inlink->format); - s->colorlevels_slice[0] = colorlevels_slice_8; - s->colorlevels_slice[1] = colorlevels_preserve_slice_8; - if (s->bpp == 2) { - s->colorlevels_slice[0] = colorlevels_slice_16; - s->colorlevels_slice[1] = colorlevels_preserve_slice_16; + if (!s->planar) { + s->colorlevels_slice[0] = colorlevels_slice_8; + s->colorlevels_slice[1] = colorlevels_preserve_slice_8; + if (s->bpp == 2) { + s->colorlevels_slice[0] = colorlevels_slice_16; + s->colorlevels_slice[1] = colorlevels_preserve_slice_16; + } + } else { + switch (s->depth) { + case 8: + s->colorlevels_slice[0] = colorlevels_slice_8_planar; + s->colorlevels_slice[1] = colorlevels_preserve_slice_8_planar; + break; + case 9: + s->colorlevels_slice[0] = colorlevels_slice_9_planar; + s->colorlevels_slice[1] = colorlevels_preserve_slice_9_planar; + break; + case 10: + s->colorlevels_slice[0] = colorlevels_slice_10_planar; + s->colorlevels_slice[1] = colorlevels_preserve_slice_10_planar; + break; + case 12: + s->colorlevels_slice[0] = colorlevels_slice_12_planar; + s->colorlevels_slice[1] = colorlevels_preserve_slice_12_planar; + break; + case 14: + s->colorlevels_slice[0] = colorlevels_slice_14_planar; + s->colorlevels_slice[1] = colorlevels_preserve_slice_14_planar; + break; + case 16: + s->colorlevels_slice[0] = colorlevels_slice_16_planar; + s->colorlevels_slice[1] = colorlevels_preserve_slice_16_planar; + break; + } } return 0; @@ -255,8 +378,25 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) td.h = inlink->h; td.dst_linesize = out->linesize[0]; td.src_linesize = in->linesize[0]; - td.srcrow = in->data[0]; - td.dstrow = out->data[0]; + if (s->planar) { + td.srcrow[R] = in->data[2]; + td.dstrow[R] = out->data[2]; + td.srcrow[G] = in->data[0]; + td.dstrow[G] = out->data[0]; + td.srcrow[B] = in->data[1]; + td.dstrow[B] = out->data[1]; + td.srcrow[A] = in->data[3]; + td.dstrow[A] = out->data[3]; + } else { + td.srcrow[R] = in->data[0] + s->rgba_map[R] * s->bpp; + td.dstrow[R] = out->data[0] + s->rgba_map[R] * s->bpp; + td.srcrow[G] = in->data[0] + s->rgba_map[G] * s->bpp; + td.dstrow[G] = out->data[0] + s->rgba_map[G] * s->bpp; + td.srcrow[B] = in->data[0] + s->rgba_map[B] * s->bpp; + td.dstrow[B] = out->data[0] + s->rgba_map[B] * s->bpp; + td.srcrow[A] = in->data[0] + s->rgba_map[A] * s->bpp; + td.dstrow[A] = out->data[0] + s->rgba_map[A] * s->bpp; + } switch (s->bpp) { case 1: @@ -378,7 +518,13 @@ const AVFilter ff_vf_colorlevels = { AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24, AV_PIX_FMT_RGB48, AV_PIX_FMT_BGR48, AV_PIX_FMT_RGBA64, AV_PIX_FMT_BGRA64, - AV_PIX_FMT_RGBA, AV_PIX_FMT_BGRA), + AV_PIX_FMT_RGBA, AV_PIX_FMT_BGRA, + AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, + 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), .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, .process_command = ff_filter_process_command, }; diff --git a/libavfilter/vf_colormap.c b/libavfilter/vf_colormap.c new file mode 100644 index 000000000..106333ced --- /dev/null +++ b/libavfilter/vf_colormap.c @@ -0,0 +1,575 @@ +/* + * Copyright (c) 2022 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 + */ + +/** + * @file + * Compute a look-up table from map of colors. + */ + +#include "libavutil/attributes.h" +#include "libavutil/avassert.h" +#include "libavutil/common.h" +#include "libavutil/opt.h" +#include "avfilter.h" +#include "internal.h" +#include "framesync.h" +#include "video.h" + +#define MAX_SIZE 64 + +enum KernelType { + EUCLIDEAN, + WEUCLIDEAN, + NB_KERNELS, +}; + +typedef struct ColorMapContext { + const AVClass *class; + int w, h; + int size; + int nb_maps; + int changed[2]; + + float source[MAX_SIZE][4]; + float ttarget[MAX_SIZE][4]; + float target[MAX_SIZE][4]; + float icoeff[4][4]; + float coeff[MAX_SIZE][4]; + + int target_type; + int kernel_type; + float (*kernel)(const float *x, const float *y); + + FFFrameSync fs; + + double A[(MAX_SIZE + 4) * (MAX_SIZE + 4)]; + double b[MAX_SIZE + 4]; + int pivot[MAX_SIZE + 4]; +} ColorMapContext; + +#define OFFSET(x) offsetof(ColorMapContext, x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM + +static const AVOption colormap_options[] = { + { "patch_size", "set patch size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "64x64"}, 0, 0, FLAGS }, + { "nb_patches", "set number of patches", OFFSET(size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, MAX_SIZE, FLAGS }, + { "type", "set the target type used", OFFSET(target_type), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, "type" }, + { "relative", "the target colors are relative", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 1, FLAGS, "type" }, + { "absolute", "the target colors are absolute", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 1, FLAGS, "type" }, + { "kernel", "set the kernel used for measuring color difference", OFFSET(kernel_type), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_KERNELS-1, FLAGS, "kernel" }, + { "euclidean", "square root of sum of squared differences", 0, AV_OPT_TYPE_CONST, {.i64=EUCLIDEAN}, 0, 0, FLAGS, "kernel" }, + { "weuclidean", "weighted square root of sum of squared differences",0, AV_OPT_TYPE_CONST, {.i64=WEUCLIDEAN}, 0, 0, FLAGS, "kernel" }, + { NULL } +}; + +static int gauss_make_triangular(double *A, int *p, int n) +{ + p[n - 1] = n - 1; + for (int k = 0; k < n; k++) { + double t1; + int m = k; + + for (int i = k + 1; i < n; i++) + if (fabs(A[k + n * i]) > fabs(A[k + n * m])) + m = i; + p[k] = m; + t1 = A[k + n * m]; + A[k + n * m] = A[k + n * k]; + A[k + n * k] = t1; + if (t1 != 0) { + for (int i = k + 1; i < n; i++) + A[k + n * i] /= -t1; + if (k != m) + for (int i = k + 1; i < n; i++) { + double t2 = A[i + n * m]; + A[i + n * m] = A[i + n * k]; + A[i + n * k] = t2; + } + for (int j = k + 1; j < n; j++) + for (int i = k + 1; i < n; i++) + A[i + n * j] += A[k + j * n] * A[i + k * n]; + } else { + return 0; + } + } + + return 1; +} + +static void gauss_solve_triangular(const double *A, const int *p, double *b, int n) +{ + for(int k = 0; k < n - 1; k++) { + int m = p[k]; + double t = b[m]; + b[m] = b[k]; + b[k] = t; + for (int i = k + 1; i < n; i++) + b[i] += A[k + n * i] * t; + } + + for(int k = n - 1; k > 0; k--) { + double t = b[k] /= A[k + n * k]; + for (int i = 0; i < k; i++) + b[i] -= A[k + n * i] * t; + } + + b[0] /= A[0 + 0 * n]; +} + +static int gauss_solve(double *A, double *b, int n) +{ + int p[3] = { 0 }; + + av_assert2(n <= FF_ARRAY_ELEMS(p)); + + if (!gauss_make_triangular(A, p, n)) + return 1; + + gauss_solve_triangular(A, p, b, n); + + return 0; +} + +#define P2(x) ((x)*(x)) + +static float euclidean_kernel(const float *x, const float *y) +{ + const float d2 = P2(x[0]-y[0]) + + P2(x[1]-y[1]) + + P2(x[2]-y[2]); + return sqrtf(d2); +} + +static float weuclidean_kernel(const float *x, const float *y) +{ + const float rm = (x[0] + y[0]) * 0.5f; + const float d2 = P2(x[0]-y[0]) * (2.f + rm) + + P2(x[1]-y[1]) * 4.f + + P2(x[2]-y[2]) * (3.f - rm); + return sqrtf(d2); +} + +static void build_map(AVFilterContext *ctx) +{ + ColorMapContext *s = ctx->priv; + + for (int j = 0; j < s->nb_maps; j++) { + s->target[j][0] = s->target_type == 0 ? s->source[j][0] + s->ttarget[j][0] : s->ttarget[j][0]; + s->target[j][1] = s->target_type == 0 ? s->source[j][1] + s->ttarget[j][1] : s->ttarget[j][1]; + s->target[j][2] = s->target_type == 0 ? s->source[j][2] + s->ttarget[j][2] : s->ttarget[j][2]; + } + + for (int c = 0; c < 3; c++) { + for (int j = 0; j < s->nb_maps; j++) + s->coeff[j][c] = 0.f; + + for (int j = 0; j < 4; j++) { + s->icoeff[j][c] = 0; + s->icoeff[j][c] = 0; + s->icoeff[j][c] = 0; + } + + s->icoeff[c+1][c] = 1.f; + + switch (s->nb_maps) { + case 1: + { + float div = fabsf(s->source[0][c]) < 1e-6f ? 1e-6f : s->source[0][c]; + s->icoeff[c][1+c] = s->target[0][c] / div; + } + break; + case 2: + { + double A[2 * 2] = { 1, s->source[0][c], + 1, s->source[1][c] }; + double b[2] = { s->target[0][c], s->target[1][c] }; + + if (gauss_solve(A, b, 2)) + continue; + + s->icoeff[0 ][c] = b[0]; + s->icoeff[1+c][c] = b[1]; + } + break; + case 3: + { + const uint8_t idx[3][3] = {{ 0, 1, 2 }, + { 1, 0, 2 }, + { 2, 0, 1 }}; + const uint8_t didx[3][4] = {{ 0, 1, 2, 2 }, + { 0, 2, 1, 2 }, + { 0, 2, 2, 1 }}; + const int C0 = idx[c][0]; + const int C1 = idx[c][1]; + const int C2 = idx[c][2]; + double A[3 * 3] = { 1, s->source[0][C0], s->source[0][C1] + s->source[0][C2], + 1, s->source[1][C0], s->source[1][C1] + s->source[1][C2], + 1, s->source[2][C0], s->source[2][C1] + s->source[2][C2] }; + double b[3] = { s->target[0][c], s->target[1][c], s->target[2][c] }; + + if (gauss_solve(A, b, 3)) + continue; + + s->icoeff[0][c] = b[didx[c][0]]; + s->icoeff[1][c] = b[didx[c][1]]; + s->icoeff[2][c] = b[didx[c][2]]; + s->icoeff[3][c] = b[didx[c][3]]; + } + break; + case 4: + { + double A[4 * 4] = { 1, s->source[0][0], s->source[0][1], s->source[0][2], + 1, s->source[1][0], s->source[1][1], s->source[1][2], + 1, s->source[2][0], s->source[2][1], s->source[2][2], + 1, s->source[3][0], s->source[3][1], s->source[3][2] }; + double b[4] = { s->target[0][c], s->target[1][c], s->target[2][c], s->target[3][c] }; + int pivot[4]; + + if (!gauss_make_triangular(A, pivot, 4)) + continue; + gauss_solve_triangular(A, pivot, b, 4); + + s->icoeff[0][c] = b[0]; + s->icoeff[1][c] = b[1]; + s->icoeff[2][c] = b[2]; + s->icoeff[3][c] = b[3]; + } + break; + default: + { + const int N = s->nb_maps; + const int N4 = N + 4; + double *A = s->A; + double *b = s->b; + int *pivot = s->pivot; + + for (int j = 0; j < N; j++) + for (int i = j; i < N; i++) + A[j*N4+i] = A[i*N4+j] = s->kernel(s->source[i], s->source[j]); + + for (int i = 0; i < N; i++) + A[i*N4+N+0] = A[(N+0)*N4+i] = 1; + for (int i = 0; i < N; i++) + A[i*N4+N+1] = A[(N+1)*N4+i] = s->source[i][0]; + for (int i = 0; i < N; i++) + A[i*N4+N+2] = A[(N+2)*N4+i] = s->source[i][1]; + for (int i = 0; i < N; i++) + A[i*N4+N+3] = A[(N+3)*N4+i] = s->source[i][2]; + + for (int j = N; j < N4; j++) + for (int i = N;i < N4; i++) + A[j * N4 + i] = 0.; + + if (gauss_make_triangular(A, pivot, N4)) { + for (int i = 0; i < N; i++) + b[i] = s->target[i][c]; + for (int i = N; i < N + 4; i++) + b[i] = 0; + + gauss_solve_triangular(A, pivot, b, N4); + + for (int i = 0; i < N; i++) + s->coeff[i][c] = b[i]; + + for (int i = 0; i < 4; i++) + s->icoeff[i][c] = b[N + i]; + } + } + } + } +} + +typedef struct ThreadData { + AVFrame *in, *out; +} ThreadData; + +static int colormap_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + ColorMapContext *s = ctx->priv; + ThreadData *td = arg; + AVFrame *in = td->in; + AVFrame *out = td->out; + const int maps = s->nb_maps; + const int width = out->width; + const int height = out->height; + const int slice_start = (height * jobnr) / nb_jobs; + const int slice_end = (height * (jobnr + 1)) / nb_jobs; + const int sr_linesize = in->linesize[2] / 4; + const int dr_linesize = out->linesize[2] / 4; + const int sg_linesize = in->linesize[0] / 4; + const int dg_linesize = out->linesize[0] / 4; + const int sb_linesize = in->linesize[1] / 4; + const int db_linesize = out->linesize[1] / 4; + const float *sr = (float *)in->data[2] + slice_start * sr_linesize; + const float *sg = (float *)in->data[0] + slice_start * sg_linesize; + const float *sb = (float *)in->data[1] + slice_start * sb_linesize; + float *r = (float *)out->data[2] + slice_start * dr_linesize; + float *g = (float *)out->data[0] + slice_start * dg_linesize; + float *b = (float *)out->data[1] + slice_start * db_linesize; + float (*kernel)(const float *x, const float *y) = s->kernel; + const float *icoeff[4] = { s->icoeff[0], s->icoeff[1], s->icoeff[2], s->icoeff[3] }; + + for (int y = slice_start; y < slice_end; y++) { + for (int x = 0; x < width; x++) { + const float input[3] = { sr[x], sg[x], sb[x] }; + float srv, sgv, sbv; + float rv, gv, bv; + + srv = sr[x]; + sgv = sg[x]; + sbv = sb[x]; + + rv = icoeff[0][0]; + gv = icoeff[0][1]; + bv = icoeff[0][2]; + + rv += icoeff[1][0] * srv + icoeff[2][0] * sgv + icoeff[3][0] * sbv; + gv += icoeff[1][1] * srv + icoeff[2][1] * sgv + icoeff[3][1] * sbv; + bv += icoeff[1][2] * srv + icoeff[2][2] * sgv + icoeff[3][2] * sbv; + + for (int z = 0; z < maps && maps > 4; z++) { + const float *coeff = s->coeff[z]; + const float cr = coeff[0]; + const float cg = coeff[1]; + const float cb = coeff[2]; + const float f = kernel(input, s->source[z]); + + rv += f * cr; + gv += f * cg; + bv += f * cb; + } + + r[x] = rv; + g[x] = gv; + b[x] = bv; + } + + sg += sg_linesize; + g += dg_linesize; + sb += sb_linesize; + b += db_linesize; + sr += sr_linesize; + r += dr_linesize; + } + + return 0; +} + +static int import_map(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + ColorMapContext *s = ctx->priv; + const int is_target = FF_INLINK_IDX(inlink) > 1; + const int pw = s->w; + const int pw2 = s->w / 2; + const int ph = s->h; + const int ph2 = s->h / 2; + int changed = 0; + int idx; + + for (int plane = 0; plane < 3; plane++) { + const int c = plane == 0 ? 1 : plane == 1 ? 2 : 0; + + idx = 0; + for (int y = ph2; y < in->height && idx < MAX_SIZE; y += ph) { + const float *src = (const float *)(in->data[plane] + y * in->linesize[plane]); + + for (int x = pw2; x < in->width && idx < MAX_SIZE; x += pw) { + float value = src[x]; + + if (is_target) { + if (s->ttarget[idx][c] != value) + changed = 1; + s->ttarget[idx][c] = value; + } else { + if (s->source[idx][c] != value) + changed = 1; + s->source[idx][c] = value; + } + + idx++; + } + } + } + + if (changed) + s->changed[is_target] = 1; + if (!s->size) + s->size = FFMIN(idx, MAX_SIZE); + if (!is_target) + s->nb_maps = FFMIN(idx, s->size); + + return 0; +} + +static int process_frame(FFFrameSync *fs) +{ + AVFilterContext *ctx = fs->parent; + ColorMapContext *s = fs->opaque; + AVFilterLink *outlink = ctx->outputs[0]; + AVFrame *in, *out, *source, *target; + ThreadData td; + int ret; + + switch (s->kernel_type) { + case EUCLIDEAN: + s->kernel = euclidean_kernel; + break; + case WEUCLIDEAN: + s->kernel = weuclidean_kernel; + break; + default: + return AVERROR_BUG; + } + + if ((ret = ff_framesync_get_frame(&s->fs, 0, &in, 1)) < 0 || + (ret = ff_framesync_get_frame(&s->fs, 1, &source, 0)) < 0 || + (ret = ff_framesync_get_frame(&s->fs, 2, &target, 0)) < 0) + return ret; + + import_map(ctx->inputs[1], source); + import_map(ctx->inputs[2], target); + + if (s->changed[0] || s->changed[1]) { + build_map(ctx); + s->changed[0] = s->changed[1] = 0; + } + + if (!ctx->is_disabled) { + if (av_frame_is_writable(in)) { + 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); + } + + td.in = in; + td.out = out; + ff_filter_execute(ctx, colormap_slice, &td, NULL, + FFMIN(in->height, ff_filter_get_nb_threads(ctx))); + + if (out != in) + av_frame_free(&in); + } else { + out = in; + } + + out->pts = av_rescale_q(s->fs.pts, s->fs.time_base, outlink->time_base); + + return ff_filter_frame(outlink, out); +} + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + ColorMapContext *s = ctx->priv; + AVFilterLink *inlink = ctx->inputs[0]; + AVFilterLink *source = ctx->inputs[1]; + AVFilterLink *target = ctx->inputs[2]; + FFFrameSyncIn *in; + int ret; + + outlink->time_base = inlink->time_base; + outlink->frame_rate = inlink->frame_rate; + outlink->sample_aspect_ratio = inlink->sample_aspect_ratio; + outlink->w = inlink->w; + outlink->h = inlink->h; + + if ((ret = ff_framesync_init(&s->fs, ctx, 3)) < 0) + return ret; + + in = s->fs.in; + in[0].time_base = inlink->time_base; + in[1].time_base = source->time_base; + in[2].time_base = target->time_base; + in[0].sync = 1; + in[0].before = EXT_STOP; + in[0].after = EXT_INFINITY; + in[1].sync = 1; + in[1].before = EXT_STOP; + in[1].after = EXT_INFINITY; + in[2].sync = 1; + in[2].before = EXT_STOP; + in[2].after = EXT_INFINITY; + s->fs.opaque = s; + s->fs.on_event = process_frame; + + ret = ff_framesync_configure(&s->fs); + outlink->time_base = s->fs.time_base; + + return ret; +} + +static int activate(AVFilterContext *ctx) +{ + ColorMapContext *s = ctx->priv; + return ff_framesync_activate(&s->fs); +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + ColorMapContext *const s = ctx->priv; + + ff_framesync_uninit(&s->fs); +} + +static const AVFilterPad inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, + { + .name = "source", + .type = AVMEDIA_TYPE_VIDEO, + }, + { + .name = "target", + .type = AVMEDIA_TYPE_VIDEO, + }, +}; + +static const AVFilterPad outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_output, + }, +}; + +AVFILTER_DEFINE_CLASS(colormap); + +const AVFilter ff_vf_colormap = { + .name = "colormap", + .description = NULL_IF_CONFIG_SMALL("Apply custom Color Maps to video stream."), + .priv_class = &colormap_class, + .priv_size = sizeof(ColorMapContext), + .activate = activate, + FILTER_INPUTS(inputs), + FILTER_OUTPUTS(outputs), + FILTER_PIXFMTS(AV_PIX_FMT_GBRPF32, AV_PIX_FMT_GBRAPF32), + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | + AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, + .uninit = uninit, +}; diff --git a/libavfilter/vf_colorspace.c b/libavfilter/vf_colorspace.c index 0bd8e2b0c..21916b7b7 100644 --- a/libavfilter/vf_colorspace.c +++ b/libavfilter/vf_colorspace.c @@ -24,6 +24,7 @@ */ #include "libavutil/avassert.h" +#include "libavutil/csp.h" #include "libavutil/mem_internal.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" @@ -55,14 +56,6 @@ enum Colorspace { CS_NB, }; -enum Whitepoint { - WP_D65, - WP_C, - WP_DCI, - WP_E, - WP_NB, -}; - enum WhitepointAdaptation { WP_ADAPT_BRADFORD, WP_ADAPT_VON_KRIES, @@ -110,11 +103,6 @@ static const enum AVColorSpace default_csp[CS_NB + 1] = { [CS_NB] = AVCOL_SPC_UNSPECIFIED, }; -struct ColorPrimaries { - enum Whitepoint wp; - struct PrimaryCoefficients coeff; -}; - struct TransferCharacteristics { double alpha, beta, gamma, delta; }; @@ -139,7 +127,7 @@ typedef struct ColorSpaceContext { unsigned rgb_sz; int *dither_scratch[3][2], *dither_scratch_base[3][2]; - const struct ColorPrimaries *in_primaries, *out_primaries; + const AVColorPrimariesDesc *in_primaries, *out_primaries; int lrgb2lrgb_passthrough; DECLARE_ALIGNED(16, int16_t, lrgb2lrgb_coeffs)[3][3][8]; @@ -147,7 +135,7 @@ typedef struct ColorSpaceContext { int rgb2rgb_passthrough; int16_t *lin_lut, *delin_lut; - const struct LumaCoefficients *in_lumacoef, *out_lumacoef; + const AVLumaCoefficients *in_lumacoef, *out_lumacoef; int yuv2yuv_passthrough, yuv2yuv_fastmode; DECLARE_ALIGNED(16, int16_t, yuv2rgb_coeffs)[3][3][8]; DECLARE_ALIGNED(16, int16_t, rgb2yuv_coeffs)[3][3][8]; @@ -201,40 +189,6 @@ static const struct TransferCharacteristics * return coeffs; } -static const struct WhitepointCoefficients whitepoint_coefficients[WP_NB] = { - [WP_D65] = { 0.3127, 0.3290 }, - [WP_C] = { 0.3100, 0.3160 }, - [WP_DCI] = { 0.3140, 0.3510 }, - [WP_E] = { 1/3.0f, 1/3.0f }, -}; - -static const struct ColorPrimaries color_primaries[AVCOL_PRI_NB] = { - [AVCOL_PRI_BT709] = { WP_D65, { 0.640, 0.330, 0.300, 0.600, 0.150, 0.060 } }, - [AVCOL_PRI_BT470M] = { WP_C, { 0.670, 0.330, 0.210, 0.710, 0.140, 0.080 } }, - [AVCOL_PRI_BT470BG] = { WP_D65, { 0.640, 0.330, 0.290, 0.600, 0.150, 0.060 } }, - [AVCOL_PRI_SMPTE170M] = { WP_D65, { 0.630, 0.340, 0.310, 0.595, 0.155, 0.070 } }, - [AVCOL_PRI_SMPTE240M] = { WP_D65, { 0.630, 0.340, 0.310, 0.595, 0.155, 0.070 } }, - [AVCOL_PRI_SMPTE428] = { WP_E, { 0.735, 0.265, 0.274, 0.718, 0.167, 0.009 } }, - [AVCOL_PRI_SMPTE431] = { WP_DCI, { 0.680, 0.320, 0.265, 0.690, 0.150, 0.060 } }, - [AVCOL_PRI_SMPTE432] = { WP_D65, { 0.680, 0.320, 0.265, 0.690, 0.150, 0.060 } }, - [AVCOL_PRI_FILM] = { WP_C, { 0.681, 0.319, 0.243, 0.692, 0.145, 0.049 } }, - [AVCOL_PRI_BT2020] = { WP_D65, { 0.708, 0.292, 0.170, 0.797, 0.131, 0.046 } }, - [AVCOL_PRI_JEDEC_P22] = { WP_D65, { 0.630, 0.340, 0.295, 0.605, 0.155, 0.077 } }, -}; - -static const struct ColorPrimaries *get_color_primaries(enum AVColorPrimaries prm) -{ - const struct ColorPrimaries *p; - - if (prm >= AVCOL_PRI_NB) - return NULL; - p = &color_primaries[prm]; - if (!p->coeff.xr) - return NULL; - - return p; -} - static int fill_gamma_table(ColorSpaceContext *s) { int n; @@ -280,7 +234,8 @@ static int fill_gamma_table(ColorSpaceContext *s) * This function uses the Bradford mechanism. */ static void fill_whitepoint_conv_table(double out[3][3], enum WhitepointAdaptation wp_adapt, - enum Whitepoint src, enum Whitepoint dst) + const AVWhitepointCoefficients *wp_src, + const AVWhitepointCoefficients *wp_dst) { static const double ma_tbl[NB_WP_ADAPT_NON_IDENTITY][3][3] = { [WP_ADAPT_BRADFORD] = { @@ -294,20 +249,20 @@ static void fill_whitepoint_conv_table(double out[3][3], enum WhitepointAdaptati }, }; const double (*ma)[3] = ma_tbl[wp_adapt]; - const struct WhitepointCoefficients *wp_src = &whitepoint_coefficients[src]; - double zw_src = 1.0 - wp_src->xw - wp_src->yw; - const struct WhitepointCoefficients *wp_dst = &whitepoint_coefficients[dst]; - double zw_dst = 1.0 - wp_dst->xw - wp_dst->yw; + double xw_src = av_q2d(wp_src->x), yw_src = av_q2d(wp_src->y); + double xw_dst = av_q2d(wp_dst->x), yw_dst = av_q2d(wp_dst->y); + double zw_src = 1.0 - xw_src - yw_src; + double zw_dst = 1.0 - xw_dst - yw_dst; double mai[3][3], fac[3][3], tmp[3][3]; double rs, gs, bs, rd, gd, bd; ff_matrix_invert_3x3(ma, mai); - rs = ma[0][0] * wp_src->xw + ma[0][1] * wp_src->yw + ma[0][2] * zw_src; - gs = ma[1][0] * wp_src->xw + ma[1][1] * wp_src->yw + ma[1][2] * zw_src; - bs = ma[2][0] * wp_src->xw + ma[2][1] * wp_src->yw + ma[2][2] * zw_src; - rd = ma[0][0] * wp_dst->xw + ma[0][1] * wp_dst->yw + ma[0][2] * zw_dst; - gd = ma[1][0] * wp_dst->xw + ma[1][1] * wp_dst->yw + ma[1][2] * zw_dst; - bd = ma[2][0] * wp_dst->xw + ma[2][1] * wp_dst->yw + ma[2][2] * zw_dst; + rs = ma[0][0] * xw_src + ma[0][1] * yw_src + ma[0][2] * zw_src; + gs = ma[1][0] * xw_src + ma[1][1] * yw_src + ma[1][2] * zw_src; + bs = ma[2][0] * xw_src + ma[2][1] * yw_src + ma[2][2] * zw_src; + rd = ma[0][0] * xw_dst + ma[0][1] * yw_dst + ma[0][2] * zw_dst; + gd = ma[1][0] * xw_dst + ma[1][1] * yw_dst + ma[1][2] * zw_dst; + bd = ma[2][0] * xw_dst + ma[2][1] * yw_dst + ma[2][2] * zw_dst; fac[0][0] = rd / rs; fac[1][1] = gd / gs; fac[2][2] = bd / bs; @@ -486,7 +441,7 @@ static int create_filtergraph(AVFilterContext *ctx, s->in_prm = default_prm[FFMIN(s->user_iall, CS_NB)]; if (s->user_iprm != AVCOL_PRI_UNSPECIFIED) s->in_prm = s->user_iprm; - s->in_primaries = get_color_primaries(s->in_prm); + s->in_primaries = av_csp_primaries_desc_from_id(s->in_prm); if (!s->in_primaries) { av_log(ctx, AV_LOG_ERROR, "Unsupported input primaries %d (%s)\n", @@ -494,7 +449,7 @@ static int create_filtergraph(AVFilterContext *ctx, return AVERROR(EINVAL); } s->out_prm = out->color_primaries; - s->out_primaries = get_color_primaries(s->out_prm); + s->out_primaries = av_csp_primaries_desc_from_id(s->out_prm); if (!s->out_primaries) { if (s->out_prm == AVCOL_PRI_UNSPECIFIED) { if (s->user_all == CS_UNSPECIFIED) { @@ -514,19 +469,19 @@ static int create_filtergraph(AVFilterContext *ctx, sizeof(*s->in_primaries)); if (!s->lrgb2lrgb_passthrough) { double rgb2xyz[3][3], xyz2rgb[3][3], rgb2rgb[3][3]; - const struct WhitepointCoefficients *wp_out, *wp_in; + const AVWhitepointCoefficients *wp_out, *wp_in; - wp_out = &whitepoint_coefficients[s->out_primaries->wp]; - wp_in = &whitepoint_coefficients[s->in_primaries->wp]; - ff_fill_rgb2xyz_table(&s->out_primaries->coeff, wp_out, rgb2xyz); + wp_out = &s->out_primaries->wp; + wp_in = &s->in_primaries->wp; + ff_fill_rgb2xyz_table(&s->out_primaries->prim, wp_out, rgb2xyz); ff_matrix_invert_3x3(rgb2xyz, xyz2rgb); - ff_fill_rgb2xyz_table(&s->in_primaries->coeff, wp_in, rgb2xyz); - if (s->out_primaries->wp != s->in_primaries->wp && + ff_fill_rgb2xyz_table(&s->in_primaries->prim, wp_in, rgb2xyz); + if (memcmp(wp_in, wp_out, sizeof(*wp_in)) != 0 && s->wp_adapt != WP_ADAPT_IDENTITY) { double wpconv[3][3], tmp[3][3]; - fill_whitepoint_conv_table(wpconv, s->wp_adapt, s->in_primaries->wp, - s->out_primaries->wp); + fill_whitepoint_conv_table(wpconv, s->wp_adapt, &s->in_primaries->wp, + &s->out_primaries->wp); ff_matrix_mul_3x3(tmp, rgb2xyz, wpconv); ff_matrix_mul_3x3(rgb2rgb, tmp, xyz2rgb); } else { @@ -599,7 +554,7 @@ static int create_filtergraph(AVFilterContext *ctx, s->in_rng = in->color_range; if (s->user_irng != AVCOL_RANGE_UNSPECIFIED) s->in_rng = s->user_irng; - s->in_lumacoef = ff_get_luma_coefficients(s->in_csp); + s->in_lumacoef = av_csp_luma_coeffs_from_avcsp(s->in_csp); if (!s->in_lumacoef) { av_log(ctx, AV_LOG_ERROR, "Unsupported input colorspace %d (%s)\n", @@ -612,7 +567,7 @@ static int create_filtergraph(AVFilterContext *ctx, if (!s->out_lumacoef) { s->out_csp = out->colorspace; s->out_rng = out->color_range; - s->out_lumacoef = ff_get_luma_coefficients(s->out_csp); + s->out_lumacoef = av_csp_luma_coeffs_from_avcsp(s->out_csp); if (!s->out_lumacoef) { if (s->out_csp == AVCOL_SPC_UNSPECIFIED) { if (s->user_all == CS_UNSPECIFIED) { diff --git a/libavfilter/vf_convolution.c b/libavfilter/vf_convolution.c index 6e6fe0d88..9a9c099e6 100644 --- a/libavfilter/vf_convolution.c +++ b/libavfilter/vf_convolution.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/avstring.h" #include "libavutil/imgutils.h" #include "libavutil/intreadwrite.h" diff --git a/libavfilter/vf_convolution_opencl.c b/libavfilter/vf_convolution_opencl.c index d886c7aea..de3d38b55 100644 --- a/libavfilter/vf_convolution_opencl.c +++ b/libavfilter/vf_convolution_opencl.c @@ -18,6 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/common.h" #include "libavutil/imgutils.h" #include "libavutil/mem.h" diff --git a/libavfilter/vf_convolve.c b/libavfilter/vf_convolve.c index 55afb582b..a61a32f00 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 "config_components.h" + #include #include "libavutil/imgutils.h" diff --git a/libavfilter/vf_curves.c b/libavfilter/vf_curves.c index 22a1f8aa7..82e2753f0 100644 --- a/libavfilter/vf_curves.c +++ b/libavfilter/vf_curves.c @@ -416,7 +416,7 @@ static int dump_curves(const char *fname, uint16_t *graph[NB_COMP + 1], AVBPrint buf; const double scale = 1. / (lut_size - 1); static const char * const colors[] = { "red", "green", "blue", "#404040", }; - FILE *f = av_fopen_utf8(fname, "w"); + FILE *f = avpriv_fopen_utf8(fname, "w"); av_assert0(FF_ARRAY_ELEMS(colors) == NB_COMP + 1); diff --git a/libavfilter/vf_dblur.c b/libavfilter/vf_dblur.c index e82102990..131a3ae30 100644 --- a/libavfilter/vf_dblur.c +++ b/libavfilter/vf_dblur.c @@ -131,14 +131,24 @@ static const enum AVPixelFormat pix_fmts[] = { 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_GRAY14, AV_PIX_FMT_GRAY16, + AV_PIX_FMT_GRAYF32, AV_PIX_FMT_GBRPF32, AV_PIX_FMT_GBRAPF32, AV_PIX_FMT_NONE }; +static av_cold void uninit(AVFilterContext *ctx) +{ + DBlurContext *s = ctx->priv; + + av_freep(&s->buffer); +} + static int config_input(AVFilterLink *inlink) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); DBlurContext *s = inlink->dst->priv; + uninit(inlink->dst); + s->depth = desc->comp[0].depth; s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w); s->planewidth[0] = s->planewidth[3] = inlink->w; @@ -205,8 +215,10 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) float *bptr = s->buffer; const uint8_t *src = in->data[plane]; const uint16_t *src16 = (const uint16_t *)in->data[plane]; + const float *src32 = (const float *)in->data[plane]; uint8_t *dst = out->data[plane]; uint16_t *dst16 = (uint16_t *)out->data[plane]; + float *dst32 = (float *)out->data[plane]; int y, x; if (!(s->planes & (1 << plane))) { @@ -225,7 +237,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) bptr += width; src += in->linesize[plane]; } - } else { + } else if (s->depth <= 16) { for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { bptr[x] = src16[x]; @@ -233,6 +245,14 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) bptr += width; src16 += in->linesize[plane] / 2; } + } else { + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + memcpy(bptr, src32, width * sizeof(float)); + } + bptr += width; + src32 += in->linesize[plane] / 4; + } } diriir2d(ctx, plane); @@ -246,7 +266,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) bptr += width; dst += out->linesize[plane]; } - } else { + } else if (s->depth <= 16) { for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { dst16[x] = av_clip_uintp2_c(lrintf(bptr[x]), s->depth); @@ -254,6 +274,14 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) bptr += width; dst16 += out->linesize[plane] / 2; } + } else { + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + memcpy(dst32, bptr, width * sizeof(float)); + } + bptr += width; + dst32 += out->linesize[plane] / 4; + } } } @@ -262,13 +290,6 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) return ff_filter_frame(outlink, out); } -static av_cold void uninit(AVFilterContext *ctx) -{ - DBlurContext *s = ctx->priv; - - av_freep(&s->buffer); -} - static const AVFilterPad dblur_inputs[] = { { .name = "default", diff --git a/libavfilter/vf_deblock.c b/libavfilter/vf_deblock.c index b7c6a03d4..770fce0ea 100644 --- a/libavfilter/vf_deblock.c +++ b/libavfilter/vf_deblock.c @@ -337,7 +337,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) s->deblockv(dst + x * s->bpc, out->linesize[plane], FFMIN(block, height), s->ath, s->bth, s->gth, s->dth, s->max); - for (y = block; y < height; y += block) { + for (y = block; y < height - block; y += block) { dst += out->linesize[plane] * block; s->deblockh(dst, out->linesize[plane], @@ -353,6 +353,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) s->ath, s->bth, s->gth, s->dth, s->max); } } + + dst += out->linesize[plane] * block; + for (x = block; x < width; x += block) + s->deblockv(dst + x * s->bpc, out->linesize[plane], + FFMIN(block, height - y), s->ath, s->bth, s->gth, s->dth, s->max); + } if (in != out) diff --git a/libavfilter/vf_decimate.c b/libavfilter/vf_decimate.c index d48823fa2..01404e6fe 100644 --- a/libavfilter/vf_decimate.c +++ b/libavfilter/vf_decimate.c @@ -289,8 +289,8 @@ static int activate(AVFilterContext *ctx) } } - if (ff_inlink_queued_frames(ctx->inputs[INPUT_MAIN]) > 0 && - (dm->ppsrc && ff_inlink_queued_frames(ctx->inputs[INPUT_CLEANSRC]) > 0)) { + if (ff_inlink_queued_frames(ctx->inputs[INPUT_MAIN]) > 0 && (!dm->ppsrc || + (dm->ppsrc && ff_inlink_queued_frames(ctx->inputs[INPUT_CLEANSRC]) > 0))) { ff_filter_set_ready(ctx, 100); } else if (ff_outlink_frame_wanted(ctx->outputs[0])) { if (dm->got_frame[INPUT_MAIN] == 0) diff --git a/libavfilter/vf_deinterlace_vaapi.c b/libavfilter/vf_deinterlace_vaapi.c index 65f319ba9..130456103 100644 --- a/libavfilter/vf_deinterlace_vaapi.c +++ b/libavfilter/vf_deinterlace_vaapi.c @@ -46,6 +46,9 @@ typedef struct DeintVAAPIContext { int queue_count; AVFrame *frame_queue[MAX_REFERENCES]; int extra_delay_for_timestamps; + + int eof; + int prev_pts; } DeintVAAPIContext; static const char *deint_vaapi_mode_name(int mode) @@ -188,9 +191,11 @@ static int deint_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame) void *filter_params_addr = NULL; 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), - input_frame->width, input_frame->height, input_frame->pts); + // NULL frame is used to flush the queue in field mode + if (input_frame) + 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->queue_count < ctx->queue_depth) { ctx->frame_queue[ctx->queue_count++] = input_frame; @@ -208,6 +213,9 @@ static int deint_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame) current_frame_index = ctx->pipeline_caps.num_forward_references; input_frame = ctx->frame_queue[current_frame_index]; + if (!input_frame) + return 0; + input_surface = (VASurfaceID)(uintptr_t)input_frame->data[3]; for (i = 0; i < ctx->pipeline_caps.num_forward_references; i++) forward_references[i] = (VASurfaceID)(uintptr_t) @@ -289,6 +297,8 @@ static int deint_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame) if (ctx->field_rate == 2) { if (field == 0) output_frame->pts = 2 * input_frame->pts; + else if (ctx->eof) + output_frame->pts = 3 * input_frame->pts - ctx->prev_pts; else output_frame->pts = input_frame->pts + ctx->frame_queue[current_frame_index + 1]->pts; @@ -304,6 +314,8 @@ static int deint_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame) break; } + ctx->prev_pts = input_frame->pts; + return err; fail: @@ -313,6 +325,25 @@ fail: return err; } +static int deint_vaapi_request_frame(AVFilterLink *link) +{ + AVFilterContext *avctx = link->src; + DeintVAAPIContext *ctx = avctx->priv; + int ret; + + if (ctx->eof) + return AVERROR_EOF; + + ret = ff_request_frame(link->src->inputs[0]); + if (ret == AVERROR_EOF && ctx->extra_delay_for_timestamps) { + ctx->eof = 1; + deint_vaapi_filter_frame(link->src->inputs[0], NULL); + } else if (ret < 0) + return ret; + + return 0; +} + static av_cold int deint_vaapi_init(AVFilterContext *avctx) { VAAPIVPPContext *vpp_ctx = avctx->priv; @@ -373,9 +404,10 @@ static const AVFilterPad deint_vaapi_inputs[] = { static const AVFilterPad deint_vaapi_outputs[] = { { - .name = "default", - .type = AVMEDIA_TYPE_VIDEO, - .config_props = &deint_vaapi_config_output, + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .request_frame = &deint_vaapi_request_frame, + .config_props = &deint_vaapi_config_output, }, }; diff --git a/libavfilter/vf_derain.c b/libavfilter/vf_derain.c index 0eb7da18d..86e9eb875 100644 --- a/libavfilter/vf_derain.c +++ b/libavfilter/vf_derain.c @@ -62,7 +62,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; DRContext *dr_context = ctx->priv; - DNNReturnType dnn_result; + int dnn_result; AVFrame *out; out = ff_get_video_buffer(outlink, outlink->w, outlink->h); @@ -74,10 +74,10 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) av_frame_copy_props(out, in); dnn_result = ff_dnn_execute_model(&dr_context->dnnctx, in, out); - if (dnn_result != DNN_SUCCESS){ + if (dnn_result != 0){ av_log(ctx, AV_LOG_ERROR, "failed to execute model\n"); av_frame_free(&in); - return AVERROR(EIO); + return dnn_result; } do { async_state = ff_dnn_get_result(&dr_context->dnnctx, &in, &out); diff --git a/libavfilter/vf_deshake.c b/libavfilter/vf_deshake.c index 4f28467bb..b37cffba9 100644 --- a/libavfilter/vf_deshake.c +++ b/libavfilter/vf_deshake.c @@ -353,7 +353,7 @@ static av_cold int init(AVFilterContext *ctx) } if (deshake->filename) - deshake->fp = fopen(deshake->filename, "w"); + deshake->fp = avpriv_fopen_utf8(deshake->filename, "w"); if (deshake->fp) fwrite("Ori x, Avg x, Fin x, Ori y, Avg y, Fin y, Ori angle, Avg angle, Fin angle, Ori zoom, Avg zoom, Fin zoom\n", 1, 104, deshake->fp); diff --git a/libavfilter/vf_deshake_opencl.c b/libavfilter/vf_deshake_opencl.c index 9c761ba5a..c2b5bef89 100644 --- a/libavfilter/vf_deshake_opencl.c +++ b/libavfilter/vf_deshake_opencl.c @@ -134,7 +134,7 @@ typedef struct DebugMatches { // for each frame typedef struct AbsoluteFrameMotion { // Array with the various ringbuffers, indexed via the RingbufferIndices enum - AVFifoBuffer *ringbuffers[RingbufCount]; + AVFifo *ringbuffers[RingbufCount]; // Offset to get to the current frame being processed // (not in bytes) @@ -144,7 +144,7 @@ typedef struct AbsoluteFrameMotion { int data_start_offset; int data_end_offset; - AVFifoBuffer *debug_matches; + AVFifo *debug_matches; } AbsoluteFrameMotion; // Takes care of freeing the arrays within the DebugMatches inside of the @@ -156,18 +156,10 @@ static void free_debug_matches(AbsoluteFrameMotion *afm) { return; } - while (av_fifo_size(afm->debug_matches) > 0) { - av_fifo_generic_read( - afm->debug_matches, - &dm, - sizeof(DebugMatches), - NULL - ); - + while (av_fifo_read(afm->debug_matches, &dm, 1) >= 0) av_freep(&dm.matches); - } - av_fifo_freep(&afm->debug_matches); + av_fifo_freep2(&afm->debug_matches); } // Stores the translation, scale, rotation, and skew deltas between two frames @@ -853,7 +845,7 @@ static IterIndices start_end_for(DeshakeOpenCLContext *deshake_ctx, int length) // clipping the offset into the appropriate range static void ringbuf_float_at( DeshakeOpenCLContext *deshake_ctx, - AVFifoBuffer *values, + AVFifo *values, float *val, int offset ) { @@ -863,7 +855,7 @@ static void ringbuf_float_at( } else { // This expression represents the last valid index in the buffer, // which we use repeatedly at the end of the video. - clip_end = deshake_ctx->smooth_window - (av_fifo_space(values) / sizeof(float)) - 1; + clip_end = deshake_ctx->smooth_window - av_fifo_can_write(values) - 1; } if (deshake_ctx->abs_motion.data_start_offset != -1) { @@ -881,13 +873,7 @@ static void ringbuf_float_at( clip_end ); - av_fifo_generic_peek_at( - values, - val, - offset_clipped * sizeof(float), - sizeof(float), - NULL - ); + av_fifo_peek(values, val, 1, offset_clipped); } // Returns smoothed current frame value of the given buffer of floats based on the @@ -905,7 +891,7 @@ static float smooth( float *gauss_kernel, int length, float max_val, - AVFifoBuffer *values + AVFifo *values ) { float new_large_s = 0, new_small_s = 0, new_best = 0, old, diff_between, percent_of_max, inverted_percent; @@ -1069,7 +1055,7 @@ static av_cold void deshake_opencl_uninit(AVFilterContext *avctx) cl_int cle; for (int i = 0; i < RingbufCount; i++) - av_fifo_freep(&ctx->abs_motion.ringbuffers[i]); + av_fifo_freep2(&ctx->abs_motion.ringbuffers[i]); if (ctx->debug_on) free_debug_matches(&ctx->abs_motion); @@ -1188,10 +1174,8 @@ static int deshake_opencl_init(AVFilterContext *avctx) } for (int i = 0; i < RingbufCount; i++) { - ctx->abs_motion.ringbuffers[i] = av_fifo_alloc_array( - ctx->smooth_window, - sizeof(float) - ); + ctx->abs_motion.ringbuffers[i] = av_fifo_alloc2(ctx->smooth_window, + sizeof(float), 0); if (!ctx->abs_motion.ringbuffers[i]) { err = AVERROR(ENOMEM); @@ -1200,9 +1184,9 @@ static int deshake_opencl_init(AVFilterContext *avctx) } if (ctx->debug_on) { - ctx->abs_motion.debug_matches = av_fifo_alloc_array( + ctx->abs_motion.debug_matches = av_fifo_alloc2( ctx->smooth_window / 2, - sizeof(DebugMatches) + sizeof(DebugMatches), 0 ); if (!ctx->abs_motion.debug_matches) { @@ -1424,12 +1408,9 @@ static int filter_frame(AVFilterLink *link, AVFrame *input_frame) const float luma_h_over_chroma_h = ((float)input_frame->height / (float)chroma_height); if (deshake_ctx->debug_on) { - av_fifo_generic_read( + av_fifo_read( deshake_ctx->abs_motion.debug_matches, - &debug_matches, - sizeof(DebugMatches), - NULL - ); + &debug_matches, 1); } if (input_frame->pkt_duration) { @@ -1441,13 +1422,9 @@ static int filter_frame(AVFilterLink *link, AVFrame *input_frame) // Get the absolute transform data for this frame for (int i = 0; i < RingbufCount; i++) { - av_fifo_generic_peek_at( - deshake_ctx->abs_motion.ringbuffers[i], - &old_vals[i], - deshake_ctx->abs_motion.curr_frame_offset * sizeof(float), - sizeof(float), - NULL - ); + av_fifo_peek(deshake_ctx->abs_motion.ringbuffers[i], + &old_vals[i], 1, + deshake_ctx->abs_motion.curr_frame_offset); } if (deshake_ctx->tripod_mode) { @@ -1842,7 +1819,7 @@ static int queue_frame(AVFilterLink *link, AVFrame *input_frame) { sizeof(cl_mem), &deshake_ctx->brief_pattern} ); - if (av_fifo_size(deshake_ctx->abs_motion.ringbuffers[RingbufX]) == 0) { + if (!av_fifo_can_read(deshake_ctx->abs_motion.ringbuffers[RingbufX])) { // This is the first frame we've been given to queue, meaning there is // no previous frame to match descriptors to @@ -1892,7 +1869,7 @@ static int queue_frame(AVFilterLink *link, AVFrame *input_frame) // old data (and just treat them all as part of the new values) if (deshake_ctx->abs_motion.data_end_offset == -1) { deshake_ctx->abs_motion.data_end_offset = - av_fifo_size(deshake_ctx->abs_motion.ringbuffers[RingbufX]) / sizeof(float) - 1; + av_fifo_can_read(deshake_ctx->abs_motion.ringbuffers[RingbufX]) - 1; } goto no_motion_data; @@ -1934,13 +1911,10 @@ static int queue_frame(AVFilterLink *link, AVFrame *input_frame) // Get the absolute transform data for the previous frame for (int i = 0; i < RingbufCount; i++) { - av_fifo_generic_peek_at( + av_fifo_peek( deshake_ctx->abs_motion.ringbuffers[i], - &prev_vals[i], - av_fifo_size(deshake_ctx->abs_motion.ringbuffers[i]) - sizeof(float), - sizeof(float), - NULL - ); + &prev_vals[i], 1, + av_fifo_can_read(deshake_ctx->abs_motion.ringbuffers[i]) - 1); } new_vals[RingbufX] = prev_vals[RingbufX] + relative.translation.s[0]; @@ -2011,21 +1985,13 @@ end: } debug_matches.num_matches = num_vectors; - av_fifo_generic_write( + av_fifo_write( deshake_ctx->abs_motion.debug_matches, - &debug_matches, - sizeof(DebugMatches), - NULL - ); + &debug_matches, 1); } for (int i = 0; i < RingbufCount; i++) { - av_fifo_generic_write( - deshake_ctx->abs_motion.ringbuffers[i], - &new_vals[i], - sizeof(float), - NULL - ); + av_fifo_write(deshake_ctx->abs_motion.ringbuffers[i], &new_vals[i], 1); } return ff_framequeue_add(&deshake_ctx->fq, input_frame); @@ -2063,9 +2029,9 @@ static int activate(AVFilterContext *ctx) // If there is no more space in the ringbuffers, remove the oldest // values to make room for the new ones - if (av_fifo_space(deshake_ctx->abs_motion.ringbuffers[RingbufX]) == 0) { + if (!av_fifo_can_write(deshake_ctx->abs_motion.ringbuffers[RingbufX])) { for (int i = 0; i < RingbufCount; i++) { - av_fifo_drain(deshake_ctx->abs_motion.ringbuffers[i], sizeof(float)); + av_fifo_drain2(deshake_ctx->abs_motion.ringbuffers[i], 1); } } ret = queue_frame(inlink, frame); @@ -2092,7 +2058,7 @@ static int activate(AVFilterContext *ctx) // Finish processing the rest of the frames in the queue. while(ff_framequeue_queued_frames(&deshake_ctx->fq) != 0) { for (int i = 0; i < RingbufCount; i++) { - av_fifo_drain(deshake_ctx->abs_motion.ringbuffers[i], sizeof(float)); + av_fifo_drain2(deshake_ctx->abs_motion.ringbuffers[i], 1); } ret = filter_frame(inlink, ff_framequeue_take(&deshake_ctx->fq)); diff --git a/libavfilter/vf_dnn_classify.c b/libavfilter/vf_dnn_classify.c index 5c6942d86..852f5ddce 100644 --- a/libavfilter/vf_dnn_classify.c +++ b/libavfilter/vf_dnn_classify.c @@ -131,7 +131,7 @@ static int read_classify_label_file(AVFilterContext *context) FILE *file; DnnClassifyContext *ctx = context->priv; - file = av_fopen_utf8(ctx->labels_filename, "r"); + file = avpriv_fopen_utf8(ctx->labels_filename, "r"); if (!file){ av_log(context, AV_LOG_ERROR, "failed to open file %s\n", ctx->labels_filename); return AVERROR(EINVAL); @@ -213,7 +213,7 @@ static int dnn_classify_flush_frame(AVFilterLink *outlink, int64_t pts, int64_t DNNAsyncStatusType async_state; ret = ff_dnn_flush(&ctx->dnnctx); - if (ret != DNN_SUCCESS) { + if (ret != 0) { return -1; } @@ -253,7 +253,7 @@ static int dnn_classify_activate(AVFilterContext *filter_ctx) if (ret < 0) return ret; if (ret > 0) { - if (ff_dnn_execute_model_classification(&ctx->dnnctx, in, NULL, ctx->target) != DNN_SUCCESS) { + if (ff_dnn_execute_model_classification(&ctx->dnnctx, in, NULL, ctx->target) != 0) { return AVERROR(EIO); } } diff --git a/libavfilter/vf_dnn_detect.c b/libavfilter/vf_dnn_detect.c index 51f8b430d..68bd2cd0c 100644 --- a/libavfilter/vf_dnn_detect.c +++ b/libavfilter/vf_dnn_detect.c @@ -244,7 +244,7 @@ static int read_detect_label_file(AVFilterContext *context) FILE *file; DnnDetectContext *ctx = context->priv; - file = av_fopen_utf8(ctx->labels_filename, "r"); + file = avpriv_fopen_utf8(ctx->labels_filename, "r"); if (!file){ av_log(context, AV_LOG_ERROR, "failed to open file %s\n", ctx->labels_filename); return AVERROR(EINVAL); @@ -356,7 +356,7 @@ static int dnn_detect_flush_frame(AVFilterLink *outlink, int64_t pts, int64_t *o DNNAsyncStatusType async_state; ret = ff_dnn_flush(&ctx->dnnctx); - if (ret != DNN_SUCCESS) { + if (ret != 0) { return -1; } @@ -396,7 +396,7 @@ static int dnn_detect_activate(AVFilterContext *filter_ctx) if (ret < 0) return ret; if (ret > 0) { - if (ff_dnn_execute_model(&ctx->dnnctx, in, NULL) != DNN_SUCCESS) { + if (ff_dnn_execute_model(&ctx->dnnctx, in, NULL) != 0) { return AVERROR(EIO); } } diff --git a/libavfilter/vf_dnn_processing.c b/libavfilter/vf_dnn_processing.c index c5ca36ef0..cac096a19 100644 --- a/libavfilter/vf_dnn_processing.c +++ b/libavfilter/vf_dnn_processing.c @@ -134,14 +134,14 @@ static int config_input(AVFilterLink *inlink) { AVFilterContext *context = inlink->dst; DnnProcessingContext *ctx = context->priv; - DNNReturnType result; + int result; DNNData model_input; int check; result = ff_dnn_get_input(&ctx->dnnctx, &model_input); - if (result != DNN_SUCCESS) { + if (result != 0) { av_log(ctx, AV_LOG_ERROR, "could not get input from the model\n"); - return AVERROR(EIO); + return result; } check = check_modelinput_inlink(&model_input, inlink); @@ -194,14 +194,14 @@ static int config_output(AVFilterLink *outlink) { AVFilterContext *context = outlink->src; DnnProcessingContext *ctx = context->priv; - DNNReturnType result; + int result; AVFilterLink *inlink = context->inputs[0]; // have a try run in case that the dnn model resize the frame result = ff_dnn_get_output(&ctx->dnnctx, inlink->w, inlink->h, &outlink->w, &outlink->h); - if (result != DNN_SUCCESS) { + if (result != 0) { av_log(ctx, AV_LOG_ERROR, "could not get output from the model\n"); - return AVERROR(EIO); + return result; } prepare_uv_scale(outlink); @@ -247,7 +247,7 @@ static int flush_frame(AVFilterLink *outlink, int64_t pts, int64_t *out_pts) DNNAsyncStatusType async_state; ret = ff_dnn_flush(&ctx->dnnctx); - if (ret != DNN_SUCCESS) { + if (ret != 0) { return -1; } @@ -296,7 +296,7 @@ static int activate(AVFilterContext *filter_ctx) return AVERROR(ENOMEM); } av_frame_copy_props(out, in); - if (ff_dnn_execute_model(&ctx->dnnctx, in, out) != DNN_SUCCESS) { + if (ff_dnn_execute_model(&ctx->dnnctx, in, out) != 0) { return AVERROR(EIO); } } diff --git a/libavfilter/vf_drawbox.c b/libavfilter/vf_drawbox.c index 919652e50..65bd039d6 100644 --- a/libavfilter/vf_drawbox.c +++ b/libavfilter/vf_drawbox.c @@ -25,6 +25,8 @@ * that needs to write in the input frame. */ +#include "config_components.h" + #include "libavutil/colorspace.h" #include "libavutil/common.h" #include "libavutil/opt.h" @@ -33,6 +35,7 @@ #include "libavutil/parseutils.h" #include "libavutil/detection_bbox.h" #include "avfilter.h" +#include "drawutils.h" #include "formats.h" #include "internal.h" #include "video.h" @@ -53,6 +56,7 @@ static const char *const var_names[] = { }; enum { Y, U, V, A }; +enum { R, G, B }; enum var_name { VAR_DAR, @@ -69,11 +73,17 @@ enum var_name { VARS_NB }; +struct DrawBoxContext; + +typedef int (*PixelBelongsToRegion)(struct DrawBoxContext *s, int x, int y); + typedef struct DrawBoxContext { const AVClass *class; int x, y, w, h; int thickness; char *color_str; + uint8_t rgba_map[4]; + uint8_t rgba_color[4]; unsigned char yuv_color[4]; int invert_color; ///< invert luma color int vsub, hsub; ///< chroma subsampling @@ -83,13 +93,15 @@ typedef struct DrawBoxContext { char *box_source_string; ///< string for box data source int have_alpha; int replace; + int step; enum AVFrameSideDataType box_source; + + void (*draw_region)(AVFrame *frame, struct DrawBoxContext *ctx, int left, int top, int right, int down, + PixelBelongsToRegion pixel_belongs_to_region); } DrawBoxContext; static const int NUM_EXPR_EVALS = 5; -typedef int (*PixelBelongsToRegion)(DrawBoxContext *s, int x, int y); - #define ASSIGN_THREE_CHANNELS \ row[0] = frame->data[0] + y * frame->linesize[0]; \ row[1] = frame->data[1] + (y >> ctx->vsub) * frame->linesize[1]; \ @@ -144,6 +156,67 @@ static void draw_region(AVFrame *frame, DrawBoxContext *ctx, int left, int top, } } +#define ASSIGN_THREE_CHANNELS_PACKED \ + row[0] = frame->data[0] + y * frame->linesize[0] + ctx->rgba_map[0]; \ + row[1] = frame->data[0] + y * frame->linesize[0] + ctx->rgba_map[1]; \ + row[2] = frame->data[0] + y * frame->linesize[0] + ctx->rgba_map[2]; + +#define ASSIGN_FOUR_CHANNELS_PACKED \ + ASSIGN_THREE_CHANNELS \ + row[3] = frame->data[0] + y * frame->linesize[0] + ctx->rgba_map[3]; + +static void draw_region_rgb_packed(AVFrame *frame, DrawBoxContext *ctx, int left, int top, int right, int down, + PixelBelongsToRegion pixel_belongs_to_region) +{ + const int C = ctx->step; + uint8_t *row[4]; + + if (ctx->have_alpha && ctx->replace) { + for (int y = top; y < down; y++) { + ASSIGN_FOUR_CHANNELS_PACKED + if (ctx->invert_color) { + for (int x = left; x < right; x++) + if (pixel_belongs_to_region(ctx, x, y)) { + row[0][x*C] = 0xff - row[0][x*C]; + row[1][x*C] = 0xff - row[1][x*C]; + row[2][x*C] = 0xff - row[2][x*C]; + } + } else { + for (int x = left; x < right; x++) { + if (pixel_belongs_to_region(ctx, x, y)) { + row[0][x*C] = ctx->rgba_color[R]; + row[1][x*C] = ctx->rgba_color[G]; + row[2][x*C] = ctx->rgba_color[B]; + row[3][x*C] = ctx->rgba_color[A]; + } + } + } + } + } else { + for (int y = top; y < down; y++) { + ASSIGN_THREE_CHANNELS_PACKED + if (ctx->invert_color) { + for (int x = left; x < right; x++) + if (pixel_belongs_to_region(ctx, x, y)) { + row[0][x*C] = 0xff - row[0][x*C]; + row[1][x*C] = 0xff - row[1][x*C]; + row[2][x*C] = 0xff - row[2][x*C]; + } + } else { + for (int x = left; x < right; x++) { + float alpha = (float)ctx->rgba_color[A] / 255.f; + + if (pixel_belongs_to_region(ctx, x, y)) { + row[0][x*C] = (1.f - alpha) * row[0][x*C] + alpha * ctx->rgba_color[R]; + row[1][x*C] = (1.f - alpha) * row[1][x*C] + alpha * ctx->rgba_color[G]; + row[2][x*C] = (1.f - alpha) * row[2][x*C] + alpha * ctx->rgba_color[B]; + } + } + } + } + } +} + static enum AVFrameSideDataType box_source_string_parse(const char *box_source_string) { av_assert0(box_source_string); @@ -158,7 +231,6 @@ static enum AVFrameSideDataType box_source_string_parse(const char *box_source_s static av_cold int init(AVFilterContext *ctx) { DrawBoxContext *s = ctx->priv; - uint8_t rgba_color[4]; if (s->box_source_string) { s->box_source = box_source_string_parse(s->box_source_string); @@ -170,14 +242,14 @@ static av_cold int init(AVFilterContext *ctx) if (!strcmp(s->color_str, "invert")) s->invert_color = 1; - else if (av_parse_color(rgba_color, s->color_str, -1, ctx) < 0) + else if (av_parse_color(s->rgba_color, s->color_str, -1, ctx) < 0) return AVERROR(EINVAL); if (!s->invert_color) { - s->yuv_color[Y] = RGB_TO_Y_CCIR(rgba_color[0], rgba_color[1], rgba_color[2]); - s->yuv_color[U] = RGB_TO_U_CCIR(rgba_color[0], rgba_color[1], rgba_color[2], 0); - s->yuv_color[V] = RGB_TO_V_CCIR(rgba_color[0], rgba_color[1], rgba_color[2], 0); - s->yuv_color[A] = rgba_color[3]; + s->yuv_color[Y] = RGB_TO_Y_CCIR(s->rgba_color[0], s->rgba_color[1], s->rgba_color[2]); + s->yuv_color[U] = RGB_TO_U_CCIR(s->rgba_color[0], s->rgba_color[1], s->rgba_color[2], 0); + s->yuv_color[V] = RGB_TO_V_CCIR(s->rgba_color[0], s->rgba_color[1], s->rgba_color[2], 0); + s->yuv_color[A] = s->rgba_color[3]; } return 0; @@ -189,6 +261,11 @@ static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24, + AV_PIX_FMT_RGBA, AV_PIX_FMT_BGRA, + AV_PIX_FMT_ARGB, AV_PIX_FMT_ABGR, + AV_PIX_FMT_0RGB, AV_PIX_FMT_0BGR, + AV_PIX_FMT_RGB0, AV_PIX_FMT_BGR0, AV_PIX_FMT_NONE }; @@ -202,6 +279,14 @@ static int config_input(AVFilterLink *inlink) int ret; int i; + ff_fill_rgba_map(s->rgba_map, inlink->format); + + if (!(desc->flags & AV_PIX_FMT_FLAG_RGB)) + s->draw_region = draw_region; + else + s->draw_region = draw_region_rgb_packed; + + s->step = av_get_padded_bits_per_pixel(desc) >> 3; s->hsub = desc->log2_chroma_w; s->vsub = desc->log2_chroma_h; s->have_alpha = desc->flags & AV_PIX_FMT_FLAG_ALPHA; @@ -313,8 +398,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) s->w = bbox->w; } - draw_region(frame, s, FFMAX(s->x, 0), FFMAX(s->y, 0), FFMIN(s->x + s->w, frame->width), - FFMIN(s->y + s->h, frame->height), pixel_belongs_to_box); + s->draw_region(frame, s, FFMAX(s->x, 0), FFMAX(s->y, 0), FFMIN(s->x + s->w, frame->width), + FFMIN(s->y + s->h, frame->height), pixel_belongs_to_box); } return ff_filter_frame(inlink->dst->outputs[0], frame); @@ -436,7 +521,7 @@ static int drawgrid_filter_frame(AVFilterLink *inlink, AVFrame *frame) { DrawBoxContext *drawgrid = inlink->dst->priv; - draw_region(frame, drawgrid, 0, 0, frame->width, frame->height, pixel_belongs_to_grid); + drawgrid->draw_region(frame, drawgrid, 0, 0, frame->width, frame->height, pixel_belongs_to_grid); return ff_filter_frame(inlink->dst->outputs[0], frame); } diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c index 2a88692cb..feb689884 100644 --- a/libavfilter/vf_drawtext.c +++ b/libavfilter/vf_drawtext.c @@ -51,6 +51,7 @@ #include "libavutil/opt.h" #include "libavutil/random_seed.h" #include "libavutil/parseutils.h" +#include "libavutil/time.h" #include "libavutil/timecode.h" #include "libavutil/time_internal.h" #include "libavutil/tree.h" @@ -198,7 +199,7 @@ typedef struct DrawTextContext { AVRational tc_rate; ///< frame rate for timecode AVTimecode tc; ///< timecode context int tc24hmax; ///< 1 if timecode is wrapped to 24 hours, 0 otherwise - int reload; ///< reload text file for each frame + int reload; ///< reload text file at specified frame interval int start_number; ///< starting frame number for n/frame_num var char *text_source_string; ///< the string to specify text data source enum AVFrameSideDataType text_source; @@ -245,7 +246,7 @@ static const AVOption drawtext_options[]= { {"timecode_rate", "set rate (timecode only)", OFFSET(tc_rate), AV_OPT_TYPE_RATIONAL, {.dbl=0}, 0, INT_MAX, FLAGS}, {"r", "set rate (timecode only)", OFFSET(tc_rate), AV_OPT_TYPE_RATIONAL, {.dbl=0}, 0, INT_MAX, FLAGS}, {"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}, + {"reload", "reload text file at specified frame interval", OFFSET(reload), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, 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=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}, @@ -1045,15 +1046,78 @@ static int func_strftime(AVFilterContext *ctx, AVBPrint *bp, char *fct, unsigned argc, char **argv, int tag) { const char *fmt = argc ? argv[0] : "%Y-%m-%d %H:%M:%S"; + const char *fmt_begin = fmt; + int64_t unow; time_t now; struct tm tm; + const char *begin; + const char *tmp; + int len; + int div; + AVBPrint fmt_bp; - time(&now); - if (tag == 'L') + av_bprint_init(&fmt_bp, 0, AV_BPRINT_SIZE_UNLIMITED); + + unow = av_gettime(); + now = unow / 1000000; + if (tag == 'L' || tag == 'm') localtime_r(&now, &tm); else tm = *gmtime_r(&now, &tm); - av_bprint_strftime(bp, fmt, &tm); + + // manually parse format for %N (fractional seconds) + begin = fmt; + while ((begin = strchr(begin, '%'))) { + tmp = begin + 1; + len = 0; + + // skip escaped "%%" + if (*tmp == '%') { + begin = tmp + 1; + continue; + } + + // count digits between % and possible N + while (*tmp != '\0' && av_isdigit((int)*tmp)) { + len++; + tmp++; + } + + // N encountered, insert time + if (*tmp == 'N') { + int num_digits = 3; // default show millisecond [1,6] + + // if digit given, expect [1,6], warn & clamp otherwise + if (len == 1) { + num_digits = av_clip(*(begin + 1) - '0', 1, 6); + } else if (len > 1) { + av_log(ctx, AV_LOG_WARNING, "Invalid number of decimals for %%N, using default of %i\n", num_digits); + } + + len += 2; // add % and N to get length of string part + + div = pow(10, 6 - num_digits); + + av_bprintf(&fmt_bp, "%.*s%0*d", (int)(begin - fmt_begin), fmt_begin, num_digits, (int)(unow % 1000000) / div); + + begin += len; + fmt_begin = begin; + + continue; + } + + begin = tmp; + } + + av_bprintf(&fmt_bp, "%s", fmt_begin); + if (!av_bprint_is_complete(&fmt_bp)) { + av_log(ctx, AV_LOG_WARNING, "Format string truncated at %u/%u.", fmt_bp.size, fmt_bp.len); + } + + av_bprint_strftime(bp, fmt_bp.str, &tm); + + av_bprint_finalize(&fmt_bp, NULL); + return 0; } @@ -1565,7 +1629,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) } } - if (s->reload) { + if (s->reload && !(inlink->frame_count_out % s->reload)) { if ((ret = load_textfile(ctx)) < 0) { av_frame_free(&frame); return ret; diff --git a/libavfilter/vf_edgedetect.c b/libavfilter/vf_edgedetect.c index 3eea34e32..90390ceb3 100644 --- a/libavfilter/vf_edgedetect.c +++ b/libavfilter/vf_edgedetect.c @@ -32,6 +32,7 @@ #include "formats.h" #include "internal.h" #include "video.h" +#include "edge_common.h" #define PLANE_R 0x4 #define PLANE_G 0x1 @@ -139,176 +140,6 @@ static int config_props(AVFilterLink *inlink) return 0; } -static void gaussian_blur(AVFilterContext *ctx, int w, int h, - uint8_t *dst, int dst_linesize, - const uint8_t *src, int src_linesize) -{ - int i, j; - - memcpy(dst, src, w); dst += dst_linesize; src += src_linesize; - if (h > 1) { - memcpy(dst, src, w); dst += dst_linesize; src += src_linesize; - } - for (j = 2; j < h - 2; j++) { - dst[0] = src[0]; - if (w > 1) - dst[1] = src[1]; - for (i = 2; i < w - 2; i++) { - /* Gaussian mask of size 5x5 with sigma = 1.4 */ - dst[i] = ((src[-2*src_linesize + i-2] + src[2*src_linesize + i-2]) * 2 - + (src[-2*src_linesize + i-1] + src[2*src_linesize + i-1]) * 4 - + (src[-2*src_linesize + i ] + src[2*src_linesize + i ]) * 5 - + (src[-2*src_linesize + i+1] + src[2*src_linesize + i+1]) * 4 - + (src[-2*src_linesize + i+2] + src[2*src_linesize + i+2]) * 2 - - + (src[ -src_linesize + i-2] + src[ src_linesize + i-2]) * 4 - + (src[ -src_linesize + i-1] + src[ src_linesize + i-1]) * 9 - + (src[ -src_linesize + i ] + src[ src_linesize + i ]) * 12 - + (src[ -src_linesize + i+1] + src[ src_linesize + i+1]) * 9 - + (src[ -src_linesize + i+2] + src[ src_linesize + i+2]) * 4 - - + src[i-2] * 5 - + src[i-1] * 12 - + src[i ] * 15 - + src[i+1] * 12 - + src[i+2] * 5) / 159; - } - if (w > 2) - dst[i ] = src[i ]; - if (w > 3) - dst[i + 1] = src[i + 1]; - - dst += dst_linesize; - src += src_linesize; - } - if (h > 2) { - memcpy(dst, src, w); dst += dst_linesize; src += src_linesize; - } - if (h > 3) - memcpy(dst, src, w); -} - -enum { - DIRECTION_45UP, - DIRECTION_45DOWN, - DIRECTION_HORIZONTAL, - DIRECTION_VERTICAL, -}; - -static int get_rounded_direction(int gx, int gy) -{ - /* reference angles: - * tan( pi/8) = sqrt(2)-1 - * tan(3pi/8) = sqrt(2)+1 - * Gy/Gx is the tangent of the angle (theta), so Gy/Gx is compared against - * , or more simply Gy against *Gx - * - * Gx and Gy bounds = [-1020;1020], using 16-bit arithmetic: - * round((sqrt(2)-1) * (1<<16)) = 27146 - * round((sqrt(2)+1) * (1<<16)) = 158218 - */ - if (gx) { - int tanpi8gx, tan3pi8gx; - - if (gx < 0) - gx = -gx, gy = -gy; - gy *= (1 << 16); - tanpi8gx = 27146 * gx; - tan3pi8gx = 158218 * gx; - if (gy > -tan3pi8gx && gy < -tanpi8gx) return DIRECTION_45UP; - if (gy > -tanpi8gx && gy < tanpi8gx) return DIRECTION_HORIZONTAL; - if (gy > tanpi8gx && gy < tan3pi8gx) return DIRECTION_45DOWN; - } - return DIRECTION_VERTICAL; -} - -static void sobel(int w, int h, - uint16_t *dst, int dst_linesize, - int8_t *dir, int dir_linesize, - const uint8_t *src, int src_linesize) -{ - int i, j; - - for (j = 1; j < h - 1; j++) { - dst += dst_linesize; - dir += dir_linesize; - src += src_linesize; - for (i = 1; i < w - 1; i++) { - const int gx = - -1*src[-src_linesize + i-1] + 1*src[-src_linesize + i+1] - -2*src[ i-1] + 2*src[ i+1] - -1*src[ src_linesize + i-1] + 1*src[ src_linesize + i+1]; - const int gy = - -1*src[-src_linesize + i-1] + 1*src[ src_linesize + i-1] - -2*src[-src_linesize + i ] + 2*src[ src_linesize + i ] - -1*src[-src_linesize + i+1] + 1*src[ src_linesize + i+1]; - - dst[i] = FFABS(gx) + FFABS(gy); - dir[i] = get_rounded_direction(gx, gy); - } - } -} - -static void non_maximum_suppression(int w, int h, - uint8_t *dst, int dst_linesize, - const int8_t *dir, int dir_linesize, - const uint16_t *src, int src_linesize) -{ - int i, j; - -#define COPY_MAXIMA(ay, ax, by, bx) do { \ - if (src[i] > src[(ay)*src_linesize + i+(ax)] && \ - src[i] > src[(by)*src_linesize + i+(bx)]) \ - dst[i] = av_clip_uint8(src[i]); \ -} while (0) - - for (j = 1; j < h - 1; j++) { - dst += dst_linesize; - dir += dir_linesize; - src += src_linesize; - for (i = 1; i < w - 1; i++) { - switch (dir[i]) { - case DIRECTION_45UP: COPY_MAXIMA( 1, -1, -1, 1); break; - case DIRECTION_45DOWN: COPY_MAXIMA(-1, -1, 1, 1); break; - case DIRECTION_HORIZONTAL: COPY_MAXIMA( 0, -1, 0, 1); break; - case DIRECTION_VERTICAL: COPY_MAXIMA(-1, 0, 1, 0); break; - } - } - } -} - -static void double_threshold(int low, int high, int w, int h, - uint8_t *dst, int dst_linesize, - const uint8_t *src, int src_linesize) -{ - int i, j; - - for (j = 0; j < h; j++) { - for (i = 0; i < w; i++) { - if (src[i] > high) { - dst[i] = src[i]; - continue; - } - - if (!(!i || i == w - 1 || !j || j == h - 1) && - src[i] > low && - (src[-src_linesize + i-1] > high || - src[-src_linesize + i ] > high || - src[-src_linesize + i+1] > high || - src[ i-1] > high || - src[ i+1] > high || - src[ src_linesize + i-1] > high || - src[ src_linesize + i ] > high || - src[ src_linesize + i+1] > high)) - dst[i] = src[i]; - else - dst[i] = 0; - } - dst += dst_linesize; - src += src_linesize; - } -} - static void color_mix(int w, int h, uint8_t *dst, int dst_linesize, const uint8_t *src, int src_linesize) @@ -360,12 +191,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) } /* gaussian filter to reduce noise */ - gaussian_blur(ctx, width, height, - tmpbuf, width, - in->data[p], in->linesize[p]); + ff_gaussian_blur(width, height, + tmpbuf, width, + in->data[p], in->linesize[p]); /* compute the 16-bits gradients and directions for the next step */ - sobel(width, height, + ff_sobel(width, height, gradients, width, directions,width, tmpbuf, width); @@ -373,13 +204,13 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) /* non_maximum_suppression() will actually keep & clip what's necessary and * ignore the rest, so we need a clean output buffer */ memset(tmpbuf, 0, width * height); - non_maximum_suppression(width, height, + ff_non_maximum_suppression(width, height, tmpbuf, width, directions,width, gradients, width); /* keep high values, or low values surrounded by high values */ - double_threshold(edgedetect->low_u8, edgedetect->high_u8, + ff_double_threshold(edgedetect->low_u8, edgedetect->high_u8, width, height, out->data[p], out->linesize[p], tmpbuf, width); diff --git a/libavfilter/vf_epx.c b/libavfilter/vf_epx.c index 9d79648ac..d706229ab 100644 --- a/libavfilter/vf_epx.c +++ b/libavfilter/vf_epx.c @@ -100,7 +100,7 @@ static int epx2_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) src_line[1] = src_line[2]; src_line[2] = src_line[1]; - if (y < height - 1) + if (y < height - 2) src_line[2] += src_linesize; } } @@ -187,7 +187,7 @@ static int epx3_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) src_line[1] = src_line[2]; src_line[2] = src_line[1]; - if (y < height - 1) + if (y < height - 2) src_line[2] += src_linesize; } } diff --git a/libavfilter/vf_eq.c b/libavfilter/vf_eq.c index 80ab21efb..46636dd29 100644 --- a/libavfilter/vf_eq.c +++ b/libavfilter/vf_eq.c @@ -74,26 +74,6 @@ static void apply_lut(EQParameters *param, uint8_t *dst, int dst_stride, } } -static void process_c(EQParameters *param, uint8_t *dst, int dst_stride, - const uint8_t *src, int src_stride, int w, int h) -{ - int x, y, pel; - - int contrast = (int) (param->contrast * 256 * 16); - int brightness = ((int) (100.0 * param->brightness + 100.0) * 511) / 200 - 128 - contrast / 32; - - for (y = 0; y < h; y++) { - for (x = 0; x < w; x++) { - pel = ((src[y * src_stride + x] * contrast) >> 12) + brightness; - - if (pel & ~255) - pel = (-pel) >> 31; - - dst[y * dst_stride + x] = pel; - } - } -} - static void check_values(EQParameters *param, EQContext *eq) { if (param->contrast == 1.0 && param->brightness == 0.0 && param->gamma == 1.0) @@ -174,13 +154,6 @@ static int set_expr(AVExpr **pexpr, const char *expr, const char *option, void * return 0; } -void ff_eq_init(EQContext *eq) -{ - eq->process = process_c; - if (ARCH_X86) - ff_eq_init_x86(eq); -} - static int initialize(AVFilterContext *ctx) { EQContext *eq = ctx->priv; diff --git a/libavfilter/vf_eq.h b/libavfilter/vf_eq.h index cd0cd75f0..fc8d4a711 100644 --- a/libavfilter/vf_eq.h +++ b/libavfilter/vf_eq.h @@ -100,7 +100,32 @@ typedef struct EQContext { enum EvalMode { EVAL_MODE_INIT, EVAL_MODE_FRAME, EVAL_MODE_NB } eval_mode; } EQContext; -void ff_eq_init(EQContext *eq); +static void process_c(EQParameters *param, uint8_t *dst, int dst_stride, + const uint8_t *src, int src_stride, int w, int h) +{ + int contrast = (int) (param->contrast * 256 * 16); + int brightness = ((int) (100.0 * param->brightness + 100.0) * 511) / 200 - 128 - contrast / 32; + + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) { + int pel = ((src[y * src_stride + x] * contrast) >> 12) + brightness; + + if (pel & ~255) + pel = (-pel) >> 31; + + dst[y * dst_stride + x] = pel; + } + } +} + void ff_eq_init_x86(EQContext *eq); +static av_unused void ff_eq_init(EQContext *eq) +{ + eq->process = process_c; +#if ARCH_X86 + ff_eq_init_x86(eq); +#endif +} + #endif /* AVFILTER_EQ_H */ diff --git a/libavfilter/vf_estdif.c b/libavfilter/vf_estdif.c index 0e5c9b422..45089a01d 100644 --- a/libavfilter/vf_estdif.c +++ b/libavfilter/vf_estdif.c @@ -95,7 +95,7 @@ static const AVOption estdif_options[] = { CONST("interlaced", "only deinterlace frames marked as interlaced", 1, "deint"), { "rslope", "specify the search radius for edge slope tracing", OFFSET(rslope), AV_OPT_TYPE_INT, {.i64=1}, 1, MAX_R, FLAGS, }, { "redge", "specify the search radius for best edge matching", OFFSET(redge), AV_OPT_TYPE_INT, {.i64=2}, 0, MAX_R, FLAGS, }, - { "ecost", "specify the edge cost for edge matching", OFFSET(ecost), AV_OPT_TYPE_FLOAT,{.dbl=0.03125},0,1,FLAGS, }, + { "ecost", "specify the edge cost for edge matching", OFFSET(ecost), AV_OPT_TYPE_FLOAT,{.dbl=1},0,9,FLAGS, }, { "mcost", "specify the middle cost for edge matching", OFFSET(mcost), AV_OPT_TYPE_FLOAT,{.dbl=0.5}, 0, 1, FLAGS, }, { "dcost", "specify the distance cost for edge matching", OFFSET(dcost), AV_OPT_TYPE_FLOAT,{.dbl=0.5}, 0, 1, FLAGS, }, { "interp", "specify the type of interpolation", OFFSET(interp), AV_OPT_TYPE_INT, {.i64=1}, 0, 2, FLAGS, "interp" }, @@ -137,9 +137,11 @@ static int config_output(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; AVFilterLink *inlink = ctx->inputs[0]; + ESTDIFContext *s = ctx->priv; outlink->time_base = av_mul_q(inlink->time_base, (AVRational){1, 2}); - outlink->frame_rate = av_mul_q(inlink->frame_rate, (AVRational){2, 1}); + if (s->mode) + outlink->frame_rate = av_mul_q(inlink->frame_rate, (AVRational){2, 1}); return 0; } diff --git a/libavfilter/vf_extractplanes.c b/libavfilter/vf_extractplanes.c index 80fbc6e4b..60b55578c 100644 --- a/libavfilter/vf_extractplanes.c +++ b/libavfilter/vf_extractplanes.c @@ -18,6 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/avstring.h" #include "libavutil/imgutils.h" #include "libavutil/opt.h" @@ -81,7 +83,12 @@ AVFILTER_DEFINE_CLASS(extractplanes); AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP #define HIGHDEPTH_FORMATS(suf) \ - AV_PIX_FMT_YA16##suf, AV_PIX_FMT_GRAY16##suf, \ + AV_PIX_FMT_YA16##suf, \ + AV_PIX_FMT_GRAY9##suf, \ + AV_PIX_FMT_GRAY10##suf, \ + AV_PIX_FMT_GRAY12##suf, \ + AV_PIX_FMT_GRAY14##suf, \ + AV_PIX_FMT_GRAY16##suf, \ AV_PIX_FMT_YUV420P16##suf, AV_PIX_FMT_YUVA420P16##suf, \ AV_PIX_FMT_YUV422P16##suf, AV_PIX_FMT_YUVA422P16##suf, \ AV_PIX_FMT_YUV444P16##suf, AV_PIX_FMT_YUVA444P16##suf, \ @@ -283,52 +290,82 @@ static void extract_from_packed(uint8_t *dst, int dst_linesize, } } -static int filter_frame(AVFilterLink *inlink, AVFrame *frame) +static int extract_plane(AVFilterLink *outlink, AVFrame *frame) { - AVFilterContext *ctx = inlink->dst; + AVFilterContext *ctx = outlink->src; ExtractPlanesContext *s = ctx->priv; - int i, eof = 0, ret = 0; + const int idx = s->map[FF_OUTLINK_IDX(outlink)]; + AVFrame *out; - for (i = 0; i < ctx->nb_outputs; i++) { - AVFilterLink *outlink = ctx->outputs[i]; - const int idx = s->map[i]; - AVFrame *out; + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) + return AVERROR(ENOMEM); + av_frame_copy_props(out, frame); - if (ff_outlink_get_status(outlink)) + if (s->is_packed) { + extract_from_packed(out->data[0], out->linesize[0], + frame->data[0], frame->linesize[0], + outlink->w, outlink->h, + s->depth, + s->step, idx); + } else { + av_image_copy_plane(out->data[0], out->linesize[0], + frame->data[idx], frame->linesize[idx], + s->linesize[idx], outlink->h); + } + + return ff_filter_frame(outlink, out); +} + +static int activate(AVFilterContext *ctx) +{ + AVFilterLink *inlink = ctx->inputs[0]; + int status, ret; + AVFrame *in; + int64_t pts; + + for (int i = 0; i < ctx->nb_outputs; i++) { + FF_FILTER_FORWARD_STATUS_BACK_ALL(ctx->outputs[i], ctx); + } + + ret = ff_inlink_consume_frame(inlink, &in); + if (ret < 0) + return ret; + if (ret > 0) { + for (int i = 0; i < ctx->nb_outputs; i++) { + if (ff_outlink_get_status(ctx->outputs[i])) + continue; + + ret = extract_plane(ctx->outputs[i], in); + if (ret < 0) + break; + } + + av_frame_free(&in); + if (ret < 0) + return ret; + } + + if (ff_inlink_acknowledge_status(inlink, &status, &pts)) { + for (int i = 0; i < ctx->nb_outputs; i++) { + if (ff_outlink_get_status(ctx->outputs[i])) + continue; + ff_outlink_set_status(ctx->outputs[i], status, pts); + } + return 0; + } + + for (int i = 0; i < ctx->nb_outputs; i++) { + if (ff_outlink_get_status(ctx->outputs[i])) continue; - out = ff_get_video_buffer(outlink, outlink->w, outlink->h); - if (!out) { - ret = AVERROR(ENOMEM); - break; + if (ff_outlink_frame_wanted(ctx->outputs[i])) { + ff_inlink_request_frame(inlink); + return 0; } - av_frame_copy_props(out, frame); - - if (s->is_packed) { - extract_from_packed(out->data[0], out->linesize[0], - frame->data[0], frame->linesize[0], - outlink->w, outlink->h, - s->depth, - s->step, idx); - } else { - av_image_copy_plane(out->data[0], out->linesize[0], - frame->data[idx], frame->linesize[idx], - s->linesize[idx], outlink->h); - } - - ret = ff_filter_frame(outlink, out); - if (ret == AVERROR_EOF) - eof++; - else if (ret < 0) - break; } - av_frame_free(&frame); - if (eof == ctx->nb_outputs) - ret = AVERROR_EOF; - else if (ret == AVERROR_EOF) - ret = 0; - return ret; + return FFERROR_NOT_READY; } static av_cold int init(AVFilterContext *ctx) @@ -363,7 +400,6 @@ static const AVFilterPad extractplanes_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .filter_frame = filter_frame, .config_props = config_input, }, }; @@ -374,6 +410,7 @@ const AVFilter ff_vf_extractplanes = { .priv_size = sizeof(ExtractPlanesContext), .priv_class = &extractplanes_class, .init = init, + .activate = activate, FILTER_INPUTS(extractplanes_inputs), .outputs = NULL, FILTER_QUERY_FUNC(query_formats), @@ -406,6 +443,7 @@ const AVFilter ff_vf_alphaextract = { "grayscale image component."), .priv_size = sizeof(ExtractPlanesContext), .init = init_alphaextract, + .activate = activate, FILTER_INPUTS(extractplanes_inputs), FILTER_OUTPUTS(alphaextract_outputs), FILTER_QUERY_FUNC(query_formats), diff --git a/libavfilter/vf_feedback.c b/libavfilter/vf_feedback.c new file mode 100644 index 000000000..15cbf95c5 --- /dev/null +++ b/libavfilter/vf_feedback.c @@ -0,0 +1,333 @@ +/* + * 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 + * feedback video filter + */ + +#include "libavutil/fifo.h" +#include "libavutil/imgutils.h" +#include "libavutil/opt.h" +#include "libavutil/internal.h" +#include "avfilter.h" +#include "filters.h" +#include "internal.h" +#include "video.h" + +typedef struct FeedbackContext { + const AVClass *class; + + int x, y; + int w, h; + + int max_step[4]; + int hsub, vsub; + + AVFrame *feed; + + AVFifo *fifo; +} FeedbackContext; + +static void adjust_pos(AVFilterContext *ctx, FeedbackContext *s) +{ + if (s->x + s->w > ctx->inputs[0]->w) + s->x = ctx->inputs[0]->w - s->w; + if (s->y + s->h > ctx->inputs[0]->h) + s->y = ctx->inputs[0]->h - s->h; +} + +static void adjust_parameters(AVFilterContext *ctx, FeedbackContext *s) +{ + if (s->x >= ctx->inputs[0]->w) + s->x = 0; + if (s->y >= ctx->inputs[0]->h) + s->y = 0; + + if (s->w <= 0) + s->w = ctx->inputs[0]->w - s->x; + if (s->h <= 0) + s->h = ctx->inputs[0]->h - s->y; + + if (s->w > ctx->inputs[0]->w) + s->w = ctx->inputs[0]->w; + if (s->h > ctx->inputs[0]->h) + s->h = ctx->inputs[0]->h; + + adjust_pos(ctx, s); +} + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(inlink->format); + FeedbackContext *s = ctx->priv; + + s->hsub = pix_desc->log2_chroma_w; + s->vsub = pix_desc->log2_chroma_h; + + av_image_fill_max_pixsteps(s->max_step, NULL, pix_desc); + + adjust_parameters(ctx, s); + + ctx->inputs[1]->w = s->w; + ctx->inputs[1]->h = s->h; + + return 0; +} + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + FeedbackContext *s = ctx->priv; + + adjust_parameters(ctx, s); + + ctx->outputs[0]->w = ctx->inputs[0]->w; + ctx->outputs[0]->h = ctx->inputs[0]->h; + ctx->outputs[1]->w = s->w; + ctx->outputs[1]->h = s->h; + + return 0; +} + +static int query_formats(AVFilterContext *ctx) +{ + return ff_set_common_formats(ctx, ff_formats_pixdesc_filter(0, AV_PIX_FMT_FLAG_BITSTREAM | + AV_PIX_FMT_FLAG_HWACCEL | + AV_PIX_FMT_FLAG_PAL)); +} + +static int activate(AVFilterContext *ctx) +{ + FeedbackContext *s = ctx->priv; + int status, ret; + int64_t pts; + + adjust_pos(ctx, s); + + for (int i = 0; i < ctx->nb_outputs; i++) + FF_FILTER_FORWARD_STATUS_BACK_ALL(ctx->outputs[i], ctx); + + if (!s->feed) { + ret = ff_inlink_consume_frame(ctx->inputs[1], &s->feed); + if (ret < 0) + return ret; + } + + if (s->feed && av_fifo_can_read(s->fifo)) { + AVFrame *src = s->feed; + AVFrame *dst = NULL; + + av_fifo_read(s->fifo, &dst, 1); + if (!dst) + return AVERROR_BUG; + + if (!av_frame_is_writable(dst)) { + AVFrame *tmp = ff_get_video_buffer(ctx->outputs[0], ctx->outputs[0]->w, ctx->outputs[0]->h); + + if (!tmp) { + av_frame_free(&dst); + return AVERROR(ENOMEM); + } + + ret = av_frame_copy(tmp, dst); + if (ret < 0) { + av_frame_free(&dst); + av_frame_free(&tmp); + return ret; + } + + av_frame_copy_props(tmp, dst); + av_frame_free(&dst); + dst = tmp; + } + + for (int y = 0; y < src->height; y++) { + memmove(dst->data[0] + (s->y + y) * dst->linesize[0] + s->x * s->max_step[0], + src->data[0] + y * src->linesize[0], src->width * s->max_step[0]); + } + + for (int i = 1; i < 3; i ++) { + if (dst->data[i]) { + for (int y = 0; y < src->height; y++) { + memmove(dst->data[i] + ((s->y + y) >> s->vsub) * dst->linesize[i] + ((s->x * s->max_step[i]) >> s->hsub), + src->data[i] + (y >> s->vsub) * src->linesize[i], (src->width * s->max_step[i]) >> s->hsub); + } + } + } + + if (dst->data[3]) { + for (int y = 0; y < src->height; y++) { + memmove(dst->data[3] + (s->y + y) * dst->linesize[3] + s->x * s->max_step[3], + src->data[3] + y * src->linesize[3], src->width * s->max_step[3]); + } + } + + ret = ff_filter_frame(ctx->outputs[0], dst); + av_frame_free(&s->feed); + return ret; + } + + if (!s->feed) { + AVFrame *in = NULL; + + ret = ff_inlink_consume_frame(ctx->inputs[0], &in); + if (ret < 0) + return ret; + + if (ret > 0) { + AVFrame *frame; + + ret = av_fifo_write(s->fifo, &in, 1); + if (ret < 0) { + av_frame_free(&in); + return ret; + } + + frame = av_frame_clone(in); + if (!frame) + return AVERROR(ENOMEM); + + frame->width = s->w; + frame->height = s->h; + + frame->data[0] += s->y * frame->linesize[0]; + frame->data[0] += s->x * s->max_step[0]; + + for (int i = 1; i < 3; i ++) { + if (frame->data[i]) { + frame->data[i] += (s->y >> s->vsub) * frame->linesize[i]; + frame->data[i] += (s->x * s->max_step[i]) >> s->hsub; + } + } + + if (frame->data[3]) { + frame->data[3] += s->y * frame->linesize[3]; + frame->data[3] += s->x * s->max_step[3]; + } + + return ff_filter_frame(ctx->outputs[1], frame); + } + } + + if (ff_inlink_acknowledge_status(ctx->inputs[0], &status, &pts)) { + ff_outlink_set_status(ctx->outputs[0], status, pts); + ff_outlink_set_status(ctx->outputs[1], status, pts); + return 0; + } + + if (ff_inlink_acknowledge_status(ctx->inputs[1], &status, &pts)) { + ff_outlink_set_status(ctx->outputs[0], status, pts); + ff_outlink_set_status(ctx->outputs[1], status, pts); + return 0; + } + + if (!s->feed) { + if (ff_outlink_frame_wanted(ctx->outputs[0])) { + ff_inlink_request_frame(ctx->inputs[0]); + ff_inlink_request_frame(ctx->inputs[1]); + return 0; + } + } + + return FFERROR_NOT_READY; +} + +static av_cold int init(AVFilterContext *ctx) +{ + FeedbackContext *s = ctx->priv; + + s->fifo = av_fifo_alloc2(8, sizeof(AVFrame *), AV_FIFO_FLAG_AUTO_GROW); + if (!s->fifo) + return AVERROR(ENOMEM); + + return 0; +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + FeedbackContext *s = ctx->priv; + if (s->fifo) { + size_t size = av_fifo_can_read(s->fifo); + + for (size_t n = 0; n < size; n++) { + AVFrame *frame = NULL; + + av_fifo_read(s->fifo, &frame, 1); + + av_frame_free(&frame); + } + + av_fifo_freep2(&s->fifo); + } +} + +static const AVFilterPad inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_input, + }, + { + .name = "feedin", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_input, + }, +}; + +static const AVFilterPad outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_output, + }, + { + .name = "feedout", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_output, + }, +}; + +#define OFFSET(x) offsetof(FeedbackContext, x) +#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM) +#define TFLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_RUNTIME_PARAM) + +static const AVOption feedback_options[] = { + { "x", "set top left crop position", OFFSET(x), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, TFLAGS }, + { "y", "set top left crop position", OFFSET(y), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, TFLAGS }, + { "w", "set crop size", OFFSET(w), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, + { "h", "set crop size", OFFSET(h), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(feedback); + +const AVFilter ff_vf_feedback = { + .name = "feedback", + .description = NULL_IF_CONFIG_SMALL("Apply feedback video filter."), + .priv_class = &feedback_class, + .priv_size = sizeof(FeedbackContext), + .activate = activate, + .init = init, + .uninit = uninit, + FILTER_INPUTS(inputs), + FILTER_OUTPUTS(outputs), + FILTER_QUERY_FUNC(query_formats), + .process_command = ff_filter_process_command, +}; diff --git a/libavfilter/vf_fftdnoiz.c b/libavfilter/vf_fftdnoiz.c index b27b4a822..c9208bf1a 100644 --- a/libavfilter/vf_fftdnoiz.c +++ b/libavfilter/vf_fftdnoiz.c @@ -22,9 +22,11 @@ #include "libavutil/imgutils.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" +#include "libavutil/tx.h" #include "internal.h" -#include "libavcodec/avfft.h" +#include "window_func.h" +#define MAX_BLOCK 256 #define MAX_THREADS 32 enum BufferTypes { @@ -41,8 +43,9 @@ typedef struct PlaneContext { int o; float n; - float *buffer[BSIZE]; - FFTComplex *hdata[MAX_THREADS], *vdata[MAX_THREADS]; + float *buffer[MAX_THREADS][BSIZE]; + AVComplexFloat *hdata[MAX_THREADS], *vdata[MAX_THREADS]; + AVComplexFloat *hdata_out[MAX_THREADS], *vdata_out[MAX_THREADS]; int data_linesize; int buffer_linesize; } PlaneContext; @@ -52,8 +55,10 @@ typedef struct FFTdnoizContext { float sigma; float amount; - int block_bits; + int block_size; float overlap; + int method; + int window; int nb_prev; int nb_next; int planesf; @@ -64,11 +69,16 @@ typedef struct FFTdnoizContext { int nb_planes; int nb_threads; PlaneContext planes[4]; + float win[MAX_BLOCK][MAX_BLOCK]; - FFTContext *fft[MAX_THREADS], *ifft[MAX_THREADS]; + AVTXContext *fft[MAX_THREADS], *ifft[MAX_THREADS]; + AVTXContext *fft_r[MAX_THREADS], *ifft_r[MAX_THREADS]; - void (*import_row)(FFTComplex *dst, uint8_t *src, int rw); - void (*export_row)(FFTComplex *src, uint8_t *dst, int rw, float scale, int depth); + av_tx_fn tx_fn, itx_fn; + av_tx_fn tx_r_fn, itx_r_fn; + + void (*import_row)(AVComplexFloat *dst, uint8_t *src, int rw, float scale, float *win, int off); + void (*export_row)(AVComplexFloat *src, uint8_t *dst, int rw, int depth, float *win); } FFTdnoizContext; #define OFFSET(x) offsetof(FFTdnoizContext, x) @@ -76,19 +86,26 @@ typedef struct FFTdnoizContext { #define TFLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption fftdnoiz_options[] = { { "sigma", "set denoise strength", - OFFSET(sigma), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 30, .flags = TFLAGS }, + OFFSET(sigma), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 100, .flags = TFLAGS }, { "amount", "set amount of denoising", OFFSET(amount), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0.01, 1, .flags = TFLAGS }, - { "block", "set block log2(size)", - OFFSET(block_bits), AV_OPT_TYPE_INT, {.i64=4}, 3, 6, .flags = FLAGS }, + { "block", "set block size", + OFFSET(block_size), AV_OPT_TYPE_INT, {.i64=32}, 8, MAX_BLOCK, .flags = FLAGS }, { "overlap", "set block overlap", OFFSET(overlap), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, 0.2, 0.8, .flags = FLAGS }, + { "method", "set method of denoising", + OFFSET(method), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, .flags = TFLAGS, "method" }, + { "wiener", "wiener method", + 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, .flags = TFLAGS, "method" }, + { "hard", "hard thresholding", + 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, .flags = TFLAGS, "method" }, { "prev", "set number of previous frames for temporal denoising", OFFSET(nb_prev), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, .flags = FLAGS }, { "next", "set number of next frames for temporal denoising", OFFSET(nb_next), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, .flags = FLAGS }, { "planes", "set planes to filter", OFFSET(planesf), AV_OPT_TYPE_INT, {.i64=7}, 0, 15, .flags = TFLAGS }, + WIN_FUNC_OPTION("window", OFFSET(window), FLAGS, WFUNC_HANNING), { NULL } }; @@ -125,42 +142,40 @@ typedef struct ThreadData { float *src, *dst; } ThreadData; -static void import_row8(FFTComplex *dst, uint8_t *src, int rw) +static void import_row8(AVComplexFloat *dst, uint8_t *src, int rw, + float scale, float *win, int off) { - int j; - - for (j = 0; j < rw; j++) { - dst[j].re = src[j]; - dst[j].im = 0; + for (int j = 0; j < rw; j++) { + const int i = abs(j + off); + dst[j].re = src[i] * scale * win[j]; + dst[j].im = 0.f; } } -static void export_row8(FFTComplex *src, uint8_t *dst, int rw, float scale, int depth) +static void export_row8(AVComplexFloat *src, uint8_t *dst, int rw, int depth, float *win) { - int j; - - for (j = 0; j < rw; j++) - dst[j] = av_clip_uint8(lrintf(src[j].re * scale)); + for (int j = 0; j < rw; j++) + dst[j] = av_clip_uint8(lrintf(src[j].re / win[j])); } -static void import_row16(FFTComplex *dst, uint8_t *srcp, int rw) +static void import_row16(AVComplexFloat *dst, uint8_t *srcp, int rw, + float scale, float *win, int off) { uint16_t *src = (uint16_t *)srcp; - int j; - for (j = 0; j < rw; j++) { - dst[j].re = src[j]; + for (int j = 0; j < rw; j++) { + const int i = abs(j + off); + dst[j].re = src[i] * scale * win[j]; dst[j].im = 0; } } -static void export_row16(FFTComplex *src, uint8_t *dstp, int rw, float scale, int depth) +static void export_row16(AVComplexFloat *src, uint8_t *dstp, int rw, int depth, float *win) { uint16_t *dst = (uint16_t *)dstp; - int j; - for (j = 0; j < rw; j++) - dst[j] = av_clip_uintp2_c(src[j].re * scale + 0.5f, depth); + for (int j = 0; j < rw; j++) + dst[j] = av_clip_uintp2_c(lrintf(src[j].re / win[j]), depth); } static int config_input(AVFilterLink *inlink) @@ -168,6 +183,8 @@ static int config_input(AVFilterLink *inlink) AVFilterContext *ctx = inlink->dst; const AVPixFmtDescriptor *desc; FFTdnoizContext *s = ctx->priv; + float lut[MAX_BLOCK + 1]; + float overlap; int i; desc = av_pix_fmt_desc_get(inlink->format); @@ -179,7 +196,6 @@ static int config_input(AVFilterLink *inlink) } else { s->import_row = import_row16; s->export_row = export_row16; - s->sigma *= 1 << (s->depth - 8) * (1 + s->nb_prev + s->nb_next); } s->planes[1].planewidth = s->planes[2].planewidth = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w); @@ -191,9 +207,13 @@ static int config_input(AVFilterLink *inlink) s->nb_threads = FFMIN(ff_filter_get_nb_threads(ctx), MAX_THREADS); for (int i = 0; i < s->nb_threads; i++) { - s->fft[i] = av_fft_init(s->block_bits, 0); - s->ifft[i] = av_fft_init(s->block_bits, 1); - if (!s->fft[i] || !s->ifft[i]) + float scale = 1.f, iscale = 1.f; + + av_tx_init(&s->fft[i], &s->tx_fn, AV_TX_FLOAT_FFT, 0, s->block_size, &scale, 0); + av_tx_init(&s->ifft[i], &s->itx_fn, AV_TX_FLOAT_FFT, 1, s->block_size, &iscale, 0); + av_tx_init(&s->fft_r[i], &s->tx_r_fn, AV_TX_FLOAT_FFT, 0, 1 + s->nb_prev + s->nb_next, &scale, 0); + av_tx_init(&s->ifft_r[i], &s->itx_r_fn, AV_TX_FLOAT_FFT, 1, 1 + s->nb_prev + s->nb_next, &iscale, 0); + if (!s->fft[i] || !s->ifft[i] || !s->fft_r[i] || !s->ifft_r[i]) return AVERROR(ENOMEM); } @@ -201,112 +221,118 @@ static int config_input(AVFilterLink *inlink) PlaneContext *p = &s->planes[i]; int size; - p->b = 1 << s->block_bits; + p->b = s->block_size; p->n = 1.f / (p->b * p->b); - p->o = p->b * s->overlap; + p->o = lrintf(p->b * s->overlap); size = p->b - p->o; p->nox = (p->planewidth + (size - 1)) / size; p->noy = (p->planeheight + (size - 1)) / size; av_log(ctx, AV_LOG_DEBUG, "nox:%d noy:%d size:%d\n", p->nox, p->noy, size); - p->buffer_linesize = p->b * p->nox * sizeof(FFTComplex); - p->buffer[CURRENT] = av_calloc(p->b * p->noy, p->buffer_linesize); - if (!p->buffer[CURRENT]) - return AVERROR(ENOMEM); - if (s->nb_prev > 0) { - p->buffer[PREV] = av_calloc(p->b * p->noy, p->buffer_linesize); - if (!p->buffer[PREV]) - return AVERROR(ENOMEM); - } - if (s->nb_next > 0) { - p->buffer[NEXT] = av_calloc(p->b * p->noy, p->buffer_linesize); - if (!p->buffer[NEXT]) - return AVERROR(ENOMEM); - } + p->buffer_linesize = p->b * sizeof(AVComplexFloat); p->data_linesize = 2 * p->b * sizeof(float); for (int j = 0; j < s->nb_threads; j++) { p->hdata[j] = av_calloc(p->b, p->data_linesize); + p->hdata_out[j] = av_calloc(p->b, p->data_linesize); p->vdata[j] = av_calloc(p->b, p->data_linesize); - if (!p->hdata[j] || !p->vdata[j]) + p->vdata_out[j] = av_calloc(p->b, p->data_linesize); + p->buffer[j][CURRENT] = av_calloc(p->b, p->buffer_linesize); + if (!p->buffer[j][CURRENT]) + return AVERROR(ENOMEM); + if (s->nb_prev > 0) { + p->buffer[j][PREV] = av_calloc(p->b, p->buffer_linesize); + if (!p->buffer[j][PREV]) + return AVERROR(ENOMEM); + } + if (s->nb_next > 0) { + p->buffer[j][NEXT] = av_calloc(p->b, p->buffer_linesize); + if (!p->buffer[j][NEXT]) + return AVERROR(ENOMEM); + } + if (!p->hdata[j] || !p->vdata[j] || + !p->hdata_out[j] || !p->vdata_out[j]) return AVERROR(ENOMEM); } } + generate_window_func(lut, s->block_size + 1, s->window, &overlap); + + for (int y = 0; y < s->block_size; y++) { + for (int x = 0; x < s->block_size; x++) + s->win[y][x] = lut[y] * lut[x]; + } + return 0; } -static void import_plane(FFTdnoizContext *s, +static void import_block(FFTdnoizContext *s, uint8_t *srcp, int src_linesize, float *buffer, int buffer_linesize, int plane, - int jobnr, int nb_jobs) + int jobnr, int y, int x) { PlaneContext *p = &s->planes[plane]; const int width = p->planewidth; const int height = p->planeheight; const int block = p->b; const int overlap = p->o; + const int hoverlap = overlap / 2; const int size = block - overlap; - const int nox = p->nox; - const int noy = p->noy; const int bpp = (s->depth + 7) / 8; - const int data_linesize = p->data_linesize / sizeof(FFTComplex); - const int slice_start = (noy * jobnr) / nb_jobs; - const int slice_end = (noy * (jobnr+1)) / nb_jobs; - FFTComplex *hdata = p->hdata[jobnr]; - FFTComplex *vdata = p->vdata[jobnr]; - int x, y, i, j; + const int data_linesize = p->data_linesize / sizeof(AVComplexFloat); + const float scale = 1.f / ((1.f + s->nb_prev + s->nb_next) * s->block_size * s->block_size); + AVComplexFloat *hdata = p->hdata[jobnr]; + AVComplexFloat *hdata_out = p->hdata_out[jobnr]; + AVComplexFloat *vdata_out = p->vdata_out[jobnr]; + const int woff = -hoverlap; + const int hoff = -hoverlap; + const int rh = FFMIN(block, height - y * size + hoverlap); + const int rw = FFMIN(block, width - x * size + hoverlap); + AVComplexFloat *ssrc, *ddst, *dst = hdata, *dst_out = hdata_out; + float *bdst = buffer; buffer_linesize /= sizeof(float); - for (y = slice_start; y < slice_end; y++) { - for (x = 0; x < nox; x++) { - const int rh = FFMIN(block, height - y * size); - const int rw = FFMIN(block, width - x * size); - uint8_t *src = srcp + src_linesize * y * size + x * size * bpp; - float *bdst = buffer + buffer_linesize * y * block + x * block * 2; - FFTComplex *ssrc, *dst = hdata; - for (i = 0; i < rh; i++) { - s->import_row(dst, src, rw); - for (j = rw; j < block; j++) { - dst[j].re = dst[block - j - 1].re; - dst[j].im = 0; - } - av_fft_permute(s->fft[jobnr], dst); - av_fft_calc(s->fft[jobnr], dst); + for (int i = 0; i < rh; i++) { + uint8_t *src = srcp + src_linesize * abs(y * size + i + hoff) + x * size * bpp; - src += src_linesize; - dst += data_linesize; - } - - dst = hdata; - for (; i < block; i++) { - for (j = 0; j < block; j++) { - dst[j].re = dst[(block - i - 1) * data_linesize + j].re; - dst[j].im = dst[(block - i - 1) * data_linesize + j].im; - } - } - - ssrc = hdata; - dst = vdata; - for (i = 0; i < block; i++) { - for (j = 0; j < block; j++) - dst[j] = ssrc[j * data_linesize + i]; - av_fft_permute(s->fft[jobnr], dst); - av_fft_calc(s->fft[jobnr], dst); - memcpy(bdst, dst, block * sizeof(FFTComplex)); - - dst += data_linesize; - bdst += buffer_linesize; - } + s->import_row(dst, src, rw, scale, s->win[i], woff); + for (int j = rw; j < block; j++) { + dst[j].re = dst[rw - 1].re; + dst[j].im = 0.f; } + s->tx_fn(s->fft[jobnr], dst_out, dst, sizeof(float)); + + ddst = dst_out; + dst += data_linesize; + dst_out += data_linesize; + } + + for (int i = rh; i < block; i++) { + for (int j = 0; j < block; j++) { + dst[j].re = ddst[j].re; + dst[j].im = ddst[j].im; + } + + dst += data_linesize; + } + + ssrc = hdata_out; + dst = vdata_out; + for (int i = 0; i < block; i++) { + for (int j = 0; j < block; j++) + dst[j] = ssrc[j * data_linesize + i]; + s->tx_fn(s->fft[jobnr], bdst, dst, sizeof(float)); + + dst += data_linesize; + bdst += buffer_linesize; } } -static void export_plane(FFTdnoizContext *s, +static void export_block(FFTdnoizContext *s, uint8_t *dstp, int dst_linesize, float *buffer, int buffer_linesize, int plane, - int jobnr, int nb_jobs) + int jobnr, int y, int x) { PlaneContext *p = &s->planes[plane]; const int depth = s->depth; @@ -317,278 +343,243 @@ static void export_plane(FFTdnoizContext *s, const int overlap = p->o; const int hoverlap = overlap / 2; const int size = block - overlap; - const int nox = p->nox; - const int noy = p->noy; - const int data_linesize = p->data_linesize / sizeof(FFTComplex); - const float scale = 1.f / (block * block); - const int slice_start = (noy * jobnr) / nb_jobs; - const int slice_end = (noy * (jobnr+1)) / nb_jobs; - FFTComplex *hdata = p->hdata[jobnr]; - FFTComplex *vdata = p->vdata[jobnr]; - int x, y, i, j; + const int data_linesize = p->data_linesize / sizeof(AVComplexFloat); + AVComplexFloat *hdata = p->hdata[jobnr]; + AVComplexFloat *hdata_out = p->hdata_out[jobnr]; + AVComplexFloat *vdata_out = p->vdata_out[jobnr]; + const int rw = FFMIN(size, width - x * size + hoverlap); + const int rh = FFMIN(size, height - y * size + hoverlap); + AVComplexFloat *hdst, *vdst = vdata_out, *hdst_out = hdata_out; + float *bsrc = buffer; + hdst = hdata; buffer_linesize /= sizeof(float); - for (y = slice_start; y < slice_end; y++) { - for (x = 0; x < nox; x++) { - const int woff = x == 0 ? 0 : hoverlap; - const int hoff = y == 0 ? 0 : hoverlap; - const int rw = x == 0 ? block : FFMIN(size, width - x * size - woff); - const int rh = y == 0 ? block : FFMIN(size, height - y * size - hoff); - float *bsrc = buffer + buffer_linesize * y * block + x * block * 2; - uint8_t *dst = dstp + dst_linesize * (y * size + hoff) + (x * size + woff) * bpp; - FFTComplex *hdst, *ddst = vdata; - hdst = hdata; - for (i = 0; i < block; i++) { - memcpy(ddst, bsrc, block * sizeof(FFTComplex)); - av_fft_permute(s->ifft[jobnr], ddst); - av_fft_calc(s->ifft[jobnr], ddst); - for (j = 0; j < block; j++) { - hdst[j * data_linesize + i] = ddst[j]; - } + for (int i = 0; i < block; i++) { + s->itx_fn(s->ifft[jobnr], vdst, bsrc, sizeof(float)); + for (int j = 0; j < block; j++) + hdst[j * data_linesize + i] = vdst[j]; - ddst += data_linesize; - bsrc += buffer_linesize; - } + vdst += data_linesize; + bsrc += buffer_linesize; + } - hdst = hdata + hoff * data_linesize; - for (i = 0; i < rh; i++) { - av_fft_permute(s->ifft[jobnr], hdst); - av_fft_calc(s->ifft[jobnr], hdst); - s->export_row(hdst + woff, dst, rw, scale, depth); + hdst = hdata + hoverlap * data_linesize; + for (int i = 0; i < rh && (y * size + i) < height; i++) { + uint8_t *dst = dstp + dst_linesize * (y * size + i) + x * size * bpp; - hdst += data_linesize; - dst += dst_linesize; - } - } + s->itx_fn(s->ifft[jobnr], hdst_out, hdst, sizeof(float)); + s->export_row(hdst_out + hoverlap, dst, rw, depth, s->win[i + hoverlap] + hoverlap); + + hdst += data_linesize; + hdst_out += data_linesize; } } -static void filter_plane3d2(FFTdnoizContext *s, int plane, float *pbuffer, float *nbuffer, - int jobnr, int nb_jobs) +static void filter_block3d2(FFTdnoizContext *s, int plane, float *pbuffer, float *nbuffer, + int jobnr) { PlaneContext *p = &s->planes[plane]; const int block = p->b; - const int nox = p->nox; - const int noy = p->noy; const int buffer_linesize = p->buffer_linesize / sizeof(float); - const float sigma = s->sigma * s->sigma * block * block; - const int slice_start = (noy * jobnr) / nb_jobs; - const int slice_end = (noy * (jobnr+1)) / nb_jobs; + const float depthx = (1 << (s->depth - 8)) * (1 << (s->depth - 8)); + const float sigma = s->sigma * depthx / (3.f * s->block_size * s->block_size); const float limit = 1.f - s->amount; - float *cbuffer = p->buffer[CURRENT]; - const float cfactor = sqrtf(3.f) * 0.5f; - const float scale = 1.f / 3.f; - int y, x, i, j; + float *cbuffer = p->buffer[jobnr][CURRENT]; + const int method = s->method; + float *cbuff = cbuffer; + float *pbuff = pbuffer; + float *nbuff = nbuffer; - for (y = slice_start; y < slice_end; y++) { - for (x = 0; x < nox; x++) { - float *cbuff = cbuffer + buffer_linesize * y * block + x * block * 2; - float *pbuff = pbuffer + buffer_linesize * y * block + x * block * 2; - float *nbuff = nbuffer + buffer_linesize * y * block + x * block * 2; + for (int i = 0; i < block; i++) { + for (int j = 0; j < block; j++) { + AVComplexFloat buffer[BSIZE]; + AVComplexFloat outbuffer[BSIZE]; - for (i = 0; i < block; i++) { - for (j = 0; j < block; j++) { - float sumr, sumi, difr, difi, mpr, mpi, mnr, mni; - float factor, power, sumpnr, sumpni; + buffer[0].re = pbuff[2 * j ]; + buffer[0].im = pbuff[2 * j + 1]; - sumpnr = pbuff[2 * j ] + nbuff[2 * j ]; - sumpni = pbuff[2 * j + 1] + nbuff[2 * j + 1]; - sumr = cbuff[2 * j ] + sumpnr; - sumi = cbuff[2 * j + 1] + sumpni; - difr = cfactor * (nbuff[2 * j ] - pbuff[2 * j ]); - difi = cfactor * (pbuff[2 * j + 1] - nbuff[2 * j + 1]); - mpr = cbuff[2 * j ] - 0.5f * sumpnr + difi; - mnr = mpr - difi - difi; - mpi = cbuff[2 * j + 1] - 0.5f * sumpni + difr; - mni = mpi - difr - difr; - power = sumr * sumr + sumi * sumi + 1e-15f; - factor = FFMAX((power - sigma) / power, limit); - sumr *= factor; - sumi *= factor; - power = mpr * mpr + mpi * mpi + 1e-15f; - factor = FFMAX((power - sigma) / power, limit); - mpr *= factor; - mpi *= factor; - power = mnr * mnr + mni * mni + 1e-15f; - factor = FFMAX((power - sigma) / power, limit); - mnr *= factor; - mni *= factor; - cbuff[2 * j ] = (sumr + mpr + mnr) * scale; - cbuff[2 * j + 1] = (sumi + mpi + mni) * scale; + buffer[1].re = cbuff[2 * j ]; + buffer[1].im = cbuff[2 * j + 1]; + buffer[2].re = nbuff[2 * j ]; + buffer[2].im = nbuff[2 * j + 1]; + + s->tx_r_fn(s->fft_r[jobnr], outbuffer, buffer, sizeof(float)); + + for (int z = 0; z < 3; z++) { + const float re = outbuffer[z].re; + const float im = outbuffer[z].im; + const float power = re * re + im * im; + float factor; + + switch (method) { + case 0: + factor = fmaxf(limit, (power - sigma) / (power + 1e-15f)); + break; + case 1: + factor = power < sigma ? limit : 1.f; + break; } - cbuff += buffer_linesize; - pbuff += buffer_linesize; - nbuff += buffer_linesize; + outbuffer[z].re *= factor; + outbuffer[z].im *= factor; } + + s->itx_r_fn(s->ifft_r[jobnr], buffer, outbuffer, sizeof(float)); + + cbuff[2 * j + 0] = buffer[1].re; + cbuff[2 * j + 1] = buffer[1].im; } + + cbuff += buffer_linesize; + pbuff += buffer_linesize; + nbuff += buffer_linesize; } } -static void filter_plane3d1(FFTdnoizContext *s, int plane, float *pbuffer, - int jobnr, int nb_jobs) +static void filter_block3d1(FFTdnoizContext *s, int plane, float *pbuffer, + int jobnr) { PlaneContext *p = &s->planes[plane]; const int block = p->b; - const int nox = p->nox; - const int noy = p->noy; const int buffer_linesize = p->buffer_linesize / sizeof(float); - const float sigma = s->sigma * s->sigma * block * block; - const int slice_start = (noy * jobnr) / nb_jobs; - const int slice_end = (noy * (jobnr+1)) / nb_jobs; + const float depthx = (1 << (s->depth - 8)) * (1 << (s->depth - 8)); + const float sigma = s->sigma * depthx / (2.f * s->block_size * s->block_size); const float limit = 1.f - s->amount; - float *cbuffer = p->buffer[CURRENT]; - int y, x, i, j; + float *cbuffer = p->buffer[jobnr][CURRENT]; + const int method = s->method; + float *cbuff = cbuffer; + float *pbuff = pbuffer; - for (y = slice_start; y < slice_end; y++) { - for (x = 0; x < nox; x++) { - float *cbuff = cbuffer + buffer_linesize * y * block + x * block * 2; - float *pbuff = pbuffer + buffer_linesize * y * block + x * block * 2; + for (int i = 0; i < block; i++) { + for (int j = 0; j < block; j++) { + AVComplexFloat buffer[BSIZE]; + AVComplexFloat outbuffer[BSIZE]; - for (i = 0; i < block; i++) { - for (j = 0; j < block; j++) { - float factor, power, re, im, pre, pim; - float sumr, sumi, difr, difi; + buffer[0].re = pbuff[2 * j ]; + buffer[0].im = pbuff[2 * j + 1]; - re = cbuff[j * 2 ]; - pre = pbuff[j * 2 ]; - im = cbuff[j * 2 + 1]; - pim = pbuff[j * 2 + 1]; + buffer[1].re = cbuff[2 * j ]; + buffer[1].im = cbuff[2 * j + 1]; - sumr = re + pre; - sumi = im + pim; - difr = re - pre; - difi = im - pim; + s->tx_r_fn(s->fft_r[jobnr], outbuffer, buffer, sizeof(float)); - power = sumr * sumr + sumi * sumi + 1e-15f; - factor = FFMAX(limit, (power - sigma) / power); - sumr *= factor; - sumi *= factor; - power = difr * difr + difi * difi + 1e-15f; - factor = FFMAX(limit, (power - sigma) / power); - difr *= factor; - difi *= factor; + for (int z = 0; z < 2; z++) { + const float re = outbuffer[z].re; + const float im = outbuffer[z].im; + const float power = re * re + im * im; + float factor; - cbuff[j * 2 ] = (sumr + difr) * 0.5f; - cbuff[j * 2 + 1] = (sumi + difi) * 0.5f; + switch (method) { + case 0: + factor = fmaxf(limit, (power - sigma) / (power + 1e-15f)); + break; + case 1: + factor = power < sigma ? limit : 1.f; + break; } - cbuff += buffer_linesize; - pbuff += buffer_linesize; + outbuffer[z].re *= factor; + outbuffer[z].im *= factor; } + + s->itx_r_fn(s->ifft_r[jobnr], buffer, outbuffer, sizeof(float)); + + cbuff[2 * j + 0] = buffer[1].re; + cbuff[2 * j + 1] = buffer[1].im; } + + cbuff += buffer_linesize; + pbuff += buffer_linesize; } } -static void filter_plane2d(FFTdnoizContext *s, int plane, - int jobnr, int nb_jobs) +static void filter_block2d(FFTdnoizContext *s, int plane, + int jobnr) { PlaneContext *p = &s->planes[plane]; const int block = p->b; - const int nox = p->nox; - const int noy = p->noy; - const int buffer_linesize = p->buffer_linesize / 4; - const float sigma = s->sigma * s->sigma * block * block; + const int method = s->method; + const int buffer_linesize = p->buffer_linesize / sizeof(float); + const float depthx = (1 << (s->depth - 8)) * (1 << (s->depth - 8)); + const float sigma = s->sigma * depthx / (s->block_size * s->block_size); const float limit = 1.f - s->amount; - const int slice_start = (noy * jobnr) / nb_jobs; - const int slice_end = (noy * (jobnr+1)) / nb_jobs; - float *buffer = p->buffer[CURRENT]; + float *buff = p->buffer[jobnr][CURRENT]; - for (int y = slice_start; y < slice_end; y++) { - for (int x = 0; x < nox; x++) { - float *buff = buffer + buffer_linesize * y * block + x * block * 2; + for (int i = 0; i < block; i++) { + for (int j = 0; j < block; j++) { + float factor, power, re, im; - for (int i = 0; i < block; i++) { - for (int j = 0; j < block; j++) { - float factor, power, re, im; - - re = buff[j * 2 ]; - im = buff[j * 2 + 1]; - power = re * re + im * im + 1e-15f; - factor = FFMAX(limit, (power - sigma) / power); - buff[j * 2 ] *= factor; - buff[j * 2 + 1] *= factor; - } - - buff += buffer_linesize; + re = buff[j * 2 ]; + im = buff[j * 2 + 1]; + power = re * re + im * im; + switch (method) { + case 0: + factor = fmaxf(limit, (power - sigma) / (power + 1e-15f)); + break; + case 1: + factor = power < sigma ? limit : 1.f; + break; } + + buff[j * 2 ] *= factor; + buff[j * 2 + 1] *= factor; } + + buff += buffer_linesize; } } -static int import_pass(AVFilterContext *ctx, void *arg, - int jobnr, int nb_jobs) -{ - FFTdnoizContext *s = ctx->priv; - - for (int plane = 0; plane < s->nb_planes; plane++) { - PlaneContext *p = &s->planes[plane]; - - if (!((1 << plane) & s->planesf) || ctx->is_disabled) - continue; - - if (s->next) { - import_plane(s, s->next->data[plane], s->next->linesize[plane], - p->buffer[NEXT], p->buffer_linesize, plane, - jobnr, nb_jobs); - } - - if (s->prev) { - import_plane(s, s->prev->data[plane], s->prev->linesize[plane], - p->buffer[PREV], p->buffer_linesize, plane, - jobnr, nb_jobs); - } - - import_plane(s, s->cur->data[plane], s->cur->linesize[plane], - p->buffer[CURRENT], p->buffer_linesize, plane, - jobnr, nb_jobs); - } - - return 0; -} - -static int filter_pass(AVFilterContext *ctx, void *arg, - int jobnr, int nb_jobs) -{ - FFTdnoizContext *s = ctx->priv; - - for (int plane = 0; plane < s->nb_planes; plane++) { - PlaneContext *p = &s->planes[plane]; - - if (!((1 << plane) & s->planesf) || ctx->is_disabled) - continue; - - if (s->next && s->prev) { - filter_plane3d2(s, plane, p->buffer[PREV], p->buffer[NEXT], jobnr, nb_jobs); - } else if (s->next) { - filter_plane3d1(s, plane, p->buffer[NEXT], jobnr, nb_jobs); - } else if (s->prev) { - filter_plane3d1(s, plane, p->buffer[PREV], jobnr, nb_jobs); - } else { - filter_plane2d(s, plane, jobnr, nb_jobs); - } - } - - return 0; -} - -static int export_pass(AVFilterContext *ctx, void *arg, - int jobnr, int nb_jobs) +static int denoise(AVFilterContext *ctx, void *arg, + int jobnr, int nb_jobs) { FFTdnoizContext *s = ctx->priv; AVFrame *out = arg; for (int plane = 0; plane < s->nb_planes; plane++) { PlaneContext *p = &s->planes[plane]; + const int nox = p->nox; + const int noy = p->noy; + const int slice_start = (noy * jobnr) / nb_jobs; + const int slice_end = (noy * (jobnr+1)) / nb_jobs; if (!((1 << plane) & s->planesf) || ctx->is_disabled) continue; - export_plane(s, out->data[plane], out->linesize[plane], - p->buffer[CURRENT], p->buffer_linesize, plane, - jobnr, nb_jobs); + for (int y = slice_start; y < slice_end; y++) { + for (int x = 0; x < nox; x++) { + if (s->next) { + import_block(s, s->next->data[plane], s->next->linesize[plane], + p->buffer[jobnr][NEXT], p->buffer_linesize, plane, + jobnr, y, x); + } + + if (s->prev) { + import_block(s, s->prev->data[plane], s->prev->linesize[plane], + p->buffer[jobnr][PREV], p->buffer_linesize, plane, + jobnr, y, x); + } + + import_block(s, s->cur->data[plane], s->cur->linesize[plane], + p->buffer[jobnr][CURRENT], p->buffer_linesize, plane, + jobnr, y, x); + + if (s->next && s->prev) { + filter_block3d2(s, plane, p->buffer[jobnr][PREV], p->buffer[jobnr][NEXT], jobnr); + } else if (s->next) { + filter_block3d1(s, plane, p->buffer[jobnr][NEXT], jobnr); + } else if (s->prev) { + filter_block3d1(s, plane, p->buffer[jobnr][PREV], jobnr); + } else { + filter_block2d(s, plane, jobnr); + } + + export_block(s, out->data[plane], out->linesize[plane], + p->buffer[jobnr][CURRENT], p->buffer_linesize, plane, + jobnr, y, x); + } + } } return 0; @@ -646,13 +637,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) av_frame_copy_props(out, s->cur); } - ff_filter_execute(ctx, import_pass, NULL, NULL, - FFMIN(s->planes[0].noy, s->nb_threads)); - - ff_filter_execute(ctx, filter_pass, NULL, NULL, - FFMIN(s->planes[0].noy, s->nb_threads)); - - ff_filter_execute(ctx, export_pass, out, NULL, + ff_filter_execute(ctx, denoise, out, NULL, FFMIN(s->planes[0].noy, s->nb_threads)); for (plane = 0; plane < s->nb_planes; plane++) { @@ -662,7 +647,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) if (!direct) av_image_copy_plane(out->data[plane], out->linesize[plane], s->cur->data[plane], s->cur->linesize[plane], - p->planewidth, p->planeheight); + p->planewidth * (1 + (s->depth > 8)), p->planeheight); continue; } } @@ -717,16 +702,19 @@ static av_cold void uninit(AVFilterContext *ctx) for (int j = 0; j < s->nb_threads; j++) { av_freep(&p->hdata[j]); av_freep(&p->vdata[j]); + av_freep(&p->hdata_out[j]); + av_freep(&p->vdata_out[j]); + av_freep(&p->buffer[j][PREV]); + av_freep(&p->buffer[j][CURRENT]); + av_freep(&p->buffer[j][NEXT]); } - - av_freep(&p->buffer[PREV]); - av_freep(&p->buffer[CURRENT]); - av_freep(&p->buffer[NEXT]); } for (i = 0; i < s->nb_threads; i++) { - av_fft_end(s->fft[i]); - av_fft_end(s->ifft[i]); + av_tx_uninit(&s->fft[i]); + av_tx_uninit(&s->ifft[i]); + av_tx_uninit(&s->fft_r[i]); + av_tx_uninit(&s->ifft_r[i]); } av_frame_free(&s->prev); diff --git a/libavfilter/vf_fftfilt.c b/libavfilter/vf_fftfilt.c index 37aa45ef8..067ce7eb3 100644 --- a/libavfilter/vf_fftfilt.c +++ b/libavfilter/vf_fftfilt.c @@ -26,10 +26,11 @@ #include "libavfilter/internal.h" #include "libavutil/common.h" +#include "libavutil/cpu.h" #include "libavutil/imgutils.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" -#include "libavcodec/avfft.h" +#include "libavutil/tx.h" #include "libavutil/eval.h" #define MAX_THREADS 32 @@ -51,16 +52,24 @@ typedef struct FFTFILTContext { int planewidth[MAX_PLANES]; int planeheight[MAX_PLANES]; - RDFTContext *hrdft[MAX_THREADS][MAX_PLANES]; - RDFTContext *vrdft[MAX_THREADS][MAX_PLANES]; - RDFTContext *ihrdft[MAX_THREADS][MAX_PLANES]; - RDFTContext *ivrdft[MAX_THREADS][MAX_PLANES]; + AVTXContext *hrdft[MAX_THREADS][MAX_PLANES]; + AVTXContext *vrdft[MAX_THREADS][MAX_PLANES]; + AVTXContext *ihrdft[MAX_THREADS][MAX_PLANES]; + AVTXContext *ivrdft[MAX_THREADS][MAX_PLANES]; + + av_tx_fn htx_fn, ihtx_fn; + av_tx_fn vtx_fn, ivtx_fn; + int rdft_hbits[MAX_PLANES]; int rdft_vbits[MAX_PLANES]; + size_t rdft_hstride[MAX_PLANES]; + size_t rdft_vstride[MAX_PLANES]; size_t rdft_hlen[MAX_PLANES]; size_t rdft_vlen[MAX_PLANES]; - FFTSample *rdft_hdata[MAX_PLANES]; - FFTSample *rdft_vdata[MAX_PLANES]; + float *rdft_hdata_in[MAX_PLANES]; + float *rdft_vdata_in[MAX_PLANES]; + float *rdft_hdata_out[MAX_PLANES]; + float *rdft_vdata_out[MAX_PLANES]; int dc[MAX_PLANES]; char *weight_str[MAX_PLANES]; @@ -97,14 +106,14 @@ AVFILTER_DEFINE_CLASS(fftfilt); static inline double lum(void *priv, double x, double y, int plane) { FFTFILTContext *s = priv; - return s->rdft_vdata[plane][(int)x * s->rdft_vlen[plane] + (int)y]; + return s->rdft_vdata_out[plane][(int)x * s->rdft_vstride[plane] + (int)y]; } static double weight_Y(void *priv, double x, double y) { return lum(priv, x, y, Y); } static double weight_U(void *priv, double x, double y) { return lum(priv, x, y, U); } static double weight_V(void *priv, double x, double y) { return lum(priv, x, y, V); } -static void copy_rev(FFTSample *dest, int w, int w2) +static void copy_rev(float *dest, int w, int w2) { int i; @@ -128,16 +137,19 @@ static int rdft_horizontal8(AVFilterContext *ctx, void *arg, int jobnr, int nb_j for (int i = slice_start; i < slice_end; i++) { const uint8_t *src = in->data[plane] + i * in->linesize[plane]; - float *hdata = s->rdft_hdata[plane] + i * s->rdft_hlen[plane]; + float *hdata_in = s->rdft_hdata_in[plane] + i * s->rdft_hstride[plane]; for (int j = 0; j < w; j++) - hdata[j] = src[j]; + hdata_in[j] = src[j]; - copy_rev(s->rdft_hdata[plane] + i * s->rdft_hlen[plane], w, s->rdft_hlen[plane]); + copy_rev(s->rdft_hdata_in[plane] + i * s->rdft_hstride[plane], w, s->rdft_hlen[plane]); } for (int i = slice_start; i < slice_end; i++) - av_rdft_calc(s->hrdft[jobnr][plane], s->rdft_hdata[plane] + i * s->rdft_hlen[plane]); + s->htx_fn(s->hrdft[jobnr][plane], + s->rdft_hdata_out[plane] + i * s->rdft_hstride[plane], + s->rdft_hdata_in[plane] + i * s->rdft_hstride[plane], + sizeof(float)); } return 0; @@ -156,16 +168,19 @@ static int rdft_horizontal16(AVFilterContext *ctx, void *arg, int jobnr, int nb_ for (int i = slice_start; i < slice_end; i++) { const uint16_t *src = (const uint16_t *)(in->data[plane] + i * in->linesize[plane]); - float *hdata = s->rdft_hdata[plane] + i * s->rdft_hlen[plane]; + float *hdata_in = s->rdft_hdata_in[plane] + i * s->rdft_hstride[plane]; for (int j = 0; j < w; j++) - hdata[j] = src[j]; + hdata_in[j] = src[j]; - copy_rev(s->rdft_hdata[plane] + i * s->rdft_hlen[plane], w, s->rdft_hlen[plane]); + copy_rev(s->rdft_hdata_in[plane] + i * s->rdft_hstride[plane], w, s->rdft_hlen[plane]); } for (int i = slice_start; i < slice_end; i++) - av_rdft_calc(s->hrdft[jobnr][plane], s->rdft_hdata[plane] + i * s->rdft_hlen[plane]); + s->htx_fn(s->hrdft[jobnr][plane], + s->rdft_hdata_out[plane] + i * s->rdft_hstride[plane], + s->rdft_hdata_in[plane] + i * s->rdft_hstride[plane], + sizeof(float)); } return 0; @@ -183,11 +198,14 @@ static int irdft_horizontal8(AVFilterContext *ctx, void *arg, int jobnr, int nb_ const int slice_end = (h * (jobnr+1)) / nb_jobs; for (int i = slice_start; i < slice_end; i++) - av_rdft_calc(s->ihrdft[jobnr][plane], s->rdft_hdata[plane] + i * s->rdft_hlen[plane]); + s->ihtx_fn(s->ihrdft[jobnr][plane], + s->rdft_hdata_out[plane] + i * s->rdft_hstride[plane], + s->rdft_hdata_in[plane] + i * s->rdft_hstride[plane], + sizeof(float)); for (int i = slice_start; i < slice_end; i++) { - const float scale = 4.f / (s->rdft_hlen[plane] * s->rdft_vlen[plane]); - const float *src = s->rdft_hdata[plane] + i * s->rdft_hlen[plane]; + const float scale = 1.f / (s->rdft_hlen[plane] * s->rdft_vlen[plane]); + const float *src = s->rdft_hdata_out[plane] + i * s->rdft_hstride[plane]; uint8_t *dst = out->data[plane] + i * out->linesize[plane]; for (int j = 0; j < w; j++) @@ -211,11 +229,14 @@ static int irdft_horizontal16(AVFilterContext *ctx, void *arg, int jobnr, int nb const int slice_end = (h * (jobnr+1)) / nb_jobs; for (int i = slice_start; i < slice_end; i++) - av_rdft_calc(s->ihrdft[jobnr][plane], s->rdft_hdata[plane] + i * s->rdft_hlen[plane]); + s->ihtx_fn(s->ihrdft[jobnr][plane], + s->rdft_hdata_out[plane] + i * s->rdft_hstride[plane], + s->rdft_hdata_in[plane] + i * s->rdft_hstride[plane], + sizeof(float)); for (int i = slice_start; i < slice_end; i++) { - const float scale = 4.f / (s->rdft_hlen[plane] * s->rdft_vlen[plane]); - const float *src = s->rdft_hdata[plane] + i * s->rdft_hlen[plane]; + const float scale = 1.f / (s->rdft_hlen[plane] * s->rdft_vlen[plane]); + const float *src = s->rdft_hdata_out[plane] + i * s->rdft_hstride[plane]; uint16_t *dst = (uint16_t *)(out->data[plane] + i * out->linesize[plane]); for (int j = 0; j < w; j++) @@ -303,34 +324,50 @@ static int config_props(AVFilterLink *inlink) /* RDFT - Array initialization for Horizontal pass*/ s->rdft_hlen[i] = 1 << (32 - ff_clz(w)); + s->rdft_hstride[i] = FFALIGN(s->rdft_hlen[i] + 2, av_cpu_max_align()); s->rdft_hbits[i] = av_log2(s->rdft_hlen[i]); - if (!(s->rdft_hdata[i] = av_malloc_array(h, s->rdft_hlen[i] * sizeof(FFTSample)))) + if (!(s->rdft_hdata_in[i] = av_calloc(h, s->rdft_hstride[i] * sizeof(float)))) + return AVERROR(ENOMEM); + + if (!(s->rdft_hdata_out[i] = av_calloc(h, s->rdft_hstride[i] * sizeof(float)))) return AVERROR(ENOMEM); for (int j = 0; j < s->nb_threads; j++) { - if (!(s->hrdft[j][i] = av_rdft_init(s->rdft_hbits[i], DFT_R2C))) + float scale = 1.f, iscale = 1.f; + + av_tx_init(&s->hrdft[j][i], &s->htx_fn, AV_TX_FLOAT_RDFT, 0, 1 << s->rdft_hbits[i], &scale, 0); + if (!s->hrdft[j][i]) return AVERROR(ENOMEM); - if (!(s->ihrdft[j][i] = av_rdft_init(s->rdft_hbits[i], IDFT_C2R))) + av_tx_init(&s->ihrdft[j][i], &s->ihtx_fn, AV_TX_FLOAT_RDFT, 1, 1 << s->rdft_hbits[i], &iscale, 0); + if (!s->ihrdft[j][i]) return AVERROR(ENOMEM); } /* RDFT - Array initialization for Vertical pass*/ s->rdft_vlen[i] = 1 << (32 - ff_clz(h)); + s->rdft_vstride[i] = FFALIGN(s->rdft_vlen[i] + 2, av_cpu_max_align()); s->rdft_vbits[i] = av_log2(s->rdft_vlen[i]); - if (!(s->rdft_vdata[i] = av_malloc_array(s->rdft_hlen[i], s->rdft_vlen[i] * sizeof(FFTSample)))) + if (!(s->rdft_vdata_in[i] = av_calloc(s->rdft_hstride[i], s->rdft_vstride[i] * sizeof(float)))) + return AVERROR(ENOMEM); + + if (!(s->rdft_vdata_out[i] = av_calloc(s->rdft_hstride[i], s->rdft_vstride[i] * sizeof(float)))) return AVERROR(ENOMEM); for (int j = 0; j < s->nb_threads; j++) { - if (!(s->vrdft[j][i] = av_rdft_init(s->rdft_vbits[i], DFT_R2C))) + float scale = 1.f, iscale = 1.f; + + av_tx_init(&s->vrdft[j][i], &s->vtx_fn, AV_TX_FLOAT_RDFT, 0, 1 << s->rdft_vbits[i], &scale, 0); + if (!s->vrdft[j][i]) return AVERROR(ENOMEM); - if (!(s->ivrdft[j][i] = av_rdft_init(s->rdft_vbits[i], IDFT_C2R))) + av_tx_init(&s->ivrdft[j][i], &s->ivtx_fn, AV_TX_FLOAT_RDFT, 1, 1 << s->rdft_vbits[i], &iscale, 0); + if (!s->ivrdft[j][i]) return AVERROR(ENOMEM); } } /*Luminance value - Array initialization*/ for (plane = 0; plane < 3; plane++) { - if(!(s->weight[plane] = av_malloc_array(s->rdft_hlen[plane], s->rdft_vlen[plane] * sizeof(double)))) + if(!(s->weight[plane] = av_calloc(s->rdft_hlen[plane], s->rdft_vlen[plane] * sizeof(double)))) return AVERROR(ENOMEM); if (s->eval_mode == EVAL_MODE_INIT) @@ -360,7 +397,7 @@ static int multiply_data(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs /*Change user defined parameters*/ for (int i = slice_start; i < slice_end; i++) { const double *weight = s->weight[plane] + i * s->rdft_vlen[plane]; - float *vdata = s->rdft_vdata[plane] + i * s->rdft_vlen[plane]; + float *vdata = s->rdft_vdata_out[plane] + i * s->rdft_vstride[plane]; for (int j = 0; j < s->rdft_vlen[plane]; j++) vdata[j] *= weight[j]; @@ -377,16 +414,18 @@ static int copy_vertical(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs for (int plane = 0; plane < s->nb_planes; plane++) { const int hlen = s->rdft_hlen[plane]; const int vlen = s->rdft_vlen[plane]; + const int hstride = s->rdft_hstride[plane]; + const int vstride = s->rdft_vstride[plane]; const int slice_start = (hlen * jobnr) / nb_jobs; const int slice_end = (hlen * (jobnr+1)) / nb_jobs; const int h = s->planeheight[plane]; - FFTSample *hdata = s->rdft_hdata[plane]; - FFTSample *vdata = s->rdft_vdata[plane]; + float *hdata = s->rdft_hdata_out[plane]; + float *vdata = s->rdft_vdata_in[plane]; for (int i = slice_start; i < slice_end; i++) { for (int j = 0; j < h; j++) - vdata[i * vlen + j] = hdata[j * hlen + i]; - copy_rev(vdata + i * vlen, h, vlen); + vdata[i * vstride + j] = hdata[j * hstride + i]; + copy_rev(vdata + i * vstride, h, vlen); } } @@ -403,7 +442,10 @@ static int rdft_vertical(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs const int slice_end = (height * (jobnr+1)) / nb_jobs; for (int i = slice_start; i < slice_end; i++) - av_rdft_calc(s->vrdft[jobnr][plane], s->rdft_vdata[plane] + i * s->rdft_vlen[plane]); + s->vtx_fn(s->vrdft[jobnr][plane], + s->rdft_vdata_out[plane] + i * s->rdft_vstride[plane], + s->rdft_vdata_in[plane] + i * s->rdft_vstride[plane], + sizeof(float)); } return 0; @@ -419,7 +461,10 @@ static int irdft_vertical(AVFilterContext *ctx, void *arg, int jobnr, int nb_job const int slice_end = (height * (jobnr+1)) / nb_jobs; for (int i = slice_start; i < slice_end; i++) - av_rdft_calc(s->ivrdft[jobnr][plane], s->rdft_vdata[plane] + i * s->rdft_vlen[plane]); + s->ivtx_fn(s->ivrdft[jobnr][plane], + s->rdft_vdata_in[plane] + i * s->rdft_vstride[plane], + s->rdft_vdata_out[plane] + i * s->rdft_vstride[plane], + sizeof(float)); } return 0; @@ -431,16 +476,17 @@ static int copy_horizontal(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo for (int plane = 0; plane < s->nb_planes; plane++) { const int hlen = s->rdft_hlen[plane]; - const int vlen = s->rdft_vlen[plane]; + const int hstride = s->rdft_hstride[plane]; + const int vstride = s->rdft_vstride[plane]; const int slice_start = (hlen * jobnr) / nb_jobs; const int slice_end = (hlen * (jobnr+1)) / nb_jobs; const int h = s->planeheight[plane]; - FFTSample *hdata = s->rdft_hdata[plane]; - FFTSample *vdata = s->rdft_vdata[plane]; + float *hdata = s->rdft_hdata_in[plane]; + float *vdata = s->rdft_vdata_in[plane]; for (int i = slice_start; i < slice_end; i++) for (int j = 0; j < h; j++) - hdata[j * hlen + i] = vdata[i * vlen + j]; + hdata[j * hstride + i] = vdata[i * vstride + j]; } return 0; @@ -461,11 +507,6 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) av_frame_copy_props(out, in); - for (int plane = 0; plane < s->nb_planes; plane++) { - if (s->eval_mode == EVAL_MODE_FRAME) - do_eval(s, inlink, plane); - } - ff_filter_execute(ctx, s->rdft_horizontal, in, NULL, FFMIN(s->planeheight[1], s->nb_threads)); @@ -475,11 +516,16 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) ff_filter_execute(ctx, rdft_vertical, NULL, NULL, FFMIN(s->planeheight[1], s->nb_threads)); + for (int plane = 0; plane < s->nb_planes; plane++) { + if (s->eval_mode == EVAL_MODE_FRAME) + do_eval(s, inlink, plane); + } + ff_filter_execute(ctx, multiply_data, NULL, NULL, FFMIN(s->planeheight[1], s->nb_threads)); for (int plane = 0; plane < s->nb_planes; plane++) - s->rdft_vdata[plane][0] += s->rdft_hlen[plane] * s->rdft_vlen[plane] * s->dc[plane]; + s->rdft_vdata_out[plane][0] += s->rdft_hlen[plane] * s->rdft_vlen[plane] * s->dc[plane] * (1 << (s->depth - 8)); ff_filter_execute(ctx, irdft_vertical, NULL, NULL, FFMIN(s->planeheight[1], s->nb_threads)); @@ -497,17 +543,19 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) static av_cold void uninit(AVFilterContext *ctx) { FFTFILTContext *s = ctx->priv; - int i; - for (i = 0; i < MAX_PLANES; i++) { - av_free(s->rdft_hdata[i]); - av_free(s->rdft_vdata[i]); + + for (int i = 0; i < MAX_PLANES; i++) { + av_freep(&s->rdft_hdata_in[i]); + av_freep(&s->rdft_vdata_in[i]); + av_freep(&s->rdft_hdata_out[i]); + av_freep(&s->rdft_vdata_out[i]); av_expr_free(s->weight_expr[i]); - av_free(s->weight[i]); + av_freep(&s->weight[i]); for (int j = 0; j < s->nb_threads; j++) { - av_rdft_end(s->hrdft[j][i]); - av_rdft_end(s->ihrdft[j][i]); - av_rdft_end(s->vrdft[j][i]); - av_rdft_end(s->ivrdft[j][i]); + av_tx_uninit(&s->hrdft[j][i]); + av_tx_uninit(&s->ihrdft[j][i]); + av_tx_uninit(&s->vrdft[j][i]); + av_tx_uninit(&s->ivrdft[j][i]); } } } diff --git a/libavfilter/vf_fieldhint.c b/libavfilter/vf_fieldhint.c index e4513dddf..e6061c6d3 100644 --- a/libavfilter/vf_fieldhint.c +++ b/libavfilter/vf_fieldhint.c @@ -27,6 +27,13 @@ #include "internal.h" #include "video.h" +enum HintModes { + ABSOLUTE_HINT, + RELATIVE_HINT, + PATTERN_HINT, + NB_HINTS, +}; + typedef struct FieldHintContext { const AVClass *class; @@ -48,9 +55,10 @@ typedef struct FieldHintContext { static const AVOption fieldhint_options[] = { { "hint", "set hint file", OFFSET(hint_file_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, - { "mode", "set hint mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "mode" }, - { "absolute", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "mode" }, - { "relative", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "mode" }, + { "mode", "set hint mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_HINTS-1, FLAGS, "mode" }, + { "absolute", 0, 0, AV_OPT_TYPE_CONST, {.i64=ABSOLUTE_HINT}, 0, 0, FLAGS, "mode" }, + { "relative", 0, 0, AV_OPT_TYPE_CONST, {.i64=RELATIVE_HINT}, 0, 0, FLAGS, "mode" }, + { "pattern", 0, 0, AV_OPT_TYPE_CONST, {.i64=PATTERN_HINT}, 0, 0, FLAGS, "mode" }, { NULL } }; @@ -65,7 +73,7 @@ static av_cold int init(AVFilterContext *ctx) av_log(ctx, AV_LOG_ERROR, "Hint file must be set.\n"); return AVERROR(EINVAL); } - s->hint = av_fopen_utf8(s->hint_file_str, "r"); + s->hint = avpriv_fopen_utf8(s->hint_file_str, "r"); if (!s->hint) { ret = AVERROR(errno); av_log(ctx, AV_LOG_ERROR, "%s: %s\n", s->hint_file_str, av_err2str(ret)); @@ -141,22 +149,30 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) return AVERROR_INVALIDDATA; } switch (s->mode) { - case 0: + case ABSOLUTE_HINT: if (tf > outlink->frame_count_in + 1 || tf < FFMAX(0, outlink->frame_count_in - 1) || bf > outlink->frame_count_in + 1 || bf < FFMAX(0, outlink->frame_count_in - 1)) { av_log(ctx, AV_LOG_ERROR, "Out of range frames %"PRId64" and/or %"PRId64" on line %"PRId64" for %"PRId64". input frame.\n", tf, bf, s->line, inlink->frame_count_out); return AVERROR_INVALIDDATA; } break; - case 1: + case PATTERN_HINT: + case RELATIVE_HINT: if (tf > 1 || tf < -1 || bf > 1 || bf < -1) { av_log(ctx, AV_LOG_ERROR, "Out of range %"PRId64" and/or %"PRId64" on line %"PRId64" for %"PRId64". input frame.\n", tf, bf, s->line, inlink->frame_count_out); return AVERROR_INVALIDDATA; } + break; + default: + return AVERROR_BUG; }; break; } else { + if (s->mode == PATTERN_HINT) { + fseek(s->hint, 0, SEEK_SET); + continue; + } av_log(ctx, AV_LOG_ERROR, "Missing entry for %"PRId64". input frame.\n", inlink->frame_count_out); return AVERROR_INVALIDDATA; } @@ -168,11 +184,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) av_frame_copy_props(out, s->frame[1]); switch (s->mode) { - case 0: + case ABSOLUTE_HINT: top = s->frame[tf - outlink->frame_count_in + 1]; bottom = s->frame[bf - outlink->frame_count_in + 1]; break; - case 1: + case PATTERN_HINT: + case RELATIVE_HINT: top = s->frame[1 + tf]; bottom = s->frame[1 + bf]; break; diff --git a/libavfilter/vf_fieldmatch.c b/libavfilter/vf_fieldmatch.c index ab027b80e..40e559df9 100644 --- a/libavfilter/vf_fieldmatch.c +++ b/libavfilter/vf_fieldmatch.c @@ -79,7 +79,7 @@ typedef struct FieldMatchContext { AVFrame *prv, *src, *nxt; ///< main sliding window of 3 frames AVFrame *prv2, *src2, *nxt2; ///< sliding window of the optional second stream int got_frame[2]; ///< frame request flag for each input stream - int hsub, vsub; ///< chroma subsampling values + int hsub[2], vsub[2]; ///< chroma subsampling values int bpc; ///< bytes per component uint32_t eof; ///< bitmask for end of stream int64_t lastscdiff; @@ -153,14 +153,14 @@ static const AVOption fieldmatch_options[] = { AVFILTER_DEFINE_CLASS(fieldmatch); -static int get_width(const FieldMatchContext *fm, const AVFrame *f, int plane) +static int get_width(const FieldMatchContext *fm, const AVFrame *f, int plane, int input) { - return plane ? AV_CEIL_RSHIFT(f->width, fm->hsub) : f->width; + return plane ? AV_CEIL_RSHIFT(f->width, fm->hsub[input]) : f->width; } -static int get_height(const FieldMatchContext *fm, const AVFrame *f, int plane) +static int get_height(const FieldMatchContext *fm, const AVFrame *f, int plane, int input) { - return plane ? AV_CEIL_RSHIFT(f->height, fm->vsub) : f->height; + return plane ? AV_CEIL_RSHIFT(f->height, fm->vsub[input]) : f->height; } static int64_t luma_abs_diff(const AVFrame *f1, const AVFrame *f2) @@ -202,8 +202,8 @@ static int calc_combed_score(const FieldMatchContext *fm, const AVFrame *src) for (plane = 0; plane < (fm->chroma ? 3 : 1); plane++) { const uint8_t *srcp = src->data[plane]; const int src_linesize = src->linesize[plane]; - const int width = get_width (fm, src, plane); - const int height = get_height(fm, src, plane); + const int width = get_width (fm, src, plane, INPUT_MAIN); + const int height = get_height(fm, src, plane, INPUT_MAIN); uint8_t *cmkp = fm->cmask_data[plane]; const int cmk_linesize = fm->cmask_linesize[plane]; @@ -272,8 +272,8 @@ static int calc_combed_score(const FieldMatchContext *fm, const AVFrame *src) uint8_t *cmkp = fm->cmask_data[0]; uint8_t *cmkpU = fm->cmask_data[1]; uint8_t *cmkpV = fm->cmask_data[2]; - const int width = AV_CEIL_RSHIFT(src->width, fm->hsub); - const int height = AV_CEIL_RSHIFT(src->height, fm->vsub); + const int width = AV_CEIL_RSHIFT(src->width, fm->hsub[INPUT_MAIN]); + const int height = AV_CEIL_RSHIFT(src->height, fm->vsub[INPUT_MAIN]); const int cmk_linesize = fm->cmask_linesize[0] << 1; const int cmk_linesizeUV = fm->cmask_linesize[2]; uint8_t *cmkpp = cmkp - (cmk_linesize>>1); @@ -503,11 +503,11 @@ static int compare_fields(FieldMatchContext *fm, int match1, int match2, int fie const int srcf_linesize = src_linesize << 1; int prv_linesize, nxt_linesize; int prvf_linesize, nxtf_linesize; - const int width = get_width (fm, src, plane); - const int height = get_height(fm, src, plane); - const int y0a = fm->y0 >> (plane ? fm->vsub : 0); - const int y1a = fm->y1 >> (plane ? fm->vsub : 0); - const int startx = (plane == 0 ? 8 : 8 >> fm->hsub); + const int width = get_width (fm, src, plane, INPUT_MAIN); + const int height = get_height(fm, src, plane, INPUT_MAIN); + const int y0a = fm->y0 >> (plane ? fm->vsub[INPUT_MAIN] : 0); + const int y1a = fm->y1 >> (plane ? fm->vsub[INPUT_MAIN] : 0); + const int startx = (plane == 0 ? 8 : 8 >> fm->hsub[INPUT_MAIN]); const int stopx = width - startx; const uint8_t *srcpf, *srcf, *srcnf; const uint8_t *prvpf, *prvnf, *nxtpf, *nxtnf; @@ -607,20 +607,20 @@ static int compare_fields(FieldMatchContext *fm, int match1, int match2, int fie } static void copy_fields(const FieldMatchContext *fm, AVFrame *dst, - const AVFrame *src, int field) + const AVFrame *src, int field, int input) { int plane; for (plane = 0; plane < 4 && src->data[plane] && src->linesize[plane]; plane++) { - const int plane_h = get_height(fm, src, plane); + const int plane_h = get_height(fm, src, plane, input); const int nb_copy_fields = (plane_h >> 1) + (field ? 0 : (plane_h & 1)); av_image_copy_plane(dst->data[plane] + field*dst->linesize[plane], dst->linesize[plane] << 1, src->data[plane] + field*src->linesize[plane], src->linesize[plane] << 1, - get_width(fm, src, plane) * fm->bpc, nb_copy_fields); + get_width(fm, src, plane, input) * fm->bpc, nb_copy_fields); } } static AVFrame *create_weave_frame(AVFilterContext *ctx, int match, int field, - const AVFrame *prv, AVFrame *src, const AVFrame *nxt) + const AVFrame *prv, AVFrame *src, const AVFrame *nxt, int input) { AVFrame *dst; FieldMatchContext *fm = ctx->priv; @@ -628,18 +628,18 @@ static AVFrame *create_weave_frame(AVFilterContext *ctx, int match, int field, if (match == mC) { dst = av_frame_clone(src); } else { - AVFilterLink *outlink = ctx->outputs[0]; + AVFilterLink *link = input == INPUT_CLEANSRC ? ctx->outputs[0] : ctx->inputs[INPUT_MAIN]; - dst = ff_get_video_buffer(outlink, outlink->w, outlink->h); + dst = ff_get_video_buffer(link, link->w, link->h); if (!dst) return NULL; av_frame_copy_props(dst, src); switch (match) { - case mP: copy_fields(fm, dst, src, 1-field); copy_fields(fm, dst, prv, field); break; - case mN: copy_fields(fm, dst, src, 1-field); copy_fields(fm, dst, nxt, field); break; - case mB: copy_fields(fm, dst, src, field); copy_fields(fm, dst, prv, 1-field); break; - case mU: copy_fields(fm, dst, src, field); copy_fields(fm, dst, nxt, 1-field); break; + case mP: copy_fields(fm, dst, src, 1-field, input); copy_fields(fm, dst, prv, field, input); break; + case mN: copy_fields(fm, dst, src, 1-field, input); copy_fields(fm, dst, nxt, field, input); break; + case mB: copy_fields(fm, dst, src, field, input); copy_fields(fm, dst, prv, 1-field, input); break; + case mU: copy_fields(fm, dst, src, field, input); copy_fields(fm, dst, nxt, 1-field, input); break; default: av_assert0(0); } } @@ -655,7 +655,8 @@ static int checkmm(AVFilterContext *ctx, int *combs, int m1, int m2, if (combs[mid] < 0) { \ if (!gen_frames[mid]) \ gen_frames[mid] = create_weave_frame(ctx, mid, field, \ - fm->prv, fm->src, fm->nxt); \ + fm->prv, fm->src, fm->nxt, \ + INPUT_MAIN); \ combs[mid] = calc_combed_score(fm, gen_frames[mid]); \ } \ } while (0) @@ -724,7 +725,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) for (i = 0; i < FF_ARRAY_ELEMS(combs); i++) { if (i > mN && fm->combdbg == COMBDBG_PCN) break; - gen_frames[i] = create_weave_frame(ctx, i, field, fm->prv, fm->src, fm->nxt); + gen_frames[i] = create_weave_frame(ctx, i, field, fm->prv, fm->src, fm->nxt, INPUT_MAIN); if (!gen_frames[i]) { ret = AVERROR(ENOMEM); goto fail; @@ -796,10 +797,10 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) if (fm->ppsrc) { /* field matching was based on a filtered/post-processed input, we now * pick the untouched fields from the clean source */ - dst = create_weave_frame(ctx, match, field, fm->prv2, fm->src2, fm->nxt2); + dst = create_weave_frame(ctx, match, field, fm->prv2, fm->src2, fm->nxt2, INPUT_CLEANSRC); } else { if (!gen_frames[match]) { // XXX: is that possible? - dst = create_weave_frame(ctx, match, field, fm->prv, fm->src, fm->nxt); + dst = create_weave_frame(ctx, match, field, fm->prv, fm->src, fm->nxt, INPUT_MAIN); } else { dst = gen_frames[match]; gen_frames[match] = NULL; @@ -944,8 +945,13 @@ static int config_input(AVFilterLink *inlink) (ret = av_image_alloc(fm->cmask_data, fm->cmask_linesize, w, h, inlink->format, 32)) < 0) return ret; - fm->hsub = pix_desc->log2_chroma_w; - fm->vsub = pix_desc->log2_chroma_h; + fm->hsub[INPUT_MAIN] = pix_desc->log2_chroma_w; + fm->vsub[INPUT_MAIN] = pix_desc->log2_chroma_h; + if (fm->ppsrc) { + pix_desc = av_pix_fmt_desc_get(ctx->inputs[INPUT_CLEANSRC]->format); + fm->hsub[INPUT_CLEANSRC] = pix_desc->log2_chroma_w; + fm->vsub[INPUT_CLEANSRC] = pix_desc->log2_chroma_h; + } fm->tpitchy = FFALIGN(w, 16); fm->tpitchuv = FFALIGN(w >> 1, 16); diff --git a/libavfilter/vf_format.c b/libavfilter/vf_format.c index c78acbf87..24b1c9ca6 100644 --- a/libavfilter/vf_format.c +++ b/libavfilter/vf_format.c @@ -23,6 +23,8 @@ * format and noformat video filters */ +#include "config_components.h" + #include #include "libavutil/internal.h" diff --git a/libavfilter/vf_fps.c b/libavfilter/vf_fps.c index 99e679441..0e5a1fec3 100644 --- a/libavfilter/vf_fps.c +++ b/libavfilter/vf_fps.c @@ -351,7 +351,7 @@ static int activate(AVFilterContext *ctx) 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) + if (again && ff_inoutlink_check_flow(inlink, outlink)) ff_filter_set_ready(ctx, 100); return ret; } diff --git a/libavfilter/vf_framerate.c b/libavfilter/vf_framerate.c index f11614775..49bf6cdff 100644 --- a/libavfilter/vf_framerate.c +++ b/libavfilter/vf_framerate.c @@ -264,8 +264,9 @@ void ff_framerate_init(FrameRateContext *s) s->blend_factor_max = 1 << BLEND_FACTOR_DEPTH(16); s->blend = blend_frames16_c; } - if (ARCH_X86) - ff_framerate_init_x86(s); +#if ARCH_X86 + ff_framerate_init_x86(s); +#endif } static int config_input(AVFilterLink *inlink) diff --git a/libavfilter/vf_frei0r.c b/libavfilter/vf_frei0r.c index 9cd0098e7..1e01114b7 100644 --- a/libavfilter/vf_frei0r.c +++ b/libavfilter/vf_frei0r.c @@ -31,6 +31,7 @@ #include "libavutil/avstring.h" #include "libavutil/common.h" #include "libavutil/eval.h" +#include "libavutil/getenv_utf8.h" #include "libavutil/imgutils.h" #include "libavutil/internal.h" #include "libavutil/mathematics.h" @@ -204,7 +205,7 @@ static av_cold int frei0r_init(AVFilterContext *ctx, } /* see: http://frei0r.dyne.org/codedoc/html/group__pluglocations.html */ - if ((path = av_strdup(getenv("FREI0R_PATH")))) { + if (path = getenv_dup("FREI0R_PATH")) { #ifdef _WIN32 const char *separator = ";"; #else @@ -231,12 +232,17 @@ static av_cold int frei0r_init(AVFilterContext *ctx, if (ret < 0) return ret; } - if (!s->dl_handle && (path = getenv("HOME"))) { + if (!s->dl_handle && (path = getenv_utf8("HOME"))) { char *prefix = av_asprintf("%s/.frei0r-1/lib/", path); - if (!prefix) - return AVERROR(ENOMEM); + if (!prefix) { + ret = AVERROR(ENOMEM); + goto home_path_end; + } ret = load_path(ctx, &s->dl_handle, prefix, dl_name); av_free(prefix); + + home_path_end: + freeenv_utf8(path); if (ret < 0) return ret; } @@ -353,15 +359,21 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) { Frei0rContext *s = inlink->dst->priv; AVFilterLink *outlink = inlink->dst->outputs[0]; - AVFrame *out; + AVFrame *out = ff_default_get_video_buffer2(outlink, outlink->w, outlink->h, 16); + if (!out) + goto fail; - 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); + if (in->linesize[0] != out->linesize[0]) { + AVFrame *in2 = ff_default_get_video_buffer2(outlink, outlink->w, outlink->h, 16); + if (!in2) + goto fail; + av_frame_copy(in2, in); + av_frame_free(&in); + in = in2; + } + s->update(s->instance, in->pts * av_q2d(inlink->time_base) * 1000, (const uint32_t *)in->data[0], (uint32_t *)out->data[0]); @@ -369,6 +381,10 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) av_frame_free(&in); return ff_filter_frame(outlink, out); +fail: + av_frame_free(&in); + av_frame_free(&out); + return AVERROR(ENOMEM); } static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, @@ -465,7 +481,7 @@ static int source_config_props(AVFilterLink *outlink) static int source_request_frame(AVFilterLink *outlink) { Frei0rContext *s = outlink->src->priv; - AVFrame *frame = ff_get_video_buffer(outlink, outlink->w, outlink->h); + AVFrame *frame = ff_default_get_video_buffer2(outlink, outlink->w, outlink->h, 16); if (!frame) return AVERROR(ENOMEM); diff --git a/libavfilter/vf_fspp.c b/libavfilter/vf_fspp.c index 46ed51450..3e04fd01b 100644 --- a/libavfilter/vf_fspp.c +++ b/libavfilter/vf_fspp.c @@ -525,8 +525,9 @@ static int config_input(AVFilterLink *inlink) fspp->row_idct = row_idct_c; fspp->row_fdct = row_fdct_c; - if (ARCH_X86) - ff_fspp_init_x86(fspp); +#if ARCH_X86 + ff_fspp_init_x86(fspp); +#endif return 0; } diff --git a/libavfilter/vf_fspp.h b/libavfilter/vf_fspp.h index 6623af450..ee7de3ffe 100644 --- a/libavfilter/vf_fspp.h +++ b/libavfilter/vf_fspp.h @@ -23,6 +23,7 @@ #ifndef AVFILTER_FSPP_H #define AVFILTER_FSPP_H +#include "libavutil/video_enc_params.h" #include "avfilter.h" #define BLOCKSZ 12 @@ -61,7 +62,7 @@ typedef struct FSPPContext { int vsub; int temp_stride; int qp; - int qscale_type; + enum AVVideoEncParamsType qscale_type; int prev_q; uint8_t *src; int16_t *temp; diff --git a/libavfilter/vf_gblur.c b/libavfilter/vf_gblur.c index 9a74686fb..8bb851a77 100644 --- a/libavfilter/vf_gblur.c +++ b/libavfilter/vf_gblur.c @@ -34,6 +34,7 @@ #include "formats.h" #include "gblur.h" #include "internal.h" +#include "vf_gblur_init.h" #include "video.h" #define OFFSET(x) offsetof(GBlurContext, x) @@ -54,37 +55,6 @@ typedef struct ThreadData { int width; } ThreadData; -static void postscale_c(float *buffer, int length, - float postscale, float min, float max) -{ - for (int i = 0; i < length; i++) { - buffer[i] *= postscale; - buffer[i] = av_clipf(buffer[i], min, max); - } -} - -static void horiz_slice_c(float *buffer, int width, int height, int steps, - float nu, float bscale, float *localbuf) -{ - int step, x, y; - float *ptr; - for (y = 0; y < height; y++) { - for (step = 0; step < steps; step++) { - ptr = buffer + width * y; - ptr[0] *= bscale; - - /* Filter rightwards */ - for (x = 1; x < width; x++) - ptr[x] += nu * ptr[x - 1]; - ptr[x = width - 1] *= bscale; - - /* Filter leftwards */ - for (; x > 0; x--) - ptr[x - 1] += nu * ptr[x]; - } - } -} - static int filter_horizontally(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { GBlurContext *s = ctx->priv; @@ -108,53 +78,6 @@ static int filter_horizontally(AVFilterContext *ctx, void *arg, int jobnr, int n return 0; } -static void do_vertical_columns(float *buffer, int width, int height, - int column_begin, int column_end, int steps, - float nu, float boundaryscale, int column_step) -{ - const int numpixels = width * height; - int i, x, k, step; - float *ptr; - for (x = column_begin; x < column_end;) { - for (step = 0; step < steps; step++) { - ptr = buffer + x; - for (k = 0; k < column_step; k++) { - ptr[k] *= boundaryscale; - } - /* Filter downwards */ - for (i = width; i < numpixels; i += width) { - for (k = 0; k < column_step; k++) { - ptr[i + k] += nu * ptr[i - width + k]; - } - } - i = numpixels - width; - - for (k = 0; k < column_step; k++) - ptr[i + k] *= boundaryscale; - - /* Filter upwards */ - for (; i > 0; i -= width) { - for (k = 0; k < column_step; k++) - ptr[i - width + k] += nu * ptr[i + k]; - } - } - x += column_step; - } -} - -static void verti_slice_c(float *buffer, int width, int height, - int slice_start, int slice_end, int steps, - float nu, float boundaryscale) -{ - int aligned_end = slice_start + (((slice_end - slice_start) >> 3) << 3); - /* Filter vertically along columns (process 8 columns in each step) */ - do_vertical_columns(buffer, width, height, slice_start, aligned_end, - steps, nu, boundaryscale, 8); - /* Filter un-aligned columns one by one */ - do_vertical_columns(buffer, width, height, aligned_end, slice_end, - steps, nu, boundaryscale, 1); -} - static int filter_vertically(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { GBlurContext *s = ctx->priv; @@ -239,14 +162,12 @@ static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_NONE }; -void ff_gblur_init(GBlurContext *s) +static av_cold void uninit(AVFilterContext *ctx) { - s->localbuf = NULL; - s->horiz_slice = horiz_slice_c; - s->verti_slice = verti_slice_c; - s->postscale_slice = postscale_c; - if (ARCH_X86) - ff_gblur_init_x86(s); + GBlurContext *s = ctx->priv; + + av_freep(&s->buffer); + av_freep(&s->localbuf); } static int config_input(AVFilterLink *inlink) @@ -254,6 +175,8 @@ static int config_input(AVFilterLink *inlink) const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); GBlurContext *s = inlink->dst->priv; + uninit(inlink->dst); + s->depth = desc->comp[0].depth; s->flt = !!(desc->flags & AV_PIX_FMT_FLAG_FLOAT); s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w); @@ -357,17 +280,15 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) width * sizeof(float), height); } else if (s->depth == 8) { for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - dst[x] = bptr[x]; - } + for (x = 0; x < width; x++) + dst[x] = lrintf(bptr[x]); bptr += width; dst += out->linesize[plane]; } } else { for (y = 0; y < height; y++) { - for (x = 0; x < width; x++) { - dst16[x] = bptr[x]; - } + for (x = 0; x < width; x++) + dst16[x] = lrintf(bptr[x]); bptr += width; dst16 += out->linesize[plane] / 2; } @@ -379,15 +300,6 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) return ff_filter_frame(outlink, out); } -static av_cold void uninit(AVFilterContext *ctx) -{ - GBlurContext *s = ctx->priv; - - av_freep(&s->buffer); - if (s->localbuf) - av_free(s->localbuf); -} - static const AVFilterPad gblur_inputs[] = { { .name = "default", diff --git a/libavfilter/vf_gblur_init.h b/libavfilter/vf_gblur_init.h new file mode 100644 index 000000000..212db9f7a --- /dev/null +++ b/libavfilter/vf_gblur_init.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2011 Pascal Getreuer + * Copyright (c) 2016 Paul B Mahol + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef AVFILTER_GBLUR_INIT_H +#define AVFILTER_GBLUR_INIT_H + +#include "config.h" +#include "libavutil/attributes.h" +#include "libavutil/common.h" +#include "gblur.h" + +static void postscale_c(float *buffer, int length, + float postscale, float min, float max) +{ + for (int i = 0; i < length; i++) { + buffer[i] *= postscale; + buffer[i] = av_clipf(buffer[i], min, max); + } +} + +static void horiz_slice_c(float *buffer, int width, int height, int steps, + float nu, float bscale, float *localbuf) +{ + int x; + for (int y = 0; y < height; y++) { + for (int step = 0; step < steps; step++) { + float *ptr = buffer + width * y; + ptr[0] *= bscale; + + /* Filter rightwards */ + for (x = 1; x < width; x++) + ptr[x] += nu * ptr[x - 1]; + ptr[x = width - 1] *= bscale; + + /* Filter leftwards */ + for (; x > 0; x--) + ptr[x - 1] += nu * ptr[x]; + } + } +} + +static void do_vertical_columns(float *buffer, int width, int height, + int column_begin, int column_end, int steps, + float nu, float boundaryscale, int column_step) +{ + const int numpixels = width * height; + int i; + for (int x = column_begin; x < column_end;) { + for (int step = 0; step < steps; step++) { + float *ptr = buffer + x; + for (int k = 0; k < column_step; k++) { + ptr[k] *= boundaryscale; + } + /* Filter downwards */ + for (i = width; i < numpixels; i += width) { + for (int k = 0; k < column_step; k++) { + ptr[i + k] += nu * ptr[i - width + k]; + } + } + i = numpixels - width; + + for (int k = 0; k < column_step; k++) + ptr[i + k] *= boundaryscale; + + /* Filter upwards */ + for (; i > 0; i -= width) { + for (int k = 0; k < column_step; k++) + ptr[i - width + k] += nu * ptr[i + k]; + } + } + x += column_step; + } +} + +static void verti_slice_c(float *buffer, int width, int height, + int slice_start, int slice_end, int steps, + float nu, float boundaryscale) +{ + int aligned_end = slice_start + (((slice_end - slice_start) >> 3) << 3); + /* Filter vertically along columns (process 8 columns in each step) */ + do_vertical_columns(buffer, width, height, slice_start, aligned_end, + steps, nu, boundaryscale, 8); + /* Filter un-aligned columns one by one */ + do_vertical_columns(buffer, width, height, aligned_end, slice_end, + steps, nu, boundaryscale, 1); +} + +static av_unused void ff_gblur_init(GBlurContext *s) +{ + s->localbuf = NULL; + s->horiz_slice = horiz_slice_c; + s->verti_slice = verti_slice_c; + s->postscale_slice = postscale_c; +#if ARCH_X86 + ff_gblur_init_x86(s); +#endif +} + +#endif /* AVFILTER_GBLUR_INIT_H */ diff --git a/libavfilter/vf_gblur_vulkan.c b/libavfilter/vf_gblur_vulkan.c index a2e33d1c9..d61f3c778 100644 --- a/libavfilter/vf_gblur_vulkan.c +++ b/libavfilter/vf_gblur_vulkan.c @@ -1,5 +1,5 @@ /* - * copyright (c) 2021 Wu Jianhua + * copyright (c) 2021-2022 Wu Jianhua * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or @@ -42,39 +42,25 @@ typedef struct GBlurVulkanContext { int initialized; int size; + int sizeV; int planes; - int kernel_size; float sigma; float sigmaV; AVFrame *tmpframe; } GBlurVulkanContext; -static const char gblur_horizontal[] = { - C(0, void gblur(const ivec2 pos, const int index) ) - C(0, { ) - C(1, vec4 sum = texture(input_image[index], pos) * kernel[0]; ) - C(0, ) - C(1, for(int i = 1; i < kernel.length(); i++) { ) - C(2, sum += texture(input_image[index], pos + vec2(i, 0.0)) * kernel[i]; ) - C(2, sum += texture(input_image[index], pos - vec2(i, 0.0)) * kernel[i]; ) - C(1, } ) - C(0, ) - C(1, imageStore(output_image[index], pos, sum); ) - C(0, } ) -}; - -static const char gblur_vertical[] = { - C(0, void gblur(const ivec2 pos, const int index) ) - C(0, { ) - C(1, vec4 sum = texture(input_image[index], pos) * kernel[0]; ) - C(0, ) - C(1, for(int i = 1; i < kernel.length(); i++) { ) - C(2, sum += texture(input_image[index], pos + vec2(0.0, i)) * kernel[i]; ) - C(2, sum += texture(input_image[index], pos - vec2(0.0, i)) * kernel[i]; ) - C(1, } ) - C(0, ) - C(1, imageStore(output_image[index], pos, sum); ) - C(0, } ) +static const char gblur_func[] = { + C(0, void gblur(const ivec2 pos, const int index) ) + C(0, { ) + C(1, vec4 sum = texture(input_images[index], pos) * kernel[0]; ) + C(0, ) + C(1, for(int i = 1; i < kernel.length(); i++) { ) + C(2, sum += texture(input_images[index], pos + OFFSET) * kernel[i]; ) + C(2, sum += texture(input_images[index], pos - OFFSET) * kernel[i]; ) + C(1, } ) + C(0, ) + C(1, imageStore(output_images[index], pos, sum); ) + C(0, } ) }; static inline float gaussian(float sigma, float x) @@ -109,46 +95,41 @@ static void init_gaussian_kernel(float *kernel, float sigma, float kernel_size) } } +static inline void init_kernel_size(GBlurVulkanContext *s, int *out_size) +{ + int size = *out_size; + + if (!(size & 1)) { + av_log(s, AV_LOG_WARNING, "The kernel size should be odd\n"); + size++; + } + + *out_size = (size >> 1) + 1; +} + static av_cold void init_gaussian_params(GBlurVulkanContext *s) { - if (!(s->size & 1)) { - av_log(s, AV_LOG_WARNING, "kernel size should be odd\n"); - s->size++; - } if (s->sigmaV <= 0) s->sigmaV = s->sigma; - s->kernel_size = (s->size >> 1) + 1; + init_kernel_size(s, &s->size); + + if (s->sizeV <= 0) + s->sizeV = s->size; + else + init_kernel_size(s, &s->sizeV); + s->tmpframe = NULL; } -static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) +static int init_gblur_pipeline(GBlurVulkanContext *s, FFVulkanPipeline *pl, FFVkSPIRVShader *shd, + FFVkBuffer *params_buf, VkDescriptorBufferInfo *params_desc, + int ksize, float sigma) { int err = 0; - char *kernel_def; uint8_t *kernel_mapped; - FFVkSPIRVShader *shd; - GBlurVulkanContext *s = ctx->priv; - const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); - FFVulkanDescriptorSetBinding image_descs[] = { - { - .name = "input_image", - .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - .dimensions = 2, - .elems = planes, - .stages = VK_SHADER_STAGE_COMPUTE_BIT, - }, - { - .name = "output_image", - .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, - .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format), - .mem_quali = "writeonly", - .dimensions = 2, - .elems = planes, - .stages = VK_SHADER_STAGE_COMPUTE_BIT, - }, - }; + const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); FFVulkanDescriptorSetBinding buf_desc = { .name = "data", @@ -160,24 +141,95 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) .buf_content = NULL, }; - image_descs[0].sampler = ff_vk_init_sampler(&s->vkctx, 1, VK_FILTER_LINEAR); - if (!image_descs[0].sampler) - return AVERROR_EXTERNAL; - - init_gaussian_params(s); - - kernel_def = av_asprintf("float kernel[%i];", s->kernel_size); + char *kernel_def = av_asprintf("float kernel[%i];", ksize); if (!kernel_def) return AVERROR(ENOMEM); + buf_desc.updater = params_desc; buf_desc.buf_content = kernel_def; + RET(ff_vk_add_descriptor_set(&s->vkctx, pl, shd, &buf_desc, 1, 0)); + + GLSLD( gblur_func ); + GLSLC(0, void main() ); + GLSLC(0, { ); + GLSLC(1, ivec2 size; ); + GLSLC(1, const ivec2 pos = ivec2(gl_GlobalInvocationID.xy); ); + for (int i = 0; i < planes; i++) { + GLSLC(0, ); + GLSLF(1, size = imageSize(output_images[%i]); ,i); + GLSLC(1, if (IS_WITHIN(pos, size)) { ); + if (s->planes & (1 << i)) { + GLSLF(2, gblur(pos, %i); ,i); + } else { + GLSLF(2, vec4 res = texture(input_images[%i], pos); ,i); + GLSLF(2, imageStore(output_images[%i], pos, res); ,i); + } + GLSLC(1, } ); + } + GLSLC(0, } ); + + RET(ff_vk_compile_shader(&s->vkctx, shd, "main")); + + RET(ff_vk_init_pipeline_layout(&s->vkctx, pl)); + RET(ff_vk_init_compute_pipeline(&s->vkctx, pl)); + + RET(ff_vk_create_buf(&s->vkctx, params_buf, sizeof(float) * ksize, + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)); + RET(ff_vk_map_buffers(&s->vkctx, params_buf, &kernel_mapped, 1, 0)); + + init_gaussian_kernel((float *)kernel_mapped, sigma, ksize); + + RET(ff_vk_unmap_buffers(&s->vkctx, params_buf, 1, 1)); + + params_desc->buffer = params_buf->buf; + params_desc->range = VK_WHOLE_SIZE; + + ff_vk_update_descriptor_set(&s->vkctx, pl, 1); + +fail: + av_free(kernel_def); + return err; +} + +static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) +{ + int err = 0; + GBlurVulkanContext *s = ctx->priv; + FFVkSPIRVShader *shd; + const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); + + FFVulkanDescriptorSetBinding image_descs[] = { + { + .name = "input_images", + .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .dimensions = 2, + .elems = planes, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + }, + { + .name = "output_images", + .type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + .mem_layout = ff_vk_shader_rep_fmt(s->vkctx.output_format), + .mem_quali = "writeonly", + .dimensions = 2, + .elems = planes, + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + }, + }; + + image_descs[0].sampler = ff_vk_init_sampler(&s->vkctx, 1, VK_FILTER_LINEAR); + if (!image_descs[0].sampler) + return AVERROR_EXTERNAL; + + init_gaussian_params(s); + ff_vk_qf_init(&s->vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0); - { /* Create shader for the horizontal pass */ + { + /* Create shader for the horizontal pass */ image_descs[0].updater = s->input_images; image_descs[1].updater = s->tmp_images; - buf_desc.updater = &s->params_desc_hor; s->pl_hor = ff_vk_create_pipeline(&s->vkctx, &s->qf); if (!s->pl_hor) { @@ -191,52 +243,18 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) goto fail; } - ff_vk_set_compute_shader_sizes(shd, (int [3]){ CGS, CGS, 1 }); + ff_vk_set_compute_shader_sizes(shd, (int [3]){ CGS, 1, 1 }); RET(ff_vk_add_descriptor_set(&s->vkctx, s->pl_hor, shd, image_descs, FF_ARRAY_ELEMS(image_descs), 0)); - RET(ff_vk_add_descriptor_set(&s->vkctx, s->pl_hor, shd, &buf_desc, 1, 0)); - GLSLD( gblur_horizontal ); - GLSLC(0, void main() ); - GLSLC(0, { ); - GLSLC(1, ivec2 size; ); - GLSLC(1, const ivec2 pos = ivec2(gl_GlobalInvocationID.xy); ); - for (int i = 0; i < planes; i++) { - GLSLC(0, ); - GLSLF(1, size = imageSize(output_image[%i]); ,i); - GLSLC(1, if (IS_WITHIN(pos, size)) { ); - if (s->planes & (1 << i)) { - GLSLF(2, gblur(pos, %i); ,i); - } else { - GLSLF(2, vec4 res = texture(input_image[%i], pos); ,i); - GLSLF(2, imageStore(output_image[%i], pos, res); ,i); - } - GLSLC(1, } ); - } - GLSLC(0, } ); - - RET(ff_vk_compile_shader(&s->vkctx, shd, "main")); - - RET(ff_vk_init_pipeline_layout(&s->vkctx, s->pl_hor)); - RET(ff_vk_init_compute_pipeline(&s->vkctx, s->pl_hor)); - - RET(ff_vk_create_buf(&s->vkctx, &s->params_buf_hor, sizeof(float) * s->kernel_size, - VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)); - RET(ff_vk_map_buffers(&s->vkctx, &s->params_buf_hor, &kernel_mapped, 1, 0)); - - init_gaussian_kernel((float *)kernel_mapped, s->sigma, s->kernel_size); - - RET(ff_vk_unmap_buffers(&s->vkctx, &s->params_buf_hor, 1, 1)); - - s->params_desc_hor.buffer = s->params_buf_hor.buf; - s->params_desc_hor.range = VK_WHOLE_SIZE; - - ff_vk_update_descriptor_set(&s->vkctx, s->pl_hor, 1); + GLSLC(0, #define OFFSET (vec2(i, 0.0))); + RET(init_gblur_pipeline(s, s->pl_hor, shd, &s->params_buf_hor, &s->params_desc_hor, + s->size, s->sigma)); } - { /* Create shader for the vertical pass */ + { + /* Create shader for the vertical pass */ image_descs[0].updater = s->tmp_images; image_descs[1].updater = s->output_images; - buf_desc.updater = &s->params_desc_ver; s->pl_ver = ff_vk_create_pipeline(&s->vkctx, &s->qf); if (!s->pl_ver) { @@ -250,46 +268,12 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) goto fail; } - ff_vk_set_compute_shader_sizes(shd, (int [3]){ CGS, CGS, 1 }); + ff_vk_set_compute_shader_sizes(shd, (int [3]){ 1, CGS, 1 }); RET(ff_vk_add_descriptor_set(&s->vkctx, s->pl_ver, shd, image_descs, FF_ARRAY_ELEMS(image_descs), 0)); - RET(ff_vk_add_descriptor_set(&s->vkctx, s->pl_ver, shd, &buf_desc, 1, 0)); - GLSLD( gblur_vertical ); - GLSLC(0, void main() ); - GLSLC(0, { ); - GLSLC(1, ivec2 size; ); - GLSLC(1, const ivec2 pos = ivec2(gl_GlobalInvocationID.xy); ); - for (int i = 0; i < planes; i++) { - GLSLC(0, ); - GLSLF(1, size = imageSize(output_image[%i]); ,i); - GLSLC(1, if (IS_WITHIN(pos, size)) { ); - if (s->planes & (1 << i)) { - GLSLF(2, gblur(pos, %i); ,i); - } else { - GLSLF(2, vec4 res = texture(input_image[%i], pos); ,i); - GLSLF(2, imageStore(output_image[%i], pos, res); ,i); - } - GLSLC(1, } ); - } - GLSLC(0, } ); - - RET(ff_vk_compile_shader(&s->vkctx, shd, "main")); - - RET(ff_vk_init_pipeline_layout(&s->vkctx, s->pl_ver)); - RET(ff_vk_init_compute_pipeline(&s->vkctx, s->pl_ver)); - - RET(ff_vk_create_buf(&s->vkctx, &s->params_buf_ver, sizeof(float) * s->kernel_size, - VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)); - RET(ff_vk_map_buffers(&s->vkctx, &s->params_buf_ver, &kernel_mapped, 1, 0)); - - init_gaussian_kernel((float *)kernel_mapped, s->sigmaV, s->kernel_size); - - RET(ff_vk_unmap_buffers(&s->vkctx, &s->params_buf_ver, 1, 1)); - - s->params_desc_ver.buffer = s->params_buf_ver.buf; - s->params_desc_ver.range = VK_WHOLE_SIZE; - - ff_vk_update_descriptor_set(&s->vkctx, s->pl_ver, 1); + GLSLC(0, #define OFFSET (vec2(0.0, i))); + RET(init_gblur_pipeline(s, s->pl_ver, shd, &s->params_buf_ver, &s->params_desc_ver, + s->sizeV, s->sigmaV)); } RET(ff_vk_create_exec_ctx(&s->vkctx, &s->exec, &s->qf)); @@ -297,7 +281,6 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) s->initialized = 1; fail: - av_free(kernel_def); return err; } @@ -318,22 +301,21 @@ static int process_frames(AVFilterContext *avctx, AVFrame *outframe, AVFrame *in { int err; VkCommandBuffer cmd_buf; - - const VkFormat *input_formats = NULL; - const VkFormat *output_formats = NULL; GBlurVulkanContext *s = avctx->priv; FFVulkanFunctions *vk = &s->vkctx.vkfn; - AVVkFrame *in = (AVVkFrame *)inframe->data[0]; - AVVkFrame *tmp = (AVVkFrame *)s->tmpframe->data[0]; - AVVkFrame *out = (AVVkFrame *)outframe->data[0]; - int planes = av_pix_fmt_count_planes(s->vkctx.output_format); + const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); + + AVVkFrame *in = (AVVkFrame *)inframe->data[0]; + AVVkFrame *out = (AVVkFrame *)outframe->data[0]; + AVVkFrame *tmp = (AVVkFrame *)s->tmpframe->data[0]; + + const VkFormat *input_formats = av_vkfmt_from_pixfmt(s->vkctx.input_format); + const VkFormat *output_formats = av_vkfmt_from_pixfmt(s->vkctx.output_format); ff_vk_start_exec_recording(&s->vkctx, s->exec); cmd_buf = ff_vk_get_exec_buf(s->exec); - input_formats = av_vkfmt_from_pixfmt(s->vkctx.input_format); - output_formats = av_vkfmt_from_pixfmt(s->vkctx.output_format); for (int i = 0; i < planes; i++) { RET(ff_vk_create_imageview(&s->vkctx, s->exec, &s->input_images[i].imageView, in->img[i], @@ -418,11 +400,11 @@ static int process_frames(AVFilterContext *avctx, AVFrame *outframe, AVFrame *in ff_vk_bind_pipeline_exec(&s->vkctx, s->exec, s->pl_hor); vk->CmdDispatch(cmd_buf, FFALIGN(s->vkctx.output_width, CGS)/CGS, - FFALIGN(s->vkctx.output_height, CGS)/CGS, 1); + s->vkctx.output_height, 1); ff_vk_bind_pipeline_exec(&s->vkctx, s->exec, s->pl_ver); - vk->CmdDispatch(cmd_buf, FFALIGN(s->vkctx.output_width, CGS)/CGS, + vk->CmdDispatch(cmd_buf,s->vkctx.output_width, FFALIGN(s->vkctx.output_height, CGS)/CGS, 1); ff_vk_add_exec_dep(&s->vkctx, s->exec, inframe, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); @@ -435,6 +417,7 @@ static int process_frames(AVFilterContext *avctx, AVFrame *outframe, AVFrame *in ff_vk_qf_rotate(&s->qf); return 0; + fail: ff_vk_discard_exec_deps(s->exec); return err; @@ -482,10 +465,11 @@ fail: #define OFFSET(x) offsetof(GBlurVulkanContext, x) #define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) static const AVOption gblur_vulkan_options[] = { - { "sigma", "Set sigma", OFFSET(sigma), AV_OPT_TYPE_FLOAT, {.dbl = 0.5}, 0.01, 1024.0, FLAGS }, - { "sigmaV", "Set vertical sigma", OFFSET(sigmaV), AV_OPT_TYPE_FLOAT, {.dbl = 0}, 0.0, 1024.0, FLAGS }, - { "planes", "Set planes to filter", OFFSET(planes), AV_OPT_TYPE_INT, {.i64 = 0xF}, 0, 0xF, FLAGS }, - { "size", "Set kernel size", OFFSET(size), AV_OPT_TYPE_INT, {.i64 = 19}, 1, GBLUR_MAX_KERNEL_SIZE, FLAGS }, + { "sigma", "Set sigma", OFFSET(sigma), AV_OPT_TYPE_FLOAT, { .dbl = 0.5 }, 0.01, 1024.0, FLAGS }, + { "sigmaV", "Set vertical sigma", OFFSET(sigmaV), AV_OPT_TYPE_FLOAT, { .dbl = 0 }, 0.0, 1024.0, FLAGS }, + { "planes", "Set planes to filter", OFFSET(planes), AV_OPT_TYPE_INT, { .i64 = 0xF }, 0, 0xF, FLAGS }, + { "size", "Set kernel size", OFFSET(size), AV_OPT_TYPE_INT, { .i64 = 19 }, 1, GBLUR_MAX_KERNEL_SIZE, FLAGS }, + { "sizeV", "Set vertical kernel size", OFFSET(sizeV), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, GBLUR_MAX_KERNEL_SIZE, FLAGS }, { NULL }, }; diff --git a/libavfilter/vf_geq.c b/libavfilter/vf_geq.c index eef1ac095..2b5398027 100644 --- a/libavfilter/vf_geq.c +++ b/libavfilter/vf_geq.c @@ -52,6 +52,7 @@ typedef struct GEQContext { AVFrame *picref; ///< current input buffer uint8_t *dst; ///< reference pointer to the 8bits output uint16_t *dst16; ///< reference pointer to the 16bits output + float *dst32; ///< reference pointer to the 32bits output double values[VAR_VARS_NB]; ///< expression values int hsub, vsub; ///< chroma subsampling int planes; ///< number of planes @@ -114,13 +115,19 @@ static inline double getpix(void *priv, double x, double y, int plane) x -= xi; y -= yi; - if (geq->bps > 8) { + if (geq->bps > 8 && geq->bps <= 16) { const uint16_t *src16 = (const uint16_t*)src; linesize /= 2; return (1-y)*((1-x)*src16[xi + yi * linesize] + x*src16[xi + 1 + yi * linesize]) + y *((1-x)*src16[xi + (yi+1) * linesize] + x*src16[xi + 1 + (yi+1) * linesize]); - } else { + } else if (geq->bps == 32) { + const float *src32 = (const float*)src; + linesize /= 4; + + return (1-y)*((1-x)*src32[xi + yi * linesize] + x*src32[xi + 1 + yi * linesize]) + + y *((1-x)*src32[xi + (yi+1) * linesize] + x*src32[xi + 1 + (yi+1) * linesize]); + } else if (geq->bps == 8) { return (1-y)*((1-x)*src[xi + yi * linesize] + x*src[xi + 1 + yi * linesize]) + y *((1-x)*src[xi + (yi+1) * linesize] + x*src[xi + 1 + (yi+1) * linesize]); } @@ -128,15 +135,22 @@ static inline double getpix(void *priv, double x, double y, int plane) xi = av_clipd(x, 0, w - 1); yi = av_clipd(y, 0, h - 1); - if (geq->bps > 8) { + if (geq->bps > 8 && geq->bps <= 16) { const uint16_t *src16 = (const uint16_t*)src; linesize /= 2; return src16[xi + yi * linesize]; - } else { + } else if (geq->bps == 32) { + const float *src32 = (const float*)src; + linesize /= 4; + + return src32[xi + yi * linesize]; + } else if (geq->bps == 8) { return src[xi + yi * linesize]; } } + + return 0; } static int calculate_sums(GEQContext *geq, int plane, int w, int h) @@ -150,10 +164,12 @@ static int calculate_sums(GEQContext *geq, int plane, int w, int h) geq->pixel_sums[plane] = av_malloc_array(w, h * sizeof (*geq->pixel_sums[plane])); if (!geq->pixel_sums[plane]) return AVERROR(ENOMEM); - if (geq->bps > 8) + if (geq->bps == 32) + linesize /= 4; + else if (geq->bps > 8 && geq->bps <= 16) linesize /= 2; for (yi = 0; yi < h; yi ++) { - if (geq->bps > 8) { + if (geq->bps > 8 && geq->bps <= 16) { const uint16_t *src16 = (const uint16_t*)src; double linesum = 0; @@ -161,13 +177,21 @@ static int calculate_sums(GEQContext *geq, int plane, int w, int h) linesum += src16[xi + yi * linesize]; geq->pixel_sums[plane][xi + yi * w] = linesum; } - } else { + } else if (geq->bps == 8) { double linesum = 0; for (xi = 0; xi < w; xi ++) { linesum += src[xi + yi * linesize]; geq->pixel_sums[plane][xi + yi * w] = linesum; } + } else if (geq->bps == 32) { + const float *src32 = (const float*)src; + double linesum = 0; + + for (xi = 0; xi < w; xi ++) { + linesum += src32[xi + yi * linesize]; + geq->pixel_sums[plane][xi + yi * w] = linesum; + } } if (yi) for (xi = 0; xi < w; xi ++) { @@ -249,8 +273,10 @@ static av_cold int geq_init(AVFilterContext *ctx) if (!geq->expr_str[V]) geq->expr_str[V] = av_strdup(geq->expr_str[U]); } - if (!geq->expr_str[A]) { + if (!geq->expr_str[A] && geq->bps != 32) { geq->expr_str[A] = av_asprintf("%d", (1<bps) - 1); + } else if (!geq->expr_str[A]) { + geq->expr_str[A] = av_asprintf("%f", 1.f); } if (!geq->expr_str[G]) geq->expr_str[G] = av_strdup("g(X,Y)"); @@ -322,6 +348,7 @@ static int geq_query_formats(AVFilterContext *ctx) AV_PIX_FMT_YUV444P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUVA444P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_GRAY16, + AV_PIX_FMT_GRAYF32, AV_PIX_FMT_NONE }; static const enum AVPixelFormat rgb_pix_fmts[] = { @@ -331,6 +358,7 @@ static int geq_query_formats(AVFilterContext *ctx) AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP16, + AV_PIX_FMT_GBRPF32, AV_PIX_FMT_GBRAPF32, AV_PIX_FMT_NONE }; const enum AVPixelFormat *pix_fmts = geq->is_rgb ? rgb_pix_fmts : yuv_pix_fmts; @@ -390,7 +418,7 @@ static int slice_geq_filter(AVFilterContext *ctx, void *arg, int jobnr, int nb_j } ptr += linesize; } - } else { + } else if (geq->bps <= 16) { uint16_t *ptr16 = geq->dst16 + (linesize/2) * slice_start; for (y = slice_start; y < slice_end; y++) { values[VAR_Y] = y; @@ -400,6 +428,16 @@ static int slice_geq_filter(AVFilterContext *ctx, void *arg, int jobnr, int nb_j } ptr16 += linesize/2; } + } else { + float *ptr32 = geq->dst32 + (linesize/4) * slice_start; + for (y = slice_start; y < slice_end; y++) { + values[VAR_Y] = y; + for (x = 0; x < width; x++) { + values[VAR_X] = x; + ptr32[x] = av_expr_eval(geq->e[plane][jobnr], values, geq); + } + ptr32 += linesize/4; + } } return 0; @@ -433,6 +471,7 @@ static int geq_filter_frame(AVFilterLink *inlink, AVFrame *in) geq->dst = out->data[plane]; geq->dst16 = (uint16_t*)out->data[plane]; + geq->dst32 = (float*)out->data[plane]; geq->values[VAR_W] = width; geq->values[VAR_H] = height; diff --git a/libavfilter/vf_gradfun.c b/libavfilter/vf_gradfun.c index 1ea65823c..71a5f9c78 100644 --- a/libavfilter/vf_gradfun.c +++ b/libavfilter/vf_gradfun.c @@ -131,8 +131,9 @@ static av_cold int init(AVFilterContext *ctx) s->blur_line = ff_gradfun_blur_line_c; s->filter_line = ff_gradfun_filter_line_c; - if (ARCH_X86) - ff_gradfun_init_x86(s); +#if ARCH_X86 + ff_gradfun_init_x86(s); +#endif av_log(ctx, AV_LOG_VERBOSE, "threshold:%.2f radius:%d\n", s->strength, s->radius); diff --git a/libavfilter/vf_guided.c b/libavfilter/vf_guided.c index 7636cd2cd..58a1ff5a2 100644 --- a/libavfilter/vf_guided.c +++ b/libavfilter/vf_guided.c @@ -59,23 +59,38 @@ typedef struct GuidedContext { int planewidth[4]; int planeheight[4]; + float *I; + float *II; + float *P; + float *IP; + float *meanI; + float *meanII; + float *meanP; + float *meanIP; + + float *A; + float *B; + float *meanA; + float *meanB; + int (*box_slice)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); } GuidedContext; #define OFFSET(x) offsetof(GuidedContext, x) -#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM +#define TFLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM static const AVOption guided_options[] = { - { "radius", "set the box radius", OFFSET(radius), AV_OPT_TYPE_INT, {.i64 = 3 }, 1, 20, FLAGS }, - { "eps", "set the regularization parameter (with square)", OFFSET(eps), AV_OPT_TYPE_FLOAT, {.dbl = 0.01 }, 0.0, 1, FLAGS }, - { "mode", "set filtering mode (0: basic mode; 1: fast mode)", OFFSET(mode), AV_OPT_TYPE_INT, {.i64 = BASIC}, BASIC, NB_MODES - 1, FLAGS, "mode" }, - { "basic", "basic guided filter", 0, AV_OPT_TYPE_CONST, {.i64 = BASIC}, 0, 0, FLAGS, "mode" }, - { "fast", "fast guided filter", 0, AV_OPT_TYPE_CONST, {.i64 = FAST }, 0, 0, FLAGS, "mode" }, - { "sub", "subsampling ratio for fast mode", OFFSET(sub), AV_OPT_TYPE_INT, {.i64 = 4 }, 2, 64, FLAGS }, - { "guidance", "set guidance mode (0: off mode; 1: on mode)", OFFSET(guidance), AV_OPT_TYPE_INT, {.i64 = OFF }, OFF, NB_GUIDANCE_MODES - 1, FLAGS, "guidance" }, - { "off", "only one input is enabled", 0, AV_OPT_TYPE_CONST, {.i64 = OFF }, 0, 0, FLAGS, "guidance" }, - { "on", "two inputs are required", 0, AV_OPT_TYPE_CONST, {.i64 = ON }, 0, 0, FLAGS, "guidance" }, - { "planes", "set planes to filter", OFFSET(planes), AV_OPT_TYPE_INT, {.i64 = 1 }, 0, 0xF, FLAGS }, + { "radius", "set the box radius", OFFSET(radius), AV_OPT_TYPE_INT, {.i64 = 3 }, 1, 20, TFLAGS }, + { "eps", "set the regularization parameter (with square)", OFFSET(eps), AV_OPT_TYPE_FLOAT, {.dbl = 0.01 }, 0.0, 1, TFLAGS }, + { "mode", "set filtering mode (0: basic mode; 1: fast mode)", OFFSET(mode), AV_OPT_TYPE_INT, {.i64 = BASIC}, BASIC, NB_MODES - 1, TFLAGS, "mode" }, + { "basic", "basic guided filter", 0, AV_OPT_TYPE_CONST, {.i64 = BASIC}, 0, 0, TFLAGS, "mode" }, + { "fast", "fast guided filter", 0, AV_OPT_TYPE_CONST, {.i64 = FAST }, 0, 0, TFLAGS, "mode" }, + { "sub", "subsampling ratio for fast mode", OFFSET(sub), AV_OPT_TYPE_INT, {.i64 = 4 }, 2, 64, TFLAGS }, + { "guidance", "set guidance mode (0: off mode; 1: on mode)", OFFSET(guidance), AV_OPT_TYPE_INT, {.i64 = OFF }, OFF, NB_GUIDANCE_MODES - 1, FLAGS, "guidance" }, + { "off", "only one input is enabled", 0, AV_OPT_TYPE_CONST, {.i64 = OFF }, 0, 0, FLAGS, "guidance" }, + { "on", "two inputs are required", 0, AV_OPT_TYPE_CONST, {.i64 = ON }, 0, 0, FLAGS, "guidance" }, + { "planes", "set planes to filter", OFFSET(planes), AV_OPT_TYPE_INT, {.i64 = 1 }, 0, 0xF, TFLAGS }, { NULL } }; @@ -196,38 +211,19 @@ static int guided_##name(AVFilterContext *ctx, GuidedContext *s, \ ThreadData t; \ const int nb_threads = ff_filter_get_nb_threads(ctx); \ - float *I; \ - float *II; \ - float *P; \ - float *IP; \ - float *meanI; \ - float *meanII; \ - float *meanP; \ - float *meanIP; \ - float *A; \ - float *B; \ - float *meanA; \ - float *meanB; \ + float *I = s->I; \ + float *II = s->II; \ + float *P = s->P; \ + float *IP = s->IP; \ + float *meanI = s->meanI; \ + float *meanII = s->meanII; \ + float *meanP = s->meanP; \ + float *meanIP = s->meanIP; \ + float *A = s->A; \ + float *B = s->B; \ + float *meanA = s->meanA; \ + float *meanB = s->meanB; \ \ - I = av_calloc(w * h, sizeof(float)); \ - II = av_calloc(w * h, sizeof(float)); \ - P = av_calloc(w * h, sizeof(float)); \ - IP = av_calloc(w * h, sizeof(float)); \ - meanI = av_calloc(w * h, sizeof(float)); \ - meanII = av_calloc(w * h, sizeof(float)); \ - meanP = av_calloc(w * h, sizeof(float)); \ - meanIP = av_calloc(w * h, sizeof(float)); \ - \ - A = av_calloc(w * h, sizeof(float)); \ - B = av_calloc(w * h, sizeof(float)); \ - meanA = av_calloc(w * h, sizeof(float)); \ - meanB = av_calloc(w * h, sizeof(float)); \ - \ - if (!I || !II || !P || !IP || !meanI || !meanII || !meanP || \ - !meanIP || !A || !B || !meanA || !meanB) { \ - ret = AVERROR(ENOMEM); \ - goto end; \ - } \ for (int i = 0;i < h;i++) { \ for (int j = 0;j < w;j++) { \ int x = i * w + j; \ @@ -279,19 +275,7 @@ static int guided_##name(AVFilterContext *ctx, GuidedContext *s, meanB[x] * maxval; \ } \ } \ -end: \ - av_freep(&I); \ - av_freep(&II); \ - av_freep(&P); \ - av_freep(&IP); \ - av_freep(&meanI); \ - av_freep(&meanII); \ - av_freep(&meanP); \ - av_freep(&meanIP); \ - av_freep(&A); \ - av_freep(&B); \ - av_freep(&meanA); \ - av_freep(&meanB); \ + \ return ret; \ } @@ -337,10 +321,12 @@ static int process_frame(FFFrameSync *fs) if (ret < 0) return ret; + if (ctx->is_disabled) + return ff_filter_frame(outlink, main_frame); + ret = filter_frame(ctx, &out_frame, main_frame, ref_frame); - if (ret < 0) { + if (ret < 0) return ret; - } av_frame_free(&main_frame); return ff_filter_frame(outlink, out_frame); @@ -349,11 +335,10 @@ static int process_frame(FFFrameSync *fs) static int config_output(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; - GuidedContext *s = ctx->priv; AVFilterLink *mainlink = ctx->inputs[0]; FFFrameSyncIn *in; - int ret; + int w, h, ret; if (s->guidance == ON) { if (ctx->inputs[0]->w != ctx->inputs[1]->w || @@ -363,12 +348,30 @@ static int config_output(AVFilterLink *outlink) } } - outlink->w = mainlink->w; - outlink->h = mainlink->h; + outlink->w = w = mainlink->w; + outlink->h = h = mainlink->h; outlink->time_base = mainlink->time_base; outlink->sample_aspect_ratio = mainlink->sample_aspect_ratio; outlink->frame_rate = mainlink->frame_rate; + s->I = av_calloc(w * h, sizeof(*s->I)); + s->II = av_calloc(w * h, sizeof(*s->II)); + s->P = av_calloc(w * h, sizeof(*s->P)); + s->IP = av_calloc(w * h, sizeof(*s->IP)); + s->meanI = av_calloc(w * h, sizeof(*s->meanI)); + s->meanII = av_calloc(w * h, sizeof(*s->meanII)); + s->meanP = av_calloc(w * h, sizeof(*s->meanP)); + s->meanIP = av_calloc(w * h, sizeof(*s->meanIP)); + + s->A = av_calloc(w * h, sizeof(*s->A)); + s->B = av_calloc(w * h, sizeof(*s->B)); + s->meanA = av_calloc(w * h, sizeof(*s->meanA)); + s->meanB = av_calloc(w * h, sizeof(*s->meanA)); + + if (!s->I || !s->II || !s->P || !s->IP || !s->meanI || !s->meanII || !s->meanP || + !s->meanIP || !s->A || !s->B || !s->meanA || !s->meanB) + return AVERROR(ENOMEM); + if (s->guidance == OFF) return 0; @@ -395,6 +398,8 @@ static int config_output(AVFilterLink *outlink) static int activate(AVFilterContext *ctx) { GuidedContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + AVFilterLink *inlink = ctx->inputs[0]; AVFrame *frame = NULL; AVFrame *out = NULL; int ret, status; @@ -402,23 +407,26 @@ static int activate(AVFilterContext *ctx) if (s->guidance) return ff_framesync_activate(&s->fs); - FF_FILTER_FORWARD_STATUS_BACK(ctx->outputs[0], ctx->inputs[0]); + FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); + + if ((ret = ff_inlink_consume_frame(inlink, &frame)) > 0) { + if (ctx->is_disabled) + return ff_filter_frame(outlink, frame); - if ((ret = ff_inlink_consume_frame(ctx->inputs[0], &frame)) > 0) { ret = filter_frame(ctx, &out, frame, frame); av_frame_free(&frame); if (ret < 0) return ret; - ret = ff_filter_frame(ctx->outputs[0], out); + ret = ff_filter_frame(outlink, out); } if (ret < 0) return ret; - if (ff_inlink_acknowledge_status(ctx->inputs[0], &status, &pts)) { - ff_outlink_set_status(ctx->outputs[0], status, pts); + if (ff_inlink_acknowledge_status(inlink, &status, &pts)) { + ff_outlink_set_status(outlink, status, pts); return 0; } - if (ff_outlink_frame_wanted(ctx->outputs[0])) - ff_inlink_request_frame(ctx->inputs[0]); + if (ff_outlink_frame_wanted(outlink)) + ff_inlink_request_frame(inlink); return 0; } @@ -452,24 +460,23 @@ static av_cold void uninit(AVFilterContext *ctx) GuidedContext *s = ctx->priv; if (s->guidance == ON) ff_framesync_uninit(&s->fs); + + av_freep(&s->I); + av_freep(&s->II); + av_freep(&s->P); + av_freep(&s->IP); + av_freep(&s->meanI); + av_freep(&s->meanII); + av_freep(&s->meanP); + av_freep(&s->meanIP); + av_freep(&s->A); + av_freep(&s->B); + av_freep(&s->meanA); + av_freep(&s->meanB); + return; } -static int process_command(AVFilterContext *ctx, - const char *cmd, - const char *arg, - char *res, - int res_len, - int flags) -{ - int ret = ff_filter_process_command(ctx, cmd, arg, res, res_len, flags); - - if (ret < 0) - return ret; - - return 0; -} - static const AVFilterPad guided_outputs[] = { { .name = "default", @@ -490,6 +497,6 @@ const AVFilter ff_vf_guided = { FILTER_OUTPUTS(guided_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), .flags = AVFILTER_FLAG_DYNAMIC_INPUTS | AVFILTER_FLAG_SLICE_THREADS | - AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, - .process_command = process_command, + AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, + .process_command = ff_filter_process_command, }; diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c index 036266067..8517b8788 100644 --- a/libavfilter/vf_hflip.c +++ b/libavfilter/vf_hflip.c @@ -31,6 +31,7 @@ #include "formats.h" #include "hflip.h" #include "internal.h" +#include "vf_hflip_init.h" #include "video.h" #include "libavutil/pixdesc.h" #include "libavutil/internal.h" @@ -61,70 +62,6 @@ 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; @@ -145,29 +82,6 @@ static int config_props(AVFilterLink *inlink) 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++) { - step[i] *= s->bayer_plus1; - 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; - 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, step, nb_planes); - - return 0; -} - typedef struct ThreadData { AVFrame *in, *out; } ThreadData; diff --git a/libavfilter/vf_hflip_init.h b/libavfilter/vf_hflip_init.h new file mode 100644 index 000000000..d0319f463 --- /dev/null +++ b/libavfilter/vf_hflip_init.h @@ -0,0 +1,111 @@ +/* + * 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_INIT_H +#define AVFILTER_HFLIP_INIT_H + +#include + +#include "config.h" +#include "libavutil/attributes.h" +#include "libavutil/intreadwrite.h" +#include "hflip.h" + +static void hflip_byte_c(const uint8_t *src, uint8_t *dst, int w) +{ + for (int 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; + + for (int 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; + + for (int 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; + + for (int 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; + + for (int 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; + + for (int j = 0; j < w; j++) + dst[j] = src[-j]; +} + +static av_unused int ff_hflip_init(FlipContext *s, int step[4], int nb_planes) +{ + for (int i = 0; i < nb_planes; i++) { + step[i] *= s->bayer_plus1; + 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; + 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, step, nb_planes); +#endif + + return 0; +} + +#endif /* AVFILTER_HFLIP_INIT_H */ diff --git a/libavfilter/vf_histogram.c b/libavfilter/vf_histogram.c index bf80b2c4f..ced7cda6f 100644 --- a/libavfilter/vf_histogram.c +++ b/libavfilter/vf_histogram.c @@ -18,6 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/colorspace.h" #include "libavutil/opt.h" #include "libavutil/parseutils.h" diff --git a/libavfilter/vf_hqdn3d.c b/libavfilter/vf_hqdn3d.c index 6078bb260..ce2b9a297 100644 --- a/libavfilter/vf_hqdn3d.c +++ b/libavfilter/vf_hqdn3d.c @@ -278,8 +278,9 @@ static int config_input(AVFilterLink *inlink) calc_coefs(ctx); - if (ARCH_X86) - ff_hqdn3d_init_x86(s); +#if ARCH_X86 + ff_hqdn3d_init_x86(s); +#endif return 0; } diff --git a/libavfilter/vf_iccdetect.c b/libavfilter/vf_iccdetect.c new file mode 100644 index 000000000..7c08a2baa --- /dev/null +++ b/libavfilter/vf_iccdetect.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2022 Niklas Haas + * 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 + * filter for generating ICC profiles + */ + +#include + +#include "libavutil/csp.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" + +#include "avfilter.h" +#include "fflcms2.h" +#include "internal.h" + +typedef struct IccDetectContext { + const AVClass *class; + FFIccContext icc; + int force; + /* (cached) detected ICC profile values */ + AVBufferRef *profile; + enum AVColorPrimaries profile_prim; + enum AVColorTransferCharacteristic profile_trc; +} IccDetectContext; + +#define OFFSET(x) offsetof(IccDetectContext, x) +#define VF AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM + +static const AVOption iccdetect_options[] = { + { "force", "overwrite existing tags", OFFSET(force), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, VF }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(iccdetect); + +static av_cold void iccdetect_uninit(AVFilterContext *avctx) +{ + IccDetectContext *s = avctx->priv; + av_buffer_unref(&s->profile); + ff_icc_context_uninit(&s->icc); +} + +static av_cold int iccdetect_init(AVFilterContext *avctx) +{ + IccDetectContext *s = avctx->priv; + return ff_icc_context_init(&s->icc, avctx); +} + +static int iccdetect_filter_frame(AVFilterLink *inlink, AVFrame *frame) +{ + AVFilterContext *avctx = inlink->dst; + IccDetectContext *s = avctx->priv; + const AVFrameSideData *sd; + AVColorPrimariesDesc coeffs; + cmsHPROFILE profile; + int ret; + + sd = av_frame_get_side_data(frame, AV_FRAME_DATA_ICC_PROFILE); + if (!sd) + return ff_filter_frame(inlink->dst->outputs[0], frame); + + if (s->profile && s->profile->data == sd->buf->data) { + /* No change from previous ICC profile */ + goto done; + } + + if ((ret = av_buffer_replace(&s->profile, sd->buf)) < 0) + return ret; + s->profile_prim = AVCOL_PRI_UNSPECIFIED; + s->profile_trc = AVCOL_TRC_UNSPECIFIED; + + profile = cmsOpenProfileFromMemTHR(s->icc.ctx, sd->data, sd->size); + if (!profile) + return AVERROR_INVALIDDATA; + + ret = ff_icc_profile_read_primaries(&s->icc, profile, &coeffs); + if (!ret) + ret = ff_icc_profile_detect_transfer(&s->icc, profile, &s->profile_trc); + cmsCloseProfile(profile); + if (ret < 0) + return ret; + + s->profile_prim = av_csp_primaries_id_from_desc(&coeffs); + +done: + if (s->profile_prim != AVCOL_PRI_UNSPECIFIED) { + if (s->force || frame->color_primaries == AVCOL_PRI_UNSPECIFIED) + frame->color_primaries = s->profile_prim; + } + + if (s->profile_trc != AVCOL_TRC_UNSPECIFIED) { + if (s->force || frame->color_trc == AVCOL_TRC_UNSPECIFIED) + frame->color_trc = s->profile_trc; + } + + return ff_filter_frame(inlink->dst->outputs[0], frame); +} + +static const AVFilterPad iccdetect_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = iccdetect_filter_frame, + }, +}; + +static const AVFilterPad iccdetect_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, +}; + +const AVFilter ff_vf_iccdetect = { + .name = "iccdetect", + .description = NULL_IF_CONFIG_SMALL("Detect and parse ICC profiles."), + .priv_size = sizeof(IccDetectContext), + .priv_class = &iccdetect_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, + .init = &iccdetect_init, + .uninit = &iccdetect_uninit, + FILTER_INPUTS(iccdetect_inputs), + FILTER_OUTPUTS(iccdetect_outputs), +}; diff --git a/libavfilter/vf_iccgen.c b/libavfilter/vf_iccgen.c new file mode 100644 index 000000000..67d02f5bc --- /dev/null +++ b/libavfilter/vf_iccgen.c @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2022 Niklas Haas + * 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 + * filter for generating ICC profiles + */ + +#include + +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" + +#include "avfilter.h" +#include "fflcms2.h" +#include "internal.h" + +typedef struct IccGenContext { + const AVClass *class; + FFIccContext icc; + /* options */ + int color_prim; + int color_trc; + int force; + /* (cached) generated ICC profile */ + cmsHPROFILE profile; + int profile_prim; + int profile_trc; +} IccGenContext; + +#define OFFSET(x) offsetof(IccGenContext, x) +#define VF AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM + +static const AVOption iccgen_options[] = { + {"color_primaries", "select color primaries", OFFSET(color_prim), AV_OPT_TYPE_INT, {.i64=0}, 0, AVCOL_PRI_NB-1, VF, "color_primaries"}, + {"auto", "infer based on frame", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, VF, "color_primaries"}, + {"bt709", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_BT709}, 0, 0, VF, "color_primaries"}, + {"bt470m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_BT470M}, 0, 0, VF, "color_primaries"}, + {"bt470bg", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_BT470BG}, 0, 0, VF, "color_primaries"}, + {"smpte170m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_SMPTE170M}, 0, 0, VF, "color_primaries"}, + {"smpte240m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_SMPTE240M}, 0, 0, VF, "color_primaries"}, + {"film", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_FILM}, 0, 0, VF, "color_primaries"}, + {"bt2020", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_BT2020}, 0, 0, VF, "color_primaries"}, + {"smpte428", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_SMPTE428}, 0, 0, VF, "color_primaries"}, + {"smpte431", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_SMPTE431}, 0, 0, VF, "color_primaries"}, + {"smpte432", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_SMPTE432}, 0, 0, VF, "color_primaries"}, + {"jedec-p22", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_JEDEC_P22}, 0, 0, VF, "color_primaries"}, + {"ebu3213", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_EBU3213}, 0, 0, VF, "color_primaries"}, + {"color_trc", "select color transfer", OFFSET(color_trc), AV_OPT_TYPE_INT, {.i64=0}, 0, AVCOL_TRC_NB-1, VF, "color_trc"}, + {"auto", "infer based on frame", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, VF, "color_trc"}, + {"bt709", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_BT709}, 0, 0, VF, "color_trc"}, + {"bt470m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_GAMMA22}, 0, 0, VF, "color_trc"}, + {"bt470bg", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_GAMMA28}, 0, 0, VF, "color_trc"}, + {"smpte170m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_SMPTE170M}, 0, 0, VF, "color_trc"}, + {"smpte240m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_SMPTE240M}, 0, 0, VF, "color_trc"}, + {"linear", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_LINEAR}, 0, 0, VF, "color_trc"}, + {"iec61966-2-4", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_IEC61966_2_4}, 0, 0, VF, "color_trc"}, + {"bt1361e", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_BT1361_ECG}, 0, 0, VF, "color_trc"}, + {"iec61966-2-1", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_IEC61966_2_1}, 0, 0, VF, "color_trc"}, + {"bt2020-10", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_BT2020_10}, 0, 0, VF, "color_trc"}, + {"bt2020-12", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_BT2020_12}, 0, 0, VF, "color_trc"}, + {"smpte2084", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_SMPTE2084}, 0, 0, VF, "color_trc"}, + {"arib-std-b67", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_ARIB_STD_B67}, 0, 0, VF, "color_trc"}, + { "force", "overwrite existing ICC profile", OFFSET(force), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, VF }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(iccgen); + +static av_cold void iccgen_uninit(AVFilterContext *avctx) +{ + IccGenContext *s = avctx->priv; + cmsCloseProfile(s->profile); + ff_icc_context_uninit(&s->icc); +} + +static av_cold int iccgen_init(AVFilterContext *avctx) +{ + IccGenContext *s = avctx->priv; + return ff_icc_context_init(&s->icc, avctx); +} + +static int iccgen_filter_frame(AVFilterLink *inlink, AVFrame *frame) +{ + AVFilterContext *avctx = inlink->dst; + IccGenContext *s = avctx->priv; + enum AVColorTransferCharacteristic trc; + enum AVColorPrimaries prim; + int ret; + + if (av_frame_get_side_data(frame, AV_FRAME_DATA_ICC_PROFILE)) { + if (s->force) { + av_frame_remove_side_data(frame, AV_FRAME_DATA_ICC_PROFILE); + } else { + return ff_filter_frame(inlink->dst->outputs[0], frame); + } + } + + trc = s->color_trc ? s->color_trc : frame->color_trc; + if (trc == AVCOL_TRC_UNSPECIFIED) { + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format); + if (!desc) + return AVERROR_INVALIDDATA; + + if ((desc->flags & AV_PIX_FMT_FLAG_RGB) || frame->color_range == AVCOL_RANGE_JPEG) { + /* Default to sRGB for RGB or full-range content */ + trc = AVCOL_TRC_IEC61966_2_1; + } else { + /* Default to an ITU-R transfer depending on the bit-depth */ + trc = desc->comp[0].depth >= 12 ? AVCOL_TRC_BT2020_12 + : desc->comp[0].depth >= 10 ? AVCOL_TRC_BT2020_10 + : AVCOL_TRC_BT709; + } + } + + prim = s->color_prim ? s->color_prim : frame->color_primaries; + if (prim == AVCOL_PRI_UNSPECIFIED) { + /* Simply always default to sRGB/BT.709 primaries to avoid surprises */ + prim = AVCOL_PRI_BT709; + } + + if (s->profile && prim != s->profile_prim && trc != s->profile_trc) { + cmsCloseProfile(s->profile); + s->profile = NULL; + } + + if (!s->profile) { + if ((ret = ff_icc_profile_generate(&s->icc, prim, trc, &s->profile)) < 0) + return ret; + s->profile_prim = prim; + s->profile_trc = trc; + } + + if ((ret = ff_icc_profile_attach(&s->icc, s->profile, frame)) < 0) + return ret; + + return ff_filter_frame(inlink->dst->outputs[0], frame); +} + +static const AVFilterPad iccgen_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = iccgen_filter_frame, + }, +}; + +static const AVFilterPad iccgen_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, +}; + +const AVFilter ff_vf_iccgen = { + .name = "iccgen", + .description = NULL_IF_CONFIG_SMALL("Generate and attach ICC profiles."), + .priv_size = sizeof(IccGenContext), + .priv_class = &iccgen_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, + .init = &iccgen_init, + .uninit = &iccgen_uninit, + FILTER_INPUTS(iccgen_inputs), + FILTER_OUTPUTS(iccgen_outputs), +}; diff --git a/libavfilter/vf_identity.c b/libavfilter/vf_identity.c index cc3076138..84def7959 100644 --- a/libavfilter/vf_identity.c +++ b/libavfilter/vf_identity.c @@ -23,6 +23,8 @@ * Calculate the Identity between two input videos. */ +#include "config_components.h" + #include "libavutil/avstring.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" diff --git a/libavfilter/vf_idet.c b/libavfilter/vf_idet.c index 9320b485d..83d992add 100644 --- a/libavfilter/vf_idet.c +++ b/libavfilter/vf_idet.c @@ -276,8 +276,9 @@ static int filter_frame(AVFilterLink *link, AVFrame *picref) idet->csp = av_pix_fmt_desc_get(link->format); if (idet->csp->comp[0].depth > 8){ idet->filter_line = (ff_idet_filter_func)ff_idet_filter_line_c_16bit; - if (ARCH_X86) - ff_idet_init_x86(idet, 1); +#if ARCH_X86 + ff_idet_init_x86(idet, 1); +#endif } if (idet->analyze_interlaced_flag) { @@ -408,8 +409,9 @@ static av_cold int init(AVFilterContext *ctx) idet->filter_line = ff_idet_filter_line_c; - if (ARCH_X86) - ff_idet_init_x86(idet, 0); +#if ARCH_X86 + ff_idet_init_x86(idet, 0); +#endif return 0; } diff --git a/libavfilter/vf_lagfun.c b/libavfilter/vf_lagfun.c index c2e0f7383..69191ac1d 100644 --- a/libavfilter/vf_lagfun.c +++ b/libavfilter/vf_lagfun.c @@ -41,7 +41,7 @@ typedef struct LagfunContext { float *old[4]; - int (*lagfun)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); + int (*lagfun[2])(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); } LagfunContext; static const enum AVPixelFormat pixel_fmts[] = { @@ -63,6 +63,7 @@ static const enum AVPixelFormat pixel_fmts[] = { AV_PIX_FMT_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, 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_GRAYF32, AV_PIX_FMT_GBRPF32, AV_PIX_FMT_GBRAPF32, AV_PIX_FMT_NONE }; @@ -70,7 +71,7 @@ typedef struct ThreadData { AVFrame *in, *out; } ThreadData; -#define LAGFUN(name, type) \ +#define LAGFUN(name, type, round, disabled) \ static int lagfun_frame##name(AVFilterContext *ctx, void *arg, \ int jobnr, int nb_jobs) \ { \ @@ -83,6 +84,7 @@ static int lagfun_frame##name(AVFilterContext *ctx, void *arg, \ for (int p = 0; p < s->nb_planes; p++) { \ const int slice_start = (s->planeheight[p] * jobnr) / nb_jobs; \ const int slice_end = (s->planeheight[p] * (jobnr+1)) / nb_jobs; \ + const int width = s->planewidth[p]; \ const type *src = (const type *)in->data[p] + \ slice_start * in->linesize[p] / sizeof(type); \ float *osrc = s->old[p] + slice_start * s->planewidth[p]; \ @@ -97,19 +99,19 @@ static int lagfun_frame##name(AVFilterContext *ctx, void *arg, \ } \ \ for (int y = slice_start; y < slice_end; y++) { \ - for (int x = 0; x < s->planewidth[p]; x++) { \ - float v = FFMAX(src[x], osrc[x] * decay); \ + for (int x = 0; x < width; x++) { \ + const float v = fmaxf(src[x], osrc[x] * decay); \ \ osrc[x] = v; \ - if (ctx->is_disabled) { \ + if (disabled) { \ dst[x] = src[x]; \ } else { \ - dst[x] = lrintf(v); \ + dst[x] = round(v); \ } \ } \ \ src += in->linesize[p] / sizeof(type); \ - osrc += s->planewidth[p]; \ + osrc += width; \ dst += out->linesize[p] / sizeof(type); \ } \ } \ @@ -117,8 +119,13 @@ static int lagfun_frame##name(AVFilterContext *ctx, void *arg, \ return 0; \ } -LAGFUN(8, uint8_t) -LAGFUN(16, uint16_t) +LAGFUN(8, uint8_t, lrintf, 0) +LAGFUN(16, uint16_t, lrintf, 0) +LAGFUN(32, float, , 0) + +LAGFUN(d8, uint8_t, lrintf, 1) +LAGFUN(d16, uint16_t, lrintf, 1) +LAGFUN(d32, float, , 1) static int config_output(AVFilterLink *outlink) { @@ -133,7 +140,8 @@ static int config_output(AVFilterLink *outlink) return AVERROR_BUG; s->nb_planes = av_pix_fmt_count_planes(outlink->format); s->depth = desc->comp[0].depth; - s->lagfun = s->depth <= 8 ? lagfun_frame8 : lagfun_frame16; + s->lagfun[0] = s->depth <= 8 ? lagfun_frame8 : s->depth <= 16 ? lagfun_frame16 : lagfun_frame32; + s->lagfun[1] = s->depth <= 8 ? lagfun_framed8 : s->depth <= 16 ? lagfun_framed16 : lagfun_framed32; if ((ret = av_image_fill_linesizes(s->linesize, inlink->format, inlink->w)) < 0) return ret; @@ -169,7 +177,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) td.out = out; td.in = in; - ff_filter_execute(ctx, s->lagfun, &td, NULL, + ff_filter_execute(ctx, s->lagfun[!!ctx->is_disabled], &td, NULL, FFMIN(s->planeheight[1], ff_filter_get_nb_threads(ctx))); av_frame_free(&in); diff --git a/libavfilter/vf_lensfun.c b/libavfilter/vf_lensfun.c index 596daed10..35c522a72 100644 --- a/libavfilter/vf_lensfun.c +++ b/libavfilter/vf_lensfun.c @@ -73,7 +73,7 @@ typedef struct DistortionCorrectionThreadData { typedef struct LensfunContext { const AVClass *class; - const char *make, *model, *lens_model; + const char *make, *model, *lens_model, *db_path; int mode; float focal_length; float aperture; @@ -97,6 +97,7 @@ static const AVOption lensfun_options[] = { { "make", "set camera maker", OFFSET(make), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, { "model", "set camera model", OFFSET(model), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, { "lens_model", "set lens model", OFFSET(lens_model), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, + { "db_path", "set path to database", OFFSET(db_path), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, { "mode", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=GEOMETRY_DISTORTION}, 0, VIGNETTING | GEOMETRY_DISTORTION | SUBPIXEL_DISTORTION, FLAGS, "mode" }, { "vignetting", "fix lens vignetting", 0, AV_OPT_TYPE_CONST, {.i64=VIGNETTING}, 0, 0, FLAGS, "mode" }, { "geometry", "correct geometry distortion", 0, AV_OPT_TYPE_CONST, {.i64=GEOMETRY_DISTORTION}, 0, 0, FLAGS, "mode" }, @@ -136,9 +137,10 @@ static av_cold int init(AVFilterContext *ctx) const lfLens **lenses; db = lf_db_create(); - if (lf_db_load(db) != LF_NO_ERROR) { + if ((lensfun->db_path ? lf_db_load_path(db, lensfun->db_path) : lf_db_load(db)) != LF_NO_ERROR) { lf_db_destroy(db); - av_log(ctx, AV_LOG_FATAL, "Failed to load lensfun database\n"); + av_log(ctx, AV_LOG_FATAL, "Failed to load lensfun database from %s path\n", + lensfun->db_path ? lensfun->db_path : "default"); return AVERROR_INVALIDDATA; } diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c index 31ae28ac3..cfee1117e 100644 --- a/libavfilter/vf_libplacebo.c +++ b/libavfilter/vf_libplacebo.c @@ -26,6 +26,33 @@ #include #include +enum { + TONE_MAP_AUTO, + TONE_MAP_CLIP, + TONE_MAP_BT2390, + TONE_MAP_BT2446A, + TONE_MAP_SPLINE, + TONE_MAP_REINHARD, + TONE_MAP_MOBIUS, + TONE_MAP_HABLE, + TONE_MAP_GAMMA, + TONE_MAP_LINEAR, + TONE_MAP_COUNT, +}; + +static const struct pl_tone_map_function * const tonemapping_funcs[TONE_MAP_COUNT] = { + [TONE_MAP_AUTO] = &pl_tone_map_auto, + [TONE_MAP_CLIP] = &pl_tone_map_clip, + [TONE_MAP_BT2390] = &pl_tone_map_bt2390, + [TONE_MAP_BT2446A] = &pl_tone_map_bt2446a, + [TONE_MAP_SPLINE] = &pl_tone_map_spline, + [TONE_MAP_REINHARD] = &pl_tone_map_reinhard, + [TONE_MAP_MOBIUS] = &pl_tone_map_mobius, + [TONE_MAP_HABLE] = &pl_tone_map_hable, + [TONE_MAP_GAMMA] = &pl_tone_map_gamma, + [TONE_MAP_LINEAR] = &pl_tone_map_linear, +}; + typedef struct LibplaceboContext { /* lavfi vulkan*/ FFVulkanContext vkctx; @@ -91,12 +118,16 @@ typedef struct LibplaceboContext { /* pl_color_map_params */ int intent; + int gamut_mode; int tonemapping; float tonemapping_param; + int tonemapping_mode; + int inverse_tonemapping; + float crosstalk; + int tonemapping_lut_size; + /* for backwards compatibility */ float desat_str; float desat_exp; - float desat_base; - float max_boost; int gamut_warning; int gamut_clipping; @@ -281,6 +312,8 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out, AVFrame *in) int err = 0, ok; LibplaceboContext *s = avctx->priv; struct pl_render_params params; + enum pl_tone_map_mode tonemapping_mode = s->tonemapping_mode; + enum pl_gamut_mode gamut_mode = s->gamut_mode; struct pl_frame image, target; ok = pl_map_avframe_ex(s->gpu, &image, pl_avframe_params( .frame = in, @@ -305,6 +338,24 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out, AVFrame *in) pl_rect2df_aspect_set(&target.crop, aspect, s->pad_crop_ratio); } + /* backwards compatibility with older API */ + if (!tonemapping_mode && (s->desat_str >= 0.0f || s->desat_exp >= 0.0f)) { + float str = s->desat_str < 0.0f ? 0.9f : s->desat_str; + float exp = s->desat_exp < 0.0f ? 0.2f : s->desat_exp; + if (str >= 0.9f && exp <= 0.1f) { + tonemapping_mode = PL_TONE_MAP_RGB; + } else if (str > 0.1f) { + tonemapping_mode = PL_TONE_MAP_HYBRID; + } else { + tonemapping_mode = PL_TONE_MAP_LUMA; + } + } + + if (s->gamut_warning) + gamut_mode = PL_GAMUT_WARN; + if (s->gamut_clipping) + gamut_mode = PL_GAMUT_DESATURATE; + /* Update render params */ params = (struct pl_render_params) { PL_RENDER_DEFAULTS @@ -338,14 +389,13 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out, AVFrame *in) .color_map_params = pl_color_map_params( .intent = s->intent, - .tone_mapping_algo = s->tonemapping, + .gamut_mode = gamut_mode, + .tone_mapping_function = tonemapping_funcs[s->tonemapping], .tone_mapping_param = s->tonemapping_param, - .desaturation_strength = s->desat_str, - .desaturation_exponent = s->desat_exp, - .desaturation_base = s->desat_base, - .max_boost = s->max_boost, - .gamut_warning = s->gamut_warning, - .gamut_clipping = s->gamut_clipping, + .tone_mapping_mode = tonemapping_mode, + .inverse_tone_mapping = s->inverse_tonemapping, + .tone_mapping_crosstalk = s->crosstalk, + .lut_size = s->tonemapping_lut_size, ), .dither_params = s->dithering < 0 ? NULL : pl_dither_params( @@ -616,21 +666,37 @@ static const AVOption libplacebo_options[] = { { "relative", "Relative colorimetric", 0, AV_OPT_TYPE_CONST, {.i64 = PL_INTENT_RELATIVE_COLORIMETRIC}, 0, 0, STATIC, "intent" }, { "absolute", "Absolute colorimetric", 0, AV_OPT_TYPE_CONST, {.i64 = PL_INTENT_ABSOLUTE_COLORIMETRIC}, 0, 0, STATIC, "intent" }, { "saturation", "Saturation mapping", 0, AV_OPT_TYPE_CONST, {.i64 = PL_INTENT_SATURATION}, 0, 0, STATIC, "intent" }, - { "tonemapping", "Tone-mapping algorithm", OFFSET(tonemapping), AV_OPT_TYPE_INT, {.i64 = PL_TONE_MAPPING_BT_2390}, 0, PL_TONE_MAPPING_ALGORITHM_COUNT - 1, DYNAMIC, "tonemap" }, - { "clip", "Hard-clipping", 0, AV_OPT_TYPE_CONST, {.i64 = PL_TONE_MAPPING_CLIP}, 0, 0, STATIC, "tonemap" }, - { "mobius", "Mobius tone-mapping", 0, AV_OPT_TYPE_CONST, {.i64 = PL_TONE_MAPPING_MOBIUS}, 0, 0, STATIC, "tonemap" }, - { "reinhard", "Reinhard tone-mapping", 0, AV_OPT_TYPE_CONST, {.i64 = PL_TONE_MAPPING_REINHARD}, 0, 0, STATIC, "tonemap" }, - { "hable", "Hable/Filmic tone-mapping", 0, AV_OPT_TYPE_CONST, {.i64 = PL_TONE_MAPPING_HABLE}, 0, 0, STATIC, "tonemap" }, - { "gamma", "Gamma tone-mapping", 0, AV_OPT_TYPE_CONST, {.i64 = PL_TONE_MAPPING_GAMMA}, 0, 0, STATIC, "tonemap" }, - { "linear", "Linear tone-mapping", 0, AV_OPT_TYPE_CONST, {.i64 = PL_TONE_MAPPING_LINEAR}, 0, 0, STATIC, "tonemap" }, - { "bt.2390", "ITU-R BT.2390 tone-mapping", 0, AV_OPT_TYPE_CONST, {.i64 = PL_TONE_MAPPING_BT_2390}, 0, 0, STATIC, "tonemap" }, + { "gamut_mode", "Gamut-mapping mode", OFFSET(gamut_mode), AV_OPT_TYPE_INT, {.i64 = PL_GAMUT_CLIP}, 0, PL_GAMUT_MODE_COUNT - 1, DYNAMIC, "gamut_mode" }, + { "clip", "Hard-clip gamut boundary", 0, AV_OPT_TYPE_CONST, {.i64 = PL_GAMUT_CLIP}, 0, 0, STATIC, "gamut_mode" }, + { "warn", "Highlight out-of-gamut colors", 0, AV_OPT_TYPE_CONST, {.i64 = PL_GAMUT_WARN}, 0, 0, STATIC, "gamut_mode" }, + { "darken", "Darken image to fit gamut", 0, AV_OPT_TYPE_CONST, {.i64 = PL_GAMUT_DARKEN}, 0, 0, STATIC, "gamut_mode" }, + { "desaturate", "Colorimetrically desaturate colors", 0, AV_OPT_TYPE_CONST, {.i64 = PL_GAMUT_DESATURATE}, 0, 0, STATIC, "gamut_mode" }, + { "tonemapping", "Tone-mapping algorithm", OFFSET(tonemapping), AV_OPT_TYPE_INT, {.i64 = TONE_MAP_AUTO}, 0, TONE_MAP_COUNT - 1, DYNAMIC, "tonemap" }, + { "auto", "Automatic selection", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_AUTO}, 0, 0, STATIC, "tonemap" }, + { "clip", "No tone mapping (clip", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_CLIP}, 0, 0, STATIC, "tonemap" }, + { "bt.2390", "ITU-R BT.2390 EETF", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_BT2390}, 0, 0, STATIC, "tonemap" }, + { "bt.2446a", "ITU-R BT.2446 Method A", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_BT2446A}, 0, 0, STATIC, "tonemap" }, + { "spline", "Single-pivot polynomial spline", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_SPLINE}, 0, 0, STATIC, "tonemap" }, + { "reinhard", "Reinhard", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_REINHARD}, 0, 0, STATIC, "tonemap" }, + { "mobius", "Mobius", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_MOBIUS}, 0, 0, STATIC, "tonemap" }, + { "hable", "Filmic tone-mapping (Hable)", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_HABLE}, 0, 0, STATIC, "tonemap" }, + { "gamma", "Gamma function with knee", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_GAMMA}, 0, 0, STATIC, "tonemap" }, + { "linear", "Perceptually linear stretch", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_LINEAR}, 0, 0, STATIC, "tonemap" }, { "tonemapping_param", "Tunable parameter for some tone-mapping functions", OFFSET(tonemapping_param), AV_OPT_TYPE_FLOAT, {.dbl = 0.0}, 0.0, 100.0, .flags = DYNAMIC }, - { "desaturation_strength", "Desaturation strength", OFFSET(desat_str), AV_OPT_TYPE_FLOAT, {.dbl = 0.90}, 0.0, 1.0, DYNAMIC }, - { "desaturation_exponent", "Desaturation exponent", OFFSET(desat_exp), AV_OPT_TYPE_FLOAT, {.dbl = 0.2}, 0.0, 10.0, DYNAMIC }, - { "desaturation_base", "Desaturation base", OFFSET(desat_base), AV_OPT_TYPE_FLOAT, {.dbl = 0.18}, 0.0, 10.0, DYNAMIC }, - { "max_boost", "Tone-mapping maximum boost", OFFSET(max_boost), AV_OPT_TYPE_FLOAT, {.dbl = 1.0}, 1.0, 10.0, DYNAMIC }, - { "gamut_warning", "Highlight out-of-gamut colors", OFFSET(gamut_warning), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC }, - { "gamut_clipping", "Enable colorimetric gamut clipping", OFFSET(gamut_clipping), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, DYNAMIC }, + { "tonemapping_mode", "Tone-mapping mode", OFFSET(tonemapping_mode), AV_OPT_TYPE_INT, {.i64 = PL_TONE_MAP_AUTO}, 0, PL_TONE_MAP_MODE_COUNT - 1, DYNAMIC, "tonemap_mode" }, + { "auto", "Automatic selection", 0, AV_OPT_TYPE_CONST, {.i64 = PL_TONE_MAP_AUTO}, 0, 0, STATIC, "tonemap_mode" }, + { "rgb", "Per-channel (RGB)", 0, AV_OPT_TYPE_CONST, {.i64 = PL_TONE_MAP_RGB}, 0, 0, STATIC, "tonemap_mode" }, + { "max", "Maximum component", 0, AV_OPT_TYPE_CONST, {.i64 = PL_TONE_MAP_MAX}, 0, 0, STATIC, "tonemap_mode" }, + { "hybrid", "Hybrid of Luma/RGB", 0, AV_OPT_TYPE_CONST, {.i64 = PL_TONE_MAP_HYBRID}, 0, 0, STATIC, "tonemap_mode" }, + { "luma", "Luminance", 0, AV_OPT_TYPE_CONST, {.i64 = PL_TONE_MAP_LUMA}, 0, 0, STATIC, "tonemap_mode" }, + { "inverse_tonemapping", "Inverse tone mapping (range expansion)", OFFSET(inverse_tonemapping), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC }, + { "tonemapping_crosstalk", "Crosstalk factor for tone-mapping", OFFSET(crosstalk), AV_OPT_TYPE_FLOAT, {.dbl = 0.04}, 0.0, 0.30, DYNAMIC }, + { "tonemapping_lut_size", "Tone-mapping LUT size", OFFSET(tonemapping_lut_size), AV_OPT_TYPE_INT, {.i64 = 256}, 2, 1024, DYNAMIC }, + /* deprecated options for backwards compatibility, defaulting to -1 to not override the new defaults */ + { "desaturation_strength", "Desaturation strength", OFFSET(desat_str), AV_OPT_TYPE_FLOAT, {.dbl = -1.0}, -1.0, 1.0, DYNAMIC | AV_OPT_FLAG_DEPRECATED }, + { "desaturation_exponent", "Desaturation exponent", OFFSET(desat_exp), AV_OPT_TYPE_FLOAT, {.dbl = -1.0}, -1.0, 10.0, DYNAMIC | AV_OPT_FLAG_DEPRECATED }, + { "gamut_warning", "Highlight out-of-gamut colors", OFFSET(gamut_warning), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC | AV_OPT_FLAG_DEPRECATED }, + { "gamut_clipping", "Enable colorimetric gamut clipping", OFFSET(gamut_clipping), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC | AV_OPT_FLAG_DEPRECATED }, { "dithering", "Dither method to use", OFFSET(dithering), AV_OPT_TYPE_INT, {.i64 = PL_DITHER_BLUE_NOISE}, -1, PL_DITHER_METHOD_COUNT - 1, DYNAMIC, "dither" }, { "none", "Disable dithering", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, STATIC, "dither" }, @@ -652,7 +718,7 @@ static const AVOption libplacebo_options[] = { /* Performance/quality tradeoff options */ { "skip_aa", "Skip anti-aliasing", OFFSET(skip_aa), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 0, DYNAMIC }, - { "polar_cutoff", "Polar LUT cutoff", OFFSET(polar_cutoff), AV_OPT_TYPE_FLOAT, {.i64 = 0}, 0.0, 1.0, DYNAMIC }, + { "polar_cutoff", "Polar LUT cutoff", OFFSET(polar_cutoff), AV_OPT_TYPE_FLOAT, {.dbl = 0}, 0.0, 1.0, DYNAMIC }, { "disable_linear", "Disable linear scaling", OFFSET(disable_linear), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC }, { "disable_builtin", "Disable built-in scalers", OFFSET(disable_builtin), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC }, { "force_icc_lut", "Force the use of a full ICC 3DLUT for color mapping", OFFSET(force_icc_lut), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC }, @@ -680,7 +746,7 @@ static const AVFilterPad libplacebo_outputs[] = { }, }; -AVFilter ff_vf_libplacebo = { +const AVFilter ff_vf_libplacebo = { .name = "libplacebo", .description = NULL_IF_CONFIG_SMALL("Apply various GPU filters from libplacebo"), .priv_size = sizeof(LibplaceboContext), diff --git a/libavfilter/vf_libvmaf.c b/libavfilter/vf_libvmaf.c index 5d492126e..eee1c280e 100644 --- a/libavfilter/vf_libvmaf.c +++ b/libavfilter/vf_libvmaf.c @@ -24,8 +24,8 @@ * Calculate the VMAF between two input videos. */ -#include #include + #include "libavutil/avstring.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" @@ -39,23 +39,9 @@ typedef struct LIBVMAFContext { const AVClass *class; FFFrameSync fs; - const AVPixFmtDescriptor *desc; - int width; - int height; - double vmaf_score; - int vmaf_thread_created; - pthread_t vmaf_thread; - pthread_mutex_t lock; - pthread_cond_t cond; - int eof; - AVFrame *gmain; - AVFrame *gref; - int frame_set; char *model_path; char *log_path; char *log_fmt; - int disable_clip; - int disable_avx; int enable_transform; int phone_model; int psnr; @@ -65,184 +51,487 @@ typedef struct LIBVMAFContext { int n_threads; int n_subsample; int enable_conf_interval; - int error; + char *model_cfg; + char *feature_cfg; + VmafContext *vmaf; + VmafModel **model; + unsigned model_cnt; + unsigned frame_cnt; + unsigned bpc; } LIBVMAFContext; #define OFFSET(x) offsetof(LIBVMAFContext, x) #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM static const AVOption libvmaf_options[] = { - {"model_path", "Set the model to be used for computing vmaf.", OFFSET(model_path), AV_OPT_TYPE_STRING, {.str="/usr/local/share/model/vmaf_v0.6.1.pkl"}, 0, 1, FLAGS}, - {"log_path", "Set the file path to be used to store logs.", OFFSET(log_path), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS}, - {"log_fmt", "Set the format of the log (csv, json or xml).", OFFSET(log_fmt), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS}, - {"enable_transform", "Enables transform for computing vmaf.", OFFSET(enable_transform), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, - {"phone_model", "Invokes the phone model that will generate higher VMAF scores.", OFFSET(phone_model), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, - {"psnr", "Enables computing psnr along with vmaf.", OFFSET(psnr), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, - {"ssim", "Enables computing ssim along with vmaf.", OFFSET(ssim), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, - {"ms_ssim", "Enables computing ms-ssim along with vmaf.", OFFSET(ms_ssim), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, + {"model_path", "use model='path=...'.", OFFSET(model_path), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS|AV_OPT_FLAG_DEPRECATED}, + {"log_path", "Set the file path to be used to write log.", OFFSET(log_path), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS}, + {"log_fmt", "Set the format of the log (csv, json, xml, or sub).", OFFSET(log_fmt), AV_OPT_TYPE_STRING, {.str="xml"}, 0, 1, FLAGS}, + {"enable_transform", "use model='enable_transform=true'.", OFFSET(enable_transform), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS|AV_OPT_FLAG_DEPRECATED}, + {"phone_model", "use model='enable_transform=true'.", OFFSET(phone_model), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS|AV_OPT_FLAG_DEPRECATED}, + {"psnr", "use feature='name=psnr'.", OFFSET(psnr), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS|AV_OPT_FLAG_DEPRECATED}, + {"ssim", "use feature='name=ssim'.", OFFSET(ssim), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS|AV_OPT_FLAG_DEPRECATED}, + {"ms_ssim", "use feature='name=ms_ssim'.", OFFSET(ms_ssim), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS|AV_OPT_FLAG_DEPRECATED}, {"pool", "Set the pool method to be used for computing vmaf.", OFFSET(pool), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS}, {"n_threads", "Set number of threads to be used when computing vmaf.", OFFSET(n_threads), AV_OPT_TYPE_INT, {.i64=0}, 0, UINT_MAX, FLAGS}, {"n_subsample", "Set interval for frame subsampling used when computing vmaf.", OFFSET(n_subsample), AV_OPT_TYPE_INT, {.i64=1}, 1, UINT_MAX, FLAGS}, - {"enable_conf_interval", "Enables confidence interval.", OFFSET(enable_conf_interval), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, + {"enable_conf_interval", "model='enable_conf_interval=true'.", OFFSET(enable_conf_interval), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS|AV_OPT_FLAG_DEPRECATED}, + {"model", "Set the model to be used for computing vmaf.", OFFSET(model_cfg), AV_OPT_TYPE_STRING, {.str="version=vmaf_v0.6.1"}, 0, 1, FLAGS}, + {"feature", "Set the feature to be used for computing vmaf.", OFFSET(feature_cfg), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 1, FLAGS}, { NULL } }; FRAMESYNC_DEFINE_CLASS(libvmaf, LIBVMAFContext, fs); -#define read_frame_fn(type, bits) \ - static int read_frame_##bits##bit(float *ref_data, float *main_data, \ - float *temp_data, int stride, void *ctx) \ -{ \ - LIBVMAFContext *s = (LIBVMAFContext *) ctx; \ - int ret; \ - \ - pthread_mutex_lock(&s->lock); \ - \ - while (!s->frame_set && !s->eof) { \ - pthread_cond_wait(&s->cond, &s->lock); \ - } \ - \ - if (s->frame_set) { \ - int ref_stride = s->gref->linesize[0]; \ - int main_stride = s->gmain->linesize[0]; \ - \ - const type *ref_ptr = (const type *) s->gref->data[0]; \ - const type *main_ptr = (const type *) s->gmain->data[0]; \ - \ - float *ptr = ref_data; \ - float factor = 1.f / (1 << (bits - 8)); \ - \ - int h = s->height; \ - int w = s->width; \ - \ - int i,j; \ - \ - for (i = 0; i < h; i++) { \ - for ( j = 0; j < w; j++) { \ - ptr[j] = ref_ptr[j] * factor; \ - } \ - ref_ptr += ref_stride / sizeof(*ref_ptr); \ - ptr += stride / sizeof(*ptr); \ - } \ - \ - ptr = main_data; \ - \ - for (i = 0; i < h; i++) { \ - for (j = 0; j < w; j++) { \ - ptr[j] = main_ptr[j] * factor; \ - } \ - main_ptr += main_stride / sizeof(*main_ptr); \ - ptr += stride / sizeof(*ptr); \ - } \ - } \ - \ - ret = !s->frame_set; \ - \ - av_frame_unref(s->gref); \ - av_frame_unref(s->gmain); \ - s->frame_set = 0; \ - \ - pthread_cond_signal(&s->cond); \ - pthread_mutex_unlock(&s->lock); \ - \ - if (ret) { \ - return 2; \ - } \ - \ - return 0; \ +static enum VmafPixelFormat pix_fmt_map(enum AVPixelFormat av_pix_fmt) +{ + switch (av_pix_fmt) { + case AV_PIX_FMT_YUV420P: + case AV_PIX_FMT_YUV420P10LE: + case AV_PIX_FMT_YUV420P12LE: + case AV_PIX_FMT_YUV420P16LE: + return VMAF_PIX_FMT_YUV420P; + case AV_PIX_FMT_YUV422P: + case AV_PIX_FMT_YUV422P10LE: + case AV_PIX_FMT_YUV422P12LE: + case AV_PIX_FMT_YUV422P16LE: + return VMAF_PIX_FMT_YUV422P; + case AV_PIX_FMT_YUV444P: + case AV_PIX_FMT_YUV444P10LE: + case AV_PIX_FMT_YUV444P12LE: + case AV_PIX_FMT_YUV444P16LE: + return VMAF_PIX_FMT_YUV444P; + default: + return VMAF_PIX_FMT_UNKNOWN; + } } -read_frame_fn(uint8_t, 8); -read_frame_fn(uint16_t, 10); - -static void compute_vmaf_score(LIBVMAFContext *s) +static int copy_picture_data(AVFrame *src, VmafPicture *dst, unsigned bpc) { - int (*read_frame)(float *ref_data, float *main_data, float *temp_data, - int stride, void *ctx); - char *format; + int err = vmaf_picture_alloc(dst, pix_fmt_map(src->format), bpc, + src->width, src->height); + if (err) + return AVERROR(ENOMEM); - if (s->desc->comp[0].depth <= 8) { - read_frame = read_frame_8bit; - } else { - read_frame = read_frame_10bit; + for (unsigned i = 0; i < 3; i++) { + uint8_t *src_data = src->data[i]; + uint8_t *dst_data = dst->data[i]; + for (unsigned j = 0; j < dst->h[i]; j++) { + memcpy(dst_data, src_data, sizeof(*dst_data) * dst->w[i]); + src_data += src->linesize[i]; + dst_data += dst->stride[i]; + } } - format = (char *) s->desc->name; - - 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, - s->n_threads, s->n_subsample, s->enable_conf_interval); -} - -static void *call_vmaf(void *ctx) -{ - LIBVMAFContext *s = (LIBVMAFContext *) ctx; - compute_vmaf_score(s); - 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; + return 0; } static int do_vmaf(FFFrameSync *fs) { AVFilterContext *ctx = fs->parent; LIBVMAFContext *s = ctx->priv; - AVFrame *master, *ref; - int ret; + VmafPicture pic_ref, pic_dist; + AVFrame *ref, *dist; + int err = 0; - ret = ff_framesync_dualinput_get(fs, &master, &ref); + int ret = ff_framesync_dualinput_get(fs, &dist, &ref); if (ret < 0) return ret; - if (!ref) - return ff_filter_frame(ctx->outputs[0], master); + if (ctx->is_disabled || !ref) + return ff_filter_frame(ctx->outputs[0], dist); - pthread_mutex_lock(&s->lock); - - while (s->frame_set && !s->error) { - pthread_cond_wait(&s->cond, &s->lock); + err = copy_picture_data(ref, &pic_ref, s->bpc); + if (err) { + av_log(s, AV_LOG_ERROR, "problem during vmaf_picture_alloc.\n"); + return AVERROR(ENOMEM); } - if (s->error) { - av_log(ctx, AV_LOG_ERROR, - "libvmaf encountered an error, check log for details\n"); - pthread_mutex_unlock(&s->lock); + err = copy_picture_data(dist, &pic_dist, s->bpc); + if (err) { + av_log(s, AV_LOG_ERROR, "problem during vmaf_picture_alloc.\n"); + vmaf_picture_unref(&pic_ref); + return AVERROR(ENOMEM); + } + + err = vmaf_read_pictures(s->vmaf, &pic_ref, &pic_dist, s->frame_cnt++); + if (err) { + av_log(s, AV_LOG_ERROR, "problem during vmaf_read_pictures.\n"); return AVERROR(EINVAL); } - av_frame_ref(s->gref, ref); - av_frame_ref(s->gmain, master); + return ff_filter_frame(ctx->outputs[0], dist); +} - s->frame_set = 1; - pthread_cond_signal(&s->cond); - pthread_mutex_unlock(&s->lock); +static AVDictionary **delimited_dict_parse(char *str, unsigned *cnt) +{ + AVDictionary **dict = NULL; + char *str_copy = NULL; + char *saveptr = NULL; + unsigned cnt2; + int err = 0; - return ff_filter_frame(ctx->outputs[0], master); + if (!str) + return NULL; + + cnt2 = 1; + for (char *p = str; *p; p++) { + if (*p == '|') + cnt2++; + } + + dict = av_calloc(cnt2, sizeof(*dict)); + if (!dict) + goto fail; + + str_copy = av_strdup(str); + if (!str_copy) + goto fail; + + *cnt = 0; + for (unsigned i = 0; i < cnt2; i++) { + char *s = av_strtok(i == 0 ? str_copy : NULL, "|", &saveptr); + if (!s) + continue; + err = av_dict_parse_string(&dict[(*cnt)++], s, "=", ":", 0); + if (err) + goto fail; + } + + av_free(str_copy); + return dict; + +fail: + if (dict) { + for (unsigned i = 0; i < *cnt; i++) { + if (dict[i]) + av_dict_free(&dict[i]); + } + av_free(dict); + } + + av_free(str_copy); + *cnt = 0; + return NULL; +} + +static int parse_features(AVFilterContext *ctx) +{ + LIBVMAFContext *s = ctx->priv; + AVDictionary **dict = NULL; + unsigned dict_cnt; + int err = 0; + + if (!s->feature_cfg) + return 0; + + dict = delimited_dict_parse(s->feature_cfg, &dict_cnt); + if (!dict) { + av_log(ctx, AV_LOG_ERROR, + "could not parse feature config: %s\n", s->feature_cfg); + return AVERROR(EINVAL); + } + + for (unsigned i = 0; i < dict_cnt; i++) { + char *feature_name = NULL; + VmafFeatureDictionary *feature_opts_dict = NULL; + AVDictionaryEntry *e = NULL; + + while (e = av_dict_get(dict[i], "", e, AV_DICT_IGNORE_SUFFIX)) { + if (av_stristr(e->key, "name")) { + feature_name = e->value; + continue; + } + + err = vmaf_feature_dictionary_set(&feature_opts_dict, e->key, + e->value); + if (err) { + av_log(ctx, AV_LOG_ERROR, + "could not set feature option: %s.%s=%s\n", + feature_name, e->key, e->value); + goto exit; + } + } + + err = vmaf_use_feature(s->vmaf, feature_name, feature_opts_dict); + if (err) { + av_log(ctx, AV_LOG_ERROR, + "problem during vmaf_use_feature: %s\n", feature_name); + goto exit; + } + } + +exit: + for (unsigned i = 0; i < dict_cnt; i++) { + if (dict[i]) + av_dict_free(&dict[i]); + } + av_free(dict); + return err; +} + +static int parse_models(AVFilterContext *ctx) +{ + LIBVMAFContext *s = ctx->priv; + AVDictionary **dict; + unsigned dict_cnt; + int err = 0; + + if (!s->model_cfg) return 0; + + dict_cnt = 0; + dict = delimited_dict_parse(s->model_cfg, &dict_cnt); + if (!dict) { + av_log(ctx, AV_LOG_ERROR, + "could not parse model config: %s\n", s->model_cfg); + return AVERROR(EINVAL); + } + + s->model_cnt = dict_cnt; + s->model = av_calloc(s->model_cnt, sizeof(*s->model)); + if (!s->model) + return AVERROR(ENOMEM); + + for (unsigned i = 0; i < dict_cnt; i++) { + VmafModelConfig model_cfg = { 0 }; + AVDictionaryEntry *e = NULL; + char *version = NULL; + char *path = NULL; + + while (e = av_dict_get(dict[i], "", e, AV_DICT_IGNORE_SUFFIX)) { + if (av_stristr(e->key, "disable_clip")) { + model_cfg.flags |= av_stristr(e->value, "true") ? + VMAF_MODEL_FLAG_DISABLE_CLIP : 0; + continue; + } + + if (av_stristr(e->key, "enable_transform")) { + model_cfg.flags |= av_stristr(e->value, "true") ? + VMAF_MODEL_FLAG_ENABLE_TRANSFORM : 0; + continue; + } + + if (av_stristr(e->key, "name")) { + model_cfg.name = e->value; + continue; + } + + if (av_stristr(e->key, "version")) { + version = e->value; + continue; + } + + if (av_stristr(e->key, "path")) { + path = e->value; + continue; + } + } + + if (version) { + err = vmaf_model_load(&s->model[i], &model_cfg, version); + if (err) { + av_log(ctx, AV_LOG_ERROR, + "could not load libvmaf model with version: %s\n", + version); + goto exit; + } + } + + if (path && !s->model[i]) { + err = vmaf_model_load_from_path(&s->model[i], &model_cfg, path); + if (err) { + av_log(ctx, AV_LOG_ERROR, + "could not load libvmaf model with path: %s\n", + path); + goto exit; + } + } + + if (!s->model[i]) { + av_log(ctx, AV_LOG_ERROR, + "could not load libvmaf model with config: %s\n", + s->model_cfg); + goto exit; + } + + while (e = av_dict_get(dict[i], "", e, AV_DICT_IGNORE_SUFFIX)) { + VmafFeatureDictionary *feature_opts_dict = NULL; + char *feature_opt = NULL; + + char *feature_name = av_strtok(e->key, ".", &feature_opt); + if (!feature_opt) + continue; + + err = vmaf_feature_dictionary_set(&feature_opts_dict, + feature_opt, e->value); + if (err) { + av_log(ctx, AV_LOG_ERROR, + "could not set feature option: %s.%s=%s\n", + feature_name, feature_opt, e->value); + err = AVERROR(EINVAL); + goto exit; + } + + err = vmaf_model_feature_overload(s->model[i], feature_name, + feature_opts_dict); + if (err) { + av_log(ctx, AV_LOG_ERROR, + "could not overload feature: %s\n", feature_name); + err = AVERROR(EINVAL); + goto exit; + } + } + } + + for (unsigned i = 0; i < s->model_cnt; i++) { + err = vmaf_use_features_from_model(s->vmaf, s->model[i]); + if (err) { + av_log(ctx, AV_LOG_ERROR, + "problem during vmaf_use_features_from_model\n"); + err = AVERROR(EINVAL); + goto exit; + } + } + +exit: + for (unsigned i = 0; i < dict_cnt; i++) { + if (dict[i]) + av_dict_free(&dict[i]); + } + av_free(dict); + return err; +} + +static enum VmafLogLevel log_level_map(int log_level) +{ + switch (log_level) { + case AV_LOG_QUIET: + return VMAF_LOG_LEVEL_NONE; + case AV_LOG_ERROR: + return VMAF_LOG_LEVEL_ERROR; + case AV_LOG_WARNING: + return VMAF_LOG_LEVEL_WARNING; + case AV_LOG_INFO: + return VMAF_LOG_LEVEL_INFO; + case AV_LOG_DEBUG: + return VMAF_LOG_LEVEL_DEBUG; + default: + return VMAF_LOG_LEVEL_INFO; + } +} + +static int parse_deprecated_options(AVFilterContext *ctx) +{ + LIBVMAFContext *s = ctx->priv; + VmafModel *model = NULL; + VmafModelCollection *model_collection = NULL; + enum VmafModelFlags flags = VMAF_MODEL_FLAGS_DEFAULT; + int err = 0; + + VmafModelConfig model_cfg = { + .name = "vmaf", + .flags = flags, + }; + + if (s->enable_transform || s->phone_model) + flags |= VMAF_MODEL_FLAG_ENABLE_TRANSFORM; + + if (!s->model_path) + goto extra_metrics_only; + + if (s->enable_conf_interval) { + err = vmaf_model_collection_load_from_path(&model, &model_collection, + &model_cfg, s->model_path); + if (err) { + av_log(ctx, AV_LOG_ERROR, + "problem loading model file: %s\n", s->model_path); + goto exit; + } + + err = vmaf_use_features_from_model_collection(s->vmaf, model_collection); + if (err) { + av_log(ctx, AV_LOG_ERROR, + "problem loading feature extractors from model file: %s\n", + s->model_path); + goto exit; + } + } else { + err = vmaf_model_load_from_path(&model, &model_cfg, s->model_path); + if (err) { + av_log(ctx, AV_LOG_ERROR, + "problem loading model file: %s\n", s->model_path); + goto exit; + } + err = vmaf_use_features_from_model(s->vmaf, model); + if (err) { + av_log(ctx, AV_LOG_ERROR, + "problem loading feature extractors from model file: %s\n", + s->model_path); + goto exit; + } + } + +extra_metrics_only: + if (s->psnr) { + VmafFeatureDictionary *d = NULL; + vmaf_feature_dictionary_set(&d, "enable_chroma", "false"); + + err = vmaf_use_feature(s->vmaf, "psnr", d); + if (err) { + av_log(ctx, AV_LOG_ERROR, + "problem loading feature extractor: psnr\n"); + goto exit; + } + } + + if (s->ssim) { + err = vmaf_use_feature(s->vmaf, "float_ssim", NULL); + if (err) { + av_log(ctx, AV_LOG_ERROR, + "problem loading feature extractor: ssim\n"); + goto exit; + } + } + + if (s->ms_ssim) { + err = vmaf_use_feature(s->vmaf, "float_ms_ssim", NULL); + if (err) { + av_log(ctx, AV_LOG_ERROR, + "problem loading feature extractor: ms_ssim\n"); + goto exit; + } + } + +exit: + return err; } static av_cold int init(AVFilterContext *ctx) { LIBVMAFContext *s = ctx->priv; + int err = 0; - s->gref = av_frame_alloc(); - s->gmain = av_frame_alloc(); - if (!s->gref || !s->gmain) - return AVERROR(ENOMEM); + VmafConfiguration cfg = { + .log_level = log_level_map(av_log_get_level()), + .n_subsample = s->n_subsample, + .n_threads = s->n_threads, + }; - s->error = 0; + err = vmaf_init(&s->vmaf, cfg); + if (err) + return AVERROR(EINVAL); - s->vmaf_thread_created = 0; - pthread_mutex_init(&s->lock, NULL); - pthread_cond_init (&s->cond, NULL); + err = parse_deprecated_options(ctx); + if (err) + return err; + + err = parse_models(ctx); + if (err) + return err; + + err = parse_features(ctx); + if (err) + return err; s->fs.on_event = do_vmaf; return 0; @@ -256,26 +545,31 @@ static const enum AVPixelFormat pix_fmts[] = { static int config_input_ref(AVFilterLink *inlink) { - AVFilterContext *ctx = inlink->dst; + AVFilterContext *ctx = inlink->dst; LIBVMAFContext *s = ctx->priv; - int th; + const AVPixFmtDescriptor *desc; + int err = 0; - if (ctx->inputs[0]->w != ctx->inputs[1]->w || - ctx->inputs[0]->h != ctx->inputs[1]->h) { - av_log(ctx, AV_LOG_ERROR, "Width and height of input videos must be same.\n"); - return AVERROR(EINVAL); + if (ctx->inputs[0]->w != ctx->inputs[1]->w) { + av_log(ctx, AV_LOG_ERROR, "input width must match.\n"); + err |= AVERROR(EINVAL); } - s->desc = av_pix_fmt_desc_get(inlink->format); - s->width = ctx->inputs[0]->w; - s->height = ctx->inputs[0]->h; - - th = pthread_create(&s->vmaf_thread, NULL, call_vmaf, (void *) s); - if (th) { - av_log(ctx, AV_LOG_ERROR, "Thread creation failed.\n"); - return AVERROR(EINVAL); + if (ctx->inputs[0]->h != ctx->inputs[1]->h) { + av_log(ctx, AV_LOG_ERROR, "input height must match.\n"); + err |= AVERROR(EINVAL); } - s->vmaf_thread_created = 1; + + if (ctx->inputs[0]->format != ctx->inputs[1]->format) { + av_log(ctx, AV_LOG_ERROR, "input pix_fmt must match.\n"); + err |= AVERROR(EINVAL); + } + + if (err) + return err; + + desc = av_pix_fmt_desc_get(inlink->format); + s->bpc = desc->comp[0].depth; return 0; } @@ -307,28 +601,80 @@ static int activate(AVFilterContext *ctx) return ff_framesync_activate(&s->fs); } +static enum VmafOutputFormat log_fmt_map(const char *log_fmt) +{ + if (log_fmt) { + if (av_stristr(log_fmt, "xml")) + return VMAF_OUTPUT_FORMAT_XML; + if (av_stristr(log_fmt, "json")) + return VMAF_OUTPUT_FORMAT_JSON; + if (av_stristr(log_fmt, "csv")) + return VMAF_OUTPUT_FORMAT_CSV; + if (av_stristr(log_fmt, "sub")) + return VMAF_OUTPUT_FORMAT_SUB; + } + + return VMAF_OUTPUT_FORMAT_XML; +} + +static enum VmafPoolingMethod pool_method_map(const char *pool_method) +{ + if (pool_method) { + if (av_stristr(pool_method, "min")) + return VMAF_POOL_METHOD_MIN; + if (av_stristr(pool_method, "mean")) + return VMAF_POOL_METHOD_MEAN; + if (av_stristr(pool_method, "harmonic_mean")) + return VMAF_POOL_METHOD_HARMONIC_MEAN; + } + + return VMAF_POOL_METHOD_MEAN; +} + static av_cold void uninit(AVFilterContext *ctx) { LIBVMAFContext *s = ctx->priv; + int err = 0; ff_framesync_uninit(&s->fs); - pthread_mutex_lock(&s->lock); - s->eof = 1; - pthread_cond_signal(&s->cond); - pthread_mutex_unlock(&s->lock); + if (!s->frame_cnt) + goto clean_up; - if (s->vmaf_thread_created) - { - pthread_join(s->vmaf_thread, NULL); - s->vmaf_thread_created = 0; + err = vmaf_read_pictures(s->vmaf, NULL, NULL, 0); + if (err) { + av_log(ctx, AV_LOG_ERROR, + "problem flushing libvmaf context.\n"); } - av_frame_free(&s->gref); - av_frame_free(&s->gmain); + for (unsigned i = 0; i < s->model_cnt; i++) { + double vmaf_score; + err = vmaf_score_pooled(s->vmaf, s->model[i], pool_method_map(s->pool), + &vmaf_score, 0, s->frame_cnt - 1); + if (err) { + av_log(ctx, AV_LOG_ERROR, + "problem getting pooled vmaf score.\n"); + } - pthread_mutex_destroy(&s->lock); - pthread_cond_destroy(&s->cond); + av_log(ctx, AV_LOG_INFO, "VMAF score: %f\n", vmaf_score); + } + + if (s->vmaf) { + if (s->log_path && !err) + vmaf_write_output(s->vmaf, s->log_path, log_fmt_map(s->log_fmt)); + } + +clean_up: + if (s->model) { + for (unsigned i = 0; i < s->model_cnt; i++) { + if (s->model[i]) + vmaf_model_destroy(s->model[i]); + } + av_free(s->model); + } + + if (s->vmaf) + vmaf_close(s->vmaf); } static const AVFilterPad libvmaf_inputs[] = { diff --git a/libavfilter/vf_limiter.c b/libavfilter/vf_limiter.c index 488c8865d..67b734229 100644 --- a/libavfilter/vf_limiter.c +++ b/libavfilter/vf_limiter.c @@ -88,42 +88,29 @@ static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_NONE }; -static void limiter8(const uint8_t *src, uint8_t *dst, - ptrdiff_t slinesize, ptrdiff_t dlinesize, - int w, int h, int min, int max) -{ - int x, y; - - for (y = 0; y < h; y++) { - for (x = 0; x < w; x++) { - dst[x] = av_clip(src[x], min, max); - } - - dst += dlinesize; - src += slinesize; - } +#define LIMITER(n, type) \ +static void limiter##n(const uint8_t *ssrc, uint8_t *ddst, \ + ptrdiff_t slinesize, ptrdiff_t dlinesize,\ + int w, int h, int min, int max) \ +{ \ + const type *src = (const type *)ssrc; \ + type *dst = (type *)ddst; \ + \ + dlinesize /= sizeof(type); \ + slinesize /= sizeof(type); \ + \ + for (int y = 0; y < h; y++) { \ + for (int x = 0; x < w; x++) { \ + dst[x] = av_clip(src[x], min, max); \ + } \ + \ + dst += dlinesize; \ + src += slinesize; \ + } \ } -static void limiter16(const uint8_t *ssrc, uint8_t *ddst, - ptrdiff_t slinesize, ptrdiff_t dlinesize, - int w, int h, int min, int max) -{ - const uint16_t *src = (const uint16_t *)ssrc; - uint16_t *dst = (uint16_t *)ddst; - int x, y; - - dlinesize /= 2; - slinesize /= 2; - - for (y = 0; y < h; y++) { - for (x = 0; x < w; x++) { - dst[x] = av_clip(src[x], min, max); - } - - dst += dlinesize; - src += slinesize; - } -} +LIMITER(8, uint8_t) +LIMITER(16, uint16_t) static int config_input(AVFilterLink *inlink) { @@ -154,8 +141,9 @@ static int config_input(AVFilterLink *inlink) s->dsp.limiter = limiter16; } - if (ARCH_X86) - ff_limiter_init_x86(&s->dsp, desc->comp[0].depth); +#if ARCH_X86 + ff_limiter_init_x86(&s->dsp, desc->comp[0].depth); +#endif return 0; } diff --git a/libavfilter/vf_lut.c b/libavfilter/vf_lut.c index fd5b36479..621291cda 100644 --- a/libavfilter/vf_lut.c +++ b/libavfilter/vf_lut.c @@ -24,6 +24,8 @@ * value, and apply it to input video. */ +#include "config_components.h" + #include "libavutil/attributes.h" #include "libavutil/bswap.h" #include "libavutil/common.h" diff --git a/libavfilter/vf_lut2.c b/libavfilter/vf_lut2.c index 868c0496f..49755544b 100644 --- a/libavfilter/vf_lut2.c +++ b/libavfilter/vf_lut2.c @@ -18,6 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/attributes.h" #include "libavutil/common.h" #include "libavutil/eval.h" diff --git a/libavfilter/vf_lut3d.c b/libavfilter/vf_lut3d.c index 7ef96906f..358fe13e0 100644 --- a/libavfilter/vf_lut3d.c +++ b/libavfilter/vf_lut3d.c @@ -24,6 +24,8 @@ * 3D Lookup table filter */ +#include "config_components.h" + #include "float.h" #include "libavutil/opt.h" @@ -1148,9 +1150,9 @@ static int config_input(AVFilterLink *inlink) av_assert0(0); } - if (ARCH_X86) { - ff_lut3d_init_x86(lut3d, desc); - } +#if ARCH_X86 + ff_lut3d_init_x86(lut3d, desc); +#endif return 0; } @@ -1215,6 +1217,11 @@ static int process_command(AVFilterContext *ctx, const char *cmd, const char *ar static const AVOption lut3d_haldclut_options[] = { #if CONFIG_LUT3D_FILTER { "file", "set 3D LUT file name", OFFSET(file), AV_OPT_TYPE_STRING, {.str=NULL}, .flags = FLAGS }, +#endif +#if CONFIG_HALDCLUT_FILTER + { "clut", "when to process CLUT", OFFSET(clut), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, .flags = TFLAGS, "clut" }, + { "first", "process only first CLUT, ignore rest", 0, AV_OPT_TYPE_CONST, {.i64=0}, .flags = TFLAGS, "clut" }, + { "all", "process all CLUTs", 0, AV_OPT_TYPE_CONST, {.i64=1}, .flags = TFLAGS, "clut" }, #endif COMMON_OPTIONS }; @@ -1236,7 +1243,7 @@ static av_cold int lut3d_init(AVFilterContext *ctx) return set_identity_matrix(ctx, 32); } - f = av_fopen_utf8(lut3d->file, "r"); + f = avpriv_fopen_utf8(lut3d->file, "r"); if (!f) { ret = AVERROR(errno); av_log(ctx, AV_LOG_ERROR, "%s: %s\n", lut3d->file, av_err2str(ret)); @@ -1517,12 +1524,15 @@ static int update_apply_clut(FFFrameSync *fs) return ret; if (!second) return ff_filter_frame(ctx->outputs[0], master); - if (lut3d->clut_float) - update_clut_float(ctx->priv, second); - else if (lut3d->clut_planar) - update_clut_planar(ctx->priv, second); - else - update_clut_packed(ctx->priv, second); + if (lut3d->clut || !lut3d->got_clut) { + if (lut3d->clut_float) + update_clut_float(ctx->priv, second); + else if (lut3d->clut_planar) + update_clut_planar(ctx->priv, second); + else + update_clut_packed(ctx->priv, second); + lut3d->got_clut = 1; + } out = apply_lut(inlink, master); return ff_filter_frame(ctx->outputs[0], out); } @@ -2124,7 +2134,7 @@ static av_cold int lut1d_init(AVFilterContext *ctx) return 0; } - f = av_fopen_utf8(lut1d->file, "r"); + f = avpriv_fopen_utf8(lut1d->file, "r"); if (!f) { ret = AVERROR(errno); av_log(ctx, AV_LOG_ERROR, "%s: %s\n", lut1d->file, av_err2str(ret)); diff --git a/libavfilter/vf_maskedclamp.c b/libavfilter/vf_maskedclamp.c index de9766987..72f98703a 100644 --- a/libavfilter/vf_maskedclamp.c +++ b/libavfilter/vf_maskedclamp.c @@ -209,8 +209,9 @@ static int config_input(AVFilterLink *inlink) else s->dsp.maskedclamp = maskedclamp16; - if (ARCH_X86) - ff_maskedclamp_init_x86(&s->dsp, s->depth); +#if ARCH_X86 + ff_maskedclamp_init_x86(&s->dsp, s->depth); +#endif return 0; } diff --git a/libavfilter/vf_maskedmerge.c b/libavfilter/vf_maskedmerge.c index f86bf0c74..7adb80976 100644 --- a/libavfilter/vf_maskedmerge.c +++ b/libavfilter/vf_maskedmerge.c @@ -56,6 +56,7 @@ static const enum AVPixelFormat pix_fmts[] = { 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_GRAY14, AV_PIX_FMT_GRAY16, + AV_PIX_FMT_GRAYF32, AV_PIX_FMT_GBRPF32, AV_PIX_FMT_GBRAPF32, AV_PIX_FMT_NONE }; @@ -95,7 +96,7 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) base->linesize[p], overlay->linesize[p], mask->linesize[p], out->linesize[p], s->width[p], slice_end - slice_start, - s->half, s->depth); + s->half, s->max); } return 0; @@ -137,51 +138,42 @@ static int process_frame(FFFrameSync *fs) return ff_filter_frame(outlink, out); } -static void maskedmerge8(const uint8_t *bsrc, const uint8_t *osrc, - const uint8_t *msrc, uint8_t *dst, - ptrdiff_t blinesize, ptrdiff_t olinesize, - ptrdiff_t mlinesize, ptrdiff_t dlinesize, - int w, int h, - int half, int shift) -{ - int x, y; - - for (y = 0; y < h; y++) { - for (x = 0; x < w; x++) { - dst[x] = bsrc[x] + ((msrc[x] * (osrc[x] - bsrc[x]) + 128) >> 8); - } - - dst += dlinesize; - bsrc += blinesize; - osrc += olinesize; - msrc += mlinesize; - } +#define MASKEDMERGE(n, type, ctype, half, max, div) \ +static void maskedmerge##n(const uint8_t *bbsrc, const uint8_t *oosrc, \ + const uint8_t *mmsrc, uint8_t *ddst, \ + ptrdiff_t blinesize, ptrdiff_t olinesize, \ + ptrdiff_t mlinesize, ptrdiff_t dlinesize, \ + int w, int h, \ + int hhalf, int mmax) \ +{ \ + const type *bsrc = (const type *)bbsrc; \ + const type *osrc = (const type *)oosrc; \ + const type *msrc = (const type *)mmsrc; \ + type *dst = (type *)ddst; \ + \ + dlinesize /= sizeof(type); \ + blinesize /= sizeof(type); \ + olinesize /= sizeof(type); \ + mlinesize /= sizeof(type); \ + \ + for (int y = 0; y < h; y++) { \ + for (int x = 0; x < w; x++) { \ + const type invm = max - msrc[x]; \ + const ctype r = ((ctype)(bsrc[x] * invm) + \ + (ctype)(msrc[x] * osrc[x] + half)) div; \ + dst[x] = r; \ + } \ + \ + dst += dlinesize; \ + bsrc += blinesize; \ + osrc += olinesize; \ + msrc += mlinesize; \ + } \ } -static void maskedmerge16(const uint8_t *bbsrc, const uint8_t *oosrc, - const uint8_t *mmsrc, uint8_t *ddst, - ptrdiff_t blinesize, ptrdiff_t olinesize, - ptrdiff_t mlinesize, ptrdiff_t dlinesize, - int w, int h, - int half, int shift) -{ - const uint16_t *bsrc = (const uint16_t *)bbsrc; - const uint16_t *osrc = (const uint16_t *)oosrc; - const uint16_t *msrc = (const uint16_t *)mmsrc; - uint16_t *dst = (uint16_t *)ddst; - int x, y; - - for (y = 0; y < h; y++) { - for (x = 0; x < w; x++) { - dst[x] = bsrc[x] + ((msrc[x] * (osrc[x] - bsrc[x]) + half) >> shift); - } - - dst += dlinesize / 2; - bsrc += blinesize / 2; - osrc += olinesize / 2; - msrc += mlinesize / 2; - } -} +MASKEDMERGE(8, uint8_t, uint16_t, 127, 255, / 255) +MASKEDMERGE(16, uint16_t, uint32_t, hhalf, mmax, / mmax) +MASKEDMERGE(32, float, float, 0.f, 1.f, + 0.f) static int config_input(AVFilterLink *inlink) { @@ -200,15 +192,19 @@ static int config_input(AVFilterLink *inlink) s->width[0] = s->width[3] = inlink->w; s->depth = desc->comp[0].depth; - s->half = (1 << s->depth) / 2; + s->max = (1 << s->depth) - 1; + s->half = s->max / 2; - if (desc->comp[0].depth == 8) + if (s->depth == 8) s->maskedmerge = maskedmerge8; - else + else if (s->depth <= 16) s->maskedmerge = maskedmerge16; + else + s->maskedmerge = maskedmerge32; - if (ARCH_X86) - ff_maskedmerge_init_x86(s); +#if ARCH_X86 + ff_maskedmerge_init_x86(s); +#endif return 0; } diff --git a/libavfilter/vf_maskedminmax.c b/libavfilter/vf_maskedminmax.c index 5b70c8437..c7a05b42d 100644 --- a/libavfilter/vf_maskedminmax.c +++ b/libavfilter/vf_maskedminmax.c @@ -82,42 +82,30 @@ static const enum AVPixelFormat pix_fmts[] = { 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_GRAY14, AV_PIX_FMT_GRAY16, + AV_PIX_FMT_GRAYF32, AV_PIX_FMT_GBRPF32, AV_PIX_FMT_GBRAPF32, AV_PIX_FMT_NONE }; -static void maskedmin8(const uint8_t *src, uint8_t *dst, const uint8_t *f1, const uint8_t *f2, int w) -{ - for (int x = 0; x < w; x++) - dst[x] = FFABS(src[x] - f2[x]) < FFABS(src[x] - f1[x]) ? f2[x] : f1[x]; +#define MASKED(n, type, op) \ +static void masked##n(const uint8_t *ssrc, uint8_t *ddst, \ + const uint8_t *ff1, \ + const uint8_t *ff2, int w) \ +{ \ + const type *src = (const type *)ssrc; \ + const type *f1 = (const type *)ff1; \ + const type *f2 = (const type *)ff2; \ + type *dst = (type *)ddst; \ + \ + for (int x = 0; x < w; x++) \ + dst[x] = FFABS(src[x] - f2[x]) op FFABS(src[x] - f1[x]) ? f2[x] : f1[x]; \ } -static void maskedmax8(const uint8_t *src, uint8_t *dst, const uint8_t *f1, const uint8_t *f2, int w) -{ - for (int x = 0; x < w; x++) - dst[x] = FFABS(src[x] - f2[x]) > FFABS(src[x] - f1[x]) ? f2[x] : f1[x]; -} - -static void maskedmin16(const uint8_t *ssrc, uint8_t *ddst, const uint8_t *ff1, const uint8_t *ff2, int w) -{ - const uint16_t *src = (const uint16_t *)ssrc; - const uint16_t *f1 = (const uint16_t *)ff1; - const uint16_t *f2 = (const uint16_t *)ff2; - uint16_t *dst = (uint16_t *)ddst; - - for (int x = 0; x < w; x++) - dst[x] = FFABS(src[x] - f2[x]) < FFABS(src[x] - f1[x]) ? f2[x] : f1[x]; -} - -static void maskedmax16(const uint8_t *ssrc, uint8_t *ddst, const uint8_t *ff1, const uint8_t *ff2, int w) -{ - const uint16_t *src = (const uint16_t *)ssrc; - const uint16_t *f1 = (const uint16_t *)ff1; - const uint16_t *f2 = (const uint16_t *)ff2; - uint16_t *dst = (uint16_t *)ddst; - - for (int x = 0; x < w; x++) - dst[x] = FFABS(src[x] - f2[x]) > FFABS(src[x] - f1[x]) ? f2[x] : f1[x]; -} +MASKED(min8, uint8_t, <) +MASKED(max8, uint8_t, >) +MASKED(min16, uint16_t, <) +MASKED(max16, uint16_t, >) +MASKED(min32, float, <) +MASKED(max32, float, >) static int config_input(AVFilterLink *inlink) { @@ -142,8 +130,10 @@ static int config_input(AVFilterLink *inlink) if (desc->comp[0].depth == 8) s->maskedminmax = s->maskedmin ? maskedmin8 : maskedmax8; - else + else if (desc->comp[0].depth <= 16) s->maskedminmax = s->maskedmin ? maskedmin16 : maskedmax16; + else + s->maskedminmax = s->maskedmin ? maskedmin32 : maskedmax32; return 0; } diff --git a/libavfilter/vf_maskfun.c b/libavfilter/vf_maskfun.c index ff4acacc7..253e5e40f 100644 --- a/libavfilter/vf_maskfun.c +++ b/libavfilter/vf_maskfun.c @@ -35,13 +35,15 @@ typedef struct MaskFunContext { int sum; int linesize[4]; - int width[4], height[4]; + int planewidth[4], planeheight[4]; int nb_planes; int depth; int max; uint64_t max_sum; + AVFrame *in; AVFrame *empty; + int (*getsum)(AVFilterContext *ctx, AVFrame *out); int (*maskfun)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); } MaskFunContext; @@ -81,29 +83,42 @@ static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_NONE }; -static int filter_frame(AVFilterLink *inlink, AVFrame *frame) +static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; MaskFunContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; + AVFrame *out; - if (s->getsum(ctx, frame)) { + if (s->getsum(ctx, in)) { AVFrame *out = av_frame_clone(s->empty); if (!out) { - av_frame_free(&frame); + av_frame_free(&in); return AVERROR(ENOMEM); } - out->pts = frame->pts; - av_frame_free(&frame); + out->pts = in->pts; + av_frame_free(&in); return ff_filter_frame(outlink, out); } - ff_filter_execute(ctx, s->maskfun, frame, NULL, - FFMIN(s->height[1], ff_filter_get_nb_threads(ctx))); + if (av_frame_is_writable(in)) { + out = in; + } else { + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) + return AVERROR(ENOMEM); + av_frame_copy_props(out, in); + } - return ff_filter_frame(outlink, frame); + s->in = in; + ff_filter_execute(ctx, s->maskfun, out, NULL, + FFMIN(s->planeheight[1], ff_filter_get_nb_threads(ctx))); + + if (out != in) + av_frame_free(&in); + return ff_filter_frame(outlink, out); } #define GETSUM(name, type, div) \ @@ -115,8 +130,8 @@ static int getsum##name(AVFilterContext *ctx, AVFrame *out) \ \ for (p = 0; p < s->nb_planes; p++) { \ const int linesize = out->linesize[p] / div; \ - const int w = s->width[p]; \ - const int h = s->height[p]; \ + const int w = s->planewidth[p]; \ + const int h = s->planeheight[p]; \ type *dst = (type *)out->data[p]; \ \ if (!((1 << p) & s->planes)) \ @@ -142,6 +157,7 @@ static int maskfun##name(AVFilterContext *ctx, void *arg, \ int jobnr, int nb_jobs) \ { \ MaskFunContext *s = ctx->priv; \ + AVFrame *in = s->in; \ AVFrame *out = arg; \ const int low = s->low; \ const int high = s->high; \ @@ -149,24 +165,30 @@ static int maskfun##name(AVFilterContext *ctx, void *arg, \ int p; \ \ for (p = 0; p < s->nb_planes; p++) { \ + const int src_linesize = in->linesize[p] / div; \ const int linesize = out->linesize[p] / div; \ - const int w = s->width[p]; \ - const int h = s->height[p]; \ + const int w = s->planewidth[p]; \ + const int h = s->planeheight[p]; \ const int slice_start = (h * jobnr) / nb_jobs; \ const int slice_end = (h * (jobnr+1)) / nb_jobs; \ - type *dst = (type *)out->data[p] + slice_start * linesize; \ + const type *src = (type *)in->data[p] + \ + slice_start * src_linesize; \ + type *dst = (type *)out->data[p] + \ + slice_start * linesize; \ \ if (!((1 << p) & s->planes)) \ continue; \ \ for (int y = slice_start; y < slice_end; y++) { \ for (int x = 0; x < w; x++) { \ + dst[x] = src[x]; \ if (dst[x] <= low) \ dst[x] = 0; \ else if (dst[x] > high) \ dst[x] = max; \ } \ \ + src += src_linesize; \ dst += linesize; \ } \ } \ @@ -186,8 +208,8 @@ static void fill_frame(AVFilterContext *ctx) for (int p = 0; p < s->nb_planes; p++) { uint8_t *dst = s->empty->data[p]; - for (int y = 0; y < s->height[p]; y++) { - memset(dst, s->fill, s->width[p]); + for (int y = 0; y < s->planeheight[p]; y++) { + memset(dst, s->fill, s->planewidth[p]); dst += s->empty->linesize[p]; } } @@ -195,8 +217,8 @@ static void fill_frame(AVFilterContext *ctx) for (int p = 0; p < s->nb_planes; p++) { uint16_t *dst = (uint16_t *)s->empty->data[p]; - for (int y = 0; y < s->height[p]; y++) { - for (int x = 0; x < s->width[p]; x++) + for (int y = 0; y < s->planeheight[p]; y++) { + for (int x = 0; x < s->planewidth[p]; x++) dst[x] = s->fill; dst += s->empty->linesize[p] / 2; } @@ -212,7 +234,7 @@ static void set_max_sum(AVFilterContext *ctx) for (int p = 0; p < s->nb_planes; p++) { if (!((1 << p) & s->planes)) continue; - s->max_sum += (uint64_t)s->sum * s->width[p] * s->height[p]; + s->max_sum += (uint64_t)s->sum * s->planewidth[p] * s->planeheight[p]; } } @@ -230,10 +252,10 @@ static int config_input(AVFilterLink *inlink) hsub = desc->log2_chroma_w; vsub = desc->log2_chroma_h; - s->height[1] = s->height[2] = AV_CEIL_RSHIFT(inlink->h, vsub); - 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->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, vsub); + s->planeheight[0] = s->planeheight[3] = inlink->h; + s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, hsub); + s->planewidth[0] = s->planewidth[3] = inlink->w; s->depth = desc->comp[0].depth; s->max = (1 << s->depth) - 1; diff --git a/libavfilter/vf_mergeplanes.c b/libavfilter/vf_mergeplanes.c index fc1d50a72..23b9f3d62 100644 --- a/libavfilter/vf_mergeplanes.c +++ b/libavfilter/vf_mergeplanes.c @@ -27,6 +27,11 @@ #include "internal.h" #include "framesync.h" +typedef struct Mapping { + int input; + int plane; +} Mapping; + typedef struct InputParam { int depth[4]; int nb_planes; @@ -42,7 +47,7 @@ typedef struct MergePlanesContext { int nb_planes; int planewidth[4]; int planeheight[4]; - int map[4][2]; + Mapping map[4]; const AVPixFmtDescriptor *outdesc; FFFrameSync fs; @@ -51,8 +56,16 @@ typedef struct MergePlanesContext { #define OFFSET(x) offsetof(MergePlanesContext, x) #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM static const AVOption mergeplanes_options[] = { - { "mapping", "set input to output plane mapping", OFFSET(mapping), AV_OPT_TYPE_INT, {.i64=0}, 0, 0x33333333, FLAGS }, + { "mapping", "set input to output plane mapping", OFFSET(mapping), AV_OPT_TYPE_INT, {.i64=-1}, -1, 0x33333333, FLAGS|AV_OPT_FLAG_DEPRECATED }, { "format", "set output pixel format", OFFSET(out_fmt), AV_OPT_TYPE_PIXEL_FMT, {.i64=AV_PIX_FMT_YUVA444P}, 0, INT_MAX, .flags=FLAGS }, + { "map0s", "set 1st input to output stream mapping", OFFSET(map[0].input), AV_OPT_TYPE_INT, {.i64=0}, 0, 3, FLAGS }, + { "map0p", "set 1st input to output plane mapping", OFFSET(map[0].plane), AV_OPT_TYPE_INT, {.i64=0}, 0, 3, FLAGS }, + { "map1s", "set 2nd input to output stream mapping", OFFSET(map[1].input), AV_OPT_TYPE_INT, {.i64=0}, 0, 3, FLAGS }, + { "map1p", "set 2nd input to output plane mapping", OFFSET(map[1].plane), AV_OPT_TYPE_INT, {.i64=0}, 0, 3, FLAGS }, + { "map2s", "set 3rd input to output stream mapping", OFFSET(map[2].input), AV_OPT_TYPE_INT, {.i64=0}, 0, 3, FLAGS }, + { "map2p", "set 3rd input to output plane mapping", OFFSET(map[2].plane), AV_OPT_TYPE_INT, {.i64=0}, 0, 3, FLAGS }, + { "map3s", "set 4th input to output stream mapping", OFFSET(map[3].input), AV_OPT_TYPE_INT, {.i64=0}, 0, 3, FLAGS }, + { "map3p", "set 4th input to output plane mapping", OFFSET(map[3].plane), AV_OPT_TYPE_INT, {.i64=0}, 0, 3, FLAGS }, { NULL } }; @@ -73,17 +86,19 @@ static av_cold int init(AVFilterContext *ctx) s->nb_planes = av_pix_fmt_count_planes(s->out_fmt); for (i = s->nb_planes - 1; i >= 0; i--) { - s->map[i][0] = m & 0xf; - m >>= 4; - s->map[i][1] = m & 0xf; - m >>= 4; + if (m >= 0 && m <= 0x33333333) { + s->map[i].plane = m & 0xf; + m >>= 4; + s->map[i].input = m & 0xf; + m >>= 4; + } - if (s->map[i][0] > 3 || s->map[i][1] > 3) { + if (s->map[i].plane > 3 || s->map[i].input > 3) { av_log(ctx, AV_LOG_ERROR, "Mapping with out of range input and/or plane number.\n"); return AVERROR(EINVAL); } - s->nb_inputs = FFMAX(s->nb_inputs, s->map[i][1] + 1); + s->nb_inputs = FFMAX(s->nb_inputs, s->map[i].input + 1); } av_assert0(s->nb_inputs && s->nb_inputs <= 4); @@ -151,8 +166,8 @@ static int process_frame(FFFrameSync *fs) out->pts = av_rescale_q(s->fs.pts, s->fs.time_base, outlink->time_base); for (i = 0; i < s->nb_planes; i++) { - const int input = s->map[i][1]; - const int plane = s->map[i][0]; + const int input = s->map[i].input; + const int plane = s->map[i].plane; av_image_copy_plane(out->data[i], out->linesize[i], in[input]->data[plane], in[input]->linesize[plane], @@ -231,8 +246,8 @@ static int config_output(AVFilterLink *outlink) } for (i = 0; i < s->nb_planes; i++) { - const int input = s->map[i][1]; - const int plane = s->map[i][0]; + const int input = s->map[i].input; + const int plane = s->map[i].plane; InputParam *inputp = &inputsp[input]; if (plane + 1 > inputp->nb_planes) { diff --git a/libavfilter/vf_mix.c b/libavfilter/vf_mix.c index 27455657f..64d07bbbb 100644 --- a/libavfilter/vf_mix.c +++ b/libavfilter/vf_mix.c @@ -18,6 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/avstring.h" #include "libavutil/imgutils.h" #include "libavutil/intreadwrite.h" @@ -35,6 +37,7 @@ typedef struct MixContext { const AVPixFmtDescriptor *desc; char *weights_str; int nb_inputs; + int nb_threads; int duration; float *weights; float scale; @@ -45,21 +48,31 @@ typedef struct MixContext { int depth; int max; + int planes; int nb_planes; - int linesize[4]; + int linesizes[4]; int height[4]; + uint8_t **data; + int *linesize; + AVFrame **frames; FFFrameSync fs; } MixContext; static int query_formats(AVFilterContext *ctx) { - int reject_flags = AV_PIX_FMT_FLAG_BITSTREAM | - AV_PIX_FMT_FLAG_HWACCEL | - AV_PIX_FMT_FLAG_PAL; + unsigned reject_flags = AV_PIX_FMT_FLAG_BITSTREAM | + AV_PIX_FMT_FLAG_HWACCEL | + AV_PIX_FMT_FLAG_PAL; + unsigned accept_flags = 0; - return ff_set_common_formats(ctx, ff_formats_pixdesc_filter(0, reject_flags)); + if (!HAVE_BIGENDIAN) + reject_flags |= AV_PIX_FMT_FLAG_BE; + else + accept_flags |= AV_PIX_FMT_FLAG_BE; + + return ff_set_common_formats(ctx, ff_formats_pixdesc_filter(accept_flags, reject_flags)); } static int parse_weights(AVFilterContext *ctx) @@ -132,58 +145,68 @@ typedef struct ThreadData { AVFrame **in, *out; } ThreadData; +#define MIX_SLICE(type, fun, clip) \ + for (int p = 0; p < s->nb_planes; p++) { \ + const int slice_start = (s->height[p] * jobnr) / nb_jobs; \ + const int slice_end = (s->height[p] * (jobnr+1)) / nb_jobs; \ + const int width = s->linesizes[p] / sizeof(type); \ + type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ + ptrdiff_t dst_linesize = out->linesize[p] / sizeof(type); \ + \ + if (!((1 << p) & s->planes)) { \ + av_image_copy_plane((uint8_t *)dst, out->linesize[p], \ + in[0]->data[p] + slice_start * in[0]->linesize[p], \ + in[0]->linesize[p], \ + s->linesizes[p], slice_end - slice_start); \ + continue; \ + } \ + \ + for (int i = 0; i < s->nb_inputs; i++) \ + linesize[i] = in[i]->linesize[p]; \ + \ + for (int i = 0; i < s->nb_inputs; i++) \ + srcf[i] = in[i]->data[p] + slice_start * linesize[i]; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + for (int x = 0; x < width; x++) { \ + float val = 0.f; \ + \ + for (int i = 0; i < s->nb_inputs; i++) { \ + float src = *(type *)(srcf[i] + x * sizeof(type)); \ + \ + val += src * weights[i]; \ + } \ + \ + dst[x] = clip(fun(val * s->wfactor), 0, s->max); \ + } \ + \ + dst += dst_linesize; \ + for (int i = 0; i < s->nb_inputs; i++) \ + srcf[i] += linesize[i]; \ + } \ + } + +#define CLIP8(x, min, max) av_clip_uint8(x) +#define CLIP16(x, min, max) av_clip(x, min, max) +#define CLIPF(x, min, max) (x) +#define NOP(x) (x) + static int mix_frames(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { MixContext *s = ctx->priv; ThreadData *td = arg; AVFrame **in = td->in; AVFrame *out = td->out; - int i, p, x, y; + const float *weights = s->weights; + uint8_t **srcf = s->data + jobnr * s->nb_inputs; + int *linesize = s->linesize + jobnr * s->nb_inputs; if (s->depth <= 8) { - for (p = 0; p < s->nb_planes; p++) { - const int slice_start = (s->height[p] * jobnr) / nb_jobs; - const int slice_end = (s->height[p] * (jobnr+1)) / nb_jobs; - uint8_t *dst = out->data[p] + slice_start * out->linesize[p]; - - for (y = slice_start; y < slice_end; 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 * in[i]->linesize[p] + x]; - - val += src * s->weights[i]; - } - - dst[x] = av_clip_uint8(val * s->wfactor); - } - - dst += out->linesize[p]; - } - } + MIX_SLICE(uint8_t, lrintf, CLIP8) + } else if (s->depth <= 16) { + MIX_SLICE(uint16_t, lrintf, CLIP16) } else { - for (p = 0; p < s->nb_planes; p++) { - const int slice_start = (s->height[p] * jobnr) / nb_jobs; - const int slice_end = (s->height[p] * (jobnr+1)) / nb_jobs; - uint16_t *dst = (uint16_t *)(out->data[p] + slice_start * out->linesize[p]); - - for (y = slice_start; y < slice_end; y++) { - for (x = 0; x < s->linesize[p] / 2; x++) { - int val = 0; - - for (i = 0; i < s->nb_inputs; i++) { - uint16_t src = AV_RN16(in[i]->data[p] + y * in[i]->linesize[p] + x * 2); - - val += src * s->weights[i]; - } - - dst[x] = av_clip(val * s->wfactor, 0, s->max); - } - - dst += out->linesize[p] / 2; - } - } + MIX_SLICE(float, NOP, CLIPF) } return 0; @@ -220,7 +243,7 @@ static int process_frame(FFFrameSync *fs) td.in = in; td.out = out; ff_filter_execute(ctx, mix_frames, &td, NULL, - FFMIN(s->height[0], ff_filter_get_nb_threads(ctx))); + FFMIN(s->height[1], s->nb_threads)); return ff_filter_frame(outlink, out); } @@ -246,6 +269,7 @@ static int config_output(AVFilterLink *outlink) } } + s->nb_threads = ff_filter_get_nb_threads(ctx); s->desc = av_pix_fmt_desc_get(outlink->format); if (!s->desc) return AVERROR_BUG; @@ -253,12 +277,20 @@ static int config_output(AVFilterLink *outlink) s->depth = s->desc->comp[0].depth; s->max = (1 << s->depth) - 1; - if ((ret = av_image_fill_linesizes(s->linesize, inlink->format, inlink->w)) < 0) + if ((ret = av_image_fill_linesizes(s->linesizes, 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; + s->data = av_calloc(s->nb_threads * s->nb_inputs, sizeof(*s->data)); + if (!s->data) + return AVERROR(ENOMEM); + + s->linesize = av_calloc(s->nb_threads * s->nb_inputs, sizeof(*s->linesize)); + if (!s->linesize) + return AVERROR(ENOMEM); + if (s->tmix) return 0; @@ -296,6 +328,8 @@ static av_cold void uninit(AVFilterContext *ctx) ff_framesync_uninit(&s->fs); av_freep(&s->weights); + av_freep(&s->data); + av_freep(&s->linesize); if (s->tmix) { for (i = 0; i < s->nb_frames && s->frames; i++) @@ -330,6 +364,7 @@ static const AVOption mix_options[] = { { "inputs", "set number of inputs", OFFSET(nb_inputs), AV_OPT_TYPE_INT, {.i64=2}, 2, INT16_MAX, .flags = FLAGS }, { "weights", "set weight for each input", OFFSET(weights_str), AV_OPT_TYPE_STRING, {.str="1 1"}, 0, 0, .flags = TFLAGS }, { "scale", "set scale", OFFSET(scale), AV_OPT_TYPE_FLOAT, {.dbl=0}, 0, INT16_MAX, .flags = TFLAGS }, + { "planes", "set what planes to filter", OFFSET(planes), AV_OPT_TYPE_FLAGS, {.i64=15}, 0, 15, .flags = TFLAGS }, { "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" }, @@ -380,8 +415,12 @@ static int tmix_filter_frame(AVFilterLink *inlink, AVFrame *in) if (s->nb_frames < s->nb_inputs) { s->frames[s->nb_frames] = in; s->nb_frames++; - if (s->nb_frames < s->nb_inputs) - return 0; + while (s->nb_frames < s->nb_inputs) { + s->frames[s->nb_frames] = av_frame_clone(s->frames[s->nb_frames - 1]); + if (!s->frames[s->nb_frames]) + return AVERROR(ENOMEM); + s->nb_frames++; + } } else { av_frame_free(&s->frames[0]); memmove(&s->frames[0], &s->frames[1], sizeof(*s->frames) * (s->nb_inputs - 1)); @@ -398,20 +437,21 @@ static int tmix_filter_frame(AVFilterLink *inlink, AVFrame *in) out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) return AVERROR(ENOMEM); - out->pts = s->frames[0]->pts; + out->pts = s->frames[s->nb_frames - 1]->pts; td.out = out; td.in = s->frames; ff_filter_execute(ctx, mix_frames, &td, NULL, - FFMIN(s->height[0], ff_filter_get_nb_threads(ctx))); + FFMIN(s->height[1], s->nb_threads)); return ff_filter_frame(outlink, out); } static const AVOption tmix_options[] = { - { "frames", "set number of successive frames to mix", OFFSET(nb_inputs), AV_OPT_TYPE_INT, {.i64=3}, 1, 128, .flags = FLAGS }, + { "frames", "set number of successive frames to mix", OFFSET(nb_inputs), AV_OPT_TYPE_INT, {.i64=3}, 1, 1024, .flags = FLAGS }, { "weights", "set weight for each frame", OFFSET(weights_str), AV_OPT_TYPE_STRING, {.str="1 1 1"}, 0, 0, .flags = TFLAGS }, { "scale", "set scale", OFFSET(scale), AV_OPT_TYPE_FLOAT, {.dbl=0}, 0, INT16_MAX, .flags = TFLAGS }, + { "planes", "set what planes to filter", OFFSET(planes), AV_OPT_TYPE_FLAGS, {.i64=15}, 0, 15, .flags = TFLAGS }, { NULL }, }; diff --git a/libavfilter/vf_monochrome.c b/libavfilter/vf_monochrome.c index 1afc21560..c77c3b8f1 100644 --- a/libavfilter/vf_monochrome.c +++ b/libavfilter/vf_monochrome.c @@ -107,7 +107,7 @@ static int monochrome_slice8(AVFilterContext *ctx, void *arg, int jobnr, int nb_ for (int x = 0; x < width; x++) { PROCESS() - yptr[x] = av_clip_uint8(ny * max); + yptr[x] = av_clip_uint8(lrintf(ny * max)); } yptr += ylinesize; @@ -146,7 +146,7 @@ static int monochrome_slice16(AVFilterContext *ctx, void *arg, int jobnr, int nb for (int x = 0; x < width; x++) { PROCESS() - yptr[x] = av_clip_uintp2_c(ny * max, depth); + yptr[x] = av_clip_uintp2_c(lrintf(ny * max), depth); } yptr += ylinesize; diff --git a/libavfilter/vf_multiply.c b/libavfilter/vf_multiply.c new file mode 100644 index 000000000..979b885eb --- /dev/null +++ b/libavfilter/vf_multiply.c @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2022 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/pixdesc.h" +#include "libavutil/opt.h" +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "video.h" +#include "framesync.h" + +typedef struct MultiplyContext { + const AVClass *class; + + float offset; + float scale; + int planes; + + int linesize[4]; + int nb_planes; + + FFFrameSync fs; +} MultiplyContext; + +#define OFFSET(x) offsetof(MultiplyContext, x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM + +typedef struct ThreadData { + AVFrame *src, *ref, *dst; +} ThreadData; + +static const AVOption multiply_options[] = { + { "scale", "set scale", OFFSET(scale), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0., 9., FLAGS }, + { "offset", "set offset", OFFSET(offset), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, -1., 1., FLAGS }, + { "planes", "set planes", OFFSET(planes), AV_OPT_TYPE_FLAGS, {.i64=0xF}, 0., 0xF, FLAGS }, + { NULL } +}; + +static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_GBRPF32, AV_PIX_FMT_GBRAPF32, + AV_PIX_FMT_NONE +}; + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + MultiplyContext *s = ctx->priv; + int ret; + + s->nb_planes = av_pix_fmt_count_planes(inlink->format); + if ((ret = av_image_fill_linesizes(s->linesize, inlink->format, inlink->w)) < 0) + return ret; + + return 0; +} + +static void multiply(const uint8_t *ssrc, const uint8_t *rref, uint8_t *ddst, + float scale, float offset, int w) +{ + const float *src = (const float *)ssrc; + const float *ref = (const float *)rref; + float *dst = (float *)ddst; + + for (int x = 0; x < w; x++) { + const float factor = (ref[x] + offset) * scale; + + dst[x] = src[x] * factor; + } +} + +static int multiply_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + MultiplyContext *s = ctx->priv; + const float offset = s->offset; + const float scale = s->scale; + ThreadData *td = arg; + + for (int p = 0; p < s->nb_planes; p++) { + const ptrdiff_t src_linesize = td->src->linesize[p]; + const ptrdiff_t ref_linesize = td->ref->linesize[p]; + const ptrdiff_t dst_linesize = td->dst->linesize[p]; + const int w = td->src->width; + const int h = td->src->height; + const int slice_start = (h * jobnr) / nb_jobs; + const int slice_end = (h * (jobnr+1)) / nb_jobs; + const uint8_t *src = td->src->data[p] + slice_start * src_linesize; + const uint8_t *ref = td->ref->data[p] + slice_start * ref_linesize; + uint8_t *dst = td->dst->data[p] + slice_start * dst_linesize; + + if (!((1 << p) & s->planes)) { + av_image_copy_plane(dst, dst_linesize, ref, ref_linesize, + s->linesize[p], slice_end - slice_start); + continue; + } + + for (int y = slice_start; y < slice_end; y++) { + multiply(src, ref, dst, scale, offset, w); + + dst += dst_linesize; + src += src_linesize; + ref += ref_linesize; + } + } + + return 0; +} + +static int process_frame(FFFrameSync *fs) +{ + AVFilterContext *ctx = fs->parent; + MultiplyContext *s = fs->opaque; + AVFilterLink *outlink = ctx->outputs[0]; + AVFrame *out, *src, *ref; + int ret; + + if ((ret = ff_framesync_get_frame(&s->fs, 0, &src, 0)) < 0 || + (ret = ff_framesync_get_frame(&s->fs, 1, &ref, 0)) < 0) + return ret; + + if (ctx->is_disabled) { + out = av_frame_clone(src); + if (!out) + return AVERROR(ENOMEM); + } else { + ThreadData td; + + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) + return AVERROR(ENOMEM); + av_frame_copy_props(out, src); + + td.src = src; + td.ref = ref; + td.dst = out; + + ff_filter_execute(ctx, multiply_slice, &td, NULL, + FFMIN(outlink->h, ff_filter_get_nb_threads(ctx))); + } + out->pts = av_rescale_q(s->fs.pts, s->fs.time_base, outlink->time_base); + + return ff_filter_frame(outlink, out); +} + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + MultiplyContext *s = ctx->priv; + AVFilterLink *source = ctx->inputs[0]; + AVFilterLink *ref = ctx->inputs[1]; + FFFrameSyncIn *in; + int ret; + + if (source->w != ref->w || source->h != ref->h) { + av_log(ctx, AV_LOG_ERROR, "First input link %s parameters " + "(size %dx%d) do not match the corresponding " + "second input link %s parameters (%dx%d)\n", + ctx->input_pads[0].name, source->w, source->h, + ctx->input_pads[1].name, ref->w, ref->h); + return AVERROR(EINVAL); + } + + outlink->w = source->w; + outlink->h = source->h; + outlink->sample_aspect_ratio = source->sample_aspect_ratio; + outlink->frame_rate = source->frame_rate; + + if ((ret = ff_framesync_init(&s->fs, ctx, 2)) < 0) + return ret; + + in = s->fs.in; + in[0].time_base = source->time_base; + in[1].time_base = ref->time_base; + in[0].sync = 1; + in[0].before = EXT_STOP; + in[0].after = EXT_INFINITY; + in[1].sync = 1; + in[1].before = EXT_STOP; + in[1].after = EXT_INFINITY; + s->fs.opaque = s; + s->fs.on_event = process_frame; + + ret = ff_framesync_configure(&s->fs); + outlink->time_base = s->fs.time_base; + + return ret; +} + +static int activate(AVFilterContext *ctx) +{ + MultiplyContext *s = ctx->priv; + return ff_framesync_activate(&s->fs); +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + MultiplyContext *s = ctx->priv; + + ff_framesync_uninit(&s->fs); +} + +static const AVFilterPad multiply_inputs[] = { + { + .name = "source", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_input, + }, + { + .name = "factor", + .type = AVMEDIA_TYPE_VIDEO, + }, +}; + +static const AVFilterPad multiply_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_output, + }, +}; + +AVFILTER_DEFINE_CLASS(multiply); + +const AVFilter ff_vf_multiply = { + .name = "multiply", + .description = NULL_IF_CONFIG_SMALL("Multiply first video stream with second video stream."), + .priv_class = &multiply_class, + .priv_size = sizeof(MultiplyContext), + .uninit = uninit, + .activate = activate, + FILTER_INPUTS(multiply_inputs), + FILTER_OUTPUTS(multiply_outputs), + FILTER_PIXFMTS_ARRAY(pix_fmts), + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, +}; diff --git a/libavfilter/vf_neighbor.c b/libavfilter/vf_neighbor.c index f48fb306b..d6638779e 100644 --- a/libavfilter/vf_neighbor.c +++ b/libavfilter/vf_neighbor.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/imgutils.h" #include "libavutil/intreadwrite.h" #include "libavutil/pixdesc.h" diff --git a/libavfilter/vf_neighbor_opencl.c b/libavfilter/vf_neighbor_opencl.c index 98b04b285..3b83cee3d 100644 --- a/libavfilter/vf_neighbor_opencl.c +++ b/libavfilter/vf_neighbor_opencl.c @@ -18,6 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/common.h" #include "libavutil/imgutils.h" #include "libavutil/opt.h" diff --git a/libavfilter/vf_nlmeans.c b/libavfilter/vf_nlmeans.c index 8a05965c9..2fc3adacc 100644 --- a/libavfilter/vf_nlmeans.c +++ b/libavfilter/vf_nlmeans.c @@ -36,6 +36,7 @@ #include "formats.h" #include "internal.h" #include "vf_nlmeans.h" +#include "vf_nlmeans_init.h" #include "video.h" typedef struct NLMeansContext { @@ -84,48 +85,6 @@ static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_NONE }; -/** - * Compute squared difference of the safe area (the zone where s1 and s2 - * overlap). It is likely the largest integral zone, so it is interesting to do - * as little checks as possible; contrary to the unsafe version of this - * function, we do not need any clipping here. - * - * The line above dst and the column to its left are always readable. - */ -static void compute_safe_ssd_integral_image_c(uint32_t *dst, ptrdiff_t dst_linesize_32, - const uint8_t *s1, ptrdiff_t linesize1, - const uint8_t *s2, ptrdiff_t linesize2, - int w, int h) -{ - const uint32_t *dst_top = dst - dst_linesize_32; - - /* SIMD-friendly assumptions allowed here */ - av_assert2(!(w & 0xf) && w >= 16 && h >= 1); - - for (int y = 0; y < h; y++) { - for (int x = 0; x < w; x += 4) { - const int d0 = s1[x ] - s2[x ]; - const int d1 = s1[x + 1] - s2[x + 1]; - const int d2 = s1[x + 2] - s2[x + 2]; - const int d3 = s1[x + 3] - s2[x + 3]; - - dst[x ] = dst_top[x ] - dst_top[x - 1] + d0*d0; - dst[x + 1] = dst_top[x + 1] - dst_top[x ] + d1*d1; - dst[x + 2] = dst_top[x + 2] - dst_top[x + 1] + d2*d2; - dst[x + 3] = dst_top[x + 3] - dst_top[x + 2] + d3*d3; - - dst[x ] += dst[x - 1]; - dst[x + 1] += dst[x ]; - dst[x + 2] += dst[x + 1]; - dst[x + 3] += dst[x + 2]; - } - s1 += linesize1; - s2 += linesize2; - dst += dst_linesize_32; - dst_top += dst_linesize_32; - } -} - /** * Compute squared difference of an unsafe area (the zone nor s1 nor s2 could * be readable). @@ -326,59 +285,6 @@ struct thread_data { int p; }; -static void compute_weights_line_c(const uint32_t *const iia, - const uint32_t *const iib, - const uint32_t *const iid, - const uint32_t *const iie, - const uint8_t *const src, - float *total_weight, - float *sum, - const float *const weight_lut, - int max_meaningful_diff, - int startx, int endx) -{ - for (int x = startx; x < endx; x++) { - /* - * M is a discrete map where every entry contains the sum of all the entries - * in the rectangle from the top-left origin of M to its coordinate. In the - * following schema, "i" contains the sum of the whole map: - * - * M = +----------+-----------------+----+ - * | | | | - * | | | | - * | a| b| c| - * +----------+-----------------+----+ - * | | | | - * | | | | - * | | X | | - * | | | | - * | d| e| f| - * +----------+-----------------+----+ - * | | | | - * | g| h| i| - * +----------+-----------------+----+ - * - * The sum of the X box can be calculated with: - * X = e-d-b+a - * - * See https://en.wikipedia.org/wiki/Summed_area_table - * - * The compute*_ssd functions compute the integral image M where every entry - * contains the sum of the squared difference of every corresponding pixels of - * two input planes of the same size as M. - */ - const uint32_t a = iia[x]; - const uint32_t b = iib[x]; - const uint32_t d = iid[x]; - const uint32_t e = iie[x]; - const uint32_t patch_diff_sq = FFMIN(e - d - b + a, max_meaningful_diff); - const float weight = weight_lut[patch_diff_sq]; // exp(-patch_diff_sq * s->pdiff_scale) - - total_weight[x] += weight; - sum[x] += weight * src[x]; - } -} - static int nlmeans_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { NLMeansContext *s = ctx->priv; @@ -512,18 +418,6 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) } \ } while (0) -void ff_nlmeans_init(NLMeansDSPContext *dsp) -{ - dsp->compute_safe_ssd_integral_image = compute_safe_ssd_integral_image_c; - dsp->compute_weights_line = compute_weights_line_c; - - if (ARCH_AARCH64) - ff_nlmeans_init_aarch64(dsp); - - if (ARCH_X86) - ff_nlmeans_init_x86(dsp); -} - static av_cold int init(AVFilterContext *ctx) { NLMeansContext *s = ctx->priv; diff --git a/libavfilter/vf_nlmeans.h b/libavfilter/vf_nlmeans.h index 43611a03b..61377f8c6 100644 --- a/libavfilter/vf_nlmeans.h +++ b/libavfilter/vf_nlmeans.h @@ -39,7 +39,6 @@ typedef struct NLMeansDSPContext { int startx, int endx); } NLMeansDSPContext; -void ff_nlmeans_init(NLMeansDSPContext *dsp); void ff_nlmeans_init_aarch64(NLMeansDSPContext *dsp); void ff_nlmeans_init_x86(NLMeansDSPContext *dsp); diff --git a/libavfilter/vf_nlmeans_init.h b/libavfilter/vf_nlmeans_init.h new file mode 100644 index 000000000..06e932936 --- /dev/null +++ b/libavfilter/vf_nlmeans_init.h @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2016 Clément Bœsch + * + * 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_NLMEANS_INIT_H +#define AVFILTER_NLMEANS_INIT_H + +#include +#include + +#include "config.h" +#include "libavutil/avassert.h" +#include "libavutil/macros.h" +#include "vf_nlmeans.h" + +/** + * Compute squared difference of the safe area (the zone where s1 and s2 + * overlap). It is likely the largest integral zone, so it is interesting to do + * as little checks as possible; contrary to the unsafe version of this + * function, we do not need any clipping here. + * + * The line above dst and the column to its left are always readable. + */ +static void compute_safe_ssd_integral_image_c(uint32_t *dst, ptrdiff_t dst_linesize_32, + const uint8_t *s1, ptrdiff_t linesize1, + const uint8_t *s2, ptrdiff_t linesize2, + int w, int h) +{ + const uint32_t *dst_top = dst - dst_linesize_32; + + /* SIMD-friendly assumptions allowed here */ + av_assert2(!(w & 0xf) && w >= 16 && h >= 1); + + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x += 4) { + const int d0 = s1[x ] - s2[x ]; + const int d1 = s1[x + 1] - s2[x + 1]; + const int d2 = s1[x + 2] - s2[x + 2]; + const int d3 = s1[x + 3] - s2[x + 3]; + + dst[x ] = dst_top[x ] - dst_top[x - 1] + d0*d0; + dst[x + 1] = dst_top[x + 1] - dst_top[x ] + d1*d1; + dst[x + 2] = dst_top[x + 2] - dst_top[x + 1] + d2*d2; + dst[x + 3] = dst_top[x + 3] - dst_top[x + 2] + d3*d3; + + dst[x ] += dst[x - 1]; + dst[x + 1] += dst[x ]; + dst[x + 2] += dst[x + 1]; + dst[x + 3] += dst[x + 2]; + } + s1 += linesize1; + s2 += linesize2; + dst += dst_linesize_32; + dst_top += dst_linesize_32; + } +} + +static void compute_weights_line_c(const uint32_t *const iia, + const uint32_t *const iib, + const uint32_t *const iid, + const uint32_t *const iie, + const uint8_t *const src, + float *total_weight, + float *sum, + const float *const weight_lut, + int max_meaningful_diff, + int startx, int endx) +{ + for (int x = startx; x < endx; x++) { + /* + * M is a discrete map where every entry contains the sum of all the entries + * in the rectangle from the top-left origin of M to its coordinate. In the + * following schema, "i" contains the sum of the whole map: + * + * M = +----------+-----------------+----+ + * | | | | + * | | | | + * | a| b| c| + * +----------+-----------------+----+ + * | | | | + * | | | | + * | | X | | + * | | | | + * | d| e| f| + * +----------+-----------------+----+ + * | | | | + * | g| h| i| + * +----------+-----------------+----+ + * + * The sum of the X box can be calculated with: + * X = e-d-b+a + * + * See https://en.wikipedia.org/wiki/Summed_area_table + * + * The compute*_ssd functions compute the integral image M where every entry + * contains the sum of the squared difference of every corresponding pixels of + * two input planes of the same size as M. + */ + const uint32_t a = iia[x]; + const uint32_t b = iib[x]; + const uint32_t d = iid[x]; + const uint32_t e = iie[x]; + const uint32_t patch_diff_sq = FFMIN(e - d - b + a, max_meaningful_diff); + const float weight = weight_lut[patch_diff_sq]; // exp(-patch_diff_sq * s->pdiff_scale) + + total_weight[x] += weight; + sum[x] += weight * src[x]; + } +} + +static av_unused void ff_nlmeans_init(NLMeansDSPContext *dsp) +{ + dsp->compute_safe_ssd_integral_image = compute_safe_ssd_integral_image_c; + dsp->compute_weights_line = compute_weights_line_c; + +#if ARCH_AARCH64 + ff_nlmeans_init_aarch64(dsp); +#elif ARCH_X86 + ff_nlmeans_init_x86(dsp); +#endif +} + +#endif /* AVFILTER_NLMEANS_INIT_H */ diff --git a/libavfilter/vf_nnedi.c b/libavfilter/vf_nnedi.c index cbe211057..e5a16918b 100644 --- a/libavfilter/vf_nnedi.c +++ b/libavfilter/vf_nnedi.c @@ -166,13 +166,15 @@ AVFILTER_DEFINE_CLASS(nnedi); static int config_output(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; + const NNEDIContext *const s = ctx->priv; outlink->time_base = av_mul_q(ctx->inputs[0]->time_base, (AVRational){1, 2}); outlink->w = ctx->inputs[0]->w; outlink->h = ctx->inputs[0]->h; - outlink->frame_rate = av_mul_q(ctx->inputs[0]->frame_rate, - (AVRational){2, 1}); + if (s->field == -2 || s->field > 1) + outlink->frame_rate = av_mul_q(ctx->inputs[0]->frame_rate, + (AVRational){2, 1}); return 0; } @@ -955,7 +957,7 @@ static av_cold int init(AVFilterContext *ctx) size_t bytes_read; int ret = 0; - weights_file = av_fopen_utf8(s->weights_file, "rb"); + weights_file = avpriv_fopen_utf8(s->weights_file, "rb"); if (!weights_file) { av_log(ctx, AV_LOG_ERROR, "No weights file provided, aborting!\n"); return AVERROR(EINVAL); diff --git a/libavfilter/vf_noise.c b/libavfilter/vf_noise.c index 0e3e72b6b..8ed12f740 100644 --- a/libavfilter/vf_noise.c +++ b/libavfilter/vf_noise.c @@ -305,8 +305,9 @@ static av_cold int init(AVFilterContext *ctx) n->line_noise = ff_line_noise_c; n->line_noise_avg = ff_line_noise_avg_c; - if (ARCH_X86) - ff_noise_init_x86(n); +#if ARCH_X86 + ff_noise_init_x86(n); +#endif return 0; } diff --git a/libavfilter/vf_overlay.c b/libavfilter/vf_overlay.c index 685b6069a..e201e07c1 100644 --- a/libavfilter/vf_overlay.c +++ b/libavfilter/vf_overlay.c @@ -538,12 +538,13 @@ static av_always_inline void blend_plane_##depth##_##nbits##bits(AVFilterContext if (i && yuv) \ *d = av_clip((*d * (max - alpha) + *s * alpha) / max + *s - mid, -mid, mid) + mid; \ else \ - *d = FFMIN((*d * (max - alpha) + *s * alpha) / max + *s, max); \ + *d = av_clip_uintp2((*d * (max - alpha) + *s * alpha) / max + *s - (16<<(nbits-8)),\ + nbits);\ } else { \ if (i && yuv) \ *d = av_clip(FAST_DIV255((*d - mid) * (max - alpha)) + *s - mid, -mid, mid) + mid; \ else \ - *d = FFMIN(FAST_DIV255(*d * (max - alpha)) + *s, max); \ + *d = av_clip_uint8(FAST_DIV255(*d * (255 - alpha)) + *s - 16); \ } \ } \ s++; \ @@ -983,9 +984,10 @@ static int config_input_main(AVFilterLink *inlink) } end: - if (ARCH_X86) - ff_overlay_init_x86(s, s->format, inlink->format, - s->alpha_format, s->main_has_alpha); +#if ARCH_X86 + ff_overlay_init_x86(s, s->format, inlink->format, + s->alpha_format, s->main_has_alpha); +#endif return 0; } diff --git a/libavfilter/vf_overlay_vaapi.c b/libavfilter/vf_overlay_vaapi.c new file mode 100644 index 000000000..b3a624ae1 --- /dev/null +++ b/libavfilter/vf_overlay_vaapi.c @@ -0,0 +1,423 @@ +/* + * 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 "framesync.h" +#include "formats.h" +#include "internal.h" +#include "vaapi_vpp.h" + +typedef struct OverlayVAAPIContext { + VAAPIVPPContext vpp_ctx; /**< must be the first field */ + FFFrameSync fs; + int overlay_ox; + int overlay_oy; + int overlay_ow; + int overlay_oh; + float alpha; +} OverlayVAAPIContext; + +static int overlay_vaapi_query_formats(AVFilterContext *ctx) +{ + int ret; + enum { + MAIN = 0, + OVERLAY = 1, + }; + + static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_VAAPI, + AV_PIX_FMT_NONE + }; + + ret = ff_formats_ref(ff_make_format_list(pix_fmts), &ctx->inputs[MAIN]->outcfg.formats); + if (ret < 0) + return ret; + + ret = ff_formats_ref(ff_make_format_list(pix_fmts), &ctx->inputs[OVERLAY]->outcfg.formats); + if (ret < 0) + return ret; + + ret = ff_formats_ref(ff_make_format_list(pix_fmts), &ctx->outputs[0]->incfg.formats); + if (ret < 0) + return ret; + + return 0; +} + +static int overlay_vaapi_build_filter_params(AVFilterContext *avctx) +{ + VAAPIVPPContext *vpp_ctx = avctx->priv; + VAStatus vas; + int support_flag; + VAProcPipelineCaps pipeline_caps; + + memset(&pipeline_caps, 0, sizeof(pipeline_caps)); + vas = vaQueryVideoProcPipelineCaps(vpp_ctx->hwctx->display, + vpp_ctx->va_context, + NULL, 0, + &pipeline_caps); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to query pipeline " + "caps: %d (%s).\n", vas, vaErrorStr(vas)); + return AVERROR(EIO); + } + + if (!pipeline_caps.blend_flags) { + av_log(avctx, AV_LOG_ERROR, "VAAPI driver doesn't support overlay\n"); + return AVERROR(EINVAL); + } + + support_flag = pipeline_caps.blend_flags & VA_BLEND_GLOBAL_ALPHA; + if (!support_flag) { + av_log(avctx, AV_LOG_ERROR, "VAAPI driver doesn't support global alpha blending\n"); + return AVERROR(EINVAL); + } + + return 0; +} + +static int overlay_vaapi_render_picture(AVFilterContext *avctx, + VAProcPipelineParameterBuffer *params, + VAProcPipelineParameterBuffer *subpic_params, + AVFrame *output_frame) +{ + VAAPIVPPContext *ctx = avctx->priv; + VASurfaceID output_surface; + VABufferID params_id; + VABufferID subpic_params_id; + VAStatus vas; + int err = 0; + + output_surface = (VASurfaceID)(uintptr_t)output_frame->data[3]; + + 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 = vaCreateBuffer(ctx->hwctx->display, ctx->va_context, + VAProcPipelineParameterBufferType, + sizeof(*subpic_params), 1, subpic_params, &subpic_params_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 subpic parameter buffer is %#x.\n", + subpic_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 = vaRenderPicture(ctx->hwctx->display, ctx->va_context, + &subpic_params_id, 1); + if (vas != VA_STATUS_SUCCESS) { + av_log(avctx, AV_LOG_ERROR, "Failed to render subpic 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; +} + +static int overlay_vaapi_blend(FFFrameSync *fs) +{ + AVFilterContext *avctx = fs->parent; + AVFilterLink *outlink = avctx->outputs[0]; + OverlayVAAPIContext *ctx = avctx->priv; + VAAPIVPPContext *vpp_ctx = avctx->priv; + AVFrame *input_main, *input_overlay; + AVFrame *output; + VAProcPipelineParameterBuffer params, subpic_params; + VABlendState blend_state; /**< Blend State */ + VARectangle overlay_region, output_region; + int err; + + err = overlay_vaapi_build_filter_params(avctx); + if (err < 0) + return err; + + 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; + + av_log(avctx, AV_LOG_DEBUG, "Filter main: %s, %ux%u (%"PRId64").\n", + av_get_pix_fmt_name(input_main->format), + input_main->width, input_main->height, input_main->pts); + + av_log(avctx, AV_LOG_DEBUG, "Filter overlay: %s, %ux%u (%"PRId64").\n", + av_get_pix_fmt_name(input_overlay->format), + input_overlay->width, input_overlay->height, input_overlay->pts); + + if (vpp_ctx->va_context == VA_INVALID_ID) + return AVERROR(EINVAL); + + output = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!output) { + err = AVERROR(ENOMEM); + goto fail; + } + + err = av_frame_copy_props(output, input_main); + if (err < 0) + goto fail; + + err = ff_vaapi_vpp_init_params(avctx, ¶ms, + input_main, output); + if (err < 0) + goto fail; + + overlay_region = (VARectangle) { + .x = ctx->overlay_ox, + .y = ctx->overlay_oy, + .width = ctx->overlay_ow ? ctx->overlay_ow : input_overlay->width, + .height = ctx->overlay_oh ? ctx->overlay_oh : input_overlay->height, + }; + + output_region = (VARectangle) { + .x = 0, + .y = 0, + .width = output->width, + .height = output->height, + }; + + if (overlay_region.x + overlay_region.width > input_main->width || + overlay_region.y + overlay_region.height > input_main->height) { + av_log(ctx, AV_LOG_WARNING, + "The overlay image exceeds the scope of the main image, " + "will crop the overlay image according based on the main image.\n"); + } + + params.filters = &vpp_ctx->filter_buffers[0]; + params.num_filters = vpp_ctx->nb_filter_buffers; + + params.output_region = &output_region; + params.output_background_color = VAAPI_VPP_BACKGROUND_BLACK; + + memcpy(&subpic_params, ¶ms, sizeof(subpic_params)); + + blend_state.flags = VA_BLEND_GLOBAL_ALPHA; + blend_state.global_alpha = ctx->alpha; + subpic_params.blend_state = &blend_state; + + subpic_params.surface = (VASurfaceID)(uintptr_t)input_overlay->data[3]; + subpic_params.output_region = &overlay_region; + + err = overlay_vaapi_render_picture(avctx, ¶ms, &subpic_params, output); + if (err < 0) + goto fail; + + 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: + av_frame_free(&output); + return err; +} + +static int overlay_vaapi_init_framesync(AVFilterContext *avctx) +{ + OverlayVAAPIContext *ctx = avctx->priv; + int ret, i; + + ctx->fs.on_event = overlay_vaapi_blend; + ctx->fs.opaque = ctx; + ret = ff_framesync_init(&ctx->fs, avctx, avctx->nb_inputs); + if (ret < 0) + return ret; + + for (i = 0; i < avctx->nb_inputs; i++) { + FFFrameSyncIn *in = &ctx->fs.in[i]; + in->before = EXT_STOP; + in->after = EXT_INFINITY; + in->sync = i ? 1 : 2; + in->time_base = avctx->inputs[i]->time_base; + } + + return ff_framesync_configure(&ctx->fs); +} + +static int overlay_vaapi_config_output(AVFilterLink *outlink) +{ + AVFilterContext *avctx = outlink->src; + OverlayVAAPIContext *ctx = avctx->priv; + VAAPIVPPContext *vpp_ctx = avctx->priv; + int err; + + err = overlay_vaapi_init_framesync(avctx); + if (err < 0) + return err; + + vpp_ctx->output_width = avctx->inputs[0]->w; + vpp_ctx->output_height = avctx->inputs[0]->h; + + err = ff_vaapi_vpp_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_vaapi_init(AVFilterContext *avctx) +{ + VAAPIVPPContext *vpp_ctx = avctx->priv; + + ff_vaapi_vpp_ctx_init(avctx); + vpp_ctx->output_format = AV_PIX_FMT_NONE; + + return 0; +} + +static int overlay_vaapi_activate(AVFilterContext *avctx) +{ + OverlayVAAPIContext *ctx = avctx->priv; + + return ff_framesync_activate(&ctx->fs); +} + +static av_cold void overlay_vaapi_uninit(AVFilterContext *avctx) +{ + OverlayVAAPIContext *ctx = avctx->priv; + + ff_framesync_uninit(&ctx->fs); +} + +#define OFFSET(x) offsetof(OverlayVAAPIContext, x) +#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) +static const AVOption overlay_vaapi_options[] = { + { "x", "Overlay x position", + OFFSET(overlay_ox), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, .flags = FLAGS }, + { "y", "Overlay y position", + OFFSET(overlay_oy), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, .flags = FLAGS }, + { "w", "Overlay width", + OFFSET(overlay_ow), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, .flags = FLAGS }, + { "h", "Overlay height", + OFFSET(overlay_oh), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, .flags = FLAGS }, + { "alpha", "Overlay global alpha", + OFFSET(alpha), AV_OPT_TYPE_FLOAT, { .dbl = 0.0}, 0.0, 1.0, .flags = FLAGS}, + { NULL }, +}; + +AVFILTER_DEFINE_CLASS(overlay_vaapi); + +static const AVFilterPad overlay_vaapi_inputs[] = { + { + .name = "main", + .type = AVMEDIA_TYPE_VIDEO, + .get_buffer.video = ff_default_get_video_buffer, + .config_props = &ff_vaapi_vpp_config_input, + }, + { + .name = "overlay", + .type = AVMEDIA_TYPE_VIDEO, + .get_buffer.video = ff_default_get_video_buffer, + }, +}; + +static const AVFilterPad overlay_vaapi_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &overlay_vaapi_config_output, + }, +}; + +const AVFilter ff_vf_overlay_vaapi = { + .name = "overlay_vaapi", + .description = NULL_IF_CONFIG_SMALL("Overlay one video on top of another"), + .priv_size = sizeof(OverlayVAAPIContext), + .priv_class = &overlay_vaapi_class, + .init = &overlay_vaapi_init, + .uninit = &overlay_vaapi_uninit, + .activate = &overlay_vaapi_activate, + FILTER_INPUTS(overlay_vaapi_inputs), + FILTER_OUTPUTS(overlay_vaapi_outputs), + FILTER_QUERY_FUNC(overlay_vaapi_query_formats), + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; diff --git a/libavfilter/vf_pad.c b/libavfilter/vf_pad.c index 738e25562..e52f7284d 100644 --- a/libavfilter/vf_pad.c +++ b/libavfilter/vf_pad.c @@ -355,7 +355,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) if (needs_copy) { av_log(inlink->dst, AV_LOG_DEBUG, "Direct padding impossible allocating new frame\n"); - out = ff_get_video_buffer(inlink->dst->outputs[0], + out = ff_get_video_buffer(outlink, FFMAX(inlink->w, s->w), FFMAX(inlink->h, s->h)); if (!out) { @@ -410,7 +410,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) if (in != out) av_frame_free(&in); - return ff_filter_frame(inlink->dst->outputs[0], out); + return ff_filter_frame(outlink, out); } #define OFFSET(x) offsetof(PadContext, x) diff --git a/libavfilter/vf_palettegen.c b/libavfilter/vf_palettegen.c index 4f53aa1aa..27f74fd14 100644 --- a/libavfilter/vf_palettegen.c +++ b/libavfilter/vf_palettegen.c @@ -528,7 +528,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) if (s->stats_mode == STATS_MODE_DIFF_FRAMES) { av_frame_free(&s->prev_frame); s->prev_frame = in; - } else if (s->stats_mode == STATS_MODE_SINGLE_FRAMES) { + } else if (s->stats_mode == STATS_MODE_SINGLE_FRAMES && s->nb_refs > 0) { AVFrame *out; int i; diff --git a/libavfilter/vf_paletteuse.c b/libavfilter/vf_paletteuse.c index 5b300be5a..5c491a290 100644 --- a/libavfilter/vf_paletteuse.c +++ b/libavfilter/vf_paletteuse.c @@ -423,7 +423,8 @@ 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(s, src[x], a8, r, g, b, search_method); + const uint32_t color_new = (unsigned)(a8) << 24 | r << 16 | g << 8 | b; + const int color = color_get(s, color_new, a8, r, g, b, search_method); if (color < 0) return color; @@ -537,7 +538,7 @@ static void disp_node(AVBPrint *buf, static int disp_tree(const struct color_node *node, const char *fname) { AVBPrint buf; - FILE *f = av_fopen_utf8(fname, "w"); + FILE *f = avpriv_fopen_utf8(fname, "w"); if (!f) { int ret = AVERROR(errno); diff --git a/libavfilter/vf_pixelize.c b/libavfilter/vf_pixelize.c new file mode 100644 index 000000000..a43651598 --- /dev/null +++ b/libavfilter/vf_pixelize.c @@ -0,0 +1,351 @@ +/* + * Copyright (c) 2022 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/internal.h" +#include "libavutil/imgutils.h" +#include "libavutil/opt.h" + +#include "avfilter.h" +#include "internal.h" +#include "video.h" + +enum PixelizeModes { + PIXELIZE_AVG, + PIXELIZE_MIN, + PIXELIZE_MAX, + PIXELIZE_MODES +}; + +typedef struct PixelizeContext { + const AVClass *class; + + int block_w[4], block_h[4]; + int mode; + + int depth; + int planes; + int nb_planes; + int linesize[4]; + int planewidth[4]; + int planeheight[4]; + + int log2_chroma_w; + int log2_chroma_h; + + int (*pixelize[PIXELIZE_MODES])(const uint8_t *src, uint8_t *dst, + ptrdiff_t src_linesize, + ptrdiff_t dst_linesize, + int w, int h); +} PixelizeContext; + +static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_GRAY8, + AV_PIX_FMT_GRAY9, + AV_PIX_FMT_GRAY10, + AV_PIX_FMT_GRAY12, + AV_PIX_FMT_GRAY14, + AV_PIX_FMT_GRAY16, + AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, + AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV444P, + AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, + AV_PIX_FMT_YUVJ440P, AV_PIX_FMT_YUVJ444P, + AV_PIX_FMT_YUVJ411P, + 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_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_YUV420P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV444P16, + 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_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA422P16, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA420P16, + AV_PIX_FMT_GBRAP, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, + AV_PIX_FMT_NONE +}; + +typedef struct ThreadData { + AVFrame *in, *out; +} ThreadData; + +#define PIXELIZE_AVG(name, type, stype) \ +static int pixelize_avg##name(const uint8_t *ssrc, uint8_t *ddst, \ + ptrdiff_t src_linesize, ptrdiff_t dst_linesize, \ + int w, int h) \ +{ \ + const type *src = (const type *)ssrc; \ + type *dst = (type *)ddst; \ + stype sum = 0; \ + type fill; \ + for (int y = 0; y < h; y++) { \ + for (int x = 0; x < w; x++) \ + sum += src[x]; \ + \ + src += src_linesize / sizeof(type); \ + } \ + \ + fill = sum / (w * h); \ + \ + for (int y = 0; y < h; y++) { \ + for (int x = 0; x < w; x++) \ + dst[x] = fill; \ + \ + dst += dst_linesize / sizeof(type); \ + } \ + \ + return 0; \ +} + +#define PIXELIZE_MIN(name, type, stype) \ +static int pixelize_min##name(const uint8_t *ssrc, uint8_t *ddst, \ + ptrdiff_t src_linesize, ptrdiff_t dst_linesize, \ + int w, int h) \ +{ \ + const type *src = (const type *)ssrc; \ + type *dst = (type *)ddst; \ + type fill = src[0]; \ + \ + for (int y = 0; y < h; y++) { \ + for (int x = 0; x < w; x++) \ + fill = FFMIN(src[x], fill); \ + \ + src += src_linesize / sizeof(type); \ + } \ + \ + for (int y = 0; y < h; y++) { \ + for (int x = 0; x < w; x++) \ + dst[x] = fill; \ + \ + dst += dst_linesize / sizeof(type); \ + } \ + \ + return 0; \ +} + +#define PIXELIZE_MAX(name, type, stype) \ +static int pixelize_max##name(const uint8_t *ssrc, uint8_t *ddst, \ + ptrdiff_t src_linesize, ptrdiff_t dst_linesize, \ + int w, int h) \ +{ \ + const type *src = (const type *)ssrc; \ + type *dst = (type *)ddst; \ + type fill = src[0]; \ + \ + for (int y = 0; y < h; y++) { \ + for (int x = 0; x < w; x++) \ + fill = FFMAX(src[x], fill); \ + \ + src += src_linesize / sizeof(type); \ + } \ + \ + for (int y = 0; y < h; y++) { \ + for (int x = 0; x < w; x++) \ + dst[x] = fill; \ + \ + dst += dst_linesize / sizeof(type); \ + } \ + \ + return 0; \ +} + +PIXELIZE_AVG(8, uint8_t, unsigned) +PIXELIZE_AVG(16, uint16_t, uint64_t) +PIXELIZE_MIN(8, uint8_t, unsigned) +PIXELIZE_MIN(16, uint16_t, uint64_t) +PIXELIZE_MAX(8, uint8_t, unsigned) +PIXELIZE_MAX(16, uint16_t, uint64_t) + +static int pixelize_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + PixelizeContext *s = ctx->priv; + const int mode = s->mode; + ThreadData *td = arg; + AVFrame *out = td->out; + AVFrame *in = td->in; + + for (int p = 0; p < s->nb_planes; p++) { + const int wh = s->planeheight[p]; + const int h = (s->planeheight[p] + s->block_h[p] - 1) / s->block_h[p]; + const int w = (s->planewidth[p] + s->block_w[p] - 1) / s->block_w[p]; + const int wslice_start = (wh * jobnr) / nb_jobs; + const int wslice_end = (wh * (jobnr+1)) / nb_jobs; + const int slice_start = (h * jobnr) / nb_jobs; + const int slice_end = (h * (jobnr+1)) / nb_jobs; + const ptrdiff_t out_linesize = out->linesize[p]; + const ptrdiff_t in_linesize = in->linesize[p]; + const uint8_t *src = in->data[p]; + uint8_t *dst = out->data[p]; + + if (!((1 << p) & s->planes)) { + av_image_copy_plane(dst + wslice_start * out_linesize, + out_linesize, + src + wslice_start * in_linesize, + in_linesize, + s->linesize[p], wslice_end - wslice_start); + continue; + } + + for (int y = slice_start; y < slice_end; y++) { + const int block_h = FFMIN(s->block_h[p], s->planeheight[p] - y * s->block_h[p]); + for (int x = 0; x < w; x++) { + const int block_w = FFMIN(s->block_w[p], s->planewidth[p] - x * s->block_w[p]); + + s->pixelize[mode](src + s->block_h[p] * y * in_linesize + + x * s->block_w[p] * (1 + (s->depth > 8)), + dst + s->block_h[p] * y * out_linesize + + x * s->block_w[p] * (1 + (s->depth > 8)), + in_linesize, out_linesize, block_w, block_h); + } + } + } + + return 0; +} + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + PixelizeContext *s = ctx->priv; + AVFilterLink *inlink = ctx->inputs[0]; + const AVPixFmtDescriptor *desc; + int ret; + + desc = av_pix_fmt_desc_get(outlink->format); + if (!desc) + return AVERROR_BUG; + s->nb_planes = av_pix_fmt_count_planes(outlink->format); + s->depth = desc->comp[0].depth; + + if ((ret = av_image_fill_linesizes(s->linesize, inlink->format, inlink->w)) < 0) + return ret; + + s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w); + s->planewidth[0] = s->planewidth[3] = inlink->w; + + s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h); + s->planeheight[0] = s->planeheight[3] = inlink->h; + + s->log2_chroma_w = desc->log2_chroma_w; + s->log2_chroma_h = desc->log2_chroma_h; + + s->pixelize[PIXELIZE_AVG] = s->depth <= 8 ? pixelize_avg8 : pixelize_avg16; + s->pixelize[PIXELIZE_MIN] = s->depth <= 8 ? pixelize_min8 : pixelize_min16; + s->pixelize[PIXELIZE_MAX] = s->depth <= 8 ? pixelize_max8 : pixelize_max16; + + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + PixelizeContext *s = ctx->priv; + ThreadData td; + AVFrame *out; + int ret; + + s->block_w[1] = s->block_w[2] = FFMAX(1, s->block_w[0] >> s->log2_chroma_w); + s->block_w[3] = s->block_w[0] = s->block_w[1] << s->log2_chroma_w; + + s->block_h[1] = s->block_h[2] = FFMAX(1, s->block_h[0] >> s->log2_chroma_h); + s->block_h[3] = s->block_h[0] = s->block_h[1] << s->log2_chroma_h; + + if (av_frame_is_writable(in)) { + out = in; + } else { + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) { + ret = AVERROR(ENOMEM); + goto fail; + } + + ret = av_frame_copy_props(out, in); + if (ret < 0) { + av_frame_free(&out); + goto fail; + } + } + + td.out = out; + td.in = in; + ff_filter_execute(ctx, pixelize_slice, &td, NULL, + FFMIN((s->planeheight[1] + s->block_h[1] - 1) / s->block_h[1], + ff_filter_get_nb_threads(ctx))); + + if (out != in) + av_frame_free(&in); + return ff_filter_frame(outlink, out); +fail: + av_frame_free(&in); + return ret; +} + +#define OFFSET(x) offsetof(PixelizeContext, x) +#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_RUNTIME_PARAM) + +static const AVOption pixelize_options[] = { + { "width", "set block width", OFFSET(block_w[0]), AV_OPT_TYPE_INT, {.i64=16}, 1, 1024, FLAGS }, + { "w", "set block width", OFFSET(block_w[0]), AV_OPT_TYPE_INT, {.i64=16}, 1, 1024, FLAGS }, + { "height", "set block height", OFFSET(block_h[0]), AV_OPT_TYPE_INT, {.i64=16}, 1, 1024, FLAGS }, + { "h", "set block height", OFFSET(block_h[0]), AV_OPT_TYPE_INT, {.i64=16}, 1, 1024, FLAGS }, + { "mode", "set the pixelize mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, PIXELIZE_MODES-1, FLAGS, "mode" }, + { "m", "set the pixelize mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, PIXELIZE_MODES-1, FLAGS, "mode" }, + { "avg", "average", 0, AV_OPT_TYPE_CONST, {.i64=PIXELIZE_AVG}, 0, 0, FLAGS, "mode" }, + { "min", "minimum", 0, AV_OPT_TYPE_CONST, {.i64=PIXELIZE_MIN}, 0, 0, FLAGS, "mode" }, + { "max", "maximum", 0, AV_OPT_TYPE_CONST, {.i64=PIXELIZE_MAX}, 0, 0, FLAGS, "mode" }, + { "planes", "set what planes to filter", OFFSET(planes), AV_OPT_TYPE_FLAGS, {.i64=15}, 0, 15, FLAGS }, + { "p", "set what planes to filter", OFFSET(planes), AV_OPT_TYPE_FLAGS, {.i64=15}, 0, 15, FLAGS }, + { NULL }, +}; + +AVFILTER_DEFINE_CLASS(pixelize); + +static const AVFilterPad pixelize_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = filter_frame, + }, +}; + +static const AVFilterPad pixelize_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_output, + }, +}; + +const AVFilter ff_vf_pixelize = { + .name = "pixelize", + .description = NULL_IF_CONFIG_SMALL("Pixelize video."), + .priv_size = sizeof(PixelizeContext), + .priv_class = &pixelize_class, + FILTER_INPUTS(pixelize_inputs), + FILTER_OUTPUTS(pixelize_outputs), + FILTER_PIXFMTS_ARRAY(pix_fmts), + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, +}; diff --git a/libavfilter/vf_pp7.c b/libavfilter/vf_pp7.c index 2faa4d2c8..b7c7cf9dd 100644 --- a/libavfilter/vf_pp7.c +++ b/libavfilter/vf_pp7.c @@ -301,8 +301,9 @@ static int config_input(AVFilterLink *inlink) pp7->dctB = dctB_c; - if (ARCH_X86) - ff_pp7_init_x86(pp7); +#if ARCH_X86 + ff_pp7_init_x86(pp7); +#endif return 0; } diff --git a/libavfilter/vf_pp7.h b/libavfilter/vf_pp7.h index 9aa8d732c..b7cbb020b 100644 --- a/libavfilter/vf_pp7.h +++ b/libavfilter/vf_pp7.h @@ -22,6 +22,7 @@ #ifndef AVFILTER_PP7_H #define AVFILTER_PP7_H +#include "libavutil/video_enc_params.h" #include "avfilter.h" typedef struct PP7Context { @@ -30,7 +31,7 @@ typedef struct PP7Context { int qp; int mode; - int qscale_type; + enum AVVideoEncParamsType qscale_type; int hsub; int vsub; int temp_stride; diff --git a/libavfilter/vf_premultiply.c b/libavfilter/vf_premultiply.c index 4b60de7b7..e077d46a9 100644 --- a/libavfilter/vf_premultiply.c +++ b/libavfilter/vf_premultiply.c @@ -18,6 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/imgutils.h" #include "libavutil/pixdesc.h" #include "libavutil/opt.h" diff --git a/libavfilter/vf_program_opencl.c b/libavfilter/vf_program_opencl.c index 5f3c71d95..55c1e6547 100644 --- a/libavfilter/vf_program_opencl.c +++ b/libavfilter/vf_program_opencl.c @@ -16,6 +16,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/avstring.h" #include "libavutil/log.h" #include "libavutil/mem.h" diff --git a/libavfilter/vf_psnr.c b/libavfilter/vf_psnr.c index 19852eaa6..fa2e887e9 100644 --- a/libavfilter/vf_psnr.c +++ b/libavfilter/vf_psnr.c @@ -280,7 +280,7 @@ static av_cold int init(AVFilterContext *ctx) if (!strcmp(s->stats_file_str, "-")) { s->stats_file = stdout; } else { - s->stats_file = fopen(s->stats_file_str, "w"); + s->stats_file = avpriv_fopen_utf8(s->stats_file_str, "w"); if (!s->stats_file) { int err = AVERROR(errno); char buf[128]; @@ -354,8 +354,9 @@ static int config_input_ref(AVFilterLink *inlink) s->average_max = lrint(average_max); s->dsp.sse_line = desc->comp[0].depth > 8 ? sse_line_16bit : sse_line_8bit; - if (ARCH_X86) - ff_psnr_init_x86(&s->dsp, desc->comp[0].depth); +#if ARCH_X86 + ff_psnr_init_x86(&s->dsp, desc->comp[0].depth); +#endif s->score = av_calloc(s->nb_threads, sizeof(*s->score)); if (!s->score) diff --git a/libavfilter/vf_pullup.c b/libavfilter/vf_pullup.c index 1ee5eb00d..054e3f90a 100644 --- a/libavfilter/vf_pullup.c +++ b/libavfilter/vf_pullup.c @@ -207,8 +207,9 @@ static int config_input(AVFilterLink *inlink) s->comb = comb_c; s->var = var_c; - if (ARCH_X86) - ff_pullup_init_x86(s); +#if ARCH_X86 + ff_pullup_init_x86(s); +#endif return 0; } diff --git a/libavfilter/vf_readeia608.c b/libavfilter/vf_readeia608.c index a5a0249fb..d85012564 100644 --- a/libavfilter/vf_readeia608.c +++ b/libavfilter/vf_readeia608.c @@ -454,7 +454,7 @@ static int extract_lines(AVFilterContext *ctx, void *arg, for (int i = start; i < end; i++) { ScanItem *scan = &s->scan[i]; - extract_line(ctx, in, scan, inlink->w, i); + extract_line(ctx, in, scan, inlink->w, s->start + i); } return 0; diff --git a/libavfilter/vf_remap_opencl.c b/libavfilter/vf_remap_opencl.c new file mode 100644 index 000000000..f3f84bde6 --- /dev/null +++ b/libavfilter/vf_remap_opencl.c @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2022 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/imgutils.h" +#include "libavutil/pixdesc.h" +#include "libavutil/opt.h" +#include "avfilter.h" +#include "drawutils.h" +#include "formats.h" +#include "framesync.h" +#include "internal.h" +#include "opencl.h" +#include "opencl_source.h" +#include "video.h" + +typedef struct RemapOpenCLContext { + OpenCLFilterContext ocf; + + int nb_planes; + int interp; + uint8_t fill_rgba[4]; + cl_float4 cl_fill_color; + + int initialised; + cl_kernel kernel; + cl_command_queue command_queue; + + FFFrameSync fs; +} RemapOpenCLContext; + +#define OFFSET(x) offsetof(RemapOpenCLContext, x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM + +static const AVOption remap_opencl_options[] = { + { "interp", "set interpolation method", OFFSET(interp), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, "interp" }, + { "near", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "interp" }, + { "linear", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "interp" }, + { "fill", "set the color of the unmapped pixels", OFFSET(fill_rgba), AV_OPT_TYPE_COLOR, {.str="black"}, .flags = FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(remap_opencl); + +static av_cold int remap_opencl_init(AVFilterContext *avctx) +{ + return ff_opencl_filter_init(avctx); +} + +static const char *kernels[] = { "remap_near", "remap_linear" }; + +static int remap_opencl_load(AVFilterContext *avctx, + enum AVPixelFormat main_format, + enum AVPixelFormat xmap_format, + enum AVPixelFormat ymap_format) +{ + RemapOpenCLContext *ctx = avctx->priv; + cl_int cle; + const char *source = ff_opencl_source_remap; + const char *kernel = kernels[ctx->interp]; + const AVPixFmtDescriptor *main_desc; + int err, main_planes; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(main_format); + int is_rgb = !!(desc->flags & AV_PIX_FMT_FLAG_RGB); + const float scale = 1.f / 255.f; + uint8_t rgba_map[4]; + + ff_fill_rgba_map(rgba_map, main_format); + + if (is_rgb) { + ctx->cl_fill_color.s[rgba_map[0]] = ctx->fill_rgba[0] * scale; + ctx->cl_fill_color.s[rgba_map[1]] = ctx->fill_rgba[1] * scale; + ctx->cl_fill_color.s[rgba_map[2]] = ctx->fill_rgba[2] * scale; + ctx->cl_fill_color.s[rgba_map[3]] = ctx->fill_rgba[3] * scale; + } else { + ctx->cl_fill_color.s[0] = RGB_TO_Y_BT709(ctx->fill_rgba[0], ctx->fill_rgba[1], ctx->fill_rgba[2]) * scale; + ctx->cl_fill_color.s[1] = RGB_TO_U_BT709(ctx->fill_rgba[0], ctx->fill_rgba[1], ctx->fill_rgba[2], 0) * scale; + ctx->cl_fill_color.s[2] = RGB_TO_V_BT709(ctx->fill_rgba[0], ctx->fill_rgba[1], ctx->fill_rgba[2], 0) * scale; + ctx->cl_fill_color.s[3] = ctx->fill_rgba[3] * scale; + } + + main_desc = av_pix_fmt_desc_get(main_format); + + main_planes = 0; + for (int i = 0; i < main_desc->nb_components; i++) + main_planes = FFMAX(main_planes, + main_desc->comp[i].plane + 1); + + ctx->nb_planes = main_planes; + + 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); + CL_FAIL_ON_ERROR(AVERROR(EIO), "Failed to create OpenCL " + "command queue %d.\n", cle); + + ctx->kernel = clCreateKernel(ctx->ocf.program, kernel, &cle); + CL_FAIL_ON_ERROR(AVERROR(EIO), "Failed to create kernel %d.\n", cle); + + ctx->initialised = 1; + return 0; + +fail: + if (ctx->command_queue) + clReleaseCommandQueue(ctx->command_queue); + if (ctx->kernel) + clReleaseKernel(ctx->kernel); + return err; +} + +static int remap_opencl_process_frame(FFFrameSync *fs) +{ + AVFilterContext *avctx = fs->parent; + AVFilterLink *outlink = avctx->outputs[0]; + RemapOpenCLContext *ctx = avctx->priv; + AVFrame *input_main, *input_xmap, *input_ymap; + AVFrame *output; + cl_mem mem; + cl_int cle; + 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_xmap, 0); + if (err < 0) + return err; + err = ff_framesync_get_frame(fs, 2, &input_ymap, 0); + if (err < 0) + return err; + + if (!ctx->initialised) { + AVHWFramesContext *main_fc = + (AVHWFramesContext*)input_main->hw_frames_ctx->data; + AVHWFramesContext *xmap_fc = + (AVHWFramesContext*)input_xmap->hw_frames_ctx->data; + AVHWFramesContext *ymap_fc = + (AVHWFramesContext*)input_ymap->hw_frames_ctx->data; + + err = remap_opencl_load(avctx, main_fc->sw_format, + xmap_fc->sw_format, + ymap_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++) { + cl_float4 cl_fill_color; + kernel_arg = 0; + + if (ctx->nb_planes == 1) + cl_fill_color = ctx->cl_fill_color; + else + cl_fill_color.s[0] = ctx->cl_fill_color.s[plane]; + + mem = (cl_mem)output->data[plane]; + CL_SET_KERNEL_ARG(ctx->kernel, kernel_arg, cl_mem, &mem); + kernel_arg++; + + mem = (cl_mem)input_main->data[plane]; + CL_SET_KERNEL_ARG(ctx->kernel, kernel_arg, cl_mem, &mem); + kernel_arg++; + + mem = (cl_mem)input_xmap->data[0]; + CL_SET_KERNEL_ARG(ctx->kernel, kernel_arg, cl_mem, &mem); + kernel_arg++; + + mem = (cl_mem)input_ymap->data[0]; + CL_SET_KERNEL_ARG(ctx->kernel, kernel_arg, cl_mem, &mem); + kernel_arg++; + + CL_SET_KERNEL_ARG(ctx->kernel, kernel_arg, cl_float4, &cl_fill_color); + kernel_arg++; + + 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); + CL_FAIL_ON_ERROR(AVERROR(EIO), "Failed to enqueue remap kernel " + "for plane %d: %d.\n", plane, cle); + } + + cle = clFinish(ctx->command_queue); + CL_FAIL_ON_ERROR(AVERROR(EIO), "Failed to finish command queue: %d.\n", cle); + + 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: + av_frame_free(&output); + return err; +} + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + RemapOpenCLContext *s = ctx->priv; + AVFilterLink *srclink = ctx->inputs[0]; + AVFilterLink *xlink = ctx->inputs[1]; + AVFilterLink *ylink = ctx->inputs[2]; + FFFrameSyncIn *in; + int ret; + + if (xlink->w != ylink->w || xlink->h != ylink->h) { + av_log(ctx, AV_LOG_ERROR, "Second input link %s parameters " + "(size %dx%d) do not match the corresponding " + "third input link %s parameters (%dx%d)\n", + ctx->input_pads[1].name, xlink->w, xlink->h, + ctx->input_pads[2].name, ylink->w, ylink->h); + return AVERROR(EINVAL); + } + + outlink->w = xlink->w; + outlink->h = xlink->h; + outlink->sample_aspect_ratio = srclink->sample_aspect_ratio; + outlink->frame_rate = srclink->frame_rate; + + ret = ff_framesync_init(&s->fs, ctx, 3); + if (ret < 0) + return ret; + + in = s->fs.in; + in[0].time_base = srclink->time_base; + in[1].time_base = xlink->time_base; + in[2].time_base = ylink->time_base; + in[0].sync = 2; + in[0].before = EXT_STOP; + in[0].after = EXT_STOP; + in[1].sync = 1; + in[1].before = EXT_NULL; + in[1].after = EXT_INFINITY; + in[2].sync = 1; + in[2].before = EXT_NULL; + in[2].after = EXT_INFINITY; + s->fs.opaque = s; + s->fs.on_event = remap_opencl_process_frame; + + ret = ff_framesync_configure(&s->fs); + outlink->time_base = s->fs.time_base; + if (ret < 0) + return ret; + + s->ocf.output_width = outlink->w; + s->ocf.output_height = outlink->h; + + return ff_opencl_filter_config_output(outlink); +} + +static int activate(AVFilterContext *ctx) +{ + RemapOpenCLContext *s = ctx->priv; + return ff_framesync_activate(&s->fs); +} + +static av_cold void remap_opencl_uninit(AVFilterContext *avctx) +{ + RemapOpenCLContext *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); +} + +static const AVFilterPad remap_opencl_inputs[] = { + { + .name = "source", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &ff_opencl_filter_config_input, + }, + { + .name = "xmap", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &ff_opencl_filter_config_input, + }, + { + .name = "ymap", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &ff_opencl_filter_config_input, + }, +}; + +static const AVFilterPad remap_opencl_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_output, + }, +}; + +const AVFilter ff_vf_remap_opencl = { + .name = "remap_opencl", + .description = NULL_IF_CONFIG_SMALL("Remap pixels using OpenCL."), + .priv_size = sizeof(RemapOpenCLContext), + .init = remap_opencl_init, + .uninit = remap_opencl_uninit, + .activate = activate, + FILTER_INPUTS(remap_opencl_inputs), + FILTER_OUTPUTS(remap_opencl_outputs), + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_OPENCL), + .priv_class = &remap_opencl_class, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; diff --git a/libavfilter/vf_removegrain.c b/libavfilter/vf_removegrain.c index 16140bf8b..0d4b070cd 100644 --- a/libavfilter/vf_removegrain.c +++ b/libavfilter/vf_removegrain.c @@ -501,8 +501,9 @@ static int config_input(AVFilterLink *inlink) } } - if (ARCH_X86) - ff_removegrain_init_x86(s); +#if ARCH_X86 + ff_removegrain_init_x86(s); +#endif return 0; } diff --git a/libavfilter/vf_scale.c b/libavfilter/vf_scale.c index 44f85cb01..996f7aaa5 100644 --- a/libavfilter/vf_scale.c +++ b/libavfilter/vf_scale.c @@ -138,6 +138,7 @@ typedef struct ScaleContext { char *out_color_matrix; int in_range; + int in_frame_range; int out_range; int out_h_chr_pos; @@ -322,6 +323,8 @@ static av_cold int init_dict(AVFilterContext *ctx, AVDictionary **opts) scale->opts = *opts; *opts = NULL; + scale->in_frame_range = AVCOL_RANGE_UNSPECIFIED; + return 0; } @@ -544,6 +547,9 @@ static int config_props(AVFilterLink *outlink) if (scale->in_range != AVCOL_RANGE_UNSPECIFIED) av_opt_set_int(s, "src_range", scale->in_range == AVCOL_RANGE_JPEG, 0); + else if (scale->in_frame_range != AVCOL_RANGE_UNSPECIFIED) + av_opt_set_int(s, "src_range", + scale->in_frame_range == AVCOL_RANGE_JPEG, 0); if (scale->out_range != AVCOL_RANGE_UNSPECIFIED) av_opt_set_int(s, "dst_range", scale->out_range == AVCOL_RANGE_JPEG, 0); @@ -690,6 +696,13 @@ static int scale_frame(AVFilterLink *link, AVFrame *in, AVFrame **frame_out) in->sample_aspect_ratio.den != link->sample_aspect_ratio.den || in->sample_aspect_ratio.num != link->sample_aspect_ratio.num; + if (in->color_range != AVCOL_RANGE_UNSPECIFIED && + scale->in_range == AVCOL_RANGE_UNSPECIFIED && + in->color_range != scale->in_frame_range) { + scale->in_frame_range = in->color_range; + frame_changed = 1; + } + if (scale->eval_mode == EVAL_MODE_FRAME || frame_changed) { unsigned vars_w[VARS_NB] = { 0 }, vars_h[VARS_NB] = { 0 }; diff --git a/libavfilter/vf_scale_qsv.c b/libavfilter/vf_scale_qsv.c index 371f62945..da3c2eca8 100644 --- a/libavfilter/vf_scale_qsv.c +++ b/libavfilter/vf_scale_qsv.c @@ -69,7 +69,6 @@ enum var_name { VARS_NB }; -#define QSV_HAVE_SCALING_CONFIG QSV_VERSION_ATLEAST(1, 19) #define MFX_IMPL_VIA_MASK(impl) (0x0f00 & (impl)) typedef struct QSVScaleContext { @@ -92,12 +91,10 @@ typedef struct QSVScaleContext { mfxExtOpaqueSurfaceAlloc opaque_alloc; -#if QSV_HAVE_SCALING_CONFIG mfxExtVPPScaling scale_conf; -#endif int mode; - mfxExtBuffer *ext_buffers[1 + QSV_HAVE_SCALING_CONFIG]; + mfxExtBuffer *ext_buffers[2]; int num_ext_buf; int shift_width, shift_height; @@ -397,14 +394,12 @@ static int init_out_session(AVFilterContext *ctx) par.IOPattern = MFX_IOPATTERN_IN_VIDEO_MEMORY | MFX_IOPATTERN_OUT_VIDEO_MEMORY; } -#if QSV_HAVE_SCALING_CONFIG memset(&s->scale_conf, 0, sizeof(mfxExtVPPScaling)); s->scale_conf.Header.BufferId = MFX_EXTBUFF_VPP_SCALING; s->scale_conf.Header.BufferSz = sizeof(mfxExtVPPScaling); s->scale_conf.ScalingMode = s->mode; s->ext_buffers[s->num_ext_buf++] = (mfxExtBuffer*)&s->scale_conf; av_log(ctx, AV_LOG_VERBOSE, "Scaling mode: %d\n", s->mode); -#endif par.ExtParam = s->ext_buffers; par.NumExtParam = s->num_ext_buf; @@ -620,15 +615,9 @@ static const AVOption options[] = { { "h", "Output video height", OFFSET(h_expr), AV_OPT_TYPE_STRING, { .str = "ih" }, .flags = FLAGS }, { "format", "Output pixel format", OFFSET(format_str), AV_OPT_TYPE_STRING, { .str = "same" }, .flags = FLAGS }, -#if QSV_HAVE_SCALING_CONFIG { "mode", "set scaling mode", OFFSET(mode), AV_OPT_TYPE_INT, { .i64 = MFX_SCALING_MODE_DEFAULT}, MFX_SCALING_MODE_DEFAULT, MFX_SCALING_MODE_QUALITY, FLAGS, "mode"}, { "low_power", "low power mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_LOWPOWER}, INT_MIN, INT_MAX, FLAGS, "mode"}, { "hq", "high quality mode", 0, AV_OPT_TYPE_CONST, { .i64 = MFX_SCALING_MODE_QUALITY}, INT_MIN, INT_MAX, FLAGS, "mode"}, -#else - { "mode", "(not supported)", OFFSET(mode), AV_OPT_TYPE_INT, { .i64 = 0}, 0, INT_MAX, FLAGS, "mode"}, - { "low_power", "", 0, AV_OPT_TYPE_CONST, { .i64 = 1}, 0, 0, FLAGS, "mode"}, - { "hq", "", 0, AV_OPT_TYPE_CONST, { .i64 = 2}, 0, 0, FLAGS, "mode"}, -#endif { NULL }, }; diff --git a/libavfilter/vf_scale_vulkan.c b/libavfilter/vf_scale_vulkan.c index c87a8d7e2..c14042089 100644 --- a/libavfilter/vf_scale_vulkan.c +++ b/libavfilter/vf_scale_vulkan.c @@ -239,29 +239,25 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) RET(ff_vk_init_compute_pipeline(vkctx, s->pl)); if (s->vkctx.output_format != s->vkctx.input_format) { - const struct LumaCoefficients *lcoeffs; + const AVLumaCoefficients *lcoeffs; double tmp_mat[3][3]; struct { float yuv_matrix[4][4]; } *par; - lcoeffs = ff_get_luma_coefficients(in->colorspace); + lcoeffs = av_csp_luma_coeffs_from_avcsp(in->colorspace); if (!lcoeffs) { av_log(ctx, AV_LOG_ERROR, "Unsupported colorspace\n"); return AVERROR(EINVAL); } - err = ff_vk_create_buf(vkctx, &s->params_buf, - sizeof(*par), - VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); - if (err) - return err; + RET(ff_vk_create_buf(vkctx, &s->params_buf, + sizeof(*par), + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)); - err = ff_vk_map_buffers(vkctx, &s->params_buf, (uint8_t **)&par, 1, 0); - if (err) - return err; + RET(ff_vk_map_buffers(vkctx, &s->params_buf, (uint8_t **)&par, 1, 0)); ff_fill_rgb2yuv_table(lcoeffs, tmp_mat); @@ -273,9 +269,7 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) par->yuv_matrix[3][3] = 1.0; - err = ff_vk_unmap_buffers(vkctx, &s->params_buf, 1, 1); - if (err) - return err; + RET(ff_vk_unmap_buffers(vkctx, &s->params_buf, 1, 1)); s->params_desc.buffer = s->params_buf.buf; s->params_desc.range = VK_WHOLE_SIZE; @@ -475,11 +469,7 @@ static int scale_vulkan_config_output(AVFilterLink *outlink) return AVERROR(EINVAL); } - err = ff_vk_filter_config_output(outlink); - if (err < 0) - return err; - - return 0; + return ff_vk_filter_config_output(outlink); } static void scale_vulkan_uninit(AVFilterContext *avctx) diff --git a/libavfilter/vf_setparams.c b/libavfilter/vf_setparams.c index b3893adc1..95a2d15c0 100644 --- a/libavfilter/vf_setparams.c +++ b/libavfilter/vf_setparams.c @@ -18,6 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/pixfmt.h" #include "libavutil/opt.h" #include "avfilter.h" diff --git a/libavfilter/vf_showinfo.c b/libavfilter/vf_showinfo.c index 71728bced..6efcafce2 100644 --- a/libavfilter/vf_showinfo.c +++ b/libavfilter/vf_showinfo.c @@ -32,6 +32,7 @@ #include "libavutil/internal.h" #include "libavutil/film_grain_params.h" #include "libavutil/hdr_dynamic_metadata.h" +#include "libavutil/hdr_dynamic_vivid_metadata.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "libavutil/spherical.h" @@ -41,6 +42,7 @@ #include "libavutil/mastering_display_metadata.h" #include "libavutil/video_enc_params.h" #include "libavutil/detection_bbox.h" +#include "libavutil/uuid.h" #include "avfilter.h" #include "internal.h" @@ -307,6 +309,89 @@ static void dump_dynamic_hdr_plus(AVFilterContext *ctx, AVFrameSideData *sd) } } +static void dump_dynamic_hdr_vivid(AVFilterContext *ctx, AVFrameSideData *sd) +{ + AVDynamicHDRVivid *hdr_vivid; + + av_log(ctx, AV_LOG_INFO, "HDR Vivid metadata: "); + if (sd->size < sizeof(*hdr_vivid)) { + av_log(ctx, AV_LOG_ERROR, "invalid hdr vivid data\n"); + return; + } + + hdr_vivid = (AVDynamicHDRVivid *)sd->data; + av_log(ctx, AV_LOG_INFO, "system_start_code: %d, ", hdr_vivid->system_start_code); + av_log(ctx, AV_LOG_INFO, "num_windows: %d, ", hdr_vivid->num_windows); + for (int w = 0; w < hdr_vivid->num_windows; w++) { + const AVHDRVividColorTransformParams *params = &hdr_vivid->params[w]; + + av_log(ctx, AV_LOG_INFO, "minimum_maxrgb[%d]: %.4f, ", w, av_q2d(params->minimum_maxrgb)); + av_log(ctx, AV_LOG_INFO, "average_maxrgb[%d]: %.4f, ", w, av_q2d(params->average_maxrgb)); + av_log(ctx, AV_LOG_INFO, "variance_maxrgb[%d]:%.4f, ", w, av_q2d(params->variance_maxrgb)); + av_log(ctx, AV_LOG_INFO, "maximum_maxrgb[%d]: %.4f, ", w, av_q2d(params->maximum_maxrgb)); + } + + for (int w = 0; w < hdr_vivid->num_windows; w++) { + const AVHDRVividColorTransformParams *params = &hdr_vivid->params[w]; + + av_log(ctx, AV_LOG_INFO, "tone_mapping_mode_flag[%d]: %d, ", w, params->tone_mapping_mode_flag); + av_log(ctx, AV_LOG_INFO, "tone_mapping_param_num[%d]: %d, ", w, params->tone_mapping_param_num); + if (params->tone_mapping_mode_flag) { + for (int i = 0; i < params->tone_mapping_param_num; i++) { + const AVHDRVividColorToneMappingParams *tm_params = ¶ms->tm_params[i]; + + av_log(ctx, AV_LOG_INFO, "targeted_system_display_maximum_luminance[%d][%d]: %.4f, ", + w, i, av_q2d(tm_params->targeted_system_display_maximum_luminance)); + av_log(ctx, AV_LOG_INFO, "base_enable_flag[%d][%d]: %d, ", + w, i, tm_params->base_enable_flag); + if (tm_params->base_enable_flag) { + av_log(ctx, AV_LOG_INFO, "base_param_m_p[%d][%d]: %.4f, ", w, i, av_q2d(tm_params->base_param_m_p)); + av_log(ctx, AV_LOG_INFO, "base_param_m_m[%d][%d]: %.4f, ", w, i, av_q2d(tm_params->base_param_m_m)); + av_log(ctx, AV_LOG_INFO, "base_param_m_a[%d][%d]: %.4f, ", w, i, av_q2d(tm_params->base_param_m_a)); + av_log(ctx, AV_LOG_INFO, "base_param_m_b[%d][%d]: %.4f, ", w, i, av_q2d(tm_params->base_param_m_b)); + av_log(ctx, AV_LOG_INFO, "base_param_m_n[%d][%d]: %.4f, ", w, i, av_q2d(tm_params->base_param_m_n)); + av_log(ctx, AV_LOG_INFO, "base_param_k1[%d][%d]: %d, ", w, i, tm_params->base_param_k1); + av_log(ctx, AV_LOG_INFO, "base_param_k2[%d][%d]: %d, ", w, i, tm_params->base_param_k2); + av_log(ctx, AV_LOG_INFO, "base_param_k3[%d][%d]: %d, ", w, i, tm_params->base_param_k3); + av_log(ctx, AV_LOG_INFO, "base_param_Delta_enable_mode[%d][%d]: %d, ", w, i, + tm_params->base_param_Delta_enable_mode); + av_log(ctx, AV_LOG_INFO, "base_param_Delta[%d][%d]: %.4f, ", w, i, av_q2d(tm_params->base_param_Delta)); + } + av_log(ctx, AV_LOG_INFO, "3Spline_enable_flag[%d][%d]: %d, ", + w, i, tm_params->three_Spline_enable_flag); + if (tm_params->three_Spline_enable_flag) { + av_log(ctx, AV_LOG_INFO, "3Spline_TH_mode[%d][%d]: %d, ", w, i, tm_params->three_Spline_TH_mode); + + for (int j = 0; j < tm_params->three_Spline_num; j++) { + av_log(ctx, AV_LOG_INFO, "3Spline_TH_enable_MB[%d][%d][%d]: %.4f, ", + w, i, j, av_q2d(tm_params->three_Spline_TH_enable_MB)); + av_log(ctx, AV_LOG_INFO, "3Spline_TH_enable[%d][%d][%d]: %.4f, ", + w, i, j, av_q2d(tm_params->three_Spline_TH_enable)); + av_log(ctx, AV_LOG_INFO, "3Spline_TH_Delta1[%d][%d][%d]: %.4f, ", + w, i, j, av_q2d(tm_params->three_Spline_TH_Delta1)); + av_log(ctx, AV_LOG_INFO, "3Spline_TH_Delta2[%d][%d][%d]: %.4f, ", + w, i, j, av_q2d(tm_params->three_Spline_TH_Delta2)); + av_log(ctx, AV_LOG_INFO, "3Spline_enable_Strength[%d][%d][%d]: %.4f, ", + w, i, j, av_q2d(tm_params->three_Spline_enable_Strength)); + } + } + } + } + + av_log(ctx, AV_LOG_INFO, "color_saturation_mapping_flag[%d]: %d", + w, params->color_saturation_mapping_flag); + if (params->color_saturation_mapping_flag) { + av_log(ctx, AV_LOG_INFO, ", color_saturation_num[%d]: %d", + w, params->color_saturation_num); + for (int i = 0; i < params->color_saturation_num; i++) { + av_log(ctx, AV_LOG_INFO, ", color_saturation_gain[%d][%d]: %.4f", + w, i, av_q2d(params->color_saturation_gain[i])); + } + } + } +} + + static void dump_content_light_metadata(AVFilterContext *ctx, AVFrameSideData *sd) { const AVContentLightMetadata *metadata = (const AVContentLightMetadata *)sd->data; @@ -337,29 +422,20 @@ static void dump_video_enc_params(AVFilterContext *ctx, const AVFrameSideData *s static void dump_sei_unregistered_metadata(AVFilterContext *ctx, const AVFrameSideData *sd) { - const int uuid_size = 16; const uint8_t *user_data = sd->data; - int i; - if (sd->size < uuid_size) { + if (sd->size < AV_UUID_LEN) { av_log(ctx, AV_LOG_ERROR, "invalid data(%"SIZE_SPECIFIER" < " - "UUID(%d-bytes))\n", sd->size, uuid_size); + "UUID(%d-bytes))\n", sd->size, AV_UUID_LEN); return; } av_log(ctx, AV_LOG_INFO, "User Data Unregistered:\n"); - av_log(ctx, AV_LOG_INFO, "UUID="); - for (i = 0; i < uuid_size; i++) { - av_log(ctx, AV_LOG_INFO, "%02x", user_data[i]); - if (i == 3 || i == 5 || i == 7 || i == 9) - av_log(ctx, AV_LOG_INFO, "-"); - } - av_log(ctx, AV_LOG_INFO, "\n"); + av_log(ctx, AV_LOG_INFO, "UUID=" AV_PRI_UUID "\n", AV_UUID_ARG(user_data)); av_log(ctx, AV_LOG_INFO, "User Data="); - for (; i < sd->size; i++) { + for (size_t i = 16; i < sd->size; i++) av_log(ctx, AV_LOG_INFO, "%02x", user_data[i]); - } av_log(ctx, AV_LOG_INFO, "\n"); } @@ -704,6 +780,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) case AV_FRAME_DATA_DYNAMIC_HDR_PLUS: dump_dynamic_hdr_plus(ctx, sd); break; + case AV_FRAME_DATA_DYNAMIC_HDR_VIVID: + dump_dynamic_hdr_vivid(ctx, sd); + break; case AV_FRAME_DATA_CONTENT_LIGHT_LEVEL: dump_content_light_metadata(ctx, sd); break; diff --git a/libavfilter/vf_signature.c b/libavfilter/vf_signature.c index 4ca57ebf1..7d434328b 100644 --- a/libavfilter/vf_signature.c +++ b/libavfilter/vf_signature.c @@ -219,7 +219,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref) dw1 = inlink->w / 32; if (inlink->w % 32) dw2 = dw1 + 1; - denom = (sc->divide) ? dh1 * dh2 * dw1 * dw2 : 1; + denom = (sc->divide) ? dh1 * (int64_t)dh2 * dw1 * dw2 : 1; for (i = 0; i < 32; i++) { rowcount = 0; @@ -245,7 +245,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *picref) } } - denom = (sc->divide) ? 1 : dh1 * dh2 * dw1 * dw2; + denom = (sc->divide) ? 1 : dh1 * (int64_t)dh2 * dw1 * dw2; for (i = 0; i < ELEMENT_COUNT; i++) { const ElemCat* elemcat = elements[i]; @@ -386,7 +386,7 @@ static int xml_export(AVFilterContext *ctx, StreamContext *sc, const char* filen FILE* f; unsigned int pot3[5] = { 3*3*3*3, 3*3*3, 3*3, 3, 1 }; - f = fopen(filename, "w"); + f = avpriv_fopen_utf8(filename, "w"); if (!f) { int err = AVERROR(EINVAL); char buf[128]; @@ -500,7 +500,7 @@ static int binary_export(AVFilterContext *ctx, StreamContext *sc, const char* fi if (!buffer) return AVERROR(ENOMEM); - f = fopen(filename, "wb"); + f = avpriv_fopen_utf8(filename, "wb"); if (!f) { int err = AVERROR(EINVAL); char buf[128]; diff --git a/libavfilter/vf_siti.c b/libavfilter/vf_siti.c new file mode 100644 index 000000000..738affa5e --- /dev/null +++ b/libavfilter/vf_siti.c @@ -0,0 +1,349 @@ +/* + * Copyright (c) 2021 Boris Baracaldo + * Copyright (c) 2022 Thilo Borgmann + * + * 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 + * Calculate Spatial Info (SI) and Temporal Info (TI) scores + */ + +#include + +#include "libavutil/imgutils.h" +#include "libavutil/internal.h" +#include "libavutil/opt.h" + +#include "avfilter.h" +#include "formats.h" +#include "internal.h" +#include "video.h" + +static const int X_FILTER[9] = { + 1, 0, -1, + 2, 0, -2, + 1, 0, -1 +}; + +static const int Y_FILTER[9] = { + 1, 2, 1, + 0, 0, 0, + -1, -2, -1 +}; + +typedef struct SiTiContext { + const AVClass *class; + int pixel_depth; + int width, height; + uint64_t nb_frames; + uint8_t *prev_frame; + float max_si; + float max_ti; + float min_si; + float min_ti; + float sum_si; + float sum_ti; + float *gradient_matrix; + float *motion_matrix; + int full_range; + int print_summary; +} SiTiContext; + +static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, + AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, + AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV422P10, + AV_PIX_FMT_NONE +}; + +static av_cold int init(AVFilterContext *ctx) +{ + // User options but no input data + SiTiContext *s = ctx->priv; + s->max_si = 0; + s->max_ti = 0; + return 0; +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + SiTiContext *s = ctx->priv; + + if (s->print_summary) { + float avg_si = s->sum_si / s->nb_frames; + float avg_ti = s->sum_ti / s->nb_frames; + av_log(ctx, AV_LOG_INFO, + "SITI Summary:\nTotal frames: %"PRId64"\n\n" + "Spatial Information:\nAverage: %f\nMax: %f\nMin: %f\n\n" + "Temporal Information:\nAverage: %f\nMax: %f\nMin: %f\n", + s->nb_frames, avg_si, s->max_si, s->min_si, avg_ti, s->max_ti, s->min_ti + ); + } + + av_freep(&s->prev_frame); + av_freep(&s->gradient_matrix); + av_freep(&s->motion_matrix); +} + +static int config_input(AVFilterLink *inlink) +{ + // Video input data avilable + AVFilterContext *ctx = inlink->dst; + SiTiContext *s = ctx->priv; + int max_pixsteps[4]; + size_t pixel_sz; + size_t data_sz; + size_t gradient_sz; + size_t motion_sz; + + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + av_image_fill_max_pixsteps(max_pixsteps, NULL, desc); + + // free previous buffers in case they are allocated already + av_freep(&s->prev_frame); + av_freep(&s->gradient_matrix); + av_freep(&s->motion_matrix); + + s->pixel_depth = max_pixsteps[0]; + s->width = inlink->w; + s->height = inlink->h; + pixel_sz = s->pixel_depth == 1 ? sizeof(uint8_t) : sizeof(uint16_t); + data_sz = s->width * pixel_sz * s->height; + + s->prev_frame = av_malloc(data_sz); + + gradient_sz = (s->width - 2) * sizeof(float) * (s->height - 2); + s->gradient_matrix = av_malloc(gradient_sz); + + motion_sz = s->width * sizeof(float) * s->height; + s->motion_matrix = av_malloc(motion_sz); + + if (!s->prev_frame || ! s->gradient_matrix || !s->motion_matrix) { + return AVERROR(ENOMEM); + } + + return 0; +} + +// Determine whether the video is in full or limited range. If not defined, assume limited. +static int is_full_range(AVFrame* frame) +{ + // If color range not specified, fallback to pixel format + if (frame->color_range == AVCOL_RANGE_UNSPECIFIED || frame->color_range == AVCOL_RANGE_NB) + return frame->format == AV_PIX_FMT_YUVJ420P || frame->format == AV_PIX_FMT_YUVJ422P; + return frame->color_range == AVCOL_RANGE_JPEG; +} + +// Check frame's color range and convert to full range if needed +static uint16_t convert_full_range(int factor, uint16_t y) +{ + int shift; + int limit_upper; + int full_upper; + int limit_y; + + // For 8 bits, limited range goes from 16 to 235, for 10 bits the range is multiplied by 4 + shift = 16 * factor; + limit_upper = 235 * factor - shift; + full_upper = 256 * factor - 1; + limit_y = fminf(fmaxf(y - shift, 0), limit_upper); + return (full_upper * limit_y / limit_upper); +} + +// Applies sobel convolution +static void convolve_sobel(SiTiContext *s, const uint8_t *src, float *dst, int linesize) +{ + double x_conv_sum; + double y_conv_sum; + float gradient; + int ki; + int kj; + int index; + uint16_t data; + int filter_width = 3; + int filter_size = filter_width * filter_width; + int stride = linesize / s->pixel_depth; + // For 8 bits, limited range goes from 16 to 235, for 10 bits the range is multiplied by 4 + int factor = s->pixel_depth == 1 ? 1 : 4; + + // Dst matrix is smaller than src since we ignore edges that can't be convolved + #define CONVOLVE(bps) \ + { \ + uint##bps##_t *vsrc = (uint##bps##_t*)src; \ + for (int j = 1; j < s->height - 1; j++) { \ + for (int i = 1; i < s->width - 1; i++) { \ + x_conv_sum = 0.0; \ + y_conv_sum = 0.0; \ + for (int k = 0; k < filter_size; k++) { \ + ki = k % filter_width - 1; \ + kj = floor(k / filter_width) - 1; \ + index = (j + kj) * stride + (i + ki); \ + data = s->full_range ? vsrc[index] : convert_full_range(factor, vsrc[index]); \ + x_conv_sum += data * X_FILTER[k]; \ + y_conv_sum += data * Y_FILTER[k]; \ + } \ + gradient = sqrt(x_conv_sum * x_conv_sum + y_conv_sum * y_conv_sum); \ + dst[(j - 1) * (s->width - 2) + (i - 1)] = gradient; \ + } \ + } \ + } + + if (s->pixel_depth == 2) { + CONVOLVE(16); + } else { + CONVOLVE(8); + } +} + +// Calculate pixel difference between current and previous frame, and update previous +static void calculate_motion(SiTiContext *s, const uint8_t *curr, + float *motion_matrix, int linesize) +{ + int stride = linesize / s->pixel_depth; + float motion; + int curr_index; + int prev_index; + uint16_t curr_data; + // For 8 bits, limited range goes from 16 to 235, for 10 bits the range is multiplied by 4 + int factor = s->pixel_depth == 1 ? 1 : 4; + + // Previous frame is already converted to full range + #define CALCULATE(bps) \ + { \ + uint##bps##_t *vsrc = (uint##bps##_t*)curr; \ + uint##bps##_t *vdst = (uint##bps##_t*)s->prev_frame; \ + for (int j = 0; j < s->height; j++) { \ + for (int i = 0; i < s->width; i++) { \ + motion = 0; \ + curr_index = j * stride + i; \ + prev_index = j * s->width + i; \ + curr_data = s->full_range ? vsrc[curr_index] : convert_full_range(factor, vsrc[curr_index]); \ + if (s->nb_frames > 1) \ + motion = curr_data - vdst[prev_index]; \ + vdst[prev_index] = curr_data; \ + motion_matrix[j * s->width + i] = motion; \ + } \ + } \ + } + + if (s->pixel_depth == 2) { + CALCULATE(16); + } else { + CALCULATE(8); + } +} + +static float std_deviation(float *img_metrics, int width, int height) +{ + int size = height * width; + double mean = 0.0; + double sqr_diff = 0; + + for (int j = 0; j < height; j++) + for (int i = 0; i < width; i++) + mean += img_metrics[j * width + i]; + + mean /= size; + + for (int j = 0; j < height; j++) { + for (int i = 0; i < width; i++) { + float mean_diff = img_metrics[j * width + i] - mean; + sqr_diff += (mean_diff * mean_diff); + } + } + sqr_diff = sqr_diff / size; + return sqrt(sqr_diff); +} + +static void set_meta(AVDictionary **metadata, const char *key, float d) +{ + char value[128]; + snprintf(value, sizeof(value), "%0.2f", d); + av_dict_set(metadata, key, value, 0); +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *frame) +{ + AVFilterContext *ctx = inlink->dst; + SiTiContext *s = ctx->priv; + float si; + float ti; + + s->full_range = is_full_range(frame); + s->nb_frames++; + + // Calculate si and ti + convolve_sobel(s, frame->data[0], s->gradient_matrix, frame->linesize[0]); + calculate_motion(s, frame->data[0], s->motion_matrix, frame->linesize[0]); + si = std_deviation(s->gradient_matrix, s->width - 2, s->height - 2); + ti = std_deviation(s->motion_matrix, s->width, s->height); + + // Calculate statistics + s->max_si = fmaxf(si, s->max_si); + s->max_ti = fmaxf(ti, s->max_ti); + s->sum_si += si; + s->sum_ti += ti; + s->min_si = s->nb_frames == 1 ? si : fminf(si, s->min_si); + s->min_ti = s->nb_frames == 1 ? ti : fminf(ti, s->min_ti); + + // Set si ti information in frame metadata + set_meta(&frame->metadata, "lavfi.siti.si", si); + set_meta(&frame->metadata, "lavfi.siti.ti", ti); + + return ff_filter_frame(inlink->dst->outputs[0], frame); +} + +#define OFFSET(x) offsetof(SiTiContext, x) +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM + +static const AVOption siti_options[] = { + { "print_summary", "Print summary showing average values", OFFSET(print_summary), AV_OPT_TYPE_BOOL, { .i64=0 }, 0, 1, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(siti); + +static const AVFilterPad avfilter_vf_siti_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_input, + .filter_frame = filter_frame, + }, +}; + +static const AVFilterPad avfilter_vf_siti_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO + }, +}; + +const AVFilter ff_vf_siti = { + .name = "siti", + .description = NULL_IF_CONFIG_SMALL("Calculate spatial information (SI) and temporal information (TI)."), + .priv_size = sizeof(SiTiContext), + .priv_class = &siti_class, + .init = init, + .uninit = uninit, + .flags = AVFILTER_FLAG_METADATA_ONLY, + FILTER_PIXFMTS_ARRAY(pix_fmts), + FILTER_INPUTS(avfilter_vf_siti_inputs), + FILTER_OUTPUTS(avfilter_vf_siti_outputs), +}; diff --git a/libavfilter/vf_spp.c b/libavfilter/vf_spp.c index 019267690..8442bcc59 100644 --- a/libavfilter/vf_spp.c +++ b/libavfilter/vf_spp.c @@ -343,8 +343,9 @@ static int config_input(AVFilterLink *inlink) av_opt_set_int(s->dct, "bits_per_sample", bps, 0); avcodec_dct_init(s->dct); - if (ARCH_X86) - ff_spp_init_x86(s); +#if ARCH_X86 + ff_spp_init_x86(s); +#endif s->hsub = desc->log2_chroma_w; s->vsub = desc->log2_chroma_h; diff --git a/libavfilter/vf_spp.h b/libavfilter/vf_spp.h index 76c0c34ab..0a8b2b512 100644 --- a/libavfilter/vf_spp.h +++ b/libavfilter/vf_spp.h @@ -22,6 +22,7 @@ #ifndef AVFILTER_SPP_H #define AVFILTER_SPP_H +#include "libavutil/video_enc_params.h" #include "libavcodec/avdct.h" #include "avfilter.h" @@ -33,7 +34,7 @@ typedef struct SPPContext { int log2_count; int qp; int mode; - int qscale_type; + enum AVVideoEncParamsType qscale_type; int temp_linesize; uint8_t *src; uint16_t *temp; diff --git a/libavfilter/vf_sr.c b/libavfilter/vf_sr.c index b07335bc3..0890c8ba1 100644 --- a/libavfilter/vf_sr.c +++ b/libavfilter/vf_sr.c @@ -76,15 +76,15 @@ static int config_output(AVFilterLink *outlink) { AVFilterContext *context = outlink->src; SRContext *ctx = context->priv; - DNNReturnType result; + int result; AVFilterLink *inlink = context->inputs[0]; int out_width, out_height; // have a try run in case that the dnn model resize the frame result = ff_dnn_get_output(&ctx->dnnctx, inlink->w, inlink->h, &out_width, &out_height); - if (result != DNN_SUCCESS) { + if (result != 0) { av_log(ctx, AV_LOG_ERROR, "could not get output from the model\n"); - return AVERROR(EIO); + return result; } if (inlink->w != out_width || inlink->h != out_height) { @@ -121,7 +121,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) SRContext *ctx = context->priv; AVFilterLink *outlink = context->outputs[0]; AVFrame *out = ff_get_video_buffer(outlink, outlink->w, outlink->h); - DNNReturnType dnn_result; + int dnn_result; if (!out){ av_log(context, AV_LOG_ERROR, "could not allocate memory for output frame\n"); @@ -139,11 +139,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) dnn_result = ff_dnn_execute_model(&ctx->dnnctx, in, out); } - if (dnn_result != DNN_SUCCESS){ + if (dnn_result != 0){ av_log(ctx, AV_LOG_ERROR, "failed to execute loaded model\n"); av_frame_free(&in); av_frame_free(&out); - return AVERROR(EIO); + return dnn_result; } do { diff --git a/libavfilter/vf_ssim.c b/libavfilter/vf_ssim.c index 32f313817..37094b23f 100644 --- a/libavfilter/vf_ssim.c +++ b/libavfilter/vf_ssim.c @@ -404,7 +404,7 @@ static av_cold int init(AVFilterContext *ctx) if (!strcmp(s->stats_file_str, "-")) { s->stats_file = stdout; } else { - s->stats_file = fopen(s->stats_file_str, "w"); + s->stats_file = avpriv_fopen_utf8(s->stats_file_str, "w"); if (!s->stats_file) { int err = AVERROR(errno); char buf[128]; @@ -478,8 +478,9 @@ static int config_input_ref(AVFilterLink *inlink) s->ssim_plane = desc->comp[0].depth > 8 ? ssim_plane_16bit : ssim_plane; s->dsp.ssim_4x4_line = ssim_4x4xn_8bit; s->dsp.ssim_end_line = ssim_endn_8bit; - if (ARCH_X86) - ff_ssim_init_x86(&s->dsp); +#if ARCH_X86 + ff_ssim_init_x86(&s->dsp); +#endif s->score = av_calloc(s->nb_threads, sizeof(*s->score)); if (!s->score) diff --git a/libavfilter/vf_stack.c b/libavfilter/vf_stack.c index f584e8349..331dc7b3e 100644 --- a/libavfilter/vf_stack.c +++ b/libavfilter/vf_stack.c @@ -18,6 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/avstring.h" #include "libavutil/imgutils.h" #include "libavutil/opt.h" @@ -46,6 +48,8 @@ typedef struct StackContext { int is_vertical; int is_horizontal; int nb_planes; + int nb_grid_columns; + int nb_grid_rows; uint8_t fillcolor[4]; char *fillcolor_str; int fillcolor_enable; @@ -83,6 +87,34 @@ static av_cold int init(AVFilterContext *ctx) if (!strcmp(ctx->filter->name, "hstack")) s->is_horizontal = 1; + if (!strcmp(ctx->filter->name, "xstack")) { + int is_grid; + if (strcmp(s->fillcolor_str, "none") && + av_parse_color(s->fillcolor, s->fillcolor_str, -1, ctx) >= 0) { + s->fillcolor_enable = 1; + } else { + s->fillcolor_enable = 0; + } + is_grid = s->nb_grid_rows && s->nb_grid_columns; + if (s->layout && is_grid) { + av_log(ctx, AV_LOG_ERROR, "Both layout and grid were specified. Only one is allowed.\n"); + return AVERROR(EINVAL); + } + if (!s->layout && !is_grid) { + if (s->nb_inputs == 2) { + s->nb_grid_rows = 1; + s->nb_grid_columns = 2; + is_grid = 1; + } else { + av_log(ctx, AV_LOG_ERROR, "No layout or grid specified.\n"); + return AVERROR(EINVAL); + } + } + + if (is_grid) + s->nb_inputs = s->nb_grid_rows * s->nb_grid_columns; + } + s->frames = av_calloc(s->nb_inputs, sizeof(*s->frames)); if (!s->frames) return AVERROR(ENOMEM); @@ -91,25 +123,6 @@ static av_cold int init(AVFilterContext *ctx) if (!s->items) return AVERROR(ENOMEM); - if (!strcmp(ctx->filter->name, "xstack")) { - if (strcmp(s->fillcolor_str, "none") && - av_parse_color(s->fillcolor, s->fillcolor_str, -1, ctx) >= 0) { - s->fillcolor_enable = 1; - } else { - s->fillcolor_enable = 0; - } - if (!s->layout) { - if (s->nb_inputs == 2) { - s->layout = av_strdup("0_0|w0_0"); - if (!s->layout) - return AVERROR(ENOMEM); - } else { - av_log(ctx, AV_LOG_ERROR, "No layout specified.\n"); - return AVERROR(EINVAL); - } - } - } - for (i = 0; i < s->nb_inputs; i++) { AVFilterPad pad = { 0 }; @@ -242,6 +255,48 @@ static int config_output(AVFilterLink *outlink) width += ctx->inputs[i]->w; } } + } else if (s->nb_grid_rows && s->nb_grid_columns) { + int inw = 0, inh = 0; + int k = 0; + int row_height; + height = 0; + width = 0; + for (i = 0; i < s->nb_grid_rows; i++, inh += row_height) { + row_height = ctx->inputs[i * s->nb_grid_columns]->h; + inw = 0; + for (int j = 0; j < s->nb_grid_columns; j++, k++) { + AVFilterLink *inlink = ctx->inputs[k]; + StackItem *item = &s->items[k]; + + if (ctx->inputs[k]->h != row_height) { + av_log(ctx, AV_LOG_ERROR, "Input %d height %d does not match current row's height %d.\n", + k, ctx->inputs[k]->h, row_height); + return AVERROR(EINVAL); + } + + if ((ret = av_image_fill_linesizes(item->linesize, inlink->format, inlink->w)) < 0) { + return ret; + } + + item->height[1] = item->height[2] = AV_CEIL_RSHIFT(inlink->h, s->desc->log2_chroma_h); + item->height[0] = item->height[3] = inlink->h; + + if ((ret = av_image_fill_linesizes(item->x, inlink->format, inw)) < 0) { + return ret; + } + + item->y[1] = item->y[2] = AV_CEIL_RSHIFT(inh, s->desc->log2_chroma_h); + item->y[0] = item->y[3] = inh; + inw += ctx->inputs[k]->w; + } + height += row_height; + if (!i) + width = inw; + if (i && width != inw) { + av_log(ctx, AV_LOG_ERROR, "Row %d width %d does not match previous row width %d.\n", i, inw, width); + return AVERROR(EINVAL); + } + } } else { char *arg, *p = s->layout, *saveptr = NULL; char *arg2, *p2, *saveptr2 = NULL; @@ -434,6 +489,7 @@ const AVFilter ff_vf_vstack = { static const AVOption xstack_options[] = { { "inputs", "set number of inputs", OFFSET(nb_inputs), AV_OPT_TYPE_INT, {.i64=2}, 2, INT_MAX, .flags = FLAGS }, { "layout", "set custom layout", OFFSET(layout), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, .flags = FLAGS }, + { "grid", "set fixed size grid layout", OFFSET(nb_grid_columns), AV_OPT_TYPE_IMAGE_SIZE, {.str=NULL}, 0, 0, .flags = FLAGS }, { "shortest", "force termination when the shortest input terminates", OFFSET(shortest), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, .flags = FLAGS }, { "fill", "set the color for unused pixels", OFFSET(fillcolor_str), AV_OPT_TYPE_STRING, {.str = "none"}, .flags = FLAGS }, { NULL }, diff --git a/libavfilter/vf_stereo3d.c b/libavfilter/vf_stereo3d.c index 0ba18861a..71041d2fe 100644 --- a/libavfilter/vf_stereo3d.c +++ b/libavfilter/vf_stereo3d.c @@ -591,8 +591,9 @@ static int config_output(AVFilterLink *outlink) s->vsub = desc->log2_chroma_h; s->dsp.anaglyph = anaglyph; - if (ARCH_X86) - ff_stereo3d_init_x86(&s->dsp); +#if ARCH_X86 + ff_stereo3d_init_x86(&s->dsp); +#endif return 0; } diff --git a/libavfilter/vf_subtitles.c b/libavfilter/vf_subtitles.c index aa5d17b8b..82e140e98 100644 --- a/libavfilter/vf_subtitles.c +++ b/libavfilter/vf_subtitles.c @@ -30,6 +30,7 @@ #include #include "config.h" +#include "config_components.h" #if CONFIG_SUBTITLES_FILTER # include "libavcodec/avcodec.h" # include "libavformat/avformat.h" @@ -274,6 +275,13 @@ static const AVOption subtitles_options[] = { }; static const char * const font_mimetypes[] = { + "font/ttf", + "font/otf", + "font/sfnt", + "font/woff", + "font/woff2", + "application/font-sfnt", + "application/font-woff", "application/x-truetype-font", "application/vnd.ms-opentype", "application/x-font-ttf", diff --git a/libavfilter/vf_swapuv.c b/libavfilter/vf_swapuv.c index 27d083f02..445202826 100644 --- a/libavfilter/vf_swapuv.c +++ b/libavfilter/vf_swapuv.c @@ -25,7 +25,6 @@ #include "libavutil/opt.h" #include "libavutil/pixdesc.h" -#include "libavutil/version.h" #include "avfilter.h" #include "formats.h" #include "internal.h" diff --git a/libavfilter/vf_threshold.c b/libavfilter/vf_threshold.c index 2a0add4a8..dc73c277d 100644 --- a/libavfilter/vf_threshold.c +++ b/libavfilter/vf_threshold.c @@ -32,6 +32,7 @@ #include "internal.h" #include "video.h" #include "threshold.h" +#include "vf_threshold_init.h" #define OFFSET(x) offsetof(ThresholdContext, x) #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM @@ -150,57 +151,6 @@ static int process_frame(FFFrameSync *fs) return ff_filter_frame(outlink, out); } -static void threshold8(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) -{ - int x, y; - - for (y = 0; y < h; y++) { - for (x = 0; x < w; x++) { - out[x] = in[x] < threshold[x] ? min[x] : max[x]; - } - - in += ilinesize; - threshold += tlinesize; - min += flinesize; - max += slinesize; - out += olinesize; - } -} - -static void threshold16(const uint8_t *iin, const uint8_t *tthreshold, - const uint8_t *ffirst, const uint8_t *ssecond, - uint8_t *oout, - ptrdiff_t ilinesize, ptrdiff_t tlinesize, - ptrdiff_t flinesize, ptrdiff_t slinesize, - ptrdiff_t olinesize, - int w, int h) -{ - const uint16_t *in = (const uint16_t *)iin; - const uint16_t *threshold = (const uint16_t *)tthreshold; - const uint16_t *min = (const uint16_t *)ffirst; - const uint16_t *max = (const uint16_t *)ssecond; - uint16_t *out = (uint16_t *)oout; - int x, y; - - for (y = 0; y < h; y++) { - for (x = 0; x < w; x++) { - out[x] = in[x] < threshold[x] ? min[x] : max[x]; - } - - in += ilinesize / 2; - threshold += tlinesize / 2; - min += flinesize / 2; - max += slinesize / 2; - out += olinesize / 2; - } -} - static int config_input(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; @@ -223,20 +173,6 @@ static int config_input(AVFilterLink *inlink) return 0; } -void ff_threshold_init(ThresholdContext *s) -{ - if (s->depth == 8) { - s->threshold = threshold8; - s->bpc = 1; - } else { - s->threshold = threshold16; - s->bpc = 2; - } - - if (ARCH_X86) - ff_threshold_init_x86(s); -} - static int config_output(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; diff --git a/libavfilter/vf_threshold_init.h b/libavfilter/vf_threshold_init.h new file mode 100644 index 000000000..7d160ddbb --- /dev/null +++ b/libavfilter/vf_threshold_init.h @@ -0,0 +1,92 @@ +/* + * 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_INIT_H +#define AVFILTER_THRESHOLD_INIT_H + +#include +#include + +#include "config.h" +#include "libavutil/attributes.h" +#include "threshold.h" + +static void threshold8(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) +{ + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) + out[x] = in[x] < threshold[x] ? min[x] : max[x]; + + in += ilinesize; + threshold += tlinesize; + min += flinesize; + max += slinesize; + out += olinesize; + } +} + +static void threshold16(const uint8_t *iin, const uint8_t *tthreshold, + const uint8_t *ffirst, const uint8_t *ssecond, + uint8_t *oout, + ptrdiff_t ilinesize, ptrdiff_t tlinesize, + ptrdiff_t flinesize, ptrdiff_t slinesize, + ptrdiff_t olinesize, + int w, int h) +{ + const uint16_t *in = (const uint16_t *)iin; + const uint16_t *threshold = (const uint16_t *)tthreshold; + const uint16_t *min = (const uint16_t *)ffirst; + const uint16_t *max = (const uint16_t *)ssecond; + uint16_t *out = (uint16_t *)oout; + + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) + out[x] = in[x] < threshold[x] ? min[x] : max[x]; + + in += ilinesize / 2; + threshold += tlinesize / 2; + min += flinesize / 2; + max += slinesize / 2; + out += olinesize / 2; + } +} + +static av_unused void ff_threshold_init(ThresholdContext *s) +{ + if (s->depth == 8) { + s->threshold = threshold8; + s->bpc = 1; + } else { + s->threshold = threshold16; + s->bpc = 2; + } + +#if ARCH_X86 + ff_threshold_init_x86(s); +#endif +} + +#endif /* AVFILTER_THRESHOLD_INIT_H */ diff --git a/libavfilter/vf_tinterlace.c b/libavfilter/vf_tinterlace.c index cda55a8c7..399adc102 100644 --- a/libavfilter/vf_tinterlace.c +++ b/libavfilter/vf_tinterlace.c @@ -269,15 +269,17 @@ static int config_out_props(AVFilterLink *outlink) tinterlace->lowpass_line = lowpass_line_complex_c_16; else tinterlace->lowpass_line = lowpass_line_complex_c; - if (ARCH_X86) - ff_tinterlace_init_x86(tinterlace); +#if ARCH_X86 + ff_tinterlace_init_x86(tinterlace); +#endif } else if (tinterlace->flags & TINTERLACE_FLAG_VLPF) { if (tinterlace->csp->comp[0].depth > 8) tinterlace->lowpass_line = lowpass_line_c_16; else tinterlace->lowpass_line = lowpass_line_c; - if (ARCH_X86) - ff_tinterlace_init_x86(tinterlace); +#if ARCH_X86 + ff_tinterlace_init_x86(tinterlace); +#endif } av_log(ctx, AV_LOG_VERBOSE, "mode:%d filter:%s h:%d -> h:%d\n", tinterlace->mode, diff --git a/libavfilter/vf_tmidequalizer.c b/libavfilter/vf_tmidequalizer.c index f92c5a90a..b5d497b63 100644 --- a/libavfilter/vf_tmidequalizer.c +++ b/libavfilter/vf_tmidequalizer.c @@ -178,6 +178,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) } else { s->l_frames++; } + if (!s->frames[idx]) + return AVERROR_EOF; in = av_frame_clone(s->frames[idx]); if (!in) return AVERROR(ENOMEM); diff --git a/libavfilter/vf_tonemap.c b/libavfilter/vf_tonemap.c index 1285dbaa4..d1087e6bd 100644 --- a/libavfilter/vf_tonemap.c +++ b/libavfilter/vf_tonemap.c @@ -27,6 +27,7 @@ #include #include +#include "libavutil/csp.h" #include "libavutil/imgutils.h" #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" @@ -50,16 +51,6 @@ enum TonemapAlgorithm { TONEMAP_MAX, }; -static const struct LumaCoefficients luma_coefficients[AVCOL_SPC_NB] = { - [AVCOL_SPC_FCC] = { 0.30, 0.59, 0.11 }, - [AVCOL_SPC_BT470BG] = { 0.299, 0.587, 0.114 }, - [AVCOL_SPC_SMPTE170M] = { 0.299, 0.587, 0.114 }, - [AVCOL_SPC_BT709] = { 0.2126, 0.7152, 0.0722 }, - [AVCOL_SPC_SMPTE240M] = { 0.212, 0.701, 0.087 }, - [AVCOL_SPC_BT2020_NCL] = { 0.2627, 0.6780, 0.0593 }, - [AVCOL_SPC_BT2020_CL] = { 0.2627, 0.6780, 0.0593 }, -}; - typedef struct TonemapContext { const AVClass *class; @@ -68,7 +59,7 @@ typedef struct TonemapContext { double desat; double peak; - const struct LumaCoefficients *coeffs; + const AVLumaCoefficients *coeffs; } TonemapContext; static av_cold int init(AVFilterContext *ctx) @@ -135,7 +126,7 @@ static void tonemap(TonemapContext *s, AVFrame *out, const AVFrame *in, /* desaturate to prevent unnatural colors */ if (s->desat > 0) { - float luma = s->coeffs->cr * *r_in + s->coeffs->cg * *g_in + s->coeffs->cb * *b_in; + float luma = av_q2d(s->coeffs->cr) * *r_in + av_q2d(s->coeffs->cg) * *g_in + av_q2d(s->coeffs->cb) * *b_in; float overbright = FFMAX(luma - s->desat, 1e-6) / FFMAX(luma, 1e-6); *r_out = MIX(*r_in, luma, overbright); *g_out = MIX(*g_in, luma, overbright); @@ -249,7 +240,7 @@ static int filter_frame(AVFilterLink *link, AVFrame *in) } /* load original color space even if pixel format is RGB to compute overbrights */ - s->coeffs = &luma_coefficients[in->colorspace]; + s->coeffs = av_csp_luma_coeffs_from_avcsp(in->colorspace); if (s->desat > 0 && (in->colorspace == AVCOL_SPC_UNSPECIFIED || !s->coeffs)) { if (in->colorspace == AVCOL_SPC_UNSPECIFIED) av_log(s, AV_LOG_WARNING, "Missing color space information, "); diff --git a/libavfilter/vf_tonemap_opencl.c b/libavfilter/vf_tonemap_opencl.c index 121ef7d6f..f6ebb694a 100644 --- a/libavfilter/vf_tonemap_opencl.c +++ b/libavfilter/vf_tonemap_opencl.c @@ -80,16 +80,6 @@ static const char *const delinearize_funcs[AVCOL_TRC_NB] = { [AVCOL_TRC_BT2020_10] = "inverse_eotf_bt1886", }; -static const struct PrimaryCoefficients primaries_table[AVCOL_PRI_NB] = { - [AVCOL_PRI_BT709] = { 0.640, 0.330, 0.300, 0.600, 0.150, 0.060 }, - [AVCOL_PRI_BT2020] = { 0.708, 0.292, 0.170, 0.797, 0.131, 0.046 }, -}; - -static const struct WhitepointCoefficients whitepoint_table[AVCOL_PRI_NB] = { - [AVCOL_PRI_BT709] = { 0.3127, 0.3290 }, - [AVCOL_PRI_BT2020] = { 0.3127, 0.3290 }, -}; - static const char *const tonemap_func[TONEMAP_MAX] = { [TONEMAP_NONE] = "direct", [TONEMAP_LINEAR] = "linear", @@ -100,14 +90,22 @@ static const char *const tonemap_func[TONEMAP_MAX] = { [TONEMAP_MOBIUS] = "mobius", }; -static void get_rgb2rgb_matrix(enum AVColorPrimaries in, enum AVColorPrimaries out, - double rgb2rgb[3][3]) { +static int get_rgb2rgb_matrix(enum AVColorPrimaries in, enum AVColorPrimaries out, + double rgb2rgb[3][3]) { double rgb2xyz[3][3], xyz2rgb[3][3]; - ff_fill_rgb2xyz_table(&primaries_table[out], &whitepoint_table[out], rgb2xyz); + const AVColorPrimariesDesc *in_primaries = av_csp_primaries_desc_from_id(in); + const AVColorPrimariesDesc *out_primaries = av_csp_primaries_desc_from_id(out); + + if (!in_primaries || !out_primaries) + return AVERROR(EINVAL); + + ff_fill_rgb2xyz_table(&out_primaries->prim, &out_primaries->wp, rgb2xyz); ff_matrix_invert_3x3(rgb2xyz, xyz2rgb); - ff_fill_rgb2xyz_table(&primaries_table[in], &whitepoint_table[in], rgb2xyz); + ff_fill_rgb2xyz_table(&in_primaries->prim, &in_primaries->wp, rgb2xyz); ff_matrix_mul_3x3(rgb2rgb, rgb2xyz, xyz2rgb); + + return 0; } #define OPENCL_SOURCE_NB 3 @@ -120,7 +118,7 @@ static int tonemap_opencl_init(AVFilterContext *avctx) TonemapOpenCLContext *ctx = avctx->priv; int rgb2rgb_passthrough = 1; double rgb2rgb[3][3], rgb2yuv[3][3], yuv2rgb[3][3]; - const struct LumaCoefficients *luma_src, *luma_dst; + const AVLumaCoefficients *luma_src, *luma_dst; cl_int cle; int err; AVBPrint header; @@ -184,7 +182,8 @@ static int tonemap_opencl_init(AVFilterContext *avctx) av_bprintf(&header, "#define DETECTION_FRAMES %d\n", DETECTION_FRAMES); if (ctx->primaries_out != ctx->primaries_in) { - get_rgb2rgb_matrix(ctx->primaries_in, ctx->primaries_out, rgb2rgb); + if ((err = get_rgb2rgb_matrix(ctx->primaries_in, ctx->primaries_out, rgb2rgb)) < 0) + goto fail; rgb2rgb_passthrough = 0; } if (ctx->range_in == AVCOL_RANGE_JPEG) @@ -201,7 +200,7 @@ static int tonemap_opencl_init(AVFilterContext *avctx) ff_opencl_print_const_matrix_3x3(&header, "rgb2rgb", rgb2rgb); - luma_src = ff_get_luma_coefficients(ctx->colorspace_in); + luma_src = av_csp_luma_coeffs_from_avcsp(ctx->colorspace_in); if (!luma_src) { err = AVERROR(EINVAL); av_log(avctx, AV_LOG_ERROR, "unsupported input colorspace %d (%s)\n", @@ -209,7 +208,7 @@ static int tonemap_opencl_init(AVFilterContext *avctx) goto fail; } - luma_dst = ff_get_luma_coefficients(ctx->colorspace_out); + luma_dst = av_csp_luma_coeffs_from_avcsp(ctx->colorspace_out); if (!luma_dst) { err = AVERROR(EINVAL); av_log(avctx, AV_LOG_ERROR, "unsupported output colorspace %d (%s)\n", @@ -225,9 +224,9 @@ static int tonemap_opencl_init(AVFilterContext *avctx) ff_opencl_print_const_matrix_3x3(&header, "rgb_matrix", yuv2rgb); av_bprintf(&header, "constant float3 luma_src = {%.4ff, %.4ff, %.4ff};\n", - luma_src->cr, luma_src->cg, luma_src->cb); + av_q2d(luma_src->cr), av_q2d(luma_src->cg), av_q2d(luma_src->cb)); av_bprintf(&header, "constant float3 luma_dst = {%.4ff, %.4ff, %.4ff};\n", - luma_dst->cr, luma_dst->cg, luma_dst->cb); + av_q2d(luma_dst->cr), av_q2d(luma_dst->cg), av_q2d(luma_dst->cb)); av_bprintf(&header, "#define linearize %s\n", linearize_funcs[ctx->trc_in]); av_bprintf(&header, "#define delinearize %s\n", diff --git a/libavfilter/vf_tonemap_vaapi.c b/libavfilter/vf_tonemap_vaapi.c index 5a41f14d0..cd2f4c219 100644 --- a/libavfilter/vf_tonemap_vaapi.c +++ b/libavfilter/vf_tonemap_vaapi.c @@ -294,6 +294,11 @@ static int tonemap_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame if (err < 0) goto fail; + if (vpp_ctx->nb_filter_buffers) { + params.filters = &vpp_ctx->filter_buffers[0]; + params.num_filters = vpp_ctx->nb_filter_buffers; + } + err = ff_vaapi_vpp_render_picture(avctx, ¶ms, output_frame); if (err < 0) goto fail; diff --git a/libavfilter/vf_tpad.c b/libavfilter/vf_tpad.c index e5acece1e..c87047815 100644 --- a/libavfilter/vf_tpad.c +++ b/libavfilter/vf_tpad.c @@ -79,6 +79,18 @@ static int activate(AVFilterContext *ctx) FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); + if (!s->eof && ff_inlink_acknowledge_status(inlink, &status, &pts)) { + if (status == AVERROR_EOF) { + pts = av_rescale_q(pts, inlink->time_base, outlink->time_base); + if (!s->pad_stop && !s->pad_start) { + ff_outlink_set_status(outlink, status, pts); + return 0; + } + s->eof = 1; + s->pts += pts; + } + } + if (s->start_mode == 0 && s->pad_start > 0 && ff_outlink_frame_wanted(outlink)) { frame = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!frame) @@ -93,7 +105,10 @@ static int activate(AVFilterContext *ctx) } if (s->start_mode == 1 && s->pad_start > 0) { - if (!s->cache_start && ff_inlink_queued_frames(inlink)) { + if (s->eof) { + ff_outlink_set_status(outlink, AVERROR_EOF, 0); + return 0; + } else if (!s->cache_start && ff_inlink_queued_frames(inlink)) { s->cache_start = ff_inlink_peek_frame(inlink, 0); } else if (!s->cache_start) { FF_FILTER_FORWARD_WANTED(outlink, inlink); @@ -123,18 +138,6 @@ static int activate(AVFilterContext *ctx) } } - if (!s->eof && ff_inlink_acknowledge_status(inlink, &status, &pts)) { - if (status == AVERROR_EOF) { - pts = av_rescale_q(pts, inlink->time_base, outlink->time_base); - if (!s->pad_stop) { - ff_outlink_set_status(outlink, status, pts); - return 0; - } - s->eof = 1; - s->pts += pts; - } - } - if (s->eof) { if (!s->pad_stop) { ff_outlink_set_status(outlink, AVERROR_EOF, s->pts); @@ -148,6 +151,11 @@ static int activate(AVFilterContext *ctx) frame->data, frame->linesize, 0, 0, frame->width, frame->height); } else if (s->stop_mode == 1) { + if (!s->cache_stop) { + s->pad_stop = 0; + ff_outlink_set_status(outlink, AVERROR_EOF, s->pts); + return 0; + } frame = av_frame_clone(s->cache_stop); if (!frame) return AVERROR(ENOMEM); diff --git a/libavfilter/vf_transpose.c b/libavfilter/vf_transpose.c index b964daeee..469e66729 100644 --- a/libavfilter/vf_transpose.c +++ b/libavfilter/vf_transpose.c @@ -235,13 +235,13 @@ static int config_props_output(AVFilterLink *outlink) } } - if (ARCH_X86) { - for (int i = 0; i < 4; i++) { - TransVtable *v = &s->vtables[i]; +#if ARCH_X86 + for (int i = 0; i < 4; i++) { + TransVtable *v = &s->vtables[i]; - ff_transpose_init_x86(v, s->pixsteps[i]); - } + ff_transpose_init_x86(v, s->pixsteps[i]); } +#endif av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d dir:%d -> w:%d h:%d rotation:%s vflip:%d\n", diff --git a/libavfilter/vf_unsharp.c b/libavfilter/vf_unsharp.c index 9a3104511..e88e732c9 100644 --- a/libavfilter/vf_unsharp.c +++ b/libavfilter/vf_unsharp.c @@ -146,17 +146,18 @@ static int apply_unsharp_c(AVFilterContext *ctx, AVFrame *in, AVFrame *out) { AVFilterLink *inlink = ctx->inputs[0]; UnsharpContext *s = ctx->priv; - int i, plane_w[3], plane_h[3]; - UnsharpFilterParam *fp[3]; + int i, plane_w[4], plane_h[4]; + UnsharpFilterParam *fp[4]; ThreadData td; - plane_w[0] = inlink->w; + plane_w[0] = plane_w[3] = inlink->w; plane_w[1] = plane_w[2] = AV_CEIL_RSHIFT(inlink->w, s->hsub); - plane_h[0] = inlink->h; + plane_h[0] = plane_h[3] = inlink->h; plane_h[1] = plane_h[2] = AV_CEIL_RSHIFT(inlink->h, s->vsub); fp[0] = &s->luma; fp[1] = fp[2] = &s->chroma; - for (i = 0; i < 3; i++) { + fp[3] = &s->alpha; + for (i = 0; i < s->nb_planes; i++) { td.fp = fp[i]; td.dst = out->data[i]; td.src = in->data[i]; @@ -188,9 +189,10 @@ static av_cold int init(AVFilterContext *ctx) 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); + set_filter_param(&s->alpha, s->amsize_x, s->amsize_y, s->aamount); - if (s->luma.scalebits >= 26 || s->chroma.scalebits >= 26) { - av_log(ctx, AV_LOG_ERROR, "luma or chroma matrix size too big\n"); + if (s->luma.scalebits >= 26 || s->chroma.scalebits >= 26 || s->alpha.scalebits >= 26) { + av_log(ctx, AV_LOG_ERROR, "luma or chroma or alpha matrix size too big\n"); return AVERROR(EINVAL); } s->apply_unsharp = apply_unsharp_c; @@ -198,6 +200,10 @@ static av_cold int init(AVFilterContext *ctx) } static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_YUVA422P9, AV_PIX_FMT_YUVA422P10, AV_PIX_FMT_YUVA422P12, AV_PIX_FMT_YUVA422P16, + AV_PIX_FMT_YUVA420P9, AV_PIX_FMT_YUVA420P10, AV_PIX_FMT_YUVA420P16, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUV420P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV444P9, @@ -242,6 +248,7 @@ static int config_input(AVFilterLink *inlink) const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); int ret; + s->nb_planes = desc->nb_components; s->hsub = desc->log2_chroma_w; s->vsub = desc->log2_chroma_h; s->bitdepth = desc->comp[0].depth; @@ -325,7 +332,12 @@ 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", "ignored", OFFSET(opencl), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS }, + { "alpha_msize_x", "set alpha matrix horizontal size", OFFSET(amsize_x), AV_OPT_TYPE_INT, { .i64 = 5 }, MIN_SIZE, MAX_SIZE, FLAGS }, + { "ax", "set alpha matrix horizontal size", OFFSET(amsize_x), AV_OPT_TYPE_INT, { .i64 = 5 }, MIN_SIZE, MAX_SIZE, FLAGS }, + { "alpha_msize_y", "set alpha matrix vertical size", OFFSET(amsize_y), AV_OPT_TYPE_INT, { .i64 = 5 }, MIN_SIZE, MAX_SIZE, FLAGS }, + { "ay", "set alpha matrix vertical size", OFFSET(amsize_y), AV_OPT_TYPE_INT, { .i64 = 5 }, MIN_SIZE, MAX_SIZE, FLAGS }, + { "alpha_amount", "set alpha effect strength", OFFSET(aamount), AV_OPT_TYPE_FLOAT, { .dbl = 0 }, -2, 5, FLAGS }, + { "aa", "set alpha effect strength", OFFSET(aamount), AV_OPT_TYPE_FLOAT, { .dbl = 0 }, -2, 5, FLAGS }, { NULL } }; diff --git a/libavfilter/vf_uspp.c b/libavfilter/vf_uspp.c index c61a2a070..051de0077 100644 --- a/libavfilter/vf_uspp.c +++ b/libavfilter/vf_uspp.c @@ -32,6 +32,7 @@ #include "libavutil/mem_internal.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" +#include "libavutil/video_enc_params.h" #include "libavcodec/avcodec.h" #include "internal.h" #include "qp_table.h" @@ -45,7 +46,7 @@ typedef struct USPPContext { int log2_count; int hsub, vsub; int qp; - int qscale_type; + enum AVVideoEncParamsType qscale_type; int temp_stride[3]; uint8_t *src[3]; uint16_t *temp[3]; diff --git a/libavfilter/vf_v360.c b/libavfilter/vf_v360.c index 9e590a228..2ac9b688d 100644 --- a/libavfilter/vf_v360.c +++ b/libavfilter/vf_v360.c @@ -389,8 +389,9 @@ void ff_v360_init(V360Context *s, int depth) break; } - if (ARCH_X86) - ff_v360_init_x86(s, depth); +#if ARCH_X86 + ff_v360_init_x86(s, depth); +#endif } /** @@ -2941,8 +2942,8 @@ static int xyz_to_fisheye(const V360Context *s, const int visible = -0.5f < uf && uf < 0.5f && -0.5f < vf && vf < 0.5f; int ui, vi; - uf = (uf + 0.5f) * width; - vf = (vf + 0.5f) * height; + uf = scale(uf * 2.f, width); + vf = scale(vf * 2.f, height); ui = floorf(uf); vi = floorf(vf); @@ -3451,7 +3452,7 @@ static int xyz_to_dfisheye(const V360Context *s, const float *vec, int width, int height, int16_t us[4][4], int16_t vs[4][4], float *du, float *dv) { - const float ew = (width - 1) * 0.5f; + const float ew = width * 0.5f; const float eh = height; const float h = hypotf(vec[0], vec[1]); @@ -3468,7 +3469,7 @@ static int xyz_to_dfisheye(const V360Context *s, u_shift = ceilf(ew); } else { u_shift = 0; - uf = ew - uf; + uf = ew - uf - 1.f; } ui = floorf(uf); @@ -3479,7 +3480,7 @@ static int xyz_to_dfisheye(const V360Context *s, for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { - us[i][j] = av_clip(u_shift + ui + j - 1, 0, width - 1); + us[i][j] = u_shift + av_clip(ui + j - 1, 0, ew - 1); vs[i][j] = av_clip( vi + i - 1, 0, height - 1); } } @@ -3676,37 +3677,39 @@ static int xyz_to_barrelsplit(const V360Context *s, } else { const float scalew = s->fin_pad > 0 ? 1.f - s->fin_pad / (width / 3.f) : 1.f - s->in_pad; const float scaleh = s->fin_pad > 0 ? 1.f - s->fin_pad / (height / 4.f) : 1.f - s->in_pad; - int v_offset = 0; ew = width / 3; eh = height / 4; u_shift = 2 * ew; + uf = vec[0] / vec[1] * scalew; + vf = vec[2] / vec[1] * scaleh; + if (theta <= 0.f && theta >= -M_PI_2 && phi <= M_PI_2 && phi >= -M_PI_2) { - uf = -vec[0] / vec[1]; - vf = -vec[2] / vec[1]; + // front top + uf *= -1.0f; + vf = -(vf + 1.f) * scaleh + 1.f; v_shift = 0; - v_offset = -eh; } else if (theta >= 0.f && theta <= M_PI_2 && phi <= M_PI_2 && phi >= -M_PI_2) { - uf = vec[0] / vec[1]; - vf = -vec[2] / vec[1]; + // front bottom + vf = -(vf - 1.f) * scaleh; v_shift = height * 0.25f; } else if (theta <= 0.f && theta >= -M_PI_2) { - uf = vec[0] / vec[1]; - vf = vec[2] / vec[1]; + // back top + vf = (vf - 1.f) * scaleh + 1.f; v_shift = height * 0.5f; - v_offset = -eh; } else { - uf = -vec[0] / vec[1]; - vf = vec[2] / vec[1]; + // back bottom + uf *= -1.0f; + vf = (vf + 1.f) * scaleh; v_shift = height * 0.75f; } - uf = 0.5f * width / 3.f * (uf * scalew + 1.f); - vf = height * 0.25f * (vf * scaleh + 1.f) + v_offset; + uf = 0.5f * width / 3.f * (uf + 1.f); + vf *= height * 0.25f; } ui = floorf(uf); @@ -3742,6 +3745,7 @@ static int barrelsplit_to_xyz(const V360Context *s, const float x = (i + 0.5f) / width; const float y = (j + 0.5f) / height; float l_x, l_y, l_z; + int ret; if (x < 2.f / 3.f) { const float scalew = s->fout_pad > 0 ? 1.f - s->fout_pad / (width * 2.f / 3.f) : 1.f - s->out_pad; @@ -3760,57 +3764,41 @@ static int barrelsplit_to_xyz(const V360Context *s, l_x = cos_theta * sin_phi; l_y = sin_theta; l_z = cos_theta * cos_phi; + + ret = 1; } else { const float scalew = s->fout_pad > 0 ? 1.f - s->fout_pad / (width / 3.f) : 1.f - s->out_pad; const float scaleh = s->fout_pad > 0 ? 1.f - s->fout_pad / (height / 4.f) : 1.f - s->out_pad; - const int face = floorf(y * 4.f); + const float facef = floorf(y * 4.f); + const int face = facef; + const float dir_vert = (face == 1 || face == 3) ? 1.0f : -1.0f; float uf, vf; uf = x * 3.f - 2.f; switch (face) { - case 0: - vf = y * 2.f; + case 0: // front top + case 1: // front bottom uf = 1.f - uf; - vf = 0.5f - vf; - - l_x = (0.5f - uf) / scalew; - l_y = -0.5f; - l_z = (0.5f - vf) / scaleh; + vf = (0.5f - 2.f * y) / scaleh + facef; break; - case 1: - vf = y * 2.f; - uf = 1.f - uf; - vf = 1.f - (vf - 0.5f); - - l_x = (0.5f - uf) / scalew; - l_y = 0.5f; - l_z = (-0.5f + vf) / scaleh; - break; - case 2: - vf = y * 2.f - 0.5f; - vf = 1.f - (1.f - vf); - - l_x = (0.5f - uf) / scalew; - l_y = -0.5f; - l_z = (0.5f - vf) / scaleh; - break; - case 3: - vf = y * 2.f - 1.5f; - - l_x = (0.5f - uf) / scalew; - l_y = 0.5f; - l_z = (-0.5f + vf) / scaleh; + case 2: // back top + case 3: // back bottom + vf = (y * 2.f - 1.5f) / scaleh + 3.f - facef; break; } + l_x = (0.5f - uf) / scalew; + l_y = 0.5f * dir_vert; + l_z = (vf - 0.5f) * dir_vert / scaleh; + ret = (l_x * l_x * scalew * scalew + l_z * l_z * scaleh * scaleh) < 0.5f * 0.5f; } vec[0] = l_x; vec[1] = l_y; vec[2] = l_z; - return 1; + return ret; } /** @@ -4239,7 +4227,7 @@ static void set_dimensions(int *outw, int *outh, int w, int h, const AVPixFmtDes } // Calculate remap data -static av_always_inline int v360_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +static int v360_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) { V360Context *s = ctx->priv; SliceXYRemap *r = &s->slice_remap[jobnr]; diff --git a/libavfilter/vf_vectorscope.c b/libavfilter/vf_vectorscope.c index 2aec09157..6a45b1146 100644 --- a/libavfilter/vf_vectorscope.c +++ b/libavfilter/vf_vectorscope.c @@ -85,6 +85,7 @@ typedef struct VectorscopeContext { #define OFFSET(x) offsetof(VectorscopeContext, x) #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +#define TFLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption vectorscope_options[] = { { "mode", "set vectorscope mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, MODE_NB-1, FLAGS, "mode"}, @@ -98,29 +99,29 @@ static const AVOption vectorscope_options[] = { { "color5", 0, 0, AV_OPT_TYPE_CONST, {.i64=COLOR5}, 0, 0, FLAGS, "mode" }, { "x", "set color component on X axis", OFFSET(x), AV_OPT_TYPE_INT, {.i64=1}, 0, 2, FLAGS}, { "y", "set color component on Y axis", OFFSET(y), AV_OPT_TYPE_INT, {.i64=2}, 0, 2, FLAGS}, - { "intensity", "set intensity", OFFSET(fintensity), AV_OPT_TYPE_FLOAT, {.dbl=0.004}, 0, 1, FLAGS}, - { "i", "set intensity", OFFSET(fintensity), AV_OPT_TYPE_FLOAT, {.dbl=0.004}, 0, 1, FLAGS}, - { "envelope", "set envelope", OFFSET(envelope), AV_OPT_TYPE_INT, {.i64=0}, 0, 3, FLAGS, "envelope"}, - { "e", "set envelope", OFFSET(envelope), AV_OPT_TYPE_INT, {.i64=0}, 0, 3, FLAGS, "envelope"}, - { "none", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "envelope" }, - { "instant", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "envelope" }, - { "peak", 0, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "envelope" }, - { "peak+instant", 0, 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, FLAGS, "envelope" }, + { "intensity", "set intensity", OFFSET(fintensity), AV_OPT_TYPE_FLOAT, {.dbl=0.004}, 0, 1, TFLAGS}, + { "i", "set intensity", OFFSET(fintensity), AV_OPT_TYPE_FLOAT, {.dbl=0.004}, 0, 1, TFLAGS}, + { "envelope", "set envelope", OFFSET(envelope), AV_OPT_TYPE_INT, {.i64=0}, 0, 3, TFLAGS, "envelope"}, + { "e", "set envelope", OFFSET(envelope), AV_OPT_TYPE_INT, {.i64=0}, 0, 3, TFLAGS, "envelope"}, + { "none", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, TFLAGS, "envelope" }, + { "instant", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, TFLAGS, "envelope" }, + { "peak", 0, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, TFLAGS, "envelope" }, + { "peak+instant", 0, 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, TFLAGS, "envelope" }, { "graticule", "set graticule", OFFSET(graticule), AV_OPT_TYPE_INT, {.i64=GRAT_NONE}, 0, NB_GRATICULES-1, FLAGS, "graticule"}, { "g", "set graticule", OFFSET(graticule), AV_OPT_TYPE_INT, {.i64=GRAT_NONE}, 0, NB_GRATICULES-1, FLAGS, "graticule"}, { "none", 0, 0, AV_OPT_TYPE_CONST, {.i64=GRAT_NONE}, 0, 0, FLAGS, "graticule" }, { "green", 0, 0, AV_OPT_TYPE_CONST, {.i64=GRAT_GREEN}, 0, 0, FLAGS, "graticule" }, { "color", 0, 0, AV_OPT_TYPE_CONST, {.i64=GRAT_COLOR}, 0, 0, FLAGS, "graticule" }, { "invert", 0, 0, AV_OPT_TYPE_CONST, {.i64=GRAT_INVERT},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=4}, 0, 7, FLAGS, "flags"}, - { "f", "set graticule flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=4}, 0, 7, FLAGS, "flags"}, - { "white", "draw white point", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "flags" }, - { "black", "draw black point", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "flags" }, - { "name", "draw point name", 0, AV_OPT_TYPE_CONST, {.i64=4}, 0, 0, FLAGS, "flags" }, - { "bgopacity", "set background opacity", OFFSET(bgopacity), AV_OPT_TYPE_FLOAT, {.dbl=0.3}, 0, 1, FLAGS}, - { "b", "set background opacity", OFFSET(bgopacity), AV_OPT_TYPE_FLOAT, {.dbl=0.3}, 0, 1, FLAGS}, + { "opacity", "set graticule opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, TFLAGS}, + { "o", "set graticule opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, TFLAGS}, + { "flags", "set graticule flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=4}, 0, 7, TFLAGS, "flags"}, + { "f", "set graticule flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=4}, 0, 7, TFLAGS, "flags"}, + { "white", "draw white point", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, TFLAGS, "flags" }, + { "black", "draw black point", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, TFLAGS, "flags" }, + { "name", "draw point name", 0, AV_OPT_TYPE_CONST, {.i64=4}, 0, 0, TFLAGS, "flags" }, + { "bgopacity", "set background opacity", OFFSET(bgopacity), AV_OPT_TYPE_FLOAT, {.dbl=0.3}, 0, 1, TFLAGS}, + { "b", "set background opacity", OFFSET(bgopacity), AV_OPT_TYPE_FLOAT, {.dbl=0.3}, 0, 1, TFLAGS}, { "lthreshold", "set low threshold", OFFSET(lthreshold), AV_OPT_TYPE_FLOAT, {.dbl=0}, 0, 1, FLAGS}, { "l", "set low threshold", OFFSET(lthreshold), AV_OPT_TYPE_FLOAT, {.dbl=0}, 0, 1, FLAGS}, { "hthreshold", "set high threshold", OFFSET(hthreshold), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 1, FLAGS}, @@ -130,10 +131,10 @@ static const AVOption vectorscope_options[] = { { "auto", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "colorspace" }, { "601", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "colorspace" }, { "709", 0, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "colorspace" }, - { "tint0", "set 1st tint", OFFSET(ftint[0]), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, FLAGS}, - { "t0", "set 1st tint", OFFSET(ftint[0]), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, FLAGS}, - { "tint1", "set 2nd tint", OFFSET(ftint[1]), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, FLAGS}, - { "t1", "set 2nd tint", OFFSET(ftint[1]), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, FLAGS}, + { "tint0", "set 1st tint", OFFSET(ftint[0]), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, TFLAGS}, + { "t0", "set 1st tint", OFFSET(ftint[0]), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, TFLAGS}, + { "tint1", "set 2nd tint", OFFSET(ftint[1]), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, TFLAGS}, + { "t1", "set 2nd tint", OFFSET(ftint[1]), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, TFLAGS}, { NULL } }; @@ -272,7 +273,6 @@ static int config_output(AVFilterLink *outlink) VectorscopeContext *s = outlink->src->priv; int i; - s->intensity = s->fintensity * (s->size - 1); outlink->h = outlink->w = s->size; outlink->sample_aspect_ratio = (AVRational){1,1}; @@ -1442,6 +1442,13 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) AVFrame *out; int plane; + s->bg_color[3] = s->bgopacity * (s->size - 1); + + s->tint[0] = .5f * (s->ftint[0] + 1.f) * (s->size - 1); + s->tint[1] = .5f * (s->ftint[1] + 1.f) * (s->size - 1); + + s->intensity = s->fintensity * (s->size - 1); + if (s->colorspace) { s->cs = (s->depth - 8) * 2 + s->colorspace - 1; } else { @@ -1529,11 +1536,6 @@ static int config_input(AVFilterLink *inlink) s->graticulef = invert_graticule16; } - s->bg_color[3] = s->bgopacity * (s->size - 1); - - s->tint[0] = .5f * (s->ftint[0] + 1.f) * (s->size - 1); - s->tint[1] = .5f * (s->ftint[1] + 1.f) * (s->size - 1); - switch (inlink->format) { case AV_PIX_FMT_GBRP12: case AV_PIX_FMT_GBRP10: @@ -1594,4 +1596,5 @@ const AVFilter ff_vf_vectorscope = { FILTER_INPUTS(inputs), FILTER_OUTPUTS(outputs), FILTER_QUERY_FUNC(query_formats), + .process_command = ff_filter_process_command, }; diff --git a/libavfilter/vf_vidstabdetect.c b/libavfilter/vf_vidstabdetect.c index 267a62ea9..044911ec2 100644 --- a/libavfilter/vf_vidstabdetect.c +++ b/libavfilter/vf_vidstabdetect.c @@ -126,7 +126,7 @@ static int config_input(AVFilterLink *inlink) av_log(ctx, AV_LOG_INFO, " show = %d\n", s->conf.show); av_log(ctx, AV_LOG_INFO, " result = %s\n", s->result); - s->f = fopen(s->result, "w"); + s->f = avpriv_fopen_utf8(s->result, "w"); if (s->f == NULL) { av_log(ctx, AV_LOG_ERROR, "cannot open transform file %s\n", s->result); return AVERROR(EINVAL); diff --git a/libavfilter/vf_vidstabtransform.c b/libavfilter/vf_vidstabtransform.c index 4619e9b25..de303554c 100644 --- a/libavfilter/vf_vidstabtransform.c +++ b/libavfilter/vf_vidstabtransform.c @@ -191,7 +191,7 @@ static int config_input(AVFilterLink *inlink) av_log(ctx, AV_LOG_INFO, " zoomspeed = %g\n", tc->conf.zoomSpeed); av_log(ctx, AV_LOG_INFO, " interpol = %s\n", getInterpolationTypeName(tc->conf.interpolType)); - f = fopen(tc->input, "r"); + f = avpriv_fopen_utf8(tc->input, "r"); if (!f) { int ret = AVERROR(errno); av_log(ctx, AV_LOG_ERROR, "cannot open input file %s\n", tc->input); diff --git a/libavfilter/vf_vmafmotion.c b/libavfilter/vf_vmafmotion.c index 8b7e9b17e..6ae968f7e 100644 --- a/libavfilter/vf_vmafmotion.c +++ b/libavfilter/vf_vmafmotion.c @@ -312,7 +312,7 @@ static av_cold int init(AVFilterContext *ctx) if (!strcmp(s->stats_file_str, "-")) { s->stats_file = stdout; } else { - s->stats_file = fopen(s->stats_file_str, "w"); + s->stats_file = avpriv_fopen_utf8(s->stats_file_str, "w"); if (!s->stats_file) { int err = AVERROR(errno); char buf[128]; diff --git a/libavfilter/vf_vpp_qsv.c b/libavfilter/vf_vpp_qsv.c index 5c96703fd..4a053f914 100644 --- a/libavfilter/vf_vpp_qsv.c +++ b/libavfilter/vf_vpp_qsv.c @@ -34,8 +34,6 @@ #include "internal.h" #include "avfilter.h" #include "filters.h" -#include "libavcodec/avcodec.h" -#include "libavformat/avformat.h" #include "qsvvpp.h" #include "transpose.h" @@ -45,9 +43,6 @@ /* number of video enhancement filters */ #define ENH_FILTERS_COUNT (8) -#define QSV_HAVE_ROTATION QSV_VERSION_ATLEAST(1, 17) -#define QSV_HAVE_MIRRORING QSV_VERSION_ATLEAST(1, 19) -#define QSV_HAVE_SCALING_CONFIG QSV_VERSION_ATLEAST(1, 19) typedef struct VPPContext{ const AVClass *class; @@ -62,9 +57,7 @@ typedef struct VPPContext{ mfxExtVPPProcAmp procamp_conf; mfxExtVPPRotation rotation_conf; mfxExtVPPMirroring mirroring_conf; -#ifdef QSV_HAVE_SCALING_CONFIG mfxExtVPPScaling scale_conf; -#endif int out_width; int out_height; @@ -140,9 +133,7 @@ static const AVOption options[] = { { "height", "Output video height", OFFSET(oh), AV_OPT_TYPE_STRING, { .str="w*ch/cw" }, 0, 255, .flags = FLAGS }, { "format", "Output pixel format", OFFSET(output_format_str), AV_OPT_TYPE_STRING, { .str = "same" }, .flags = FLAGS }, { "async_depth", "Internal parallelization depth, the higher the value the higher the latency.", OFFSET(async_depth), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, .flags = FLAGS }, -#ifdef QSV_HAVE_SCALING_CONFIG { "scale_mode", "scale mode: 0=auto, 1=low power, 2=high quality", OFFSET(scale_mode), AV_OPT_TYPE_INT, { .i64 = MFX_SCALING_MODE_DEFAULT }, MFX_SCALING_MODE_DEFAULT, MFX_SCALING_MODE_QUALITY, .flags = FLAGS, "scale mode" }, -#endif { NULL } }; @@ -424,84 +415,83 @@ static int config_output(AVFilterLink *outlink) } if (vpp->transpose >= 0) { -#ifdef QSV_HAVE_ROTATION - switch (vpp->transpose) { - case TRANSPOSE_CCLOCK_FLIP: - vpp->rotate = MFX_ANGLE_270; - vpp->hflip = MFX_MIRRORING_HORIZONTAL; - break; - case TRANSPOSE_CLOCK: - vpp->rotate = MFX_ANGLE_90; - vpp->hflip = MFX_MIRRORING_DISABLED; - break; - case TRANSPOSE_CCLOCK: - vpp->rotate = MFX_ANGLE_270; - vpp->hflip = MFX_MIRRORING_DISABLED; - break; - case TRANSPOSE_CLOCK_FLIP: - vpp->rotate = MFX_ANGLE_90; - vpp->hflip = MFX_MIRRORING_HORIZONTAL; - break; - case TRANSPOSE_REVERSAL: - vpp->rotate = MFX_ANGLE_180; - vpp->hflip = MFX_MIRRORING_DISABLED; - break; - case TRANSPOSE_HFLIP: - vpp->rotate = MFX_ANGLE_0; - vpp->hflip = MFX_MIRRORING_HORIZONTAL; - break; - case TRANSPOSE_VFLIP: - vpp->rotate = MFX_ANGLE_180; - vpp->hflip = MFX_MIRRORING_HORIZONTAL; - break; - default: - av_log(ctx, AV_LOG_ERROR, "Failed to set transpose mode to %d.\n", vpp->transpose); - return AVERROR(EINVAL); + if (QSV_RUNTIME_VERSION_ATLEAST(mfx_version, 1, 17)) { + switch (vpp->transpose) { + case TRANSPOSE_CCLOCK_FLIP: + vpp->rotate = MFX_ANGLE_270; + vpp->hflip = MFX_MIRRORING_HORIZONTAL; + break; + case TRANSPOSE_CLOCK: + vpp->rotate = MFX_ANGLE_90; + vpp->hflip = MFX_MIRRORING_DISABLED; + break; + case TRANSPOSE_CCLOCK: + vpp->rotate = MFX_ANGLE_270; + vpp->hflip = MFX_MIRRORING_DISABLED; + break; + case TRANSPOSE_CLOCK_FLIP: + vpp->rotate = MFX_ANGLE_90; + vpp->hflip = MFX_MIRRORING_HORIZONTAL; + break; + case TRANSPOSE_REVERSAL: + vpp->rotate = MFX_ANGLE_180; + vpp->hflip = MFX_MIRRORING_DISABLED; + break; + case TRANSPOSE_HFLIP: + vpp->rotate = MFX_ANGLE_0; + vpp->hflip = MFX_MIRRORING_HORIZONTAL; + break; + case TRANSPOSE_VFLIP: + vpp->rotate = MFX_ANGLE_180; + vpp->hflip = MFX_MIRRORING_HORIZONTAL; + break; + default: + av_log(ctx, AV_LOG_ERROR, "Failed to set transpose mode to %d.\n", vpp->transpose); + return AVERROR(EINVAL); + } + } else { + av_log(ctx, AV_LOG_WARNING, "The QSV VPP transpose option is " + "not supported with this MSDK version.\n"); + vpp->transpose = 0; } -#else - av_log(ctx, AV_LOG_WARNING, "The QSV VPP transpose option is " - "not supported with this MSDK version.\n"); - vpp->transpose = 0; -#endif } if (vpp->rotate) { -#ifdef QSV_HAVE_ROTATION - memset(&vpp->rotation_conf, 0, sizeof(mfxExtVPPRotation)); - vpp->rotation_conf.Header.BufferId = MFX_EXTBUFF_VPP_ROTATION; - vpp->rotation_conf.Header.BufferSz = sizeof(mfxExtVPPRotation); - vpp->rotation_conf.Angle = vpp->rotate; + if (QSV_RUNTIME_VERSION_ATLEAST(mfx_version, 1, 17)) { + memset(&vpp->rotation_conf, 0, sizeof(mfxExtVPPRotation)); + vpp->rotation_conf.Header.BufferId = MFX_EXTBUFF_VPP_ROTATION; + vpp->rotation_conf.Header.BufferSz = sizeof(mfxExtVPPRotation); + vpp->rotation_conf.Angle = vpp->rotate; - if (MFX_ANGLE_90 == vpp->rotate || MFX_ANGLE_270 == vpp->rotate) { - FFSWAP(int, vpp->out_width, vpp->out_height); - FFSWAP(int, outlink->w, outlink->h); - av_log(ctx, AV_LOG_DEBUG, "Swap width and height for clock/cclock rotation.\n"); + if (MFX_ANGLE_90 == vpp->rotate || MFX_ANGLE_270 == vpp->rotate) { + FFSWAP(int, vpp->out_width, vpp->out_height); + FFSWAP(int, outlink->w, outlink->h); + av_log(ctx, AV_LOG_DEBUG, "Swap width and height for clock/cclock rotation.\n"); + } + + param.ext_buf[param.num_ext_buf++] = (mfxExtBuffer*)&vpp->rotation_conf; + } else { + av_log(ctx, AV_LOG_WARNING, "The QSV VPP rotate option is " + "not supported with this MSDK version.\n"); + vpp->rotate = 0; } - - param.ext_buf[param.num_ext_buf++] = (mfxExtBuffer*)&vpp->rotation_conf; -#else - av_log(ctx, AV_LOG_WARNING, "The QSV VPP rotate option is " - "not supported with this MSDK version.\n"); - vpp->rotate = 0; -#endif } if (vpp->hflip) { -#ifdef QSV_HAVE_MIRRORING - memset(&vpp->mirroring_conf, 0, sizeof(mfxExtVPPMirroring)); - vpp->mirroring_conf.Header.BufferId = MFX_EXTBUFF_VPP_MIRRORING; - vpp->mirroring_conf.Header.BufferSz = sizeof(mfxExtVPPMirroring); - vpp->mirroring_conf.Type = vpp->hflip; + if (QSV_RUNTIME_VERSION_ATLEAST(mfx_version, 1, 19)) { + memset(&vpp->mirroring_conf, 0, sizeof(mfxExtVPPMirroring)); + vpp->mirroring_conf.Header.BufferId = MFX_EXTBUFF_VPP_MIRRORING; + vpp->mirroring_conf.Header.BufferSz = sizeof(mfxExtVPPMirroring); + vpp->mirroring_conf.Type = vpp->hflip; - param.ext_buf[param.num_ext_buf++] = (mfxExtBuffer*)&vpp->mirroring_conf; -#else - av_log(ctx, AV_LOG_WARNING, "The QSV VPP hflip option is " - "not supported with this MSDK version.\n"); - vpp->hflip = 0; -#endif + param.ext_buf[param.num_ext_buf++] = (mfxExtBuffer*)&vpp->mirroring_conf; + } else { + av_log(ctx, AV_LOG_WARNING, "The QSV VPP hflip option is " + "not supported with this MSDK version.\n"); + vpp->hflip = 0; + } } -#ifdef QSV_HAVE_SCALING_CONFIG if (inlink->w != outlink->w || inlink->h != outlink->h) { if (QSV_RUNTIME_VERSION_ATLEAST(mfx_version, 1, 19)) { memset(&vpp->scale_conf, 0, sizeof(mfxExtVPPScaling)); @@ -514,7 +504,6 @@ static int config_output(AVFilterLink *outlink) av_log(ctx, AV_LOG_WARNING, "The QSV VPP Scale option is " "not supported with this MSDK version.\n"); } -#endif if (vpp->use_frc || vpp->use_crop || vpp->deinterlace || vpp->denoise || vpp->detail || vpp->procamp || vpp->rotate || vpp->hflip || @@ -558,15 +547,17 @@ static int activate(AVFilterContext *ctx) qsv->eof = s->eof; ret = ff_qsvvpp_filter_frame(qsv, inlink, in); av_frame_free(&in); + if (ret == AVERROR(EAGAIN)) + goto not_ready; + else if (ret < 0) + return ret; - if (s->eof) { - ff_outlink_set_status(outlink, status, pts); - return 0; - } + if (s->eof) + goto eof; if (qsv->got_frame) { qsv->got_frame = 0; - return ret; + return 0; } } } else { @@ -575,18 +566,27 @@ static int activate(AVFilterContext *ctx) in->pts = av_rescale_q(in->pts, inlink->time_base, outlink->time_base); ret = ff_filter_frame(outlink, in); - return ret; + if (ret < 0) + return ret; + + if (s->eof) + goto eof; + + return 0; } } - if (s->eof) { - ff_outlink_set_status(outlink, status, pts); - return 0; - } else { - FF_FILTER_FORWARD_WANTED(outlink, inlink); - } +not_ready: + if (s->eof) + goto eof; + + FF_FILTER_FORWARD_WANTED(outlink, inlink); return FFERROR_NOT_READY; + +eof: + ff_outlink_set_status(outlink, status, pts); + return 0; } static int query_formats(AVFilterContext *ctx) diff --git a/libavfilter/vf_w3fdif.c b/libavfilter/vf_w3fdif.c index 41a45ea06..512c8070c 100644 --- a/libavfilter/vf_w3fdif.c +++ b/libavfilter/vf_w3fdif.c @@ -317,18 +317,22 @@ static int config_input(AVFilterLink *inlink) s->dsp.filter_scale = filter16_scale; } - if (ARCH_X86) - ff_w3fdif_init_x86(&s->dsp, depth); +#if ARCH_X86 + ff_w3fdif_init_x86(&s->dsp, depth); +#endif return 0; } static int config_output(AVFilterLink *outlink) { - AVFilterLink *inlink = outlink->src->inputs[0]; + AVFilterContext *ctx = outlink->src; + AVFilterLink *inlink = ctx->inputs[0]; + W3FDIFContext *s = ctx->priv; outlink->time_base = av_mul_q(inlink->time_base, (AVRational){1, 2}); - outlink->frame_rate = av_mul_q(inlink->frame_rate, (AVRational){2, 1}); + if (s->mode) + outlink->frame_rate = av_mul_q(inlink->frame_rate, (AVRational){2, 1}); return 0; } diff --git a/libavfilter/vf_waveform.c b/libavfilter/vf_waveform.c index 33a3ac08d..37eb0679d 100644 --- a/libavfilter/vf_waveform.c +++ b/libavfilter/vf_waveform.c @@ -135,14 +135,15 @@ typedef struct WaveformContext { #define OFFSET(x) offsetof(WaveformContext, x) #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM +#define TFLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption waveform_options[] = { { "mode", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, "mode" }, { "m", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS, "mode" }, { "row", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "mode" }, { "column", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "mode" }, - { "intensity", "set intensity", OFFSET(fintensity), AV_OPT_TYPE_FLOAT, {.dbl=0.04}, 0, 1, FLAGS }, - { "i", "set intensity", OFFSET(fintensity), AV_OPT_TYPE_FLOAT, {.dbl=0.04}, 0, 1, FLAGS }, + { "intensity", "set intensity", OFFSET(fintensity), AV_OPT_TYPE_FLOAT, {.dbl=0.04}, 0, 1, TFLAGS }, + { "i", "set intensity", OFFSET(fintensity), AV_OPT_TYPE_FLOAT, {.dbl=0.04}, 0, 1, TFLAGS }, { "mirror", "set mirroring", OFFSET(mirror), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS }, { "r", "set mirroring", OFFSET(mirror), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS }, { "display", "set display mode", OFFSET(display), AV_OPT_TYPE_INT, {.i64=STACK}, 0, NB_DISPLAYS-1, FLAGS, "display" }, @@ -152,12 +153,12 @@ static const AVOption waveform_options[] = { { "parade", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PARADE}, 0, 0, FLAGS, "display" }, { "components", "set components to display", OFFSET(pcomp), AV_OPT_TYPE_INT, {.i64=1}, 1, 15, FLAGS }, { "c", "set components to display", OFFSET(pcomp), AV_OPT_TYPE_INT, {.i64=1}, 1, 15, FLAGS }, - { "envelope", "set envelope to display", OFFSET(envelope), AV_OPT_TYPE_INT, {.i64=0}, 0, 3, FLAGS, "envelope" }, - { "e", "set envelope to display", OFFSET(envelope), AV_OPT_TYPE_INT, {.i64=0}, 0, 3, FLAGS, "envelope" }, - { "none", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "envelope" }, - { "instant", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "envelope" }, - { "peak", NULL, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "envelope" }, - { "peak+instant", NULL, 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, FLAGS, "envelope" }, + { "envelope", "set envelope to display", OFFSET(envelope), AV_OPT_TYPE_INT, {.i64=0}, 0, 3, TFLAGS, "envelope" }, + { "e", "set envelope to display", OFFSET(envelope), AV_OPT_TYPE_INT, {.i64=0}, 0, 3, TFLAGS, "envelope" }, + { "none", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, TFLAGS, "envelope" }, + { "instant", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, TFLAGS, "envelope" }, + { "peak", NULL, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, TFLAGS, "envelope" }, + { "peak+instant", NULL, 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, TFLAGS, "envelope" }, { "filter", "set filter", OFFSET(filter), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_FILTERS-1, FLAGS, "filter" }, { "f", "set filter", OFFSET(filter), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_FILTERS-1, FLAGS, "filter" }, { "lowpass", NULL, 0, AV_OPT_TYPE_CONST, {.i64=LOWPASS}, 0, 0, FLAGS, "filter" }, @@ -174,23 +175,23 @@ static const AVOption waveform_options[] = { { "green", NULL, 0, AV_OPT_TYPE_CONST, {.i64=GRAT_GREEN}, 0, 0, FLAGS, "graticule" }, { "orange", NULL, 0, AV_OPT_TYPE_CONST, {.i64=GRAT_ORANGE}, 0, 0, FLAGS, "graticule" }, { "invert", NULL, 0, AV_OPT_TYPE_CONST, {.i64=GRAT_INVERT}, 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" }, - { "fl", "set graticule flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=1}, 0, 3, FLAGS, "flags" }, - { "numbers", "draw numbers", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "flags" }, - { "dots", "draw dots instead of lines", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "flags" }, + { "opacity", "set graticule opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, TFLAGS }, + { "o", "set graticule opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, TFLAGS }, + { "flags", "set graticule flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=1}, 0, 3, TFLAGS, "flags" }, + { "fl", "set graticule flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=1}, 0, 3, TFLAGS, "flags" }, + { "numbers", "draw numbers", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, TFLAGS, "flags" }, + { "dots", "draw dots instead of lines", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, TFLAGS, "flags" }, { "scale", "set scale", OFFSET(scale), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_SCALES-1, FLAGS, "scale" }, { "s", "set scale", OFFSET(scale), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_SCALES-1, FLAGS, "scale" }, { "digital", NULL, 0, AV_OPT_TYPE_CONST, {.i64=DIGITAL}, 0, 0, FLAGS, "scale" }, { "millivolts", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MILLIVOLTS}, 0, 0, FLAGS, "scale" }, { "ire", NULL, 0, AV_OPT_TYPE_CONST, {.i64=IRE}, 0, 0, FLAGS, "scale" }, - { "bgopacity", "set background opacity", OFFSET(bgopacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS }, - { "b", "set background opacity", OFFSET(bgopacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS }, - { "tint0", "set 1st tint", OFFSET(ftint[0]), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, FLAGS}, - { "t0", "set 1st tint", OFFSET(ftint[0]), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, FLAGS}, - { "tint1", "set 2nd tint", OFFSET(ftint[1]), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, FLAGS}, - { "t1", "set 2nd tint", OFFSET(ftint[1]), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, FLAGS}, + { "bgopacity", "set background opacity", OFFSET(bgopacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, TFLAGS }, + { "b", "set background opacity", OFFSET(bgopacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, TFLAGS }, + { "tint0", "set 1st tint", OFFSET(ftint[0]), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, TFLAGS}, + { "t0", "set 1st tint", OFFSET(ftint[0]), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, TFLAGS}, + { "tint1", "set 2nd tint", OFFSET(ftint[1]), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, TFLAGS}, + { "t1", "set 2nd tint", OFFSET(ftint[1]), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, TFLAGS}, { "fitmode", "set fit mode", OFFSET(fitmode), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_FITMODES-1, FLAGS, "fitmode" }, { "fm", "set fit mode", OFFSET(fitmode), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_FITMODES-1, FLAGS, "fitmode" }, { "none", NULL, 0, AV_OPT_TYPE_CONST, {.i64=FM_NONE}, 0, 0, FLAGS, "fitmode" }, @@ -881,7 +882,7 @@ static av_always_inline void lowpass(WaveformContext *s, dst_data += dst_linesize * step; } - if (s->display != OVERLAY && column && !s->rgb) { + if (s->display != OVERLAY && column && !s->rgb && out->data[1] && out->data[2]) { const int bg = s->bg_color[0]; const int dst_h = 256; const int t0 = s->tint[0]; @@ -905,7 +906,7 @@ static av_always_inline void lowpass(WaveformContext *s, dst0 += dst_linesize; dst1 += dst_linesize; } - } else if (s->display != OVERLAY && !s->rgb) { + } else if (s->display != OVERLAY && !s->rgb && out->data[1] && out->data[2]) { const int bg = s->bg_color[0]; const int dst_w = 256; const int t0 = s->tint[0]; @@ -3049,7 +3050,6 @@ static int config_input(AVFilterLink *inlink) s->ncomp = s->desc->nb_components; s->bits = s->desc->comp[0].depth; s->max = 1 << s->bits; - s->intensity = s->fintensity * (s->max - 1); s->shift_w[0] = s->shift_w[3] = 0; s->shift_h[0] = s->shift_h[3] = 0; @@ -3290,9 +3290,6 @@ static int config_input(AVFilterLink *inlink) s->size = s->size << (s->bits - 8); - s->tint[0] = .5f * (s->ftint[0] + 1.f) * (s->size - 1); - s->tint[1] = .5f * (s->ftint[1] + 1.f) * (s->size - 1); - switch (inlink->format) { case AV_PIX_FMT_GBRAP: case AV_PIX_FMT_GBRP: @@ -3306,8 +3303,6 @@ static int config_input(AVFilterLink *inlink) memcpy(s->bg_color, black_yuva_color, sizeof(s->bg_color)); } - s->bg_color[3] *= s->bgopacity; - return 0; } @@ -3394,13 +3389,16 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) AVFrame *out; int i, j, k; + s->intensity = s->fintensity * (s->max - 1); + s->bg_color[3] = s->bgopacity * (s->max - 1); + s->tint[0] = .5f * (s->ftint[0] + 1.f) * (s->size - 1); + s->tint[1] = .5f * (s->ftint[1] + 1.f) * (s->size - 1); + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) { av_frame_free(&in); return AVERROR(ENOMEM); } - out->pts = in->pts; - out->color_range = AVCOL_RANGE_JPEG; for (k = 0; k < s->dcomp; k++) { if (s->bits <= 8) { @@ -3484,6 +3482,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) } s->graticulef(s, out); + av_frame_copy_props(out, in); + out->color_range = AVCOL_RANGE_JPEG; av_frame_free(&in); out->sample_aspect_ratio = outlink->sample_aspect_ratio; return ff_filter_frame(outlink, out); @@ -3523,4 +3523,5 @@ const AVFilter ff_vf_waveform = { FILTER_OUTPUTS(outputs), FILTER_QUERY_FUNC(query_formats), .flags = AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, }; diff --git a/libavfilter/vf_xfade.c b/libavfilter/vf_xfade.c index 7f3abe776..9f6692736 100644 --- a/libavfilter/vf_xfade.c +++ b/libavfilter/vf_xfade.c @@ -74,6 +74,8 @@ enum XFadeTransitions { SQUEEZEH, SQUEEZEV, ZOOMIN, + FADEFAST, + FADESLOW, NB_TRANSITIONS, }; @@ -193,6 +195,8 @@ static const AVOption xfade_options[] = { { "squeezeh", "squeeze h transition", 0, AV_OPT_TYPE_CONST, {.i64=SQUEEZEH}, 0, 0, FLAGS, "transition" }, { "squeezev", "squeeze v transition", 0, AV_OPT_TYPE_CONST, {.i64=SQUEEZEV}, 0, 0, FLAGS, "transition" }, { "zoomin", "zoom in transition", 0, AV_OPT_TYPE_CONST, {.i64=ZOOMIN}, 0, 0, FLAGS, "transition" }, + { "fadefast", "fast fade transition", 0, AV_OPT_TYPE_CONST, {.i64=FADEFAST}, 0, 0, FLAGS, "transition" }, + { "fadeslow", "slow fade transition", 0, AV_OPT_TYPE_CONST, {.i64=FADESLOW}, 0, 0, FLAGS, "transition" }, { "duration", "set cross fade duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64=1000000}, 0, 60000000, FLAGS }, { "offset", "set cross fade start relative to first input stream", OFFSET(offset), AV_OPT_TYPE_DURATION, {.i64=0}, INT64_MIN, INT64_MAX, FLAGS }, { "expr", "set expression for custom transition", OFFSET(custom_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, @@ -429,7 +433,7 @@ static void slideleft##name##_transition(AVFilterContext *ctx, for (int x = 0; x < width; x++) { \ const int zx = z + x; \ const int zz = zx % width + width * (zx < 0); \ - dst[x] = (zx > 0) && (zx < width) ? xf1[zz] : xf0[zz]; \ + dst[x] = (zx >= 0) && (zx < width) ? xf1[zz] : xf0[zz]; \ } \ \ dst += out->linesize[p] / div; \ @@ -462,7 +466,7 @@ static void slideright##name##_transition(AVFilterContext *ctx, for (int x = 0; x < out->width; x++) { \ const int zx = z + x; \ const int zz = zx % width + width * (zx < 0); \ - dst[x] = (zx > 0) && (zx < width) ? xf1[zz] : xf0[zz]; \ + dst[x] = (zx >= 0) && (zx < width) ? xf1[zz] : xf0[zz]; \ } \ \ dst += out->linesize[p] / div; \ @@ -495,7 +499,7 @@ static void slideup##name##_transition(AVFilterContext *ctx, const type *xf1 = (const type *)(b->data[p] + zz * b->linesize[p]); \ \ for (int x = 0; x < out->width; x++) { \ - dst[x] = (zy > 0) && (zy < height) ? xf1[x] : xf0[x]; \ + dst[x] = (zy >= 0) && (zy < height) ? xf1[x] : xf0[x]; \ } \ \ dst += out->linesize[p] / div; \ @@ -526,7 +530,7 @@ static void slidedown##name##_transition(AVFilterContext *ctx, const type *xf1 = (const type *)(b->data[p] + zz * b->linesize[p]); \ \ for (int x = 0; x < out->width; x++) { \ - dst[x] = (zy > 0) && (zy < height) ? xf1[x] : xf0[x]; \ + dst[x] = (zy >= 0) && (zy < height) ? xf1[x] : xf0[x]; \ } \ \ dst += out->linesize[p] / div; \ @@ -1670,6 +1674,70 @@ static void zoomin##name##_transition(AVFilterContext *ctx, ZOOMIN_TRANSITION(8, uint8_t, 1) ZOOMIN_TRANSITION(16, uint16_t, 2) +#define FADEFAST_TRANSITION(name, type, div) \ +static void fadefast##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int height = slice_end - slice_start; \ + const float imax = 1.f / s->max_value; \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ + \ + for (int y = 0; y < height; y++) { \ + for (int x = 0; x < out->width; x++) { \ + dst[x] = mix(xf0[x], xf1[x], powf(progress, 1.f + \ + logf(1.f+FFABS(xf0[x]-xf1[x])*imax)\ + )); \ + } \ + \ + dst += out->linesize[p] / div; \ + xf0 += a->linesize[p] / div; \ + xf1 += b->linesize[p] / div; \ + } \ + } \ +} + +FADEFAST_TRANSITION(8, uint8_t, 1) +FADEFAST_TRANSITION(16, uint16_t, 2) + +#define FADESLOW_TRANSITION(name, type, div) \ +static void fadeslow##name##_transition(AVFilterContext *ctx, \ + const AVFrame *a, const AVFrame *b, AVFrame *out, \ + float progress, \ + int slice_start, int slice_end, int jobnr) \ +{ \ + XFadeContext *s = ctx->priv; \ + const int height = slice_end - slice_start; \ + const float imax = 1.f / s->max_value; \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + const type *xf0 = (const type *)(a->data[p] + slice_start * a->linesize[p]); \ + const type *xf1 = (const type *)(b->data[p] + slice_start * b->linesize[p]); \ + type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ + \ + for (int y = 0; y < height; y++) { \ + for (int x = 0; x < out->width; x++) { \ + dst[x] = mix(xf0[x], xf1[x], powf(progress, 1.f + \ + logf(2.f-FFABS(xf0[x]-xf1[x])*imax)\ + )); \ + } \ + \ + dst += out->linesize[p] / div; \ + xf0 += a->linesize[p] / div; \ + xf1 += b->linesize[p] / div; \ + } \ + } \ +} + +FADESLOW_TRANSITION(8, uint8_t, 1) +FADESLOW_TRANSITION(16, uint16_t, 2) + static inline double getpix(void *priv, double x, double y, int plane, int nb) { XFadeContext *s = priv; @@ -1816,6 +1884,8 @@ static int config_output(AVFilterLink *outlink) case SQUEEZEH: s->transitionf = s->depth <= 8 ? squeezeh8_transition : squeezeh16_transition; break; case SQUEEZEV: s->transitionf = s->depth <= 8 ? squeezev8_transition : squeezev16_transition; break; case ZOOMIN: s->transitionf = s->depth <= 8 ? zoomin8_transition : zoomin16_transition; break; + case FADEFAST: s->transitionf = s->depth <= 8 ? fadefast8_transition : fadefast16_transition; break; + case FADESLOW: s->transitionf = s->depth <= 8 ? fadeslow8_transition : fadeslow16_transition; break; default: return AVERROR_BUG; } diff --git a/libavfilter/vf_xmedian.c b/libavfilter/vf_xmedian.c index f9dc0f7ec..7f7f3de12 100644 --- a/libavfilter/vf_xmedian.c +++ b/libavfilter/vf_xmedian.c @@ -18,6 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/avstring.h" #include "libavutil/imgutils.h" #include "libavutil/intreadwrite.h" @@ -36,6 +38,7 @@ typedef struct XMedianContext { const AVPixFmtDescriptor *desc; int nb_inputs; int nb_frames; + int nb_threads; int planes; float percentile; @@ -45,10 +48,13 @@ typedef struct XMedianContext { int depth; int max; int nb_planes; - int linesize[4]; + int linesizes[4]; int width[4]; int height[4]; + uint8_t **data; + int *linesize; + AVFrame **frames; FFFrameSync fs; @@ -107,99 +113,87 @@ typedef struct ThreadData { AVFrame **in, *out; } ThreadData; -static int comparei(const void *p1, const void *p2) +static int compare8(const void *p1, const void *p2) { - int left = *(const int *)p1; - int right = *(const int *)p2; + int left = *(const uint8_t *)p1; + int right = *(const uint8_t *)p2; return FFDIFFSIGN(left, right); } -static int median_frames16(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +static int compare16(const void *p1, const void *p2) { - XMedianContext *s = ctx->priv; - ThreadData *td = arg; - AVFrame **in = td->in; - AVFrame *out = td->out; - const int nb_inputs = s->nb_inputs; - const int radius = s->radius; - const int index = s->index; - int values[256]; - - for (int p = 0; p < s->nb_planes; p++) { - const int slice_start = (s->height[p] * jobnr) / nb_jobs; - const int slice_end = (s->height[p] * (jobnr+1)) / nb_jobs; - uint16_t *dst = (uint16_t *)(out->data[p] + slice_start * out->linesize[p]); - - if (!((1 << p) & s->planes)) { - av_image_copy_plane((uint8_t *)dst, out->linesize[p], - in[radius]->data[p] + slice_start * in[radius]->linesize[p], - in[radius]->linesize[p], - s->linesize[p], slice_end - slice_start); - continue; - } - - for (int y = slice_start; y < slice_end; y++) { - for (int x = 0; x < s->width[p]; x++) { - for (int i = 0; i < nb_inputs; i++) { - const uint16_t *src = (const uint16_t *)(in[i]->data[p] + y * in[i]->linesize[p]); - values[i] = src[x]; - } - - AV_QSORT(values, nb_inputs, int, comparei); - if (nb_inputs & 1) - dst[x] = values[index]; - else - dst[x] = (values[index] + values[index - 1]) >> 1; - } - - dst += out->linesize[p] / 2; - } - } - - return 0; + int left = *(const uint16_t *)p1; + int right = *(const uint16_t *)p2; + return FFDIFFSIGN(left, right); } -static int median_frames8(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +#define MEDIAN_SLICE(name, type, comparei) \ +static int median_frames ## name(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \ +{ \ + XMedianContext *s = ctx->priv; \ + ThreadData *td = arg; \ + AVFrame **in = td->in; \ + AVFrame *out = td->out; \ + const int nb_inputs = s->nb_inputs; \ + uint8_t **srcf = s->data + jobnr * nb_inputs; \ + int *linesize = s->linesize + jobnr * nb_inputs; \ + const int radius = s->radius; \ + const int index = s->index; \ + type values[256]; \ + \ + for (int p = 0; p < s->nb_planes; p++) { \ + const int slice_start = (s->height[p] * jobnr) / nb_jobs; \ + const int slice_end = (s->height[p] * (jobnr+1)) / nb_jobs; \ + const int width = s->width[p]; \ + type *dst = (type *)(out->data[p] + slice_start * out->linesize[p]); \ + ptrdiff_t dst_linesize = out->linesize[p] / sizeof(type); \ + \ + if (!((1 << p) & s->planes)) { \ + av_image_copy_plane((uint8_t *)dst, out->linesize[p], \ + in[radius]->data[p] + slice_start * in[radius]->linesize[p], \ + in[radius]->linesize[p], \ + s->linesizes[p], slice_end - slice_start); \ + continue; \ + } \ + \ + for (int i = 0; i < nb_inputs; i++) \ + linesize[i] = in[i]->linesize[p]; \ + \ + for (int i = 0; i < nb_inputs; i++) \ + srcf[i] = in[i]->data[p] + slice_start * linesize[i]; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + for (int x = 0; x < width; x++) { \ + for (int i = 0; i < nb_inputs; i++) { \ + const type *src = (const type *)srcf[i]; \ + values[i] = src[x]; \ + } \ + \ + AV_QSORT(values, nb_inputs, type, comparei); \ + if (nb_inputs & 1) \ + dst[x] = values[index]; \ + else \ + dst[x] = (values[index] + values[index - 1]) >> 1; \ + } \ + \ + dst += dst_linesize; \ + for (int i = 0; i < nb_inputs; i++) \ + srcf[i] += linesize[i]; \ + } \ + } \ + \ + return 0; \ +} + +MEDIAN_SLICE(8, uint8_t, compare8) +MEDIAN_SLICE(16, uint16_t, compare16) + +static void update_index(XMedianContext *s) { - XMedianContext *s = ctx->priv; - ThreadData *td = arg; - AVFrame **in = td->in; - AVFrame *out = td->out; - const int nb_inputs = s->nb_inputs; - const int radius = s->radius; - const int index = s->index; - int values[256]; - - for (int p = 0; p < s->nb_planes; p++) { - const int slice_start = (s->height[p] * jobnr) / nb_jobs; - const int slice_end = (s->height[p] * (jobnr+1)) / nb_jobs; - uint8_t *dst = out->data[p] + slice_start * out->linesize[p]; - - if (!((1 << p) & s->planes)) { - av_image_copy_plane(dst, out->linesize[p], - in[radius]->data[p] + slice_start * in[radius]->linesize[p], - in[radius]->linesize[p], - s->linesize[p], slice_end - slice_start); - continue; - } - - for (int y = slice_start; y < slice_end; y++) { - for (int x = 0; x < s->width[p]; x++) { - for (int i = 0; i < nb_inputs; i++) - values[i] = in[i]->data[p][y * in[i]->linesize[p] + x]; - - AV_QSORT(values, nb_inputs, int, comparei); - if (nb_inputs & 1) - dst[x] = values[index]; - else - dst[x] = (values[index] + values[index - 1]) >> 1; - } - - dst += out->linesize[p]; - } - } - - return 0; + if (s->nb_inputs & 1) + s->index = s->radius * 2.f * s->percentile; + else + s->index = av_clip(s->radius * 2.f * s->percentile, 1, s->nb_inputs - 1); } static int process_frame(FFFrameSync *fs) @@ -212,6 +206,8 @@ static int process_frame(FFFrameSync *fs) ThreadData td; int i, ret; + update_index(s); + for (i = 0; i < s->nb_inputs; i++) { if ((ret = ff_framesync_get_frame(&s->fs, i, &in[i], 0)) < 0) return ret; @@ -230,7 +226,7 @@ static int process_frame(FFFrameSync *fs) td.in = in; td.out = out; ff_filter_execute(ctx, s->median_frames, &td, NULL, - FFMIN(s->height[1], ff_filter_get_nb_threads(ctx))); + FFMIN(s->height[1], s->nb_threads)); } return ff_filter_frame(outlink, out); @@ -261,13 +257,14 @@ static int config_output(AVFilterLink *outlink) s->nb_planes = av_pix_fmt_count_planes(outlink->format); s->depth = s->desc->comp[0].depth; s->max = (1 << s->depth) - 1; + s->nb_threads = ff_filter_get_nb_threads(ctx); if (s->depth <= 8) s->median_frames = median_frames8; else s->median_frames = median_frames16; - if ((ret = av_image_fill_linesizes(s->linesize, inlink->format, inlink->w)) < 0) + if ((ret = av_image_fill_linesizes(s->linesizes, inlink->format, inlink->w)) < 0) return ret; s->width[1] = s->width[2] = AV_CEIL_RSHIFT(inlink->w, s->desc->log2_chroma_w); @@ -275,6 +272,14 @@ static int config_output(AVFilterLink *outlink) s->height[1] = s->height[2] = AV_CEIL_RSHIFT(inlink->h, s->desc->log2_chroma_h); s->height[0] = s->height[3] = inlink->h; + s->data = av_calloc(s->nb_threads * s->nb_inputs, sizeof(*s->data)); + if (!s->data) + return AVERROR(ENOMEM); + + s->linesize = av_calloc(s->nb_threads * s->nb_inputs, sizeof(*s->linesize)); + if (!s->linesize) + return AVERROR(ENOMEM); + if (!s->xmedian) return 0; @@ -314,6 +319,8 @@ static av_cold void uninit(AVFilterContext *ctx) for (int i = 0; i < s->nb_frames && s->frames && !s->xmedian; i++) av_frame_free(&s->frames[i]); av_freep(&s->frames); + av_freep(&s->data); + av_freep(&s->linesize); } static int activate(AVFilterContext *ctx) @@ -322,24 +329,6 @@ static int activate(AVFilterContext *ctx) return ff_framesync_activate(&s->fs); } -static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, - char *res, int res_len, int flags) -{ - XMedianContext *s = ctx->priv; - int ret; - - ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); - if (ret < 0) - return ret; - - if (s->nb_inputs & 1) - s->index = s->radius * 2.f * s->percentile; - else - s->index = av_clip(s->radius * 2.f * s->percentile, 1, s->nb_inputs - 1); - - return 0; -} - #if CONFIG_XMEDIAN_FILTER static av_cold int xmedian_init(AVFilterContext *ctx) { @@ -399,7 +388,7 @@ const AVFilter ff_vf_xmedian = { .activate = activate, .flags = AVFILTER_FLAG_DYNAMIC_INPUTS | AVFILTER_FLAG_SLICE_THREADS | AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, - .process_command = process_command, + .process_command = ff_filter_process_command, }; #endif /* CONFIG_XMEDIAN_FILTER */ @@ -413,6 +402,8 @@ static int tmedian_filter_frame(AVFilterLink *inlink, AVFrame *in) ThreadData td; AVFrame *out; + update_index(s); + if (s->nb_frames < s->nb_inputs) { s->frames[s->nb_frames] = in; s->nb_frames++; @@ -439,7 +430,7 @@ static int tmedian_filter_frame(AVFilterLink *inlink, AVFrame *in) td.out = out; td.in = s->frames; ff_filter_execute(ctx, s->median_frames, &td, NULL, - FFMIN(s->height[0], ff_filter_get_nb_threads(ctx))); + FFMIN(s->height[1], s->nb_threads)); return ff_filter_frame(outlink, out); } @@ -480,7 +471,7 @@ const AVFilter ff_vf_tmedian = { .init = init, .uninit = uninit, .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, - .process_command = process_command, + .process_command = ff_filter_process_command, }; #endif /* CONFIG_TMEDIAN_FILTER */ diff --git a/libavfilter/vf_yadif.c b/libavfilter/vf_yadif.c index 21f6c8544..afa4d1d53 100644 --- a/libavfilter/vf_yadif.c +++ b/libavfilter/vf_yadif.c @@ -311,8 +311,9 @@ static int config_output(AVFilterLink *outlink) s->filter_edges = filter_edges; } - if (ARCH_X86) - ff_yadif_init_x86(s); +#if ARCH_X86 + ff_yadif_init_x86(s); +#endif return 0; } diff --git a/libavfilter/vf_yadif_videotoolbox.m b/libavfilter/vf_yadif_videotoolbox.m index 455745817..69186c225 100644 --- a/libavfilter/vf_yadif_videotoolbox.m +++ b/libavfilter/vf_yadif_videotoolbox.m @@ -440,7 +440,7 @@ static const AVFilterPad yadif_videotoolbox_outputs[] = { }, }; -AVFilter ff_vf_yadif_videotoolbox = { +const AVFilter ff_vf_yadif_videotoolbox = { .name = "yadif_videotoolbox", .description = NULL_IF_CONFIG_SMALL("YADIF for VideoToolbox frames using Metal compute"), .priv_size = YADIF_VT_CTX_SIZE, diff --git a/libavfilter/vf_zscale.c b/libavfilter/vf_zscale.c index 1288c5efc..91166dcbc 100644 --- a/libavfilter/vf_zscale.c +++ b/libavfilter/vf_zscale.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2015 Paul B Mahol + * Copyright (c) 2022 Victoria Zhislina, Intel * * This file is part of FFmpeg. * @@ -43,7 +44,9 @@ #include "libavutil/pixdesc.h" #include "libavutil/imgutils.h" -#define ZIMG_ALIGNMENT 32 +#define ZIMG_ALIGNMENT 64 +#define MIN_TILESIZE 64 +#define MAX_THREADS 64 static const char *const var_names[] = { "in_w", "iw", @@ -111,15 +114,24 @@ typedef struct ZScaleContext { int in_h_chr_pos; int in_v_chr_pos; + int first_time; int force_original_aspect_ratio; - void *tmp; - size_t tmp_size; + void *tmp[MAX_THREADS]; //separate for each thread; + int nb_threads; + int jobs_ret[MAX_THREADS]; + double in_slice_start[MAX_THREADS]; + double in_slice_end[MAX_THREADS]; + int out_slice_start[MAX_THREADS]; + int out_slice_end[MAX_THREADS]; zimg_image_format src_format, dst_format; zimg_image_format alpha_src_format, alpha_dst_format; + zimg_image_format src_format_tmp, dst_format_tmp; + zimg_image_format alpha_src_format_tmp, alpha_dst_format_tmp; zimg_graph_builder_params alpha_params, params; - zimg_filter_graph *alpha_graph, *graph; + zimg_graph_builder_params alpha_params_tmp, params_tmp; + zimg_filter_graph *alpha_graph[MAX_THREADS], *graph[MAX_THREADS]; enum AVColorSpace in_colorspace, out_colorspace; enum AVColorTransferCharacteristic in_trc, out_trc; @@ -128,10 +140,29 @@ typedef struct ZScaleContext { enum AVChromaLocation in_chromal, out_chromal; } ZScaleContext; +typedef struct ThreadData { + const AVPixFmtDescriptor *desc, *odesc; + AVFrame *in, *out; +} ThreadData; + static av_cold int init(AVFilterContext *ctx) { ZScaleContext *s = ctx->priv; int ret; + zimg_image_format_default(&s->src_format, ZIMG_API_VERSION); + zimg_image_format_default(&s->dst_format, ZIMG_API_VERSION); + zimg_image_format_default(&s->src_format_tmp, ZIMG_API_VERSION); + zimg_image_format_default(&s->dst_format_tmp, ZIMG_API_VERSION); + + zimg_image_format_default(&s->alpha_src_format, ZIMG_API_VERSION); + zimg_image_format_default(&s->alpha_dst_format, ZIMG_API_VERSION); + zimg_image_format_default(&s->alpha_src_format_tmp, ZIMG_API_VERSION); + zimg_image_format_default(&s->alpha_dst_format_tmp, ZIMG_API_VERSION); + + zimg_graph_builder_params_default(&s->params, ZIMG_API_VERSION); + zimg_graph_builder_params_default(&s->params_tmp, ZIMG_API_VERSION); + zimg_graph_builder_params_default(&s->alpha_params, ZIMG_API_VERSION); + zimg_graph_builder_params_default(&s->alpha_params_tmp, ZIMG_API_VERSION); if (s->size_str && (s->w_expr || s->h_expr)) { av_log(ctx, AV_LOG_ERROR, @@ -194,6 +225,21 @@ static int query_formats(AVFilterContext *ctx) return ff_formats_ref(ff_make_format_list(pixel_fmts), &ctx->outputs[0]->incfg.formats); } +static void slice_params(ZScaleContext *s, int out_h, int in_h) +{ + s->out_slice_start[0] = 0; + for (int i = 1; i < s->nb_threads; i++) { + int slice_end = out_h * i / s->nb_threads; + s->out_slice_end[i - 1] = s->out_slice_start[i] = FFALIGN(slice_end, 2); + } + s->out_slice_end[s->nb_threads - 1] = out_h; + + for (int i = 0; i < s->nb_threads; i++) { + s->in_slice_start[i] = s->out_slice_start[i] * in_h / (double)out_h; + s->in_slice_end[i] = s->out_slice_end[i] * in_h / (double)out_h; + } +} + static int config_props(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; @@ -290,12 +336,7 @@ static int config_props(AVFilterLink *outlink) outlink->w = w; outlink->h = h; - if (inlink->w == outlink->w && - inlink->h == outlink->h && - inlink->format == outlink->format) - ; - else { - } + s->first_time = 1; 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); @@ -471,6 +512,51 @@ static enum AVColorRange convert_range_from_zimg(enum zimg_pixel_range_e color_r return AVCOL_RANGE_UNSPECIFIED; } +/* returns 0 if image formats are the same and 1 otherwise */ +static int compare_zimg_image_formats(zimg_image_format *img_fmt0, zimg_image_format *img_fmt1) +{ + return ((img_fmt0->chroma_location != img_fmt1->chroma_location) || +#if ZIMG_API_VERSION >= 0x204 + (img_fmt0->alpha != img_fmt1->alpha) || +#endif + (img_fmt0->color_family != img_fmt1->color_family) || + (img_fmt0->color_primaries != img_fmt1->color_primaries) || + (img_fmt0->depth != img_fmt1->depth) || + (img_fmt0->field_parity != img_fmt1->field_parity) || + (img_fmt0->height != img_fmt1->height) || + (img_fmt0->matrix_coefficients != img_fmt1->matrix_coefficients) || + (img_fmt0->pixel_range != img_fmt1->pixel_range) || + (img_fmt0->pixel_type != img_fmt1->pixel_type) || + (img_fmt0->subsample_h != img_fmt1->subsample_h) || + (img_fmt0->subsample_w != img_fmt1->subsample_w) || + (img_fmt0->transfer_characteristics != img_fmt1->transfer_characteristics) || + (img_fmt0->width != img_fmt1->width)); +} + +/* returns 0 if graph builder parameters are the same and 1 otherwise */ +static int compare_zimg_graph_builder_params(zimg_graph_builder_params *parm0, zimg_graph_builder_params *parm1) +{ + /* the parameters that could be changed inside a single ffmpeg zscale invocation are checked only + and NaN values that are default for some params are treated properly*/ + int ret = (parm0->allow_approximate_gamma != parm1->allow_approximate_gamma) || + (parm0->dither_type != parm1->dither_type) || + (parm0->resample_filter != parm1->resample_filter) || + (parm0->resample_filter_uv != parm1->resample_filter_uv); + + if ((isnan(parm0->nominal_peak_luminance) == 0) || (isnan(parm1->nominal_peak_luminance) == 0)) + ret = ret || (parm0->nominal_peak_luminance != parm1->nominal_peak_luminance); + if ((isnan(parm0->filter_param_a) == 0) || (isnan(parm1->filter_param_a) == 0)) + ret = ret || (parm0->filter_param_a != parm1->filter_param_a); + if ((isnan(parm0->filter_param_a_uv) == 0) || (isnan(parm1->filter_param_a_uv) == 0)) + ret = ret || (parm0->filter_param_a_uv != parm1->filter_param_a_uv); + if ((isnan(parm0->filter_param_b) == 0) || (isnan(parm1->filter_param_b) == 0)) + ret = ret || (parm0->filter_param_b != parm1->filter_param_b); + if ((isnan(parm0->filter_param_b_uv) == 0) || (isnan(parm1->filter_param_b_uv) == 0)) + ret = ret || (parm0->filter_param_b_uv != parm1->filter_param_b_uv); + + return ret; +} + static void format_init(zimg_image_format *format, AVFrame *frame, const AVPixFmtDescriptor *desc, int colorspace, int primaries, int transfer, int range, int location) { @@ -483,46 +569,87 @@ static void format_init(zimg_image_format *format, AVFrame *frame, const AVPixFm format->color_family = (desc->flags & AV_PIX_FMT_FLAG_RGB) ? ZIMG_COLOR_RGB : ZIMG_COLOR_YUV; format->matrix_coefficients = (desc->flags & AV_PIX_FMT_FLAG_RGB) ? ZIMG_MATRIX_RGB : colorspace == -1 ? convert_matrix(frame->colorspace) : colorspace; format->color_primaries = primaries == -1 ? convert_primaries(frame->color_primaries) : primaries; - format->transfer_characteristics = transfer == - 1 ? convert_trc(frame->color_trc) : transfer; + format->transfer_characteristics = transfer == -1 ? convert_trc(frame->color_trc) : transfer; format->pixel_range = (desc->flags & AV_PIX_FMT_FLAG_RGB) ? ZIMG_RANGE_FULL : range == -1 ? convert_range(frame->color_range) : range; format->chroma_location = location == -1 ? convert_chroma_location(frame->chroma_location) : location; } -static int graph_build(zimg_filter_graph **graph, zimg_graph_builder_params *params, - zimg_image_format *src_format, zimg_image_format *dst_format, - void **tmp, size_t *tmp_size) +static int graphs_build(AVFrame *in, AVFrame *out, const AVPixFmtDescriptor *desc, const AVPixFmtDescriptor *out_desc, + AVFilterContext *ctx, int job_nr, int n_jobs) { + ZScaleContext *s = ctx->priv; int ret; size_t size; + zimg_image_format src_format; + zimg_image_format dst_format; + zimg_image_format alpha_src_format; + zimg_image_format alpha_dst_format; + const double in_slice_start = s->in_slice_start[job_nr]; + const double in_slice_end = s->in_slice_end[job_nr]; + const int out_slice_start = s->out_slice_start[job_nr]; + const int out_slice_end = s->out_slice_end[job_nr]; - zimg_filter_graph_free(*graph); - *graph = zimg_filter_graph_build(src_format, dst_format, params); - if (!*graph) - return print_zimg_error(NULL); + src_format = s->src_format; + dst_format = s->dst_format; + /* The input slice is specified through the active_region field, + unlike the output slice. + according to zimg requirements input and output slices should have even dimensions */ + src_format.active_region.width = in->width; + src_format.active_region.height = in_slice_end - in_slice_start; + src_format.active_region.left = 0; + src_format.active_region.top = in_slice_start; + //dst now is the single tile only!! + dst_format.width = out->width; + dst_format.height = out_slice_end - out_slice_start; - ret = zimg_filter_graph_get_tmp_size(*graph, &size); - if (ret) - return print_zimg_error(NULL); - - if (size > *tmp_size) { - av_freep(tmp); - *tmp = av_malloc(size); - if (!*tmp) - return AVERROR(ENOMEM); - - *tmp_size = size; + if (s->graph[job_nr]) { + zimg_filter_graph_free(s->graph[job_nr]); } + s->graph[job_nr] = zimg_filter_graph_build(&src_format, &dst_format, &s->params); + if (!s->graph[job_nr]) + return print_zimg_error(ctx); + ret = zimg_filter_graph_get_tmp_size(s->graph[job_nr], &size); + if (ret) + return print_zimg_error(ctx); + + if (s->tmp[job_nr]) + av_freep(&s->tmp[job_nr]); + s->tmp[job_nr] = av_calloc(size, 1); + if (!s->tmp[job_nr]) + return AVERROR(ENOMEM); + + if (desc->flags & AV_PIX_FMT_FLAG_ALPHA && out_desc->flags & AV_PIX_FMT_FLAG_ALPHA) { + alpha_src_format = s->alpha_src_format; + alpha_dst_format = s->alpha_dst_format; + /* The input slice is specified through the active_region field, unlike the output slice. + according to zimg requirements input and output slices should have even dimentions */ + alpha_src_format.active_region.width = in->width; + alpha_src_format.active_region.height = in_slice_end - in_slice_start; + alpha_src_format.active_region.left = 0; + alpha_src_format.active_region.top = in_slice_start; + //dst now is the single tile only!! + alpha_dst_format.width = out->width; + alpha_dst_format.height = out_slice_end - out_slice_start; + + if (s->alpha_graph[job_nr]) { + zimg_filter_graph_free(s->alpha_graph[job_nr]); + } + s->alpha_graph[job_nr] = zimg_filter_graph_build(&alpha_src_format, &alpha_dst_format, &s->alpha_params); + if (!s->alpha_graph[job_nr]) + return print_zimg_error(ctx); + } return 0; } -static int realign_frame(const AVPixFmtDescriptor *desc, AVFrame **frame) +static int realign_frame(const AVPixFmtDescriptor *desc, AVFrame **frame, int needs_copy) { AVFrame *aligned = NULL; - int ret = 0, plane; + int ret = 0, plane, planes; /* Realign any unaligned input frame. */ - for (plane = 0; plane < 3; plane++) { + planes = av_pix_fmt_count_planes(desc->nb_components); + for (plane = 0; plane < planes; plane++) { int p = desc->comp[plane].plane; if ((uintptr_t)(*frame)->data[p] % ZIMG_ALIGNMENT || (*frame)->linesize[p] % ZIMG_ALIGNMENT) { if (!(aligned = av_frame_alloc())) { @@ -537,10 +664,10 @@ static int realign_frame(const AVPixFmtDescriptor *desc, AVFrame **frame) if ((ret = av_frame_get_buffer(aligned, ZIMG_ALIGNMENT)) < 0) goto fail; - if ((ret = av_frame_copy(aligned, *frame)) < 0) + if (needs_copy && (ret = av_frame_copy(aligned, *frame)) < 0) goto fail; - if ((ret = av_frame_copy_props(aligned, *frame)) < 0) + if (needs_copy && (ret = av_frame_copy_props(aligned, *frame)) < 0) goto fail; av_frame_free(frame); @@ -572,43 +699,112 @@ static void update_output_color_information(ZScaleContext *s, AVFrame *frame) frame->chroma_location = (int)s->dst_format.chroma_location + 1; } -static int filter_frame(AVFilterLink *link, AVFrame *in) +static int filter_slice(AVFilterContext *ctx, void *data, int job_nr, int n_jobs) { - ZScaleContext *s = link->dst->priv; - AVFilterLink *outlink = link->dst->outputs[0]; - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format); - const AVPixFmtDescriptor *odesc = av_pix_fmt_desc_get(outlink->format); + ThreadData *td = data; + int ret = 0; + int p; + int need_gb; + ZScaleContext *s = ctx->priv; zimg_image_buffer_const src_buf = { ZIMG_API_VERSION }; zimg_image_buffer dst_buf = { ZIMG_API_VERSION }; - char buf[32]; - int ret = 0, plane; - AVFrame *out = NULL; + const int out_slice_start = s->out_slice_start[job_nr]; - if ((ret = realign_frame(desc, &in)) < 0) - goto fail; + /* create zimg filter graphs for each thread + only if not created earlier or there is some change in frame parameters */ + need_gb = compare_zimg_image_formats(&s->src_format, &s->src_format_tmp) || + compare_zimg_image_formats(&s->dst_format, &s->dst_format_tmp) || + compare_zimg_graph_builder_params(&s->params, &s->params_tmp); + if(td->desc->flags & AV_PIX_FMT_FLAG_ALPHA && td->odesc->flags & AV_PIX_FMT_FLAG_ALPHA) + need_gb = need_gb || compare_zimg_image_formats(&s->alpha_src_format, &s->alpha_src_format_tmp) || + compare_zimg_image_formats(&s->alpha_dst_format, &s->alpha_dst_format_tmp) || + compare_zimg_graph_builder_params(&s->alpha_params, &s->alpha_params_tmp); - if (!(out = ff_get_video_buffer(outlink, outlink->w, outlink->h))) { - ret = AVERROR(ENOMEM); - goto fail; + if (need_gb){ + ret = graphs_build(td->in, td->out, td->desc, td->odesc, ctx, job_nr, n_jobs); + if (ret < 0) + return print_zimg_error(ctx); } + for (int i = 0; i < 3; i++) { + const int vsamp = i >= 1 ? td->odesc->log2_chroma_h : 0; - av_frame_copy_props(out, in); - out->width = outlink->w; - out->height = outlink->h; + p = td->desc->comp[i].plane; + + src_buf.plane[i].data = td->in->data[p]; + src_buf.plane[i].stride = td->in->linesize[p]; + src_buf.plane[i].mask = -1; + + p = td->odesc->comp[i].plane; + dst_buf.plane[i].data = td->out->data[p] + td->out->linesize[p] * (out_slice_start >> vsamp); + dst_buf.plane[i].stride = td->out->linesize[p]; + dst_buf.plane[i].mask = -1; + } + if (!s->graph[job_nr]) + return AVERROR(EINVAL); + ret = zimg_filter_graph_process(s->graph[job_nr], &src_buf, &dst_buf, s->tmp[job_nr], 0, 0, 0, 0); + if (ret) + return print_zimg_error(ctx); + + if (td->desc->flags & AV_PIX_FMT_FLAG_ALPHA && td->odesc->flags & AV_PIX_FMT_FLAG_ALPHA) { + src_buf.plane[0].data = td->in->data[3]; + src_buf.plane[0].stride = td->in->linesize[3]; + src_buf.plane[0].mask = -1; + + dst_buf.plane[0].data = td->out->data[3] + td->out->linesize[3] * out_slice_start; + dst_buf.plane[0].stride = td->out->linesize[3]; + dst_buf.plane[0].mask = -1; + + if (!s->alpha_graph[job_nr]) + return AVERROR(EINVAL); + ret = zimg_filter_graph_process(s->alpha_graph[job_nr], &src_buf, &dst_buf, s->tmp[job_nr], 0, 0, 0, 0); + if (ret) + return print_zimg_error(ctx); + } + return 0; +} + +static int filter_frame(AVFilterLink *link, AVFrame *in) +{ + AVFilterContext *ctx = link->dst; + ZScaleContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format); + const AVPixFmtDescriptor *odesc = av_pix_fmt_desc_get(outlink->format); + char buf[32]; + int ret = 0; + AVFrame *out = NULL; + ThreadData td; + + //we need to use this filter if something is different for an input and output only + //otherwise - just copy the input frame to the output + if ((link->format != outlink->format) || + (link->w != outlink->w) || + (link->h != outlink->h) || + s->first_time || + (s->src_format.chroma_location != s->dst_format.chroma_location) || + (s->src_format.color_family !=s->dst_format.color_family) || + (s->src_format.color_primaries !=s->dst_format.color_primaries) || + (s->src_format.depth !=s->dst_format.depth) || + (s->src_format.matrix_coefficients !=s->dst_format.matrix_coefficients) || + (s->src_format.field_parity !=s->dst_format.field_parity) || + (s->src_format.pixel_range !=s->dst_format.pixel_range) || + (s->src_format.pixel_type !=s->dst_format.pixel_type) || + (s->src_format.transfer_characteristics !=s->dst_format.transfer_characteristics) + ){ + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) { + ret = AVERROR(ENOMEM); + goto fail; + } + + if ((ret = realign_frame(odesc, &out, 0)) < 0) + goto fail; + + av_frame_copy_props(out, in); + + if ((ret = realign_frame(desc, &in, 1)) < 0) + goto fail; - if( in->width != link->w - || in->height != link->h - || in->format != link->format - || s->in_colorspace != in->colorspace - || s->in_trc != in->color_trc - || s->in_primaries != in->color_primaries - || s->in_range != in->color_range - || s->out_colorspace != out->colorspace - || s->out_trc != out->color_trc - || s->out_primaries != out->color_primaries - || s->out_range != out->color_range - || s->in_chromal != in->chroma_location - || s->out_chromal != out->chroma_location) { snprintf(buf, sizeof(buf)-1, "%d", outlink->w); av_opt_set(s, "w", buf, 0); snprintf(buf, sizeof(buf)-1, "%d", outlink->h); @@ -618,15 +814,30 @@ static int filter_frame(AVFilterLink *link, AVFrame *in) link->dst->inputs[0]->w = in->width; link->dst->inputs[0]->h = in->height; - if ((ret = config_props(outlink)) < 0) - goto fail; + s->nb_threads = av_clip(FFMIN(ff_filter_get_nb_threads(ctx), FFMIN(link->h, outlink->h) / MIN_TILESIZE), 1, MAX_THREADS); + s->in_colorspace = in->colorspace; + s->in_trc = in->color_trc; + s->in_primaries = in->color_primaries; + s->in_range = in->color_range; + s->out_colorspace = out->colorspace; + s->out_trc = out->color_trc; + s->out_primaries = out->color_primaries; + s->out_range = out->color_range; + + slice_params(s, out->height, in->height); zimg_image_format_default(&s->src_format, ZIMG_API_VERSION); zimg_image_format_default(&s->dst_format, ZIMG_API_VERSION); zimg_graph_builder_params_default(&s->params, ZIMG_API_VERSION); + format_init(&s->src_format, in, desc, s->colorspace_in, + s->primaries_in, s->trc_in, s->range_in, s->chromal_in); + format_init(&s->dst_format, out, odesc, s->colorspace, + s->primaries, s->trc, s->range, s->chromal); + s->first_time = 0; + s->params.dither_type = s->dither; - s->params.cpu_type = ZIMG_CPU_AUTO; + s->params.cpu_type = ZIMG_CPU_AUTO_64B; s->params.resample_filter = s->filter; s->params.resample_filter_uv = s->filter; s->params.nominal_peak_luminance = s->nominal_peak_luminance; @@ -634,34 +845,13 @@ static int filter_frame(AVFilterLink *link, AVFrame *in) s->params.filter_param_a = s->params.filter_param_a_uv = s->param_a; s->params.filter_param_b = s->params.filter_param_b_uv = s->param_b; - format_init(&s->src_format, in, desc, s->colorspace_in, - s->primaries_in, s->trc_in, s->range_in, s->chromal_in); - format_init(&s->dst_format, out, odesc, s->colorspace, - s->primaries, s->trc, s->range, s->chromal); - - update_output_color_information(s, out); - - ret = graph_build(&s->graph, &s->params, &s->src_format, &s->dst_format, - &s->tmp, &s->tmp_size); - if (ret < 0) - goto fail; - - s->in_colorspace = in->colorspace; - s->in_trc = in->color_trc; - s->in_primaries = in->color_primaries; - s->in_range = in->color_range; - s->out_colorspace = out->colorspace; - s->out_trc = out->color_trc; - s->out_primaries = out->color_primaries; - s->out_range = out->color_range; - if (desc->flags & AV_PIX_FMT_FLAG_ALPHA && odesc->flags & AV_PIX_FMT_FLAG_ALPHA) { zimg_image_format_default(&s->alpha_src_format, ZIMG_API_VERSION); zimg_image_format_default(&s->alpha_dst_format, ZIMG_API_VERSION); zimg_graph_builder_params_default(&s->alpha_params, ZIMG_API_VERSION); s->alpha_params.dither_type = s->dither; - s->alpha_params.cpu_type = ZIMG_CPU_AUTO; + s->alpha_params.cpu_type = ZIMG_CPU_AUTO_64B; s->alpha_params.resample_filter = s->filter; s->alpha_src_format.width = in->width; @@ -670,76 +860,60 @@ static int filter_frame(AVFilterLink *link, AVFrame *in) s->alpha_src_format.pixel_type = (desc->flags & AV_PIX_FMT_FLAG_FLOAT) ? ZIMG_PIXEL_FLOAT : desc->comp[0].depth > 8 ? ZIMG_PIXEL_WORD : ZIMG_PIXEL_BYTE; s->alpha_src_format.color_family = ZIMG_COLOR_GREY; - 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 = (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); - s->alpha_graph = zimg_filter_graph_build(&s->alpha_src_format, &s->alpha_dst_format, &s->alpha_params); - if (!s->alpha_graph) { - ret = print_zimg_error(link->dst); - goto fail; - } } - } - update_output_color_information(s, out); + update_output_color_information(s, out); + av_reduce(&out->sample_aspect_ratio.num, &out->sample_aspect_ratio.den, + (int64_t)in->sample_aspect_ratio.num * outlink->h * link->w, + (int64_t)in->sample_aspect_ratio.den * outlink->w * link->h, + INT_MAX); - av_reduce(&out->sample_aspect_ratio.num, &out->sample_aspect_ratio.den, - (int64_t)in->sample_aspect_ratio.num * outlink->h * link->w, - (int64_t)in->sample_aspect_ratio.den * outlink->w * link->h, - INT_MAX); + td.in = in; + td.out = out; + td.desc = desc; + td.odesc = odesc; - for (plane = 0; plane < 3; plane++) { - int p = desc->comp[plane].plane; - src_buf.plane[plane].data = in->data[p]; - src_buf.plane[plane].stride = in->linesize[p]; - src_buf.plane[plane].mask = -1; - - p = odesc->comp[plane].plane; - dst_buf.plane[plane].data = out->data[p]; - dst_buf.plane[plane].stride = out->linesize[p]; - dst_buf.plane[plane].mask = -1; - } - - ret = zimg_filter_graph_process(s->graph, &src_buf, &dst_buf, s->tmp, 0, 0, 0, 0); - if (ret) { - ret = print_zimg_error(link->dst); - goto fail; - } - - if (desc->flags & AV_PIX_FMT_FLAG_ALPHA && odesc->flags & AV_PIX_FMT_FLAG_ALPHA) { - src_buf.plane[0].data = in->data[3]; - src_buf.plane[0].stride = in->linesize[3]; - src_buf.plane[0].mask = -1; - - dst_buf.plane[0].data = out->data[3]; - dst_buf.plane[0].stride = out->linesize[3]; - dst_buf.plane[0].mask = -1; - - ret = zimg_filter_graph_process(s->alpha_graph, &src_buf, &dst_buf, s->tmp, 0, 0, 0, 0); - if (ret) { - ret = print_zimg_error(link->dst); - goto fail; + memset(s->jobs_ret, 0, s->nb_threads * sizeof(*s->jobs_ret)); + ret = ff_filter_execute(ctx, filter_slice, &td, s->jobs_ret, s->nb_threads); + for (int i = 0; ret >= 0 && i < s->nb_threads; i++) + if (s->jobs_ret[i] < 0) + ret = s->jobs_ret[i]; + if (ret < 0) { + av_frame_free(&in); + av_frame_free(&out); + return ret; } - } else if (odesc->flags & AV_PIX_FMT_FLAG_ALPHA) { - int x, y; - if (odesc->flags & AV_PIX_FMT_FLAG_FLOAT) { - for (y = 0; y < out->height; y++) { - for (x = 0; x < out->width; x++) { - AV_WN32(out->data[3] + x * odesc->comp[3].step + y * out->linesize[3], - av_float2int(1.0f)); + s->src_format_tmp = s->src_format; + s->dst_format_tmp = s->dst_format; + s->params_tmp = s->params; + if (desc->flags & AV_PIX_FMT_FLAG_ALPHA && odesc->flags & AV_PIX_FMT_FLAG_ALPHA) { + s->alpha_src_format_tmp = s->alpha_src_format; + s->alpha_dst_format_tmp = s->alpha_dst_format; + s->alpha_params_tmp = s->alpha_params; + } + + if ((!(desc->flags & AV_PIX_FMT_FLAG_ALPHA)) && (odesc->flags & AV_PIX_FMT_FLAG_ALPHA) ){ + int x, y; + if (odesc->flags & AV_PIX_FMT_FLAG_FLOAT) { + for (y = 0; y < out->height; y++) { + for (x = 0; x < out->width; x++) { + AV_WN32(out->data[3] + x * odesc->comp[3].step + y * out->linesize[3], + av_float2int(1.0f)); + } } + } else { + for (y = 0; y < outlink->h; y++) + memset(out->data[3] + y * out->linesize[3], 0xff, outlink->w); } - } else { - for (y = 0; y < outlink->h; y++) - memset(out->data[3] + y * out->linesize[3], 0xff, outlink->w); } + } else { + /*no need for any filtering */ + return ff_filter_frame(outlink, in); } - fail: av_frame_free(&in); if (ret) { @@ -754,10 +928,17 @@ static av_cold 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; + for (int i = 0; i < s->nb_threads; i++) { + av_freep(&s->tmp[i]); + if (s->graph[i]) { + zimg_filter_graph_free(s->graph[i]); + s->graph[i] = NULL; + } + if (s->alpha_graph[i]) { + zimg_filter_graph_free(s->alpha_graph[i]); + s->alpha_graph[i] = NULL; + } + } } static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, @@ -941,4 +1122,5 @@ const AVFilter ff_vf_zscale = { FILTER_OUTPUTS(avfilter_vf_zscale_outputs), FILTER_QUERY_FUNC(query_formats), .process_command = process_command, + .flags = AVFILTER_FLAG_SLICE_THREADS, }; diff --git a/libavfilter/video.c b/libavfilter/video.c index 7ef04144e..e9eb110ff 100644 --- a/libavfilter/video.c +++ b/libavfilter/video.c @@ -24,6 +24,7 @@ #include #include "libavutil/buffer.h" +#include "libavutil/cpu.h" #include "libavutil/hwcontext.h" #include "libavutil/imgutils.h" @@ -32,15 +33,12 @@ #include "internal.h" #include "video.h" -#define BUFFER_ALIGN 32 - - AVFrame *ff_null_get_video_buffer(AVFilterLink *link, int w, int h) { return ff_get_video_buffer(link->dst->outputs[0], w, h); } -AVFrame *ff_default_get_video_buffer(AVFilterLink *link, int w, int h) +AVFrame *ff_default_get_video_buffer2(AVFilterLink *link, int w, int h, int align) { AVFrame *frame = NULL; int pool_width = 0; @@ -51,7 +49,7 @@ AVFrame *ff_default_get_video_buffer(AVFilterLink *link, int w, int h) if (link->hw_frames_ctx && ((AVHWFramesContext*)link->hw_frames_ctx->data)->format == link->format) { int ret; - AVFrame *frame = av_frame_alloc(); + frame = av_frame_alloc(); if (!frame) return NULL; @@ -65,7 +63,7 @@ AVFrame *ff_default_get_video_buffer(AVFilterLink *link, int w, int h) if (!link->frame_pool) { link->frame_pool = ff_frame_pool_video_init(av_buffer_allocz, w, h, - link->format, BUFFER_ALIGN); + link->format, align); if (!link->frame_pool) return NULL; } else { @@ -76,11 +74,11 @@ AVFrame *ff_default_get_video_buffer(AVFilterLink *link, int w, int h) } if (pool_width != w || pool_height != h || - pool_format != link->format || pool_align != BUFFER_ALIGN) { + pool_format != link->format || pool_align != align) { ff_frame_pool_uninit((FFFramePool **)&link->frame_pool); link->frame_pool = ff_frame_pool_video_init(av_buffer_allocz, w, h, - link->format, BUFFER_ALIGN); + link->format, align); if (!link->frame_pool) return NULL; } @@ -95,6 +93,11 @@ AVFrame *ff_default_get_video_buffer(AVFilterLink *link, int w, int h) return frame; } +AVFrame *ff_default_get_video_buffer(AVFilterLink *link, int w, int h) +{ + return ff_default_get_video_buffer2(link, w, h, av_cpu_max_align()); +} + AVFrame *ff_get_video_buffer(AVFilterLink *link, int w, int h) { AVFrame *ret = NULL; diff --git a/libavfilter/video.h b/libavfilter/video.h index f448e4ada..f37bab9d0 100644 --- a/libavfilter/video.h +++ b/libavfilter/video.h @@ -24,6 +24,7 @@ #include "avfilter.h" AVFrame *ff_default_get_video_buffer(AVFilterLink *link, int w, int h); +AVFrame *ff_default_get_video_buffer2(AVFilterLink *link, int w, int h, int align); AVFrame *ff_null_get_video_buffer(AVFilterLink *link, int w, int h); /** diff --git a/libavfilter/vsrc_cellauto.c b/libavfilter/vsrc_cellauto.c index ceac86a34..226182daf 100644 --- a/libavfilter/vsrc_cellauto.c +++ b/libavfilter/vsrc_cellauto.c @@ -222,6 +222,7 @@ static int config_props(AVFilterLink *outlink) outlink->w = s->w; outlink->h = s->h; outlink->time_base = av_inv_q(s->frame_rate); + outlink->frame_rate = s->frame_rate; return 0; } diff --git a/libavfilter/vsrc_gradients.c b/libavfilter/vsrc_gradients.c index b976f7f82..c005613d4 100644 --- a/libavfilter/vsrc_gradients.c +++ b/libavfilter/vsrc_gradients.c @@ -42,6 +42,7 @@ typedef struct GradientsContext { float speed; uint8_t color_rgba[8][4]; + float color_rgbaf[8][4]; int nb_colors; int x0, y0, x1, y1; float fx0, fy0, fx1, fy1; @@ -75,14 +76,27 @@ static const AVOption gradients_options[] = { {"nb_colors", "set the number of colors", OFFSET(nb_colors), AV_OPT_TYPE_INT, {.i64=2}, 2, 8, FLAGS }, {"n", "set the number of colors", OFFSET(nb_colors), AV_OPT_TYPE_INT, {.i64=2}, 2, 8, FLAGS }, {"seed", "set the seed", OFFSET(seed), AV_OPT_TYPE_INT64, {.i64=-1}, -1, UINT32_MAX, FLAGS }, - {"duration", "set video duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64=-1}, -1, INT64_MAX, FLAGS },\ - {"d", "set video duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64=-1}, -1, INT64_MAX, FLAGS },\ - {"speed", "set gradients rotation speed", OFFSET(speed), AV_OPT_TYPE_FLOAT,{.dbl=0.01}, 0.00001, 1, FLAGS },\ + {"duration", "set video duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64=-1}, -1, INT64_MAX, FLAGS }, + {"d", "set video duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64=-1}, -1, INT64_MAX, FLAGS }, + {"speed", "set gradients rotation speed", OFFSET(speed), AV_OPT_TYPE_FLOAT,{.dbl=0.01}, 0.00001, 1, FLAGS }, + {"type", "set gradient type", OFFSET(type), AV_OPT_TYPE_INT, {.i64=0}, 0, 3, FLAGS, "type" }, + {"t", "set gradient type", OFFSET(type), AV_OPT_TYPE_INT, {.i64=0}, 0, 3, FLAGS, "type" }, + {"linear", "set gradient type", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "type" }, + {"radial", "set gradient type", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "type" }, + {"circular", "set gradient type", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "type" }, + {"spiral", "set gradient type", 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, FLAGS, "type" }, {NULL}, }; AVFILTER_DEFINE_CLASS(gradients); +static float lerpf(float a, float b, float x) +{ + const float y = 1.f - x; + + return a * y + b * x; +} + static uint32_t lerp_color(uint8_t c0[4], uint8_t c1[4], float x) { const float y = 1.f - x; @@ -103,10 +117,10 @@ static uint64_t lerp_color16(uint8_t c0[4], uint8_t c1[4], float x) (llrintf((c0[3] * y + c1[3] * x) * 256)) << 48; } -static uint32_t lerp_colors(uint8_t arr[3][4], int nb_colors, float step) +static uint32_t lerp_colors(uint8_t arr[3][4], int nb_colors, int nb_wrap_colors, float step) { float scl; - int i; + int i, j; if (nb_colors == 1 || step <= 0.0) { return arr[0][0] | (arr[0][1] << 8) | (arr[0][2] << 16) | (arr[0][3] << 24); @@ -115,16 +129,21 @@ static uint32_t lerp_colors(uint8_t arr[3][4], int nb_colors, float step) return arr[i][0] | (arr[i][1] << 8) | (arr[i][2] << 16) | (arr[i][3] << 24); } - scl = step * (nb_colors - 1); + scl = step * (nb_wrap_colors - 1); i = floorf(scl); + j = i + 1; + if (i >= nb_colors - 1) { + i = nb_colors - 1; + j = 0; + } - return lerp_color(arr[i], arr[i + 1], scl - i); + return lerp_color(arr[i], arr[j], scl - i); } -static uint64_t lerp_colors16(uint8_t arr[3][4], int nb_colors, float step) +static uint64_t lerp_colors16(uint8_t arr[3][4], int nb_colors, int nb_wrap_colors, float step) { float scl; - int i; + int i, j; if (nb_colors == 1 || step <= 0.0) { return ((uint64_t)arr[0][0] << 8) | ((uint64_t)arr[0][1] << 24) | ((uint64_t)arr[0][2] << 40) | ((uint64_t)arr[0][3] << 56); @@ -133,27 +152,92 @@ static uint64_t lerp_colors16(uint8_t arr[3][4], int nb_colors, float step) return ((uint64_t)arr[i][0] << 8) | ((uint64_t)arr[i][1] << 24) | ((uint64_t)arr[i][2] << 40) | ((uint64_t)arr[i][3] << 56); } - scl = step * (nb_colors - 1); + scl = step * (nb_wrap_colors - 1); i = floorf(scl); + j = i + 1; + if (i >= nb_colors - 1) { + i = nb_colors - 1; + j = 0; + } - return lerp_color16(arr[i], arr[i + 1], scl - i); + return lerp_color16(arr[i], arr[j], scl - i); +} + +static void lerp_colors32(float arr[3][4], int nb_colors, + int nb_wrap_colors, float step, + float *r, float *g, float *b, float *a) +{ + float scl, x; + int i, j; + + if (nb_colors == 1 || step <= 0.0) { + *r = arr[0][0]; + *g = arr[0][1]; + *b = arr[0][2]; + *a = arr[0][3]; + return; + } else if (step >= 1.0) { + i = nb_colors - 1; + *r = arr[i][0]; + *g = arr[i][1]; + *b = arr[i][2]; + *a = arr[i][3]; + return; + } + + scl = step * (nb_wrap_colors - 1); + i = floorf(scl); + x = scl - i; + j = i + 1; + if (i >= nb_colors - 1) { + i = nb_colors - 1; + j = 0; + } + + *r = lerpf(arr[i][0], arr[j][0], x); + *g = lerpf(arr[i][1], arr[j][1], x); + *b = lerpf(arr[i][2], arr[j][2], x); + *a = lerpf(arr[i][3], arr[j][3], x); } static float project(float origin_x, float origin_y, float dest_x, float dest_y, - int point_x, int point_y) + float point_x, float point_y, int type) { - // Rise and run of line. - float od_x = dest_x - origin_x; - float od_y = dest_y - origin_y; - - // Distance-squared of line. - float od_s_q = od_x * od_x + od_y * od_y; - - // Rise and run of projection. float op_x = point_x - origin_x; float op_y = point_y - origin_y; - float op_x_od = op_x * od_x + op_y * od_y; + float od_x = dest_x - origin_x; + float od_y = dest_y - origin_y; + float op_x_od; + float od_s_q; + + switch (type) { + case 0: + od_s_q = od_x * od_x + od_y * od_y; + break; + case 1: + od_s_q = sqrtf(od_x * od_x + od_y * od_y); + break; + case 2: + case 3: + od_s_q = M_PI * 2.f; + break; + } + + switch (type) { + case 0: + op_x_od = op_x * od_x + op_y * od_y; + break; + case 1: + op_x_od = sqrtf(op_x * op_x + op_y * op_y); + break; + case 2: + op_x_od = atan2f(op_x, op_y) + M_PI; + break; + case 3: + op_x_od = fmodf(atan2f(op_x, op_y) + M_PI + point_x / fmaxf(origin_x, dest_x), 2.f * M_PI); + break; + } // Normalize and clamp range. return av_clipf(op_x_od / od_s_q, 0.f, 1.f); @@ -172,8 +256,8 @@ static int draw_gradients_slice(AVFilterContext *ctx, void *arg, int job, int nb for (int y = start; y < end; y++) { for (int x = 0; x < width; x++) { - float factor = project(s->fx0, s->fy0, s->fx1, s->fy1, x, y); - dst[x] = lerp_colors(s->color_rgba, s->nb_colors, factor); + float factor = project(s->fx0, s->fy0, s->fx1, s->fy1, x, y, s->type); + dst[x] = lerp_colors(s->color_rgba, s->nb_colors, s->nb_colors + (s->type >= 2), factor); } dst += linesize; @@ -195,32 +279,80 @@ static int draw_gradients_slice16(AVFilterContext *ctx, void *arg, int job, int for (int y = start; y < end; y++) { for (int x = 0; x < width; x++) { - float factor = project(s->fx0, s->fy0, s->fx1, s->fy1, x, y); - dst[x] = lerp_colors16(s->color_rgba, s->nb_colors, factor); + float factor = project(s->fx0, s->fy0, s->fx1, s->fy1, x, y, s->type); + dst[x] = lerp_colors16(s->color_rgba, s->nb_colors, s->nb_colors + s->type >= 2, factor); } dst += linesize; } return 0; -}static int config_output(AVFilterLink *inlink) +} + +static int draw_gradients_slice32_planar(AVFilterContext *ctx, void *arg, int job, int nb_jobs) { - AVFilterContext *ctx = inlink->src; GradientsContext *s = ctx->priv; - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + AVFrame *frame = arg; + const int width = frame->width; + const int height = frame->height; + const int start = (height * job ) / nb_jobs; + const int end = (height * (job+1)) / nb_jobs; + const int linesize_g = frame->linesize[0] / 4; + const int linesize_b = frame->linesize[1] / 4; + const int linesize_r = frame->linesize[2] / 4; + const int linesize_a = frame->linesize[3] / 4; + float *dst_g = (float *)frame->data[0] + start * linesize_g; + float *dst_b = (float *)frame->data[0] + start * linesize_b; + float *dst_r = (float *)frame->data[0] + start * linesize_r; + float *dst_a = (float *)frame->data[0] + start * linesize_a; + + for (int y = start; y < end; y++) { + for (int x = 0; x < width; x++) { + float factor = project(s->fx0, s->fy0, s->fx1, s->fy1, x, y, s->type); + lerp_colors32(s->color_rgbaf, s->nb_colors, s->nb_colors + s->type >= 2 ,factor, + &dst_r[x], &dst_g[x], &dst_b[x], &dst_a[x]); + } + + dst_g += linesize_g; + dst_b += linesize_b; + dst_r += linesize_r; + dst_a += linesize_a; + } + + return 0; +} + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + GradientsContext *s = ctx->priv; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(outlink->format); if (av_image_check_size(s->w, s->h, 0, ctx) < 0) return AVERROR(EINVAL); - inlink->w = s->w; - inlink->h = s->h; - inlink->time_base = av_inv_q(s->frame_rate); - inlink->sample_aspect_ratio = (AVRational) {1, 1}; + outlink->w = s->w; + outlink->h = s->h; + outlink->time_base = av_inv_q(s->frame_rate); + outlink->sample_aspect_ratio = (AVRational) {1, 1}; + outlink->frame_rate = s->frame_rate; if (s->seed == -1) s->seed = av_get_random_seed(); av_lfg_init(&s->lfg, s->seed); - s->draw_slice = desc->comp[0].depth == 16 ? draw_gradients_slice16 : draw_gradients_slice; + switch (desc->comp[0].depth) { + case 8: + s->draw_slice = draw_gradients_slice; + break; + case 16: + s->draw_slice = draw_gradients_slice16; + break; + case 32: + s->draw_slice = draw_gradients_slice32_planar; + break; + default: + return AVERROR_BUG; + } if (s->x0 < 0 || s->x0 >= s->w) s->x0 = av_lfg_get(&s->lfg) % s->w; @@ -231,6 +363,11 @@ static int draw_gradients_slice16(AVFilterContext *ctx, void *arg, int job, int if (s->y1 < 0 || s->y1 >= s->h) s->y1 = av_lfg_get(&s->lfg) % s->h; + for (int n = 0; n < 8; n++) { + for (int c = 0; c < 4; c++) + s->color_rgbaf[n][c] = s->color_rgba[n][c] / 255.f; + } + return 0; } @@ -290,7 +427,7 @@ const AVFilter ff_vsrc_gradients = { .priv_class = &gradients_class, .inputs = NULL, FILTER_OUTPUTS(gradients_outputs), - FILTER_PIXFMTS(AV_PIX_FMT_RGBA, AV_PIX_FMT_RGBA64), + FILTER_PIXFMTS(AV_PIX_FMT_RGBA, AV_PIX_FMT_RGBA64, AV_PIX_FMT_GBRAPF32), .activate = activate, .flags = AVFILTER_FLAG_SLICE_THREADS, }; diff --git a/libavfilter/vsrc_life.c b/libavfilter/vsrc_life.c index 38df2a6a5..d40c38b95 100644 --- a/libavfilter/vsrc_life.c +++ b/libavfilter/vsrc_life.c @@ -284,6 +284,7 @@ static int config_props(AVFilterLink *outlink) outlink->w = life->w; outlink->h = life->h; outlink->time_base = av_inv_q(life->frame_rate); + outlink->frame_rate = life->frame_rate; return 0; } diff --git a/libavfilter/vsrc_mandelbrot.c b/libavfilter/vsrc_mandelbrot.c index 83e39f1d1..d4d7e2fa4 100644 --- a/libavfilter/vsrc_mandelbrot.c +++ b/libavfilter/vsrc_mandelbrot.c @@ -134,6 +134,9 @@ static av_cold int init(AVFilterContext *ctx) s-> next_cache= av_malloc_array(s->cache_allocated, sizeof(*s-> next_cache)); s-> zyklus = av_malloc_array(s->maxiter + 16, sizeof(*s->zyklus)); + if (!s->point_cache || !s->next_cache || !s->zyklus) + return AVERROR(ENOMEM); + return 0; } @@ -146,17 +149,18 @@ static av_cold void uninit(AVFilterContext *ctx) av_freep(&s->zyklus); } -static int config_props(AVFilterLink *inlink) +static int config_props(AVFilterLink *outlink) { - AVFilterContext *ctx = inlink->src; + AVFilterContext *ctx = outlink->src; MBContext *s = ctx->priv; if (av_image_check_size(s->w, s->h, 0, ctx) < 0) return AVERROR(EINVAL); - inlink->w = s->w; - inlink->h = s->h; - inlink->time_base = av_inv_q(s->frame_rate); + outlink->w = s->w; + outlink->h = s->h; + outlink->time_base = av_inv_q(s->frame_rate); + outlink->frame_rate = s->frame_rate; return 0; } diff --git a/libavfilter/vsrc_mptestsrc.c b/libavfilter/vsrc_mptestsrc.c index f1bb777ef..03073dcf5 100644 --- a/libavfilter/vsrc_mptestsrc.c +++ b/libavfilter/vsrc_mptestsrc.c @@ -286,6 +286,7 @@ static int config_props(AVFilterLink *outlink) outlink->w = WIDTH; outlink->h = HEIGHT; outlink->time_base = av_inv_q(test->frame_rate); + outlink->frame_rate = test->frame_rate; return 0; } diff --git a/libavfilter/vsrc_sierpinski.c b/libavfilter/vsrc_sierpinski.c index 047811c11..898fb5ae5 100644 --- a/libavfilter/vsrc_sierpinski.c +++ b/libavfilter/vsrc_sierpinski.c @@ -137,18 +137,19 @@ static int draw_carpet_slice(AVFilterContext *ctx, void *arg, int job, int nb_jo return 0; } -static int config_output(AVFilterLink *inlink) +static int config_output(AVFilterLink *outlink) { - AVFilterContext *ctx = inlink->src; + AVFilterContext *ctx = outlink->src; SierpinskiContext *s = ctx->priv; if (av_image_check_size(s->w, s->h, 0, ctx) < 0) return AVERROR(EINVAL); - inlink->w = s->w; - inlink->h = s->h; - inlink->time_base = av_inv_q(s->frame_rate); - inlink->sample_aspect_ratio = (AVRational) {1, 1}; + outlink->w = s->w; + outlink->h = s->h; + outlink->time_base = av_inv_q(s->frame_rate); + outlink->sample_aspect_ratio = (AVRational) {1, 1}; + outlink->frame_rate = s->frame_rate; if (s->seed == -1) s->seed = av_get_random_seed(); av_lfg_init(&s->lfg, s->seed); diff --git a/libavfilter/vsrc_testsrc.c b/libavfilter/vsrc_testsrc.c index 20b915d47..e7d8d9ea1 100644 --- a/libavfilter/vsrc_testsrc.c +++ b/libavfilter/vsrc_testsrc.c @@ -33,6 +33,8 @@ * allyuv, smptebars and smptehdbars are by Paul B Mahol. */ +#include "config_components.h" + #include #include "libavutil/avassert.h" @@ -53,6 +55,7 @@ typedef struct TestSourceContext { const AVClass *class; int w, h; + int pw, ph; unsigned int nb_frame; AVRational time_base, frame_rate; int64_t pts; @@ -1883,3 +1886,155 @@ const AVFilter ff_vsrc_colorspectrum = { }; #endif /* CONFIG_COLORSPECTRUM_FILTER */ + +#if CONFIG_COLORCHART_FILTER + +static const AVOption colorchart_options[] = { + COMMON_OPTIONS_NOSIZE + { "patch_size", "set the single patch size", OFFSET(pw), AV_OPT_TYPE_IMAGE_SIZE, {.str="64x64"}, 0, 0, FLAGS }, + { "preset", "set the color checker chart preset", OFFSET(type), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "preset" }, + { "reference", "reference", 0, AV_OPT_TYPE_CONST,{.i64=0}, 0, 0, FLAGS, "preset" }, + { "skintones", "skintones", 0, AV_OPT_TYPE_CONST,{.i64=1}, 0, 0, FLAGS, "preset" }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(colorchart); + +static const uint8_t reference_colors[][3] = { + { 115, 82, 68 }, // dark skin + { 194, 150, 130 }, // light skin + { 98, 122, 157 }, // blue sky + { 87, 108, 67 }, // foliage + { 133, 128, 177 }, // blue flower + { 103, 189, 170 }, // bluish green + + { 214, 126, 44 }, // orange + { 80, 91, 166 }, // purple red + { 193, 90, 99 }, // moderate red + { 94, 60, 108 }, // purple + { 157, 188, 64 }, // yellow green + { 224, 163, 46 }, // orange yellow + + { 56, 61, 150 }, // blue + { 70, 148, 73 }, // green + { 175, 54, 60 }, // red + { 231, 199, 31 }, // yellow + { 187, 86, 149 }, // magenta + { 8, 133, 161 }, // cyan + + { 243, 243, 242 }, // white + { 200, 200, 200 }, // neutral 8 + { 160, 160, 160 }, // neutral 65 + { 122, 122, 121 }, // neutral 5 + { 85, 85, 85 }, // neutral 35 + { 52, 52, 52 }, // black +}; + +static const uint8_t skintones_colors[][3] = { + { 54, 38, 43 }, + { 105, 43, 42 }, + { 147, 43, 43 }, + { 77, 41, 42 }, + { 134, 43, 41 }, + { 201, 134, 118 }, + + { 59, 41, 41 }, + { 192, 103, 76 }, + { 208, 156, 141 }, + { 152, 82, 61 }, + { 162, 132, 118 }, + { 212, 171, 150 }, + + { 205, 91, 31 }, + { 164, 100, 55 }, + { 204, 136, 95 }, + { 178, 142, 116 }, + { 210, 152, 108 }, + { 217, 167, 131 }, + + { 206, 166, 126 }, + { 208, 163, 97 }, + { 245, 180, 0 }, + { 212, 184, 125 }, + { 179, 165, 150 }, + { 196, 184, 105 }, +}; + +typedef struct ColorChartPreset { + int w, h; + const uint8_t (*colors)[3]; +} ColorChartPreset; + +static const ColorChartPreset colorchart_presets[] = { + { 6, 4, reference_colors, }, + { 6, 4, skintones_colors, }, +}; + +static int colorchart_config_props(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->src; + TestSourceContext *s = ctx->priv; + + av_assert0(ff_draw_init(&s->draw, inlink->format, 0) >= 0); + if (av_image_check_size(s->w, s->h, 0, ctx) < 0) + return AVERROR(EINVAL); + return config_props(inlink); +} + +static void colorchart_fill_picture(AVFilterContext *ctx, AVFrame *frame) +{ + TestSourceContext *test = ctx->priv; + const int preset = test->type; + const int w = colorchart_presets[preset].w; + const int h = colorchart_presets[preset].h; + const int pw = test->pw; + const int ph = test->pw; + + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) { + uint32_t pc = AV_RB24(colorchart_presets[preset].colors[y * w + x]); + FFDrawColor color; + + set_color(test, &color, pc); + ff_fill_rectangle(&test->draw, &color, frame->data, frame->linesize, + x * pw, y * ph, pw, ph); + } + } +} + +static av_cold int colorchart_init(AVFilterContext *ctx) +{ + TestSourceContext *test = ctx->priv; + const int preset = test->type; + const int w = colorchart_presets[preset].w; + const int h = colorchart_presets[preset].h; + + test->w = w * test->pw; + test->h = h * test->ph; + test->draw_once = 1; + test->fill_picture_fn = colorchart_fill_picture; + return init(ctx); +} + +static const AVFilterPad avfilter_vsrc_colorchart_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = colorchart_config_props, + }, +}; + +const AVFilter ff_vsrc_colorchart = { + .name = "colorchart", + .description = NULL_IF_CONFIG_SMALL("Generate color checker chart."), + .priv_size = sizeof(TestSourceContext), + .priv_class = &colorchart_class, + .init = colorchart_init, + .uninit = uninit, + .activate = activate, + .inputs = NULL, + FILTER_OUTPUTS(avfilter_vsrc_colorchart_outputs), + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_GBRP), +}; + +#endif /* CONFIG_COLORCHART_FILTER */ diff --git a/libavfilter/window_func.h b/libavfilter/window_func.h index b7c8c0027..bff1fa604 100644 --- a/libavfilter/window_func.h +++ b/libavfilter/window_func.h @@ -24,6 +24,7 @@ #include #include "libavutil/avassert.h" +#include "libavutil/common.h" enum WindowFunc { WFUNC_RECT, WFUNC_HANNING, WFUNC_HAMMING, WFUNC_BLACKMAN, WFUNC_BARTLETT, WFUNC_WELCH, WFUNC_FLATTOP, diff --git a/libavfilter/x86/af_afir_init.c b/libavfilter/x86/af_afir_init.c index c37212c38..e53817b9c 100644 --- a/libavfilter/x86/af_afir_init.c +++ b/libavfilter/x86/af_afir_init.c @@ -20,7 +20,7 @@ #include "libavutil/attributes.h" #include "libavutil/cpu.h" #include "libavutil/x86/cpu.h" -#include "libavfilter/af_afir.h" +#include "libavfilter/af_afirdsp.h" void ff_fcmul_add_sse3(float *sum, const float *t, const float *c, ptrdiff_t len); diff --git a/libavfilter/x86/vf_blend.asm b/libavfilter/x86/vf_blend.asm index 766e5b7bc..277b100e4 100644 --- a/libavfilter/x86/vf_blend.asm +++ b/libavfilter/x86/vf_blend.asm @@ -75,7 +75,7 @@ BLEND_INIT %1, 2, %3 movu m0, [topq + xq] movu m1, [bottomq + xq] p%2 m0, m1 - mova [dstq + xq], m0 + movu [dstq + xq], m0 add xq, mmsize jl .loop BLEND_END @@ -108,7 +108,7 @@ BLEND_INIT %1, 6, %4 packus%3%2 m0, m1 - mova [dstq + xq], m0 + movu [dstq + xq], m0 add xq, mmsize jl .loop BLEND_END @@ -148,7 +148,7 @@ BLEND_INIT multiply, 6 MULTIPLY m1, m3, m5 packuswb m0, m1 - mova [dstq + xq], m0 + movu [dstq + xq], m0 add xq, mmsize jl .loop BLEND_END @@ -175,7 +175,7 @@ BLEND_INIT screen, 7 SCREEN m1, m3, m5, m6 packuswb m0, m1 - mova [dstq + xq], m0 + movu [dstq + xq], m0 add xq, mmsize jl .loop BLEND_END @@ -196,7 +196,7 @@ BLEND_INIT %1, 3, %3 pxor m1, m2 pavg%2 m0, m1 pxor m0, m2 - mova [dstq + xq], m0 + movu [dstq + xq], m0 add xq, mmsize jl .loop BLEND_END @@ -230,7 +230,7 @@ BLEND_INIT %1, 6, %4 packus%3%2 m0, m1 - mova [dstq + xq], m0 + movu [dstq + xq], m0 add xq, mmsize jl .loop BLEND_END @@ -251,7 +251,7 @@ BLEND_INIT hardmix, 5 pxor m0, m3 pcmpgtb m1, m0 pxor m1, m2 - mova [dstq + xq], m1 + movu [dstq + xq], m1 add xq, mmsize jl .loop BLEND_END @@ -304,7 +304,7 @@ BLEND_INIT %1, 4, %3 mova m2, m3 psubus%2 m2, m1 paddus%2 m2, m0 - mova [dstq + xq], m2 + movu [dstq + xq], m2 add xq, mmsize jl .loop BLEND_END @@ -333,7 +333,7 @@ BLEND_INIT %1, 5, %4 ABS2 m0, m3, m1, m4 %endif packus%3%2 m0, m3 - mova [dstq + xq], m0 + movu [dstq + xq], m0 add xq, mmsize jl .loop BLEND_END @@ -369,7 +369,7 @@ BLEND_INIT %1, 8, %4 ABS2 m3, m7, m1, m6 %endif packus%3%2 m3, m7 - mova [dstq + xq], m3 + movu [dstq + xq], m3 add xq, mmsize jl .loop BLEND_END @@ -406,7 +406,7 @@ BLEND_INIT %1, 8, %4 psub%3 m0, m4, m3 psub%3 m1, m4, m7 packus%3%2 m0, m1 - mova [dstq + xq], m0 + movu [dstq + xq], m0 add xq, mmsize jl .loop BLEND_END diff --git a/libavfilter/x86/vf_bwdif.asm b/libavfilter/x86/vf_bwdif.asm index 147b7c6ac..0b453da53 100644 --- a/libavfilter/x86/vf_bwdif.asm +++ b/libavfilter/x86/vf_bwdif.asm @@ -264,7 +264,3 @@ INIT_XMM ssse3 BWDIF INIT_XMM sse2 BWDIF -%if ARCH_X86_32 -INIT_MMX mmxext -BWDIF -%endif diff --git a/libavfilter/x86/vf_bwdif_init.c b/libavfilter/x86/vf_bwdif_init.c index f632c4f34..e24e5cd9b 100644 --- a/libavfilter/x86/vf_bwdif_init.c +++ b/libavfilter/x86/vf_bwdif_init.c @@ -24,10 +24,6 @@ #include "libavutil/x86/cpu.h" #include "libavfilter/bwdif.h" -void ff_bwdif_filter_line_mmxext(void *dst, void *prev, void *cur, void *next, - int w, int prefs, int mrefs, int prefs2, - int mrefs2, int prefs3, int mrefs3, int prefs4, - int mrefs4, int parity, int clip_max); void ff_bwdif_filter_line_sse2(void *dst, void *prev, void *cur, void *next, int w, int prefs, int mrefs, int prefs2, int mrefs2, int prefs3, int mrefs3, int prefs4, @@ -37,10 +33,6 @@ void ff_bwdif_filter_line_ssse3(void *dst, void *prev, void *cur, void *next, int mrefs2, int prefs3, int mrefs3, int prefs4, int mrefs4, int parity, int clip_max); -void ff_bwdif_filter_line_12bit_mmxext(void *dst, void *prev, void *cur, void *next, - int w, int prefs, int mrefs, int prefs2, - int mrefs2, int prefs3, int mrefs3, int prefs4, - int mrefs4, int parity, int clip_max); void ff_bwdif_filter_line_12bit_sse2(void *dst, void *prev, void *cur, void *next, int w, int prefs, int mrefs, int prefs2, int mrefs2, int prefs3, int mrefs3, int prefs4, @@ -57,19 +49,11 @@ av_cold void ff_bwdif_init_x86(BWDIFContext *bwdif) int bit_depth = (!yadif->csp) ? 8 : yadif->csp->comp[0].depth; if (bit_depth <= 8) { -#if ARCH_X86_32 - if (EXTERNAL_MMXEXT(cpu_flags)) - bwdif->filter_line = ff_bwdif_filter_line_mmxext; -#endif /* ARCH_X86_32 */ if (EXTERNAL_SSE2(cpu_flags)) bwdif->filter_line = ff_bwdif_filter_line_sse2; if (EXTERNAL_SSSE3(cpu_flags)) bwdif->filter_line = ff_bwdif_filter_line_ssse3; } else if (bit_depth <= 12) { -#if ARCH_X86_32 - if (EXTERNAL_MMXEXT(cpu_flags)) - bwdif->filter_line = ff_bwdif_filter_line_12bit_mmxext; -#endif /* ARCH_X86_32 */ if (EXTERNAL_SSE2(cpu_flags)) bwdif->filter_line = ff_bwdif_filter_line_12bit_sse2; if (EXTERNAL_SSSE3(cpu_flags)) diff --git a/libavfilter/x86/vf_eq.asm b/libavfilter/x86/vf_eq.asm index a30a28702..5118ffcba 100644 --- a/libavfilter/x86/vf_eq.asm +++ b/libavfilter/x86/vf_eq.asm @@ -24,7 +24,7 @@ SECTION .text -%macro PROCESS_ONE_LINE 1 +INIT_XMM sse2 cglobal process_one_line, 5, 7, 5, src, dst, contrast, brightness, w movd m3, contrastd movd m4, brightnessd @@ -39,7 +39,7 @@ cglobal process_one_line, 5, 7, 5, src, dst, contrast, brightness, w pxor m1, m1 mov scalard, wd and scalard, mmsize-1 - sar wd, %1 + sar wd, 4 cmp wd, 1 jl .loop1 @@ -80,11 +80,3 @@ cglobal process_one_line, 5, 7, 5, src, dst, contrast, brightness, w .end: RET - -%endmacro - -INIT_MMX mmxext -PROCESS_ONE_LINE 3 - -INIT_XMM sse2 -PROCESS_ONE_LINE 4 diff --git a/libavfilter/x86/vf_eq_init.c b/libavfilter/x86/vf_eq_init.c index 113056e76..a1719672d 100644 --- a/libavfilter/x86/vf_eq_init.c +++ b/libavfilter/x86/vf_eq_init.c @@ -25,27 +25,10 @@ #include "libavutil/x86/asm.h" #include "libavfilter/vf_eq.h" -extern void ff_process_one_line_mmxext(const uint8_t *src, uint8_t *dst, short contrast, - short brightness, int w); extern void ff_process_one_line_sse2(const uint8_t *src, uint8_t *dst, short contrast, short brightness, int w); #if HAVE_X86ASM -static void process_mmxext(EQParameters *param, uint8_t *dst, int dst_stride, - const uint8_t *src, int src_stride, int w, int h) -{ - short contrast = (short) (param->contrast * 256 * 16); - short brightness = ((short) (100.0 * param->brightness + 100.0) * 511) - / 200 - 128 - contrast / 32; - - while (h--) { - ff_process_one_line_mmxext(src, dst, contrast, brightness, w); - src += src_stride; - dst += dst_stride; - } - emms_c(); -} - static void process_sse2(EQParameters *param, uint8_t *dst, int dst_stride, const uint8_t *src, int src_stride, int w, int h) { @@ -65,9 +48,6 @@ av_cold void ff_eq_init_x86(EQContext *eq) { #if HAVE_X86ASM int cpu_flags = av_get_cpu_flags(); - if (EXTERNAL_MMXEXT(cpu_flags)) { - eq->process = process_mmxext; - } if (EXTERNAL_SSE2(cpu_flags)) { eq->process = process_sse2; } diff --git a/libavfilter/x86/vf_idet.asm b/libavfilter/x86/vf_idet.asm index 9596abd7e..7bc8e7d2c 100644 --- a/libavfilter/x86/vf_idet.asm +++ b/libavfilter/x86/vf_idet.asm @@ -25,60 +25,6 @@ SECTION .text -; Implementation that does 8-bytes at a time using single-word operations. -%macro IDET_FILTER_LINE 1 -INIT_MMX %1 -cglobal idet_filter_line, 4, 5, 0, a, b, c, width, index - xor indexq, indexq -%define m_zero m2 -%define m_sum m5 - pxor m_sum, m_sum - pxor m_zero, m_zero - -.loop: - movu m0, [aq + indexq*1] - punpckhbw m1, m0, m_zero - punpcklbw m0, m_zero - - movu m3, [cq + indexq*1] - punpckhbw m4, m3, m_zero - punpcklbw m3, m_zero - - paddsw m1, m4 - paddsw m0, m3 - - movu m3, [bq + indexq*1] - punpckhbw m4, m3, m_zero - punpcklbw m3, m_zero - - paddw m4, m4 - paddw m3, m3 - psubsw m1, m4 - psubsw m0, m3 - - ABS2 m1, m0, m4, m3 - - paddw m0, m1 - punpckhwd m1, m0, m_zero - punpcklwd m0, m_zero - - paddd m0, m1 - paddd m_sum, m0 - - add indexq, 0x8 - CMP widthd, indexd - jg .loop - - HADDD m_sum, m0 - movd eax, m_sum - RET -%endmacro - -%if ARCH_X86_32 -IDET_FILTER_LINE mmxext -IDET_FILTER_LINE mmx -%endif - ;****************************************************************************** ; 16bit implementation that does 4/8-pixels at a time @@ -128,10 +74,6 @@ cglobal idet_filter_line_16bit, 4, 5, 8, a, b, c, width, index INIT_XMM sse2 IDET_FILTER_LINE_16BIT 8 -%if ARCH_X86_32 -INIT_MMX mmx -IDET_FILTER_LINE_16BIT 4 -%endif ;****************************************************************************** ; SSE2 8-bit implementation that does 16-bytes at a time: diff --git a/libavfilter/x86/vf_idet_init.c b/libavfilter/x86/vf_idet_init.c index d4d9bd089..acb4e2a77 100644 --- a/libavfilter/x86/vf_idet_init.c +++ b/libavfilter/x86/vf_idet_init.c @@ -24,7 +24,7 @@ #if HAVE_X86ASM -/* declares main callable idet_filter_line_{mmx,mmxext,sse2}() */ +/* declares main callable idet_filter_line_sse2() */ #define FUNC_MAIN_DECL(KIND, SPAN) \ int ff_idet_filter_line_##KIND(const uint8_t *a, const uint8_t *b, \ const uint8_t *c, int w); \ @@ -58,11 +58,6 @@ static int idet_filter_line_16bit_##KIND(const uint16_t *a, const uint16_t *b, \ FUNC_MAIN_DECL(sse2, 16) FUNC_MAIN_DECL_16bit(sse2, 8) -#if ARCH_X86_32 -FUNC_MAIN_DECL(mmx, 8) -FUNC_MAIN_DECL(mmxext, 8) -FUNC_MAIN_DECL_16bit(mmx, 4) -#endif #endif av_cold void ff_idet_init_x86(IDETContext *idet, int for_16b) @@ -70,15 +65,6 @@ av_cold void ff_idet_init_x86(IDETContext *idet, int for_16b) #if HAVE_X86ASM const int cpu_flags = av_get_cpu_flags(); -#if ARCH_X86_32 - if (EXTERNAL_MMX(cpu_flags)) { - idet->filter_line = for_16b ? (ff_idet_filter_func)idet_filter_line_16bit_mmx : idet_filter_line_mmx; - } - if (EXTERNAL_MMXEXT(cpu_flags)) { - idet->filter_line = for_16b ? (ff_idet_filter_func)idet_filter_line_16bit_mmx : idet_filter_line_mmxext; - } -#endif // ARCH_x86_32 - if (EXTERNAL_SSE2(cpu_flags)) { idet->filter_line = for_16b ? (ff_idet_filter_func)idet_filter_line_16bit_sse2 : idet_filter_line_sse2; } diff --git a/libavfilter/x86/vf_limiter.asm b/libavfilter/x86/vf_limiter.asm index c5b9b0a64..e1b80eba6 100644 --- a/libavfilter/x86/vf_limiter.asm +++ b/libavfilter/x86/vf_limiter.asm @@ -41,7 +41,7 @@ cglobal limiter_8bit, 6, 7, 3, src, dst, slinesize, dlinesize, w, h, x .loop: movu m0, [srcq + xq] CLIPUB m0, m1, m2 - mova [dstq+xq], m0 + movu [dstq+xq], m0 add xq, mmsize jl .loop @@ -69,7 +69,7 @@ cglobal limiter_16bit, 6, 7, 3, src, dst, slinesize, dlinesize, w, h, x movu m0, [srcq + xq] pmaxuw m0, m1 pminuw m0, m2 - mova [dstq+xq], m0 + movu [dstq+xq], m0 add xq, mmsize jl .loop diff --git a/libavfilter/x86/vf_maskedmerge.asm b/libavfilter/x86/vf_maskedmerge.asm index 7e61935b9..102829908 100644 --- a/libavfilter/x86/vf_maskedmerge.asm +++ b/libavfilter/x86/vf_maskedmerge.asm @@ -24,26 +24,28 @@ SECTION_RODATA -pw_128: times 8 dw 128 -pw_256: times 8 dw 256 +pw_127: times 8 dw 127 +pw_255: times 8 dw 255 +pw_32897: times 8 dw 32897 SECTION .text INIT_XMM sse2 %if ARCH_X86_64 -cglobal maskedmerge8, 8, 11, 7, bsrc, osrc, msrc, dst, blinesize, olinesize, mlinesize, dlinesize, w, h, x +cglobal maskedmerge8, 8, 11, 8, bsrc, osrc, msrc, dst, blinesize, olinesize, mlinesize, dlinesize, w, h, x mov wd, dword wm mov hd, dword hm %else -cglobal maskedmerge8, 5, 7, 7, bsrc, osrc, msrc, dst, blinesize, w, x +cglobal maskedmerge8, 5, 7, 8, bsrc, osrc, msrc, dst, blinesize, w, x mov wd, r8m %define olinesizeq r5mp %define mlinesizeq r6mp %define dlinesizeq r7mp %define hd r9mp %endif - mova m4, [pw_256] - mova m5, [pw_128] + mova m4, [pw_255] + mova m5, [pw_127] + mova m7, [pw_32897] pxor m6, m6 add bsrcq, wq add osrcq, wq @@ -66,7 +68,8 @@ cglobal maskedmerge8, 5, 7, 7, bsrc, osrc, msrc, dst, blinesize, w, x pmullw m1, m3 paddw m1, m2 paddw m1, m5 - psrlw m1, 8 + pmulhuw m1, m7 + psrlw m1, 7 packuswb m1, m1 movh [dstq + xq], m1 add xq, mmsize / 2 diff --git a/libavfilter/x86/vf_noise.c b/libavfilter/x86/vf_noise.c index f7a4d0033..43387c990 100644 --- a/libavfilter/x86/vf_noise.c +++ b/libavfilter/x86/vf_noise.c @@ -25,34 +25,6 @@ #include "libavfilter/vf_noise.h" #if HAVE_INLINE_ASM -static void line_noise_mmx(uint8_t *dst, const uint8_t *src, - const int8_t *noise, int len, int shift) -{ - x86_reg mmx_len= len & (~7); - noise += shift; - - __asm__ volatile( - "mov %3, %%"FF_REG_a" \n\t" - "pcmpeqb %%mm7, %%mm7 \n\t" - "psllw $15, %%mm7 \n\t" - "packsswb %%mm7, %%mm7 \n\t" - ".p2align 4 \n\t" - "1: \n\t" - "movq (%0, %%"FF_REG_a"), %%mm0 \n\t" - "movq (%1, %%"FF_REG_a"), %%mm1 \n\t" - "pxor %%mm7, %%mm0 \n\t" - "paddsb %%mm1, %%mm0 \n\t" - "pxor %%mm7, %%mm0 \n\t" - "movq %%mm0, (%2, %%"FF_REG_a") \n\t" - "add $8, %%"FF_REG_a" \n\t" - " js 1b \n\t" - :: "r" (src+mmx_len), "r" (noise+mmx_len), "r" (dst+mmx_len), "g" (-mmx_len) - : "%"FF_REG_a - ); - if (mmx_len != len) - ff_line_noise_c(dst+mmx_len, src+mmx_len, noise+mmx_len, len-mmx_len, 0); -} - #if HAVE_6REGS static void line_noise_avg_mmx(uint8_t *dst, const uint8_t *src, int len, const int8_t * const *shift) @@ -132,7 +104,6 @@ av_cold void ff_noise_init_x86(NoiseContext *n) int cpu_flags = av_get_cpu_flags(); if (INLINE_MMX(cpu_flags)) { - n->line_noise = line_noise_mmx; #if HAVE_6REGS n->line_noise_avg = line_noise_avg_mmx; #endif diff --git a/libavfilter/x86/vf_yadif.asm b/libavfilter/x86/vf_yadif.asm index a29620ce5..809cebdd3 100644 --- a/libavfilter/x86/vf_yadif.asm +++ b/libavfilter/x86/vf_yadif.asm @@ -133,12 +133,8 @@ SECTION .text psubusb m2, m3 psubusb m3, m4 pmaxub m2, m3 -%if mmsize == 16 mova m3, m2 psrldq m3, 2 -%else - pshufw m3, m2, q0021 -%endif punpcklbw m2, m7 punpcklbw m3, m7 paddw m0, m2 @@ -237,7 +233,3 @@ INIT_XMM ssse3 YADIF INIT_XMM sse2 YADIF -%if ARCH_X86_32 -INIT_MMX mmxext -YADIF -%endif diff --git a/libavfilter/x86/vf_yadif_init.c b/libavfilter/x86/vf_yadif_init.c index 66cbee851..257c3f919 100644 --- a/libavfilter/x86/vf_yadif_init.c +++ b/libavfilter/x86/vf_yadif_init.c @@ -23,9 +23,6 @@ #include "libavutil/x86/cpu.h" #include "libavfilter/yadif.h" -void ff_yadif_filter_line_mmxext(void *dst, void *prev, void *cur, - void *next, int w, int prefs, - int mrefs, int parity, int mode); void ff_yadif_filter_line_sse2(void *dst, void *prev, void *cur, void *next, int w, int prefs, int mrefs, int parity, int mode); @@ -33,9 +30,6 @@ void ff_yadif_filter_line_ssse3(void *dst, void *prev, void *cur, void *next, int w, int prefs, int mrefs, int parity, int mode); -void ff_yadif_filter_line_16bit_mmxext(void *dst, void *prev, void *cur, - void *next, int w, int prefs, - int mrefs, int parity, int mode); void ff_yadif_filter_line_16bit_sse2(void *dst, void *prev, void *cur, void *next, int w, int prefs, int mrefs, int parity, int mode); @@ -46,9 +40,6 @@ void ff_yadif_filter_line_16bit_sse4(void *dst, void *prev, void *cur, void *next, int w, int prefs, int mrefs, int parity, int mode); -void ff_yadif_filter_line_10bit_mmxext(void *dst, void *prev, void *cur, - void *next, int w, int prefs, - int mrefs, int parity, int mode); void ff_yadif_filter_line_10bit_sse2(void *dst, void *prev, void *cur, void *next, int w, int prefs, int mrefs, int parity, int mode); @@ -63,10 +54,6 @@ av_cold void ff_yadif_init_x86(YADIFContext *yadif) : yadif->csp->comp[0].depth; if (bit_depth >= 15) { -#if ARCH_X86_32 - if (EXTERNAL_MMXEXT(cpu_flags)) - yadif->filter_line = ff_yadif_filter_line_16bit_mmxext; -#endif /* ARCH_X86_32 */ if (EXTERNAL_SSE2(cpu_flags)) yadif->filter_line = ff_yadif_filter_line_16bit_sse2; if (EXTERNAL_SSSE3(cpu_flags)) @@ -74,19 +61,11 @@ av_cold void ff_yadif_init_x86(YADIFContext *yadif) if (EXTERNAL_SSE4(cpu_flags)) yadif->filter_line = ff_yadif_filter_line_16bit_sse4; } else if ( bit_depth >= 9 && bit_depth <= 14) { -#if ARCH_X86_32 - if (EXTERNAL_MMXEXT(cpu_flags)) - yadif->filter_line = ff_yadif_filter_line_10bit_mmxext; -#endif /* ARCH_X86_32 */ if (EXTERNAL_SSE2(cpu_flags)) yadif->filter_line = ff_yadif_filter_line_10bit_sse2; if (EXTERNAL_SSSE3(cpu_flags)) yadif->filter_line = ff_yadif_filter_line_10bit_ssse3; } else { -#if ARCH_X86_32 - if (EXTERNAL_MMXEXT(cpu_flags)) - yadif->filter_line = ff_yadif_filter_line_mmxext; -#endif /* ARCH_X86_32 */ if (EXTERNAL_SSE2(cpu_flags)) yadif->filter_line = ff_yadif_filter_line_sse2; if (EXTERNAL_SSSE3(cpu_flags)) diff --git a/libavfilter/x86/yadif-10.asm b/libavfilter/x86/yadif-10.asm index 8853e0d2c..c6952db64 100644 --- a/libavfilter/x86/yadif-10.asm +++ b/libavfilter/x86/yadif-10.asm @@ -249,7 +249,3 @@ INIT_XMM ssse3 YADIF INIT_XMM sse2 YADIF -%if ARCH_X86_32 -INIT_MMX mmxext -YADIF -%endif diff --git a/libavfilter/x86/yadif-16.asm b/libavfilter/x86/yadif-16.asm index 9053b378a..09cc543d7 100644 --- a/libavfilter/x86/yadif-16.asm +++ b/libavfilter/x86/yadif-16.asm @@ -287,7 +287,3 @@ INIT_XMM ssse3 YADIF INIT_XMM sse2 YADIF -%if ARCH_X86_32 -INIT_MMX mmxext -YADIF -%endif diff --git a/libavformat/3dostr.c b/libavformat/3dostr.c index 0c136c9ea..fea12d03e 100644 --- a/libavformat/3dostr.c +++ b/libavformat/3dostr.c @@ -102,15 +102,15 @@ static int threedostr_read_header(AVFormatContext *s) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->sample_rate = avio_rb32(s->pb); - st->codecpar->channels = avio_rb32(s->pb); - if (st->codecpar->channels <= 0 || st->codecpar->sample_rate <= 0) + st->codecpar->ch_layout.nb_channels = avio_rb32(s->pb); + if (st->codecpar->ch_layout.nb_channels <= 0 || st->codecpar->sample_rate <= 0) return AVERROR_INVALIDDATA; codec = avio_rl32(s->pb); avio_skip(s->pb, 4); if (ctrl_size == 20 || ctrl_size == 3 || ctrl_size == -1) - st->duration = (avio_rb32(s->pb) - 1) / st->codecpar->channels; + st->duration = (avio_rb32(s->pb) - 1) / st->codecpar->ch_layout.nb_channels; else - st->duration = avio_rb32(s->pb) * 16 / st->codecpar->channels; + st->duration = avio_rb32(s->pb) * 16 / st->codecpar->ch_layout.nb_channels; size -= 56; found_shdr = 1; break; @@ -135,7 +135,7 @@ static int threedostr_read_header(AVFormatContext *s) switch (codec) { case MKTAG('S','D','X','2'): st->codecpar->codec_id = AV_CODEC_ID_SDX2_DPCM; - st->codecpar->block_align = 1 * st->codecpar->channels; + st->codecpar->block_align = 1 * st->codecpar->ch_layout.nb_channels; break; default: avpriv_request_sample(s, "codec %X", codec); @@ -178,7 +178,7 @@ static int threedostr_read_packet(AVFormatContext *s, AVPacket *pkt) ret = av_get_packet(s->pb, pkt, size); pkt->pos = pos; pkt->stream_index = 0; - pkt->duration = size / st->codecpar->channels; + pkt->duration = size / st->codecpar->ch_layout.nb_channels; return ret; default: av_log(s, AV_LOG_DEBUG, "skipping unknown chunk: %X\n", chunk); diff --git a/libavformat/4xm.c b/libavformat/4xm.c index e30756001..fdf6e4b84 100644 --- a/libavformat/4xm.c +++ b/libavformat/4xm.c @@ -190,13 +190,13 @@ static int parse_strk(AVFormatContext *s, st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_tag = 0; - st->codecpar->channels = fourxm->tracks[track].channels; + st->codecpar->ch_layout.nb_channels = fourxm->tracks[track].channels; st->codecpar->sample_rate = fourxm->tracks[track].sample_rate; st->codecpar->bits_per_coded_sample = fourxm->tracks[track].bits; - st->codecpar->bit_rate = (int64_t)st->codecpar->channels * + st->codecpar->bit_rate = (int64_t)st->codecpar->ch_layout.nb_channels * st->codecpar->sample_rate * st->codecpar->bits_per_coded_sample; - st->codecpar->block_align = st->codecpar->channels * + st->codecpar->block_align = st->codecpar->ch_layout.nb_channels * st->codecpar->bits_per_coded_sample; if (fourxm->tracks[track].adpcm){ diff --git a/libavformat/Makefile b/libavformat/Makefile index 84e73e3c6..6c6b77908 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -4,17 +4,22 @@ DESC = FFmpeg container format library HEADERS = avformat.h \ avio.h \ version.h \ + version_major.h \ OBJS = allformats.o \ + avformat.o \ avio.o \ aviobuf.o \ demux.o \ + demux_utils.o \ dump.o \ format.o \ id3v1.o \ id3v2.o \ + isom_tags.o \ metadata.o \ mux.o \ + mux_utils.o \ options.o \ os_support.o \ protocols.o \ @@ -23,11 +28,12 @@ OBJS = allformats.o \ seek.o \ url.o \ utils.o \ + version.o \ OBJS-$(HAVE_LIBC_MSVCRT) += file_open.o # subsystems -OBJS-$(CONFIG_ISO_MEDIA) += isom.o isom_tags.o +OBJS-$(CONFIG_ISO_MEDIA) += isom.o OBJS-$(CONFIG_NETWORK) += network.o OBJS-$(CONFIG_RIFFDEC) += riffdec.o OBJS-$(CONFIG_RIFFENC) += riffenc.o @@ -111,9 +117,9 @@ OBJS-$(CONFIG_ARGO_BRP_DEMUXER) += argo_brp.o argo_asf.o OBJS-$(CONFIG_ARGO_CVG_DEMUXER) += argo_cvg.o OBJS-$(CONFIG_ARGO_CVG_MUXER) += argo_cvg.o OBJS-$(CONFIG_ASF_DEMUXER) += asfdec_f.o asf.o asfcrypt.o \ - avlanguage.o + asf_tags.o avlanguage.o OBJS-$(CONFIG_ASF_O_DEMUXER) += asfdec_o.o asf.o asfcrypt.o \ - avlanguage.o + asf_tags.o avlanguage.o OBJS-$(CONFIG_ASF_MUXER) += asfenc.o asf.o avlanguage.o OBJS-$(CONFIG_ASS_DEMUXER) += assdec.o subtitles.o OBJS-$(CONFIG_ASS_MUXER) += assenc.o @@ -121,7 +127,7 @@ OBJS-$(CONFIG_AST_DEMUXER) += ast.o astdec.o OBJS-$(CONFIG_AST_MUXER) += ast.o astenc.o OBJS-$(CONFIG_AU_DEMUXER) += au.o pcm.o OBJS-$(CONFIG_AU_MUXER) += au.o rawenc.o -OBJS-$(CONFIG_AVI_DEMUXER) += avidec.o isom_tags.o +OBJS-$(CONFIG_AVI_DEMUXER) += avidec.o OBJS-$(CONFIG_AVI_MUXER) += avienc.o mpegtsenc.o avlanguage.o rawutils.o OBJS-$(CONFIG_AVM2_MUXER) += swfenc.o swf.o OBJS-$(CONFIG_AVR_DEMUXER) += avr.o pcm.o @@ -165,6 +171,8 @@ OBJS-$(CONFIG_DAUD_MUXER) += daudenc.o OBJS-$(CONFIG_DCSTR_DEMUXER) += dcstr.o OBJS-$(CONFIG_DERF_DEMUXER) += derf.o pcm.o OBJS-$(CONFIG_DFA_DEMUXER) += dfa.o +OBJS-$(CONFIG_DFPWM_DEMUXER) += dfpwmdec.o pcm.o +OBJS-$(CONFIG_DFPWM_MUXER) += rawenc.o OBJS-$(CONFIG_DHAV_DEMUXER) += dhav.o OBJS-$(CONFIG_DIRAC_DEMUXER) += diracdec.o rawdec.o OBJS-$(CONFIG_DIRAC_MUXER) += rawenc.o @@ -268,18 +276,22 @@ OBJS-$(CONFIG_IMAGE_GIF_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_J2K_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_JPEG_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_JPEGLS_PIPE_DEMUXER) += img2dec.o img2.o +OBJS-$(CONFIG_IMAGE_JPEGXL_PIPE_DEMUXER) += img2dec.o img2.o jpegxl_probe.o OBJS-$(CONFIG_IMAGE_PAM_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_PBM_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_PCX_PIPE_DEMUXER) += img2dec.o img2.o +OBJS-$(CONFIG_IMAGE_PFM_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_PGMYUV_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_PGM_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_PGX_PIPE_DEMUXER) += img2dec.o img2.o +OBJS-$(CONFIG_IMAGE_PHM_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_PHOTOCD_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_PICTOR_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_PNG_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_PPM_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_PSD_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_QDRAW_PIPE_DEMUXER) += img2dec.o img2.o +OBJS-$(CONFIG_IMAGE_QOI_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_SGI_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_SVG_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_SUNRAST_PIPE_DEMUXER) += img2dec.o img2.o @@ -316,11 +328,11 @@ OBJS-$(CONFIG_LXF_DEMUXER) += lxfdec.o OBJS-$(CONFIG_M4V_DEMUXER) += m4vdec.o rawdec.o OBJS-$(CONFIG_M4V_MUXER) += rawenc.o OBJS-$(CONFIG_MATROSKA_DEMUXER) += matroskadec.o matroska.o \ - flac_picture.o isom_tags.o rmsipr.o \ + flac_picture.o rmsipr.o \ oggparsevorbis.o vorbiscomment.o \ qtpalette.o replaygain.o dovi_isom.o OBJS-$(CONFIG_MATROSKA_MUXER) += matroskaenc.o matroska.o \ - av1.o avc.o hevc.o isom_tags.o \ + av1.o avc.o hevc.o \ flacenc_header.o avlanguage.o \ vorbiscomment.o wv.o dovi_isom.o OBJS-$(CONFIG_MCA_DEMUXER) += mca.o @@ -374,7 +386,7 @@ OBJS-$(CONFIG_MTV_DEMUXER) += mtv.o OBJS-$(CONFIG_MUSX_DEMUXER) += musx.o OBJS-$(CONFIG_MV_DEMUXER) += mvdec.o OBJS-$(CONFIG_MVI_DEMUXER) += mvi.o -OBJS-$(CONFIG_MXF_DEMUXER) += mxfdec.o mxf.o +OBJS-$(CONFIG_MXF_DEMUXER) += mxfdec.o mxf.o avlanguage.o OBJS-$(CONFIG_MXF_MUXER) += mxfenc.o mxf.o avc.o OBJS-$(CONFIG_MXG_DEMUXER) += mxg.o OBJS-$(CONFIG_NC_DEMUXER) += ncdec.o @@ -382,7 +394,7 @@ OBJS-$(CONFIG_NISTSPHERE_DEMUXER) += nistspheredec.o pcm.o OBJS-$(CONFIG_NSP_DEMUXER) += nspdec.o pcm.o OBJS-$(CONFIG_NSV_DEMUXER) += nsvdec.o OBJS-$(CONFIG_NULL_MUXER) += nullenc.o -OBJS-$(CONFIG_NUT_DEMUXER) += nutdec.o nut.o isom_tags.o +OBJS-$(CONFIG_NUT_DEMUXER) += nutdec.o nut.o OBJS-$(CONFIG_NUT_MUXER) += nutenc.o nut.o OBJS-$(CONFIG_NUV_DEMUXER) += nuv.o OBJS-$(CONFIG_AV1_DEMUXER) += av1dec.o @@ -505,7 +517,7 @@ 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 +OBJS-$(CONFIG_SCC_MUXER) += sccenc.o OBJS-$(CONFIG_SCD_DEMUXER) += scd.o OBJS-$(CONFIG_SDP_DEMUXER) += rtsp.o OBJS-$(CONFIG_SDR2_DEMUXER) += sdr2.o @@ -563,8 +575,8 @@ 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 -OBJS-$(CONFIG_V210X_DEMUXER) += v210.o +OBJS-$(CONFIG_V210_DEMUXER) += rawvideodec.o +OBJS-$(CONFIG_V210X_DEMUXER) += rawvideodec.o OBJS-$(CONFIG_VAG_DEMUXER) += vag.o OBJS-$(CONFIG_VC1_DEMUXER) += rawdec.o vc1dec.o OBJS-$(CONFIG_VC1_MUXER) += rawenc.o @@ -640,8 +652,8 @@ OBJS-$(CONFIG_HTTPPROXY_PROTOCOL) += http.o httpauth.o urldecode.o OBJS-$(CONFIG_HTTPS_PROTOCOL) += http.o httpauth.o urldecode.o OBJS-$(CONFIG_ICECAST_PROTOCOL) += icecast.o 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_MMSH_PROTOCOL) += mmsh.o mms.o asf_tags.o +OBJS-$(CONFIG_MMST_PROTOCOL) += mmst.o mms.o asf_tags.o OBJS-$(CONFIG_PIPE_PROTOCOL) += file.o OBJS-$(CONFIG_PROMPEG_PROTOCOL) += prompeg.o OBJS-$(CONFIG_RTMP_PROTOCOL) += rtmpproto.o rtmpdigest.o rtmppkt.o @@ -656,6 +668,8 @@ OBJS-$(CONFIG_SRTP_PROTOCOL) += srtpproto.o srtp.o OBJS-$(CONFIG_SUBFILE_PROTOCOL) += subfile.o OBJS-$(CONFIG_TEE_PROTOCOL) += teeproto.o tee_common.o OBJS-$(CONFIG_TCP_PROTOCOL) += tcp.o +OBJS-$(CONFIG_IPFS_PROTOCOL) += ipfsgateway.o +OBJS-$(CONFIG_IPNS_PROTOCOL) += ipfsgateway.o TLS-OBJS-$(CONFIG_GNUTLS) += tls_gnutls.o TLS-OBJS-$(CONFIG_LIBTLS) += tls_libtls.o TLS-OBJS-$(CONFIG_MBEDTLS) += tls_mbedtls.o @@ -707,6 +721,7 @@ SKIPHEADERS-$(CONFIG_NETWORK) += network.h rtsp.h TESTPROGS = seek \ url \ + seek_utils # async \ FIFO-MUXER-TESTPROGS-$(CONFIG_NETWORK) += fifo_muxer diff --git a/libavformat/a64.c b/libavformat/a64.c index 6e19162fe..a66f2542b 100644 --- a/libavformat/a64.c +++ b/libavformat/a64.c @@ -19,9 +19,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/intreadwrite.h" #include "libavcodec/codec_id.h" #include "libavcodec/codec_par.h" -#include "libavcodec/bytestream.h" #include "avformat.h" #include "rawenc.h" diff --git a/libavformat/aadec.c b/libavformat/aadec.c index b8a5428f1..e7b048b1f 100644 --- a/libavformat/aadec.c +++ b/libavformat/aadec.c @@ -24,6 +24,7 @@ */ #include "avformat.h" +#include "demux.h" #include "internal.h" #include "libavutil/avstring.h" #include "libavutil/dict.h" @@ -178,7 +179,7 @@ static int aa_read_header(AVFormatContext *s) } else if (!strcmp(codec_name, "acelp85")) { st->codecpar->codec_id = AV_CODEC_ID_SIPR; st->codecpar->block_align = 19; - st->codecpar->channels = 1; + st->codecpar->ch_layout.nb_channels = 1; st->codecpar->sample_rate = 8500; st->codecpar->bit_rate = 8500; sti->need_parsing = AVSTREAM_PARSE_FULL_RAW; @@ -186,7 +187,7 @@ static int aa_read_header(AVFormatContext *s) } else if (!strcmp(codec_name, "acelp16")) { st->codecpar->codec_id = AV_CODEC_ID_SIPR; st->codecpar->block_align = 20; - st->codecpar->channels = 1; + st->codecpar->ch_layout.nb_channels = 1; st->codecpar->sample_rate = 16000; st->codecpar->bit_rate = 16000; sti->need_parsing = AVSTREAM_PARSE_FULL_RAW; diff --git a/libavformat/aaxdec.c b/libavformat/aaxdec.c index b08ee036e..4e352f8ce 100644 --- a/libavformat/aaxdec.c +++ b/libavformat/aaxdec.c @@ -22,6 +22,7 @@ #include "libavutil/intreadwrite.h" #include "avformat.h" #include "avio_internal.h" +#include "demux.h" #include "internal.h" typedef struct AAXColumn { @@ -249,8 +250,14 @@ static int aax_read_header(AVFormatContext *s) start = avio_rb32(pb); size = avio_rb32(pb); + if (!size) + return AVERROR_INVALIDDATA; a->segments[r].start = start + a->data_offset; a->segments[r].end = a->segments[r].start + size; + if (r && + a->segments[r].start < a->segments[r-1].end && + a->segments[r].end > a->segments[r-1].start) + return AVERROR_INVALIDDATA; } else return AVERROR_INVALIDDATA; } @@ -279,9 +286,9 @@ static int aax_read_header(AVFormatContext *s) ret = ff_get_extradata(s, par, pb, extradata_size); if (ret < 0) return ret; - par->channels = AV_RB8 (par->extradata + 7); + par->ch_layout.nb_channels = AV_RB8 (par->extradata + 7); par->sample_rate = AV_RB32(par->extradata + 8); - if (!par->channels || !par->sample_rate) + if (!par->ch_layout.nb_channels || !par->sample_rate) return AVERROR_INVALIDDATA; avpriv_set_pts_info(st, 64, 32, par->sample_rate); @@ -299,7 +306,7 @@ static int aax_read_packet(AVFormatContext *s, AVPacket *pkt) AAXContext *a = s->priv_data; AVCodecParameters *par = s->streams[0]->codecpar; AVIOContext *pb = s->pb; - const int size = 18 * par->channels; + const int size = 18 * par->ch_layout.nb_channels; int ret, extradata_size = 0; uint8_t *extradata = NULL; int skip = 0; diff --git a/libavformat/ac3dec.c b/libavformat/ac3dec.c index ad9b65a9b..51461befd 100644 --- a/libavformat/ac3dec.c +++ b/libavformat/ac3dec.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/avassert.h" #include "libavutil/crc.h" #include "libavcodec/ac3_parser.h" diff --git a/libavformat/acedec.c b/libavformat/acedec.c index a52a0f0e5..6322af31f 100644 --- a/libavformat/acedec.c +++ b/libavformat/acedec.c @@ -74,7 +74,7 @@ static int ace_read_header(AVFormatContext *s) st->start_time = 0; par = st->codecpar; par->codec_type = AVMEDIA_TYPE_AUDIO; - par->channels = nb_channels; + par->ch_layout.nb_channels = nb_channels; par->sample_rate = rate; par->block_align = (codec == 4 ? 0x60 : codec == 5 ? 0x98 : 0xC0) * nb_channels; st->duration = (size / par->block_align) * 1024LL; @@ -85,7 +85,7 @@ static int ace_read_header(AVFormatContext *s) return ret; AV_WL16(st->codecpar->extradata, 1); - AV_WL16(st->codecpar->extradata+2, 2048 * par->channels); + AV_WL16(st->codecpar->extradata+2, 2048 * nb_channels); AV_WL16(st->codecpar->extradata+4, 0); AV_WL16(st->codecpar->extradata+6, codec == 4 ? 1 : 0); AV_WL16(st->codecpar->extradata+8, codec == 4 ? 1 : 0); diff --git a/libavformat/acm.c b/libavformat/acm.c index 0ee9114f7..28a040330 100644 --- a/libavformat/acm.c +++ b/libavformat/acm.c @@ -21,6 +21,7 @@ #include "libavutil/intreadwrite.h" #include "avformat.h" +#include "demux.h" #include "rawdec.h" #include "internal.h" @@ -48,12 +49,12 @@ static int acm_read_header(AVFormatContext *s) if (ret < 0) return ret; - st->codecpar->channels = AV_RL16(st->codecpar->extradata + 8); + st->codecpar->ch_layout.nb_channels = AV_RL16(st->codecpar->extradata + 8); st->codecpar->sample_rate = AV_RL16(st->codecpar->extradata + 10); - if (st->codecpar->channels <= 0 || st->codecpar->sample_rate <= 0) + if (st->codecpar->ch_layout.nb_channels <= 0 || st->codecpar->sample_rate <= 0) return AVERROR_INVALIDDATA; st->start_time = 0; - st->duration = AV_RL32(st->codecpar->extradata + 4) / st->codecpar->channels; + st->duration = AV_RL32(st->codecpar->extradata + 4) / st->codecpar->ch_layout.nb_channels; ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL_RAW; avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); diff --git a/libavformat/act.c b/libavformat/act.c index a36915764..da73fccec 100644 --- a/libavformat/act.c +++ b/libavformat/act.c @@ -18,11 +18,12 @@ * 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 "avio_internal.h" #include "riff.h" #include "internal.h" -#include "libavcodec/get_bits.h" #define CHUNK_SIZE 512 #define RIFF_TAG MKTAG('R','I','F','F') @@ -67,6 +68,7 @@ static int read_header(AVFormatContext *s) AVIOContext *pb = s->pb; int size; AVStream* st; + int ret; int min,sec,msec; @@ -76,7 +78,9 @@ static int read_header(AVFormatContext *s) avio_skip(pb, 16); size=avio_rl32(pb); - ff_get_wav_header(s, pb, st->codecpar, size, 0); + ret = ff_get_wav_header(s, pb, st->codecpar, size, 0); + if (ret < 0) + return ret; /* 8000Hz (Fine-rec) file format has 10 bytes long @@ -88,7 +92,7 @@ static int read_header(AVFormatContext *s) } st->codecpar->frame_size=80; - st->codecpar->channels=1; + st->codecpar->ch_layout.nb_channels = 1; avpriv_set_pts_info(st, 64, 1, 100); st->codecpar->codec_id=AV_CODEC_ID_G729; diff --git a/libavformat/adp.c b/libavformat/adp.c index 6d5f9d274..c9a5a0450 100644 --- a/libavformat/adp.c +++ b/libavformat/adp.c @@ -55,8 +55,7 @@ static int adp_read_header(AVFormatContext *s) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_ADPCM_DTK; - st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; - st->codecpar->channels = 2; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; st->codecpar->sample_rate = 48000; st->start_time = 0; if (s->pb->seekable & AVIO_SEEKABLE_NORMAL) diff --git a/libavformat/ads.c b/libavformat/ads.c index e7b419ce8..c19498490 100644 --- a/libavformat/ads.c +++ b/libavformat/ads.c @@ -48,11 +48,11 @@ static int ads_read_header(AVFormatContext *s) st->codecpar->sample_rate = avio_rl32(s->pb); if (st->codecpar->sample_rate <= 0) return AVERROR_INVALIDDATA; - st->codecpar->channels = avio_rl32(s->pb); - if (st->codecpar->channels <= 0) + st->codecpar->ch_layout.nb_channels = avio_rl32(s->pb); + if (st->codecpar->ch_layout.nb_channels <= 0) return AVERROR_INVALIDDATA; align = avio_rl32(s->pb); - if (align <= 0 || align > INT_MAX / st->codecpar->channels) + if (align <= 0 || align > INT_MAX / st->codecpar->ch_layout.nb_channels) return AVERROR_INVALIDDATA; if (codec == 1) @@ -60,11 +60,11 @@ static int ads_read_header(AVFormatContext *s) else st->codecpar->codec_id = AV_CODEC_ID_ADPCM_PSX; - st->codecpar->block_align = st->codecpar->channels * align; + st->codecpar->block_align = st->codecpar->ch_layout.nb_channels * align; avio_skip(s->pb, 12); size = avio_rl32(s->pb); if (st->codecpar->codec_id == AV_CODEC_ID_ADPCM_PSX && size >= 0x40) - st->duration = (size - 0x40) / 16 / st->codecpar->channels * 28; + st->duration = (size - 0x40) / 16 / st->codecpar->ch_layout.nb_channels * 28; avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); return 0; diff --git a/libavformat/adxdec.c b/libavformat/adxdec.c index d91d43d11..982e82542 100644 --- a/libavformat/adxdec.c +++ b/libavformat/adxdec.c @@ -25,6 +25,7 @@ #include "libavutil/intreadwrite.h" #include "avformat.h" +#include "demux.h" #include "internal.h" #define BLOCK_SIZE 18 @@ -56,12 +57,12 @@ static int adx_read_packet(AVFormatContext *s, AVPacket *pkt) if (avio_feof(s->pb)) return AVERROR_EOF; - if (par->channels <= 0) { - av_log(s, AV_LOG_ERROR, "invalid number of channels %d\n", par->channels); + if (par->ch_layout.nb_channels <= 0) { + av_log(s, AV_LOG_ERROR, "invalid number of channels %d\n", par->ch_layout.nb_channels); return AVERROR_INVALIDDATA; } - size = BLOCK_SIZE * par->channels; + size = BLOCK_SIZE * par->ch_layout.nb_channels; pkt->pos = avio_tell(s->pb); pkt->stream_index = 0; @@ -79,8 +80,8 @@ static int adx_read_packet(AVFormatContext *s, AVPacket *pkt) size = ret; } - pkt->duration = size / (BLOCK_SIZE * par->channels); - pkt->pts = (pkt->pos - c->header_size) / (BLOCK_SIZE * par->channels); + pkt->duration = size / (BLOCK_SIZE * par->ch_layout.nb_channels); + pkt->pts = (pkt->pos - c->header_size) / (BLOCK_SIZE * par->ch_layout.nb_channels); return 0; } @@ -90,6 +91,8 @@ static int adx_read_header(AVFormatContext *s) ADXDemuxerContext *c = s->priv_data; AVCodecParameters *par; int ret; + int channels; + AVStream *st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); @@ -107,11 +110,11 @@ static int adx_read_header(AVFormatContext *s) av_log(s, AV_LOG_ERROR, "Invalid extradata size.\n"); return AVERROR_INVALIDDATA; } - par->channels = AV_RB8 (par->extradata + 7); + channels = AV_RB8 (par->extradata + 7); par->sample_rate = AV_RB32(par->extradata + 8); - if (par->channels <= 0) { - av_log(s, AV_LOG_ERROR, "invalid number of channels %d\n", par->channels); + if (channels <= 0) { + av_log(s, AV_LOG_ERROR, "invalid number of channels %d\n", channels); return AVERROR_INVALIDDATA; } @@ -120,9 +123,10 @@ static int adx_read_header(AVFormatContext *s) return AVERROR_INVALIDDATA; } + par->ch_layout.nb_channels = channels; par->codec_type = AVMEDIA_TYPE_AUDIO; par->codec_id = s->iformat->raw_codec_id; - par->bit_rate = (int64_t)par->sample_rate * par->channels * BLOCK_SIZE * 8LL / BLOCK_SAMPLES; + par->bit_rate = (int64_t)par->sample_rate * par->ch_layout.nb_channels * BLOCK_SIZE * 8LL / BLOCK_SAMPLES; avpriv_set_pts_info(st, 64, BLOCK_SAMPLES, par->sample_rate); diff --git a/libavformat/aea.c b/libavformat/aea.c index 14d0840cf..f4b39e4f9 100644 --- a/libavformat/aea.c +++ b/libavformat/aea.c @@ -62,12 +62,13 @@ static int aea_read_probe(const AVProbeData *p) static int aea_read_header(AVFormatContext *s) { AVStream *st = avformat_new_stream(s, NULL); + int channels; if (!st) return AVERROR(ENOMEM); /* Parse the amount of channels and skip to pos 2048(0x800) */ avio_skip(s->pb, 264); - st->codecpar->channels = avio_r8(s->pb); + channels = avio_r8(s->pb); avio_skip(s->pb, 1783); @@ -76,14 +77,14 @@ static int aea_read_header(AVFormatContext *s) st->codecpar->sample_rate = 44100; st->codecpar->bit_rate = 292000; - if (st->codecpar->channels != 1 && st->codecpar->channels != 2) { - av_log(s, AV_LOG_ERROR, "Channels %d not supported!\n", st->codecpar->channels); + if (channels != 1 && channels != 2) { + av_log(s, AV_LOG_ERROR, "Channels %d not supported!\n", channels); return AVERROR_INVALIDDATA; } - st->codecpar->channel_layout = (st->codecpar->channels == 1) ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO; + av_channel_layout_default(&st->codecpar->ch_layout, channels); - st->codecpar->block_align = AT1_SU_SIZE * st->codecpar->channels; + st->codecpar->block_align = AT1_SU_SIZE * st->codecpar->ch_layout.nb_channels; return 0; } diff --git a/libavformat/afc.c b/libavformat/afc.c index 102b74bae..898c7d03e 100644 --- a/libavformat/afc.c +++ b/libavformat/afc.c @@ -38,12 +38,11 @@ static int afc_read_header(AVFormatContext *s) return AVERROR(ENOMEM); st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_ADPCM_AFC; - st->codecpar->channels = 2; - st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; if ((ret = ff_alloc_extradata(st->codecpar, 1)) < 0) return ret; - st->codecpar->extradata[0] = 8 * st->codecpar->channels; + st->codecpar->extradata[0] = 8 * st->codecpar->ch_layout.nb_channels; c->data_end = avio_rb32(s->pb) + 32LL; st->duration = avio_rb32(s->pb); diff --git a/libavformat/aiffdec.c b/libavformat/aiffdec.c index 7afadeb08..0487d3f02 100644 --- a/libavformat/aiffdec.c +++ b/libavformat/aiffdec.c @@ -22,6 +22,7 @@ #include "libavutil/intreadwrite.h" #include "libavutil/dict.h" #include "avformat.h" +#include "demux.h" #include "internal.h" #include "pcm.h" #include "aiff.h" @@ -53,9 +54,9 @@ static enum AVCodecID aiff_codec_get_id(int bps) } /* returns the size of the found tag */ -static int get_tag(AVIOContext *pb, uint32_t * tag) +static int64_t get_tag(AVIOContext *pb, uint32_t * tag) { - int size; + int64_t size; if (avio_feof(pb)) return AVERROR(EIO); @@ -63,16 +64,16 @@ static int get_tag(AVIOContext *pb, uint32_t * tag) *tag = avio_rl32(pb); size = avio_rb32(pb); - if (size < 0) - size = 0x7fffffff; - return size; } /* Metadata string read */ -static void get_meta(AVFormatContext *s, const char *key, int size) +static void get_meta(AVFormatContext *s, const char *key, int64_t size) { - uint8_t *str = av_malloc(size+1); + uint8_t *str = NULL; + + if (size < SIZE_MAX) + str = av_malloc(size+1); if (str) { int res = avio_read(s->pb, str, size); @@ -89,7 +90,7 @@ static void get_meta(AVFormatContext *s, const char *key, int size) } /* Returns the number of sound data frames or negative on error */ -static int get_aiff_header(AVFormatContext *s, int size, +static int get_aiff_header(AVFormatContext *s, int64_t size, unsigned version) { AVIOContext *pb = s->pb; @@ -99,14 +100,13 @@ static int get_aiff_header(AVFormatContext *s, int size, uint64_t val; int sample_rate; unsigned int num_frames; - - if (size == INT_MAX) - return AVERROR_INVALIDDATA; + int channels; if (size & 1) size++; par->codec_type = AVMEDIA_TYPE_AUDIO; - par->channels = avio_rb16(pb); + channels = avio_rb16(pb); + par->ch_layout.nb_channels = channels; num_frames = avio_rb32(pb); par->bits_per_coded_sample = avio_rb16(pb); @@ -154,10 +154,10 @@ static int get_aiff_header(AVFormatContext *s, int size, aiff->block_duration = 1; break; case AV_CODEC_ID_ADPCM_IMA_QT: - par->block_align = 34 * par->channels; + par->block_align = 34 * channels; break; case AV_CODEC_ID_MACE3: - par->block_align = 2 * par->channels; + par->block_align = 2 * channels; break; case AV_CODEC_ID_ADPCM_G726LE: par->bits_per_coded_sample = 5; @@ -165,7 +165,7 @@ static int get_aiff_header(AVFormatContext *s, int size, case AV_CODEC_ID_ADPCM_G722: case AV_CODEC_ID_MACE6: case AV_CODEC_ID_SDX2_DPCM: - par->block_align = 1 * par->channels; + par->block_align = 1 * channels; break; case AV_CODEC_ID_GSM: par->block_align = 33; @@ -182,7 +182,7 @@ static int get_aiff_header(AVFormatContext *s, int size, /* Block align needs to be computed in all cases, as the definition * is specific to applications -> here we use the WAVE format definition */ if (!par->block_align) - par->block_align = (av_get_bits_per_sample(par->codec_id) * par->channels) >> 3; + par->block_align = (av_get_bits_per_sample(par->codec_id) * channels) >> 3; if (aiff->block_duration) { par->bit_rate = av_rescale(par->sample_rate, par->block_align * 8LL, @@ -213,7 +213,8 @@ static int aiff_probe(const AVProbeData *p) /* aiff input */ static int aiff_read_header(AVFormatContext *s) { - int ret, size, filesize; + int ret; + int64_t filesize, size; int64_t offset = 0, position; uint32_t tag; unsigned version = AIFF_C_VERSION1; @@ -224,7 +225,7 @@ static int aiff_read_header(AVFormatContext *s) /* check FORM header */ filesize = get_tag(pb, &tag); - if (filesize < 0 || tag != MKTAG('F', 'O', 'R', 'M')) + if (filesize < 4 || tag != MKTAG('F', 'O', 'R', 'M')) return AVERROR_INVALIDDATA; /* AIFF data type */ @@ -251,10 +252,7 @@ static int aiff_read_header(AVFormatContext *s) if (size < 0) return size; - if (size >= 0x7fffffff - 8) - filesize = 0; - else - filesize -= size + 8; + filesize -= size + 8; switch (tag) { case MKTAG('C', 'O', 'M', 'M'): /* Common chunk */ diff --git a/libavformat/aiffenc.c b/libavformat/aiffenc.c index 1fd6b8a70..bdaf5c2c3 100644 --- a/libavformat/aiffenc.c +++ b/libavformat/aiffenc.c @@ -144,10 +144,10 @@ static int aiff_write_header(AVFormatContext *s) avio_wb32(pb, 0xA2805140); } - if (par->channels > 2 && par->channel_layout) { + if (par->ch_layout.order == AV_CHANNEL_ORDER_NATIVE && par->ch_layout.nb_channels > 2) { ffio_wfourcc(pb, "CHAN"); avio_wb32(pb, 12); - ff_mov_write_chan(pb, par->channel_layout); + ff_mov_write_chan(pb, par->ch_layout.u.mask); } put_meta(s, "title", MKTAG('N', 'A', 'M', 'E')); @@ -158,7 +158,7 @@ static int aiff_write_header(AVFormatContext *s) /* Common chunk */ ffio_wfourcc(pb, "COMM"); avio_wb32(pb, aifc ? 24 : 18); /* size */ - avio_wb16(pb, par->channels); /* Number of channels */ + avio_wb16(pb, par->ch_layout.nb_channels); /* Number of channels */ aiff->frames = avio_tell(pb); avio_wb32(pb, 0); /* Number of frames */ @@ -170,7 +170,7 @@ static int aiff_write_header(AVFormatContext *s) return AVERROR(EINVAL); } if (!par->block_align) - par->block_align = (par->bits_per_coded_sample * par->channels) >> 3; + par->block_align = (par->bits_per_coded_sample * par->ch_layout.nb_channels) >> 3; avio_wb16(pb, par->bits_per_coded_sample); /* Sample size */ diff --git a/libavformat/aixdec.c b/libavformat/aixdec.c index 59c3d60da..f7d8e17ac 100644 --- a/libavformat/aixdec.c +++ b/libavformat/aixdec.c @@ -21,6 +21,7 @@ #include "libavutil/intreadwrite.h" #include "avformat.h" +#include "demux.h" #include "internal.h" static int aix_probe(const AVProbeData *p) @@ -64,7 +65,7 @@ static int aix_read_header(AVFormatContext *s) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_ADPCM_ADX; st->codecpar->sample_rate = avio_rb32(s->pb); - st->codecpar->channels = avio_r8(s->pb); + st->codecpar->ch_layout.nb_channels = avio_r8(s->pb); avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); avio_skip(s->pb, 3); } diff --git a/libavformat/allformats.c b/libavformat/allformats.c index d066a7745..32698b857 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -81,6 +81,7 @@ extern const AVOutputFormat ff_au_muxer; extern const AVInputFormat ff_av1_demuxer; extern const AVInputFormat ff_avi_demuxer; extern const AVOutputFormat ff_avi_muxer; +extern const AVOutputFormat ff_avif_muxer; extern const AVInputFormat ff_avisynth_demuxer; extern const AVOutputFormat ff_avm2_muxer; extern const AVInputFormat ff_avr_demuxer; @@ -124,6 +125,8 @@ extern const AVOutputFormat ff_daud_muxer; extern const AVInputFormat ff_dcstr_demuxer; extern const AVInputFormat ff_derf_demuxer; extern const AVInputFormat ff_dfa_demuxer; +extern const AVInputFormat ff_dfpwm_demuxer; +extern const AVOutputFormat ff_dfpwm_muxer; extern const AVInputFormat ff_dhav_demuxer; extern const AVInputFormat ff_dirac_demuxer; extern const AVOutputFormat ff_dirac_muxer; @@ -508,22 +511,27 @@ extern const AVInputFormat ff_image_gif_pipe_demuxer; extern const AVInputFormat ff_image_j2k_pipe_demuxer; extern const AVInputFormat ff_image_jpeg_pipe_demuxer; extern const AVInputFormat ff_image_jpegls_pipe_demuxer; +extern const AVInputFormat ff_image_jpegxl_pipe_demuxer; extern const AVInputFormat ff_image_pam_pipe_demuxer; extern const AVInputFormat ff_image_pbm_pipe_demuxer; extern const AVInputFormat ff_image_pcx_pipe_demuxer; +extern const AVInputFormat ff_image_pfm_pipe_demuxer; extern const AVInputFormat ff_image_pgmyuv_pipe_demuxer; extern const AVInputFormat ff_image_pgm_pipe_demuxer; extern const AVInputFormat ff_image_pgx_pipe_demuxer; +extern const AVInputFormat ff_image_phm_pipe_demuxer; extern const AVInputFormat ff_image_photocd_pipe_demuxer; extern const AVInputFormat ff_image_pictor_pipe_demuxer; extern const AVInputFormat ff_image_png_pipe_demuxer; extern const AVInputFormat ff_image_ppm_pipe_demuxer; extern const AVInputFormat ff_image_psd_pipe_demuxer; extern const AVInputFormat ff_image_qdraw_pipe_demuxer; +extern const AVInputFormat ff_image_qoi_pipe_demuxer; extern const AVInputFormat ff_image_sgi_pipe_demuxer; extern const AVInputFormat ff_image_svg_pipe_demuxer; extern const AVInputFormat ff_image_sunrast_pipe_demuxer; extern const AVInputFormat ff_image_tiff_pipe_demuxer; +extern const AVInputFormat ff_image_vbn_pipe_demuxer; extern const AVInputFormat ff_image_webp_pipe_demuxer; extern const AVInputFormat ff_image_xbm_pipe_demuxer; extern const AVInputFormat ff_image_xpm_pipe_demuxer; diff --git a/libavformat/alp.c b/libavformat/alp.c index f46bdb451..40e4890a3 100644 --- a/libavformat/alp.c +++ b/libavformat/alp.c @@ -20,6 +20,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/channel_layout.h" #include "avformat.h" #include "internal.h" @@ -119,18 +121,14 @@ static int alp_read_header(AVFormatContext *s) par->codec_id = AV_CODEC_ID_ADPCM_IMA_ALP; par->format = AV_SAMPLE_FMT_S16; par->sample_rate = hdr->sample_rate; - par->channels = hdr->num_channels; - if (hdr->num_channels == 1) - par->channel_layout = AV_CH_LAYOUT_MONO; - else if (hdr->num_channels == 2) - par->channel_layout = AV_CH_LAYOUT_STEREO; - else + if (hdr->num_channels > 2 || hdr->num_channels == 0) return AVERROR_INVALIDDATA; + av_channel_layout_default(&par->ch_layout, hdr->num_channels); par->bits_per_coded_sample = 4; par->block_align = 1; - par->bit_rate = par->channels * + par->bit_rate = par->ch_layout.nb_channels * par->sample_rate * par->bits_per_coded_sample; @@ -148,7 +146,7 @@ static int alp_read_packet(AVFormatContext *s, AVPacket *pkt) pkt->flags &= ~AV_PKT_FLAG_CORRUPT; pkt->stream_index = 0; - pkt->duration = ret * 2 / par->channels; + pkt->duration = ret * 2 / par->ch_layout.nb_channels; return 0; } @@ -202,7 +200,7 @@ static int alp_write_init(AVFormatContext *s) return AVERROR(EINVAL); } - if (par->channels > 2) { + if (par->ch_layout.nb_channels > 2) { av_log(s, AV_LOG_ERROR, "A maximum of 2 channels are supported\n"); return AVERROR(EINVAL); } @@ -228,7 +226,7 @@ static int alp_write_header(AVFormatContext *s) avio_wl32(s->pb, alp->type == ALP_TYPE_PCM ? 12 : 8); avio_write(s->pb, "ADPCM", 6); avio_w8(s->pb, 0); - avio_w8(s->pb, par->channels); + avio_w8(s->pb, par->ch_layout.nb_channels); if (alp->type == ALP_TYPE_PCM) avio_wl32(s->pb, par->sample_rate); diff --git a/libavformat/amr.c b/libavformat/amr.c index bc22c2f84..88f07ce0b 100644 --- a/libavformat/amr.c +++ b/libavformat/amr.c @@ -23,6 +23,8 @@ Write and read amr data according to RFC3267, http://www.ietf.org/rfc/rfc3267.txt?number=3267 */ +#include "config_components.h" + #include "libavutil/channel_layout.h" #include "libavutil/intreadwrite.h" #include "avformat.h" @@ -100,33 +102,31 @@ static int amr_read_header(AVFormatContext *s) 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->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; back = read - sizeof(AMR_header); } else if (!memcmp(header, AMRWB_header, sizeof(AMRWB_header))) { 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->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; back = read - sizeof(AMRWB_header); } else if (!memcmp(header, AMRMC_header, sizeof(AMRMC_header))) { 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 = AV_RL32(header + 12); + st->codecpar->ch_layout.nb_channels = AV_RL32(header + 12); back = read - 4 - sizeof(AMRMC_header); } else if (!memcmp(header, AMRWBMC_header, sizeof(AMRWBMC_header))) { 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 = AV_RL32(header + 15); + st->codecpar->ch_layout.nb_channels = AV_RL32(header + 15); back = read - 4 - sizeof(AMRWBMC_header); } else { return AVERROR_INVALIDDATA; } - if (st->codecpar->channels < 1) + if (st->codecpar->ch_layout.nb_channels < 1) return AVERROR_INVALIDDATA; st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; @@ -188,8 +188,7 @@ static int amrnb_read_header(AVFormatContext *s) return AVERROR(ENOMEM); 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->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL_RAW; avpriv_set_pts_info(st, 64, 1, 8000); @@ -246,8 +245,7 @@ static int amrwb_read_header(AVFormatContext *s) return AVERROR(ENOMEM); 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->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL_RAW; avpriv_set_pts_info(st, 64, 1, 16000); diff --git a/libavformat/amvenc.c b/libavformat/amvenc.c index fece2f49b..28d4879b1 100644 --- a/libavformat/amvenc.c +++ b/libavformat/amvenc.c @@ -244,9 +244,9 @@ static void amv_write_alist(AVFormatContext *s, AVCodecParameters *par) /* Bodge an (incorrect) WAVEFORMATEX (+2 pad bytes) */ tag_str = ff_start_tag(pb, "strf"); AV_WL16(buf + 0, 1); - AV_WL16(buf + 2, par->channels); + AV_WL16(buf + 2, par->ch_layout.nb_channels); AV_WL32(buf + 4, par->sample_rate); - AV_WL32(buf + 8, par->sample_rate * par->channels * 2); + AV_WL32(buf + 8, par->sample_rate * par->ch_layout.nb_channels * 2); AV_WL16(buf + 12, 2); AV_WL16(buf + 14, 16); AV_WL16(buf + 16, 0); diff --git a/libavformat/anm.c b/libavformat/anm.c index 1c29bbca2..7feba4ed1 100644 --- a/libavformat/anm.c +++ b/libavformat/anm.c @@ -26,6 +26,7 @@ #include "libavutil/intreadwrite.h" #include "avformat.h" +#include "demux.h" #include "internal.h" typedef struct Page { diff --git a/libavformat/apc.c b/libavformat/apc.c index 56151bb59..b8b18c966 100644 --- a/libavformat/apc.c +++ b/libavformat/apc.c @@ -23,7 +23,7 @@ #include "libavutil/channel_layout.h" #include "avformat.h" -#include "internal.h" +#include "demux.h" static int apc_probe(const AVProbeData *p) { @@ -38,6 +38,7 @@ static int apc_read_header(AVFormatContext *s) AVIOContext *pb = s->pb; AVStream *st; int ret; + int channels; avio_rl32(pb); /* CRYO */ avio_rl32(pb); /* _APC */ @@ -57,16 +58,11 @@ static int apc_read_header(AVFormatContext *s) if ((ret = ff_get_extradata(s, st->codecpar, pb, 2 * 4)) < 0) return ret; - if (avio_rl32(pb)) { - st->codecpar->channels = 2; - st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; - } else { - st->codecpar->channels = 1; - st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; - } + channels = !!avio_rl32(pb) + 1; + av_channel_layout_default(&st->codecpar->ch_layout, channels); st->codecpar->bits_per_coded_sample = 4; - st->codecpar->bit_rate = (int64_t)st->codecpar->bits_per_coded_sample * st->codecpar->channels + st->codecpar->bit_rate = (int64_t)st->codecpar->bits_per_coded_sample * channels * st->codecpar->sample_rate; st->codecpar->block_align = 1; diff --git a/libavformat/ape.c b/libavformat/ape.c index b1222d9ce..bf1254e7b 100644 --- a/libavformat/ape.c +++ b/libavformat/ape.c @@ -42,8 +42,8 @@ typedef struct APEFrame { int64_t pos; + int64_t size; int nblocks; - int size; int skip; int64_t pts; } APEFrame; @@ -128,7 +128,7 @@ static void ape_dumpinfo(AVFormatContext * s, APEContext * ape_ctx) av_log(s, AV_LOG_DEBUG, "\nFrames\n\n"); for (i = 0; i < ape_ctx->totalframes; i++) - av_log(s, AV_LOG_DEBUG, "%8d %8"PRId64" %8d (%d samples)\n", i, + av_log(s, AV_LOG_DEBUG, "%8d %8"PRId64" %8"PRId64" (%d samples)\n", i, ape_ctx->frames[i].pos, ape_ctx->frames[i].size, ape_ctx->frames[i].nblocks); @@ -146,7 +146,8 @@ static int ape_read_header(AVFormatContext * s) AVStream *st; uint32_t tag; int i, ret; - int total_blocks, final_size = 0; + int total_blocks; + int64_t final_size = 0; int64_t pts, file_size; /* Skip any leading junk such as id3v2 tags */ @@ -331,7 +332,7 @@ static int ape_read_header(AVFormatContext * s) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_APE; st->codecpar->codec_tag = MKTAG('A', 'P', 'E', ' '); - st->codecpar->channels = ape->channels; + st->codecpar->ch_layout.nb_channels = ape->channels; st->codecpar->sample_rate = ape->samplerate; st->codecpar->bits_per_coded_sample = ape->bps; @@ -387,7 +388,7 @@ static int ape_read_packet(AVFormatContext * s, AVPacket * pkt) if (ape->frames[ape->currentframe].size <= 0 || ape->frames[ape->currentframe].size > INT_MAX - extra_size) { - av_log(s, AV_LOG_ERROR, "invalid packet size: %d\n", + av_log(s, AV_LOG_ERROR, "invalid packet size: %8"PRId64"\n", ape->frames[ape->currentframe].size); ape->currentframe++; return AVERROR(EIO); diff --git a/libavformat/apetag.c b/libavformat/apetag.c index 6f82fbe20..e861aac0f 100644 --- a/libavformat/apetag.c +++ b/libavformat/apetag.c @@ -22,12 +22,13 @@ #include -#include "libavutil/intreadwrite.h" #include "libavutil/dict.h" #include "avformat.h" #include "avio_internal.h" #include "apetag.h" +#include "demux.h" #include "internal.h" +#include "mux.h" #define APE_TAG_FLAG_CONTAINS_HEADER (1U << 31) #define APE_TAG_FLAG_LACKS_FOOTER (1 << 30) diff --git a/libavformat/apm.c b/libavformat/apm.c index 1ced77174..baf7d2f94 100644 --- a/libavformat/apm.c +++ b/libavformat/apm.c @@ -19,6 +19,9 @@ * 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_components.h" + #include "avformat.h" #include "internal.h" #include "rawenc.h" @@ -104,6 +107,7 @@ static int apm_read_header(AVFormatContext *s) APMExtraData extradata; AVCodecParameters *par; uint8_t buf[APM_FILE_EXTRADATA_SIZE]; + int channels; if (!(st = avformat_new_stream(s, NULL))) return AVERROR(ENOMEM); @@ -116,7 +120,7 @@ static int apm_read_header(AVFormatContext *s) return AVERROR_INVALIDDATA; par = st->codecpar; - par->channels = avio_rl16(s->pb); + channels = avio_rl16(s->pb); par->sample_rate = avio_rl32(s->pb); /* Skip the bitrate, it's usually wrong anyway. */ @@ -136,17 +140,14 @@ static int apm_read_header(AVFormatContext *s) if (par->bits_per_coded_sample != 4) return AVERROR_INVALIDDATA; - if (par->channels == 2) - par->channel_layout = AV_CH_LAYOUT_STEREO; - else if (par->channels == 1) - par->channel_layout = AV_CH_LAYOUT_MONO; - else + if (channels > 2 || channels == 0) return AVERROR_INVALIDDATA; + av_channel_layout_default(&par->ch_layout, channels); par->codec_type = AVMEDIA_TYPE_AUDIO; par->codec_id = AV_CODEC_ID_ADPCM_IMA_APM; par->format = AV_SAMPLE_FMT_S16; - par->bit_rate = par->channels * + par->bit_rate = par->ch_layout.nb_channels * par->sample_rate * par->bits_per_coded_sample; @@ -175,7 +176,7 @@ static int apm_read_header(AVFormatContext *s) st->start_time = 0; st->duration = extradata.data_size * (8 / par->bits_per_coded_sample) / - par->channels; + par->ch_layout.nb_channels; return 0; } @@ -195,7 +196,7 @@ static int apm_read_packet(AVFormatContext *s, AVPacket *pkt) pkt->flags &= ~AV_PKT_FLAG_CORRUPT; pkt->stream_index = 0; - pkt->duration = ret * (8 / par->bits_per_coded_sample) / par->channels; + pkt->duration = ret * (8 / par->bits_per_coded_sample) / par->ch_layout.nb_channels; return 0; } @@ -227,7 +228,7 @@ static int apm_write_init(AVFormatContext *s) return AVERROR(EINVAL); } - if (par->channels > 2) { + if (par->ch_layout.nb_channels > 2) { av_log(s, AV_LOG_ERROR, "APM files only support up to 2 channels\n"); return AVERROR(EINVAL); } @@ -260,10 +261,10 @@ static int apm_write_header(AVFormatContext *s) * be used because of the extra 2 bytes. */ avio_wl16(s->pb, APM_TAG_CODEC); - avio_wl16(s->pb, par->channels); + avio_wl16(s->pb, par->ch_layout.nb_channels); avio_wl32(s->pb, par->sample_rate); /* This is the wrong calculation, but it's what the orginal files have. */ - avio_wl32(s->pb, par->sample_rate * par->channels * 2); + avio_wl32(s->pb, par->sample_rate * par->ch_layout.nb_channels * 2); avio_wl16(s->pb, par->block_align); avio_wl16(s->pb, par->bits_per_coded_sample); avio_wl32(s->pb, APM_FILE_EXTRADATA_SIZE); diff --git a/libavformat/apngdec.c b/libavformat/apngdec.c index e84f74e9d..47cdbfcbf 100644 --- a/libavformat/apngdec.c +++ b/libavformat/apngdec.c @@ -222,7 +222,7 @@ static int apng_read_header(AVFormatContext *s) ctx->num_frames, ctx->num_play); break; case MKTAG('f', 'c', 'T', 'L'): - if (!acTL_found || len != 26) { + if (!acTL_found || len != APNG_FCTL_CHUNK_SIZE) { return AVERROR_INVALIDDATA; } if ((ret = avio_seek(pb, -8, SEEK_CUR)) < 0) @@ -336,7 +336,7 @@ static int apng_read_packet(AVFormatContext *s, AVPacket *pkt) switch (tag) { case MKTAG('f', 'c', 'T', 'L'): - if (len != 26) + if (len != APNG_FCTL_CHUNK_SIZE) return AVERROR_INVALIDDATA; if ((ret = decode_fctl_chunk(s, ctx, pkt)) < 0) diff --git a/libavformat/apngenc.c b/libavformat/apngenc.c index 767074ecf..cddb148d5 100644 --- a/libavformat/apngenc.c +++ b/libavformat/apngenc.c @@ -22,14 +22,13 @@ */ #include "avformat.h" -#include "internal.h" #include "libavutil/avassert.h" #include "libavutil/crc.h" #include "libavutil/intreadwrite.h" #include "libavutil/log.h" #include "libavutil/opt.h" -#include "libavcodec/png.h" #include "libavcodec/apng.h" +#include "libavcodec/png.h" typedef struct APNGMuxContext { AVClass *class; @@ -49,10 +48,11 @@ typedef struct APNGMuxContext { int extra_data_size; } APNGMuxContext; -static uint8_t *apng_find_chunk(uint32_t tag, uint8_t *buf, size_t length) +static const uint8_t *apng_find_chunk(uint32_t tag, const uint8_t *buf, + size_t length) { size_t b; - for (b = 0; b < length; b += AV_RB32(buf + b) + 12) + for (b = 0; AV_RB32(buf + b) + 12ULL <= length - b; b += AV_RB32(buf + b) + 12ULL) if (AV_RB32(&buf[b + 4]) == tag) return &buf[b]; return NULL; @@ -135,15 +135,15 @@ static int flush_packet(AVFormatContext *format_context, AVPacket *packet) } if (apng->frame_number == 0 && !packet) { - uint8_t *existing_acTL_chunk; - uint8_t *existing_fcTL_chunk; + const uint8_t *existing_acTL_chunk; + const uint8_t *existing_fcTL_chunk; av_log(format_context, AV_LOG_INFO, "Only a single frame so saving as a normal PNG.\n"); // Write normal PNG headers without acTL chunk existing_acTL_chunk = apng_find_chunk(MKBETAG('a', 'c', 'T', 'L'), apng->extra_data, apng->extra_data_size); if (existing_acTL_chunk) { - uint8_t *chunk_after_acTL = existing_acTL_chunk + AV_RB32(existing_acTL_chunk) + 12; + const uint8_t *chunk_after_acTL = existing_acTL_chunk + AV_RB32(existing_acTL_chunk) + 12; avio_write(io_context, apng->extra_data, existing_acTL_chunk - apng->extra_data); avio_write(io_context, chunk_after_acTL, apng->extra_data + apng->extra_data_size - chunk_after_acTL); } else { @@ -153,17 +153,18 @@ static int flush_packet(AVFormatContext *format_context, AVPacket *packet) // Write frame data without fcTL chunk existing_fcTL_chunk = apng_find_chunk(MKBETAG('f', 'c', 'T', 'L'), apng->prev_packet->data, apng->prev_packet->size); if (existing_fcTL_chunk) { - uint8_t *chunk_after_fcTL = existing_fcTL_chunk + AV_RB32(existing_fcTL_chunk) + 12; + const uint8_t *chunk_after_fcTL = existing_fcTL_chunk + AV_RB32(existing_fcTL_chunk) + 12; avio_write(io_context, apng->prev_packet->data, existing_fcTL_chunk - apng->prev_packet->data); avio_write(io_context, chunk_after_fcTL, apng->prev_packet->data + apng->prev_packet->size - chunk_after_fcTL); } else { avio_write(io_context, apng->prev_packet->data, apng->prev_packet->size); } } else { - uint8_t *existing_fcTL_chunk; + const uint8_t *data, *data_end; + const uint8_t *existing_fcTL_chunk; if (apng->frame_number == 0) { - uint8_t *existing_acTL_chunk; + const uint8_t *existing_acTL_chunk; // Write normal PNG headers avio_write(io_context, apng->extra_data, apng->extra_data_size); @@ -179,15 +180,22 @@ static int flush_packet(AVFormatContext *format_context, AVPacket *packet) } } + data = apng->prev_packet->data; + data_end = data + apng->prev_packet->size; existing_fcTL_chunk = apng_find_chunk(MKBETAG('f', 'c', 'T', 'L'), apng->prev_packet->data, apng->prev_packet->size); if (existing_fcTL_chunk) { AVRational delay; + if (AV_RB32(existing_fcTL_chunk) != APNG_FCTL_CHUNK_SIZE) + return AVERROR_INVALIDDATA; + existing_fcTL_chunk += 8; delay.num = AV_RB16(existing_fcTL_chunk + 20); delay.den = AV_RB16(existing_fcTL_chunk + 22); if (delay.num == 0 && delay.den == 0) { + uint8_t new_fcTL_chunk[APNG_FCTL_CHUNK_SIZE]; + if (packet) { int64_t delay_num_raw = (packet->dts - apng->prev_packet->dts) * codec_stream->time_base.num; int64_t delay_den_raw = codec_stream->time_base.den; @@ -203,16 +211,20 @@ static int flush_packet(AVFormatContext *format_context, AVPacket *packet) delay = apng->prev_delay; } + avio_write(io_context, data, (existing_fcTL_chunk - 8) - data); + data = existing_fcTL_chunk + APNG_FCTL_CHUNK_SIZE + 4 /* CRC-32 */; // Update frame control header with new delay - AV_WB16(existing_fcTL_chunk + 20, delay.num); - AV_WB16(existing_fcTL_chunk + 22, delay.den); - AV_WB32(existing_fcTL_chunk + 26, ~av_crc(av_crc_get_table(AV_CRC_32_IEEE_LE), ~0U, existing_fcTL_chunk - 4, 26 + 4)); + memcpy(new_fcTL_chunk, existing_fcTL_chunk, sizeof(new_fcTL_chunk)); + AV_WB16(new_fcTL_chunk + 20, delay.num); + AV_WB16(new_fcTL_chunk + 22, delay.den); + apng_write_chunk(io_context, MKBETAG('f', 'c', 'T', 'L'), + new_fcTL_chunk, sizeof(new_fcTL_chunk)); } apng->prev_delay = delay; } // Write frame data - avio_write(io_context, apng->prev_packet->data, apng->prev_packet->size); + avio_write(io_context, data, data_end - data); } ++apng->frame_number; diff --git a/libavformat/aptxdec.c b/libavformat/aptxdec.c index 7153e262a..693316eeb 100644 --- a/libavformat/aptxdec.c +++ b/libavformat/aptxdec.c @@ -20,6 +20,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/opt.h" #include "avformat.h" @@ -42,7 +44,7 @@ static AVStream *aptx_read_header_common(AVFormatContext *s) return NULL; st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->format = AV_SAMPLE_FMT_S32P; - st->codecpar->channels = 2; + st->codecpar->ch_layout.nb_channels = 2; st->codecpar->sample_rate = s1->sample_rate; st->start_time = 0; return st; diff --git a/libavformat/argo_asf.c b/libavformat/argo_asf.c index d26844d1e..39a60a0dd 100644 --- a/libavformat/argo_asf.c +++ b/libavformat/argo_asf.c @@ -19,6 +19,9 @@ * 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_components.h" + #include "libavutil/avstring.h" #include "avformat.h" #include "internal.h" @@ -96,11 +99,9 @@ int ff_argo_asf_fill_stream(AVFormatContext *s, AVStream *st, const ArgoASFFileH st->codecpar->format = AV_SAMPLE_FMT_S16P; if (ckhdr->flags & ASF_CF_STEREO) { - st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; - st->codecpar->channels = 2; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; } else { - st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; - st->codecpar->channels = 1; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; } /* v1.1 files (FX Fighter) are all marked as 44100, but are actually 22050. */ @@ -121,11 +122,11 @@ int ff_argo_asf_fill_stream(AVFormatContext *s, AVStream *st, const ArgoASFFileH * (nchannel control bytes) + ((bytes_per_channel) * nchannel) * For mono, this is 17. For stereo, this is 34. */ - st->codecpar->block_align = st->codecpar->channels + + st->codecpar->block_align = st->codecpar->ch_layout.nb_channels + (ckhdr->num_samples / 2) * - st->codecpar->channels; + st->codecpar->ch_layout.nb_channels; - st->codecpar->bit_rate = st->codecpar->channels * + st->codecpar->bit_rate = st->codecpar->ch_layout.nb_channels * st->codecpar->sample_rate * st->codecpar->bits_per_coded_sample; @@ -305,12 +306,12 @@ static int argo_asf_write_init(AVFormatContext *s) return AVERROR(EINVAL); } - if (par->channels > 2) { + if (par->ch_layout.nb_channels > 2) { av_log(s, AV_LOG_ERROR, "ASF files only support up to 2 channels\n"); return AVERROR(EINVAL); } - if (par->block_align != 17 * par->channels) + if (par->block_align != 17 * par->ch_layout.nb_channels) return AVERROR(EINVAL); if (par->sample_rate > UINT16_MAX) { @@ -392,7 +393,7 @@ static int argo_asf_write_header(AVFormatContext *s) chdr.unk2 = ~0; chdr.flags = ASF_CF_BITS_PER_SAMPLE | ASF_CF_ALWAYS1; - if (par->channels == 2) + if (par->ch_layout.nb_channels == 2) chdr.flags |= ASF_CF_STEREO; argo_asf_write_file_header(&fhdr, s->pb); diff --git a/libavformat/argo_asf.h b/libavformat/argo_asf.h index 1fab31a90..948459d0b 100644 --- a/libavformat/argo_asf.h +++ b/libavformat/argo_asf.h @@ -24,7 +24,7 @@ #define AVFORMAT_ARGO_ASF_H #include -#include "libavutil/common.h" +#include "libavutil/macros.h" #include "avformat.h" diff --git a/libavformat/argo_cvg.c b/libavformat/argo_cvg.c index c5da32536..f32487023 100644 --- a/libavformat/argo_cvg.c +++ b/libavformat/argo_cvg.c @@ -20,6 +20,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/avstring.h" #include "libavutil/channel_layout.h" #include "avformat.h" @@ -182,8 +184,7 @@ static int argo_cvg_read_header(AVFormatContext *s) break; } - par->channels = 1; - par->channel_layout = AV_CH_LAYOUT_MONO; + par->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; par->bits_per_coded_sample = 4; par->block_align = ARGO_CVG_BLOCK_ALIGN; @@ -275,7 +276,7 @@ static int argo_cvg_write_init(AVFormatContext *s) return AVERROR(EINVAL); } - if (par->channels != 1) { + if (par->ch_layout.nb_channels != 1) { av_log(s, AV_LOG_ERROR, "CVG files only support 1 channel\n"); return AVERROR(EINVAL); } @@ -335,19 +336,14 @@ static int argo_cvg_write_trailer(AVFormatContext *s) ArgoCVGMuxContext *ctx = s->priv_data; int64_t ret; + ctx->checksum += (ctx->size & 255) + + ((ctx->size>> 8) & 255) + + ((ctx->size>>16) & 255) + + (ctx->size>>24); + av_log(s, AV_LOG_TRACE, "size = %zu\n", ctx->size); av_log(s, AV_LOG_TRACE, "checksum = %u\n", ctx->checksum); - /* - * NB: This is wrong. We're always slightly under the original. - * Verified by remuxing. For reference (orig - remuxed): - * - TCLD.CVG: 4706074 - 4705696 = 378 - * - DANLOOP1.CVG: 5684641 - 5684212 = 429 - * - CRYS.CVG: 2495499 - 2495367 = 132 - * - PICKUP88.CVG: 1348091 - 1347937 = 154 - * - SELECT1.CVG: 549987 - 549752 = 235 - * Also NB: it doesn't matter, the game doesn't check them. - */ avio_wl32(s->pb, ctx->checksum); if ((ret = avio_seek(s->pb, 0, SEEK_SET)) < 0) diff --git a/libavformat/asf.c b/libavformat/asf.c index 1ac8b5f07..128506222 100644 --- a/libavformat/asf.c +++ b/libavformat/asf.c @@ -19,138 +19,10 @@ */ #include "asf.h" +#include "demux.h" #include "id3v2.h" #include "internal.h" -const ff_asf_guid ff_asf_header = { - 0x30, 0x26, 0xB2, 0x75, 0x8E, 0x66, 0xCF, 0x11, 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C -}; - -const ff_asf_guid ff_asf_file_header = { - 0xA1, 0xDC, 0xAB, 0x8C, 0x47, 0xA9, 0xCF, 0x11, 0x8E, 0xE4, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 -}; - -const ff_asf_guid ff_asf_stream_header = { - 0x91, 0x07, 0xDC, 0xB7, 0xB7, 0xA9, 0xCF, 0x11, 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 -}; - -const ff_asf_guid ff_asf_ext_stream_header = { - 0xCB, 0xA5, 0xE6, 0x14, 0x72, 0xC6, 0x32, 0x43, 0x83, 0x99, 0xA9, 0x69, 0x52, 0x06, 0x5B, 0x5A -}; - -const ff_asf_guid ff_asf_audio_stream = { - 0x40, 0x9E, 0x69, 0xF8, 0x4D, 0x5B, 0xCF, 0x11, 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B -}; - -const ff_asf_guid ff_asf_audio_conceal_spread = { - 0x50, 0xCD, 0xC3, 0xBF, 0x8F, 0x61, 0xCF, 0x11, 0x8B, 0xB2, 0x00, 0xAA, 0x00, 0xB4, 0xE2, 0x20 -}; - -const ff_asf_guid ff_asf_video_stream = { - 0xC0, 0xEF, 0x19, 0xBC, 0x4D, 0x5B, 0xCF, 0x11, 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B -}; - -const ff_asf_guid ff_asf_jfif_media = { - 0x00, 0xE1, 0x1B, 0xB6, 0x4E, 0x5B, 0xCF, 0x11, 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B -}; - -const ff_asf_guid ff_asf_video_conceal_none = { - 0x00, 0x57, 0xFB, 0x20, 0x55, 0x5B, 0xCF, 0x11, 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B -}; - -const ff_asf_guid ff_asf_command_stream = { - 0xC0, 0xCF, 0xDA, 0x59, 0xE6, 0x59, 0xD0, 0x11, 0xA3, 0xAC, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6 -}; - -const ff_asf_guid ff_asf_comment_header = { - 0x33, 0x26, 0xb2, 0x75, 0x8E, 0x66, 0xCF, 0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c -}; - -const ff_asf_guid ff_asf_codec_comment_header = { - 0x40, 0x52, 0xD1, 0x86, 0x1D, 0x31, 0xD0, 0x11, 0xA3, 0xA4, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6 -}; -const ff_asf_guid ff_asf_codec_comment1_header = { - 0x41, 0x52, 0xd1, 0x86, 0x1D, 0x31, 0xD0, 0x11, 0xa3, 0xa4, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6 -}; - -const ff_asf_guid ff_asf_data_header = { - 0x36, 0x26, 0xb2, 0x75, 0x8E, 0x66, 0xCF, 0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c -}; - -const ff_asf_guid ff_asf_head1_guid = { - 0xb5, 0x03, 0xbf, 0x5f, 0x2E, 0xA9, 0xCF, 0x11, 0x8e, 0xe3, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65 -}; - -const ff_asf_guid ff_asf_head2_guid = { - 0x11, 0xd2, 0xd3, 0xab, 0xBA, 0xA9, 0xCF, 0x11, 0x8e, 0xe6, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65 -}; - -const ff_asf_guid ff_asf_extended_content_header = { - 0x40, 0xA4, 0xD0, 0xD2, 0x07, 0xE3, 0xD2, 0x11, 0x97, 0xF0, 0x00, 0xA0, 0xC9, 0x5E, 0xA8, 0x50 -}; - -const ff_asf_guid ff_asf_simple_index_header = { - 0x90, 0x08, 0x00, 0x33, 0xB1, 0xE5, 0xCF, 0x11, 0x89, 0xF4, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xCB -}; - -const ff_asf_guid ff_asf_ext_stream_embed_stream_header = { - 0xe2, 0x65, 0xfb, 0x3a, 0xEF, 0x47, 0xF2, 0x40, 0xac, 0x2c, 0x70, 0xa9, 0x0d, 0x71, 0xd3, 0x43 -}; - -const ff_asf_guid ff_asf_ext_stream_audio_stream = { - 0x9d, 0x8c, 0x17, 0x31, 0xE1, 0x03, 0x28, 0x45, 0xb5, 0x82, 0x3d, 0xf9, 0xdb, 0x22, 0xf5, 0x03 -}; - -const ff_asf_guid ff_asf_metadata_header = { - 0xea, 0xcb, 0xf8, 0xc5, 0xaf, 0x5b, 0x77, 0x48, 0x84, 0x67, 0xaa, 0x8c, 0x44, 0xfa, 0x4c, 0xca -}; - -const ff_asf_guid ff_asf_metadata_library_header = { - 0x94, 0x1c, 0x23, 0x44, 0x98, 0x94, 0xd1, 0x49, 0xa1, 0x41, 0x1d, 0x13, 0x4e, 0x45, 0x70, 0x54 -}; - -const ff_asf_guid ff_asf_marker_header = { - 0x01, 0xCD, 0x87, 0xF4, 0x51, 0xA9, 0xCF, 0x11, 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 -}; - -const ff_asf_guid ff_asf_reserved_4 = { - 0x20, 0xdb, 0xfe, 0x4c, 0xf6, 0x75, 0xCF, 0x11, 0x9c, 0x0f, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xcb -}; - -/* I am not a number !!! This GUID is the one found on the PC used to - * generate the stream */ -const ff_asf_guid ff_asf_my_guid = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -const ff_asf_guid ff_asf_language_guid = { - 0xa9, 0x46, 0x43, 0x7c, 0xe0, 0xef, 0xfc, 0x4b, 0xb2, 0x29, 0x39, 0x3e, 0xde, 0x41, 0x5c, 0x85 -}; - -const ff_asf_guid ff_asf_content_encryption = { - 0xfb, 0xb3, 0x11, 0x22, 0x23, 0xbd, 0xd2, 0x11, 0xb4, 0xb7, 0x00, 0xa0, 0xc9, 0x55, 0xfc, 0x6e -}; - -const ff_asf_guid ff_asf_ext_content_encryption = { - 0x14, 0xe6, 0x8a, 0x29, 0x22, 0x26, 0x17, 0x4c, 0xb9, 0x35, 0xda, 0xe0, 0x7e, 0xe9, 0x28, 0x9c -}; - -const ff_asf_guid ff_asf_digital_signature = { - 0xfc, 0xb3, 0x11, 0x22, 0x23, 0xbd, 0xd2, 0x11, 0xb4, 0xb7, 0x00, 0xa0, 0xc9, 0x55, 0xfc, 0x6e -}; - -const ff_asf_guid ff_asf_extended_stream_properties_object = { - 0xcb, 0xa5, 0xe6, 0x14, 0x72, 0xc6, 0x32, 0x43, 0x83, 0x99, 0xa9, 0x69, 0x52, 0x06, 0x5b, 0x5a -}; - -const ff_asf_guid ff_asf_group_mutual_exclusion_object = { - 0x40, 0x5a, 0x46, 0xd1, 0x79, 0x5a, 0x38, 0x43, 0xb7, 0x1b, 0xe3, 0x6b, 0x8f, 0xd6, 0xc2, 0x49 -}; - -const ff_asf_guid ff_asf_mutex_language = { - 0x00, 0x2a, 0xe2, 0xd6, 0xda, 0x35, 0xd1, 0x11, 0x90, 0x34, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xbe -}; - /* List of official tags at http://msdn.microsoft.com/en-us/library/dd743066(VS.85).aspx */ const AVMetadataConv ff_asf_metadata_conv[] = { { "WM/AlbumArtist", "album_artist" }, diff --git a/libavformat/asf_tags.c b/libavformat/asf_tags.c new file mode 100644 index 000000000..53d886f18 --- /dev/null +++ b/libavformat/asf_tags.c @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2000, 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 "asf.h" + +const ff_asf_guid ff_asf_header = { + 0x30, 0x26, 0xB2, 0x75, 0x8E, 0x66, 0xCF, 0x11, 0xA6, 0xD9, 0x00, 0xAA, 0x00, 0x62, 0xCE, 0x6C +}; + +const ff_asf_guid ff_asf_file_header = { + 0xA1, 0xDC, 0xAB, 0x8C, 0x47, 0xA9, 0xCF, 0x11, 0x8E, 0xE4, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 +}; + +const ff_asf_guid ff_asf_stream_header = { + 0x91, 0x07, 0xDC, 0xB7, 0xB7, 0xA9, 0xCF, 0x11, 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 +}; + +const ff_asf_guid ff_asf_ext_stream_header = { + 0xCB, 0xA5, 0xE6, 0x14, 0x72, 0xC6, 0x32, 0x43, 0x83, 0x99, 0xA9, 0x69, 0x52, 0x06, 0x5B, 0x5A +}; + +const ff_asf_guid ff_asf_audio_stream = { + 0x40, 0x9E, 0x69, 0xF8, 0x4D, 0x5B, 0xCF, 0x11, 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B +}; + +const ff_asf_guid ff_asf_audio_conceal_spread = { + 0x50, 0xCD, 0xC3, 0xBF, 0x8F, 0x61, 0xCF, 0x11, 0x8B, 0xB2, 0x00, 0xAA, 0x00, 0xB4, 0xE2, 0x20 +}; + +const ff_asf_guid ff_asf_video_stream = { + 0xC0, 0xEF, 0x19, 0xBC, 0x4D, 0x5B, 0xCF, 0x11, 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B +}; + +const ff_asf_guid ff_asf_jfif_media = { + 0x00, 0xE1, 0x1B, 0xB6, 0x4E, 0x5B, 0xCF, 0x11, 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B +}; + +const ff_asf_guid ff_asf_video_conceal_none = { + 0x00, 0x57, 0xFB, 0x20, 0x55, 0x5B, 0xCF, 0x11, 0xA8, 0xFD, 0x00, 0x80, 0x5F, 0x5C, 0x44, 0x2B +}; + +const ff_asf_guid ff_asf_command_stream = { + 0xC0, 0xCF, 0xDA, 0x59, 0xE6, 0x59, 0xD0, 0x11, 0xA3, 0xAC, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6 +}; + +const ff_asf_guid ff_asf_comment_header = { + 0x33, 0x26, 0xb2, 0x75, 0x8E, 0x66, 0xCF, 0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c +}; + +const ff_asf_guid ff_asf_codec_comment_header = { + 0x40, 0x52, 0xD1, 0x86, 0x1D, 0x31, 0xD0, 0x11, 0xA3, 0xA4, 0x00, 0xA0, 0xC9, 0x03, 0x48, 0xF6 +}; +const ff_asf_guid ff_asf_codec_comment1_header = { + 0x41, 0x52, 0xd1, 0x86, 0x1D, 0x31, 0xD0, 0x11, 0xa3, 0xa4, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6 +}; + +const ff_asf_guid ff_asf_data_header = { + 0x36, 0x26, 0xb2, 0x75, 0x8E, 0x66, 0xCF, 0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c +}; + +const ff_asf_guid ff_asf_head1_guid = { + 0xb5, 0x03, 0xbf, 0x5f, 0x2E, 0xA9, 0xCF, 0x11, 0x8e, 0xe3, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65 +}; + +const ff_asf_guid ff_asf_head2_guid = { + 0x11, 0xd2, 0xd3, 0xab, 0xBA, 0xA9, 0xCF, 0x11, 0x8e, 0xe6, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65 +}; + +const ff_asf_guid ff_asf_extended_content_header = { + 0x40, 0xA4, 0xD0, 0xD2, 0x07, 0xE3, 0xD2, 0x11, 0x97, 0xF0, 0x00, 0xA0, 0xC9, 0x5E, 0xA8, 0x50 +}; + +const ff_asf_guid ff_asf_simple_index_header = { + 0x90, 0x08, 0x00, 0x33, 0xB1, 0xE5, 0xCF, 0x11, 0x89, 0xF4, 0x00, 0xA0, 0xC9, 0x03, 0x49, 0xCB +}; + +const ff_asf_guid ff_asf_ext_stream_embed_stream_header = { + 0xe2, 0x65, 0xfb, 0x3a, 0xEF, 0x47, 0xF2, 0x40, 0xac, 0x2c, 0x70, 0xa9, 0x0d, 0x71, 0xd3, 0x43 +}; + +const ff_asf_guid ff_asf_ext_stream_audio_stream = { + 0x9d, 0x8c, 0x17, 0x31, 0xE1, 0x03, 0x28, 0x45, 0xb5, 0x82, 0x3d, 0xf9, 0xdb, 0x22, 0xf5, 0x03 +}; + +const ff_asf_guid ff_asf_metadata_header = { + 0xea, 0xcb, 0xf8, 0xc5, 0xaf, 0x5b, 0x77, 0x48, 0x84, 0x67, 0xaa, 0x8c, 0x44, 0xfa, 0x4c, 0xca +}; + +const ff_asf_guid ff_asf_metadata_library_header = { + 0x94, 0x1c, 0x23, 0x44, 0x98, 0x94, 0xd1, 0x49, 0xa1, 0x41, 0x1d, 0x13, 0x4e, 0x45, 0x70, 0x54 +}; + +const ff_asf_guid ff_asf_marker_header = { + 0x01, 0xCD, 0x87, 0xF4, 0x51, 0xA9, 0xCF, 0x11, 0x8E, 0xE6, 0x00, 0xC0, 0x0C, 0x20, 0x53, 0x65 +}; + +const ff_asf_guid ff_asf_reserved_4 = { + 0x20, 0xdb, 0xfe, 0x4c, 0xf6, 0x75, 0xCF, 0x11, 0x9c, 0x0f, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xcb +}; + +/* I am not a number !!! This GUID is the one found on the PC used to + * generate the stream */ +const ff_asf_guid ff_asf_my_guid = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +const ff_asf_guid ff_asf_language_guid = { + 0xa9, 0x46, 0x43, 0x7c, 0xe0, 0xef, 0xfc, 0x4b, 0xb2, 0x29, 0x39, 0x3e, 0xde, 0x41, 0x5c, 0x85 +}; + +const ff_asf_guid ff_asf_content_encryption = { + 0xfb, 0xb3, 0x11, 0x22, 0x23, 0xbd, 0xd2, 0x11, 0xb4, 0xb7, 0x00, 0xa0, 0xc9, 0x55, 0xfc, 0x6e +}; + +const ff_asf_guid ff_asf_ext_content_encryption = { + 0x14, 0xe6, 0x8a, 0x29, 0x22, 0x26, 0x17, 0x4c, 0xb9, 0x35, 0xda, 0xe0, 0x7e, 0xe9, 0x28, 0x9c +}; + +const ff_asf_guid ff_asf_digital_signature = { + 0xfc, 0xb3, 0x11, 0x22, 0x23, 0xbd, 0xd2, 0x11, 0xb4, 0xb7, 0x00, 0xa0, 0xc9, 0x55, 0xfc, 0x6e +}; + +const ff_asf_guid ff_asf_extended_stream_properties_object = { + 0xcb, 0xa5, 0xe6, 0x14, 0x72, 0xc6, 0x32, 0x43, 0x83, 0x99, 0xa9, 0x69, 0x52, 0x06, 0x5b, 0x5a +}; + +const ff_asf_guid ff_asf_group_mutual_exclusion_object = { + 0x40, 0x5a, 0x46, 0xd1, 0x79, 0x5a, 0x38, 0x43, 0xb7, 0x1b, 0xe3, 0x6b, 0x8f, 0xd6, 0xc2, 0x49 +}; + +const ff_asf_guid ff_asf_mutex_language = { + 0x00, 0x2a, 0xe2, 0xd6, 0xda, 0x35, 0xd1, 0x11, 0x90, 0x34, 0x00, 0xa0, 0xc9, 0x03, 0x49, 0xbe +}; diff --git a/libavformat/asfcrypt.c b/libavformat/asfcrypt.c index 221a8a89b..c77e37503 100644 --- a/libavformat/asfcrypt.c +++ b/libavformat/asfcrypt.c @@ -20,10 +20,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include "libavutil/bswap.h" -#include "libavutil/common.h" #include "libavutil/des.h" #include "libavutil/intreadwrite.h" +#include "libavutil/mem.h" #include "libavutil/rc4.h" #include "asfcrypt.h" diff --git a/libavformat/asfdec_f.c b/libavformat/asfdec_f.c index a8f36ed28..bdbd4271c 100644 --- a/libavformat/asfdec_f.c +++ b/libavformat/asfdec_f.c @@ -33,6 +33,7 @@ #include "avformat.h" #include "avio_internal.h" #include "avlanguage.h" +#include "demux.h" #include "internal.h" #include "riff.h" #include "asf.h" @@ -103,7 +104,7 @@ typedef struct ASFContext { int ts_is_pts; int packet_multi_size; int packet_time_delta; - int packet_time_start; + int64_t packet_time_start; int64_t packet_pos; int stream_index; @@ -270,7 +271,7 @@ finish: avio_seek(s->pb, off + len, SEEK_SET); } -static int asf_read_file_properties(AVFormatContext *s, int64_t size) +static int asf_read_file_properties(AVFormatContext *s) { ASFContext *asf = s->priv_data; AVIOContext *pb = s->pb; @@ -465,7 +466,7 @@ static int asf_read_stream_properties(AVFormatContext *s, int64_t size) return 0; } -static int asf_read_ext_stream_properties(AVFormatContext *s, int64_t size) +static int asf_read_ext_stream_properties(AVFormatContext *s) { ASFContext *asf = s->priv_data; AVIOContext *pb = s->pb; @@ -525,7 +526,7 @@ static int asf_read_ext_stream_properties(AVFormatContext *s, int64_t size) return 0; } -static int asf_read_content_desc(AVFormatContext *s, int64_t size) +static int asf_read_content_desc(AVFormatContext *s) { AVIOContext *pb = s->pb; int len1, len2, len3, len4, len5; @@ -544,7 +545,7 @@ static int asf_read_content_desc(AVFormatContext *s, int64_t size) return 0; } -static int asf_read_ext_content_desc(AVFormatContext *s, int64_t size) +static int asf_read_ext_content_desc(AVFormatContext *s) { AVIOContext *pb = s->pb; ASFContext *asf = s->priv_data; @@ -578,7 +579,7 @@ static int asf_read_ext_content_desc(AVFormatContext *s, int64_t size) return 0; } -static int asf_read_language_list(AVFormatContext *s, int64_t size) +static int asf_read_language_list(AVFormatContext *s) { AVIOContext *pb = s->pb; ASFContext *asf = s->priv_data; @@ -598,7 +599,7 @@ static int asf_read_language_list(AVFormatContext *s, int64_t size) return 0; } -static int asf_read_metadata(AVFormatContext *s, int64_t size) +static int asf_read_metadata(AVFormatContext *s) { AVIOContext *pb = s->pb; ASFContext *asf = s->priv_data; @@ -646,7 +647,7 @@ static int asf_read_metadata(AVFormatContext *s, int64_t size) return 0; } -static int asf_read_marker(AVFormatContext *s, int64_t size) +static int asf_read_marker(AVFormatContext *s) { AVIOContext *pb = s->pb; ASFContext *asf = s->priv_data; @@ -725,21 +726,21 @@ static int asf_read_header(AVFormatContext *s) if (gsize < 24) return AVERROR_INVALIDDATA; if (!ff_guidcmp(&g, &ff_asf_file_header)) { - ret = asf_read_file_properties(s, gsize); + ret = asf_read_file_properties(s); } else if (!ff_guidcmp(&g, &ff_asf_stream_header)) { ret = asf_read_stream_properties(s, gsize); } else if (!ff_guidcmp(&g, &ff_asf_comment_header)) { - asf_read_content_desc(s, gsize); + asf_read_content_desc(s); } else if (!ff_guidcmp(&g, &ff_asf_language_guid)) { - asf_read_language_list(s, gsize); + asf_read_language_list(s); } else if (!ff_guidcmp(&g, &ff_asf_extended_content_header)) { - asf_read_ext_content_desc(s, gsize); + asf_read_ext_content_desc(s); } else if (!ff_guidcmp(&g, &ff_asf_metadata_header)) { - asf_read_metadata(s, gsize); + asf_read_metadata(s); } else if (!ff_guidcmp(&g, &ff_asf_metadata_library_header)) { - asf_read_metadata(s, gsize); + asf_read_metadata(s); } else if (!ff_guidcmp(&g, &ff_asf_ext_stream_header)) { - asf_read_ext_stream_properties(s, gsize); + asf_read_ext_stream_properties(s); // there could be an optional stream properties object to follow // if so the next iteration will pick it up @@ -749,7 +750,7 @@ static int asf_read_header(AVFormatContext *s) avio_skip(pb, 6); continue; } else if (!ff_guidcmp(&g, &ff_asf_marker_header)) { - asf_read_marker(s, gsize); + asf_read_marker(s); } else if (avio_feof(pb)) { return AVERROR_EOF; } else { @@ -1216,10 +1217,12 @@ static int asf_parse_packet(AVFormatContext *s, AVIOContext *pb, AVPacket *pkt) if ((ret = av_new_packet(&asf_st->pkt, asf_st->packet_obj_size)) < 0) return ret; asf_st->seq = asf->packet_seq; - if (asf->ts_is_pts) { - asf_st->pkt.pts = asf->packet_frag_timestamp - asf->hdr.preroll; - } else - asf_st->pkt.dts = asf->packet_frag_timestamp - asf->hdr.preroll; + if (asf->packet_frag_timestamp != AV_NOPTS_VALUE) { + if (asf->ts_is_pts) { + asf_st->pkt.pts = asf->packet_frag_timestamp - asf->hdr.preroll; + } else + asf_st->pkt.dts = asf->packet_frag_timestamp - asf->hdr.preroll; + } asf_st->pkt.stream_index = asf->stream_index; asf_st->pkt.pos = asf_st->packet_pos = asf->packet_pos; asf_st->pkt_clean = 0; diff --git a/libavformat/asfdec_o.c b/libavformat/asfdec_o.c index fb614d42d..907be6de0 100644 --- a/libavformat/asfdec_o.c +++ b/libavformat/asfdec_o.c @@ -27,8 +27,8 @@ #include "libavutil/time_internal.h" #include "avformat.h" -#include "avio_internal.h" #include "avlanguage.h" +#include "demux.h" #include "internal.h" #include "riff.h" #include "asf.h" diff --git a/libavformat/asfenc.c b/libavformat/asfenc.c index 041019b18..e1563b1da 100644 --- a/libavformat/asfenc.c +++ b/libavformat/asfenc.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/avassert.h" #include "libavutil/dict.h" #include "libavutil/mathematics.h" @@ -27,6 +29,7 @@ #include "avlanguage.h" #include "avio_internal.h" #include "internal.h" +#include "mux.h" #include "riff.h" #include "asf.h" diff --git a/libavformat/assdec.c b/libavformat/assdec.c index 2ab7fb9ef..0915f6faf 100644 --- a/libavformat/assdec.c +++ b/libavformat/assdec.c @@ -25,7 +25,6 @@ #include "avformat.h" #include "internal.h" #include "subtitles.h" -#include "libavcodec/internal.h" #include "libavutil/bprint.h" typedef struct ASSContext { diff --git a/libavformat/astdec.c b/libavformat/astdec.c index 629372acf..f812f6437 100644 --- a/libavformat/astdec.c +++ b/libavformat/astdec.c @@ -57,14 +57,14 @@ static int ast_read_header(AVFormatContext *s) return AVERROR_INVALIDDATA; } - st->codecpar->channels = avio_rb16(s->pb); - if (!st->codecpar->channels) + st->codecpar->ch_layout.nb_channels = avio_rb16(s->pb); + if (!st->codecpar->ch_layout.nb_channels) return AVERROR_INVALIDDATA; - if (st->codecpar->channels == 2) - st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; - else if (st->codecpar->channels == 4) - st->codecpar->channel_layout = AV_CH_LAYOUT_4POINT0; + if (st->codecpar->ch_layout.nb_channels == 2) + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; + else if (st->codecpar->ch_layout.nb_channels == 4) + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_4POINT0; avio_skip(s->pb, 2); st->codecpar->sample_rate = avio_rb32(s->pb); @@ -90,10 +90,11 @@ static int ast_read_packet(AVFormatContext *s, AVPacket *pkt) pos = avio_tell(s->pb); type = avio_rl32(s->pb); size = avio_rb32(s->pb); - if (!s->streams[0]->codecpar->channels || size > INT_MAX / s->streams[0]->codecpar->channels) + if (!s->streams[0]->codecpar->ch_layout.nb_channels || + size > INT_MAX / s->streams[0]->codecpar->ch_layout.nb_channels) return AVERROR_INVALIDDATA; - size *= s->streams[0]->codecpar->channels; + size *= s->streams[0]->codecpar->ch_layout.nb_channels; if ((ret = avio_skip(s->pb, 24)) < 0) // padding return ret; diff --git a/libavformat/astenc.c b/libavformat/astenc.c index a5792e0b0..b29cfc4aa 100644 --- a/libavformat/astenc.c +++ b/libavformat/astenc.c @@ -84,7 +84,7 @@ static int ast_write_header(AVFormatContext *s) avio_wb32(pb, 0); /* File size minus header */ avio_wb16(pb, codec_tag); avio_wb16(pb, 16); /* Bit depth */ - avio_wb16(pb, par->channels); + avio_wb16(pb, par->ch_layout.nb_channels); avio_wb16(pb, 0); /* Loop flag */ avio_wb32(pb, par->sample_rate); @@ -109,7 +109,7 @@ static int ast_write_packet(AVFormatContext *s, AVPacket *pkt) AVIOContext *pb = s->pb; ASTMuxContext *ast = s->priv_data; AVCodecParameters *par = s->streams[0]->codecpar; - int size = pkt->size / par->channels; + int size = pkt->size / par->ch_layout.nb_channels; if (s->streams[0]->nb_frames == 0) ast->fbs = size; diff --git a/libavformat/async.c b/libavformat/async.c index 5a81507ef..547417aa1 100644 --- a/libavformat/async.c +++ b/libavformat/async.c @@ -47,7 +47,7 @@ typedef struct RingBuffer { - AVFifoBuffer *fifo; + AVFifo *fifo; int read_back_capacity; int read_pos; @@ -83,7 +83,7 @@ typedef struct Context { static int ring_init(RingBuffer *ring, unsigned int capacity, int read_back_capacity) { memset(ring, 0, sizeof(RingBuffer)); - ring->fifo = av_fifo_alloc(capacity + read_back_capacity); + ring->fifo = av_fifo_alloc2(capacity + read_back_capacity, 1, 0); if (!ring->fifo) return AVERROR(ENOMEM); @@ -93,45 +93,59 @@ static int ring_init(RingBuffer *ring, unsigned int capacity, int read_back_capa static void ring_destroy(RingBuffer *ring) { - av_fifo_freep(&ring->fifo); + av_fifo_freep2(&ring->fifo); } static void ring_reset(RingBuffer *ring) { - av_fifo_reset(ring->fifo); + av_fifo_reset2(ring->fifo); ring->read_pos = 0; } static int ring_size(RingBuffer *ring) { - return av_fifo_size(ring->fifo) - ring->read_pos; + return av_fifo_can_read(ring->fifo) - ring->read_pos; } static int ring_space(RingBuffer *ring) { - return av_fifo_space(ring->fifo); + return av_fifo_can_write(ring->fifo); } -static int ring_generic_read(RingBuffer *ring, void *dest, int buf_size, void (*func)(void*, void*, int)) +static int ring_read(RingBuffer *ring, void *dest, int buf_size) { - int ret; + int ret = 0; av_assert2(buf_size <= ring_size(ring)); - ret = av_fifo_generic_peek_at(ring->fifo, dest, ring->read_pos, buf_size, func); + if (dest) + ret = av_fifo_peek(ring->fifo, dest, buf_size, ring->read_pos); ring->read_pos += buf_size; if (ring->read_pos > ring->read_back_capacity) { - av_fifo_drain(ring->fifo, ring->read_pos - ring->read_back_capacity); + av_fifo_drain2(ring->fifo, ring->read_pos - ring->read_back_capacity); ring->read_pos = ring->read_back_capacity; } return ret; } -static int ring_generic_write(RingBuffer *ring, void *src, int size, int (*func)(void*, void*, int)) +static int wrapped_url_read(void *src, void *dst, size_t *size) +{ + URLContext *h = src; + Context *c = h->priv_data; + int ret; + + ret = ffurl_read(c->inner, dst, *size); + *size = ret > 0 ? ret : 0; + c->inner_io_error = ret < 0 ? ret : 0; + + return c->inner_io_error; +} + +static int ring_write(RingBuffer *ring, URLContext *h, size_t size) { av_assert2(size <= ring_space(ring)); - return av_fifo_generic_write(ring->fifo, src, size, func); + return av_fifo_write_from_cb(ring->fifo, wrapped_url_read, h, &size); } static int ring_size_of_read_back(RingBuffer *ring) @@ -161,18 +175,6 @@ static int async_check_interrupt(void *arg) return c->abort_request; } -static int wrapped_url_read(void *src, void *dst, int size) -{ - URLContext *h = src; - Context *c = h->priv_data; - int ret; - - ret = ffurl_read(c->inner, dst, size); - c->inner_io_error = ret < 0 ? ret : 0; - - return ret; -} - static void *async_buffer_task(void *arg) { URLContext *h = arg; @@ -221,7 +223,7 @@ static void *async_buffer_task(void *arg) pthread_mutex_unlock(&c->mutex); to_copy = FFMIN(4096, fifo_space); - ret = ring_generic_write(ring, (void *)h, to_copy, wrapped_url_read); + ret = ring_write(ring, h, to_copy); pthread_mutex_lock(&c->mutex); if (ret <= 0) { @@ -327,11 +329,11 @@ static int async_close(URLContext *h) return 0; } -static int async_read_internal(URLContext *h, void *dest, int size, int read_complete, - void (*func)(void*, void*, int)) +static int async_read_internal(URLContext *h, void *dest, int size) { Context *c = h->priv_data; RingBuffer *ring = &c->ring; + int read_complete = !dest; int to_read = size; int ret = 0; @@ -346,8 +348,8 @@ static int async_read_internal(URLContext *h, void *dest, int size, int read_com fifo_size = ring_size(ring); to_copy = FFMIN(to_read, fifo_size); if (to_copy > 0) { - ring_generic_read(ring, dest, to_copy, func); - if (!func) + ring_read(ring, dest, to_copy); + if (dest) dest = (uint8_t *)dest + to_copy; c->logical_pos += to_copy; to_read -= to_copy; @@ -376,11 +378,7 @@ static int async_read_internal(URLContext *h, void *dest, int size, int read_com static int async_read(URLContext *h, unsigned char *buf, int size) { - return async_read_internal(h, buf, size, 0, NULL); -} - -static void fifo_do_not_copy_func(void* dest, void* src, int size) { - // do not copy + return async_read_internal(h, buf, size); } static int64_t async_seek(URLContext *h, int64_t pos, int whence) @@ -422,7 +420,7 @@ static int64_t async_seek(URLContext *h, int64_t pos, int whence) if (pos_delta > 0) { // fast seek forwards - async_read_internal(h, NULL, pos_delta, 1, fifo_do_not_copy_func); + async_read_internal(h, NULL, pos_delta); } else { // fast seek backwards ring_drain(ring, pos_delta); diff --git a/libavformat/au.c b/libavformat/au.c index 9bd408f65..f7c47d533 100644 --- a/libavformat/au.c +++ b/libavformat/au.c @@ -27,6 +27,8 @@ * http://www.goice.co.jp/member/mo/formats/au.html */ +#include "config_components.h" + #include "libavutil/bprint.h" #include "avformat.h" #include "internal.h" @@ -213,13 +215,13 @@ static int au_read_header(AVFormatContext *s) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_tag = id; st->codecpar->codec_id = codec; - st->codecpar->channels = channels; + st->codecpar->ch_layout.nb_channels = channels; st->codecpar->sample_rate = rate; st->codecpar->bits_per_coded_sample = bps; st->codecpar->bit_rate = channels * rate * bps; - st->codecpar->block_align = ba ? ba : FFMAX(bps * st->codecpar->channels / 8, 1); + st->codecpar->block_align = ba ? ba : FFMAX(bps * channels / 8, 1); if (data_size != AU_UNKNOWN_SIZE) - st->duration = (((int64_t)data_size)<<3) / (st->codecpar->channels * (int64_t)bps); + st->duration = (((int64_t)data_size)<<3) / (channels * (int64_t)bps); st->start_time = 0; avpriv_set_pts_info(st, 64, 1, rate); @@ -304,7 +306,7 @@ static int au_write_header(AVFormatContext *s) avio_wb32(pb, AU_UNKNOWN_SIZE); /* data size */ avio_wb32(pb, par->codec_tag); /* codec ID */ avio_wb32(pb, par->sample_rate); - avio_wb32(pb, par->channels); + avio_wb32(pb, par->ch_layout.nb_channels); avio_write(pb, annotations.str, annotations.len & ~7); fail: diff --git a/libavformat/av1.c b/libavformat/av1.c index 1fcfac235..b6eaf5062 100644 --- a/libavformat/av1.c +++ b/libavformat/av1.c @@ -23,7 +23,7 @@ #include "libavutil/mem.h" #include "libavcodec/av1.h" #include "libavcodec/av1_parse.h" -#include "libavcodec/profiles.h" +#include "libavcodec/avcodec.h" #include "libavcodec/put_bits.h" #include "av1.h" #include "avio.h" @@ -33,8 +33,7 @@ static int av1_filter_obus(AVIOContext *pb, const uint8_t *buf, int size, int *offset) { const uint8_t *start = buf, *end = buf + size; - int64_t obu_size; - int off, start_pos, type, temporal_id, spatial_id; + int off; enum { START_NOT_FOUND, START_FOUND, @@ -44,6 +43,8 @@ static int av1_filter_obus(AVIOContext *pb, const uint8_t *buf, off = size = 0; while (buf < end) { + int64_t obu_size; + int start_pos, type, temporal_id, spatial_id; int len = parse_obu_header(buf, end - buf, &obu_size, &start_pos, &type, &temporal_id, &spatial_id); if (len < 0) @@ -333,13 +334,46 @@ static int parse_sequence_header(AV1SequenceParameters *seq_params, const uint8_ int ff_av1_parse_seq_header(AV1SequenceParameters *seq, const uint8_t *buf, int size) { - int64_t obu_size; - int start_pos, type, temporal_id, spatial_id; + int is_av1c; if (size <= 0) return AVERROR_INVALIDDATA; + is_av1c = !!(buf[0] & 0x80); + if (is_av1c) { + GetBitContext gb; + int ret, version = buf[0] & 0x7F; + + if (version != 1 || size < 4) + return AVERROR_INVALIDDATA; + + ret = init_get_bits8(&gb, buf, 4); + if (ret < 0) + return ret; + + memset(seq, 0, sizeof(*seq)); + + skip_bits(&gb, 8); + seq->profile = get_bits(&gb, 3); + seq->level = get_bits(&gb, 5); + seq->tier = get_bits(&gb, 1); + seq->bitdepth = get_bits(&gb, 1) * 2 + 8; + seq->bitdepth += get_bits(&gb, 1) * 2; + seq->monochrome = get_bits(&gb, 1); + seq->chroma_subsampling_x = get_bits(&gb, 1); + seq->chroma_subsampling_y = get_bits(&gb, 1); + seq->chroma_sample_position = get_bits(&gb, 2); + seq->color_primaries = AVCOL_PRI_UNSPECIFIED; + seq->transfer_characteristics = AVCOL_TRC_UNSPECIFIED; + seq->matrix_coefficients = AVCOL_SPC_UNSPECIFIED; + + size -= 4; + buf += 4; + } + while (size > 0) { + int64_t obu_size; + int start_pos, type, temporal_id, spatial_id; int len = parse_obu_header(buf, size, &obu_size, &start_pos, &type, &temporal_id, &spatial_id); if (len < 0) @@ -358,18 +392,17 @@ int ff_av1_parse_seq_header(AV1SequenceParameters *seq, const uint8_t *buf, int buf += len; } - return AVERROR_INVALIDDATA; + return is_av1c ? 0 : AVERROR_INVALIDDATA; } -int ff_isom_write_av1c(AVIOContext *pb, const uint8_t *buf, int size) +int ff_isom_write_av1c(AVIOContext *pb, const uint8_t *buf, int size, + int write_seq_header) { AVIOContext *meta_pb; AV1SequenceParameters seq_params; PutBitContext pbc; uint8_t header[4], *meta; const uint8_t *seq; - int64_t obu_size; - int start_pos, type, temporal_id, spatial_id; int ret, nb_seq = 0, seq_size, meta_size; if (size <= 0) @@ -394,6 +427,8 @@ int ff_isom_write_av1c(AVIOContext *pb, const uint8_t *buf, int size) return ret; while (size > 0) { + int64_t obu_size; + int start_pos, type, temporal_id, spatial_id; int len = parse_obu_header(buf, size, &obu_size, &start_pos, &type, &temporal_id, &spatial_id); if (len < 0) { @@ -451,7 +486,9 @@ int ff_isom_write_av1c(AVIOContext *pb, const uint8_t *buf, int size) flush_put_bits(&pbc); avio_write(pb, header, sizeof(header)); - avio_write(pb, seq, seq_size); + if (write_seq_header) { + avio_write(pb, seq, seq_size); + } meta_size = avio_get_dyn_buf(meta_pb, &meta); if (meta_size) diff --git a/libavformat/av1.h b/libavformat/av1.h index dd5b47dc2..a393fbb78 100644 --- a/libavformat/av1.h +++ b/libavformat/av1.h @@ -46,12 +46,14 @@ typedef struct AV1SequenceParameters { * the resulting bitstream to the provided AVIOContext. * * @param pb pointer to the AVIOContext where the filtered bitstream shall be - * written + * written; may be NULL, in which case nothing is written. * @param buf input data buffer * @param size size of the input data buffer * - * @return the amount of bytes written in case of success, a negative AVERROR + * @return the amount of bytes written (or would have been written in case + * pb had been supplied) in case of success, a negative AVERROR * code in case of failure + * @note One can use NULL for pb to just get the output size. */ int ff_av1_filter_obus(AVIOContext *pb, const uint8_t *buf, int size); @@ -94,9 +96,11 @@ int ff_av1_parse_seq_header(AV1SequenceParameters *seq, const uint8_t *buf, int * @param pb pointer to the AVIOContext where the av1C box shall be written * @param buf input data buffer * @param size size in bytes of the input data buffer + * @param write_seq_header If 1, Sequence Header OBU will be written inside the + * av1C box. Otherwise, Sequence Header OBU will be omitted. * * @return >= 0 in case of success, a negative AVERROR code in case of failure */ -int ff_isom_write_av1c(AVIOContext *pb, const uint8_t *buf, int size); +int ff_isom_write_av1c(AVIOContext *pb, const uint8_t *buf, int size, int write_seq_header); #endif /* AVFORMAT_AV1_H */ diff --git a/libavformat/av1dec.c b/libavformat/av1dec.c index 6e1c2a45f..350f5360d 100644 --- a/libavformat/av1dec.c +++ b/libavformat/av1dec.c @@ -20,6 +20,7 @@ */ #include "config.h" +#include "config_components.h" #include "libavutil/common.h" #include "libavutil/opt.h" diff --git a/libavformat/avc.c b/libavformat/avc.c index b5e292138..b0ceb1d2d 100644 --- a/libavformat/avc.c +++ b/libavformat/avc.c @@ -70,7 +70,8 @@ const uint8_t *ff_avc_find_startcode(const uint8_t *p, const uint8_t *end){ return out; } -int ff_avc_parse_nal_units(AVIOContext *pb, const uint8_t *buf_in, int size) +static int avc_parse_nal_units(AVIOContext *pb, NALUList *list, + const uint8_t *buf_in, int size) { const uint8_t *p = buf_in; const uint8_t *end = p + size; @@ -79,19 +80,52 @@ int ff_avc_parse_nal_units(AVIOContext *pb, const uint8_t *buf_in, int size) size = 0; nal_start = ff_avc_find_startcode(p, end); for (;;) { + const size_t nalu_limit = SIZE_MAX / sizeof(*list->nalus); while (nal_start < end && !*(nal_start++)); if (nal_start == end) break; nal_end = ff_avc_find_startcode(nal_start, end); - avio_wb32(pb, nal_end - nal_start); - avio_write(pb, nal_start, nal_end - nal_start); + if (pb) { + avio_wb32(pb, nal_end - nal_start); + avio_write(pb, nal_start, nal_end - nal_start); + } else if (list->nb_nalus >= nalu_limit) { + return AVERROR(ERANGE); + } else { + NALU *tmp = av_fast_realloc(list->nalus, &list->nalus_array_size, + (list->nb_nalus + 1) * sizeof(*list->nalus)); + if (!tmp) + return AVERROR(ENOMEM); + list->nalus = tmp; + tmp[list->nb_nalus++] = (NALU){ .offset = nal_start - p, + .size = nal_end - nal_start }; + } size += 4 + nal_end - nal_start; nal_start = nal_end; } return size; } +int ff_avc_parse_nal_units(AVIOContext *pb, const uint8_t *buf_in, int size) +{ + return avc_parse_nal_units(pb, NULL, buf_in, size); +} + +int ff_nal_units_create_list(NALUList *list, const uint8_t *buf, int size) +{ + list->nb_nalus = 0; + return avc_parse_nal_units(NULL, list, buf, size); +} + +void ff_nal_units_write_list(const NALUList *list, AVIOContext *pb, + const uint8_t *buf) +{ + for (unsigned i = 0; i < list->nb_nalus; i++) { + avio_wb32(pb, list->nalus[i].size); + avio_write(pb, buf + list->nalus[i].offset, list->nalus[i].size); + } +} + int ff_avc_parse_nal_units_buf(const uint8_t *buf_in, uint8_t **buf, int *size) { AVIOContext *pb; diff --git a/libavformat/avc.h b/libavformat/avc.h index 9792b7791..0ce95c194 100644 --- a/libavformat/avc.h +++ b/libavformat/avc.h @@ -23,8 +23,38 @@ #define AVFORMAT_AVC_H #include +#include "libavutil/rational.h" #include "avio.h" +typedef struct NALU { + int offset; + uint32_t size; +} NALU; + +typedef struct NALUList { + NALU *nalus; + unsigned nalus_array_size; + unsigned nb_nalus; ///< valid entries in nalus +} NALUList; + +/* This function will parse the given annex B buffer and create + * a NALUList from it. This list can be passed to ff_nal_units_write_list() + * to write the access unit reformatted to mp4. + * + * @param list A NALUList. The list->nalus and list->nalus_array_size + * must be valid when calling this function and may be updated. + * nb_nalus is set by this function on success. + * @param buf buffer containing annex B H.264 or H.265. Must be padded. + * @param size size of buf, excluding padding. + * @return < 0 on error, the size of the mp4-style packet on success. + */ +int ff_nal_units_create_list(NALUList *list, const uint8_t *buf, int size); + +/* Writes a NALUList to the specified AVIOContext. The list must originate + * from ff_nal_units_create_list() with the same buf. */ +void ff_nal_units_write_list(const NALUList *list, AVIOContext *pb, + const uint8_t *buf); + int ff_avc_parse_nal_units(AVIOContext *s, const uint8_t *buf, int size); 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); diff --git a/libavformat/avformat.c b/libavformat/avformat.c new file mode 100644 index 000000000..30d6ea6a4 --- /dev/null +++ b/libavformat/avformat.c @@ -0,0 +1,790 @@ +/* + * Various functions used by both muxers and demuxers + * 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/avassert.h" +#include "libavutil/avstring.h" +#include "libavutil/channel_layout.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/mem.h" +#include "libavutil/opt.h" +#include "libavutil/pixfmt.h" +#include "libavutil/samplefmt.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/bsf.h" +#include "libavcodec/codec_desc.h" +#include "libavcodec/packet_internal.h" +#include "avformat.h" +#include "avio.h" +#include "demux.h" +#include "internal.h" + +void ff_free_stream(AVStream **pst) +{ + AVStream *st = *pst; + FFStream *const sti = ffstream(st); + + if (!st) + return; + + for (int i = 0; i < st->nb_side_data; i++) + av_freep(&st->side_data[i].data); + av_freep(&st->side_data); + + if (st->attached_pic.data) + av_packet_unref(&st->attached_pic); + + av_parser_close(sti->parser); + avcodec_free_context(&sti->avctx); + av_bsf_free(&sti->bsfc); + av_freep(&sti->priv_pts); + av_freep(&sti->index_entries); + av_freep(&sti->probe_data.buf); + + av_bsf_free(&sti->extract_extradata.bsf); + + if (sti->info) { + av_freep(&sti->info->duration_error); + av_freep(&sti->info); + } + + av_dict_free(&st->metadata); + avcodec_parameters_free(&st->codecpar); + av_freep(&st->priv_data); + + av_freep(pst); +} + +void ff_remove_stream(AVFormatContext *s, AVStream *st) +{ + av_assert0(s->nb_streams>0); + av_assert0(s->streams[ s->nb_streams - 1 ] == st); + + ff_free_stream(&s->streams[ --s->nb_streams ]); +} + +/* XXX: suppress the packet queue */ +void ff_flush_packet_queue(AVFormatContext *s) +{ + FFFormatContext *const si = ffformatcontext(s); + avpriv_packet_list_free(&si->parse_queue); + avpriv_packet_list_free(&si->packet_buffer); + avpriv_packet_list_free(&si->raw_packet_buffer); + + si->raw_packet_buffer_size = 0; +} + +void avformat_free_context(AVFormatContext *s) +{ + FFFormatContext *si; + + if (!s) + return; + si = ffformatcontext(s); + + if (s->oformat && s->oformat->deinit && si->initialized) + s->oformat->deinit(s); + + av_opt_free(s); + if (s->iformat && s->iformat->priv_class && s->priv_data) + av_opt_free(s->priv_data); + if (s->oformat && s->oformat->priv_class && s->priv_data) + av_opt_free(s->priv_data); + + for (unsigned i = 0; i < s->nb_streams; i++) + ff_free_stream(&s->streams[i]); + s->nb_streams = 0; + + for (unsigned i = 0; i < s->nb_programs; i++) { + av_dict_free(&s->programs[i]->metadata); + av_freep(&s->programs[i]->stream_index); + av_freep(&s->programs[i]); + } + s->nb_programs = 0; + + av_freep(&s->programs); + av_freep(&s->priv_data); + while (s->nb_chapters--) { + av_dict_free(&s->chapters[s->nb_chapters]->metadata); + av_freep(&s->chapters[s->nb_chapters]); + } + av_freep(&s->chapters); + av_dict_free(&s->metadata); + av_dict_free(&si->id3v2_meta); + av_packet_free(&si->pkt); + av_packet_free(&si->parse_pkt); + av_freep(&s->streams); + ff_flush_packet_queue(s); + av_freep(&s->url); + av_free(s); +} + +uint8_t *av_stream_get_side_data(const AVStream *st, + enum AVPacketSideDataType type, size_t *size) +{ + for (int i = 0; i < st->nb_side_data; i++) { + if (st->side_data[i].type == type) { + if (size) + *size = st->side_data[i].size; + return st->side_data[i].data; + } + } + if (size) + *size = 0; + return NULL; +} + +int av_stream_add_side_data(AVStream *st, enum AVPacketSideDataType type, + uint8_t *data, size_t size) +{ + AVPacketSideData *sd, *tmp; + + for (int i = 0; i < st->nb_side_data; i++) { + sd = &st->side_data[i]; + + if (sd->type == type) { + av_freep(&sd->data); + sd->data = data; + sd->size = size; + return 0; + } + } + + if (st->nb_side_data + 1U > FFMIN(INT_MAX, SIZE_MAX / sizeof(*tmp))) + return AVERROR(ERANGE); + + tmp = av_realloc_array(st->side_data, st->nb_side_data + 1, sizeof(*tmp)); + if (!tmp) { + return AVERROR(ENOMEM); + } + + st->side_data = tmp; + st->nb_side_data++; + + sd = &st->side_data[st->nb_side_data - 1]; + sd->type = type; + sd->data = data; + sd->size = size; + + return 0; +} + +uint8_t *av_stream_new_side_data(AVStream *st, enum AVPacketSideDataType type, + size_t size) +{ + int ret; + uint8_t *data = av_malloc(size); + + if (!data) + return NULL; + + ret = av_stream_add_side_data(st, type, data, size); + if (ret < 0) { + av_freep(&data); + return NULL; + } + + return data; +} + +int ff_stream_side_data_copy(AVStream *dst, const AVStream *src) +{ + /* Free existing side data*/ + for (int i = 0; i < dst->nb_side_data; i++) + av_free(dst->side_data[i].data); + av_freep(&dst->side_data); + dst->nb_side_data = 0; + + /* Copy side data if present */ + if (src->nb_side_data) { + dst->side_data = av_calloc(src->nb_side_data, + sizeof(*dst->side_data)); + if (!dst->side_data) + return AVERROR(ENOMEM); + dst->nb_side_data = src->nb_side_data; + + for (int i = 0; i < src->nb_side_data; i++) { + uint8_t *data = av_memdup(src->side_data[i].data, + src->side_data[i].size); + if (!data) + return AVERROR(ENOMEM); + dst->side_data[i].type = src->side_data[i].type; + dst->side_data[i].size = src->side_data[i].size; + dst->side_data[i].data = data; + } + } + + return 0; +} + +AVProgram *av_new_program(AVFormatContext *ac, int id) +{ + AVProgram *program = NULL; + int ret; + + av_log(ac, AV_LOG_TRACE, "new_program: id=0x%04x\n", id); + + for (unsigned i = 0; i < ac->nb_programs; i++) + if (ac->programs[i]->id == id) + program = ac->programs[i]; + + if (!program) { + program = av_mallocz(sizeof(*program)); + if (!program) + return NULL; + ret = av_dynarray_add_nofree(&ac->programs, &ac->nb_programs, program); + if (ret < 0) { + av_free(program); + return NULL; + } + program->discard = AVDISCARD_NONE; + program->pmt_version = -1; + program->id = id; + program->pts_wrap_reference = AV_NOPTS_VALUE; + program->pts_wrap_behavior = AV_PTS_WRAP_IGNORE; + program->start_time = + program->end_time = AV_NOPTS_VALUE; + } + return program; +} + +void av_program_add_stream_index(AVFormatContext *ac, int progid, unsigned idx) +{ + AVProgram *program = NULL; + void *tmp; + + if (idx >= ac->nb_streams) { + av_log(ac, AV_LOG_ERROR, "stream index %d is not valid\n", idx); + return; + } + + for (unsigned i = 0; i < ac->nb_programs; i++) { + if (ac->programs[i]->id != progid) + continue; + program = ac->programs[i]; + for (unsigned j = 0; j < program->nb_stream_indexes; j++) + if (program->stream_index[j] == idx) + return; + + tmp = av_realloc_array(program->stream_index, program->nb_stream_indexes+1, sizeof(unsigned int)); + if (!tmp) + return; + program->stream_index = tmp; + program->stream_index[program->nb_stream_indexes++] = idx; + return; + } +} + +AVProgram *av_find_program_from_stream(AVFormatContext *ic, AVProgram *last, int s) +{ + for (unsigned i = 0; i < ic->nb_programs; i++) { + if (ic->programs[i] == last) { + last = NULL; + } else { + if (!last) + for (unsigned j = 0; j < ic->programs[i]->nb_stream_indexes; j++) + if (ic->programs[i]->stream_index[j] == s) + return ic->programs[i]; + } + } + return NULL; +} + +int av_find_default_stream_index(AVFormatContext *s) +{ + int best_stream = 0; + int best_score = INT_MIN; + + if (s->nb_streams <= 0) + return -1; + for (unsigned i = 0; i < s->nb_streams; i++) { + const AVStream *const st = s->streams[i]; + const FFStream *const sti = cffstream(st); + int score = 0; + if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + if (st->disposition & AV_DISPOSITION_ATTACHED_PIC) + score -= 400; + if (st->codecpar->width && st->codecpar->height) + score += 50; + score+= 25; + } + if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + if (st->codecpar->sample_rate) + score += 50; + } + if (sti->codec_info_nb_frames) + score += 12; + + if (st->discard != AVDISCARD_ALL) + score += 200; + + if (score > best_score) { + best_score = score; + best_stream = i; + } + } + return best_stream; +} + +int av_find_best_stream(AVFormatContext *ic, enum AVMediaType type, + int wanted_stream_nb, int related_stream, + const AVCodec **decoder_ret, int flags) +{ + int nb_streams = ic->nb_streams; + int ret = AVERROR_STREAM_NOT_FOUND; + int best_count = -1, best_multiframe = -1, best_disposition = -1; + int count, multiframe, disposition; + int64_t best_bitrate = -1; + int64_t bitrate; + unsigned *program = NULL; + const AVCodec *decoder = NULL, *best_decoder = NULL; + + if (related_stream >= 0 && wanted_stream_nb < 0) { + AVProgram *p = av_find_program_from_stream(ic, NULL, related_stream); + if (p) { + program = p->stream_index; + nb_streams = p->nb_stream_indexes; + } + } + for (unsigned i = 0; i < nb_streams; i++) { + int real_stream_index = program ? program[i] : i; + AVStream *st = ic->streams[real_stream_index]; + AVCodecParameters *par = st->codecpar; + if (par->codec_type != type) + continue; + if (wanted_stream_nb >= 0 && real_stream_index != wanted_stream_nb) + continue; + if (type == AVMEDIA_TYPE_AUDIO && !(par->ch_layout.nb_channels && par->sample_rate)) + continue; + if (decoder_ret) { + decoder = ff_find_decoder(ic, st, par->codec_id); + if (!decoder) { + if (ret < 0) + ret = AVERROR_DECODER_NOT_FOUND; + continue; + } + } + disposition = !(st->disposition & (AV_DISPOSITION_HEARING_IMPAIRED | AV_DISPOSITION_VISUAL_IMPAIRED)) + + !! (st->disposition & AV_DISPOSITION_DEFAULT); + count = ffstream(st)->codec_info_nb_frames; + bitrate = par->bit_rate; + multiframe = FFMIN(5, count); + if ((best_disposition > disposition) || + (best_disposition == disposition && best_multiframe > multiframe) || + (best_disposition == disposition && best_multiframe == multiframe && best_bitrate > bitrate) || + (best_disposition == disposition && best_multiframe == multiframe && best_bitrate == bitrate && best_count >= count)) + continue; + best_disposition = disposition; + best_count = count; + best_bitrate = bitrate; + best_multiframe = multiframe; + ret = real_stream_index; + best_decoder = decoder; + if (program && i == nb_streams - 1 && ret < 0) { + program = NULL; + nb_streams = ic->nb_streams; + /* no related stream found, try again with everything */ + i = 0; + } + } + if (decoder_ret) + *decoder_ret = best_decoder; + return ret; +} + +/** + * Matches a stream specifier (but ignores requested index). + * + * @param indexptr set to point to the requested stream index if there is one + * + * @return <0 on error + * 0 if st is NOT a matching stream + * >0 if st is a matching stream + */ +static int match_stream_specifier(const AVFormatContext *s, const AVStream *st, + const char *spec, const char **indexptr, + const AVProgram **p) +{ + int match = 1; /* Stores if the specifier matches so far. */ + while (*spec) { + if (*spec <= '9' && *spec >= '0') { /* opt:index */ + if (indexptr) + *indexptr = spec; + return match; + } else if (*spec == 'v' || *spec == 'a' || *spec == 's' || *spec == 'd' || + *spec == 't' || *spec == 'V') { /* opt:[vasdtV] */ + enum AVMediaType type; + int nopic = 0; + + switch (*spec++) { + 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; + case 't': type = AVMEDIA_TYPE_ATTACHMENT; break; + case 'V': type = AVMEDIA_TYPE_VIDEO; nopic = 1; break; + default: av_assert0(0); + } + if (*spec && *spec++ != ':') /* If we are not at the end, then another specifier must follow. */ + return AVERROR(EINVAL); + + if (type != st->codecpar->codec_type) + match = 0; + if (nopic && (st->disposition & AV_DISPOSITION_ATTACHED_PIC)) + match = 0; + } else if (*spec == 'p' && *(spec + 1) == ':') { + int prog_id; + int found = 0; + char *endptr; + spec += 2; + prog_id = strtol(spec, &endptr, 0); + /* Disallow empty id and make sure that if we are not at the end, then another specifier must follow. */ + if (spec == endptr || (*endptr && *endptr++ != ':')) + return AVERROR(EINVAL); + spec = endptr; + if (match) { + for (unsigned i = 0; i < s->nb_programs; i++) { + if (s->programs[i]->id != prog_id) + continue; + + for (unsigned j = 0; j < s->programs[i]->nb_stream_indexes; j++) { + if (st->index == s->programs[i]->stream_index[j]) { + found = 1; + if (p) + *p = s->programs[i]; + i = s->nb_programs; + break; + } + } + } + } + if (!found) + match = 0; + } else if (*spec == '#' || + (*spec == 'i' && *(spec + 1) == ':')) { + int stream_id; + char *endptr; + spec += 1 + (*spec == 'i'); + stream_id = strtol(spec, &endptr, 0); + if (spec == endptr || *endptr) /* Disallow empty id and make sure we are at the end. */ + return AVERROR(EINVAL); + return match && (stream_id == st->id); + } else if (*spec == 'm' && *(spec + 1) == ':') { + const AVDictionaryEntry *tag; + char *key, *val; + int ret; + + if (match) { + spec += 2; + val = strchr(spec, ':'); + + key = val ? av_strndup(spec, val - spec) : av_strdup(spec); + if (!key) + return AVERROR(ENOMEM); + + tag = av_dict_get(st->metadata, key, NULL, 0); + if (tag) { + if (!val || !strcmp(tag->value, val + 1)) + ret = 1; + else + ret = 0; + } else + ret = 0; + + av_freep(&key); + } + return match && ret; + } else if (*spec == 'u' && *(spec + 1) == '\0') { + const AVCodecParameters *par = st->codecpar; + int val; + switch (par->codec_type) { + case AVMEDIA_TYPE_AUDIO: + val = par->sample_rate && par->ch_layout.nb_channels; + if (par->format == AV_SAMPLE_FMT_NONE) + return 0; + break; + case AVMEDIA_TYPE_VIDEO: + val = par->width && par->height; + if (par->format == AV_PIX_FMT_NONE) + return 0; + break; + case AVMEDIA_TYPE_UNKNOWN: + val = 0; + break; + default: + val = 1; + break; + } + return match && (par->codec_id != AV_CODEC_ID_NONE && val != 0); + } else { + return AVERROR(EINVAL); + } + } + + return match; +} + +int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st, + const char *spec) +{ + int ret, index; + char *endptr; + const char *indexptr = NULL; + const AVProgram *p = NULL; + int nb_streams; + + ret = match_stream_specifier(s, st, spec, &indexptr, &p); + if (ret < 0) + goto error; + + if (!indexptr) + return ret; + + index = strtol(indexptr, &endptr, 0); + if (*endptr) { /* We can't have anything after the requested index. */ + ret = AVERROR(EINVAL); + goto error; + } + + /* This is not really needed but saves us a loop for simple stream index specifiers. */ + if (spec == indexptr) + return (index == st->index); + + /* If we requested a matching stream index, we have to ensure st is that. */ + nb_streams = p ? p->nb_stream_indexes : s->nb_streams; + for (int i = 0; i < nb_streams && index >= 0; i++) { + const AVStream *candidate = s->streams[p ? p->stream_index[i] : i]; + ret = match_stream_specifier(s, candidate, spec, NULL, NULL); + if (ret < 0) + goto error; + if (ret > 0 && index-- == 0 && st == candidate) + return 1; + } + return 0; + +error: + if (ret == AVERROR(EINVAL)) + av_log(s, AV_LOG_ERROR, "Invalid stream specifier: %s.\n", spec); + return ret; +} + +AVRational av_guess_sample_aspect_ratio(AVFormatContext *format, AVStream *stream, AVFrame *frame) +{ + AVRational undef = {0, 1}; + AVRational stream_sample_aspect_ratio = stream ? stream->sample_aspect_ratio : undef; + AVRational codec_sample_aspect_ratio = stream && stream->codecpar ? stream->codecpar->sample_aspect_ratio : undef; + AVRational frame_sample_aspect_ratio = frame ? frame->sample_aspect_ratio : codec_sample_aspect_ratio; + + av_reduce(&stream_sample_aspect_ratio.num, &stream_sample_aspect_ratio.den, + stream_sample_aspect_ratio.num, stream_sample_aspect_ratio.den, INT_MAX); + if (stream_sample_aspect_ratio.num <= 0 || stream_sample_aspect_ratio.den <= 0) + stream_sample_aspect_ratio = undef; + + av_reduce(&frame_sample_aspect_ratio.num, &frame_sample_aspect_ratio.den, + frame_sample_aspect_ratio.num, frame_sample_aspect_ratio.den, INT_MAX); + if (frame_sample_aspect_ratio.num <= 0 || frame_sample_aspect_ratio.den <= 0) + frame_sample_aspect_ratio = undef; + + if (stream_sample_aspect_ratio.num) + return stream_sample_aspect_ratio; + else + return frame_sample_aspect_ratio; +} + +AVRational av_guess_frame_rate(AVFormatContext *format, AVStream *st, AVFrame *frame) +{ + AVRational fr = st->r_frame_rate; + AVCodecContext *const avctx = ffstream(st)->avctx; + AVRational codec_fr = avctx->framerate; + AVRational avg_fr = st->avg_frame_rate; + + if (avg_fr.num > 0 && avg_fr.den > 0 && fr.num > 0 && fr.den > 0 && + av_q2d(avg_fr) < 70 && av_q2d(fr) > 210) { + fr = avg_fr; + } + + if (avctx->ticks_per_frame > 1) { + if ( codec_fr.num > 0 && codec_fr.den > 0 && + (fr.num == 0 || av_q2d(codec_fr) < av_q2d(fr)*0.7 && fabs(1.0 - av_q2d(av_div_q(avg_fr, fr))) > 0.1)) + fr = codec_fr; + } + + return fr; +} + +int avformat_transfer_internal_stream_timing_info(const AVOutputFormat *ofmt, + AVStream *ost, const AVStream *ist, + enum AVTimebaseSource copy_tb) +{ + const AVCodecContext *const dec_ctx = cffstream(ist)->avctx; + AVCodecContext *const enc_ctx = ffstream(ost)->avctx; + + enc_ctx->time_base = ist->time_base; + /* + * Avi is a special case here because it supports variable fps but + * having the fps and timebase differe significantly adds quite some + * overhead + */ + if (!strcmp(ofmt->name, "avi")) { +#if FF_API_R_FRAME_RATE + if (copy_tb == AVFMT_TBCF_AUTO && ist->r_frame_rate.num + && av_q2d(ist->r_frame_rate) >= av_q2d(ist->avg_frame_rate) + && 0.5/av_q2d(ist->r_frame_rate) > av_q2d(ist->time_base) + && 0.5/av_q2d(ist->r_frame_rate) > av_q2d(dec_ctx->time_base) + && av_q2d(ist->time_base) < 1.0/500 && av_q2d(dec_ctx->time_base) < 1.0/500 + || copy_tb == AVFMT_TBCF_R_FRAMERATE) { + enc_ctx->time_base.num = ist->r_frame_rate.den; + enc_ctx->time_base.den = 2*ist->r_frame_rate.num; + enc_ctx->ticks_per_frame = 2; + } else +#endif + if (copy_tb == AVFMT_TBCF_AUTO && av_q2d(dec_ctx->time_base)*dec_ctx->ticks_per_frame > 2*av_q2d(ist->time_base) + && av_q2d(ist->time_base) < 1.0/500 + || copy_tb == AVFMT_TBCF_DECODER) { + enc_ctx->time_base = dec_ctx->time_base; + enc_ctx->time_base.num *= dec_ctx->ticks_per_frame; + enc_ctx->time_base.den *= 2; + enc_ctx->ticks_per_frame = 2; + } + } else if (!(ofmt->flags & AVFMT_VARIABLE_FPS) + && !av_match_name(ofmt->name, "mov,mp4,3gp,3g2,psp,ipod,ismv,f4v")) { + if (copy_tb == AVFMT_TBCF_AUTO && dec_ctx->time_base.den + && av_q2d(dec_ctx->time_base)*dec_ctx->ticks_per_frame > av_q2d(ist->time_base) + && av_q2d(ist->time_base) < 1.0/500 + || copy_tb == AVFMT_TBCF_DECODER) { + enc_ctx->time_base = dec_ctx->time_base; + enc_ctx->time_base.num *= dec_ctx->ticks_per_frame; + } + } + + if ((enc_ctx->codec_tag == AV_RL32("tmcd") || ost->codecpar->codec_tag == AV_RL32("tmcd")) + && dec_ctx->time_base.num < dec_ctx->time_base.den + && dec_ctx->time_base.num > 0 + && 121LL*dec_ctx->time_base.num > dec_ctx->time_base.den) { + enc_ctx->time_base = dec_ctx->time_base; + } + + av_reduce(&enc_ctx->time_base.num, &enc_ctx->time_base.den, + enc_ctx->time_base.num, enc_ctx->time_base.den, INT_MAX); + + return 0; +} + +AVRational av_stream_get_codec_timebase(const AVStream *st) +{ + // See avformat_transfer_internal_stream_timing_info() TODO. + return cffstream(st)->avctx->time_base; +} + +void avpriv_set_pts_info(AVStream *st, int pts_wrap_bits, + unsigned int pts_num, unsigned int pts_den) +{ + FFStream *const sti = ffstream(st); + AVRational new_tb; + if (av_reduce(&new_tb.num, &new_tb.den, pts_num, pts_den, INT_MAX)) { + if (new_tb.num != pts_num) + av_log(NULL, AV_LOG_DEBUG, + "st:%d removing common factor %d from timebase\n", + st->index, pts_num / new_tb.num); + } else + av_log(NULL, AV_LOG_WARNING, + "st:%d has too large timebase, reducing\n", st->index); + + if (new_tb.num <= 0 || new_tb.den <= 0) { + av_log(NULL, AV_LOG_ERROR, + "Ignoring attempt to set invalid timebase %d/%d for st:%d\n", + new_tb.num, new_tb.den, + st->index); + return; + } + st->time_base = new_tb; + sti->avctx->pkt_timebase = new_tb; + st->pts_wrap_bits = pts_wrap_bits; +} + +const AVCodec *ff_find_decoder(AVFormatContext *s, const AVStream *st, + enum AVCodecID codec_id) +{ + switch (st->codecpar->codec_type) { + case AVMEDIA_TYPE_VIDEO: + if (s->video_codec) return s->video_codec; + break; + case AVMEDIA_TYPE_AUDIO: + if (s->audio_codec) return s->audio_codec; + break; + case AVMEDIA_TYPE_SUBTITLE: + if (s->subtitle_codec) return s->subtitle_codec; + break; + } + + return avcodec_find_decoder(codec_id); +} + +int ff_copy_whiteblacklists(AVFormatContext *dst, const AVFormatContext *src) +{ + av_assert0(!dst->codec_whitelist && + !dst->format_whitelist && + !dst->protocol_whitelist && + !dst->protocol_blacklist); + dst-> codec_whitelist = av_strdup(src->codec_whitelist); + dst->format_whitelist = av_strdup(src->format_whitelist); + dst->protocol_whitelist = av_strdup(src->protocol_whitelist); + dst->protocol_blacklist = av_strdup(src->protocol_blacklist); + if ( (src-> codec_whitelist && !dst-> codec_whitelist) + || (src-> format_whitelist && !dst-> format_whitelist) + || (src->protocol_whitelist && !dst->protocol_whitelist) + || (src->protocol_blacklist && !dst->protocol_blacklist)) { + av_log(dst, AV_LOG_ERROR, "Failed to duplicate black/whitelist\n"); + return AVERROR(ENOMEM); + } + return 0; +} + +int ff_is_intra_only(enum AVCodecID id) +{ + const AVCodecDescriptor *d = avcodec_descriptor_get(id); + if (!d) + return 0; + if ((d->type == AVMEDIA_TYPE_VIDEO || d->type == AVMEDIA_TYPE_AUDIO) && + !(d->props & AV_CODEC_PROP_INTRA_ONLY)) + return 0; + return 1; +} + +void ff_format_set_url(AVFormatContext *s, char *url) +{ + av_assert0(url); + av_freep(&s->url); + s->url = url; +} + +int ff_format_io_close(AVFormatContext *s, AVIOContext **pb) +{ + int ret = 0; + if (*pb) { + if (s->io_close == ff_format_io_close_default || s->io_close == NULL) + ret = s->io_close2(s, *pb); + else + s->io_close(s, *pb); + } + *pb = NULL; + return ret; +} diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 6ce367e85..f12fa7d90 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -319,7 +319,13 @@ #include "libavutil/log.h" #include "avio.h" +#include "libavformat/version_major.h" +#ifndef HAVE_AV_CONFIG_H +/* When included as part of the ffmpeg build, only include the major version + * to avoid unnecessary rebuilds. When included externally, keep including + * the full version information. */ #include "libavformat/version.h" +#endif struct AVFormatContext; struct AVStream; @@ -879,6 +885,13 @@ typedef struct AVIndexEntry { */ #define AV_DISPOSITION_TIMED_THUMBNAILS (1 << 11) +/** + * The stream is intended to be mixed with a spatial audio track. For example, + * it could be used for narration or stereo music, and may remain unchanged by + * listener head rotation. + */ +#define AV_DISPOSITION_NON_DIEGETIC (1 << 12) + /** * The subtitle stream contains captions, providing a transcription and possibly * a translation of audio. Typically intended for hearing-impaired audiences. @@ -1527,12 +1540,13 @@ typedef struct AVFormatContext { /** * Avoid negative timestamps during muxing. * Any value of the AVFMT_AVOID_NEG_TS_* constants. - * Note, this only works when using av_interleaved_write_frame. (interleave_packet_per_dts is in use) + * Note, this works better when using av_interleaved_write_frame(). * - muxing: Set by user * - demuxing: unused */ int avoid_negative_ts; #define AVFMT_AVOID_NEG_TS_AUTO -1 ///< Enabled when required by target format +#define AVFMT_AVOID_NEG_TS_DISABLED 0 ///< Do not shift timestamps even when they are negative. #define AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE 1 ///< Shift timestamps so they are non negative #define AVFMT_AVOID_NEG_TS_MAKE_ZERO 2 ///< Shift timestamps so that they start at 0 diff --git a/libavformat/avidec.c b/libavformat/avidec.c index 8584b4a88..937d9e6ff 100644 --- a/libavformat/avidec.c +++ b/libavformat/avidec.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include #include "libavutil/avassert.h" @@ -30,13 +32,14 @@ #include "libavutil/mathematics.h" #include "avformat.h" #include "avi.h" +#include "demux.h" #include "dv.h" #include "internal.h" #include "isom.h" #include "riff.h" #include "libavcodec/bytestream.h" #include "libavcodec/exif.h" -#include "libavcodec/internal.h" +#include "libavcodec/startcode.h" typedef struct AVIStream { int64_t frame_offset; /* current frame (video) or byte (audio) counter @@ -619,7 +622,7 @@ static int avi_read_header(AVFormatContext *s) ast = s->streams[0]->priv_data; st->priv_data = NULL; - ff_free_stream(s, st); + ff_remove_stream(s, st); avi->dv_demux = avpriv_dv_init_demux(s); if (!avi->dv_demux) { diff --git a/libavformat/avienc.c b/libavformat/avienc.c index be2493ce5..14115b3e2 100644 --- a/libavformat/avienc.c +++ b/libavformat/avienc.c @@ -25,8 +25,10 @@ #include "internal.h" #include "avi.h" #include "avio_internal.h" +#include "config_components.h" #include "riff.h" #include "mpegts.h" +#include "rawutils.h" #include "libavformat/avlanguage.h" #include "libavutil/avstring.h" #include "libavutil/avutil.h" @@ -424,6 +426,10 @@ static int avi_write_header(AVFormatContext *s) avio_wl32(pb, -1); /* quality */ avio_wl32(pb, au_ssize); /* sample size */ avio_wl32(pb, 0); + if (par->width > 65535 || par->height > 65535) { + av_log(s, AV_LOG_ERROR, "%dx%d dimensions are too big\n", par->width, par->height); + return AVERROR(EINVAL); + } avio_wl16(pb, par->width); avio_wl16(pb, par->height); ff_end_tag(pb, strh); diff --git a/libavformat/avio.h b/libavformat/avio.h index cd63322a6..36c3d7b43 100644 --- a/libavformat/avio.h +++ b/libavformat/avio.h @@ -27,12 +27,13 @@ */ #include +#include -#include "libavutil/common.h" +#include "libavutil/attributes.h" #include "libavutil/dict.h" #include "libavutil/log.h" -#include "libavformat/version.h" +#include "libavformat/version_major.h" /** * Seeking works like for a local file. @@ -518,6 +519,12 @@ int64_t avio_size(AVIOContext *s); */ int avio_feof(AVIOContext *s); +/** + * Writes a formatted string to the context taking a va_list. + * @return number of bytes written, < 0 on error. + */ +int avio_vprintf(AVIOContext *s, const char *fmt, va_list ap); + /** * Writes a formatted string to the context. * @return number of bytes written, < 0 on error. diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index 29d4bd751..b20b1a611 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -1062,6 +1062,9 @@ int ffio_ensure_seekback(AVIOContext *s, int64_t buf_size) if (buf_size <= s->buf_end - s->buf_ptr) return 0; + if (buf_size > INT_MAX - max_buffer_size) + return AVERROR(EINVAL); + buf_size += max_buffer_size - 1; if (buf_size + s->buf_ptr - s->buffer <= s->buffer_size || s->seekable || !s->read_packet) @@ -1289,15 +1292,12 @@ int avio_closep(AVIOContext **s) return ret; } -int avio_printf(AVIOContext *s, const char *fmt, ...) +int avio_vprintf(AVIOContext *s, const char *fmt, va_list ap) { - va_list ap; AVBPrint bp; av_bprint_init(&bp, 0, INT_MAX); - va_start(ap, fmt); av_vbprintf(&bp, fmt, ap); - va_end(ap); if (!av_bprint_is_complete(&bp)) { av_bprint_finalize(&bp, NULL); s->error = AVERROR(ENOMEM); @@ -1308,6 +1308,18 @@ int avio_printf(AVIOContext *s, const char *fmt, ...) return bp.len; } +int avio_printf(AVIOContext *s, const char *fmt, ...) +{ + va_list ap; + int ret; + + va_start(ap, fmt); + ret = avio_vprintf(s, fmt, ap); + va_end(ap); + + return ret; +} + void avio_print_string_array(AVIOContext *s, const char *strings[]) { for(; *strings; strings++) diff --git a/libavformat/avisynth.c b/libavformat/avisynth.c index 350ac6d11..a97d12b6b 100644 --- a/libavformat/avisynth.c +++ b/libavformat/avisynth.c @@ -34,6 +34,7 @@ /* Platform-specific directives. */ #ifdef _WIN32 #include "compat/w32dlfcn.h" + #include "libavutil/wchar_filename.h" #undef EXTERN_C #define AVISYNTH_LIB "avisynth" #else @@ -56,6 +57,7 @@ typedef struct AviSynthLibrary { #define AVSC_DECLARE_FUNC(name) name ## _func name AVSC_DECLARE_FUNC(avs_bit_blt); AVSC_DECLARE_FUNC(avs_clip_get_error); + AVSC_DECLARE_FUNC(avs_check_version); AVSC_DECLARE_FUNC(avs_create_script_environment); AVSC_DECLARE_FUNC(avs_delete_script_environment); AVSC_DECLARE_FUNC(avs_get_audio); @@ -76,6 +78,10 @@ typedef struct AviSynthLibrary { AVSC_DECLARE_FUNC(avs_get_row_size_p); AVSC_DECLARE_FUNC(avs_is_planar_rgb); AVSC_DECLARE_FUNC(avs_is_planar_rgba); + AVSC_DECLARE_FUNC(avs_get_frame_props_ro); + AVSC_DECLARE_FUNC(avs_prop_get_int); + AVSC_DECLARE_FUNC(avs_prop_get_type); + AVSC_DECLARE_FUNC(avs_get_env_property); #undef AVSC_DECLARE_FUNC } AviSynthLibrary; @@ -133,6 +139,7 @@ static av_cold int avisynth_load_library(void) LOAD_AVS_FUNC(avs_bit_blt, 0); LOAD_AVS_FUNC(avs_clip_get_error, 0); + LOAD_AVS_FUNC(avs_check_version, 0); LOAD_AVS_FUNC(avs_create_script_environment, 0); LOAD_AVS_FUNC(avs_delete_script_environment, 0); LOAD_AVS_FUNC(avs_get_audio, 0); @@ -153,6 +160,10 @@ static av_cold int avisynth_load_library(void) LOAD_AVS_FUNC(avs_get_row_size_p, 1); LOAD_AVS_FUNC(avs_is_planar_rgb, 1); LOAD_AVS_FUNC(avs_is_planar_rgba, 1); + LOAD_AVS_FUNC(avs_get_frame_props_ro, 1); + LOAD_AVS_FUNC(avs_prop_get_int, 1); + LOAD_AVS_FUNC(avs_prop_get_type, 1); + LOAD_AVS_FUNC(avs_get_env_property, 1); #undef LOAD_AVS_FUNC atexit(avisynth_atexit_handler); @@ -236,6 +247,9 @@ static av_cold void avisynth_atexit_handler(void) static int avisynth_create_stream_video(AVFormatContext *s, AVStream *st) { AviSynthContext *avs = s->priv_data; + const AVS_Map *avsmap; + AVS_VideoFrame *frame; + int error; int planar = 0; // 0: packed, 1: YUV, 2: Y8, 3: Planar RGB, 4: YUVA, 5: Planar RGBA st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; @@ -250,22 +264,6 @@ static int avisynth_create_stream_video(AVFormatContext *s, AVStream *st) st->nb_frames = avs->vi->num_frames; avpriv_set_pts_info(st, 32, avs->vi->fps_denominator, avs->vi->fps_numerator); - av_log(s, AV_LOG_TRACE, "avs_is_field_based: %d\n", avs_is_field_based(avs->vi)); - av_log(s, AV_LOG_TRACE, "avs_is_parity_known: %d\n", avs_is_parity_known(avs->vi)); - - /* The following typically only works when assumetff (-bff) and - * assumefieldbased is used in-script. Additional - * logic using GetParity() could deliver more accurate results - * but also decodes a frame which we want to avoid. */ - st->codecpar->field_order = AV_FIELD_UNKNOWN; - if (avs_is_field_based(avs->vi)) { - if (avs_is_tff(avs->vi)) { - st->codecpar->field_order = AV_FIELD_TT; - } - else if (avs_is_bff(avs->vi)) { - st->codecpar->field_order = AV_FIELD_BB; - } - } switch (avs->vi->pixel_type) { /* 10~16-bit YUV pix_fmts (AviSynth+) */ @@ -502,6 +500,249 @@ static int avisynth_create_stream_video(AVFormatContext *s, AVStream *st) avs->n_planes = 1; avs->planes = avs_planes_packed; } + + /* Read AviSynth+'s frame properties to set additional info. + * + * Due to a bug preventing the C interface from accessing frame + * properties in earlier versions of interface version 8, and + * previous attempts at being clever resulting in pre-8 versions + * of AviSynth+ segfaulting, only enable this if we detect + * version 9 at the minimum. Technically, 8.1 works, but the time + * distance between 8.1 and 9 is very small, so just restrict it to 9. */ + + if (avs_library.avs_get_version(avs->clip) >= 9) { + + frame = avs_library.avs_get_frame(avs->clip, 0); + avsmap = avs_library.avs_get_frame_props_ro(avs->env, frame); + + /* Field order */ + if(avs_library.avs_prop_get_type(avs->env, avsmap, "_FieldBased") == AVS_PROPTYPE_UNSET) { + st->codecpar->field_order = AV_FIELD_UNKNOWN; + } else { + switch (avs_library.avs_prop_get_int(avs->env, avsmap, "_FieldBased", 0, &error)) { + case 0: + st->codecpar->field_order = AV_FIELD_PROGRESSIVE; + break; + case 1: + st->codecpar->field_order = AV_FIELD_BB; + break; + case 2: + st->codecpar->field_order = AV_FIELD_TT; + break; + default: + st->codecpar->field_order = AV_FIELD_UNKNOWN; + } + } + + /* Color Range */ + if(avs_library.avs_prop_get_type(avs->env, avsmap, "_ColorRange") == AVS_PROPTYPE_UNSET) { + st->codecpar->color_range = AVCOL_RANGE_UNSPECIFIED; + } else { + switch (avs_library.avs_prop_get_int(avs->env, avsmap, "_ColorRange", 0, &error)) { + case 0: + st->codecpar->color_range = AVCOL_RANGE_JPEG; + break; + case 1: + st->codecpar->color_range = AVCOL_RANGE_MPEG; + break; + default: + st->codecpar->color_range = AVCOL_RANGE_UNSPECIFIED; + } + } + + /* Color Primaries */ + switch (avs_library.avs_prop_get_int(avs->env, avsmap, "_Primaries", 0, &error)) { + case 1: + st->codecpar->color_primaries = AVCOL_PRI_BT709; + break; + case 2: + st->codecpar->color_primaries = AVCOL_PRI_UNSPECIFIED; + break; + case 4: + st->codecpar->color_primaries = AVCOL_PRI_BT470M; + break; + case 5: + st->codecpar->color_primaries = AVCOL_PRI_BT470BG; + break; + case 6: + st->codecpar->color_primaries = AVCOL_PRI_SMPTE170M; + break; + case 7: + st->codecpar->color_primaries = AVCOL_PRI_SMPTE240M; + break; + case 8: + st->codecpar->color_primaries = AVCOL_PRI_FILM; + break; + case 9: + st->codecpar->color_primaries = AVCOL_PRI_BT2020; + break; + case 10: + st->codecpar->color_primaries = AVCOL_PRI_SMPTE428; + break; + case 11: + st->codecpar->color_primaries = AVCOL_PRI_SMPTE431; + break; + case 12: + st->codecpar->color_primaries = AVCOL_PRI_SMPTE432; + break; + case 22: + st->codecpar->color_primaries = AVCOL_PRI_EBU3213; + break; + default: + st->codecpar->color_primaries = AVCOL_PRI_UNSPECIFIED; + } + + /* Color Transfer Characteristics */ + switch (avs_library.avs_prop_get_int(avs->env, avsmap, "_Transfer", 0, &error)) { + case 1: + st->codecpar->color_trc = AVCOL_TRC_BT709; + break; + case 2: + st->codecpar->color_trc = AVCOL_TRC_UNSPECIFIED; + break; + case 4: + st->codecpar->color_trc = AVCOL_TRC_GAMMA22; + break; + case 5: + st->codecpar->color_trc = AVCOL_TRC_GAMMA28; + break; + case 6: + st->codecpar->color_trc = AVCOL_TRC_SMPTE170M; + break; + case 7: + st->codecpar->color_trc = AVCOL_TRC_SMPTE240M; + break; + case 8: + st->codecpar->color_trc = AVCOL_TRC_LINEAR; + break; + case 9: + st->codecpar->color_trc = AVCOL_TRC_LOG; + break; + case 10: + st->codecpar->color_trc = AVCOL_TRC_LOG_SQRT; + break; + case 11: + st->codecpar->color_trc = AVCOL_TRC_IEC61966_2_4; + break; + case 12: + st->codecpar->color_trc = AVCOL_TRC_BT1361_ECG; + break; + case 13: + st->codecpar->color_trc = AVCOL_TRC_IEC61966_2_1; + break; + case 14: + st->codecpar->color_trc = AVCOL_TRC_BT2020_10; + break; + case 15: + st->codecpar->color_trc = AVCOL_TRC_BT2020_12; + break; + case 16: + st->codecpar->color_trc = AVCOL_TRC_SMPTE2084; + break; + case 17: + st->codecpar->color_trc = AVCOL_TRC_SMPTE428; + break; + case 18: + st->codecpar->color_trc = AVCOL_TRC_ARIB_STD_B67; + break; + default: + st->codecpar->color_trc = AVCOL_TRC_UNSPECIFIED; + } + + /* Matrix coefficients */ + if(avs_library.avs_prop_get_type(avs->env, avsmap, "_Matrix") == AVS_PROPTYPE_UNSET) { + st->codecpar->color_space = AVCOL_SPC_UNSPECIFIED; + } else { + switch (avs_library.avs_prop_get_int(avs->env, avsmap, "_Matrix", 0, &error)) { + case 0: + st->codecpar->color_space = AVCOL_SPC_RGB; + break; + case 1: + st->codecpar->color_space = AVCOL_SPC_BT709; + break; + case 2: + st->codecpar->color_space = AVCOL_SPC_UNSPECIFIED; + break; + case 4: + st->codecpar->color_space = AVCOL_SPC_FCC; + break; + case 5: + st->codecpar->color_space = AVCOL_SPC_BT470BG; + break; + case 6: + st->codecpar->color_space = AVCOL_SPC_SMPTE170M; + break; + case 7: + st->codecpar->color_space = AVCOL_SPC_SMPTE240M; + break; + case 8: + st->codecpar->color_space = AVCOL_SPC_YCGCO; + break; + case 9: + st->codecpar->color_space = AVCOL_SPC_BT2020_NCL; + break; + case 10: + st->codecpar->color_space = AVCOL_SPC_BT2020_CL; + break; + case 11: + st->codecpar->color_space = AVCOL_SPC_SMPTE2085; + break; + case 12: + st->codecpar->color_space = AVCOL_SPC_CHROMA_DERIVED_NCL; + break; + case 13: + st->codecpar->color_space = AVCOL_SPC_CHROMA_DERIVED_CL; + break; + case 14: + st->codecpar->color_space = AVCOL_SPC_ICTCP; + break; + default: + st->codecpar->color_space = AVCOL_SPC_UNSPECIFIED; + } + } + + /* Chroma Location */ + if(avs_library.avs_prop_get_type(avs->env, avsmap, "_ChromaLocation") == AVS_PROPTYPE_UNSET) { + st->codecpar->chroma_location = AVCHROMA_LOC_UNSPECIFIED; + } else { + switch (avs_library.avs_prop_get_int(avs->env, avsmap, "_ChromaLocation", 0, &error)) { + case 0: + st->codecpar->chroma_location = AVCHROMA_LOC_LEFT; + break; + case 1: + st->codecpar->chroma_location = AVCHROMA_LOC_CENTER; + break; + case 2: + st->codecpar->chroma_location = AVCHROMA_LOC_TOPLEFT; + break; + case 3: + st->codecpar->chroma_location = AVCHROMA_LOC_TOP; + break; + case 4: + st->codecpar->chroma_location = AVCHROMA_LOC_BOTTOMLEFT; + break; + case 5: + st->codecpar->chroma_location = AVCHROMA_LOC_BOTTOM; + break; + default: + st->codecpar->chroma_location = AVCHROMA_LOC_UNSPECIFIED; + } + } + } else { + st->codecpar->field_order = AV_FIELD_UNKNOWN; + /* AviSynth works with frame-based video, detecting field order can + * only work when avs_is_field_based returns 'false'. */ + av_log(s, AV_LOG_TRACE, "avs_is_field_based: %d\n", avs_is_field_based(avs->vi)); + if (avs_is_field_based(avs->vi) == 0) { + if (avs_is_tff(avs->vi)) { + st->codecpar->field_order = AV_FIELD_TT; + } + else if (avs_is_bff(avs->vi)) { + st->codecpar->field_order = AV_FIELD_BB; + } + } + } + return 0; } @@ -569,26 +810,38 @@ static int avisynth_create_stream(AVFormatContext *s) static int avisynth_open_file(AVFormatContext *s) { AviSynthContext *avs = s->priv_data; - AVS_Value arg, val; + AVS_Value val; int ret; -#ifdef _WIN32 - char filename_ansi[MAX_PATH * 4]; - wchar_t filename_wc[MAX_PATH * 4]; -#endif if (ret = avisynth_context_create(s)) return ret; + if (!avs_library.avs_check_version(avs->env, 7)) { + AVS_Value args[] = { + avs_new_value_string(s->url), + avs_new_value_bool(1) // filename is in UTF-8 + }; + val = avs_library.avs_invoke(avs->env, "Import", + avs_new_value_array(args, 2), 0); + } else { + AVS_Value arg; #ifdef _WIN32 - /* Convert UTF-8 to ANSI code page */ - MultiByteToWideChar(CP_UTF8, 0, s->url, -1, filename_wc, MAX_PATH * 4); - WideCharToMultiByte(CP_THREAD_ACP, 0, filename_wc, -1, filename_ansi, - MAX_PATH * 4, NULL, NULL); - arg = avs_new_value_string(filename_ansi); + char *filename_ansi; + /* Convert UTF-8 to ANSI code page */ + if (utf8toansi(s->url, &filename_ansi)) { + ret = AVERROR_UNKNOWN; + goto fail; + } + arg = avs_new_value_string(filename_ansi); #else - arg = avs_new_value_string(s->url); + arg = avs_new_value_string(s->url); #endif - val = avs_library.avs_invoke(avs->env, "Import", arg, 0); + val = avs_library.avs_invoke(avs->env, "Import", arg, 0); +#ifdef _WIN32 + av_free(filename_ansi); +#endif + } + if (avs_is_error(val)) { av_log(s, AV_LOG_ERROR, "%s\n", avs_as_error(val)); ret = AVERROR_UNKNOWN; diff --git a/libavformat/avlanguage.c b/libavformat/avlanguage.c index c36893c99..782a58adb 100644 --- a/libavformat/avlanguage.c +++ b/libavformat/avlanguage.c @@ -19,8 +19,7 @@ */ #include "avlanguage.h" -#include "libavutil/avstring.h" -#include "libavutil/common.h" +#include "libavutil/macros.h" #include #include #include diff --git a/libavformat/avr.c b/libavformat/avr.c index 6fdcf6895..1cc4d56bf 100644 --- a/libavformat/avr.c +++ b/libavformat/avr.c @@ -53,9 +53,9 @@ static int avr_read_header(AVFormatContext *s) chan = avio_rb16(s->pb); if (!chan) { - st->codecpar->channels = 1; + st->codecpar->ch_layout.nb_channels = 1; } else if (chan == 0xFFFFu) { - st->codecpar->channels = 2; + st->codecpar->ch_layout.nb_channels = 2; } else { avpriv_request_sample(s, "chan %d", chan); return AVERROR_PATCHWELCOME; @@ -81,7 +81,7 @@ static int avr_read_header(AVFormatContext *s) return AVERROR_PATCHWELCOME; } - st->codecpar->block_align = bps * st->codecpar->channels / 8; + st->codecpar->block_align = bps * st->codecpar->ch_layout.nb_channels / 8; avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); return 0; diff --git a/libavformat/avs2dec.c b/libavformat/avs2dec.c index 51908d2b6..0d5b23b65 100644 --- a/libavformat/avs2dec.c +++ b/libavformat/avs2dec.c @@ -22,7 +22,7 @@ #include "avformat.h" #include "rawdec.h" -#include "libavcodec/internal.h" +#include "libavcodec/startcode.h" #include "libavutil/intreadwrite.h" #define AVS2_ISSQH(x) ((x) == 0xB0) diff --git a/libavformat/avs3dec.c b/libavformat/avs3dec.c index 253caa7c1..2395df171 100644 --- a/libavformat/avs3dec.c +++ b/libavformat/avs3dec.c @@ -22,7 +22,7 @@ */ #include "libavcodec/avs3.h" -#include "libavcodec/internal.h" +#include "libavcodec/startcode.h" #include "avformat.h" #include "rawdec.h" diff --git a/libavformat/bethsoftvid.c b/libavformat/bethsoftvid.c index 65aab11ad..cfb7d5733 100644 --- a/libavformat/bethsoftvid.c +++ b/libavformat/bethsoftvid.c @@ -254,8 +254,7 @@ static int vid_read_packet(AVFormatContext *s, vid->audio_index = st->index; st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_PCM_U8; - st->codecpar->channels = 1; - st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; st->codecpar->bits_per_coded_sample = 8; st->codecpar->sample_rate = vid->sample_rate; st->codecpar->bit_rate = 8 * st->codecpar->sample_rate; diff --git a/libavformat/bfi.c b/libavformat/bfi.c index 69000118f..6bcd3cd40 100644 --- a/libavformat/bfi.c +++ b/libavformat/bfi.c @@ -29,6 +29,7 @@ #include "libavutil/channel_layout.h" #include "libavutil/intreadwrite.h" #include "avformat.h" +#include "demux.h" #include "internal.h" typedef struct BFIContext { @@ -106,8 +107,7 @@ static int bfi_read_header(AVFormatContext * s) /* Set up the audio codec now... */ astream->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; astream->codecpar->codec_id = AV_CODEC_ID_PCM_U8; - astream->codecpar->channels = 1; - astream->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + astream->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; astream->codecpar->bits_per_coded_sample = 8; astream->codecpar->bit_rate = (int64_t)astream->codecpar->sample_rate * astream->codecpar->bits_per_coded_sample; @@ -140,12 +140,12 @@ static int bfi_read_packet(AVFormatContext * s, AVPacket * pkt) audio_offset = avio_rl32(pb); avio_rl32(pb); video_offset = avio_rl32(pb); - audio_size = video_offset - audio_offset; - bfi->video_size = chunk_size - video_offset; - if (audio_size < 0 || bfi->video_size < 0) { + if (audio_offset < 0 || video_offset < audio_offset || chunk_size < video_offset) { av_log(s, AV_LOG_ERROR, "Invalid audio/video offsets or chunk size\n"); return AVERROR_INVALIDDATA; } + audio_size = video_offset - audio_offset; + bfi->video_size = chunk_size - video_offset; //Tossing an audio packet at the audio decoder. ret = av_get_packet(pb, pkt, audio_size); diff --git a/libavformat/bink.c b/libavformat/bink.c index 6627a17e7..f4079dfb1 100644 --- a/libavformat/bink.c +++ b/libavformat/bink.c @@ -33,6 +33,7 @@ #include "libavutil/channel_layout.h" #include "libavutil/intreadwrite.h" #include "avformat.h" +#include "demux.h" #include "internal.h" enum BinkAudFlags { @@ -186,11 +187,9 @@ static int read_header(AVFormatContext *s) ast->codecpar->codec_id = flags & BINK_AUD_USEDCT ? AV_CODEC_ID_BINKAUDIO_DCT : AV_CODEC_ID_BINKAUDIO_RDFT; if (flags & BINK_AUD_STEREO) { - ast->codecpar->channels = 2; - ast->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; + ast->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; } else { - ast->codecpar->channels = 1; - ast->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + ast->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; } if ((ret = ff_alloc_extradata(ast->codecpar, 4)) < 0) return ret; @@ -283,7 +282,7 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt) (in bytes). We use this value to calculate the audio PTS */ if (pkt->size >= 4) bink->audio_pts[bink->current_track -1] += - AV_RL32(pkt->data) / (2 * s->streams[bink->current_track]->codecpar->channels); + AV_RL32(pkt->data) / (2 * s->streams[bink->current_track]->codecpar->ch_layout.nb_channels); return 0; } else { avio_skip(pb, audio_size); diff --git a/libavformat/binka.c b/libavformat/binka.c index d4cfee036..00703ad01 100644 --- a/libavformat/binka.c +++ b/libavformat/binka.c @@ -44,7 +44,7 @@ static int binka_read_header(AVFormatContext *s) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_BINKAUDIO_DCT; - st->codecpar->channels = avio_r8(pb); + st->codecpar->ch_layout.nb_channels = avio_r8(pb); st->codecpar->sample_rate = avio_rl16(pb); st->duration = avio_rl32(pb); diff --git a/libavformat/bintext.c b/libavformat/bintext.c index 1270c7fb2..b6f14a03e 100644 --- a/libavformat/bintext.c +++ b/libavformat/bintext.c @@ -30,6 +30,8 @@ * iCEDraw File demuxer */ +#include "config_components.h" + #include "libavutil/intreadwrite.h" #include "libavutil/opt.h" #include "libavutil/parseutils.h" @@ -130,8 +132,6 @@ static int bin_probe(const 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)); @@ -155,12 +155,6 @@ static int bin_probe(const AVProbeData *p) 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 0; diff --git a/libavformat/bit.c b/libavformat/bit.c index 380cbd37c..9efb4ac07 100644 --- a/libavformat/bit.c +++ b/libavformat/bit.c @@ -18,6 +18,9 @@ * 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_components.h" + #include "avformat.h" #include "internal.h" #include "libavcodec/get_bits.h" @@ -63,7 +66,7 @@ static int read_header(AVFormatContext *s) st->codecpar->codec_id=AV_CODEC_ID_G729; st->codecpar->sample_rate=8000; st->codecpar->block_align = 16; - st->codecpar->channels=1; + st->codecpar->ch_layout.nb_channels = 1; avpriv_set_pts_info(st, 64, 1, 100); return 0; @@ -124,14 +127,14 @@ static int write_header(AVFormatContext *s) { AVCodecParameters *par = s->streams[0]->codecpar; - if ((par->codec_id != AV_CODEC_ID_G729) || par->channels != 1) { + if ((par->codec_id != AV_CODEC_ID_G729) || par->ch_layout.nb_channels != 1) { av_log(s, AV_LOG_ERROR, "only codec g729 with 1 channel is supported by this format\n"); return AVERROR(EINVAL); } par->bits_per_coded_sample = 16; - par->block_align = (par->bits_per_coded_sample * par->channels) >> 3; + par->block_align = (par->bits_per_coded_sample * par->ch_layout.nb_channels) >> 3; return 0; } diff --git a/libavformat/bmv.c b/libavformat/bmv.c index 873ecb027..e1f667076 100644 --- a/libavformat/bmv.c +++ b/libavformat/bmv.c @@ -58,8 +58,7 @@ static int bmv_read_header(AVFormatContext *s) return AVERROR(ENOMEM); ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; ast->codecpar->codec_id = AV_CODEC_ID_BMV_AUDIO; - ast->codecpar->channels = 2; - ast->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; + ast->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; ast->codecpar->sample_rate = 22050; avpriv_set_pts_info(ast, 16, 1, 22050); diff --git a/libavformat/boadec.c b/libavformat/boadec.c index 536300a89..02763142f 100644 --- a/libavformat/boadec.c +++ b/libavformat/boadec.c @@ -55,15 +55,16 @@ static int read_header(AVFormatContext *s) avio_rl32(s->pb); avio_rl32(s->pb); st->codecpar->sample_rate = avio_rl32(s->pb); - st->codecpar->channels = avio_rl32(s->pb); - if (st->codecpar->channels > FF_SANE_NB_CHANNELS || st->codecpar->channels <= 0) + st->codecpar->ch_layout.nb_channels = avio_rl32(s->pb); + if (st->codecpar->ch_layout.nb_channels > FF_SANE_NB_CHANNELS || + st->codecpar->ch_layout.nb_channels <= 0) return AVERROR(ENOSYS); ffformatcontext(s)->data_offset = data_offset = avio_rl32(s->pb); avio_r8(s->pb); st->codecpar->block_align = avio_rl32(s->pb); if (st->codecpar->block_align > INT_MAX / FF_SANE_NB_CHANNELS || st->codecpar->block_align <= 0) return AVERROR_INVALIDDATA; - st->codecpar->block_align *= st->codecpar->channels; + st->codecpar->block_align *= st->codecpar->ch_layout.nb_channels; avio_seek(s->pb, data_offset, SEEK_SET); diff --git a/libavformat/brstm.c b/libavformat/brstm.c index 338491d9e..628c556e6 100644 --- a/libavformat/brstm.c +++ b/libavformat/brstm.c @@ -22,6 +22,7 @@ #include "libavutil/intreadwrite.h" #include "libavcodec/bytestream.h" #include "avformat.h" +#include "demux.h" #include "internal.h" typedef struct BRSTMCoeffOffset { @@ -209,8 +210,8 @@ static int read_header(AVFormatContext *s) loop = avio_r8(s->pb); // loop flag st->codecpar->codec_id = codec; - st->codecpar->channels = avio_r8(s->pb); - if (!st->codecpar->channels) + st->codecpar->ch_layout.nb_channels = avio_r8(s->pb); + if (!st->codecpar->ch_layout.nb_channels) return AVERROR_INVALIDDATA; avio_skip(s->pb, 1); // padding @@ -246,14 +247,14 @@ static int read_header(AVFormatContext *s) } b->block_size = read32(s); - if (b->block_size > UINT32_MAX / st->codecpar->channels) + if (b->block_size > UINT32_MAX / st->codecpar->ch_layout.nb_channels) return AVERROR_INVALIDDATA; b->samples_per_block = read32(s); b->last_block_used_bytes = read32(s); b->last_block_samples = read32(s); b->last_block_size = read32(s); - if (b->last_block_size > UINT32_MAX / st->codecpar->channels) + if (b->last_block_size > UINT32_MAX / st->codecpar->ch_layout.nb_channels) return AVERROR_INVALIDDATA; if (b->last_block_used_bytes > b->last_block_size) return AVERROR_INVALIDDATA; @@ -266,24 +267,24 @@ static int read_header(AVFormatContext *s) if (!bfstm) toffset = read32(s) + 16LL; else - toffset = toffset + read32(s) + st->codecpar->channels * 8 - 8; + toffset = toffset + read32(s) + st->codecpar->ch_layout.nb_channels * 8 - 8; if (toffset > size) return AVERROR_INVALIDDATA; if (!bfstm) { - avio_skip(s->pb, pos + toffset - avio_tell(s->pb) - 8LL * (st->codecpar->channels + 1)); - for (ch = 0; ch < st->codecpar->channels; ch++) { + avio_skip(s->pb, pos + toffset - avio_tell(s->pb) - 8LL * (st->codecpar->ch_layout.nb_channels + 1)); + for (ch = 0; ch < st->codecpar->ch_layout.nb_channels; ch++) { avio_skip(s->pb, 4); b->offsets[ch].channel = ch; b->offsets[ch].offset = read32(s); } - qsort(b->offsets, st->codecpar->channels, sizeof(*b->offsets), sort_offsets); + qsort(b->offsets, st->codecpar->ch_layout.nb_channels, sizeof(*b->offsets), sort_offsets); } avio_skip(s->pb, pos + toffset - avio_tell(s->pb)); - for (ch = 0; ch < st->codecpar->channels; ch++) { + for (ch = 0; ch < st->codecpar->ch_layout.nb_channels; ch++) { if (!bfstm) avio_skip(s->pb, pos + 16LL + b->offsets[ch].offset - avio_tell(s->pb)); @@ -313,7 +314,7 @@ static int read_header(AVFormatContext *s) codec != AV_CODEC_ID_ADPCM_THP_LE) goto skip; - asize = b->block_count * st->codecpar->channels * 4; + asize = b->block_count * st->codecpar->ch_layout.nb_channels * 4; if (size < asize) return AVERROR_INVALIDDATA; if (b->adpc) { @@ -369,6 +370,7 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt) AVCodecParameters *par = s->streams[0]->codecpar; BRSTMDemuxContext *b = s->priv_data; uint32_t samples, size, skip = 0; + int channels = par->ch_layout.nb_channels; int ret, i; if (avio_feof(s->pb)) @@ -404,24 +406,24 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt) } if (size > (INT_MAX - 32 - 4) || - (32 + 4 + size) > (INT_MAX / par->channels) || - (32 + 4 + size) * par->channels > INT_MAX - 8) + (32 + 4 + size) > (INT_MAX / channels) || + (32 + 4 + size) * channels > INT_MAX - 8) return AVERROR_INVALIDDATA; - if ((ret = av_new_packet(pkt, 8 + (32 + 4 + size) * par->channels)) < 0) + if ((ret = av_new_packet(pkt, 8 + (32 + 4 + size) * channels)) < 0) return ret; dst = pkt->data; if (par->codec_id == AV_CODEC_ID_ADPCM_THP_LE) { - bytestream_put_le32(&dst, size * par->channels); + bytestream_put_le32(&dst, size * channels); bytestream_put_le32(&dst, samples); } else { - bytestream_put_be32(&dst, size * par->channels); + bytestream_put_be32(&dst, size * channels); bytestream_put_be32(&dst, samples); } - bytestream_put_buffer(&dst, b->table, 32 * par->channels); - bytestream_put_buffer(&dst, b->adpc + 4 * par->channels * - (b->current_block - 1), 4 * par->channels); + bytestream_put_buffer(&dst, b->table, 32 * channels); + bytestream_put_buffer(&dst, b->adpc + 4 * channels * + (b->current_block - 1), 4 * channels); - for (i = 0; i < par->channels; i++) { + for (i = 0; i < channels; i++) { ret = avio_read(s->pb, dst, size); dst += size; avio_skip(s->pb, skip); @@ -431,7 +433,7 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt) } pkt->duration = samples; } else { - size *= par->channels; + size *= channels; ret = av_get_packet(s->pb, pkt, size); } @@ -456,7 +458,7 @@ static int read_seek(AVFormatContext *s, int stream_index, if (timestamp >= b->block_count) timestamp = b->block_count - 1; ret = avio_seek(s->pb, b->data_start + timestamp * b->block_size * - st->codecpar->channels, SEEK_SET); + st->codecpar->ch_layout.nb_channels, SEEK_SET); if (ret < 0) return ret; diff --git a/libavformat/caf.c b/libavformat/caf.c index a700e4055..a61c39fae 100644 --- a/libavformat/caf.c +++ b/libavformat/caf.c @@ -46,6 +46,7 @@ const AVCodecTag ff_codec_caf_tags[] = { { AV_CODEC_ID_GSM, MKTAG('a','g','s','m') }, { AV_CODEC_ID_GSM_MS, MKTAG('m','s', 0, '1') }, { AV_CODEC_ID_ILBC, MKTAG('i','l','b','c') }, + { AV_CODEC_ID_FLAC, MKTAG('f','l','a','c') }, { AV_CODEC_ID_MACE3, MKTAG('M','A','C','3') }, { AV_CODEC_ID_MACE6, MKTAG('M','A','C','6') }, { AV_CODEC_ID_MP1, MKTAG('.','m','p','1') }, diff --git a/libavformat/cafdec.c b/libavformat/cafdec.c index d5668bfe1..d5b8c38c2 100644 --- a/libavformat/cafdec.c +++ b/libavformat/cafdec.c @@ -28,9 +28,11 @@ #include #include "avformat.h" +#include "demux.h" #include "internal.h" #include "isom.h" #include "mov_chan.h" +#include "libavcodec/flac.h" #include "libavutil/intreadwrite.h" #include "libavutil/intfloat.h" #include "libavutil/dict.h" @@ -76,10 +78,10 @@ static int read_desc_chunk(AVFormatContext *s) caf->bytes_per_packet = avio_rb32(pb); st->codecpar->block_align = caf->bytes_per_packet; caf->frames_per_packet = avio_rb32(pb); - st->codecpar->channels = avio_rb32(pb); + st->codecpar->ch_layout.nb_channels = avio_rb32(pb); st->codecpar->bits_per_coded_sample = avio_rb32(pb); - if (caf->bytes_per_packet < 0 || caf->frames_per_packet < 0 || st->codecpar->channels < 0) + if (caf->bytes_per_packet < 0 || caf->frames_per_packet < 0 || st->codecpar->ch_layout.nb_channels < 0) return AVERROR_INVALIDDATA; /* calculate bit rate for constant size packets */ @@ -169,10 +171,53 @@ static int read_kuki_chunk(AVFormatContext *s, int64_t size) } avio_skip(pb, size - ALAC_NEW_KUKI); } + } else if (st->codecpar->codec_id == AV_CODEC_ID_FLAC) { + int last, type, flac_metadata_size; + uint8_t buf[4]; + /* The magic cookie format for FLAC consists mostly of an mp4 dfLa atom. */ + if (size < (16 + FLAC_STREAMINFO_SIZE)) { + av_log(s, AV_LOG_ERROR, "invalid FLAC magic cookie\n"); + return AVERROR_INVALIDDATA; + } + /* Check cookie version. */ + if (avio_r8(pb) != 0) { + av_log(s, AV_LOG_ERROR, "unknown FLAC magic cookie\n"); + return AVERROR_INVALIDDATA; + } + avio_rb24(pb); /* Flags */ + /* read dfLa fourcc */ + if (avio_read(pb, buf, 4) != 4) { + av_log(s, AV_LOG_ERROR, "failed to read FLAC magic cookie\n"); + return pb->error < 0 ? pb->error : AVERROR_INVALIDDATA; + } + if (memcmp(buf, "dfLa", 4)) { + av_log(s, AV_LOG_ERROR, "invalid FLAC magic cookie\n"); + return AVERROR_INVALIDDATA; + } + /* Check dfLa version. */ + if (avio_r8(pb) != 0) { + av_log(s, AV_LOG_ERROR, "unknown dfLa version\n"); + return AVERROR_INVALIDDATA; + } + avio_rb24(pb); /* Flags */ + if (avio_read(pb, buf, sizeof(buf)) != sizeof(buf)) { + av_log(s, AV_LOG_ERROR, "failed to read FLAC metadata block header\n"); + return pb->error < 0 ? pb->error : AVERROR_INVALIDDATA; + } + flac_parse_block_header(buf, &last, &type, &flac_metadata_size); + if (type != FLAC_METADATA_TYPE_STREAMINFO || flac_metadata_size != FLAC_STREAMINFO_SIZE) { + av_log(s, AV_LOG_ERROR, "STREAMINFO must be first FLACMetadataBlock\n"); + return AVERROR_INVALIDDATA; + } + ret = ff_get_extradata(s, st->codecpar, pb, FLAC_STREAMINFO_SIZE); + if (ret < 0) + return ret; + if (!last) + av_log(s, AV_LOG_WARNING, "non-STREAMINFO FLACMetadataBlock(s) ignored\n"); } 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) { + if (st->codecpar->ch_layout.nb_channels > 2) { avpriv_request_sample(s, "multichannel Opus in CAF"); return AVERROR_PATCHWELCOME; } diff --git a/libavformat/cafenc.c b/libavformat/cafenc.c index 412b3230e..fedb430b1 100644 --- a/libavformat/cafenc.c +++ b/libavformat/cafenc.c @@ -23,6 +23,7 @@ #include "caf.h" #include "isom.h" #include "avio_internal.h" +#include "mux.h" #include "libavutil/intfloat.h" #include "libavutil/dict.h" @@ -122,7 +123,7 @@ static int caf_write_header(AVFormatContext *s) return AVERROR_PATCHWELCOME; } - if (par->codec_id == AV_CODEC_ID_OPUS && par->channels > 2) { + if (par->codec_id == AV_CODEC_ID_OPUS && par->ch_layout.nb_channels > 2) { av_log(s, AV_LOG_ERROR, "Only mono and stereo are supported for Opus\n"); return AVERROR_INVALIDDATA; } @@ -138,7 +139,7 @@ static int caf_write_header(AVFormatContext *s) } if (par->codec_id != AV_CODEC_ID_MP3 || frame_size != 576) - frame_size = samples_per_packet(par->codec_id, par->channels, par->block_align); + frame_size = samples_per_packet(par->codec_id, par->ch_layout.nb_channels, par->block_align); ffio_wfourcc(pb, "caff"); //< mFileType avio_wb16(pb, 1); //< mFileVersion @@ -151,13 +152,13 @@ static int caf_write_header(AVFormatContext *s) avio_wb32(pb, codec_flags(par->codec_id)); //< mFormatFlags avio_wb32(pb, par->block_align); //< mBytesPerPacket avio_wb32(pb, frame_size); //< mFramesPerPacket - avio_wb32(pb, par->channels); //< mChannelsPerFrame + avio_wb32(pb, par->ch_layout.nb_channels); //< mChannelsPerFrame avio_wb32(pb, av_get_bits_per_sample(par->codec_id)); //< mBitsPerChannel - if (par->channel_layout) { + if (par->ch_layout.order == AV_CHANNEL_ORDER_NATIVE) { ffio_wfourcc(pb, "chan"); avio_wb64(pb, 12); - ff_mov_write_chan(pb, par->channel_layout); + ff_mov_write_chan(pb, par->ch_layout.u.mask); } if (par->codec_id == AV_CODEC_ID_ALAC) { @@ -247,7 +248,7 @@ static int caf_write_trailer(AVFormatContext *s) avio_seek(pb, caf->data, SEEK_SET); avio_wb64(pb, file_size - caf->data - 8); if (!par->block_align) { - int packet_size = samples_per_packet(par->codec_id, par->channels, par->block_align); + int packet_size = samples_per_packet(par->codec_id, par->ch_layout.nb_channels, par->block_align); if (!packet_size) { packet_size = st->duration / (caf->packets - 1); avio_seek(pb, FRAME_SIZE_OFFSET, SEEK_SET); diff --git a/libavformat/cavsvideodec.c b/libavformat/cavsvideodec.c index 8900b9759..b89851fbb 100644 --- a/libavformat/cavsvideodec.c +++ b/libavformat/cavsvideodec.c @@ -19,16 +19,17 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavcodec/startcode.h" #include "avformat.h" #include "rawdec.h" -#include "libavcodec/internal.h" #define CAVS_SEQ_START_CODE 0x000001b0 #define CAVS_PIC_I_START_CODE 0x000001b3 #define CAVS_UNDEF_START_CODE 0x000001b4 #define CAVS_PIC_PB_START_CODE 0x000001b6 #define CAVS_VIDEO_EDIT_CODE 0x000001b7 -#define CAVS_PROFILE_JIZHUN 0x20 +#define CAVS_PROFILE_JIZHUN 0x20 // AVS1 P2 +#define CAVS_PROFILE_GUANGDIAN 0x48 // AVS1 P16/AVS+ static int cavsvideo_probe(const AVProbeData *p) { @@ -50,7 +51,7 @@ static int cavsvideo_probe(const AVProbeData *p) if (code == CAVS_SEQ_START_CODE) { seq++; /* check for the only currently supported profile */ - if (*ptr != CAVS_PROFILE_JIZHUN) + if (*ptr != CAVS_PROFILE_JIZHUN && *ptr != CAVS_PROFILE_GUANGDIAN) return 0; } else if ((code == CAVS_PIC_I_START_CODE) || (code == CAVS_PIC_PB_START_CODE)) { @@ -66,4 +67,4 @@ static int cavsvideo_probe(const AVProbeData *p) return 0; } -FF_DEF_RAWVIDEO_DEMUXER(cavsvideo, "raw Chinese AVS (Audio Video Standard)", cavsvideo_probe, NULL, AV_CODEC_ID_CAVS) +FF_DEF_RAWVIDEO_DEMUXER(cavsvideo, "raw Chinese AVS (Audio Video Standard)", cavsvideo_probe, "avs", AV_CODEC_ID_CAVS) diff --git a/libavformat/cdxl.c b/libavformat/cdxl.c index c42e0d354..065148360 100644 --- a/libavformat/cdxl.c +++ b/libavformat/cdxl.c @@ -178,8 +178,7 @@ static int cdxl_read_packet(AVFormatContext *s, AVPacket *pkt) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_tag = 0; st->codecpar->codec_id = AV_CODEC_ID_PCM_S8_PLANAR; - st->codecpar->channels = channels; - st->codecpar->channel_layout = channels == 2 ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO; + av_channel_layout_default(&st->codecpar->ch_layout, channels); st->codecpar->sample_rate= cdxl->srate; st->start_time = 0; cdxl->audio_stream_index = st->index; diff --git a/libavformat/chromaprint.c b/libavformat/chromaprint.c index e4882c8e6..3953a5ced 100644 --- a/libavformat/chromaprint.c +++ b/libavformat/chromaprint.c @@ -22,7 +22,6 @@ #include "avformat.h" #include "internal.h" #include "libavutil/opt.h" -#include "libavcodec/internal.h" #include #define CPR_VERSION_INT AV_VERSION_INT(CHROMAPRINT_VERSION_MAJOR, \ @@ -92,7 +91,7 @@ static int write_header(AVFormatContext *s) st = s->streams[0]; - if (st->codecpar->channels > 2) { + if (st->codecpar->ch_layout.nb_channels > 2) { av_log(s, AV_LOG_ERROR, "Only up to 2 channels are supported\n"); return AVERROR(EINVAL); } @@ -102,7 +101,7 @@ static int write_header(AVFormatContext *s) return AVERROR(EINVAL); } - if (!chromaprint_start(cpr->ctx, st->codecpar->sample_rate, st->codecpar->channels)) { + if (!chromaprint_start(cpr->ctx, st->codecpar->sample_rate, st->codecpar->ch_layout.nb_channels)) { av_log(s, AV_LOG_ERROR, "Failed to start chromaprint\n"); return AVERROR_EXTERNAL; } diff --git a/libavformat/cinedec.c b/libavformat/cinedec.c index f4779b267..e8d9657ee 100644 --- a/libavformat/cinedec.c +++ b/libavformat/cinedec.c @@ -273,10 +273,11 @@ static int cine_read_header(AVFormatContext *avctx) /* parse image offsets */ avio_seek(pb, offImageOffsets, SEEK_SET); for (i = 0; i < st->duration; i++) { - if (avio_feof(pb)) + int64_t pos = avio_rl64(pb); + if (avio_feof(pb) || pos < 0) return AVERROR_INVALIDDATA; - av_add_index_entry(st, avio_rl64(pb), i, 0, 0, AVINDEX_KEYFRAME); + av_add_index_entry(st, pos, i, 0, 0, AVINDEX_KEYFRAME); } return 0; @@ -302,10 +303,10 @@ static int cine_read_packet(AVFormatContext *avctx, AVPacket *pkt) return AVERROR_INVALIDDATA; avio_skip(pb, n - 8); size = avio_rl32(pb); - if (avio_feof(pb)) + if (avio_feof(pb) || size < 0) return AVERROR_INVALIDDATA; - if (cine->maxsize && sti->index_entries[cine->pts].pos + size + n > cine->maxsize) + if (cine->maxsize && (uint64_t)sti->index_entries[cine->pts].pos + size + n > cine->maxsize) size = cine->maxsize - sti->index_entries[cine->pts].pos - n; ret = av_get_packet(pb, pkt, size); @@ -313,7 +314,7 @@ static int cine_read_packet(AVFormatContext *avctx, AVPacket *pkt) return ret; if (ret != size) - cine->maxsize = sti->index_entries[cine->pts].pos + n + ret; + cine->maxsize = (uint64_t)sti->index_entries[cine->pts].pos + n + ret; pkt->pts = cine->pts++; pkt->stream_index = 0; diff --git a/libavformat/codec2.c b/libavformat/codec2.c index 0b992836b..400c5acbd 100644 --- a/libavformat/codec2.c +++ b/libavformat/codec2.c @@ -19,7 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include +#include "config_components.h" + #include "libavcodec/codec2utils.h" #include "libavutil/channel_layout.h" #include "libavutil/intreadwrite.h" @@ -129,9 +130,8 @@ static int codec2_read_header_common(AVFormatContext *s, AVStream *st) 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->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; st->codecpar->bit_rate = codec2_mode_bit_rate(s, mode); st->codecpar->frame_size = codec2_mode_frame_size(s, mode); st->codecpar->block_align = codec2_mode_block_align(s, mode); diff --git a/libavformat/concat.c b/libavformat/concat.c index faeba2293..dc0985e40 100644 --- a/libavformat/concat.c +++ b/libavformat/concat.c @@ -21,6 +21,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/avstring.h" #include "libavutil/bprint.h" #include "libavutil/mem.h" diff --git a/libavformat/concatdec.c b/libavformat/concatdec.c index 0603c6e25..e57da59e0 100644 --- a/libavformat/concatdec.c +++ b/libavformat/concatdec.c @@ -28,6 +28,7 @@ #include "libavcodec/bsf.h" #include "avformat.h" #include "avio_internal.h" +#include "demux.h" #include "internal.h" #include "url.h" @@ -816,16 +817,6 @@ static int concat_read_packet(AVFormatContext *avf, AVPacket *pkt) return 0; } -static void rescale_interval(AVRational tb_in, AVRational tb_out, - int64_t *min_ts, int64_t *ts, int64_t *max_ts) -{ - *ts = av_rescale_q (* ts, tb_in, tb_out); - *min_ts = av_rescale_q_rnd(*min_ts, tb_in, tb_out, - AV_ROUND_UP | AV_ROUND_PASS_MINMAX); - *max_ts = av_rescale_q_rnd(*max_ts, tb_in, tb_out, - AV_ROUND_DOWN | AV_ROUND_PASS_MINMAX); -} - static int try_seek(AVFormatContext *avf, int stream, int64_t min_ts, int64_t ts, int64_t max_ts, int flags) { @@ -838,8 +829,8 @@ static int try_seek(AVFormatContext *avf, int stream, if (stream >= 0) { if (stream >= cat->avf->nb_streams) return AVERROR(EIO); - rescale_interval(AV_TIME_BASE_Q, cat->avf->streams[stream]->time_base, - &min_ts, &ts, &max_ts); + ff_rescale_interval(AV_TIME_BASE_Q, cat->avf->streams[stream]->time_base, + &min_ts, &ts, &max_ts); } return avformat_seek_file(cat->avf, stream, min_ts, ts, max_ts, flags); } @@ -853,8 +844,8 @@ static int real_seek(AVFormatContext *avf, int stream, if (stream >= 0) { if (stream >= avf->nb_streams) return AVERROR(EINVAL); - rescale_interval(avf->streams[stream]->time_base, AV_TIME_BASE_Q, - &min_ts, &ts, &max_ts); + ff_rescale_interval(avf->streams[stream]->time_base, AV_TIME_BASE_Q, + &min_ts, &ts, &max_ts); } left = 0; diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c index 797fe7415..63bf7e96a 100644 --- a/libavformat/dashdec.c +++ b/libavformat/dashdec.c @@ -21,17 +21,15 @@ */ #include #include "libavutil/bprint.h" -#include "libavutil/intreadwrite.h" #include "libavutil/opt.h" #include "libavutil/time.h" #include "libavutil/parseutils.h" #include "internal.h" #include "avio_internal.h" #include "dash.h" +#include "demux.h" #define INITIAL_BUFFER_SIZE 32768 -#define MAX_BPRINT_READ_SIZE (UINT_MAX - 1) -#define DEFAULT_MANIFEST_SIZE 8 * 1024 struct fragment { int64_t url_offset; @@ -152,6 +150,7 @@ typedef struct DASHContext { char *allowed_extensions; AVDictionary *avio_opts; int max_url_size; + char *cenc_decryption_key; /* Flags for init section*/ int is_init_section_common_video; @@ -405,6 +404,7 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, const char *url, DASHContext *c = s->priv_data; AVDictionary *tmp = NULL; const char *proto_name = NULL; + int proto_name_len; int ret; if (av_strstart(url, "crypto", NULL)) { @@ -418,6 +418,7 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, const char *url, if (!proto_name) return AVERROR_INVALIDDATA; + proto_name_len = strlen(proto_name); // only http(s) & file are allowed if (av_strstart(proto_name, "file", NULL)) { if (strcmp(c->allowed_extensions, "ALL") && !av_match_ext(url, c->allowed_extensions)) { @@ -432,9 +433,9 @@ static int open_url(AVFormatContext *s, AVIOContext **pb, const char *url, } else return AVERROR_INVALIDDATA; - if (!strncmp(proto_name, url, strlen(proto_name)) && url[strlen(proto_name)] == ':') + if (!strncmp(proto_name, url, proto_name_len) && url[proto_name_len] == ':') ; - else if (av_strstart(url, "crypto", NULL) && !strncmp(proto_name, url + 7, strlen(proto_name)) && url[7 + strlen(proto_name)] == ':') + else if (av_strstart(url, "crypto", NULL) && !strncmp(proto_name, url + 7, proto_name_len) && url[7 + proto_name_len] == ':') ; else if (strcmp(proto_name, "file") || !strncmp(url, "file,", 5)) return AVERROR_INVALIDDATA; @@ -1195,7 +1196,6 @@ static int parse_manifest(AVFormatContext *s, const char *url, AVIOContext *in) DASHContext *c = s->priv_data; int ret = 0; int close_in = 0; - int64_t filesize = 0; AVBPrint buf; AVDictionary *opts = NULL; xmlDoc *doc = NULL; @@ -1226,26 +1226,17 @@ static int parse_manifest(AVFormatContext *s, const char *url, AVIOContext *in) if (av_opt_get(in, "location", AV_OPT_SEARCH_CHILDREN, (uint8_t**)&c->base_url) < 0) c->base_url = av_strdup(url); - filesize = avio_size(in); - filesize = filesize > 0 ? filesize : DEFAULT_MANIFEST_SIZE; + av_bprint_init(&buf, 0, INT_MAX); // xmlReadMemory uses integer bufsize - if (filesize > MAX_BPRINT_READ_SIZE) { - av_log(s, AV_LOG_ERROR, "Manifest too large: %"PRId64"\n", filesize); - return AVERROR_INVALIDDATA; - } - - av_bprint_init(&buf, filesize + 1, AV_BPRINT_SIZE_UNLIMITED); - - if ((ret = avio_read_to_bprint(in, &buf, MAX_BPRINT_READ_SIZE)) < 0 || - !avio_feof(in) || - (filesize = buf.len) == 0) { + if ((ret = avio_read_to_bprint(in, &buf, SIZE_MAX)) < 0 || + !avio_feof(in)) { av_log(s, AV_LOG_ERROR, "Unable to read to manifest '%s'\n", url); if (ret == 0) ret = AVERROR_INVALIDDATA; } else { LIBXML_TEST_VERSION - doc = xmlReadMemory(buf.str, filesize, c->base_url, NULL, 0); + doc = xmlReadMemory(buf.str, buf.len, c->base_url, NULL, 0); root_element = xmlDocGetRootElement(doc); node = root_element; @@ -1903,6 +1894,9 @@ static int reopen_demux_for_component(AVFormatContext *s, struct representation pls->ctx->pb = &pls->pb.pub; pls->ctx->io_open = nested_io_open; + if (c->cenc_decryption_key) + av_dict_set(&in_fmt_opts, "decryption_key", c->cenc_decryption_key, 0); + // provide additional information from mpd if available ret = avformat_open_input(&pls->ctx, "", in_fmt, &in_fmt_opts); //pls->init_section->url av_dict_free(&in_fmt_opts); @@ -2354,6 +2348,7 @@ static const AVOption dash_options[] = { OFFSET(allowed_extensions), AV_OPT_TYPE_STRING, {.str = "aac,m4a,m4s,m4v,mov,mp4,webm,ts"}, INT_MIN, INT_MAX, FLAGS}, + { "cenc_decryption_key", "Media decryption key (hex)", OFFSET(cenc_decryption_key), AV_OPT_TYPE_STRING, {.str = NULL}, INT_MIN, INT_MAX, .flags = FLAGS }, {NULL} }; diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 4709bc661..295b01e22 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -21,6 +21,7 @@ */ #include "config.h" +#include "config_components.h" #if HAVE_UNISTD_H #include #endif @@ -47,6 +48,7 @@ #endif #include "internal.h" #include "isom.h" +#include "mux.h" #include "os_support.h" #include "url.h" #include "vpcc.h" @@ -859,7 +861,7 @@ static int write_adaptation_set(AVFormatContext *s, AVIOContext *out, int as_ind avio_printf(out, "\t\t\t\n", i, os->format_name, os->codec_str, bandwidth_str, s->streams[i]->codecpar->sample_rate); avio_printf(out, "\t\t\t\t\n", - s->streams[i]->codecpar->channels); + s->streams[i]->codecpar->ch_layout.nb_channels); } if (!final && c->write_prft && os->producer_reference_time_str[0]) { avio_printf(out, "\t\t\t\t\n", diff --git a/libavformat/data_uri.c b/libavformat/data_uri.c index 1863830ab..28eb2b9e0 100644 --- a/libavformat/data_uri.c +++ b/libavformat/data_uri.c @@ -20,6 +20,7 @@ #include #include "libavutil/avstring.h" +#include "libavutil/avutil.h" #include "libavutil/base64.h" #include "url.h" diff --git a/libavformat/dauddec.c b/libavformat/dauddec.c index 6a5962c23..dbbd39a3b 100644 --- a/libavformat/dauddec.c +++ b/libavformat/dauddec.c @@ -29,8 +29,7 @@ static int daud_header(AVFormatContext *s) { st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_PCM_S24DAUD; st->codecpar->codec_tag = MKTAG('d', 'a', 'u', 'd'); - st->codecpar->channels = 6; - st->codecpar->channel_layout = AV_CH_LAYOUT_5POINT1; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1; st->codecpar->sample_rate = 96000; st->codecpar->bit_rate = 3 * 6 * 96000 * 8; st->codecpar->block_align = 3 * 6; diff --git a/libavformat/daudenc.c b/libavformat/daudenc.c index 183a08ba3..2e252449e 100644 --- a/libavformat/daudenc.c +++ b/libavformat/daudenc.c @@ -24,7 +24,7 @@ static int daud_init(struct AVFormatContext *s) { AVCodecParameters *par = s->streams[0]->codecpar; - if (par->channels!=6 || par->sample_rate!=96000) + if (par->ch_layout.nb_channels != 6 || par->sample_rate != 96000) return AVERROR(EINVAL); return 0; } diff --git a/libavformat/dcstr.c b/libavformat/dcstr.c index 71dce08bf..286ec92df 100644 --- a/libavformat/dcstr.c +++ b/libavformat/dcstr.c @@ -41,7 +41,7 @@ static int dcstr_read_header(AVFormatContext *s) return AVERROR(ENOMEM); st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; - st->codecpar->channels = avio_rl32(s->pb); + st->codecpar->ch_layout.nb_channels = avio_rl32(s->pb); st->codecpar->sample_rate = avio_rl32(s->pb); if (st->codecpar->sample_rate <= 0) return AVERROR_INVALIDDATA; @@ -50,14 +50,16 @@ static int dcstr_read_header(AVFormatContext *s) avio_skip(s->pb, 4); st->duration = avio_rl32(s->pb); mult = avio_rl32(s->pb); - if (st->codecpar->channels <= 0 || mult <= 0 || mult > INT_MAX / st->codecpar->channels) { - av_log(s, AV_LOG_ERROR, "invalid number of channels %d x %d\n", st->codecpar->channels, mult); + if (st->codecpar->ch_layout.nb_channels <= 0 || mult <= 0 || + mult > INT_MAX / st->codecpar->ch_layout.nb_channels) { + av_log(s, AV_LOG_ERROR, "invalid number of channels %d x %d\n", + st->codecpar->ch_layout.nb_channels, mult); return AVERROR_INVALIDDATA; } - st->codecpar->channels *= mult; - if (!align || align > INT_MAX / st->codecpar->channels) + st->codecpar->ch_layout.nb_channels *= mult; + if (!align || align > INT_MAX / st->codecpar->ch_layout.nb_channels) return AVERROR_INVALIDDATA; - st->codecpar->block_align = align * st->codecpar->channels; + st->codecpar->block_align = align * st->codecpar->ch_layout.nb_channels; switch (codec) { case 4: st->codecpar->codec_id = AV_CODEC_ID_ADPCM_AICA; break; diff --git a/libavformat/demux.c b/libavformat/demux.c index f895f0ba8..162071671 100644 --- a/libavformat/demux.c +++ b/libavformat/demux.c @@ -21,7 +21,7 @@ #include -#include "config.h" +#include "config_components.h" #include "libavutil/avassert.h" #include "libavutil/avstring.h" @@ -41,6 +41,7 @@ #include "avformat.h" #include "avio_internal.h" +#include "demux.h" #include "id3v2.h" #include "internal.h" #include "url.h" @@ -194,6 +195,18 @@ static int update_stream_avctx(AVFormatContext *s) sti->parser = NULL; } +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + if (st->codecpar->ch_layout.nb_channels && + !st->codecpar->channels) { + st->codecpar->channels = st->codecpar->ch_layout.nb_channels; + st->codecpar->channel_layout = st->codecpar->ch_layout.order == AV_CHANNEL_ORDER_NATIVE ? + st->codecpar->ch_layout.u.mask : 0; + + } +FF_ENABLE_DEPRECATION_WARNINGS +#endif + /* update internal codec context, for the parser */ ret = avcodec_parameters_to_context(sti->avctx, st->codecpar); if (ret < 0) @@ -1321,8 +1334,16 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) return ret; st->codecpar->sample_rate = sti->avctx->sample_rate; st->codecpar->bit_rate = sti->avctx->bit_rate; - st->codecpar->channels = sti->avctx->channels; - st->codecpar->channel_layout = sti->avctx->channel_layout; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + st->codecpar->channels = sti->avctx->ch_layout.nb_channels; + st->codecpar->channel_layout = sti->avctx->ch_layout.order == AV_CHANNEL_ORDER_NATIVE ? + sti->avctx->ch_layout.u.mask : 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + ret = av_channel_layout_copy(&st->codecpar->ch_layout, &sti->avctx->ch_layout); + if (ret < 0) + return ret; st->codecpar->codec_id = sti->avctx->codec_id; } else { /* free packet */ @@ -1346,7 +1367,7 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) if (sti->first_discard_sample && pkt->pts != AV_NOPTS_VALUE) { int64_t pts = pkt->pts - (is_relative(pkt->pts) ? RELATIVE_TS_BASE : 0); int64_t sample = ts_to_samples(st, pts); - int duration = ts_to_samples(st, pkt->duration); + int64_t duration = ts_to_samples(st, pkt->duration); int64_t end_sample = sample + duration; if (duration > 0 && end_sample >= sti->first_discard_sample && sample < sti->last_discard_sample) @@ -1354,12 +1375,14 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) } if (sti->start_skip_samples && (pkt->pts == 0 || pkt->pts == RELATIVE_TS_BASE)) sti->skip_samples = sti->start_skip_samples; + sti->skip_samples = FFMAX(0, sti->skip_samples); if (sti->skip_samples || discard_padding) { uint8_t *p = av_packet_new_side_data(pkt, AV_PKT_DATA_SKIP_SAMPLES, 10); if (p) { AV_WL32(p, sti->skip_samples); AV_WL32(p + 4, discard_padding); - av_log(s, AV_LOG_DEBUG, "demuxer injecting skip %d / discard %d\n", sti->skip_samples, discard_padding); + av_log(s, AV_LOG_DEBUG, "demuxer injecting skip %u / discard %u\n", + (unsigned)sti->skip_samples, (unsigned)discard_padding); } sti->skip_samples = 0; } @@ -1384,12 +1407,15 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) } } - av_opt_get_dict_val(s, "metadata", AV_OPT_SEARCH_CHILDREN, &metadata); - if (metadata) { - s->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED; - av_dict_copy(&s->metadata, metadata, 0); - av_dict_free(&metadata); - av_opt_set_dict_val(s, "metadata", NULL, AV_OPT_SEARCH_CHILDREN); + if (!si->metafree) { + int metaret = av_opt_get_dict_val(s, "metadata", AV_OPT_SEARCH_CHILDREN, &metadata); + if (metadata) { + s->event_flags |= AVFMT_EVENT_FLAG_METADATA_UPDATED; + av_dict_copy(&s->metadata, metadata, 0); + av_dict_free(&metadata); + av_opt_set_dict_val(s, "metadata", NULL, AV_OPT_SEARCH_CHILDREN); + } + si->metafree = metaret == AVERROR_OPTION_NOT_FOUND; } if (s->debug & FF_FDEBUG_TS) @@ -1586,7 +1612,7 @@ static void update_stream_timings(AVFormatContext *ic) 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); - if (duration == INT64_MIN || (duration < duration_text && duration_text - duration < AV_TIME_BASE)) + if (duration == INT64_MIN || (duration < duration_text && (uint64_t)duration_text - duration < AV_TIME_BASE)) duration = duration_text; else if (duration < duration_text) av_log(ic, AV_LOG_VERBOSE, "Ignoring outlier non primary stream duration %f\n", duration_text / (float)AV_TIME_BASE); @@ -1930,7 +1956,7 @@ static int has_codec_parameters(const AVStream *st, const char **errmsg_ptr) FAIL("unspecified sample format"); if (!avctx->sample_rate) FAIL("unspecified sample rate"); - if (!avctx->channels) + if (!avctx->ch_layout.nb_channels) FAIL("unspecified number of channels"); if (sti->info->found_decoder >= 0 && !sti->nb_decoded_frames && avctx->codec_id == AV_CODEC_ID_DTS) FAIL("no decodable DTS frames"); @@ -2147,59 +2173,60 @@ static int tb_unreliable(AVCodecContext *c) int ff_rfps_add_frame(AVFormatContext *ic, AVStream *st, int64_t ts) { FFStream *const sti = ffstream(st); - int64_t last = sti->info->last_dts; + FFStreamInfo *info = sti->info; + int64_t last = info->last_dts; if ( ts != AV_NOPTS_VALUE && last != AV_NOPTS_VALUE && ts > last && ts - (uint64_t)last < INT64_MAX) { double dts = (is_relative(ts) ? ts - RELATIVE_TS_BASE : ts) * av_q2d(st->time_base); int64_t duration = ts - last; - if (!sti->info->duration_error) - sti->info->duration_error = av_mallocz(sizeof(sti->info->duration_error[0])*2); - if (!sti->info->duration_error) + if (!info->duration_error) + info->duration_error = av_mallocz(sizeof(info->duration_error[0])*2); + if (!info->duration_error) return AVERROR(ENOMEM); // if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) // av_log(NULL, AV_LOG_ERROR, "%f\n", dts); for (int i = 0; i < MAX_STD_TIMEBASES; i++) { - if (sti->info->duration_error[0][1][i] < 1e10) { + if (info->duration_error[0][1][i] < 1e10) { int framerate = get_std_framerate(i); double sdts = dts*framerate/(1001*12); for (int j = 0; j < 2; j++) { int64_t ticks = llrint(sdts+j*0.5); double error = sdts - ticks + j*0.5; - sti->info->duration_error[j][0][i] += error; - sti->info->duration_error[j][1][i] += error*error; + info->duration_error[j][0][i] += error; + info->duration_error[j][1][i] += error*error; } } } - if (sti->info->rfps_duration_sum <= INT64_MAX - duration) { - sti->info->duration_count++; - sti->info->rfps_duration_sum += duration; + if (info->rfps_duration_sum <= INT64_MAX - duration) { + info->duration_count++; + info->rfps_duration_sum += duration; } - if (sti->info->duration_count % 10 == 0) { - int n = sti->info->duration_count; + if (info->duration_count % 10 == 0) { + int n = info->duration_count; for (int i = 0; i < MAX_STD_TIMEBASES; i++) { - if (sti->info->duration_error[0][1][i] < 1e10) { - double a0 = sti->info->duration_error[0][0][i] / n; - double error0 = sti->info->duration_error[0][1][i] / n - a0*a0; - double a1 = sti->info->duration_error[1][0][i] / n; - double error1 = sti->info->duration_error[1][1][i] / n - a1*a1; + if (info->duration_error[0][1][i] < 1e10) { + double a0 = info->duration_error[0][0][i] / n; + double error0 = info->duration_error[0][1][i] / n - a0*a0; + double a1 = info->duration_error[1][0][i] / n; + double error1 = info->duration_error[1][1][i] / n - a1*a1; if (error0 > 0.04 && error1 > 0.04) { - sti->info->duration_error[0][1][i] = 2e10; - sti->info->duration_error[1][1][i] = 2e10; + info->duration_error[0][1][i] = 2e10; + info->duration_error[1][1][i] = 2e10; } } } } // ignore the first 4 values, they might have some random jitter - if (sti->info->duration_count > 3 && is_relative(ts) == is_relative(last)) - sti->info->duration_gcd = av_gcd(sti->info->duration_gcd, duration); + if (info->duration_count > 3 && is_relative(ts) == is_relative(last)) + info->duration_gcd = av_gcd(info->duration_gcd, duration); } if (ts != AV_NOPTS_VALUE) - sti->info->last_dts = ts; + info->last_dts = ts; return 0; } @@ -2934,6 +2961,9 @@ find_stream_info_err: av_freep(&sti->info); } avcodec_close(sti->avctx); + // FIXME: avcodec_close() frees AVOption settable fields which includes ch_layout, + // so we need to restore it. + av_channel_layout_copy(&sti->avctx->ch_layout, &st->codecpar->ch_layout); av_bsf_free(&sti->extract_extradata.bsf); } if (ic->pb) { diff --git a/libavformat/demux.h b/libavformat/demux.h new file mode 100644 index 000000000..1f57e062f --- /dev/null +++ b/libavformat/demux.h @@ -0,0 +1,241 @@ +/* + * 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_DEMUX_H +#define AVFORMAT_DEMUX_H + +#include +#include "libavutil/rational.h" +#include "libavcodec/packet.h" +#include "avformat.h" + +#define MAX_STD_TIMEBASES (30*12+30+3+6) +typedef struct FFStreamInfo { + int64_t last_dts; + int64_t duration_gcd; + int duration_count; + int64_t rfps_duration_sum; + 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. + * >0 -> decoder found + * <0 -> decoder with codec_id == -found_decoder has not been found + */ + int found_decoder; + + int64_t last_duration; + + /** + * Those are used for average framerate estimation. + */ + int64_t fps_first_dts; + int fps_first_dts_idx; + int64_t fps_last_dts; + int fps_last_dts_idx; +} FFStreamInfo; + +/** + * Returned by demuxers to indicate that data was consumed but discarded + * (ignored streams or junk data). The framework will re-call the demuxer. + */ +#define FFERROR_REDO FFERRTAG('R','E','D','O') + +#define RELATIVE_TS_BASE (INT64_MAX - (1LL << 48)) + +static av_always_inline int is_relative(int64_t ts) +{ + return ts > (RELATIVE_TS_BASE - (1LL << 48)); +} + +/** + * Wrap a given time stamp, if there is an indication for an overflow + * + * @param st stream + * @param timestamp the time stamp to wrap + * @return resulting time stamp + */ +int64_t ff_wrap_timestamp(const AVStream *st, int64_t timestamp); + +/** + * Read a transport packet from a media file. + * + * @param s media file handle + * @param pkt is filled + * @return 0 if OK, AVERROR_xxx on error + */ +int ff_read_packet(AVFormatContext *s, AVPacket *pkt); + +void ff_read_frame_flush(AVFormatContext *s); + +/** + * Perform a binary search using av_index_search_timestamp() and + * AVInputFormat.read_timestamp(). + * + * @param target_ts target timestamp in the time base of the given stream + * @param stream_index stream number + */ +int ff_seek_frame_binary(AVFormatContext *s, int stream_index, + int64_t target_ts, int flags); + +/** + * Update cur_dts of all streams based on the given timestamp and AVStream. + * + * Stream ref_st unchanged, others set cur_dts in their native time base. + * Only needed for timestamp wrapping or if (dts not set and pts!=dts). + * @param timestamp new dts expressed in time_base of param ref_st + * @param ref_st reference stream giving time_base of param timestamp + */ +void avpriv_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp); + +int ff_find_last_ts(AVFormatContext *s, int stream_index, int64_t *ts, int64_t *pos, + int64_t (*read_timestamp)(struct AVFormatContext *, int , int64_t *, int64_t )); + +/** + * Perform a binary search using read_timestamp(). + * + * @param target_ts target timestamp in the time base of the given stream + * @param stream_index stream number + */ +int64_t ff_gen_search(AVFormatContext *s, int stream_index, + int64_t target_ts, int64_t pos_min, + int64_t pos_max, int64_t pos_limit, + int64_t ts_min, int64_t ts_max, + int flags, int64_t *ts_ret, + int64_t (*read_timestamp)(struct AVFormatContext *, int , int64_t *, int64_t )); + +/** + * Internal version of av_index_search_timestamp + */ +int ff_index_search_timestamp(const AVIndexEntry *entries, int nb_entries, + int64_t wanted_timestamp, int flags); + +/** + * Internal version of av_add_index_entry + */ +int ff_add_index_entry(AVIndexEntry **index_entries, + int *nb_index_entries, + unsigned int *index_entries_allocated_size, + int64_t pos, int64_t timestamp, int size, int distance, int flags); + +void ff_configure_buffers_for_index(AVFormatContext *s, int64_t time_tolerance); + +/** + * Ensure the index uses less memory than the maximum specified in + * AVFormatContext.max_index_size by discarding entries if it grows + * too large. + */ +void ff_reduce_index(AVFormatContext *s, int stream_index); + +/** + * add frame for rfps calculation. + * + * @param dts timestamp of the i-th frame + * @return 0 if OK, AVERROR_xxx on error + */ +int ff_rfps_add_frame(AVFormatContext *ic, AVStream *st, int64_t dts); + +void ff_rfps_calculate(AVFormatContext *ic); + +/** + * Rescales a timestamp and the endpoints of an interval to which the temstamp + * belongs, from a timebase `tb_in` to a timebase `tb_out`. + * + * The upper (lower) bound of the output interval is rounded up (down) such that + * the output interval always falls within the intput interval. The timestamp is + * rounded to the nearest integer and halfway cases away from zero, and can + * therefore fall outside of the output interval. + * + * Useful to simplify the rescaling of the arguments of AVInputFormat::read_seek2() + * + * @param[in] tb_in Timebase of the input `min_ts`, `ts` and `max_ts` + * @param[in] tb_out Timebase of the ouput `min_ts`, `ts` and `max_ts` + * @param[in,out] min_ts Lower bound of the interval + * @param[in,out] ts Timestamp + * @param[in,out] max_ts Upper bound of the interval + */ +void ff_rescale_interval(AVRational tb_in, AVRational tb_out, + int64_t *min_ts, int64_t *ts, int64_t *max_ts); + +void avpriv_stream_set_need_parsing(AVStream *st, enum AVStreamParseType type); + +/** + * Add a new chapter. + * + * @param s media file handle + * @param id unique ID for this chapter + * @param start chapter start time in time_base units + * @param end chapter end time in time_base units + * @param title chapter title + * + * @return AVChapter or NULL on error + */ +AVChapter *avpriv_new_chapter(AVFormatContext *s, int64_t id, AVRational time_base, + int64_t start, int64_t end, const char *title); + +/** + * Add an attached pic to an AVStream. + * + * @param st if set, the stream to add the attached pic to; + * if unset, a new stream will be added to s. + * @param pb AVIOContext to read data from if buf is unset. + * @param buf if set, it contains the data and size information to be used + * for the attached pic; if unset, data is read from pb. + * @param size the size of the data to read if buf is unset. + * + * @return 0 on success, < 0 on error. On error, this function removes + * the stream it has added (if any). + */ +int ff_add_attached_pic(AVFormatContext *s, AVStream *st, AVIOContext *pb, + AVBufferRef **buf, int size); + +/** + * Add side data to a packet for changing parameters to the given values. + * Parameters set to 0 aren't included in the change. + */ +int ff_add_param_change(AVPacket *pkt, int32_t channels, + uint64_t channel_layout, int32_t sample_rate, + int32_t width, int32_t height); + +/** + * Generate standard extradata for AVC-Intra based on width/height and field + * order. + */ +int ff_generate_avci_extradata(AVStream *st); + +/** + * Allocate extradata with additional AV_INPUT_BUFFER_PADDING_SIZE at end + * which is always set to 0 and fill it from pb. + * + * @param size size of extradata + * @return >= 0 if OK, AVERROR_xxx on error + */ +int ff_get_extradata(void *logctx, AVCodecParameters *par, AVIOContext *pb, int size); + +/** + * Find stream index based on format-specific stream ID + * @return stream index, or < 0 on error + */ +int ff_find_stream_index(const AVFormatContext *s, int id); + +#endif /* AVFORMAT_DEMUX_H */ diff --git a/libavformat/demux_utils.c b/libavformat/demux_utils.c new file mode 100644 index 000000000..56cc6e15d --- /dev/null +++ b/libavformat/demux_utils.c @@ -0,0 +1,377 @@ +/* + * Various utility demuxing functions + * 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 "libavutil/version.h" + +#include "libavutil/avassert.h" +#include "libavcodec/bytestream.h" +#include "libavcodec/packet_internal.h" +#include "avformat.h" +#include "avio_internal.h" +#include "demux.h" +#include "internal.h" + +struct AVCodecParserContext *av_stream_get_parser(const AVStream *st) +{ + return cffstream(st)->parser; +} + +void avpriv_stream_set_need_parsing(AVStream *st, enum AVStreamParseType type) +{ + ffstream(st)->need_parsing = type; +} + +AVChapter *avpriv_new_chapter(AVFormatContext *s, int64_t id, AVRational time_base, + int64_t start, int64_t end, const char *title) +{ + FFFormatContext *const si = ffformatcontext(s); + AVChapter *chapter = NULL; + int ret; + + if (end != AV_NOPTS_VALUE && start > end) { + av_log(s, AV_LOG_ERROR, "Chapter end time %"PRId64" before start %"PRId64"\n", end, start); + return NULL; + } + + if (!s->nb_chapters) { + si->chapter_ids_monotonic = 1; + } else if (!si->chapter_ids_monotonic || s->chapters[s->nb_chapters-1]->id >= id) { + for (unsigned i = 0; i < s->nb_chapters; i++) + if (s->chapters[i]->id == id) + chapter = s->chapters[i]; + if (!chapter) + si->chapter_ids_monotonic = 0; + } + + if (!chapter) { + chapter = av_mallocz(sizeof(*chapter)); + if (!chapter) + return NULL; + ret = av_dynarray_add_nofree(&s->chapters, &s->nb_chapters, chapter); + if (ret < 0) { + av_free(chapter); + return NULL; + } + } + av_dict_set(&chapter->metadata, "title", title, 0); + chapter->id = id; + chapter->time_base = time_base; + chapter->start = start; + chapter->end = end; + + return chapter; +} + +void av_format_inject_global_side_data(AVFormatContext *s) +{ + FFFormatContext *const si = ffformatcontext(s); + si->inject_global_side_data = 1; + for (unsigned i = 0; i < s->nb_streams; i++) { + AVStream *st = s->streams[i]; + ffstream(st)->inject_global_side_data = 1; + } +} + +int avformat_queue_attached_pictures(AVFormatContext *s) +{ + FFFormatContext *const si = ffformatcontext(s); + int ret; + for (unsigned i = 0; i < s->nb_streams; i++) + if (s->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC && + s->streams[i]->discard < AVDISCARD_ALL) { + if (s->streams[i]->attached_pic.size <= 0) { + av_log(s, AV_LOG_WARNING, + "Attached picture on stream %d has invalid size, " + "ignoring\n", i); + continue; + } + + ret = avpriv_packet_list_put(&si->raw_packet_buffer, + &s->streams[i]->attached_pic, + av_packet_ref, 0); + if (ret < 0) + return ret; + } + return 0; +} + +int ff_add_attached_pic(AVFormatContext *s, AVStream *st0, AVIOContext *pb, + AVBufferRef **buf, int size) +{ + AVStream *st = st0; + AVPacket *pkt; + int ret; + + if (!st && !(st = avformat_new_stream(s, NULL))) + return AVERROR(ENOMEM); + pkt = &st->attached_pic; + if (buf) { + av_assert1(*buf); + av_packet_unref(pkt); + pkt->buf = *buf; + pkt->data = (*buf)->data; + pkt->size = (*buf)->size - AV_INPUT_BUFFER_PADDING_SIZE; + *buf = NULL; + } else { + ret = av_get_packet(pb, pkt, size); + if (ret < 0) + goto fail; + } + st->disposition |= AV_DISPOSITION_ATTACHED_PIC; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + + pkt->stream_index = st->index; + pkt->flags |= AV_PKT_FLAG_KEY; + + return 0; +fail: + if (!st0) + ff_remove_stream(s, st); + return ret; +} + +int ff_add_param_change(AVPacket *pkt, int32_t channels, + uint64_t channel_layout, int32_t sample_rate, + int32_t width, int32_t height) +{ + uint32_t flags = 0; + int size = 4; + uint8_t *data; + if (!pkt) + return AVERROR(EINVAL); + +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + if (channels) { + size += 4; + flags |= AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT; + } + if (channel_layout) { + size += 8; + flags |= AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT; + } +FF_ENABLE_DEPRECATION_WARNINGS +#endif + if (sample_rate) { + size += 4; + flags |= AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE; + } + if (width || height) { + size += 8; + flags |= AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS; + } + data = av_packet_new_side_data(pkt, AV_PKT_DATA_PARAM_CHANGE, size); + if (!data) + return AVERROR(ENOMEM); + bytestream_put_le32(&data, flags); +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + if (channels) + bytestream_put_le32(&data, channels); + if (channel_layout) + bytestream_put_le64(&data, channel_layout); +FF_ENABLE_DEPRECATION_WARNINGS +#endif + if (sample_rate) + bytestream_put_le32(&data, sample_rate); + if (width || height) { + bytestream_put_le32(&data, width); + bytestream_put_le32(&data, height); + } + return 0; +} + +int av_read_play(AVFormatContext *s) +{ + if (s->iformat->read_play) + return s->iformat->read_play(s); + if (s->pb) + return avio_pause(s->pb, 0); + return AVERROR(ENOSYS); +} + +int av_read_pause(AVFormatContext *s) +{ + if (s->iformat->read_pause) + return s->iformat->read_pause(s); + if (s->pb) + return avio_pause(s->pb, 1); + return AVERROR(ENOSYS); +} + +int ff_generate_avci_extradata(AVStream *st) +{ + static const uint8_t avci100_1080p_extradata[] = { + // SPS + 0x00, 0x00, 0x00, 0x01, 0x67, 0x7a, 0x10, 0x29, + 0xb6, 0xd4, 0x20, 0x22, 0x33, 0x19, 0xc6, 0x63, + 0x23, 0x21, 0x01, 0x11, 0x98, 0xce, 0x33, 0x19, + 0x18, 0x21, 0x02, 0x56, 0xb9, 0x3d, 0x7d, 0x7e, + 0x4f, 0xe3, 0x3f, 0x11, 0xf1, 0x9e, 0x08, 0xb8, + 0x8c, 0x54, 0x43, 0xc0, 0x78, 0x02, 0x27, 0xe2, + 0x70, 0x1e, 0x30, 0x10, 0x10, 0x14, 0x00, 0x00, + 0x03, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0xca, + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // PPS + 0x00, 0x00, 0x00, 0x01, 0x68, 0xce, 0x33, 0x48, + 0xd0 + }; + static const uint8_t avci100_1080i_extradata[] = { + // SPS + 0x00, 0x00, 0x00, 0x01, 0x67, 0x7a, 0x10, 0x29, + 0xb6, 0xd4, 0x20, 0x22, 0x33, 0x19, 0xc6, 0x63, + 0x23, 0x21, 0x01, 0x11, 0x98, 0xce, 0x33, 0x19, + 0x18, 0x21, 0x03, 0x3a, 0x46, 0x65, 0x6a, 0x65, + 0x24, 0xad, 0xe9, 0x12, 0x32, 0x14, 0x1a, 0x26, + 0x34, 0xad, 0xa4, 0x41, 0x82, 0x23, 0x01, 0x50, + 0x2b, 0x1a, 0x24, 0x69, 0x48, 0x30, 0x40, 0x2e, + 0x11, 0x12, 0x08, 0xc6, 0x8c, 0x04, 0x41, 0x28, + 0x4c, 0x34, 0xf0, 0x1e, 0x01, 0x13, 0xf2, 0xe0, + 0x3c, 0x60, 0x20, 0x20, 0x28, 0x00, 0x00, 0x03, + 0x00, 0x08, 0x00, 0x00, 0x03, 0x01, 0x94, 0x20, + // PPS + 0x00, 0x00, 0x00, 0x01, 0x68, 0xce, 0x33, 0x48, + 0xd0 + }; + static const uint8_t avci50_1080p_extradata[] = { + // SPS + 0x00, 0x00, 0x00, 0x01, 0x67, 0x6e, 0x10, 0x28, + 0xa6, 0xd4, 0x20, 0x32, 0x33, 0x0c, 0x71, 0x18, + 0x88, 0x62, 0x10, 0x19, 0x19, 0x86, 0x38, 0x8c, + 0x44, 0x30, 0x21, 0x02, 0x56, 0x4e, 0x6f, 0x37, + 0xcd, 0xf9, 0xbf, 0x81, 0x6b, 0xf3, 0x7c, 0xde, + 0x6e, 0x6c, 0xd3, 0x3c, 0x05, 0xa0, 0x22, 0x7e, + 0x5f, 0xfc, 0x00, 0x0c, 0x00, 0x13, 0x8c, 0x04, + 0x04, 0x05, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, + 0x00, 0x03, 0x00, 0x32, 0x84, 0x00, 0x00, 0x00, + // PPS + 0x00, 0x00, 0x00, 0x01, 0x68, 0xee, 0x31, 0x12, + 0x11 + }; + static const uint8_t avci50_1080i_extradata[] = { + // SPS + 0x00, 0x00, 0x00, 0x01, 0x67, 0x6e, 0x10, 0x28, + 0xa6, 0xd4, 0x20, 0x32, 0x33, 0x0c, 0x71, 0x18, + 0x88, 0x62, 0x10, 0x19, 0x19, 0x86, 0x38, 0x8c, + 0x44, 0x30, 0x21, 0x02, 0x56, 0x4e, 0x6e, 0x61, + 0x87, 0x3e, 0x73, 0x4d, 0x98, 0x0c, 0x03, 0x06, + 0x9c, 0x0b, 0x73, 0xe6, 0xc0, 0xb5, 0x18, 0x63, + 0x0d, 0x39, 0xe0, 0x5b, 0x02, 0xd4, 0xc6, 0x19, + 0x1a, 0x79, 0x8c, 0x32, 0x34, 0x24, 0xf0, 0x16, + 0x81, 0x13, 0xf7, 0xff, 0x80, 0x02, 0x00, 0x01, + 0xf1, 0x80, 0x80, 0x80, 0xa0, 0x00, 0x00, 0x03, + 0x00, 0x20, 0x00, 0x00, 0x06, 0x50, 0x80, 0x00, + // PPS + 0x00, 0x00, 0x00, 0x01, 0x68, 0xee, 0x31, 0x12, + 0x11 + }; + static const uint8_t avci100_720p_extradata[] = { + // SPS + 0x00, 0x00, 0x00, 0x01, 0x67, 0x7a, 0x10, 0x29, + 0xb6, 0xd4, 0x20, 0x2a, 0x33, 0x1d, 0xc7, 0x62, + 0xa1, 0x08, 0x40, 0x54, 0x66, 0x3b, 0x8e, 0xc5, + 0x42, 0x02, 0x10, 0x25, 0x64, 0x2c, 0x89, 0xe8, + 0x85, 0xe4, 0x21, 0x4b, 0x90, 0x83, 0x06, 0x95, + 0xd1, 0x06, 0x46, 0x97, 0x20, 0xc8, 0xd7, 0x43, + 0x08, 0x11, 0xc2, 0x1e, 0x4c, 0x91, 0x0f, 0x01, + 0x40, 0x16, 0xec, 0x07, 0x8c, 0x04, 0x04, 0x05, + 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x03, + 0x00, 0x64, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, + // PPS + 0x00, 0x00, 0x00, 0x01, 0x68, 0xce, 0x31, 0x12, + 0x11 + }; + static const uint8_t avci50_720p_extradata[] = { + // SPS + 0x00, 0x00, 0x00, 0x01, 0x67, 0x6e, 0x10, 0x20, + 0xa6, 0xd4, 0x20, 0x32, 0x33, 0x0c, 0x71, 0x18, + 0x88, 0x62, 0x10, 0x19, 0x19, 0x86, 0x38, 0x8c, + 0x44, 0x30, 0x21, 0x02, 0x56, 0x4e, 0x6f, 0x37, + 0xcd, 0xf9, 0xbf, 0x81, 0x6b, 0xf3, 0x7c, 0xde, + 0x6e, 0x6c, 0xd3, 0x3c, 0x0f, 0x01, 0x6e, 0xff, + 0xc0, 0x00, 0xc0, 0x01, 0x38, 0xc0, 0x40, 0x40, + 0x50, 0x00, 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, + 0x06, 0x48, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, + // PPS + 0x00, 0x00, 0x00, 0x01, 0x68, 0xee, 0x31, 0x12, + 0x11 + }; + + const uint8_t *data = NULL; + int ret, size = 0; + + if (st->codecpar->width == 1920) { + if (st->codecpar->field_order == AV_FIELD_PROGRESSIVE) { + data = avci100_1080p_extradata; + size = sizeof(avci100_1080p_extradata); + } else { + data = avci100_1080i_extradata; + size = sizeof(avci100_1080i_extradata); + } + } else if (st->codecpar->width == 1440) { + if (st->codecpar->field_order == AV_FIELD_PROGRESSIVE) { + data = avci50_1080p_extradata; + size = sizeof(avci50_1080p_extradata); + } else { + data = avci50_1080i_extradata; + size = sizeof(avci50_1080i_extradata); + } + } else if (st->codecpar->width == 1280) { + data = avci100_720p_extradata; + size = sizeof(avci100_720p_extradata); + } else if (st->codecpar->width == 960) { + data = avci50_720p_extradata; + size = sizeof(avci50_720p_extradata); + } + + if (!size) + return 0; + + if ((ret = ff_alloc_extradata(st->codecpar, size)) < 0) + return ret; + memcpy(st->codecpar->extradata, data, size); + + return 0; +} + +int ff_get_extradata(void *logctx, AVCodecParameters *par, AVIOContext *pb, int size) +{ + int ret = ff_alloc_extradata(par, size); + if (ret < 0) + return ret; + ret = ffio_read_size(pb, par->extradata, size); + if (ret < 0) { + av_freep(&par->extradata); + par->extradata_size = 0; + av_log(logctx, AV_LOG_ERROR, "Failed to read extradata of size %d\n", size); + return ret; + } + + return ret; +} + +int ff_find_stream_index(const AVFormatContext *s, int id) +{ + for (unsigned i = 0; i < s->nb_streams; i++) + if (s->streams[i]->id == id) + return i; + return -1; +} diff --git a/libavformat/derf.c b/libavformat/derf.c index d50a85319..9da7fc4f1 100644 --- a/libavformat/derf.c +++ b/libavformat/derf.c @@ -38,6 +38,7 @@ static int derf_probe(const AVProbeData *p) static int derf_read_header(AVFormatContext *s) { unsigned data_size; + int channels; AVIOContext *pb = s->pb; AVCodecParameters *par; AVStream *st; @@ -52,15 +53,12 @@ static int derf_read_header(AVFormatContext *s) par->codec_type = AVMEDIA_TYPE_AUDIO; par->codec_id = AV_CODEC_ID_DERF_DPCM; par->format = AV_SAMPLE_FMT_S16; - par->channels = avio_rl32(pb); - if (par->channels != 1 && par->channels != 2) + channels = avio_rl32(pb); + if (channels != 1 && channels != 2) return AVERROR_INVALIDDATA; - if (par->channels == 1) - par->channel_layout = AV_CH_LAYOUT_MONO; - else if (par->channels == 2) - par->channel_layout = AV_CH_LAYOUT_STEREO; + av_channel_layout_default(&par->ch_layout, channels); data_size = avio_rl32(pb); - st->duration = data_size / par->channels; + st->duration = data_size / channels; par->sample_rate = 22050; par->block_align = 1; diff --git a/libavformat/dfpwmdec.c b/libavformat/dfpwmdec.c new file mode 100644 index 000000000..685b95148 --- /dev/null +++ b/libavformat/dfpwmdec.c @@ -0,0 +1,100 @@ +/* + * RAW PCM demuxers + * Copyright (c) 2002 Fabrice Bellard + * Copyright (c) 2022 Jack Bruienne + * + * 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 "avformat.h" +#include "internal.h" +#include "pcm.h" +#include "libavutil/log.h" +#include "libavutil/opt.h" +#include "libavutil/avassert.h" + +typedef struct DFPWMAudioDemuxerContext { + AVClass *class; + int sample_rate; +#if FF_API_OLD_CHANNEL_LAYOUT + int channels; +#endif + AVChannelLayout ch_layout; +} DFPWMAudioDemuxerContext; + +static int dfpwm_read_header(AVFormatContext *s) +{ + DFPWMAudioDemuxerContext *s1 = s->priv_data; + AVCodecParameters *par; + AVStream *st; + int ret; + + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + par = st->codecpar; + + par->codec_type = AVMEDIA_TYPE_AUDIO; + par->codec_id = s->iformat->raw_codec_id; + par->sample_rate = s1->sample_rate; +#if FF_API_OLD_CHANNEL_LAYOUT + if (s1->ch_layout.nb_channels) { +#endif + ret = av_channel_layout_copy(&par->ch_layout, &s1->ch_layout); + if (ret < 0) + return ret; +#if FF_API_OLD_CHANNEL_LAYOUT + } else + par->ch_layout.nb_channels = s1->channels; +#endif + par->bits_per_coded_sample = 1; + par->block_align = 1; + + avpriv_set_pts_info(st, 64, 1, par->sample_rate); + return 0; +} + +static const AVOption dfpwm_options[] = { + { "sample_rate", "", offsetof(DFPWMAudioDemuxerContext, sample_rate), AV_OPT_TYPE_INT, {.i64 = 48000}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, +#if FF_API_OLD_CHANNEL_LAYOUT + { "channels", "", offsetof(DFPWMAudioDemuxerContext, channels), AV_OPT_TYPE_INT, {.i64 = 1}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_DEPRECATED }, + { "ch_layout", "", offsetof(DFPWMAudioDemuxerContext, ch_layout), AV_OPT_TYPE_CHLAYOUT, {.str = NULL}, 0, 0, AV_OPT_FLAG_DECODING_PARAM }, +#else + { "ch_layout", "", offsetof(DFPWMAudioDemuxerContext, ch_layout), AV_OPT_TYPE_CHLAYOUT, {.str = "mono"}, 0, 0, AV_OPT_FLAG_DECODING_PARAM }, +#endif + { NULL }, +}; +static const AVClass dfpwm_demuxer_class = { + .class_name = "dfpwm demuxer", + .item_name = av_default_item_name, + .option = dfpwm_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +const AVInputFormat ff_dfpwm_demuxer = { + .name = "dfpwm", + .long_name = NULL_IF_CONFIG_SMALL("raw DFPWM1a"), + .priv_data_size = sizeof(DFPWMAudioDemuxerContext), + .read_header = dfpwm_read_header, + .read_packet = ff_pcm_read_packet, + .read_seek = ff_pcm_read_seek, + .flags = AVFMT_GENERIC_INDEX, + .extensions = "dfpwm", + .raw_codec_id = AV_CODEC_ID_DFPWM, + .priv_class = &dfpwm_demuxer_class, +}; diff --git a/libavformat/dhav.c b/libavformat/dhav.c index 6c1cdde32..9d26efe8f 100644 --- a/libavformat/dhav.c +++ b/libavformat/dhav.c @@ -78,10 +78,11 @@ static const uint32_t sample_rates[] = { static int parse_ext(AVFormatContext *s, int length) { DHAVContext *dhav = s->priv_data; - int index, ret = 0; + int64_t ret = 0; while (length > 0) { int type = avio_r8(s->pb); + int index; switch (type) { case 0x80: @@ -168,8 +169,7 @@ static int read_chunk(AVFormatContext *s) { DHAVContext *dhav = s->priv_data; int frame_length, ext_length; - int64_t start, end; - int ret; + int64_t start, end, ret; if (avio_feof(s->pb)) return AVERROR_EOF; @@ -395,7 +395,7 @@ retry: default: avpriv_request_sample(s, "Unknown audio codec %X", dhav->audio_codec); } st->duration = dhav->duration; - st->codecpar->channels = dhav->audio_channels; + st->codecpar->ch_layout.nb_channels = dhav->audio_channels; st->codecpar->sample_rate = dhav->sample_rate; st->priv_data = dst = av_mallocz(sizeof(DHAVStream)); if (!st->priv_data) diff --git a/libavformat/dsfdec.c b/libavformat/dsfdec.c index 40c8210a0..3d3a82956 100644 --- a/libavformat/dsfdec.c +++ b/libavformat/dsfdec.c @@ -38,15 +38,15 @@ static int dsf_probe(const AVProbeData *p) return AVPROBE_SCORE_MAX; } -static const uint64_t dsf_channel_layout[] = { - 0, - AV_CH_LAYOUT_MONO, - AV_CH_LAYOUT_STEREO, - AV_CH_LAYOUT_SURROUND, - AV_CH_LAYOUT_QUAD, - AV_CH_LAYOUT_4POINT0, - AV_CH_LAYOUT_5POINT0_BACK, - AV_CH_LAYOUT_5POINT1_BACK, +static const AVChannelLayout dsf_channel_layout[] = { + { .order = AV_CHANNEL_ORDER_UNSPEC }, + AV_CHANNEL_LAYOUT_MONO, + AV_CHANNEL_LAYOUT_STEREO, + AV_CHANNEL_LAYOUT_SURROUND, + AV_CHANNEL_LAYOUT_QUAD, + AV_CHANNEL_LAYOUT_4POINT0, + AV_CHANNEL_LAYOUT_5POINT0_BACK, + AV_CHANNEL_LAYOUT_5POINT1_BACK, }; static void read_id3(AVFormatContext *s, uint64_t id3pos) @@ -70,6 +70,7 @@ static int dsf_read_header(AVFormatContext *s) AVStream *st; uint64_t id3pos; unsigned int channel_type; + int channels; avio_skip(pb, 4); if (avio_rl64(pb) != 28) @@ -104,15 +105,21 @@ static int dsf_read_header(AVFormatContext *s) channel_type = avio_rl32(pb); if (channel_type < FF_ARRAY_ELEMS(dsf_channel_layout)) - st->codecpar->channel_layout = dsf_channel_layout[channel_type]; - if (!st->codecpar->channel_layout) + st->codecpar->ch_layout = dsf_channel_layout[channel_type]; + if (!st->codecpar->ch_layout.nb_channels) avpriv_request_sample(s, "channel type %i", channel_type); st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; - st->codecpar->channels = avio_rl32(pb); + channels = avio_rl32(pb); + if (!st->codecpar->ch_layout.nb_channels) { + st->codecpar->ch_layout.nb_channels = channels; + } else if (channels != st->codecpar->ch_layout.nb_channels) { + av_log(s, AV_LOG_ERROR, "Channel count mismatch\n"); + return AVERROR(EINVAL); + } st->codecpar->sample_rate = avio_rl32(pb) / 8; - if (st->codecpar->channels <= 0) + if (st->codecpar->ch_layout.nb_channels <= 0) return AVERROR_INVALIDDATA; switch(avio_rl32(pb)) { @@ -123,14 +130,15 @@ static int dsf_read_header(AVFormatContext *s) return AVERROR_INVALIDDATA; } - dsf->audio_size = avio_rl64(pb) / 8 * st->codecpar->channels; + dsf->audio_size = avio_rl64(pb) / 8 * st->codecpar->ch_layout.nb_channels; st->codecpar->block_align = avio_rl32(pb); - if (st->codecpar->block_align > INT_MAX / st->codecpar->channels || st->codecpar->block_align <= 0) { + if (st->codecpar->block_align > INT_MAX / st->codecpar->ch_layout.nb_channels || + st->codecpar->block_align <= 0) { avpriv_request_sample(s, "block_align invalid"); return AVERROR_INVALIDDATA; } - st->codecpar->block_align *= st->codecpar->channels; - st->codecpar->bit_rate = st->codecpar->channels * 8LL * st->codecpar->sample_rate; + st->codecpar->block_align *= st->codecpar->ch_layout.nb_channels; + st->codecpar->bit_rate = st->codecpar->ch_layout.nb_channels * 8LL * st->codecpar->sample_rate; avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); avio_skip(pb, 4); @@ -152,6 +160,7 @@ static int dsf_read_packet(AVFormatContext *s, AVPacket *pkt) AVIOContext *pb = s->pb; AVStream *st = s->streams[0]; int64_t pos = avio_tell(pb); + int channels = st->codecpar->ch_layout.nb_channels; int ret; if (pos >= dsf->data_end) @@ -173,19 +182,19 @@ static int dsf_read_packet(AVFormatContext *s, AVPacket *pkt) if ((ret = av_new_packet(pkt, packet_size)) < 0) return ret; dst = pkt->data; - for (ch = 0; ch < st->codecpar->channels; ch++) { - ret = avio_read(pb, dst, packet_size / st->codecpar->channels); - if (ret < packet_size / st->codecpar->channels) + for (ch = 0; ch < st->codecpar->ch_layout.nb_channels; ch++) { + ret = avio_read(pb, dst, packet_size / st->codecpar->ch_layout.nb_channels); + if (ret < packet_size / st->codecpar->ch_layout.nb_channels) return AVERROR_EOF; dst += ret; - avio_skip(pb, skip_size / st->codecpar->channels); + avio_skip(pb, skip_size / st->codecpar->ch_layout.nb_channels); } pkt->pos = pos; pkt->stream_index = 0; - pkt->pts = (pos - si->data_offset) / st->codecpar->channels; - pkt->duration = packet_size / st->codecpar->channels; + pkt->pts = (pos - si->data_offset) / channels; + pkt->duration = packet_size / channels; return 0; } } @@ -194,8 +203,8 @@ static int dsf_read_packet(AVFormatContext *s, AVPacket *pkt) return ret; pkt->stream_index = 0; - pkt->pts = (pos - si->data_offset) / st->codecpar->channels; - pkt->duration = st->codecpar->block_align / st->codecpar->channels; + pkt->pts = (pos - si->data_offset) / channels; + pkt->duration = st->codecpar->block_align / channels; return 0; } diff --git a/libavformat/dsicin.c b/libavformat/dsicin.c index 481f365a5..13ee9f87b 100644 --- a/libavformat/dsicin.c +++ b/libavformat/dsicin.c @@ -132,11 +132,12 @@ static int cin_read_header(AVFormatContext *s) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_DSICINAUDIO; st->codecpar->codec_tag = 0; /* no tag */ - st->codecpar->channels = 1; - st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; st->codecpar->sample_rate = 22050; st->codecpar->bits_per_coded_sample = 8; - st->codecpar->bit_rate = st->codecpar->sample_rate * st->codecpar->bits_per_coded_sample * st->codecpar->channels; + st->codecpar->bit_rate = st->codecpar->sample_rate * + st->codecpar->bits_per_coded_sample * + st->codecpar->ch_layout.nb_channels; return 0; } diff --git a/libavformat/dss.c b/libavformat/dss.c index ee3a099a9..d619ea00d 100644 --- a/libavformat/dss.c +++ b/libavformat/dss.c @@ -155,8 +155,7 @@ static int dss_read_header(AVFormatContext *s) } st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; - st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; - st->codecpar->channels = 1; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); st->start_time = 0; diff --git a/libavformat/dtshddec.c b/libavformat/dtshddec.c index b84588af7..edd02b456 100644 --- a/libavformat/dtshddec.c +++ b/libavformat/dtshddec.c @@ -104,7 +104,7 @@ static int dtshd_read_header(AVFormatContext *s) duration *= avio_rb16(pb); // samples_per_frames st->duration = duration; avio_skip(pb, 5); - st->codecpar->channels = ff_dca_count_chs_for_mask(avio_rb16(pb)); + st->codecpar->ch_layout.nb_channels = ff_dca_count_chs_for_mask(avio_rb16(pb)); st->codecpar->initial_padding = avio_rb16(pb); avio_skip(pb, chunk_size - 21); break; diff --git a/libavformat/dump.c b/libavformat/dump.c index 4824965ee..e3f0056c2 100644 --- a/libavformat/dump.c +++ b/libavformat/dump.c @@ -164,8 +164,11 @@ static void dump_paramchange(void *ctx, const AVPacketSideData *sd) { int size = sd->size; const uint8_t *data = sd->data; - uint32_t flags, channels, sample_rate, width, height; + uint32_t flags, sample_rate, width, height; +#if FF_API_OLD_CHANNEL_LAYOUT + uint32_t channels; uint64_t layout; +#endif if (!data || sd->size < 4) goto fail; @@ -174,6 +177,8 @@ static void dump_paramchange(void *ctx, const AVPacketSideData *sd) data += 4; size -= 4; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS if (flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT) { if (size < 4) goto fail; @@ -191,6 +196,8 @@ static void dump_paramchange(void *ctx, const AVPacketSideData *sd) av_log(ctx, AV_LOG_INFO, "channel layout: %s, ", av_get_channel_name(layout)); } +FF_ENABLE_DEPRECATION_WARNINGS +#endif /* FF_API_OLD_CHANNEL_LAYOUT */ if (flags & AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE) { if (size < 4) goto fail; @@ -611,6 +618,8 @@ static void dump_stream_format(const AVFormatContext *ic, int i, av_log(NULL, AV_LOG_INFO, " (dependent)"); if (st->disposition & AV_DISPOSITION_STILL_IMAGE) av_log(NULL, AV_LOG_INFO, " (still image)"); + if (st->disposition & AV_DISPOSITION_NON_DIEGETIC) + av_log(NULL, AV_LOG_INFO, " (non-diegetic)"); av_log(NULL, AV_LOG_INFO, "\n"); dump_metadata(NULL, st->metadata, " "); diff --git a/libavformat/dv.c b/libavformat/dv.c index 77a6ede37..1dadaf6e6 100644 --- a/libavformat/dv.c +++ b/libavformat/dv.c @@ -281,8 +281,7 @@ static int dv_extract_audio_info(DVDemuxContext *c, const uint8_t *frame) c->audio_pkt[i].pos = -1; } c->ast[i]->codecpar->sample_rate = dv_audio_frequency[freq]; - c->ast[i]->codecpar->channels = 2; - c->ast[i]->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; + c->ast[i]->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; c->ast[i]->codecpar->bit_rate = 2 * dv_audio_frequency[freq] * 16; c->ast[i]->start_time = 0; } diff --git a/libavformat/dvenc.c b/libavformat/dvenc.c index 9a853ba7c..7ef969230 100644 --- a/libavformat/dvenc.c +++ b/libavformat/dvenc.c @@ -31,15 +31,14 @@ #include "libavutil/time_internal.h" #include "avformat.h" -#include "internal.h" #include "libavcodec/dv_profile.h" #include "libavcodec/dv.h" #include "dv.h" +#include "mux.h" #include "libavutil/avassert.h" #include "libavutil/fifo.h" #include "libavutil/mathematics.h" #include "libavutil/intreadwrite.h" -#include "libavutil/opt.h" #include "libavutil/timecode.h" #define MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32-bit audio @@ -49,7 +48,7 @@ struct DVMuxContext { const AVDVProfile* sys; /* current DV profile, e.g.: 525/60, 625/50 */ int n_ast; /* number of stereo audio streams (up to 2) */ AVStream *ast[4]; /* stereo audio streams */ - AVFifoBuffer *audio_data[4]; /* FIFO for storing excessive amounts of PCM */ + AVFifo *audio_data[4]; /* FIFO for storing excessive amounts of PCM */ int frames; /* current frame number */ int64_t start_time; /* recording start time */ int has_audio; /* frame under construction has audio */ @@ -201,8 +200,9 @@ static void dv_inject_audio(DVMuxContext *c, int channel, uint8_t* frame_ptr) if (of*2 >= size) continue; - frame_ptr[d] = *av_fifo_peek2(c->audio_data[channel], of*2+1); // FIXME: maybe we have to admit - frame_ptr[d+1] = *av_fifo_peek2(c->audio_data[channel], of*2); // that DV is a big-endian PCM + // FIXME: maybe we have to admit that DV is a big-endian PCM + av_fifo_peek(c->audio_data[channel], frame_ptr + d, 2, of * 2); + FFSWAP(uint8_t, frame_ptr[d], frame_ptr[d + 1]); } frame_ptr += 16 * 80; /* 15 Video DIFs + 1 Audio DIF */ } @@ -245,7 +245,7 @@ static void dv_inject_metadata(DVMuxContext *c, uint8_t* frame) static int dv_assemble_frame(AVFormatContext *s, DVMuxContext *c, AVStream* st, - uint8_t* data, int data_size, uint8_t** frame) + const uint8_t *data, int data_size, uint8_t **frame) { int i, reqasize; @@ -254,8 +254,10 @@ static int dv_assemble_frame(AVFormatContext *s, switch (st->codecpar->codec_type) { case AVMEDIA_TYPE_VIDEO: /* FIXME: we have to have more sensible approach than this one */ - if (c->has_video) + if (c->has_video) { av_log(s, AV_LOG_ERROR, "Can't process DV frame #%d. Insufficient audio data or severe sync problem.\n", c->frames); + return AVERROR(EINVAL); + } if (data_size != c->sys->frame_size) { av_log(s, AV_LOG_ERROR, "Unexpected frame size, %d != %d\n", data_size, c->sys->frame_size); @@ -269,14 +271,16 @@ static int dv_assemble_frame(AVFormatContext *s, for (i = 0; i < c->n_ast && st != c->ast[i]; i++); /* FIXME: we have to have more sensible approach than this one */ - if (av_fifo_size(c->audio_data[i]) + data_size >= 100*MAX_AUDIO_FRAME_SIZE) + if (av_fifo_can_write(c->audio_data[i]) < data_size) { av_log(s, AV_LOG_ERROR, "Can't process DV frame #%d. Insufficient video data or severe sync problem.\n", c->frames); - av_fifo_generic_write(c->audio_data[i], data, data_size, NULL); + return AVERROR(EINVAL); + } + av_fifo_write(c->audio_data[i], data, data_size); reqasize = 4 * dv_audio_frame_size(c->sys, c->frames, st->codecpar->sample_rate); /* Let us see if we've got enough audio for one DV frame. */ - c->has_audio |= ((reqasize <= av_fifo_size(c->audio_data[i])) << i); + c->has_audio |= ((reqasize <= av_fifo_can_read(c->audio_data[i])) << i); break; default: @@ -290,8 +294,8 @@ static int dv_assemble_frame(AVFormatContext *s, for (i=0; i < c->n_ast; i++) { dv_inject_audio(c, i, *frame); reqasize = 4 * dv_audio_frame_size(c->sys, c->frames, c->ast[i]->codecpar->sample_rate); - av_fifo_drain(c->audio_data[i], reqasize); - c->has_audio |= ((reqasize <= av_fifo_size(c->audio_data[i])) << i); + av_fifo_drain2(c->audio_data[i], reqasize); + c->has_audio |= ((reqasize <= av_fifo_can_read(c->audio_data[i])) << i); } c->has_video = 0; @@ -328,7 +332,7 @@ static DVMuxContext* dv_init_mux(AVFormatContext* s) if (c->n_ast > 1) return NULL; /* Some checks -- DV format is very picky about its incoming streams */ if(st->codecpar->codec_id != AV_CODEC_ID_PCM_S16LE || - st->codecpar->channels != 2) + st->codecpar->ch_layout.nb_channels != 2) goto bail_out; if (st->codecpar->sample_rate != 48000 && st->codecpar->sample_rate != 44100 && @@ -369,9 +373,11 @@ static DVMuxContext* dv_init_mux(AVFormatContext* s) ff_parse_creation_time_metadata(s, &c->start_time, 1); for (i=0; i < c->n_ast; i++) { - if (c->ast[i] && !(c->audio_data[i]=av_fifo_alloc_array(100, MAX_AUDIO_FRAME_SIZE))) { + if (!c->ast[i]) + continue; + c->audio_data[i] = av_fifo_alloc2(100 * MAX_AUDIO_FRAME_SIZE, 1, 0); + if (!c->audio_data[i]) goto bail_out; - } } return c; @@ -433,7 +439,7 @@ static void dv_deinit(AVFormatContext *s) DVMuxContext *c = s->priv_data; for (int i = 0; i < c->n_ast; i++) - av_fifo_freep(&c->audio_data[i]); + av_fifo_freep2(&c->audio_data[i]); } const AVOutputFormat ff_dv_muxer = { diff --git a/libavformat/eacdata.c b/libavformat/eacdata.c index 0ad1c937a..ebc98d274 100644 --- a/libavformat/eacdata.c +++ b/libavformat/eacdata.c @@ -32,6 +32,8 @@ #include "avformat.h" #include "internal.h" +#include "libavutil/channel_layout.h" + typedef struct CdataDemuxContext { unsigned int channels; unsigned int audio_pts; @@ -52,18 +54,25 @@ static int cdata_read_header(AVFormatContext *s) AVIOContext *pb = s->pb; unsigned int sample_rate, header; AVStream *st; - int64_t channel_layout = 0; + AVChannelLayout channel_layout; header = avio_rb16(pb); switch (header) { - case 0x0400: cdata->channels = 1; break; - case 0x0404: cdata->channels = 2; break; - case 0x040C: cdata->channels = 4; channel_layout = AV_CH_LAYOUT_QUAD; break; - case 0x0414: cdata->channels = 6; channel_layout = AV_CH_LAYOUT_5POINT1_BACK; break; + case 0x0400: + channel_layout = (AVChannelLayout){ .nb_channels = 1, .order = AV_CHANNEL_ORDER_UNSPEC }; + break; + case 0x0404: + channel_layout = (AVChannelLayout){ .nb_channels = 2, .order = AV_CHANNEL_ORDER_UNSPEC }; + break; + case 0x040C: + channel_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_QUAD; break; + case 0x0414: + channel_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1_BACK; break; default: av_log(s, AV_LOG_INFO, "unknown header 0x%04x\n", header); return -1; }; + cdata->channels = channel_layout.nb_channels; sample_rate = avio_rb16(pb); avio_skip(pb, (avio_r8(pb) & 0x20) ? 15 : 11); @@ -74,8 +83,7 @@ static int cdata_read_header(AVFormatContext *s) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_tag = 0; /* no fourcc */ st->codecpar->codec_id = AV_CODEC_ID_ADPCM_EA_XAS; - st->codecpar->channels = cdata->channels; - st->codecpar->channel_layout = channel_layout; + st->codecpar->ch_layout = channel_layout; st->codecpar->sample_rate = sample_rate; avpriv_set_pts_info(st, 64, 1, sample_rate); diff --git a/libavformat/electronicarts.c b/libavformat/electronicarts.c index 2fb09b34c..e7f0cb9b9 100644 --- a/libavformat/electronicarts.c +++ b/libavformat/electronicarts.c @@ -551,13 +551,13 @@ static int ea_read_header(AVFormatContext *s) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = ea->audio_codec; st->codecpar->codec_tag = 0; /* no tag */ - st->codecpar->channels = ea->num_channels; + st->codecpar->ch_layout.nb_channels = ea->num_channels; st->codecpar->sample_rate = ea->sample_rate; st->codecpar->bits_per_coded_sample = ea->bytes * 8; - st->codecpar->bit_rate = (int64_t)st->codecpar->channels * + st->codecpar->bit_rate = (int64_t)ea->num_channels * st->codecpar->sample_rate * st->codecpar->bits_per_coded_sample / 4; - st->codecpar->block_align = st->codecpar->channels * + st->codecpar->block_align = ea->num_channels * st->codecpar->bits_per_coded_sample; ea->audio_stream_index = st->index; st->start_time = 0; diff --git a/libavformat/epafdec.c b/libavformat/epafdec.c index 8b94278c0..a132360eb 100644 --- a/libavformat/epafdec.c +++ b/libavformat/epafdec.c @@ -68,7 +68,7 @@ static int epaf_read_header(AVFormatContext *s) return AVERROR(ENOMEM); st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; - st->codecpar->channels = channels; + st->codecpar->ch_layout.nb_channels = channels; st->codecpar->sample_rate = sample_rate; switch (codec) { case 0: @@ -84,7 +84,8 @@ static int epaf_read_header(AVFormatContext *s) } st->codecpar->bits_per_coded_sample = av_get_bits_per_sample(st->codecpar->codec_id); - st->codecpar->block_align = st->codecpar->bits_per_coded_sample * st->codecpar->channels / 8; + st->codecpar->block_align = st->codecpar->bits_per_coded_sample * + st->codecpar->ch_layout.nb_channels / 8; avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); diff --git a/libavformat/ffmetadec.c b/libavformat/ffmetadec.c index 93ec6f589..90f2e2b86 100644 --- a/libavformat/ffmetadec.c +++ b/libavformat/ffmetadec.c @@ -22,8 +22,8 @@ #include "libavutil/bprint.h" #include "libavutil/mathematics.h" #include "avformat.h" +#include "demux.h" #include "ffmeta.h" -#include "internal.h" #include "libavutil/dict.h" static int probe(const AVProbeData *p) diff --git a/libavformat/fifo.c b/libavformat/fifo.c index 86e5d369b..ead2bdc5c 100644 --- a/libavformat/fifo.c +++ b/libavformat/fifo.c @@ -28,6 +28,7 @@ #include "libavutil/threadmessage.h" #include "avformat.h" #include "internal.h" +#include "mux.h" #define FIFO_DEFAULT_QUEUE_SIZE 60 #define FIFO_DEFAULT_MAX_RECOVERY_ATTEMPTS 0 diff --git a/libavformat/file.c b/libavformat/file.c index 7001750c8..98c9e81bc 100644 --- a/libavformat/file.c +++ b/libavformat/file.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/avstring.h" #include "libavutil/internal.h" #include "libavutil/opt.h" @@ -152,11 +154,7 @@ static int file_check(URLContext *h, int mask) ret |= AVIO_FLAG_WRITE; #else struct stat st; -# ifndef _WIN32 ret = stat(filename, &st); -# else - ret = win32_stat(filename, &st); -# endif if (ret < 0) return AVERROR(errno); diff --git a/libavformat/fitsenc.c b/libavformat/fitsenc.c index 5cf34ef06..37ee10bb1 100644 --- a/libavformat/fitsenc.c +++ b/libavformat/fitsenc.c @@ -24,6 +24,7 @@ * FITS muxer. */ +#include "avio_internal.h" #include "internal.h" typedef struct FITSContext { @@ -177,11 +178,7 @@ static int write_image_header(AVFormatContext *s) lines_written++; lines_left = ((lines_written + 35) / 36) * 36 - lines_written; - memset(buffer, ' ', 80); - while (lines_left > 0) { - avio_write(s->pb, buffer, sizeof(buffer)); - lines_left--; - } + ffio_fill(s->pb, ' ', sizeof(buffer) * lines_left); return 0; } diff --git a/libavformat/flac_picture.c b/libavformat/flac_picture.c index 0effbf04f..b33fee75b 100644 --- a/libavformat/flac_picture.c +++ b/libavformat/flac_picture.c @@ -23,6 +23,7 @@ #include "libavcodec/bytestream.h" #include "libavcodec/png.h" #include "avformat.h" +#include "demux.h" #include "flac_picture.h" #include "id3v2.h" #include "internal.h" diff --git a/libavformat/flacdec.c b/libavformat/flacdec.c index 3401aebe8..09404b67b 100644 --- a/libavformat/flacdec.c +++ b/libavformat/flacdec.c @@ -22,11 +22,11 @@ #include "libavutil/channel_layout.h" #include "libavcodec/flac.h" #include "avformat.h" +#include "demux.h" #include "flac_picture.h" #include "internal.h" #include "rawdec.h" #include "oggdec.h" -#include "vorbiscomment.h" #include "replaygain.h" #define SEEKPOINT_SIZE 18 @@ -191,8 +191,7 @@ static int flac_read_header(AVFormatContext *s) av_log(s, AV_LOG_WARNING, "Invalid value of WAVEFORMATEXTENSIBLE_CHANNEL_MASK\n"); } else { - st->codecpar->channel_layout = mask; - st->codecpar->channels = av_get_channel_layout_nb_channels(mask); + av_channel_layout_from_mask(&st->codecpar->ch_layout, mask); av_dict_set(&s->metadata, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK", NULL, 0); } } diff --git a/libavformat/flacenc.c b/libavformat/flacenc.c index b267197cc..d7930f4a6 100644 --- a/libavformat/flacenc.c +++ b/libavformat/flacenc.c @@ -30,6 +30,7 @@ #include "flacenc.h" #include "id3v2.h" #include "internal.h" +#include "version.h" #include "vorbiscomment.h" @@ -238,9 +239,9 @@ static int flac_init(struct AVFormatContext *s) } /* add the channel layout tag */ - if (par->channel_layout && - !(par->channel_layout & ~0x3ffffULL) && - !ff_flac_is_native_layout(par->channel_layout)) { + if (par->ch_layout.order == AV_CHANNEL_ORDER_NATIVE && + !(par->ch_layout.u.mask & ~0x3ffffULL) && + !ff_flac_is_native_layout(par->ch_layout.u.mask)) { AVDictionaryEntry *chmask = av_dict_get(s->metadata, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK", NULL, 0); @@ -249,7 +250,7 @@ static int flac_init(struct AVFormatContext *s) "already present, this muxer will not overwrite it.\n"); } else { uint8_t buf[32]; - snprintf(buf, sizeof(buf), "0x%"PRIx64, par->channel_layout); + snprintf(buf, sizeof(buf), "0x%"PRIx64, par->ch_layout.u.mask); av_dict_set(&s->metadata, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK", buf, 0); } } diff --git a/libavformat/flacenc.h b/libavformat/flacenc.h index b308d0d02..02937b240 100644 --- a/libavformat/flacenc.h +++ b/libavformat/flacenc.h @@ -22,9 +22,8 @@ #ifndef AVFORMAT_FLACENC_H #define AVFORMAT_FLACENC_H -#include "libavcodec/flac.h" -#include "libavcodec/bytestream.h" -#include "avformat.h" +#include +#include "avio.h" int ff_flac_write_header(AVIOContext *pb, const uint8_t *extradata, int extradata_size, int last_block); diff --git a/libavformat/flic.c b/libavformat/flic.c index 44ed69642..222452eac 100644 --- a/libavformat/flic.c +++ b/libavformat/flic.c @@ -157,10 +157,9 @@ static int flic_read_header(AVFormatContext *s) ast->codecpar->codec_id = AV_CODEC_ID_PCM_U8; ast->codecpar->codec_tag = 0; ast->codecpar->sample_rate = FLIC_TFTD_SAMPLE_RATE; - ast->codecpar->channels = 1; ast->codecpar->bit_rate = st->codecpar->sample_rate * 8; ast->codecpar->bits_per_coded_sample = 8; - ast->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + ast->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; ast->codecpar->extradata_size = 0; /* Since the header information is incorrect we have to figure out the diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c index b9e36b3ff..8dba92661 100644 --- a/libavformat/flvdec.c +++ b/libavformat/flvdec.c @@ -24,18 +24,18 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/channel_layout.h" #include "libavutil/dict.h" #include "libavutil/opt.h" #include "libavutil/internal.h" #include "libavutil/intfloat.h" +#include "libavutil/intreadwrite.h" #include "libavutil/mathematics.h" -#include "libavutil/time_internal.h" -#include "libavcodec/bytestream.h" #include "avformat.h" +#include "demux.h" #include "internal.h" -#include "avio_internal.h" #include "flv.h" #define VALIDATE_INDEX_TS_THRESH 2500 @@ -463,6 +463,8 @@ static int parse_keyframes_index(AVFormatContext *s, AVIOContext *ioc, int64_t m goto invalid; if (current_array == × && (d <= INT64_MIN / 1000 || d >= INT64_MAX / 1000)) goto invalid; + if (avio_feof(ioc)) + goto invalid; current_array[0][i] = d; } if (times && filepositions) { @@ -629,10 +631,7 @@ static int amf_parse_object(AVFormatContext *s, AVStream *astream, } else if (!strcmp(key, "audiosamplesize") && apar) { apar->bits_per_coded_sample = num_val; } else if (!strcmp(key, "stereo") && apar) { - apar->channels = num_val + 1; - apar->channel_layout = apar->channels == 2 ? - AV_CH_LAYOUT_STEREO : - AV_CH_LAYOUT_MONO; + av_channel_layout_default(&apar->ch_layout, num_val + 1); } else if (!strcmp(key, "width") && vpar) { vpar->width = num_val; } else if (!strcmp(key, "height") && vpar) { @@ -1202,12 +1201,10 @@ retry_duration: sample_rate = 44100 << ((flags & FLV_AUDIO_SAMPLERATE_MASK) >> FLV_AUDIO_SAMPLERATE_OFFSET) >> 3; bits_per_coded_sample = (flags & FLV_AUDIO_SAMPLESIZE_MASK) ? 16 : 8; - if (!st->codecpar->channels || !st->codecpar->sample_rate || + if (!av_channel_layout_check(&st->codecpar->ch_layout) || + !st->codecpar->sample_rate || !st->codecpar->bits_per_coded_sample) { - st->codecpar->channels = channels; - st->codecpar->channel_layout = channels == 1 - ? AV_CH_LAYOUT_MONO - : AV_CH_LAYOUT_STEREO; + av_channel_layout_default(&st->codecpar->ch_layout, channels); st->codecpar->sample_rate = sample_rate; st->codecpar->bits_per_coded_sample = bits_per_coded_sample; } @@ -1217,7 +1214,7 @@ retry_duration: flv->last_sample_rate = sample_rate = st->codecpar->sample_rate; flv->last_channels = - channels = st->codecpar->channels; + channels = st->codecpar->ch_layout.nb_channels; } else { AVCodecParameters *par = avcodec_parameters_alloc(); if (!par) { diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c index 66c530a2f..770ca319e 100644 --- a/libavformat/flvenc.c +++ b/libavformat/flvenc.c @@ -25,13 +25,12 @@ #include "libavutil/avassert.h" #include "libavutil/mathematics.h" #include "libavcodec/mpeg4audio.h" -#include "avio_internal.h" #include "avio.h" #include "avc.h" #include "avformat.h" #include "flv.h" #include "internal.h" -#include "metadata.h" +#include "mux.h" #include "libavutil/opt.h" #include "libavcodec/put_bits.h" @@ -138,7 +137,7 @@ static int get_audio_flags(AVFormatContext *s, AVCodecParameters *par) "FLV only supports wideband (16kHz) Speex audio\n"); return AVERROR(EINVAL); } - if (par->channels != 1) { + if (par->ch_layout.nb_channels != 1) { av_log(s, AV_LOG_ERROR, "FLV only supports mono Speex audio\n"); return AVERROR(EINVAL); } @@ -178,7 +177,7 @@ error: } } - if (par->channels > 1) + if (par->ch_layout.nb_channels > 1) flags |= FLV_STEREO; switch (par->codec_id) { @@ -342,7 +341,7 @@ static void write_metadata(AVFormatContext *s, unsigned int ts) put_amf_double(pb, flv->audio_par->codec_id == AV_CODEC_ID_PCM_U8 ? 8 : 16); put_amf_string(pb, "stereo"); - put_amf_bool(pb, flv->audio_par->channels == 2); + put_amf_bool(pb, flv->audio_par->ch_layout.nb_channels == 2); put_amf_string(pb, "audiocodecid"); put_amf_double(pb, flv->audio_par->codec_tag); @@ -507,8 +506,8 @@ static void flv_write_codec_header(AVFormatContext* s, AVCodecParameters* par, i if (!par->extradata_size && (flv->flags & FLV_AAC_SEQ_HEADER_DETECT)) { PutBitContext pbc; int samplerate_index; - int channels = flv->audio_par->channels - - (flv->audio_par->channels == 8 ? 1 : 0); + int channels = flv->audio_par->ch_layout.nb_channels + - (flv->audio_par->ch_layout.nb_channels == 8 ? 1 : 0); uint8_t data[2]; for (samplerate_index = 0; samplerate_index < 16; @@ -734,7 +733,7 @@ static int flv_write_trailer(AVFormatContext *s) int64_t cur_pos = avio_tell(s->pb); if (build_keyframes_idx) { - FLVFileposition *newflv_posinfo, *p; + const FLVFileposition *newflv_posinfo; avio_seek(pb, flv->videosize_offset, SEEK_SET); put_amf_double(pb, flv->videosize); @@ -769,19 +768,6 @@ static int flv_write_trailer(AVFormatContext *s) put_amf_double(pb, newflv_posinfo->keyframe_timestamp); } - newflv_posinfo = flv->head_filepositions; - while (newflv_posinfo) { - p = newflv_posinfo->next; - if (p) { - newflv_posinfo->next = p->next; - av_free(p); - p = NULL; - } else { - av_free(newflv_posinfo); - newflv_posinfo = NULL; - } - } - put_amf_string(pb, ""); avio_w8(pb, AMF_END_OF_OBJECT); @@ -1048,6 +1034,20 @@ static int flv_check_bitstream(AVFormatContext *s, AVStream *st, return ret; } +static void flv_deinit(AVFormatContext *s) +{ + FLVContext *flv = s->priv_data; + FLVFileposition *filepos = flv->head_filepositions; + + while (filepos) { + FLVFileposition *next = filepos->next; + av_free(filepos); + filepos = next; + } + flv->filepositions = flv->head_filepositions = NULL; + flv->filepositions_count = 0; +} + static const AVOption options[] = { { "flvflags", "FLV muxer flags", offsetof(FLVContext, flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "flvflags" }, { "aac_seq_header_detect", "Put AAC sequence header based on stream data", 0, AV_OPT_TYPE_CONST, {.i64 = FLV_AAC_SEQ_HEADER_DETECT}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "flvflags" }, @@ -1077,6 +1077,7 @@ const AVOutputFormat ff_flv_muxer = { .write_header = flv_write_header, .write_packet = flv_write_packet, .write_trailer = flv_write_trailer, + .deinit = flv_deinit, .check_bitstream= flv_check_bitstream, .codec_tag = (const AVCodecTag* const []) { flv_video_codec_ids, flv_audio_codec_ids, 0 diff --git a/libavformat/format.c b/libavformat/format.c index 52b85c16a..4b1f3c298 100644 --- a/libavformat/format.c +++ b/libavformat/format.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/avstring.h" #include "libavutil/bprint.h" #include "libavutil/opt.h" @@ -97,7 +99,7 @@ enum AVCodecID av_guess_codec(const AVOutputFormat *fmt, const char *short_name, if (type == AVMEDIA_TYPE_VIDEO) { enum AVCodecID codec_id = AV_CODEC_ID_NONE; -#if CONFIG_IMAGE2_MUXER +#if CONFIG_IMAGE2_MUXER || CONFIG_IMAGE2PIPE_MUXER if (!strcmp(fmt->name, "image2") || !strcmp(fmt->name, "image2pipe")) { codec_id = ff_guess_image2_codec(filename); } diff --git a/libavformat/framehash.c b/libavformat/framehash.c index 04c40825b..654996e8e 100644 --- a/libavformat/framehash.c +++ b/libavformat/framehash.c @@ -20,6 +20,7 @@ #include "libavutil/channel_layout.h" #include "internal.h" +#include "version.h" int ff_framehash_write_header(AVFormatContext *s) { @@ -35,12 +36,14 @@ int ff_framehash_write_header(AVFormatContext *s) avio_printf(s->pb, "#media_type %d: %s\n", i, av_get_media_type_string(avctx->codec_type)); avio_printf(s->pb, "#codec_id %d: %s\n", i, avcodec_get_name(avctx->codec_id)); switch (avctx->codec_type) { - case AVMEDIA_TYPE_AUDIO: - av_get_channel_layout_string(buf, sizeof(buf), avctx->channels, avctx->channel_layout); + case AVMEDIA_TYPE_AUDIO: { + int ret = av_channel_layout_describe(&avctx->ch_layout, buf, sizeof(buf)); + if (ret < 0) + return ret; avio_printf(s->pb, "#sample_rate %d: %d\n", i,avctx->sample_rate); - avio_printf(s->pb, "#channel_layout %d: %"PRIx64"\n", i,avctx->channel_layout); avio_printf(s->pb, "#channel_layout_name %d: %s\n", i, buf); break; + } case AVMEDIA_TYPE_VIDEO: avio_printf(s->pb, "#dimensions %d: %dx%d\n", i, avctx->width, avctx->height); avio_printf(s->pb, "#sar %d: %d/%d\n", i, st->sample_aspect_ratio.num, st->sample_aspect_ratio.den); diff --git a/libavformat/frmdec.c b/libavformat/frmdec.c index 478656b03..e6c1179dc 100644 --- a/libavformat/frmdec.c +++ b/libavformat/frmdec.c @@ -24,7 +24,6 @@ * Megalux Frame demuxer */ -#include "libavcodec/raw.h" #include "libavutil/imgutils.h" #include "libavutil/intreadwrite.h" #include "avformat.h" diff --git a/libavformat/fsb.c b/libavformat/fsb.c index 9e8b9ca6b..12b67f631 100644 --- a/libavformat/fsb.c +++ b/libavformat/fsb.c @@ -68,30 +68,30 @@ static int fsb_read_header(AVFormatContext *s) if (par->sample_rate <= 0) return AVERROR_INVALIDDATA; avio_skip(pb, 6); - par->channels = avio_rl16(pb); - if (!par->channels) + par->ch_layout.nb_channels = avio_rl16(pb); + if (!par->ch_layout.nb_channels) return AVERROR_INVALIDDATA; if (format & 0x00000100) { par->codec_id = AV_CODEC_ID_PCM_S16LE; - par->block_align = 4096 * par->channels; + par->block_align = 4096 * par->ch_layout.nb_channels; } else if (format & 0x00400000) { par->bits_per_coded_sample = 4; par->codec_id = AV_CODEC_ID_ADPCM_IMA_WAV; - par->block_align = 36 * par->channels; + par->block_align = 36 * par->ch_layout.nb_channels; } else if (format & 0x00800000) { par->codec_id = AV_CODEC_ID_ADPCM_PSX; - par->block_align = 16 * par->channels; + par->block_align = 16 * par->ch_layout.nb_channels; } else if (format & 0x02000000) { par->codec_id = AV_CODEC_ID_ADPCM_THP; - par->block_align = 8 * par->channels; - if (par->channels > INT_MAX / 32) + par->block_align = 8 * par->ch_layout.nb_channels; + if (par->ch_layout.nb_channels > INT_MAX / 32) return AVERROR_INVALIDDATA; - ret = ff_alloc_extradata(par, 32 * par->channels); + ret = ff_alloc_extradata(par, 32 * par->ch_layout.nb_channels); if (ret < 0) return ret; avio_seek(pb, 0x68, SEEK_SET); - for (c = 0; c < par->channels; c++) { + for (c = 0; c < par->ch_layout.nb_channels; c++) { avio_read(pb, par->extradata + 32 * c, 32); avio_skip(pb, 14); } @@ -125,8 +125,8 @@ static int fsb_read_header(AVFormatContext *s) return AVERROR_INVALIDDATA; avio_skip(pb, 6); - par->channels = avio_rl16(pb); - if (!par->channels) + par->ch_layout.nb_channels = avio_rl16(pb); + if (!par->ch_layout.nb_channels) return AVERROR_INVALIDDATA; switch (par->codec_id) { @@ -138,17 +138,17 @@ static int fsb_read_header(AVFormatContext *s) par->block_align = 2048; break; case AV_CODEC_ID_ADPCM_THP: - if (par->channels > INT_MAX / 32) + if (par->ch_layout.nb_channels > INT_MAX / 32) return AVERROR_INVALIDDATA; - ret = ff_alloc_extradata(par, 32 * par->channels); + ret = ff_alloc_extradata(par, 32 * par->ch_layout.nb_channels); if (ret < 0) return ret; avio_seek(pb, 0x80, SEEK_SET); - for (c = 0; c < par->channels; c++) { + for (c = 0; c < par->ch_layout.nb_channels; c++) { avio_read(pb, par->extradata + 32 * c, 32); avio_skip(pb, 14); } - par->block_align = 8 * par->channels; + par->block_align = 8 * par->ch_layout.nb_channels; break; } } else { @@ -174,14 +174,14 @@ static int fsb_read_packet(AVFormatContext *s, AVPacket *pkt) pos = avio_tell(s->pb); if (par->codec_id == AV_CODEC_ID_ADPCM_THP && - par->channels > 1) { + par->ch_layout.nb_channels > 1) { int i, ch; ret = av_new_packet(pkt, par->block_align); if (ret < 0) return ret; for (i = 0; i < 4; i++) { - for (ch = 0; ch < par->channels; ch++) { + for (ch = 0; ch < par->ch_layout.nb_channels; ch++) { pkt->data[ch * 8 + i * 2 + 0] = avio_r8(s->pb); pkt->data[ch * 8 + i * 2 + 1] = avio_r8(s->pb); } diff --git a/libavformat/fwse.c b/libavformat/fwse.c index ed8cd3a6d..28a322d9d 100644 --- a/libavformat/fwse.c +++ b/libavformat/fwse.c @@ -40,6 +40,7 @@ static int fwse_probe(const AVProbeData *p) static int fwse_read_header(AVFormatContext *s) { unsigned start_offset, version; + int channels; AVIOContext *pb = s->pb; AVCodecParameters *par; AVStream *st; @@ -59,13 +60,10 @@ static int fwse_read_header(AVFormatContext *s) par->codec_type = AVMEDIA_TYPE_AUDIO; par->codec_id = AV_CODEC_ID_ADPCM_IMA_MTF; par->format = AV_SAMPLE_FMT_S16; - par->channels = avio_rl32(pb); - if (par->channels != 1 && par->channels != 2) + channels = avio_rl32(pb); + if (channels != 1 && channels != 2) return AVERROR_INVALIDDATA; - if (par->channels == 1) - par->channel_layout = AV_CH_LAYOUT_MONO; - else if (par->channels == 2) - par->channel_layout = AV_CH_LAYOUT_STEREO; + av_channel_layout_default(&par->ch_layout, channels); st->duration = avio_rl32(pb); par->sample_rate = avio_rl32(pb); if (par->sample_rate <= 0 || par->sample_rate > INT_MAX) diff --git a/libavformat/g722.c b/libavformat/g722.c index 3bfe05ea6..08cd2cbc8 100644 --- a/libavformat/g722.c +++ b/libavformat/g722.c @@ -35,7 +35,7 @@ static int g722_read_header(AVFormatContext *s) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_ADPCM_G722; st->codecpar->sample_rate = 16000; - st->codecpar->channels = 1; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; st->codecpar->bits_per_coded_sample = av_get_bits_per_sample(st->codecpar->codec_id); diff --git a/libavformat/g723_1.c b/libavformat/g723_1.c index f38064b5b..e35b4ed50 100644 --- a/libavformat/g723_1.c +++ b/libavformat/g723_1.c @@ -41,8 +41,7 @@ static av_cold int g723_1_init(AVFormatContext *s) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_G723_1; - st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; - st->codecpar->channels = 1; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; st->codecpar->sample_rate = 8000; avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); diff --git a/libavformat/g726.c b/libavformat/g726.c index 4b08d0a9f..97580a74f 100644 --- a/libavformat/g726.c +++ b/libavformat/g726.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "avformat.h" #include "internal.h" #include "libavutil/opt.h" @@ -42,7 +44,7 @@ static int g726_read_header(AVFormatContext *s) st->codecpar->sample_rate = c->sample_rate; st->codecpar->bits_per_coded_sample = c->code_size; st->codecpar->bit_rate = ((int[]){ 16000, 24000, 32000, 40000 })[c->code_size - 2]; - st->codecpar->channels = 1; + st->codecpar->ch_layout.nb_channels = 1; return 0; } diff --git a/libavformat/g729dec.c b/libavformat/g729dec.c index 51112f561..9c92ea4fc 100644 --- a/libavformat/g729dec.c +++ b/libavformat/g729dec.c @@ -43,7 +43,7 @@ static int g729_read_header(AVFormatContext *s) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_G729; st->codecpar->sample_rate = 8000; - st->codecpar->channels = 1; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; if (s1 && s1->bit_rate) s->bit_rate = s1->bit_rate; diff --git a/libavformat/gdv.c b/libavformat/gdv.c index b20691a2a..f8a8f5035 100644 --- a/libavformat/gdv.c +++ b/libavformat/gdv.c @@ -99,7 +99,7 @@ static int gdv_read_header(AVFormatContext *ctx) ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; ast->codecpar->codec_tag = 0; ast->codecpar->sample_rate = avio_rl16(pb); - ast->codecpar->channels = 1 + !!(snd_flags & 2); + ast->codecpar->ch_layout.nb_channels = 1 + !!(snd_flags & 2); if (snd_flags & 8) { ast->codecpar->codec_id = AV_CODEC_ID_GREMLIN_DPCM; } else { @@ -108,7 +108,8 @@ static int gdv_read_header(AVFormatContext *ctx) avpriv_set_pts_info(ast, 64, 1, ast->codecpar->sample_rate); gdv->audio_size = (ast->codecpar->sample_rate / fps) * - ast->codecpar->channels * (1 + !!(snd_flags & 4)) / (1 + !!(snd_flags & 8)); + ast->codecpar->ch_layout.nb_channels * + (1 + !!(snd_flags & 4)) / (1 + !!(snd_flags & 8)); gdv->is_audio = 1; } else { avio_skip(pb, 2); diff --git a/libavformat/genh.c b/libavformat/genh.c index f9b222d8c..a25d4d625 100644 --- a/libavformat/genh.c +++ b/libavformat/genh.c @@ -21,7 +21,6 @@ #include "libavutil/channel_layout.h" #include "libavutil/intreadwrite.h" -#include "libavcodec/internal.h" #include "avformat.h" #include "internal.h" @@ -55,19 +54,22 @@ static int genh_read_header(AVFormatContext *s) return AVERROR(ENOMEM); st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; - st->codecpar->channels = avio_rl32(s->pb); - if (st->codecpar->channels <= 0 || st->codecpar->channels > FF_SANE_NB_CHANNELS) + st->codecpar->ch_layout.nb_channels = avio_rl32(s->pb); + if (st->codecpar->ch_layout.nb_channels <= 0) return AVERROR_INVALIDDATA; - if (st->codecpar->channels == 1) - st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; - else if (st->codecpar->channels == 2) - st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; + if (st->codecpar->ch_layout.nb_channels == 1) + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; + else if (st->codecpar->ch_layout.nb_channels == 2) + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; align = c->interleave_size = avio_rl32(s->pb); - if (align < 0 || align > INT_MAX / st->codecpar->channels) + if (align < 0 || align > INT_MAX / st->codecpar->ch_layout.nb_channels) return AVERROR_INVALIDDATA; - st->codecpar->block_align = align * st->codecpar->channels; + st->codecpar->block_align = align * st->codecpar->ch_layout.nb_channels; st->codecpar->sample_rate = avio_rl32(s->pb); + if (st->codecpar->sample_rate < 0) + return AVERROR_INVALIDDATA; + avio_skip(s->pb, 4); st->duration = avio_rl32(s->pb); @@ -76,7 +78,7 @@ static int genh_read_header(AVFormatContext *s) case 0: st->codecpar->codec_id = AV_CODEC_ID_ADPCM_PSX; break; case 1: case 11: st->codecpar->bits_per_coded_sample = 4; - st->codecpar->block_align = 36 * st->codecpar->channels; + st->codecpar->block_align = 36 * st->codecpar->ch_layout.nb_channels; st->codecpar->codec_id = AV_CODEC_ID_ADPCM_IMA_WAV; break; case 2: st->codecpar->codec_id = AV_CODEC_ID_ADPCM_DTK; break; case 3: st->codecpar->codec_id = st->codecpar->block_align > 0 ? @@ -122,13 +124,13 @@ static int genh_read_header(AVFormatContext *s) coef_splitted[1] = avio_rl32(s->pb); if (st->codecpar->codec_id == AV_CODEC_ID_ADPCM_THP) { - if (st->codecpar->channels > 2) { - avpriv_request_sample(s, "channels %d>2", st->codecpar->channels); + if (st->codecpar->ch_layout.nb_channels > 2) { + avpriv_request_sample(s, "channels %d>2", st->codecpar->ch_layout.nb_channels); return AVERROR_PATCHWELCOME; } - ff_alloc_extradata(st->codecpar, 32 * st->codecpar->channels); - for (ch = 0; ch < st->codecpar->channels; ch++) { + ff_alloc_extradata(st->codecpar, 32 * st->codecpar->ch_layout.nb_channels); + for (ch = 0; ch < st->codecpar->ch_layout.nb_channels; ch++) { if (coef_type & 1) { avpriv_request_sample(s, "coef_type & 1"); return AVERROR_PATCHWELCOME; @@ -139,7 +141,7 @@ static int genh_read_header(AVFormatContext *s) } if (c->dsp_int_type == 1) { - st->codecpar->block_align = 8 * st->codecpar->channels; + st->codecpar->block_align = 8 * st->codecpar->ch_layout.nb_channels; if (c->interleave_size != 1 && c->interleave_size != 2 && c->interleave_size != 4) @@ -164,16 +166,16 @@ static int genh_read_packet(AVFormatContext *s, AVPacket *pkt) int ret; if (c->dsp_int_type == 1 && par->codec_id == AV_CODEC_ID_ADPCM_THP && - par->channels > 1) { + par->ch_layout.nb_channels > 1) { int i, ch; if (avio_feof(s->pb)) return AVERROR_EOF; - ret = av_new_packet(pkt, 8 * par->channels); + ret = av_new_packet(pkt, 8 * par->ch_layout.nb_channels); if (ret < 0) return ret; for (i = 0; i < 8 / c->interleave_size; i++) { - for (ch = 0; ch < par->channels; ch++) { + for (ch = 0; ch < par->ch_layout.nb_channels; ch++) { pkt->data[ch * 8 + i*c->interleave_size+0] = avio_r8(s->pb); pkt->data[ch * 8 + i*c->interleave_size+1] = avio_r8(s->pb); } @@ -183,7 +185,8 @@ static int genh_read_packet(AVFormatContext *s, AVPacket *pkt) ret = av_get_packet(s->pb, pkt, par->block_align * 1024); } else { - ret = av_get_packet(s->pb, pkt, par->block_align ? par->block_align : 1024 * par->channels); + ret = av_get_packet(s->pb, pkt, par->block_align ? par->block_align : + 1024 * par->ch_layout.nb_channels); } pkt->stream_index = 0; diff --git a/libavformat/gif.c b/libavformat/gif.c index cba87d3ea..b52ff4dd3 100644 --- a/libavformat/gif.c +++ b/libavformat/gif.c @@ -54,7 +54,7 @@ static int gif_write_header(AVFormatContext *s) return 0; } -static int gif_parse_packet(AVFormatContext *s, uint8_t *data, int size) +static int gif_parse_packet(AVFormatContext *s, const uint8_t *data, int size) { GetByteContext gb; int x; diff --git a/libavformat/gopher.c b/libavformat/gopher.c index 9bbe17164..9497ffacf 100644 --- a/libavformat/gopher.c +++ b/libavformat/gopher.c @@ -24,6 +24,7 @@ */ #include "config.h" +#include "config_components.h" #include "libavutil/avstring.h" #include "avformat.h" diff --git a/libavformat/gsmdec.c b/libavformat/gsmdec.c index e14e9aa21..09dc0e0fb 100644 --- a/libavformat/gsmdec.c +++ b/libavformat/gsmdec.c @@ -79,8 +79,7 @@ static int gsm_read_header(AVFormatContext *s) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = s->iformat->raw_codec_id; - st->codecpar->channels = 1; - st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; st->codecpar->sample_rate = c->sample_rate; st->codecpar->bit_rate = GSM_BLOCK_SIZE * 8 * c->sample_rate / GSM_BLOCK_SAMPLES; diff --git a/libavformat/gxf.c b/libavformat/gxf.c index 6f370c1b5..f720521c1 100644 --- a/libavformat/gxf.c +++ b/libavformat/gxf.c @@ -24,9 +24,9 @@ #include "libavutil/channel_layout.h" #include "libavutil/common.h" #include "avformat.h" +#include "demux.h" #include "internal.h" #include "gxf.h" -#include "libavcodec/mpeg12data.h" struct gxf_stream_info { int64_t first_field; @@ -143,8 +143,7 @@ static int get_sindex(AVFormatContext *s, int id, int format) { case 9: st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE; - st->codecpar->channels = 1; - st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; st->codecpar->sample_rate = 48000; st->codecpar->bit_rate = 3 * 1 * 48000 * 8; st->codecpar->block_align = 3 * 1; @@ -153,8 +152,7 @@ static int get_sindex(AVFormatContext *s, int id, int format) { case 10: st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE; - st->codecpar->channels = 1; - st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; st->codecpar->sample_rate = 48000; st->codecpar->bit_rate = 2 * 1 * 48000 * 8; st->codecpar->block_align = 2 * 1; @@ -163,8 +161,7 @@ static int get_sindex(AVFormatContext *s, int id, int format) { case 17: st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_AC3; - st->codecpar->channels = 2; - st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; st->codecpar->sample_rate = 48000; break; case 26: /* AVCi50 / AVCi100 (AVC Intra) */ diff --git a/libavformat/gxfenc.c b/libavformat/gxfenc.c index 133d1e9fb..0f971c039 100644 --- a/libavformat/gxfenc.c +++ b/libavformat/gxfenc.c @@ -21,13 +21,12 @@ #include "libavutil/avassert.h" #include "libavutil/intfloat.h" -#include "libavutil/opt.h" #include "libavutil/mathematics.h" -#include "libavutil/timecode.h" #include "avformat.h" #include "avio_internal.h" #include "internal.h" #include "gxf.h" +#include "mux.h" #define GXF_SAMPLES_PER_FRAME 32768 #define GXF_AUDIO_PACKET_SIZE 65536 @@ -714,7 +713,7 @@ static int gxf_write_header(AVFormatContext *s) av_log(s, AV_LOG_ERROR, "only 48000hz sampling rate is allowed\n"); return -1; } - if (st->codecpar->channels != 1) { + if (st->codecpar->ch_layout.nb_channels != 1) { av_log(s, AV_LOG_ERROR, "only mono tracks are allowed\n"); return -1; } diff --git a/libavformat/h261dec.c b/libavformat/h261dec.c index b5161ff57..0fca1a340 100644 --- a/libavformat/h261dec.c +++ b/libavformat/h261dec.c @@ -19,7 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavcodec/get_bits.h" +#include "libavutil/intreadwrite.h" #include "avformat.h" #include "rawdec.h" diff --git a/libavformat/h264dec.c b/libavformat/h264dec.c index 199e87fbf..ac804c019 100644 --- a/libavformat/h264dec.c +++ b/libavformat/h264dec.c @@ -23,7 +23,6 @@ #include "libavcodec/golomb.h" #include "avformat.h" #include "rawdec.h" -#include "libavcodec/internal.h" #define MAX_SPS_COUNT 32 #define MAX_PPS_COUNT 256 diff --git a/libavformat/hashenc.c b/libavformat/hashenc.c index 622491d2e..1aaba0b30 100644 --- a/libavformat/hashenc.c +++ b/libavformat/hashenc.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/avstring.h" #include "libavutil/hash.h" #include "libavutil/intreadwrite.h" diff --git a/libavformat/hca.c b/libavformat/hca.c index eaa96a9b1..74ac00acc 100644 --- a/libavformat/hca.c +++ b/libavformat/hca.c @@ -79,7 +79,7 @@ static int hca_read_header(AVFormatContext *s) par->codec_type = AVMEDIA_TYPE_AUDIO; par->codec_id = AV_CODEC_ID_HCA; par->codec_tag = 0; - par->channels = bytestream2_get_byte(&gb); + st->codecpar->ch_layout.nb_channels = bytestream2_get_byte(&gb); par->sample_rate = bytestream2_get_be24(&gb); block_count = bytestream2_get_be32(&gb); bytestream2_skip(&gb, 4); diff --git a/libavformat/hcom.c b/libavformat/hcom.c index b7fb7314c..5031f0029 100644 --- a/libavformat/hcom.c +++ b/libavformat/hcom.c @@ -20,7 +20,6 @@ */ #include "libavutil/intreadwrite.h" -#include "libavcodec/internal.h" #include "avformat.h" #include "internal.h" #include "pcm.h" @@ -62,7 +61,7 @@ static int hcom_read_header(AVFormatContext *s) return AVERROR(ENOMEM); st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; - st->codecpar->channels = 1; + st->codecpar->ch_layout.nb_channels = 1; st->codecpar->sample_rate = 22050 / divisor; st->codecpar->codec_id = AV_CODEC_ID_HCOM; st->codecpar->bits_per_coded_sample = 8; diff --git a/libavformat/hdsenc.c b/libavformat/hdsenc.c index 2a5201912..a8f340ac4 100644 --- a/libavformat/hdsenc.c +++ b/libavformat/hdsenc.c @@ -20,14 +20,13 @@ */ #include "config.h" -#include #if HAVE_UNISTD_H #include #endif #include "avformat.h" -#include "avio_internal.h" #include "internal.h" +#include "mux.h" #include "os_support.h" #include "libavutil/avstring.h" diff --git a/libavformat/hls.c b/libavformat/hls.c index 53be0f591..3dc7bd393 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -27,7 +27,10 @@ * https://www.rfc-editor.org/rfc/rfc8216.txt */ +#include "config_components.h" + #include "libavformat/http.h" +#include "libavutil/aes.h" #include "libavutil/avstring.h" #include "libavutil/avassert.h" #include "libavutil/intreadwrite.h" @@ -36,6 +39,7 @@ #include "libavutil/dict.h" #include "libavutil/time.h" #include "avformat.h" +#include "demux.h" #include "internal.h" #include "avio_internal.h" #include "id3v2.h" @@ -116,6 +120,8 @@ struct playlist { enum PlaylistType type; int64_t target_duration; int64_t start_seq_no; + int time_offset_flag; + int64_t start_time_offset; int n_segments; struct segment **segments; int needed; @@ -207,6 +213,7 @@ typedef struct HLSContext { int64_t cur_seq_no; int m3u8_hold_counters; int live_start_index; + int prefer_x_start; int first_packet; int64_t first_timestamp; int64_t cur_timestamp; @@ -833,10 +840,10 @@ static int parse_playlist(HLSContext *c, const char *url, if (ret < 0) goto fail; seq_no = strtoull(ptr, NULL, 10); - if (seq_no > INT64_MAX) { + if (seq_no > INT64_MAX/2) { av_log(c->ctx, AV_LOG_DEBUG, "MEDIA-SEQUENCE higher than " - "INT64_MAX, mask out the highest bit\n"); - seq_no &= INT64_MAX; + "INT64_MAX/2, mask out the highest bit\n"); + seq_no &= INT64_MAX/2; } pls->start_seq_no = seq_no; } else if (av_strstart(line, "#EXT-X-PLAYLIST-TYPE:", &ptr)) { @@ -885,6 +892,21 @@ static int parse_playlist(HLSContext *c, const char *url, cur_init_section->key = NULL; } + } else if (av_strstart(line, "#EXT-X-START:", &ptr)) { + const char *time_offset_value = NULL; + ret = ensure_playlist(c, &pls, url); + if (ret < 0) { + goto fail; + } + if (av_strstart(ptr, "TIME-OFFSET=", &time_offset_value)) { + float offset = strtof(time_offset_value, NULL); + pls->start_time_offset = offset * AV_TIME_BASE; + pls->time_offset_flag = 1; + } else { + av_log(c->ctx, AV_LOG_WARNING, "#EXT-X-START value is" + "invalid, it will be ignored"); + continue; + } } else if (av_strstart(line, "#EXT-X-ENDLIST", &ptr)) { if (pls) pls->finished = 1; @@ -1659,7 +1681,8 @@ static void add_metadata_from_renditions(AVFormatContext *s, struct playlist *pl /* if timestamp was in valid range: returns 1 and sets seq_no * if not: returns 0 and sets seq_no to closest segment */ static int find_timestamp_in_playlist(HLSContext *c, struct playlist *pls, - int64_t timestamp, int64_t *seq_no) + int64_t timestamp, int64_t *seq_no, + int64_t *seg_start_ts) { int i; int64_t pos = c->first_timestamp == AV_NOPTS_VALUE ? @@ -1674,6 +1697,9 @@ static int find_timestamp_in_playlist(HLSContext *c, struct playlist *pls, int64_t diff = pos + pls->segments[i]->duration - timestamp; if (diff > 0) { *seq_no = pls->start_seq_no + i; + if (seg_start_ts) { + *seg_start_ts = pos; + } return 1; } pos += pls->segments[i]->duration; @@ -1697,7 +1723,7 @@ static int64_t select_cur_seq_no(HLSContext *c, struct playlist *pls) * playlist) and this is a complete file, find the matching segment * by counting durations. */ if (pls->finished && c->cur_timestamp != AV_NOPTS_VALUE) { - find_timestamp_in_playlist(c, pls, c->cur_timestamp, &seq_no); + find_timestamp_in_playlist(c, pls, c->cur_timestamp, &seq_no, NULL); return seq_no; } @@ -1714,9 +1740,45 @@ static int64_t select_cur_seq_no(HLSContext *c, struct playlist *pls) /* If this is a live stream, start live_start_index segments from the * start or end */ if (c->live_start_index < 0) - return pls->start_seq_no + FFMAX(pls->n_segments + c->live_start_index, 0); + seq_no = pls->start_seq_no + FFMAX(pls->n_segments + + c->live_start_index, 0); else - return pls->start_seq_no + FFMIN(c->live_start_index, pls->n_segments - 1); + seq_no = pls->start_seq_no + FFMIN(c->live_start_index, + pls->n_segments - 1); + + /* If #EXT-X-START in playlist, need to recalculate */ + if (pls->time_offset_flag && c->prefer_x_start) { + int64_t start_timestamp; + int64_t playlist_duration = 0; + int64_t cur_timestamp = c->cur_timestamp == AV_NOPTS_VALUE ? 0 : + c->cur_timestamp; + + for (int i = 0; i < pls->n_segments; i++) + playlist_duration += pls->segments[i]->duration; + + /* If the absolute value of TIME-OFFSET exceeds + * the duration of the playlist, it indicates either the end of the + * playlist (if positive) or the beginning of the playlist (if + * negative). */ + if (pls->start_time_offset >=0 && + pls->start_time_offset > playlist_duration) + start_timestamp = cur_timestamp + playlist_duration; + else if (pls->start_time_offset >= 0 && + pls->start_time_offset <= playlist_duration) + start_timestamp = cur_timestamp + pls->start_time_offset; + else if (pls->start_time_offset < 0 && + pls->start_time_offset < -playlist_duration) + start_timestamp = cur_timestamp; + else if (pls->start_time_offset < 0 && + pls->start_time_offset > -playlist_duration) + start_timestamp = cur_timestamp + playlist_duration + + pls->start_time_offset; + else + start_timestamp = cur_timestamp; + + find_timestamp_in_playlist(c, pls, start_timestamp, &seq_no, NULL); + } + return seq_no; } /* Otherwise just start on the first segment. */ @@ -2030,7 +2092,7 @@ static int hls_read_header(AVFormatContext *s) if (seg && seg->key_type == KEY_SAMPLE_AES && pls->is_id3_timestamped && pls->audio_setup_info.codec_id != AV_CODEC_ID_NONE) { void *iter = NULL; - while ((in_fmt = (const AVInputFormat *)av_demuxer_iterate(&iter))) + while ((in_fmt = av_demuxer_iterate(&iter))) if (in_fmt->raw_codec_id == pls->audio_setup_info.codec_id) break; } else { @@ -2057,7 +2119,7 @@ static int hls_read_header(AVFormatContext *s) if (strstr(in_fmt->name, "mov")) { char key[33]; ff_data_to_hex(key, pls->key, sizeof(pls->key), 0); - av_dict_set(&options, "decryption_key", key, AV_OPT_FLAG_DECODING_PARAM); + av_dict_set(&options, "decryption_key", key, 0); } else if (!c->crypto_ctx.aes_ctx) { c->crypto_ctx.aes_ctx = av_aes_alloc(); if (!c->crypto_ctx.aes_ctx) { @@ -2368,7 +2430,7 @@ static int hls_read_seek(AVFormatContext *s, int stream_index, int i, j; int stream_subdemuxer_index; int64_t first_timestamp, seek_timestamp, duration; - int64_t seq_no; + int64_t seq_no, seg_start_ts; if ((flags & AVSEEK_FLAG_BYTE) || (c->ctx->ctx_flags & AVFMTCTX_UNSEEKABLE)) return AVERROR(ENOSYS); @@ -2378,8 +2440,7 @@ static int hls_read_seek(AVFormatContext *s, int stream_index, seek_timestamp = av_rescale_rnd(timestamp, AV_TIME_BASE, s->streams[stream_index]->time_base.den, - flags & AVSEEK_FLAG_BACKWARD ? - AV_ROUND_DOWN : AV_ROUND_UP); + AV_ROUND_DOWN); duration = s->duration == AV_NOPTS_VALUE ? 0 : s->duration; @@ -2400,9 +2461,16 @@ static int hls_read_seek(AVFormatContext *s, int stream_index, } /* check if the timestamp is valid for the playlist with the * specified stream index */ - if (!seek_pls || !find_timestamp_in_playlist(c, seek_pls, seek_timestamp, &seq_no)) + if (!seek_pls || !find_timestamp_in_playlist(c, seek_pls, seek_timestamp, &seq_no, &seg_start_ts)) return AVERROR(EIO); + if (s->streams[stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && + flags & AVSEEK_FLAG_BACKWARD && !(flags & AVSEEK_FLAG_ANY)) { + /* Seeking to start of segment ensures we seek to a keyframe located + * before the given timestamp. */ + seek_timestamp = seg_start_ts; + } + /* set segment now so we do not need to search again below */ seek_pls->cur_seq_no = seq_no; seek_pls->seek_stream_index = stream_subdemuxer_index; @@ -2429,7 +2497,7 @@ static int hls_read_seek(AVFormatContext *s, int stream_index, if (pls != seek_pls) { /* set closest segment seq_no for playlists not handled above */ - find_timestamp_in_playlist(c, pls, seek_timestamp, &pls->cur_seq_no); + find_timestamp_in_playlist(c, pls, seek_timestamp, &pls->cur_seq_no, NULL); /* seek the playlist to the given position without taking * keyframes into account since this playlist does not have the * specified stream where we should look for the keyframes */ @@ -2462,6 +2530,8 @@ static int hls_probe(const AVProbeData *p) static const AVOption hls_options[] = { {"live_start_index", "segment index to start live streams at (negative values are from the end)", OFFSET(live_start_index), AV_OPT_TYPE_INT, {.i64 = -3}, INT_MIN, INT_MAX, FLAGS}, + {"prefer_x_start", "prefer to use #EXT-X-START if it's in playlist instead of live_start_index", + OFFSET(prefer_x_start), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS}, {"allowed_extensions", "List of file extensions that hls is allowed to access", OFFSET(allowed_extensions), AV_OPT_TYPE_STRING, {.str = "3gp,aac,avi,ac3,eac3,flac,mkv,m3u8,m4a,m4s,m4v,mpg,mov,mp2,mp3,mp4,mpeg,mpegts,ogg,ogv,oga,ts,vob,wav"}, @@ -2493,7 +2563,7 @@ const 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 | AVFMT_TS_DISCONT, + .flags = AVFMT_NOGENSEARCH | AVFMT_TS_DISCONT | AVFMT_NO_BYTE_SEEK, .flags_internal = FF_FMT_INIT_CLEANUP, .read_probe = hls_probe, .read_header = hls_read_header, diff --git a/libavformat/hls_sample_encryption.c b/libavformat/hls_sample_encryption.c index 3dbaff717..089662905 100644 --- a/libavformat/hls_sample_encryption.c +++ b/libavformat/hls_sample_encryption.c @@ -26,12 +26,14 @@ * https://developer.apple.com/library/ios/documentation/AudioVideo/Conceptual/HLS_Sample_Encryption */ +#include "libavutil/aes.h" #include "libavutil/channel_layout.h" #include "hls_sample_encryption.h" #include "libavcodec/adts_header.h" #include "libavcodec/adts_parser.h" +#include "libavcodec/ac3tab.h" #include "libavcodec/ac3_parser_internal.h" @@ -109,13 +111,14 @@ int ff_hls_senc_parse_audio_setup_info(AVStream *st, HLSAudioSetupInfo *info) } st->codecpar->sample_rate = ac3hdr->sample_rate; - st->codecpar->channels = ac3hdr->channels; - st->codecpar->channel_layout = ac3hdr->channel_layout; + av_channel_layout_uninit(&st->codecpar->ch_layout); + av_channel_layout_from_mask(&st->codecpar->ch_layout, ac3hdr->channel_layout); st->codecpar->bit_rate = ac3hdr->bit_rate; av_free(ac3hdr); } else { /* Parse 'dec3' EC3SpecificBox */ GetBitContext gb; + uint64_t mask; int data_rate, fscod, acmod, lfeon; ret = init_get_bits8(&gb, info->setup_data, info->setup_data_length); @@ -131,11 +134,12 @@ int ff_hls_senc_parse_audio_setup_info(AVStream *st, HLSAudioSetupInfo *info) st->codecpar->sample_rate = eac3_sample_rate_tab[fscod]; - st->codecpar->channel_layout = ff_ac3_channel_layout_tab[acmod]; + mask = ff_ac3_channel_layout_tab[acmod]; if (lfeon) - st->codecpar->channel_layout |= AV_CH_LOW_FREQUENCY; + mask |= AV_CH_LOW_FREQUENCY; - st->codecpar->channels = av_get_channel_layout_nb_channels(st->codecpar->channel_layout); + av_channel_layout_uninit(&st->codecpar->ch_layout); + av_channel_layout_from_mask(&st->codecpar->ch_layout, mask); st->codecpar->bit_rate = data_rate*1000; } diff --git a/libavformat/hls_sample_encryption.h b/libavformat/hls_sample_encryption.h index ff3f9c22f..d86eccb74 100644 --- a/libavformat/hls_sample_encryption.h +++ b/libavformat/hls_sample_encryption.h @@ -29,12 +29,13 @@ #ifndef AVFORMAT_HLS_SAMPLE_ENCRYPTION_H #define AVFORMAT_HLS_SAMPLE_ENCRYPTION_H +#include #include +#include "libavcodec/codec_id.h" +#include "libavcodec/packet.h" #include "avformat.h" -#include "libavcodec/avcodec.h" -#include "libavutil/aes.h" #define HLS_MAX_ID3_TAGS_DATA_LEN 138 #define HLS_MAX_AUDIO_SETUP_DATA_LEN 10 diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index ef8973cea..6f49ae1aa 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -21,7 +21,7 @@ */ #include "config.h" -#include +#include "config_components.h" #include #if HAVE_UNISTD_H #include @@ -35,11 +35,9 @@ #include "libavutil/avassert.h" #include "libavutil/mathematics.h" -#include "libavutil/parseutils.h" #include "libavutil/avstring.h" #include "libavutil/bprint.h" #include "libavutil/intreadwrite.h" -#include "libavutil/random_seed.h" #include "libavutil/opt.h" #include "libavutil/log.h" #include "libavutil/time.h" @@ -53,6 +51,7 @@ #endif #include "hlsplaylist.h" #include "internal.h" +#include "mux.h" #include "os_support.h" typedef enum { @@ -316,8 +315,7 @@ static int hlsenc_io_close(AVFormatContext *s, AVIOContext **pb, char *filename) URLContext *http_url_context = ffio_geturlcontext(*pb); av_assert0(http_url_context); avio_flush(*pb); - ffurl_shutdown(http_url_context, AVIO_FLAG_WRITE); - ret = ff_http_get_shutdown_status(http_url_context); + ret = ffurl_shutdown(http_url_context, AVIO_FLAG_WRITE); #endif } return ret; @@ -1288,8 +1286,10 @@ static int parse_playlist(AVFormatContext *s, const char *url, VariantStream *vs new_start_pos = avio_tell(vs->avf->pb); vs->size = new_start_pos - vs->start_pos; ret = hls_append_segment(s, hls, vs, vs->duration, vs->start_pos, vs->size); - vs->last_segment->discont_program_date_time = discont_program_date_time; - discont_program_date_time += vs->duration; + if (discont_program_date_time) { + vs->last_segment->discont_program_date_time = discont_program_date_time; + discont_program_date_time += vs->duration; + } if (ret < 0) goto fail; vs->start_pos = new_start_pos; @@ -1550,7 +1550,11 @@ static int hls_window(AVFormatContext *s, int last, VariantStream *vs) 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; + hls->version = 2; + if (!(hls->flags & HLS_ROUND_DURATIONS)) { + hls->version = 3; + } + if (byterange_mode) { hls->version = 4; sequence = 0; @@ -2631,6 +2635,9 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) vs->start_pos += vs->size; if (hls->key_info_file || hls->encrypt) ret = hls_start(s, vs); + if (hls->segment_type == SEGMENT_TYPE_MPEGTS && oc->oformat->priv_class && oc->priv_data) { + av_opt_set(oc->priv_data, "mpegts_flags", "resend_headers", 0); + } } else if (hls->max_seg_size > 0) { if (vs->size + vs->start_pos >= hls->max_seg_size) { vs->sequence++; diff --git a/libavformat/hlsplaylist.h b/libavformat/hlsplaylist.h index 29487da3e..1928fe787 100644 --- a/libavformat/hlsplaylist.h +++ b/libavformat/hlsplaylist.h @@ -25,7 +25,6 @@ #include -#include "libavutil/common.h" #include "avformat.h" #include "avio.h" diff --git a/libavformat/http.c b/libavformat/http.c index 4415a26f2..c5c48c790 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -20,6 +20,7 @@ */ #include "config.h" +#include "config_components.h" #if CONFIG_ZLIB #include @@ -28,6 +29,7 @@ #include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/bprint.h" +#include "libavutil/getenv_utf8.h" #include "libavutil/opt.h" #include "libavutil/time.h" #include "libavutil/parseutils.h" @@ -39,6 +41,7 @@ #include "network.h" #include "os_support.h" #include "url.h" +#include "version.h" /* XXX: POST protocol is not completely implemented because ffmpeg uses * only a subset of it. */ @@ -48,6 +51,7 @@ * path names). */ #define BUFFER_SIZE (MAX_URL_SIZE + HTTP_HEADERS_SIZE) #define MAX_REDIRECTS 8 +#define MAX_CACHED_REDIRECTS 32 #define HTTP_SINGLE 1 #define HTTP_MUTLI 2 #define MAX_EXPIRY 19 @@ -71,7 +75,6 @@ typedef struct HTTPContext { uint64_t off, end_off, filesize; char *uri; char *location; - int cache_redirect; HTTPAuthState auth_state; HTTPAuthState proxy_auth_state; char *http_proxy; @@ -129,6 +132,10 @@ typedef struct HTTPContext { HandshakeState handshake_step; int is_connected_server; int short_seek_size; + int64_t expires; + char *new_location; + AVDictionary *redirect_cache; + uint64_t filesize_from_content_range; } HTTPContext; #define OFFSET(x) offsetof(HTTPContext, x) @@ -171,14 +178,13 @@ 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}, { "short_seek_size", "Threshold to favor readahead over seek.", OFFSET(short_seek_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, D }, - { "cache_redirect", "Save redirected URL for subsequent seek operations", OFFSET(cache_redirect), AV_OPT_TYPE_BOOL, { .i64 = FF_HTTP_CACHE_REDIRECT_DEFAULT }, 0, 1, D }, { NULL } }; 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); + const char *proxyauth); +static int http_read_header(URLContext *h); static int http_shutdown(URLContext *h, int flags); void ff_http_init_auth_state(URLContext *dest, const URLContext *src) @@ -194,12 +200,13 @@ void ff_http_init_auth_state(URLContext *dest, const URLContext *src) static int http_open_cnx_internal(URLContext *h, AVDictionary **options) { const char *path, *proxy_path, *lower_proto = "tcp", *local_path; + char *env_http_proxy, *env_no_proxy; char *hashmark; char hostname[1024], hoststr[1024], proto[10]; char auth[1024], proxyauth[1024] = ""; char path1[MAX_URL_SIZE], sanitized_path[MAX_URL_SIZE + 1]; char buf[1024], urlbuf[MAX_URL_SIZE]; - int port, use_proxy, err, location_changed = 0; + int port, use_proxy, err = 0; HTTPContext *s = h->priv_data; av_url_split(proto, sizeof(proto), auth, sizeof(auth), @@ -207,9 +214,13 @@ static int http_open_cnx_internal(URLContext *h, AVDictionary **options) path1, sizeof(path1), s->location); ff_url_join(hoststr, sizeof(hoststr), NULL, NULL, hostname, port, NULL); - proxy_path = s->http_proxy ? s->http_proxy : getenv("http_proxy"); - use_proxy = !ff_http_match_no_proxy(getenv("no_proxy"), hostname) && + env_http_proxy = getenv_utf8("http_proxy"); + proxy_path = s->http_proxy ? s->http_proxy : env_http_proxy; + + env_no_proxy = getenv_utf8("no_proxy"); + use_proxy = !ff_http_match_no_proxy(env_no_proxy, hostname) && proxy_path && av_strstart(proxy_path, "http://", NULL); + freeenv_utf8(env_no_proxy); if (!strcmp(proto, "https")) { lower_proto = "tls"; @@ -220,7 +231,7 @@ static int http_open_cnx_internal(URLContext *h, AVDictionary **options) if (s->http_proxy) { err = av_dict_set(options, "http_proxy", s->http_proxy, 0); if (err < 0) - return err; + goto end; } } if (port < 0) @@ -255,16 +266,12 @@ static int http_open_cnx_internal(URLContext *h, AVDictionary **options) err = ffurl_open_whitelist(&s->hd, buf, AVIO_FLAG_READ_WRITE, &h->interrupt_callback, options, h->protocol_whitelist, h->protocol_blacklist, h); - if (err < 0) - return err; } - err = http_connect(h, path, local_path, hoststr, - auth, proxyauth, &location_changed); - if (err < 0) - return err; - - return location_changed; +end: + freeenv_utf8(env_http_proxy); + return err < 0 ? err : http_connect( + h, path, local_path, hoststr, auth, proxyauth); } static int http_should_reconnect(HTTPContext *s, int err) @@ -300,31 +307,85 @@ static int http_should_reconnect(HTTPContext *s, int err) return av_match_list(http_code, s->reconnect_on_http_error, ',') > 0; } +static char *redirect_cache_get(HTTPContext *s) +{ + AVDictionaryEntry *re; + int64_t expiry; + char *delim; + + re = av_dict_get(s->redirect_cache, s->location, NULL, AV_DICT_MATCH_CASE); + if (!re) { + return NULL; + } + + delim = strchr(re->value, ';'); + if (!delim) { + return NULL; + } + + expiry = strtoll(re->value, NULL, 10); + if (time(NULL) > expiry) { + return NULL; + } + + return delim + 1; +} + +static int redirect_cache_set(HTTPContext *s, const char *source, const char *dest, int64_t expiry) +{ + char *value; + int ret; + + value = av_asprintf("%"PRIi64";%s", expiry, dest); + if (!value) { + return AVERROR(ENOMEM); + } + + ret = av_dict_set(&s->redirect_cache, source, value, AV_DICT_MATCH_CASE | AV_DICT_DONT_STRDUP_VAL); + if (ret < 0) + return ret; + + return 0; +} + /* return non zero if error */ static int http_open_cnx(URLContext *h, AVDictionary **options) { HTTPAuthType cur_auth_type, cur_proxy_auth_type; HTTPContext *s = h->priv_data; - int location_changed, attempts = 0, redirects = 0; + int ret, attempts = 0, redirects = 0; int reconnect_delay = 0; uint64_t off; + char *cached; redo: + + cached = redirect_cache_get(s); + if (cached) { + av_free(s->location); + s->location = av_strdup(cached); + if (!s->location) { + ret = AVERROR(ENOMEM); + goto fail; + } + goto redo; + } + av_dict_copy(options, s->chained_options, 0); cur_auth_type = s->auth_state.auth_type; cur_proxy_auth_type = s->auth_state.auth_type; off = s->off; - location_changed = http_open_cnx_internal(h, options); - if (location_changed < 0) { - if (!http_should_reconnect(s, location_changed) || + ret = http_open_cnx_internal(h, options); + if (ret < 0) { + if (!http_should_reconnect(s, ret) || reconnect_delay > s->reconnect_delay_max) goto fail; av_log(h, AV_LOG_WARNING, "Will reconnect at %"PRIu64" in %d second(s).\n", off, reconnect_delay); - location_changed = ff_network_sleep_interruptible(1000U * 1000 * reconnect_delay, &h->interrupt_callback); - if (location_changed != AVERROR(ETIMEDOUT)) + ret = ff_network_sleep_interruptible(1000U * 1000 * reconnect_delay, &h->interrupt_callback); + if (ret != AVERROR(ETIMEDOUT)) goto fail; reconnect_delay = 1 + 2 * reconnect_delay; @@ -354,16 +415,28 @@ redo: } if ((s->http_code == 301 || s->http_code == 302 || s->http_code == 303 || s->http_code == 307 || s->http_code == 308) && - location_changed == 1) { + s->new_location) { /* url moved, get next */ ffurl_closep(&s->hd); if (redirects++ >= MAX_REDIRECTS) return AVERROR(EIO); + + if (!s->expires) { + s->expires = (s->http_code == 301 || s->http_code == 308) ? INT64_MAX : -1; + } + + if (s->expires > time(NULL) && av_dict_count(s->redirect_cache) < MAX_CACHED_REDIRECTS) { + redirect_cache_set(s, s->location, s->new_location, s->expires); + } + + av_free(s->location); + s->location = s->new_location; + s->new_location = NULL; + /* Restart the authentication process with the new target, which * might use a different auth mechanism. */ memset(&s->auth_state, 0, sizeof(s->auth_state)); attempts = 0; - location_changed = 0; goto redo; } return 0; @@ -371,25 +444,10 @@ redo: fail: if (s->hd) ffurl_closep(&s->hd); - if (location_changed < 0) - return location_changed; + if (ret < 0) + return ret; return ff_http_averror(s->http_code, AVERROR(EIO)); } -int ff_http_get_shutdown_status(URLContext *h) -{ - int ret = 0; - HTTPContext *s = h->priv_data; - - /* flush the receive buffer when it is write only mode */ - char buf[1024]; - int read_ret; - read_ret = ffurl_read(s->hd, buf, sizeof(buf)); - if (read_ret < 0) { - ret = read_ret; - } - - return ret; -} int ff_http_do_new_request(URLContext *h, const char *uri) { return ff_http_do_new_request2(h, uri, NULL); @@ -554,7 +612,7 @@ static void handle_http_errors(URLContext *h, int error) static int http_handshake(URLContext *c) { - int ret, err, new_location; + int ret, err; HTTPContext *ch = c->priv_data; URLContext *cl = ch->hd; switch (ch->handshake_step) { @@ -569,7 +627,7 @@ static int http_handshake(URLContext *c) return 2; case READ_HEADERS: av_log(c, AV_LOG_TRACE, "Read headers\n"); - if ((err = http_read_header(c, &new_location)) < 0) { + if ((err = http_read_header(c)) < 0) { handle_http_errors(c, err); return err; } @@ -666,6 +724,8 @@ bail_out: if (ret < 0) { av_dict_free(&s->chained_options); av_dict_free(&s->cookie_dict); + av_dict_free(&s->redirect_cache); + av_freep(&s->new_location); av_freep(&s->uri); } return ret; @@ -753,14 +813,13 @@ static int check_http_code(URLContext *h, int http_code, const char *end) static int parse_location(HTTPContext *s, const char *p) { - char redirected_location[MAX_URL_SIZE], *new_loc; + char redirected_location[MAX_URL_SIZE]; ff_make_absolute_url(redirected_location, sizeof(redirected_location), s->location, p); - new_loc = av_strdup(redirected_location); - if (!new_loc) + av_freep(&s->new_location); + s->new_location = av_strdup(redirected_location); + if (!s->new_location) return AVERROR(ENOMEM); - av_free(s->location); - s->location = new_loc; return 0; } @@ -774,7 +833,7 @@ static void parse_content_range(URLContext *h, const char *p) p += 6; s->off = strtoull(p, NULL, 10); if ((slash = strchr(p, '/')) && strlen(slash) > 0) - s->filesize = strtoull(slash + 1, NULL, 10); + s->filesize_from_content_range = strtoull(slash + 1, NULL, 10); } if (s->seekable == -1 && (!s->is_akamai || s->filesize != 2147483647)) h->is_streamed = 0; /* we _can_ in fact seek */ @@ -983,8 +1042,43 @@ static int cookie_string(AVDictionary *dict, char **cookies) return 0; } -static int process_line(URLContext *h, char *line, int line_count, - int *new_location) +static void parse_expires(HTTPContext *s, const char *p) +{ + struct tm tm; + + if (!parse_set_cookie_expiry_time(p, &tm)) { + s->expires = av_timegm(&tm); + } +} + +static void parse_cache_control(HTTPContext *s, const char *p) +{ + char *age; + int offset; + + /* give 'Expires' higher priority over 'Cache-Control' */ + if (s->expires) { + return; + } + + if (av_stristr(p, "no-cache") || av_stristr(p, "no-store")) { + s->expires = -1; + return; + } + + age = av_stristr(p, "s-maxage="); + offset = 9; + if (!age) { + age = av_stristr(p, "max-age="); + offset = 8; + } + + if (age) { + s->expires = time(NULL) + atoi(p + offset); + } +} + +static int process_line(URLContext *h, char *line, int line_count) { HTTPContext *s = h->priv_data; const char *auto_method = h->flags & AVIO_FLAG_READ ? "POST" : "GET"; @@ -1081,7 +1175,6 @@ static int process_line(URLContext *h, char *line, int line_count, if (!av_strcasecmp(tag, "Location")) { if ((ret = parse_location(s, p)) < 0) return ret; - *new_location = 1; } else if (!av_strcasecmp(tag, "Content-Length") && s->filesize == UINT64_MAX) { s->filesize = strtoull(p, NULL, 10); @@ -1124,6 +1217,10 @@ static int process_line(URLContext *h, char *line, int line_count, } else if (!av_strcasecmp(tag, "Content-Encoding")) { if ((ret = parse_content_encoding(h, p)) < 0) return ret; + } else if (!av_strcasecmp(tag, "Expires")) { + parse_expires(s, p); + } else if (!av_strcasecmp(tag, "Cache-Control")) { + parse_cache_control(s, p); } } return 1; @@ -1229,13 +1326,16 @@ static inline int has_header(const char *str, const char *header) return av_stristart(str, header + 2, NULL) || av_stristr(str, header); } -static int http_read_header(URLContext *h, int *new_location) +static int http_read_header(URLContext *h) { HTTPContext *s = h->priv_data; char line[MAX_URL_SIZE]; int err = 0; + av_freep(&s->new_location); + s->expires = 0; s->chunksize = UINT64_MAX; + s->filesize_from_content_range = UINT64_MAX; for (;;) { if ((err = http_get_line(s, line, sizeof(line))) < 0) @@ -1243,7 +1343,7 @@ static int http_read_header(URLContext *h, int *new_location) av_log(h, AV_LOG_TRACE, "header='%s'\n", line); - err = process_line(h, line, s->line_count, new_location); + err = process_line(h, line, s->line_count); if (err < 0) return err; if (err == 0) @@ -1251,6 +1351,10 @@ static int http_read_header(URLContext *h, int *new_location) s->line_count++; } + // filesize from Content-Range can always be used, even if using chunked Transfer-Encoding + if (s->filesize_from_content_range != UINT64_MAX) + s->filesize = s->filesize_from_content_range; + if (s->seekable == -1 && s->is_mediagateway && s->filesize == 2000000000) h->is_streamed = 1; /* we can in fact _not_ seek */ @@ -1294,7 +1398,7 @@ static void bprint_escaped_path(AVBPrint *bp, const char *path) 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) + const char *proxyauth) { HTTPContext *s = h->priv_data; int post, err; @@ -1358,10 +1462,10 @@ static int http_connect(URLContext *h, const char *path, const char *local_path, } if (!has_header(s->headers, "\r\nAccept: ")) av_bprintf(&request, "Accept: */*\r\n"); - // Note: we send this on purpose even when s->off is 0 when we're probing, + // Note: we send the Range header on purpose, even when we're probing, // since it allows us to detect more reliably if a (non-conforming) // server supports seeking by analysing the reply headers. - if (!has_header(s->headers, "\r\nRange: ") && !post && (s->off > 0 || s->end_off || s->seekable == -1)) { + if (!has_header(s->headers, "\r\nRange: ") && !post && (s->off > 0 || s->end_off || s->seekable != 0)) { av_bprintf(&request, "Range: bytes=%"PRIu64"-", s->off); if (s->end_off) av_bprintf(&request, "%"PRId64, s->end_off - 1); @@ -1438,11 +1542,11 @@ static int http_connect(URLContext *h, const char *path, const char *local_path, } /* wait for header */ - err = http_read_header(h, new_location); + err = http_read_header(h); if (err < 0) goto done; - if (*new_location) + if (s->new_location) s->off = off; err = (off == s->off) ? 0 : -1; @@ -1564,7 +1668,7 @@ static int64_t http_seek_internal(URLContext *h, int64_t off, int whence, int fo static int http_read_stream(URLContext *h, uint8_t *buf, int size) { HTTPContext *s = h->priv_data; - int err, new_location, read_ret; + int err, read_ret; int64_t seek_ret; int reconnect_delay = 0; @@ -1572,7 +1676,7 @@ static int http_read_stream(URLContext *h, uint8_t *buf, int size) return AVERROR_EOF; if (s->end_chunked_post && !s->end_header) { - err = http_read_header(h, &new_location); + err = http_read_header(h); if (err < 0) return err; } @@ -1785,6 +1889,8 @@ static int http_close(URLContext *h) ffurl_closep(&s->hd); av_dict_free(&s->chained_options); av_dict_free(&s->cookie_dict); + av_dict_free(&s->redirect_cache); + av_freep(&s->new_location); av_freep(&s->uri); return ret; } @@ -1827,8 +1933,8 @@ static int64_t http_seek_internal(URLContext *h, int64_t off, int whence, int fo return s->off; } - /* if redirect caching is disabled, revert to the original uri */ - if (!s->cache_redirect && strcmp(s->uri, s->location)) { + /* if the location changed (redirect), revert to the original uri */ + if (strcmp(s->uri, s->location)) { char *new_uri; new_uri = av_strdup(s->uri); if (!new_uri) @@ -1944,7 +2050,6 @@ static int http_proxy_open(URLContext *h, const char *uri, int flags) int port, ret = 0, attempts = 0; HTTPAuthType cur_auth_type; char *authstr; - int new_loc; if( s->seekable == 1 ) h->is_streamed = 0; @@ -1998,7 +2103,7 @@ redo: * since the client starts the conversation there, so there * is no extra data that we might buffer up here. */ - ret = http_read_header(h, &new_loc); + ret = http_read_header(h); if (ret < 0) goto fail; diff --git a/libavformat/http.h b/libavformat/http.h index 5557ce9b5..5f650ef14 100644 --- a/libavformat/http.h +++ b/libavformat/http.h @@ -37,15 +37,6 @@ */ void ff_http_init_auth_state(URLContext *dest, const URLContext *src); -/** - * Get the HTTP shutdown response status, be used after http_shutdown. - * - * @param h pointer to the resource - * @return a negative value if an error condition occurred, 0 - * otherwise - */ -int ff_http_get_shutdown_status(URLContext *h); - /** * Send a new HTTP request, reusing the old connection. * diff --git a/libavformat/icodec.c b/libavformat/icodec.c index 2e677c78f..290f658d0 100644 --- a/libavformat/icodec.c +++ b/libavformat/icodec.c @@ -26,7 +26,6 @@ #include "libavutil/intreadwrite.h" #include "libavcodec/bytestream.h" -#include "libavcodec/bmp.h" #include "libavcodec/png.h" #include "avformat.h" #include "internal.h" diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c index ff27c062e..191a305ff 100644 --- a/libavformat/id3v2.c +++ b/libavformat/id3v2.c @@ -38,7 +38,7 @@ #include "libavutil/intreadwrite.h" #include "libavcodec/png.h" #include "avio_internal.h" -#include "internal.h" +#include "demux.h" #include "id3v1.h" #include "id3v2.h" @@ -69,6 +69,7 @@ const AVMetadataConv ff_id3v2_4_metadata_conv[] = { { "TSOA", "album-sort" }, { "TSOP", "artist-sort" }, { "TSOT", "title-sort" }, + { "TIT1", "grouping" }, { 0 } }; diff --git a/libavformat/id3v2enc.c b/libavformat/id3v2enc.c index 5d821ea4d..515d2efd7 100644 --- a/libavformat/id3v2enc.c +++ b/libavformat/id3v2enc.c @@ -28,6 +28,7 @@ #include "avio.h" #include "avio_internal.h" #include "id3v2.h" +#include "mux.h" static void id3v2_put_size(AVIOContext *pb, int size) { diff --git a/libavformat/idcin.c b/libavformat/idcin.c index b7402107d..1560d58e3 100644 --- a/libavformat/idcin.c +++ b/libavformat/idcin.c @@ -72,6 +72,7 @@ #include "libavutil/imgutils.h" #include "libavutil/intreadwrite.h" #include "avformat.h" +#include "demux.h" #include "internal.h" #define HUFFMAN_TABLE_SIZE (64 * 1024) @@ -218,9 +219,7 @@ static int idcin_read_header(AVFormatContext *s) idcin->audio_stream_index = st->index; st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_tag = 1; - st->codecpar->channels = channels; - st->codecpar->channel_layout = channels > 1 ? AV_CH_LAYOUT_STEREO : - AV_CH_LAYOUT_MONO; + av_channel_layout_default(&st->codecpar->ch_layout, channels); st->codecpar->sample_rate = sample_rate; st->codecpar->bits_per_coded_sample = bytes_per_sample * 8; st->codecpar->bit_rate = sample_rate * bytes_per_sample * 8 * channels; diff --git a/libavformat/idroqdec.c b/libavformat/idroqdec.c index 0c8b7278e..c9fc97278 100644 --- a/libavformat/idroqdec.c +++ b/libavformat/idroqdec.c @@ -185,18 +185,16 @@ static int roq_read_packet(AVFormatContext *s, st->codecpar->codec_id = AV_CODEC_ID_ROQ_DPCM; st->codecpar->codec_tag = 0; /* no tag */ if (chunk_type == RoQ_SOUND_STEREO) { - st->codecpar->channels = 2; - st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; } else { - st->codecpar->channels = 1; - st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; } - roq->audio_channels = st->codecpar->channels; + roq->audio_channels = st->codecpar->ch_layout.nb_channels; st->codecpar->sample_rate = RoQ_AUDIO_SAMPLE_RATE; st->codecpar->bits_per_coded_sample = 16; - st->codecpar->bit_rate = st->codecpar->channels * st->codecpar->sample_rate * + st->codecpar->bit_rate = roq->audio_channels * st->codecpar->sample_rate * st->codecpar->bits_per_coded_sample; - st->codecpar->block_align = st->codecpar->channels * st->codecpar->bits_per_coded_sample; + st->codecpar->block_align = roq->audio_channels * st->codecpar->bits_per_coded_sample; } case RoQ_QUAD_VQ: if (chunk_type == RoQ_QUAD_VQ) { diff --git a/libavformat/iff.c b/libavformat/iff.c index 078406b7e..b37600605 100644 --- a/libavformat/iff.c +++ b/libavformat/iff.c @@ -183,20 +183,20 @@ static const uint32_t dsd_5point0[] = { DSD_MLFT, DSD_MRGT, DSD_C, DSD_LS, DSD_R static const uint32_t dsd_5point1[] = { DSD_MLFT, DSD_MRGT, DSD_C, DSD_LFE, DSD_LS, DSD_RS }; typedef struct { - uint64_t layout; + AVChannelLayout layout; const uint32_t * dsd_layout; } DSDLayoutDesc; static const DSDLayoutDesc dsd_channel_layout[] = { - { AV_CH_LAYOUT_STEREO, dsd_stereo }, - { AV_CH_LAYOUT_5POINT0, dsd_5point0 }, - { AV_CH_LAYOUT_5POINT1, dsd_5point1 }, + { AV_CHANNEL_LAYOUT_STEREO, dsd_stereo }, + { AV_CHANNEL_LAYOUT_5POINT0, dsd_5point0 }, + { AV_CHANNEL_LAYOUT_5POINT1, dsd_5point1 }, }; -static const uint64_t dsd_loudspeaker_config[] = { - AV_CH_LAYOUT_STEREO, - 0, 0, - AV_CH_LAYOUT_5POINT0, AV_CH_LAYOUT_5POINT1, +static const AVChannelLayout dsd_loudspeaker_config[] = { + AV_CHANNEL_LAYOUT_STEREO, + { 0 }, { 0 }, + AV_CHANNEL_LAYOUT_5POINT0, AV_CHANNEL_LAYOUT_5POINT1, }; static const char * dsd_source_comment[] = { @@ -276,21 +276,21 @@ static int parse_dsd_prop(AVFormatContext *s, AVStream *st, uint64_t eof) case MKTAG('C','H','N','L'): if (size < 2) return AVERROR_INVALIDDATA; - st->codecpar->channels = avio_rb16(pb); - if (size < 2 + st->codecpar->channels * 4) + st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + st->codecpar->ch_layout.nb_channels = avio_rb16(pb); + if (size < 2 + st->codecpar->ch_layout.nb_channels * 4) return AVERROR_INVALIDDATA; - st->codecpar->channel_layout = 0; - if (st->codecpar->channels > FF_ARRAY_ELEMS(dsd_layout)) { + if (st->codecpar->ch_layout.nb_channels > FF_ARRAY_ELEMS(dsd_layout)) { avpriv_request_sample(s, "channel layout"); break; } - for (i = 0; i < st->codecpar->channels; i++) + for (i = 0; i < st->codecpar->ch_layout.nb_channels; i++) dsd_layout[i] = avio_rl32(pb); for (i = 0; i < FF_ARRAY_ELEMS(dsd_channel_layout); i++) { const DSDLayoutDesc * d = &dsd_channel_layout[i]; - if (av_get_channel_layout_nb_channels(d->layout) == st->codecpar->channels && - !memcmp(d->dsd_layout, dsd_layout, st->codecpar->channels * sizeof(uint32_t))) { - st->codecpar->channel_layout = d->layout; + if (d->layout.nb_channels == st->codecpar->ch_layout.nb_channels && + !memcmp(d->dsd_layout, dsd_layout, d->layout.nb_channels * sizeof(uint32_t))) { + st->codecpar->ch_layout = d->layout; break; } } @@ -337,8 +337,8 @@ static int parse_dsd_prop(AVFormatContext *s, AVStream *st, uint64_t eof) config = avio_rb16(pb); if (config != 0xFFFF) { if (config < FF_ARRAY_ELEMS(dsd_loudspeaker_config)) - st->codecpar->channel_layout = dsd_loudspeaker_config[config]; - if (!st->codecpar->channel_layout) + st->codecpar->ch_layout = dsd_loudspeaker_config[config]; + if (!st->codecpar->ch_layout.nb_channels) avpriv_request_sample(s, "loudspeaker configuration %d", config); } break; @@ -384,7 +384,7 @@ static int read_dst_frame(AVFormatContext *s, AVPacket *pkt) avio_skip(pb, 1); pkt->flags |= AV_PKT_FLAG_KEY; pkt->stream_index = 0; - pkt->duration = 588LL * s->streams[0]->codecpar->sample_rate / 44100; + pkt->duration = s->streams[0]->codecpar->sample_rate / 75; pkt->pos = chunk_pos; chunk_pos = avio_tell(pb); @@ -397,7 +397,8 @@ static int read_dst_frame(AVFormatContext *s, AVPacket *pkt) case ID_FRTE: if (data_size < 4) return AVERROR_INVALIDDATA; - s->streams[0]->duration = avio_rb32(pb) * 588LL * s->streams[0]->codecpar->sample_rate / 44100; + s->streams[0]->duration = avio_rb32(pb) * (uint64_t)s->streams[0]->codecpar->sample_rate / 75; + break; } @@ -431,8 +432,7 @@ static int iff_read_header(AVFormatContext *s) if (!st) return AVERROR(ENOMEM); - st->codecpar->channels = 1; - st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; iff->is_64bit = avio_rl32(pb) == ID_FRM8; avio_skip(pb, iff->is_64bit ? 8 : 4); // codec_tag used by ByteRun1 decoder to distinguish progressive (PBM) and interlaced (ILBM) content @@ -485,12 +485,13 @@ static int iff_read_header(AVFormatContext *s) return AVERROR_INVALIDDATA; avio_skip(pb, 2); st->codecpar->sample_rate = num / den; - st->codecpar->channels = avio_rb16(pb); + st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + st->codecpar->ch_layout.nb_channels = avio_rb16(pb); iff->maud_compression = avio_rb16(pb); - if (st->codecpar->channels == 1) - st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; - else if (st->codecpar->channels == 2) - st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; + if (st->codecpar->ch_layout.nb_channels == 1) + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; + else if (st->codecpar->ch_layout.nb_channels == 2) + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; break; case ID_ABIT: @@ -513,11 +514,9 @@ static int iff_read_header(AVFormatContext *s) if (data_size < 4) return AVERROR_INVALIDDATA; if (avio_rb32(pb) < 6) { - st->codecpar->channels = 1; - st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; } else { - st->codecpar->channels = 2; - st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; } break; @@ -760,8 +759,11 @@ static int iff_read_header(AVFormatContext *s) } st->codecpar->bits_per_coded_sample = av_get_bits_per_sample(st->codecpar->codec_id); - st->codecpar->bit_rate = (int64_t)st->codecpar->channels * st->codecpar->sample_rate * st->codecpar->bits_per_coded_sample; - st->codecpar->block_align = st->codecpar->channels * st->codecpar->bits_per_coded_sample; + st->codecpar->bit_rate = (int64_t)st->codecpar->ch_layout.nb_channels * + st->codecpar->sample_rate * + st->codecpar->bits_per_coded_sample; + st->codecpar->block_align = st->codecpar->ch_layout.nb_channels * + st->codecpar->bits_per_coded_sample; if ((st->codecpar->codec_tag == ID_DSD || st->codecpar->codec_tag == ID_MAUD) && st->codecpar->block_align <= 0) return AVERROR_INVALIDDATA; break; diff --git a/libavformat/ifv.c b/libavformat/ifv.c index d38c3ef5a..490608c5d 100644 --- a/libavformat/ifv.c +++ b/libavformat/ifv.c @@ -155,8 +155,7 @@ static int ifv_read_header(AVFormatContext *s) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE; - st->codecpar->channels = 1; - st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; st->codecpar->sample_rate = ifv->sample_rate; ifv->audio_stream_index = st->index; diff --git a/libavformat/ilbc.c b/libavformat/ilbc.c index 0cbdd3d5b..26336ef2a 100644 --- a/libavformat/ilbc.c +++ b/libavformat/ilbc.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "avformat.h" #include "internal.h" #include "rawenc.h" @@ -75,7 +77,7 @@ static int ilbc_read_header(AVFormatContext *s) return AVERROR(ENOMEM); st->codecpar->codec_id = AV_CODEC_ID_ILBC; st->codecpar->sample_rate = 8000; - st->codecpar->channels = 1; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->start_time = 0; avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); diff --git a/libavformat/imf.h b/libavformat/imf.h index 62c4468ce..4271cd958 100644 --- a/libavformat/imf.h +++ b/libavformat/imf.h @@ -58,17 +58,9 @@ #include "avformat.h" #include "libavformat/avio.h" #include "libavutil/rational.h" +#include "libavutil/uuid.h" #include -#define FF_IMF_UUID_FORMAT \ - "urn:uuid:%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-" \ - "%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx" - -/** - * UUID as defined in IETF RFC 422 - */ -typedef uint8_t FFIMFUUID[16]; - /** * IMF Composition Playlist Base Resource */ @@ -84,7 +76,7 @@ typedef struct FFIMFBaseResource { */ typedef struct FFIMFTrackFileResource { FFIMFBaseResource base; - FFIMFUUID track_file_uuid; /**< TrackFileResourceType/TrackFileId */ + AVUUID track_file_uuid; /**< TrackFileResourceType/TrackFileId */ } FFIMFTrackFileResource; /** @@ -109,7 +101,7 @@ typedef struct FFIMFMarkerResource { * IMF Composition Playlist Virtual Track */ typedef struct FFIMFBaseVirtualTrack { - FFIMFUUID id_uuid; /**< TrackId associated with the Virtual Track */ + AVUUID id_uuid; /**< TrackId associated with the Virtual Track */ } FFIMFBaseVirtualTrack; /** @@ -135,7 +127,7 @@ typedef struct FFIMFMarkerVirtualTrack { * IMF Composition Playlist */ typedef struct FFIMFCPL { - FFIMFUUID id_uuid; /**< CompositionPlaylist/Id element */ + AVUUID id_uuid; /**< CompositionPlaylist/Id element */ xmlChar *content_title_utf8; /**< CompositionPlaylist/ContentTitle element */ AVRational edit_rate; /**< CompositionPlaylist/EditRate element */ FFIMFMarkerVirtualTrack *main_markers_track; /**< Main Marker Virtual Track */ @@ -196,7 +188,7 @@ int ff_imf_xml_read_rational(xmlNodePtr element, AVRational *rational); * Reads a UUID from an XML element * @return 0 on success, < 0 AVERROR code on error. */ -int ff_imf_xml_read_uuid(xmlNodePtr element, uint8_t uuid[16]); +int ff_imf_xml_read_uuid(xmlNodePtr element, AVUUID uuid); /** * Returns the first child element with the specified local name diff --git a/libavformat/imf_cpl.c b/libavformat/imf_cpl.c index 102a6b454..4acc20fee 100644 --- a/libavformat/imf_cpl.c +++ b/libavformat/imf_cpl.c @@ -70,32 +70,14 @@ xmlNodePtr ff_imf_xml_get_child_element_by_name(xmlNodePtr parent, const char *n return NULL; } -int ff_imf_xml_read_uuid(xmlNodePtr element, uint8_t uuid[16]) +int ff_imf_xml_read_uuid(xmlNodePtr element, AVUUID uuid) { xmlChar *element_text = NULL; - int scanf_ret; int ret = 0; element_text = xmlNodeListGetString(element->doc, element->xmlChildrenNode, 1); - scanf_ret = sscanf(element_text, - FF_IMF_UUID_FORMAT, - &uuid[0], - &uuid[1], - &uuid[2], - &uuid[3], - &uuid[4], - &uuid[5], - &uuid[6], - &uuid[7], - &uuid[8], - &uuid[9], - &uuid[10], - &uuid[11], - &uuid[12], - &uuid[13], - &uuid[14], - &uuid[15]); - if (scanf_ret != 16) { + ret = av_uuid_urn_parse(element_text, uuid); + if (ret) { av_log(NULL, AV_LOG_ERROR, "Invalid UUID\n"); ret = AVERROR_INVALIDDATA; } @@ -370,7 +352,7 @@ static int fill_marker_resource(xmlNodePtr marker_resource_elem, static int push_marker_sequence(xmlNodePtr marker_sequence_elem, FFIMFCPL *cpl) { int ret = 0; - uint8_t uuid[16]; + AVUUID uuid; xmlNodePtr resource_list_elem = NULL; xmlNodePtr resource_elem = NULL; xmlNodePtr track_id_elem = NULL; @@ -388,8 +370,8 @@ static int push_marker_sequence(xmlNodePtr marker_sequence_elem, FFIMFCPL *cpl) } av_log(NULL, AV_LOG_DEBUG, - "Processing IMF CPL Marker Sequence for Virtual Track " FF_IMF_UUID_FORMAT "\n", - UID_ARG(uuid)); + "Processing IMF CPL Marker Sequence for Virtual Track " AV_PRI_UUID "\n", + AV_UUID_ARG(uuid)); /* create main marker virtual track if it does not exist */ if (!cpl->main_markers_track) { @@ -397,9 +379,9 @@ static int push_marker_sequence(xmlNodePtr marker_sequence_elem, FFIMFCPL *cpl) if (!cpl->main_markers_track) return AVERROR(ENOMEM); imf_marker_virtual_track_init(cpl->main_markers_track); - memcpy(cpl->main_markers_track->base.id_uuid, uuid, sizeof(uuid)); + av_uuid_copy(cpl->main_markers_track->base.id_uuid, uuid); - } else if (memcmp(cpl->main_markers_track->base.id_uuid, uuid, sizeof(uuid)) != 0) { + } else if (!av_uuid_equal(cpl->main_markers_track->base.id_uuid, uuid)) { av_log(NULL, AV_LOG_ERROR, "Multiple marker virtual tracks were found\n"); return AVERROR_INVALIDDATA; } @@ -457,7 +439,7 @@ static int has_stereo_resources(xmlNodePtr element) static int push_main_audio_sequence(xmlNodePtr audio_sequence_elem, FFIMFCPL *cpl) { int ret = 0; - uint8_t uuid[16]; + AVUUID uuid; xmlNodePtr resource_list_elem = NULL; xmlNodePtr resource_elem = NULL; xmlNodePtr track_id_elem = NULL; @@ -476,12 +458,12 @@ static int push_main_audio_sequence(xmlNodePtr audio_sequence_elem, FFIMFCPL *cp } av_log(NULL, AV_LOG_DEBUG, - "Processing IMF CPL Audio Sequence for Virtual Track " FF_IMF_UUID_FORMAT "\n", - UID_ARG(uuid)); + "Processing IMF CPL Audio Sequence for Virtual Track " AV_PRI_UUID "\n", + AV_UUID_ARG(uuid)); /* get the main audio virtual track corresponding to the sequence */ for (uint32_t i = 0; i < cpl->main_audio_track_count; i++) { - if (memcmp(cpl->main_audio_tracks[i].base.id_uuid, uuid, sizeof(uuid)) == 0) { + if (av_uuid_equal(cpl->main_audio_tracks[i].base.id_uuid, uuid)) { vt = &cpl->main_audio_tracks[i]; break; } @@ -501,7 +483,7 @@ static int push_main_audio_sequence(xmlNodePtr audio_sequence_elem, FFIMFCPL *cp vt = &cpl->main_audio_tracks[cpl->main_audio_track_count]; imf_trackfile_virtual_track_init(vt); cpl->main_audio_track_count++; - memcpy(vt->base.id_uuid, uuid, sizeof(uuid)); + av_uuid_copy(vt->base.id_uuid, uuid); } /* process resources */ @@ -544,7 +526,7 @@ static int push_main_audio_sequence(xmlNodePtr audio_sequence_elem, FFIMFCPL *cp static int push_main_image_2d_sequence(xmlNodePtr image_sequence_elem, FFIMFCPL *cpl) { int ret = 0; - uint8_t uuid[16]; + AVUUID uuid; xmlNodePtr resource_list_elem = NULL; xmlNodePtr resource_elem = NULL; xmlNodePtr track_id_elem = NULL; @@ -573,16 +555,16 @@ static int push_main_image_2d_sequence(xmlNodePtr image_sequence_elem, FFIMFCPL if (!cpl->main_image_2d_track) return AVERROR(ENOMEM); imf_trackfile_virtual_track_init(cpl->main_image_2d_track); - memcpy(cpl->main_image_2d_track->base.id_uuid, uuid, sizeof(uuid)); + av_uuid_copy(cpl->main_image_2d_track->base.id_uuid, uuid); - } else if (memcmp(cpl->main_image_2d_track->base.id_uuid, uuid, sizeof(uuid)) != 0) { + } else if (!av_uuid_equal(cpl->main_image_2d_track->base.id_uuid, uuid)) { av_log(NULL, AV_LOG_ERROR, "Multiple MainImage virtual tracks found\n"); return AVERROR_INVALIDDATA; } av_log(NULL, AV_LOG_DEBUG, - "Processing IMF CPL Main Image Sequence for Virtual Track " FF_IMF_UUID_FORMAT "\n", - UID_ARG(uuid)); + "Processing IMF CPL Main Image Sequence for Virtual Track " AV_PRI_UUID "\n", + AV_UUID_ARG(uuid)); /* process resources */ resource_list_elem = ff_imf_xml_get_child_element_by_name(image_sequence_elem, "ResourceList"); @@ -746,7 +728,7 @@ static void imf_trackfile_virtual_track_free(FFIMFTrackFileVirtualTrack *vt) static void imf_cpl_init(FFIMFCPL *cpl) { - memset(cpl->id_uuid, 0, sizeof(cpl->id_uuid)); + av_uuid_nil(cpl->id_uuid); cpl->content_title_utf8 = NULL; cpl->edit_rate = av_make_q(0, 1); cpl->main_markers_track = NULL; @@ -828,8 +810,8 @@ int ff_imf_parse_cpl(AVIOContext *in, FFIMFCPL **cpl) (*cpl)->content_title_utf8); av_log(NULL, AV_LOG_INFO, - "IMF CPL Id: " FF_IMF_UUID_FORMAT "\n", - UID_ARG((*cpl)->id_uuid)); + "IMF CPL Id: " AV_PRI_UUID "\n", + AV_UUID_ARG((*cpl)->id_uuid)); } xmlFreeDoc(doc); diff --git a/libavformat/imfdec.c b/libavformat/imfdec.c index bd1135e2e..71dfb2695 100644 --- a/libavformat/imfdec.c +++ b/libavformat/imfdec.c @@ -63,6 +63,7 @@ */ #include "avio_internal.h" +#include "demux.h" #include "imf.h" #include "internal.h" #include "libavcodec/packet.h" @@ -71,7 +72,6 @@ #include "libavutil/intreadwrite.h" #include "libavutil/opt.h" #include "mxf.h" -#include "url.h" #include #include @@ -82,7 +82,7 @@ * IMF Asset locator */ typedef struct IMFAssetLocator { - FFIMFUUID uuid; + AVUUID uuid; char *absolute_uri; } IMFAssetLocator; @@ -96,12 +96,12 @@ typedef struct IMFAssetLocatorMap { } IMFAssetLocatorMap; typedef struct IMFVirtualTrackResourcePlaybackCtx { - IMFAssetLocator *locator; - FFIMFTrackFileResource *resource; - AVFormatContext *ctx; - AVRational start_time; - AVRational end_time; - AVRational ts_offset; + IMFAssetLocator *locator; /**< Location of the resource */ + FFIMFTrackFileResource *resource; /**< Underlying IMF CPL resource */ + AVFormatContext *ctx; /**< Context associated with the resource */ + AVRational start_time; /**< inclusive start time of the resource on the CPL timeline (s) */ + AVRational end_time; /**< exclusive end time of the resource on the CPL timeline (s) */ + AVRational ts_offset; /**< start_time minus the entry point into the resource (s) */ } IMFVirtualTrackResourcePlaybackCtx; typedef struct IMFVirtualTrackPlaybackCtx { @@ -154,6 +154,25 @@ static int imf_uri_is_dos_abs_path(const char *string) return 0; } +static int imf_time_to_ts(int64_t *ts, AVRational t, AVRational time_base) +{ + int dst_num; + int dst_den; + AVRational r; + + r = av_div_q(t, time_base); + + if ((av_reduce(&dst_num, &dst_den, r.num, r.den, INT64_MAX) != 1)) + return 1; + + if (dst_den != 1) + return 1; + + *ts = dst_num; + + return 0; +} + /** * Parse a ASSETMAP XML file to extract the UUID-URI mapping of assets. * @param s the current format context, if any (can be NULL). @@ -184,11 +203,8 @@ static int parse_imf_asset_map_from_xml_dom(AVFormatContext *s, } if (asset_map_element->type != XML_ELEMENT_NODE || av_strcasecmp(asset_map_element->name, "AssetMap")) { - av_log(s, - AV_LOG_ERROR, - "Unable to parse asset map XML - wrong root node name[%s] type[%d]\n", - asset_map_element->name, - (int)asset_map_element->type); + av_log(s, AV_LOG_ERROR, "Unable to parse asset map XML - wrong root node name[%s] type[%d]\n", + asset_map_element->name, (int)asset_map_element->type); return AVERROR_INVALIDDATA; } @@ -222,7 +238,7 @@ static int parse_imf_asset_map_from_xml_dom(AVFormatContext *s, return AVERROR_INVALIDDATA; } - av_log(s, AV_LOG_DEBUG, "Found asset id: " FF_IMF_UUID_FORMAT "\n", UID_ARG(asset->uuid)); + av_log(s, AV_LOG_DEBUG, "Found asset id: " AV_PRI_URN_UUID "\n", AV_UUID_ARG(asset->uuid)); if (!(node = ff_imf_xml_get_child_element_by_name(asset_element, "ChunkList"))) { av_log(s, AV_LOG_ERROR, "Unable to parse asset map XML - missing ChunkList node\n"); @@ -314,11 +330,8 @@ static int parse_assetmap(AVFormatContext *s, const char *url) ret = parse_imf_asset_map_from_xml_dom(s, doc, &c->asset_locator_map, base_url); if (!ret) - av_log(s, - AV_LOG_DEBUG, - "Found %d assets from %s\n", - c->asset_locator_map.asset_count, - url); + av_log(s, AV_LOG_DEBUG, "Found %d assets from %s\n", + c->asset_locator_map.asset_count, url); xmlFreeDoc(doc); @@ -330,7 +343,7 @@ clean_up: return ret; } -static IMFAssetLocator *find_asset_map_locator(IMFAssetLocatorMap *asset_map, FFIMFUUID uuid) +static IMFAssetLocator *find_asset_map_locator(IMFAssetLocatorMap *asset_map, AVUUID uuid) { for (uint32_t i = 0; i < asset_map->asset_count; i++) { if (memcmp(asset_map->assets[i].uuid, uuid, 16) == 0) @@ -340,18 +353,18 @@ static IMFAssetLocator *find_asset_map_locator(IMFAssetLocatorMap *asset_map, FF } static int open_track_resource_context(AVFormatContext *s, - IMFVirtualTrackResourcePlaybackCtx *track_resource) + IMFVirtualTrackPlaybackCtx *track, + int32_t resource_index) { IMFContext *c = s->priv_data; int ret = 0; - int64_t entry_point; + int64_t seek_offset = 0; AVDictionary *opts = NULL; AVStream *st; + IMFVirtualTrackResourcePlaybackCtx *track_resource = track->resources + resource_index; if (track_resource->ctx) { - av_log(s, - AV_LOG_DEBUG, - "Input context already opened for %s.\n", + av_log(s, AV_LOG_DEBUG, "Input context already opened for %s.\n", track_resource->locator->absolute_uri); return 0; } @@ -379,11 +392,8 @@ static int open_track_resource_context(AVFormatContext *s, NULL, &opts); if (ret < 0) { - av_log(s, - AV_LOG_ERROR, - "Could not open %s input context: %s\n", - track_resource->locator->absolute_uri, - av_err2str(ret)); + av_log(s, AV_LOG_ERROR, "Could not open %s input context: %s\n", + track_resource->locator->absolute_uri, av_err2str(ret)); goto cleanup; } av_dict_free(&opts); @@ -397,32 +407,26 @@ static int open_track_resource_context(AVFormatContext *s, st = track_resource->ctx->streams[0]; - /* Warn if the resource time base does not match the file time base */ - if (av_cmp_q(st->time_base, av_inv_q(track_resource->resource->base.edit_rate))) - av_log(s, - AV_LOG_WARNING, - "Incoherent source stream timebase " AVRATIONAL_FORMAT - "regarding resource edit rate: " AVRATIONAL_FORMAT, - st->time_base.num, - st->time_base.den, - track_resource->resource->base.edit_rate.den, - track_resource->resource->base.edit_rate.num); + /* Determine the seek offset into the Track File, taking into account: + * - the current timestamp within the virtual track + * - the entry point of the resource + */ + if (imf_time_to_ts(&seek_offset, + av_sub_q(track->current_timestamp, track_resource->ts_offset), + st->time_base)) + av_log(s, AV_LOG_WARNING, "Incoherent stream timebase " AVRATIONAL_FORMAT + "and composition timeline position: " AVRATIONAL_FORMAT "\n", + AVRATIONAL_ARG(st->time_base), AVRATIONAL_ARG(track->current_timestamp)); - entry_point = av_rescale_q(track_resource->resource->base.entry_point, st->time_base, - av_inv_q(track_resource->resource->base.edit_rate)); - - if (entry_point) { - av_log(s, - AV_LOG_DEBUG, - "Seek at resource %s entry point: %" PRIu32 "\n", - track_resource->locator->absolute_uri, - track_resource->resource->base.entry_point); - ret = avformat_seek_file(track_resource->ctx, 0, entry_point, entry_point, entry_point, 0); + if (seek_offset) { + av_log(s, AV_LOG_DEBUG, "Seek at resource %s entry point: %" PRIi64 "\n", + track_resource->locator->absolute_uri, seek_offset); + ret = avformat_seek_file(track_resource->ctx, 0, seek_offset, seek_offset, seek_offset, 0); if (ret < 0) { av_log(s, AV_LOG_ERROR, "Could not seek at %" PRId64 "on %s: %s\n", - entry_point, + seek_offset, track_resource->locator->absolute_uri, av_err2str(ret)); avformat_close_input(&track_resource->ctx); @@ -449,17 +453,15 @@ static int open_track_file_resource(AVFormatContext *s, asset_locator = find_asset_map_locator(&c->asset_locator_map, track_file_resource->track_file_uuid); if (!asset_locator) { - av_log(s, - AV_LOG_ERROR, - "Could not find asset locator for UUID: " FF_IMF_UUID_FORMAT "\n", - UID_ARG(track_file_resource->track_file_uuid)); + av_log(s, AV_LOG_ERROR, "Could not find asset locator for UUID: " AV_PRI_URN_UUID "\n", + AV_UUID_ARG(track_file_resource->track_file_uuid)); return AVERROR_INVALIDDATA; } av_log(s, AV_LOG_DEBUG, - "Found locator for " FF_IMF_UUID_FORMAT ": %s\n", - UID_ARG(asset_locator->uuid), + "Found locator for " AV_PRI_URN_UUID ": %s\n", + AV_UUID_ARG(asset_locator->uuid), asset_locator->absolute_uri); if (track->resource_count > INT32_MAX - track_file_resource->base.repeat_count @@ -521,14 +523,14 @@ static int open_virtual_track(AVFormatContext *s, for (uint32_t i = 0; i < virtual_track->resource_count; i++) { av_log(s, AV_LOG_DEBUG, - "Open stream from file " FF_IMF_UUID_FORMAT ", stream %d\n", - UID_ARG(virtual_track->resources[i].track_file_uuid), + "Open stream from file " AV_PRI_URN_UUID ", stream %d\n", + AV_UUID_ARG(virtual_track->resources[i].track_file_uuid), i); if ((ret = open_track_file_resource(s, &virtual_track->resources[i], track)) != 0) { av_log(s, AV_LOG_ERROR, - "Could not open image track resource " FF_IMF_UUID_FORMAT "\n", - UID_ARG(virtual_track->resources[i].track_file_uuid)); + "Could not open image track resource " AV_PRI_URN_UUID "\n", + AV_UUID_ARG(virtual_track->resources[i].track_file_uuid)); goto clean_up; } } @@ -565,7 +567,7 @@ static int set_context_streams_from_tracks(AVFormatContext *s) AVStream *first_resource_stream; /* Open the first resource of the track to get stream information */ - ret = open_track_resource_context(s, &c->tracks[i]->resources[0]); + ret = open_track_resource_context(s, c->tracks[i], 0); if (ret) return ret; first_resource_stream = c->tracks[i]->resources[0].ctx->streams[0]; @@ -602,20 +604,16 @@ static int open_cpl_tracks(AVFormatContext *s) if (c->cpl->main_image_2d_track) { if ((ret = open_virtual_track(s, c->cpl->main_image_2d_track, track_index++)) != 0) { - av_log(s, - AV_LOG_ERROR, - "Could not open image track " FF_IMF_UUID_FORMAT "\n", - UID_ARG(c->cpl->main_image_2d_track->base.id_uuid)); + av_log(s, AV_LOG_ERROR, "Could not open image track " AV_PRI_URN_UUID "\n", + AV_UUID_ARG(c->cpl->main_image_2d_track->base.id_uuid)); return ret; } } for (uint32_t i = 0; i < c->cpl->main_audio_track_count; i++) { if ((ret = open_virtual_track(s, &c->cpl->main_audio_tracks[i], track_index++)) != 0) { - av_log(s, - AV_LOG_ERROR, - "Could not open audio track " FF_IMF_UUID_FORMAT "\n", - UID_ARG(c->cpl->main_audio_tracks[i].base.id_uuid)); + av_log(s, AV_LOG_ERROR, "Could not open audio track " AV_PRI_URN_UUID "\n", + AV_UUID_ARG(c->cpl->main_audio_tracks[i].base.id_uuid)); return ret; } } @@ -649,8 +647,8 @@ static int imf_read_header(AVFormatContext *s) av_log(s, AV_LOG_DEBUG, - "parsed IMF CPL: " FF_IMF_UUID_FORMAT "\n", - UID_ARG(c->cpl->id_uuid)); + "parsed IMF CPL: " AV_PRI_URN_UUID "\n", + AV_UUID_ARG(c->cpl->id_uuid)); if (!c->asset_map_paths) { c->asset_map_paths = av_append_path_component(c->base_url, "ASSETMAP.xml"); @@ -690,13 +688,9 @@ static IMFVirtualTrackPlaybackCtx *get_next_track_with_minimum_timestamp(AVForma AVRational minimum_timestamp = av_make_q(INT32_MAX, 1); for (uint32_t i = c->track_count; i > 0; i--) { - av_log(s, - AV_LOG_DEBUG, - "Compare track %d timestamp " AVRATIONAL_FORMAT + av_log(s, AV_LOG_TRACE, "Compare track %d timestamp " AVRATIONAL_FORMAT " to minimum " AVRATIONAL_FORMAT - " (over duration: " AVRATIONAL_FORMAT - ")\n", - i, + " (over duration: " AVRATIONAL_FORMAT ")\n", i, AVRATIONAL_ARG(c->tracks[i - 1]->current_timestamp), AVRATIONAL_ARG(minimum_timestamp), AVRATIONAL_ARG(c->tracks[i - 1]->duration)); @@ -707,12 +701,8 @@ static IMFVirtualTrackPlaybackCtx *get_next_track_with_minimum_timestamp(AVForma } } - av_log(s, - AV_LOG_DEBUG, - "Found next track to read: %d (timestamp: %lf / %lf)\n", - track->index, - av_q2d(track->current_timestamp), - av_q2d(minimum_timestamp)); + av_log(s, AV_LOG_DEBUG, "Found next track to read: %d (timestamp: %lf / %lf)\n", + track->index, av_q2d(track->current_timestamp), av_q2d(minimum_timestamp)); return track; } @@ -726,7 +716,7 @@ static int get_resource_context_for_timestamp(AVFormatContext *s, IMFVirtualTrac } av_log(s, - AV_LOG_DEBUG, + AV_LOG_TRACE, "Looking for track %d resource for timestamp = %lf / %lf\n", track->index, av_q2d(track->current_timestamp), @@ -734,15 +724,9 @@ static int get_resource_context_for_timestamp(AVFormatContext *s, IMFVirtualTrac for (uint32_t i = 0; i < track->resource_count; i++) { if (av_cmp_q(track->resources[i].end_time, track->current_timestamp) > 0) { - av_log(s, - AV_LOG_DEBUG, - "Found resource %d in track %d to read at timestamp %lf: " - "entry=%" PRIu32 - ", duration=%" PRIu32 - ", editrate=" AVRATIONAL_FORMAT, - i, - track->index, - av_q2d(track->current_timestamp), + av_log(s, AV_LOG_DEBUG, "Found resource %d in track %d to read at timestamp %lf: " + "entry=%" PRIu32 ", duration=%" PRIu32 ", editrate=" AVRATIONAL_FORMAT "\n", + i, track->index, av_q2d(track->current_timestamp), track->resources[i].resource->base.entry_point, track->resources[i].resource->base.duration, AVRATIONAL_ARG(track->resources[i].resource->base.edit_rate)); @@ -750,12 +734,10 @@ static int get_resource_context_for_timestamp(AVFormatContext *s, IMFVirtualTrac if (track->current_resource_index != i) { int ret; - av_log(s, - AV_LOG_DEBUG, - "Switch resource on track %d: re-open context\n", + av_log(s, AV_LOG_TRACE, "Switch resource on track %d: re-open context\n", track->index); - ret = open_track_resource_context(s, track->resources + i); + ret = open_track_resource_context(s, track, i); if (ret != 0) return ret; if (track->current_resource_index > 0) @@ -772,25 +754,6 @@ static int get_resource_context_for_timestamp(AVFormatContext *s, IMFVirtualTrac return AVERROR_STREAM_NOT_FOUND; } -static int imf_time_to_ts(int64_t *ts, AVRational t, AVRational time_base) -{ - int dst_num; - int dst_den; - AVRational r; - - r = av_div_q(t, time_base); - - if ((av_reduce(&dst_num, &dst_den, r.num, r.den, INT64_MAX) != 1)) - return 1; - - if (dst_den != 1) - return 1; - - *ts = dst_num; - - return 0; -} - static int imf_read_packet(AVFormatContext *s, AVPacket *pkt) { IMFVirtualTrackResourcePlaybackCtx *resource = NULL; @@ -807,15 +770,13 @@ static int imf_read_packet(AVFormatContext *s, AVPacket *pkt) return ret; ret = av_read_frame(resource->ctx, pkt); - if (ret) { - av_log(s, AV_LOG_ERROR, "Failed to read frame\n"); + if (ret) return ret; - } av_log(s, AV_LOG_DEBUG, "Got packet: pts=%" PRId64 ", dts=%" PRId64 ", duration=%" PRId64 ", stream_index=%d, pos=%" PRId64 ", time_base=" AVRATIONAL_FORMAT "\n", pkt->pts, pkt->dts, pkt->duration, - pkt->stream_index, pkt->pos, pkt->time_base.num, pkt->time_base.den); + pkt->stream_index, pkt->pos, AVRATIONAL_ARG(pkt->time_base)); /* IMF resources contain only one stream */ @@ -835,9 +796,10 @@ static int imf_read_packet(AVFormatContext *s, AVPacket *pkt) if (pkt->dts != AV_NOPTS_VALUE) pkt->dts += delta_ts; } else { - av_log(s, AV_LOG_WARNING, "Incoherent time stamp " AVRATIONAL_FORMAT " for time base " AVRATIONAL_FORMAT, - resource->ts_offset.num, resource->ts_offset.den, pkt->time_base.num, - pkt->time_base.den); + av_log(s, AV_LOG_WARNING, "Incoherent time stamp " AVRATIONAL_FORMAT + " for time base " AVRATIONAL_FORMAT, + AVRATIONAL_ARG(resource->ts_offset), + AVRATIONAL_ARG(pkt->time_base)); } /* advance the track timestamp by the packet duration */ @@ -860,7 +822,7 @@ static int imf_read_packet(AVFormatContext *s, AVPacket *pkt) if (!ret) pkt->duration = new_pkt_dur; else - av_log(s, AV_LOG_WARNING, "Incoherent time base in packet duration calculation"); + av_log(s, AV_LOG_WARNING, "Incoherent time base in packet duration calculation\n"); /* shrink the packet itself for audio essence */ @@ -874,7 +836,7 @@ static int imf_read_packet(AVFormatContext *s, AVPacket *pkt) int64_t nbsamples = av_rescale_q(pkt->duration, st->time_base, av_make_q(1, st->codecpar->sample_rate)); - av_shrink_packet(pkt, nbsamples * st->codecpar->channels * bytes_per_sample); + av_shrink_packet(pkt, nbsamples * st->codecpar->ch_layout.nb_channels * bytes_per_sample); } else { /* in all other cases, use side data to skip samples */ @@ -885,7 +847,7 @@ static int imf_read_packet(AVFormatContext *s, AVPacket *pkt) av_make_q(1, st->codecpar->sample_rate)); if (ret || skip_samples < 0 || skip_samples > UINT32_MAX) { - av_log(s, AV_LOG_WARNING, "Cannot skip audio samples"); + av_log(s, AV_LOG_WARNING, "Cannot skip audio samples\n"); } else { uint8_t *side_data = av_packet_new_side_data(pkt, AV_PKT_DATA_SKIP_SAMPLES, 10); if (!side_data) @@ -899,7 +861,7 @@ static int imf_read_packet(AVFormatContext *s, AVPacket *pkt) next_timestamp = resource->end_time; } else { - av_log(s, AV_LOG_WARNING, "Non-audio packet duration reduced"); + av_log(s, AV_LOG_WARNING, "Non-audio packet duration reduced\n"); } } @@ -942,6 +904,75 @@ static int imf_probe(const AVProbeData *p) return AVPROBE_SCORE_MAX; } +static int coherent_ts(int64_t ts, AVRational in_tb, AVRational out_tb) +{ + int dst_num; + int dst_den; + int ret; + + ret = av_reduce(&dst_num, &dst_den, ts * in_tb.num * out_tb.den, + in_tb.den * out_tb.num, INT64_MAX); + if (!ret || dst_den != 1) + return 0; + + return 1; +} + +static int imf_seek(AVFormatContext *s, int stream_index, int64_t min_ts, + int64_t ts, int64_t max_ts, int flags) +{ + IMFContext *c = s->priv_data; + uint32_t i; + + if (flags & (AVSEEK_FLAG_BYTE | AVSEEK_FLAG_FRAME)) + return AVERROR(ENOSYS); + + /* rescale timestamps to Composition edit units */ + if (stream_index < 0) + ff_rescale_interval(AV_TIME_BASE_Q, + av_make_q(c->cpl->edit_rate.den, c->cpl->edit_rate.num), + &min_ts, &ts, &max_ts); + else + ff_rescale_interval(s->streams[stream_index]->time_base, + av_make_q(c->cpl->edit_rate.den, c->cpl->edit_rate.num), + &min_ts, &ts, &max_ts); + + /* requested timestamp bounds are too close */ + if (max_ts < min_ts) + return -1; + + /* clamp requested timestamp to provided bounds */ + ts = FFMAX(FFMIN(ts, max_ts), min_ts); + + av_log(s, AV_LOG_DEBUG, "Seeking to Composition Playlist edit unit %" PRIi64 "\n", ts); + + /* set the dts of each stream and temporal offset of each track */ + for (i = 0; i < c->track_count; i++) { + AVStream *st = s->streams[i]; + IMFVirtualTrackPlaybackCtx *t = c->tracks[i]; + int64_t dts; + + if (!coherent_ts(ts, av_make_q(c->cpl->edit_rate.den, c->cpl->edit_rate.num), + st->time_base)) + av_log(s, AV_LOG_WARNING, "Seek position is not coherent across tracks\n"); + + dts = av_rescale(ts, + st->time_base.den * c->cpl->edit_rate.den, + st->time_base.num * c->cpl->edit_rate.num); + + av_log(s, AV_LOG_DEBUG, "Seeking to dts=%" PRId64 " on stream_index=%d\n", + dts, i); + + t->current_timestamp = av_mul_q(av_make_q(dts, 1), st->time_base); + if (t->current_resource_index >= 0) { + avformat_close_input(&t->resources[t->current_resource_index].ctx); + t->current_resource_index = -1; + } + } + + return 0; +} + static const AVOption imf_options[] = { { .name = "assetmaps", @@ -966,7 +997,7 @@ static const AVClass imf_class = { const AVInputFormat ff_imf_demuxer = { .name = "imf", .long_name = NULL_IF_CONFIG_SMALL("IMF (Interoperable Master Format)"), - .flags = AVFMT_EXPERIMENTAL, + .flags = AVFMT_EXPERIMENTAL | AVFMT_NO_BYTE_SEEK, .flags_internal = FF_FMT_INIT_CLEANUP, .priv_class = &imf_class, .priv_data_size = sizeof(IMFContext), @@ -974,4 +1005,5 @@ const AVInputFormat ff_imf_demuxer = { .read_header = imf_read_header, .read_packet = imf_read_packet, .read_close = imf_close, + .read_seek2 = imf_seek, }; diff --git a/libavformat/img2.c b/libavformat/img2.c index 4153102c9..870d2ebbc 100644 --- a/libavformat/img2.c +++ b/libavformat/img2.c @@ -41,6 +41,7 @@ const IdStrMap ff_img_tags[] = { { AV_CODEC_ID_PBM, "pbm" }, { AV_CODEC_ID_PAM, "pam" }, { AV_CODEC_ID_PFM, "pfm" }, + { AV_CODEC_ID_PHM, "phm" }, { AV_CODEC_ID_CRI, "cri" }, { AV_CODEC_ID_ALIAS_PIX, "pix" }, { AV_CODEC_ID_DDS, "dds" }, @@ -87,6 +88,9 @@ const IdStrMap ff_img_tags[] = { { AV_CODEC_ID_GEM, "img" }, { AV_CODEC_ID_GEM, "ximg" }, { AV_CODEC_ID_GEM, "timg" }, + { AV_CODEC_ID_VBN, "vbn" }, + { AV_CODEC_ID_JPEGXL, "jxl" }, + { AV_CODEC_ID_QOI, "qoi" }, { AV_CODEC_ID_NONE, NULL } }; diff --git a/libavformat/img2dec.c b/libavformat/img2dec.c index a6084ceef..e7ff26e5d 100644 --- a/libavformat/img2dec.c +++ b/libavformat/img2dec.c @@ -20,6 +20,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #define _DEFAULT_SOURCE #define _BSD_SOURCE #include @@ -34,7 +36,9 @@ #include "avio_internal.h" #include "internal.h" #include "img2.h" +#include "jpegxl_probe.h" #include "libavcodec/mjpeg.h" +#include "libavcodec/vbn.h" #include "libavcodec/xwd.h" #include "subtitles.h" @@ -834,6 +838,24 @@ static int jpegls_probe(const AVProbeData *p) return 0; } +static int jpegxl_probe(const AVProbeData *p) +{ + const uint8_t *b = p->buf; + + /* ISOBMFF-based container */ + /* 0x4a584c20 == "JXL " */ + if (AV_RL64(b) == FF_JPEGXL_CONTAINER_SIGNATURE_LE) + return AVPROBE_SCORE_EXTENSION + 1; + /* Raw codestreams all start with 0xff0a */ + if (AV_RL16(b) != FF_JPEGXL_CODESTREAM_SIGNATURE_LE) + return 0; +#if CONFIG_IMAGE_JPEGXL_PIPE_DEMUXER + if (ff_jpegxl_verify_codestream_header(p->buf, p->buf_size) >= 0) + return AVPROBE_SCORE_MAX - 2; +#endif + return 0; +} + static int pcx_probe(const AVProbeData *p) { const uint8_t *b = p->buf; @@ -998,7 +1020,19 @@ static inline int pnm_probe(const AVProbeData *p) static int pbm_probe(const AVProbeData *p) { - return pnm_magic_check(p, 1) || pnm_magic_check(p, 4) || pnm_magic_check(p, 22) || pnm_magic_check(p, 54) ? pnm_probe(p) : 0; + return pnm_magic_check(p, 1) || pnm_magic_check(p, 4) ? pnm_probe(p) : 0; +} + +static int pfm_probe(const AVProbeData *p) +{ + return pnm_magic_check(p, 'F' - '0') || + pnm_magic_check(p, 'f' - '0') ? pnm_probe(p) : 0; +} + +static int phm_probe(const AVProbeData *p) +{ + return pnm_magic_check(p, 'H' - '0') || + pnm_magic_check(p, 'h' - '0') ? pnm_probe(p) : 0; } static inline int pgmx_probe(const AVProbeData *p) @@ -1109,28 +1143,55 @@ static int photocd_probe(const AVProbeData *p) return AVPROBE_SCORE_MAX - 1; } +static int qoi_probe(const AVProbeData *p) +{ + if (memcmp(p->buf, "qoif", 4)) + return 0; + + if (AV_RB32(p->buf + 4) == 0 || AV_RB32(p->buf + 8) == 0) + return 0; + + if (p->buf[12] != 3 && p->buf[12] != 4) + return 0; + + if (p->buf[13] > 1) + return 0; + + return AVPROBE_SCORE_MAX - 1; +} + static int gem_probe(const AVProbeData *p) { const uint8_t *b = p->buf; - int ret = 0; if ( AV_RB16(b ) >= 1 && AV_RB16(b ) <= 3 && AV_RB16(b + 2) >= 8 && AV_RB16(b + 2) <= 779 && - (AV_RB16(b + 4) > 0 || AV_RB16(b + 4) <= 8) && - (AV_RB16(b + 6) > 0 || AV_RB16(b + 6) <= 8) && + (AV_RB16(b + 4) > 0 && AV_RB16(b + 4) <= 32) && /* planes */ + (AV_RB16(b + 6) > 0 && AV_RB16(b + 6) <= 8) && /* pattern_size */ AV_RB16(b + 8) && AV_RB16(b + 10) && AV_RB16(b + 12) && AV_RB16(b + 14)) { - ret = AVPROBE_SCORE_EXTENSION / 4; if (AV_RN32(b + 16) == AV_RN32("STTT") || AV_RN32(b + 16) == AV_RN32("TIMG") || AV_RN32(b + 16) == AV_RN32("XIMG")) - ret += 1; + return AVPROBE_SCORE_EXTENSION + 1; + return AVPROBE_SCORE_EXTENSION / 4; } - return ret; + return 0; } -#define IMAGEAUTO_DEMUXER(imgname, codecid)\ +static int vbn_probe(const AVProbeData *p) +{ + const uint8_t *b = p->buf; + if (AV_RL32(b ) == VBN_MAGIC && + AV_RL32(b + 4) == VBN_MAJOR && + AV_RL32(b + 8) == VBN_MINOR) + return AVPROBE_SCORE_MAX - 1; + return 0; +} + +#define IMAGEAUTO_DEMUXER_0(imgname, codecid) +#define IMAGEAUTO_DEMUXER_1(imgname, codecid)\ const AVInputFormat ff_image_ ## imgname ## _pipe_demuxer = {\ .name = AV_STRINGIFY(imgname) "_pipe",\ .long_name = NULL_IF_CONFIG_SMALL("piped " AV_STRINGIFY(imgname) " sequence"),\ @@ -1143,33 +1204,48 @@ const AVInputFormat ff_image_ ## imgname ## _pipe_demuxer = {\ .raw_codec_id = codecid,\ }; -IMAGEAUTO_DEMUXER(bmp, AV_CODEC_ID_BMP) -IMAGEAUTO_DEMUXER(cri, AV_CODEC_ID_CRI) -IMAGEAUTO_DEMUXER(dds, AV_CODEC_ID_DDS) -IMAGEAUTO_DEMUXER(dpx, AV_CODEC_ID_DPX) -IMAGEAUTO_DEMUXER(exr, AV_CODEC_ID_EXR) -IMAGEAUTO_DEMUXER(gem, AV_CODEC_ID_GEM) -IMAGEAUTO_DEMUXER(gif, AV_CODEC_ID_GIF) -IMAGEAUTO_DEMUXER(j2k, AV_CODEC_ID_JPEG2000) -IMAGEAUTO_DEMUXER(jpeg, AV_CODEC_ID_MJPEG) -IMAGEAUTO_DEMUXER(jpegls, AV_CODEC_ID_JPEGLS) -IMAGEAUTO_DEMUXER(pam, AV_CODEC_ID_PAM) -IMAGEAUTO_DEMUXER(pbm, AV_CODEC_ID_PBM) -IMAGEAUTO_DEMUXER(pcx, AV_CODEC_ID_PCX) -IMAGEAUTO_DEMUXER(pgm, AV_CODEC_ID_PGM) -IMAGEAUTO_DEMUXER(pgmyuv, AV_CODEC_ID_PGMYUV) -IMAGEAUTO_DEMUXER(pgx, AV_CODEC_ID_PGX) -IMAGEAUTO_DEMUXER(photocd, AV_CODEC_ID_PHOTOCD) -IMAGEAUTO_DEMUXER(pictor, AV_CODEC_ID_PICTOR) -IMAGEAUTO_DEMUXER(png, AV_CODEC_ID_PNG) -IMAGEAUTO_DEMUXER(ppm, AV_CODEC_ID_PPM) -IMAGEAUTO_DEMUXER(psd, AV_CODEC_ID_PSD) -IMAGEAUTO_DEMUXER(qdraw, AV_CODEC_ID_QDRAW) -IMAGEAUTO_DEMUXER(sgi, AV_CODEC_ID_SGI) -IMAGEAUTO_DEMUXER(sunrast, AV_CODEC_ID_SUNRAST) -IMAGEAUTO_DEMUXER(svg, AV_CODEC_ID_SVG) -IMAGEAUTO_DEMUXER(tiff, AV_CODEC_ID_TIFF) -IMAGEAUTO_DEMUXER(webp, AV_CODEC_ID_WEBP) -IMAGEAUTO_DEMUXER(xbm, AV_CODEC_ID_XBM) -IMAGEAUTO_DEMUXER(xpm, AV_CODEC_ID_XPM) -IMAGEAUTO_DEMUXER(xwd, AV_CODEC_ID_XWD) +#define IMAGEAUTO_DEMUXER_2(imgname, codecid, enabled) \ + IMAGEAUTO_DEMUXER_ ## enabled(imgname, codecid) +#define IMAGEAUTO_DEMUXER_3(imgname, codecid, config) \ + IMAGEAUTO_DEMUXER_2(imgname, codecid, config) +#define IMAGEAUTO_DEMUXER_EXT(imgname, codecid, uppercase_name) \ + IMAGEAUTO_DEMUXER_3(imgname, AV_CODEC_ID_ ## codecid, \ + CONFIG_IMAGE_ ## uppercase_name ## _PIPE_DEMUXER) +#define IMAGEAUTO_DEMUXER(imgname, codecid) \ + IMAGEAUTO_DEMUXER_EXT(imgname, codecid, codecid) + +IMAGEAUTO_DEMUXER(bmp, BMP) +IMAGEAUTO_DEMUXER(cri, CRI) +IMAGEAUTO_DEMUXER(dds, DDS) +IMAGEAUTO_DEMUXER(dpx, DPX) +IMAGEAUTO_DEMUXER(exr, EXR) +IMAGEAUTO_DEMUXER(gem, GEM) +IMAGEAUTO_DEMUXER(gif, GIF) +IMAGEAUTO_DEMUXER_EXT(j2k, JPEG2000, J2K) +IMAGEAUTO_DEMUXER_EXT(jpeg, MJPEG, JPEG) +IMAGEAUTO_DEMUXER(jpegls, JPEGLS) +IMAGEAUTO_DEMUXER(jpegxl, JPEGXL) +IMAGEAUTO_DEMUXER(pam, PAM) +IMAGEAUTO_DEMUXER(pbm, PBM) +IMAGEAUTO_DEMUXER(pcx, PCX) +IMAGEAUTO_DEMUXER(pfm, PFM) +IMAGEAUTO_DEMUXER(pgm, PGM) +IMAGEAUTO_DEMUXER(pgmyuv, PGMYUV) +IMAGEAUTO_DEMUXER(pgx, PGX) +IMAGEAUTO_DEMUXER(phm, PHM) +IMAGEAUTO_DEMUXER(photocd, PHOTOCD) +IMAGEAUTO_DEMUXER(pictor, PICTOR) +IMAGEAUTO_DEMUXER(png, PNG) +IMAGEAUTO_DEMUXER(ppm, PPM) +IMAGEAUTO_DEMUXER(psd, PSD) +IMAGEAUTO_DEMUXER(qdraw, QDRAW) +IMAGEAUTO_DEMUXER(qoi, QOI) +IMAGEAUTO_DEMUXER(sgi, SGI) +IMAGEAUTO_DEMUXER(sunrast, SUNRAST) +IMAGEAUTO_DEMUXER(svg, SVG) +IMAGEAUTO_DEMUXER(tiff, TIFF) +IMAGEAUTO_DEMUXER(vbn, VBN) +IMAGEAUTO_DEMUXER(webp, WEBP) +IMAGEAUTO_DEMUXER(xbm, XBM) +IMAGEAUTO_DEMUXER(xpm, XPM) +IMAGEAUTO_DEMUXER(xwd, XWD) diff --git a/libavformat/img2enc.c b/libavformat/img2enc.c index ded91d6b9..0224fb5b0 100644 --- a/libavformat/img2enc.c +++ b/libavformat/img2enc.c @@ -20,6 +20,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/intreadwrite.h" #include "libavutil/avstring.h" #include "libavutil/dict.h" @@ -34,6 +36,7 @@ typedef struct VideoMuxData { const AVClass *class; /**< Class for private options. */ + int start_img_number; int img_number; int split_planes; /**< use independent file for each Y, U, V plane */ char tmp[4][1024]; @@ -56,6 +59,8 @@ static int write_header(AVFormatContext *s) img->muxer = "gif"; } else if (st->codecpar->codec_id == AV_CODEC_ID_FITS) { img->muxer = "fits"; + } else if (st->codecpar->codec_id == AV_CODEC_ID_AV1) { + img->muxer = "avif"; } else if (st->codecpar->codec_id == AV_CODEC_ID_RAWVIDEO) { const char *str = strrchr(s->url, '.'); img->split_planes = str @@ -65,6 +70,7 @@ static int write_header(AVFormatContext *s) &&(desc->flags & AV_PIX_FMT_FLAG_PLANAR) && desc->nb_components >= 3; } + img->img_number = img->start_img_number; return 0; } @@ -157,13 +163,17 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) } } else if (av_get_frame_filename2(filename, sizeof(filename), s->url, img->img_number, - 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'. " - "Use '-frames:v 1' for a single image, or '-update' option, or use a pattern such as %%03d within the filename.\n", - img->img_number, s->url); - return AVERROR(EINVAL); + AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0) { + if (img->img_number == img->start_img_number) { + av_log(s, AV_LOG_WARNING, "The specified filename '%s' does not contain an image sequence pattern or a pattern is invalid.\n", s->url); + av_log(s, AV_LOG_WARNING, + "Use a pattern such as %%03d for an image sequence or " + "use the -update option (with -frames:v 1 if needed) to write a single image.\n"); + av_strlcpy(filename, s->url, sizeof(filename)); + } else { + av_log(s, AV_LOG_ERROR, "Cannot write more than one file with the same name. Are you missing the -update option or a sequence pattern?\n"); + return AVERROR(EINVAL); + } } for (i = 0; i < 4; i++) { av_dict_copy(&options, img->protocol_opts, 0); @@ -242,7 +252,7 @@ static int query_codec(enum AVCodecID id, int std_compliance) #define ENC AV_OPT_FLAG_ENCODING_PARAM 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 }, + { "start_number", "set first number in the sequence", OFFSET(start_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 }, @@ -261,9 +271,9 @@ static const AVClass img2mux_class = { const AVOutputFormat ff_image2_muxer = { .name = "image2", .long_name = NULL_IF_CONFIG_SMALL("image2 sequence"), - .extensions = "bmp,dpx,exr,jls,jpeg,jpg,ljpg,pam,pbm,pcx,pfm,pgm,pgmyuv,png," - "ppm,sgi,tga,tif,tiff,jp2,j2c,j2k,xwd,sun,ras,rs,im1,im8,im24," - "sunras,xbm,xface,pix,y", + .extensions = "bmp,dpx,exr,jls,jpeg,jpg,jxl,ljpg,pam,pbm,pcx,pfm,pgm,pgmyuv,phm," + "png,ppm,sgi,tga,tif,tiff,jp2,j2c,j2k,xwd,sun,ras,rs,im1,im8," + "im24,sunras,vbn,xbm,xface,pix,y,avif,qoi", .priv_data_size = sizeof(VideoMuxData), .video_codec = AV_CODEC_ID_MJPEG, .write_header = write_header, diff --git a/libavformat/imx.c b/libavformat/imx.c index e8ca79d05..c8b1a3b2a 100644 --- a/libavformat/imx.c +++ b/libavformat/imx.c @@ -76,8 +76,7 @@ static int simbiosis_imx_read_header(AVFormatContext *s) ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; ast->codecpar->codec_tag = 0; ast->codecpar->codec_id = AV_CODEC_ID_PCM_U8; - ast->codecpar->channels = 1; - ast->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + ast->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; ast->codecpar->sample_rate = 22050; ast->start_time = 0; diff --git a/libavformat/internal.h b/libavformat/internal.h index bffb8e66f..b6b8fbf56 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -24,7 +24,6 @@ #include #include "libavcodec/avcodec.h" -#include "libavcodec/bsf.h" #include "libavcodec/packet_internal.h" #include "avformat.h" @@ -82,6 +81,17 @@ typedef struct FFFormatContext { */ int nb_interleaved_streams; + /** + * Whether the timestamp shift offset has already been determined. + * -1: disabled, 0: not yet determined, 1: determined. + */ + enum { + AVOID_NEGATIVE_TS_DISABLED = -1, + AVOID_NEGATIVE_TS_UNKNOWN = 0, + AVOID_NEGATIVE_TS_KNOWN = 1, + } avoid_negative_ts_status; +#define AVOID_NEGATIVE_TS_ENABLED(status) ((status) >= 0) + /** * The interleavement function in use. Always set for muxers. */ @@ -135,18 +145,6 @@ typedef struct FFFormatContext { */ int raw_packet_buffer_size; - /** - * Offset to remap timestamps to be non-negative. - * Expressed in timebase units. - * @see AVStream.mux_ts_offset - */ - int64_t offset; - - /** - * Timebase for the timestamp offset. - */ - AVRational offset_timebase; - #if FF_API_COMPUTE_PKT_FIELDS2 int missing_ts_warning; #endif @@ -184,6 +182,11 @@ typedef struct FFFormatContext { * Set if chapter ids are strictly monotonic. */ int chapter_ids_monotonic; + + /** + * Contexts and child contexts do not contain a metadata option + */ + int metafree; } FFFormatContext; static av_always_inline FFFormatContext *ffformatcontext(AVFormatContext *s) @@ -208,7 +211,7 @@ typedef struct FFStream { * - encoding: Set by muxer using ff_stream_add_bitstream_filter * - decoding: unused */ - AVBSFContext *bsfc; + struct AVBSFContext *bsfc; /** * Whether or not check_bitstream should still be run on each packet @@ -228,7 +231,7 @@ typedef struct FFStream { * inited=1/bsf=NULL signals that extracting is not possible (codec not * supported) */ struct { - AVBSFContext *bsf; + struct AVBSFContext *bsf; int inited; } extract_extradata; @@ -241,38 +244,10 @@ typedef struct FFStream { FFFrac *priv_pts; -#define MAX_STD_TIMEBASES (30*12+30+3+6) /** * Stream information used internally by avformat_find_stream_info() */ - struct { - int64_t last_dts; - int64_t duration_gcd; - int duration_count; - int64_t rfps_duration_sum; - 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. - * >0 -> decoder found - * <0 -> decoder with codec_id == -found_decoder has not been found - */ - int found_decoder; - - int64_t last_duration; - - /** - * Those are used for average framerate estimation. - */ - int64_t fps_first_dts; - int fps_first_dts_idx; - int64_t fps_last_dts; - int fps_last_dts_idx; - - } *info; + struct FFStreamInfo *info; AVIndexEntry *index_entries; /**< Only used if the format does not support seeking natively. */ @@ -439,8 +414,6 @@ static av_always_inline const FFStream *cffstream(const AVStream *st) return (FFStream*)st; } -void avpriv_stream_set_need_parsing(AVStream *st, enum AVStreamParseType type); - #ifdef __GNUC__ #define dynarray_add(tab, nb_ptr, elem)\ do {\ @@ -456,21 +429,6 @@ do {\ } while(0) #endif -#define RELATIVE_TS_BASE (INT64_MAX - (1LL << 48)) - -static av_always_inline int is_relative(int64_t ts) -{ - return ts > (RELATIVE_TS_BASE - (1LL << 48)); -} - -/** - * Wrap a given time stamp, if there is an indication for an overflow - * - * @param st stream - * @param timestamp the time stamp to wrap - * @return resulting time stamp - */ -int64_t ff_wrap_timestamp(const AVStream *st, int64_t timestamp); void ff_flush_packet_queue(AVFormatContext *s); @@ -505,16 +463,6 @@ char *ff_data_to_hex(char *buf, const uint8_t *src, int size, int lowercase); */ int ff_hex_to_data(uint8_t *data, const char *p); -/** - * Add packet to an AVFormatContext's packet_buffer list, determining its - * interleaved position using compare() function argument. - * @return 0 on success, < 0 on error. pkt will always be blank on return. - */ -int ff_interleave_add_packet(AVFormatContext *s, AVPacket *pkt, - int (*compare)(AVFormatContext *, const AVPacket *, const AVPacket *)); - -void ff_read_frame_flush(AVFormatContext *s); - #define NTP_OFFSET 2208988800ULL #define NTP_OFFSET_US (NTP_OFFSET * 1000000ULL) @@ -560,22 +508,6 @@ int ff_sdp_write_media(char *buff, int size, const AVStream *st, int idx, const char *dest_addr, const char *dest_type, int port, int ttl, AVFormatContext *fmt); -/** - * Write a packet to another muxer than the one the user originally - * intended. Useful when chaining muxers, where one muxer internally - * writes a received packet to another muxer. - * - * @param dst the muxer to write the packet to - * @param dst_stream the stream index within dst to write the packet to - * @param pkt the packet to be written. It will be returned blank when - * av_interleaved_write_frame() is used, unchanged otherwise. - * @param src the muxer the packet originally was intended for - * @param interleave 0->use av_write_frame, 1->av_interleaved_write_frame - * @return the value av_write_frame returned - */ -int ff_write_chained(AVFormatContext *dst, int dst_stream, AVPacket *pkt, - AVFormatContext *src, int interleave); - /** * Read a whole line of text from AVIOContext. Stop reading after reaching * either a \\n, a \\0 or EOF. The returned string is always \\0-terminated, @@ -625,88 +557,10 @@ typedef void (*ff_parse_key_val_cb)(void *context, const char *key, void ff_parse_key_value(const char *str, ff_parse_key_val_cb callback_get_buf, void *context); -/** - * Find stream index based on format-specific stream ID - * @return stream index, or < 0 on error - */ -int ff_find_stream_index(const AVFormatContext *s, int id); - -/** - * Internal version of av_index_search_timestamp - */ -int ff_index_search_timestamp(const AVIndexEntry *entries, int nb_entries, - int64_t wanted_timestamp, int flags); - -/** - * Internal version of av_add_index_entry - */ -int ff_add_index_entry(AVIndexEntry **index_entries, - int *nb_index_entries, - unsigned int *index_entries_allocated_size, - int64_t pos, int64_t timestamp, int size, int distance, int flags); - -void ff_configure_buffers_for_index(AVFormatContext *s, int64_t time_tolerance); - -/** - * Add a new chapter. - * - * @param s media file handle - * @param id unique ID for this chapter - * @param start chapter start time in time_base units - * @param end chapter end time in time_base units - * @param title chapter title - * - * @return AVChapter or NULL on error - */ -AVChapter *avpriv_new_chapter(AVFormatContext *s, int64_t id, AVRational time_base, - int64_t start, int64_t end, const char *title); - -/** - * Ensure the index uses less memory than the maximum specified in - * AVFormatContext.max_index_size by discarding entries if it grows - * too large. - */ -void ff_reduce_index(AVFormatContext *s, int stream_index); - enum AVCodecID ff_guess_image2_codec(const char *filename); const AVCodec *ff_find_decoder(AVFormatContext *s, const AVStream *st, enum AVCodecID codec_id); -/** - * Perform a binary search using av_index_search_timestamp() and - * AVInputFormat.read_timestamp(). - * - * @param target_ts target timestamp in the time base of the given stream - * @param stream_index stream number - */ -int ff_seek_frame_binary(AVFormatContext *s, int stream_index, - int64_t target_ts, int flags); - -/** - * Update cur_dts of all streams based on the given timestamp and AVStream. - * - * Stream ref_st unchanged, others set cur_dts in their native time base. - * Only needed for timestamp wrapping or if (dts not set and pts!=dts). - * @param timestamp new dts expressed in time_base of param ref_st - * @param ref_st reference stream giving time_base of param timestamp - */ -void avpriv_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp); - -int ff_find_last_ts(AVFormatContext *s, int stream_index, int64_t *ts, int64_t *pos, - int64_t (*read_timestamp)(struct AVFormatContext *, int , int64_t *, int64_t )); - -/** - * Perform a binary search using read_timestamp(). - * - * @param target_ts target timestamp in the time base of the given stream - * @param stream_index stream number - */ -int64_t ff_gen_search(AVFormatContext *s, int stream_index, - int64_t target_ts, int64_t pos_min, - int64_t pos_max, int64_t pos_limit, - int64_t ts_min, int64_t ts_max, - int flags, int64_t *ts_ret, - int64_t (*read_timestamp)(struct AVFormatContext *, int , int64_t *, int64_t )); /** * Set the time base and wrapping info for a given stream. This will be used @@ -723,14 +577,6 @@ int64_t ff_gen_search(AVFormatContext *s, int stream_index, void avpriv_set_pts_info(AVStream *st, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den); -/** - * Add side data to a packet for changing parameters to the given values. - * Parameters set to 0 aren't included in the change. - */ -int ff_add_param_change(AVPacket *pkt, int32_t channels, - uint64_t channel_layout, int32_t sample_rate, - int32_t width, int32_t height); - /** * Set the timebase for each stream from the corresponding codec timebase and * print it. @@ -738,45 +584,16 @@ int ff_add_param_change(AVPacket *pkt, int32_t channels, int ff_framehash_write_header(AVFormatContext *s); /** - * Read a transport packet from a media file. - * - * @param s media file handle - * @param pkt is filled - * @return 0 if OK, AVERROR_xxx on error + * Frees a stream without modifying the corresponding AVFormatContext. + * Must only be called if the latter doesn't matter or if the stream + * is not yet attached to an AVFormatContext. */ -int ff_read_packet(AVFormatContext *s, AVPacket *pkt); - +void ff_free_stream(AVStream **st); /** - * Add an attached pic to an AVStream. - * - * @param st if set, the stream to add the attached pic to; - * if unset, a new stream will be added to s. - * @param pb AVIOContext to read data from if buf is unset. - * @param buf if set, it contains the data and size information to be used - * for the attached pic; if unset, data is read from pb. - * @param size the size of the data to read if buf is unset. - * - * @return 0 on success, < 0 on error. On error, this function removes - * the stream it has added (if any). + * Remove a stream from its AVFormatContext and free it. + * The stream must be the last stream of the AVFormatContext. */ -int ff_add_attached_pic(AVFormatContext *s, AVStream *st, AVIOContext *pb, - AVBufferRef **buf, int size); - -/** - * Interleave an AVPacket per dts so it can be muxed. - * See the documentation of AVOutputFormat.interleave_packet for details. - */ -int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *pkt, - int flush, int has_packet); - -/** - * Interleave packets directly in the order in which they arrive - * without any sort of buffering. - */ -int ff_interleave_packet_passthrough(AVFormatContext *s, AVPacket *pkt, - int flush, int has_packet); - -void ff_free_stream(AVFormatContext *s, AVStream *st); +void ff_remove_stream(AVFormatContext *s, AVStream *st); unsigned int ff_codec_get_tag(const AVCodecTag *tags, enum AVCodecID id); @@ -799,46 +616,6 @@ int ff_is_intra_only(enum AVCodecID id); */ enum AVCodecID ff_get_pcm_codec_id(int bps, int flt, int be, int sflags); -/** - * Chooses a timebase for muxing the specified stream. - * - * The chosen timebase allows sample accurate timestamps based - * on the framerate or sample rate for audio streams. It also is - * at least as precise as 1/min_precision would be. - */ -AVRational ff_choose_timebase(AVFormatContext *s, AVStream *st, int min_precision); - -/** - * Chooses a timebase for muxing the specified stream. - */ -enum AVChromaLocation ff_choose_chroma_location(AVFormatContext *s, AVStream *st); - -/** - * Generate standard extradata for AVC-Intra based on width/height and field - * order. - */ -int ff_generate_avci_extradata(AVStream *st); - -/** - * Add a bitstream filter to a stream. - * - * @param st output stream to add a filter to - * @param name the name of the filter to add - * @param args filter-specific argument string - * @return >0 on success; - * AVERROR code on failure - */ -int ff_stream_add_bitstream_filter(AVStream *st, const char *name, const char *args); - -/** - * Copy encoding parameters from source to destination stream - * - * @param dst pointer to destination AVStream - * @param src pointer to source AVStream - * @return >=0 on success, AVERROR code on error - */ -int ff_stream_encode_params_copy(AVStream *dst, const AVStream *src); - /** * Copy side data from source to destination stream * @@ -868,59 +645,11 @@ int ff_rename(const char *url_src, const char *url_dst, void *logctx); */ int ff_alloc_extradata(AVCodecParameters *par, int size); -/** - * Allocate extradata with additional AV_INPUT_BUFFER_PADDING_SIZE at end - * which is always set to 0 and fill it from pb. - * - * @param size size of extradata - * @return >= 0 if OK, AVERROR_xxx on error - */ -int ff_get_extradata(AVFormatContext *s, AVCodecParameters *par, AVIOContext *pb, int size); - -/** - * add frame for rfps calculation. - * - * @param dts timestamp of the i-th frame - * @return 0 if OK, AVERROR_xxx on error - */ -int ff_rfps_add_frame(AVFormatContext *ic, AVStream *st, int64_t dts); - -void ff_rfps_calculate(AVFormatContext *ic); - -/** - * Flags for AVFormatContext.write_uncoded_frame() - */ -enum AVWriteUncodedFrameFlags { - - /** - * Query whether the feature is possible on this stream. - * The frame argument is ignored. - */ - AV_WRITE_UNCODED_FRAME_QUERY = 0x0001, - -}; - /** * Copies the whilelists from one context to the other */ int ff_copy_whiteblacklists(AVFormatContext *dst, const AVFormatContext *src); -/** - * Returned by demuxers to indicate that data was consumed but discarded - * (ignored streams or junk data). The framework will re-call the demuxer. - */ -#define FFERROR_REDO FFERRTAG('R','E','D','O') - -/** - * Utility function to open IO stream of output format. - * - * @param s AVFormatContext - * @param url URL or file name to open for writing - * @options optional options which will be passed to io_open callback - * @return >=0 on success, negative AVERROR in case of failure - */ -int ff_format_output_open(AVFormatContext *s, const char *url, AVDictionary **options); - /* * A wrapper around AVFormatContext.io_close that should be used * instead of calling the pointer directly. @@ -943,68 +672,12 @@ void ff_format_io_close_default(AVFormatContext *s, AVIOContext *pb); */ int ff_is_http_proto(const char *filename); -/** - * Parse creation_time in AVFormatContext metadata if exists and warn if the - * parsing fails. - * - * @param s AVFormatContext - * @param timestamp parsed timestamp in microseconds, only set on successful parsing - * @param return_seconds set this to get the number of seconds in timestamp instead of microseconds - * @return 1 if OK, 0 if the metadata was not present, AVERROR(EINVAL) on parse error - */ -int ff_parse_creation_time_metadata(AVFormatContext *s, int64_t *timestamp, int return_seconds); - -/** - * Standardize creation_time metadata in AVFormatContext to an ISO-8601 - * timestamp string. - * - * @param s AVFormatContext - * @return <0 on error - */ -int ff_standardize_creation_time(AVFormatContext *s); - -#define CONTAINS_PAL 2 -/** - * Reshuffles the lines to use the user specified stride. - * - * @param ppkt input and output packet - * @return negative error code or - * 0 if no new packet was allocated - * non-zero if a new packet was allocated and ppkt has to be freed - * CONTAINS_PAL if in addition to a new packet the old contained a palette - */ -int ff_reshuffle_raw_rgb(AVFormatContext *s, AVPacket **ppkt, AVCodecParameters *par, int expected_stride); - -/** - * Retrieves the palette from a packet, either from side data, or - * appended to the video data in the packet itself (raw video only). - * It is commonly used after a call to ff_reshuffle_raw_rgb(). - * - * Use 0 for the ret parameter to check for side data only. - * - * @param pkt pointer to packet before calling ff_reshuffle_raw_rgb() - * @param ret return value from ff_reshuffle_raw_rgb(), or 0 - * @param palette pointer to palette buffer - * @return negative error code or - * 1 if the packet has a palette, else 0 - */ -int ff_get_packet_palette(AVFormatContext *s, AVPacket *pkt, int ret, uint32_t *palette); - struct AVBPrint; /** * Finalize buf into extradata and set its size appropriately. */ int ff_bprint_to_codecpar_extradata(AVCodecParameters *par, struct AVBPrint *buf); -/** - * Find the next packet in the interleaving queue for the given stream. - * - * @return a pointer to a packet if one was found, NULL otherwise. - */ -const AVPacket *ff_interleaved_peek(AVFormatContext *s, int stream); - -int ff_get_muxer_ts_offset(AVFormatContext *s, int stream_index, int64_t *offset); - int ff_lock_avformat(void); int ff_unlock_avformat(void); @@ -1017,11 +690,4 @@ void ff_format_set_url(AVFormatContext *s, char *url); void avpriv_register_devices(const AVOutputFormat * const o[], const AVInputFormat * const i[]); -/** - * Make shift_size amount of space at read_start by shifting data in the output - * at read_start until the current IO position. The underlying IO context must - * be seekable. - */ -int ff_format_shift_data(AVFormatContext *s, int64_t read_start, int shift_size); - #endif /* AVFORMAT_INTERNAL_H */ diff --git a/libavformat/ip.c b/libavformat/ip.c index 70c5529b7..b2c7ef07e 100644 --- a/libavformat/ip.c +++ b/libavformat/ip.c @@ -18,8 +18,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include "ip.h" #include "libavutil/avstring.h" +#include "libavutil/mem.h" static int compare_addr(const struct sockaddr_storage *a, const struct sockaddr_storage *b) diff --git a/libavformat/ipfsgateway.c b/libavformat/ipfsgateway.c new file mode 100644 index 000000000..5a5178c56 --- /dev/null +++ b/libavformat/ipfsgateway.c @@ -0,0 +1,359 @@ +/* + * IPFS and IPNS protocol support through IPFS Gateway. + * Copyright (c) 2022 Mark Gaiser + * + * 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/getenv_utf8.h" +#include "libavutil/opt.h" +#include +#include "os_support.h" +#include "url.h" + +// Define the posix PATH_MAX if not there already. +// This fixes a compile issue for MSVC. +#ifndef PATH_MAX +#define PATH_MAX 4096 +#endif + +typedef struct IPFSGatewayContext { + AVClass *class; + URLContext *inner; + // Is filled by the -gateway argument and not changed after. + char *gateway; + // If the above gateway is non null, it will be copied into this buffer. + // Else this buffer will contain the auto detected gateway. + // In either case, the gateway to use will be in this buffer. + char gateway_buffer[PATH_MAX]; +} IPFSGatewayContext; + +// A best-effort way to find the IPFS gateway. +// Only the most appropiate gateway is set. It's not actually requested +// (http call) to prevent a potential slowdown in startup. A potential timeout +// is handled by the HTTP protocol. +static int populate_ipfs_gateway(URLContext *h) +{ + IPFSGatewayContext *c = h->priv_data; + char ipfs_full_data_folder[PATH_MAX]; + char ipfs_gateway_file[PATH_MAX]; + struct stat st; + int stat_ret = 0; + int ret = AVERROR(EINVAL); + FILE *gateway_file = NULL; + char *env_ipfs_gateway, *env_ipfs_path; + + // Test $IPFS_GATEWAY. + env_ipfs_gateway = getenv_utf8("IPFS_GATEWAY"); + if (env_ipfs_gateway != NULL) { + int printed = snprintf(c->gateway_buffer, sizeof(c->gateway_buffer), + "%s", env_ipfs_gateway); + freeenv_utf8(env_ipfs_gateway); + if (printed >= sizeof(c->gateway_buffer)) { + av_log(h, AV_LOG_WARNING, + "The IPFS_GATEWAY environment variable " + "exceeds the maximum length. " + "We allow a max of %zu characters\n", + sizeof(c->gateway_buffer)); + ret = AVERROR(EINVAL); + goto err; + } + + ret = 1; + goto err; + } else + av_log(h, AV_LOG_DEBUG, "$IPFS_GATEWAY is empty.\n"); + + // We need to know the IPFS folder to - eventually - read the contents of + // the "gateway" file which would tell us the gateway to use. + env_ipfs_path = getenv_utf8("IPFS_PATH"); + if (env_ipfs_path == NULL) { + int printed; + char *env_home = getenv_utf8("HOME"); + + av_log(h, AV_LOG_DEBUG, "$IPFS_PATH is empty.\n"); + + // Try via the home folder. + if (env_home == NULL) { + av_log(h, AV_LOG_WARNING, "$HOME appears to be empty.\n"); + ret = AVERROR(EINVAL); + goto err; + } + + // Verify the composed path fits. + printed = snprintf( + ipfs_full_data_folder, sizeof(ipfs_full_data_folder), + "%s/.ipfs/", env_home); + freeenv_utf8(env_home); + if (printed >= sizeof(ipfs_full_data_folder)) { + av_log(h, AV_LOG_WARNING, + "The IPFS data path exceeds the " + "max path length (%zu)\n", + sizeof(ipfs_full_data_folder)); + ret = AVERROR(EINVAL); + goto err; + } + + // Stat the folder. + // It should exist in a default IPFS setup when run as local user. + stat_ret = stat(ipfs_full_data_folder, &st); + + if (stat_ret < 0) { + av_log(h, AV_LOG_INFO, + "Unable to find IPFS folder. We tried:\n" + "- $IPFS_PATH, which was empty.\n" + "- $HOME/.ipfs (full uri: %s) which doesn't exist.\n", + ipfs_full_data_folder); + ret = AVERROR(ENOENT); + goto err; + } + } else { + int printed = snprintf( + ipfs_full_data_folder, sizeof(ipfs_full_data_folder), + "%s", env_ipfs_path); + freeenv_utf8(env_ipfs_path); + if (printed >= sizeof(ipfs_full_data_folder)) { + av_log(h, AV_LOG_WARNING, + "The IPFS_PATH environment variable " + "exceeds the maximum length. " + "We allow a max of %zu characters\n", + sizeof(c->gateway_buffer)); + ret = AVERROR(EINVAL); + goto err; + } + } + + // Copy the fully composed gateway path into ipfs_gateway_file. + if (snprintf(ipfs_gateway_file, sizeof(ipfs_gateway_file), "%sgateway", + ipfs_full_data_folder) + >= sizeof(ipfs_gateway_file)) { + av_log(h, AV_LOG_WARNING, + "The IPFS gateway file path exceeds " + "the max path length (%zu)\n", + sizeof(ipfs_gateway_file)); + ret = AVERROR(ENOENT); + goto err; + } + + // Get the contents of the gateway file. + gateway_file = avpriv_fopen_utf8(ipfs_gateway_file, "r"); + if (!gateway_file) { + av_log(h, AV_LOG_WARNING, + "The IPFS gateway file (full uri: %s) doesn't exist. " + "Is the gateway enabled?\n", + ipfs_gateway_file); + ret = AVERROR(ENOENT); + goto err; + } + + // Read a single line (fgets stops at new line mark). + if (!fgets(c->gateway_buffer, sizeof(c->gateway_buffer) - 1, gateway_file)) { + av_log(h, AV_LOG_WARNING, "Unable to read from file (full uri: %s).\n", + ipfs_gateway_file); + ret = AVERROR(ENOENT); + goto err; + } + + // Replace first occurence of end of line with \0 + c->gateway_buffer[strcspn(c->gateway_buffer, "\r\n")] = 0; + + // If strlen finds anything longer then 0 characters then we have a + // potential gateway url. + if (*c->gateway_buffer == '\0') { + av_log(h, AV_LOG_WARNING, + "The IPFS gateway file (full uri: %s) appears to be empty. " + "Is the gateway started?\n", + ipfs_gateway_file); + ret = AVERROR(EILSEQ); + goto err; + } else { + // We're done, the c->gateway_buffer has something that looks valid. + ret = 1; + goto err; + } + +err: + if (gateway_file) + fclose(gateway_file); + + return ret; +} + +static int translate_ipfs_to_http(URLContext *h, const char *uri, int flags, AVDictionary **options) +{ + const char *ipfs_cid; + char *fulluri = NULL; + int ret; + IPFSGatewayContext *c = h->priv_data; + + // Test for ipfs://, ipfs:, ipns:// and ipns:. This prefix is stripped from + // the string leaving just the CID in ipfs_cid. + int is_ipfs = av_stristart(uri, "ipfs://", &ipfs_cid); + int is_ipns = av_stristart(uri, "ipns://", &ipfs_cid); + + // We must have either ipns or ipfs. + if (!is_ipfs && !is_ipns) { + ret = AVERROR(EINVAL); + av_log(h, AV_LOG_WARNING, "Unsupported url %s\n", uri); + goto err; + } + + // If the CID has a length greater then 0 then we assume we have a proper working one. + // It could still be wrong but in that case the gateway should save us and + // ruturn a 403 error. The http protocol handles this. + if (strlen(ipfs_cid) < 1) { + av_log(h, AV_LOG_WARNING, "A CID must be provided.\n"); + ret = AVERROR(EILSEQ); + goto err; + } + + // Populate c->gateway_buffer with whatever is in c->gateway + if (c->gateway != NULL) { + if (snprintf(c->gateway_buffer, sizeof(c->gateway_buffer), "%s", + c->gateway) + >= sizeof(c->gateway_buffer)) { + av_log(h, AV_LOG_WARNING, + "The -gateway parameter is too long. " + "We allow a max of %zu characters\n", + sizeof(c->gateway_buffer)); + ret = AVERROR(EINVAL); + goto err; + } + } else { + // Populate the IPFS gateway if we have any. + // If not, inform the user how to properly set one. + ret = populate_ipfs_gateway(h); + + if (ret < 1) { + // We fallback on dweb.link (managed by Protocol Labs). + snprintf(c->gateway_buffer, sizeof(c->gateway_buffer), "https://dweb.link"); + + av_log(h, AV_LOG_WARNING, + "IPFS does not appear to be running. " + "You’re now using the public gateway at dweb.link.\n"); + av_log(h, AV_LOG_INFO, + "Installing IPFS locally is recommended to " + "improve performance and reliability, " + "and not share all your activity with a single IPFS gateway.\n" + "There are multiple options to define this gateway.\n" + "1. Call ffmpeg with a gateway param, " + "without a trailing slash: -gateway .\n" + "2. Define an $IPFS_GATEWAY environment variable with the " + "full HTTP URL to the gateway " + "without trailing forward slash.\n" + "3. Define an $IPFS_PATH environment variable " + "and point it to the IPFS data path " + "- this is typically ~/.ipfs\n"); + } + } + + // Test if the gateway starts with either http:// or https:// + if (av_stristart(c->gateway_buffer, "http://", NULL) == 0 + && av_stristart(c->gateway_buffer, "https://", NULL) == 0) { + av_log(h, AV_LOG_WARNING, + "The gateway URL didn't start with http:// or " + "https:// and is therefore invalid.\n"); + ret = AVERROR(EILSEQ); + goto err; + } + + // Concatenate the url. + // This ends up with something like: http://localhost:8080/ipfs/Qm..... + // The format of "%s%s%s%s" is the following: + // 1st %s = The gateway. + // 2nd %s = If the gateway didn't end in a slash, add a "/". Otherwise it's an empty string + // 3rd %s = Either ipns/ or ipfs/. + // 4th %s = The IPFS CID (Qm..., bafy..., ...). + fulluri = av_asprintf("%s%s%s%s", + c->gateway_buffer, + (c->gateway_buffer[strlen(c->gateway_buffer) - 1] == '/') ? "" : "/", + (is_ipns) ? "ipns/" : "ipfs/", + ipfs_cid); + + if (!fulluri) { + av_log(h, AV_LOG_ERROR, "Failed to compose the URL\n"); + ret = AVERROR(ENOMEM); + goto err; + } + + // Pass the URL back to FFMpeg's protocol handler. + ret = ffurl_open_whitelist(&c->inner, fulluri, flags, + &h->interrupt_callback, options, + h->protocol_whitelist, + h->protocol_blacklist, h); + if (ret < 0) { + av_log(h, AV_LOG_WARNING, "Unable to open resource: %s\n", fulluri); + goto err; + } + +err: + av_free(fulluri); + return ret; +} + +static int ipfs_read(URLContext *h, unsigned char *buf, int size) +{ + IPFSGatewayContext *c = h->priv_data; + return ffurl_read(c->inner, buf, size); +} + +static int64_t ipfs_seek(URLContext *h, int64_t pos, int whence) +{ + IPFSGatewayContext *c = h->priv_data; + return ffurl_seek(c->inner, pos, whence); +} + +static int ipfs_close(URLContext *h) +{ + IPFSGatewayContext *c = h->priv_data; + return ffurl_closep(&c->inner); +} + +#define OFFSET(x) offsetof(IPFSGatewayContext, x) + +static const AVOption options[] = { + {"gateway", "The gateway to ask for IPFS data.", OFFSET(gateway), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, AV_OPT_FLAG_DECODING_PARAM}, + {NULL}, +}; + +static const AVClass ipfs_context_class = { + .class_name = "IPFS", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +const URLProtocol ff_ipfs_protocol = { + .name = "ipfs", + .url_open2 = translate_ipfs_to_http, + .url_read = ipfs_read, + .url_seek = ipfs_seek, + .url_close = ipfs_close, + .priv_data_size = sizeof(IPFSGatewayContext), + .priv_data_class = &ipfs_context_class, +}; + +const URLProtocol ff_ipns_protocol = { + .name = "ipns", + .url_open2 = translate_ipfs_to_http, + .url_read = ipfs_read, + .url_seek = ipfs_seek, + .url_close = ipfs_close, + .priv_data_size = sizeof(IPFSGatewayContext), + .priv_data_class = &ipfs_context_class, +}; diff --git a/libavformat/ipmovie.c b/libavformat/ipmovie.c index 9c996d4a9..4f5c164d3 100644 --- a/libavformat/ipmovie.c +++ b/libavformat/ipmovie.c @@ -35,6 +35,7 @@ #include "libavutil/channel_layout.h" #include "libavutil/intreadwrite.h" #include "avformat.h" +#include "demux.h" #include "internal.h" #define CHUNK_PREAMBLE_SIZE 4 @@ -254,16 +255,14 @@ static int init_audio(AVFormatContext *s) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = ipmovie->audio_type; st->codecpar->codec_tag = 0; /* no tag */ - st->codecpar->channels = ipmovie->audio_channels; - st->codecpar->channel_layout = st->codecpar->channels == 1 ? AV_CH_LAYOUT_MONO : - AV_CH_LAYOUT_STEREO; + av_channel_layout_default(&st->codecpar->ch_layout, ipmovie->audio_channels); st->codecpar->sample_rate = ipmovie->audio_sample_rate; st->codecpar->bits_per_coded_sample = ipmovie->audio_bits; - st->codecpar->bit_rate = st->codecpar->channels * st->codecpar->sample_rate * + st->codecpar->bit_rate = ipmovie->audio_channels * st->codecpar->sample_rate * st->codecpar->bits_per_coded_sample; if (st->codecpar->codec_id == AV_CODEC_ID_INTERPLAY_DPCM) st->codecpar->bit_rate /= 2; - st->codecpar->block_align = st->codecpar->channels * st->codecpar->bits_per_coded_sample; + st->codecpar->block_align = ipmovie->audio_channels * st->codecpar->bits_per_coded_sample; return 0; } diff --git a/libavformat/ipudec.c b/libavformat/ipudec.c index a314a8900..4e346f963 100644 --- a/libavformat/ipudec.c +++ b/libavformat/ipudec.c @@ -25,7 +25,6 @@ #include "rawdec.h" #include "libavutil/intreadwrite.h" -#include "libavcodec/internal.h" static int ipu_read_probe(const AVProbeData *p) { diff --git a/libavformat/ircamdec.c b/libavformat/ircamdec.c index a05ca5c9c..eb59c95e1 100644 --- a/libavformat/ircamdec.c +++ b/libavformat/ircamdec.c @@ -87,8 +87,8 @@ static int ircam_read_header(AVFormatContext *s) return AVERROR(ENOMEM); st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; - st->codecpar->channels = channels; - if (st->codecpar->channels > FF_SANE_NB_CHANNELS) + st->codecpar->ch_layout.nb_channels = channels; + if (st->codecpar->ch_layout.nb_channels > FF_SANE_NB_CHANNELS) return AVERROR(ENOSYS); st->codecpar->sample_rate = sample_rate; @@ -99,7 +99,8 @@ static int ircam_read_header(AVFormatContext *s) } st->codecpar->bits_per_coded_sample = av_get_bits_per_sample(st->codecpar->codec_id); - st->codecpar->block_align = st->codecpar->bits_per_coded_sample * st->codecpar->channels / 8; + st->codecpar->block_align = st->codecpar->bits_per_coded_sample * + st->codecpar->ch_layout.nb_channels / 8; avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); avio_skip(s->pb, 1008); diff --git a/libavformat/ircamenc.c b/libavformat/ircamenc.c index d49a427b2..df1494b2b 100644 --- a/libavformat/ircamenc.c +++ b/libavformat/ircamenc.c @@ -44,7 +44,7 @@ static int ircam_write_header(AVFormatContext *s) avio_wl32(s->pb, 0x0001A364); avio_wl32(s->pb, av_q2intfloat((AVRational){par->sample_rate, 1})); - avio_wl32(s->pb, par->channels); + avio_wl32(s->pb, par->ch_layout.nb_channels); avio_wl32(s->pb, tag); ffio_fill(s->pb, 0, 1008); return 0; diff --git a/libavformat/isom.c b/libavformat/isom.c index 015c82e1b..cf27f5808 100644 --- a/libavformat/isom.c +++ b/libavformat/isom.c @@ -22,13 +22,12 @@ */ #include "avformat.h" +#include "demux.h" #include "internal.h" #include "isom.h" #include "libavcodec/mpeg4audio.h" #include "libavcodec/mpegaudiodata.h" -#include "libavutil/avstring.h" #include "libavutil/channel_layout.h" -#include "libavutil/intreadwrite.h" /* http://www.mp4ra.org */ /* ordered by muxing preference */ @@ -119,9 +118,9 @@ static const char mov_mdhd_language_map[][4] = { "hun", /* 26 Hungarian */ "est", /* 27 Estonian */ "lav", /* 28 Latvian */ - "", /* 29 Sami */ + "smi", /* 29 Sami */ "fo ", /* 30 Faroese */ - "", /* 31 Farsi */ + "per", /* 31 Farsi */ "rus", /* 32 Russian */ "chi", /* 33 Simplified Chinese */ "", /* 34 Flemish */ @@ -166,7 +165,7 @@ static const char mov_mdhd_language_map[][4] = { "kan", /* 73 Kannada */ "tam", /* 74 Tamil */ "tel", /* 75 Telugu */ - "", /* 76 Sinhala */ + "sin", /* 76 Sinhala */ "bur", /* 77 Burmese */ "khm", /* 78 Khmer */ "lao", /* 79 Lao */ @@ -180,9 +179,9 @@ static const char mov_mdhd_language_map[][4] = { "orm", /* 87 Oromo */ "som", /* 88 Somali */ "swa", /* 89 Swahili */ - "", /* 90 Kinyarwanda */ + "kin", /* 90 Kinyarwanda */ "run", /* 91 Rundi */ - "", /* 92 Nyanja */ + "nya", /* 92 Nyanja */ "mlg", /* 93 Malagasy */ "epo", /* 94 Esperanto */ "", /* 95 */ @@ -360,7 +359,8 @@ int ff_mp4_read_dec_config_descr(AVFormatContext *fc, AVStream *st, AVIOContext st->codecpar->extradata_size, 1, fc); if (ret < 0) return ret; - st->codecpar->channels = cfg.channels; + st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + st->codecpar->ch_layout.nb_channels = cfg.channels; if (cfg.object_type == 29 && cfg.sampling_index < 3) // old mp3on4 st->codecpar->sample_rate = ff_mpa_freq_tab[cfg.sampling_index]; else if (cfg.ext_sample_rate) @@ -368,7 +368,7 @@ int ff_mp4_read_dec_config_descr(AVFormatContext *fc, AVStream *st, AVIOContext else st->codecpar->sample_rate = cfg.sample_rate; av_log(fc, AV_LOG_TRACE, "mp4a config channels %d obj %d ext obj %d " - "sample rate %d ext sample rate %d\n", st->codecpar->channels, + "sample rate %d ext sample rate %d\n", cfg.channels, cfg.object_type, cfg.ext_object_type, cfg.sample_rate, cfg.ext_sample_rate); if (!(st->codecpar->codec_id = ff_codec_get_id(mp4_audio_types, diff --git a/libavformat/isom.h b/libavformat/isom.h index 625dea842..f05c2d9c2 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -214,10 +214,20 @@ typedef struct MOVStreamContext { int has_palette; int64_t data_size; uint32_t tmcd_flags; ///< tmcd track flags + uint8_t tmcd_nb_frames; ///< tmcd number of frames per tick / second int64_t track_end; ///< used for dts generation in fragmented movie files int start_pad; ///< amount of samples to skip due to enc-dec delay unsigned int rap_group_count; MOVSbgp *rap_group; + unsigned int sync_group_count; + MOVSbgp *sync_group; + uint8_t *sgpd_sync; + uint32_t sgpd_sync_count; + int32_t *sample_offsets; + int sample_offsets_count; + int *open_key_samples; + int open_key_samples_count; + uint32_t min_sample_duration; int nb_frames_for_fps; int64_t duration_for_fps; @@ -306,6 +316,8 @@ typedef struct MOVContext { int have_read_mfra_size; uint32_t mfra_size; uint32_t max_stts_delta; + int is_still_picture_avif; + int primary_item_id; } MOVContext; int ff_mp4_read_descr_len(AVIOContext *pb); diff --git a/libavformat/isom_tags.c b/libavformat/isom_tags.c index 62e60470a..c5fd7987f 100644 --- a/libavformat/isom_tags.c +++ b/libavformat/isom_tags.c @@ -89,6 +89,8 @@ const AVCodecTag ff_codec_movvideo_tags[] = { { AV_CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'c', 'p') }, /* DV PAL */ { AV_CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'c', ' ') }, /* DV NTSC */ + { AV_CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'l', 'p') }, /* DV PAL 16:9 produced by Radius SoftDV */ + { AV_CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'l', ' ') }, /* DV NTSC 16:9 produced by Radius SoftDV */ { AV_CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'p', 'p') }, /* DVCPRO PAL produced by FCP */ { AV_CODEC_ID_DVVIDEO, MKTAG('d', 'v', '5', 'p') }, /* DVCPRO50 PAL produced by FCP */ { AV_CODEC_ID_DVVIDEO, MKTAG('d', 'v', '5', 'n') }, /* DVCPRO50 NTSC produced by FCP */ diff --git a/libavformat/iss.c b/libavformat/iss.c index c58c5923b..f54ff8b0d 100644 --- a/libavformat/iss.c +++ b/libavformat/iss.c @@ -109,19 +109,20 @@ static av_cold int iss_read_header(AVFormatContext *s) return AVERROR(ENOMEM); st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_ADPCM_IMA_ISS; + if (stereo) { - st->codecpar->channels = 2; - st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; } else { - st->codecpar->channels = 1; - st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; } + st->codecpar->sample_rate = 44100; if(rate_divisor > 0) st->codecpar->sample_rate /= rate_divisor; st->codecpar->bits_per_coded_sample = 4; - st->codecpar->bit_rate = st->codecpar->channels * st->codecpar->sample_rate - * st->codecpar->bits_per_coded_sample; + st->codecpar->bit_rate = st->codecpar->ch_layout.nb_channels * + st->codecpar->sample_rate * + st->codecpar->bits_per_coded_sample; st->codecpar->block_align = iss->packet_size; avpriv_set_pts_info(st, 32, 1, st->codecpar->sample_rate); @@ -138,8 +139,8 @@ static int iss_read_packet(AVFormatContext *s, AVPacket *pkt) pkt->stream_index = 0; pkt->pts = avio_tell(s->pb) - iss->sample_start_pos; - if(s->streams[0]->codecpar->channels > 0) - pkt->pts /= s->streams[0]->codecpar->channels*2; + if (s->streams[0]->codecpar->ch_layout.nb_channels > 0) + pkt->pts /= s->streams[0]->codecpar->ch_layout.nb_channels * 2; return 0; } diff --git a/libavformat/ivfenc.c b/libavformat/ivfenc.c index 5aa8bd125..ed5ec90ce 100644 --- a/libavformat/ivfenc.c +++ b/libavformat/ivfenc.c @@ -19,6 +19,7 @@ */ #include "avformat.h" #include "internal.h" +#include "mux.h" #include "libavutil/intreadwrite.h" typedef struct IVFEncContext { diff --git a/libavformat/jacosubdec.c b/libavformat/jacosubdec.c index 68ed7511d..0ee4820f6 100644 --- a/libavformat/jacosubdec.c +++ b/libavformat/jacosubdec.c @@ -28,7 +28,6 @@ #include "avformat.h" #include "internal.h" #include "subtitles.h" -#include "libavcodec/internal.h" #include "libavcodec/jacosub.h" #include "libavutil/avstring.h" #include "libavutil/bprint.h" diff --git a/libavformat/jpegxl_probe.c b/libavformat/jpegxl_probe.c new file mode 100644 index 000000000..3de002f00 --- /dev/null +++ b/libavformat/jpegxl_probe.c @@ -0,0 +1,396 @@ +/* + * Jpeg XL header verification + * Copyright (c) 2022 Leo Izen + * + * 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 "jpegxl_probe.h" + +#define BITSTREAM_READER_LE +#include "libavcodec/get_bits.h" + +enum JpegXLExtraChannelType { + FF_JPEGXL_CT_ALPHA = 0, + FF_JPEGXL_CT_DEPTH, + FF_JPEGXL_CT_SPOT_COLOR, + FF_JPEGXL_CT_SELECTION_MASK, + FF_JPEGXL_CT_BLACK, + FF_JPEGXL_CT_CFA, + FF_JPEGXL_CT_THERMAL, + FF_JPEGXL_CT_NON_OPTIONAL = 15, + FF_JPEGXL_CT_OPTIONAL +}; + +enum JpegXLColorSpace { + FF_JPEGXL_CS_RGB = 0, + FF_JPEGXL_CS_GRAY, + FF_JPEGXL_CS_XYB, + FF_JPEGXL_CS_UNKNOWN +}; + +enum JpegXLWhitePoint { + FF_JPEGXL_WP_D65 = 1, + FF_JPEGXL_WP_CUSTOM, + FF_JPEGXL_WP_E = 10, + FF_JPEGXL_WP_DCI = 11 +}; + +enum JpegXLPrimaries { + FF_JPEGXL_PR_SRGB = 1, + FF_JPEGXL_PR_CUSTOM, + FF_JPEGXL_PR_2100 = 9, + FF_JPEGXL_PR_P3 = 11, +}; + +#define jxl_bits(n) get_bits_long(gb, (n)) +#define jxl_bits_skip(n) skip_bits_long(gb, (n)) +#define jxl_u32(c0, c1, c2, c3, u0, u1, u2, u3) jpegxl_u32(gb, \ + (const uint32_t[]){c0, c1, c2, c3}, (const uint32_t[]){u0, u1, u2, u3}) +#define jxl_u64() jpegxl_u64(gb) +#define jxl_enum() jxl_u32(0, 1, 2, 18, 0, 0, 4, 6) + +/* read a U32(c_i + u(u_i)) */ +static uint32_t jpegxl_u32(GetBitContext *gb, + const uint32_t constants[4], const uint32_t ubits[4]) +{ + uint32_t ret, choice = jxl_bits(2); + + ret = constants[choice]; + if (ubits[choice]) + ret += jxl_bits(ubits[choice]); + + return ret; +} + +/* read a U64() */ +static uint64_t jpegxl_u64(GetBitContext *gb) +{ + uint64_t shift = 12, ret; + + switch (jxl_bits(2)) { + case 0: + ret = 0; + break; + case 1: + ret = 1 + jxl_bits(4); + break; + case 2: + ret = 17 + jxl_bits(8); + break; + case 3: + ret = jxl_bits(12); + while (jxl_bits(1)) { + if (shift < 60) { + ret |= (uint64_t)jxl_bits(8) << shift; + shift += 8; + } else { + ret |= (uint64_t)jxl_bits(4) << shift; + break; + } + } + break; + } + + return ret; +} + +static uint32_t jpegxl_width_from_ratio(uint32_t height, int ratio) +{ + uint64_t height64 = height; /* avoid integer overflow */ + switch (ratio) { + case 1: + return height; + case 2: + return (uint32_t)((height64 * 12) / 10); + case 3: + return (uint32_t)((height64 * 4) / 3); + case 4: + return (uint32_t)((height64 * 3) / 2); + case 5: + return (uint32_t)((height64 * 16) / 9); + case 6: + return (uint32_t)((height64 * 5) / 4); + case 7: + return (uint32_t)(height64 * 2); + default: + break; + } + + return 0; /* manual width */ +} + +/** + * validate a Jpeg XL Size Header + * @return >= 0 upon valid size, < 0 upon invalid size found + */ +static int jpegxl_read_size_header(GetBitContext *gb) +{ + uint32_t width, height; + + if (jxl_bits(1)) { + /* small size header */ + height = (jxl_bits(5) + 1) << 3; + width = jpegxl_width_from_ratio(height, jxl_bits(3)); + if (!width) + width = (jxl_bits(5) + 1) << 3; + } else { + /* large size header */ + height = 1 + jxl_u32(0, 0, 0, 0, 9, 13, 18, 30); + width = jpegxl_width_from_ratio(height, jxl_bits(3)); + if (!width) + width = 1 + jxl_u32(0, 0, 0, 0, 9, 13, 18, 30); + } + if (width > (1 << 18) || height > (1 << 18) + || (width >> 4) * (height >> 4) > (1 << 20)) + return -1; + + return 0; +} + +/** + * validate a Jpeg XL Preview Header + * @return >= 0 upon valid size, < 0 upon invalid size found + */ +static int jpegxl_read_preview_header(GetBitContext *gb) +{ + uint32_t width, height; + + if (jxl_bits(1)) { + /* coded height and width divided by eight */ + height = jxl_u32(16, 32, 1, 33, 0, 0, 5, 9) << 3; + width = jpegxl_width_from_ratio(height, jxl_bits(3)); + if (!width) + width = jxl_u32(16, 32, 1, 33, 0, 0, 5, 9) << 3; + } else { + /* full height and width coded */ + height = jxl_u32(1, 65, 321, 1345, 6, 8, 10, 12); + width = jpegxl_width_from_ratio(height, jxl_bits(3)); + if (!width) + width = jxl_u32(1, 65, 321, 1345, 6, 8, 10, 12); + } + if (width > 4096 || height > 4096) + return -1; + + return 0; +} + +/** + * skip a Jpeg XL BitDepth Header. These cannot be invalid. + */ +static void jpegxl_skip_bit_depth(GetBitContext *gb) +{ + if (jxl_bits(1)) { + /* float samples */ + jxl_u32(32, 16, 24, 1, 0, 0, 0, 6); /* mantissa */ + jxl_bits_skip(4); /* exponent */ + } else { + /* integer samples */ + jxl_u32(8, 10, 12, 1, 0, 0, 0, 6); + } +} + +/** + * validate a Jpeg XL Extra Channel Info bundle + * @return >= 0 upon valid, < 0 upon invalid + */ +static int jpegxl_read_extra_channel_info(GetBitContext *gb) +{ + int all_default = jxl_bits(1); + uint32_t type, name_len = 0; + + if (!all_default) { + type = jxl_enum(); + if (type > 63) + return -1; /* enum types cannot be 64+ */ + if (type == FF_JPEGXL_CT_BLACK) + return -1; + jpegxl_skip_bit_depth(gb); + jxl_u32(0, 3, 4, 1, 0, 0, 0, 3); /* dim-shift */ + /* max of name_len is 1071 = 48 + 2^10 - 1 */ + name_len = jxl_u32(0, 0, 16, 48, 0, 4, 5, 10); + } else { + type = FF_JPEGXL_CT_ALPHA; + } + + /* skip over the name */ + jxl_bits_skip(8 * name_len); + + if (!all_default && type == FF_JPEGXL_CT_ALPHA) + jxl_bits_skip(1); + + if (type == FF_JPEGXL_CT_SPOT_COLOR) + jxl_bits_skip(16 * 4); + + if (type == FF_JPEGXL_CT_CFA) + jxl_u32(1, 0, 3, 19, 0, 2, 4, 8); + + return 0; +} + +/* verify that a codestream header is valid */ +int ff_jpegxl_verify_codestream_header(const uint8_t *buf, int buflen) +{ + GetBitContext gbi, *gb = &gbi; + int all_default, extra_fields = 0; + int xyb_encoded = 1, have_icc_profile = 0; + uint32_t num_extra_channels; + uint64_t extensions; + int ret; + + ret = init_get_bits8(gb, buf, buflen); + if (ret < 0) + return ret; + + if (jxl_bits(16) != FF_JPEGXL_CODESTREAM_SIGNATURE_LE) + return -1; + + if (jpegxl_read_size_header(gb) < 0) + return -1; + + all_default = jxl_bits(1); + if (!all_default) + extra_fields = jxl_bits(1); + + if (extra_fields) { + jxl_bits_skip(3); /* orientation */ + + /* + * intrinstic size + * any size header here is valid, but as it + * is variable length we have to read it + */ + if (jxl_bits(1)) + jpegxl_read_size_header(gb); + + /* preview header */ + if (jxl_bits(1)) { + if (jpegxl_read_preview_header(gb) < 0) + return -1; + } + + /* animation header */ + if (jxl_bits(1)) { + jxl_u32(100, 1000, 1, 1, 0, 0, 10, 30); + jxl_u32(1, 1001, 1, 1, 0, 0, 8, 10); + jxl_u32(0, 0, 0, 0, 0, 3, 16, 32); + jxl_bits_skip(1); + } + } + + if (!all_default) { + jpegxl_skip_bit_depth(gb); + + /* modular_16bit_buffers must equal 1 */ + if (!jxl_bits(1)) + return -1; + + num_extra_channels = jxl_u32(0, 1, 2, 1, 0, 0, 4, 12); + if (num_extra_channels > 4) + return -1; + for (uint32_t i = 0; i < num_extra_channels; i++) { + if (jpegxl_read_extra_channel_info(gb) < 0) + return -1; + } + + xyb_encoded = jxl_bits(1); + + /* color encoding bundle */ + if (!jxl_bits(1)) { + uint32_t color_space; + have_icc_profile = jxl_bits(1); + color_space = jxl_enum(); + if (color_space > 63) + return -1; + + if (!have_icc_profile) { + if (color_space != FF_JPEGXL_CS_XYB) { + uint32_t white_point = jxl_enum(); + if (white_point > 63) + return -1; + if (white_point == FF_JPEGXL_WP_CUSTOM) { + /* ux and uy values */ + jxl_u32(0, 524288, 1048576, 2097152, 19, 19, 20, 21); + jxl_u32(0, 524288, 1048576, 2097152, 19, 19, 20, 21); + } + if (color_space != FF_JPEGXL_CS_GRAY) { + /* primaries */ + uint32_t primaries = jxl_enum(); + if (primaries > 63) + return -1; + if (primaries == FF_JPEGXL_PR_CUSTOM) { + /* ux/uy values for r,g,b */ + for (int i = 0; i < 6; i++) + jxl_u32(0, 524288, 1048576, 2097152, 19, 19, 20, 21); + } + } + } + + /* transfer characteristics */ + if (jxl_bits(1)) { + /* gamma */ + jxl_bits_skip(24); + } else { + /* transfer function */ + if (jxl_enum() > 63) + return -1; + } + + /* rendering intent */ + if (jxl_enum() > 63) + return -1; + } + } + + /* tone mapping bundle */ + if (extra_fields && !jxl_bits(1)) + jxl_bits_skip(16 + 16 + 1 + 16); + + extensions = jxl_u64(); + if (extensions) { + for (int i = 0; i < 64; i++) { + if (extensions & (UINT64_C(1) << i)) + jxl_u64(); + } + } + } + + /* default transform */ + if (!jxl_bits(1)) { + /* opsin inverse matrix */ + if (xyb_encoded && !jxl_bits(1)) + jxl_bits_skip(16 * 16); + /* cw_mask and default weights */ + if (jxl_bits(1)) + jxl_bits_skip(16 * 15); + if (jxl_bits(1)) + jxl_bits_skip(16 * 55); + if (jxl_bits(1)) + jxl_bits_skip(16 * 210); + } + + if (!have_icc_profile) { + int bits_remaining = 7 - (get_bits_count(gb) - 1) % 8; + if (bits_remaining && jxl_bits(bits_remaining)) + return -1; + } + + if (get_bits_left(gb) < 0) + return -1; + + return 0; +} diff --git a/libavformat/jpegxl_probe.h b/libavformat/jpegxl_probe.h new file mode 100644 index 000000000..2960e81e1 --- /dev/null +++ b/libavformat/jpegxl_probe.h @@ -0,0 +1,32 @@ +/* + * Jpeg XL header verification + * Copyright (c) 2022 Leo Izen + * + * 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_JPEGXL_PROBE_H +#define AVFORMAT_JPEGXL_PROBE_H + +#include + +#define FF_JPEGXL_CODESTREAM_SIGNATURE_LE 0x0aff +#define FF_JPEGXL_CONTAINER_SIGNATURE_LE 0x204c584a0c000000 + +int ff_jpegxl_verify_codestream_header(const uint8_t *buf, int buflen); + +#endif /* AVFORMAT_JPEGXL_PROBE_H */ diff --git a/libavformat/jvdec.c b/libavformat/jvdec.c index 93569c87d..5e0e2239f 100644 --- a/libavformat/jvdec.c +++ b/libavformat/jvdec.c @@ -102,8 +102,7 @@ static int read_header(AVFormatContext *s) ast->codecpar->codec_id = AV_CODEC_ID_PCM_U8; ast->codecpar->codec_tag = 0; /* no fourcc */ ast->codecpar->sample_rate = avio_rl16(pb); - ast->codecpar->channels = 1; - ast->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + ast->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; avpriv_set_pts_info(ast, 64, 1, ast->codecpar->sample_rate); avio_skip(pb, 10); diff --git a/libavformat/kvag.c b/libavformat/kvag.c index a277c2812..7c3816ab8 100644 --- a/libavformat/kvag.c +++ b/libavformat/kvag.c @@ -20,6 +20,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/channel_layout.h" #include "avformat.h" #include "avio_internal.h" @@ -71,18 +73,11 @@ static int kvag_read_header(AVFormatContext *s) par->codec_id = AV_CODEC_ID_ADPCM_IMA_SSI; par->format = AV_SAMPLE_FMT_S16; - if (hdr.stereo) { - par->channel_layout = AV_CH_LAYOUT_STEREO; - par->channels = 2; - } else { - par->channel_layout = AV_CH_LAYOUT_MONO; - par->channels = 1; - } - + av_channel_layout_default(&par->ch_layout, !!hdr.stereo + 1); par->sample_rate = hdr.sample_rate; par->bits_per_coded_sample = 4; par->block_align = 1; - par->bit_rate = par->channels * + par->bit_rate = par->ch_layout.nb_channels * (uint64_t)par->sample_rate * par->bits_per_coded_sample; @@ -90,7 +85,7 @@ static int kvag_read_header(AVFormatContext *s) st->start_time = 0; st->duration = hdr.data_size * (8 / par->bits_per_coded_sample) / - par->channels; + par->ch_layout.nb_channels; return 0; } @@ -105,7 +100,7 @@ static int kvag_read_packet(AVFormatContext *s, AVPacket *pkt) pkt->flags &= ~AV_PKT_FLAG_CORRUPT; pkt->stream_index = 0; - pkt->duration = ret * (8 / par->bits_per_coded_sample) / par->channels; + pkt->duration = ret * (8 / par->bits_per_coded_sample) / par->ch_layout.nb_channels; return 0; } @@ -147,7 +142,7 @@ static int kvag_write_init(AVFormatContext *s) return AVERROR(EINVAL); } - if (par->channels > 2) { + if (par->ch_layout.nb_channels > 2) { av_log(s, AV_LOG_ERROR, "KVAG files only support up to 2 channels\n"); return AVERROR(EINVAL); } @@ -168,7 +163,7 @@ static int kvag_write_header(AVFormatContext *s) AV_WL32(buf + 0, KVAG_TAG); AV_WL32(buf + 4, 0); /* Data size, we fix this up later. */ AV_WL32(buf + 8, par->sample_rate); - AV_WL16(buf + 12, par->channels == 2); + AV_WL16(buf + 12, par->ch_layout.nb_channels == 2); avio_write(s->pb, buf, sizeof(buf)); return 0; diff --git a/libavformat/latmenc.c b/libavformat/latmenc.c index 72865c956..6553c28d9 100644 --- a/libavformat/latmenc.c +++ b/libavformat/latmenc.c @@ -28,6 +28,7 @@ #include "libavutil/opt.h" #include "avformat.h" #include "internal.h" +#include "mux.h" #include "rawenc.h" #define MAX_EXTRADATA_SIZE 1024 diff --git a/libavformat/libgme.c b/libavformat/libgme.c index 6a145349a..695155c9a 100644 --- a/libavformat/libgme.c +++ b/libavformat/libgme.c @@ -142,7 +142,7 @@ static int read_header_gme(AVFormatContext *s) st->duration = duration; st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE); - st->codecpar->channels = 2; + st->codecpar->ch_layout.nb_channels = 2; st->codecpar->sample_rate = gme->sample_rate; return 0; diff --git a/libavformat/libmodplug.c b/libavformat/libmodplug.c index 8f8d0e974..0cae13bd2 100644 --- a/libavformat/libmodplug.c +++ b/libavformat/libmodplug.c @@ -238,7 +238,7 @@ static int modplug_read_header(AVFormatContext *s) st->duration = ModPlug_GetLength(modplug->f); st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE; - st->codecpar->channels = settings.mChannels; + st->codecpar->ch_layout.nb_channels = settings.mChannels; st->codecpar->sample_rate = settings.mFrequency; // timebase = 1/1000, 2ch 16bits 44.1kHz-> 2*2*44100 diff --git a/libavformat/libopenmpt.c b/libavformat/libopenmpt.c index 8006c085d..3ca59f506 100644 --- a/libavformat/libopenmpt.c +++ b/libavformat/libopenmpt.c @@ -40,11 +40,10 @@ typedef struct OpenMPTContext { const AVClass *class; openmpt_module *module; - int channels; double duration; /* options */ int sample_rate; - int64_t layout; + AVChannelLayout ch_layout; int subsong; } OpenMPTContext; @@ -53,7 +52,7 @@ typedef struct OpenMPTContext { #define D AV_OPT_FLAG_DECODING_PARAM static const AVOption options[] = { { "sample_rate", "set sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, { .i64 = 48000 }, 1000, INT_MAX, A | D }, - { "layout", "set channel layout", OFFSET(layout), AV_OPT_TYPE_CHANNEL_LAYOUT, { .i64 = AV_CH_LAYOUT_STEREO }, 0, INT64_MAX, A | D }, + { "layout", "set channel layout", OFFSET(ch_layout), AV_OPT_TYPE_CHLAYOUT, { .str = "stereo" }, 0, 0, A | D }, { "subsong", "set subsong", OFFSET(subsong), AV_OPT_TYPE_INT, { .i64 = -2 }, -2, INT_MAX, A | D, "subsong"}, { "all", "all", 0, AV_OPT_TYPE_CONST, { .i64 = -1}, 0, 0, A | D, "subsong" }, { "auto", "auto", 0, AV_OPT_TYPE_CONST, { .i64 = -2}, 0, 0, A | D, "subsong" }, @@ -120,8 +119,6 @@ static int read_header_openmpt(AVFormatContext *s) return AVERROR_INVALIDDATA; #endif - openmpt->channels = av_get_channel_layout_nb_channels(openmpt->layout); - if (openmpt->subsong >= openmpt_module_get_num_subsongs(openmpt->module)) { av_log(s, AV_LOG_ERROR, "Invalid subsong index: %d\n", openmpt->subsong); return AVERROR(EINVAL); @@ -154,8 +151,10 @@ static int read_header_openmpt(AVFormatContext *s) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_NE(AV_CODEC_ID_PCM_F32BE, AV_CODEC_ID_PCM_F32LE); - st->codecpar->channels = openmpt->channels; st->codecpar->sample_rate = openmpt->sample_rate; + ret = av_channel_layout_copy(&st->codecpar->ch_layout, &openmpt->ch_layout); + if (ret < 0) + return ret; return 0; } @@ -165,13 +164,13 @@ static int read_header_openmpt(AVFormatContext *s) static int read_packet_openmpt(AVFormatContext *s, AVPacket *pkt) { OpenMPTContext *openmpt = s->priv_data; - int n_samples = AUDIO_PKT_SIZE / (openmpt->channels ? openmpt->channels*4 : 4); + int n_samples = AUDIO_PKT_SIZE / (openmpt->ch_layout.nb_channels ? openmpt->ch_layout.nb_channels*4 : 4); int ret; if ((ret = av_new_packet(pkt, AUDIO_PKT_SIZE)) < 0) return ret; - switch (openmpt->channels) { + switch (openmpt->ch_layout.nb_channels) { case 1: ret = openmpt_module_read_float_mono(openmpt->module, openmpt->sample_rate, n_samples, (float *)pkt->data); @@ -185,7 +184,7 @@ static int read_packet_openmpt(AVFormatContext *s, AVPacket *pkt) n_samples, (float *)pkt->data); break; default: - av_log(s, AV_LOG_ERROR, "Unsupported number of channels: %d", openmpt->channels); + av_log(s, AV_LOG_ERROR, "Unsupported number of channels: %d", openmpt->ch_layout.nb_channels); return AVERROR(EINVAL); } @@ -194,7 +193,7 @@ static int read_packet_openmpt(AVFormatContext *s, AVPacket *pkt) return AVERROR_EOF; } - pkt->size = ret * (openmpt->channels * 4); + pkt->size = ret * (openmpt->ch_layout.nb_channels * 4); return 0; } diff --git a/libavformat/librist.c b/libavformat/librist.c index 378b635ea..5f27cacd4 100644 --- a/libavformat/librist.c +++ b/libavformat/librist.c @@ -38,11 +38,7 @@ // RIST_MAX_PACKET_SIZE - 28 minimum protocol overhead #define MAX_PAYLOAD_SIZE (10000-28) - -#define FF_LIBRIST_MAKE_VERSION(major, minor, patch) \ - ((patch) + ((minor)* 0x100) + ((major) *0x10000)) -#define FF_LIBRIST_VERSION FF_LIBRIST_MAKE_VERSION(LIBRIST_API_VERSION_MAJOR, LIBRIST_API_VERSION_MINOR, LIBRIST_API_VERSION_PATCH) -#define FF_LIBRIST_VERSION_41 FF_LIBRIST_MAKE_VERSION(4, 1, 0) +#define FIFO_SIZE_DEFAULT 8192 typedef struct RISTContext { const AVClass *class; @@ -52,6 +48,8 @@ typedef struct RISTContext { int packet_size; int log_level; int encryption; + int fifo_size; + int overrun_nonfatal; char *secret; struct rist_logging_settings logging_settings; @@ -70,6 +68,8 @@ static const AVOption librist_options[] = { { "main", NULL, 0, AV_OPT_TYPE_CONST, {.i64=RIST_PROFILE_MAIN}, 0, 0, .flags = D|E, "profile" }, { "advanced", NULL, 0, AV_OPT_TYPE_CONST, {.i64=RIST_PROFILE_ADVANCED}, 0, 0, .flags = D|E, "profile" }, { "buffer_size", "set buffer_size in ms", OFFSET(buffer_size), AV_OPT_TYPE_INT, {.i64=0}, 0, 30000, .flags = D|E }, + { "fifo_size", "set fifo buffer size, must be a power of 2", OFFSET(fifo_size), AV_OPT_TYPE_INT, {.i64=FIFO_SIZE_DEFAULT}, 32, 262144, .flags = D|E }, + { "overrun_nonfatal", "survive in case of receiving fifo buffer overrun", OFFSET(overrun_nonfatal), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, D }, { "pkt_size", "set packet size", OFFSET(packet_size), AV_OPT_TYPE_INT, {.i64=1316}, 1, MAX_PAYLOAD_SIZE, .flags = D|E }, { "log_level", "set loglevel", OFFSET(log_level), AV_OPT_TYPE_INT, {.i64=RIST_LOG_INFO}, -1, INT_MAX, .flags = D|E }, { "secret", "set encryption secret",OFFSET(secret), AV_OPT_TYPE_STRING,{.str=NULL}, 0, 0, .flags = D|E }, @@ -153,14 +153,16 @@ static int librist_open(URLContext *h, const char *uri, int flags) if (ret < 0) goto err; -#if FF_LIBRIST_VERSION < FF_LIBRIST_VERSION_41 - ret = rist_parse_address(uri, (const struct rist_peer_config **)&peer_config); -#else ret = rist_parse_address2(uri, &peer_config); -#endif if (ret < 0) goto err; + if (flags & AVIO_FLAG_READ) { + ret = rist_receiver_set_output_fifo_size(s->ctx, s->fifo_size); + if (ret != 0) + goto err; + } + if (((s->encryption == 128 || s->encryption == 256) && !s->secret) || ((peer_config->key_size == 128 || peer_config->key_size == 256) && !peer_config->secret[0])) { av_log(h, AV_LOG_ERROR, "secret is mandatory if encryption is enabled\n"); @@ -200,13 +202,8 @@ static int librist_read(URLContext *h, uint8_t *buf, int size) RISTContext *s = h->priv_data; int ret; -#if FF_LIBRIST_VERSION < FF_LIBRIST_VERSION_41 - const struct rist_data_block *data_block; - ret = rist_receiver_data_read(s->ctx, &data_block, POLLING_TIME); -#else struct rist_data_block *data_block; ret = rist_receiver_data_read2(s->ctx, &data_block, POLLING_TIME); -#endif if (ret < 0) return risterr2ret(ret); @@ -215,21 +212,24 @@ static int librist_read(URLContext *h, uint8_t *buf, int size) return AVERROR(EAGAIN); if (data_block->payload_len > MAX_PAYLOAD_SIZE) { -#if FF_LIBRIST_VERSION < FF_LIBRIST_VERSION_41 - rist_receiver_data_block_free((struct rist_data_block**)&data_block); -#else rist_receiver_data_block_free2(&data_block); -#endif return AVERROR_EXTERNAL; } + if (data_block->flags & RIST_DATA_FLAGS_OVERFLOW) { + if (!s->overrun_nonfatal) { + av_log(h, AV_LOG_ERROR, "Fifo buffer overrun. " + "To avoid, increase fifo_size option. " + "To survive in such case, use overrun_nonfatal option\n"); + size = AVERROR(EIO); + goto out_free; + } + } + size = data_block->payload_len; memcpy(buf, data_block->payload, size); -#if FF_LIBRIST_VERSION < FF_LIBRIST_VERSION_41 - rist_receiver_data_block_free((struct rist_data_block**)&data_block); -#else +out_free: rist_receiver_data_block_free2(&data_block); -#endif return size; } diff --git a/libavformat/librtmp.c b/libavformat/librtmp.c index 43013e46e..b7e9fc81c 100644 --- a/libavformat/librtmp.c +++ b/libavformat/librtmp.c @@ -25,6 +25,7 @@ */ #include "libavutil/avstring.h" +#include "libavutil/bprint.h" #include "libavutil/mathematics.h" #include "libavutil/opt.h" #include "avformat.h" @@ -38,6 +39,7 @@ typedef struct LibRTMPContext { const AVClass *class; + AVBPrint filename; RTMP rtmp; char *app; char *conn; @@ -50,7 +52,6 @@ typedef struct LibRTMPContext { char *pageurl; char *client_buffer_time; int live; - char *temp_filename; int buffer_size; } LibRTMPContext; @@ -76,7 +77,7 @@ static int rtmp_close(URLContext *s) RTMP *r = &ctx->rtmp; RTMP_Close(r); - av_freep(&ctx->temp_filename); + av_bprint_finalize(&ctx->filename, NULL); return 0; } @@ -97,8 +98,8 @@ static int rtmp_open(URLContext *s, const char *uri, int flags) LibRTMPContext *ctx = s->priv_data; RTMP *r = &ctx->rtmp; int rc = 0, level; - char *filename = s->filename; - int len = strlen(s->filename) + 1; + /* This needs to stay allocated for as long as the RTMP context exists. */ + av_bprint_init(&ctx->filename, 0, AV_BPRINT_SIZE_UNLIMITED); switch (av_log_get_level()) { default: @@ -112,84 +113,28 @@ static int rtmp_open(URLContext *s, const char *uri, int flags) RTMP_LogSetLevel(level); RTMP_LogSetCallback(rtmp_log); - if (ctx->app) len += strlen(ctx->app) + sizeof(" app="); - if (ctx->tcurl) len += strlen(ctx->tcurl) + sizeof(" tcUrl="); - if (ctx->pageurl) len += strlen(ctx->pageurl) + sizeof(" pageUrl="); - if (ctx->flashver) len += strlen(ctx->flashver) + sizeof(" flashver="); - - if (ctx->conn) { - char *sep, *p = ctx->conn; - int options = 0; - - while (p) { - options++; - p += strspn(p, " "); - if (!*p) - break; - sep = strchr(p, ' '); - if (sep) - p = sep + 1; - else - break; - } - len += options * sizeof(" conn="); - len += strlen(ctx->conn); - } - - if (ctx->playpath) - len += strlen(ctx->playpath) + sizeof(" playpath="); - if (ctx->live) - len += sizeof(" live=1"); - if (ctx->subscribe) - len += strlen(ctx->subscribe) + sizeof(" subscribe="); - - if (ctx->client_buffer_time) - len += strlen(ctx->client_buffer_time) + sizeof(" buffer="); - - if (ctx->swfurl || ctx->swfverify) { - len += sizeof(" swfUrl="); - - if (ctx->swfverify) - len += strlen(ctx->swfverify) + sizeof(" swfVfy=1"); - else - len += strlen(ctx->swfurl); - } - - if (!(ctx->temp_filename = filename = av_malloc(len))) - return AVERROR(ENOMEM); - - av_strlcpy(filename, s->filename, len); - if (ctx->app) { - av_strlcat(filename, " app=", len); - av_strlcat(filename, ctx->app, len); - } - if (ctx->tcurl) { - av_strlcat(filename, " tcUrl=", len); - av_strlcat(filename, ctx->tcurl, len); - } - if (ctx->pageurl) { - av_strlcat(filename, " pageUrl=", len); - av_strlcat(filename, ctx->pageurl, len); - } - if (ctx->swfurl) { - av_strlcat(filename, " swfUrl=", len); - av_strlcat(filename, ctx->swfurl, len); - } - if (ctx->flashver) { - av_strlcat(filename, " flashVer=", len); - av_strlcat(filename, ctx->flashver, len); - } + av_bprintf(&ctx->filename, "%s", s->filename); + if (ctx->app) + av_bprintf(&ctx->filename, " app=%s", ctx->app); + if (ctx->tcurl) + av_bprintf(&ctx->filename, " tcUrl=%s", ctx->tcurl); + if (ctx->pageurl) + av_bprintf(&ctx->filename, " pageUrl=%s", ctx->pageurl); + if (ctx->swfurl) + av_bprintf(&ctx->filename, " swfUrl=%s", ctx->swfurl); + if (ctx->flashver) + av_bprintf(&ctx->filename, " flashVer=%s", ctx->flashver); if (ctx->conn) { char *sep, *p = ctx->conn; while (p) { - av_strlcat(filename, " conn=", len); + av_bprintf(&ctx->filename, " conn="); p += strspn(p, " "); if (!*p) break; sep = strchr(p, ' '); if (sep) *sep = '\0'; - av_strlcat(filename, p, len); + av_bprintf(&ctx->filename, "%s", p); if (sep) p = sep + 1; @@ -197,33 +142,29 @@ static int rtmp_open(URLContext *s, const char *uri, int flags) break; } } - if (ctx->playpath) { - av_strlcat(filename, " playpath=", len); - av_strlcat(filename, ctx->playpath, len); - } + if (ctx->playpath) + av_bprintf(&ctx->filename, " playpath=%s", ctx->playpath); if (ctx->live) - av_strlcat(filename, " live=1", len); - if (ctx->subscribe) { - av_strlcat(filename, " subscribe=", len); - av_strlcat(filename, ctx->subscribe, len); - } - if (ctx->client_buffer_time) { - av_strlcat(filename, " buffer=", len); - av_strlcat(filename, ctx->client_buffer_time, len); - } + av_bprintf(&ctx->filename, " live=1"); + if (ctx->subscribe) + av_bprintf(&ctx->filename, " subscribe=%s", ctx->subscribe); + if (ctx->client_buffer_time) + av_bprintf(&ctx->filename, " buffer=%s", ctx->client_buffer_time); if (ctx->swfurl || ctx->swfverify) { - av_strlcat(filename, " swfUrl=", len); + if (ctx->swfverify) + av_bprintf(&ctx->filename, " swfUrl=%s swfVfy=1", ctx->swfverify); + else + av_bprintf(&ctx->filename, " swfUrl=%s", ctx->swfurl); + } - if (ctx->swfverify) { - av_strlcat(filename, ctx->swfverify, len); - av_strlcat(filename, " swfVfy=1", len); - } else { - av_strlcat(filename, ctx->swfurl, len); - } + if (!av_bprint_is_complete(&ctx->filename)) { + av_bprint_finalize(&ctx->filename, NULL); + return AVERROR(ENOMEM); } RTMP_Init(r); - if (!RTMP_SetupURL(r, filename)) { + /* This will modify filename by null terminating the URL portion */ + if (!RTMP_SetupURL(r, ctx->filename.str)) { rc = AVERROR_UNKNOWN; goto fail; } @@ -249,9 +190,10 @@ static int rtmp_open(URLContext *s, const char *uri, int flags) s->is_streamed = 1; return 0; fail: - av_freep(&ctx->temp_filename); + if (rc) RTMP_Close(r); + av_bprint_finalize(&ctx->filename, NULL); return rc; } diff --git a/libavformat/libsrt.c b/libavformat/libsrt.c index 19b9cb989..cd8f5b1e7 100644 --- a/libavformat/libsrt.c +++ b/libavformat/libsrt.c @@ -429,7 +429,11 @@ static int libsrt_setup(URLContext *h, const char *uri, int flags) restart: +#if SRT_VERSION_VALUE >= 0x010401 + fd = srt_create_socket(); +#else fd = srt_socket(cur_ai->ai_family, cur_ai->ai_socktype, 0); +#endif if (fd < 0) { ret = libsrt_neterrno(h); goto fail; @@ -525,7 +529,7 @@ static int libsrt_open(URLContext *h, const char *uri, int flags) { SRTContext *s = h->priv_data; const char * p; - char buf[256]; + char buf[1024]; int ret = 0; if (srt_startup() < 0) { diff --git a/libavformat/libzmq.c b/libavformat/libzmq.c index 1b0d8638d..04c72ac60 100644 --- a/libavformat/libzmq.c +++ b/libavformat/libzmq.c @@ -51,7 +51,7 @@ static int zmq_proto_wait(URLContext *h, void *socket, int write) zmq_pollitem_t items = { .socket = socket, .fd = 0, .events = ev, .revents = 0 }; ret = zmq_poll(&items, 1, POLLING_TIME); if (ret == -1) { - av_log(h, AV_LOG_ERROR, "Error occured during zmq_poll(): %s\n", ZMQ_STRERROR); + av_log(h, AV_LOG_ERROR, "Error occurred during zmq_poll(): %s\n", ZMQ_STRERROR); return AVERROR_EXTERNAL; } return items.revents & ev ? 0 : AVERROR(EAGAIN); @@ -90,7 +90,7 @@ static int zmq_proto_open(URLContext *h, const char *uri, int flags) s->context = zmq_ctx_new(); if (!s->context) { /*errno not set on failure during zmq_ctx_new()*/ - av_log(h, AV_LOG_ERROR, "Error occured during zmq_ctx_new()\n"); + av_log(h, AV_LOG_ERROR, "Error occurred during zmq_ctx_new()\n"); return AVERROR_EXTERNAL; } @@ -100,13 +100,13 @@ static int zmq_proto_open(URLContext *h, const char *uri, int flags) if (h->flags & AVIO_FLAG_WRITE) { s->socket = zmq_socket(s->context, ZMQ_PUB); if (!s->socket) { - av_log(h, AV_LOG_ERROR, "Error occured during zmq_socket(): %s\n", ZMQ_STRERROR); + av_log(h, AV_LOG_ERROR, "Error occurred during zmq_socket(): %s\n", ZMQ_STRERROR); goto fail_term; } ret = zmq_bind(s->socket, uri); if (ret == -1) { - av_log(h, AV_LOG_ERROR, "Error occured during zmq_bind(): %s\n", ZMQ_STRERROR); + av_log(h, AV_LOG_ERROR, "Error occurred during zmq_bind(): %s\n", ZMQ_STRERROR); goto fail_close; } } @@ -115,19 +115,19 @@ static int zmq_proto_open(URLContext *h, const char *uri, int flags) if (h->flags & AVIO_FLAG_READ) { s->socket = zmq_socket(s->context, ZMQ_SUB); if (!s->socket) { - av_log(h, AV_LOG_ERROR, "Error occured during zmq_socket(): %s\n", ZMQ_STRERROR); + av_log(h, AV_LOG_ERROR, "Error occurred during zmq_socket(): %s\n", ZMQ_STRERROR); goto fail_term; } ret = zmq_setsockopt(s->socket, ZMQ_SUBSCRIBE, "", 0); if (ret == -1) { - av_log(h, AV_LOG_ERROR, "Error occured during zmq_setsockopt(): %s\n", ZMQ_STRERROR); + av_log(h, AV_LOG_ERROR, "Error occurred during zmq_setsockopt(): %s\n", ZMQ_STRERROR); goto fail_close; } ret = zmq_connect(s->socket, uri); if (ret == -1) { - av_log(h, AV_LOG_ERROR, "Error occured during zmq_connect(): %s\n", ZMQ_STRERROR); + av_log(h, AV_LOG_ERROR, "Error occurred during zmq_connect(): %s\n", ZMQ_STRERROR); goto fail_close; } } @@ -150,7 +150,7 @@ static int zmq_proto_write(URLContext *h, const unsigned char *buf, int size) return ret; ret = zmq_send(s->socket, buf, size, 0); if (ret == -1) { - av_log(h, AV_LOG_ERROR, "Error occured during zmq_send(): %s\n", ZMQ_STRERROR); + av_log(h, AV_LOG_ERROR, "Error occurred during zmq_send(): %s\n", ZMQ_STRERROR); return AVERROR_EXTERNAL; } return ret; /*number of bytes sent*/ @@ -166,7 +166,7 @@ static int zmq_proto_read(URLContext *h, unsigned char *buf, int size) return ret; ret = zmq_recv(s->socket, buf, size, 0); if (ret == -1) { - av_log(h, AV_LOG_ERROR, "Error occured during zmq_recv(): %s\n", ZMQ_STRERROR); + av_log(h, AV_LOG_ERROR, "Error occurred during zmq_recv(): %s\n", ZMQ_STRERROR); return AVERROR_EXTERNAL; } if (ret > size) { diff --git a/libavformat/lrcenc.c b/libavformat/lrcenc.c index 5703a9518..cdf94e6cd 100644 --- a/libavformat/lrcenc.c +++ b/libavformat/lrcenc.c @@ -27,6 +27,7 @@ #include "internal.h" #include "lrc.h" #include "metadata.h" +#include "mux.h" #include "version.h" #include "libavutil/dict.h" #include "libavutil/log.h" diff --git a/libavformat/lvfdec.c b/libavformat/lvfdec.c index cd64fb9ae..cc1e9be58 100644 --- a/libavformat/lvfdec.c +++ b/libavformat/lvfdec.c @@ -79,7 +79,7 @@ static int lvf_read_header(AVFormatContext *s) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_tag = avio_rl16(s->pb); - st->codecpar->channels = avio_rl16(s->pb); + st->codecpar->ch_layout.nb_channels = avio_rl16(s->pb); st->codecpar->sample_rate = avio_rl16(s->pb); avio_skip(s->pb, 8); st->codecpar->bits_per_coded_sample = avio_r8(s->pb); diff --git a/libavformat/lxfdec.c b/libavformat/lxfdec.c index 7889abb2c..8003ae98b 100644 --- a/libavformat/lxfdec.c +++ b/libavformat/lxfdec.c @@ -24,6 +24,7 @@ #include "libavutil/intreadwrite.h" #include "libavcodec/bytestream.h" #include "avformat.h" +#include "demux.h" #include "internal.h" #define LXF_MAX_PACKET_HEADER_SIZE 256 @@ -281,7 +282,7 @@ static int lxf_read_header(AVFormatContext *s) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->sample_rate = LXF_SAMPLERATE; - st->codecpar->channels = lxf->channels; + st->codecpar->ch_layout.nb_channels = lxf->channels; avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); } diff --git a/libavformat/matroska.c b/libavformat/matroska.c index 7c56aba40..90d94b65b 100644 --- a/libavformat/matroska.c +++ b/libavformat/matroska.c @@ -78,6 +78,8 @@ const CodecTags ff_mkv_codec_tags[]={ {"S_HDMV/TEXTST" , AV_CODEC_ID_HDMV_TEXT_SUBTITLE}, {"V_AV1" , AV_CODEC_ID_AV1}, + {"V_AVS2" , AV_CODEC_ID_AVS2}, + {"V_AVS3" , AV_CODEC_ID_AVS3}, {"V_DIRAC" , AV_CODEC_ID_DIRAC}, {"V_FFV1" , AV_CODEC_ID_FFV1}, {"V_MJPEG" , AV_CODEC_ID_MJPEG}, diff --git a/libavformat/matroska.h b/libavformat/matroska.h index 16491aae2..45077ed33 100644 --- a/libavformat/matroska.h +++ b/libavformat/matroska.h @@ -23,8 +23,8 @@ #define AVFORMAT_MATROSKA_H #include "libavcodec/codec_id.h" +#include "avformat.h" #include "metadata.h" -#include "internal.h" /* EBML version supported */ #define EBML_VERSION 1 diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index 4fd4bb94b..ad7ee390a 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -29,6 +29,7 @@ */ #include "config.h" +#include "config_components.h" #include #include @@ -37,6 +38,7 @@ #include "libavutil/base64.h" #include "libavutil/bprint.h" #include "libavutil/dict.h" +#include "libavutil/display.h" #include "libavutil/intfloat.h" #include "libavutil/intreadwrite.h" #include "libavutil/lzo.h" @@ -53,6 +55,7 @@ #include "avformat.h" #include "avio_internal.h" +#include "demux.h" #include "dovi_isom.h" #include "internal.h" #include "isom.h" @@ -803,7 +806,6 @@ static const CodecMime mkv_image_mime_tags[] = { }; static const CodecMime mkv_mime_tags[] = { - {"text/plain" , AV_CODEC_ID_TEXT}, {"application/x-truetype-font", AV_CODEC_ID_TTF}, {"application/x-font" , AV_CODEC_ID_TTF}, {"application/vnd.ms-opentype", AV_CODEC_ID_OTF}, @@ -1683,7 +1685,6 @@ static int matroska_decode_buffer(uint8_t **buf, int *buf_size, memcpy(pkt_data + header_size, data, isize); break; } -#if CONFIG_LZO case MATROSKA_TRACK_ENCODING_COMP_LZO: do { int insize = isize; @@ -1703,7 +1704,6 @@ static int matroska_decode_buffer(uint8_t **buf, int *buf_size, } pkt_size -= olen; break; -#endif #if CONFIG_ZLIB case MATROSKA_TRACK_ENCODING_COMP_ZLIB: { @@ -2083,7 +2083,7 @@ static int matroska_parse_flac(AVFormatContext *s, av_log(s, AV_LOG_WARNING, "Invalid value of WAVEFORMATEXTENSIBLE_CHANNEL_MASK\n"); } else - st->codecpar->channel_layout = mask; + av_channel_layout_from_mask(&st->codecpar->ch_layout, mask); } av_dict_free(&dict); } @@ -2095,7 +2095,7 @@ static int matroska_parse_flac(AVFormatContext *s, return 0; } -static int mkv_field_order(MatroskaDemuxContext *matroska, int64_t field_order) +static int mkv_field_order(MatroskaDemuxContext *matroska, uint64_t field_order) { int minor, micro, bttb = 0; @@ -2231,6 +2231,44 @@ static int mkv_parse_video_color(AVStream *st, const MatroskaTrack *track) { return 0; } +static int mkv_create_display_matrix(AVStream *st, + const MatroskaTrackVideoProjection *proj, + void *logctx) +{ + double pitch = proj->pitch, yaw = proj->yaw, roll = proj->roll; + int32_t *matrix; + int hflip; + + if (pitch == 0.0 && yaw == 0.0 && roll == 0.0) + return 0; + + /* Note: The following constants are exactly representable + * as floating-point numbers. */ + if (pitch != 0.0 || (yaw != 0.0 && yaw != 180.0 && yaw != -180.0) || + isnan(roll)) { + av_log(logctx, AV_LOG_WARNING, "Ignoring non-2D rectangular " + "projection in stream %u (yaw %f, pitch %f, roll %f)\n", + st->index, yaw, pitch, roll); + return 0; + } + matrix = (int32_t*)av_stream_new_side_data(st, AV_PKT_DATA_DISPLAYMATRIX, + 9 * sizeof(*matrix)); + if (!matrix) + return AVERROR(ENOMEM); + + hflip = yaw != 0.0; + /* ProjectionPoseRoll is in the counter-clockwise direction + * whereas av_display_rotation_set() expects its argument + * to be oriented clockwise, so we need to negate roll. + * Furthermore, if hflip is set, we need to negate it again + * to account for the fact that the Matroska specifications + * require the yaw rotation to be applied first. */ + av_display_rotation_set(matrix, roll * (2 * hflip - 1)); + av_display_matrix_flip(matrix, hflip, 0); + + return 0; +} + static int mkv_parse_video_projection(AVStream *st, const MatroskaTrack *track, void *logctx) { @@ -2249,6 +2287,8 @@ static int mkv_parse_video_projection(AVStream *st, const MatroskaTrack *track, } switch (track->video.projection.type) { + case MATROSKA_VIDEO_PROJECTION_TYPE_RECTANGULAR: + return mkv_create_display_matrix(st, mkv_projection, logctx); case MATROSKA_VIDEO_PROJECTION_TYPE_EQUIRECTANGULAR: if (track->video.projection.private.size == 20) { t = AV_RB32(priv_data + 4); @@ -2291,9 +2331,6 @@ 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(logctx, AV_LOG_WARNING, "Unknown spherical metadata type %"PRIu64"\n", @@ -2489,9 +2526,7 @@ static int matroska_parse_tracks(AVFormatContext *s) #if CONFIG_BZLIB encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_BZLIB && #endif -#if CONFIG_LZO encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_LZO && -#endif encodings[0].compression.algo != MATROSKA_TRACK_ENCODING_COMP_HEADERSTRIP) { encodings[0].scope = 0; av_log(matroska->ctx, AV_LOG_ERROR, @@ -2851,11 +2886,14 @@ static int matroska_parse_tracks(AVFormatContext *s) mkv_stereo_mode_display_mul(track->video.stereo_mode, &display_width_mul, &display_height_mul); if (track->video.display_unit < MATROSKA_VIDEO_DISPLAYUNIT_UNKNOWN) { - av_reduce(&st->sample_aspect_ratio.num, - &st->sample_aspect_ratio.den, - st->codecpar->height * track->video.display_width * display_width_mul, - st->codecpar->width * track->video.display_height * display_height_mul, - INT_MAX); + if (track->video.display_width && track->video.display_height && + st->codecpar->height < INT64_MAX / track->video.display_width / display_width_mul && + st->codecpar->width < INT64_MAX / track->video.display_height / display_height_mul) + av_reduce(&st->sample_aspect_ratio.num, + &st->sample_aspect_ratio.den, + st->codecpar->height * track->video.display_width * display_width_mul, + st->codecpar->width * track->video.display_height * display_height_mul, + INT_MAX); } if (st->codecpar->codec_id != AV_CODEC_ID_HEVC) sti->need_parsing = AVSTREAM_PARSE_HEADERS; @@ -2911,7 +2949,11 @@ static int matroska_parse_tracks(AVFormatContext *s) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_tag = fourcc; st->codecpar->sample_rate = track->audio.out_samplerate; - st->codecpar->channels = track->audio.channels; + // channel layout may be already set by codec private checks above + if (!av_channel_layout_check(&st->codecpar->ch_layout)) { + st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + st->codecpar->ch_layout.nb_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 || @@ -3661,6 +3703,8 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, AVBufferRef *buf uint64_t num; int trust_default_duration; + av_assert1(buf); + ffio_init_context(&pb, data, size, 0, NULL, NULL, NULL, NULL); if ((n = ebml_read_num(matroska, &pb.pub, 8, &num, 1)) < 0) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 152312102..1256bdfe3 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -21,7 +21,7 @@ #include -#include "config.h" +#include "config_components.h" #include "av1.h" #include "avc.h" @@ -34,7 +34,9 @@ #include "internal.h" #include "isom.h" #include "matroska.h" +#include "mux.h" #include "riff.h" +#include "version.h" #include "vorbiscomment.h" #include "wv.h" @@ -54,6 +56,7 @@ #include "libavutil/samplefmt.h" #include "libavutil/stereo3d.h" +#include "libavcodec/av1.h" #include "libavcodec/xiph.h" #include "libavcodec/mpeg4audio.h" @@ -61,6 +64,12 @@ * Info, Tracks, Chapters, Attachments, Tags (potentially twice) and Cues */ #define MAX_SEEKHEAD_ENTRIES 7 +/* Largest known-length EBML length */ +#define MAX_EBML_LENGTH ((1ULL << 56) - 2) +/* The dynamic buffer API we rely upon has a limit of INT_MAX; + * and so has avio_write(). */ +#define MAX_SUPPORTED_EBML_LENGTH FFMIN(MAX_EBML_LENGTH, INT_MAX) + #define MODE_MATROSKAv2 0x01 #define MODE_WEBM 0x02 @@ -85,6 +94,58 @@ typedef struct ebml_stored_master { int64_t pos; } ebml_stored_master; +typedef enum EbmlType { + EBML_UINT, + EBML_SINT, + EBML_FLOAT, + EBML_UID, + EBML_STR, + EBML_UTF8 = EBML_STR, + EBML_BIN, + EBML_BLOCK, ///< pseudo-type for writing (Simple)Blocks + EBML_MASTER, +} EbmlType; + +typedef struct BlockContext { + struct mkv_track *track; + const AVPacket *pkt; + int16_t rel_ts; + uint8_t flags; + NALUList h2645_nalu_list; +} BlockContext; + +typedef struct EbmlMaster { + int nb_elements; ///< -1 if not finished + int containing_master; ///< -1 if no parent exists +} EbmlMaster; + +typedef struct EbmlElement { + uint32_t id; + EbmlType type; + unsigned length_size; + uint64_t size; ///< excluding id and length field + union { + uint64_t uint; + int64_t sint; + double f; + const char *str; + const uint8_t *bin; + struct MatroskaMuxContext *mkv; ///< used by EBML_BLOCK + EbmlMaster master; + } priv; +} EbmlElement; + +typedef struct EbmlWriter { + unsigned nb_elements; + int current_master_element; + EbmlElement *elements; +} EbmlWriter; + +#define EBML_WRITER(max_nb_elems) \ + EbmlElement elements[max_nb_elems]; \ + EbmlWriter writer = (EbmlWriter){ .elements = elements, \ + .current_master_element = -1 } + typedef struct mkv_seekhead_entry { uint32_t elementid; uint64_t segmentpos; @@ -110,6 +171,8 @@ typedef struct mkv_cues { int num_entries; } mkv_cues; +struct MatroskaMuxContext; + typedef struct mkv_track { int write_dts; int has_cue; @@ -117,16 +180,27 @@ typedef struct mkv_track { unsigned track_num; int track_num_size; int sample_rate; + unsigned offset; int64_t sample_rate_offset; int64_t last_timestamp; int64_t duration; int64_t duration_offset; - int64_t codecpriv_offset; + int codecpriv_offset; + unsigned codecpriv_size; ///< size reserved for CodecPrivate excluding header+length field int64_t ts_offset; + /* This callback will be called twice: First with a NULL AVIOContext + * to return the size of the (Simple)Block's data via size + * and a second time with the AVIOContext set when the data + * shall be written. + * The callback shall not return an error on the second call. */ + int (*reformat)(struct MatroskaMuxContext *, AVIOContext *, + const AVPacket *, int *size); } mkv_track; typedef struct MatroskaMuxContext { const AVClass *class; + AVFormatContext *ctx; + int mode; ebml_stored_master info; ebml_stored_master track; @@ -142,6 +216,16 @@ typedef struct MatroskaMuxContext { mkv_cues cues; int64_t cues_pos; + BlockContext cur_block; + + /* Used as temporary buffer to use the minimal amount of bytes + * to write the length field of EBML Masters. + * Every user has to reset the buffer after using it and + * different uses may not overlap. It is currently used in + * mkv_write_tag(), in mkv_assemble_cues() as well as in + * mkv_update_codecprivate() and mkv_write_track(). */ + AVIOContext *tmp_bc; + AVPacket *cur_audio_pkt; unsigned nb_attachments; @@ -161,14 +245,11 @@ typedef struct MatroskaMuxContext { int allow_raw_vfw; int flipped_raw_rgb; int default_mode; + int move_cues_to_front; uint32_t segment_uid[4]; } MatroskaMuxContext; -/** 2 bytes * 7 for EBML IDs, 7 1-byte EBML lengths, 6 1-byte uint, - * 8 byte for "matroska" doctype string */ -#define MAX_EBML_HEADER_SIZE 35 - /** 2 bytes * 3 for EBML IDs, 3 1-byte EBML lengths, 8 bytes for 64 bit * offset, 4 bytes for target EBML ID */ #define MAX_SEEKENTRY_SIZE 21 @@ -176,6 +257,9 @@ typedef struct MatroskaMuxContext { /** 4 * (1-byte EBML ID, 1-byte EBML size, 8-byte uint max) */ #define MAX_CUETRACKPOS_SIZE 40 +/** 2 + 1 Simpletag header, 2 + 1 + 8 Name "DURATION", 23B for TagString */ +#define DURATION_SIMPLETAG_SIZE (2 + 1 + (2 + 1 + 8) + 23) + /** Seek preroll value for opus */ #define OPUS_SEEK_PREROLL 80000000 @@ -282,20 +366,6 @@ static void put_ebml_uint(AVIOContext *pb, uint32_t elementid, uint64_t val) avio_w8(pb, (uint8_t)(val >> i * 8)); } -static void put_ebml_sint(AVIOContext *pb, uint32_t elementid, int64_t val) -{ - int i, bytes = 1; - uint64_t tmp = 2*(val < 0 ? val^-1 : val); - - while (tmp >>= 8) - bytes++; - - put_ebml_id(pb, elementid); - put_ebml_length(pb, bytes, 0); - for (i = bytes - 1; i >= 0; i--) - avio_w8(pb, (uint8_t)(val >> i * 8)); -} - static void put_ebml_float(AVIOContext *pb, uint32_t elementid, double val) { put_ebml_id(pb, elementid); @@ -361,6 +431,311 @@ static void end_ebml_master(AVIOContext *pb, ebml_master master) avio_seek(pb, pos, SEEK_SET); } +static EbmlElement *ebml_writer_add(EbmlWriter *writer, + uint32_t id, EbmlType type) +{ + writer->elements[writer->nb_elements].id = id; + writer->elements[writer->nb_elements].type = type; + return &writer->elements[writer->nb_elements++]; +} + +static void ebml_writer_open_master(EbmlWriter *writer, uint32_t id) +{ + EbmlElement *const elem = ebml_writer_add(writer, id, EBML_MASTER); + EbmlMaster *const master = &elem->priv.master; + + master->containing_master = writer->current_master_element; + master->nb_elements = -1; + + writer->current_master_element = writer->nb_elements - 1; +} + +static void ebml_writer_close_master(EbmlWriter *writer) +{ + EbmlElement *elem; + av_assert2(writer->current_master_element >= 0); + av_assert2(writer->current_master_element < writer->nb_elements); + elem = &writer->elements[writer->current_master_element]; + av_assert2(elem->type == EBML_MASTER); + av_assert2(elem->priv.master.nb_elements < 0); /* means unset */ + elem->priv.master.nb_elements = writer->nb_elements - writer->current_master_element - 1; + av_assert2(elem->priv.master.containing_master < 0 || + elem->priv.master.containing_master < writer->current_master_element); + writer->current_master_element = elem->priv.master.containing_master; +} + +static void ebml_writer_close_or_discard_master(EbmlWriter *writer) +{ + av_assert2(writer->nb_elements > 0); + av_assert2(0 <= writer->current_master_element); + av_assert2(writer->current_master_element < writer->nb_elements); + if (writer->current_master_element == writer->nb_elements - 1) { + const EbmlElement *const elem = &writer->elements[writer->nb_elements - 1]; + /* The master element has no children. Discard it. */ + av_assert2(elem->type == EBML_MASTER); + av_assert2(elem->priv.master.containing_master < 0 || + elem->priv.master.containing_master < writer->current_master_element); + writer->current_master_element = elem->priv.master.containing_master; + writer->nb_elements--; + return; + } + ebml_writer_close_master(writer); +} + +static void ebml_writer_add_string(EbmlWriter *writer, uint32_t id, + const char *str) +{ + EbmlElement *const elem = ebml_writer_add(writer, id, EBML_STR); + + elem->priv.str = str; +} + +static void ebml_writer_add_bin(EbmlWriter *writer, uint32_t id, + const uint8_t *data, size_t size) +{ + EbmlElement *const elem = ebml_writer_add(writer, id, EBML_BIN); + +#if SIZE_MAX > UINT64_MAX + size = FFMIN(size, UINT64_MAX); +#endif + elem->size = size; + elem->priv.bin = data; +} + +static void ebml_writer_add_float(EbmlWriter *writer, uint32_t id, + double val) +{ + EbmlElement *const elem = ebml_writer_add(writer, id, EBML_FLOAT); + + elem->priv.f = val; +} + +static void ebml_writer_add_uid(EbmlWriter *writer, uint32_t id, + uint64_t val) +{ + EbmlElement *const elem = ebml_writer_add(writer, id, EBML_UID); + elem->priv.uint = val; +} + +static void ebml_writer_add_uint(EbmlWriter *writer, uint32_t id, + uint64_t val) +{ + EbmlElement *elem = ebml_writer_add(writer, id, EBML_UINT); + elem->priv.uint = val; +} + +static void ebml_writer_add_sint(EbmlWriter *writer, uint32_t id, + int64_t val) +{ + EbmlElement *elem = ebml_writer_add(writer, id, EBML_SINT); + elem->priv.sint = val; +} + +static void ebml_writer_add_block(EbmlWriter *writer, MatroskaMuxContext *mkv) +{ + EbmlElement *elem = ebml_writer_add(writer, MATROSKA_ID_BLOCK, EBML_BLOCK); + elem->priv.mkv = mkv; +} + +static int ebml_writer_str_len(EbmlElement *elem) +{ + size_t len = strlen(elem->priv.str); +#if SIZE_MAX > UINT64_MAX + len = FF_MIN(len, UINT64_MAX); +#endif + elem->size = len; + return 0; +} + +static av_const int uint_size(uint64_t val) +{ + int bytes = 0; + do { + bytes++; + } while (val >>= 8); + return bytes; +} + +static int ebml_writer_uint_len(EbmlElement *elem) +{ + elem->size = uint_size(elem->priv.uint); + return 0; +} + +static av_const int sint_size(int64_t val) +{ + uint64_t tmp = 2 * (uint64_t)(val < 0 ? val^-1 : val); + return uint_size(tmp); +} + +static int ebml_writer_sint_len(EbmlElement *elem) +{ + elem->size = sint_size(elem->priv.sint); + return 0; +} + +static int ebml_writer_elem_len(EbmlWriter *writer, EbmlElement *elem, + int remaining_elems); + +static int ebml_writer_master_len(EbmlWriter *writer, EbmlElement *elem, + int remaining_elems) +{ + int nb_elems = elem->priv.master.nb_elements >= 0 ? elem->priv.master.nb_elements : remaining_elems - 1; + EbmlElement *const master = elem; + uint64_t total_size = 0; + + master->priv.master.nb_elements = nb_elems; + for (; elem++, nb_elems > 0;) { + int ret = ebml_writer_elem_len(writer, elem, nb_elems); + if (ret < 0) + return ret; + av_assert2(ret < nb_elems); + /* No overflow is possible here, as both total_size and elem->size + * are bounded by MAX_SUPPORTED_EBML_LENGTH. */ + total_size += ebml_id_size(elem->id) + elem->length_size + elem->size; + if (total_size > MAX_SUPPORTED_EBML_LENGTH) + return AVERROR(ERANGE); + nb_elems--; /* consume elem */ + elem += ret, nb_elems -= ret; /* and elem's children */ + } + master->size = total_size; + + return master->priv.master.nb_elements; +} + +static int ebml_writer_block_len(EbmlElement *elem) +{ + MatroskaMuxContext *const mkv = elem->priv.mkv; + BlockContext *const block = &mkv->cur_block; + mkv_track *const track = block->track; + const AVPacket *const pkt = block->pkt; + int err, size; + + if (track->reformat) { + err = track->reformat(mkv, NULL, pkt, &size); + if (err < 0) { + av_log(mkv->ctx, AV_LOG_ERROR, "Error when reformatting data of " + "a packet from stream %d.\n", pkt->stream_index); + return err; + } + } else { + size = pkt->size; + if (track->offset <= size) + size -= track->offset; + } + elem->size = track->track_num_size + 3U + size; + + return 0; +} + +static void ebml_writer_write_block(const EbmlElement *elem, AVIOContext *pb) +{ + MatroskaMuxContext *const mkv = elem->priv.mkv; + BlockContext *const block = &mkv->cur_block; + mkv_track *const track = block->track; + const AVPacket *const pkt = block->pkt; + + put_ebml_num(pb, track->track_num, track->track_num_size); + avio_wb16(pb, block->rel_ts); + avio_w8(pb, block->flags); + + if (track->reformat) { + int size; + track->reformat(mkv, pb, pkt, &size); + } else { + const uint8_t *data = pkt->data; + unsigned offset = track->offset <= pkt->size ? track->offset : 0; + avio_write(pb, data + offset, pkt->size - offset); + } +} + +static int ebml_writer_elem_len(EbmlWriter *writer, EbmlElement *elem, + int remaining_elems) +{ + int ret = 0; + + switch (elem->type) { + case EBML_FLOAT: + case EBML_UID: + elem->size = 8; + break; + case EBML_STR: + ret = ebml_writer_str_len(elem); + break; + case EBML_UINT: + ret = ebml_writer_uint_len(elem); + break; + case EBML_SINT: + ret = ebml_writer_sint_len(elem); + break; + case EBML_BLOCK: + ret = ebml_writer_block_len(elem); + break; + case EBML_MASTER: + ret = ebml_writer_master_len(writer, elem, remaining_elems); + break; + } + if (ret < 0) + return ret; + if (elem->size > MAX_SUPPORTED_EBML_LENGTH) + return AVERROR(ERANGE); + elem->length_size = ebml_length_size(elem->size); + return ret; /* number of elements consumed excluding elem itself */ +} + +static int ebml_writer_elem_write(const EbmlElement *elem, AVIOContext *pb) +{ + put_ebml_id(pb, elem->id); + put_ebml_num(pb, elem->size, elem->length_size); + switch (elem->type) { + case EBML_UID: + case EBML_FLOAT: { + uint64_t val = elem->type == EBML_UID ? elem->priv.uint + : av_double2int(elem->priv.f); + avio_wb64(pb, val); + break; + } + case EBML_UINT: + case EBML_SINT: { + uint64_t val = elem->type == EBML_UINT ? elem->priv.uint + : elem->priv.sint; + for (int i = elem->size; --i >= 0; ) + avio_w8(pb, (uint8_t)(val >> i * 8)); + break; + } + case EBML_STR: + case EBML_BIN: { + const uint8_t *data = elem->type == EBML_BIN ? elem->priv.bin + : (const uint8_t*)elem->priv.str; + avio_write(pb, data, elem->size); + break; + } + case EBML_BLOCK: + ebml_writer_write_block(elem, pb); + break; + case EBML_MASTER: { + int nb_elems = elem->priv.master.nb_elements; + + elem++; + for (int i = 0; i < nb_elems; i++) + i += ebml_writer_elem_write(elem + i, pb); + + return nb_elems; + } + } + return 0; +} + +static int ebml_writer_write(EbmlWriter *writer, AVIOContext *pb) +{ + int ret = ebml_writer_elem_len(writer, writer->elements, + writer->nb_elements); + if (ret < 0) + return ret; + ebml_writer_elem_write(writer->elements, pb); + return 0; +} + static void mkv_add_seekhead_entry(MatroskaMuxContext *mkv, uint32_t elementid, uint64_t filepos) { @@ -462,7 +837,9 @@ static void mkv_deinit(AVFormatContext *s) ffio_free_dyn_buf(&mkv->info.bc); ffio_free_dyn_buf(&mkv->track.bc); ffio_free_dyn_buf(&mkv->tags.bc); + ffio_free_dyn_buf(&mkv->tmp_bc); + av_freep(&mkv->cur_block.h2645_nalu_list.nalus); av_freep(&mkv->cues.entries); av_freep(&mkv->tracks); } @@ -565,16 +942,10 @@ static int mkv_add_cuepoint(MatroskaMuxContext *mkv, int stream, int64_t ts, return 0; } -static int mkv_assemble_cues(AVStream **streams, AVIOContext *dyn_cp, - mkv_cues *cues, mkv_track *tracks, int num_tracks) +static int mkv_assemble_cues(AVStream **streams, AVIOContext *dyn_cp, AVIOContext *cuepoint, + const mkv_cues *cues, mkv_track *tracks, int num_tracks, + uint64_t offset) { - AVIOContext *cuepoint; - int ret; - - ret = avio_open_dyn_buf(&cuepoint); - if (ret < 0) - return ret; - for (mkv_cuepoint *entry = cues->entries, *end = entry + cues->num_entries; entry < end;) { uint64_t pts = entry->pts; @@ -597,25 +968,25 @@ static int mkv_assemble_cues(AVStream **streams, AVIOContext *dyn_cp, tracks[idx].has_cue = 1; track_positions = start_ebml_master(cuepoint, MATROSKA_ID_CUETRACKPOSITION, MAX_CUETRACKPOS_SIZE); put_ebml_uint(cuepoint, MATROSKA_ID_CUETRACK , tracks[idx].track_num); - put_ebml_uint(cuepoint, MATROSKA_ID_CUECLUSTERPOSITION , entry->cluster_pos); + put_ebml_uint(cuepoint, MATROSKA_ID_CUECLUSTERPOSITION , entry->cluster_pos + offset); put_ebml_uint(cuepoint, MATROSKA_ID_CUERELATIVEPOSITION, entry->relative_pos); if (entry->duration > 0) put_ebml_uint(cuepoint, MATROSKA_ID_CUEDURATION , entry->duration); end_ebml_master(cuepoint, track_positions); } while (++entry < end && entry->pts == pts); size = avio_get_dyn_buf(cuepoint, &buf); - if ((ret = cuepoint->error) < 0) - break; + if (cuepoint->error < 0) + return cuepoint->error; put_ebml_binary(dyn_cp, MATROSKA_ID_POINTENTRY, buf, size); ffio_reset_dyn_buf(cuepoint); } - ffio_free_dyn_buf(&cuepoint); - return ret; + return 0; } static int put_xiph_codecpriv(AVFormatContext *s, AVIOContext *pb, - const AVCodecParameters *par) + const AVCodecParameters *par, + const uint8_t *extradata, int extradata_size) { const uint8_t *header_start[3]; int header_len[3]; @@ -627,7 +998,7 @@ static int put_xiph_codecpriv(AVFormatContext *s, AVIOContext *pb, else first_header_size = 42; - err = avpriv_split_xiph_headers(par->extradata, par->extradata_size, + err = avpriv_split_xiph_headers(extradata, extradata_size, first_header_size, header_start, header_len); if (err < 0) { av_log(s, AV_LOG_ERROR, "Extradata corrupt.\n"); @@ -645,22 +1016,23 @@ static int put_xiph_codecpriv(AVFormatContext *s, AVIOContext *pb, } #if CONFIG_MATROSKA_MUXER -static int put_wv_codecpriv(AVIOContext *pb, const AVCodecParameters *par) +static int put_wv_codecpriv(AVIOContext *pb, const uint8_t *extradata, int extradata_size) { - if (par->extradata && par->extradata_size == 2) - avio_write(pb, par->extradata, 2); + if (extradata && extradata_size == 2) + avio_write(pb, extradata, 2); else avio_wl16(pb, 0x410); // fallback to the most recent version return 0; } static int put_flac_codecpriv(AVFormatContext *s, AVIOContext *pb, - const AVCodecParameters *par) + const AVCodecParameters *par, + const uint8_t *extradata, int extradata_size) { - int write_comment = (par->channel_layout && - !(par->channel_layout & ~0x3ffffULL) && - !ff_flac_is_native_layout(par->channel_layout)); - int ret = ff_flac_write_header(pb, par->extradata, par->extradata_size, + int write_comment = (par->ch_layout.order == AV_CHANNEL_ORDER_NATIVE && + !(par->ch_layout.u.mask & ~0x3ffffULL) && + !ff_flac_is_native_layout(par->ch_layout.u.mask)); + int ret = ff_flac_write_header(pb, extradata, extradata_size, !write_comment); if (ret < 0) @@ -673,7 +1045,7 @@ static int put_flac_codecpriv(AVFormatContext *s, AVIOContext *pb, uint8_t buf[32]; int64_t len; - snprintf(buf, sizeof(buf), "0x%"PRIx64, par->channel_layout); + snprintf(buf, sizeof(buf), "0x%"PRIx64, par->ch_layout.u.mask); av_dict_set(&dict, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK", buf, 0); len = ff_vorbiscomment_length(dict, vendor, NULL, 0); @@ -724,75 +1096,79 @@ static int get_aac_sample_rates(AVFormatContext *s, MatroskaMuxContext *mkv, } #endif -static int mkv_write_native_codecprivate(AVFormatContext *s, AVIOContext *pb, - const AVCodecParameters *par, - AVIOContext *dyn_cp) +static int mkv_assemble_native_codecprivate(AVFormatContext *s, AVIOContext *dyn_cp, + const AVCodecParameters *par, + const uint8_t *extradata, + int extradata_size, + unsigned *size_to_reserve) { switch (par->codec_id) { case AV_CODEC_ID_VORBIS: case AV_CODEC_ID_THEORA: - return put_xiph_codecpriv(s, dyn_cp, par); + return put_xiph_codecpriv(s, dyn_cp, par, extradata, extradata_size); case AV_CODEC_ID_AV1: - if (par->extradata_size) - return ff_isom_write_av1c(dyn_cp, par->extradata, - par->extradata_size); + if (extradata_size) + return ff_isom_write_av1c(dyn_cp, extradata, + extradata_size, 1); else - put_ebml_void(pb, 4 + 3); + *size_to_reserve = (AV1_SANE_SEQUENCE_HEADER_MAX_BITS + 7) / 8 + 100; break; #if CONFIG_MATROSKA_MUXER case AV_CODEC_ID_FLAC: - return put_flac_codecpriv(s, dyn_cp, par); + return put_flac_codecpriv(s, dyn_cp, par, extradata, extradata_size); case AV_CODEC_ID_WAVPACK: - return put_wv_codecpriv(dyn_cp, par); + return put_wv_codecpriv(dyn_cp, extradata, extradata_size); case AV_CODEC_ID_H264: - return ff_isom_write_avcc(dyn_cp, par->extradata, - par->extradata_size); + return ff_isom_write_avcc(dyn_cp, extradata, + extradata_size); case AV_CODEC_ID_HEVC: - return ff_isom_write_hvcc(dyn_cp, par->extradata, - par->extradata_size, 0); + return ff_isom_write_hvcc(dyn_cp, extradata, + extradata_size, 0); case AV_CODEC_ID_ALAC: - if (par->extradata_size < 36) { + if (extradata_size < 36) { av_log(s, AV_LOG_ERROR, "Invalid extradata found, ALAC expects a 36-byte " "QuickTime atom."); return AVERROR_INVALIDDATA; } else - avio_write(dyn_cp, par->extradata + 12, - par->extradata_size - 12); + avio_write(dyn_cp, extradata + 12, + extradata_size - 12); break; case AV_CODEC_ID_AAC: - if (par->extradata_size) - avio_write(dyn_cp, par->extradata, par->extradata_size); + if (extradata_size) + avio_write(dyn_cp, extradata, extradata_size); else - put_ebml_void(pb, MAX_PCE_SIZE + 2 + 4); + *size_to_reserve = MAX_PCE_SIZE; break; #endif default: if (CONFIG_MATROSKA_MUXER && par->codec_id == AV_CODEC_ID_PRORES && ff_codec_get_id(ff_codec_movvideo_tags, par->codec_tag) == AV_CODEC_ID_PRORES) { avio_wl32(dyn_cp, par->codec_tag); - } else if (par->extradata_size && par->codec_id != AV_CODEC_ID_TTA) - avio_write(dyn_cp, par->extradata, par->extradata_size); + } else if (extradata_size && par->codec_id != AV_CODEC_ID_TTA) + avio_write(dyn_cp, extradata, extradata_size); } return 0; } -static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb, - AVCodecParameters *par, - int native_id, int qt_id) +static int mkv_assemble_codecprivate(AVFormatContext *s, AVIOContext *dyn_cp, + AVCodecParameters *par, + const uint8_t *extradata, int extradata_size, + int native_id, int qt_id, + uint8_t **codecpriv, int *codecpriv_size, + unsigned *max_payload_size) { MatroskaMuxContext av_unused *const mkv = s->priv_data; - AVIOContext *dyn_cp; - uint8_t *codecpriv; - int ret, codecpriv_size; - - ret = avio_open_dyn_buf(&dyn_cp); - if (ret < 0) - return ret; + unsigned size_to_reserve = 0; + int ret; if (native_id) { - ret = mkv_write_native_codecprivate(s, pb, par, dyn_cp); + ret = mkv_assemble_native_codecprivate(s, dyn_cp, par, + extradata, extradata_size, + &size_to_reserve); + if (ret < 0) + return ret; #if CONFIG_MATROSKA_MUXER } else if (par->codec_type == AVMEDIA_TYPE_VIDEO) { if (qt_id) { @@ -800,13 +1176,13 @@ static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb, par->codec_tag = ff_codec_get_tag(ff_codec_movvideo_tags, par->codec_id); if ( ff_codec_get_id(ff_codec_movvideo_tags, par->codec_tag) == par->codec_id - && (!par->extradata_size || ff_codec_get_id(ff_codec_movvideo_tags, AV_RL32(par->extradata + 4)) != par->codec_id) + && (!extradata_size || ff_codec_get_id(ff_codec_movvideo_tags, AV_RL32(extradata + 4)) != par->codec_id) ) { - avio_wb32(dyn_cp, 0x5a + par->extradata_size); + avio_wb32(dyn_cp, 0x5a + extradata_size); avio_wl32(dyn_cp, par->codec_tag); ffio_fill(dyn_cp, 0, 0x5a - 8); } - avio_write(dyn_cp, par->extradata, par->extradata_size); + avio_write(dyn_cp, extradata, extradata_size); } else { if (!ff_codec_get_tag(ff_codec_bmp_tags, par->codec_id)) av_log(s, AV_LOG_WARNING, "codec %s is not supported by this format\n", @@ -818,9 +1194,11 @@ static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb, if (!par->codec_tag && par->codec_id != AV_CODEC_ID_RAWVIDEO) { av_log(s, AV_LOG_ERROR, "No bmp codec tag found for codec %s\n", avcodec_get_name(par->codec_id)); - ret = AVERROR(EINVAL); + return AVERROR(EINVAL); } + /* If vfw extradata updates are supported, this will have + * to be updated to pass extradata(_size) explicitly. */ ff_put_bmp_header(dyn_cp, par, 0, 0, mkv->flipped_raw_rgb); } } else if (par->codec_type == AVMEDIA_TYPE_AUDIO) { @@ -829,117 +1207,177 @@ static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb, if (!tag) { av_log(s, AV_LOG_ERROR, "No wav codec tag found for codec %s\n", avcodec_get_name(par->codec_id)); - ret = AVERROR(EINVAL); + return AVERROR(EINVAL); } if (!par->codec_tag) par->codec_tag = tag; + /* Same comment as for ff_put_bmp_header applies here. */ ff_put_wav_header(s, dyn_cp, par, FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX); #endif } - if (ret >= 0) { - codecpriv_size = avio_get_dyn_buf(dyn_cp, &codecpriv); - if ((ret = dyn_cp->error) >= 0 && codecpriv_size) - put_ebml_binary(pb, MATROSKA_ID_CODECPRIVATE, codecpriv, - codecpriv_size); + *codecpriv_size = avio_get_dyn_buf(dyn_cp, codecpriv); + if (dyn_cp->error < 0) + return dyn_cp->error; + *max_payload_size = *codecpriv_size + size_to_reserve; + + return 0; +} + +static void mkv_put_codecprivate(AVIOContext *pb, unsigned max_payload_size, + const uint8_t *codecpriv, unsigned codecpriv_size) +{ + unsigned total_codecpriv_size = 0, total_size; + + av_assert1(codecpriv_size <= max_payload_size); + + if (!max_payload_size) + return; + + total_size = 2 + ebml_length_size(max_payload_size) + max_payload_size; + + if (codecpriv_size) { + unsigned length_size = ebml_length_size(codecpriv_size); + + total_codecpriv_size = 2U + length_size + codecpriv_size; + if (total_codecpriv_size + 1 == total_size) { + /* It is impossible to add one byte of padding via an EBML Void. */ + length_size++; + total_codecpriv_size++; + } + put_ebml_id(pb, MATROSKA_ID_CODECPRIVATE); + put_ebml_length(pb, codecpriv_size, length_size); + avio_write(pb, codecpriv, codecpriv_size); } - ffio_free_dyn_buf(&dyn_cp); + if (total_codecpriv_size < total_size) + put_ebml_void(pb, total_size - total_codecpriv_size); +} + +static int mkv_update_codecprivate(AVFormatContext *s, MatroskaMuxContext *mkv, + uint8_t *side_data, int side_data_size, + AVCodecParameters *par, AVIOContext *pb, + mkv_track *track, unsigned alternative_size) +{ + AVIOContext *const dyn_bc = mkv->tmp_bc; + uint8_t *codecpriv; + unsigned max_payload_size; + int ret, codecpriv_size; + + ret = mkv_assemble_codecprivate(s, dyn_bc, par, + side_data, side_data_size, 1, 0, + &codecpriv, &codecpriv_size, &max_payload_size); + if (ret < 0) + goto fail; + if (codecpriv_size > track->codecpriv_size && !alternative_size) { + ret = AVERROR(ENOSPC); + goto fail; + } else if (codecpriv_size > track->codecpriv_size) { + av_assert1(alternative_size < track->codecpriv_size); + codecpriv_size = alternative_size; + } + avio_seek(pb, track->codecpriv_offset, SEEK_SET); + mkv_put_codecprivate(pb, track->codecpriv_size, + codecpriv, codecpriv_size); + + if (!par->extradata_size) { + ret = ff_alloc_extradata(par, side_data_size); + if (ret < 0) + goto fail; + memcpy(par->extradata, side_data, side_data_size); + } +fail: + ffio_reset_dyn_buf(dyn_bc); return ret; } -static void mkv_write_video_color(AVIOContext *pb, const AVStream *st, +#define MAX_VIDEO_COLOR_ELEMS 20 +static void mkv_write_video_color(EbmlWriter *writer, const AVStream *st, const AVCodecParameters *par) { - /* 18 Elements with two bytes ID, one byte length field, 8 bytes payload - * a master element with two bytes ID and one byte length field - * plus another byte to stay clear of the end. */ - uint8_t colour[(2 + 1 + 8) * 18 + (2 + 1) + 1]; - FFIOContext buf; - AVIOContext *const dyn_cp = &buf.pub; - int colorinfo_size; const void *side_data; - ffio_init_context(&buf, colour, sizeof(colour), 1, NULL, NULL, NULL, NULL); + ebml_writer_open_master(writer, MATROSKA_ID_VIDEOCOLOR); if (par->color_trc != AVCOL_TRC_UNSPECIFIED && par->color_trc < AVCOL_TRC_NB) { - put_ebml_uint(dyn_cp, MATROSKA_ID_VIDEOCOLORTRANSFERCHARACTERISTICS, - par->color_trc); + ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOCOLORTRANSFERCHARACTERISTICS, + par->color_trc); } if (par->color_space != AVCOL_SPC_UNSPECIFIED && par->color_space < AVCOL_SPC_NB) { - put_ebml_uint(dyn_cp, MATROSKA_ID_VIDEOCOLORMATRIXCOEFF, par->color_space); + ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOCOLORMATRIXCOEFF, + par->color_space); } if (par->color_primaries != AVCOL_PRI_UNSPECIFIED && par->color_primaries < AVCOL_PRI_NB) { - put_ebml_uint(dyn_cp, MATROSKA_ID_VIDEOCOLORPRIMARIES, par->color_primaries); + ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOCOLORPRIMARIES, + par->color_primaries); } if (par->color_range != AVCOL_RANGE_UNSPECIFIED && par->color_range < AVCOL_RANGE_NB) { - put_ebml_uint(dyn_cp, MATROSKA_ID_VIDEOCOLORRANGE, par->color_range); + ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOCOLORRANGE, par->color_range); } if (par->chroma_location != AVCHROMA_LOC_UNSPECIFIED && par->chroma_location <= AVCHROMA_LOC_TOP) { int xpos, ypos; avcodec_enum_to_chroma_pos(&xpos, &ypos, par->chroma_location); - put_ebml_uint(dyn_cp, MATROSKA_ID_VIDEOCOLORCHROMASITINGHORZ, (xpos >> 7) + 1); - put_ebml_uint(dyn_cp, MATROSKA_ID_VIDEOCOLORCHROMASITINGVERT, (ypos >> 7) + 1); + ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOCOLORCHROMASITINGHORZ, + (xpos >> 7) + 1); + ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOCOLORCHROMASITINGVERT, + (ypos >> 7) + 1); } side_data = av_stream_get_side_data(st, AV_PKT_DATA_CONTENT_LIGHT_LEVEL, NULL); if (side_data) { const AVContentLightMetadata *metadata = side_data; - put_ebml_uint(dyn_cp, MATROSKA_ID_VIDEOCOLORMAXCLL, metadata->MaxCLL); - put_ebml_uint(dyn_cp, MATROSKA_ID_VIDEOCOLORMAXFALL, metadata->MaxFALL); + ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOCOLORMAXCLL, + metadata->MaxCLL); + ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOCOLORMAXFALL, + metadata->MaxFALL); } side_data = av_stream_get_side_data(st, AV_PKT_DATA_MASTERING_DISPLAY_METADATA, NULL); if (side_data) { - ebml_master meta_element = start_ebml_master( - dyn_cp, MATROSKA_ID_VIDEOCOLORMASTERINGMETA, 10 * (2 + 1 + 8)); const AVMasteringDisplayMetadata *metadata = side_data; + ebml_writer_open_master(writer, MATROSKA_ID_VIDEOCOLORMASTERINGMETA); if (metadata->has_primaries) { - put_ebml_float(dyn_cp, MATROSKA_ID_VIDEOCOLOR_RX, - av_q2d(metadata->display_primaries[0][0])); - put_ebml_float(dyn_cp, MATROSKA_ID_VIDEOCOLOR_RY, - av_q2d(metadata->display_primaries[0][1])); - put_ebml_float(dyn_cp, MATROSKA_ID_VIDEOCOLOR_GX, - av_q2d(metadata->display_primaries[1][0])); - put_ebml_float(dyn_cp, MATROSKA_ID_VIDEOCOLOR_GY, - av_q2d(metadata->display_primaries[1][1])); - put_ebml_float(dyn_cp, MATROSKA_ID_VIDEOCOLOR_BX, - av_q2d(metadata->display_primaries[2][0])); - put_ebml_float(dyn_cp, MATROSKA_ID_VIDEOCOLOR_BY, - av_q2d(metadata->display_primaries[2][1])); - put_ebml_float(dyn_cp, MATROSKA_ID_VIDEOCOLOR_WHITEX, - av_q2d(metadata->white_point[0])); - put_ebml_float(dyn_cp, MATROSKA_ID_VIDEOCOLOR_WHITEY, - av_q2d(metadata->white_point[1])); + ebml_writer_add_float(writer, MATROSKA_ID_VIDEOCOLOR_RX, + av_q2d(metadata->display_primaries[0][0])); + ebml_writer_add_float(writer, MATROSKA_ID_VIDEOCOLOR_RY, + av_q2d(metadata->display_primaries[0][1])); + ebml_writer_add_float(writer, MATROSKA_ID_VIDEOCOLOR_GX, + av_q2d(metadata->display_primaries[1][0])); + ebml_writer_add_float(writer, MATROSKA_ID_VIDEOCOLOR_GY, + av_q2d(metadata->display_primaries[1][1])); + ebml_writer_add_float(writer, MATROSKA_ID_VIDEOCOLOR_BX, + av_q2d(metadata->display_primaries[2][0])); + ebml_writer_add_float(writer, MATROSKA_ID_VIDEOCOLOR_BY, + av_q2d(metadata->display_primaries[2][1])); + ebml_writer_add_float(writer, MATROSKA_ID_VIDEOCOLOR_WHITEX, + av_q2d(metadata->white_point[0])); + ebml_writer_add_float(writer, MATROSKA_ID_VIDEOCOLOR_WHITEY, + av_q2d(metadata->white_point[1])); } if (metadata->has_luminance) { - put_ebml_float(dyn_cp, MATROSKA_ID_VIDEOCOLOR_LUMINANCEMAX, - av_q2d(metadata->max_luminance)); - put_ebml_float(dyn_cp, MATROSKA_ID_VIDEOCOLOR_LUMINANCEMIN, - av_q2d(metadata->min_luminance)); + ebml_writer_add_float(writer, MATROSKA_ID_VIDEOCOLOR_LUMINANCEMAX, + av_q2d(metadata->max_luminance)); + ebml_writer_add_float(writer, MATROSKA_ID_VIDEOCOLOR_LUMINANCEMIN, + av_q2d(metadata->min_luminance)); } - end_ebml_master(dyn_cp, meta_element); + ebml_writer_close_or_discard_master(writer); } - colorinfo_size = avio_tell(dyn_cp); - if (colorinfo_size) - put_ebml_binary(pb, MATROSKA_ID_VIDEOCOLOR, colour, colorinfo_size); + ebml_writer_close_or_discard_master(writer); } -static void mkv_write_video_projection(AVFormatContext *s, AVIOContext *pb, - const AVStream *st) +#define MAX_VIDEO_PROJECTION_ELEMS 6 +static void mkv_write_video_projection(AVFormatContext *s, EbmlWriter *writer, + const AVStream *st, uint8_t private[]) { - ebml_master projection; - uint8_t private[20]; - const AVSphericalMapping *spherical = (const AVSphericalMapping *)av_stream_get_side_data(st, AV_PKT_DATA_SPHERICAL, NULL); @@ -954,93 +1392,96 @@ static void mkv_write_video_projection(AVFormatContext *s, AVIOContext *pb, return; } - // Maximally 4 8-byte elements with id-length 2 + 1 byte length field - // and the private data of the AV_SPHERICAL_EQUIRECTANGULAR_TILE case - projection = start_ebml_master(pb, MATROSKA_ID_VIDEOPROJECTION, - 4 * (2 + 1 + 8) + (2 + 1 + 20)); + ebml_writer_open_master(writer, MATROSKA_ID_VIDEOPROJECTION); switch (spherical->projection) { case AV_SPHERICAL_EQUIRECTANGULAR: - put_ebml_uint(pb, MATROSKA_ID_VIDEOPROJECTIONTYPE, - MATROSKA_VIDEO_PROJECTION_TYPE_EQUIRECTANGULAR); - break; case AV_SPHERICAL_EQUIRECTANGULAR_TILE: - put_ebml_uint(pb, MATROSKA_ID_VIDEOPROJECTIONTYPE, - MATROSKA_VIDEO_PROJECTION_TYPE_EQUIRECTANGULAR); + ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOPROJECTIONTYPE, + MATROSKA_VIDEO_PROJECTION_TYPE_EQUIRECTANGULAR); AV_WB32(private, 0); // version + flags - AV_WB32(private + 4, spherical->bound_top); - AV_WB32(private + 8, spherical->bound_bottom); - AV_WB32(private + 12, spherical->bound_left); - AV_WB32(private + 16, spherical->bound_right); - put_ebml_binary(pb, MATROSKA_ID_VIDEOPROJECTIONPRIVATE, - private, 20); + if (spherical->projection == AV_SPHERICAL_EQUIRECTANGULAR) { + AV_WB32(private + 4, 0); + AV_WB32(private + 8, 0); + AV_WB32(private + 12, 0); + AV_WB32(private + 16, 0); + } else { + AV_WB32(private + 4, spherical->bound_top); + AV_WB32(private + 8, spherical->bound_bottom); + AV_WB32(private + 12, spherical->bound_left); + AV_WB32(private + 16, spherical->bound_right); + } + ebml_writer_add_bin(writer, MATROSKA_ID_VIDEOPROJECTIONPRIVATE, + private, 20); break; case AV_SPHERICAL_CUBEMAP: - put_ebml_uint(pb, MATROSKA_ID_VIDEOPROJECTIONTYPE, - MATROSKA_VIDEO_PROJECTION_TYPE_CUBEMAP); + ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOPROJECTIONTYPE, + MATROSKA_VIDEO_PROJECTION_TYPE_CUBEMAP); AV_WB32(private, 0); // version + flags AV_WB32(private + 4, 0); // layout AV_WB32(private + 8, spherical->padding); - put_ebml_binary(pb, MATROSKA_ID_VIDEOPROJECTIONPRIVATE, - private, 12); + ebml_writer_add_bin(writer, MATROSKA_ID_VIDEOPROJECTIONPRIVATE, + private, 12); break; default: av_assert0(0); } if (spherical->yaw) - put_ebml_float(pb, MATROSKA_ID_VIDEOPROJECTIONPOSEYAW, - (double) spherical->yaw / (1 << 16)); + ebml_writer_add_float(writer, MATROSKA_ID_VIDEOPROJECTIONPOSEYAW, + (double) spherical->yaw / (1 << 16)); if (spherical->pitch) - put_ebml_float(pb, MATROSKA_ID_VIDEOPROJECTIONPOSEPITCH, + ebml_writer_add_float(writer, MATROSKA_ID_VIDEOPROJECTIONPOSEPITCH, (double) spherical->pitch / (1 << 16)); if (spherical->roll) - put_ebml_float(pb, MATROSKA_ID_VIDEOPROJECTIONPOSEROLL, + ebml_writer_add_float(writer, MATROSKA_ID_VIDEOPROJECTIONPOSEROLL, (double) spherical->roll / (1 << 16)); - end_ebml_master(pb, projection); + ebml_writer_close_master(writer); } -static void mkv_write_field_order(AVIOContext *pb, int is_webm, +#define MAX_FIELD_ORDER_ELEMS 2 +static void mkv_write_field_order(EbmlWriter *writer, int is_webm, enum AVFieldOrder field_order) { switch (field_order) { case AV_FIELD_UNKNOWN: break; case AV_FIELD_PROGRESSIVE: - put_ebml_uint(pb, MATROSKA_ID_VIDEOFLAGINTERLACED, - MATROSKA_VIDEO_INTERLACE_FLAG_PROGRESSIVE); + ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOFLAGINTERLACED, + MATROSKA_VIDEO_INTERLACE_FLAG_PROGRESSIVE); break; case AV_FIELD_TT: case AV_FIELD_BB: case AV_FIELD_TB: case AV_FIELD_BT: - put_ebml_uint(pb, MATROSKA_ID_VIDEOFLAGINTERLACED, - MATROSKA_VIDEO_INTERLACE_FLAG_INTERLACED); + ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOFLAGINTERLACED, + MATROSKA_VIDEO_INTERLACE_FLAG_INTERLACED); if (!is_webm) { switch (field_order) { case AV_FIELD_TT: - put_ebml_uint(pb, MATROSKA_ID_VIDEOFIELDORDER, - MATROSKA_VIDEO_FIELDORDER_TT); + ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOFIELDORDER, + MATROSKA_VIDEO_FIELDORDER_TT); break; case AV_FIELD_BB: - put_ebml_uint(pb, MATROSKA_ID_VIDEOFIELDORDER, - MATROSKA_VIDEO_FIELDORDER_BB); + ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOFIELDORDER, + MATROSKA_VIDEO_FIELDORDER_BB); break; case AV_FIELD_TB: - put_ebml_uint(pb, MATROSKA_ID_VIDEOFIELDORDER, - MATROSKA_VIDEO_FIELDORDER_TB); + ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOFIELDORDER, + MATROSKA_VIDEO_FIELDORDER_TB); break; case AV_FIELD_BT: - put_ebml_uint(pb, MATROSKA_ID_VIDEOFIELDORDER, - MATROSKA_VIDEO_FIELDORDER_BT); + ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOFIELDORDER, + MATROSKA_VIDEO_FIELDORDER_BT); break; } } } } -static int mkv_write_stereo_mode(AVFormatContext *s, AVIOContext *pb, +#define MAX_STEREO_MODE_ELEMS 1 +static int mkv_write_stereo_mode(AVFormatContext *s, EbmlWriter *writer, AVStream *st, int is_webm, int *h_width, int *h_height) { @@ -1127,7 +1568,7 @@ static int mkv_write_stereo_mode(AVFormatContext *s, AVIOContext *pb, } // write StereoMode if format is valid - put_ebml_uint(pb, MATROSKA_ID_VIDEOSTEREOMODE, format); + ebml_writer_add_uint(writer, MATROSKA_ID_VIDEOSTEREOMODE, format); return 0; } @@ -1165,6 +1606,86 @@ static void mkv_write_dovi(AVFormatContext *s, AVIOContext *pb, AVStream *st) #endif } +static int mkv_write_track_video(AVFormatContext *s, MatroskaMuxContext *mkv, + AVStream *st, const AVCodecParameters *par, + AVIOContext *pb) +{ + const AVDictionaryEntry *tag; + int display_width_div = 1, display_height_div = 1; + uint8_t color_space[4], projection_private[20]; + EBML_WRITER(MAX_FIELD_ORDER_ELEMS + MAX_STEREO_MODE_ELEMS + + MAX_VIDEO_COLOR_ELEMS + MAX_VIDEO_PROJECTION_ELEMS + 8); + int ret; + + ebml_writer_open_master(&writer, MATROSKA_ID_TRACKVIDEO); + + ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEOPIXELWIDTH , par->width); + ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEOPIXELHEIGHT, par->height); + + mkv_write_field_order(&writer, IS_WEBM(mkv), par->field_order); + + // 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, &writer, st, IS_WEBM(mkv), + &display_width_div, + &display_height_div); + if (ret < 0) + return ret; + + if (((tag = av_dict_get(st->metadata, "alpha_mode", NULL, 0)) && atoi(tag->value)) || + ((tag = av_dict_get( s->metadata, "alpha_mode", NULL, 0)) && atoi(tag->value)) || + (par->format == AV_PIX_FMT_YUVA420P)) { + ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEOALPHAMODE, 1); + } + + // write DisplayWidth and DisplayHeight, they contain the size of + // a single source view and/or the display aspect ratio + if (st->sample_aspect_ratio.num) { + int64_t d_width = av_rescale(par->width, st->sample_aspect_ratio.num, st->sample_aspect_ratio.den); + if (d_width > INT_MAX) { + av_log(s, AV_LOG_ERROR, "Overflow in display width\n"); + return AVERROR(EINVAL); + } + if (d_width != par->width || display_width_div != 1 || display_height_div != 1) { + if (IS_WEBM(mkv) || display_width_div != 1 || display_height_div != 1) { + ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEODISPLAYWIDTH, + d_width / display_width_div); + ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEODISPLAYHEIGHT, + par->height / display_height_div); + } else { + AVRational display_aspect_ratio; + av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den, + par->width * (int64_t)st->sample_aspect_ratio.num, + par->height * (int64_t)st->sample_aspect_ratio.den, + 1024 * 1024); + ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEODISPLAYWIDTH, + display_aspect_ratio.num); + ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEODISPLAYHEIGHT, + display_aspect_ratio.den); + ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEODISPLAYUNIT, + MATROSKA_VIDEO_DISPLAYUNIT_DAR); + } + } + } else if (display_width_div != 1 || display_height_div != 1) { + ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEODISPLAYWIDTH, + par->width / display_width_div); + ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEODISPLAYHEIGHT, + par->height / display_height_div); + } else if (!IS_WEBM(mkv)) + ebml_writer_add_uint(&writer, MATROSKA_ID_VIDEODISPLAYUNIT, + MATROSKA_VIDEO_DISPLAYUNIT_UNKNOWN); + + if (par->codec_id == AV_CODEC_ID_RAWVIDEO) { + AV_WL32(color_space, par->codec_tag); + ebml_writer_add_bin(&writer, MATROSKA_ID_VIDEOCOLORSPACE, + color_space, sizeof(color_space)); + } + mkv_write_video_color(&writer, st, par); + mkv_write_video_projection(s, &writer, st, projection_private); + + return ebml_writer_write(&writer, pb); +} + static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, AVStream *st, mkv_track *track, AVIOContext *pb, int is_default) @@ -1176,8 +1697,6 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, int bit_depth; int sample_rate = par->sample_rate; int output_sample_rate = 0; - int display_width_div = 1; - int display_height_div = 1; int j, ret; const AVDictionaryEntry *tag; @@ -1299,65 +1818,10 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, ffformatcontext(s)->avoid_negative_ts_use_pts = 0; } - subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKVIDEO, 0); - - put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELWIDTH , par->width); - put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELHEIGHT, par->height); - - mkv_write_field_order(pb, IS_WEBM(mkv), par->field_order); - - // 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, IS_WEBM(mkv), - &display_width_div, - &display_height_div); + ret = mkv_write_track_video(s, mkv, st, par, pb); if (ret < 0) return ret; - if (((tag = av_dict_get(st->metadata, "alpha_mode", NULL, 0)) && atoi(tag->value)) || - ((tag = av_dict_get( s->metadata, "alpha_mode", NULL, 0)) && atoi(tag->value)) || - (par->format == AV_PIX_FMT_YUVA420P)) { - put_ebml_uint(pb, MATROSKA_ID_VIDEOALPHAMODE, 1); - } - - // write DisplayWidth and DisplayHeight, they contain the size of - // a single source view and/or the display aspect ratio - if (st->sample_aspect_ratio.num) { - int64_t d_width = av_rescale(par->width, st->sample_aspect_ratio.num, st->sample_aspect_ratio.den); - if (d_width > INT_MAX) { - av_log(s, AV_LOG_ERROR, "Overflow in display width\n"); - return AVERROR(EINVAL); - } - if (d_width != par->width || display_width_div != 1 || display_height_div != 1) { - if (IS_WEBM(mkv) || display_width_div != 1 || display_height_div != 1) { - put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYWIDTH , d_width / display_width_div); - put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYHEIGHT, par->height / display_height_div); - } else { - AVRational display_aspect_ratio; - av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den, - par->width * (int64_t)st->sample_aspect_ratio.num, - par->height * (int64_t)st->sample_aspect_ratio.den, - 1024 * 1024); - put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYWIDTH, display_aspect_ratio.num); - put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYHEIGHT, display_aspect_ratio.den); - put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYUNIT, MATROSKA_VIDEO_DISPLAYUNIT_DAR); - } - } - } else if (display_width_div != 1 || display_height_div != 1) { - put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYWIDTH , par->width / display_width_div); - put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYHEIGHT, par->height / display_height_div); - } else if (!IS_WEBM(mkv)) - put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYUNIT, MATROSKA_VIDEO_DISPLAYUNIT_UNKNOWN); - - if (par->codec_id == AV_CODEC_ID_RAWVIDEO) { - uint32_t color_space = av_le2ne32(par->codec_tag); - put_ebml_binary(pb, MATROSKA_ID_VIDEOCOLORSPACE, &color_space, sizeof(color_space)); - } - mkv_write_video_color(pb, st, par); - mkv_write_video_projection(s, pb, st); - - end_ebml_master(pb, subinfo); - if (!IS_WEBM(mkv)) mkv_write_dovi(s, pb, st); @@ -1396,7 +1860,7 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, put_ebml_string(pb, MATROSKA_ID_CODECID, "A_MS/ACM"); subinfo = start_ebml_master(pb, MATROSKA_ID_TRACKAUDIO, 6 + 4 * 9); - put_ebml_uint (pb, MATROSKA_ID_AUDIOCHANNELS , par->channels); + put_ebml_uint(pb, MATROSKA_ID_AUDIOCHANNELS, par->ch_layout.nb_channels); track->sample_rate_offset = avio_tell(pb); put_ebml_float (pb, MATROSKA_ID_AUDIOSAMPLINGFREQ, sample_rate); @@ -1436,15 +1900,25 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, } if (!IS_WEBM(mkv) || par->codec_id != AV_CODEC_ID_WEBVTT) { + uint8_t *codecpriv; + int codecpriv_size, max_payload_size; track->codecpriv_offset = avio_tell(pb); - ret = mkv_write_codecprivate(s, pb, par, native_id, qt_id); + ret = mkv_assemble_codecprivate(s, mkv->tmp_bc, par, + par->extradata, par->extradata_size, + native_id, qt_id, + &codecpriv, &codecpriv_size, &max_payload_size); if (ret < 0) - return ret; + goto fail; + mkv_put_codecprivate(pb, max_payload_size, codecpriv, codecpriv_size); + track->codecpriv_size = max_payload_size; } end_ebml_master(pb, track_master); + ret = 0; +fail: + ffio_reset_dyn_buf(mkv->tmp_bc); - return 0; + return ret; } static int mkv_write_tracks(AVFormatContext *s) @@ -1503,10 +1977,11 @@ static int mkv_write_tracks(AVFormatContext *s) static int mkv_write_simpletag(AVIOContext *pb, const AVDictionaryEntry *t) { + EBML_WRITER(4); uint8_t *key = av_strdup(t->key); uint8_t *p = key; const uint8_t *lang = NULL; - ebml_master tag; + int ret; if (!key) return AVERROR(ENOMEM); @@ -1524,35 +1999,25 @@ static int mkv_write_simpletag(AVIOContext *pb, const AVDictionaryEntry *t) p++; } - tag = start_ebml_master(pb, MATROSKA_ID_SIMPLETAG, 0); - put_ebml_string(pb, MATROSKA_ID_TAGNAME, key); + ebml_writer_open_master(&writer, MATROSKA_ID_SIMPLETAG); + ebml_writer_add_string(&writer, MATROSKA_ID_TAGNAME, key); if (lang) - put_ebml_string(pb, MATROSKA_ID_TAGLANG, lang); - put_ebml_string(pb, MATROSKA_ID_TAGSTRING, t->value); - end_ebml_master(pb, tag); + ebml_writer_add_string(&writer, MATROSKA_ID_TAGLANG, lang); + ebml_writer_add_string(&writer, MATROSKA_ID_TAGSTRING, t->value); + ret = ebml_writer_write(&writer, pb); av_freep(&key); - return 0; + return ret; } -static int mkv_write_tag_targets(MatroskaMuxContext *mkv, AVIOContext **pb, - ebml_master *tag, uint32_t elementid, uint64_t uid) +static void mkv_write_tag_targets(MatroskaMuxContext *mkv, AVIOContext *pb, + uint32_t elementid, uint64_t uid) { - ebml_master targets; - int ret; - - if (!*pb) { - ret = start_ebml_master_crc32(pb, mkv); - if (ret < 0) - return ret; - } - - *tag = start_ebml_master(*pb, MATROSKA_ID_TAG, 0); - targets = start_ebml_master(*pb, MATROSKA_ID_TAGTARGETS, 4 + 1 + 8); + ebml_master targets = start_ebml_master(pb, MATROSKA_ID_TAGTARGETS, + 4 + 1 + 8); if (elementid) - put_ebml_uid(*pb, elementid, uid); - end_ebml_master(*pb, targets); - return 0; + put_ebml_uid(pb, elementid, uid); + end_ebml_master(pb, targets); } static int mkv_check_tag_name(const char *name, uint32_t elementid) @@ -1570,57 +2035,58 @@ static int mkv_check_tag_name(const char *name, uint32_t elementid) } static int mkv_write_tag(MatroskaMuxContext *mkv, const AVDictionary *m, - AVIOContext **pb, ebml_master *tag, + AVIOContext **pb, unsigned reserved_size, uint32_t elementid, uint64_t uid) { const AVDictionaryEntry *t = NULL; - ebml_master tag2; - int ret; + AVIOContext *const tmp_bc = mkv->tmp_bc; + uint8_t *buf; + int ret = 0, size, tag_written = 0; - ret = mkv_write_tag_targets(mkv, pb, tag ? tag : &tag2, elementid, uid); - if (ret < 0) - return ret; + mkv_write_tag_targets(mkv, tmp_bc, elementid, uid); while ((t = av_dict_get(m, "", t, AV_DICT_IGNORE_SUFFIX))) { if (mkv_check_tag_name(t->key, elementid)) { - ret = mkv_write_simpletag(*pb, t); + ret = mkv_write_simpletag(tmp_bc, t); if (ret < 0) - return ret; + goto end; + tag_written = 1; } } + if (reserved_size) + put_ebml_void(tmp_bc, reserved_size); + else if (!tag_written) + goto end; - if (!tag) - end_ebml_master(*pb, tag2); + size = avio_get_dyn_buf(tmp_bc, &buf); + if (tmp_bc->error) { + ret = tmp_bc->error; + goto end; + } + if (!*pb) { + ret = start_ebml_master_crc32(pb, mkv); + if (ret < 0) + goto end; + } + put_ebml_binary(*pb, MATROSKA_ID_TAG, buf, size); - return 0; -} - -static int mkv_check_tag(const AVDictionary *m, uint32_t elementid) -{ - const AVDictionaryEntry *t = NULL; - - while ((t = av_dict_get(m, "", t, AV_DICT_IGNORE_SUFFIX))) - if (mkv_check_tag_name(t->key, elementid)) - return 1; - - return 0; +end: + ffio_reset_dyn_buf(tmp_bc); + return ret; } static int mkv_write_tags(AVFormatContext *s) { MatroskaMuxContext *mkv = s->priv_data; - ebml_master tag, *tagp = IS_SEEKABLE(s->pb, mkv) ? &tag : NULL; - int i, ret; + int i, ret, seekable = IS_SEEKABLE(s->pb, mkv); mkv->wrote_tags = 1; ff_metadata_conv_ctx(s, ff_mkv_metadata_conv, NULL); - if (mkv_check_tag(s->metadata, 0)) { - ret = mkv_write_tag(mkv, s->metadata, &mkv->tags.bc, NULL, 0, 0); - if (ret < 0) - return ret; - } + ret = mkv_write_tag(mkv, s->metadata, &mkv->tags.bc, 0, 0, 0); + if (ret < 0) + return ret; for (i = 0; i < s->nb_streams; i++) { const AVStream *st = s->streams[i]; @@ -1629,29 +2095,13 @@ static int mkv_write_tags(AVFormatContext *s) if (st->codecpar->codec_type == AVMEDIA_TYPE_ATTACHMENT) continue; - if (!tagp && !mkv_check_tag(st->metadata, MATROSKA_ID_TAGTARGETS_TRACKUID)) - continue; - - ret = mkv_write_tag(mkv, st->metadata, &mkv->tags.bc, tagp, + ret = mkv_write_tag(mkv, st->metadata, &mkv->tags.bc, + seekable ? DURATION_SIMPLETAG_SIZE : 0, MATROSKA_ID_TAGTARGETS_TRACKUID, track->uid); if (ret < 0) return ret; - - if (tagp) { - AVIOContext *pb = mkv->tags.bc; - ebml_master simpletag; - - simpletag = start_ebml_master(pb, MATROSKA_ID_SIMPLETAG, - 2 + 1 + 8 + 23); - put_ebml_string(pb, MATROSKA_ID_TAGNAME, "DURATION"); - track->duration_offset = avio_tell(pb); - - // Reserve space to write duration as a 20-byte string. - // 2 (ebml id) + 1 (data size) + 20 (data) - put_ebml_void(pb, 23); - end_ebml_master(pb, simpletag); - end_ebml_master(pb, tag); - } + if (seekable) + track->duration_offset = avio_tell(mkv->tags.bc) - DURATION_SIMPLETAG_SIZE; } if (mkv->nb_attachments && !IS_WEBM(mkv)) { @@ -1662,10 +2112,7 @@ static int mkv_write_tags(AVFormatContext *s) if (st->codecpar->codec_type != AVMEDIA_TYPE_ATTACHMENT) continue; - if (!mkv_check_tag(st->metadata, MATROSKA_ID_TAGTARGETS_ATTACHUID)) - continue; - - ret = mkv_write_tag(mkv, st->metadata, &mkv->tags.bc, NULL, + ret = mkv_write_tag(mkv, st->metadata, &mkv->tags.bc, 0, MATROSKA_ID_TAGTARGETS_ATTACHUID, track->uid); if (ret < 0) return ret; @@ -1718,12 +2165,13 @@ static int mkv_write_chapters(AVFormatContext *s) create_new_ids = mkv_new_chapter_ids_needed(s); for (unsigned i = 0; i < s->nb_chapters; i++) { - ebml_master chapteratom, chapterdisplay; - const AVChapter *c = s->chapters[i]; + AVChapter *const c = s->chapters[i]; int64_t chapterstart = av_rescale_q(c->start, c->time_base, scale); int64_t chapterend = av_rescale_q(c->end, c->time_base, scale); const AVDictionaryEntry *t; uint64_t uid = create_new_ids ? i + 1ULL : c->id; + EBML_WRITER(7); + if (chapterstart < 0 || chapterstart > chapterend || chapterend < 0) { av_log(s, AV_LOG_ERROR, "Invalid chapter start (%"PRId64") or end (%"PRId64").\n", @@ -1732,20 +2180,23 @@ static int mkv_write_chapters(AVFormatContext *s) goto fail; } - chapteratom = start_ebml_master(dyn_cp, MATROSKA_ID_CHAPTERATOM, 0); - put_ebml_uint(dyn_cp, MATROSKA_ID_CHAPTERUID, uid); - put_ebml_uint(dyn_cp, MATROSKA_ID_CHAPTERTIMESTART, chapterstart); - put_ebml_uint(dyn_cp, MATROSKA_ID_CHAPTERTIMEEND, chapterend); + ebml_writer_open_master(&writer, MATROSKA_ID_CHAPTERATOM); + ebml_writer_add_uint(&writer, MATROSKA_ID_CHAPTERUID, uid); + ebml_writer_add_uint(&writer, MATROSKA_ID_CHAPTERTIMESTART, chapterstart); + ebml_writer_add_uint(&writer, MATROSKA_ID_CHAPTERTIMEEND, chapterend); if ((t = av_dict_get(c->metadata, "title", NULL, 0))) { - chapterdisplay = start_ebml_master(dyn_cp, MATROSKA_ID_CHAPTERDISPLAY, 0); - put_ebml_string(dyn_cp, MATROSKA_ID_CHAPSTRING, t->value); - put_ebml_string(dyn_cp, MATROSKA_ID_CHAPLANG , "und"); - end_ebml_master(dyn_cp, chapterdisplay); + ebml_writer_open_master(&writer, MATROSKA_ID_CHAPTERDISPLAY); + ebml_writer_add_string(&writer, MATROSKA_ID_CHAPSTRING, t->value); + ebml_writer_add_string(&writer, MATROSKA_ID_CHAPLANG , "und"); } - end_ebml_master(dyn_cp, chapteratom); + ret = ebml_writer_write(&writer, dyn_cp); + if (ret < 0) + goto fail; - if (tags && mkv_check_tag(c->metadata, MATROSKA_ID_TAGTARGETS_CHAPTERUID)) { - ret = mkv_write_tag(mkv, c->metadata, tags, NULL, + if (tags) { + ff_metadata_conv(&c->metadata, ff_mkv_metadata_conv, NULL); + + ret = mkv_write_tag(mkv, c->metadata, tags, 0, MATROSKA_ID_TAGTARGETS_CHAPTERUID, uid); if (ret < 0) goto fail; @@ -1805,30 +2256,35 @@ static int mkv_write_attachments(AVFormatContext *s) for (i = 0; i < s->nb_streams; i++) { const AVStream *st = s->streams[i]; mkv_track *track = &mkv->tracks[i]; - ebml_master attached_file; + EBML_WRITER(6); const AVDictionaryEntry *t; const char *mimetype; if (st->codecpar->codec_type != AVMEDIA_TYPE_ATTACHMENT) continue; - attached_file = start_ebml_master(dyn_cp, MATROSKA_ID_ATTACHEDFILE, 0); + ebml_writer_open_master(&writer, MATROSKA_ID_ATTACHEDFILE); if (t = av_dict_get(st->metadata, "title", NULL, 0)) - put_ebml_string(dyn_cp, MATROSKA_ID_FILEDESC, t->value); + ebml_writer_add_string(&writer, MATROSKA_ID_FILEDESC, t->value); if (!(t = av_dict_get(st->metadata, "filename", NULL, 0))) { av_log(s, AV_LOG_ERROR, "Attachment stream %d has no filename tag.\n", i); ffio_free_dyn_buf(&dyn_cp); return AVERROR(EINVAL); } - put_ebml_string(dyn_cp, MATROSKA_ID_FILENAME, t->value); + ebml_writer_add_string(&writer, MATROSKA_ID_FILENAME, t->value); mimetype = get_mimetype(st); av_assert0(mimetype); - put_ebml_string(dyn_cp, MATROSKA_ID_FILEMIMETYPE, mimetype); - put_ebml_binary(dyn_cp, MATROSKA_ID_FILEDATA, st->codecpar->extradata, st->codecpar->extradata_size); - put_ebml_uid(dyn_cp, MATROSKA_ID_FILEUID, track->uid); - end_ebml_master(dyn_cp, attached_file); + ebml_writer_add_string(&writer, MATROSKA_ID_FILEMIMETYPE, mimetype); + ebml_writer_add_bin(&writer, MATROSKA_ID_FILEDATA, + st->codecpar->extradata, st->codecpar->extradata_size); + ebml_writer_add_uid(&writer, MATROSKA_ID_FILEUID, track->uid); + ret = ebml_writer_write(&writer, dyn_cp); + if (ret < 0) { + ffio_free_dyn_buf(&dyn_cp); + return ret; + } } return end_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_ATTACHMENTS, 0, 0, 1); @@ -1858,46 +2314,29 @@ static int64_t get_metadata_duration(AVFormatContext *s) return max; } -static int mkv_write_header(AVFormatContext *s) +static void ebml_write_header(AVIOContext *pb, + const char *doctype, int version) +{ + EBML_WRITER(8); + ebml_writer_open_master(&writer, EBML_ID_HEADER); + ebml_writer_add_uint (&writer, EBML_ID_EBMLVERSION, 1); + ebml_writer_add_uint (&writer, EBML_ID_EBMLREADVERSION, 1); + ebml_writer_add_uint (&writer, EBML_ID_EBMLMAXIDLENGTH, 4); + ebml_writer_add_uint (&writer, EBML_ID_EBMLMAXSIZELENGTH, 8); + ebml_writer_add_string(&writer, EBML_ID_DOCTYPE, doctype); + ebml_writer_add_uint (&writer, EBML_ID_DOCTYPEVERSION, version); + ebml_writer_add_uint (&writer, EBML_ID_DOCTYPEREADVERSION, 2); + /* The size is bounded, so no need to check this. */ + ebml_writer_write(&writer, pb); +} + +static int mkv_write_info(AVFormatContext *s) { MatroskaMuxContext *mkv = s->priv_data; - AVIOContext *pb = s->pb; - ebml_master ebml_header; const AVDictionaryEntry *tag; - int ret, i, version = 2; int64_t creation_time; - - if (!IS_WEBM(mkv) || - av_dict_get(s->metadata, "stereo_mode", NULL, 0) || - av_dict_get(s->metadata, "alpha_mode", NULL, 0)) - version = 4; - - for (i = 0; i < s->nb_streams; i++) { - 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)) - version = 4; - } - - ebml_header = start_ebml_master(pb, EBML_ID_HEADER, MAX_EBML_HEADER_SIZE); - put_ebml_uint (pb, EBML_ID_EBMLVERSION , 1); - put_ebml_uint (pb, EBML_ID_EBMLREADVERSION , 1); - put_ebml_uint (pb, EBML_ID_EBMLMAXIDLENGTH , 4); - put_ebml_uint (pb, EBML_ID_EBMLMAXSIZELENGTH , 8); - put_ebml_string(pb, EBML_ID_DOCTYPE , s->oformat->name); - put_ebml_uint (pb, EBML_ID_DOCTYPEVERSION , version); - put_ebml_uint (pb, EBML_ID_DOCTYPEREADVERSION, 2); - end_ebml_master(pb, ebml_header); - - put_ebml_id(pb, MATROSKA_ID_SEGMENT); - put_ebml_size_unknown(pb, 8); - mkv->segment_offset = avio_tell(pb); - - // We write a SeekHead at the beginning to point to all other level - // one elements (except Clusters). - mkv_start_seekhead(mkv, pb); - - ret = start_ebml_master_crc32(&mkv->info.bc, mkv); + AVIOContext *pb; + int ret = start_ebml_master_crc32(&mkv->info.bc, mkv); if (ret < 0) return ret; pb = mkv->info.bc; @@ -1946,11 +2385,44 @@ static int mkv_write_header(AVFormatContext *s) put_ebml_void(pb, 11); // assumes double-precision float to be written } } - ret = end_ebml_master_crc32_tentatively(s->pb, &mkv->info, - mkv, MATROSKA_ID_INFO); + return end_ebml_master_crc32_tentatively(s->pb, &mkv->info, + mkv, MATROSKA_ID_INFO); +} + +static int mkv_write_header(AVFormatContext *s) +{ + MatroskaMuxContext *mkv = s->priv_data; + AVIOContext *pb = s->pb; + int ret, version = 2; + + ret = avio_open_dyn_buf(&mkv->tmp_bc); + if (ret < 0) + return ret; + + if (!IS_WEBM(mkv) || + av_dict_get(s->metadata, "stereo_mode", NULL, 0) || + av_dict_get(s->metadata, "alpha_mode", NULL, 0)) + version = 4; + + for (unsigned i = 0; i < s->nb_streams; i++) { + 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)) + version = 4; + } + + ebml_write_header(pb, s->oformat->name, version); + put_ebml_id(pb, MATROSKA_ID_SEGMENT); + put_ebml_size_unknown(pb, 8); + mkv->segment_offset = avio_tell(pb); + + // We write a SeekHead at the beginning to point to all other level + // one elements (except Clusters). + mkv_start_seekhead(mkv, pb); + + ret = mkv_write_info(s); if (ret < 0) return ret; - pb = s->pb; ret = mkv_write_tracks(s); if (ret < 0) @@ -1984,12 +2456,14 @@ static int mkv_write_header(AVFormatContext *s) put_ebml_void(pb, s->metadata_header_padding); } - if (mkv->reserve_cues_space) { + if (mkv->reserve_cues_space || mkv->move_cues_to_front) { if (IS_SEEKABLE(pb, mkv)) { mkv->cues_pos = avio_tell(pb); - if (mkv->reserve_cues_space == 1) - mkv->reserve_cues_space++; - put_ebml_void(pb, mkv->reserve_cues_space); + if (mkv->reserve_cues_space >= 1) { + if (mkv->reserve_cues_space == 1) + mkv->reserve_cues_space++; + put_ebml_void(pb, mkv->reserve_cues_space); + } } else mkv->reserve_cues_space = -1; } @@ -2013,127 +2487,134 @@ static int mkv_write_header(AVFormatContext *s) return 0; } -static int mkv_blockgroup_size(int pkt_size, int track_num_size) +#if CONFIG_MATROSKA_MUXER +static int mkv_reformat_h2645(MatroskaMuxContext *mkv, AVIOContext *pb, + const AVPacket *pkt, int *size) { - int size = pkt_size + track_num_size + 3; - size += ebml_length_size(size); - size += 2; // EBML ID for block and block duration - size += 9; // max size of block duration incl. length field - return size; + int ret; + if (pb) { + ff_nal_units_write_list(&mkv->cur_block.h2645_nalu_list, pb, pkt->data); + } else { + ret = ff_nal_units_create_list(&mkv->cur_block.h2645_nalu_list, pkt->data, pkt->size); + if (ret < 0) + return ret; + *size = ret; + } + return 0; } -#if CONFIG_MATROSKA_MUXER -static int mkv_strip_wavpack(const uint8_t *src, uint8_t **pdst, int *size) +static int mkv_reformat_wavpack(MatroskaMuxContext *mkv, AVIOContext *pb, + const AVPacket *pkt, int *size) { - uint8_t *dst; - int srclen = *size; + const uint8_t *src = pkt->data; + int srclen = pkt->size; int offset = 0; int ret; - dst = av_malloc(srclen); - if (!dst) - return AVERROR(ENOMEM); - while (srclen >= WV_HEADER_SIZE) { WvHeader header; ret = ff_wv_parse_header(&header, src); if (ret < 0) - goto fail; + return ret; src += WV_HEADER_SIZE; srclen -= WV_HEADER_SIZE; - if (srclen < header.blocksize) { - ret = AVERROR_INVALIDDATA; - goto fail; - } + if (srclen < header.blocksize) + return AVERROR_INVALIDDATA; - if (header.initial) { - AV_WL32(dst + offset, header.samples); - offset += 4; - } - AV_WL32(dst + offset, header.flags); - AV_WL32(dst + offset + 4, header.crc); - offset += 8; + offset += 4 * !!header.initial + 8 + 4 * !(header.initial && header.final); + if (pb) { + if (header.initial) + avio_wl32(pb, header.samples); + avio_wl32(pb, header.flags); + avio_wl32(pb, header.crc); - if (!(header.initial && header.final)) { - AV_WL32(dst + offset, header.blocksize); - offset += 4; - } + if (!(header.initial && header.final)) + avio_wl32(pb, header.blocksize); - memcpy(dst + offset, src, header.blocksize); + avio_write(pb, src, header.blocksize); + } src += header.blocksize; srclen -= header.blocksize; offset += header.blocksize; } - - *pdst = dst; *size = offset; return 0; -fail: - av_freep(&dst); - return ret; } #endif -static int mkv_write_block(AVFormatContext *s, AVIOContext *pb, - uint32_t blockid, const AVPacket *pkt, int keyframe) +static int mkv_reformat_av1(MatroskaMuxContext *mkv, AVIOContext *pb, + const AVPacket *pkt, int *size) { - MatroskaMuxContext *mkv = s->priv_data; - AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar; - mkv_track *track = &mkv->tracks[pkt->stream_index]; - uint8_t *data = NULL, *side_data = NULL; + int ret = ff_av1_filter_obus(pb, pkt->data, pkt->size); + if (ret < 0) + return ret; + *size = ret; + return 0; +} + +static int webm_reformat_vtt(MatroskaMuxContext *mkv, AVIOContext *pb, + const AVPacket *pkt, int *size) +{ + const uint8_t *id, *settings; + size_t id_size, settings_size; + unsigned total = pkt->size + 2U; + + if (total > INT_MAX) + return AVERROR(ERANGE); + + id = av_packet_get_side_data(pkt, AV_PKT_DATA_WEBVTT_IDENTIFIER, + &id_size); + settings = av_packet_get_side_data(pkt, AV_PKT_DATA_WEBVTT_SETTINGS, + &settings_size); + if (id_size > INT_MAX - total || settings_size > INT_MAX - (total += id_size)) + return AVERROR(ERANGE); + *size = total += settings_size; + if (pb) { + avio_write(pb, id, id_size); + avio_w8(pb, '\n'); + avio_write(pb, settings, settings_size); + avio_w8(pb, '\n'); + avio_write(pb, pkt->data, pkt->size); + } + return 0; +} + +static int mkv_write_block(void *logctx, MatroskaMuxContext *mkv, + AVIOContext *pb, const AVCodecParameters *par, + mkv_track *track, const AVPacket *pkt, + int keyframe, int64_t ts, uint64_t duration, + int force_blockgroup, int64_t relative_packet_pos) +{ + uint8_t *side_data; size_t side_data_size; - int err = 0, offset = 0, size = pkt->size; - int64_t ts = track->write_dts ? pkt->dts : pkt->pts; uint64_t additional_id; int64_t discard_padding = 0; unsigned track_number = track->track_num; - ebml_master block_group, block_additions, block_more; + EBML_WRITER(9); - ts += track->ts_offset; + mkv->cur_block.track = track; + mkv->cur_block.pkt = pkt; + mkv->cur_block.rel_ts = ts - mkv->cluster_pts; + mkv->cur_block.flags = 0; - /* The following string is identical to the one in mkv_write_vtt_blocks - * so that only one copy needs to exist in binaries. */ - av_log(s, AV_LOG_DEBUG, + /* Open a BlockGroup with a Block now; it will later be converted + * to a SimpleBlock if possible. */ + ebml_writer_open_master(&writer, MATROSKA_ID_BLOCKGROUP); + ebml_writer_add_block(&writer, mkv); + + if (duration) + ebml_writer_add_uint(&writer, MATROSKA_ID_BLOCKDURATION, duration); + + av_log(logctx, AV_LOG_DEBUG, "Writing block of size %d with pts %" PRId64 ", dts %" PRId64 ", " "duration %" PRId64 " at relative offset %" PRId64 " in cluster " "at offset %" PRId64 ". TrackNumber %u, keyframe %d\n", - pkt->size, pkt->pts, pkt->dts, pkt->duration, avio_tell(pb), + pkt->size, pkt->pts, pkt->dts, pkt->duration, relative_packet_pos, mkv->cluster_pos, track_number, keyframe != 0); -#if CONFIG_MATROSKA_MUXER - if (par->codec_id == AV_CODEC_ID_H264 && par->extradata_size > 0 && - (AV_RB24(par->extradata) == 1 || AV_RB32(par->extradata) == 1)) { - err = ff_avc_parse_nal_units_buf(pkt->data, &data, &size); - } else if (par->codec_id == AV_CODEC_ID_HEVC && par->extradata_size > 6 && - (AV_RB24(par->extradata) == 1 || AV_RB32(par->extradata) == 1)) { - /* extradata is Annex B, assume the bitstream is too and convert it */ - err = ff_hevc_annexb2mp4_buf(pkt->data, &data, &size, 0, NULL); - } else if (par->codec_id == AV_CODEC_ID_WAVPACK) { - err = mkv_strip_wavpack(pkt->data, &data, &size); - } else -#endif - if (par->codec_id == AV_CODEC_ID_AV1) { - err = ff_av1_filter_obus_buf(pkt->data, &data, &size, &offset); - } else - data = pkt->data; - - if (err < 0) { - av_log(s, AV_LOG_ERROR, "Error when reformatting data of " - "a packet from stream %d.\n", pkt->stream_index); - return err; - } - - if (CONFIG_MATROSKA_MUXER && - par->codec_id == AV_CODEC_ID_PRORES && size >= 8) { - /* Matroska specification requires to remove the first QuickTime atom - */ - size -= 8; - offset = 8; - } - side_data = av_packet_get_side_data(pkt, AV_PKT_DATA_SKIP_SAMPLES, &side_data_size); @@ -2141,110 +2622,39 @@ static int mkv_write_block(AVFormatContext *s, AVIOContext *pb, discard_padding = av_rescale_q(AV_RL32(side_data + 4), (AVRational){1, par->sample_rate}, (AVRational){1, 1000000000}); + ebml_writer_add_sint(&writer, MATROSKA_ID_DISCARDPADDING, discard_padding); } side_data = av_packet_get_side_data(pkt, AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, &side_data_size); - if (side_data) { + if (side_data && side_data_size >= 8 && // Only the Codec-specific BlockMore (id == 1) is currently supported. - if (side_data_size < 8 || (additional_id = AV_RB64(side_data)) != 1) { - side_data_size = 0; - } else { - side_data += 8; - side_data_size -= 8; - } - } - - if (side_data_size || discard_padding) { - block_group = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP, 0); - blockid = MATROSKA_ID_BLOCK; - } - - put_ebml_id(pb, blockid); - put_ebml_length(pb, size + track->track_num_size + 3, 0); - put_ebml_num(pb, track_number, track->track_num_size); - avio_wb16(pb, ts - mkv->cluster_pts); - avio_w8(pb, (blockid == MATROSKA_ID_SIMPLEBLOCK && keyframe) ? (1 << 7) : 0); - avio_write(pb, data + offset, size); - if (data != pkt->data) - av_free(data); - - if (blockid == MATROSKA_ID_BLOCK && !keyframe) - put_ebml_sint(pb, MATROSKA_ID_BLOCKREFERENCE, track->last_timestamp - ts); - track->last_timestamp = ts; - - if (discard_padding) - put_ebml_sint(pb, MATROSKA_ID_DISCARDPADDING, discard_padding); - - if (side_data_size) { - block_additions = start_ebml_master(pb, MATROSKA_ID_BLOCKADDITIONS, 0); - block_more = start_ebml_master(pb, MATROSKA_ID_BLOCKMORE, 0); + (additional_id = AV_RB64(side_data)) == 1) { + ebml_writer_open_master(&writer, MATROSKA_ID_BLOCKADDITIONS); + ebml_writer_open_master(&writer, MATROSKA_ID_BLOCKMORE); /* Until dbc50f8a our demuxer used a wrong default value * of BlockAddID, so we write it unconditionally. */ - put_ebml_uint (pb, MATROSKA_ID_BLOCKADDID, additional_id); - put_ebml_binary(pb, MATROSKA_ID_BLOCKADDITIONAL, - side_data, side_data_size); - end_ebml_master(pb, block_more); - end_ebml_master(pb, block_additions); + ebml_writer_add_uint(&writer, MATROSKA_ID_BLOCKADDID, additional_id); + ebml_writer_add_bin (&writer, MATROSKA_ID_BLOCKADDITIONAL, + side_data + 8, side_data_size - 8); + ebml_writer_close_master(&writer); + ebml_writer_close_master(&writer); } - if (side_data_size || discard_padding) - end_ebml_master(pb, block_group); - return 0; -} + if (!force_blockgroup && writer.nb_elements == 2) { + /* Nothing except the BlockGroup + Block. Can use a SimpleBlock. */ + writer.elements++; // Skip the BlockGroup. + writer.nb_elements--; + av_assert2(writer.elements[0].id == MATROSKA_ID_BLOCK); + writer.elements[0].id = MATROSKA_ID_SIMPLEBLOCK; + if (keyframe) + mkv->cur_block.flags |= 1 << 7; + } else if (!keyframe) + ebml_writer_add_sint(&writer, MATROSKA_ID_BLOCKREFERENCE, + track->last_timestamp - ts); -static int mkv_write_vtt_blocks(AVFormatContext *s, AVIOContext *pb, const AVPacket *pkt) -{ - MatroskaMuxContext *mkv = s->priv_data; - mkv_track *track = &mkv->tracks[pkt->stream_index]; - ebml_master blockgroup; - size_t id_size, settings_size; - int size, id_size_int, settings_size_int; - const char *id, *settings; - int64_t ts = track->write_dts ? pkt->dts : pkt->pts; - const int flags = 0; - - id = av_packet_get_side_data(pkt, AV_PKT_DATA_WEBVTT_IDENTIFIER, - &id_size); - id = id ? id : ""; - - settings = av_packet_get_side_data(pkt, AV_PKT_DATA_WEBVTT_SETTINGS, - &settings_size); - settings = settings ? settings : ""; - - if (id_size > INT_MAX - 2 || settings_size > INT_MAX - id_size - 2 || - pkt->size > INT_MAX - settings_size - id_size - 2) - return AVERROR(EINVAL); - - size = id_size + 1 + settings_size + 1 + pkt->size; - - /* The following string is identical to the one in mkv_write_block so that - * only one copy needs to exist in binaries. */ - av_log(s, AV_LOG_DEBUG, - "Writing block of size %d with pts %" PRId64 ", dts %" PRId64 ", " - "duration %" PRId64 " at relative offset %" PRId64 " in cluster " - "at offset %" PRId64 ". TrackNumber %u, keyframe %d\n", - size, pkt->pts, pkt->dts, pkt->duration, avio_tell(pb), - mkv->cluster_pos, track->track_num, 1); - - blockgroup = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP, - mkv_blockgroup_size(size, track->track_num_size)); - - put_ebml_id(pb, MATROSKA_ID_BLOCK); - put_ebml_length(pb, size + track->track_num_size + 3, 0); - put_ebml_num(pb, track->track_num, track->track_num_size); - avio_wb16(pb, ts - mkv->cluster_pts); - avio_w8(pb, flags); - - id_size_int = id_size; - settings_size_int = settings_size; - avio_printf(pb, "%.*s\n%.*s\n%.*s", id_size_int, id, settings_size_int, settings, pkt->size, pkt->data); - - put_ebml_uint(pb, MATROSKA_ID_BLOCKDURATION, pkt->duration); - end_ebml_master(pb, blockgroup); - - return 0; + return ebml_writer_write(&writer, pb); } static int mkv_end_cluster(AVFormatContext *s) @@ -2282,22 +2692,17 @@ static int mkv_check_new_extra_data(AVFormatContext *s, const AVPacket *pkt) #if CONFIG_MATROSKA_MUXER case AV_CODEC_ID_AAC: if (side_data_size && mkv->track.bc) { - int filler, output_sample_rate = 0; + int output_sample_rate = 0; ret = get_aac_sample_rates(s, mkv, side_data, side_data_size, &track->sample_rate, &output_sample_rate); if (ret < 0) return ret; if (!output_sample_rate) output_sample_rate = track->sample_rate; // Space is already reserved, so it's this or a void element. - ret = ff_alloc_extradata(par, side_data_size); + ret = mkv_update_codecprivate(s, mkv, side_data, side_data_size, + par, mkv->track.bc, track, 0); if (ret < 0) return ret; - memcpy(par->extradata, side_data, side_data_size); - avio_seek(mkv->track.bc, track->codecpriv_offset, SEEK_SET); - mkv_write_codecprivate(s, mkv->track.bc, par, 1, 0); - filler = MAX_PCE_SIZE + 2 + 4 - (avio_tell(mkv->track.bc) - track->codecpriv_offset); - if (filler) - put_ebml_void(mkv->track.bc, filler); avio_seek(mkv->track.bc, track->sample_rate_offset, SEEK_SET); put_ebml_float(mkv->track.bc, MATROSKA_ID_AUDIOSAMPLINGFREQ, track->sample_rate); put_ebml_float(mkv->track.bc, MATROSKA_ID_AUDIOOUTSAMPLINGFREQ, output_sample_rate); @@ -2309,44 +2714,28 @@ static int mkv_check_new_extra_data(AVFormatContext *s, const AVPacket *pkt) break; case AV_CODEC_ID_FLAC: if (side_data_size && mkv->track.bc) { - uint8_t *old_extradata = par->extradata; if (side_data_size != par->extradata_size) { av_log(s, AV_LOG_ERROR, "Invalid FLAC STREAMINFO metadata for output stream %d\n", pkt->stream_index); return AVERROR(EINVAL); } - par->extradata = side_data; - avio_seek(mkv->track.bc, track->codecpriv_offset, SEEK_SET); - mkv_write_codecprivate(s, mkv->track.bc, par, 1, 0); - par->extradata = old_extradata; + ret = mkv_update_codecprivate(s, mkv, side_data, side_data_size, + par, mkv->track.bc, track, 0); + if (ret < 0) + return ret; } break; #endif - // FIXME: Remove the following once libaom starts propagating extradata during init() - // See https://bugs.chromium.org/p/aomedia/issues/detail?id=2012 + // FIXME: Remove the following once libaom starts propagating proper extradata during init() + // See https://bugs.chromium.org/p/aomedia/issues/detail?id=2208 case AV_CODEC_ID_AV1: if (side_data_size && mkv->track.bc && !par->extradata_size) { - AVIOContext *dyn_cp; - uint8_t *codecpriv; - int codecpriv_size; - ret = avio_open_dyn_buf(&dyn_cp); + // If the reserved space doesn't suffice, only write + // the first four bytes of the av1C. + ret = mkv_update_codecprivate(s, mkv, side_data, side_data_size, + par, mkv->track.bc, track, 4); if (ret < 0) return ret; - ff_isom_write_av1c(dyn_cp, side_data, side_data_size); - codecpriv_size = avio_get_dyn_buf(dyn_cp, &codecpriv); - if ((ret = dyn_cp->error) < 0 || - !codecpriv_size && (ret = AVERROR_INVALIDDATA)) { - ffio_free_dyn_buf(&dyn_cp); - return ret; - } - avio_seek(mkv->track.bc, track->codecpriv_offset, SEEK_SET); - // Do not write the OBUs as we don't have space saved for them - put_ebml_binary(mkv->track.bc, MATROSKA_ID_CODECPRIVATE, codecpriv, 4); - ffio_free_dyn_buf(&dyn_cp); - ret = ff_alloc_extradata(par, side_data_size); - if (ret < 0) - return ret; - memcpy(par->extradata, side_data, side_data_size); } else if (!par->extradata_size) return AVERROR_INVALIDDATA; break; @@ -2365,8 +2754,11 @@ static int mkv_write_packet_internal(AVFormatContext *s, const AVPacket *pkt) AVIOContext *pb; AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar; mkv_track *track = &mkv->tracks[pkt->stream_index]; - int keyframe = !!(pkt->flags & AV_PKT_FLAG_KEY); - int64_t duration = pkt->duration; + int is_sub = par->codec_type == AVMEDIA_TYPE_SUBTITLE; + /* All subtitle blocks are considered to be keyframes. */ + int keyframe = is_sub || !!(pkt->flags & AV_PKT_FLAG_KEY); + int64_t duration = FFMAX(pkt->duration, 0); + int64_t write_duration = is_sub ? duration : 0; int ret; int64_t ts = track->write_dts ? pkt->dts : pkt->pts; int64_t relative_packet_pos; @@ -2391,6 +2783,7 @@ static int mkv_write_packet_internal(AVFormatContext *s, const AVPacket *pkt) ret = start_ebml_master_crc32(&mkv->cluster_bc, mkv); if (ret < 0) return ret; + mkv->cluster_bc->direct = 1; mkv->cluster_pos = avio_tell(s->pb); put_ebml_uint(mkv->cluster_bc, MATROSKA_ID_CLUSTERTIMECODE, FFMAX(0, ts)); mkv->cluster_pts = FFMAX(0, ts); @@ -2403,45 +2796,27 @@ static int mkv_write_packet_internal(AVFormatContext *s, const AVPacket *pkt) relative_packet_pos = avio_tell(pb); - if (par->codec_type != AVMEDIA_TYPE_SUBTITLE || - (par->codec_id != AV_CODEC_ID_WEBVTT && duration <= 0)) { - ret = mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe); + /* The WebM spec requires WebVTT to be muxed in BlockGroups; + * so we force it even for packets without duration. */ + ret = mkv_write_block(s, mkv, pb, par, track, pkt, + keyframe, ts, write_duration, + par->codec_id == AV_CODEC_ID_WEBVTT, + relative_packet_pos); + if (ret < 0) + return ret; + if (keyframe && IS_SEEKABLE(s->pb, mkv) && + (par->codec_type == AVMEDIA_TYPE_VIDEO || + par->codec_type == AVMEDIA_TYPE_SUBTITLE || + !mkv->have_video && !track->has_cue)) { + ret = mkv_add_cuepoint(mkv, pkt->stream_index, ts, + mkv->cluster_pos, relative_packet_pos, + write_duration); if (ret < 0) return ret; - if (keyframe && IS_SEEKABLE(s->pb, mkv) && - (par->codec_type == AVMEDIA_TYPE_VIDEO || - par->codec_type == AVMEDIA_TYPE_SUBTITLE || - !mkv->have_video && !track->has_cue)) { - ret = mkv_add_cuepoint(mkv, pkt->stream_index, ts, - mkv->cluster_pos, relative_packet_pos, 0); - if (ret < 0) - return ret; - track->has_cue = 1; - } - } else { - if (par->codec_id == AV_CODEC_ID_WEBVTT) { - ret = mkv_write_vtt_blocks(s, pb, pkt); - if (ret < 0) - return ret; - } else { - ebml_master blockgroup = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP, - mkv_blockgroup_size(pkt->size, - track->track_num_size)); - - /* All subtitle blocks are considered to be keyframes. */ - mkv_write_block(s, pb, MATROSKA_ID_BLOCK, pkt, 1); - put_ebml_uint(pb, MATROSKA_ID_BLOCKDURATION, duration); - end_ebml_master(pb, blockgroup); - } - - if (IS_SEEKABLE(s->pb, mkv)) { - ret = mkv_add_cuepoint(mkv, pkt->stream_index, ts, - mkv->cluster_pos, relative_packet_pos, duration); - if (ret < 0) - return ret; - } + track->has_cue = 1; } + track->last_timestamp = ts; mkv->duration = FFMAX(mkv->duration, ts + duration); track->duration = FFMAX(track->duration, ts + duration); @@ -2575,25 +2950,31 @@ static int mkv_write_trailer(AVFormatContext *s) if (mkv->cues.num_entries && mkv->reserve_cues_space >= 0) { AVIOContext *cues = NULL; - uint64_t size; + uint64_t size, offset = 0; int length_size = 0; +redo_cues: ret = start_ebml_master_crc32(&cues, mkv); if (ret < 0) return ret; - ret = mkv_assemble_cues(s->streams, cues, &mkv->cues, - mkv->tracks, s->nb_streams); + ret = mkv_assemble_cues(s->streams, cues, mkv->tmp_bc, &mkv->cues, + mkv->tracks, s->nb_streams, offset); if (ret < 0) { ffio_free_dyn_buf(&cues); return ret; } - if (mkv->reserve_cues_space) { + if (mkv->reserve_cues_space || mkv->move_cues_to_front) { size = avio_tell(cues); length_size = ebml_length_size(size); size += 4 + length_size; - if (mkv->reserve_cues_space < size) { + if (offset + mkv->reserve_cues_space < size) { + if (mkv->move_cues_to_front) { + offset = size - mkv->reserve_cues_space; + ffio_reset_dyn_buf(cues); + goto redo_cues; + } av_log(s, AV_LOG_WARNING, "Insufficient space reserved for Cues: " "%d < %"PRIu64". No Cues will be output.\n", @@ -2601,6 +2982,15 @@ static int mkv_write_trailer(AVFormatContext *s) ret2 = AVERROR(EINVAL); goto after_cues; } else { + if (offset) { + ret = ff_format_shift_data(s, mkv->cues_pos + mkv->reserve_cues_space, + offset); + if (ret < 0) { + ffio_free_dyn_buf(&cues); + return ret; + } + endpos += offset; + } if ((ret64 = avio_seek(pb, mkv->cues_pos, SEEK_SET)) < 0) { ffio_free_dyn_buf(&cues); return ret64; @@ -2623,7 +3013,7 @@ static int mkv_write_trailer(AVFormatContext *s) if (mkv->reserve_cues_space) { if (size < mkv->reserve_cues_space) put_ebml_void(pb, mkv->reserve_cues_space - size); - } else + } else if (!mkv->move_cues_to_front) endpos = avio_tell(pb); } @@ -2662,6 +3052,7 @@ after_cues: // update stream durations if (mkv->tags.bc) { + AVIOContext *tags_bc = mkv->tags.bc; int i; for (i = 0; i < s->nb_streams; ++i) { const AVStream *st = s->streams[i]; @@ -2670,17 +3061,22 @@ after_cues: if (track->duration_offset > 0) { double duration_sec = track->duration * av_q2d(st->time_base); char duration_string[20] = ""; + ebml_master simpletag; av_log(s, AV_LOG_DEBUG, "stream %d end duration = %" PRIu64 "\n", i, track->duration); - avio_seek(mkv->tags.bc, track->duration_offset, SEEK_SET); + avio_seek(tags_bc, track->duration_offset, SEEK_SET); + simpletag = start_ebml_master(tags_bc, MATROSKA_ID_SIMPLETAG, + 2 + 1 + 8 + 23); + put_ebml_string(tags_bc, MATROSKA_ID_TAGNAME, "DURATION"); snprintf(duration_string, 20, "%02d:%02d:%012.9f", (int) duration_sec / 3600, ((int) duration_sec / 60) % 60, fmod(duration_sec, 60)); - put_ebml_binary(mkv->tags.bc, MATROSKA_ID_TAGSTRING, duration_string, 20); + put_ebml_binary(tags_bc, MATROSKA_ID_TAGSTRING, duration_string, 20); + end_ebml_master(tags_bc, simpletag); } } @@ -2722,6 +3118,8 @@ static int mkv_init(struct AVFormatContext *s) unsigned nb_tracks = 0; int i; + mkv->ctx = s; + 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 || @@ -2764,8 +3162,35 @@ static int mkv_init(struct AVFormatContext *s) for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; + const AVCodecParameters *const par = st->codecpar; mkv_track *track = &mkv->tracks[i]; + switch (par->codec_id) { +#if CONFIG_MATROSKA_MUXER + case AV_CODEC_ID_WAVPACK: + track->reformat = mkv_reformat_wavpack; + break; + case AV_CODEC_ID_H264: + case AV_CODEC_ID_HEVC: + if ((par->codec_id == AV_CODEC_ID_H264 && par->extradata_size > 0 || + par->codec_id == AV_CODEC_ID_HEVC && par->extradata_size > 6) && + (AV_RB24(par->extradata) == 1 || AV_RB32(par->extradata) == 1)) + track->reformat = mkv_reformat_h2645; + break; + case AV_CODEC_ID_PRORES: + /* Matroska specification requires to remove + * the first QuickTime atom. */ + track->offset = 8; + break; +#endif + case AV_CODEC_ID_AV1: + track->reformat = mkv_reformat_av1; + break; + case AV_CODEC_ID_WEBVTT: + track->reformat = webm_reformat_vtt; + break; + } + if (s->flags & AVFMT_FLAG_BITEXACT) { track->uid = i + 1; } else { @@ -2809,6 +3234,9 @@ static int mkv_check_bitstream(AVFormatContext *s, AVStream *st, ret = ff_stream_add_bitstream_filter(st, "aac_adtstoasc", NULL); } else if (st->codecpar->codec_id == AV_CODEC_ID_VP9) { ret = ff_stream_add_bitstream_filter(st, "vp9_superframe", NULL); + } else if (CONFIG_MATROSKA_MUXER && + st->codecpar->codec_id == AV_CODEC_ID_HDMV_PGS_SUBTITLE) { + ret = ff_stream_add_bitstream_filter(st, "pgs_frame_merge", NULL); } return ret; @@ -2848,6 +3276,7 @@ static const AVCodecTag additional_subtitle_tags[] = { #define FLAGS AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { { "reserve_index_space", "Reserve a given amount of space (in bytes) at the beginning of the file for the index (cues).", OFFSET(reserve_cues_space), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, + { "cues_to_front", "Move Cues (the index) to the front by shifting data if necessary", OFFSET(move_cues_to_front), AV_OPT_TYPE_BOOL, { .i64 = 0}, 0, 1, FLAGS }, { "cluster_size_limit", "Store at most the provided amount of bytes in a cluster. ", OFFSET(cluster_size_limit), AV_OPT_TYPE_INT , { .i64 = -1 }, -1, INT_MAX, FLAGS }, { "cluster_time_limit", "Store at most the provided number of milliseconds in a cluster.", OFFSET(cluster_time_limit), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, FLAGS }, { "dash", "Create a WebM file conforming to WebM DASH specification", OFFSET(is_dash), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS }, diff --git a/libavformat/mca.c b/libavformat/mca.c index ca0f76d6b..74654c3b3 100644 --- a/libavformat/mca.c +++ b/libavformat/mca.c @@ -22,6 +22,7 @@ #include "libavutil/intreadwrite.h" #include "avformat.h" #include "avio_internal.h" +#include "demux.h" #include "internal.h" typedef struct MCADemuxContext { @@ -62,7 +63,7 @@ static int read_header(AVFormatContext *s) avio_skip(s->pb, 0x4); // skip the file magic version = avio_rl16(s->pb); avio_skip(s->pb, 0x2); // padding - par->channels = avio_r8(s->pb); + par->ch_layout.nb_channels = avio_r8(s->pb); avio_skip(s->pb, 0x1); // padding m->block_size = avio_rl16(s->pb); nb_samples = avio_rl32(s->pb); @@ -85,7 +86,7 @@ static int read_header(AVFormatContext *s) st->duration = nb_samples; // sanity checks - if (!par->channels || par->sample_rate <= 0 + if (!par->ch_layout.nb_channels || par->sample_rate <= 0 || loop_start > loop_end || m->block_count < 1) return AVERROR_INVALIDDATA; if ((ret = av_dict_set_int(&s->metadata, "loop_start", @@ -96,8 +97,8 @@ static int read_header(AVFormatContext *s) av_rescale(loop_end, AV_TIME_BASE, par->sample_rate), 0)) < 0) return ret; - if ((32 + 4 + m->block_size) > (INT_MAX / par->channels) || - (32 + 4 + m->block_size) * par->channels > INT_MAX - 8) + if ((32 + 4 + m->block_size) > (INT_MAX / par->ch_layout.nb_channels) || + (32 + 4 + m->block_size) * par->ch_layout.nb_channels > INT_MAX - 8) return AVERROR_INVALIDDATA; avpriv_set_pts_info(st, 64, 1, par->sample_rate); @@ -116,9 +117,9 @@ static int read_header(AVFormatContext *s) } } else if (version == 5) { // read data_start location from the header - if (0x30 * par->channels + 0x4 > header_size) + if (0x30 * par->ch_layout.nb_channels + 0x4 > header_size) return AVERROR_INVALIDDATA; - data_offset = header_size - 0x30 * par->channels - 0x4; + data_offset = header_size - 0x30 * par->ch_layout.nb_channels - 0x4; if ((ret_size = avio_seek(s->pb, data_offset, SEEK_SET)) < 0) return ret_size; m->data_start = avio_rl32(s->pb); @@ -144,21 +145,21 @@ static int read_header(AVFormatContext *s) } // coefficient alignment = 0x30; metadata size = 0x14 - if (0x30 * par->channels + nb_metadata * 0x14 > header_size) + if (0x30 * par->ch_layout.nb_channels + nb_metadata * 0x14 > header_size) return AVERROR_INVALIDDATA; coef_offset = - header_size - 0x30 * par->channels + nb_metadata * 0x14; + header_size - 0x30 * par->ch_layout.nb_channels + nb_metadata * 0x14; st->start_time = 0; par->codec_id = AV_CODEC_ID_ADPCM_THP_LE; - ret = ff_alloc_extradata(st->codecpar, 32 * par->channels); + ret = ff_alloc_extradata(st->codecpar, 32 * par->ch_layout.nb_channels); if (ret < 0) return ret; if ((ret_size = avio_seek(s->pb, coef_offset, SEEK_SET)) < 0) return ret_size; - for (ch = 0; ch < par->channels; ch++) { + for (ch = 0; ch < par->ch_layout.nb_channels; ch++) { if ((ret = ffio_read_size(s->pb, par->extradata + ch * 32, 32)) < 0) return ret; // 0x30 (alignment) - 0x20 (actual size, 32) = 0x10 (padding) @@ -187,7 +188,7 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt) if (m->current_block > m->block_count) return AVERROR_EOF; - if ((ret = av_get_packet(s->pb, pkt, size * par->channels)) < 0) + if ((ret = av_get_packet(s->pb, pkt, size * par->ch_layout.nb_channels)) < 0) return ret; pkt->duration = samples; pkt->stream_index = 0; @@ -208,7 +209,7 @@ static int read_seek(AVFormatContext *s, int stream_index, if (timestamp >= m->block_count) timestamp = m->block_count - 1; ret = avio_seek(s->pb, m->data_start + timestamp * m->block_size * - st->codecpar->channels, SEEK_SET); + st->codecpar->ch_layout.nb_channels, SEEK_SET); if (ret < 0) return ret; diff --git a/libavformat/mj2kdec.c b/libavformat/mj2kdec.c index 703ff91ef..2373f31b9 100644 --- a/libavformat/mj2kdec.c +++ b/libavformat/mj2kdec.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/intreadwrite.h" #include "avformat.h" #include "rawdec.h" diff --git a/libavformat/mlpdec.c b/libavformat/mlpdec.c index f0996fef3..f4fed6585 100644 --- a/libavformat/mlpdec.c +++ b/libavformat/mlpdec.c @@ -21,6 +21,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "avformat.h" #include "avio_internal.h" #include "internal.h" @@ -32,12 +34,11 @@ static int av_always_inline mlp_thd_probe(const AVProbeData *p, uint32_t sync) { const uint8_t *buf, *last_buf = p->buf, *end = p->buf + p->buf_size; - int frames = 0, valid = 0, size = 0; + int valid = 0, size = 0; int nsubframes = 0; for (buf = p->buf; buf + 8 <= end; buf++) { if (AV_RB32(buf + 4) == sync) { - frames++; if (last_buf + size == buf) { valid += 1 + nsubframes / 8; } diff --git a/libavformat/mlvdec.c b/libavformat/mlvdec.c index a02b19062..db3b77bb9 100644 --- a/libavformat/mlvdec.c +++ b/libavformat/mlvdec.c @@ -24,12 +24,11 @@ * Magic Lantern Video (MLV) demuxer */ -#include "libavutil/eval.h" #include "libavutil/imgutils.h" #include "libavutil/intreadwrite.h" #include "libavutil/rational.h" #include "avformat.h" -#include "avio_internal.h" +#include "demux.h" #include "internal.h" #include "riff.h" diff --git a/libavformat/mm.c b/libavformat/mm.c index d1acfef44..1d44f41a9 100644 --- a/libavformat/mm.c +++ b/libavformat/mm.c @@ -124,8 +124,7 @@ static int read_header(AVFormatContext *s) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_tag = 0; /* no fourcc */ st->codecpar->codec_id = AV_CODEC_ID_PCM_U8; - st->codecpar->channels = 1; - st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; st->codecpar->sample_rate = 8000; avpriv_set_pts_info(st, 64, 1, 8000); /* 8000 hz */ } diff --git a/libavformat/mmf.c b/libavformat/mmf.c index 0c067a102..3f20d5bc0 100644 --- a/libavformat/mmf.c +++ b/libavformat/mmf.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/channel_layout.h" #include "avformat.h" #include "avio_internal.h" @@ -26,6 +28,7 @@ #include "pcm.h" #include "rawenc.h" #include "riff.h" +#include "version.h" typedef struct MMFContext { int64_t atrpos, atsqpos, awapos; @@ -80,7 +83,7 @@ static int mmf_write_header(AVFormatContext *s) return AVERROR(EINVAL); } - mmf->stereo = s->streams[0]->codecpar->channels > 1; + mmf->stereo = s->streams[0]->codecpar->ch_layout.nb_channels > 1; if (mmf->stereo && s->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) { av_log(s, AV_LOG_ERROR, "Yamaha SMAF stereo is experimental, " @@ -261,8 +264,7 @@ static int mmf_read_header(AVFormatContext *s) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_ADPCM_YAMAHA; st->codecpar->sample_rate = rate; - st->codecpar->channels = (params >> 7) + 1; - st->codecpar->channel_layout = params >> 7 ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO; + av_channel_layout_default(&st->codecpar->ch_layout, (params >> 7) + 1); st->codecpar->bits_per_coded_sample = 4; st->codecpar->bit_rate = st->codecpar->sample_rate * st->codecpar->bits_per_coded_sample; diff --git a/libavformat/mmsh.c b/libavformat/mmsh.c index 495d7fb73..672f4b378 100644 --- a/libavformat/mmsh.c +++ b/libavformat/mmsh.c @@ -31,7 +31,6 @@ #include "libavutil/opt.h" #include "internal.h" #include "mms.h" -#include "asf.h" #include "http.h" #include "url.h" diff --git a/libavformat/moflex.c b/libavformat/moflex.c index 1d342417f..2ea7c1f99 100644 --- a/libavformat/moflex.c +++ b/libavformat/moflex.c @@ -233,7 +233,7 @@ static int moflex_read_sync(AVFormatContext *s) st->codecpar->width = width; st->codecpar->height = height; st->codecpar->sample_rate= sample_rate; - st->codecpar->channels = channels; + st->codecpar->ch_layout.nb_channels = channels; st->priv_data = av_packet_alloc(); if (!st->priv_data) return AVERROR(ENOMEM); diff --git a/libavformat/mov.c b/libavformat/mov.c index 6fb09df7e..a644f9ac6 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -23,6 +23,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include #include #include @@ -34,11 +36,9 @@ #include "libavutil/intreadwrite.h" #include "libavutil/intfloat.h" #include "libavutil/mathematics.h" -#include "libavutil/time_internal.h" #include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/dict.h" -#include "libavutil/display.h" #include "libavutil/opt.h" #include "libavutil/aes.h" #include "libavutil/aes_ctr.h" @@ -47,14 +47,16 @@ #include "libavutil/spherical.h" #include "libavutil/stereo3d.h" #include "libavutil/timecode.h" -#include "libavutil/dovi_meta.h" +#include "libavutil/uuid.h" #include "libavcodec/ac3tab.h" #include "libavcodec/flac.h" +#include "libavcodec/hevc.h" #include "libavcodec/mpegaudiodecheader.h" #include "libavcodec/mlp_parse.h" #include "avformat.h" #include "internal.h" #include "avio_internal.h" +#include "demux.h" #include "dovi_isom.h" #include "riff.h" #include "isom.h" @@ -407,7 +409,7 @@ retry: atom.size -= 16; if (!key && c->found_hdlr_mdta && c->meta_keys) { - uint32_t index = AV_RB32(&atom.type); + uint32_t index = av_bswap32(atom.type); // BE number has been read as LE if (index < c->meta_keys_count && index > 0) { key = c->meta_keys[index]; } else if (atom.type != MKTAG('c', 'o', 'v', 'r')) { @@ -798,6 +800,7 @@ static int mov_read_dac3(MOVContext *c, AVIOContext *pb, MOVAtom atom) AVStream *st; enum AVAudioServiceType *ast; int ac3info, acmod, lfeon, bsmod; + uint64_t mask; if (c->fc->nb_streams < 1) return 0; @@ -812,12 +815,15 @@ static int mov_read_dac3(MOVContext *c, AVIOContext *pb, MOVAtom atom) bsmod = (ac3info >> 14) & 0x7; acmod = (ac3info >> 11) & 0x7; lfeon = (ac3info >> 10) & 0x1; - st->codecpar->channels = ((int[]){2,1,2,3,3,4,4,5})[acmod] + lfeon; - st->codecpar->channel_layout = ff_ac3_channel_layout_tab[acmod]; + + mask = ff_ac3_channel_layout_tab[acmod]; if (lfeon) - st->codecpar->channel_layout |= AV_CH_LOW_FREQUENCY; + mask |= AV_CH_LOW_FREQUENCY; + av_channel_layout_uninit(&st->codecpar->ch_layout); + av_channel_layout_from_mask(&st->codecpar->ch_layout, mask); + *ast = bsmod; - if (st->codecpar->channels > 1 && bsmod == 0x7) + if (st->codecpar->ch_layout.nb_channels > 1 && bsmod == 0x7) *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE; return 0; @@ -828,6 +834,7 @@ static int mov_read_dec3(MOVContext *c, AVIOContext *pb, MOVAtom atom) AVStream *st; enum AVAudioServiceType *ast; int eac3info, acmod, lfeon, bsmod; + uint64_t mask; if (c->fc->nb_streams < 1) return 0; @@ -846,12 +853,15 @@ static int mov_read_dec3(MOVContext *c, AVIOContext *pb, MOVAtom atom) bsmod = (eac3info >> 12) & 0x1f; acmod = (eac3info >> 9) & 0x7; lfeon = (eac3info >> 8) & 0x1; - st->codecpar->channel_layout = ff_ac3_channel_layout_tab[acmod]; + + mask = ff_ac3_channel_layout_tab[acmod]; if (lfeon) - st->codecpar->channel_layout |= AV_CH_LOW_FREQUENCY; - st->codecpar->channels = av_get_channel_layout_nb_channels(st->codecpar->channel_layout); + mask |= AV_CH_LOW_FREQUENCY; + av_channel_layout_uninit(&st->codecpar->ch_layout); + av_channel_layout_from_mask(&st->codecpar->ch_layout, mask); + *ast = bsmod; - if (st->codecpar->channels > 1 && bsmod == 0x7) + if (st->codecpar->ch_layout.nb_channels > 1 && bsmod == 0x7) *ast = AV_AUDIO_SERVICE_TYPE_KARAOKE; return 0; @@ -898,15 +908,14 @@ static int mov_read_ddts(MOVContext *c, AVIOContext *pb, MOVAtom atom) if (channel_layout_code > 0xff) { av_log(c->fc, AV_LOG_WARNING, "Unsupported DTS audio channel layout\n"); } - st->codecpar->channel_layout = + av_channel_layout_uninit(&st->codecpar->ch_layout); + av_channel_layout_from_mask(&st->codecpar->ch_layout, ((channel_layout_code & 0x1) ? AV_CH_FRONT_CENTER : 0) | ((channel_layout_code & 0x2) ? AV_CH_FRONT_LEFT : 0) | ((channel_layout_code & 0x2) ? AV_CH_FRONT_RIGHT : 0) | ((channel_layout_code & 0x4) ? AV_CH_SIDE_LEFT : 0) | ((channel_layout_code & 0x4) ? AV_CH_SIDE_RIGHT : 0) | - ((channel_layout_code & 0x8) ? AV_CH_LOW_FREQUENCY : 0); - - st->codecpar->channels = av_get_channel_layout_nb_channels(st->codecpar->channel_layout); + ((channel_layout_code & 0x8) ? AV_CH_LOW_FREQUENCY : 0)); return 0; } @@ -1126,6 +1135,7 @@ static int mov_read_ftyp(MOVContext *c, AVIOContext *pb, MOVAtom atom) c->isom = 1; av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type); av_dict_set(&c->fc->metadata, "major_brand", type, 0); + c->is_still_picture_avif = !strncmp(type, "avif", 4); minor_ver = avio_rb32(pb); /* minor version */ av_dict_set_int(&c->fc->metadata, "minor_version", minor_ver, 0); @@ -1534,35 +1544,59 @@ static int mov_read_mvhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) return 0; } -static int mov_read_enda(MOVContext *c, AVIOContext *pb, MOVAtom atom) +static void set_last_stream_little_endian(AVFormatContext *fc) { AVStream *st; - int little_endian; - if (c->fc->nb_streams < 1) - return 0; - st = c->fc->streams[c->fc->nb_streams-1]; + if (fc->nb_streams < 1) + return; + st = fc->streams[fc->nb_streams-1]; - little_endian = avio_rb16(pb) & 0xFF; - av_log(c->fc, AV_LOG_TRACE, "enda %d\n", little_endian); - if (little_endian == 1) { - switch (st->codecpar->codec_id) { - case AV_CODEC_ID_PCM_S24BE: - st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE; - break; - case AV_CODEC_ID_PCM_S32BE: - st->codecpar->codec_id = AV_CODEC_ID_PCM_S32LE; - break; - case AV_CODEC_ID_PCM_F32BE: - st->codecpar->codec_id = AV_CODEC_ID_PCM_F32LE; - break; - case AV_CODEC_ID_PCM_F64BE: - st->codecpar->codec_id = AV_CODEC_ID_PCM_F64LE; - break; - default: - break; - } + switch (st->codecpar->codec_id) { + case AV_CODEC_ID_PCM_S16BE: + st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE; + break; + case AV_CODEC_ID_PCM_S24BE: + st->codecpar->codec_id = AV_CODEC_ID_PCM_S24LE; + break; + case AV_CODEC_ID_PCM_S32BE: + st->codecpar->codec_id = AV_CODEC_ID_PCM_S32LE; + break; + case AV_CODEC_ID_PCM_F32BE: + st->codecpar->codec_id = AV_CODEC_ID_PCM_F32LE; + break; + case AV_CODEC_ID_PCM_F64BE: + st->codecpar->codec_id = AV_CODEC_ID_PCM_F64LE; + break; + default: + break; } +} + +static int mov_read_enda(MOVContext *c, AVIOContext *pb, MOVAtom atom) +{ + int little_endian = avio_rb16(pb) & 0xFF; + av_log(c->fc, AV_LOG_TRACE, "enda %d\n", little_endian); + if (little_endian == 1) + set_last_stream_little_endian(c->fc); + return 0; +} + +static int mov_read_pcmc(MOVContext *c, AVIOContext *pb, MOVAtom atom) +{ + int format_flags; + + if (atom.size < 6) { + av_log(c->fc, AV_LOG_ERROR, "Empty pcmC box\n"); + return AVERROR_INVALIDDATA; + } + + avio_r8(pb); // version + avio_rb24(pb); // flags + format_flags = avio_r8(pb); + if (format_flags == 1) // indicates little-endian format. If not present, big-endian format is used + set_last_stream_little_endian(c->fc); + return 0; } @@ -2162,14 +2196,18 @@ static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb, uint16_t version = avio_rb16(pb); uint32_t id = 0; AVDictionaryEntry *compatible_brands = av_dict_get(c->fc->metadata, "compatible_brands", NULL, AV_DICT_MATCH_CASE); + int channel_count; avio_rb16(pb); /* revision level */ id = avio_rl32(pb); /* vendor */ av_dict_set(&st->metadata, "vendor_id", av_fourcc2str(id), 0); - st->codecpar->channels = avio_rb16(pb); /* channel count */ + channel_count = avio_rb16(pb); + + st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + st->codecpar->ch_layout.nb_channels = channel_count; st->codecpar->bits_per_coded_sample = avio_rb16(pb); /* sample size */ - av_log(c->fc, AV_LOG_TRACE, "audio channels %d\n", st->codecpar->channels); + av_log(c->fc, AV_LOG_TRACE, "audio channels %d\n", channel_count); sc->audio_cid = avio_rb16(pb); avio_rb16(pb); /* packet size = 0 */ @@ -2189,7 +2227,9 @@ static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb, } else if (version == 2) { avio_rb32(pb); /* sizeof struct only */ st->codecpar->sample_rate = av_int2double(avio_rb64(pb)); - st->codecpar->channels = avio_rb32(pb); + channel_count = avio_rb32(pb); + st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + st->codecpar->ch_layout.nb_channels = channel_count; avio_rb32(pb); /* always 0x7F000000 */ st->codecpar->bits_per_coded_sample = avio_rb32(pb); @@ -2241,15 +2281,15 @@ static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb, /* set values for old format before stsd version 1 appeared */ case AV_CODEC_ID_MACE3: sc->samples_per_frame = 6; - sc->bytes_per_frame = 2 * st->codecpar->channels; + sc->bytes_per_frame = 2 * st->codecpar->ch_layout.nb_channels; break; case AV_CODEC_ID_MACE6: sc->samples_per_frame = 6; - sc->bytes_per_frame = 1 * st->codecpar->channels; + sc->bytes_per_frame = 1 * st->codecpar->ch_layout.nb_channels; break; case AV_CODEC_ID_ADPCM_IMA_QT: sc->samples_per_frame = 64; - sc->bytes_per_frame = 34 * st->codecpar->channels; + sc->bytes_per_frame = 34 * st->codecpar->ch_layout.nb_channels; break; case AV_CODEC_ID_GSM: sc->samples_per_frame = 160; @@ -2260,9 +2300,9 @@ static void mov_parse_stsd_audio(MOVContext *c, AVIOContext *pb, } bits_per_sample = av_get_bits_per_sample(st->codecpar->codec_id); - if (bits_per_sample && (bits_per_sample >> 3) * (uint64_t)st->codecpar->channels <= INT_MAX) { + if (bits_per_sample && (bits_per_sample >> 3) * (uint64_t)st->codecpar->ch_layout.nb_channels <= INT_MAX) { st->codecpar->bits_per_coded_sample = bits_per_sample; - sc->sample_size = (bits_per_sample >> 3) * st->codecpar->channels; + sc->sample_size = (bits_per_sample >> 3) * st->codecpar->ch_layout.nb_channels; } } @@ -2348,6 +2388,7 @@ static int mov_parse_stsd_data(MOVContext *c, AVIOContext *pb, tmcd_ctx->tmcd_flags = val; st->avg_frame_rate.num = AV_RB32(st->codecpar->extradata + 8); /* timescale */ st->avg_frame_rate.den = AV_RB32(st->codecpar->extradata + 12); /* frameDuration */ + tmcd_ctx->tmcd_nb_frames = st->codecpar->extradata[16]; /* number of frames */ if (size > 30) { uint32_t len = AV_RB32(st->codecpar->extradata + 18); /* name atom length */ uint32_t format = AV_RB32(st->codecpar->extradata + 22); @@ -2402,7 +2443,8 @@ static int mov_finalize_stsd_codec(MOVContext *c, AVIOContext *pb, #endif /* no ifdef since parameters are always those */ case AV_CODEC_ID_QCELP: - st->codecpar->channels = 1; + av_channel_layout_uninit(&st->codecpar->ch_layout); + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; // force sample rate for qcelp when not stored in mov if (st->codecpar->codec_tag != MKTAG('Q','c','l','p')) st->codecpar->sample_rate = 8000; @@ -2412,12 +2454,14 @@ static int mov_finalize_stsd_codec(MOVContext *c, AVIOContext *pb, sc->bytes_per_frame = 35; break; case AV_CODEC_ID_AMR_NB: - st->codecpar->channels = 1; + av_channel_layout_uninit(&st->codecpar->ch_layout); + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; /* force sample rate for amr, stsd in 3gp does not store sample rate */ st->codecpar->sample_rate = 8000; break; case AV_CODEC_ID_AMR_WB: - st->codecpar->channels = 1; + av_channel_layout_uninit(&st->codecpar->ch_layout); + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; st->codecpar->sample_rate = 16000; break; case AV_CODEC_ID_MP2: @@ -2436,7 +2480,12 @@ static int mov_finalize_stsd_codec(MOVContext *c, AVIOContext *pb, break; case AV_CODEC_ID_ALAC: if (st->codecpar->extradata_size == 36) { - st->codecpar->channels = AV_RB8 (st->codecpar->extradata + 21); + int channel_count = AV_RB8(st->codecpar->extradata + 21); + if (st->codecpar->ch_layout.nb_channels != channel_count) { + av_channel_layout_uninit(&st->codecpar->ch_layout); + st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + st->codecpar->ch_layout.nb_channels = channel_count; + } st->codecpar->sample_rate = AV_RB32(st->codecpar->extradata + 32); } break; @@ -2463,8 +2512,6 @@ static int mov_skip_multiple_stsd(MOVContext *c, AVIOContext *pb, int codec_tag, int format, int64_t size) { - int video_codec_id = ff_codec_get_id(ff_codec_movvideo_tags, format); - if (codec_tag && (codec_tag != format && // AVID 1:1 samples with differing data format and codec tag exist @@ -2473,7 +2520,7 @@ static int mov_skip_multiple_stsd(MOVContext *c, AVIOContext *pb, codec_tag != AV_RL32("apcn") && codec_tag != AV_RL32("apch") && // so is dv (sigh) codec_tag != AV_RL32("dvpp") && codec_tag != AV_RL32("dvcp") && - (c->fc->video_codec_id ? video_codec_id != c->fc->video_codec_id + (c->fc->video_codec_id ? ff_codec_get_id(ff_codec_movvideo_tags, format) != c->fc->video_codec_id : codec_tag != MKTAG('j','p','e','g')))) { /* Multiple fourcc, we skip JPEG. This is not correct, we should * export it as a separate AVStream but this needs a few changes @@ -2543,8 +2590,8 @@ int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries) av_log(c->fc, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate); return AVERROR_INVALIDDATA; } - if (st->codecpar->channels < 0) { - av_log(c->fc, AV_LOG_ERROR, "Invalid channels %d\n", st->codecpar->channels); + if (st->codecpar->ch_layout.nb_channels < 0) { + av_log(c->fc, AV_LOG_ERROR, "Invalid channels %d\n", st->codecpar->ch_layout.nb_channels); return AVERROR_INVALIDDATA; } } else if (st->codecpar->codec_type==AVMEDIA_TYPE_SUBTITLE){ @@ -3130,6 +3177,62 @@ static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom) return 0; } +static int mov_read_sgpd(MOVContext *c, AVIOContext *pb, MOVAtom atom) +{ + AVStream *st; + MOVStreamContext *sc; + uint8_t version; + uint32_t grouping_type; + uint32_t default_length; + av_unused uint32_t default_group_description_index; + uint32_t entry_count; + + if (c->fc->nb_streams < 1) + return 0; + st = c->fc->streams[c->fc->nb_streams - 1]; + sc = st->priv_data; + + version = avio_r8(pb); /* version */ + avio_rb24(pb); /* flags */ + grouping_type = avio_rl32(pb); + + /* + * This function only supports "sync" boxes, but the code is able to parse + * other boxes (such as "tscl", "tsas" and "stsa") + */ + if (grouping_type != MKTAG('s','y','n','c')) + return 0; + + default_length = version >= 1 ? avio_rb32(pb) : 0; + default_group_description_index = version >= 2 ? avio_rb32(pb) : 0; + entry_count = avio_rb32(pb); + + av_freep(&sc->sgpd_sync); + sc->sgpd_sync_count = entry_count; + sc->sgpd_sync = av_calloc(entry_count, sizeof(*sc->sgpd_sync)); + if (!sc->sgpd_sync) + return AVERROR(ENOMEM); + + for (uint32_t i = 0; i < entry_count && !pb->eof_reached; i++) { + uint32_t description_length = default_length; + if (version >= 1 && default_length == 0) + description_length = avio_rb32(pb); + if (grouping_type == MKTAG('s','y','n','c')) { + const uint8_t nal_unit_type = avio_r8(pb) & 0x3f; + sc->sgpd_sync[i] = nal_unit_type; + description_length -= 1; + } + avio_skip(pb, description_length); + } + + if (pb->eof_reached) { + av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SGPD atom\n"); + return AVERROR_EOF; + } + + return 0; +} + static int mov_read_sbgp(MOVContext *c, AVIOContext *pb, MOVAtom atom) { AVStream *st; @@ -3137,6 +3240,8 @@ static int mov_read_sbgp(MOVContext *c, AVIOContext *pb, MOVAtom atom) unsigned int i, entries; uint8_t version; uint32_t grouping_type; + MOVSbgp *table, **tablep; + int *table_count; if (c->fc->nb_streams < 1) return 0; @@ -3146,28 +3251,37 @@ static int mov_read_sbgp(MOVContext *c, AVIOContext *pb, MOVAtom atom) version = avio_r8(pb); /* version */ avio_rb24(pb); /* flags */ grouping_type = avio_rl32(pb); - if (grouping_type != MKTAG( 'r','a','p',' ')) - return 0; /* only support 'rap ' grouping */ + + if (grouping_type == MKTAG('r','a','p',' ')) { + tablep = &sc->rap_group; + table_count = &sc->rap_group_count; + } else if (grouping_type == MKTAG('s','y','n','c')) { + tablep = &sc->sync_group; + table_count = &sc->sync_group_count; + } else { + return 0; + } + if (version == 1) avio_rb32(pb); /* grouping_type_parameter */ entries = avio_rb32(pb); if (!entries) return 0; - if (sc->rap_group) - av_log(c->fc, AV_LOG_WARNING, "Duplicated SBGP atom\n"); - av_free(sc->rap_group); - sc->rap_group_count = 0; - sc->rap_group = av_malloc_array(entries, sizeof(*sc->rap_group)); - if (!sc->rap_group) + if (*tablep) + av_log(c->fc, AV_LOG_WARNING, "Duplicated SBGP %s atom\n", av_fourcc2str(grouping_type)); + av_freep(tablep); + table = av_malloc_array(entries, sizeof(*table)); + if (!table) return AVERROR(ENOMEM); + *tablep = table; for (i = 0; i < entries && !pb->eof_reached; i++) { - sc->rap_group[i].count = avio_rb32(pb); /* sample_count */ - sc->rap_group[i].index = avio_rb32(pb); /* group_description_index */ + table[i].count = avio_rb32(pb); /* sample_count */ + table[i].index = avio_rb32(pb); /* group_description_index */ } - sc->rap_group_count = i; + *table_count = i; if (pb->eof_reached) { av_log(c->fc, AV_LOG_WARNING, "reached eof, corrupted SBGP atom\n"); @@ -3815,6 +3929,69 @@ static void mov_fix_index(MOVContext *mov, AVStream *st) msc->current_index = msc->index_ranges[0].start; } +static uint32_t get_sgpd_sync_index(const MOVStreamContext *sc, int nal_unit_type) +{ + for (uint32_t i = 0; i < sc->sgpd_sync_count; i++) + if (sc->sgpd_sync[i] == HEVC_NAL_CRA_NUT) + return i + 1; + return 0; +} + +static int build_open_gop_key_points(AVStream *st) +{ + int k; + int sample_id = 0; + uint32_t cra_index; + MOVStreamContext *sc = st->priv_data; + + if (st->codecpar->codec_id != AV_CODEC_ID_HEVC || !sc->sync_group_count) + return 0; + + /* Build an unrolled index of the samples */ + sc->sample_offsets_count = 0; + for (uint32_t i = 0; i < sc->ctts_count; i++) + sc->sample_offsets_count += sc->ctts_data[i].count; + av_freep(&sc->sample_offsets); + sc->sample_offsets = av_calloc(sc->sample_offsets_count, sizeof(*sc->sample_offsets)); + if (!sc->sample_offsets) + return AVERROR(ENOMEM); + k = 0; + for (uint32_t i = 0; i < sc->ctts_count; i++) + for (int j = 0; j < sc->ctts_data[i].count; j++) + sc->sample_offsets[k++] = sc->ctts_data[i].duration; + + /* The following HEVC NAL type reveal the use of open GOP sync points + * (TODO: BLA types may also be concerned) */ + cra_index = get_sgpd_sync_index(sc, HEVC_NAL_CRA_NUT); /* Clean Random Access */ + if (!cra_index) + return 0; + + /* Build a list of open-GOP key samples */ + sc->open_key_samples_count = 0; + for (uint32_t i = 0; i < sc->sync_group_count; i++) + if (sc->sync_group[i].index == cra_index) + sc->open_key_samples_count += sc->sync_group[i].count; + av_freep(&sc->open_key_samples); + sc->open_key_samples = av_calloc(sc->open_key_samples_count, sizeof(*sc->open_key_samples)); + if (!sc->open_key_samples) + return AVERROR(ENOMEM); + k = 0; + for (uint32_t i = 0; i < sc->sync_group_count; i++) { + const MOVSbgp *sg = &sc->sync_group[i]; + if (sg->index == cra_index) + for (uint32_t j = 0; j < sg->count; j++) + sc->open_key_samples[k++] = sample_id; + sample_id += sg->count; + } + + /* Identify the minimal time step between samples */ + sc->min_sample_duration = UINT_MAX; + for (uint32_t i = 0; i < sc->stts_count; i++) + sc->min_sample_duration = FFMIN(sc->min_sample_duration, sc->stts_data[i].duration); + + return 0; +} + static void mov_build_index(MOVContext *mov, AVStream *st) { MOVStreamContext *sc = st->priv_data; @@ -3830,6 +4007,10 @@ static void mov_build_index(MOVContext *mov, AVStream *st) MOVCtts *ctts_data_old = sc->ctts_data; unsigned int ctts_count_old = sc->ctts_count; + int ret = build_open_gop_key_points(st); + if (ret < 0) + return; + if (sc->elst_count) { int i, edit_start_index = 0, multiple_edits = 0; int64_t empty_duration = 0; // empty duration of the first edit list entry @@ -4363,6 +4544,8 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom) av_freep(&sc->stps_data); av_freep(&sc->elst_data); av_freep(&sc->rap_group); + av_freep(&sc->sync_group); + av_freep(&sc->sgpd_sync); return 0; } @@ -4863,7 +5046,7 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) // 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); + ", using it for dts\n", frag_stream_info->sidx_pts); } else { dts = sc->track_end - sc->time_offset; av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64 @@ -4996,6 +5179,8 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) distance++; if (av_sat_add64(dts, sample_duration) != dts + (uint64_t)sample_duration) return AVERROR_INVALIDDATA; + if (!sample_size) + return AVERROR_INVALIDDATA; dts += sample_duration; offset += sample_size; sc->data_size += sample_size; @@ -5798,21 +5983,21 @@ static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom) AVStream *st; MOVStreamContext *sc; int64_t ret; - uint8_t uuid[16]; - static const uint8_t uuid_isml_manifest[] = { + AVUUID uuid; + static const AVUUID uuid_isml_manifest = { 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd, 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 }; - static const uint8_t uuid_xmp[] = { + static const AVUUID uuid_xmp = { 0xbe, 0x7a, 0xcf, 0xcb, 0x97, 0xa9, 0x42, 0xe8, 0x9c, 0x71, 0x99, 0x94, 0x91, 0xe3, 0xaf, 0xac }; - static const uint8_t uuid_spherical[] = { + static const AVUUID uuid_spherical = { 0xff, 0xcc, 0x82, 0x63, 0xf8, 0x55, 0x4a, 0x93, 0x88, 0x14, 0x58, 0x7a, 0x02, 0x52, 0x1f, 0xdd, }; - if (atom.size < sizeof(uuid) || atom.size >= FFMIN(INT_MAX, SIZE_MAX)) + if (atom.size < AV_UUID_LEN || atom.size >= FFMIN(INT_MAX, SIZE_MAX)) return AVERROR_INVALIDDATA; if (c->fc->nb_streams < 1) @@ -5820,13 +6005,13 @@ static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom) st = c->fc->streams[c->fc->nb_streams - 1]; sc = st->priv_data; - ret = ffio_read_size(pb, uuid, sizeof(uuid)); + ret = ffio_read_size(pb, uuid, AV_UUID_LEN); if (ret < 0) return ret; - if (!memcmp(uuid, uuid_isml_manifest, sizeof(uuid))) { + if (av_uuid_equal(uuid, uuid_isml_manifest)) { uint8_t *buffer, *ptr; char *endptr; - size_t len = atom.size - sizeof(uuid); + size_t len = atom.size - AV_UUID_LEN; if (len < 4) { return AVERROR_INVALIDDATA; @@ -5864,9 +6049,9 @@ static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom) } av_free(buffer); - } else if (!memcmp(uuid, uuid_xmp, sizeof(uuid))) { + } else if (av_uuid_equal(uuid, uuid_xmp)) { uint8_t *buffer; - size_t len = atom.size - sizeof(uuid); + size_t len = atom.size - AV_UUID_LEN; if (c->export_xmp) { buffer = av_mallocz(len + 1); if (!buffer) { @@ -5886,8 +6071,8 @@ static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom) if (ret < 0) return ret; } - } else if (!memcmp(uuid, uuid_spherical, sizeof(uuid))) { - size_t len = atom.size - sizeof(uuid); + } else if (av_uuid_equal(uuid, uuid_spherical)) { + size_t len = atom.size - AV_UUID_LEN; ret = mov_parse_uuid_spherical(sc, pb, len); if (ret < 0) return ret; @@ -6614,7 +6799,10 @@ static int mov_read_dfla(MOVContext *c, AVIOContext *pb, MOVAtom atom) avio_rb24(pb); /* Flags */ - avio_read(pb, buf, sizeof(buf)); + if (avio_read(pb, buf, sizeof(buf)) != sizeof(buf)) { + av_log(c->fc, AV_LOG_ERROR, "failed to read FLAC metadata block header\n"); + return pb->error < 0 ? pb->error : AVERROR_INVALIDDATA; + } flac_parse_block_header(buf, &last, &type, &size); if (type != FLAC_METADATA_TYPE_STREAMINFO || size != FLAC_STREAMINFO_SIZE) { @@ -6636,9 +6824,6 @@ static int cenc_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryption { int i, ret; int bytes_of_protected_data; - int partially_encrypted_block_size; - uint8_t *partially_encrypted_block; - uint8_t block[16]; if (!sc->cenc.aes_ctr) { /* initialize the cipher */ @@ -6661,8 +6846,6 @@ static int cenc_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryption return 0; } - partially_encrypted_block_size = 0; - for (i = 0; i < sample->subsample_count; i++) { if (sample->subsamples[i].bytes_of_clear_data + sample->subsamples[i].bytes_of_protected_data > size) { av_log(c->fc, AV_LOG_ERROR, "subsample size exceeds the packet size left\n"); @@ -6675,28 +6858,8 @@ static int cenc_scheme_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryption /* decrypt the encrypted bytes */ - if (partially_encrypted_block_size) { - memcpy(block, partially_encrypted_block, partially_encrypted_block_size); - memcpy(block+partially_encrypted_block_size, input, 16-partially_encrypted_block_size); - av_aes_ctr_crypt(sc->cenc.aes_ctr, block, block, 16); - memcpy(partially_encrypted_block, block, partially_encrypted_block_size); - memcpy(input, block+partially_encrypted_block_size, 16-partially_encrypted_block_size); - input += 16-partially_encrypted_block_size; - size -= 16-partially_encrypted_block_size; - bytes_of_protected_data = sample->subsamples[i].bytes_of_protected_data - (16-partially_encrypted_block_size); - } else { - bytes_of_protected_data = sample->subsamples[i].bytes_of_protected_data; - } - - if (i < sample->subsample_count-1) { - int num_of_encrypted_blocks = bytes_of_protected_data/16; - partially_encrypted_block_size = bytes_of_protected_data%16; - if (partially_encrypted_block_size) - partially_encrypted_block = input + 16*num_of_encrypted_blocks; - av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, 16*num_of_encrypted_blocks); - } else { - av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, bytes_of_protected_data); - } + bytes_of_protected_data = sample->subsamples[i].bytes_of_protected_data; + av_aes_ctr_crypt(sc->cenc.aes_ctr, input, input, bytes_of_protected_data); input += bytes_of_protected_data; size -= bytes_of_protected_data; @@ -7038,6 +7201,7 @@ static int mov_read_dmlp(MOVContext *c, AVIOContext *pb, MOVAtom atom) unsigned format_info; int channel_assignment, channel_assignment1, channel_assignment2; int ratebits; + uint64_t chmask; if (c->fc->nb_streams < 1) return 0; @@ -7058,8 +7222,10 @@ static int mov_read_dmlp(MOVContext *c, AVIOContext *pb, MOVAtom atom) st->codecpar->frame_size = 40 << (ratebits & 0x7); st->codecpar->sample_rate = mlp_samplerate(ratebits); - st->codecpar->channels = truehd_channels(channel_assignment); - st->codecpar->channel_layout = truehd_layout(channel_assignment); + + av_channel_layout_uninit(&st->codecpar->ch_layout); + chmask = truehd_layout(channel_assignment); + av_channel_layout_from_mask(&st->codecpar->ch_layout, chmask); return 0; } @@ -7173,6 +7339,241 @@ cleanup: return ret; } +static int mov_read_SA3D(MOVContext *c, AVIOContext *pb, MOVAtom atom) +{ + AVStream *st; + int i, version, type; + int ambisonic_order, channel_order, normalization, channel_count; + + if (c->fc->nb_streams < 1) + return 0; + + st = c->fc->streams[c->fc->nb_streams - 1]; + + if (atom.size < 16) { + av_log(c->fc, AV_LOG_ERROR, "SA3D audio box too small\n"); + return AVERROR_INVALIDDATA; + } + + version = avio_r8(pb); + if (version) { + av_log(c->fc, AV_LOG_WARNING, "Unsupported SA3D box version %d\n", version); + return 0; + } + + type = avio_r8(pb); + if (type) { + av_log(c->fc, AV_LOG_WARNING, + "Unsupported ambisonic type %d\n", type); + return 0; + } + + ambisonic_order = avio_rb32(pb); + + channel_order = avio_r8(pb); + if (channel_order) { + av_log(c->fc, AV_LOG_WARNING, + "Unsupported channel_order %d\n", channel_order); + return 0; + } + + normalization = avio_r8(pb); + if (normalization) { + av_log(c->fc, AV_LOG_WARNING, + "Unsupported normalization %d\n", normalization); + return 0; + } + + channel_count = avio_rb32(pb); + if (ambisonic_order < 0 || channel_count != (ambisonic_order + 1LL) * (ambisonic_order + 1LL)) { + av_log(c->fc, AV_LOG_ERROR, + "Invalid number of channels (%d / %d)\n", + channel_count, ambisonic_order); + return 0; + } + + for (i = 0; i < channel_count; i++) { + if (i != avio_rb32(pb)) { + av_log(c->fc, AV_LOG_WARNING, + "Ambisonic channel reordering is not supported\n"); + return 0; + } + } + + av_channel_layout_uninit(&st->codecpar->ch_layout); + st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_AMBISONIC; + st->codecpar->ch_layout.nb_channels = channel_count; + + return 0; +} + +static int mov_read_SAND(MOVContext *c, AVIOContext *pb, MOVAtom atom) +{ + AVStream *st; + int version; + + if (c->fc->nb_streams < 1) + return 0; + + st = c->fc->streams[c->fc->nb_streams - 1]; + + if (atom.size < 5) { + av_log(c->fc, AV_LOG_ERROR, "Empty SAND audio box\n"); + return AVERROR_INVALIDDATA; + } + + version = avio_r8(pb); + if (version) { + av_log(c->fc, AV_LOG_WARNING, "Unsupported SAND box version %d\n", version); + return 0; + } + + st->disposition |= AV_DISPOSITION_NON_DIEGETIC; + + return 0; +} + +static int rb_size(AVIOContext *pb, uint64_t* value, int size) +{ + if (size == 0) + *value = 0; + else if (size == 1) + *value = avio_r8(pb); + else if (size == 2) + *value = avio_rb16(pb); + else if (size == 4) + *value = avio_rb32(pb); + else if (size == 8) + *value = avio_rb64(pb); + else + return -1; + return size; +} + +static int mov_read_pitm(MOVContext *c, AVIOContext *pb, MOVAtom atom) +{ + avio_rb32(pb); // version & flags. + c->primary_item_id = avio_rb16(pb); + return atom.size; +} + +static int mov_read_iloc(MOVContext *c, AVIOContext *pb, MOVAtom atom) +{ + int version, offset_size, length_size, base_offset_size, index_size; + int item_count, extent_count; + uint64_t base_offset, extent_offset, extent_length; + uint8_t value; + AVStream *st; + MOVStreamContext *sc; + + if (!c->is_still_picture_avif) { + // * For non-avif, we simply ignore the iloc box. + // * For animated avif, we don't care about the iloc box as all the + // necessary information can be found in the moov box. + return 0; + } + + if (c->fc->nb_streams) { + av_log(c->fc, AV_LOG_INFO, "Duplicate iloc box found\n"); + return 0; + } + + st = avformat_new_stream(c->fc, NULL); + if (!st) + return AVERROR(ENOMEM); + st->id = c->fc->nb_streams; + sc = av_mallocz(sizeof(MOVStreamContext)); + if (!sc) + return AVERROR(ENOMEM); + + st->priv_data = sc; + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_AV1; + sc->ffindex = st->index; + c->trak_index = st->index; + st->avg_frame_rate.num = st->avg_frame_rate.den = 1; + st->time_base.num = st->time_base.den = 1; + st->nb_frames = 1; + sc->time_scale = 1; + sc = st->priv_data; + sc->pb = c->fc->pb; + sc->pb_is_copied = 1; + + version = avio_r8(pb); + avio_rb24(pb); // flags. + + value = avio_r8(pb); + offset_size = (value >> 4) & 0xF; + length_size = value & 0xF; + value = avio_r8(pb); + base_offset_size = (value >> 4) & 0xF; + index_size = !version ? 0 : (value & 0xF); + if (index_size) { + av_log(c->fc, AV_LOG_ERROR, "iloc: index_size != 0 not supported.\n"); + return AVERROR_PATCHWELCOME; + } + item_count = (version < 2) ? avio_rb16(pb) : avio_rb32(pb); + + // Populate the necessary fields used by mov_build_index. + sc->stsc_count = 1; + sc->stsc_data = av_malloc_array(1, sizeof(*sc->stsc_data)); + if (!sc->stsc_data) + return AVERROR(ENOMEM); + sc->stsc_data[0].first = 1; + sc->stsc_data[0].count = 1; + sc->stsc_data[0].id = 1; + sc->chunk_count = 1; + sc->chunk_offsets = av_malloc_array(1, sizeof(*sc->chunk_offsets)); + if (!sc->chunk_offsets) + return AVERROR(ENOMEM); + sc->sample_count = 1; + sc->sample_sizes = av_malloc_array(1, sizeof(*sc->sample_sizes)); + if (!sc->sample_sizes) + return AVERROR(ENOMEM); + sc->stts_count = 1; + sc->stts_data = av_malloc_array(1, sizeof(*sc->stts_data)); + if (!sc->stts_data) + return AVERROR(ENOMEM); + sc->stts_data[0].count = 1; + // Not used for still images. But needed by mov_build_index. + sc->stts_data[0].duration = 0; + + for (int i = 0; i < item_count; i++) { + int item_id = (version < 2) ? avio_rb16(pb) : avio_rb32(pb); + if (avio_feof(pb)) + return AVERROR_INVALIDDATA; + if (version > 0) + avio_rb16(pb); // construction_method. + avio_rb16(pb); // data_reference_index. + if (rb_size(pb, &base_offset, base_offset_size) < 0) + return AVERROR_INVALIDDATA; + extent_count = avio_rb16(pb); + if (extent_count > 1) { + // For still AVIF images, we only support one extent item. + av_log(c->fc, AV_LOG_ERROR, "iloc: extent_count > 1 not supported.\n"); + return AVERROR_PATCHWELCOME; + } + for (int j = 0; j < extent_count; j++) { + if (rb_size(pb, &extent_offset, offset_size) < 0 || + rb_size(pb, &extent_length, length_size) < 0) + return AVERROR_INVALIDDATA; + if (item_id == c->primary_item_id) { + sc->sample_sizes[0] = extent_length; + sc->chunk_offsets[0] = base_offset + extent_offset; + } + } + } + + mov_build_index(c, st); + + // For still AVIF images, the iloc box contains all the necessary + // information that would generally be provided by the moov box. So simply + // mark that we have found the moov box so that parsing can continue. + c->found_moov = 1; + + return atom.size; +} + static const MOVParseTableEntry mov_default_parse_table[] = { { MKTAG('A','C','L','R'), mov_read_aclr }, { MKTAG('A','P','R','G'), mov_read_avid }, @@ -7243,6 +7644,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = { { MKTAG('c','m','o','v'), mov_read_cmov }, { MKTAG('c','h','a','n'), mov_read_chan }, /* channel layout */ { MKTAG('d','v','c','1'), mov_read_dvc1 }, +{ MKTAG('s','g','p','d'), mov_read_sgpd }, { MKTAG('s','b','g','p'), mov_read_sbgp }, { MKTAG('h','v','c','C'), mov_read_glbl }, { MKTAG('u','u','i','d'), mov_read_uuid }, @@ -7272,6 +7674,11 @@ static const MOVParseTableEntry mov_default_parse_table[] = { { MKTAG('d','v','v','C'), mov_read_dvcc_dvvc }, { MKTAG('d','v','w','C'), mov_read_dvcc_dvvc }, { MKTAG('k','i','n','d'), mov_read_kind }, +{ MKTAG('S','A','3','D'), mov_read_SA3D }, /* ambisonic audio box */ +{ MKTAG('S','A','N','D'), mov_read_SAND }, /* non diegetic audio box */ +{ MKTAG('i','l','o','c'), mov_read_iloc }, +{ MKTAG('p','c','m','C'), mov_read_pcmc }, /* PCM configuration box */ +{ MKTAG('p','i','t','m'), mov_read_pitm }, { 0, NULL } }; @@ -7289,17 +7696,16 @@ static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom) if (atom.size < 0) atom.size = INT64_MAX; - while (total_size <= atom.size - 8 && !avio_feof(pb)) { + while (total_size <= atom.size - 8) { int (*parse)(MOVContext*, AVIOContext*, MOVAtom) = NULL; - a.size = atom.size; - a.type=0; - if (atom.size >= 8) { - a.size = avio_rb32(pb); - a.type = avio_rl32(pb); - if (((a.type == MKTAG('f','r','e','e') && c->moov_retry) || - a.type == MKTAG('h','o','o','v')) && - a.size >= 8 && - c->fc->strict_std_compliance < FF_COMPLIANCE_STRICT) { + a.size = avio_rb32(pb); + a.type = avio_rl32(pb); + if (avio_feof(pb)) + break; + if (((a.type == MKTAG('f','r','e','e') && c->moov_retry) || + a.type == MKTAG('h','o','o','v')) && + a.size >= 8 && + c->fc->strict_std_compliance < FF_COMPLIANCE_STRICT) { uint32_t type; avio_skip(pb, 4); type = avio_rl32(pb); @@ -7311,22 +7717,21 @@ static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom) av_log(c->fc, AV_LOG_ERROR, "Detected moov in a free or hoov atom.\n"); a.type = MKTAG('m','o','o','v'); } + } + if (atom.type != MKTAG('r','o','o','t') && + atom.type != MKTAG('m','o','o','v')) { + if (a.type == MKTAG('t','r','a','k') || + a.type == MKTAG('m','d','a','t')) { + av_log(c->fc, AV_LOG_ERROR, "Broken file, trak/mdat not at top-level\n"); + avio_skip(pb, -8); + c->atom_depth --; + return 0; } - if (atom.type != MKTAG('r','o','o','t') && - atom.type != MKTAG('m','o','o','v')) { - if (a.type == MKTAG('t','r','a','k') || - a.type == MKTAG('m','d','a','t')) { - av_log(c->fc, AV_LOG_ERROR, "Broken file, trak/mdat not at top-level\n"); - avio_skip(pb, -8); - c->atom_depth --; - return 0; - } - } + } + total_size += 8; + if (a.size == 1 && total_size + 8 <= atom.size) { /* 64 bit extended size */ + a.size = avio_rb64(pb) - 8; total_size += 8; - if (a.size == 1 && total_size + 8 <= atom.size) { /* 64 bit extended size */ - a.size = avio_rb64(pb) - 8; - total_size += 8; - } } av_log(c->fc, AV_LOG_TRACE, "type:'%s' parent:'%s' sz: %"PRId64" %"PRId64" %"PRId64"\n", av_fourcc2str(a.type), av_fourcc2str(atom.type), a.size, total_size, atom.size); @@ -7437,6 +7842,7 @@ static int mov_probe(const AVProbeData *p) if (tag == MKTAG('f','t','y','p') && ( AV_RL32(p->buf + offset + 8) == MKTAG('j','p','2',' ') || AV_RL32(p->buf + offset + 8) == MKTAG('j','p','x',' ') + || AV_RL32(p->buf + offset + 8) == MKTAG('j','x','l',' ') )) { score = FFMAX(score, 5); } else { @@ -7588,7 +7994,7 @@ finish: } static int parse_timecode_in_framenum_format(AVFormatContext *s, AVStream *st, - uint32_t value, int flags) + int64_t value, int flags) { AVTimecode tc; char buf[AV_TIMECODE_STR_SIZE]; @@ -7633,11 +8039,17 @@ static int mov_read_timecode_track(AVFormatContext *s, AVStream *st) FFStream *const sti = ffstream(st); int flags = 0; int64_t cur_pos = avio_tell(sc->pb); - uint32_t value; + int64_t value; + AVRational tc_rate = st->avg_frame_rate; + int tmcd_nb_frames = sc->tmcd_nb_frames; + int rounded_tc_rate; if (!sti->nb_index_entries) return -1; + if (!tc_rate.num || !tc_rate.den || !tmcd_nb_frames) + return -1; + avio_seek(sc->pb, sti->index_entries->pos, SEEK_SET); value = avio_rb32(s->pb); @@ -7650,6 +8062,18 @@ static int mov_read_timecode_track(AVFormatContext *s, AVStream *st) * No sample with tmcd track can be found with a QT timecode at the moment, * despite what the tmcd track "suggests" (Counter flag set to 0 means QT * format). */ + + /* 60 fps content have tmcd_nb_frames set to 30 but tc_rate set to 60, so + * we multiply the frame number with the quotient. + * See tickets #9492, #9710. */ + rounded_tc_rate = (tc_rate.num + tc_rate.den / 2) / tc_rate.den; + /* Work around files where tmcd_nb_frames is rounded down from frame rate + * instead of up. See ticket #5978. */ + if (tmcd_nb_frames == tc_rate.num / tc_rate.den && + s->strict_std_compliance < FF_COMPLIANCE_STRICT) + tmcd_nb_frames = rounded_tc_rate; + value = av_rescale(value, rounded_tc_rate, tmcd_nb_frames); + parse_timecode_in_framenum_format(s, st, value, flags); avio_seek(sc->pb, cur_pos, SEEK_SET); @@ -7702,6 +8126,10 @@ static int mov_read_close(AVFormatContext *s) av_freep(&sc->stps_data); av_freep(&sc->elst_data); av_freep(&sc->rap_group); + av_freep(&sc->sync_group); + av_freep(&sc->sgpd_sync); + av_freep(&sc->sample_offsets); + av_freep(&sc->open_key_samples); av_freep(&sc->display_matrix); av_freep(&sc->index_ranges); @@ -8327,20 +8755,20 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt) /* Multiple stsd handling. */ if (sc->stsc_data) { - /* Keep track of the stsc index for the given sample, then check - * if the stsd index is different from the last used one. */ + if (sc->stsc_data[sc->stsc_index].id > 0 && + sc->stsc_data[sc->stsc_index].id - 1 < sc->stsd_count && + sc->stsc_data[sc->stsc_index].id - 1 != sc->last_stsd_index) { + ret = mov_change_extradata(sc, pkt); + if (ret < 0) + return ret; + } + + /* Update the stsc index for the next sample */ sc->stsc_sample++; if (mov_stsc_index_valid(sc->stsc_index, sc->stsc_count) && mov_get_stsc_samples(sc, sc->stsc_index) == sc->stsc_sample) { sc->stsc_index++; sc->stsc_sample = 0; - /* Do not check indexes after a switch. */ - } else if (sc->stsc_data[sc->stsc_index].id > 0 && - sc->stsc_data[sc->stsc_index].id - 1 < sc->stsd_count && - sc->stsc_data[sc->stsc_index].id - 1 != sc->last_stsd_index) { - ret = mov_change_extradata(sc, pkt); - if (ret < 0) - return ret; } } @@ -8374,6 +8802,49 @@ static int mov_seek_fragment(AVFormatContext *s, AVStream *st, int64_t timestamp return 0; } +static int is_open_key_sample(const MOVStreamContext *sc, int sample) +{ + // TODO: a bisect search would scale much better + for (int i = 0; i < sc->open_key_samples_count; i++) { + const int oks = sc->open_key_samples[i]; + if (oks == sample) + return 1; + if (oks > sample) /* list is monotically increasing so we can stop early */ + break; + } + return 0; +} + +/* + * Some key sample may be key frames but not IDR frames, so a random access to + * them may not be allowed. + */ +static int can_seek_to_key_sample(AVStream *st, int sample, int64_t requested_pts) +{ + MOVStreamContext *sc = st->priv_data; + FFStream *const sti = ffstream(st); + int64_t key_sample_dts, key_sample_pts; + + if (st->codecpar->codec_id != AV_CODEC_ID_HEVC) + return 1; + + if (sample >= sc->sample_offsets_count) + return 1; + + key_sample_dts = sti->index_entries[sample].timestamp; + key_sample_pts = key_sample_dts + sc->sample_offsets[sample] + sc->dts_shift; + + /* + * If the sample needs to be presented before an open key sample, they may + * not be decodable properly, even though they come after in decoding + * order. + */ + if (is_open_key_sample(sc, sample) && key_sample_pts > requested_pts) + return 0; + + return 1; +} + static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, int flags) { MOVStreamContext *sc = st->priv_data; @@ -8389,12 +8860,19 @@ static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, if (ret < 0) return ret; - sample = av_index_search_timestamp(st, timestamp, flags); - av_log(s, AV_LOG_TRACE, "stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample); - if (sample < 0 && sti->nb_index_entries && timestamp < sti->index_entries[0].timestamp) - sample = 0; - if (sample < 0) /* not sure what to do */ - return AVERROR_INVALIDDATA; + for (;;) { + sample = av_index_search_timestamp(st, timestamp, flags); + av_log(s, AV_LOG_TRACE, "stream %d, timestamp %"PRId64", sample %d\n", st->index, timestamp, sample); + if (sample < 0 && sti->nb_index_entries && timestamp < sti->index_entries[0].timestamp) + sample = 0; + if (sample < 0) /* not sure what to do */ + return AVERROR_INVALIDDATA; + + if (!sample || can_seek_to_key_sample(st, sample, timestamp)) + break; + timestamp -= FFMAX(sc->min_sample_duration, 1); + } + mov_current_sample_set(sc, sample); av_log(s, AV_LOG_TRACE, "stream %d, found sample %d\n", st->index, sc->current_sample); /* adjust ctts index */ @@ -8568,7 +9046,7 @@ const AVInputFormat ff_mov_demuxer = { .long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"), .priv_class = &mov_class, .priv_data_size = sizeof(MOVContext), - .extensions = "mov,mp4,m4a,3gp,3g2,mj2,psp,m4b,ism,ismv,isma,f4v", + .extensions = "mov,mp4,m4a,3gp,3g2,mj2,psp,m4b,ism,ismv,isma,f4v,avif", .flags_internal = FF_FMT_INIT_CLEANUP, .read_probe = mov_probe, .read_header = mov_read_header, diff --git a/libavformat/mov_chan.c b/libavformat/mov_chan.c index 349634094..5b757c6a8 100644 --- a/libavformat/mov_chan.c +++ b/libavformat/mov_chan.c @@ -29,110 +29,6 @@ #include "libavcodec/codec_id.h" #include "mov_chan.h" -/** - * Channel Layout Tag - * This tells which channels are present in the audio stream and the order in - * which they appear. - * - * @note We're using the channel layout tag to indicate channel order - * when the value is greater than 0x10000. The Apple documentation has - * some contradictions as to how this is actually supposed to be handled. - * - * Core Audio File Format Spec: - * "The high 16 bits indicates a specific ordering of the channels." - * Core Audio Data Types Reference: - * "These identifiers specify the channels included in a layout but - * do not specify a particular ordering of those channels." - */ -enum MovChannelLayoutTag { -#define MOV_CH_LAYOUT_UNKNOWN 0xFFFF0000 - MOV_CH_LAYOUT_USE_DESCRIPTIONS = ( 0 << 16) | 0, - MOV_CH_LAYOUT_USE_BITMAP = ( 1 << 16) | 0, - MOV_CH_LAYOUT_DISCRETEINORDER = (147 << 16) | 0, - MOV_CH_LAYOUT_MONO = (100 << 16) | 1, - MOV_CH_LAYOUT_STEREO = (101 << 16) | 2, - MOV_CH_LAYOUT_STEREOHEADPHONES = (102 << 16) | 2, - MOV_CH_LAYOUT_MATRIXSTEREO = (103 << 16) | 2, - MOV_CH_LAYOUT_MIDSIDE = (104 << 16) | 2, - MOV_CH_LAYOUT_XY = (105 << 16) | 2, - MOV_CH_LAYOUT_BINAURAL = (106 << 16) | 2, - MOV_CH_LAYOUT_AMBISONIC_B_FORMAT = (107 << 16) | 4, - MOV_CH_LAYOUT_QUADRAPHONIC = (108 << 16) | 4, - MOV_CH_LAYOUT_PENTAGONAL = (109 << 16) | 5, - MOV_CH_LAYOUT_HEXAGONAL = (110 << 16) | 6, - MOV_CH_LAYOUT_OCTAGONAL = (111 << 16) | 8, - MOV_CH_LAYOUT_CUBE = (112 << 16) | 8, - MOV_CH_LAYOUT_MPEG_3_0_A = (113 << 16) | 3, - MOV_CH_LAYOUT_MPEG_3_0_B = (114 << 16) | 3, - MOV_CH_LAYOUT_MPEG_4_0_A = (115 << 16) | 4, - MOV_CH_LAYOUT_MPEG_4_0_B = (116 << 16) | 4, - MOV_CH_LAYOUT_MPEG_5_0_A = (117 << 16) | 5, - MOV_CH_LAYOUT_MPEG_5_0_B = (118 << 16) | 5, - MOV_CH_LAYOUT_MPEG_5_0_C = (119 << 16) | 5, - MOV_CH_LAYOUT_MPEG_5_0_D = (120 << 16) | 5, - MOV_CH_LAYOUT_MPEG_5_1_A = (121 << 16) | 6, - MOV_CH_LAYOUT_MPEG_5_1_B = (122 << 16) | 6, - MOV_CH_LAYOUT_MPEG_5_1_C = (123 << 16) | 6, - MOV_CH_LAYOUT_MPEG_5_1_D = (124 << 16) | 6, - MOV_CH_LAYOUT_MPEG_6_1_A = (125 << 16) | 7, - MOV_CH_LAYOUT_MPEG_7_1_A = (126 << 16) | 8, - MOV_CH_LAYOUT_MPEG_7_1_B = (127 << 16) | 8, - MOV_CH_LAYOUT_MPEG_7_1_C = (128 << 16) | 8, - MOV_CH_LAYOUT_EMAGIC_DEFAULT_7_1 = (129 << 16) | 8, - MOV_CH_LAYOUT_SMPTE_DTV = (130 << 16) | 8, - MOV_CH_LAYOUT_ITU_2_1 = (131 << 16) | 3, - MOV_CH_LAYOUT_ITU_2_2 = (132 << 16) | 4, - MOV_CH_LAYOUT_DVD_4 = (133 << 16) | 3, - MOV_CH_LAYOUT_DVD_5 = (134 << 16) | 4, - MOV_CH_LAYOUT_DVD_6 = (135 << 16) | 5, - MOV_CH_LAYOUT_DVD_10 = (136 << 16) | 4, - MOV_CH_LAYOUT_DVD_11 = (137 << 16) | 5, - MOV_CH_LAYOUT_DVD_18 = (138 << 16) | 5, - MOV_CH_LAYOUT_AUDIOUNIT_6_0 = (139 << 16) | 6, - MOV_CH_LAYOUT_AUDIOUNIT_7_0 = (140 << 16) | 7, - MOV_CH_LAYOUT_AUDIOUNIT_7_0_FRONT = (148 << 16) | 7, - MOV_CH_LAYOUT_AAC_6_0 = (141 << 16) | 6, - MOV_CH_LAYOUT_AAC_6_1 = (142 << 16) | 7, - MOV_CH_LAYOUT_AAC_7_0 = (143 << 16) | 7, - MOV_CH_LAYOUT_AAC_OCTAGONAL = (144 << 16) | 8, - MOV_CH_LAYOUT_TMH_10_2_STD = (145 << 16) | 16, - MOV_CH_LAYOUT_TMH_10_2_FULL = (146 << 16) | 21, - MOV_CH_LAYOUT_AC3_1_0_1 = (149 << 16) | 2, - MOV_CH_LAYOUT_AC3_3_0 = (150 << 16) | 3, - MOV_CH_LAYOUT_AC3_3_1 = (151 << 16) | 4, - MOV_CH_LAYOUT_AC3_3_0_1 = (152 << 16) | 4, - MOV_CH_LAYOUT_AC3_2_1_1 = (153 << 16) | 4, - MOV_CH_LAYOUT_AC3_3_1_1 = (154 << 16) | 5, - MOV_CH_LAYOUT_EAC3_6_0_A = (155 << 16) | 6, - MOV_CH_LAYOUT_EAC3_7_0_A = (156 << 16) | 7, - MOV_CH_LAYOUT_EAC3_6_1_A = (157 << 16) | 7, - MOV_CH_LAYOUT_EAC3_6_1_B = (158 << 16) | 7, - MOV_CH_LAYOUT_EAC3_6_1_C = (159 << 16) | 7, - MOV_CH_LAYOUT_EAC3_7_1_A = (160 << 16) | 8, - MOV_CH_LAYOUT_EAC3_7_1_B = (161 << 16) | 8, - MOV_CH_LAYOUT_EAC3_7_1_C = (162 << 16) | 8, - MOV_CH_LAYOUT_EAC3_7_1_D = (163 << 16) | 8, - MOV_CH_LAYOUT_EAC3_7_1_E = (164 << 16) | 8, - MOV_CH_LAYOUT_EAC3_7_1_F = (165 << 16) | 8, - MOV_CH_LAYOUT_EAC3_7_1_G = (166 << 16) | 8, - MOV_CH_LAYOUT_EAC3_7_1_H = (167 << 16) | 8, - MOV_CH_LAYOUT_DTS_3_1 = (168 << 16) | 4, - MOV_CH_LAYOUT_DTS_4_1 = (169 << 16) | 5, - MOV_CH_LAYOUT_DTS_6_0_A = (170 << 16) | 6, - MOV_CH_LAYOUT_DTS_6_0_B = (171 << 16) | 6, - MOV_CH_LAYOUT_DTS_6_0_C = (172 << 16) | 6, - MOV_CH_LAYOUT_DTS_6_1_A = (173 << 16) | 7, - MOV_CH_LAYOUT_DTS_6_1_B = (174 << 16) | 7, - MOV_CH_LAYOUT_DTS_6_1_C = (175 << 16) | 7, - MOV_CH_LAYOUT_DTS_6_1_D = (182 << 16) | 7, - MOV_CH_LAYOUT_DTS_7_0 = (176 << 16) | 7, - MOV_CH_LAYOUT_DTS_7_1 = (177 << 16) | 8, - MOV_CH_LAYOUT_DTS_8_0_A = (178 << 16) | 8, - MOV_CH_LAYOUT_DTS_8_0_B = (179 << 16) | 8, - MOV_CH_LAYOUT_DTS_8_1_A = (180 << 16) | 9, - MOV_CH_LAYOUT_DTS_8_1_B = (181 << 16) | 9, -}; - struct MovChannelLayoutMap { uint32_t tag; uint64_t layout; @@ -485,12 +381,18 @@ static uint64_t mov_get_channel_layout(uint32_t tag, uint32_t bitmap) return layout_map[i].layout; } -static uint32_t mov_get_channel_label(uint32_t label) +static uint64_t mov_get_channel_mask(uint32_t label) { if (label == 0) return 0; if (label <= 18) return 1U << (label - 1); + if (label == 35) + return AV_CH_WIDE_LEFT; + if (label == 36) + return AV_CH_WIDE_RIGHT; + if (label == 37) + return AV_CH_LOW_FREQUENCY_2; if (label == 38) return AV_CH_STEREO_LEFT; if (label == 39) @@ -498,9 +400,29 @@ static uint32_t mov_get_channel_label(uint32_t label) return 0; } -uint32_t ff_mov_get_channel_layout_tag(enum AVCodecID codec_id, - uint64_t channel_layout, - uint32_t *bitmap) +static uint32_t mov_get_channel_label(enum AVChannel channel) +{ + if (channel < 0) + return 0; + if (channel <= AV_CHAN_TOP_BACK_RIGHT) + return channel + 1; + if (channel == AV_CHAN_WIDE_LEFT) + return 35; + if (channel == AV_CHAN_WIDE_RIGHT) + return 36; + if (channel == AV_CHAN_LOW_FREQUENCY_2) + return 37; + if (channel == AV_CHAN_STEREO_LEFT) + return 38; + if (channel == AV_CHAN_STEREO_RIGHT) + return 39; + return 0; +} + +int ff_mov_get_channel_layout_tag(const AVCodecParameters *par, + uint32_t *layout, + uint32_t *bitmap, + uint32_t **pchannel_desc) { int i, j; uint32_t tag = 0; @@ -508,7 +430,7 @@ uint32_t ff_mov_get_channel_layout_tag(enum AVCodecID codec_id, /* find the layout list for the specified codec */ for (i = 0; mov_codec_ch_layouts[i].codec_id != AV_CODEC_ID_NONE; i++) { - if (mov_codec_ch_layouts[i].codec_id == codec_id) + if (mov_codec_ch_layouts[i].codec_id == par->codec_id) break; } if (mov_codec_ch_layouts[i].codec_id != AV_CODEC_ID_NONE) @@ -519,7 +441,7 @@ uint32_t ff_mov_get_channel_layout_tag(enum AVCodecID codec_id, const struct MovChannelLayoutMap *layout_map; /* get the layout map based on the channel count */ - channels = av_get_channel_layout_nb_channels(channel_layout); + channels = par->ch_layout.nb_channels; if (channels > 9) channels = 0; layout_map = mov_ch_layout_map[channels]; @@ -530,7 +452,8 @@ uint32_t ff_mov_get_channel_layout_tag(enum AVCodecID codec_id, continue; for (j = 0; layout_map[j].tag != 0; j++) { if (layout_map[j].tag == layouts[i] && - layout_map[j].layout == channel_layout) + (par->ch_layout.order == AV_CHANNEL_ORDER_NATIVE && + layout_map[j].layout == par->ch_layout.u.mask)) break; } if (layout_map[j].tag) @@ -539,22 +462,46 @@ uint32_t ff_mov_get_channel_layout_tag(enum AVCodecID codec_id, tag = layouts[i]; } - /* if no tag was found, use channel bitmap as a backup if possible */ - if (tag == 0 && channel_layout > 0 && channel_layout < 0x40000) { - tag = MOV_CH_LAYOUT_USE_BITMAP; - *bitmap = (uint32_t)channel_layout; - } else - *bitmap = 0; + *layout = tag; + *bitmap = 0; + *pchannel_desc = NULL; - /* TODO: set channel descriptions as a secondary backup */ + /* if no tag was found, use channel bitmap or description as a backup if possible */ + if (tag == 0) { + uint32_t *channel_desc; + if (par->ch_layout.order == AV_CHANNEL_ORDER_NATIVE && + par->ch_layout.u.mask < 0x40000) { + *layout = MOV_CH_LAYOUT_USE_BITMAP; + *bitmap = (uint32_t)par->ch_layout.u.mask; + return 0; + } else if (par->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) + return AVERROR(ENOSYS); - return tag; + channel_desc = av_malloc_array(par->ch_layout.nb_channels, sizeof(*channel_desc)); + if (!channel_desc) + return AVERROR(ENOMEM); + + for (i = 0; i < par->ch_layout.nb_channels; i++) { + channel_desc[i] = + mov_get_channel_label(av_channel_layout_channel_from_index(&par->ch_layout, i)); + + if (channel_desc[i] == 0) { + av_free(channel_desc); + return AVERROR(ENOSYS); + } + } + + *pchannel_desc = channel_desc; + } + + return 0; } int ff_mov_read_chan(AVFormatContext *s, AVIOContext *pb, AVStream *st, int64_t size) { - uint32_t layout_tag, bitmap, num_descr, label_mask; + uint32_t layout_tag, bitmap, num_descr; + uint64_t label_mask, mask = 0; int i; if (size < 12) @@ -564,7 +511,7 @@ int ff_mov_read_chan(AVFormatContext *s, AVIOContext *pb, AVStream *st, bitmap = avio_rb32(pb); num_descr = avio_rb32(pb); - av_log(s, AV_LOG_TRACE, "chan: layout=%"PRIu32" " + av_log(s, AV_LOG_DEBUG, "chan: layout=%"PRIu32" " "bitmap=%"PRIu32" num_descr=%"PRIu32"\n", layout_tag, bitmap, num_descr); @@ -586,7 +533,7 @@ int ff_mov_read_chan(AVFormatContext *s, AVIOContext *pb, AVStream *st, avio_rl32(pb); // mCoordinates[2] size -= 20; if (layout_tag == 0) { - uint32_t mask_incr = mov_get_channel_label(label); + uint64_t mask_incr = mov_get_channel_mask(label); if (mask_incr == 0) { label_mask = 0; break; @@ -596,9 +543,14 @@ int ff_mov_read_chan(AVFormatContext *s, AVIOContext *pb, AVStream *st, } if (layout_tag == 0) { if (label_mask) - st->codecpar->channel_layout = label_mask; + mask = label_mask; } else - st->codecpar->channel_layout = mov_get_channel_layout(layout_tag, bitmap); + mask = mov_get_channel_layout(layout_tag, bitmap); + + if (mask) { + av_channel_layout_uninit(&st->codecpar->ch_layout); + av_channel_layout_from_mask(&st->codecpar->ch_layout, mask); + } avio_skip(pb, size - 12); return 0; diff --git a/libavformat/mov_chan.h b/libavformat/mov_chan.h index f7916e989..93d987879 100644 --- a/libavformat/mov_chan.h +++ b/libavformat/mov_chan.h @@ -28,9 +28,115 @@ #include +#include "libavutil/channel_layout.h" #include "libavcodec/codec_id.h" +#include "libavcodec/codec_par.h" #include "avformat.h" +/** + * Channel Layout Tag + * This tells which channels are present in the audio stream and the order in + * which they appear. + * + * @note We're using the channel layout tag to indicate channel order + * when the value is greater than 0x10000. The Apple documentation has + * some contradictions as to how this is actually supposed to be handled. + * + * Core Audio File Format Spec: + * "The high 16 bits indicates a specific ordering of the channels." + * Core Audio Data Types Reference: + * "These identifiers specify the channels included in a layout but + * do not specify a particular ordering of those channels." + */ +enum MovChannelLayoutTag { +#define MOV_CH_LAYOUT_UNKNOWN 0xFFFF0000 + MOV_CH_LAYOUT_USE_DESCRIPTIONS = ( 0 << 16) | 0, + MOV_CH_LAYOUT_USE_BITMAP = ( 1 << 16) | 0, + MOV_CH_LAYOUT_DISCRETEINORDER = (147 << 16) | 0, + MOV_CH_LAYOUT_MONO = (100 << 16) | 1, + MOV_CH_LAYOUT_STEREO = (101 << 16) | 2, + MOV_CH_LAYOUT_STEREOHEADPHONES = (102 << 16) | 2, + MOV_CH_LAYOUT_MATRIXSTEREO = (103 << 16) | 2, + MOV_CH_LAYOUT_MIDSIDE = (104 << 16) | 2, + MOV_CH_LAYOUT_XY = (105 << 16) | 2, + MOV_CH_LAYOUT_BINAURAL = (106 << 16) | 2, + MOV_CH_LAYOUT_AMBISONIC_B_FORMAT = (107 << 16) | 4, + MOV_CH_LAYOUT_QUADRAPHONIC = (108 << 16) | 4, + MOV_CH_LAYOUT_PENTAGONAL = (109 << 16) | 5, + MOV_CH_LAYOUT_HEXAGONAL = (110 << 16) | 6, + MOV_CH_LAYOUT_OCTAGONAL = (111 << 16) | 8, + MOV_CH_LAYOUT_CUBE = (112 << 16) | 8, + MOV_CH_LAYOUT_MPEG_3_0_A = (113 << 16) | 3, + MOV_CH_LAYOUT_MPEG_3_0_B = (114 << 16) | 3, + MOV_CH_LAYOUT_MPEG_4_0_A = (115 << 16) | 4, + MOV_CH_LAYOUT_MPEG_4_0_B = (116 << 16) | 4, + MOV_CH_LAYOUT_MPEG_5_0_A = (117 << 16) | 5, + MOV_CH_LAYOUT_MPEG_5_0_B = (118 << 16) | 5, + MOV_CH_LAYOUT_MPEG_5_0_C = (119 << 16) | 5, + MOV_CH_LAYOUT_MPEG_5_0_D = (120 << 16) | 5, + MOV_CH_LAYOUT_MPEG_5_1_A = (121 << 16) | 6, + MOV_CH_LAYOUT_MPEG_5_1_B = (122 << 16) | 6, + MOV_CH_LAYOUT_MPEG_5_1_C = (123 << 16) | 6, + MOV_CH_LAYOUT_MPEG_5_1_D = (124 << 16) | 6, + MOV_CH_LAYOUT_MPEG_6_1_A = (125 << 16) | 7, + MOV_CH_LAYOUT_MPEG_7_1_A = (126 << 16) | 8, + MOV_CH_LAYOUT_MPEG_7_1_B = (127 << 16) | 8, + MOV_CH_LAYOUT_MPEG_7_1_C = (128 << 16) | 8, + MOV_CH_LAYOUT_EMAGIC_DEFAULT_7_1 = (129 << 16) | 8, + MOV_CH_LAYOUT_SMPTE_DTV = (130 << 16) | 8, + MOV_CH_LAYOUT_ITU_2_1 = (131 << 16) | 3, + MOV_CH_LAYOUT_ITU_2_2 = (132 << 16) | 4, + MOV_CH_LAYOUT_DVD_4 = (133 << 16) | 3, + MOV_CH_LAYOUT_DVD_5 = (134 << 16) | 4, + MOV_CH_LAYOUT_DVD_6 = (135 << 16) | 5, + MOV_CH_LAYOUT_DVD_10 = (136 << 16) | 4, + MOV_CH_LAYOUT_DVD_11 = (137 << 16) | 5, + MOV_CH_LAYOUT_DVD_18 = (138 << 16) | 5, + MOV_CH_LAYOUT_AUDIOUNIT_6_0 = (139 << 16) | 6, + MOV_CH_LAYOUT_AUDIOUNIT_7_0 = (140 << 16) | 7, + MOV_CH_LAYOUT_AUDIOUNIT_7_0_FRONT = (148 << 16) | 7, + MOV_CH_LAYOUT_AAC_6_0 = (141 << 16) | 6, + MOV_CH_LAYOUT_AAC_6_1 = (142 << 16) | 7, + MOV_CH_LAYOUT_AAC_7_0 = (143 << 16) | 7, + MOV_CH_LAYOUT_AAC_OCTAGONAL = (144 << 16) | 8, + MOV_CH_LAYOUT_TMH_10_2_STD = (145 << 16) | 16, + MOV_CH_LAYOUT_TMH_10_2_FULL = (146 << 16) | 21, + MOV_CH_LAYOUT_AC3_1_0_1 = (149 << 16) | 2, + MOV_CH_LAYOUT_AC3_3_0 = (150 << 16) | 3, + MOV_CH_LAYOUT_AC3_3_1 = (151 << 16) | 4, + MOV_CH_LAYOUT_AC3_3_0_1 = (152 << 16) | 4, + MOV_CH_LAYOUT_AC3_2_1_1 = (153 << 16) | 4, + MOV_CH_LAYOUT_AC3_3_1_1 = (154 << 16) | 5, + MOV_CH_LAYOUT_EAC3_6_0_A = (155 << 16) | 6, + MOV_CH_LAYOUT_EAC3_7_0_A = (156 << 16) | 7, + MOV_CH_LAYOUT_EAC3_6_1_A = (157 << 16) | 7, + MOV_CH_LAYOUT_EAC3_6_1_B = (158 << 16) | 7, + MOV_CH_LAYOUT_EAC3_6_1_C = (159 << 16) | 7, + MOV_CH_LAYOUT_EAC3_7_1_A = (160 << 16) | 8, + MOV_CH_LAYOUT_EAC3_7_1_B = (161 << 16) | 8, + MOV_CH_LAYOUT_EAC3_7_1_C = (162 << 16) | 8, + MOV_CH_LAYOUT_EAC3_7_1_D = (163 << 16) | 8, + MOV_CH_LAYOUT_EAC3_7_1_E = (164 << 16) | 8, + MOV_CH_LAYOUT_EAC3_7_1_F = (165 << 16) | 8, + MOV_CH_LAYOUT_EAC3_7_1_G = (166 << 16) | 8, + MOV_CH_LAYOUT_EAC3_7_1_H = (167 << 16) | 8, + MOV_CH_LAYOUT_DTS_3_1 = (168 << 16) | 4, + MOV_CH_LAYOUT_DTS_4_1 = (169 << 16) | 5, + MOV_CH_LAYOUT_DTS_6_0_A = (170 << 16) | 6, + MOV_CH_LAYOUT_DTS_6_0_B = (171 << 16) | 6, + MOV_CH_LAYOUT_DTS_6_0_C = (172 << 16) | 6, + MOV_CH_LAYOUT_DTS_6_1_A = (173 << 16) | 7, + MOV_CH_LAYOUT_DTS_6_1_B = (174 << 16) | 7, + MOV_CH_LAYOUT_DTS_6_1_C = (175 << 16) | 7, + MOV_CH_LAYOUT_DTS_6_1_D = (182 << 16) | 7, + MOV_CH_LAYOUT_DTS_7_0 = (176 << 16) | 7, + MOV_CH_LAYOUT_DTS_7_1 = (177 << 16) | 8, + MOV_CH_LAYOUT_DTS_8_0_A = (178 << 16) | 8, + MOV_CH_LAYOUT_DTS_8_0_B = (179 << 16) | 8, + MOV_CH_LAYOUT_DTS_8_1_A = (180 << 16) | 9, + MOV_CH_LAYOUT_DTS_8_1_B = (181 << 16) | 9, +}; + /** * Get the channel layout tag for the specified codec id and channel layout. * If the layout tag was not found, use a channel bitmap if possible. @@ -40,9 +146,10 @@ * @param[out] bitmap channel bitmap * @return channel layout tag */ -uint32_t ff_mov_get_channel_layout_tag(enum AVCodecID codec_id, - uint64_t channel_layout, - uint32_t *bitmap); +int ff_mov_get_channel_layout_tag(const AVCodecParameters *par, + uint32_t *layout, + uint32_t *bitmap, + uint32_t **pchannel_desc); /** * Read 'chan' tag from the input stream. diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 4c868919a..5608afde4 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -21,6 +21,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include #include @@ -55,11 +57,15 @@ #include "libavutil/timecode.h" #include "libavutil/dovi_meta.h" #include "libavutil/color_utils.h" +#include "libavutil/uuid.h" #include "hevc.h" #include "rtpenc.h" #include "mov_chan.h" #include "movenc_ttml.h" +#include "mux.h" +#include "rawutils.h" #include "ttmlenc.h" +#include "version.h" #include "vpcc.h" static const AVOption options[] = { @@ -106,6 +112,7 @@ static const AVOption options[] = { { "encryption_key", "The media encryption key (hex)", offsetof(MOVMuxContext, encryption_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_ENCODING_PARAM }, { "encryption_kid", "The media encryption key identifier (hex)", offsetof(MOVMuxContext, encryption_kid), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_ENCODING_PARAM }, { "use_stream_ids_as_track_ids", "use stream ids as track ids", offsetof(MOVMuxContext, use_stream_ids_as_track_ids), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM}, + { "write_btrt", "force or disable writing btrt", offsetof(MOVMuxContext, write_btrt), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM}, { "write_tmcd", "force or disable writing tmcd", offsetof(MOVMuxContext, write_tmcd), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM}, { "write_prft", "Write producer reference time box with specified time source", offsetof(MOVMuxContext, write_prft), AV_OPT_TYPE_INT, {.i64 = MOV_PRFT_NONE}, 0, MOV_PRFT_NB-1, AV_OPT_FLAG_ENCODING_PARAM, "prft"}, { "wallclock", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = MOV_PRFT_SRC_WALLCLOCK}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM, "prft"}, @@ -321,54 +328,6 @@ static int mov_write_amr_tag(AVIOContext *pb, MOVTrack *track) return 0x11; } -static int mov_write_ac3_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track) -{ - GetBitContext gbc; - PutBitContext pbc; - uint8_t buf[3]; - int fscod, bsid, bsmod, acmod, lfeon, frmsizecod; - - if (track->vos_len < 7) { - av_log(s, AV_LOG_ERROR, - "Cannot write moov atom before AC3 packets." - " Set the delay_moov flag to fix this.\n"); - return AVERROR(EINVAL); - } - - avio_wb32(pb, 11); - ffio_wfourcc(pb, "dac3"); - - init_get_bits(&gbc, track->vos_data + 4, (track->vos_len - 4) * 8); - fscod = get_bits(&gbc, 2); - frmsizecod = get_bits(&gbc, 6); - bsid = get_bits(&gbc, 5); - bsmod = get_bits(&gbc, 3); - acmod = get_bits(&gbc, 3); - if (acmod == 2) { - skip_bits(&gbc, 2); // dsurmod - } else { - if ((acmod & 1) && acmod != 1) - skip_bits(&gbc, 2); // cmixlev - if (acmod & 4) - skip_bits(&gbc, 2); // surmixlev - } - lfeon = get_bits1(&gbc); - - init_put_bits(&pbc, buf, sizeof(buf)); - put_bits(&pbc, 2, fscod); - put_bits(&pbc, 5, bsid); - put_bits(&pbc, 3, bsmod); - put_bits(&pbc, 3, acmod); - put_bits(&pbc, 1, lfeon); - put_bits(&pbc, 5, frmsizecod >> 1); // bit_rate_code - put_bits(&pbc, 5, 0); // reserved - - flush_put_bits(&pbc); - avio_write(pb, buf, sizeof(buf)); - - return 11; -} - struct eac3_info { AVPacket *pkt; uint8_t ec3_done; @@ -377,6 +336,7 @@ struct eac3_info { /* Layout of the EC3SpecificBox */ /* maximum bitrate */ uint16_t data_rate; + int8_t ac3_bit_rate_code; /* number of independent substreams */ uint8_t num_ind_sub; struct { @@ -401,21 +361,73 @@ struct eac3_info { } substream[1]; /* TODO: support 8 independent substreams */ }; -#if CONFIG_AC3_PARSER +static int mov_write_ac3_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track) +{ + struct eac3_info *info = track->eac3_priv; + PutBitContext pbc; + uint8_t buf[3]; + + if (!info || !info->ec3_done) { + av_log(s, AV_LOG_ERROR, + "Cannot write moov atom before AC3 packets." + " Set the delay_moov flag to fix this.\n"); + return AVERROR(EINVAL); + } + + if (info->substream[0].bsid > 8) { + av_log(s, AV_LOG_ERROR, + "RealAudio AC-3/DolbyNet with bsid %d is not defined by the " + "ISOBMFF specification in ETSI TS 102 366!\n", + info->substream[0].bsid); + return AVERROR(EINVAL); + } + + if (info->ac3_bit_rate_code < 0) { + av_log(s, AV_LOG_ERROR, + "No valid AC3 bit rate code for data rate of %d!\n", + info->data_rate); + return AVERROR(EINVAL); + } + + avio_wb32(pb, 11); + ffio_wfourcc(pb, "dac3"); + + init_put_bits(&pbc, buf, sizeof(buf)); + put_bits(&pbc, 2, info->substream[0].fscod); + put_bits(&pbc, 5, info->substream[0].bsid); + put_bits(&pbc, 3, info->substream[0].bsmod); + put_bits(&pbc, 3, info->substream[0].acmod); + put_bits(&pbc, 1, info->substream[0].lfeon); + put_bits(&pbc, 5, info->ac3_bit_rate_code); // bit_rate_code + put_bits(&pbc, 5, 0); // reserved + + flush_put_bits(&pbc); + avio_write(pb, buf, sizeof(buf)); + + return 11; +} + static int handle_eac3(MOVMuxContext *mov, AVPacket *pkt, MOVTrack *track) { AC3HeaderInfo *hdr = NULL; struct eac3_info *info; int num_blocks, ret; - if (!track->eac3_priv && !(track->eac3_priv = av_mallocz(sizeof(*info)))) - return AVERROR(ENOMEM); + if (!track->eac3_priv) { + if (!(track->eac3_priv = av_mallocz(sizeof(*info)))) + return AVERROR(ENOMEM); + + ((struct eac3_info *)track->eac3_priv)->ac3_bit_rate_code = -1; + } info = track->eac3_priv; if (!info->pkt && !(info->pkt = av_packet_alloc())) return AVERROR(ENOMEM); - if (avpriv_ac3_parse_header(&hdr, pkt->data, pkt->size) < 0) { + if ((ret = avpriv_ac3_parse_header(&hdr, pkt->data, pkt->size)) < 0) { + if (ret == AVERROR(ENOMEM)) + goto end; + /* drop the packets until we see a good one */ if (!track->entry) { av_log(mov->fc, AV_LOG_WARNING, "Dropping invalid packet from start of the stream\n"); @@ -426,6 +438,8 @@ static int handle_eac3(MOVMuxContext *mov, AVPacket *pkt, MOVTrack *track) } info->data_rate = FFMAX(info->data_rate, hdr->bit_rate / 1000); + info->ac3_bit_rate_code = FFMAX(info->ac3_bit_rate_code, + hdr->ac3_bit_rate_code); num_blocks = hdr->num_blocks; if (!info->ec3_done) { @@ -437,7 +451,8 @@ static int handle_eac3(MOVMuxContext *mov, AVPacket *pkt, MOVTrack *track) /* 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) { + if (hdr->frame_type == EAC3_FRAME_TYPE_INDEPENDENT || + hdr->frame_type == EAC3_FRAME_TYPE_AC3_CONVERT) { /* substream ids must be incremental */ if (hdr->substreamid > info->num_ind_sub + 1) { ret = AVERROR(EINVAL); @@ -469,6 +484,14 @@ static int handle_eac3(MOVMuxContext *mov, AVPacket *pkt, MOVTrack *track) info->substream[hdr->substreamid].acmod = hdr->channel_mode; info->substream[hdr->substreamid].lfeon = hdr->lfe_on; + if (track->par->codec_id == AV_CODEC_ID_AC3) { + // with AC-3 we only require the information of a single packet, + // so we can finish as soon as the basic values of the bit stream + // have been set to the track's informational structure. + info->ec3_done = 1; + goto concatenate; + } + /* Parse dependent substream(s), if any */ if (pkt->size != hdr->frame_size) { int cumul_size = hdr->frame_size; @@ -542,7 +565,6 @@ end: return ret; } -#endif static int mov_write_eac3_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track) { @@ -864,28 +886,56 @@ static int mov_write_dmlp_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *tra static int mov_write_chan_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track) { - uint32_t layout_tag, bitmap; + uint32_t layout_tag, bitmap, *channel_desc; int64_t pos = avio_tell(pb); - - layout_tag = ff_mov_get_channel_layout_tag(track->par->codec_id, - track->par->channel_layout, - &bitmap); - if (!layout_tag) { - av_log(s, AV_LOG_WARNING, "not writing 'chan' tag due to " - "lack of channel information\n"); - return 0; - } + int num_desc, ret; if (track->multichannel_as_mono) return 0; + ret = ff_mov_get_channel_layout_tag(track->par, &layout_tag, + &bitmap, &channel_desc); + + if (ret < 0) { + if (ret == AVERROR(ENOSYS)) { + av_log(s, AV_LOG_WARNING, "not writing 'chan' tag due to " + "lack of channel information\n"); + ret = 0; + } + + return ret; + } + + if (layout_tag == MOV_CH_LAYOUT_MONO && track->mono_as_fc > 0) { + av_assert0(!channel_desc); + channel_desc = av_malloc(sizeof(*channel_desc)); + if (!channel_desc) + return AVERROR(ENOMEM); + + layout_tag = 0; + bitmap = 0; + *channel_desc = 3; // channel label "Center" + } + + num_desc = layout_tag ? 0 : track->par->ch_layout.nb_channels; + avio_wb32(pb, 0); // Size ffio_wfourcc(pb, "chan"); // Type avio_w8(pb, 0); // Version avio_wb24(pb, 0); // Flags avio_wb32(pb, layout_tag); // mChannelLayoutTag avio_wb32(pb, bitmap); // mChannelBitmap - avio_wb32(pb, 0); // mNumberChannelDescriptions + avio_wb32(pb, num_desc); // mNumberChannelDescriptions + + for (int i = 0; i < num_desc; i++) { + avio_wb32(pb, channel_desc[i]); // mChannelLabel + avio_wb32(pb, 0); // mChannelFlags + avio_wl32(pb, 0); // mCoordinates[0] + avio_wl32(pb, 0); // mCoordinates[1] + avio_wl32(pb, 0); // mCoordinates[2] + } + + av_free(channel_desc); return update_size(pb, pos); } @@ -1137,7 +1187,7 @@ static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContex int ret = 0; if (track->mode == MODE_MOV) { - if (track->timescale > UINT16_MAX || !track->par->channels) { + if (track->timescale > UINT16_MAX || !track->par->ch_layout.nb_channels) { if (mov_get_lpcm_flags(track->par->codec_id)) tag = AV_RL32("lpcm"); version = 2; @@ -1173,7 +1223,7 @@ static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContex avio_wb32(pb, 0x00010000); avio_wb32(pb, 72); avio_wb64(pb, av_double2int(track->par->sample_rate)); - avio_wb32(pb, track->par->channels); + avio_wb32(pb, track->par->ch_layout.nb_channels); avio_wb32(pb, 0x7F000000); avio_wb32(pb, av_get_bits_per_sample(track->par->codec_id)); avio_wb32(pb, mov_get_lpcm_flags(track->par->codec_id)); @@ -1181,7 +1231,7 @@ static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContex avio_wb32(pb, get_samples_per_packet(track)); } else { if (track->mode == MODE_MOV) { - avio_wb16(pb, track->par->channels); + avio_wb16(pb, track->par->ch_layout.nb_channels); if (track->par->codec_id == AV_CODEC_ID_PCM_U8 || track->par->codec_id == AV_CODEC_ID_PCM_S8) avio_wb16(pb, 8); /* bits per sample */ @@ -1194,7 +1244,7 @@ static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContex if (track->par->codec_id == AV_CODEC_ID_FLAC || track->par->codec_id == AV_CODEC_ID_ALAC || track->par->codec_id == AV_CODEC_ID_OPUS) { - avio_wb16(pb, track->par->channels); + avio_wb16(pb, track->par->ch_layout.nb_channels); } else { avio_wb16(pb, 2); } @@ -1226,7 +1276,7 @@ static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContex avio_wb32(pb, 1); /* must be 1 for uncompressed formats */ else avio_wb32(pb, track->par->frame_size); /* Samples per packet */ - avio_wb32(pb, track->sample_size / track->par->channels); /* Bytes per packet */ + avio_wb32(pb, track->sample_size / track->par->ch_layout.nb_channels); /* Bytes per packet */ avio_wb32(pb, track->sample_size); /* Bytes per frame */ avio_wb32(pb, 2); /* Bytes per sample */ } @@ -1277,7 +1327,7 @@ static int mov_write_audio_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContex return ret; } - if (track->mode == MODE_MP4 && + if (mov->write_btrt && ((ret = mov_write_btrt_tag(pb, track)) < 0)) return ret; @@ -1303,7 +1353,7 @@ static int mov_write_av1c_tag(AVIOContext *pb, MOVTrack *track) avio_wb32(pb, 0); ffio_wfourcc(pb, "av1C"); - ff_isom_write_av1c(pb, track->vos_data, track->vos_len); + ff_isom_write_av1c(pb, track->vos_data, track->vos_len, track->mode != MODE_AVIF); return update_size(pb, pos); } @@ -1778,8 +1828,9 @@ static int mov_write_fiel_tag(AVIOContext *pb, MOVTrack *track, int field_order) return 10; } -static int mov_write_subtitle_tag(AVIOContext *pb, MOVTrack *track) +static int mov_write_subtitle_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track) { + MOVMuxContext *mov = s->priv_data; int ret = AVERROR_BUG; int64_t pos = avio_tell(pb); avio_wb32(pb, 0); /* size */ @@ -1815,7 +1866,7 @@ static int mov_write_subtitle_tag(AVIOContext *pb, MOVTrack *track) } else if (track->par->extradata_size) avio_write(pb, track->par->extradata, track->par->extradata_size); - if (track->mode == MODE_MP4 && + if (mov->write_btrt && ((ret = mov_write_btrt_tag(pb, track)) < 0)) return ret; @@ -2004,12 +2055,13 @@ static int mov_write_colr_tag(AVIOContext *pb, MOVTrack *track, int prefer_icc) } } - /* We should only ever be called by MOV or MP4. */ - av_assert0(track->mode == MODE_MOV || track->mode == MODE_MP4); + /* We should only ever be called for MOV, MP4 and AVIF. */ + av_assert0(track->mode == MODE_MOV || track->mode == MODE_MP4 || + track->mode == MODE_AVIF); avio_wb32(pb, 0); /* size */ ffio_wfourcc(pb, "colr"); - if (track->mode == MODE_MP4) + if (track->mode == MODE_MP4 || track->mode == MODE_AVIF) ffio_wfourcc(pb, "nclx"); else ffio_wfourcc(pb, "nclc"); @@ -2019,7 +2071,7 @@ static int mov_write_colr_tag(AVIOContext *pb, MOVTrack *track, int prefer_icc) avio_wb16(pb, track->par->color_primaries); avio_wb16(pb, track->par->color_trc); avio_wb16(pb, track->par->color_space); - if (track->mode == MODE_MP4) { + if (track->mode == MODE_MP4 || track->mode == MODE_AVIF) { int full_range = track->par->color_range == AVCOL_RANGE_JPEG; avio_w8(pb, full_range << 7); } @@ -2085,7 +2137,9 @@ static void find_compressor(char * compressor_name, int len, MOVTrack *track) || (track->par->width == 1440 && track->par->height == 1080) || (track->par->width == 1920 && track->par->height == 1080); - if (track->mode == MODE_MOV && + if ((track->mode == MODE_AVIF || + track->mode == MODE_MOV || + track->mode == MODE_MP4) && (encoder = av_dict_get(track->st->metadata, "encoder", NULL, 0))) { av_strlcpy(compressor_name, encoder->value, 32); } else if (track->par->codec_id == AV_CODEC_ID_MPEG2VIDEO && xdcam_res) { @@ -2106,6 +2160,25 @@ static void find_compressor(char * compressor_name, int len, MOVTrack *track) } } +static int mov_write_ccst_tag(AVIOContext *pb) +{ + int64_t pos = avio_tell(pb); + // Write sane defaults: + // all_ref_pics_intra = 0 : all samples can use any type of reference. + // intra_pred_used = 1 : intra prediction may or may not be used. + // max_ref_per_pic = 15 : reserved value to indicate that any number of + // reference images can be used. + uint8_t ccstValue = (0 << 7) | /* all_ref_pics_intra */ + (1 << 6) | /* intra_pred_used */ + (15 << 2); /* max_ref_per_pic */ + avio_wb32(pb, 0); /* size */ + ffio_wfourcc(pb, "ccst"); + avio_wb32(pb, 0); /* Version & flags */ + avio_w8(pb, ccstValue); + avio_wb24(pb, 0); /* reserved */ + return update_size(pb, pos); +} + static int mov_write_video_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track) { int ret = AVERROR_BUG; @@ -2155,7 +2228,6 @@ static int mov_write_video_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContex avio_wb32(pb, 0); /* Data size (= 0) */ avio_wb16(pb, 1); /* Frame count (= 1) */ - /* FIXME not sure, ISO 14496-1 draft where it shall be set to 0 */ find_compressor(compressor_name, 32, track); avio_w8(pb, strlen(compressor_name)); avio_write(pb, compressor_name, 31); @@ -2239,7 +2311,7 @@ static int mov_write_video_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContex else av_log(mov->fc, AV_LOG_WARNING, "Not writing 'gama' atom. Format is not MOV.\n"); } - if (track->mode == MODE_MOV || track->mode == MODE_MP4) { + if (track->mode == MODE_MOV || track->mode == MODE_MP4 || track->mode == MODE_AVIF) { int has_color_info = track->par->color_primaries != AVCOL_PRI_UNSPECIFIED && track->par->color_trc != AVCOL_TRC_UNSPECIFIED && track->par->color_space != AVCOL_SPC_UNSPECIFIED; @@ -2282,7 +2354,7 @@ static int mov_write_video_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContex ff_mov_cenc_write_sinf_tag(track, pb, mov->encryption_kid); } - if (track->mode == MODE_MP4 && + if (mov->write_btrt && ((ret = mov_write_btrt_tag(pb, track)) < 0)) return ret; @@ -2291,6 +2363,9 @@ static int mov_write_video_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContex if (avid) avio_wb32(pb, 0); + if (track->mode == MODE_AVIF) + mov_write_ccst_tag(pb); + return update_size(pb, pos); } @@ -2407,7 +2482,7 @@ static int mov_write_stsd_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) ret = mov_write_audio_tag(s, pb, mov, track); else if (track->par->codec_type == AVMEDIA_TYPE_SUBTITLE) - ret = mov_write_subtitle_tag(pb, track); + ret = mov_write_subtitle_tag(s, pb, track); else if (track->par->codec_tag == MKTAG('r','t','p',' ')) ret = mov_write_rtp_tag(pb, track); else if (track->par->codec_tag == MKTAG('t','m','c','d')) @@ -2793,8 +2868,13 @@ static int mov_write_hdlr_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *tra if (track) { hdlr = (track->mode == MODE_MOV) ? "mhlr" : "\0\0\0\0"; if (track->par->codec_type == AVMEDIA_TYPE_VIDEO) { - hdlr_type = "vide"; - descr = "VideoHandler"; + if (track->mode == MODE_AVIF) { + hdlr_type = (track == &mov->tracks[0]) ? "pict" : "auxv"; + descr = "PictureHandler"; + } else { + hdlr_type = "vide"; + descr = "VideoHandler"; + } } else if (track->par->codec_type == AVMEDIA_TYPE_AUDIO) { hdlr_type = "soun"; descr = "SoundHandler"; @@ -2859,6 +2939,172 @@ static int mov_write_hdlr_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *tra return update_size(pb, pos); } +static int mov_write_pitm_tag(AVIOContext *pb, int item_id) +{ + int64_t pos = avio_tell(pb); + avio_wb32(pb, 0); /* size */ + ffio_wfourcc(pb, "pitm"); + avio_wb32(pb, 0); /* Version & flags */ + avio_wb16(pb, item_id); /* item_id */ + return update_size(pb, pos); +} + +static int mov_write_iloc_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s) +{ + int64_t pos = avio_tell(pb); + avio_wb32(pb, 0); /* size */ + ffio_wfourcc(pb, "iloc"); + avio_wb32(pb, 0); /* Version & flags */ + avio_w8(pb, (4 << 4) + 4); /* offset_size(4) and length_size(4) */ + avio_w8(pb, 0); /* base_offset_size(4) and reserved(4) */ + avio_wb16(pb, s->nb_streams); /* item_count */ + + for (int i = 0; i < s->nb_streams; i++) { + avio_wb16(pb, i + 1); /* item_id */ + avio_wb16(pb, 0); /* data_reference_index */ + avio_wb16(pb, 1); /* extent_count */ + mov->avif_extent_pos[i] = avio_tell(pb); + avio_wb32(pb, 0); /* extent_offset (written later) */ + // For animated AVIF, we simply write the first packet's size. + avio_wb32(pb, mov->avif_extent_length[i]); /* extent_length */ + } + + return update_size(pb, pos); +} + +static int mov_write_iinf_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s) +{ + int64_t iinf_pos = avio_tell(pb); + avio_wb32(pb, 0); /* size */ + ffio_wfourcc(pb, "iinf"); + avio_wb32(pb, 0); /* Version & flags */ + avio_wb16(pb, s->nb_streams); /* entry_count */ + + for (int i = 0; i < s->nb_streams; i++) { + int64_t infe_pos = avio_tell(pb); + avio_wb32(pb, 0); /* size */ + ffio_wfourcc(pb, "infe"); + avio_w8(pb, 0x2); /* Version */ + avio_wb24(pb, 0); /* flags */ + avio_wb16(pb, i + 1); /* item_id */ + avio_wb16(pb, 0); /* item_protection_index */ + avio_write(pb, "av01", 4); /* item_type */ + avio_write(pb, !i ? "Color\0" : "Alpha\0", 6); /* item_name */ + update_size(pb, infe_pos); + } + + return update_size(pb, iinf_pos); +} + + +static int mov_write_iref_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s) +{ + int64_t auxl_pos; + int64_t iref_pos = avio_tell(pb); + avio_wb32(pb, 0); /* size */ + ffio_wfourcc(pb, "iref"); + avio_wb32(pb, 0); /* Version & flags */ + + auxl_pos = avio_tell(pb); + avio_wb32(pb, 0); /* size */ + ffio_wfourcc(pb, "auxl"); + avio_wb16(pb, 2); /* from_item_ID */ + avio_wb16(pb, 1); /* reference_count */ + avio_wb16(pb, 1); /* to_item_ID */ + update_size(pb, auxl_pos); + + return update_size(pb, iref_pos); +} + +static int mov_write_ispe_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s, + int stream_index) +{ + int64_t pos = avio_tell(pb); + avio_wb32(pb, 0); /* size */ + ffio_wfourcc(pb, "ispe"); + avio_wb32(pb, 0); /* Version & flags */ + avio_wb32(pb, s->streams[stream_index]->codecpar->width); /* image_width */ + avio_wb32(pb, s->streams[stream_index]->codecpar->height); /* image_height */ + return update_size(pb, pos); +} + +static int mov_write_pixi_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s, + int stream_index) +{ + int64_t pos = avio_tell(pb); + const AVPixFmtDescriptor *pixdesc = + av_pix_fmt_desc_get(s->streams[stream_index]->codecpar->format); + avio_wb32(pb, 0); /* size */ + ffio_wfourcc(pb, "pixi"); + avio_wb32(pb, 0); /* Version & flags */ + avio_w8(pb, pixdesc->nb_components); /* num_channels */ + for (int i = 0; i < pixdesc->nb_components; ++i) { + avio_w8(pb, pixdesc->comp[i].depth); /* bits_per_channel */ + } + return update_size(pb, pos); +} + +static int mov_write_auxC_tag(AVIOContext *pb) +{ + int64_t pos = avio_tell(pb); + avio_wb32(pb, 0); /* size */ + ffio_wfourcc(pb, "auxC"); + avio_wb32(pb, 0); /* Version & flags */ + avio_write(pb, "urn:mpeg:mpegB:cicp:systems:auxiliary:alpha\0", 44); + return update_size(pb, pos); +} + +static int mov_write_ipco_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s) +{ + int64_t pos = avio_tell(pb); + avio_wb32(pb, 0); /* size */ + ffio_wfourcc(pb, "ipco"); + for (int i = 0; i < s->nb_streams; i++) { + mov_write_ispe_tag(pb, mov, s, i); + mov_write_pixi_tag(pb, mov, s, i); + mov_write_av1c_tag(pb, &mov->tracks[i]); + if (!i) + mov_write_colr_tag(pb, &mov->tracks[0], 0); + else + mov_write_auxC_tag(pb); + } + return update_size(pb, pos); +} + +static int mov_write_ipma_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s) +{ + int64_t pos = avio_tell(pb); + avio_wb32(pb, 0); /* size */ + ffio_wfourcc(pb, "ipma"); + avio_wb32(pb, 0); /* Version & flags */ + avio_wb32(pb, s->nb_streams); /* entry_count */ + + for (int i = 0, index = 1; i < s->nb_streams; i++) { + avio_wb16(pb, i + 1); /* item_ID */ + avio_w8(pb, 4); /* association_count */ + + // ispe association. + avio_w8(pb, index++); /* essential and property_index */ + // pixi association. + avio_w8(pb, index++); /* essential and property_index */ + // av1C association. + avio_w8(pb, 0x80 | index++); /* essential and property_index */ + // colr/auxC association. + avio_w8(pb, index++); /* essential and property_index */ + } + return update_size(pb, pos); +} + +static int mov_write_iprp_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s) +{ + int64_t pos = avio_tell(pb); + avio_wb32(pb, 0); /* size */ + ffio_wfourcc(pb, "iprp"); + mov_write_ipco_tag(pb, mov, s); + mov_write_ipma_tag(pb, mov, s); + return update_size(pb, pos); +} + static int mov_write_hmhd_tag(AVIOContext *pb) { /* This atom must be present, but leaving the values at zero @@ -3104,7 +3350,7 @@ static int mov_write_tkhd_tag(AVIOContext *pb, MOVMuxContext *mov, if (st && (track->par->codec_type == AVMEDIA_TYPE_VIDEO || track->par->codec_type == AVMEDIA_TYPE_SUBTITLE)) { int64_t track_width_1616; - if (track->mode == MODE_MOV) { + if (track->mode == MODE_MOV || track->mode == MODE_AVIF) { track_width_1616 = track->par->width * 0x10000ULL; } else { track_width_1616 = av_rescale(st->sample_aspect_ratio.num, @@ -3503,6 +3749,7 @@ static int mov_write_mvhd_tag(AVIOContext *pb, MOVMuxContext *mov) int max_track_id = 1, i; int64_t max_track_len = 0; int version; + int timescale; for (i = 0; i < mov->nb_streams; i++) { if (mov->tracks[i].entry > 0 && mov->tracks[i].timescale) { @@ -3537,7 +3784,12 @@ static int mov_write_mvhd_tag(AVIOContext *pb, MOVMuxContext *mov) avio_wb32(pb, mov->time); /* creation time */ avio_wb32(pb, mov->time); /* modification time */ } - avio_wb32(pb, mov->movie_timescale); + + timescale = mov->movie_timescale; + if (mov->mode == MODE_AVIF && !timescale) + timescale = mov->tracks[0].timescale; + + avio_wb32(pb, timescale); (version == 1) ? avio_wb64(pb, max_track_len) : avio_wb32(pb, max_track_len); /* duration of longest track */ avio_wb32(pb, 0x00010000); /* reserved (preferred rate) 1.0 = normal */ @@ -3914,8 +4166,17 @@ static int mov_write_meta_tag(AVIOContext *pb, MOVMuxContext *mov, mov_write_mdta_hdlr_tag(pb, mov, s); mov_write_mdta_keys_tag(pb, mov, s); mov_write_mdta_ilst_tag(pb, mov, s); - } - else { + } else if (mov->mode == MODE_AVIF) { + mov_write_hdlr_tag(s, pb, &mov->tracks[0]); + // We always write the primary item id as 1 since only one track is + // supported for AVIF. + mov_write_pitm_tag(pb, 1); + mov_write_iloc_tag(pb, mov, s); + mov_write_iinf_tag(pb, mov, s); + if (s->nb_streams > 1) + mov_write_iref_tag(pb, mov, s); + mov_write_iprp_tag(pb, mov, s); + } else { /* iTunes metadata tag */ mov_write_itunes_hdlr_tag(pb, mov, s); mov_write_ilst_tag(pb, mov, s); @@ -4108,7 +4369,7 @@ static int mov_write_uuidusmt_tag(AVIOContext *pb, AVFormatContext *s) avio_wb16(pb, 0x021C); /* data */ if (!(s->flags & AVFMT_FLAG_BITEXACT)) - mov_write_psp_udta_tag(pb, LIBAVCODEC_IDENT, "eng", 0x04); + mov_write_psp_udta_tag(pb, LIBAVFORMAT_IDENT, "eng", 0x04); mov_write_psp_udta_tag(pb, title->value, "eng", 0x01); mov_write_psp_udta_tag(pb, "2006/04/01 11:11:11", "und", 0x03); @@ -4245,10 +4506,11 @@ static int mov_write_moov_tag(AVIOContext *pb, MOVMuxContext *mov, } mov_write_mvhd_tag(pb, mov); - if (mov->mode != MODE_MOV && !mov->iods_skip) + if (mov->mode != MODE_MOV && mov->mode != MODE_AVIF && !mov->iods_skip) mov_write_iods_tag(pb, mov); for (i = 0; i < mov->nb_streams; i++) { - if (mov->tracks[i].entry > 0 || mov->flags & FF_MOV_FLAG_FRAGMENT) { + if (mov->tracks[i].entry > 0 || mov->flags & FF_MOV_FLAG_FRAGMENT || + mov->mode == MODE_AVIF) { int ret = mov_write_trak_tag(s, pb, mov, &(mov->tracks[i]), i < s->nb_streams ? s->streams[i] : NULL); if (ret < 0) return ret; @@ -4259,7 +4521,7 @@ static int mov_write_moov_tag(AVIOContext *pb, MOVMuxContext *mov, if (mov->mode == MODE_PSP) mov_write_uuidusmt_tag(pb, s); - else + else if (mov->mode != MODE_AVIF) mov_write_udta_tag(pb, mov, s); return update_size(pb, pos); @@ -4288,14 +4550,14 @@ static int mov_write_isml_manifest(AVIOContext *pb, MOVMuxContext *mov, AVFormat int64_t pos = avio_tell(pb); int i; - static const uint8_t uuid[] = { + static const AVUUID uuid = { 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd, 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 }; avio_wb32(pb, 0); ffio_wfourcc(pb, "uuid"); - avio_write(pb, uuid, sizeof(uuid)); + avio_write(pb, uuid, AV_UUID_LEN); avio_wb32(pb, 0); avio_printf(pb, "\n"); @@ -4392,7 +4654,7 @@ static int mov_write_isml_manifest(AVIOContext *pb, MOVMuxContext *mov, AVFormat track->par->extradata_size); param_write_int(pb, "AudioTag", ff_codec_get_tag(ff_codec_wav_tags, track->par->codec_id)); - param_write_int(pb, "Channels", track->par->channels); + param_write_int(pb, "Channels", track->par->ch_layout.nb_channels); param_write_int(pb, "SamplingRate", track->par->sample_rate); param_write_int(pb, "BitsPerSample", 16); param_write_int(pb, "PacketSize", track->par->block_align ? @@ -4554,7 +4816,7 @@ static int mov_write_tfxd_tag(AVIOContext *pb, MOVTrack *track) avio_wb32(pb, 0); /* size placeholder */ ffio_wfourcc(pb, "uuid"); - avio_write(pb, uuid, sizeof(uuid)); + avio_write(pb, uuid, AV_UUID_LEN); avio_w8(pb, 1); avio_wb24(pb, 0); avio_wb64(pb, track->cluster[0].dts + track->cluster[0].cts); @@ -4580,7 +4842,7 @@ static int mov_write_tfrf_tag(AVIOContext *pb, MOVMuxContext *mov, avio_seek(pb, track->frag_info[entry].tfrf_offset, SEEK_SET); avio_wb32(pb, size); ffio_wfourcc(pb, "uuid"); - avio_write(pb, uuid, sizeof(uuid)); + avio_write(pb, uuid, AV_UUID_LEN); avio_w8(pb, 1); avio_wb24(pb, 0); avio_w8(pb, n); @@ -4750,7 +5012,8 @@ static int mov_write_sidx_tag(AVIOContext *pb, if (track->entry) { entries = 1; - presentation_time = track->cluster[0].dts + track->cluster[0].cts; + presentation_time = track->cluster[0].dts + track->cluster[0].cts - + track->start_dts - track->start_cts; duration = track->end_pts - (track->cluster[0].dts + track->cluster[0].cts); starts_with_SAP = track->cluster[0].flags & MOV_SYNC_SAMPLE; @@ -4765,6 +5028,9 @@ static int mov_write_sidx_tag(AVIOContext *pb, if (entries <= 0) return 0; presentation_time = track->frag_info[0].time; + /* presentation_time <= 0 is handled by mov_add_tfra_entries() */ + if (presentation_time > 0) + presentation_time -= track->start_dts + track->start_cts; } avio_wb32(pb, 0); /* size */ @@ -5002,6 +5268,9 @@ static void mov_write_ftyp_tag_internal(AVIOContext *pb, AVFormatContext *s, else if (mov->mode == MODE_3GP) { ffio_wfourcc(pb, has_h264 ? "3gp6" : "3gp4"); minor = has_h264 ? 0x100 : 0x200; + } else if (mov->mode == MODE_AVIF) { + ffio_wfourcc(pb, mov->is_animated_avif ? "avis" : "avif"); + minor = 0; } else if (mov->mode & MODE_3G2) { ffio_wfourcc(pb, has_h264 ? "3g2b" : "3g2a"); minor = has_h264 ? 0x20000 : 0x10000; @@ -5065,6 +5334,31 @@ static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s) // compatible brand a second time. if (mov->mode == MODE_ISM) { ffio_wfourcc(pb, "piff"); + } else if (mov->mode == MODE_AVIF) { + const AVPixFmtDescriptor *pix_fmt_desc = + av_pix_fmt_desc_get(s->streams[0]->codecpar->format); + const int depth = pix_fmt_desc->comp[0].depth; + if (mov->is_animated_avif) { + // For animated AVIF, major brand is "avis". Add "avif" as a + // compatible brand. + ffio_wfourcc(pb, "avif"); + ffio_wfourcc(pb, "msf1"); + ffio_wfourcc(pb, "iso8"); + } + ffio_wfourcc(pb, "mif1"); + ffio_wfourcc(pb, "miaf"); + if (depth == 8 || depth == 10) { + // MA1B and MA1A brands are based on AV1 profile. Short hand for + // computing that is based on chroma subsampling type. 420 chroma + // subsampling is MA1B. 444 chroma subsampling is MA1A. + if (!pix_fmt_desc->log2_chroma_w && !pix_fmt_desc->log2_chroma_h) { + // 444 chroma subsampling. + ffio_wfourcc(pb, "MA1A"); + } else { + // 420 chroma subsampling. + ffio_wfourcc(pb, "MA1B"); + } + } } else if (mov->mode != MODE_MOV) { // We add tfdt atoms when fragmenting, signal this with the iso6 compatible // brand, if not already the major brand. This is compatible with users that @@ -5150,7 +5444,7 @@ static int mov_write_uuidprof_tag(AVIOContext *pb, AVFormatContext *s) avio_wb32(pb, audio_kbitrate); avio_wb32(pb, audio_kbitrate); avio_wb32(pb, audio_rate); - avio_wb32(pb, audio_par->channels); + avio_wb32(pb, audio_par->ch_layout.nb_channels); avio_wb32(pb, 0x34); /* size */ ffio_wfourcc(pb, "VPRF"); /* video */ @@ -5638,9 +5932,8 @@ static int check_pkt(AVFormatContext *s, AVPacket *pkt) duration = pkt->dts - ref; if (pkt->dts < ref || duration >= INT_MAX) { - av_log(s, AV_LOG_ERROR, "Application provided duration: %"PRId64" / timestamp: %"PRId64" is out of range for mov/mp4 format\n", - duration, pkt->dts - ); + av_log(s, AV_LOG_WARNING, "Packet duration: %"PRId64" / dts: %"PRId64" is out of range\n", + duration, pkt->dts); pkt->dts = ref + 1; pkt->pts = AV_NOPTS_VALUE; @@ -5669,7 +5962,7 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) if (ret < 0) return ret; - if (mov->flags & FF_MOV_FLAG_FRAGMENT) { + if (mov->flags & FF_MOV_FLAG_FRAGMENT || mov->mode == MODE_AVIF) { int ret; if (mov->moov_written || mov->flags & FF_MOV_FLAG_EMPTY_MOOV) { if (mov->frag_interleave && mov->fragments > 0) { @@ -5737,8 +6030,7 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) if ((par->codec_id == AV_CODEC_ID_DNXHD || par->codec_id == AV_CODEC_ID_H264 || par->codec_id == AV_CODEC_ID_HEVC || - par->codec_id == AV_CODEC_ID_TRUEHD || - par->codec_id == AV_CODEC_ID_AC3) && !trk->vos_len && + par->codec_id == AV_CODEC_ID_TRUEHD) && !trk->vos_len && !TAG_IS_AVCI(trk->tag)) { /* copy frame to create needed atoms */ trk->vos_len = size; @@ -5810,16 +6102,19 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) avio_write(pb, reformatted_data, size); } else { size = ff_av1_filter_obus(pb, pkt->data, pkt->size); + if (trk->mode == MODE_AVIF && !mov->avif_extent_length[pkt->stream_index]) { + mov->avif_extent_length[pkt->stream_index] = size; + } } -#if CONFIG_AC3_PARSER - } else if (par->codec_id == AV_CODEC_ID_EAC3) { + + } else if (par->codec_id == AV_CODEC_ID_AC3 || + par->codec_id == AV_CODEC_ID_EAC3) { size = handle_eac3(mov, pkt, trk); if (size < 0) return size; else if (!size) goto end; avio_write(pb, pkt->data, size); -#endif } else if (par->codec_id == AV_CODEC_ID_EIA_608) { size = 8; @@ -6218,6 +6513,9 @@ static int mov_write_packet(AVFormatContext *s, AVPacket *pkt) } else if (trk->par->codec_id == AV_CODEC_ID_RAWVIDEO && (trk->par->format == AV_PIX_FMT_GRAY8 || trk->par->format == AV_PIX_FMT_MONOBLACK)) { + ret = av_packet_make_writable(pkt); + if (ret < 0) + goto fail; for (i = 0; i < pkt->size; i++) pkt->data[i] = ~pkt->data[i]; } @@ -6238,12 +6536,32 @@ fail: // as samples, and a tref pointing from the other tracks to the chapter one. static int mov_create_chapter_track(AVFormatContext *s, int tracknum) { - AVIOContext *pb; - + static const uint8_t stub_header[] = { + // TextSampleEntry + 0x00, 0x00, 0x00, 0x01, // displayFlags + 0x00, 0x00, // horizontal + vertical justification + 0x00, 0x00, 0x00, 0x00, // bgColourRed/Green/Blue/Alpha + // BoxRecord + 0x00, 0x00, 0x00, 0x00, // defTextBoxTop/Left + 0x00, 0x00, 0x00, 0x00, // defTextBoxBottom/Right + // StyleRecord + 0x00, 0x00, 0x00, 0x00, // startChar + endChar + 0x00, 0x01, // fontID + 0x00, 0x00, // fontStyleFlags + fontSize + 0x00, 0x00, 0x00, 0x00, // fgColourRed/Green/Blue/Alpha + // FontTableBox + 0x00, 0x00, 0x00, 0x0D, // box size + 'f', 't', 'a', 'b', // box atom name + 0x00, 0x01, // entry count + // FontRecord + 0x00, 0x01, // font ID + 0x00, // font name length + }; MOVMuxContext *mov = s->priv_data; MOVTrack *track = &mov->tracks[tracknum]; AVPacket *pkt = mov->pkt; int i, len; + int ret; track->mode = mov->mode; track->tag = MKTAG('t','e','x','t'); @@ -6252,57 +6570,10 @@ static int mov_create_chapter_track(AVFormatContext *s, int tracknum) if (!track->par) return AVERROR(ENOMEM); track->par->codec_type = AVMEDIA_TYPE_SUBTITLE; -#if 0 - // These properties are required to make QT recognize the chapter track - uint8_t chapter_properties[43] = { 0, 0, 0, 0, 0, 0, 0, 1, }; - if (ff_alloc_extradata(track->par, sizeof(chapter_properties))) - return AVERROR(ENOMEM); - memcpy(track->par->extradata, chapter_properties, sizeof(chapter_properties)); -#else - if (avio_open_dyn_buf(&pb) >= 0) { - int size; - uint8_t *buf; - - /* Stub header (usually for Quicktime chapter track) */ - // TextSampleEntry - avio_wb32(pb, 0x01); // displayFlags - avio_w8(pb, 0x00); // horizontal justification - avio_w8(pb, 0x00); // vertical justification - avio_w8(pb, 0x00); // bgColourRed - avio_w8(pb, 0x00); // bgColourGreen - avio_w8(pb, 0x00); // bgColourBlue - avio_w8(pb, 0x00); // bgColourAlpha - // BoxRecord - avio_wb16(pb, 0x00); // defTextBoxTop - avio_wb16(pb, 0x00); // defTextBoxLeft - avio_wb16(pb, 0x00); // defTextBoxBottom - avio_wb16(pb, 0x00); // defTextBoxRight - // StyleRecord - avio_wb16(pb, 0x00); // startChar - avio_wb16(pb, 0x00); // endChar - avio_wb16(pb, 0x01); // fontID - avio_w8(pb, 0x00); // fontStyleFlags - avio_w8(pb, 0x00); // fontSize - avio_w8(pb, 0x00); // fgColourRed - avio_w8(pb, 0x00); // fgColourGreen - avio_w8(pb, 0x00); // fgColourBlue - avio_w8(pb, 0x00); // fgColourAlpha - // FontTableBox - avio_wb32(pb, 0x0D); // box size - ffio_wfourcc(pb, "ftab"); // box atom name - avio_wb16(pb, 0x01); // entry count - // FontRecord - avio_wb16(pb, 0x01); // font ID - avio_w8(pb, 0x00); // font name length - - if ((size = avio_close_dyn_buf(pb, &buf)) > 0) { - track->par->extradata = buf; - track->par->extradata_size = size; - } else { - av_freep(&buf); - } - } -#endif + ret = ff_alloc_extradata(track->par, sizeof(stub_header)); + if (ret < 0) + return ret; + memcpy(track->par->extradata, stub_header, sizeof(stub_header)); pkt->stream_index = tracknum; pkt->flags = AV_PKT_FLAG_KEY; @@ -6383,6 +6654,7 @@ static int mov_create_timecode_track(AVFormatContext *s, int index, int src_inde pkt->data = data; pkt->stream_index = index; pkt->flags = AV_PKT_FLAG_KEY; + pkt->pts = pkt->dts = av_rescale_q(tc.start, av_inv_q(rate), (AVRational){1,mov->movie_timescale}); pkt->size = 4; AV_WB32(pkt->data, tc.start); ret = ff_mov_write_packet(s, pkt); @@ -6569,11 +6841,15 @@ static int mov_init(AVFormatContext *s) else if (IS_MODE(ipod, IPOD)) mov->mode = MODE_IPOD; else if (IS_MODE(ismv, ISMV)) mov->mode = MODE_ISM; else if (IS_MODE(f4v, F4V)) mov->mode = MODE_F4V; + else if (IS_MODE(avif, AVIF)) mov->mode = MODE_AVIF; #undef IS_MODE if (mov->flags & FF_MOV_FLAG_DELAY_MOOV) mov->flags |= FF_MOV_FLAG_EMPTY_MOOV; + if (mov->mode == MODE_AVIF) + mov->flags |= FF_MOV_FLAG_DELAY_MOOV; + /* Set the FRAGMENT flag if any of the fragmentation methods are * enabled. */ if (mov->max_fragment_duration || mov->max_fragment_size || @@ -6654,11 +6930,35 @@ static int mov_init(AVFormatContext *s) /* Non-seekable output is ok if using fragmentation. If ism_lookahead * is enabled, we don't support non-seekable output at all. */ if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL) && - (!(mov->flags & FF_MOV_FLAG_FRAGMENT) || mov->ism_lookahead)) { + (!(mov->flags & FF_MOV_FLAG_FRAGMENT) || mov->ism_lookahead || + mov->mode == MODE_AVIF)) { av_log(s, AV_LOG_ERROR, "muxer does not support non seekable output\n"); return AVERROR(EINVAL); } + /* AVIF output must have at most two video streams (one for YUV and one for + * alpha). */ + if (mov->mode == MODE_AVIF) { + if (s->nb_streams > 2) { + av_log(s, AV_LOG_ERROR, "AVIF output requires exactly one or two streams\n"); + return AVERROR(EINVAL); + } + if (s->streams[0]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO && + (s->nb_streams > 1 && s->streams[1]->codecpar->codec_type != AVMEDIA_TYPE_VIDEO)) { + av_log(s, AV_LOG_ERROR, "AVIF output supports only video streams\n"); + return AVERROR(EINVAL); + } + if (s->nb_streams > 1) { + const AVPixFmtDescriptor *pixdesc = + av_pix_fmt_desc_get(s->streams[1]->codecpar->format); + if (pixdesc->nb_components != 1) { + av_log(s, AV_LOG_ERROR, "Second stream for AVIF (alpha) output must have exactly one plane\n"); + return AVERROR(EINVAL); + } + } + s->streams[0]->disposition |= AV_DISPOSITION_DEFAULT; + } + mov->nb_streams = s->nb_streams; if (mov->mode & (MODE_MP4|MODE_MOV|MODE_IPOD) && s->nb_chapters) mov->chapter_track = mov->nb_streams++; @@ -6669,6 +6969,10 @@ static int mov_init(AVFormatContext *s) mov->nb_streams++; } + if (mov->write_btrt < 0) { + mov->write_btrt = mov->mode == MODE_MP4; + } + if ( mov->write_tmcd == -1 && (mov->mode == MODE_MOV || mov->mode == MODE_MP4) || mov->write_tmcd == 1) { AVDictionaryEntry *global_tcr = av_dict_get(s->metadata, "timecode", @@ -6797,12 +7101,13 @@ static int mov_init(AVFormatContext *s) pix_fmt == AV_PIX_FMT_MONOWHITE || pix_fmt == AV_PIX_FMT_MONOBLACK; } - if (track->par->codec_id == AV_CODEC_ID_VP9 || - track->par->codec_id == AV_CODEC_ID_AV1) { - if (track->mode != MODE_MP4) { - av_log(s, AV_LOG_ERROR, "%s only supported in MP4.\n", avcodec_get_name(track->par->codec_id)); - return AVERROR(EINVAL); - } + if (track->par->codec_id == AV_CODEC_ID_VP9 && track->mode != MODE_MP4) { + av_log(s, AV_LOG_ERROR, "%s only supported in MP4.\n", avcodec_get_name(track->par->codec_id)); + return AVERROR(EINVAL); + } else if (track->par->codec_id == AV_CODEC_ID_AV1 && + track->mode != MODE_MP4 && track->mode != MODE_AVIF) { + av_log(s, AV_LOG_ERROR, "%s only supported in MP4 and AVIF.\n", avcodec_get_name(track->par->codec_id)); + 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 */ @@ -6830,7 +7135,8 @@ static int mov_init(AVFormatContext *s) }else if (st->codecpar->frame_size > 1){ /* assume compressed audio */ track->audio_vbr = 1; }else{ - track->sample_size = (av_get_bits_per_sample(st->codecpar->codec_id) >> 3) * st->codecpar->channels; + track->sample_size = (av_get_bits_per_sample(st->codecpar->codec_id) >> 3) * + st->codecpar->ch_layout.nb_channels; } if (st->codecpar->codec_id == AV_CODEC_ID_ILBC || st->codecpar->codec_id == AV_CODEC_ID_ADPCM_IMA_QT) { @@ -6966,7 +7272,8 @@ static int mov_write_header(AVFormatContext *s) } if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO || - track->par->channel_layout != AV_CH_LAYOUT_MONO) + av_channel_layout_compare(&track->par->ch_layout, + &(AVChannelLayout)AV_CHANNEL_LAYOUT_MONO)) continue; for (j = 0; j < s->nb_streams; j++) { @@ -6975,8 +7282,23 @@ static int mov_write_header(AVFormatContext *s) if (j == i) continue; + if (stj->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && + (trackj->par->ch_layout.nb_channels != 1 || + !av_channel_layout_compare(&trackj->par->ch_layout, + &(AVChannelLayout)AV_CHANNEL_LAYOUT_MONO)) + ) + track->mono_as_fc = -1; + + if (stj->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && + av_channel_layout_compare(&trackj->par->ch_layout, + &(AVChannelLayout)AV_CHANNEL_LAYOUT_MONO) && + trackj->par->ch_layout.nb_channels == 1 && track->mono_as_fc >= 0 + ) + track->mono_as_fc++; + if (stj->codecpar->codec_type != AVMEDIA_TYPE_AUDIO || - trackj->par->channel_layout != AV_CH_LAYOUT_MONO || + av_channel_layout_compare(&trackj->par->ch_layout, + &(AVChannelLayout)AV_CHANNEL_LAYOUT_MONO) || trackj->language != track->language || trackj->tag != track->tag ) @@ -7003,7 +7325,7 @@ static int mov_write_header(AVFormatContext *s) FF_MOV_FLAG_FRAG_EVERY_FRAME)) && !mov->max_fragment_duration && !mov->max_fragment_size) mov->flags |= FF_MOV_FLAG_FRAG_KEYFRAME; - } else { + } else if (mov->mode != MODE_AVIF) { if (mov->flags & FF_MOV_FLAG_FASTSTART) mov->reserved_header_pos = avio_tell(pb); mov_write_mdat_tag(pb, mov); @@ -7291,6 +7613,62 @@ static int mov_check_bitstream(AVFormatContext *s, AVStream *st, return ret; } +static int avif_write_trailer(AVFormatContext *s) +{ + AVIOContext *pb = s->pb; + MOVMuxContext *mov = s->priv_data; + int64_t pos_backup, extent_offsets[2]; + uint8_t *buf; + int buf_size, moov_size, i; + + if (mov->moov_written) return 0; + + mov->is_animated_avif = s->streams[0]->nb_frames > 1; + if (mov->is_animated_avif && s->nb_streams > 1) { + // For animated avif with alpha channel, we need to write a tref tag + // with type "auxl". + mov->tracks[1].tref_tag = MKTAG('a', 'u', 'x', 'l'); + mov->tracks[1].tref_id = 1; + } + mov_write_identification(pb, s); + mov_write_meta_tag(pb, mov, s); + + moov_size = get_moov_size(s); + for (i = 0; i < s->nb_streams; i++) + mov->tracks[i].data_offset = avio_tell(pb) + moov_size + 8; + + if (mov->is_animated_avif) { + int ret; + if ((ret = mov_write_moov_tag(pb, mov, s)) < 0) + return ret; + } + + buf_size = avio_get_dyn_buf(mov->mdat_buf, &buf); + avio_wb32(pb, buf_size + 8); + ffio_wfourcc(pb, "mdat"); + + // The offset for the YUV planes is the starting position of mdat. + extent_offsets[0] = avio_tell(pb); + // The offset for alpha plane is YUV offset + YUV size. + extent_offsets[1] = extent_offsets[0] + mov->avif_extent_length[0]; + + avio_write(pb, buf, buf_size); + + // write extent offsets. + pos_backup = avio_tell(pb); + for (i = 0; i < s->nb_streams; i++) { + if (extent_offsets[i] != (uint32_t)extent_offsets[i]) { + av_log(s, AV_LOG_ERROR, "extent offset does not fit in 32 bits\n"); + return AVERROR_INVALIDDATA; + } + avio_seek(pb, mov->avif_extent_pos[i], SEEK_SET); + avio_wb32(pb, extent_offsets[i]); /* rewrite offset */ + } + avio_seek(pb, pos_backup, SEEK_SET); + + return 0; +} + #if CONFIG_TGP_MUXER || CONFIG_TG2_MUXER static const AVCodecTag codec_3gp_tags[] = { { AV_CODEC_ID_H263, MKTAG('s','2','6','3') }, @@ -7373,6 +7751,20 @@ static const AVCodecTag codec_f4v_tags[] = { { AV_CODEC_ID_NONE, 0 }, }; +#if CONFIG_AVIF_MUXER +static const AVCodecTag codec_avif_tags[] = { + { AV_CODEC_ID_AV1, MKTAG('a','v','0','1') }, + { AV_CODEC_ID_NONE, 0 }, +}; +static const AVCodecTag *const codec_avif_tags_list[] = { codec_avif_tags, NULL }; + +static const AVClass mov_avif_muxer_class = { + .class_name = "avif muxer", + .item_name = av_default_item_name, + .version = LIBAVUTIL_VERSION_INT, +}; +#endif + #if CONFIG_MOV_MUXER const AVOutputFormat ff_mov_muxer = { .name = "mov", @@ -7535,3 +7927,21 @@ const AVOutputFormat ff_f4v_muxer = { .priv_class = &mov_isobmff_muxer_class, }; #endif +#if CONFIG_AVIF_MUXER +const AVOutputFormat ff_avif_muxer = { + .name = "avif", + .long_name = NULL_IF_CONFIG_SMALL("AVIF"), + .mime_type = "image/avif", + .extensions = "avif", + .priv_data_size = sizeof(MOVMuxContext), + .video_codec = AV_CODEC_ID_AV1, + .init = mov_init, + .write_header = mov_write_header, + .write_packet = mov_write_packet, + .write_trailer = avif_write_trailer, + .deinit = mov_free, + .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH, + .codec_tag = codec_avif_tags_list, + .priv_class = &mov_avif_muxer_class, +}; +#endif diff --git a/libavformat/movenc.h b/libavformat/movenc.h index 2ac84ed07..c6b3313de 100644 --- a/libavformat/movenc.h +++ b/libavformat/movenc.h @@ -43,6 +43,7 @@ #define MODE_IPOD 0x20 #define MODE_ISM 0x40 #define MODE_F4V 0x80 +#define MODE_AVIF 0x100 typedef struct MOVIentry { uint64_t pos; @@ -61,7 +62,7 @@ typedef struct MOVIentry { } MOVIentry; typedef struct HintSample { - uint8_t *data; + const uint8_t *data; int size; int sample_number; int offset; @@ -107,6 +108,7 @@ typedef struct MOVTrack { int tag; ///< stsd fourcc AVStream *st; AVCodecParameters *par; + int mono_as_fc; int multichannel_as_mono; int vos_len; @@ -238,10 +240,15 @@ typedef struct MOVMuxContext { int use_stream_ids_as_track_ids; int track_ids_ok; + int write_btrt; int write_tmcd; MOVPrftBox write_prft; int empty_hdlr_name; int movie_timescale; + + int64_t avif_extent_pos[2]; // index 0 is YUV and 1 is Alpha. + int avif_extent_length[2]; // index 0 is YUV and 1 is Alpha. + int is_animated_avif; } MOVMuxContext; #define FF_MOV_FLAG_RTP_HINT (1 << 0) diff --git a/libavformat/movenchint.c b/libavformat/movenchint.c index 35212f2c5..016934118 100644 --- a/libavformat/movenchint.c +++ b/libavformat/movenchint.c @@ -21,7 +21,7 @@ #include "movenc.h" #include "libavutil/intreadwrite.h" -#include "internal.h" +#include "mux.h" #include "rtpenc_chain.h" #include "avio_internal.h" #include "rtp.h" @@ -96,7 +96,7 @@ static void sample_queue_free(HintSampleQueue *queue) * not copied. sample_queue_retain should be called before pkt->data * is reused/freed. */ -static void sample_queue_push(HintSampleQueue *queue, uint8_t *data, int size, +static void sample_queue_push(HintSampleQueue *queue, const uint8_t *data, int size, int sample) { /* No need to keep track of smaller samples, since describing them diff --git a/libavformat/mp3dec.c b/libavformat/mp3dec.c index f617348b2..458d6dbd0 100644 --- a/libavformat/mp3dec.c +++ b/libavformat/mp3dec.c @@ -20,14 +20,13 @@ */ #include "libavutil/opt.h" -#include "libavutil/avstring.h" #include "libavutil/intreadwrite.h" -#include "libavutil/crc.h" #include "libavutil/dict.h" #include "libavutil/mathematics.h" #include "avformat.h" #include "internal.h" #include "avio_internal.h" +#include "demux.h" #include "id3v2.h" #include "id3v1.h" #include "replaygain.h" diff --git a/libavformat/mp3enc.c b/libavformat/mp3enc.c index 3ff19da27..91874fa14 100644 --- a/libavformat/mp3enc.c +++ b/libavformat/mp3enc.c @@ -175,7 +175,7 @@ static int mp3_write_xing(AVFormatContext *s) return -1; } - switch (par->channels) { + switch (par->ch_layout.nb_channels) { case 1: channels = MPA_MONO; break; case 2: channels = MPA_STEREO; break; default: av_log(s, AV_LOG_WARNING, "Unsupported number of channels, " diff --git a/libavformat/mpc.c b/libavformat/mpc.c index b5b2bab33..ef16237ab 100644 --- a/libavformat/mpc.c +++ b/libavformat/mpc.c @@ -22,6 +22,7 @@ #include "libavutil/channel_layout.h" #include "avformat.h" +#include "demux.h" #include "internal.h" #include "apetag.h" #include "id3v1.h" @@ -95,8 +96,7 @@ static int mpc_read_header(AVFormatContext *s) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_MUSEPACK7; - st->codecpar->channels = 2; - st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; st->codecpar->bits_per_coded_sample = 16; if ((ret = ff_get_extradata(s, st->codecpar, s->pb, 16)) < 0) diff --git a/libavformat/mpc8.c b/libavformat/mpc8.c index 0cf46b36a..2822a08b5 100644 --- a/libavformat/mpc8.c +++ b/libavformat/mpc8.c @@ -23,6 +23,7 @@ #include "libavcodec/unary.h" #include "apetag.h" #include "avformat.h" +#include "demux.h" #include "internal.h" #include "avio_internal.h" @@ -230,6 +231,7 @@ static int mpc8_read_header(AVFormatContext *s) AVIOContext *pb = s->pb; AVStream *st; int tag = 0, ret; + int channels; int64_t size, pos; c->header_pos = avio_tell(pb); @@ -273,7 +275,8 @@ static int mpc8_read_header(AVFormatContext *s) if ((ret = ff_get_extradata(s, st->codecpar, pb, 2)) < 0) return ret; - st->codecpar->channels = (st->codecpar->extradata[1] >> 4) + 1; + channels = (st->codecpar->extradata[1] >> 4) + 1; + st->codecpar->ch_layout.nb_channels = channels; st->codecpar->sample_rate = mpc8_rate[st->codecpar->extradata[0] >> 5]; avpriv_set_pts_info(st, 64, 1152 << (st->codecpar->extradata[1]&3)*2, st->codecpar->sample_rate); st->start_time = 0; diff --git a/libavformat/mpeg.c b/libavformat/mpeg.c index ca15d9f24..864b08d8f 100644 --- a/libavformat/mpeg.c +++ b/libavformat/mpeg.c @@ -19,9 +19,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/channel_layout.h" #include "avformat.h" #include "avio_internal.h" +#include "demux.h" #include "internal.h" #include "mpeg.h" @@ -621,8 +624,7 @@ skip: st->codecpar->codec_id = codec_id; if ( st->codecpar->codec_id == AV_CODEC_ID_PCM_MULAW || st->codecpar->codec_id == AV_CODEC_ID_PCM_ALAW) { - st->codecpar->channels = 1; - st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; st->codecpar->sample_rate = 8000; } sti->request_probe = request_probe; diff --git a/libavformat/mpegenc.c b/libavformat/mpegenc.c index b1d8bf9c3..3ab4bd3f9 100644 --- a/libavformat/mpegenc.c +++ b/libavformat/mpegenc.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include #include "libavutil/attributes.h" @@ -45,7 +47,7 @@ typedef struct PacketDesc { } PacketDesc; typedef struct StreamInfo { - AVFifoBuffer *fifo; + AVFifo *fifo; uint8_t id; int max_buffer_size; /* in bytes */ int buffer_index; @@ -380,14 +382,14 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx) av_log(ctx, AV_LOG_INFO, "\n"); return AVERROR(EINVAL); } - if (st->codecpar->channels > 8) { + if (st->codecpar->ch_layout.nb_channels > 8) { av_log(ctx, AV_LOG_ERROR, "At most 8 channels allowed for LPCM streams.\n"); return AVERROR(EINVAL); } stream->lpcm_header[0] = 0x0c; - stream->lpcm_header[1] = (st->codecpar->channels - 1) | (j << 4); + stream->lpcm_header[1] = (st->codecpar->ch_layout.nb_channels - 1) | (j << 4); stream->lpcm_header[2] = 0x80; - stream->lpcm_align = st->codecpar->channels * 2; + stream->lpcm_align = st->codecpar->ch_layout.nb_channels * 2; } else if (st->codecpar->codec_id == AV_CODEC_ID_PCM_DVD) { int freq; @@ -404,10 +406,10 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx) stream->lpcm_header[0] = 0x0c; stream->lpcm_header[1] = (freq << 4) | (((st->codecpar->bits_per_coded_sample - 16) / 4) << 6) | - st->codecpar->channels - 1; + st->codecpar->ch_layout.nb_channels - 1; stream->lpcm_header[2] = 0x80; stream->id = lpcm_id++; - stream->lpcm_align = st->codecpar->channels * st->codecpar->bits_per_coded_sample / 8; + stream->lpcm_align = st->codecpar->ch_layout.nb_channels * st->codecpar->bits_per_coded_sample / 8; } else if (st->codecpar->codec_id == AV_CODEC_ID_MLP || st->codecpar->codec_id == AV_CODEC_ID_TRUEHD) { av_log(ctx, AV_LOG_ERROR, "Support for muxing audio codec %s not implemented.\n", @@ -459,7 +461,7 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx) av_get_media_type_string(st->codecpar->codec_type), i); return AVERROR(EINVAL); } - stream->fifo = av_fifo_alloc(16); + stream->fifo = av_fifo_alloc2(16, 1, 0); if (!stream->fifo) return AVERROR(ENOMEM); } @@ -626,6 +628,12 @@ static int get_nb_frames(AVFormatContext *ctx, StreamInfo *stream, int len) return nb_frames; } +static int fifo_avio_wrapper(void *opaque, void *buf, size_t *nb_elems) +{ + avio_write(opaque, buf, *nb_elems); + return 0; +} + /* flush the packet on stream stream_index */ static int flush_packet(AVFormatContext *ctx, int stream_index, int64_t pts, int64_t dts, int64_t scr, int trailer_size) @@ -741,6 +749,7 @@ static int flush_packet(AVFormatContext *ctx, int stream_index, packet_size -= pad_packet_bytes + zero_trail_bytes; if (packet_size > 0) { + size_t fifo_data; /* packet header size */ packet_size -= 6; @@ -776,7 +785,7 @@ static int flush_packet(AVFormatContext *ctx, int stream_index, startcode = 0x100 + id; } - stuffing_size = payload_size - av_fifo_size(stream->fifo); + stuffing_size = payload_size - av_fifo_can_read(stream->fifo); // first byte does not fit -> reset pts/dts + stuffing if (payload_size <= trailer_size && pts != AV_NOPTS_VALUE) { @@ -814,7 +823,7 @@ static int flush_packet(AVFormatContext *ctx, int stream_index, stuffing_size = 0; if (startcode == PRIVATE_STREAM_1 && id >= 0xa0) { - if (payload_size < av_fifo_size(stream->fifo)) + if (payload_size < av_fifo_can_read(stream->fifo)) stuffing_size += payload_size % stream->lpcm_align; } @@ -907,11 +916,10 @@ static int flush_packet(AVFormatContext *ctx, int stream_index, } /* output data */ - av_assert0(payload_size - stuffing_size <= av_fifo_size(stream->fifo)); - av_fifo_generic_read(stream->fifo, ctx->pb, - payload_size - stuffing_size, - (void (*)(void*, void*, int))avio_write); - stream->bytes_to_iframe -= payload_size - stuffing_size; + fifo_data = payload_size - stuffing_size; + av_assert0(fifo_data <= av_fifo_can_read(stream->fifo)); + av_fifo_read_to_cb(stream->fifo, fifo_avio_wrapper, ctx->pb, &fifo_data); + stream->bytes_to_iframe -= fifo_data; } else { payload_size = stuffing_size = 0; @@ -1005,7 +1013,7 @@ retry: for (i = 0; i < ctx->nb_streams; i++) { AVStream *st = ctx->streams[i]; StreamInfo *stream = st->priv_data; - const int avail_data = av_fifo_size(stream->fifo); + const size_t avail_data = av_fifo_can_read(stream->fifo); const int space = stream->max_buffer_size - stream->buffer_index; int rel_space = 1024LL * space / stream->max_buffer_size; PacketDesc *next_pkt = stream->premux_packet; @@ -1075,7 +1083,7 @@ retry: st = ctx->streams[best_i]; stream = st->priv_data; - av_assert0(av_fifo_size(stream->fifo) > 0); + av_assert0(av_fifo_can_read(stream->fifo) > 0); av_assert0(avail_space >= s->packet_size || ignore_constraints); @@ -1095,7 +1103,7 @@ retry: es_size = flush_packet(ctx, best_i, timestamp_packet->pts, timestamp_packet->dts, scr, trailer_size); } else { - av_assert0(av_fifo_size(stream->fifo) == trailer_size); + av_assert0(av_fifo_can_read(stream->fifo) == trailer_size); es_size = flush_packet(ctx, best_i, AV_NOPTS_VALUE, AV_NOPTS_VALUE, scr, trailer_size); } @@ -1137,13 +1145,14 @@ static int mpeg_mux_write_packet(AVFormatContext *ctx, AVPacket *pkt) { int stream_index = pkt->stream_index; int size = pkt->size; - uint8_t *buf = pkt->data; + const uint8_t *buf = pkt->data; MpegMuxContext *s = ctx->priv_data; AVStream *st = ctx->streams[stream_index]; StreamInfo *stream = st->priv_data; int64_t pts, dts; PacketDesc *pkt_desc; int preload, ret; + size_t can_write; const int is_iframe = st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && (pkt->flags & AV_PKT_FLAG_KEY); @@ -1184,6 +1193,14 @@ static int mpeg_mux_write_packet(AVFormatContext *ctx, AVPacket *pkt) size -= 3; } + /* Enlarge the FIFO before adding a new PacketDesc + * in order to avoid inconsistencies on failure. */ + can_write = av_fifo_can_write(stream->fifo); + if (can_write < size) { + ret = av_fifo_grow2(stream->fifo, size - can_write); + if (ret < 0) + return ret; + } pkt_desc = av_mallocz(sizeof(PacketDesc)); if (!pkt_desc) return AVERROR(ENOMEM); @@ -1199,22 +1216,18 @@ static int mpeg_mux_write_packet(AVFormatContext *ctx, AVPacket *pkt) pkt_desc->unwritten_size = pkt_desc->size = size; - ret = av_fifo_realloc2(stream->fifo, av_fifo_size(stream->fifo) + size); - if (ret < 0) - return ret; - if (s->is_dvd) { // min VOBU length 0.4 seconds (mpucoder) if (is_iframe && (s->packet_number == 0 || pts != AV_NOPTS_VALUE && (pts - stream->vobu_start_pts >= 36000))) { - stream->bytes_to_iframe = av_fifo_size(stream->fifo); + stream->bytes_to_iframe = av_fifo_can_read(stream->fifo); stream->align_iframe = 1; stream->vobu_start_pts = pts; } } - av_fifo_generic_write(stream->fifo, buf, size, NULL); + av_fifo_write(stream->fifo, buf, size); for (;;) { int ret = output_packet(ctx, 0); @@ -1244,7 +1257,7 @@ static int mpeg_mux_end(AVFormatContext *ctx) for (i = 0; i < ctx->nb_streams; i++) { stream = ctx->streams[i]->priv_data; - av_assert0(av_fifo_size(stream->fifo) == 0); + av_assert0(av_fifo_can_read(stream->fifo) == 0); } return 0; } @@ -1260,7 +1273,7 @@ static void mpeg_mux_deinit(AVFormatContext *ctx) av_free(pkt); pkt = tmp; } - av_fifo_freep(&stream->fifo); + av_fifo_freep2(&stream->fifo); } } diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index 2479cb6f7..8a3436f2b 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/buffer.h" #include "libavutil/common.h" #include "libavutil/crc.h" @@ -37,6 +39,7 @@ #include "mpegts.h" #include "internal.h" #include "avio_internal.h" +#include "demux.h" #include "mpeg.h" #include "isom.h" #if CONFIG_ICONV @@ -47,8 +50,6 @@ * synchronization is lost */ #define MAX_RESYNC_SIZE 65536 -#define MAX_PES_PAYLOAD 200 * 1024 - #define MAX_MP4_DESCR_COUNT 16 #define MOD_UNLIKELY(modulus, dividend, divisor, prev_dividend) \ @@ -162,6 +163,7 @@ struct MpegTSContext { int resync_size; int merge_pmt_versions; + int max_packet_size; /******************************************/ /* private mpegts data */ @@ -198,6 +200,8 @@ static const AVOption options[] = { {.i64 = 0}, 0, 1, 0 }, {"skip_clear", "skip clearing programs", offsetof(MpegTSContext, skip_clear), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, 0 }, + {"max_packet_size", "maximum size of emitted packet", offsetof(MpegTSContext, max_packet_size), AV_OPT_TYPE_INT, + {.i64 = 204800}, 1, INT_MAX/2, AV_OPT_FLAG_DECODING_PARAM }, { NULL }, }; @@ -642,6 +646,7 @@ typedef struct SectionHeader { uint8_t tid; uint16_t id; uint8_t version; + uint8_t current_next; uint8_t sec_num; uint8_t last_sec_num; } SectionHeader; @@ -770,6 +775,7 @@ static int parse_section_header(SectionHeader *h, if (val < 0) return val; h->version = (val >> 1) & 0x1f; + h->current_next = val & 0x01; val = get8(pp, p_end); if (val < 0) return val; @@ -1121,7 +1127,7 @@ static AVBufferRef *buffer_pool_get(MpegTSContext *ts, int size) { int index = av_log2(size + AV_INPUT_BUFFER_PADDING_SIZE); if (!ts->pools[index]) { - int pool_size = FFMIN(MAX_PES_PAYLOAD + AV_INPUT_BUFFER_PADDING_SIZE, 2 << index); + int pool_size = FFMIN(ts->max_packet_size + AV_INPUT_BUFFER_PADDING_SIZE, 2 << index); ts->pools[index] = av_buffer_pool_init(pool_size, NULL); if (!ts->pools[index]) return NULL; @@ -1368,7 +1374,7 @@ skip: break; case MPEGTS_PAYLOAD: do { - int max_packet_size = MAX_PES_PAYLOAD; + int max_packet_size = ts->max_packet_size; if (pes->PES_packet_length && pes->PES_packet_length + PES_START_SIZE > pes->pes_header_size) max_packet_size = pes->PES_packet_length + PES_START_SIZE - pes->pes_header_size; @@ -1378,7 +1384,7 @@ skip: if (ret < 0) return ret; pes->PES_packet_length = 0; - max_packet_size = MAX_PES_PAYLOAD; + max_packet_size = ts->max_packet_size; ts->stop_parse = 1; } else if (pes->data_index == 0 && buf_size > max_packet_size) { @@ -2329,6 +2335,8 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len return; if (h->tid != PMT_TID) return; + if (!h->current_next) + return; if (skip_identical(h, tssf)) return; @@ -2538,6 +2546,8 @@ static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len return; if (h->tid != PAT_TID) return; + if (!h->current_next) + return; if (ts->skip_changes) return; @@ -2676,6 +2686,8 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len return; if (h->tid != SDT_TID) return; + if (!h->current_next) + return; if (ts->skip_changes) return; if (skip_identical(h, tssf)) @@ -2715,13 +2727,13 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len switch (desc_tag) { case 0x48: - service_type = get8(&p, p_end); + service_type = get8(&p, desc_end); if (service_type < 0) break; - provider_name = getstr8(&p, p_end); + provider_name = getstr8(&p, desc_end); if (!provider_name) break; - name = getstr8(&p, p_end); + name = getstr8(&p, desc_end); if (name) { AVProgram *program = av_new_program(ts->stream, sid); if (program) { @@ -2858,16 +2870,8 @@ static int handle_packet(MpegTSContext *ts, const uint8_t *packet, int64_t pos) break; } if (i == ts->nb_prg && ts->nb_prg > 0) { - int types = 0; - for (i = 0; i < ts->stream->nb_streams; i++) { - AVStream *st = ts->stream->streams[i]; - if (st->codecpar->codec_type >= 0) - types |= 1<codecpar->codec_type; - } - if ((types & (1< 100000) { - av_log(ts->stream, AV_LOG_DEBUG, "All programs have pmt, headers found\n"); - ts->stream->ctx_flags &= ~AVFMTCTX_NOHEADER; - } + av_log(ts->stream, AV_LOG_DEBUG, "All programs have pmt, headers found\n"); + ts->stream->ctx_flags &= ~AVFMTCTX_NOHEADER; } } @@ -3376,6 +3380,7 @@ MpegTSContext *avpriv_mpegts_parse_open(AVFormatContext *s) return NULL; /* no stream case, currently used by RTP */ ts->raw_packet_size = TS_PACKET_SIZE; + ts->max_packet_size = 2048000; ts->stream = s; ts->auto_guess = 1; diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c index 92b4cc808..c964d58c8 100644 --- a/libavformat/mpegtsenc.c +++ b/libavformat/mpegtsenc.c @@ -28,12 +28,13 @@ #include "libavutil/opt.h" #include "libavcodec/ac3_parser_internal.h" -#include "libavcodec/internal.h" +#include "libavcodec/startcode.h" #include "avformat.h" #include "avio_internal.h" #include "internal.h" #include "mpegts.h" +#include "mux.h" #define PCR_TIME_BASE 27000000 @@ -466,7 +467,7 @@ static int get_m2ts_stream_type(AVFormatContext *s, AVStream *st) stream_type = 0x81; break; case AV_CODEC_ID_DTS: - stream_type = (st->codecpar->channels > 6) ? 0x85 : 0x82; + stream_type = (st->codecpar->ch_layout.nb_channels > 6) ? 0x85 : 0x82; break; case AV_CODEC_ID_TRUEHD: stream_type = 0x83; @@ -592,6 +593,8 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service) if (codec_id == AV_CODEC_ID_S302M) put_registration_descriptor(&q, MKTAG('B', 'S', 'S', 'D')); if (codec_id == AV_CODEC_ID_OPUS) { + int ch = st->codecpar->ch_layout.nb_channels; + /* 6 bytes registration descriptor, 4 bytes Opus audio descriptor */ if (q - data > SECTION_LENGTH - 6 - 4) { err = 1; @@ -605,11 +608,11 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service) *q++ = 0x80; if (st->codecpar->extradata && st->codecpar->extradata_size >= 19) { - if (st->codecpar->extradata[18] == 0 && st->codecpar->channels <= 2) { + if (st->codecpar->extradata[18] == 0 && ch <= 2) { /* RTP mapping family */ - *q++ = st->codecpar->channels; - } else if (st->codecpar->extradata[18] == 1 && st->codecpar->channels <= 8 && - st->codecpar->extradata_size >= 21 + st->codecpar->channels) { + *q++ = ch; + } else if (st->codecpar->extradata[18] == 1 && ch <= 8 && + st->codecpar->extradata_size >= 21 + ch) { static const uint8_t coupled_stream_counts[9] = { 1, 0, 1, 1, 2, 2, 2, 3, 3 }; @@ -635,14 +638,14 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service) }; /* Vorbis mapping family */ - if (st->codecpar->extradata[19] == st->codecpar->channels - coupled_stream_counts[st->codecpar->channels] && - st->codecpar->extradata[20] == coupled_stream_counts[st->codecpar->channels] && - memcmp(&st->codecpar->extradata[21], channel_map_a[st->codecpar->channels-1], st->codecpar->channels) == 0) { - *q++ = st->codecpar->channels; - } else if (st->codecpar->channels >= 2 && st->codecpar->extradata[19] == st->codecpar->channels && + if (st->codecpar->extradata[19] == ch - coupled_stream_counts[ch] && + st->codecpar->extradata[20] == coupled_stream_counts[ch] && + memcmp(&st->codecpar->extradata[21], channel_map_a[ch - 1], ch) == 0) { + *q++ = ch; + } else if (ch >= 2 && st->codecpar->extradata[19] == ch && st->codecpar->extradata[20] == 0 && - memcmp(&st->codecpar->extradata[21], channel_map_b[st->codecpar->channels-1], st->codecpar->channels) == 0) { - *q++ = st->codecpar->channels | 0x80; + memcmp(&st->codecpar->extradata[21], channel_map_b[ch - 1], ch) == 0) { + *q++ = ch | 0x80; } else { /* Unsupported, could write an extended descriptor here */ av_log(s, AV_LOG_ERROR, "Unsupported Opus Vorbis-style channel mapping"); @@ -653,9 +656,9 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service) av_log(s, AV_LOG_ERROR, "Unsupported Opus channel mapping for family %d", st->codecpar->extradata[18]); *q++ = 0xff; } - } else if (st->codecpar->channels <= 2) { + } else if (ch <= 2) { /* Assume RTP mapping family */ - *q++ = st->codecpar->channels; + *q++ = ch; } else { /* Unsupported */ av_log(s, AV_LOG_ERROR, "Unsupported Opus channel mapping"); @@ -1833,7 +1836,7 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt) { AVStream *st = s->streams[pkt->stream_index]; int size = pkt->size; - uint8_t *buf = pkt->data; + const uint8_t *buf = pkt->data; uint8_t *data = NULL; MpegTSWrite *ts = s->priv_data; MpegTSWriteStream *ts_st = st->priv_data; @@ -2097,6 +2100,10 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt) ts_st->dvb_ac3_desc = dvb_ac3_desc; } av_free(hdr); + } else if (st->codecpar->codec_id == AV_CODEC_ID_PCM_BLURAY && ts->m2ts_mode) { + mpegts_write_pes(s, st, buf, size, pts, dts, + pkt->flags & AV_PKT_FLAG_KEY, stream_id); + return 0; } if (ts_st->payload_size && (ts_st->payload_size + size > ts->pes_payload_size || diff --git a/libavformat/mpegvideodec.c b/libavformat/mpegvideodec.c index 2d6f81aaa..33c5d7979 100644 --- a/libavformat/mpegvideodec.c +++ b/libavformat/mpegvideodec.c @@ -24,7 +24,7 @@ #include "rawdec.h" #include "libavutil/intreadwrite.h" -#include "libavcodec/internal.h" +#include "libavcodec/startcode.h" #define SEQ_START_CODE 0x000001b3 #define GOP_START_CODE 0x000001b8 diff --git a/libavformat/msf.c b/libavformat/msf.c index 98a7ca11c..354758971 100644 --- a/libavformat/msf.c +++ b/libavformat/msf.c @@ -54,8 +54,9 @@ static int msf_read_header(AVFormatContext *s) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; codec = avio_rb32(s->pb); - st->codecpar->channels = avio_rb32(s->pb); - if (st->codecpar->channels <= 0 || st->codecpar->channels >= INT_MAX / 1024) + st->codecpar->ch_layout.nb_channels = avio_rb32(s->pb); + if (st->codecpar->ch_layout.nb_channels <= 0 || + st->codecpar->ch_layout.nb_channels >= INT_MAX / 1024) return AVERROR_INVALIDDATA; size = avio_rb32(s->pb); st->codecpar->sample_rate = avio_rb32(s->pb); @@ -65,19 +66,19 @@ static int msf_read_header(AVFormatContext *s) switch (codec) { case 0: st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE; break; case 1: st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE; break; - case 3: st->codecpar->block_align = 16 * st->codecpar->channels; + case 3: st->codecpar->block_align = 16 * st->codecpar->ch_layout.nb_channels; st->codecpar->codec_id = AV_CODEC_ID_ADPCM_PSX; break; case 4: case 5: - case 6: st->codecpar->block_align = (codec == 4 ? 96 : codec == 5 ? 152 : 192) * st->codecpar->channels; - if (st->codecpar->channels > UINT16_MAX / 2048) + case 6: st->codecpar->block_align = (codec == 4 ? 96 : codec == 5 ? 152 : 192) * st->codecpar->ch_layout.nb_channels; + if (st->codecpar->ch_layout.nb_channels > UINT16_MAX / 2048) return AVERROR_INVALIDDATA; ret = ff_alloc_extradata(st->codecpar, 14); if (ret < 0) return ret; memset(st->codecpar->extradata, 0, st->codecpar->extradata_size); AV_WL16(st->codecpar->extradata, 1); /* version */ - AV_WL16(st->codecpar->extradata+2, 2048 * st->codecpar->channels); /* unknown size */ + AV_WL16(st->codecpar->extradata+2, 2048 * st->codecpar->ch_layout.nb_channels); /* unknown size */ AV_WL16(st->codecpar->extradata+6, codec == 4 ? 1 : 0); /* joint stereo */ AV_WL16(st->codecpar->extradata+8, codec == 4 ? 1 : 0); /* joint stereo (repeat?) */ AV_WL16(st->codecpar->extradata+10, 1); @@ -99,7 +100,7 @@ static int msf_read_packet(AVFormatContext *s, AVPacket *pkt) { AVCodecParameters *par = s->streams[0]->codecpar; - return av_get_packet(s->pb, pkt, par->block_align ? par->block_align : 1024 * par->channels); + return av_get_packet(s->pb, pkt, par->block_align ? par->block_align : 1024 * par->ch_layout.nb_channels); } const AVInputFormat ff_msf_demuxer = { diff --git a/libavformat/mtaf.c b/libavformat/mtaf.c index 5da82e713..954ffaa8b 100644 --- a/libavformat/mtaf.c +++ b/libavformat/mtaf.c @@ -54,9 +54,9 @@ static int mtaf_read_header(AVFormatContext *s) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_ADPCM_MTAF; - st->codecpar->channels = 2 * stream_count; + st->codecpar->ch_layout.nb_channels = 2 * stream_count; st->codecpar->sample_rate = 48000; - st->codecpar->block_align = 0x110 * st->codecpar->channels / 2; + st->codecpar->block_align = 0x110 * st->codecpar->ch_layout.nb_channels / 2; avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); avio_seek(s->pb, 0x800, SEEK_SET); diff --git a/libavformat/musx.c b/libavformat/musx.c index fd5a9297f..5bf793f88 100644 --- a/libavformat/musx.c +++ b/libavformat/musx.c @@ -68,30 +68,30 @@ static int musx_read_header(AVFormatContext *s) offset = avio_rl32(s->pb); st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_ADPCM_PSX; - st->codecpar->channels = 2; + st->codecpar->ch_layout.nb_channels = 2; st->codecpar->sample_rate = 32000; - st->codecpar->block_align = 0x80 * st->codecpar->channels; + st->codecpar->block_align = 0x80 * st->codecpar->ch_layout.nb_channels; } else if (version == 10) { type = avio_rl32(s->pb); st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; offset = 0x800; switch (type) { case MKTAG('P', 'S', '3', '_'): - st->codecpar->channels = 2; + st->codecpar->ch_layout.nb_channels = 2; st->codecpar->sample_rate = 44100; avio_skip(s->pb, 44); coding = avio_rl32(s->pb); if (coding == MKTAG('D', 'A', 'T', '4') || coding == MKTAG('D', 'A', 'T', '8')) { avio_skip(s->pb, 4); - st->codecpar->channels = avio_rl32(s->pb); - if (st->codecpar->channels <= 0 || - st->codecpar->channels > INT_MAX / 0x20) + st->codecpar->ch_layout.nb_channels = avio_rl32(s->pb); + if (st->codecpar->ch_layout.nb_channels <= 0 || + st->codecpar->ch_layout.nb_channels > INT_MAX / 0x20) return AVERROR_INVALIDDATA; st->codecpar->sample_rate = avio_rl32(s->pb); } st->codecpar->codec_id = AV_CODEC_ID_ADPCM_IMA_DAT4; - st->codecpar->block_align = 0x20 * st->codecpar->channels; + st->codecpar->block_align = 0x20 * st->codecpar->ch_layout.nb_channels; break; case MKTAG('W', 'I', 'I', '_'): avio_skip(s->pb, 44); @@ -103,30 +103,30 @@ static int musx_read_header(AVFormatContext *s) } avio_skip(s->pb, 4); st->codecpar->codec_id = AV_CODEC_ID_ADPCM_IMA_DAT4; - st->codecpar->channels = avio_rl32(s->pb); - if (st->codecpar->channels <= 0 || - st->codecpar->channels > INT_MAX / 0x20) + st->codecpar->ch_layout.nb_channels = avio_rl32(s->pb); + if (st->codecpar->ch_layout.nb_channels <= 0 || + st->codecpar->ch_layout.nb_channels > INT_MAX / 0x20) return AVERROR_INVALIDDATA; st->codecpar->sample_rate = avio_rl32(s->pb); - st->codecpar->block_align = 0x20 * st->codecpar->channels; + st->codecpar->block_align = 0x20 * st->codecpar->ch_layout.nb_channels; break; case MKTAG('X', 'E', '_', '_'): st->codecpar->codec_id = AV_CODEC_ID_ADPCM_IMA_DAT4; - st->codecpar->channels = 2; + st->codecpar->ch_layout.nb_channels = 2; st->codecpar->sample_rate = 32000; - st->codecpar->block_align = 0x20 * st->codecpar->channels; + st->codecpar->block_align = 0x20 * st->codecpar->ch_layout.nb_channels; break; case MKTAG('P', 'S', 'P', '_'): st->codecpar->codec_id = AV_CODEC_ID_ADPCM_PSX; - st->codecpar->channels = 2; + st->codecpar->ch_layout.nb_channels = 2; st->codecpar->sample_rate = 32768; - st->codecpar->block_align = 0x80 * st->codecpar->channels; + st->codecpar->block_align = 0x80 * st->codecpar->ch_layout.nb_channels; break; case MKTAG('P', 'S', '2', '_'): st->codecpar->codec_id = AV_CODEC_ID_ADPCM_PSX; - st->codecpar->channels = 2; + st->codecpar->ch_layout.nb_channels = 2; st->codecpar->sample_rate = 32000; - st->codecpar->block_align = 0x80 * st->codecpar->channels; + st->codecpar->block_align = 0x80 * st->codecpar->ch_layout.nb_channels; break; default: avpriv_request_sample(s, "Unsupported type: %X", type); @@ -136,23 +136,23 @@ static int musx_read_header(AVFormatContext *s) type = avio_rl32(s->pb); avio_skip(s->pb, 20); st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; - st->codecpar->channels = 2; + st->codecpar->ch_layout.nb_channels = 2; switch (type) { case MKTAG('G', 'C', '_', '_'): st->codecpar->codec_id = AV_CODEC_ID_ADPCM_IMA_DAT4; - st->codecpar->block_align = 0x20 * st->codecpar->channels; + st->codecpar->block_align = 0x20 * st->codecpar->ch_layout.nb_channels; st->codecpar->sample_rate = 32000; offset = avio_rb32(s->pb); break; case MKTAG('P', 'S', '2', '_'): st->codecpar->codec_id = AV_CODEC_ID_ADPCM_PSX; - st->codecpar->block_align = 0x80 * st->codecpar->channels; + st->codecpar->block_align = 0x80 * st->codecpar->ch_layout.nb_channels; st->codecpar->sample_rate = 32000; offset = avio_rl32(s->pb); break; case MKTAG('X', 'B', '_', '_'): st->codecpar->codec_id = AV_CODEC_ID_ADPCM_IMA_DAT4; - st->codecpar->block_align = 0x20 * st->codecpar->channels; + st->codecpar->block_align = 0x20 * st->codecpar->ch_layout.nb_channels; st->codecpar->sample_rate = 44100; offset = avio_rl32(s->pb); break; diff --git a/libavformat/mux.c b/libavformat/mux.c index c387f8ec6..31361f9b4 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -21,15 +21,15 @@ #include "avformat.h" #include "internal.h" +#include "mux.h" +#include "version.h" #include "libavcodec/bsf.h" #include "libavcodec/internal.h" #include "libavcodec/packet_internal.h" #include "libavutil/opt.h" #include "libavutil/dict.h" -#include "libavutil/pixdesc.h" #include "libavutil/timestamp.h" #include "libavutil/avassert.h" -#include "libavutil/avstring.h" #include "libavutil/internal.h" #include "libavutil/mathematics.h" @@ -88,51 +88,6 @@ static void frac_add(FFFrac *f, int64_t incr) f->num = num; } -AVRational ff_choose_timebase(AVFormatContext *s, AVStream *st, int min_precision) -{ - AVRational q; - - q = st->time_base; - - for (int j = 2; j < 14; j += 1 + (j > 2)) - while (q.den / q.num < min_precision && q.num % j == 0) - q.num /= j; - while (q.den / q.num < min_precision && q.den < (1<<24)) - q.den <<= 1; - - return q; -} - -enum AVChromaLocation ff_choose_chroma_location(AVFormatContext *s, AVStream *st) -{ - AVCodecParameters *par = st->codecpar; - const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(par->format); - - if (par->chroma_location != AVCHROMA_LOC_UNSPECIFIED) - return par->chroma_location; - - if (pix_desc) { - if (pix_desc->log2_chroma_h == 0) { - return AVCHROMA_LOC_TOPLEFT; - } else if (pix_desc->log2_chroma_w == 1 && pix_desc->log2_chroma_h == 1) { - if (par->field_order == AV_FIELD_UNKNOWN || par->field_order == AV_FIELD_PROGRESSIVE) { - switch (par->codec_id) { - case AV_CODEC_ID_MJPEG: - case AV_CODEC_ID_MPEG1VIDEO: return AVCHROMA_LOC_CENTER; - } - } - if (par->field_order == AV_FIELD_UNKNOWN || par->field_order != AV_FIELD_PROGRESSIVE) { - switch (par->codec_id) { - case AV_CODEC_ID_MPEG2VIDEO: return AVCHROMA_LOC_LEFT; - } - } - } - } - - return AVCHROMA_LOC_UNSPECIFIED; - -} - int avformat_alloc_output_context2(AVFormatContext **avctx, const AVOutputFormat *oformat, const char *format, const char *filename) { @@ -272,8 +227,25 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options) ret = AVERROR(EINVAL); goto fail; } + +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + /* if the caller is using the deprecated channel layout API, + * convert it to the new style */ + if (!par->ch_layout.nb_channels && + par->channels) { + if (par->channel_layout) { + av_channel_layout_from_mask(&par->ch_layout, par->channel_layout); + } else { + par->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + par->ch_layout.nb_channels = par->channels; + } + } +FF_ENABLE_DEPRECATION_WARNINGS +#endif + if (!par->block_align) - par->block_align = par->channels * + par->block_align = par->ch_layout.nb_channels * av_get_bits_per_sample(par->codec_id) >> 3; break; case AVMEDIA_TYPE_VIDEO: @@ -388,6 +360,8 @@ fail: static int init_pts(AVFormatContext *s) { + FFFormatContext *const si = ffformatcontext(s); + /* init PTS generation */ for (unsigned i = 0; i < s->nb_streams; i++) { AVStream *const st = s->streams[i]; @@ -418,13 +392,16 @@ static int init_pts(AVFormatContext *s) } } + si->avoid_negative_ts_status = AVOID_NEGATIVE_TS_UNKNOWN; 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; + s->avoid_negative_ts = AVFMT_AVOID_NEG_TS_DISABLED; + si->avoid_negative_ts_status = AVOID_NEGATIVE_TS_DISABLED; } else s->avoid_negative_ts = AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE; - } + } else if (s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_DISABLED) + si->avoid_negative_ts_status = AVOID_NEGATIVE_TS_DISABLED; return 0; } @@ -638,6 +615,81 @@ static void guess_pkt_duration(AVFormatContext *s, AVStream *st, AVPacket *pkt) } } +static void handle_avoid_negative_ts(FFFormatContext *si, FFStream *sti, + AVPacket *pkt) +{ + AVFormatContext *const s = &si->pub; + int64_t offset; + + if (!AVOID_NEGATIVE_TS_ENABLED(si->avoid_negative_ts_status)) + return; + + if (si->avoid_negative_ts_status == AVOID_NEGATIVE_TS_UNKNOWN) { + int use_pts = si->avoid_negative_ts_use_pts; + int64_t ts = use_pts ? pkt->pts : pkt->dts; + AVRational tb = sti->pub.time_base; + + if (ts == AV_NOPTS_VALUE) + return; + + /* Peek into the muxing queue to improve our estimate + * of the lowest timestamp if av_interleaved_write_frame() is used. */ + for (const PacketListEntry *pktl = si->packet_buffer.head; + pktl; pktl = pktl->next) { + AVRational cmp_tb = s->streams[pktl->pkt.stream_index]->time_base; + int64_t cmp_ts = use_pts ? pktl->pkt.pts : pktl->pkt.dts; + if (cmp_ts == AV_NOPTS_VALUE) + continue; + if (s->output_ts_offset) + cmp_ts += av_rescale_q(s->output_ts_offset, AV_TIME_BASE_Q, cmp_tb); + if (av_compare_ts(cmp_ts, cmp_tb, ts, tb) < 0) { + ts = cmp_ts; + tb = cmp_tb; + } + } + + if (ts < 0 || + ts > 0 && s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO) { + for (unsigned i = 0; i < s->nb_streams; i++) { + AVStream *const st2 = s->streams[i]; + FFStream *const sti2 = ffstream(st2); + sti2->mux_ts_offset = av_rescale_q_rnd(-ts, tb, + st2->time_base, + AV_ROUND_UP); + } + } + si->avoid_negative_ts_status = AVOID_NEGATIVE_TS_KNOWN; + } + + offset = sti->mux_ts_offset; + + if (pkt->dts != AV_NOPTS_VALUE) + pkt->dts += offset; + if (pkt->pts != AV_NOPTS_VALUE) + pkt->pts += offset; + + if (si->avoid_negative_ts_use_pts) { + if (pkt->pts != AV_NOPTS_VALUE && pkt->pts < 0) { + av_log(s, AV_LOG_WARNING, "failed to avoid negative " + "pts %s in stream %d.\n" + "Try -avoid_negative_ts 1 as a possible workaround.\n", + av_ts2str(pkt->pts), + pkt->stream_index + ); + } + } else { + if (pkt->dts != AV_NOPTS_VALUE && pkt->dts < 0) { + av_log(s, AV_LOG_WARNING, + "Packets poorly interleaved, failed to avoid negative " + "timestamp %s in stream %d.\n" + "Try -max_interleave_delta 0 as a possible workaround.\n", + av_ts2str(pkt->dts), + pkt->stream_index + ); + } + } +} + /** * Shift timestamps and call muxer; the original pts/dts are not kept. * @@ -663,52 +715,7 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) if (pkt->pts != AV_NOPTS_VALUE) pkt->pts += offset; } - - if (s->avoid_negative_ts > 0) { - int64_t offset = sti->mux_ts_offset; - int64_t ts = si->avoid_negative_ts_use_pts ? pkt->pts : pkt->dts; - - if (si->offset == AV_NOPTS_VALUE && ts != AV_NOPTS_VALUE && - (ts < 0 || s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_MAKE_ZERO)) { - si->offset = -ts; - si->offset_timebase = st->time_base; - } - - if (si->offset != AV_NOPTS_VALUE && !offset) { - offset = sti->mux_ts_offset = - av_rescale_q_rnd(si->offset, - si->offset_timebase, - st->time_base, - AV_ROUND_UP); - } - - if (pkt->dts != AV_NOPTS_VALUE) - pkt->dts += offset; - if (pkt->pts != AV_NOPTS_VALUE) - pkt->pts += offset; - - if (si->avoid_negative_ts_use_pts) { - if (pkt->pts != AV_NOPTS_VALUE && pkt->pts < 0) { - av_log(s, AV_LOG_WARNING, "failed to avoid negative " - "pts %s in stream %d.\n" - "Try -avoid_negative_ts 1 as a possible workaround.\n", - av_ts2str(pkt->pts), - pkt->stream_index - ); - } - } else { - av_assert2(pkt->dts == AV_NOPTS_VALUE || pkt->dts >= 0 || s->max_interleave_delta > 0); - if (pkt->dts != AV_NOPTS_VALUE && pkt->dts < 0) { - av_log(s, AV_LOG_WARNING, - "Packets poorly interleaved, failed to avoid negative " - "timestamp %s in stream %d.\n" - "Try -max_interleave_delta 0 as a possible workaround.\n", - av_ts2str(pkt->dts), - pkt->stream_index - ); - } - } - } + handle_avoid_negative_ts(si, sti, pkt); if ((pkt->flags & AV_PKT_FLAG_UNCODED_FRAME)) { AVFrame **frame = (AVFrame **)pkt->data; @@ -1297,6 +1304,49 @@ int av_get_output_timestamp(struct AVFormatContext *s, int stream, return 0; } +int ff_stream_add_bitstream_filter(AVStream *st, const char *name, const char *args) +{ + int ret; + const AVBitStreamFilter *bsf; + FFStream *const sti = ffstream(st); + AVBSFContext *bsfc; + + av_assert0(!sti->bsfc); + + if (!(bsf = av_bsf_get_by_name(name))) { + av_log(NULL, AV_LOG_ERROR, "Unknown bitstream filter '%s'\n", name); + return AVERROR_BSF_NOT_FOUND; + } + + if ((ret = av_bsf_alloc(bsf, &bsfc)) < 0) + return ret; + + bsfc->time_base_in = st->time_base; + if ((ret = avcodec_parameters_copy(bsfc->par_in, st->codecpar)) < 0) { + av_bsf_free(&bsfc); + return ret; + } + + if (args && bsfc->filter->priv_class) { + if ((ret = av_set_options_string(bsfc->priv_data, args, "=", ":")) < 0) { + av_bsf_free(&bsfc); + return ret; + } + } + + if ((ret = av_bsf_init(bsfc)) < 0) { + av_bsf_free(&bsfc); + return ret; + } + + sti->bsfc = bsfc; + + av_log(NULL, AV_LOG_VERBOSE, + "Automatically inserted bitstream filter '%s'; args='%s'\n", + name, args ? args : ""); + return 1; +} + int ff_write_chained(AVFormatContext *dst, int dst_stream, AVPacket *pkt, AVFormatContext *src, int interleave) { diff --git a/libavformat/mux.h b/libavformat/mux.h new file mode 100644 index 000000000..c01da8219 --- /dev/null +++ b/libavformat/mux.h @@ -0,0 +1,145 @@ +/* + * 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_MUX_H +#define AVFORMAT_MUX_H + +#include +#include "libavcodec/packet.h" +#include "avformat.h" + +/** + * Add packet to an AVFormatContext's packet_buffer list, determining its + * interleaved position using compare() function argument. + * @return 0 on success, < 0 on error. pkt will always be blank on return. + */ +int ff_interleave_add_packet(AVFormatContext *s, AVPacket *pkt, + int (*compare)(AVFormatContext *, const AVPacket *, const AVPacket *)); + +/** + * Interleave an AVPacket per dts so it can be muxed. + * See the documentation of AVOutputFormat.interleave_packet for details. + */ +int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *pkt, + int flush, int has_packet); + +/** + * Interleave packets directly in the order in which they arrive + * without any sort of buffering. + */ +int ff_interleave_packet_passthrough(AVFormatContext *s, AVPacket *pkt, + int flush, int has_packet); + +/** + * Find the next packet in the interleaving queue for the given stream. + * + * @return a pointer to a packet if one was found, NULL otherwise. + */ +const AVPacket *ff_interleaved_peek(AVFormatContext *s, int stream); + +int ff_get_muxer_ts_offset(AVFormatContext *s, int stream_index, int64_t *offset); + +/** + * Add a bitstream filter to a stream. + * + * @param st output stream to add a filter to + * @param name the name of the filter to add + * @param args filter-specific argument string + * @return >0 on success; + * AVERROR code on failure + */ +int ff_stream_add_bitstream_filter(AVStream *st, const char *name, const char *args); + +/** + * Write a packet to another muxer than the one the user originally + * intended. Useful when chaining muxers, where one muxer internally + * writes a received packet to another muxer. + * + * @param dst the muxer to write the packet to + * @param dst_stream the stream index within dst to write the packet to + * @param pkt the packet to be written. It will be returned blank when + * av_interleaved_write_frame() is used, unchanged otherwise. + * @param src the muxer the packet originally was intended for + * @param interleave 0->use av_write_frame, 1->av_interleaved_write_frame + * @return the value av_write_frame returned + */ +int ff_write_chained(AVFormatContext *dst, int dst_stream, AVPacket *pkt, + AVFormatContext *src, int interleave); + +/** + * Flags for AVFormatContext.write_uncoded_frame() + */ +enum AVWriteUncodedFrameFlags { + + /** + * Query whether the feature is possible on this stream. + * The frame argument is ignored. + */ + AV_WRITE_UNCODED_FRAME_QUERY = 0x0001, + +}; + +/** + * Make shift_size amount of space at read_start by shifting data in the output + * at read_start until the current IO position. The underlying IO context must + * be seekable. + */ +int ff_format_shift_data(AVFormatContext *s, int64_t read_start, int shift_size); + +/** + * Utility function to open IO stream of output format. + * + * @param s AVFormatContext + * @param url URL or file name to open for writing + * @options optional options which will be passed to io_open callback + * @return >=0 on success, negative AVERROR in case of failure + */ +int ff_format_output_open(AVFormatContext *s, const char *url, AVDictionary **options); + +/** + * Copy encoding parameters from source to destination stream + * + * @param dst pointer to destination AVStream + * @param src pointer to source AVStream + * @return >=0 on success, AVERROR code on error + */ +int ff_stream_encode_params_copy(AVStream *dst, const AVStream *src); + +/** + * Parse creation_time in AVFormatContext metadata if exists and warn if the + * parsing fails. + * + * @param s AVFormatContext + * @param timestamp parsed timestamp in microseconds, only set on successful parsing + * @param return_seconds set this to get the number of seconds in timestamp instead of microseconds + * @return 1 if OK, 0 if the metadata was not present, AVERROR(EINVAL) on parse error + */ +int ff_parse_creation_time_metadata(AVFormatContext *s, int64_t *timestamp, int return_seconds); + +/** + * Standardize creation_time metadata in AVFormatContext to an ISO-8601 + * timestamp string. + * + * @param s AVFormatContext + * @return <0 on error + */ +int ff_standardize_creation_time(AVFormatContext *s); + +#endif /* AVFORMAT_MUX_H */ diff --git a/libavformat/mux_utils.c b/libavformat/mux_utils.c new file mode 100644 index 000000000..eb8ea3d56 --- /dev/null +++ b/libavformat/mux_utils.c @@ -0,0 +1,176 @@ +/* + * Various muxing utility functions + * 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 "libavutil/dict.h" +#include "libavutil/internal.h" +#include "libavutil/log.h" +#include "libavutil/mem.h" +#include "libavutil/parseutils.h" +#include "avformat.h" +#include "avio.h" +#include "internal.h" +#include "mux.h" + +int64_t av_stream_get_end_pts(const AVStream *st) +{ + if (cffstream(st)->priv_pts) { + return cffstream(st)->priv_pts->val; + } else + return AV_NOPTS_VALUE; +} + +int avformat_query_codec(const AVOutputFormat *ofmt, enum AVCodecID codec_id, + int std_compliance) +{ + if (ofmt) { + unsigned int codec_tag; + if (ofmt->query_codec) + return ofmt->query_codec(codec_id, std_compliance); + else if (ofmt->codec_tag) + return !!av_codec_get_tag2(ofmt->codec_tag, codec_id, &codec_tag); + else if (codec_id == ofmt->video_codec || + codec_id == ofmt->audio_codec || + codec_id == ofmt->subtitle_codec || + codec_id == ofmt->data_codec) + return 1; + } + return AVERROR_PATCHWELCOME; +} + +int ff_format_shift_data(AVFormatContext *s, int64_t read_start, int shift_size) +{ + int ret; + int64_t pos, pos_end; + uint8_t *buf, *read_buf[2]; + int read_buf_id = 0; + int read_size[2]; + AVIOContext *read_pb; + + buf = av_malloc_array(shift_size, 2); + if (!buf) + return AVERROR(ENOMEM); + read_buf[0] = buf; + read_buf[1] = buf + shift_size; + + /* Shift the data: the AVIO context of the output can only be used for + * 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->url, AVIO_FLAG_READ, NULL); + if (ret < 0) { + av_log(s, AV_LOG_ERROR, "Unable to re-open %s output file for shifting data\n", s->url); + goto end; + } + + /* mark the end of the shift to up to the last data we wrote, and get ready + * for writing */ + pos_end = avio_tell(s->pb); + avio_seek(s->pb, read_start + shift_size, SEEK_SET); + + avio_seek(read_pb, read_start, 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(s->pb, read_buf[read_buf_id], n); + pos += n; + } while (pos < pos_end); + ret = ff_format_io_close(s, &read_pb); + +end: + av_free(buf); + return ret; +} + +int ff_format_output_open(AVFormatContext *s, const char *url, AVDictionary **options) +{ + if (!s->oformat) + return AVERROR(EINVAL); + + if (!(s->oformat->flags & AVFMT_NOFILE)) + return s->io_open(s, &s->pb, url, AVIO_FLAG_WRITE, options); + return 0; +} + +int ff_stream_encode_params_copy(AVStream *dst, const AVStream *src) +{ + int ret; + + dst->id = src->id; + dst->time_base = src->time_base; + dst->nb_frames = src->nb_frames; + dst->disposition = src->disposition; + dst->sample_aspect_ratio = src->sample_aspect_ratio; + dst->avg_frame_rate = src->avg_frame_rate; + dst->r_frame_rate = src->r_frame_rate; + + av_dict_free(&dst->metadata); + ret = av_dict_copy(&dst->metadata, src->metadata, 0); + if (ret < 0) + return ret; + + ret = avcodec_parameters_copy(dst->codecpar, src->codecpar); + if (ret < 0) + return ret; + + ret = ff_stream_side_data_copy(dst, src); + if (ret < 0) + return ret; + + return 0; +} + +int ff_parse_creation_time_metadata(AVFormatContext *s, int64_t *timestamp, int return_seconds) +{ + AVDictionaryEntry *entry; + int64_t parsed_timestamp; + int ret; + if ((entry = av_dict_get(s->metadata, "creation_time", NULL, 0))) { + if ((ret = av_parse_time(&parsed_timestamp, entry->value, 0)) >= 0) { + *timestamp = return_seconds ? parsed_timestamp / 1000000 : parsed_timestamp; + return 1; + } else { + av_log(s, AV_LOG_WARNING, "Failed to parse creation_time %s\n", entry->value); + return ret; + } + } + return 0; +} + +int ff_standardize_creation_time(AVFormatContext *s) +{ + int64_t timestamp; + int ret = ff_parse_creation_time_metadata(s, ×tamp, 0); + if (ret == 1) + return avpriv_dict_set_timestamp(&s->metadata, "creation_time", timestamp); + return ret; +} diff --git a/libavformat/mvdec.c b/libavformat/mvdec.c index ea955d2b1..b37fe2ce6 100644 --- a/libavformat/mvdec.c +++ b/libavformat/mvdec.c @@ -45,6 +45,10 @@ typedef struct MvContext { int aformat; ///< audio format } MvContext; +/* these magic numbers are defined in moviefile.h on Silicon Grahpics IRIX */ +#define MOVIE_SOUND 1 +#define MOVIE_SILENT 2 + #define AUDIO_FORMAT_SIGNED 401 static int mv_probe(const AVProbeData *p) @@ -107,9 +111,7 @@ static int set_channels(AVFormatContext *avctx, AVStream *st, int channels) av_log(avctx, AV_LOG_ERROR, "Channel count %d invalid.\n", channels); return AVERROR_INVALIDDATA; } - st->codecpar->channels = channels; - st->codecpar->channel_layout = (st->codecpar->channels == 1) ? AV_CH_LAYOUT_MONO - : AV_CH_LAYOUT_STEREO; + av_channel_layout_default(&st->codecpar->ch_layout, channels); return 0; } @@ -279,7 +281,7 @@ static void read_index(AVIOContext *pb, AVStream *st) return ; av_add_index_entry(st, pos, timestamp, size, 0, AVINDEX_KEYFRAME); if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { - timestamp += size / (st->codecpar->channels * 2LL); + timestamp += size / (st->codecpar->ch_layout.nb_channels * 2LL); } else { timestamp++; } @@ -305,18 +307,25 @@ static int mv_read_header(AVFormatContext *avctx) avio_skip(pb, 10); + fps = av_d2q(av_int2double(avio_rb64(pb)), INT_MAX); + /* allocate audio track first to prevent unnecessary seeking * (audio packet always precede video packet for a given frame) */ - ast = avformat_new_stream(avctx, NULL); - if (!ast) - return AVERROR(ENOMEM); + v = avio_rb16(pb); + if (v == MOVIE_SOUND) { + /* movie has sound so allocate an audio stream */ + ast = avformat_new_stream(avctx, NULL); + if (!ast) + return AVERROR(ENOMEM); + } else if (v != MOVIE_SILENT) + return AVERROR_INVALIDDATA; + + avio_skip(pb, 2); vst = avformat_new_stream(avctx, NULL); if (!vst) return AVERROR(ENOMEM); - fps = av_d2q(av_int2double(avio_rb64(pb)), INT_MAX); avpriv_set_pts_info(vst, 64, fps.den, fps.num); - avio_skip(pb, 4); vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; vst->avg_frame_rate = fps; vst->duration = vst->nb_frames = avio_rb32(pb); @@ -338,41 +347,44 @@ static int mv_read_header(AVFormatContext *avctx) vst->codecpar->height = avio_rb32(pb); avio_skip(pb, 12); - ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; - ast->nb_frames = vst->nb_frames; - ast->codecpar->sample_rate = avio_rb32(pb); - if (ast->codecpar->sample_rate <= 0) { - av_log(avctx, AV_LOG_ERROR, "Invalid sample rate %d\n", ast->codecpar->sample_rate); - return AVERROR_INVALIDDATA; - } - avpriv_set_pts_info(ast, 33, 1, ast->codecpar->sample_rate); - - bytes_per_sample = avio_rb32(pb); - - v = avio_rb32(pb); - if (v == AUDIO_FORMAT_SIGNED) { - switch (bytes_per_sample) { - case 1: - ast->codecpar->codec_id = AV_CODEC_ID_PCM_S8; - break; - case 2: - ast->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE; - break; - default: - avpriv_request_sample(avctx, "Audio sample size %i bytes", bytes_per_sample); - break; + if (ast) { + ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; + ast->nb_frames = vst->nb_frames; + ast->codecpar->sample_rate = avio_rb32(pb); + if (ast->codecpar->sample_rate <= 0) { + av_log(avctx, AV_LOG_ERROR, "Invalid sample rate %d\n", ast->codecpar->sample_rate); + return AVERROR_INVALIDDATA; } - } else { - avpriv_request_sample(avctx, "Audio compression (format %i)", v); - } + avpriv_set_pts_info(ast, 33, 1, ast->codecpar->sample_rate); - if (bytes_per_sample == 0) - return AVERROR_INVALIDDATA; + bytes_per_sample = avio_rb32(pb); - if (set_channels(avctx, ast, avio_rb32(pb)) < 0) - return AVERROR_INVALIDDATA; + v = avio_rb32(pb); + if (v == AUDIO_FORMAT_SIGNED) { + switch (bytes_per_sample) { + case 1: + ast->codecpar->codec_id = AV_CODEC_ID_PCM_S8; + break; + case 2: + ast->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE; + break; + default: + avpriv_request_sample(avctx, "Audio sample size %i bytes", bytes_per_sample); + break; + } + } else { + avpriv_request_sample(avctx, "Audio compression (format %i)", v); + } - avio_skip(pb, 8); + if (bytes_per_sample == 0) + return AVERROR_INVALIDDATA; + + if (set_channels(avctx, ast, avio_rb32(pb)) < 0) + return AVERROR_INVALIDDATA; + + avio_skip(pb, 8); + } else + avio_skip(pb, 24); /* skip meaningless audio metadata */ var_read_metadata(avctx, "title", 0x80); var_read_metadata(avctx, "comment", 0x100); @@ -386,9 +398,11 @@ static int mv_read_header(AVFormatContext *avctx) if (avio_feof(pb)) return AVERROR_INVALIDDATA; avio_skip(pb, 8); - av_add_index_entry(ast, pos, timestamp, asize, 0, AVINDEX_KEYFRAME); + if (ast) { + av_add_index_entry(ast, pos, timestamp, asize, 0, AVINDEX_KEYFRAME); + timestamp += asize / (ast->codecpar->ch_layout.nb_channels * (uint64_t)bytes_per_sample); + } av_add_index_entry(vst, pos + asize, i, vsize, 0, AVINDEX_KEYFRAME); - timestamp += asize / (ast->codecpar->channels * (uint64_t)bytes_per_sample); } } else if (!version && avio_rb16(pb) == 3) { avio_skip(pb, 4); @@ -423,7 +437,7 @@ static int mv_read_header(AVFormatContext *avctx) ast->codecpar->bits_per_coded_sample); ast->codecpar->codec_id = AV_CODEC_ID_NONE; } - if (ast->codecpar->channels <= 0) { + if (ast->codecpar->ch_layout.nb_channels <= 0) { av_log(avctx, AV_LOG_ERROR, "No valid channel count found.\n"); return AVERROR_INVALIDDATA; } diff --git a/libavformat/mvi.c b/libavformat/mvi.c index 4c67e3569..b2d6a92a4 100644 --- a/libavformat/mvi.c +++ b/libavformat/mvi.c @@ -84,8 +84,7 @@ static int read_header(AVFormatContext *s) avpriv_set_pts_info(ast, 64, 1, ast->codecpar->sample_rate); ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; ast->codecpar->codec_id = AV_CODEC_ID_PCM_U8; - ast->codecpar->channels = 1; - ast->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + ast->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; ast->codecpar->bits_per_coded_sample = 8; ast->codecpar->bit_rate = ast->codecpar->sample_rate * 8; diff --git a/libavformat/mxf.h b/libavformat/mxf.h index d53a16df5..4d9f5119a 100644 --- a/libavformat/mxf.h +++ b/libavformat/mxf.h @@ -25,8 +25,9 @@ #include "libavutil/log.h" #include "libavutil/pixfmt.h" #include "libavutil/rational.h" +#include "libavutil/uuid.h" -typedef uint8_t UID[16]; +typedef AVUUID UID; enum MXFMetadataSetType { AnyType, diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index f8c1df796..400941c34 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -59,6 +59,7 @@ #include "libavutil/opt.h" #include "avformat.h" #include "avlanguage.h" +#include "demux.h" #include "internal.h" #include "mxf.h" @@ -591,18 +592,19 @@ static int mxf_get_d10_aes3_packet(AVIOContext *pb, AVStream *st, AVPacket *pkt, end_ptr = pkt->data + length; buf_ptr = pkt->data + 4; /* skip SMPTE 331M header */ - if (st->codecpar->channels > 8) + if (st->codecpar->ch_layout.nb_channels > 8) return AVERROR_INVALIDDATA; - for (; end_ptr - buf_ptr >= st->codecpar->channels * 4; ) { - for (i = 0; i < st->codecpar->channels; i++) { + for (; end_ptr - buf_ptr >= st->codecpar->ch_layout.nb_channels * 4; ) { + for (i = 0; i < st->codecpar->ch_layout.nb_channels; i++) { uint32_t sample = bytestream_get_le32(&buf_ptr); if (st->codecpar->bits_per_coded_sample == 24) bytestream_put_le24(&data_ptr, (sample >> 4) & 0xffffff); else bytestream_put_le16(&data_ptr, (sample >> 12) & 0xffff); } - buf_ptr += 32 - st->codecpar->channels*4; // always 8 channels stored SMPTE 331M + // always 8 channels stored SMPTE 331M + buf_ptr += 32 - st->codecpar->ch_layout.nb_channels * 4; } av_shrink_packet(pkt, data_ptr - pkt->data); return 0; @@ -2116,43 +2118,12 @@ static int mxf_is_intra_only(MXFDescriptor *descriptor) &descriptor->essence_codec_ul)->id != AV_CODEC_ID_NONE; } -static int mxf_uid_to_str(UID uid, char **str) +static void mxf_umid_to_str(const UID ul, const UID uid, + char str[2 + sizeof(UID) * 4 + 1]) { - int i; - char *p; - p = *str = av_mallocz(sizeof(UID) * 2 + 4 + 1); - if (!p) - return AVERROR(ENOMEM); - for (i = 0; i < sizeof(UID); i++) { - snprintf(p, 2 + 1, "%.2x", uid[i]); - p += 2; - if (i == 3 || i == 5 || i == 7 || i == 9) { - snprintf(p, 1 + 1, "-"); - p++; - } - } - return 0; -} - -static int mxf_umid_to_str(UID ul, UID uid, char **str) -{ - int i; - char *p; - p = *str = av_mallocz(sizeof(UID) * 4 + 2 + 1); - if (!p) - return AVERROR(ENOMEM); - snprintf(p, 2 + 1, "0x"); - p += 2; - for (i = 0; i < sizeof(UID); i++) { - snprintf(p, 2 + 1, "%.2X", ul[i]); - p += 2; - - } - for (i = 0; i < sizeof(UID); i++) { - snprintf(p, 2 + 1, "%.2X", uid[i]); - p += 2; - } - return 0; + snprintf(str, 2 + sizeof(UID) * 4 + 1, "0x"); + ff_data_to_hex(str + 2, ul, sizeof(UID), 0); + ff_data_to_hex(str + 2 + 2 * sizeof(UID), uid, sizeof(UID), 0); } static int mxf_version_to_str(uint16_t major, uint16_t minor, uint16_t tertiary, @@ -2166,13 +2137,11 @@ static int mxf_version_to_str(uint16_t major, uint16_t minor, uint16_t tertiary, static int mxf_add_umid_metadata(AVDictionary **pm, const char *key, MXFPackage* package) { - char *str; - int ret; + char str[2 + 4 * sizeof(UID) + 1]; if (!package) return 0; - if ((ret = mxf_umid_to_str(package->package_ul, package->package_uid, &str)) < 0) - return ret; - av_dict_set(pm, key, str, AV_DICT_DONT_STRDUP_VAL); + mxf_umid_to_str(package->package_ul, package->package_uid, str); + av_dict_set(pm, key, str, 0); return 0; } @@ -2548,6 +2517,7 @@ static int parse_mca_labels(MXFContext *mxf, MXFTrack *source_track, MXFDescript if (has_channel_label) { uint64_t channel_layout = 0; + int ret; for (int i = 0; i < descriptor->channels; i++) { if (!routing[i]) { @@ -2556,9 +2526,11 @@ static int parse_mca_labels(MXFContext *mxf, MXFTrack *source_track, MXFDescript return 0; } if (channel_layout & routing[i]) { + char buf[32]; + av_channel_name(buf, sizeof(buf), routing[i]); av_log(mxf->fc, AV_LOG_WARNING, "%s audio channel is used multiple times in stream #%d, " "falling back to unknown channel layout\n", - av_get_channel_name(routing[i]), st->index); + buf, st->index); return 0; } if (routing[i] < channel_layout) { @@ -2569,9 +2541,11 @@ static int parse_mca_labels(MXFContext *mxf, MXFTrack *source_track, MXFDescript channel_layout |= routing[i]; } - av_assert0(descriptor->channels == av_get_channel_layout_nb_channels(channel_layout)); + av_assert0(descriptor->channels == av_popcount64(channel_layout)); - st->codecpar->channel_layout = channel_layout; + ret = av_channel_layout_from_mask(&st->codecpar->ch_layout, channel_layout); + if (ret < 0) + return ret; } return 0; @@ -2939,7 +2913,7 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) /* Only overwrite existing codec ID if it is unset or A-law, which is the default according to SMPTE RP 224. */ if (st->codecpar->codec_id == AV_CODEC_ID_NONE || (st->codecpar->codec_id == AV_CODEC_ID_PCM_ALAW && (enum AVCodecID)container_ul->id != AV_CODEC_ID_NONE)) st->codecpar->codec_id = (enum AVCodecID)container_ul->id; - st->codecpar->channels = descriptor->channels; + st->codecpar->ch_layout.nb_channels = descriptor->channels; if (descriptor->sample_rate.den > 0) { st->codecpar->sample_rate = descriptor->sample_rate.num / descriptor->sample_rate.den; @@ -3081,10 +3055,10 @@ static int64_t mxf_timestamp_to_int64(uint64_t timestamp) } while (0) #define SET_UID_METADATA(pb, name, var, str) do { \ + char uuid_str[2 * AV_UUID_LEN + 4 + 1]; \ avio_read(pb, var, 16); \ - if ((ret = mxf_uid_to_str(var, &str)) < 0) \ - return ret; \ - av_dict_set(&s->metadata, name, str, AV_DICT_DONT_STRDUP_VAL); \ + av_uuid_unparse(uid, uuid_str); \ + av_dict_set(&s->metadata, name, uuid_str, 0); \ } while (0) #define SET_TS_METADATA(pb, name, var, str) do { \ @@ -3565,7 +3539,8 @@ static int mxf_handle_missing_index_segment(MXFContext *mxf, AVStream *st) return 0; if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && is_pcm(st->codecpar->codec_id)) { - edit_unit_byte_count = (av_get_bits_per_sample(st->codecpar->codec_id) * st->codecpar->channels) >> 3; + edit_unit_byte_count = (av_get_bits_per_sample(st->codecpar->codec_id) * + st->codecpar->ch_layout.nb_channels) >> 3; } else if (st->duration > 0 && p->first_essence_klv.length > 0 && p->first_essence_klv.length % st->duration == 0) { edit_unit_byte_count = p->first_essence_klv.length / st->duration; } @@ -3870,12 +3845,12 @@ static int mxf_set_audio_pts(MXFContext *mxf, AVCodecParameters *par, pkt->pts = track->sample_count; - if ( par->channels <= 0 - || bits_per_sample <= 0 - || par->channels * (int64_t)bits_per_sample < 8) + if (par->ch_layout.nb_channels <= 0 || + bits_per_sample <= 0 || + par->ch_layout.nb_channels * (int64_t)bits_per_sample < 8) track->sample_count = mxf_compute_sample_count(mxf, st, av_rescale_q(track->sample_count, st->time_base, av_inv_q(track->edit_rate)) + 1); else - track->sample_count += pkt->size / (par->channels * (int64_t)bits_per_sample / 8); + track->sample_count += pkt->size / (par->ch_layout.nb_channels * (int64_t)bits_per_sample / 8); return 0; } diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index 5e068c822..9a9acbfa0 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -38,7 +38,6 @@ */ #include -#include #include #include "libavutil/opt.h" @@ -48,18 +47,18 @@ #include "libavutil/mastering_display_metadata.h" #include "libavutil/pixdesc.h" #include "libavutil/time_internal.h" -#include "libavcodec/bytestream.h" -#include "libavcodec/dv_profile.h" -#include "libavcodec/h264_ps.h" #include "libavcodec/golomb.h" -#include "libavcodec/internal.h" +#include "libavcodec/h264.h" #include "libavcodec/packet_internal.h" +#include "libavcodec/startcode.h" #include "avformat.h" #include "avio_internal.h" #include "internal.h" #include "avc.h" +#include "mux.h" #include "mxf.h" #include "config.h" +#include "version.h" extern const AVOutputFormat ff_mxf_d10_muxer; extern const AVOutputFormat ff_mxf_opatom_muxer; @@ -229,7 +228,8 @@ static const UID mxf_d10_container_uls[] = { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x06,0x01 }, // D-10 525/50 NTSC 30mb/s }; -static const uint8_t uuid_base[] = { 0xAD,0xAB,0x44,0x24,0x2f,0x25,0x4d,0xc7,0x92,0xff,0x29,0xbd }; +static const uint8_t product_uid[] = { 0xAD,0xAB,0x44,0x24,0x2f,0x25,0x4d,0xc7,0x92,0xff,0x29,0xbd,0x00,0x0c,0x00,0x02}; +static const uint8_t uuid_base[] = { 0xAD,0xAB,0x44,0x24,0x2f,0x25,0x4d,0xc7,0x92,0xff }; static const uint8_t umid_ul[] = { 0x06,0x0A,0x2B,0x34,0x01,0x01,0x01,0x05,0x01,0x01,0x0D,0x00,0x13 }; /** @@ -426,9 +426,9 @@ typedef struct MXFContext { static void mxf_write_uuid(AVIOContext *pb, enum MXFMetadataSetType type, int value) { - avio_write(pb, uuid_base, 12); + avio_write(pb, uuid_base, 10); avio_wb16(pb, type); - avio_wb16(pb, value); + avio_wb32(pb, value); } static void mxf_write_umid(AVFormatContext *s, int type) @@ -799,7 +799,7 @@ static void mxf_write_identification(AVFormatContext *s) // write product uid mxf_write_local_tag(s, 16, 0x3C05); - mxf_write_uuid(pb, Identification, 2); + avio_write(pb, product_uid, 16); // modification date mxf_write_local_tag(s, 8, 0x3C06); @@ -1455,17 +1455,19 @@ static int64_t mxf_write_generic_sound_common(AVFormatContext *s, AVStream *st, mxf_write_local_tag(s, 4, 0x3D07); if (mxf->channel_count == -1) { - if (show_warnings && (s->oformat == &ff_mxf_d10_muxer) && (st->codecpar->channels != 4) && (st->codecpar->channels != 8)) + if (show_warnings && (s->oformat == &ff_mxf_d10_muxer) && + (st->codecpar->ch_layout.nb_channels != 4) && + (st->codecpar->ch_layout.nb_channels != 8)) av_log(s, AV_LOG_WARNING, "the number of audio channels shall be 4 or 8 : the output will not comply to MXF D-10 specs, use -d10_channelcount to fix this\n"); - avio_wb32(pb, st->codecpar->channels); + avio_wb32(pb, st->codecpar->ch_layout.nb_channels); } else if (s->oformat == &ff_mxf_d10_muxer) { - if (show_warnings && (mxf->channel_count < st->codecpar->channels)) + if (show_warnings && (mxf->channel_count < st->codecpar->ch_layout.nb_channels)) av_log(s, AV_LOG_WARNING, "d10_channelcount < actual number of audio channels : some channels will be discarded\n"); if (show_warnings && (mxf->channel_count != 4) && (mxf->channel_count != 8)) av_log(s, AV_LOG_WARNING, "d10_channelcount shall be set to 4 or 8 : the output will not comply to MXF D-10 specs\n"); avio_wb32(pb, mxf->channel_count); } else { - avio_wb32(pb, st->codecpar->channels); + avio_wb32(pb, st->codecpar->ch_layout.nb_channels); } mxf_write_local_tag(s, 4, 0x3D01); @@ -1758,7 +1760,7 @@ static void mxf_write_index_table_segment(AVFormatContext *s) // instance id mxf_write_local_tag(s, 16, 0x3C0A); - mxf_write_uuid(pb, IndexTableSegment, 0); + mxf_write_uuid(pb, IndexTableSegment, mxf->last_indexed_edit_unit); // index edit rate mxf_write_local_tag(s, 8, 0x3F0B); @@ -2137,7 +2139,7 @@ static int mxf_parse_dv_frame(AVFormatContext *s, AVStream *st, AVPacket *pkt) { MXFContext *mxf = s->priv_data; MXFStreamContext *sc = st->priv_data; - uint8_t *vs_pack, *vsc_pack; + const uint8_t *vs_pack, *vsc_pack; int apt, ul_index, stype, pal; if (mxf->header_written) @@ -2494,6 +2496,35 @@ static int mxf_init_timecode(AVFormatContext *s, AVStream *st, AVRational tbc) return av_timecode_init(&mxf->tc, av_inv_q(tbc), 0, 0, s); } +static enum AVChromaLocation choose_chroma_location(AVFormatContext *s, AVStream *st) +{ + AVCodecParameters *par = st->codecpar; + const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(par->format); + + if (par->chroma_location != AVCHROMA_LOC_UNSPECIFIED) + return par->chroma_location; + + if (pix_desc) { + if (pix_desc->log2_chroma_h == 0) { + return AVCHROMA_LOC_TOPLEFT; + } else if (pix_desc->log2_chroma_w == 1 && pix_desc->log2_chroma_h == 1) { + if (par->field_order == AV_FIELD_UNKNOWN || par->field_order == AV_FIELD_PROGRESSIVE) { + switch (par->codec_id) { + case AV_CODEC_ID_MJPEG: + case AV_CODEC_ID_MPEG1VIDEO: return AVCHROMA_LOC_CENTER; + } + } + if (par->field_order == AV_FIELD_UNKNOWN || par->field_order != AV_FIELD_PROGRESSIVE) { + switch (par->codec_id) { + case AV_CODEC_ID_MPEG2VIDEO: return AVCHROMA_LOC_LEFT; + } + } + } + } + + return AVCHROMA_LOC_UNSPECIFIED; +} + static int mxf_init(AVFormatContext *s) { MXFContext *mxf = s->priv_data; @@ -2542,7 +2573,7 @@ static int mxf_init(AVFormatContext *s) sc->h_chroma_sub_sample = 1 << pix_desc->log2_chroma_w; sc->v_chroma_sub_sample = 1 << pix_desc->log2_chroma_h; } - switch (ff_choose_chroma_location(s, st)) { + switch (choose_chroma_location(s, st)) { case AVCHROMA_LOC_TOPLEFT: sc->color_siting = 0; break; case AVCHROMA_LOC_LEFT: sc->color_siting = 6; break; case AVCHROMA_LOC_TOP: sc->color_siting = 1; break; @@ -2624,7 +2655,7 @@ static int mxf_init(AVFormatContext *s) av_log(s, AV_LOG_ERROR, "Only pcm_s16le and pcm_s24le audio codecs are implemented\n"); return AVERROR_PATCHWELCOME; } - if (st->codecpar->channels != 1) { + if (st->codecpar->ch_layout.nb_channels != 1) { av_log(s, AV_LOG_ERROR, "MXF OPAtom only supports single channel audio\n"); return AVERROR(EINVAL); } @@ -2633,11 +2664,11 @@ static int mxf_init(AVFormatContext *s) if((ret = mxf_init_timecode(s, st, tbc)) < 0) return ret; - mxf->edit_unit_byte_count = (av_get_bits_per_sample(st->codecpar->codec_id) * st->codecpar->channels) >> 3; + mxf->edit_unit_byte_count = (av_get_bits_per_sample(st->codecpar->codec_id) * st->codecpar->ch_layout.nb_channels) >> 3; sc->index = INDEX_WAV; } else { mxf->slice_count = 1; - sc->frame_size = st->codecpar->channels * + sc->frame_size = st->codecpar->ch_layout.nb_channels * av_rescale_rnd(st->codecpar->sample_rate, mxf->time_base.num, mxf->time_base.den, AV_ROUND_UP) * av_get_bits_per_sample(st->codecpar->codec_id) / 8; } @@ -2775,18 +2806,18 @@ static void mxf_write_d10_audio_packet(AVFormatContext *s, AVStream *st, AVPacke MXFContext *mxf = s->priv_data; AVIOContext *pb = s->pb; int frame_size = pkt->size / st->codecpar->block_align; - uint8_t *samples = pkt->data; - uint8_t *end = pkt->data + pkt->size; + const uint8_t *samples = pkt->data; + const uint8_t *const end = pkt->data + pkt->size; int i; klv_encode_ber4_length(pb, 4 + frame_size*4*8); avio_w8(pb, (frame_size == 1920 ? 0 : (mxf->edit_units_count-1) % 5 + 1)); avio_wl16(pb, frame_size); - avio_w8(pb, (1<codecpar->channels)-1); + avio_w8(pb, (1 << st->codecpar->ch_layout.nb_channels)-1); while (samples < end) { - for (i = 0; i < st->codecpar->channels; i++) { + for (i = 0; i < st->codecpar->ch_layout.nb_channels; i++) { uint32_t sample; if (st->codecpar->codec_id == AV_CODEC_ID_PCM_S24LE) { sample = AV_RL24(samples)<< 4; diff --git a/libavformat/mxg.c b/libavformat/mxg.c index d5c1d666f..b160ccb9f 100644 --- a/libavformat/mxg.c +++ b/libavformat/mxg.c @@ -57,8 +57,7 @@ static int mxg_read_header(AVFormatContext *s) return AVERROR(ENOMEM); audio_st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; audio_st->codecpar->codec_id = AV_CODEC_ID_PCM_ALAW; - audio_st->codecpar->channels = 1; - audio_st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + audio_st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; audio_st->codecpar->sample_rate = 8000; audio_st->codecpar->bits_per_coded_sample = 8; audio_st->codecpar->block_align = 1; diff --git a/libavformat/network.c b/libavformat/network.c index 0f5a575f7..21e20b3e9 100644 --- a/libavformat/network.c +++ b/libavformat/network.c @@ -18,12 +18,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include #include "network.h" #include "tls.h" #include "url.h" -#include "libavcodec/internal.h" -#include "libavutil/avutil.h" #include "libavutil/avassert.h" #include "libavutil/mem.h" #include "libavutil/time.h" @@ -180,7 +180,7 @@ static int ff_poll_interrupt(struct pollfd *p, nfds_t nfds, int timeout, return ret; } -int ff_socket(int af, int type, int proto) +int ff_socket(int af, int type, int proto, void *logctx) { int fd; @@ -193,14 +193,14 @@ int ff_socket(int af, int type, int proto) #if HAVE_FCNTL if (fd != -1) { if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) - av_log(NULL, AV_LOG_DEBUG, "Failed to set close on exec\n"); + av_log(logctx, AV_LOG_DEBUG, "Failed to set close on exec\n"); } #endif } #ifdef SO_NOSIGPIPE if (fd != -1) { if (setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &(int){1}, sizeof(int))) { - av_log(NULL, AV_LOG_WARNING, "setsockopt(SO_NOSIGPIPE) failed\n"); + av_log(logctx, AV_LOG_WARNING, "setsockopt(SO_NOSIGPIPE) failed\n"); } } #endif @@ -208,12 +208,12 @@ int ff_socket(int af, int type, int proto) } int ff_listen(int fd, const struct sockaddr *addr, - socklen_t addrlen) + socklen_t addrlen, void *logctx) { int ret; int reuse = 1; if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))) { - av_log(NULL, AV_LOG_WARNING, "setsockopt(SO_REUSEADDR) failed\n"); + av_log(logctx, AV_LOG_WARNING, "setsockopt(SO_REUSEADDR) failed\n"); } ret = bind(fd, addr, addrlen); if (ret) @@ -247,7 +247,7 @@ int ff_listen_bind(int fd, const struct sockaddr *addr, socklen_t addrlen, int timeout, URLContext *h) { int ret; - if ((ret = ff_listen(fd, addr, addrlen)) < 0) + if ((ret = ff_listen(fd, addr, addrlen, h)) < 0) return ret; if ((ret = ff_accept(fd, timeout, h)) < 0) return ret; @@ -363,7 +363,7 @@ static int start_connect_attempt(struct ConnectionAttempt *attempt, *ptr = ai->ai_next; - attempt->fd = ff_socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + attempt->fd = ff_socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol, h); if (attempt->fd < 0) return ff_neterrno(); attempt->deadline_us = av_gettime_relative() + timeout_ms * 1000; diff --git a/libavformat/network.h b/libavformat/network.h index 71347e815..71c49a73f 100644 --- a/libavformat/network.h +++ b/libavformat/network.h @@ -271,7 +271,8 @@ int ff_listen_bind(int fd, const struct sockaddr *addr, * @param addrlen Third argument of bind(). * @return 0 on success or an AVERROR on failure. */ -int ff_listen(int fd, const struct sockaddr *addr, socklen_t addrlen); +int ff_listen(int fd, const struct sockaddr *addr, socklen_t addrlen, + void *logctx); /** * Poll for a single connection on the passed file descriptor. @@ -305,7 +306,7 @@ int ff_listen_connect(int fd, const struct sockaddr *addr, int ff_http_match_no_proxy(const char *no_proxy, const char *hostname); -int ff_socket(int domain, int type, int protocol); +int ff_socket(int domain, int type, int protocol, void *logctx); void ff_log_net_error(void *ctx, int level, const char* prefix); diff --git a/libavformat/nistspheredec.c b/libavformat/nistspheredec.c index b606ce72a..85aa5e2cb 100644 --- a/libavformat/nistspheredec.c +++ b/libavformat/nistspheredec.c @@ -80,7 +80,8 @@ static int nist_read_header(AVFormatContext *s) avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); - st->codecpar->block_align = st->codecpar->bits_per_coded_sample * st->codecpar->channels / 8; + st->codecpar->block_align = st->codecpar->bits_per_coded_sample * + st->codecpar->ch_layout.nb_channels / 8; if (avio_tell(s->pb) > header_size) return AVERROR_INVALIDDATA; @@ -89,8 +90,8 @@ static int nist_read_header(AVFormatContext *s) return 0; } else if (!memcmp(buffer, "channel_count", 13)) { - sscanf(buffer, "%*s %*s %u", &st->codecpar->channels); - if (st->codecpar->channels <= 0 || st->codecpar->channels > INT16_MAX) + sscanf(buffer, "%*s %*s %u", &st->codecpar->ch_layout.nb_channels); + if (st->codecpar->ch_layout.nb_channels <= 0 || st->codecpar->ch_layout.nb_channels > INT16_MAX) return AVERROR_INVALIDDATA; } else if (!memcmp(buffer, "sample_byte_format", 18)) { sscanf(buffer, "%*s %*s %31s", format); diff --git a/libavformat/nspdec.c b/libavformat/nspdec.c index 3aaf88774..923432ac9 100644 --- a/libavformat/nspdec.c +++ b/libavformat/nspdec.c @@ -88,7 +88,7 @@ static int nsp_read_header(AVFormatContext *s) } st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; - st->codecpar->channels = channels; + st->codecpar->ch_layout.nb_channels = channels; st->codecpar->sample_rate = rate; st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE; st->codecpar->block_align = 2 * channels; diff --git a/libavformat/nsvdec.c b/libavformat/nsvdec.c index 27471125f..852e6194b 100644 --- a/libavformat/nsvdec.c +++ b/libavformat/nsvdec.c @@ -618,7 +618,7 @@ null_chunk_retry: st[NSV_ST_AUDIO]->codecpar->codec_id = AV_CODEC_ID_PCM_U8; samplerate /= 4;/* UGH ??? XXX */ channels = 1; - st[NSV_ST_AUDIO]->codecpar->channels = channels; + st[NSV_ST_AUDIO]->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; st[NSV_ST_AUDIO]->codecpar->sample_rate = samplerate; av_log(s, AV_LOG_TRACE, "NSV RAWAUDIO: bps %d, nchan %d, srate %d\n", bps, channels, samplerate); } diff --git a/libavformat/nullenc.c b/libavformat/nullenc.c index d4769d592..3deca5a7e 100644 --- a/libavformat/nullenc.c +++ b/libavformat/nullenc.c @@ -20,7 +20,7 @@ */ #include "avformat.h" -#include "internal.h" +#include "mux.h" static int null_write_packet(struct AVFormatContext *s, AVPacket *pkt) { diff --git a/libavformat/nutdec.c b/libavformat/nutdec.c index 0a8a700ac..8cc56615a 100644 --- a/libavformat/nutdec.c +++ b/libavformat/nutdec.c @@ -29,6 +29,7 @@ #include "libavutil/tree.h" #include "libavcodec/bytestream.h" #include "avio_internal.h" +#include "demux.h" #include "isom.h" #include "nut.h" #include "riff.h" @@ -199,6 +200,8 @@ static int decode_main_header(NUTContext *nut) int tmp_stream, tmp_mul, tmp_pts, tmp_size, tmp_res, tmp_head_idx; length = get_packetheader(nut, bc, 1, MAIN_STARTCODE); + if (length == (uint64_t)-1) + return AVERROR_INVALIDDATA; end = length + avio_tell(bc); nut->version = ffio_read_varlen(bc); @@ -351,8 +354,12 @@ static int decode_main_header(NUTContext *nut) ret = AVERROR(ENOMEM); goto fail; } - for (i = 0; i < stream_count; i++) - avformat_new_stream(s, NULL); + for (i = 0; i < stream_count; i++) { + if (!avformat_new_stream(s, NULL)) { + ret = AVERROR(ENOMEM); + goto fail; + } + } return 0; fail: @@ -453,7 +460,7 @@ static int decode_stream_header(NUTContext *nut) } else if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { GET_V(st->codecpar->sample_rate, tmp > 0); ffio_read_varlen(bc); // samplerate_den - GET_V(st->codecpar->channels, tmp > 0); + GET_V(st->codecpar->ch_layout.nb_channels, tmp > 0); } if (skip_reserved(bc, end) || ffio_get_checksum(bc)) { av_log(s, AV_LOG_ERROR, @@ -800,19 +807,23 @@ static int nut_read_header(AVFormatContext *s) NUTContext *nut = s->priv_data; AVIOContext *bc = s->pb; int64_t pos; - int initialized_stream_count; + int initialized_stream_count, ret; nut->avf = s; /* main header */ pos = 0; + ret = 0; do { + if (ret == AVERROR(ENOMEM)) + return ret; + pos = find_startcode(bc, MAIN_STARTCODE, pos) + 1; if (pos < 0 + 1) { av_log(s, AV_LOG_ERROR, "No main startcode found.\n"); return AVERROR_INVALIDDATA; } - } while (decode_main_header(nut) < 0); + } while ((ret = decode_main_header(nut)) < 0); /* stream headers */ pos = 0; @@ -953,8 +964,10 @@ static int read_sm_data(AVFormatContext *s, AVIOContext *bc, AVPacket *pkt, int if (!dst) return AVERROR(ENOMEM); bytestream_put_le32(&dst, +#if FF_API_OLD_CHANNEL_LAYOUT AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT*(!!channels) + AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT*(!!channel_layout) + +#endif AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE*(!!sample_rate) + AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS*(!!(width|height)) ); diff --git a/libavformat/nutenc.c b/libavformat/nutenc.c index 585ce953c..1afdeeb8a 100644 --- a/libavformat/nutenc.c +++ b/libavformat/nutenc.c @@ -30,10 +30,32 @@ #include "libavutil/opt.h" #include "libavcodec/bytestream.h" #include "libavcodec/mpegaudiodata.h" +#include "mux.h" #include "nut.h" #include "internal.h" #include "avio_internal.h" #include "riff.h" +#include "version.h" + +/** + * Chooses a timebase for muxing the specified stream. + * + * The chosen timebase allows sample accurate timestamps based + * on the framerate or sample rate for audio streams. It also is + * at least as precise as 1/min_precision would be. + */ +static AVRational choose_timebase(AVFormatContext *s, AVStream *st, int min_precision) +{ + AVRational q = st->time_base; + + for (int j = 2; j < 14; j += 1 + (j > 2)) + while (q.den / q.num < min_precision && q.num % j == 0) + q.num /= j; + while (q.den / q.num < min_precision && q.den < (1<<24)) + q.den <<= 1; + + return q; +} static int find_expected_header(AVCodecParameters *p, int size, int key_frame, uint8_t out[64]) @@ -461,7 +483,7 @@ static int write_streamheader(AVFormatContext *avctx, AVIOContext *bc, case AVMEDIA_TYPE_AUDIO: put_v(bc, par->sample_rate); put_v(bc, 1); - put_v(bc, par->channels); + put_v(bc, par->ch_layout.nb_channels); break; case AVMEDIA_TYPE_VIDEO: put_v(bc, par->width); @@ -727,7 +749,7 @@ static int nut_write_header(AVFormatContext *s) if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && st->codecpar->sample_rate) { time_base = (AVRational) {1, st->codecpar->sample_rate}; } else { - time_base = ff_choose_timebase(s, st, 48000); + time_base = choose_timebase(s, st, 48000); } avpriv_set_pts_info(st, 64, time_base.num, time_base.den); @@ -894,6 +916,7 @@ static int write_sm_data(AVFormatContext *s, AVIOContext *bc, AVPacket *pkt, int break; case AV_PKT_DATA_PARAM_CHANGE: flags = bytestream_get_le32(&data); +#if FF_API_OLD_CHANNEL_LAYOUT if (flags & AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT) { put_str(dyn_bc, "Channels"); put_s(dyn_bc, bytestream_get_le32(&data)); @@ -907,6 +930,7 @@ static int write_sm_data(AVFormatContext *s, AVIOContext *bc, AVPacket *pkt, int avio_write(dyn_bc, data, 8); data+=8; sm_data_count++; } +#endif if (flags & AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE) { put_str(dyn_bc, "SampleRate"); put_s(dyn_bc, bytestream_get_le32(&data)); diff --git a/libavformat/nuv.c b/libavformat/nuv.c index 5f5cc5030..12c6c691e 100644 --- a/libavformat/nuv.c +++ b/libavformat/nuv.c @@ -25,6 +25,7 @@ #include "libavutil/intfloat.h" #include "avformat.h" #include "avio_internal.h" +#include "demux.h" #include "internal.h" #include "riff.h" @@ -116,10 +117,11 @@ static int get_codec_data(AVFormatContext *s, AVIOContext *pb, AVStream *vst, return AVERROR_INVALIDDATA; } ast->codecpar->bits_per_coded_sample = avio_rl32(pb); - ast->codecpar->channels = avio_rl32(pb); - ast->codecpar->channel_layout = 0; - if (ast->codecpar->channels <= 0) { - av_log(s, AV_LOG_ERROR, "Invalid channels %d\n", ast->codecpar->channels); + av_channel_layout_uninit(&ast->codecpar->ch_layout); + ast->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + ast->codecpar->ch_layout.nb_channels = avio_rl32(pb); + if (ast->codecpar->ch_layout.nb_channels <= 0) { + av_log(s, AV_LOG_ERROR, "Invalid channels %d\n", ast->codecpar->ch_layout.nb_channels); return AVERROR_INVALIDDATA; } @@ -227,8 +229,7 @@ static int nuv_header(AVFormatContext *s) ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; ast->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE; - ast->codecpar->channels = 2; - ast->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; + ast->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; ast->codecpar->sample_rate = 44100; ast->codecpar->bit_rate = 2 * 2 * 44100 * 8; ast->codecpar->block_align = 2 * 2; diff --git a/libavformat/oggdec.c b/libavformat/oggdec.c index 87f178bb7..3b19e0bd8 100644 --- a/libavformat/oggdec.c +++ b/libavformat/oggdec.c @@ -32,10 +32,10 @@ #include "libavutil/avassert.h" #include "libavutil/intreadwrite.h" #include "avio_internal.h" +#include "demux.h" #include "oggdec.h" #include "avformat.h" #include "internal.h" -#include "vorbiscomment.h" #define MAX_PAGE_SIZE 65307 #define DECODER_BUFFER_SIZE MAX_PAGE_SIZE diff --git a/libavformat/oggdec.h b/libavformat/oggdec.h index 1d28e50aa..43df23f4c 100644 --- a/libavformat/oggdec.h +++ b/libavformat/oggdec.h @@ -26,7 +26,6 @@ #define AVFORMAT_OGGDEC_H #include "avformat.h" -#include "metadata.h" struct ogg_codec { const int8_t *magic; diff --git a/libavformat/oggenc.c b/libavformat/oggenc.c index a88dab8cc..ae0705ba5 100644 --- a/libavformat/oggenc.c +++ b/libavformat/oggenc.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include #include "libavutil/crc.h" @@ -31,6 +33,7 @@ #include "avformat.h" #include "avio_internal.h" #include "internal.h" +#include "version.h" #include "vorbiscomment.h" #define MAX_PAGE_SIZE 65025 @@ -194,13 +197,13 @@ static int ogg_buffer_page(AVFormatContext *s, OGGStreamContext *oggstream) } static int ogg_buffer_data(AVFormatContext *s, AVStream *st, - uint8_t *data, unsigned size, int64_t granule, + const uint8_t *data, unsigned size, int64_t granule, int header) { OGGStreamContext *oggstream = st->priv_data; OGGContext *ogg = s->priv_data; int total_segments = size / 255 + 1; - uint8_t *p = data; + const uint8_t *p = data; int i, segments, len, flush = 0; // Handles VFR by flushing page because this frame needs to have a timestamp diff --git a/libavformat/oggparsecelt.c b/libavformat/oggparsecelt.c index f7a88af61..e528fd1f4 100644 --- a/libavformat/oggparsecelt.c +++ b/libavformat/oggparsecelt.c @@ -64,7 +64,7 @@ static int celt_header(AVFormatContext *s, int idx) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_CELT; st->codecpar->sample_rate = sample_rate; - st->codecpar->channels = nb_channels; + st->codecpar->ch_layout.nb_channels = nb_channels; if (sample_rate) avpriv_set_pts_info(st, 64, 1, sample_rate); diff --git a/libavformat/oggparseogm.c b/libavformat/oggparseogm.c index f77779052..1e794745a 100644 --- a/libavformat/oggparseogm.c +++ b/libavformat/oggparseogm.c @@ -97,7 +97,7 @@ ogm_header(AVFormatContext *s, int idx) st->codecpar->height = bytestream2_get_le32(&p); avpriv_set_pts_info(st, 64, time_unit, spu * 10000000); } else { - st->codecpar->channels = bytestream2_get_le16(&p); + st->codecpar->ch_layout.nb_channels = bytestream2_get_le16(&p); bytestream2_skip(&p, 2); /* block_align */ st->codecpar->bit_rate = bytestream2_get_le32(&p) * 8; st->codecpar->sample_rate = spu * 10000000 / time_unit; @@ -160,7 +160,7 @@ ogm_dshow_header(AVFormatContext *s, int idx) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = ff_codec_get_id(ff_codec_wav_tags, AV_RL16(p + 124)); - st->codecpar->channels = AV_RL16(p + 126); + st->codecpar->ch_layout.nb_channels = AV_RL16(p + 126); st->codecpar->sample_rate = AV_RL32(p + 128); st->codecpar->bit_rate = AV_RL32(p + 132) * 8; } diff --git a/libavformat/oggparseopus.c b/libavformat/oggparseopus.c index 36d691e9a..54aa725be 100644 --- a/libavformat/oggparseopus.c +++ b/libavformat/oggparseopus.c @@ -55,7 +55,7 @@ static int opus_header(AVFormatContext *avf, int idx) return AVERROR_INVALIDDATA; st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_OPUS; - st->codecpar->channels = AV_RL8(packet + 9); + st->codecpar->ch_layout.nb_channels = AV_RL8(packet + 9); priv->pre_skip = AV_RL16(packet + 10); st->codecpar->initial_padding = priv->pre_skip; diff --git a/libavformat/oggparseskeleton.c b/libavformat/oggparseskeleton.c index 532fa6aef..2016b16c9 100644 --- a/libavformat/oggparseskeleton.c +++ b/libavformat/oggparseskeleton.c @@ -18,7 +18,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavcodec/bytestream.h" +#include "libavutil/intreadwrite.h" #include "avformat.h" #include "internal.h" #include "oggdec.h" diff --git a/libavformat/oggparsespeex.c b/libavformat/oggparsespeex.c index c4fee7e07..d20d14fa4 100644 --- a/libavformat/oggparsespeex.c +++ b/libavformat/oggparsespeex.c @@ -22,13 +22,8 @@ DEALINGS IN THE SOFTWARE. **/ -#include - -#include "libavutil/bswap.h" -#include "libavutil/avstring.h" #include "libavutil/channel_layout.h" - -#include "libavcodec/bytestream.h" +#include "libavutil/intreadwrite.h" #include "avformat.h" #include "internal.h" @@ -60,6 +55,7 @@ static int speex_header(AVFormatContext *s, int idx) { if (spxp->seq == 0) { int frames_per_packet; + int channels; st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_SPEEX; @@ -73,13 +69,12 @@ static int speex_header(AVFormatContext *s, int idx) { av_log(s, AV_LOG_ERROR, "Invalid sample rate %d\n", st->codecpar->sample_rate); return AVERROR_INVALIDDATA; } - st->codecpar->channels = AV_RL32(p + 48); - if (st->codecpar->channels < 1 || st->codecpar->channels > 2) { + channels = AV_RL32(p + 48); + if (channels < 1 || channels > 2) { av_log(s, AV_LOG_ERROR, "invalid channel count. Speex must be mono or stereo.\n"); return AVERROR_INVALIDDATA; } - st->codecpar->channel_layout = st->codecpar->channels == 1 ? AV_CH_LAYOUT_MONO : - AV_CH_LAYOUT_STEREO; + av_channel_layout_default(&st->codecpar->ch_layout, channels); spxp->packet_size = AV_RL32(p + 56); frames_per_packet = AV_RL32(p + 64); diff --git a/libavformat/oggparsevorbis.c b/libavformat/oggparsevorbis.c index e1ef51089..061840c2e 100644 --- a/libavformat/oggparsevorbis.c +++ b/libavformat/oggparsevorbis.c @@ -26,13 +26,13 @@ #include "libavutil/avstring.h" #include "libavutil/base64.h" -#include "libavutil/bswap.h" #include "libavutil/dict.h" #include "libavcodec/bytestream.h" #include "libavcodec/vorbis_parser.h" #include "avformat.h" +#include "demux.h" #include "flac_picture.h" #include "internal.h" #include "oggdec.h" @@ -336,11 +336,12 @@ static int vorbis_header(AVFormatContext *s, int idx) return AVERROR_INVALIDDATA; channels = bytestream_get_byte(&p); - if (st->codecpar->channels && channels != st->codecpar->channels) { + if (st->codecpar->ch_layout.nb_channels && + channels != st->codecpar->ch_layout.nb_channels) { av_log(s, AV_LOG_ERROR, "Channel change is not supported\n"); return AVERROR_PATCHWELCOME; } - st->codecpar->channels = channels; + st->codecpar->ch_layout.nb_channels = channels; srate = bytestream_get_le32(&p); p += 4; // skip maximum bitrate st->codecpar->bit_rate = bytestream_get_le32(&p); // nominal bitrate diff --git a/libavformat/oma.h b/libavformat/oma.h index 85d5932f1..1a8e16f6d 100644 --- a/libavformat/oma.h +++ b/libavformat/oma.h @@ -23,6 +23,8 @@ #include +#include "libavutil/channel_layout.h" + #include "internal.h" #define EA3_HEADER_SIZE 96 diff --git a/libavformat/omadec.c b/libavformat/omadec.c index 4c418a5ff..066b2d85b 100644 --- a/libavformat/omadec.c +++ b/libavformat/omadec.c @@ -60,19 +60,16 @@ static const uint64_t leaf_table[] = { }; /** map ATRAC-X channel id to internal channel layout */ -static const uint64_t oma_chid_to_native_layout[7] = { - AV_CH_LAYOUT_MONO, - AV_CH_LAYOUT_STEREO, - AV_CH_LAYOUT_SURROUND, - AV_CH_LAYOUT_4POINT0, - AV_CH_LAYOUT_5POINT1_BACK, - AV_CH_LAYOUT_6POINT1_BACK, - AV_CH_LAYOUT_7POINT1 +static const AVChannelLayout oma_chid_to_native_layout[7] = { + AV_CHANNEL_LAYOUT_MONO, + AV_CHANNEL_LAYOUT_STEREO, + AV_CHANNEL_LAYOUT_SURROUND, + AV_CHANNEL_LAYOUT_4POINT0, + AV_CHANNEL_LAYOUT_5POINT1_BACK, + AV_CHANNEL_LAYOUT_6POINT1_BACK, + AV_CHANNEL_LAYOUT_7POINT1 }; -/** map ATRAC-X channel id to total number of channels */ -static const int oma_chid_to_num_channels[7] = { 1, 2, 3, 4, 6, 7, 8 }; - typedef struct OMAContext { uint64_t content_start; int encrypted; @@ -474,8 +471,7 @@ static int oma_read_header(AVFormatContext *s) /* get stereo coding mode, 1 for joint-stereo */ jsflag = (codec_params >> 17) & 1; - st->codecpar->channels = 2; - st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; st->codecpar->sample_rate = samplerate; st->codecpar->bit_rate = st->codecpar->sample_rate * framesize / (1024 / 8); @@ -501,8 +497,8 @@ static int oma_read_header(AVFormatContext *s) "Invalid ATRAC-X channel id: %"PRIu32"\n", channel_id); return AVERROR_INVALIDDATA; } - st->codecpar->channel_layout = oma_chid_to_native_layout[channel_id - 1]; - st->codecpar->channels = oma_chid_to_num_channels[channel_id - 1]; + av_channel_layout_copy(&st->codecpar->ch_layout, + &oma_chid_to_native_layout[channel_id - 1]); framesize = ((codec_params & 0x3FF) * 8) + 8; samplerate = ff_oma_srate_tab[(codec_params >> 13) & 7] * 100; if (!samplerate) { @@ -519,8 +515,7 @@ static int oma_read_header(AVFormatContext *s) break; case OMA_CODECID_LPCM: /* PCM 44.1 kHz 16 bit stereo big-endian */ - st->codecpar->channels = 2; - st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; st->codecpar->sample_rate = 44100; framesize = 1024; /* bit rate = sample rate x PCM block align (= 4) x 8 */ @@ -530,16 +525,14 @@ static int oma_read_header(AVFormatContext *s) avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); break; case OMA_CODECID_ATRAC3AL: - st->codecpar->channels = 2; - st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; st->codecpar->sample_rate = 44100; avpriv_set_pts_info(st, 64, 1, 44100); oc->read_packet = aal_read_packet; framesize = 4096; break; case OMA_CODECID_ATRAC3PAL: - st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; - st->codecpar->channels = 2; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; st->codecpar->sample_rate = 44100; avpriv_set_pts_info(st, 64, 1, 44100); oc->read_packet = aal_read_packet; diff --git a/libavformat/omaenc.c b/libavformat/omaenc.c index 1c4edcac5..246f5195f 100644 --- a/libavformat/omaenc.c +++ b/libavformat/omaenc.c @@ -58,7 +58,7 @@ static av_cold int oma_write_header(AVFormatContext *s) switch (par->codec_tag) { case OMA_CODECID_ATRAC3: - if (par->channels != 2) { + if (par->ch_layout.nb_channels != 2) { av_log(s, AV_LOG_ERROR, "ATRAC3 in OMA is only supported with 2 channels\n"); return AVERROR(EINVAL); } @@ -78,7 +78,7 @@ static av_cold int oma_write_header(AVFormatContext *s) case OMA_CODECID_ATRAC3P: avio_wb32(s->pb, (OMA_CODECID_ATRAC3P << 24) | (srate_index << 13) | - (par->channels << 10) | + (par->ch_layout.nb_channels << 10) | (par->block_align/8 - 1)); break; default: diff --git a/libavformat/options.c b/libavformat/options.c index 1634388ac..0079a06d9 100644 --- a/libavformat/options.c +++ b/libavformat/options.c @@ -19,10 +19,15 @@ */ #include "avformat.h" #include "avio_internal.h" +#include "demux.h" #include "internal.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/codec_par.h" + #include "libavutil/avassert.h" #include "libavutil/internal.h" +#include "libavutil/intmath.h" #include "libavutil/opt.h" /** @@ -146,6 +151,11 @@ static int io_open_default(AVFormatContext *s, AVIOContext **pb, return ffio_open_whitelist(pb, url, flags, &s->interrupt_callback, options, s->protocol_whitelist, s->protocol_blacklist); } +void ff_format_io_close_default(AVFormatContext *s, AVIOContext *pb) +{ + avio_close(pb); +} + static int io_close2_default(AVFormatContext *s, AVIOContext *pb) { return avio_close(pb); @@ -174,7 +184,6 @@ AVFormatContext *avformat_alloc_context(void) return NULL; } - si->offset = AV_NOPTS_VALUE; si->shortest_end = AV_NOPTS_VALUE; return s; @@ -189,3 +198,150 @@ const AVClass *avformat_get_class(void) { return &av_format_context_class; } + +static const AVOption stream_options[] = { + { "disposition", NULL, offsetof(AVStream, disposition), AV_OPT_TYPE_FLAGS, { .i64 = 0 }, + .flags = AV_OPT_FLAG_ENCODING_PARAM, .unit = "disposition" }, + { "default", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DEFAULT }, .unit = "disposition" }, + { "dub", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DUB }, .unit = "disposition" }, + { "original", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_ORIGINAL }, .unit = "disposition" }, + { "comment", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_COMMENT }, .unit = "disposition" }, + { "lyrics", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_LYRICS }, .unit = "disposition" }, + { "karaoke", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_KARAOKE }, .unit = "disposition" }, + { "forced", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_FORCED }, .unit = "disposition" }, + { "hearing_impaired", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_HEARING_IMPAIRED }, .unit = "disposition" }, + { "visual_impaired", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_VISUAL_IMPAIRED }, .unit = "disposition" }, + { "clean_effects", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_CLEAN_EFFECTS }, .unit = "disposition" }, + { "attached_pic", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_ATTACHED_PIC }, .unit = "disposition" }, + { "timed_thumbnails", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_TIMED_THUMBNAILS }, .unit = "disposition" }, + { "captions", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_CAPTIONS }, .unit = "disposition" }, + { "descriptions", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DESCRIPTIONS }, .unit = "disposition" }, + { "metadata", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_METADATA }, .unit = "disposition" }, + { "dependent", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DEPENDENT }, .unit = "disposition" }, + { "still_image", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_STILL_IMAGE }, .unit = "disposition" }, + { NULL } +}; + +static const AVClass stream_class = { + .class_name = "AVStream", + .item_name = av_default_item_name, + .version = LIBAVUTIL_VERSION_INT, + .option = stream_options, +}; + +const AVClass *av_stream_get_class(void) +{ + return &stream_class; +} + +AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c) +{ + FFFormatContext *const si = ffformatcontext(s); + FFStream *sti; + AVStream *st; + AVStream **streams; + + if (s->nb_streams >= s->max_streams) { + av_log(s, AV_LOG_ERROR, "Number of streams exceeds max_streams parameter" + " (%d), see the documentation if you wish to increase it\n", + s->max_streams); + return NULL; + } + streams = av_realloc_array(s->streams, s->nb_streams + 1, sizeof(*streams)); + if (!streams) + return NULL; + s->streams = streams; + + sti = av_mallocz(sizeof(*sti)); + if (!sti) + return NULL; + st = &sti->pub; + +#if FF_API_AVSTREAM_CLASS + st->av_class = &stream_class; +#endif + + st->codecpar = avcodec_parameters_alloc(); + if (!st->codecpar) + goto fail; + + sti->avctx = avcodec_alloc_context3(NULL); + if (!sti->avctx) + goto fail; + + if (s->iformat) { + sti->info = av_mallocz(sizeof(*sti->info)); + if (!sti->info) + goto fail; + +#if FF_API_R_FRAME_RATE + sti->info->last_dts = AV_NOPTS_VALUE; +#endif + sti->info->fps_first_dts = AV_NOPTS_VALUE; + sti->info->fps_last_dts = AV_NOPTS_VALUE; + + /* default pts setting is MPEG-like */ + avpriv_set_pts_info(st, 33, 1, 90000); + /* we set the current DTS to 0 so that formats without any timestamps + * but durations get some timestamps, formats with some unknown + * timestamps have their first few packets buffered and the + * timestamps corrected before they are returned to the user */ + sti->cur_dts = RELATIVE_TS_BASE; + } else { + sti->cur_dts = AV_NOPTS_VALUE; + } + + st->index = s->nb_streams; + st->start_time = AV_NOPTS_VALUE; + st->duration = AV_NOPTS_VALUE; + sti->first_dts = AV_NOPTS_VALUE; + sti->probe_packets = s->max_probe_packets; + sti->pts_wrap_reference = AV_NOPTS_VALUE; + sti->pts_wrap_behavior = AV_PTS_WRAP_IGNORE; + + sti->last_IP_pts = AV_NOPTS_VALUE; + sti->last_dts_for_order_check = AV_NOPTS_VALUE; + for (int i = 0; i < MAX_REORDER_DELAY + 1; i++) + sti->pts_buffer[i] = AV_NOPTS_VALUE; + + st->sample_aspect_ratio = (AVRational) { 0, 1 }; + + sti->inject_global_side_data = si->inject_global_side_data; + + sti->need_context_update = 1; + + s->streams[s->nb_streams++] = st; + return st; +fail: + ff_free_stream(&st); + return NULL; +} + +static int option_is_disposition(const AVOption *opt) +{ + return opt->type == AV_OPT_TYPE_CONST && + opt->unit && !strcmp(opt->unit, "disposition"); +} + +int av_disposition_from_string(const char *disp) +{ + for (const AVOption *opt = stream_options; opt->name; opt++) + if (option_is_disposition(opt) && !strcmp(disp, opt->name)) + return opt->default_val.i64; + return AVERROR(EINVAL); +} + +const char *av_disposition_to_string(int disposition) +{ + int val; + + if (disposition <= 0) + return NULL; + + val = 1 << ff_ctz(disposition); + for (const AVOption *opt = stream_options; opt->name; opt++) + if (option_is_disposition(opt) && opt->default_val.i64 == val) + return opt->name; + + return NULL; +} diff --git a/libavformat/options_table.h b/libavformat/options_table.h index 62c5bb40a..86d836cfe 100644 --- a/libavformat/options_table.h +++ b/libavformat/options_table.h @@ -95,7 +95,7 @@ static const AVOption avformat_options[] = { {"max_ts_probe", "maximum number of packets to read while waiting for the first timestamp", OFFSET(max_ts_probe), AV_OPT_TYPE_INT, { .i64 = 50 }, 0, INT_MAX, D }, {"avoid_negative_ts", "shift timestamps so they start at 0", OFFSET(avoid_negative_ts), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 2, E, "avoid_negative_ts"}, {"auto", "enabled when required by target format", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_AVOID_NEG_TS_AUTO }, INT_MIN, INT_MAX, E, "avoid_negative_ts"}, -{"disabled", "do not change timestamps", 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, INT_MIN, INT_MAX, E, "avoid_negative_ts"}, +{"disabled", "do not change timestamps", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_AVOID_NEG_TS_DISABLED }, INT_MIN, INT_MAX, E, "avoid_negative_ts"}, {"make_non_negative", "shift timestamps so they are non negative", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE }, INT_MIN, INT_MAX, E, "avoid_negative_ts"}, {"make_zero", "shift timestamps so they start at 0", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_AVOID_NEG_TS_MAKE_ZERO }, INT_MIN, INT_MAX, E, "avoid_negative_ts"}, {"dump_separator", "set information dump field separator", OFFSET(dump_separator), AV_OPT_TYPE_STRING, {.str = ", "}, 0, 0, D|E}, diff --git a/libavformat/os_support.h b/libavformat/os_support.h index 5e6b32d2d..b419efa40 100644 --- a/libavformat/os_support.h +++ b/libavformat/os_support.h @@ -49,11 +49,38 @@ # ifdef stat # undef stat # endif -# define stat _stati64 + +# define stat win32_stat + + /* + * The POSIX definition for the stat() function uses a struct of the + * same name (struct stat), that why it takes this extra effort for + * redirecting/replacing the stat() function with our own one which + * is capable to handle long path names on Windows. + * The struct below roughly follows the POSIX definition. Time values + * are 64bit, but in cases when _USE_32BIT_TIME_T is defined, they + * will be set to values no larger than INT32_MAX which corresponds + * to file times up to the year 2038. + */ + struct win32_stat + { + _dev_t st_dev; /* ID of device containing file */ + _ino_t st_ino; /* inode number */ + unsigned short st_mode; /* protection */ + short st_nlink; /* number of hard links */ + short st_uid; /* user ID of owner */ + short st_gid; /* group ID of owner */ + _dev_t st_rdev; /* device ID (if special file) */ + int64_t st_size; /* total size, in bytes */ + int64_t st_atime; /* time of last access */ + int64_t st_mtime; /* time of last modification */ + int64_t st_ctime; /* time of last status change */ + }; + # ifdef fstat # undef fstat # endif -# define fstat(f,s) _fstati64((f), (s)) +# define fstat win32_fstat #endif /* defined(_WIN32) */ @@ -153,7 +180,7 @@ static inline int win32_##name(const char *filename_utf8) \ wchar_t *filename_w; \ int ret; \ \ - if (utf8towchar(filename_utf8, &filename_w)) \ + if (get_extended_win32_path(filename_utf8, &filename_w)) \ return -1; \ if (!filename_w) \ goto fallback; \ @@ -171,37 +198,76 @@ DEF_FS_FUNCTION(unlink, _wunlink, _unlink) DEF_FS_FUNCTION(mkdir, _wmkdir, _mkdir) DEF_FS_FUNCTION(rmdir, _wrmdir , _rmdir) -#define DEF_FS_FUNCTION2(name, wfunc, afunc, partype) \ -static inline int win32_##name(const char *filename_utf8, partype par) \ -{ \ - wchar_t *filename_w; \ - int ret; \ - \ - if (utf8towchar(filename_utf8, &filename_w)) \ - return -1; \ - if (!filename_w) \ - goto fallback; \ - \ - ret = wfunc(filename_w, par); \ - av_free(filename_w); \ - return ret; \ - \ -fallback: \ - /* filename may be be in CP_ACP */ \ - return afunc(filename_utf8, par); \ +static inline int win32_access(const char *filename_utf8, int mode) +{ + wchar_t *filename_w; + int ret; + if (get_extended_win32_path(filename_utf8, &filename_w)) + return -1; + if (!filename_w) + goto fallback; + ret = _waccess(filename_w, mode); + av_free(filename_w); + return ret; +fallback: + return _access(filename_utf8, mode); } -DEF_FS_FUNCTION2(access, _waccess, _access, int) -DEF_FS_FUNCTION2(stat, _wstati64, _stati64, struct stat*) +static inline void copy_stat(struct _stat64 *crtstat, struct win32_stat *buf) +{ + buf->st_dev = crtstat->st_dev; + buf->st_ino = crtstat->st_ino; + buf->st_mode = crtstat->st_mode; + buf->st_nlink = crtstat->st_nlink; + buf->st_uid = crtstat->st_uid; + buf->st_gid = crtstat->st_gid; + buf->st_rdev = crtstat->st_rdev; + buf->st_size = crtstat->st_size; + buf->st_atime = crtstat->st_atime; + buf->st_mtime = crtstat->st_mtime; + buf->st_ctime = crtstat->st_ctime; +} + +static inline int win32_stat(const char *filename_utf8, struct win32_stat *buf) +{ + struct _stat64 crtstat = { 0 }; + wchar_t *filename_w; + int ret; + + if (get_extended_win32_path(filename_utf8, &filename_w)) + return -1; + + if (filename_w) { + ret = _wstat64(filename_w, &crtstat); + av_free(filename_w); + } else + ret = _stat64(filename_utf8, &crtstat); + + copy_stat(&crtstat, buf); + + return ret; +} + +static inline int win32_fstat(int fd, struct win32_stat *buf) +{ + struct _stat64 crtstat = { 0 }; + int ret; + + ret = _fstat64(fd, &crtstat); + + copy_stat(&crtstat, buf); + + return ret; +} static inline int win32_rename(const char *src_utf8, const char *dest_utf8) { wchar_t *src_w, *dest_w; int ret; - if (utf8towchar(src_utf8, &src_w)) + if (get_extended_win32_path(src_utf8, &src_w)) return -1; - if (utf8towchar(dest_utf8, &dest_w)) { + if (get_extended_win32_path(dest_utf8, &dest_w)) { av_free(src_w); return -1; } diff --git a/libavformat/paf.c b/libavformat/paf.c index 140e0567e..d48cf5764 100644 --- a/libavformat/paf.c +++ b/libavformat/paf.c @@ -127,8 +127,7 @@ static int read_header(AVFormatContext *s) ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; ast->codecpar->codec_tag = 0; ast->codecpar->codec_id = AV_CODEC_ID_PAF_AUDIO; - ast->codecpar->channels = 2; - ast->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; + ast->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; ast->codecpar->sample_rate = 22050; avpriv_set_pts_info(ast, 64, 1, 22050); diff --git a/libavformat/pcm.c b/libavformat/pcm.c index e91117ce5..9741f7366 100644 --- a/libavformat/pcm.c +++ b/libavformat/pcm.c @@ -63,7 +63,7 @@ int ff_pcm_read_seek(AVFormatContext *s, st = s->streams[0]; block_align = st->codecpar->block_align ? st->codecpar->block_align : - (av_get_bits_per_sample(st->codecpar->codec_id) * st->codecpar->channels) >> 3; + (av_get_bits_per_sample(st->codecpar->codec_id) * st->codecpar->ch_layout.nb_channels) >> 3; byte_rate = st->codecpar->bit_rate ? st->codecpar->bit_rate >> 3 : block_align * st->codecpar->sample_rate; diff --git a/libavformat/pcmdec.c b/libavformat/pcmdec.c index 63539a47c..11ba0b5c0 100644 --- a/libavformat/pcmdec.c +++ b/libavformat/pcmdec.c @@ -19,7 +19,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/avstring.h" +#include "libavutil/channel_layout.h" #include "avformat.h" #include "internal.h" #include "pcm.h" @@ -30,7 +33,10 @@ typedef struct PCMAudioDemuxerContext { AVClass *class; int sample_rate; +#if FF_API_OLD_CHANNEL_LAYOUT int channels; +#endif + AVChannelLayout ch_layout; } PCMAudioDemuxerContext; static int pcm_read_header(AVFormatContext *s) @@ -39,6 +45,7 @@ static int pcm_read_header(AVFormatContext *s) AVCodecParameters *par; AVStream *st; uint8_t *mime_type = NULL; + int ret; st = avformat_new_stream(s, NULL); if (!st) @@ -48,7 +55,16 @@ static int pcm_read_header(AVFormatContext *s) par->codec_type = AVMEDIA_TYPE_AUDIO; par->codec_id = s->iformat->raw_codec_id; par->sample_rate = s1->sample_rate; - par->channels = s1->channels; +#if FF_API_OLD_CHANNEL_LAYOUT + if (s1->ch_layout.nb_channels) { +#endif + ret = av_channel_layout_copy(&par->ch_layout, &s1->ch_layout); + if (ret < 0) + return ret; +#if FF_API_OLD_CHANNEL_LAYOUT + } else + par->ch_layout.nb_channels = s1->channels; +#endif av_opt_get(s->pb, "mime_type", AV_OPT_SEARCH_CHILDREN, &mime_type); if (mime_type && s->iformat->mime_type) { @@ -76,8 +92,10 @@ static int pcm_read_header(AVFormatContext *s) return AVERROR_INVALIDDATA; } par->sample_rate = rate; - if (channels > 0) - par->channels = channels; + if (channels > 0) { + av_channel_layout_uninit(&par->ch_layout); + par->ch_layout.nb_channels = channels; + } if (little_endian) par->codec_id = AV_CODEC_ID_PCM_S16LE; } @@ -88,7 +106,7 @@ static int pcm_read_header(AVFormatContext *s) av_assert0(par->bits_per_coded_sample > 0); - par->block_align = par->bits_per_coded_sample * par->channels / 8; + par->block_align = par->bits_per_coded_sample * par->ch_layout.nb_channels / 8; avpriv_set_pts_info(st, 64, 1, par->sample_rate); return 0; @@ -96,7 +114,12 @@ static int pcm_read_header(AVFormatContext *s) static const AVOption pcm_options[] = { { "sample_rate", "", offsetof(PCMAudioDemuxerContext, sample_rate), AV_OPT_TYPE_INT, {.i64 = 44100}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, - { "channels", "", offsetof(PCMAudioDemuxerContext, channels), AV_OPT_TYPE_INT, {.i64 = 1}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, +#if FF_API_OLD_CHANNEL_LAYOUT + { "channels", "", offsetof(PCMAudioDemuxerContext, channels), AV_OPT_TYPE_INT, {.i64 = 1}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_DEPRECATED }, + { "ch_layout", "", offsetof(PCMAudioDemuxerContext, ch_layout), AV_OPT_TYPE_CHLAYOUT, {.str = NULL}, 0, 0, AV_OPT_FLAG_DECODING_PARAM }, +#else + { "ch_layout", "", offsetof(PCMAudioDemuxerContext, ch_layout), AV_OPT_TYPE_CHLAYOUT, {.str = "mono"}, 0, 0, AV_OPT_FLAG_DECODING_PARAM }, +#endif { NULL }, }; static const AVClass pcm_demuxer_class = { @@ -157,7 +180,12 @@ PCMDEF(vidc, "PCM Archimedes VIDC", NULL, VIDC) #if CONFIG_SLN_DEMUXER static const AVOption sln_options[] = { { "sample_rate", "", offsetof(PCMAudioDemuxerContext, sample_rate), AV_OPT_TYPE_INT, {.i64 = 8000}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, - { "channels", "", offsetof(PCMAudioDemuxerContext, channels), AV_OPT_TYPE_INT, {.i64 = 1}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, +#if FF_API_OLD_CHANNEL_LAYOUT + { "channels", "", offsetof(PCMAudioDemuxerContext, channels), AV_OPT_TYPE_INT, {.i64 = 1}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_DEPRECATED }, + { "ch_layout", "", offsetof(PCMAudioDemuxerContext, ch_layout), AV_OPT_TYPE_CHLAYOUT, {.str = NULL}, 0, 0, AV_OPT_FLAG_DECODING_PARAM }, +#else + { "ch_layout", "", offsetof(PCMAudioDemuxerContext, ch_layout), AV_OPT_TYPE_CHLAYOUT, {.str = "mono"}, 0, 0, AV_OPT_FLAG_DECODING_PARAM }, +#endif { NULL }, }; diff --git a/libavformat/pcmenc.c b/libavformat/pcmenc.c index cbfcee7b4..0cf497989 100644 --- a/libavformat/pcmenc.c +++ b/libavformat/pcmenc.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "avformat.h" #include "rawenc.h" diff --git a/libavformat/pmpdec.c b/libavformat/pmpdec.c index ce8e89515..554f1a776 100644 --- a/libavformat/pmpdec.c +++ b/libavformat/pmpdec.c @@ -119,7 +119,7 @@ static int pmp_header(AVFormatContext *s) return AVERROR(ENOMEM); ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; ast->codecpar->codec_id = audio_codec_id; - ast->codecpar->channels = channels; + ast->codecpar->ch_layout.nb_channels = channels; ast->codecpar->sample_rate = srate; avpriv_set_pts_info(ast, 32, 1, srate); } diff --git a/libavformat/pp_bnk.c b/libavformat/pp_bnk.c index b1e1b6115..c4172e226 100644 --- a/libavformat/pp_bnk.c +++ b/libavformat/pp_bnk.c @@ -205,18 +205,12 @@ static int pp_bnk_read_header(AVFormatContext *s) par->codec_id = AV_CODEC_ID_ADPCM_IMA_CUNNING; par->format = AV_SAMPLE_FMT_S16P; - if (ctx->is_music) { - par->channel_layout = AV_CH_LAYOUT_STEREO; - par->channels = 2; - } else { - par->channel_layout = AV_CH_LAYOUT_MONO; - par->channels = 1; - } - + av_channel_layout_default(&par->ch_layout, ctx->is_music + 1); par->sample_rate = hdr.sample_rate; par->bits_per_coded_sample = 4; par->block_align = 1; - par->bit_rate = par->sample_rate * (int64_t)par->bits_per_coded_sample * par->channels; + par->bit_rate = par->sample_rate * (int64_t)par->bits_per_coded_sample * + par->ch_layout.nb_channels; avpriv_set_pts_info(st, 64, 1, par->sample_rate); st->start_time = 0; diff --git a/libavformat/protocols.c b/libavformat/protocols.c index 948fae411..6ee62a598 100644 --- a/libavformat/protocols.c +++ b/libavformat/protocols.c @@ -16,8 +16,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "config.h" - #include "libavutil/avstring.h" #include "libavutil/mem.h" @@ -73,6 +71,8 @@ extern const URLProtocol ff_libsrt_protocol; extern const URLProtocol ff_libssh_protocol; extern const URLProtocol ff_libsmbclient_protocol; extern const URLProtocol ff_libzmq_protocol; +extern const URLProtocol ff_ipfs_protocol; +extern const URLProtocol ff_ipns_protocol; #include "libavformat/protocol_list.c" diff --git a/libavformat/psxstr.c b/libavformat/psxstr.c index e649ba3ab..bb56b0568 100644 --- a/libavformat/psxstr.c +++ b/libavformat/psxstr.c @@ -252,18 +252,12 @@ static int str_read_packet(AVFormatContext *s, st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_ADPCM_XA; st->codecpar->codec_tag = 0; /* no fourcc */ - if (fmt & 1) { - st->codecpar->channels = 2; - st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; - } else { - st->codecpar->channels = 1; - st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; - } + av_channel_layout_default(&st->codecpar->ch_layout, (fmt & 1) + 1); st->codecpar->sample_rate = (fmt&4)?18900:37800; // st->codecpar->bit_rate = 0; //FIXME; st->codecpar->block_align = 128; - avpriv_set_pts_info(st, 64, 18 * 224 / st->codecpar->channels, + avpriv_set_pts_info(st, 64, 18 * 224 / st->codecpar->ch_layout.nb_channels, st->codecpar->sample_rate); st->start_time = 0; } diff --git a/libavformat/pvfdec.c b/libavformat/pvfdec.c index 7205b0b37..62c169a31 100644 --- a/libavformat/pvfdec.c +++ b/libavformat/pvfdec.c @@ -54,11 +54,11 @@ static int pvf_read_header(AVFormatContext *s) return AVERROR(ENOMEM); st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; - st->codecpar->channels = channels; + st->codecpar->ch_layout.nb_channels = channels; st->codecpar->sample_rate = sample_rate; st->codecpar->codec_id = ff_get_pcm_codec_id(bps, 0, 1, 0xFFFF); st->codecpar->bits_per_coded_sample = bps; - st->codecpar->block_align = bps * st->codecpar->channels / 8; + st->codecpar->block_align = bps * st->codecpar->ch_layout.nb_channels / 8; avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); diff --git a/libavformat/qcp.c b/libavformat/qcp.c index 7e0d9b9b8..8d80b726a 100644 --- a/libavformat/qcp.c +++ b/libavformat/qcp.c @@ -103,8 +103,7 @@ static int qcp_read_header(AVFormatContext *s) avio_skip(pb, 4 + 8 + 4 + 1 + 1); // filesize + "QLCMfmt " + chunk-size + major-version + minor-version st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; - st->codecpar->channels = 1; - st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; avio_read(pb, buf, 16); if (is_qcelp_13k_guid(buf)) { st->codecpar->codec_id = AV_CODEC_ID_QCELP; diff --git a/libavformat/r3d.c b/libavformat/r3d.c index c98e3dbc6..be119b6b7 100644 --- a/libavformat/r3d.c +++ b/libavformat/r3d.c @@ -286,7 +286,7 @@ static int r3d_read_reda(AVFormatContext *s, AVPacket *pkt, Atom *atom) return AVERROR(ENOMEM); st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_PCM_S32BE; - st->codecpar->channels = r3d->audio_channels; + st->codecpar->ch_layout.nb_channels = r3d->audio_channels; avpriv_set_pts_info(st, 32, 1, s->streams[0]->time_base.den); } else { st = s->streams[1]; diff --git a/libavformat/rawdec.c b/libavformat/rawdec.c index 15e26c03b..17649bc07 100644 --- a/libavformat/rawdec.c +++ b/libavformat/rawdec.c @@ -20,6 +20,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "avformat.h" #include "internal.h" #include "avio_internal.h" diff --git a/libavformat/rawenc.c b/libavformat/rawenc.c index 4bbae7717..26099cb1c 100644 --- a/libavformat/rawenc.c +++ b/libavformat/rawenc.c @@ -20,11 +20,13 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/intreadwrite.h" #include "avformat.h" #include "rawenc.h" -#include "internal.h" +#include "mux.h" int ff_raw_write_packet(AVFormatContext *s, AVPacket *pkt) { @@ -79,7 +81,7 @@ static int adx_write_trailer(AVFormatContext *s) if (pb->seekable & AVIO_SEEKABLE_NORMAL) { int64_t file_size = avio_tell(pb); - uint64_t sample_count = (file_size - 36) / par->channels / 18 * 32; + uint64_t sample_count = (file_size - 36) / par->ch_layout.nb_channels / 18 * 32; if (sample_count <= UINT32_MAX) { avio_seek(pb, 12, SEEK_SET); avio_wb32(pb, sample_count); @@ -192,6 +194,19 @@ const AVOutputFormat ff_data_muxer = { }; #endif +#if CONFIG_DFPWM_MUXER +const AVOutputFormat ff_dfpwm_muxer = { + .name = "dfpwm", + .long_name = NULL_IF_CONFIG_SMALL("raw DFPWM1a"), + .extensions = "dfpwm", + .audio_codec = AV_CODEC_ID_DFPWM, + .video_codec = AV_CODEC_ID_NONE, + .init = force_one_stream, + .write_packet = ff_raw_write_packet, + .flags = AVFMT_NOTIMESTAMPS, +}; +#endif + #if CONFIG_DIRAC_MUXER const AVOutputFormat ff_dirac_muxer = { .name = "dirac", diff --git a/libavformat/rawutils.c b/libavformat/rawutils.c index 996412adb..e44c946d4 100644 --- a/libavformat/rawutils.c +++ b/libavformat/rawutils.c @@ -19,8 +19,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/intreadwrite.h" +#include "libavcodec/packet.h" #include "avformat.h" -#include "internal.h" +#include "rawutils.h" int ff_reshuffle_raw_rgb(AVFormatContext *s, AVPacket **ppkt, AVCodecParameters *par, int expected_stride) { @@ -65,3 +67,27 @@ fail: return ret; } + +int ff_get_packet_palette(AVFormatContext *s, AVPacket *pkt, int ret, uint32_t *palette) +{ + uint8_t *side_data; + size_t size; + + side_data = av_packet_get_side_data(pkt, AV_PKT_DATA_PALETTE, &size); + if (side_data) { + if (size != AVPALETTE_SIZE) { + av_log(s, AV_LOG_ERROR, "Invalid palette side data\n"); + return AVERROR_INVALIDDATA; + } + memcpy(palette, side_data, AVPALETTE_SIZE); + return 1; + } + + if (ret == CONTAINS_PAL) { + for (int i = 0; i < AVPALETTE_COUNT; i++) + palette[i] = AV_RL32(pkt->data + pkt->size - AVPALETTE_SIZE + i*4); + return 1; + } + + return 0; +} diff --git a/libavformat/rawutils.h b/libavformat/rawutils.h new file mode 100644 index 000000000..a91123412 --- /dev/null +++ b/libavformat/rawutils.h @@ -0,0 +1,56 @@ +/* + * 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_RAWUTILS_H +#define AVFORMAT_RAWUTILS_H + +#include +#include "libavcodec/codec_par.h" +#include "libavcodec/packet.h" +#include "avformat.h" + +#define CONTAINS_PAL 2 +/** + * Reshuffles the lines to use the user specified stride. + * + * @param ppkt input and output packet + * @return negative error code or + * 0 if no new packet was allocated + * non-zero if a new packet was allocated and ppkt has to be freed + * CONTAINS_PAL if in addition to a new packet the old contained a palette + */ +int ff_reshuffle_raw_rgb(AVFormatContext *s, AVPacket **ppkt, AVCodecParameters *par, int expected_stride); + +/** + * Retrieves the palette from a packet, either from side data, or + * appended to the video data in the packet itself (raw video only). + * It is commonly used after a call to ff_reshuffle_raw_rgb(). + * + * Use 0 for the ret parameter to check for side data only. + * + * @param pkt pointer to packet before calling ff_reshuffle_raw_rgb() + * @param ret return value from ff_reshuffle_raw_rgb(), or 0 + * @param palette pointer to palette buffer + * @return negative error code or + * 1 if the packet has a palette, else 0 + */ +int ff_get_packet_palette(AVFormatContext *s, AVPacket *pkt, int ret, uint32_t *palette); + +#endif /* AVFORMAT_RAWUTILS_H */ diff --git a/libavformat/rawvideodec.c b/libavformat/rawvideodec.c index a7d6a72be..514e4e044 100644 --- a/libavformat/rawvideodec.c +++ b/libavformat/rawvideodec.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/imgutils.h" #include "libavutil/parseutils.h" #include "libavutil/pixdesc.h" @@ -33,6 +35,8 @@ typedef struct RawVideoDemuxerContext { AVRational framerate; /**< AVRational describing framerate, set by a private option. */ } RawVideoDemuxerContext; +// v210 frame width is padded to multiples of 48 +#define GET_PACKET_SIZE(w, h) (((w + 47) / 48) * 48 * h * 8 / 3) static int rawvideo_read_header(AVFormatContext *ctx) { @@ -50,10 +54,13 @@ static int rawvideo_read_header(AVFormatContext *ctx) st->codecpar->codec_id = ctx->iformat->raw_codec_id; - if ((pix_fmt = av_get_pix_fmt(s->pixel_format)) == AV_PIX_FMT_NONE) { - av_log(ctx, AV_LOG_ERROR, "No such pixel format: %s.\n", - s->pixel_format); - return AVERROR(EINVAL); + if ((ctx->iformat->raw_codec_id != AV_CODEC_ID_V210) && + (ctx->iformat->raw_codec_id != AV_CODEC_ID_V210X)) { + if ((pix_fmt = av_get_pix_fmt(s->pixel_format)) == AV_PIX_FMT_NONE) { + av_log(ctx, AV_LOG_ERROR, "No such pixel format: %s.\n", + s->pixel_format); + return AVERROR(EINVAL); + } } avpriv_set_pts_info(st, 64, s->framerate.den, s->framerate.num); @@ -89,6 +96,12 @@ static int rawvideo_read_header(AVFormatContext *ctx) } st->codecpar->codec_tag = tag; packet_size = s->width * s->height * pgroup / xinc; + } else if ((ctx->iformat->raw_codec_id == AV_CODEC_ID_V210) || + (ctx->iformat->raw_codec_id == AV_CODEC_ID_V210X)) { + pix_fmt = ctx->iformat->raw_codec_id == AV_CODEC_ID_V210 ? + AV_PIX_FMT_YUV422P10 : AV_PIX_FMT_YUV422P16; + + packet_size = GET_PACKET_SIZE(s->width, s->height); } else { packet_size = av_image_get_buffer_size(pix_fmt, s->width, s->height, 1); if (packet_size < 0) @@ -122,8 +135,9 @@ static int rawvideo_read_packet(AVFormatContext *s, AVPacket *pkt) #define OFFSET(x) offsetof(RawVideoDemuxerContext, x) #define DEC AV_OPT_FLAG_DECODING_PARAM static const AVOption rawvideo_options[] = { - { "video_size", "set frame size", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, DEC }, + /* pixel_format is not used by the v210 demuxers. */ { "pixel_format", "set pixel format", OFFSET(pixel_format), AV_OPT_TYPE_STRING, {.str = "yuv420p"}, 0, 0, DEC }, + { "video_size", "set frame size", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, DEC }, { "framerate", "set frame rate", OFFSET(framerate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, DEC }, { NULL }, }; @@ -167,3 +181,38 @@ const AVInputFormat ff_bitpacked_demuxer = { .priv_class = &bitpacked_demuxer_class, }; #endif // CONFIG_BITPACKED_DEMUXER + +static const AVClass v210_demuxer_class = { + .class_name = "v210(x) demuxer", + .item_name = av_default_item_name, + .option = rawvideo_options + 1, + .version = LIBAVUTIL_VERSION_INT, +}; + +#if CONFIG_V210_DEMUXER +const AVInputFormat ff_v210_demuxer = { + .name = "v210", + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"), + .priv_data_size = sizeof(RawVideoDemuxerContext), + .read_header = rawvideo_read_header, + .read_packet = rawvideo_read_packet, + .flags = AVFMT_GENERIC_INDEX, + .extensions = "v210", + .raw_codec_id = AV_CODEC_ID_V210, + .priv_class = &v210_demuxer_class, +}; +#endif // CONFIG_V210_DEMUXER + +#if CONFIG_V210X_DEMUXER +const AVInputFormat ff_v210x_demuxer = { + .name = "v210x", + .long_name = NULL_IF_CONFIG_SMALL("Uncompressed 4:2:2 10-bit"), + .priv_data_size = sizeof(RawVideoDemuxerContext), + .read_header = rawvideo_read_header, + .read_packet = rawvideo_read_packet, + .flags = AVFMT_GENERIC_INDEX, + .extensions = "yuv10", + .raw_codec_id = AV_CODEC_ID_V210X, + .priv_class = &v210_demuxer_class, +}; +#endif // CONFIG_V210X_DEMUXER diff --git a/libavformat/redspark.c b/libavformat/redspark.c index eca182c3a..c6ee22678 100644 --- a/libavformat/redspark.c +++ b/libavformat/redspark.c @@ -97,26 +97,26 @@ static int redspark_read_header(AVFormatContext *s) st->duration = bytestream2_get_be32u(&gbc) * 14; redspark->samples_count = 0; bytestream2_skipu(&gbc, 10); - par->channels = bytestream2_get_byteu(&gbc); - if (!par->channels) { + par->ch_layout.nb_channels = bytestream2_get_byteu(&gbc); + if (!par->ch_layout.nb_channels) { return AVERROR_INVALIDDATA; } - coef_off = 0x54 + par->channels * 8; + coef_off = 0x54 + par->ch_layout.nb_channels * 8; if (bytestream2_get_byteu(&gbc)) // Loop flag coef_off += 16; - if (coef_off + par->channels * (32 + 14) > HEADER_SIZE) { + if (coef_off + par->ch_layout.nb_channels * (32 + 14) > HEADER_SIZE) { return AVERROR_INVALIDDATA; } - if (ff_alloc_extradata(par, 32 * par->channels)) { + if (ff_alloc_extradata(par, 32 * par->ch_layout.nb_channels)) { return AVERROR_INVALIDDATA; } /* Get the ADPCM table */ bytestream2_seek(&gbc, coef_off, SEEK_SET); - for (i = 0; i < par->channels; i++) { + for (i = 0; i < par->ch_layout.nb_channels; i++) { if (bytestream2_get_bufferu(&gbc, par->extradata + i * 32, 32) != 32) { return AVERROR_INVALIDDATA; } @@ -132,7 +132,7 @@ static int redspark_read_packet(AVFormatContext *s, AVPacket *pkt) { AVCodecParameters *par = s->streams[0]->codecpar; RedSparkContext *redspark = s->priv_data; - uint32_t size = 8 * par->channels; + uint32_t size = 8 * par->ch_layout.nb_channels; int ret; if (avio_feof(s->pb) || redspark->samples_count == s->streams[0]->duration) diff --git a/libavformat/riff.c b/libavformat/riff.c index 27a970651..df7e9df31 100644 --- a/libavformat/riff.c +++ b/libavformat/riff.c @@ -19,8 +19,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include "config.h" -#include "libavutil/common.h" +#include "config_components.h" +#include "libavutil/macros.h" #include "avformat.h" #include "internal.h" #include "metadata.h" @@ -586,6 +588,8 @@ const AVCodecTag ff_codec_wav_tags[] = { { AV_CODEC_ID_AAC, 0xA106 }, { AV_CODEC_ID_SPEEX, 0xA109 }, { AV_CODEC_ID_FLAC, 0xF1AC }, + /* DFPWM does not have an assigned format tag; it uses a GUID in WAVEFORMATEX instead */ + { AV_CODEC_ID_DFPWM, 0xFFFE }, { AV_CODEC_ID_ADPCM_SWF, ('S' << 8) + 'F' }, /* HACK/FIXME: Does Vorbis in WAV/AVI have an (in)official ID? */ { AV_CODEC_ID_VORBIS, ('V' << 8) + 'o' }, @@ -636,5 +640,6 @@ const AVCodecGuid ff_codec_wav_guids[] = { { AV_CODEC_ID_EAC3, { 0xAF, 0x87, 0xFB, 0xA7, 0x02, 0x2D, 0xFB, 0x42, 0xA4, 0xD4, 0x05, 0xCD, 0x93, 0x84, 0x3B, 0xDD } }, { AV_CODEC_ID_MP2, { 0x2B, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB, 0xEA } }, { AV_CODEC_ID_ADPCM_AGM,{ 0x82, 0xEC, 0x1F, 0x6A, 0xCA, 0xDB, 0x19, 0x45, 0xBD, 0xE7, 0x56, 0xD3, 0xB3, 0xEF, 0x98, 0x1D } }, + { AV_CODEC_ID_DFPWM, { 0x3A, 0xC1, 0xFA, 0x38, 0x81, 0x1D, 0x43, 0x61, 0xA4, 0x0D, 0xCE, 0x53, 0xCA, 0x60, 0x7C, 0xD1 } }, { AV_CODEC_ID_NONE } }; diff --git a/libavformat/riffdec.c b/libavformat/riffdec.c index bd32e5983..3946ecb72 100644 --- a/libavformat/riffdec.c +++ b/libavformat/riffdec.c @@ -26,6 +26,7 @@ #include "libavutil/log.h" #include "avformat.h" #include "avio_internal.h" +#include "demux.h" #include "riff.h" int ff_get_guid(AVIOContext *s, ff_asf_guid *g) @@ -61,11 +62,14 @@ static void parse_waveformatex(AVFormatContext *s, AVIOContext *pb, AVCodecParam { ff_asf_guid subformat; int bps; + uint64_t mask; bps = avio_rl16(pb); if (bps) par->bits_per_coded_sample = bps; - par->channel_layout = avio_rl32(pb); /* dwChannelMask */ + + mask = avio_rl32(pb); /* dwChannelMask */ + av_channel_layout_from_mask(&par->ch_layout, mask); ff_get_guid(pb, &subformat); if (!memcmp(subformat + 4, @@ -90,7 +94,7 @@ static void parse_waveformatex(AVFormatContext *s, AVIOContext *pb, AVCodecParam int ff_get_wav_header(AVFormatContext *s, AVIOContext *pb, AVCodecParameters *par, int size, int big_endian) { - int id; + int id, channels; uint64_t bitrate = 0; if (size < 14) { @@ -102,14 +106,14 @@ int ff_get_wav_header(AVFormatContext *s, AVIOContext *pb, if (!big_endian) { id = avio_rl16(pb); if (id != 0x0165) { - par->channels = avio_rl16(pb); + channels = avio_rl16(pb); par->sample_rate = avio_rl32(pb); bitrate = avio_rl32(pb) * 8LL; par->block_align = avio_rl16(pb); } } else { id = avio_rb16(pb); - par->channels = avio_rb16(pb); + channels = avio_rb16(pb); par->sample_rate = avio_rb32(pb); bitrate = avio_rb32(pb) * 8LL; par->block_align = avio_rb16(pb); @@ -160,12 +164,12 @@ int ff_get_wav_header(AVFormatContext *s, AVIOContext *pb, return AVERROR(ENOMEM); nb_streams = AV_RL16(par->extradata + 4); par->sample_rate = AV_RL32(par->extradata + 12); - par->channels = 0; + channels = 0; bitrate = 0; if (size < 8 + nb_streams * 20) return AVERROR_INVALIDDATA; for (i = 0; i < nb_streams; i++) - par->channels += par->extradata[8 + i * 20 + 17]; + channels += par->extradata[8 + i * 20 + 17]; } par->bit_rate = bitrate; @@ -178,13 +182,17 @@ int ff_get_wav_header(AVFormatContext *s, AVIOContext *pb, if (par->codec_id == AV_CODEC_ID_AAC_LATM) { /* Channels and sample_rate values are those prior to applying SBR * and/or PS. */ - par->channels = 0; + channels = 0; par->sample_rate = 0; } /* override bits_per_coded_sample for G.726 */ if (par->codec_id == AV_CODEC_ID_ADPCM_G726 && par->sample_rate) par->bits_per_coded_sample = par->bit_rate / par->sample_rate; + av_channel_layout_uninit(&par->ch_layout); + par->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + par->ch_layout.nb_channels = channels; + return 0; } diff --git a/libavformat/riffenc.c b/libavformat/riffenc.c index ffccfa3d4..7825c4e74 100644 --- a/libavformat/riffenc.c +++ b/libavformat/riffenc.c @@ -77,11 +77,11 @@ int ff_put_wav_header(AVFormatContext *s, AVIOContext *pb, * for indicating packet duration. */ frame_size = av_get_audio_frame_duration2(par, par->block_align); - waveformatextensible = (par->channels > 2 && par->channel_layout) || - par->channels == 1 && par->channel_layout && par->channel_layout != AV_CH_LAYOUT_MONO || - par->channels == 2 && par->channel_layout && par->channel_layout != AV_CH_LAYOUT_STEREO || + waveformatextensible = (par->ch_layout.order == AV_CHANNEL_ORDER_NATIVE && + av_channel_layout_compare(&par->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_MONO) && + av_channel_layout_compare(&par->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO)) || par->sample_rate > 48000 || - par->codec_id == AV_CODEC_ID_EAC3 || + par->codec_id == AV_CODEC_ID_EAC3 || par->codec_id == AV_CODEC_ID_DFPWM || av_get_bits_per_sample(par->codec_id) > 16; if (waveformatextensible) @@ -89,7 +89,7 @@ int ff_put_wav_header(AVFormatContext *s, AVIOContext *pb, else avio_wl16(pb, par->codec_tag); - avio_wl16(pb, par->channels); + avio_wl16(pb, par->ch_layout.nb_channels); avio_wl32(pb, par->sample_rate); if (par->codec_id == AV_CODEC_ID_ATRAC3 || par->codec_id == AV_CODEC_ID_G723_1 || @@ -119,13 +119,13 @@ int ff_put_wav_header(AVFormatContext *s, AVIOContext *pb, } else if (par->codec_id == AV_CODEC_ID_AC3) { blkalign = 3840; /* maximum bytes per frame */ } else if (par->codec_id == AV_CODEC_ID_AAC) { - blkalign = 768 * par->channels; /* maximum bytes per frame */ + blkalign = 768 * par->ch_layout.nb_channels; /* maximum bytes per frame */ } else if (par->codec_id == AV_CODEC_ID_G723_1) { blkalign = 24; } else if (par->block_align != 0) { /* specified by the codec */ blkalign = par->block_align; } else - blkalign = bps * par->channels / av_gcd(8, bps); + blkalign = bps * par->ch_layout.nb_channels / av_gcd(8, bps); if (par->codec_id == AV_CODEC_ID_PCM_U8 || par->codec_id == AV_CODEC_ID_PCM_S24LE || par->codec_id == AV_CODEC_ID_PCM_S32LE || @@ -153,7 +153,7 @@ int ff_put_wav_header(AVFormatContext *s, AVIOContext *pb, /* dwHeadBitrate */ bytestream_put_le32(&riff_extradata, par->bit_rate); /* fwHeadMode */ - bytestream_put_le16(&riff_extradata, par->channels == 2 ? 1 : 8); + bytestream_put_le16(&riff_extradata, par->ch_layout.nb_channels == 2 ? 1 : 8); /* fwHeadModeExt */ bytestream_put_le16(&riff_extradata, 0); /* wHeadEmphasis */ @@ -180,15 +180,15 @@ int ff_put_wav_header(AVFormatContext *s, AVIOContext *pb, if (waveformatextensible) { int write_channel_mask = !(flags & FF_PUT_WAV_HEADER_SKIP_CHANNELMASK) && (s->strict_std_compliance < FF_COMPLIANCE_NORMAL || - par->channel_layout < 0x40000); + par->ch_layout.u.mask < 0x40000); /* 22 is WAVEFORMATEXTENSIBLE size */ avio_wl16(pb, riff_extradata - riff_extradata_start + 22); /* ValidBitsPerSample || SamplesPerBlock || Reserved */ avio_wl16(pb, bps); /* dwChannelMask */ - avio_wl32(pb, write_channel_mask ? par->channel_layout : 0); + avio_wl32(pb, write_channel_mask ? par->ch_layout.u.mask : 0); /* GUID + next 3 */ - if (par->codec_id == AV_CODEC_ID_EAC3) { + if (par->codec_id == AV_CODEC_ID_EAC3 || par->codec_id == AV_CODEC_ID_DFPWM) { ff_put_guid(pb, ff_get_codec_guid(par->codec_id, ff_codec_wav_guids)); } else { avio_wl32(pb, par->codec_tag); diff --git a/libavformat/rl2.c b/libavformat/rl2.c index 6a559c729..669cb0400 100644 --- a/libavformat/rl2.c +++ b/libavformat/rl2.c @@ -37,6 +37,7 @@ #include "libavutil/intreadwrite.h" #include "libavutil/mathematics.h" #include "avformat.h" +#include "demux.h" #include "internal.h" #define EXTRADATA1_SIZE (6 + 256 * 3) ///< video base, clr, palette @@ -147,12 +148,12 @@ static av_cold int rl2_read_header(AVFormatContext *s) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_PCM_U8; st->codecpar->codec_tag = 1; - st->codecpar->channels = channels; + st->codecpar->ch_layout.nb_channels = channels; st->codecpar->bits_per_coded_sample = 8; st->codecpar->sample_rate = rate; - st->codecpar->bit_rate = st->codecpar->channels * st->codecpar->sample_rate * + st->codecpar->bit_rate = channels * st->codecpar->sample_rate * st->codecpar->bits_per_coded_sample; - st->codecpar->block_align = st->codecpar->channels * + st->codecpar->block_align = channels * st->codecpar->bits_per_coded_sample / 8; avpriv_set_pts_info(st,32,1,rate); } diff --git a/libavformat/rmdec.c b/libavformat/rmdec.c index b0a38bee8..881d7002a 100644 --- a/libavformat/rmdec.c +++ b/libavformat/rmdec.c @@ -22,13 +22,13 @@ #include #include "libavutil/avassert.h" -#include "libavutil/avstring.h" #include "libavutil/channel_layout.h" #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" #include "libavutil/dict.h" #include "avformat.h" #include "avio_internal.h" +#include "demux.h" #include "internal.h" #include "rmsipr.h" #include "rm.h" @@ -148,8 +148,7 @@ static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb, if (bytes_per_minute) st->codecpar->bit_rate = 8LL * bytes_per_minute / 60; st->codecpar->sample_rate = 8000; - st->codecpar->channels = 1; - st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_RA_144; ast->deint_id = DEINT_ID_INT0; @@ -185,7 +184,7 @@ static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb, } st->codecpar->sample_rate = avio_rb16(pb); avio_rb32(pb); - st->codecpar->channels = avio_rb16(pb); + st->codecpar->ch_layout.nb_channels = avio_rb16(pb); if (version == 5) { ast->deint_id = avio_rl32(pb); avio_read(pb, buf, 4); @@ -350,7 +349,7 @@ int ff_rm_read_mdpr_codecdata(AVFormatContext *s, AVIOContext *pb, st->codecpar->codec_tag); } else if(mime && !strcmp(mime, "logical-fileinfo")){ int stream_count, rule_count, property_count, i; - ff_free_stream(s, st); + ff_remove_stream(s, st); if (avio_rb16(pb) != 0) { av_log(s, AV_LOG_WARNING, "Unsupported version\n"); goto skip; diff --git a/libavformat/rmenc.c b/libavformat/rmenc.c index 1b2b0ecf3..1fba092b8 100644 --- a/libavformat/rmenc.c +++ b/libavformat/rmenc.c @@ -228,7 +228,7 @@ static int rv10_write_header(AVFormatContext *ctx, avio_wb32(s, 0); /* unknown */ avio_wb16(s, stream->par->sample_rate); /* sample rate */ avio_wb32(s, 0x10); /* unknown */ - avio_wb16(s, stream->par->channels); + avio_wb16(s, stream->par->ch_layout.nb_channels); put_str8(s, "Int0"); /* codec name */ if (stream->par->codec_tag) { avio_w8(s, 4); /* tag length */ diff --git a/libavformat/rpl.c b/libavformat/rpl.c index 459791ffd..d025589bf 100644 --- a/libavformat/rpl.c +++ b/libavformat/rpl.c @@ -194,23 +194,25 @@ static int rpl_read_header(AVFormatContext *s) audio_format = read_int(line, &endptr, &error); // audio format ID av_strlcpy(audio_codec, endptr, RPL_LINE_LENGTH); if (audio_format) { + int channels; ast = avformat_new_stream(s, NULL); if (!ast) return AVERROR(ENOMEM); ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; ast->codecpar->codec_tag = audio_format; ast->codecpar->sample_rate = read_line_and_int(pb, &error); // audio bitrate - ast->codecpar->channels = read_line_and_int(pb, &error); // number of audio channels + channels = read_line_and_int(pb, &error); // number of audio channels error |= read_line(pb, line, sizeof(line)); ast->codecpar->bits_per_coded_sample = read_int(line, &endptr, &error); // audio bits per sample av_strlcpy(audio_type, endptr, RPL_LINE_LENGTH); + ast->codecpar->ch_layout.nb_channels = channels; // At least one sample uses 0 for ADPCM, which is really 4 bits // per sample. if (ast->codecpar->bits_per_coded_sample == 0) ast->codecpar->bits_per_coded_sample = 4; ast->codecpar->bit_rate = ast->codecpar->sample_rate * - (int64_t)ast->codecpar->channels; + (int64_t)ast->codecpar->ch_layout.nb_channels; if (ast->codecpar->bit_rate > INT64_MAX / ast->codecpar->bits_per_coded_sample) return AVERROR_INVALIDDATA; ast->codecpar->bit_rate *= ast->codecpar->bits_per_coded_sample; diff --git a/libavformat/rsd.c b/libavformat/rsd.c index ba3b3429b..33aa0e2c0 100644 --- a/libavformat/rsd.c +++ b/libavformat/rsd.c @@ -19,10 +19,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavcodec/bytestream.h" #include "libavutil/intreadwrite.h" #include "avformat.h" #include "avio.h" +#include "demux.h" #include "internal.h" static const AVCodecTag rsd_tags[] = { @@ -81,9 +81,9 @@ static int rsd_read_header(AVFormatContext *s) return AVERROR_INVALIDDATA; } - par->channels = avio_rl32(pb); - if (par->channels <= 0 || par->channels > INT_MAX / 36) { - av_log(s, AV_LOG_ERROR, "Invalid number of channels: %d\n", par->channels); + par->ch_layout.nb_channels = avio_rl32(pb); + if (par->ch_layout.nb_channels <= 0 || par->ch_layout.nb_channels > INT_MAX / 36) { + av_log(s, AV_LOG_ERROR, "Invalid number of channels: %d\n", par->ch_layout.nb_channels); return AVERROR_INVALIDDATA; } @@ -102,17 +102,17 @@ static int rsd_read_header(AVFormatContext *s) memset(par->extradata, 0, 34); break; case AV_CODEC_ID_ADPCM_PSX: - par->block_align = 16 * par->channels; + par->block_align = 16 * par->ch_layout.nb_channels; break; case AV_CODEC_ID_ADPCM_IMA_RAD: - par->block_align = 20 * par->channels; + par->block_align = 20 * par->ch_layout.nb_channels; break; case AV_CODEC_ID_ADPCM_IMA_WAV: if (version == 2) start = avio_rl32(pb); par->bits_per_coded_sample = 4; - par->block_align = 36 * par->channels; + par->block_align = 36 * par->ch_layout.nb_channels; break; case AV_CODEC_ID_ADPCM_THP_LE: /* RSD3GADP is mono, so only alloc enough memory @@ -124,13 +124,13 @@ static int rsd_read_header(AVFormatContext *s) return ret; break; case AV_CODEC_ID_ADPCM_THP: - par->block_align = 8 * par->channels; + par->block_align = 8 * par->ch_layout.nb_channels; avio_skip(s->pb, 0x1A4 - avio_tell(s->pb)); - if ((ret = ff_alloc_extradata(st->codecpar, 32 * par->channels)) < 0) + if ((ret = ff_alloc_extradata(st->codecpar, 32 * par->ch_layout.nb_channels)) < 0) return ret; - for (i = 0; i < par->channels; i++) { + for (i = 0; i < par->ch_layout.nb_channels; i++) { if (avio_feof(pb)) return AVERROR_EOF; avio_read(s->pb, st->codecpar->extradata + 32 * i, 32); @@ -159,11 +159,11 @@ static int rsd_read_header(AVFormatContext *s) st->duration = av_get_audio_frame_duration2(par, remaining - start); break; case AV_CODEC_ID_ADPCM_THP: - st->duration = (remaining - start) / (8 * par->channels) * 14; + st->duration = (remaining - start) / (8 * par->ch_layout.nb_channels) * 14; break; case AV_CODEC_ID_PCM_S16LE: case AV_CODEC_ID_PCM_S16BE: - st->duration = (remaining - start) / 2 / par->channels; + st->duration = (remaining - start) / 2 / par->ch_layout.nb_channels; } } @@ -194,14 +194,14 @@ static int rsd_read_packet(AVFormatContext *s, AVPacket *pkt) par->codec_id == AV_CODEC_ID_XMA2) { ret = av_get_packet(s->pb, pkt, par->block_align); } else if (par->codec_tag == MKTAG('W','A','D','P') && - par->channels > 1) { + par->ch_layout.nb_channels > 1) { int i, ch; ret = av_new_packet(pkt, par->block_align); if (ret < 0) return ret; for (i = 0; i < 4; i++) { - for (ch = 0; ch < par->channels; ch++) { + for (ch = 0; ch < par->ch_layout.nb_channels; ch++) { pkt->data[ch * 8 + i * 2 + 0] = avio_r8(s->pb); pkt->data[ch * 8 + i * 2 + 1] = avio_r8(s->pb); } diff --git a/libavformat/rsodec.c b/libavformat/rsodec.c index ffd0fdff0..569368b42 100644 --- a/libavformat/rsodec.c +++ b/libavformat/rsodec.c @@ -62,8 +62,7 @@ static int rso_read_header(AVFormatContext *s) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_tag = id; st->codecpar->codec_id = codec; - st->codecpar->channels = 1; - st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; st->codecpar->sample_rate = rate; st->codecpar->block_align = 1; diff --git a/libavformat/rsoenc.c b/libavformat/rsoenc.c index fc327d8a2..858b53f6c 100644 --- a/libavformat/rsoenc.c +++ b/libavformat/rsoenc.c @@ -34,7 +34,7 @@ static int rso_write_header(AVFormatContext *s) if (!par->codec_tag) return AVERROR_INVALIDDATA; - if (par->channels != 1) { + if (par->ch_layout.nb_channels != 1) { av_log(s, AV_LOG_ERROR, "RSO only supports mono\n"); return AVERROR_INVALIDDATA; } diff --git a/libavformat/rtmpproto.c b/libavformat/rtmpproto.c index 34020bc38..f0ef223f0 100644 --- a/libavformat/rtmpproto.c +++ b/libavformat/rtmpproto.c @@ -24,6 +24,8 @@ * RTMP protocol */ +#include "config_components.h" + #include "libavcodec/bytestream.h" #include "libavutil/avstring.h" #include "libavutil/base64.h" @@ -42,6 +44,7 @@ #include "rtmpcrypt.h" #include "rtmppkt.h" #include "url.h" +#include "version.h" #if CONFIG_ZLIB #include @@ -1854,11 +1857,10 @@ static int write_begin(URLContext *s) } static int write_status(URLContext *s, RTMPPacket *pkt, - const char *status, const char *filename) + const char *status, const char *description, const char *details) { RTMPContext *rt = s->priv_data; RTMPPacket spkt = { 0 }; - char statusmsg[128]; uint8_t *pp; int ret; @@ -1881,11 +1883,11 @@ static int write_status(URLContext *s, RTMPPacket *pkt, ff_amf_write_field_name(&pp, "code"); ff_amf_write_string(&pp, status); ff_amf_write_field_name(&pp, "description"); - snprintf(statusmsg, sizeof(statusmsg), - "%s is now published", filename); - ff_amf_write_string(&pp, statusmsg); - ff_amf_write_field_name(&pp, "details"); - ff_amf_write_string(&pp, filename); + ff_amf_write_string(&pp, description); + if (details) { + ff_amf_write_field_name(&pp, "details"); + ff_amf_write_string(&pp, details); + } ff_amf_write_object_end(&pp); spkt.size = pp - spkt.data; @@ -1961,20 +1963,22 @@ static int send_invoke_response(URLContext *s, RTMPPacket *pkt) pp = spkt.data; ff_amf_write_string(&pp, "onFCPublish"); } else if (!strcmp(command, "publish")) { + char statusmsg[128]; + snprintf(statusmsg, sizeof(statusmsg), "%s is now published", filename); ret = write_begin(s); if (ret < 0) return ret; // Send onStatus(NetStream.Publish.Start) return write_status(s, pkt, "NetStream.Publish.Start", - filename); + statusmsg, filename); } else if (!strcmp(command, "play")) { ret = write_begin(s); if (ret < 0) return ret; rt->state = STATE_SENDING; return write_status(s, pkt, "NetStream.Play.Start", - filename); + "playing stream", NULL); } else { if ((ret = ff_rtmp_packet_create(&spkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0, diff --git a/libavformat/rtp.c b/libavformat/rtp.c index c536a6f08..564489b61 100644 --- a/libavformat/rtp.c +++ b/libavformat/rtp.c @@ -77,8 +77,11 @@ int ff_rtp_get_codec_info(AVCodecParameters *par, int payload_type) if (rtp_payload_types[i].codec_id != AV_CODEC_ID_NONE) { par->codec_type = rtp_payload_types[i].codec_type; par->codec_id = rtp_payload_types[i].codec_id; - if (rtp_payload_types[i].audio_channels > 0) - par->channels = rtp_payload_types[i].audio_channels; + if (rtp_payload_types[i].audio_channels > 0) { + av_channel_layout_uninit(&par->ch_layout); + par->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + par->ch_layout.nb_channels = rtp_payload_types[i].audio_channels; + } if (rtp_payload_types[i].clock_rate > 0) par->sample_rate = rtp_payload_types[i].clock_rate; return 0; @@ -111,13 +114,13 @@ int ff_rtp_get_payload_type(const AVFormatContext *fmt, /* G722 has 8000 as nominal rate even if the sample rate is 16000, * see section 4.5.2 in RFC 3551. */ if (par->codec_id == AV_CODEC_ID_ADPCM_G722 && - par->sample_rate == 16000 && par->channels == 1) + par->sample_rate == 16000 && par->ch_layout.nb_channels == 1) return rtp_payload_types[i].pt; if (par->codec_type == AVMEDIA_TYPE_AUDIO && ((rtp_payload_types[i].clock_rate > 0 && par->sample_rate != rtp_payload_types[i].clock_rate) || (rtp_payload_types[i].audio_channels > 0 && - par->channels != rtp_payload_types[i].audio_channels))) + par->ch_layout.nb_channels != rtp_payload_types[i].audio_channels))) continue; return rtp_payload_types[i].pt; } diff --git a/libavformat/rtpdec.c b/libavformat/rtpdec.c index 20fe2b82d..fa7544cc0 100644 --- a/libavformat/rtpdec.c +++ b/libavformat/rtpdec.c @@ -538,7 +538,7 @@ static int opus_write_extradata(AVCodecParameters *codecpar) * This mapping family only supports mono and stereo layouts. And RFC7587 * specifies that the number of channels in the SDP must be 2. */ - if (codecpar->channels > 2) { + if (codecpar->ch_layout.nb_channels > 2) { return AVERROR_INVALIDDATA; } @@ -553,7 +553,7 @@ static int opus_write_extradata(AVCodecParameters *codecpar) /* Version */ bytestream_put_byte (&bs, 0x1); /* Channel count */ - bytestream_put_byte (&bs, codecpar->channels); + bytestream_put_byte (&bs, codecpar->ch_layout.nb_channels); /* Pre skip */ bytestream_put_le16 (&bs, 0); /* Input sample rate */ @@ -835,9 +835,14 @@ static int rtp_parse_queued_packet(RTPDemuxContext *s, AVPacket *pkt) if (s->queue_len <= 0) return -1; - if (!has_next_packet(s)) + if (!has_next_packet(s)) { + int pkt_missed = s->queue->seq - s->seq - 1; + + if (pkt_missed < 0) + pkt_missed += UINT16_MAX; av_log(s->ic, AV_LOG_WARNING, - "RTP: missed %d packets\n", s->queue->seq - s->seq - 1); + "RTP: missed %d packets\n", pkt_missed); + } /* Parse the first packet in the queue, and dequeue it */ rv = rtp_parse_packet_internal(s, pkt, s->queue->buf, s->queue->len); diff --git a/libavformat/rtpdec_amr.c b/libavformat/rtpdec_amr.c index 988b7bddf..ca4f0ff03 100644 --- a/libavformat/rtpdec_amr.c +++ b/libavformat/rtpdec_amr.c @@ -64,11 +64,11 @@ static int amr_handle_packet(AVFormatContext *ctx, PayloadContext *data, return AVERROR_INVALIDDATA; } - if (st->codecpar->channels != 1) { + if (st->codecpar->ch_layout.nb_channels != 1) { av_log(ctx, AV_LOG_ERROR, "Only mono AMR is supported\n"); return AVERROR_INVALIDDATA; } - st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + av_channel_layout_default(&st->codecpar->ch_layout, 1); /* The AMR RTP packet consists of one header byte, followed * by one TOC byte for each AMR frame in the packet, followed diff --git a/libavformat/rtpdec_asf.c b/libavformat/rtpdec_asf.c index eb19e8535..72ead6975 100644 --- a/libavformat/rtpdec_asf.c +++ b/libavformat/rtpdec_asf.c @@ -28,11 +28,11 @@ #include "libavutil/base64.h" #include "libavutil/avstring.h" #include "libavutil/intreadwrite.h" -#include "rtp.h" #include "rtpdec_formats.h" #include "rtsp.h" #include "asf.h" #include "avio_internal.h" +#include "demux.h" #include "internal.h" /** diff --git a/libavformat/rtpdec_dv.c b/libavformat/rtpdec_dv.c index 53a5855ad..fa75a77a8 100644 --- a/libavformat/rtpdec_dv.c +++ b/libavformat/rtpdec_dv.c @@ -21,10 +21,8 @@ #include "libavutil/avstring.h" -#include "libavcodec/bytestream.h" - #include "avio_internal.h" -#include "rtpdec_formats.h" +#include "rtpdec.h" struct PayloadContext { AVIOContext *buf; diff --git a/libavformat/rtpdec_h261.c b/libavformat/rtpdec_h261.c index a102909c6..57bc10fb3 100644 --- a/libavformat/rtpdec_h261.c +++ b/libavformat/rtpdec_h261.c @@ -119,7 +119,9 @@ static int h261_handle_packet(AVFormatContext *ctx, PayloadContext *rtp_h261_ctx } else { /* ebit/sbit values inconsistent, assuming packet loss */ GetBitContext gb; - init_get_bits(&gb, buf, len*8 - ebit); + res = init_get_bits(&gb, buf, len*8 - ebit); + if (res < 0) + return res; skip_bits(&gb, sbit); if (rtp_h261_ctx->endbyte_bits) { rtp_h261_ctx->endbyte |= get_bits(&gb, 8 - rtp_h261_ctx->endbyte_bits); diff --git a/libavformat/rtpdec_h263_rfc2190.c b/libavformat/rtpdec_h263_rfc2190.c index a0f587f5c..47aaec0fb 100644 --- a/libavformat/rtpdec_h263_rfc2190.c +++ b/libavformat/rtpdec_h263_rfc2190.c @@ -142,7 +142,9 @@ static int h263_handle_packet(AVFormatContext *ctx, PayloadContext *data, } else { /* Start/end skip bits not matching - missed packets? */ GetBitContext gb; - init_get_bits(&gb, buf, len*8 - ebit); + ret = init_get_bits(&gb, buf, len*8 - ebit); + if (ret < 0) + return ret; skip_bits(&gb, sbit); if (data->endbyte_bits) { data->endbyte |= get_bits(&gb, 8 - data->endbyte_bits); diff --git a/libavformat/rtpdec_hevc.c b/libavformat/rtpdec_hevc.c index f467104ca..a739ed5bd 100644 --- a/libavformat/rtpdec_hevc.c +++ b/libavformat/rtpdec_hevc.c @@ -21,8 +21,6 @@ #include "libavutil/avassert.h" #include "libavutil/avstring.h" -#include "libavutil/base64.h" -#include "libavcodec/get_bits.h" #include "avformat.h" #include "internal.h" diff --git a/libavformat/rtpdec_latm.c b/libavformat/rtpdec_latm.c index 104a00af1..329b8dbc3 100644 --- a/libavformat/rtpdec_latm.c +++ b/libavformat/rtpdec_latm.c @@ -101,7 +101,9 @@ static int parse_fmtp_config(AVStream *st, const char *value) if (!config) return AVERROR(ENOMEM); ff_hex_to_data(config, value); - init_get_bits(&gb, config, len*8); + ret = init_get_bits(&gb, config, len*8); + if (ret < 0) + return ret; audio_mux_version = get_bits(&gb, 1); same_time_framing = get_bits(&gb, 1); skip_bits(&gb, 6); /* num_sub_frames */ diff --git a/libavformat/rtpdec_mpeg4.c b/libavformat/rtpdec_mpeg4.c index 34c7950bc..723b6fc6e 100644 --- a/libavformat/rtpdec_mpeg4.c +++ b/libavformat/rtpdec_mpeg4.c @@ -124,6 +124,7 @@ static int rtp_parse_mp4_au(PayloadContext *data, const uint8_t *buf, int len) { int au_headers_length, au_header_size, i; GetBitContext getbitcontext; + int ret; if (len < 2) return AVERROR_INVALIDDATA; @@ -144,7 +145,9 @@ static int rtp_parse_mp4_au(PayloadContext *data, const uint8_t *buf, int len) if (len < data->au_headers_length_bytes) return AVERROR_INVALIDDATA; - init_get_bits(&getbitcontext, buf, data->au_headers_length_bytes * 8); + ret = init_get_bits(&getbitcontext, buf, data->au_headers_length_bytes * 8); + if (ret < 0) + return ret; /* XXX: Wrong if optional additional sections are present (cts, dts etc...) */ au_header_size = data->sizelength + data->indexlength; diff --git a/libavformat/rtpdec_qt.c b/libavformat/rtpdec_qt.c index 6723cd1bb..495a3ec14 100644 --- a/libavformat/rtpdec_qt.c +++ b/libavformat/rtpdec_qt.c @@ -82,7 +82,9 @@ static int qt_rtp_parse_packet(AVFormatContext *s, PayloadContext *qt, * The RTP payload is described in: * http://developer.apple.com/quicktime/icefloe/dispatch026.html */ - init_get_bits(&gb, buf, len << 3); + ret = init_get_bits(&gb, buf, len << 3); + if (ret < 0) + return ret; ffio_init_context(&pb0, (uint8_t*)buf, len, 0, NULL, NULL, NULL, NULL); if (len < 4) diff --git a/libavformat/rtpdec_rfc4175.c b/libavformat/rtpdec_rfc4175.c index a66e00d5f..83abe499f 100644 --- a/libavformat/rtpdec_rfc4175.c +++ b/libavformat/rtpdec_rfc4175.c @@ -33,6 +33,8 @@ struct PayloadContext { int depth; int width; int height; + int interlaced; + int field; uint8_t *frame; unsigned int frame_size; @@ -104,6 +106,11 @@ static int rfc4175_parse_format(AVStream *stream, PayloadContext *data) stream->codecpar->bits_per_coded_sample = av_get_bits_per_pixel(desc); data->frame_size = data->width * data->height * data->pgroup / data->xinc; + if (data->interlaced) + stream->codecpar->field_order = AV_FIELD_TT; + else + stream->codecpar->field_order = AV_FIELD_PROGRESSIVE; + if (data->framerate.den > 0) { stream->avg_frame_rate = data->framerate; stream->codecpar->bit_rate = data->frame_size * av_q2d(data->framerate) * 8; @@ -124,6 +131,8 @@ static int rfc4175_parse_fmtp(AVFormatContext *s, AVStream *stream, data->sampling = av_strdup(value); else if (!strncmp(attr, "depth", 5)) data->depth = atoi(value); + else if (!strncmp(attr, "interlace", 9)) + data->interlaced = 1; else if (!strncmp(attr, "exactframerate", 14)) { if (av_parse_video_rate(&data->framerate, value) < 0) return AVERROR(EINVAL); @@ -195,15 +204,18 @@ static int rfc4175_parse_sdp_line(AVFormatContext *s, int st_index, static int rfc4175_finalize_packet(PayloadContext *data, AVPacket *pkt, int stream_index) { - int ret; + int ret = 0; pkt->stream_index = stream_index; - ret = av_packet_from_data(pkt, data->frame, data->frame_size); - if (ret < 0) { - av_freep(&data->frame); + if (!data->interlaced || data->field) { + ret = av_packet_from_data(pkt, data->frame, data->frame_size); + if (ret < 0) { + av_freep(&data->frame); + } + data->frame = NULL; } - data->frame = NULL; + data->field = 0; return ret; } @@ -213,7 +225,7 @@ static int rfc4175_handle_packet(AVFormatContext *ctx, PayloadContext *data, const uint8_t * buf, int len, uint16_t seq, int flags) { - int length, line, offset, cont; + int length, line, offset, cont, field; const uint8_t *headers = buf + 2; /* skip extended seqnum */ const uint8_t *payload = buf + 2; int payload_len = len - 2; @@ -222,20 +234,21 @@ static int rfc4175_handle_packet(AVFormatContext *ctx, PayloadContext *data, uint8_t *dest; if (*timestamp != data->timestamp) { - if (data->frame) { + if (data->frame && (!data->interlaced || data->field)) { /* - * if we're here, it means that two RTP packets didn't have the - * same timestamp, which is a sign that they were packets from two - * different frames, but we didn't get the flag RTP_FLAG_MARKER on - * the first one of these frames (last packet of a frame). - * Finalize the previous frame anyway by filling the AVPacket. + * if we're here, it means that we missed the cue to return + * the previous AVPacket, that cue being the RTP_FLAG_MARKER + * in the last packet of either the previous frame (progressive) + * or the previous second field (interlace). Let's finalize the + * previous frame (or pair of fields) anyway by filling the AVPacket. */ av_log(ctx, AV_LOG_ERROR, "Missed previous RTP Marker\n"); missed_last_packet = 1; rfc4175_finalize_packet(data, pkt, st->index); } - data->frame = av_malloc(data->frame_size); + if (!data->frame) + data->frame = av_malloc(data->frame_size); data->timestamp = *timestamp; @@ -266,10 +279,12 @@ static int rfc4175_handle_packet(AVFormatContext *ctx, PayloadContext *data, return AVERROR_INVALIDDATA; length = (headers[0] << 8) | headers[1]; + field = (headers[2] & 0x80) >> 7; line = ((headers[2] & 0x7f) << 8) | headers[3]; offset = ((headers[4] & 0x7f) << 8) | headers[5]; cont = headers[4] & 0x80; headers += 6; + data->field = field; if (!data->pgroup || length % data->pgroup) return AVERROR_INVALIDDATA; @@ -277,9 +292,12 @@ static int rfc4175_handle_packet(AVFormatContext *ctx, PayloadContext *data, if (length > payload_len) length = payload_len; + if (data->interlaced) + line = 2 * line + field; + /* prevent ill-formed packets to write after buffer's end */ copy_offset = (line * data->width + offset) * data->pgroup / data->xinc; - if (copy_offset + length > data->frame_size) + if (copy_offset + length > data->frame_size || !data->frame) return AVERROR_INVALIDDATA; dest = data->frame + copy_offset; diff --git a/libavformat/rtpdec_vp8.c b/libavformat/rtpdec_vp8.c index 360dd5c78..6701ad59f 100644 --- a/libavformat/rtpdec_vp8.c +++ b/libavformat/rtpdec_vp8.c @@ -27,10 +27,10 @@ * @see http://tools.ietf.org/html/draft-ietf-payload-vp8-05 */ -#include "libavcodec/bytestream.h" +#include "libavutil/intreadwrite.h" #include "avio_internal.h" -#include "rtpdec_formats.h" +#include "rtpdec.h" struct PayloadContext { AVIOContext *data; diff --git a/libavformat/rtpenc.c b/libavformat/rtpenc.c index 17f5d9d30..ce629a809 100644 --- a/libavformat/rtpenc.c +++ b/libavformat/rtpenc.c @@ -236,7 +236,7 @@ static int rtp_write_header(AVFormatContext *s1) avpriv_set_pts_info(st, 32, 1, 8000); break; case AV_CODEC_ID_OPUS: - if (st->codecpar->channels > 2) { + if (st->codecpar->ch_layout.nb_channels > 2) { av_log(s1, AV_LOG_ERROR, "Multistream opus not supported in RTP\n"); goto fail; } @@ -264,7 +264,7 @@ static int rtp_write_header(AVFormatContext *s1) av_log(s1, AV_LOG_ERROR, "RTP max payload size too small for AMR\n"); goto fail; } - if (st->codecpar->channels != 1) { + if (st->codecpar->ch_layout.nb_channels != 1) { av_log(s1, AV_LOG_ERROR, "Only mono is supported\n"); goto fail; } @@ -541,24 +541,24 @@ static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt) case AV_CODEC_ID_PCM_ALAW: case AV_CODEC_ID_PCM_U8: case AV_CODEC_ID_PCM_S8: - return rtp_send_samples(s1, pkt->data, size, 8 * st->codecpar->channels); + return rtp_send_samples(s1, pkt->data, size, 8 * st->codecpar->ch_layout.nb_channels); case AV_CODEC_ID_PCM_U16BE: case AV_CODEC_ID_PCM_U16LE: case AV_CODEC_ID_PCM_S16BE: case AV_CODEC_ID_PCM_S16LE: - return rtp_send_samples(s1, pkt->data, size, 16 * st->codecpar->channels); + return rtp_send_samples(s1, pkt->data, size, 16 * st->codecpar->ch_layout.nb_channels); case AV_CODEC_ID_PCM_S24BE: - return rtp_send_samples(s1, pkt->data, size, 24 * st->codecpar->channels); + return rtp_send_samples(s1, pkt->data, size, 24 * st->codecpar->ch_layout.nb_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, * the correct parameter for send_samples_bits is 8 bits per stream * clock. */ - return rtp_send_samples(s1, pkt->data, size, 8 * st->codecpar->channels); + return rtp_send_samples(s1, pkt->data, size, 8 * st->codecpar->ch_layout.nb_channels); case AV_CODEC_ID_ADPCM_G726: case AV_CODEC_ID_ADPCM_G726LE: return rtp_send_samples(s1, pkt->data, size, - st->codecpar->bits_per_coded_sample * st->codecpar->channels); + st->codecpar->bits_per_coded_sample * st->codecpar->ch_layout.nb_channels); case AV_CODEC_ID_MP2: case AV_CODEC_ID_MP3: rtp_send_mpegaudio(s1, pkt->data, size); @@ -622,9 +622,14 @@ static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt) ff_rtp_send_jpeg(s1, pkt->data, size); break; case AV_CODEC_ID_BITPACKED: - case AV_CODEC_ID_RAWVIDEO: - ff_rtp_send_raw_rfc4175 (s1, pkt->data, size); + case AV_CODEC_ID_RAWVIDEO: { + int interlaced = st->codecpar->field_order != AV_FIELD_PROGRESSIVE; + + ff_rtp_send_raw_rfc4175(s1, pkt->data, size, interlaced, 0); + if (interlaced) + ff_rtp_send_raw_rfc4175(s1, pkt->data, size, interlaced, 1); break; + } case AV_CODEC_ID_OPUS: if (size > s->max_payload_size) { av_log(s1, AV_LOG_ERROR, diff --git a/libavformat/rtpenc.h b/libavformat/rtpenc.h index 70ea85bf3..9c8ad14a5 100644 --- a/libavformat/rtpenc.h +++ b/libavformat/rtpenc.h @@ -95,7 +95,7 @@ void ff_rtp_send_vc2hq(AVFormatContext *s1, const uint8_t *buf, int size, int in void ff_rtp_send_vp8(AVFormatContext *s1, const uint8_t *buff, int size); void ff_rtp_send_vp9(AVFormatContext *s1, const uint8_t *buff, int size); void ff_rtp_send_jpeg(AVFormatContext *s1, const uint8_t *buff, int size); -void ff_rtp_send_raw_rfc4175(AVFormatContext *s1, const uint8_t *buf, int size); +void ff_rtp_send_raw_rfc4175(AVFormatContext *s1, const uint8_t *buf, int size, int interlaced, int field); const uint8_t *ff_h263_find_resync_marker_reverse(const uint8_t *av_restrict start, const uint8_t *av_restrict end); diff --git a/libavformat/rtpenc_mpv.c b/libavformat/rtpenc_mpv.c index 4b45f5177..c18c75082 100644 --- a/libavformat/rtpenc_mpv.c +++ b/libavformat/rtpenc_mpv.c @@ -20,7 +20,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavcodec/internal.h" +#include "libavcodec/startcode.h" #include "avformat.h" #include "rtpenc.h" diff --git a/libavformat/rtpenc_rfc4175.c b/libavformat/rtpenc_rfc4175.c index ea4c3705f..257d072cd 100644 --- a/libavformat/rtpenc_rfc4175.c +++ b/libavformat/rtpenc_rfc4175.c @@ -21,36 +21,40 @@ #include "avformat.h" #include "rtpenc.h" -void ff_rtp_send_raw_rfc4175(AVFormatContext *s1, const uint8_t *buf, int size) +void ff_rtp_send_raw_rfc4175(AVFormatContext *s1, const uint8_t *buf, int size, int interlaced, int field) { RTPMuxContext *s = s1->priv_data; int width = s1->streams[0]->codecpar->width; int height = s1->streams[0]->codecpar->height; int xinc, yinc, pgroup; - int field = 0; int i = 0; int offset = 0; s->timestamp = s->cur_timestamp; switch (s1->streams[0]->codecpar->format) { case AV_PIX_FMT_UYVY422: - xinc = yinc = 2; + xinc = 2; + yinc = 1 << interlaced; pgroup = 4; break; case AV_PIX_FMT_YUV422P10: - xinc = yinc = 2; + xinc = 2; + yinc = 1 << interlaced; pgroup = 5; break; case AV_PIX_FMT_YUV420P: - xinc = yinc = 4; + xinc = 4; + yinc = 1 << interlaced; pgroup = 6; break; case AV_PIX_FMT_RGB24: - xinc = yinc = 1; + xinc = 1; + yinc = 1 << interlaced; pgroup = 3; break; case AV_PIX_FMT_BGR24: - xinc = yinc = 1; + xinc = 1; + yinc = 1 << interlaced; pgroup = 3; break; default: @@ -72,7 +76,9 @@ void ff_rtp_send_raw_rfc4175(AVFormatContext *s1, const uint8_t *buf, int size) headers = dest; do { - pixels = width * xinc - offset; + int l_line; + + pixels = width - offset; length = (pixels * pgroup) / xinc; left -= head_size; @@ -90,8 +96,9 @@ void ff_rtp_send_raw_rfc4175(AVFormatContext *s1, const uint8_t *buf, int size) *dest++ = length & 0xff; /* Line No */ - *dest++ = ((i >> 8) & 0x7f) | ((field << 7) & 0x80); - *dest++ = i & 0xff; + l_line = i >> interlaced; + *dest++ = ((l_line >> 8) & 0x7f) | ((field << 7) & 0x80); + *dest++ = l_line & 0xff; if (next_line) i += yinc; cont = (left > (head_size + pgroup) && i < height) ? 0x80 : 0x00; @@ -106,16 +113,20 @@ void ff_rtp_send_raw_rfc4175(AVFormatContext *s1, const uint8_t *buf, int size) } while (cont); do { + int l_field; int l_line; int l_off; int copy_offset; length = (headers[0] << 8) | headers[1]; + l_field = (headers[2] & 0x80) >> 7; l_line = ((headers[2] & 0x7f) << 8) | headers[3]; l_off = ((headers[4] & 0x7f) << 8) | headers[5]; cont = headers[4] & 0x80; headers += head_size; + if (interlaced) + l_line = 2 * l_line + l_field; copy_offset = (l_line * width + l_off) * pgroup / xinc; if (copy_offset + length > size) break; diff --git a/libavformat/rtpenc_vp8.c b/libavformat/rtpenc_vp8.c index 671d24575..655d44517 100644 --- a/libavformat/rtpenc_vp8.c +++ b/libavformat/rtpenc_vp8.c @@ -35,7 +35,8 @@ void ff_rtp_send_vp8(AVFormatContext *s1, const uint8_t *buf, int size) // partition id 0 *s->buf_ptr++ = 0x90; *s->buf_ptr++ = 0x80; // Picture id present - *s->buf_ptr++ = s->frame_count++ & 0x7f; + *s->buf_ptr++ = ((s->frame_count & 0x7f00) >> 8) | 0x80; + *s->buf_ptr++ = s->frame_count++ & 0xff; // Calculate the number of remaining bytes header_size = s->buf_ptr - s->buf; max_packet_size = s->max_payload_size - header_size; diff --git a/libavformat/rtpproto.c b/libavformat/rtpproto.c index c92cda63b..b970901d0 100644 --- a/libavformat/rtpproto.c +++ b/libavformat/rtpproto.c @@ -68,7 +68,7 @@ typedef struct RTPContext { #define D AV_OPT_FLAG_DECODING_PARAM #define E AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { - { "ttl", "Time to live (in milliseconds, multicast only)", OFFSET(ttl), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, + { "ttl", "Time to live (multicast only)", OFFSET(ttl), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 255, .flags = D|E }, { "buffer_size", "Send/Receive buffer size (in bytes)", OFFSET(buffer_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, { "rtcp_port", "Custom rtcp port", OFFSET(rtcp_port), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, { "local_rtpport", "Local rtp port", OFFSET(local_rtpport), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index 70c18941c..f948f1d39 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/avassert.h" #include "libavutil/base64.h" #include "libavutil/bprint.h" @@ -50,6 +52,7 @@ #include "url.h" #include "rtpenc.h" #include "mpegts.h" +#include "version.h" /* Default timeout values for read packet in seconds */ #define READ_PACKET_TIMEOUT_S 10 @@ -74,7 +77,7 @@ #define COMMON_OPTS() \ { "reorder_queue_size", "set number of packets to buffer for handling of reordered packets", OFFSET(reordering_queue_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, DEC }, \ { "buffer_size", "Underlying protocol send/receive buffer size", OFFSET(buffer_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, DEC|ENC }, \ - { "pkt_size", "Underlying protocol send packet size", OFFSET(pkt_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, ENC } \ + { "pkt_size", "Underlying protocol send packet size", OFFSET(pkt_size), AV_OPT_TYPE_INT, { .i64 = 1472 }, -1, INT_MAX, ENC } \ const AVOption ff_rtsp_options[] = { @@ -323,19 +326,19 @@ static int sdp_parse_rtpmap(AVFormatContext *s, case AVMEDIA_TYPE_AUDIO: av_log(s, AV_LOG_DEBUG, "audio codec set to: %s\n", c_name); par->sample_rate = RTSP_DEFAULT_AUDIO_SAMPLERATE; - par->channels = RTSP_DEFAULT_NB_AUDIO_CHANNELS; + par->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; if (i > 0) { par->sample_rate = i; avpriv_set_pts_info(st, 32, 1, par->sample_rate); get_word_sep(buf, sizeof(buf), "/", &p); i = atoi(buf); if (i > 0) - par->channels = i; + av_channel_layout_default(&par->ch_layout, i); } av_log(s, AV_LOG_DEBUG, "audio samplerate set to: %i\n", par->sample_rate); av_log(s, AV_LOG_DEBUG, "audio channels set to: %i\n", - par->channels); + par->ch_layout.nb_channels); break; case AVMEDIA_TYPE_VIDEO: av_log(s, AV_LOG_DEBUG, "video codec set to: %s\n", c_name); @@ -840,7 +843,7 @@ int ff_rtsp_open_transport_ctx(AVFormatContext *s, RTSPStream *rtsp_st) if (CONFIG_RTSP_MUXER && s->oformat && st) { int ret = ff_rtp_chain_mux_open((AVFormatContext **)&rtsp_st->transport_priv, s, st, rtsp_st->rtp_handle, - RTSP_TCP_MAX_PACKET_SIZE, + rt->pkt_size, rtsp_st->stream_index); /* Ownership of rtp_handle is passed to the rtp mux context */ rtsp_st->rtp_handle = NULL; @@ -946,6 +949,8 @@ static void rtsp_parse_transport(AVFormatContext *s, ";,", &p); } th->transport = RTSP_TRANSPORT_RAW; + } else { + break; } if (!av_strcasecmp(lower_transport, "TCP")) th->lower_transport = RTSP_LOWER_TRANSPORT_TCP; diff --git a/libavformat/rtsp.h b/libavformat/rtsp.h index 8b64e29d7..6e500fd56 100644 --- a/libavformat/rtsp.h +++ b/libavformat/rtsp.h @@ -74,8 +74,6 @@ enum RTSPControlTransport { #define RTSP_DEFAULT_PORT 554 #define RTSPS_DEFAULT_PORT 322 #define RTSP_MAX_TRANSPORTS 8 -#define RTSP_TCP_MAX_PACKET_SIZE 1472 -#define RTSP_DEFAULT_NB_AUDIO_CHANNELS 1 #define RTSP_DEFAULT_AUDIO_SAMPLERATE 44100 #define RTSP_RTP_PORT_MIN 5000 #define RTSP_RTP_PORT_MAX 65000 diff --git a/libavformat/rtspdec.c b/libavformat/rtspdec.c index 2ada29a2d..bbabec7db 100644 --- a/libavformat/rtspdec.c +++ b/libavformat/rtspdec.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavutil/avstring.h" #include "libavutil/intreadwrite.h" #include "libavutil/mathematics.h" @@ -34,6 +36,7 @@ #include "rdt.h" #include "tls.h" #include "url.h" +#include "version.h" static const struct RTSPStatusMessage { enum RTSPStatusCode code; diff --git a/libavformat/rtspenc.c b/libavformat/rtspenc.c index 2a00b3e18..21b204381 100644 --- a/libavformat/rtspenc.c +++ b/libavformat/rtspenc.c @@ -24,6 +24,7 @@ #if HAVE_POLL_H #include #endif +#include "mux.h" #include "network.h" #include "os_support.h" #include "rtsp.h" @@ -174,7 +175,7 @@ int ff_rtsp_tcp_write_packet(AVFormatContext *s, RTSPStream *rtsp_st) size -= packet_len; } av_free(buf); - return ffio_open_dyn_packet_buf(&rtpctx->pb, RTSP_TCP_MAX_PACKET_SIZE); + return ffio_open_dyn_packet_buf(&rtpctx->pb, rt->pkt_size); } static int rtsp_write_packet(AVFormatContext *s, AVPacket *pkt) diff --git a/libavformat/samidec.c b/libavformat/samidec.c index 698164b6a..0da299343 100644 --- a/libavformat/samidec.c +++ b/libavformat/samidec.c @@ -27,10 +27,8 @@ #include "avformat.h" #include "internal.h" #include "subtitles.h" -#include "libavcodec/internal.h" #include "libavutil/avstring.h" #include "libavutil/bprint.h" -#include "libavutil/intreadwrite.h" typedef struct { FFDemuxSubtitlesQueue q; diff --git a/libavformat/sapenc.c b/libavformat/sapenc.c index 9319ee6f8..8eb9d3b92 100644 --- a/libavformat/sapenc.c +++ b/libavformat/sapenc.c @@ -27,6 +27,7 @@ #include "libavutil/intreadwrite.h" #include "libavutil/time.h" #include "internal.h" +#include "mux.h" #include "network.h" #include "os_support.h" #include "rtpenc_chain.h" diff --git a/libavformat/sbgdec.c b/libavformat/sbgdec.c index baffbbd6f..8a6d67905 100644 --- a/libavformat/sbgdec.c +++ b/libavformat/sbgdec.c @@ -1446,8 +1446,7 @@ static av_cold int sbg_read_header(AVFormatContext *avf) sti = ffstream(st); st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_FFWAVESYNTH; - st->codecpar->channels = 2; - st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; st->codecpar->sample_rate = sbg->sample_rate; st->codecpar->frame_size = sbg->frame_size; avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); diff --git a/libavformat/sccenc.c b/libavformat/sccenc.c index c8c4d097e..2b924ba6e 100644 --- a/libavformat/sccenc.c +++ b/libavformat/sccenc.c @@ -72,11 +72,11 @@ static int scc_write_packet(AVFormatContext *avf, AVPacket *pkt) s = (int)(pts / 1000) % 60; f = (int)(pts % 1000) / 33; - for (i = 0; i < pkt->size; i+=3) { + for (i = 0; i < pkt->size - 2; i+=3) { if (pkt->data[i] == 0xfc && ((pkt->data[i + 1] != 0x80 || pkt->data[i + 2] != 0x80))) break; } - if (i >= pkt->size) + if (i >= pkt->size - 2) return 0; if (!scc->inside && (scc->prev_h != h || scc->prev_m != m || scc->prev_s != s || scc->prev_f != f)) { diff --git a/libavformat/scd.c b/libavformat/scd.c index 0ed5322a1..91b2262ff 100644 --- a/libavformat/scd.c +++ b/libavformat/scd.c @@ -194,7 +194,7 @@ static int scd_read_track(AVFormatContext *s, SCDTrackHeader *track, int index) par = st->codecpar; par->codec_type = AVMEDIA_TYPE_AUDIO; - par->channels = (int)track->num_channels; + par->ch_layout.nb_channels = (int)track->num_channels; par->sample_rate = (int)track->sample_rate; st->index = index; st->start_time = 0; @@ -218,7 +218,7 @@ static int scd_read_track(AVFormatContext *s, SCDTrackHeader *track, int index) case SCD_TRACK_ID_PCM: par->codec_id = AV_CODEC_ID_PCM_S16BE; par->bits_per_coded_sample = 16; - par->block_align = par->bits_per_coded_sample * par->channels / 8; + par->block_align = par->bits_per_coded_sample * par->ch_layout.nb_channels / 8; break; case SCD_TRACK_ID_MP3: par->codec_id = AV_CODEC_ID_MP3; @@ -325,8 +325,8 @@ static int scd_read_packet(AVFormatContext *s, AVPacket *pkt) } if (trk->data_type == SCD_TRACK_ID_PCM) { - pkt->pts = trk->bytes_read / (par->channels * sizeof(uint16_t)); - pkt->duration = size / (par->channels * sizeof(int16_t)); + pkt->pts = trk->bytes_read / (par->ch_layout.nb_channels * sizeof(uint16_t)); + pkt->duration = size / (par->ch_layout.nb_channels * sizeof(int16_t)); } trk->bytes_read += ret; diff --git a/libavformat/sctp.c b/libavformat/sctp.c index 9a80e9b01..9d9e90097 100644 --- a/libavformat/sctp.c +++ b/libavformat/sctp.c @@ -220,7 +220,7 @@ static int sctp_open(URLContext *h, const char *uri, int flags) cur_ai = ai; restart: - fd = ff_socket(cur_ai->ai_family, SOCK_STREAM, IPPROTO_SCTP); + fd = ff_socket(cur_ai->ai_family, SOCK_STREAM, IPPROTO_SCTP, h); if (fd < 0) { ret = ff_neterrno(); goto fail; @@ -282,6 +282,8 @@ fail: goto restart; } fail1: + if (fd >= 0) + closesocket(fd); ret = AVERROR(EIO); freeaddrinfo(ai); return ret; diff --git a/libavformat/sdp.c b/libavformat/sdp.c index 2230d7474..99a19852f 100644 --- a/libavformat/sdp.c +++ b/libavformat/sdp.c @@ -18,6 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include #include "libavutil/avstring.h" #include "libavutil/base64.h" @@ -450,16 +452,16 @@ static int latm_context2profilelevel(const AVCodecParameters *par) * Different Object Types should implement different Profile Levels */ if (par->sample_rate <= 24000) { - if (par->channels <= 2) + if (par->ch_layout.nb_channels <= 2) profile_level = 0x28; // AAC Profile, Level 1 } else if (par->sample_rate <= 48000) { - if (par->channels <= 2) { + if (par->ch_layout.nb_channels <= 2) { profile_level = 0x29; // AAC Profile, Level 2 - } else if (par->channels <= 5) { + } else if (par->ch_layout.nb_channels <= 5) { profile_level = 0x2A; // AAC Profile, Level 4 } } else if (par->sample_rate <= 96000) { - if (par->channels <= 5) { + if (par->ch_layout.nb_channels <= 5) { profile_level = 0x2B; // AAC Profile, Level 5 } } @@ -491,7 +493,7 @@ static int latm_context2config(AVFormatContext *s, const AVCodecParameters *par, config_byte[0] = 0x40; config_byte[1] = 0; config_byte[2] = 0x20 | rate_index; - config_byte[3] = par->channels << 4; + config_byte[3] = par->ch_layout.nb_channels << 4; config_byte[4] = 0x3f; config_byte[5] = 0xc0; @@ -591,7 +593,7 @@ static int sdp_write_media_attributes(char *buff, int size, const AVStream *st, return ret; av_strlcatf(buff, size, "a=rtpmap:%d MP4A-LATM/%d/%d\r\n" "a=fmtp:%d profile-level-id=%d;cpresent=0;config=%s\r\n", - payload_type, p->sample_rate, p->channels, + payload_type, p->sample_rate, p->ch_layout.nb_channels, payload_type, latm_context2profilelevel(p), config); } else { if (p->extradata_size) { @@ -609,7 +611,7 @@ static int sdp_write_media_attributes(char *buff, int size, const AVStream *st, "a=fmtp:%d profile-level-id=1;" "mode=AAC-hbr;sizelength=13;indexlength=3;" "indexdeltalength=3%s\r\n", - payload_type, p->sample_rate, p->channels, + payload_type, p->sample_rate, p->ch_layout.nb_channels, payload_type, config); } break; @@ -617,36 +619,36 @@ static int sdp_write_media_attributes(char *buff, int size, const AVStream *st, if (payload_type >= RTP_PT_PRIVATE) av_strlcatf(buff, size, "a=rtpmap:%d L16/%d/%d\r\n", payload_type, - p->sample_rate, p->channels); + p->sample_rate, p->ch_layout.nb_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); + p->sample_rate, p->ch_layout.nb_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", payload_type, - p->sample_rate, p->channels); + p->sample_rate, p->ch_layout.nb_channels); break; case AV_CODEC_ID_PCM_ALAW: if (payload_type >= RTP_PT_PRIVATE) av_strlcatf(buff, size, "a=rtpmap:%d PCMA/%d/%d\r\n", payload_type, - p->sample_rate, p->channels); + p->sample_rate, p->ch_layout.nb_channels); break; case AV_CODEC_ID_AMR_NB: av_strlcatf(buff, size, "a=rtpmap:%d AMR/%d/%d\r\n" "a=fmtp:%d octet-align=1\r\n", - payload_type, p->sample_rate, p->channels, + payload_type, p->sample_rate, p->ch_layout.nb_channels, payload_type); break; case AV_CODEC_ID_AMR_WB: av_strlcatf(buff, size, "a=rtpmap:%d AMR-WB/%d/%d\r\n" "a=fmtp:%d octet-align=1\r\n", - payload_type, p->sample_rate, p->channels, + payload_type, p->sample_rate, p->ch_layout.nb_channels, payload_type); break; case AV_CODEC_ID_VORBIS: @@ -661,7 +663,7 @@ static int sdp_write_media_attributes(char *buff, int size, const AVStream *st, av_strlcatf(buff, size, "a=rtpmap:%d vorbis/%d/%d\r\n" "a=fmtp:%d configuration=%s\r\n", - payload_type, p->sample_rate, p->channels, + payload_type, p->sample_rate, p->ch_layout.nb_channels, payload_type, config); break; case AV_CODEC_ID_THEORA: { @@ -728,9 +730,12 @@ static int sdp_write_media_attributes(char *buff, int size, const AVStream *st, av_strlcatf(buff, size, "a=rtpmap:%d raw/90000\r\n" "a=fmtp:%d sampling=%s; " "width=%d; height=%d; " - "depth=%d\r\n", + "depth=%d", payload_type, payload_type, pix_fmt, p->width, p->height, bit_depth); + if (p->field_order != AV_FIELD_PROGRESSIVE) + av_strlcatf(buff, size, "; interlace"); + av_strlcatf(buff, size, "\r\n"); break; } @@ -751,7 +756,7 @@ static int sdp_write_media_attributes(char *buff, int size, const AVStream *st, if (payload_type >= RTP_PT_PRIVATE) av_strlcatf(buff, size, "a=rtpmap:%d G722/%d/%d\r\n", payload_type, - 8000, p->channels); + 8000, p->ch_layout.nb_channels); break; case AV_CODEC_ID_ADPCM_G726: { if (payload_type >= RTP_PT_PRIVATE) @@ -788,7 +793,7 @@ static int sdp_write_media_attributes(char *buff, int size, const AVStream *st, receivers MUST be able to receive and process stereo packets. */ av_strlcatf(buff, size, "a=rtpmap:%d opus/48000/2\r\n", payload_type); - if (p->channels == 2) { + if (p->ch_layout.nb_channels == 2) { av_strlcatf(buff, size, "a=fmtp:%d sprop-stereo=1\r\n", payload_type); } diff --git a/libavformat/sdr2.c b/libavformat/sdr2.c index 679933942..3023d5f7d 100644 --- a/libavformat/sdr2.c +++ b/libavformat/sdr2.c @@ -54,7 +54,7 @@ static int sdr2_read_header(AVFormatContext *s) ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL; ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; - ast->codecpar->channels = 1; + ast->codecpar->ch_layout.nb_channels = 1; ast->codecpar->sample_rate = 8000; ast->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE; avpriv_set_pts_info(ast, 64, 1, 8000); diff --git a/libavformat/sdsdec.c b/libavformat/sdsdec.c index 073dadafb..f98096dca 100644 --- a/libavformat/sdsdec.c +++ b/libavformat/sdsdec.c @@ -110,7 +110,7 @@ static int sds_read_header(AVFormatContext *ctx) avio_skip(pb, 11); st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; - st->codecpar->channels = 1; + st->codecpar->ch_layout.nb_channels = 1; st->codecpar->sample_rate = sample_period ? 1000000000 / sample_period : 16000; st->duration = (avio_size(pb) - 21) / (127) * s->size / 4; diff --git a/libavformat/sdxdec.c b/libavformat/sdxdec.c index 76fd2caa0..562827892 100644 --- a/libavformat/sdxdec.c +++ b/libavformat/sdxdec.c @@ -54,7 +54,7 @@ static int sdx_read_header(AVFormatContext *s) return AVERROR(ENOMEM); st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; - st->codecpar->channels = 1; + st->codecpar->ch_layout.nb_channels = 1; st->codecpar->sample_rate = avio_rl32(s->pb); switch (depth) { case 8: diff --git a/libavformat/seek.c b/libavformat/seek.c index 405ca316b..3b1c75f1b 100644 --- a/libavformat/seek.c +++ b/libavformat/seek.c @@ -27,6 +27,7 @@ #include "avformat.h" #include "avio_internal.h" +#include "demux.h" #include "internal.h" void avpriv_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp) @@ -751,3 +752,13 @@ int avformat_flush(AVFormatContext *s) ff_read_frame_flush(s); return 0; } + +void ff_rescale_interval(AVRational tb_in, AVRational tb_out, + int64_t *min_ts, int64_t *ts, int64_t *max_ts) +{ + *ts = av_rescale_q (* ts, tb_in, tb_out); + *min_ts = av_rescale_q_rnd(*min_ts, tb_in, tb_out, + AV_ROUND_UP | AV_ROUND_PASS_MINMAX); + *max_ts = av_rescale_q_rnd(*max_ts, tb_in, tb_out, + AV_ROUND_DOWN | AV_ROUND_PASS_MINMAX); +} diff --git a/libavformat/segafilm.c b/libavformat/segafilm.c index 3af7518d0..4c6b68426 100644 --- a/libavformat/segafilm.c +++ b/libavformat/segafilm.c @@ -177,20 +177,20 @@ static int film_read_header(AVFormatContext *s) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = film->audio_type; st->codecpar->codec_tag = 1; - st->codecpar->channels = film->audio_channels; + st->codecpar->ch_layout.nb_channels = film->audio_channels; st->codecpar->sample_rate = film->audio_samplerate; if (film->audio_type == AV_CODEC_ID_ADPCM_ADX) { st->codecpar->bits_per_coded_sample = 18 * 8 / 32; - st->codecpar->block_align = st->codecpar->channels * 18; + st->codecpar->block_align = film->audio_channels * 18; ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL; } else { st->codecpar->bits_per_coded_sample = film->audio_bits; - st->codecpar->block_align = st->codecpar->channels * + st->codecpar->block_align = film->audio_channels * st->codecpar->bits_per_coded_sample / 8; } - st->codecpar->bit_rate = st->codecpar->channels * st->codecpar->sample_rate * + st->codecpar->bit_rate = film->audio_channels * st->codecpar->sample_rate * st->codecpar->bits_per_coded_sample; } diff --git a/libavformat/segafilmenc.c b/libavformat/segafilmenc.c index 737805faa..42d56fccd 100644 --- a/libavformat/segafilmenc.c +++ b/libavformat/segafilmenc.c @@ -33,8 +33,8 @@ #include "libavutil/intreadwrite.h" #include "libavcodec/bytestream.h" #include "avformat.h" -#include "internal.h" #include "avio_internal.h" +#include "mux.h" typedef struct FILMOutputContext { AVIOContext *header; @@ -236,7 +236,7 @@ static int film_write_header(AVFormatContext *format_context) AVStream *audio = format_context->streams[film->audio_index]; int audio_codec = get_audio_codec_id(audio->codecpar->codec_id); - bytestream_put_byte(&ptr, audio->codecpar->channels); /* Audio channels */ + bytestream_put_byte(&ptr, audio->codecpar->ch_layout.nb_channels); /* Audio channels */ bytestream_put_byte(&ptr, audio->codecpar->bits_per_coded_sample); /* Audio bit depth */ bytestream_put_byte(&ptr, audio_codec); /* Compression - 0 is PCM, 2 is ADX */ bytestream_put_be16(&ptr, audio->codecpar->sample_rate); /* Audio sampling rate */ diff --git a/libavformat/segment.c b/libavformat/segment.c index e9b0aa4fa..fa435d9f3 100644 --- a/libavformat/segment.c +++ b/libavformat/segment.c @@ -24,12 +24,13 @@ * @url{http://tools.ietf.org/id/draft-pantos-http-live-streaming} */ -#include +#include "config_components.h" + #include #include "avformat.h" -#include "avio_internal.h" #include "internal.h" +#include "mux.h" #include "libavutil/avassert.h" #include "libavutil/internal.h" diff --git a/libavformat/sga.c b/libavformat/sga.c index 16e8fe516..12e9cc144 100644 --- a/libavformat/sga.c +++ b/libavformat/sga.c @@ -323,8 +323,7 @@ static int sga_audio_packet(AVFormatContext *s, AVPacket *pkt) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_tag = 0; st->codecpar->codec_id = AV_CODEC_ID_PCM_SGA; - st->codecpar->channels = 1; - st->codecpar->channel_layout= AV_CH_LAYOUT_MONO; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; st->codecpar->sample_rate = av_rescale(AV_RB16(sga->sector + 8), SEGA_CD_PCM_NUM, SEGA_CD_PCM_DEN); diff --git a/libavformat/sierravmd.c b/libavformat/sierravmd.c index e35faae50..d110457ec 100644 --- a/libavformat/sierravmd.c +++ b/libavformat/sierravmd.c @@ -134,6 +134,7 @@ static int vmd_read_header(AVFormatContext *s) /* if sample rate is 0, assume no audio */ vmd->sample_rate = AV_RL16(&vmd->vmd_header[804]); if (vmd->sample_rate) { + int channels; st = avformat_new_stream(s, NULL); if (!st) return AVERROR(ENOMEM); @@ -150,24 +151,22 @@ static int vmd_read_header(AVFormatContext *s) st->codecpar->bits_per_coded_sample = 8; } if (vmd->vmd_header[811] & 0x80) { - st->codecpar->channels = 2; - st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; + channels = 2; } else if (vmd->vmd_header[811] & 0x2) { /* Shivers 2 stereo audio */ /* Frame length is for 1 channel */ - st->codecpar->channels = 2; - st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; + channels = 2; st->codecpar->block_align = st->codecpar->block_align << 1; } else { - st->codecpar->channels = 1; - st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + channels = 1; } + av_channel_layout_default(&st->codecpar->ch_layout, channels); st->codecpar->bit_rate = st->codecpar->sample_rate * - st->codecpar->bits_per_coded_sample * st->codecpar->channels; + st->codecpar->bits_per_coded_sample * channels; /* calculate pts */ num = st->codecpar->block_align; - den = st->codecpar->sample_rate * st->codecpar->channels; + den = st->codecpar->sample_rate * channels; av_reduce(&num, &den, num, den, (1UL<<31)-1); if (vst) avpriv_set_pts_info(vst, 33, num, den); diff --git a/libavformat/siff.c b/libavformat/siff.c index a34de24ec..99756574b 100644 --- a/libavformat/siff.c +++ b/libavformat/siff.c @@ -80,8 +80,7 @@ static int create_audio_stream(AVFormatContext *s, SIFFContext *c) return AVERROR(ENOMEM); ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; ast->codecpar->codec_id = AV_CODEC_ID_PCM_U8; - ast->codecpar->channels = 1; - ast->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + ast->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; ast->codecpar->bits_per_coded_sample = 8; ast->codecpar->sample_rate = c->rate; avpriv_set_pts_info(ast, 16, 1, c->rate); diff --git a/libavformat/smacker.c b/libavformat/smacker.c index 98436bd70..1d54e8e91 100644 --- a/libavformat/smacker.c +++ b/libavformat/smacker.c @@ -29,6 +29,7 @@ #include "libavutil/intreadwrite.h" #include "avformat.h" #include "avio_internal.h" +#include "demux.h" #include "internal.h" #define SMACKER_PAL 0x01 @@ -94,6 +95,7 @@ static int smacker_read_header(AVFormatContext *s) AVStream *st; AVCodecParameters *par; uint32_t magic, width, height, flags, treesize; + int64_t pos; int i, ret, pts_inc; int tbase; @@ -186,13 +188,8 @@ static int smacker_read_header(AVFormatContext *s) } else { par->codec_id = AV_CODEC_ID_PCM_U8; } - if (aflag & SMK_AUD_STEREO) { - par->channels = 2; - par->channel_layout = AV_CH_LAYOUT_STEREO; - } else { - par->channels = 1; - par->channel_layout = AV_CH_LAYOUT_MONO; - } + av_channel_layout_default(&par->ch_layout, + !!(aflag & SMK_AUD_STEREO) + 1); par->sample_rate = rate; par->bits_per_coded_sample = (aflag & SMK_AUD_16BITS) ? 16 : 8; if (par->bits_per_coded_sample == 16 && @@ -200,7 +197,7 @@ static int smacker_read_header(AVFormatContext *s) par->codec_id = AV_CODEC_ID_PCM_S16LE; else smk->duration_size[i] = 4; - avpriv_set_pts_info(ast, 64, 1, par->sample_rate * par->channels + avpriv_set_pts_info(ast, 64, 1, par->sample_rate * par->ch_layout.nb_channels * par->bits_per_coded_sample / 8); } } @@ -216,8 +213,13 @@ static int smacker_read_header(AVFormatContext *s) smk->frm_flags = (void*)(smk->frm_size + smk->frames); /* read frame info */ + pos = 0; for (i = 0; i < smk->frames; i++) { smk->frm_size[i] = avio_rl32(pb); + if ((ret = av_add_index_entry(st, pos, i, smk->frm_size[i], 0, + (i == 0 || (smk->frm_size[i] & 1)) ? AVINDEX_KEYFRAME : 0)) < 0) + return ret; + pos += smk->frm_size[i]; } if ((ret = ffio_read_size(pb, smk->frm_flags, smk->frames)) < 0 || /* load trees to extradata, they will be unpacked by decoder */ @@ -340,7 +342,7 @@ static int smacker_read_packet(AVFormatContext *s, AVPacket *pkt) if ((ret = av_new_packet(pkt, smk->frame_size + 769)) < 0) goto next_frame; flags = smk->new_palette; - if (smk->frm_size[smk->cur_frame] & 1) + if ((smk->frm_size[smk->cur_frame] & 1) || smk->cur_frame == 0) flags |= 2; pkt->data[0] = flags; memcpy(pkt->data + 1, smk->pal, 768); @@ -349,6 +351,9 @@ static int smacker_read_packet(AVFormatContext *s, AVPacket *pkt) goto next_frame; pkt->stream_index = smk->videoindex; pkt->pts = smk->cur_frame; + pkt->duration = 1; + if (flags & 2) + pkt->flags |= AV_PKT_FLAG_KEY; smk->next_audio_index = 0; smk->new_palette = 0; smk->cur_frame++; @@ -364,20 +369,28 @@ next_frame: static int smacker_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) { + AVStream *st = s->streams[stream_index]; SmackerContext *smk = s->priv_data; - int64_t ret; + int64_t pos; + int ret; - /* only rewinding to start is supported */ - if (timestamp != 0) { - av_log(s, AV_LOG_ERROR, - "Random seeks are not supported (can only seek to start).\n"); + if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) + return -1; + + if (timestamp < 0 || timestamp >= smk->frames) return AVERROR(EINVAL); - } - if ((ret = avio_seek(s->pb, ffformatcontext(s)->data_offset, SEEK_SET)) < 0) + ret = av_index_search_timestamp(st, timestamp, flags); + if (ret < 0) return ret; - smk->cur_frame = 0; + pos = ffformatcontext(s)->data_offset; + pos += ffstream(st)->index_entries[ret].pos; + pos = avio_seek(s->pb, pos, SEEK_SET); + if (pos < 0) + return pos; + + smk->cur_frame = ret; smk->next_audio_index = 0; smk->new_palette = 0; memset(smk->pal, 0, sizeof(smk->pal)); diff --git a/libavformat/smjpegdec.c b/libavformat/smjpegdec.c index dc95a822c..02d0f29b9 100644 --- a/libavformat/smjpegdec.c +++ b/libavformat/smjpegdec.c @@ -94,7 +94,7 @@ static int smjpeg_read_header(AVFormatContext *s) ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; ast->codecpar->sample_rate = avio_rb16(pb); ast->codecpar->bits_per_coded_sample = avio_r8(pb); - ast->codecpar->channels = avio_r8(pb); + ast->codecpar->ch_layout.nb_channels = avio_r8(pb); ast->codecpar->codec_tag = avio_rl32(pb); ast->codecpar->codec_id = ff_codec_get_id(ff_codec_smjpeg_audio_tags, ast->codecpar->codec_tag); diff --git a/libavformat/smjpegenc.c b/libavformat/smjpegenc.c index ac5576fa7..888ece2f7 100644 --- a/libavformat/smjpegenc.c +++ b/libavformat/smjpegenc.c @@ -26,6 +26,7 @@ #include "avformat.h" #include "internal.h" +#include "mux.h" #include "smjpeg.h" typedef struct SMJPEGMuxContext { @@ -68,7 +69,7 @@ static int smjpeg_write_header(AVFormatContext *s) avio_wb32(pb, 8); avio_wb16(pb, par->sample_rate); avio_w8(pb, par->bits_per_coded_sample); - avio_w8(pb, par->channels); + avio_w8(pb, par->ch_layout.nb_channels); avio_wl32(pb, tag); avpriv_set_pts_info(st, 32, 1, 1000); } else if (par->codec_type == AVMEDIA_TYPE_VIDEO) { diff --git a/libavformat/smoothstreamingenc.c b/libavformat/smoothstreamingenc.c index a0ea5b8fa..ade6d5723 100644 --- a/libavformat/smoothstreamingenc.c +++ b/libavformat/smoothstreamingenc.c @@ -20,24 +20,21 @@ */ #include "config.h" -#include #if HAVE_UNISTD_H #include #endif #include "avformat.h" -#include "avio_internal.h" #include "internal.h" +#include "mux.h" #include "os_support.h" #include "avc.h" #include "url.h" -#include "isom.h" #include "libavutil/opt.h" #include "libavutil/avstring.h" -#include "libavutil/file.h" #include "libavutil/mathematics.h" -#include "libavutil/intreadwrite.h" +#include "libavutil/uuid.h" typedef struct Fragment { int64_t start_time, duration; @@ -267,7 +264,9 @@ static int write_manifest(AVFormatContext *s, int final) if (s->streams[i]->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) continue; last = i; - avio_printf(out, "\n", index, s->streams[i]->codecpar->bit_rate, os->fourcc, s->streams[i]->codecpar->sample_rate, s->streams[i]->codecpar->channels, os->packet_size, os->audio_tag, os->private_str); + avio_printf(out, "\n", + index, s->streams[i]->codecpar->bit_rate, os->fourcc, s->streams[i]->codecpar->sample_rate, + s->streams[i]->codecpar->ch_layout.nb_channels, os->packet_size, os->audio_tag, os->private_str); index++; } output_chunk_list(&c->streams[last], out, final, c->lookahead_count, c->window_size); @@ -418,13 +417,13 @@ static int parse_fragment(AVFormatContext *s, const char *filename, int64_t *sta if (len < 8 || len >= *moof_size) goto fail; if (tag == MKTAG('u','u','i','d')) { - static const uint8_t tfxd[] = { + static const AVUUID tfxd = { 0x6d, 0x1d, 0x9b, 0x05, 0x42, 0xd5, 0x44, 0xe6, 0x80, 0xe2, 0x14, 0x1d, 0xaf, 0xf7, 0x57, 0xb2 }; - uint8_t uuid[16]; + AVUUID uuid; avio_read(in, uuid, 16); - if (!memcmp(uuid, tfxd, 16) && len >= 8 + 16 + 4 + 16) { + if (av_uuid_equal(uuid, tfxd) && len >= 8 + 16 + 4 + 16) { avio_seek(in, 4, SEEK_CUR); *start_ts = avio_rb64(in); *duration = avio_rb64(in); diff --git a/libavformat/smush.c b/libavformat/smush.c index 59807ab96..f133bbb02 100644 --- a/libavformat/smush.c +++ b/libavformat/smush.c @@ -178,8 +178,7 @@ static int smush_read_header(AVFormatContext *ctx) ast->codecpar->codec_id = AV_CODEC_ID_ADPCM_VIMA; ast->codecpar->codec_tag = 0; ast->codecpar->sample_rate = sample_rate; - ast->codecpar->channels = channels; - + ast->codecpar->ch_layout.nb_channels = channels; avpriv_set_pts_info(ast, 64, 1, ast->codecpar->sample_rate); } diff --git a/libavformat/sol.c b/libavformat/sol.c index 42498492b..b92cfb36f 100644 --- a/libavformat/sol.c +++ b/libavformat/sol.c @@ -113,9 +113,7 @@ static int sol_read_header(AVFormatContext *s) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_tag = id; st->codecpar->codec_id = codec; - st->codecpar->channels = channels; - st->codecpar->channel_layout = channels == 1 ? AV_CH_LAYOUT_MONO : - AV_CH_LAYOUT_STEREO; + av_channel_layout_default(&st->codecpar->ch_layout,channels); st->codecpar->sample_rate = rate; avpriv_set_pts_info(st, 64, 1, rate); return 0; diff --git a/libavformat/soxdec.c b/libavformat/soxdec.c index 83fb5e375..10bea2523 100644 --- a/libavformat/soxdec.c +++ b/libavformat/soxdec.c @@ -49,6 +49,7 @@ static int sox_read_header(AVFormatContext *s) AVIOContext *pb = s->pb; unsigned header_size, comment_size; double sample_rate, sample_rate_frac; + int channels; AVStream *st; st = avformat_new_stream(s, NULL); @@ -62,17 +63,19 @@ static int sox_read_header(AVFormatContext *s) header_size = avio_rl32(pb); avio_skip(pb, 8); /* sample count */ sample_rate = av_int2double(avio_rl64(pb)); - st->codecpar->channels = avio_rl32(pb); + channels = avio_rl32(pb); comment_size = avio_rl32(pb); } else { st->codecpar->codec_id = AV_CODEC_ID_PCM_S32BE; header_size = avio_rb32(pb); avio_skip(pb, 8); /* sample count */ sample_rate = av_int2double(avio_rb64(pb)); - st->codecpar->channels = avio_rb32(pb); + channels = avio_rb32(pb); comment_size = avio_rb32(pb); } + st->codecpar->ch_layout.nb_channels = channels; + if (comment_size > 0xFFFFFFFFU - SOX_FIXED_HDR - 4U) { av_log(s, AV_LOG_ERROR, "invalid comment size (%u)\n", comment_size); return AVERROR_INVALIDDATA; @@ -90,7 +93,7 @@ static int sox_read_header(AVFormatContext *s) sample_rate_frac); if ((header_size + 4) & 7 || header_size < SOX_FIXED_HDR + comment_size - || st->codecpar->channels > 65535 || st->codecpar->channels <= 0) /* Reserve top 16 bits */ { + || channels > 65535 || channels <= 0) /* Reserve top 16 bits */ { av_log(s, AV_LOG_ERROR, "invalid header\n"); return AVERROR_INVALIDDATA; } @@ -115,9 +118,9 @@ static int sox_read_header(AVFormatContext *s) st->codecpar->bits_per_coded_sample = 32; st->codecpar->bit_rate = (int64_t)st->codecpar->sample_rate * st->codecpar->bits_per_coded_sample * - st->codecpar->channels; + channels; st->codecpar->block_align = st->codecpar->bits_per_coded_sample * - st->codecpar->channels / 8; + channels / 8; avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); diff --git a/libavformat/soxenc.c b/libavformat/soxenc.c index e24501bac..ac01f97df 100644 --- a/libavformat/soxenc.c +++ b/libavformat/soxenc.c @@ -61,14 +61,14 @@ static int sox_write_header(AVFormatContext *s) avio_wl32(pb, sox->header_size); avio_wl64(pb, 0); /* number of samples */ avio_wl64(pb, av_double2int(par->sample_rate)); - avio_wl32(pb, par->channels); + avio_wl32(pb, par->ch_layout.nb_channels); avio_wl32(pb, comment_size); } else if (par->codec_id == AV_CODEC_ID_PCM_S32BE) { ffio_wfourcc(pb, "XoS."); avio_wb32(pb, sox->header_size); avio_wb64(pb, 0); /* number of samples */ avio_wb64(pb, av_double2int(par->sample_rate)); - avio_wb32(pb, par->channels); + avio_wb32(pb, par->ch_layout.nb_channels); avio_wb32(pb, comment_size); } else { av_log(s, AV_LOG_ERROR, "invalid codec; use pcm_s32le or pcm_s32be\n"); diff --git a/libavformat/spdifdec.c b/libavformat/spdifdec.c index e39a30424..2af75ca9d 100644 --- a/libavformat/spdifdec.c +++ b/libavformat/spdifdec.c @@ -27,7 +27,7 @@ #include "libavutil/bswap.h" -#include "libavcodec/ac3.h" +#include "libavcodec/ac3defs.h" #include "libavcodec/adts_parser.h" #include "avformat.h" diff --git a/libavformat/spdifenc.c b/libavformat/spdifenc.c index 3be89328d..7b8e231cf 100644 --- a/libavformat/spdifenc.c +++ b/libavformat/spdifenc.c @@ -49,7 +49,7 @@ #include "avformat.h" #include "avio_internal.h" #include "spdif.h" -#include "libavcodec/ac3.h" +#include "libavcodec/ac3defs.h" #include "libavcodec/adts_parser.h" #include "libavcodec/dca.h" #include "libavcodec/dca_syncwords.h" @@ -63,7 +63,7 @@ typedef struct IEC61937Context { uint8_t *buffer; ///< allocated buffer, used for swap bytes int buffer_size; ///< size of allocated buffer - uint8_t *out_buf; ///< pointer to the outgoing data before byte-swapping + const uint8_t *out_buf; ///< pointer to the outgoing data before byte-swapping int out_bytes; ///< amount of outgoing bytes int use_preamble; ///< preamble enabled (disabled for exactly pre-padded DTS) @@ -657,7 +657,7 @@ static int spdif_write_packet(struct AVFormatContext *s, AVPacket *pkt) av_fast_malloc(&ctx->buffer, &ctx->buffer_size, ctx->out_bytes + AV_INPUT_BUFFER_PADDING_SIZE); if (!ctx->buffer) return AVERROR(ENOMEM); - ff_spdif_bswap_buf16((uint16_t *)ctx->buffer, (uint16_t *)ctx->out_buf, ctx->out_bytes >> 1); + ff_spdif_bswap_buf16((uint16_t *)ctx->buffer, (const uint16_t *)ctx->out_buf, ctx->out_bytes >> 1); avio_write(s->pb, ctx->buffer, ctx->out_bytes & ~1); } diff --git a/libavformat/subviewerdec.c b/libavformat/subviewerdec.c index bcd103bd8..e3a950fce 100644 --- a/libavformat/subviewerdec.c +++ b/libavformat/subviewerdec.c @@ -28,7 +28,6 @@ #include "internal.h" #include "subtitles.h" #include "avio_internal.h" -#include "libavcodec/internal.h" #include "libavutil/avstring.h" #include "libavutil/bprint.h" #include "libavutil/intreadwrite.h" diff --git a/libavformat/supenc.c b/libavformat/supenc.c index 1ca19fa16..c45d8a532 100644 --- a/libavformat/supenc.c +++ b/libavformat/supenc.c @@ -27,7 +27,7 @@ static int sup_write_packet(AVFormatContext *s, AVPacket *pkt) { - uint8_t *data = pkt->data; + const uint8_t *data = pkt->data; size_t size = pkt->size; uint32_t pts = 0, dts = 0; diff --git a/libavformat/svag.c b/libavformat/svag.c index 0774eae11..45d04727f 100644 --- a/libavformat/svag.c +++ b/libavformat/svag.c @@ -47,14 +47,15 @@ static int svag_read_header(AVFormatContext *s) st->codecpar->sample_rate = avio_rl32(s->pb); if (st->codecpar->sample_rate <= 0) return AVERROR_INVALIDDATA; - st->codecpar->channels = avio_rl32(s->pb); - if (st->codecpar->channels <= 0 || st->codecpar->channels > 8) + st->codecpar->ch_layout.nb_channels = avio_rl32(s->pb); + if (st->codecpar->ch_layout.nb_channels <= 0 || + st->codecpar->ch_layout.nb_channels > 8) return AVERROR_INVALIDDATA; - st->duration = size / (16 * st->codecpar->channels) * 28; + st->duration = size / (16 * st->codecpar->ch_layout.nb_channels) * 28; align = avio_rl32(s->pb); - if (align <= 0 || align > INT_MAX / st->codecpar->channels) + if (align <= 0 || align > INT_MAX / st->codecpar->ch_layout.nb_channels) return AVERROR_INVALIDDATA; - st->codecpar->block_align = align * st->codecpar->channels; + st->codecpar->block_align = align * st->codecpar->ch_layout.nb_channels; avio_skip(s->pb, 0x800 - avio_tell(s->pb)); avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); diff --git a/libavformat/svs.c b/libavformat/svs.c index e5300203f..b91d29f5a 100644 --- a/libavformat/svs.c +++ b/libavformat/svs.c @@ -53,8 +53,7 @@ static int svs_read_header(AVFormatContext *s) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_ADPCM_PSX; - st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; - st->codecpar->channels = 2; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; st->codecpar->sample_rate = av_rescale_rnd(pitch, 48000, 4096, AV_ROUND_INF); st->codecpar->block_align = 32; st->start_time = 0; diff --git a/libavformat/swfdec.c b/libavformat/swfdec.c index e549e4f50..716c95a74 100644 --- a/libavformat/swfdec.c +++ b/libavformat/swfdec.c @@ -32,6 +32,7 @@ #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" #include "libavcodec/get_bits.h" +#include "demux.h" #include "swf.h" #include "flv.h" @@ -195,13 +196,7 @@ static AVStream *create_new_audio_stream(AVFormatContext *s, int id, int info) if (!ast) return NULL; ast->id = id; - if (info & 1) { - ast->codecpar->channels = 2; - ast->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; - } else { - ast->codecpar->channels = 1; - ast->codecpar->channel_layout = AV_CH_LAYOUT_MONO; - } + av_channel_layout_default(&ast->codecpar->ch_layout, 1 + (info & 1)); ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; ast->codecpar->codec_id = ff_codec_get_id(swf_audio_codec_tags, info>>4 & 15); ffstream(ast)->need_parsing = AVSTREAM_PARSE_FULL; diff --git a/libavformat/swfenc.c b/libavformat/swfenc.c index 1fd2ad81a..75b892087 100644 --- a/libavformat/swfenc.c +++ b/libavformat/swfenc.c @@ -20,6 +20,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include "libavcodec/put_bits.h" #include "libavutil/avassert.h" #include "libavutil/fifo.h" @@ -38,7 +40,7 @@ typedef struct SWFEncContext { int swf_frame_number; int video_frame_number; int tag; - AVFifoBuffer *audio_fifo; + AVFifo *audio_fifo; AVCodecParameters *audio_par, *video_par; AVStream *video_st; } SWFEncContext; @@ -211,7 +213,7 @@ static int swf_write_header(AVFormatContext *s) } if (par->codec_id == AV_CODEC_ID_MP3) { swf->audio_par = par; - swf->audio_fifo= av_fifo_alloc(AUDIO_FIFO_SIZE); + swf->audio_fifo = av_fifo_alloc2(AUDIO_FIFO_SIZE, 1, 0); if (!swf->audio_fifo) return AVERROR(ENOMEM); } else { @@ -348,7 +350,7 @@ static int swf_write_header(AVFormatContext *s) return -1; } v |= 0x02; /* 16 bit playback */ - if (swf->audio_par->channels == 2) + if (swf->audio_par->ch_layout.nb_channels == 2) v |= 0x01; /* stereo playback */ avio_w8(s->pb, v); v |= 0x20; /* mp3 compressed */ @@ -362,6 +364,12 @@ static int swf_write_header(AVFormatContext *s) return 0; } +static int fifo_avio_wrapper(void *opaque, void *buf, size_t *nb_elems) +{ + avio_write(opaque, buf, *nb_elems); + return 0; +} + static int swf_write_video(AVFormatContext *s, AVCodecParameters *par, const uint8_t *buf, int size, unsigned pkt_flags) { @@ -454,12 +462,12 @@ static int swf_write_video(AVFormatContext *s, swf->swf_frame_number++; /* streaming sound always should be placed just before showframe tags */ - if (swf->audio_par && av_fifo_size(swf->audio_fifo)) { - int frame_size = av_fifo_size(swf->audio_fifo); + if (swf->audio_par && av_fifo_can_read(swf->audio_fifo)) { + size_t frame_size = av_fifo_can_read(swf->audio_fifo); put_swf_tag(s, TAG_STREAMBLOCK | TAG_LONG); avio_wl16(pb, swf->sound_samples); avio_wl16(pb, 0); // seek samples - av_fifo_generic_read(swf->audio_fifo, pb, frame_size, (void*)avio_write); + av_fifo_read_to_cb(swf->audio_fifo, fifo_avio_wrapper, pb, &frame_size); put_swf_end_tag(s); /* update FIFO */ @@ -473,8 +481,8 @@ static int swf_write_video(AVFormatContext *s, return 0; } -static int swf_write_audio(AVFormatContext *s, - AVCodecParameters *par, uint8_t *buf, int size) +static int swf_write_audio(AVFormatContext *s, AVCodecParameters *par, + const uint8_t *buf, int size) { SWFEncContext *swf = s->priv_data; @@ -482,12 +490,12 @@ static int swf_write_audio(AVFormatContext *s, if (swf->swf_frame_number == 16000) av_log(s, AV_LOG_INFO, "warning: Flash Player limit of 16000 frames reached\n"); - if (av_fifo_size(swf->audio_fifo) + size > AUDIO_FIFO_SIZE) { + if (av_fifo_can_write(swf->audio_fifo) < size) { av_log(s, AV_LOG_ERROR, "audio fifo too small to mux audio essence\n"); return -1; } - av_fifo_generic_write(swf->audio_fifo, buf, size, NULL); + av_fifo_write(swf->audio_fifo, buf, size); swf->sound_samples += av_get_audio_frame_duration2(par, size); /* if audio only stream make sure we add swf frames */ @@ -535,7 +543,7 @@ static void swf_deinit(AVFormatContext *s) { SWFEncContext *swf = s->priv_data; - av_fifo_freep(&swf->audio_fifo); + av_fifo_freep2(&swf->audio_fifo); } #if CONFIG_SWF_MUXER diff --git a/libavformat/takdec.c b/libavformat/takdec.c index bb256e119..08f6e6a25 100644 --- a/libavformat/takdec.c +++ b/libavformat/takdec.c @@ -152,9 +152,13 @@ static int tak_read_header(AVFormatContext *s) st->duration = ti.samples; st->codecpar->bits_per_coded_sample = ti.bps; if (ti.ch_layout) - st->codecpar->channel_layout = ti.ch_layout; + av_channel_layout_from_mask(&st->codecpar->ch_layout, ti.ch_layout); + else { + av_channel_layout_uninit(&st->codecpar->ch_layout); + st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + st->codecpar->ch_layout.nb_channels = ti.channels; + } st->codecpar->sample_rate = ti.sample_rate; - st->codecpar->channels = ti.channels; st->start_time = 0; avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); st->codecpar->extradata = buffer; @@ -171,9 +175,8 @@ static int tak_read_header(AVFormatContext *s) 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_RL24(buffer)); av_freep(&buffer); } } diff --git a/libavformat/tcp.c b/libavformat/tcp.c index 1c19aed88..a11ccbb91 100644 --- a/libavformat/tcp.c +++ b/libavformat/tcp.c @@ -175,7 +175,7 @@ static int tcp_open(URLContext *h, const char *uri, int flags) while (cur_ai && fd < 0) { fd = ff_socket(cur_ai->ai_family, cur_ai->ai_socktype, - cur_ai->ai_protocol); + cur_ai->ai_protocol, h); if (fd < 0) { ret = ff_neterrno(); cur_ai = cur_ai->ai_next; @@ -188,7 +188,7 @@ static int tcp_open(URLContext *h, const char *uri, int flags) if (s->listen == 2) { // multi-client - if ((ret = ff_listen(fd, cur_ai->ai_addr, cur_ai->ai_addrlen)) < 0) + if ((ret = ff_listen(fd, cur_ai->ai_addr, cur_ai->ai_addrlen, h)) < 0) goto fail1; } else if (s->listen == 1) { // single client diff --git a/libavformat/tee.c b/libavformat/tee.c index b3bcd70b9..f1f2a9d2a 100644 --- a/libavformat/tee.c +++ b/libavformat/tee.c @@ -26,7 +26,7 @@ #include "libavcodec/bsf.h" #include "internal.h" #include "avformat.h" -#include "avio_internal.h" +#include "mux.h" #include "tee_common.h" typedef enum { diff --git a/libavformat/tee_common.c b/libavformat/tee_common.c index a9608871b..e516b0a60 100644 --- a/libavformat/tee_common.c +++ b/libavformat/tee_common.c @@ -19,8 +19,9 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/avutil.h" -#include "libavutil/avstring.h" +#include + +#include "libavutil/log.h" #include "libavutil/opt.h" #include "tee_common.h" diff --git a/libavformat/tests/imf.c b/libavformat/tests/imf.c index 142aa0426..e65629ccb 100644 --- a/libavformat/tests/imf.c +++ b/libavformat/tests/imf.c @@ -304,7 +304,7 @@ static int test_cpl_parsing(void) } printf("%s\n", cpl->content_title_utf8); - printf(FF_IMF_UUID_FORMAT "\n", UID_ARG(cpl->id_uuid)); + printf(AV_PRI_URN_UUID "\n", AV_UUID_ARG(cpl->id_uuid)); printf("%i %i\n", cpl->edit_rate.num, cpl->edit_rate.den); printf("Marker resource count: %" PRIu32 "\n", cpl->main_markers_track->resource_count); @@ -320,7 +320,7 @@ static int test_cpl_parsing(void) printf("Main image resource count: %" PRIu32 "\n", cpl->main_image_2d_track->resource_count); for (uint32_t i = 0; i < cpl->main_image_2d_track->resource_count; i++) { printf("Track file resource %" PRIu32 "\n", i); - printf(" " FF_IMF_UUID_FORMAT "\n", UID_ARG(cpl->main_image_2d_track->resources[i].track_file_uuid)); + printf(" " AV_PRI_URN_UUID "\n", AV_UUID_ARG(cpl->main_image_2d_track->resources[i].track_file_uuid)); } printf("Main audio track count: %" PRIu32 "\n", cpl->main_audio_track_count); @@ -329,7 +329,7 @@ static int test_cpl_parsing(void) printf(" Main audio resource count: %" PRIu32 "\n", cpl->main_audio_tracks[i].resource_count); for (uint32_t j = 0; j < cpl->main_audio_tracks[i].resource_count; j++) { printf(" Track file resource %" PRIu32 "\n", j); - printf(" " FF_IMF_UUID_FORMAT "\n", UID_ARG(cpl->main_audio_tracks[i].resources[j].track_file_uuid)); + printf(" " AV_PRI_URN_UUID "\n", AV_UUID_ARG(cpl->main_audio_tracks[i].resources[j].track_file_uuid)); } } @@ -363,15 +363,15 @@ static int test_bad_cpl_parsing(void) static int check_asset_locator_attributes(IMFAssetLocator *asset, IMFAssetLocator *expected_asset) { - printf("\tCompare " FF_IMF_UUID_FORMAT " to " FF_IMF_UUID_FORMAT ".\n", - UID_ARG(asset->uuid), - UID_ARG(expected_asset->uuid)); + printf("\tCompare " AV_PRI_URN_UUID " to " AV_PRI_URN_UUID ".\n", + AV_UUID_ARG(asset->uuid), + AV_UUID_ARG(expected_asset->uuid)); for (uint32_t i = 0; i < 16; ++i) { if (asset->uuid[i] != expected_asset->uuid[i]) { - printf("Invalid asset locator UUID: found " FF_IMF_UUID_FORMAT " instead of " FF_IMF_UUID_FORMAT " expected.\n", - UID_ARG(asset->uuid), - UID_ARG(expected_asset->uuid)); + printf("Invalid asset locator UUID: found " AV_PRI_URN_UUID " instead of " AV_PRI_URN_UUID " expected.\n", + AV_UUID_ARG(asset->uuid), + AV_UUID_ARG(expected_asset->uuid)); return 1; } } diff --git a/libavformat/tests/movenc.c b/libavformat/tests/movenc.c index 2af72f11c..6f9d38192 100644 --- a/libavformat/tests/movenc.c +++ b/libavformat/tests/movenc.c @@ -214,7 +214,7 @@ static void init_fps(int bf, int audio_preroll, int fps) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_AAC; st->codecpar->sample_rate = 44100; - st->codecpar->channels = 2; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; st->time_base.num = 1; st->time_base.den = 44100; st->codecpar->extradata_size = sizeof(aac_extradata); @@ -455,7 +455,7 @@ int main(int argc, char **argv) init_count_warnings(); init_out("empty-moov-no-elst-no-adjust"); av_dict_set(&opts, "movflags", "frag_keyframe+empty_moov", 0); - av_dict_set(&opts, "avoid_negative_ts", "0", 0); + av_dict_set(&opts, "avoid_negative_ts", "disabled", 0); init(1, 0); mux_gops(2); finish(); @@ -578,7 +578,7 @@ int main(int argc, char **argv) // one before. av_dict_set(&opts, "movflags", "frag_custom+empty_moov+dash+frag_discont", 0); av_dict_set(&opts, "fragment_index", "2", 0); - av_dict_set(&opts, "avoid_negative_ts", "0", 0); + av_dict_set(&opts, "avoid_negative_ts", "disabled", 0); av_dict_set(&opts, "use_editlist", "0", 0); init(0, 0); skip_gops(1); diff --git a/libavformat/tests/seek.c b/libavformat/tests/seek.c index e0067a64f..94a72d942 100644 --- a/libavformat/tests/seek.c +++ b/libavformat/tests/seek.c @@ -88,7 +88,7 @@ int main(int argc, char **argv) } } - av_dict_set(&format_opts, "channels", "1", 0); + av_dict_set(&format_opts, "ch_layout", "mono", 0); av_dict_set(&format_opts, "sample_rate", "22050", 0); if (argc < 2) { diff --git a/libavformat/tests/seek_utils.c b/libavformat/tests/seek_utils.c new file mode 100644 index 000000000..4cb94ad68 --- /dev/null +++ b/libavformat/tests/seek_utils.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2022 Pierre-Anthony Lemieux + * + * 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 "libavformat/demux.h" + +int main(void) +{ + int64_t ts_min; + int64_t ts; + int64_t ts_max; + + ts_min = 10; + ts = 20; + ts_max = 30; + + ff_rescale_interval(av_make_q(1, 1), av_make_q(10, 1), &ts_min, &ts, &ts_max); + + if (ts_min != 1 || ts != 2 || ts_max != 3) + return 1; + + ts_min = 10; + ts = 32; + ts_max = 32; + + ff_rescale_interval(av_make_q(1, 1), av_make_q(3, 1), &ts_min, &ts, &ts_max); + + if (ts_min != 4 || ts != 11 || ts_max != 10) + return 1; + + ts_min = 10; + ts = 10; + ts_max = 32; + + ff_rescale_interval(av_make_q(1, 1), av_make_q(3, 1), &ts_min, &ts, &ts_max); + + if (ts_min != 4 || ts != 3 || ts_max != 10) + return 1; + + return 0; +} diff --git a/libavformat/thp.c b/libavformat/thp.c index 7103cf4f8..fdb499bf4 100644 --- a/libavformat/thp.c +++ b/libavformat/thp.c @@ -142,7 +142,7 @@ static int thp_read_header(AVFormatContext *s) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_ADPCM_THP; st->codecpar->codec_tag = 0; /* no fourcc */ - st->codecpar->channels = avio_rb32(pb); /* numChannels. */ + st->codecpar->ch_layout.nb_channels = avio_rb32(pb); st->codecpar->sample_rate = avio_rb32(pb); /* Frequency. */ st->duration = avio_rb32(pb); diff --git a/libavformat/tiertexseq.c b/libavformat/tiertexseq.c index ecc15e403..d06853d0d 100644 --- a/libavformat/tiertexseq.c +++ b/libavformat/tiertexseq.c @@ -242,12 +242,11 @@ static int seq_read_header(AVFormatContext *s) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE; st->codecpar->codec_tag = 0; /* no tag */ - st->codecpar->channels = 1; - st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; st->codecpar->sample_rate = SEQ_SAMPLE_RATE; st->codecpar->bits_per_coded_sample = 16; - st->codecpar->bit_rate = st->codecpar->sample_rate * st->codecpar->bits_per_coded_sample * st->codecpar->channels; - st->codecpar->block_align = st->codecpar->channels * st->codecpar->bits_per_coded_sample / 8; + st->codecpar->bit_rate = st->codecpar->sample_rate * st->codecpar->bits_per_coded_sample * st->codecpar->ch_layout.nb_channels; + st->codecpar->block_align = st->codecpar->ch_layout.nb_channels * st->codecpar->bits_per_coded_sample / 8; return 0; } diff --git a/libavformat/tls.c b/libavformat/tls.c index 302c0f8d5..e42d39986 100644 --- a/libavformat/tls.c +++ b/libavformat/tls.c @@ -26,6 +26,7 @@ #include "url.h" #include "tls.h" #include "libavutil/avstring.h" +#include "libavutil/getenv_utf8.h" #include "libavutil/opt.h" #include "libavutil/parseutils.h" @@ -60,6 +61,7 @@ int ff_tls_open_underlying(TLSShared *c, URLContext *parent, const char *uri, AV char buf[200], opts[50] = ""; struct addrinfo hints = { 0 }, *ai = NULL; const char *proxy_path; + char *env_http_proxy, *env_no_proxy; int use_proxy; set_options(c, uri); @@ -89,9 +91,13 @@ int ff_tls_open_underlying(TLSShared *c, URLContext *parent, const char *uri, AV if (!c->host && !(c->host = av_strdup(c->underlying_host))) return AVERROR(ENOMEM); - proxy_path = c->http_proxy ? c->http_proxy : getenv("http_proxy"); - use_proxy = !ff_http_match_no_proxy(getenv("no_proxy"), c->underlying_host) && + env_http_proxy = getenv_utf8("http_proxy"); + proxy_path = c->http_proxy ? c->http_proxy : env_http_proxy; + + env_no_proxy = getenv_utf8("no_proxy"); + use_proxy = !ff_http_match_no_proxy(env_no_proxy, c->underlying_host) && proxy_path && av_strstart(proxy_path, "http://", NULL); + freeenv_utf8(env_no_proxy); if (use_proxy) { char proxy_host[200], proxy_auth[200], dest[200]; @@ -104,6 +110,7 @@ int ff_tls_open_underlying(TLSShared *c, URLContext *parent, const char *uri, AV proxy_port, "/%s", dest); } + freeenv_utf8(env_http_proxy); return ffurl_open_whitelist(&c->tcp, buf, AVIO_FLAG_READ_WRITE, &parent->interrupt_callback, options, parent->protocol_whitelist, parent->protocol_blacklist, parent); diff --git a/libavformat/tls_gnutls.c b/libavformat/tls_gnutls.c index 741578a59..2ab38a199 100644 --- a/libavformat/tls_gnutls.c +++ b/libavformat/tls_gnutls.c @@ -192,7 +192,7 @@ static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **op gnutls_transport_set_pull_function(p->session, gnutls_url_pull); gnutls_transport_set_push_function(p->session, gnutls_url_push); gnutls_transport_set_ptr(p->session, p); - gnutls_priority_set_direct(p->session, "NORMAL", NULL); + gnutls_set_default_priority(p->session); do { if (ff_check_interrupt(&h->interrupt_callback)) { ret = AVERROR_EXIT; diff --git a/libavformat/tls_libtls.c b/libavformat/tls_libtls.c index 911c8094b..22858d486 100644 --- a/libavformat/tls_libtls.c +++ b/libavformat/tls_libtls.c @@ -158,6 +158,8 @@ static int ff_tls_read(URLContext *h, uint8_t *buf, int size) return ret; else if (ret == 0) return AVERROR_EOF; + else if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) + return AVERROR(EAGAIN); av_log(h, AV_LOG_ERROR, "%s\n", tls_error(p->ctx)); return AVERROR(EIO); } @@ -171,6 +173,8 @@ static int ff_tls_write(URLContext *h, const uint8_t *buf, int size) return ret; else if (ret == 0) return AVERROR_EOF; + else if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) + return AVERROR(EAGAIN); av_log(h, AV_LOG_ERROR, "%s\n", tls_error(p->ctx)); return AVERROR(EIO); } diff --git a/libavformat/tls_mbedtls.c b/libavformat/tls_mbedtls.c index 5754d0d01..8503523b6 100644 --- a/libavformat/tls_mbedtls.c +++ b/libavformat/tls_mbedtls.c @@ -19,8 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include -#include +#include #include #include #include @@ -130,9 +129,15 @@ static void handle_pk_parse_error(URLContext *h, int ret) static void handle_handshake_error(URLContext *h, int ret) { switch (ret) { +#if MBEDTLS_VERSION_MAJOR < 3 case MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE: av_log(h, AV_LOG_ERROR, "None of the common ciphersuites is usable. Was the local certificate correctly set?\n"); break; +#else + case MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE: + av_log(h, AV_LOG_ERROR, "TLS handshake failed.\n"); + break; +#endif case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE: av_log(h, AV_LOG_ERROR, "A fatal alert message was received from the peer, has the peer a correct certificate?\n"); break; @@ -195,16 +200,6 @@ static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **op } } - // load key file - if (shr->key_file) { - if ((ret = mbedtls_pk_parse_keyfile(&tls_ctx->priv_key, - shr->key_file, - tls_ctx->priv_key_pw)) != 0) { - handle_pk_parse_error(h, ret); - goto fail; - } - } - // seed the random number generator if ((ret = mbedtls_ctr_drbg_seed(&tls_ctx->ctr_drbg_context, mbedtls_entropy_func, @@ -214,6 +209,21 @@ static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **op goto fail; } + // load key file + if (shr->key_file) { + if ((ret = mbedtls_pk_parse_keyfile(&tls_ctx->priv_key, + shr->key_file, + tls_ctx->priv_key_pw +#if MBEDTLS_VERSION_MAJOR >= 3 + , mbedtls_ctr_drbg_random, + &tls_ctx->ctr_drbg_context +#endif + )) != 0) { + handle_pk_parse_error(h, ret); + goto fail; + } + } + if ((ret = mbedtls_ssl_config_defaults(&tls_ctx->ssl_config, shr->listen ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, diff --git a/libavformat/tls_openssl.c b/libavformat/tls_openssl.c index 1d813cbbb..8bf766c01 100644 --- a/libavformat/tls_openssl.c +++ b/libavformat/tls_openssl.c @@ -25,7 +25,6 @@ #include "os_support.h" #include "url.h" #include "tls.h" -#include "libavcodec/internal.h" #include "libavutil/avstring.h" #include "libavutil/avutil.h" #include "libavutil/opt.h" diff --git a/libavformat/tmv.c b/libavformat/tmv.c index 507f6cd03..ea3995419 100644 --- a/libavformat/tmv.c +++ b/libavformat/tmv.c @@ -113,19 +113,13 @@ static int tmv_read_header(AVFormatContext *s) ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; ast->codecpar->codec_id = AV_CODEC_ID_PCM_U8; - if (features & TMV_STEREO) { - ast->codecpar->channels = 2; - ast->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; - } else { - ast->codecpar->channels = 1; - ast->codecpar->channel_layout = AV_CH_LAYOUT_MONO; - } + av_channel_layout_default(&ast->codecpar->ch_layout, !!(features & TMV_STEREO) + 1); ast->codecpar->bits_per_coded_sample = 8; ast->codecpar->bit_rate = ast->codecpar->sample_rate * ast->codecpar->bits_per_coded_sample; avpriv_set_pts_info(ast, 32, 1, ast->codecpar->sample_rate); - fps.num = ast->codecpar->sample_rate * ast->codecpar->channels; + fps.num = ast->codecpar->sample_rate * ast->codecpar->ch_layout.nb_channels; fps.den = tmv->audio_chunk_size; av_reduce(&fps.num, &fps.den, fps.num, fps.den, 0xFFFFFFFFLL); diff --git a/libavformat/tta.c b/libavformat/tta.c index 6de8c620a..218304594 100644 --- a/libavformat/tta.c +++ b/libavformat/tta.c @@ -134,7 +134,7 @@ static int tta_read_header(AVFormatContext *s) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_TTA; - st->codecpar->channels = channels; + st->codecpar->ch_layout.nb_channels = channels; st->codecpar->sample_rate = samplerate; st->codecpar->bits_per_coded_sample = bps; diff --git a/libavformat/ttaenc.c b/libavformat/ttaenc.c index 486f8bdd1..1938582bb 100644 --- a/libavformat/ttaenc.c +++ b/libavformat/ttaenc.c @@ -82,7 +82,7 @@ static int tta_write_header(AVFormatContext *s) ffio_init_checksum(tta->seek_table, ff_crcEDB88320_update, UINT32_MAX); avio_write(s->pb, "TTA1", 4); avio_wl16(s->pb, par->extradata ? AV_RL16(par->extradata + 4) : 1); - avio_wl16(s->pb, par->channels); + avio_wl16(s->pb, par->ch_layout.nb_channels); avio_wl16(s->pb, par->bits_per_raw_sample); avio_wl32(s->pb, par->sample_rate); diff --git a/libavformat/udp.c b/libavformat/udp.c index 180d96a98..3b36a4a09 100644 --- a/libavformat/udp.c +++ b/libavformat/udp.c @@ -98,7 +98,7 @@ typedef struct UDPContext { /* Circular Buffer variables for use in UDP receive code */ int circular_buffer_size; - AVFifoBuffer *fifo; + AVFifo *fifo; int circular_buffer_error; int64_t bitrate; /* number of bits to send per second */ int64_t burst_bits; @@ -134,7 +134,7 @@ static const AVOption options[] = { { "reuse", "explicitly allow reusing UDP sockets", OFFSET(reuse_socket), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, D|E }, { "reuse_socket", "explicitly allow reusing UDP sockets", OFFSET(reuse_socket), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, .flags = D|E }, { "broadcast", "explicitly allow or disallow broadcast destination", OFFSET(is_broadcast), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E }, - { "ttl", "Time to live (multicast only)", OFFSET(ttl), AV_OPT_TYPE_INT, { .i64 = 16 }, 0, INT_MAX, E }, + { "ttl", "Time to live (multicast only)", OFFSET(ttl), AV_OPT_TYPE_INT, { .i64 = 16 }, 0, 255, E }, { "connect", "set if connect() should be called on socket", OFFSET(is_connected), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = D|E }, { "fifo_size", "set the UDP receiving circular buffer size, expressed as a number of packets with size of 188 bytes", OFFSET(circular_buffer_size), AV_OPT_TYPE_INT, {.i64 = 7*4096}, 0, INT_MAX, D }, { "overrun_nonfatal", "survive in case of UDP receiving circular buffer overrun", OFFSET(overrun_nonfatal), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, D }, @@ -159,28 +159,48 @@ static const AVClass udplite_context_class = { }; static int udp_set_multicast_ttl(int sockfd, int mcastTTL, - struct sockaddr *addr) + struct sockaddr *addr, + void *logctx) { + int protocol, cmd; + + /* There is some confusion in the world whether IP_MULTICAST_TTL + * takes a byte or an int as an argument. + * BSD seems to indicate byte so we are going with that and use + * int and fall back to byte to be safe */ + switch (addr->sa_family) { #ifdef IP_MULTICAST_TTL - if (addr->sa_family == AF_INET) { - if (setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &mcastTTL, sizeof(mcastTTL)) < 0) { - ff_log_net_error(NULL, AV_LOG_ERROR, "setsockopt(IP_MULTICAST_TTL)"); + case AF_INET: + protocol = IPPROTO_IP; + cmd = IP_MULTICAST_TTL; + break; +#endif +#ifdef IPV6_MULTICAST_HOPS + case AF_INET6: + protocol = IPPROTO_IPV6; + cmd = IPV6_MULTICAST_HOPS; + break; +#endif + default: + return 0; + } + + if (setsockopt(sockfd, protocol, cmd, &mcastTTL, sizeof(mcastTTL)) < 0) { + /* BSD compatibility */ + unsigned char ttl = (unsigned char) mcastTTL; + + ff_log_net_error(logctx, AV_LOG_DEBUG, "setsockopt(IPV4/IPV6 MULTICAST TTL)"); + if (setsockopt(sockfd, protocol, cmd, &ttl, sizeof(ttl)) < 0) { + ff_log_net_error(logctx, AV_LOG_ERROR, "setsockopt(IPV4/IPV6 MULTICAST TTL)"); return ff_neterrno(); } } -#endif -#if defined(IPPROTO_IPV6) && defined(IPV6_MULTICAST_HOPS) - if (addr->sa_family == AF_INET6) { - if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &mcastTTL, sizeof(mcastTTL)) < 0) { - ff_log_net_error(NULL, AV_LOG_ERROR, "setsockopt(IPV6_MULTICAST_HOPS)"); - return ff_neterrno(); - } - } -#endif + return 0; } -static int udp_join_multicast_group(int sockfd, struct sockaddr *addr,struct sockaddr *local_addr) +static int udp_join_multicast_group(int sockfd, struct sockaddr *addr, + struct sockaddr *local_addr, void *logctx) { #ifdef IP_ADD_MEMBERSHIP if (addr->sa_family == AF_INET) { @@ -192,7 +212,7 @@ static int udp_join_multicast_group(int sockfd, struct sockaddr *addr,struct soc else mreq.imr_interface.s_addr = INADDR_ANY; if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const void *)&mreq, sizeof(mreq)) < 0) { - ff_log_net_error(NULL, AV_LOG_ERROR, "setsockopt(IP_ADD_MEMBERSHIP)"); + ff_log_net_error(logctx, AV_LOG_ERROR, "setsockopt(IP_ADD_MEMBERSHIP)"); return ff_neterrno(); } } @@ -205,7 +225,7 @@ static int udp_join_multicast_group(int sockfd, struct sockaddr *addr,struct soc //TODO: Interface index should be looked up from local_addr mreq6.ipv6mr_interface = 0; if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq6, sizeof(mreq6)) < 0) { - ff_log_net_error(NULL, AV_LOG_ERROR, "setsockopt(IPV6_ADD_MEMBERSHIP)"); + ff_log_net_error(logctx, AV_LOG_ERROR, "setsockopt(IPV6_ADD_MEMBERSHIP)"); return ff_neterrno(); } } @@ -213,7 +233,8 @@ static int udp_join_multicast_group(int sockfd, struct sockaddr *addr,struct soc return 0; } -static int udp_leave_multicast_group(int sockfd, struct sockaddr *addr,struct sockaddr *local_addr) +static int udp_leave_multicast_group(int sockfd, struct sockaddr *addr, + struct sockaddr *local_addr, void *logctx) { #ifdef IP_DROP_MEMBERSHIP if (addr->sa_family == AF_INET) { @@ -225,7 +246,7 @@ static int udp_leave_multicast_group(int sockfd, struct sockaddr *addr,struct so else mreq.imr_interface.s_addr = INADDR_ANY; if (setsockopt(sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP, (const void *)&mreq, sizeof(mreq)) < 0) { - ff_log_net_error(NULL, AV_LOG_ERROR, "setsockopt(IP_DROP_MEMBERSHIP)"); + ff_log_net_error(logctx, AV_LOG_ERROR, "setsockopt(IP_DROP_MEMBERSHIP)"); return -1; } } @@ -238,7 +259,7 @@ static int udp_leave_multicast_group(int sockfd, struct sockaddr *addr,struct so //TODO: Interface index should be looked up from local_addr mreq6.ipv6mr_interface = 0; if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &mreq6, sizeof(mreq6)) < 0) { - ff_log_net_error(NULL, AV_LOG_ERROR, "setsockopt(IPV6_DROP_MEMBERSHIP)"); + ff_log_net_error(logctx, AV_LOG_ERROR, "setsockopt(IPV6_DROP_MEMBERSHIP)"); return -1; } } @@ -272,9 +293,9 @@ static int udp_set_multicast_sources(URLContext *h, include ? MCAST_JOIN_SOURCE_GROUP : MCAST_BLOCK_SOURCE, (const void *)&mreqs, sizeof(mreqs)) < 0) { if (include) - ff_log_net_error(NULL, AV_LOG_ERROR, "setsockopt(MCAST_JOIN_SOURCE_GROUP)"); + ff_log_net_error(h, AV_LOG_ERROR, "setsockopt(MCAST_JOIN_SOURCE_GROUP)"); else - ff_log_net_error(NULL, AV_LOG_ERROR, "setsockopt(MCAST_BLOCK_SOURCE)"); + ff_log_net_error(h, AV_LOG_ERROR, "setsockopt(MCAST_BLOCK_SOURCE)"); return ff_neterrno(); } } @@ -348,11 +369,11 @@ static int udp_socket_create(URLContext *h, struct sockaddr_storage *addr, goto fail; for (res = res0; res; res=res->ai_next) { if (s->udplite_coverage) - udp_fd = ff_socket(res->ai_family, SOCK_DGRAM, IPPROTO_UDPLITE); + udp_fd = ff_socket(res->ai_family, SOCK_DGRAM, IPPROTO_UDPLITE, h); else - udp_fd = ff_socket(res->ai_family, SOCK_DGRAM, 0); + udp_fd = ff_socket(res->ai_family, SOCK_DGRAM, 0, h); if (udp_fd != -1) break; - ff_log_net_error(NULL, AV_LOG_ERROR, "socket"); + ff_log_net_error(h, AV_LOG_ERROR, "socket"); } if (udp_fd < 0) @@ -497,7 +518,7 @@ static void *circular_buffer_task_rx( void *_URLContext) continue; AV_WL32(s->tmp, len); - if(av_fifo_space(s->fifo) < len + 4) { + if (av_fifo_can_write(s->fifo) < len + 4) { /* No Space left */ if (s->overrun_nonfatal) { av_log(h, AV_LOG_WARNING, "Circular buffer overrun. " @@ -511,7 +532,7 @@ static void *circular_buffer_task_rx( void *_URLContext) goto end; } } - av_fifo_generic_write(s->fifo, s->tmp, len+4, NULL); + av_fifo_write(s->fifo, s->tmp, len + 4); pthread_cond_signal(&s->cond); } @@ -545,22 +566,22 @@ static void *circular_buffer_task_tx( void *_URLContext) uint8_t tmp[4]; int64_t timestamp; - len = av_fifo_size(s->fifo); + len = av_fifo_can_read(s->fifo); while (len<4) { if (s->close_req) goto end; pthread_cond_wait(&s->cond, &s->mutex); - len = av_fifo_size(s->fifo); + len = av_fifo_can_read(s->fifo); } - av_fifo_generic_read(s->fifo, tmp, 4, NULL); + av_fifo_read(s->fifo, tmp, 4); len = AV_RL32(tmp); av_assert0(len >= 0); av_assert0(len <= sizeof(s->tmp)); - av_fifo_generic_read(s->fifo, s->tmp, len, NULL); + av_fifo_read(s->fifo, s->tmp, len); pthread_mutex_unlock(&s->mutex); @@ -671,6 +692,11 @@ static int udp_open(URLContext *h, const char *uri, int flags) } if (av_find_info_tag(buf, sizeof(buf), "ttl", p)) { s->ttl = strtol(buf, NULL, 10); + if (s->ttl < 0 || s->ttl > 255) { + av_log(h, AV_LOG_ERROR, "ttl(%d) should be in range [0,255]\n", s->ttl); + ret = AVERROR(EINVAL); + goto fail; + } } if (av_find_info_tag(buf, sizeof(buf), "udplite_coverage", p)) { s->udplite_coverage = strtol(buf, NULL, 10); @@ -825,7 +851,7 @@ static int udp_open(URLContext *h, const char *uri, int flags) if (s->is_multicast) { if (h->flags & AVIO_FLAG_WRITE) { /* output */ - if ((ret = udp_set_multicast_ttl(udp_fd, s->ttl, (struct sockaddr *)&s->dest_addr)) < 0) + if ((ret = udp_set_multicast_ttl(udp_fd, s->ttl, (struct sockaddr *)&s->dest_addr, h)) < 0) goto fail; } if (h->flags & AVIO_FLAG_READ) { @@ -838,7 +864,8 @@ static int udp_open(URLContext *h, const char *uri, int flags) s->filters.nb_include_addrs, 1)) < 0) goto fail; } else { - if ((ret = udp_join_multicast_group(udp_fd, (struct sockaddr *)&s->dest_addr,(struct sockaddr *)&s->local_addr_storage)) < 0) + if ((ret = udp_join_multicast_group(udp_fd, (struct sockaddr *)&s->dest_addr, + (struct sockaddr *)&s->local_addr_storage, h)) < 0) goto fail; } if (s->filters.nb_exclude_addrs) { @@ -902,7 +929,7 @@ static int udp_open(URLContext *h, const char *uri, int flags) if ((!is_output && s->circular_buffer_size) || (is_output && s->bitrate && s->circular_buffer_size)) { /* start the task going */ - s->fifo = av_fifo_alloc(s->circular_buffer_size); + s->fifo = av_fifo_alloc2(s->circular_buffer_size, 1, 0); if (!s->fifo) { ret = AVERROR(ENOMEM); goto fail; @@ -939,7 +966,7 @@ static int udp_open(URLContext *h, const char *uri, int flags) fail: if (udp_fd >= 0) closesocket(udp_fd); - av_fifo_freep(&s->fifo); + av_fifo_freep2(&s->fifo); ff_ip_reset_filters(&s->filters); return ret; } @@ -966,19 +993,19 @@ static int udp_read(URLContext *h, uint8_t *buf, int size) if (s->fifo) { pthread_mutex_lock(&s->mutex); do { - avail = av_fifo_size(s->fifo); + avail = av_fifo_can_read(s->fifo); if (avail) { // >=size) { uint8_t tmp[4]; - av_fifo_generic_read(s->fifo, tmp, 4, NULL); + av_fifo_read(s->fifo, tmp, 4); avail = AV_RL32(tmp); if(avail > size){ av_log(h, AV_LOG_WARNING, "Part of datagram lost due to insufficient buffer size\n"); avail = size; } - av_fifo_generic_read(s->fifo, buf, avail, NULL); - av_fifo_drain(s->fifo, AV_RL32(tmp) - avail); + av_fifo_read(s->fifo, buf, avail); + av_fifo_drain2(s->fifo, AV_RL32(tmp) - avail); pthread_mutex_unlock(&s->mutex); return avail; } else if(s->circular_buffer_error){ @@ -1039,14 +1066,14 @@ static int udp_write(URLContext *h, const uint8_t *buf, int size) return err; } - if(av_fifo_space(s->fifo) < size + 4) { + if (av_fifo_can_write(s->fifo) < size + 4) { /* What about a partial packet tx ? */ pthread_mutex_unlock(&s->mutex); return AVERROR(ENOMEM); } AV_WL32(tmp, size); - av_fifo_generic_write(s->fifo, tmp, 4, NULL); /* size of packet */ - av_fifo_generic_write(s->fifo, (uint8_t *)buf, size, NULL); /* the data */ + av_fifo_write(s->fifo, tmp, 4); /* size of packet */ + av_fifo_write(s->fifo, buf, size); /* the data */ pthread_cond_signal(&s->cond); pthread_mutex_unlock(&s->mutex); return size; @@ -1083,7 +1110,8 @@ static int udp_close(URLContext *h) #endif if (s->is_multicast && (h->flags & AVIO_FLAG_READ)) - udp_leave_multicast_group(s->udp_fd, (struct sockaddr *)&s->dest_addr,(struct sockaddr *)&s->local_addr_storage); + udp_leave_multicast_group(s->udp_fd, (struct sockaddr *)&s->dest_addr, + (struct sockaddr *)&s->local_addr_storage, h); #if HAVE_PTHREAD_CANCEL if (s->thread_started) { int ret; @@ -1107,7 +1135,7 @@ static int udp_close(URLContext *h) } #endif closesocket(s->udp_fd); - av_fifo_freep(&s->fifo); + av_fifo_freep2(&s->fifo); ff_ip_reset_filters(&s->filters); return 0; } diff --git a/libavformat/uncodedframecrcenc.c b/libavformat/uncodedframecrcenc.c index e30fe4ddb..99990616d 100644 --- a/libavformat/uncodedframecrcenc.c +++ b/libavformat/uncodedframecrcenc.c @@ -23,6 +23,7 @@ #include "libavutil/bprint.h" #include "libavutil/imgutils.h" #include "libavutil/pixdesc.h" +#include "libavformat/mux.h" #include "avformat.h" #include "internal.h" @@ -79,7 +80,7 @@ static void audio_frame_cksum(AVBPrint *bp, AVFrame *frame) int nb_planes, nb_samples, p; const char *name; - nb_planes = frame->channels; + nb_planes = frame->ch_layout.nb_channels; nb_samples = frame->nb_samples; if (!av_sample_fmt_is_planar(frame->format)) { nb_samples *= nb_planes; diff --git a/libavformat/unix.c b/libavformat/unix.c index 38016dbaf..e66874458 100644 --- a/libavformat/unix.c +++ b/libavformat/unix.c @@ -69,7 +69,7 @@ static int unix_open(URLContext *h, const char *filename, int flags) s->addr.sun_family = AF_UNIX; av_strlcpy(s->addr.sun_path, filename, sizeof(s->addr.sun_path)); - if ((fd = ff_socket(AF_UNIX, s->type, 0)) < 0) + if ((fd = ff_socket(AF_UNIX, s->type, 0, h)) < 0) return ff_neterrno(); if (s->timeout < 0 && h->rw_timeout) diff --git a/libavformat/url.h b/libavformat/url.h index a129150d7..3cfe3ecc5 100644 --- a/libavformat/url.h +++ b/libavformat/url.h @@ -25,7 +25,6 @@ #define AVFORMAT_URL_H #include "avio.h" -#include "libavformat/version.h" #include "libavutil/dict.h" #include "libavutil/log.h" diff --git a/libavformat/utils.c b/libavformat/utils.c index cee86ae87..cf4d68bff 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -23,22 +23,13 @@ #include "config.h" -#include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/bprint.h" -#include "libavutil/dict.h" #include "libavutil/internal.h" -#include "libavutil/intmath.h" -#include "libavutil/opt.h" -#include "libavutil/parseutils.h" -#include "libavutil/pixfmt.h" #include "libavutil/thread.h" #include "libavutil/time.h" -#include "libavcodec/bsf.h" -#include "libavcodec/bytestream.h" #include "libavcodec/internal.h" -#include "libavcodec/packet_internal.h" #include "avformat.h" #include "avio_internal.h" @@ -47,9 +38,6 @@ #include "network.h" #endif -#include "libavutil/ffversion.h" -const char av_format_ffversion[] = "FFmpeg version " FFMPEG_VERSION; - static AVMutex avformat_mutex = AV_MUTEX_INITIALIZER; /** @@ -57,23 +45,6 @@ static AVMutex avformat_mutex = AV_MUTEX_INITIALIZER; * various utility functions for use within FFmpeg */ -unsigned avformat_version(void) -{ - av_assert0(LIBAVFORMAT_VERSION_MICRO >= 100); - return LIBAVFORMAT_VERSION_INT; -} - -const char *avformat_configuration(void) -{ - return FFMPEG_CONFIGURATION; -} - -const char *avformat_license(void) -{ -#define LICENSE_PREFIX "libavformat license: " - return &LICENSE_PREFIX FFMPEG_LICENSE[sizeof(LICENSE_PREFIX) - 1]; -} - int ff_lock_avformat(void) { return ff_mutex_lock(&avformat_mutex) ? -1 : 0; @@ -84,72 +55,6 @@ int ff_unlock_avformat(void) return ff_mutex_unlock(&avformat_mutex) ? -1 : 0; } -int64_t av_stream_get_end_pts(const AVStream *st) -{ - if (cffstream(st)->priv_pts) { - return cffstream(st)->priv_pts->val; - } else - return AV_NOPTS_VALUE; -} - -struct AVCodecParserContext *av_stream_get_parser(const AVStream *st) -{ - return cffstream(st)->parser; -} - -void avpriv_stream_set_need_parsing(AVStream *st, enum AVStreamParseType type) -{ - ffstream(st)->need_parsing = type; -} - -void av_format_inject_global_side_data(AVFormatContext *s) -{ - FFFormatContext *const si = ffformatcontext(s); - si->inject_global_side_data = 1; - for (unsigned i = 0; i < s->nb_streams; i++) { - AVStream *st = s->streams[i]; - ffstream(st)->inject_global_side_data = 1; - } -} - -int ff_copy_whiteblacklists(AVFormatContext *dst, const AVFormatContext *src) -{ - av_assert0(!dst->codec_whitelist && - !dst->format_whitelist && - !dst->protocol_whitelist && - !dst->protocol_blacklist); - dst-> codec_whitelist = av_strdup(src->codec_whitelist); - dst->format_whitelist = av_strdup(src->format_whitelist); - dst->protocol_whitelist = av_strdup(src->protocol_whitelist); - dst->protocol_blacklist = av_strdup(src->protocol_blacklist); - if ( (src-> codec_whitelist && !dst-> codec_whitelist) - || (src-> format_whitelist && !dst-> format_whitelist) - || (src->protocol_whitelist && !dst->protocol_whitelist) - || (src->protocol_blacklist && !dst->protocol_blacklist)) { - av_log(dst, AV_LOG_ERROR, "Failed to duplicate black/whitelist\n"); - return AVERROR(ENOMEM); - } - return 0; -} - -const AVCodec *ff_find_decoder(AVFormatContext *s, const AVStream *st, - enum AVCodecID codec_id) -{ - switch (st->codecpar->codec_type) { - case AVMEDIA_TYPE_VIDEO: - if (s->video_codec) return s->video_codec; - break; - case AVMEDIA_TYPE_AUDIO: - if (s->audio_codec) return s->audio_codec; - break; - case AVMEDIA_TYPE_SUBTITLE: - if (s->subtitle_codec) return s->subtitle_codec; - break; - } - - return avcodec_find_decoder(codec_id); -} - /* an arbitrarily chosen "sane" max packet size -- 50M */ #define SANE_CHUNK_SIZE (50000000) @@ -224,126 +129,8 @@ int av_filename_number_test(const char *filename) (av_get_frame_filename(buf, sizeof(buf), filename, 1) >= 0); } -int avformat_queue_attached_pictures(AVFormatContext *s) -{ - FFFormatContext *const si = ffformatcontext(s); - int ret; - for (unsigned i = 0; i < s->nb_streams; i++) - if (s->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC && - s->streams[i]->discard < AVDISCARD_ALL) { - if (s->streams[i]->attached_pic.size <= 0) { - av_log(s, AV_LOG_WARNING, - "Attached picture on stream %d has invalid size, " - "ignoring\n", i); - continue; - } - - ret = avpriv_packet_list_put(&si->raw_packet_buffer, - &s->streams[i]->attached_pic, - av_packet_ref, 0); - if (ret < 0) - return ret; - } - return 0; -} - -int ff_add_attached_pic(AVFormatContext *s, AVStream *st0, AVIOContext *pb, - AVBufferRef **buf, int size) -{ - AVStream *st = st0; - AVPacket *pkt; - int ret; - - if (!st && !(st = avformat_new_stream(s, NULL))) - return AVERROR(ENOMEM); - pkt = &st->attached_pic; - if (buf) { - av_assert1(*buf); - av_packet_unref(pkt); - pkt->buf = *buf; - pkt->data = (*buf)->data; - pkt->size = (*buf)->size - AV_INPUT_BUFFER_PADDING_SIZE; - *buf = NULL; - } else { - ret = av_get_packet(pb, pkt, size); - if (ret < 0) - goto fail; - } - st->disposition |= AV_DISPOSITION_ATTACHED_PIC; - st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; - - pkt->stream_index = st->index; - pkt->flags |= AV_PKT_FLAG_KEY; - - return 0; -fail: - if (!st0) - ff_free_stream(s, st); - return ret; -} - /**********************************************************/ -int ff_is_intra_only(enum AVCodecID id) -{ - const AVCodecDescriptor *d = avcodec_descriptor_get(id); - if (!d) - return 0; - if ((d->type == AVMEDIA_TYPE_VIDEO || d->type == AVMEDIA_TYPE_AUDIO) && - !(d->props & AV_CODEC_PROP_INTRA_ONLY)) - return 0; - return 1; -} - -/* XXX: suppress the packet queue */ -void ff_flush_packet_queue(AVFormatContext *s) -{ - FFFormatContext *const si = ffformatcontext(s); - avpriv_packet_list_free(&si->parse_queue); - avpriv_packet_list_free(&si->packet_buffer); - avpriv_packet_list_free(&si->raw_packet_buffer); - - si->raw_packet_buffer_size = 0; -} - -int av_find_default_stream_index(AVFormatContext *s) -{ - int best_stream = 0; - int best_score = INT_MIN; - - if (s->nb_streams <= 0) - return -1; - for (unsigned i = 0; i < s->nb_streams; i++) { - const AVStream *const st = s->streams[i]; - const FFStream *const sti = cffstream(st); - int score = 0; - if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { - if (st->disposition & AV_DISPOSITION_ATTACHED_PIC) - score -= 400; - if (st->codecpar->width && st->codecpar->height) - score += 50; - score+= 25; - } - if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { - if (st->codecpar->sample_rate) - score += 50; - } - if (sti->codec_info_nb_frames) - score += 12; - - if (st->discard != AVDISCARD_ALL) - score += 200; - - if (score > best_score) { - best_score = score; - best_stream = i; - } - } - return best_stream; -} - -/*******************************************************/ - unsigned int ff_codec_get_tag(const AVCodecTag *tags, enum AVCodecID id) { while (tags->id != AV_CODEC_ID_NONE) { @@ -466,488 +253,8 @@ int ff_alloc_extradata(AVCodecParameters *par, int size) return 0; } -int ff_get_extradata(AVFormatContext *s, AVCodecParameters *par, AVIOContext *pb, int size) -{ - int ret = ff_alloc_extradata(par, size); - if (ret < 0) - return ret; - ret = ffio_read_size(pb, par->extradata, size); - if (ret < 0) { - av_freep(&par->extradata); - par->extradata_size = 0; - av_log(s, AV_LOG_ERROR, "Failed to read extradata of size %d\n", size); - return ret; - } - - return ret; -} - -AVProgram *av_find_program_from_stream(AVFormatContext *ic, AVProgram *last, int s) -{ - for (unsigned i = 0; i < ic->nb_programs; i++) { - if (ic->programs[i] == last) { - last = NULL; - } else { - if (!last) - for (unsigned j = 0; j < ic->programs[i]->nb_stream_indexes; j++) - if (ic->programs[i]->stream_index[j] == s) - return ic->programs[i]; - } - } - return NULL; -} - -int av_find_best_stream(AVFormatContext *ic, enum AVMediaType type, - int wanted_stream_nb, int related_stream, - const AVCodec **decoder_ret, int flags) -{ - int nb_streams = ic->nb_streams; - int ret = AVERROR_STREAM_NOT_FOUND; - int best_count = -1, best_multiframe = -1, best_disposition = -1; - int count, multiframe, disposition; - int64_t best_bitrate = -1; - int64_t bitrate; - unsigned *program = NULL; - const AVCodec *decoder = NULL, *best_decoder = NULL; - - if (related_stream >= 0 && wanted_stream_nb < 0) { - AVProgram *p = av_find_program_from_stream(ic, NULL, related_stream); - if (p) { - program = p->stream_index; - nb_streams = p->nb_stream_indexes; - } - } - for (unsigned i = 0; i < nb_streams; i++) { - int real_stream_index = program ? program[i] : i; - AVStream *st = ic->streams[real_stream_index]; - AVCodecParameters *par = st->codecpar; - if (par->codec_type != type) - continue; - if (wanted_stream_nb >= 0 && real_stream_index != wanted_stream_nb) - continue; - if (type == AVMEDIA_TYPE_AUDIO && !(par->channels && par->sample_rate)) - continue; - if (decoder_ret) { - decoder = ff_find_decoder(ic, st, par->codec_id); - if (!decoder) { - if (ret < 0) - ret = AVERROR_DECODER_NOT_FOUND; - continue; - } - } - disposition = !(st->disposition & (AV_DISPOSITION_HEARING_IMPAIRED | AV_DISPOSITION_VISUAL_IMPAIRED)) - + !! (st->disposition & AV_DISPOSITION_DEFAULT); - count = ffstream(st)->codec_info_nb_frames; - bitrate = par->bit_rate; - multiframe = FFMIN(5, count); - if ((best_disposition > disposition) || - (best_disposition == disposition && best_multiframe > multiframe) || - (best_disposition == disposition && best_multiframe == multiframe && best_bitrate > bitrate) || - (best_disposition == disposition && best_multiframe == multiframe && best_bitrate == bitrate && best_count >= count)) - continue; - best_disposition = disposition; - best_count = count; - best_bitrate = bitrate; - best_multiframe = multiframe; - ret = real_stream_index; - best_decoder = decoder; - if (program && i == nb_streams - 1 && ret < 0) { - program = NULL; - nb_streams = ic->nb_streams; - /* no related stream found, try again with everything */ - i = 0; - } - } - if (decoder_ret) - *decoder_ret = best_decoder; - return ret; -} - /*******************************************************/ -int av_read_play(AVFormatContext *s) -{ - if (s->iformat->read_play) - return s->iformat->read_play(s); - if (s->pb) - return avio_pause(s->pb, 0); - return AVERROR(ENOSYS); -} - -int av_read_pause(AVFormatContext *s) -{ - if (s->iformat->read_pause) - return s->iformat->read_pause(s); - if (s->pb) - return avio_pause(s->pb, 1); - return AVERROR(ENOSYS); -} - -int ff_stream_encode_params_copy(AVStream *dst, const AVStream *src) -{ - int ret; - - dst->id = src->id; - dst->time_base = src->time_base; - dst->nb_frames = src->nb_frames; - dst->disposition = src->disposition; - dst->sample_aspect_ratio = src->sample_aspect_ratio; - dst->avg_frame_rate = src->avg_frame_rate; - dst->r_frame_rate = src->r_frame_rate; - - av_dict_free(&dst->metadata); - ret = av_dict_copy(&dst->metadata, src->metadata, 0); - if (ret < 0) - return ret; - - ret = avcodec_parameters_copy(dst->codecpar, src->codecpar); - if (ret < 0) - return ret; - - ret = ff_stream_side_data_copy(dst, src); - if (ret < 0) - return ret; - - return 0; -} - -int ff_stream_side_data_copy(AVStream *dst, const AVStream *src) -{ - /* Free existing side data*/ - for (int i = 0; i < dst->nb_side_data; i++) - av_free(dst->side_data[i].data); - av_freep(&dst->side_data); - dst->nb_side_data = 0; - - /* Copy side data if present */ - if (src->nb_side_data) { - dst->side_data = av_calloc(src->nb_side_data, - sizeof(*dst->side_data)); - if (!dst->side_data) - return AVERROR(ENOMEM); - dst->nb_side_data = src->nb_side_data; - - for (int i = 0; i < src->nb_side_data; i++) { - uint8_t *data = av_memdup(src->side_data[i].data, - src->side_data[i].size); - if (!data) - return AVERROR(ENOMEM); - dst->side_data[i].type = src->side_data[i].type; - dst->side_data[i].size = src->side_data[i].size; - dst->side_data[i].data = data; - } - } - - return 0; -} - -static void free_stream(AVStream **pst) -{ - AVStream *st = *pst; - FFStream *const sti = ffstream(st); - - if (!st) - return; - - for (int i = 0; i < st->nb_side_data; i++) - av_freep(&st->side_data[i].data); - av_freep(&st->side_data); - - if (st->attached_pic.data) - av_packet_unref(&st->attached_pic); - - av_parser_close(sti->parser); - avcodec_free_context(&sti->avctx); - av_bsf_free(&sti->bsfc); - av_freep(&sti->priv_pts); - av_freep(&sti->index_entries); - av_freep(&sti->probe_data.buf); - - av_bsf_free(&sti->extract_extradata.bsf); - - if (sti->info) { - av_freep(&sti->info->duration_error); - av_freep(&sti->info); - } - - av_dict_free(&st->metadata); - avcodec_parameters_free(&st->codecpar); - av_freep(&st->priv_data); - - av_freep(pst); -} - -void ff_free_stream(AVFormatContext *s, AVStream *st) -{ - av_assert0(s->nb_streams>0); - av_assert0(s->streams[ s->nb_streams - 1 ] == st); - - free_stream(&s->streams[ --s->nb_streams ]); -} - -void avformat_free_context(AVFormatContext *s) -{ - FFFormatContext *si; - - if (!s) - return; - si = ffformatcontext(s); - - if (s->oformat && s->oformat->deinit && si->initialized) - s->oformat->deinit(s); - - av_opt_free(s); - if (s->iformat && s->iformat->priv_class && s->priv_data) - av_opt_free(s->priv_data); - if (s->oformat && s->oformat->priv_class && s->priv_data) - av_opt_free(s->priv_data); - - for (unsigned i = 0; i < s->nb_streams; i++) - free_stream(&s->streams[i]); - s->nb_streams = 0; - - for (unsigned i = 0; i < s->nb_programs; i++) { - av_dict_free(&s->programs[i]->metadata); - av_freep(&s->programs[i]->stream_index); - av_freep(&s->programs[i]); - } - s->nb_programs = 0; - - av_freep(&s->programs); - av_freep(&s->priv_data); - while (s->nb_chapters--) { - av_dict_free(&s->chapters[s->nb_chapters]->metadata); - av_freep(&s->chapters[s->nb_chapters]); - } - av_freep(&s->chapters); - av_dict_free(&s->metadata); - av_dict_free(&si->id3v2_meta); - av_packet_free(&si->pkt); - av_packet_free(&si->parse_pkt); - av_freep(&s->streams); - ff_flush_packet_queue(s); - av_freep(&s->url); - av_free(s); -} - -static const AVOption stream_options[] = { - { "disposition", NULL, offsetof(AVStream, disposition), AV_OPT_TYPE_FLAGS, { .i64 = 0 }, - .flags = AV_OPT_FLAG_ENCODING_PARAM, .unit = "disposition" }, - { "default", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DEFAULT }, .unit = "disposition" }, - { "dub", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DUB }, .unit = "disposition" }, - { "original", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_ORIGINAL }, .unit = "disposition" }, - { "comment", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_COMMENT }, .unit = "disposition" }, - { "lyrics", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_LYRICS }, .unit = "disposition" }, - { "karaoke", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_KARAOKE }, .unit = "disposition" }, - { "forced", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_FORCED }, .unit = "disposition" }, - { "hearing_impaired", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_HEARING_IMPAIRED }, .unit = "disposition" }, - { "visual_impaired", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_VISUAL_IMPAIRED }, .unit = "disposition" }, - { "clean_effects", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_CLEAN_EFFECTS }, .unit = "disposition" }, - { "attached_pic", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_ATTACHED_PIC }, .unit = "disposition" }, - { "timed_thumbnails", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_TIMED_THUMBNAILS }, .unit = "disposition" }, - { "captions", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_CAPTIONS }, .unit = "disposition" }, - { "descriptions", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DESCRIPTIONS }, .unit = "disposition" }, - { "metadata", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_METADATA }, .unit = "disposition" }, - { "dependent", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DEPENDENT }, .unit = "disposition" }, - { "still_image", .type = AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_STILL_IMAGE }, .unit = "disposition" }, - { NULL } -}; - -static const AVClass stream_class = { - .class_name = "AVStream", - .item_name = av_default_item_name, - .version = LIBAVUTIL_VERSION_INT, - .option = stream_options, -}; - -const AVClass *av_stream_get_class(void) -{ - return &stream_class; -} - -AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c) -{ - FFFormatContext *const si = ffformatcontext(s); - FFStream *sti; - AVStream *st; - AVStream **streams; - - if (s->nb_streams >= s->max_streams) { - av_log(s, AV_LOG_ERROR, "Number of streams exceeds max_streams parameter" - " (%d), see the documentation if you wish to increase it\n", - s->max_streams); - return NULL; - } - streams = av_realloc_array(s->streams, s->nb_streams + 1, sizeof(*streams)); - if (!streams) - return NULL; - s->streams = streams; - - - sti = av_mallocz(sizeof(*sti)); - if (!sti) - return NULL; - st = &sti->pub; - -#if FF_API_AVSTREAM_CLASS - st->av_class = &stream_class; -#endif - - st->codecpar = avcodec_parameters_alloc(); - if (!st->codecpar) - goto fail; - - sti->avctx = avcodec_alloc_context3(NULL); - if (!sti->avctx) - goto fail; - - if (s->iformat) { - sti->info = av_mallocz(sizeof(*sti->info)); - if (!sti->info) - goto fail; - -#if FF_API_R_FRAME_RATE - sti->info->last_dts = AV_NOPTS_VALUE; -#endif - sti->info->fps_first_dts = AV_NOPTS_VALUE; - sti->info->fps_last_dts = AV_NOPTS_VALUE; - - /* default pts setting is MPEG-like */ - avpriv_set_pts_info(st, 33, 1, 90000); - /* we set the current DTS to 0 so that formats without any timestamps - * but durations get some timestamps, formats with some unknown - * timestamps have their first few packets buffered and the - * timestamps corrected before they are returned to the user */ - sti->cur_dts = RELATIVE_TS_BASE; - } else { - sti->cur_dts = AV_NOPTS_VALUE; - } - - st->index = s->nb_streams; - st->start_time = AV_NOPTS_VALUE; - st->duration = AV_NOPTS_VALUE; - sti->first_dts = AV_NOPTS_VALUE; - sti->probe_packets = s->max_probe_packets; - sti->pts_wrap_reference = AV_NOPTS_VALUE; - sti->pts_wrap_behavior = AV_PTS_WRAP_IGNORE; - - sti->last_IP_pts = AV_NOPTS_VALUE; - sti->last_dts_for_order_check = AV_NOPTS_VALUE; - for (int i = 0; i < MAX_REORDER_DELAY + 1; i++) - sti->pts_buffer[i] = AV_NOPTS_VALUE; - - st->sample_aspect_ratio = (AVRational) { 0, 1 }; - - sti->inject_global_side_data = si->inject_global_side_data; - - sti->need_context_update = 1; - - s->streams[s->nb_streams++] = st; - return st; -fail: - free_stream(&st); - return NULL; -} - -AVProgram *av_new_program(AVFormatContext *ac, int id) -{ - AVProgram *program = NULL; - int ret; - - av_log(ac, AV_LOG_TRACE, "new_program: id=0x%04x\n", id); - - for (unsigned i = 0; i < ac->nb_programs; i++) - if (ac->programs[i]->id == id) - program = ac->programs[i]; - - if (!program) { - program = av_mallocz(sizeof(AVProgram)); - if (!program) - return NULL; - ret = av_dynarray_add_nofree(&ac->programs, &ac->nb_programs, program); - if (ret < 0) { - av_free(program); - return NULL; - } - program->discard = AVDISCARD_NONE; - program->pmt_version = -1; - program->id = id; - program->pts_wrap_reference = AV_NOPTS_VALUE; - program->pts_wrap_behavior = AV_PTS_WRAP_IGNORE; - program->start_time = - program->end_time = AV_NOPTS_VALUE; - } - return program; -} - -AVChapter *avpriv_new_chapter(AVFormatContext *s, int64_t id, AVRational time_base, - int64_t start, int64_t end, const char *title) -{ - FFFormatContext *const si = ffformatcontext(s); - AVChapter *chapter = NULL; - int ret; - - if (end != AV_NOPTS_VALUE && start > end) { - av_log(s, AV_LOG_ERROR, "Chapter end time %"PRId64" before start %"PRId64"\n", end, start); - return NULL; - } - - if (!s->nb_chapters) { - si->chapter_ids_monotonic = 1; - } else if (!si->chapter_ids_monotonic || s->chapters[s->nb_chapters-1]->id >= id) { - for (unsigned i = 0; i < s->nb_chapters; i++) - if (s->chapters[i]->id == id) - chapter = s->chapters[i]; - if (!chapter) - si->chapter_ids_monotonic = 0; - } - - if (!chapter) { - chapter = av_mallocz(sizeof(AVChapter)); - if (!chapter) - return NULL; - ret = av_dynarray_add_nofree(&s->chapters, &s->nb_chapters, chapter); - if (ret < 0) { - av_free(chapter); - return NULL; - } - } - av_dict_set(&chapter->metadata, "title", title, 0); - chapter->id = id; - chapter->time_base = time_base; - chapter->start = start; - chapter->end = end; - - return chapter; -} - -void av_program_add_stream_index(AVFormatContext *ac, int progid, unsigned idx) -{ - AVProgram *program = NULL; - void *tmp; - - if (idx >= ac->nb_streams) { - av_log(ac, AV_LOG_ERROR, "stream index %d is not valid\n", idx); - return; - } - - for (unsigned i = 0; i < ac->nb_programs; i++) { - if (ac->programs[i]->id != progid) - continue; - program = ac->programs[i]; - for (unsigned j = 0; j < program->nb_stream_indexes; j++) - if (program->stream_index[j] == idx) - return; - - tmp = av_realloc_array(program->stream_index, program->nb_stream_indexes+1, sizeof(unsigned int)); - if (!tmp) - return; - program->stream_index = tmp; - program->stream_index[program->nb_stream_indexes++] = idx; - return; - } -} - uint64_t ff_ntp_time(void) { return (av_gettime() / 1000) * 1000 + NTP_OFFSET_US; @@ -1136,7 +443,7 @@ int ff_mkdir_p(const char *path) } } - if ((*(pos - 1) != '/') || (*(pos - 1) != '\\')) { + if ((*(pos - 1) != '/') && (*(pos - 1) != '\\')) { ret = mkdir(temp, 0755); } @@ -1193,32 +500,6 @@ int ff_hex_to_data(uint8_t *data, const char *p) return len; } -void avpriv_set_pts_info(AVStream *st, int pts_wrap_bits, - unsigned int pts_num, unsigned int pts_den) -{ - FFStream *const sti = ffstream(st); - AVRational new_tb; - if (av_reduce(&new_tb.num, &new_tb.den, pts_num, pts_den, INT_MAX)) { - if (new_tb.num != pts_num) - av_log(NULL, AV_LOG_DEBUG, - "st:%d removing common factor %d from timebase\n", - st->index, pts_num / new_tb.num); - } else - av_log(NULL, AV_LOG_WARNING, - "st:%d has too large timebase, reducing\n", st->index); - - if (new_tb.num <= 0 || new_tb.den <= 0) { - av_log(NULL, AV_LOG_ERROR, - "Ignoring attempt to set invalid timebase %d/%d for st:%d\n", - new_tb.num, new_tb.den, - st->index); - return; - } - st->time_base = new_tb; - sti->avctx->pkt_timebase = new_tb; - st->pts_wrap_bits = pts_wrap_bits; -} - void ff_parse_key_value(const char *str, ff_parse_key_val_cb callback_get_buf, void *context) { @@ -1273,32 +554,6 @@ void ff_parse_key_value(const char *str, ff_parse_key_val_cb callback_get_buf, } } -int ff_find_stream_index(const AVFormatContext *s, int id) -{ - for (unsigned i = 0; i < s->nb_streams; i++) - if (s->streams[i]->id == id) - return i; - return -1; -} - -int avformat_query_codec(const AVOutputFormat *ofmt, enum AVCodecID codec_id, - int std_compliance) -{ - if (ofmt) { - unsigned int codec_tag; - if (ofmt->query_codec) - return ofmt->query_codec(codec_id, std_compliance); - else if (ofmt->codec_tag) - return !!av_codec_get_tag2(ofmt->codec_tag, codec_id, &codec_tag); - else if (codec_id == ofmt->video_codec || - codec_id == ofmt->audio_codec || - codec_id == ofmt->subtitle_codec || - codec_id == ofmt->data_codec) - return 1; - } - return AVERROR_PATCHWELCOME; -} - int avformat_network_init(void) { #if CONFIG_NETWORK @@ -1320,599 +575,11 @@ int avformat_network_deinit(void) return 0; } -int ff_add_param_change(AVPacket *pkt, int32_t channels, - uint64_t channel_layout, int32_t sample_rate, - int32_t width, int32_t height) -{ - uint32_t flags = 0; - int size = 4; - uint8_t *data; - if (!pkt) - return AVERROR(EINVAL); - if (channels) { - size += 4; - flags |= AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT; - } - if (channel_layout) { - size += 8; - flags |= AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_LAYOUT; - } - if (sample_rate) { - size += 4; - flags |= AV_SIDE_DATA_PARAM_CHANGE_SAMPLE_RATE; - } - if (width || height) { - size += 8; - flags |= AV_SIDE_DATA_PARAM_CHANGE_DIMENSIONS; - } - data = av_packet_new_side_data(pkt, AV_PKT_DATA_PARAM_CHANGE, size); - if (!data) - return AVERROR(ENOMEM); - bytestream_put_le32(&data, flags); - if (channels) - bytestream_put_le32(&data, channels); - if (channel_layout) - bytestream_put_le64(&data, channel_layout); - if (sample_rate) - bytestream_put_le32(&data, sample_rate); - if (width || height) { - bytestream_put_le32(&data, width); - bytestream_put_le32(&data, height); - } - return 0; -} - -AVRational av_guess_sample_aspect_ratio(AVFormatContext *format, AVStream *stream, AVFrame *frame) -{ - AVRational undef = {0, 1}; - AVRational stream_sample_aspect_ratio = stream ? stream->sample_aspect_ratio : undef; - AVRational codec_sample_aspect_ratio = stream && stream->codecpar ? stream->codecpar->sample_aspect_ratio : undef; - AVRational frame_sample_aspect_ratio = frame ? frame->sample_aspect_ratio : codec_sample_aspect_ratio; - - av_reduce(&stream_sample_aspect_ratio.num, &stream_sample_aspect_ratio.den, - stream_sample_aspect_ratio.num, stream_sample_aspect_ratio.den, INT_MAX); - if (stream_sample_aspect_ratio.num <= 0 || stream_sample_aspect_ratio.den <= 0) - stream_sample_aspect_ratio = undef; - - av_reduce(&frame_sample_aspect_ratio.num, &frame_sample_aspect_ratio.den, - frame_sample_aspect_ratio.num, frame_sample_aspect_ratio.den, INT_MAX); - if (frame_sample_aspect_ratio.num <= 0 || frame_sample_aspect_ratio.den <= 0) - frame_sample_aspect_ratio = undef; - - if (stream_sample_aspect_ratio.num) - return stream_sample_aspect_ratio; - else - return frame_sample_aspect_ratio; -} - -AVRational av_guess_frame_rate(AVFormatContext *format, AVStream *st, AVFrame *frame) -{ - AVRational fr = st->r_frame_rate; - AVCodecContext *const avctx = ffstream(st)->avctx; - AVRational codec_fr = avctx->framerate; - AVRational avg_fr = st->avg_frame_rate; - - if (avg_fr.num > 0 && avg_fr.den > 0 && fr.num > 0 && fr.den > 0 && - av_q2d(avg_fr) < 70 && av_q2d(fr) > 210) { - fr = avg_fr; - } - - - if (avctx->ticks_per_frame > 1) { - if ( codec_fr.num > 0 && codec_fr.den > 0 && - (fr.num == 0 || av_q2d(codec_fr) < av_q2d(fr)*0.7 && fabs(1.0 - av_q2d(av_div_q(avg_fr, fr))) > 0.1)) - fr = codec_fr; - } - - return fr; -} - -/** - * Matches a stream specifier (but ignores requested index). - * - * @param indexptr set to point to the requested stream index if there is one - * - * @return <0 on error - * 0 if st is NOT a matching stream - * >0 if st is a matching stream - */ -static int match_stream_specifier(const AVFormatContext *s, const AVStream *st, - const char *spec, const char **indexptr, - const AVProgram **p) -{ - int match = 1; /* Stores if the specifier matches so far. */ - while (*spec) { - if (*spec <= '9' && *spec >= '0') { /* opt:index */ - if (indexptr) - *indexptr = spec; - return match; - } else if (*spec == 'v' || *spec == 'a' || *spec == 's' || *spec == 'd' || - *spec == 't' || *spec == 'V') { /* opt:[vasdtV] */ - enum AVMediaType type; - int nopic = 0; - - switch (*spec++) { - 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; - case 't': type = AVMEDIA_TYPE_ATTACHMENT; break; - case 'V': type = AVMEDIA_TYPE_VIDEO; nopic = 1; break; - default: av_assert0(0); - } - if (*spec && *spec++ != ':') /* If we are not at the end, then another specifier must follow. */ - return AVERROR(EINVAL); - - if (type != st->codecpar->codec_type) - match = 0; - if (nopic && (st->disposition & AV_DISPOSITION_ATTACHED_PIC)) - match = 0; - } else if (*spec == 'p' && *(spec + 1) == ':') { - int prog_id; - int found = 0; - char *endptr; - spec += 2; - prog_id = strtol(spec, &endptr, 0); - /* Disallow empty id and make sure that if we are not at the end, then another specifier must follow. */ - if (spec == endptr || (*endptr && *endptr++ != ':')) - return AVERROR(EINVAL); - spec = endptr; - if (match) { - for (unsigned i = 0; i < s->nb_programs; i++) { - if (s->programs[i]->id != prog_id) - continue; - - for (unsigned j = 0; j < s->programs[i]->nb_stream_indexes; j++) { - if (st->index == s->programs[i]->stream_index[j]) { - found = 1; - if (p) - *p = s->programs[i]; - i = s->nb_programs; - break; - } - } - } - } - if (!found) - match = 0; - } else if (*spec == '#' || - (*spec == 'i' && *(spec + 1) == ':')) { - int stream_id; - char *endptr; - spec += 1 + (*spec == 'i'); - stream_id = strtol(spec, &endptr, 0); - if (spec == endptr || *endptr) /* Disallow empty id and make sure we are at the end. */ - return AVERROR(EINVAL); - return match && (stream_id == st->id); - } else if (*spec == 'm' && *(spec + 1) == ':') { - const AVDictionaryEntry *tag; - char *key, *val; - int ret; - - if (match) { - spec += 2; - val = strchr(spec, ':'); - - key = val ? av_strndup(spec, val - spec) : av_strdup(spec); - if (!key) - return AVERROR(ENOMEM); - - tag = av_dict_get(st->metadata, key, NULL, 0); - if (tag) { - if (!val || !strcmp(tag->value, val + 1)) - ret = 1; - else - ret = 0; - } else - ret = 0; - - av_freep(&key); - } - return match && ret; - } else if (*spec == 'u' && *(spec + 1) == '\0') { - const AVCodecParameters *par = st->codecpar; - int val; - switch (par->codec_type) { - case AVMEDIA_TYPE_AUDIO: - val = par->sample_rate && par->channels; - if (par->format == AV_SAMPLE_FMT_NONE) - return 0; - break; - case AVMEDIA_TYPE_VIDEO: - val = par->width && par->height; - if (par->format == AV_PIX_FMT_NONE) - return 0; - break; - case AVMEDIA_TYPE_UNKNOWN: - val = 0; - break; - default: - val = 1; - break; - } - return match && (par->codec_id != AV_CODEC_ID_NONE && val != 0); - } else { - return AVERROR(EINVAL); - } - } - - return match; -} - - -int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st, - const char *spec) -{ - int ret, index; - char *endptr; - const char *indexptr = NULL; - const AVProgram *p = NULL; - int nb_streams; - - ret = match_stream_specifier(s, st, spec, &indexptr, &p); - if (ret < 0) - goto error; - - if (!indexptr) - return ret; - - index = strtol(indexptr, &endptr, 0); - if (*endptr) { /* We can't have anything after the requested index. */ - ret = AVERROR(EINVAL); - goto error; - } - - /* This is not really needed but saves us a loop for simple stream index specifiers. */ - if (spec == indexptr) - return (index == st->index); - - /* If we requested a matching stream index, we have to ensure st is that. */ - nb_streams = p ? p->nb_stream_indexes : s->nb_streams; - for (int i = 0; i < nb_streams && index >= 0; i++) { - const AVStream *candidate = s->streams[p ? p->stream_index[i] : i]; - ret = match_stream_specifier(s, candidate, spec, NULL, NULL); - if (ret < 0) - goto error; - if (ret > 0 && index-- == 0 && st == candidate) - return 1; - } - return 0; - -error: - if (ret == AVERROR(EINVAL)) - av_log(s, AV_LOG_ERROR, "Invalid stream specifier: %s.\n", spec); - return ret; -} - -int ff_generate_avci_extradata(AVStream *st) -{ - static const uint8_t avci100_1080p_extradata[] = { - // SPS - 0x00, 0x00, 0x00, 0x01, 0x67, 0x7a, 0x10, 0x29, - 0xb6, 0xd4, 0x20, 0x22, 0x33, 0x19, 0xc6, 0x63, - 0x23, 0x21, 0x01, 0x11, 0x98, 0xce, 0x33, 0x19, - 0x18, 0x21, 0x02, 0x56, 0xb9, 0x3d, 0x7d, 0x7e, - 0x4f, 0xe3, 0x3f, 0x11, 0xf1, 0x9e, 0x08, 0xb8, - 0x8c, 0x54, 0x43, 0xc0, 0x78, 0x02, 0x27, 0xe2, - 0x70, 0x1e, 0x30, 0x10, 0x10, 0x14, 0x00, 0x00, - 0x03, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0xca, - 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // PPS - 0x00, 0x00, 0x00, 0x01, 0x68, 0xce, 0x33, 0x48, - 0xd0 - }; - static const uint8_t avci100_1080i_extradata[] = { - // SPS - 0x00, 0x00, 0x00, 0x01, 0x67, 0x7a, 0x10, 0x29, - 0xb6, 0xd4, 0x20, 0x22, 0x33, 0x19, 0xc6, 0x63, - 0x23, 0x21, 0x01, 0x11, 0x98, 0xce, 0x33, 0x19, - 0x18, 0x21, 0x03, 0x3a, 0x46, 0x65, 0x6a, 0x65, - 0x24, 0xad, 0xe9, 0x12, 0x32, 0x14, 0x1a, 0x26, - 0x34, 0xad, 0xa4, 0x41, 0x82, 0x23, 0x01, 0x50, - 0x2b, 0x1a, 0x24, 0x69, 0x48, 0x30, 0x40, 0x2e, - 0x11, 0x12, 0x08, 0xc6, 0x8c, 0x04, 0x41, 0x28, - 0x4c, 0x34, 0xf0, 0x1e, 0x01, 0x13, 0xf2, 0xe0, - 0x3c, 0x60, 0x20, 0x20, 0x28, 0x00, 0x00, 0x03, - 0x00, 0x08, 0x00, 0x00, 0x03, 0x01, 0x94, 0x20, - // PPS - 0x00, 0x00, 0x00, 0x01, 0x68, 0xce, 0x33, 0x48, - 0xd0 - }; - static const uint8_t avci50_1080p_extradata[] = { - // SPS - 0x00, 0x00, 0x00, 0x01, 0x67, 0x6e, 0x10, 0x28, - 0xa6, 0xd4, 0x20, 0x32, 0x33, 0x0c, 0x71, 0x18, - 0x88, 0x62, 0x10, 0x19, 0x19, 0x86, 0x38, 0x8c, - 0x44, 0x30, 0x21, 0x02, 0x56, 0x4e, 0x6f, 0x37, - 0xcd, 0xf9, 0xbf, 0x81, 0x6b, 0xf3, 0x7c, 0xde, - 0x6e, 0x6c, 0xd3, 0x3c, 0x05, 0xa0, 0x22, 0x7e, - 0x5f, 0xfc, 0x00, 0x0c, 0x00, 0x13, 0x8c, 0x04, - 0x04, 0x05, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, - 0x00, 0x03, 0x00, 0x32, 0x84, 0x00, 0x00, 0x00, - // PPS - 0x00, 0x00, 0x00, 0x01, 0x68, 0xee, 0x31, 0x12, - 0x11 - }; - static const uint8_t avci50_1080i_extradata[] = { - // SPS - 0x00, 0x00, 0x00, 0x01, 0x67, 0x6e, 0x10, 0x28, - 0xa6, 0xd4, 0x20, 0x32, 0x33, 0x0c, 0x71, 0x18, - 0x88, 0x62, 0x10, 0x19, 0x19, 0x86, 0x38, 0x8c, - 0x44, 0x30, 0x21, 0x02, 0x56, 0x4e, 0x6e, 0x61, - 0x87, 0x3e, 0x73, 0x4d, 0x98, 0x0c, 0x03, 0x06, - 0x9c, 0x0b, 0x73, 0xe6, 0xc0, 0xb5, 0x18, 0x63, - 0x0d, 0x39, 0xe0, 0x5b, 0x02, 0xd4, 0xc6, 0x19, - 0x1a, 0x79, 0x8c, 0x32, 0x34, 0x24, 0xf0, 0x16, - 0x81, 0x13, 0xf7, 0xff, 0x80, 0x02, 0x00, 0x01, - 0xf1, 0x80, 0x80, 0x80, 0xa0, 0x00, 0x00, 0x03, - 0x00, 0x20, 0x00, 0x00, 0x06, 0x50, 0x80, 0x00, - // PPS - 0x00, 0x00, 0x00, 0x01, 0x68, 0xee, 0x31, 0x12, - 0x11 - }; - static const uint8_t avci100_720p_extradata[] = { - // SPS - 0x00, 0x00, 0x00, 0x01, 0x67, 0x7a, 0x10, 0x29, - 0xb6, 0xd4, 0x20, 0x2a, 0x33, 0x1d, 0xc7, 0x62, - 0xa1, 0x08, 0x40, 0x54, 0x66, 0x3b, 0x8e, 0xc5, - 0x42, 0x02, 0x10, 0x25, 0x64, 0x2c, 0x89, 0xe8, - 0x85, 0xe4, 0x21, 0x4b, 0x90, 0x83, 0x06, 0x95, - 0xd1, 0x06, 0x46, 0x97, 0x20, 0xc8, 0xd7, 0x43, - 0x08, 0x11, 0xc2, 0x1e, 0x4c, 0x91, 0x0f, 0x01, - 0x40, 0x16, 0xec, 0x07, 0x8c, 0x04, 0x04, 0x05, - 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x03, - 0x00, 0x64, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, - // PPS - 0x00, 0x00, 0x00, 0x01, 0x68, 0xce, 0x31, 0x12, - 0x11 - }; - static const uint8_t avci50_720p_extradata[] = { - // SPS - 0x00, 0x00, 0x00, 0x01, 0x67, 0x6e, 0x10, 0x20, - 0xa6, 0xd4, 0x20, 0x32, 0x33, 0x0c, 0x71, 0x18, - 0x88, 0x62, 0x10, 0x19, 0x19, 0x86, 0x38, 0x8c, - 0x44, 0x30, 0x21, 0x02, 0x56, 0x4e, 0x6f, 0x37, - 0xcd, 0xf9, 0xbf, 0x81, 0x6b, 0xf3, 0x7c, 0xde, - 0x6e, 0x6c, 0xd3, 0x3c, 0x0f, 0x01, 0x6e, 0xff, - 0xc0, 0x00, 0xc0, 0x01, 0x38, 0xc0, 0x40, 0x40, - 0x50, 0x00, 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, - 0x06, 0x48, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, - // PPS - 0x00, 0x00, 0x00, 0x01, 0x68, 0xee, 0x31, 0x12, - 0x11 - }; - - const uint8_t *data = NULL; - int ret, size = 0; - - if (st->codecpar->width == 1920) { - if (st->codecpar->field_order == AV_FIELD_PROGRESSIVE) { - data = avci100_1080p_extradata; - size = sizeof(avci100_1080p_extradata); - } else { - data = avci100_1080i_extradata; - size = sizeof(avci100_1080i_extradata); - } - } else if (st->codecpar->width == 1440) { - if (st->codecpar->field_order == AV_FIELD_PROGRESSIVE) { - data = avci50_1080p_extradata; - size = sizeof(avci50_1080p_extradata); - } else { - data = avci50_1080i_extradata; - size = sizeof(avci50_1080i_extradata); - } - } else if (st->codecpar->width == 1280) { - data = avci100_720p_extradata; - size = sizeof(avci100_720p_extradata); - } else if (st->codecpar->width == 960) { - data = avci50_720p_extradata; - size = sizeof(avci50_720p_extradata); - } - - if (!size) - return 0; - - if ((ret = ff_alloc_extradata(st->codecpar, size)) < 0) - return ret; - memcpy(st->codecpar->extradata, data, size); - - return 0; -} - -uint8_t *av_stream_get_side_data(const AVStream *st, - enum AVPacketSideDataType type, size_t *size) -{ - for (int i = 0; i < st->nb_side_data; i++) { - if (st->side_data[i].type == type) { - if (size) - *size = st->side_data[i].size; - return st->side_data[i].data; - } - } - if (size) - *size = 0; - return NULL; -} - -int av_stream_add_side_data(AVStream *st, enum AVPacketSideDataType type, - uint8_t *data, size_t size) -{ - AVPacketSideData *sd, *tmp; - - for (int i = 0; i < st->nb_side_data; i++) { - sd = &st->side_data[i]; - - if (sd->type == type) { - av_freep(&sd->data); - sd->data = data; - sd->size = size; - return 0; - } - } - - if ((unsigned)st->nb_side_data + 1 >= INT_MAX / sizeof(*st->side_data)) - return AVERROR(ERANGE); - - tmp = av_realloc(st->side_data, (st->nb_side_data + 1) * sizeof(*tmp)); - if (!tmp) { - return AVERROR(ENOMEM); - } - - st->side_data = tmp; - st->nb_side_data++; - - sd = &st->side_data[st->nb_side_data - 1]; - sd->type = type; - sd->data = data; - sd->size = size; - - return 0; -} - -uint8_t *av_stream_new_side_data(AVStream *st, enum AVPacketSideDataType type, - size_t size) -{ - int ret; - uint8_t *data = av_malloc(size); - - if (!data) - return NULL; - - ret = av_stream_add_side_data(st, type, data, size); - if (ret < 0) { - av_freep(&data); - return NULL; - } - - return data; -} - -int ff_stream_add_bitstream_filter(AVStream *st, const char *name, const char *args) -{ - int ret; - const AVBitStreamFilter *bsf; - FFStream *const sti = ffstream(st); - AVBSFContext *bsfc; - - av_assert0(!sti->bsfc); - - if (!(bsf = av_bsf_get_by_name(name))) { - av_log(NULL, AV_LOG_ERROR, "Unknown bitstream filter '%s'\n", name); - return AVERROR_BSF_NOT_FOUND; - } - - if ((ret = av_bsf_alloc(bsf, &bsfc)) < 0) - return ret; - - bsfc->time_base_in = st->time_base; - if ((ret = avcodec_parameters_copy(bsfc->par_in, st->codecpar)) < 0) { - av_bsf_free(&bsfc); - return ret; - } - - if (args && bsfc->filter->priv_class) { - if ((ret = av_set_options_string(bsfc->priv_data, args, "=", ":")) < 0) { - av_bsf_free(&bsfc); - return ret; - } - } - - if ((ret = av_bsf_init(bsfc)) < 0) { - av_bsf_free(&bsfc); - return ret; - } - - sti->bsfc = bsfc; - - av_log(NULL, AV_LOG_VERBOSE, - "Automatically inserted bitstream filter '%s'; args='%s'\n", - name, args ? args : ""); - return 1; -} - -int ff_format_output_open(AVFormatContext *s, const char *url, AVDictionary **options) -{ - if (!s->oformat) - return AVERROR(EINVAL); - - if (!(s->oformat->flags & AVFMT_NOFILE)) - return s->io_open(s, &s->pb, url, AVIO_FLAG_WRITE, options); - return 0; -} - -void ff_format_io_close_default(AVFormatContext *s, AVIOContext *pb) -{ - avio_close(pb); -} - -int ff_format_io_close(AVFormatContext *s, AVIOContext **pb) -{ - int ret = 0; - if (*pb) { - if (s->io_close == ff_format_io_close_default || s->io_close == NULL) - ret = s->io_close2(s, *pb); - else - s->io_close(s, *pb); - } - *pb = NULL; - return ret; -} - int ff_is_http_proto(const 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; - int64_t parsed_timestamp; - int ret; - if ((entry = av_dict_get(s->metadata, "creation_time", NULL, 0))) { - if ((ret = av_parse_time(&parsed_timestamp, entry->value, 0)) >= 0) { - *timestamp = return_seconds ? parsed_timestamp / 1000000 : parsed_timestamp; - return 1; - } else { - av_log(s, AV_LOG_WARNING, "Failed to parse creation_time %s\n", entry->value); - return ret; - } - } - return 0; -} - -int ff_standardize_creation_time(AVFormatContext *s) -{ - int64_t timestamp; - int ret = ff_parse_creation_time_metadata(s, ×tamp, 0); - if (ret == 1) - return avpriv_dict_set_timestamp(&s->metadata, "creation_time", timestamp); - return ret; -} - -int ff_get_packet_palette(AVFormatContext *s, AVPacket *pkt, int ret, uint32_t *palette) -{ - uint8_t *side_data; - size_t size; - - side_data = av_packet_get_side_data(pkt, AV_PKT_DATA_PALETTE, &size); - if (side_data) { - if (size != AVPALETTE_SIZE) { - av_log(s, AV_LOG_ERROR, "Invalid palette side data\n"); - return AVERROR_INVALIDDATA; - } - memcpy(palette, side_data, AVPALETTE_SIZE); - return 1; - } - - if (ret == CONTAINS_PAL) { - for (int i = 0; i < AVPALETTE_COUNT; i++) - palette[i] = AV_RL32(pkt->data + pkt->size - AVPALETTE_SIZE + i*4); - return 1; - } - - return 0; -} - int ff_bprint_to_codecpar_extradata(AVCodecParameters *par, struct AVBPrint *buf) { int ret; @@ -1935,159 +602,3 @@ int ff_bprint_to_codecpar_extradata(AVCodecParameters *par, struct AVBPrint *buf par->extradata_size = buf->len; return 0; } - -int avformat_transfer_internal_stream_timing_info(const AVOutputFormat *ofmt, - AVStream *ost, const AVStream *ist, - enum AVTimebaseSource copy_tb) -{ - const AVCodecContext *const dec_ctx = cffstream(ist)->avctx; - AVCodecContext *const enc_ctx = ffstream(ost)->avctx; - - enc_ctx->time_base = ist->time_base; - /* - * Avi is a special case here because it supports variable fps but - * having the fps and timebase differe significantly adds quite some - * overhead - */ - if (!strcmp(ofmt->name, "avi")) { -#if FF_API_R_FRAME_RATE - if (copy_tb == AVFMT_TBCF_AUTO && ist->r_frame_rate.num - && av_q2d(ist->r_frame_rate) >= av_q2d(ist->avg_frame_rate) - && 0.5/av_q2d(ist->r_frame_rate) > av_q2d(ist->time_base) - && 0.5/av_q2d(ist->r_frame_rate) > av_q2d(dec_ctx->time_base) - && av_q2d(ist->time_base) < 1.0/500 && av_q2d(dec_ctx->time_base) < 1.0/500 - || copy_tb == AVFMT_TBCF_R_FRAMERATE) { - enc_ctx->time_base.num = ist->r_frame_rate.den; - enc_ctx->time_base.den = 2*ist->r_frame_rate.num; - enc_ctx->ticks_per_frame = 2; - } else -#endif - if (copy_tb == AVFMT_TBCF_AUTO && av_q2d(dec_ctx->time_base)*dec_ctx->ticks_per_frame > 2*av_q2d(ist->time_base) - && av_q2d(ist->time_base) < 1.0/500 - || copy_tb == AVFMT_TBCF_DECODER) { - enc_ctx->time_base = dec_ctx->time_base; - enc_ctx->time_base.num *= dec_ctx->ticks_per_frame; - enc_ctx->time_base.den *= 2; - enc_ctx->ticks_per_frame = 2; - } - } else if (!(ofmt->flags & AVFMT_VARIABLE_FPS) - && !av_match_name(ofmt->name, "mov,mp4,3gp,3g2,psp,ipod,ismv,f4v")) { - if (copy_tb == AVFMT_TBCF_AUTO && dec_ctx->time_base.den - && av_q2d(dec_ctx->time_base)*dec_ctx->ticks_per_frame > av_q2d(ist->time_base) - && av_q2d(ist->time_base) < 1.0/500 - || copy_tb == AVFMT_TBCF_DECODER) { - enc_ctx->time_base = dec_ctx->time_base; - enc_ctx->time_base.num *= dec_ctx->ticks_per_frame; - } - } - - if ((enc_ctx->codec_tag == AV_RL32("tmcd") || ost->codecpar->codec_tag == AV_RL32("tmcd")) - && dec_ctx->time_base.num < dec_ctx->time_base.den - && dec_ctx->time_base.num > 0 - && 121LL*dec_ctx->time_base.num > dec_ctx->time_base.den) { - enc_ctx->time_base = dec_ctx->time_base; - } - - av_reduce(&enc_ctx->time_base.num, &enc_ctx->time_base.den, - enc_ctx->time_base.num, enc_ctx->time_base.den, INT_MAX); - - return 0; -} - -AVRational av_stream_get_codec_timebase(const AVStream *st) -{ - // See avformat_transfer_internal_stream_timing_info() TODO. - return cffstream(st)->avctx->time_base; -} - -void ff_format_set_url(AVFormatContext *s, char *url) -{ - av_assert0(url); - av_freep(&s->url); - s->url = url; -} - -static int option_is_disposition(const AVOption *opt) -{ - return opt->type == AV_OPT_TYPE_CONST && - opt->unit && !strcmp(opt->unit, "disposition"); -} - -int av_disposition_from_string(const char *disp) -{ - for (const AVOption *opt = stream_options; opt->name; opt++) - if (option_is_disposition(opt) && !strcmp(disp, opt->name)) - return opt->default_val.i64; - return AVERROR(EINVAL); -} - -const char *av_disposition_to_string(int disposition) -{ - int val; - - if (disposition <= 0) - return NULL; - - val = 1 << ff_ctz(disposition); - for (const AVOption *opt = stream_options; opt->name; opt++) - if (option_is_disposition(opt) && opt->default_val.i64 == val) - return opt->name; - - return NULL; -} - -int ff_format_shift_data(AVFormatContext *s, int64_t read_start, int shift_size) -{ - int ret; - int64_t pos, pos_end; - uint8_t *buf, *read_buf[2]; - int read_buf_id = 0; - int read_size[2]; - AVIOContext *read_pb; - - buf = av_malloc_array(shift_size, 2); - if (!buf) - return AVERROR(ENOMEM); - read_buf[0] = buf; - read_buf[1] = buf + shift_size; - - /* Shift the data: the AVIO context of the output can only be used for - * 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->url, AVIO_FLAG_READ, NULL); - if (ret < 0) { - av_log(s, AV_LOG_ERROR, "Unable to re-open %s output file for shifting data\n", s->url); - goto end; - } - - /* mark the end of the shift to up to the last data we wrote, and get ready - * for writing */ - pos_end = avio_tell(s->pb); - avio_seek(s->pb, read_start + shift_size, SEEK_SET); - - avio_seek(read_pb, read_start, 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(s->pb, read_buf[read_buf_id], n); - pos += n; - } while (pos < pos_end); - ret = ff_format_io_close(s, &read_pb); - -end: - av_free(buf); - return ret; -} diff --git a/libavformat/vag.c b/libavformat/vag.c index 9ef5466e3..b3aa1c5b9 100644 --- a/libavformat/vag.c +++ b/libavformat/vag.c @@ -42,9 +42,9 @@ static int vag_read_header(AVFormatContext *s) avio_skip(s->pb, 4); st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_ADPCM_PSX; - st->codecpar->channels = 1 + (avio_rb32(s->pb) == 0x00000004); + st->codecpar->ch_layout.nb_channels = 1 + (avio_rb32(s->pb) == 0x00000004); avio_skip(s->pb, 4); - if (st->codecpar->channels > 1) { + if (st->codecpar->ch_layout.nb_channels > 1) { st->duration = avio_rb32(s->pb); } else { st->duration = avio_rb32(s->pb) / 16 * 28; @@ -54,12 +54,12 @@ static int vag_read_header(AVFormatContext *s) return AVERROR_INVALIDDATA; avio_seek(s->pb, 0x1000, SEEK_SET); if (avio_rl32(s->pb) == MKTAG('V','A','G','p')) { - st->codecpar->block_align = 0x1000 * st->codecpar->channels; + st->codecpar->block_align = 0x1000 * st->codecpar->ch_layout.nb_channels; avio_seek(s->pb, 0, SEEK_SET); st->duration = st->duration / 16 * 28; } else { - st->codecpar->block_align = 16 * st->codecpar->channels; - avio_seek(s->pb, st->codecpar->channels > 1 ? 0x80 : 0x30, SEEK_SET); + st->codecpar->block_align = 16 * st->codecpar->ch_layout.nb_channels; + avio_seek(s->pb, st->codecpar->ch_layout.nb_channels > 1 ? 0x80 : 0x30, SEEK_SET); } avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); diff --git a/libavformat/vc1test.c b/libavformat/vc1test.c index 90ea729e0..67edc699c 100644 --- a/libavformat/vc1test.c +++ b/libavformat/vc1test.c @@ -28,6 +28,7 @@ #include "libavutil/intreadwrite.h" #include "avformat.h" +#include "demux.h" #include "internal.h" #define VC1_EXTRADATA_SIZE 4 diff --git a/libavformat/version.c b/libavformat/version.c new file mode 100644 index 000000000..5f321d847 --- /dev/null +++ b/libavformat/version.c @@ -0,0 +1,45 @@ +/* + * Version functions. + * + * 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/avassert.h" +#include "avformat.h" +#include "version.h" + +#include "libavutil/ffversion.h" +const char av_format_ffversion[] = "FFmpeg version " FFMPEG_VERSION; + +unsigned avformat_version(void) +{ + av_assert0(LIBAVFORMAT_VERSION_MICRO >= 100); + return LIBAVFORMAT_VERSION_INT; +} + +const char *avformat_configuration(void) +{ + return FFMPEG_CONFIGURATION; +} + +const char *avformat_license(void) +{ +#define LICENSE_PREFIX "libavformat license: " + return &LICENSE_PREFIX FFMPEG_LICENSE[sizeof(LICENSE_PREFIX) - 1]; +} diff --git a/libavformat/version.h b/libavformat/version.h index c53d9a644..b234218b1 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -29,10 +29,9 @@ #include "libavutil/version.h" -// 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 59 -#define LIBAVFORMAT_VERSION_MINOR 16 +#include "version_major.h" + +#define LIBAVFORMAT_VERSION_MINOR 27 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ @@ -45,23 +44,4 @@ #define LIBAVFORMAT_IDENT "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION) -/** - * FF_API_* defines may be placed below to indicate public API that will be - * 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. - * - * @note, when bumping the major version it is recommended to manually - * disable each FF_API_* in its own commit instead of disabling them all - * at once through the bump. This improves the git bisect-ability of the change. - * - */ -#define FF_API_LAVF_PRIV_OPT (LIBAVFORMAT_VERSION_MAJOR < 60) -#define FF_API_COMPUTE_PKT_FIELDS2 (LIBAVFORMAT_VERSION_MAJOR < 60) -#define FF_API_AVIOCONTEXT_WRITTEN (LIBAVFORMAT_VERSION_MAJOR < 60) -#define FF_HLS_TS_OPTIONS (LIBAVFORMAT_VERSION_MAJOR < 60) -#define FF_API_AVSTREAM_CLASS (LIBAVFORMAT_VERSION_MAJOR > 59) -#define FF_HTTP_CACHE_REDIRECT_DEFAULT (LIBAVFORMAT_VERSION_MAJOR < 60) - - -#define FF_API_R_FRAME_RATE 1 #endif /* AVFORMAT_VERSION_H */ diff --git a/libavformat/version_major.h b/libavformat/version_major.h new file mode 100644 index 000000000..5f71298bc --- /dev/null +++ b/libavformat/version_major.h @@ -0,0 +1,53 @@ +/* + * Version macros. + * + * 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_VERSION_MAJOR_H +#define AVFORMAT_VERSION_MAJOR_H + +/** + * @file + * @ingroup libavf + * Libavformat version macros + */ + +// 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 59 + +/** + * FF_API_* defines may be placed below to indicate public API that will be + * 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. + * + * @note, when bumping the major version it is recommended to manually + * disable each FF_API_* in its own commit instead of disabling them all + * at once through the bump. This improves the git bisect-ability of the change. + * + */ +#define FF_API_LAVF_PRIV_OPT (LIBAVFORMAT_VERSION_MAJOR < 60) +#define FF_API_COMPUTE_PKT_FIELDS2 (LIBAVFORMAT_VERSION_MAJOR < 60) +#define FF_API_AVIOCONTEXT_WRITTEN (LIBAVFORMAT_VERSION_MAJOR < 60) +#define FF_HLS_TS_OPTIONS (LIBAVFORMAT_VERSION_MAJOR < 60) +#define FF_API_AVSTREAM_CLASS (LIBAVFORMAT_VERSION_MAJOR > 59) + + +#define FF_API_R_FRAME_RATE 1 + +#endif /* AVFORMAT_VERSION_MAJOR_H */ diff --git a/libavformat/vividas.c b/libavformat/vividas.c index d7a6e7465..e9954f73e 100644 --- a/libavformat/vividas.c +++ b/libavformat/vividas.c @@ -372,9 +372,9 @@ static int track_header(VividasDemuxContext *viv, AVFormatContext *s, uint8_t * avio_r8(pb); // '5' avio_r8(pb); //codec_id avio_rl16(pb); //codec_subid - st->codecpar->channels = avio_rl16(pb); // channels + st->codecpar->ch_layout.nb_channels = avio_rl16(pb); // channels st->codecpar->sample_rate = avio_rl32(pb); // sample_rate - if (st->codecpar->sample_rate <= 0 || st->codecpar->channels <= 0) + if (st->codecpar->sample_rate <= 0 || st->codecpar->ch_layout.nb_channels <= 0) return AVERROR_INVALIDDATA; avio_seek(pb, 10, SEEK_CUR); // data_1 q = avio_r8(pb); @@ -655,7 +655,8 @@ static int viv_read_packet(AVFormatContext *s, astream = s->streams[pkt->stream_index]; pkt->pts = av_rescale_q(viv->audio_sample, av_make_q(1, astream->codecpar->sample_rate), astream->time_base); - viv->audio_sample += viv->audio_subpackets[viv->current_audio_subpacket].pcm_bytes / 2 / astream->codecpar->channels; + viv->audio_sample += viv->audio_subpackets[viv->current_audio_subpacket].pcm_bytes / 2 / + astream->codecpar->ch_layout.nb_channels; pkt->flags |= AV_PKT_FLAG_KEY; viv->current_audio_subpacket++; return 0; diff --git a/libavformat/vivo.c b/libavformat/vivo.c index 2a08e1df0..02df4f001 100644 --- a/libavformat/vivo.c +++ b/libavformat/vivo.c @@ -249,7 +249,7 @@ static int vivo_read_header(AVFormatContext *s) ast->start_time = 0; ast->codecpar->codec_tag = 0; ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; - ast->codecpar->channels = 1; + ast->codecpar->ch_layout.nb_channels = 1; return 0; } diff --git a/libavformat/voc.c b/libavformat/voc.c index 04ec0da9b..a836ecb79 100644 --- a/libavformat/voc.c +++ b/libavformat/voc.c @@ -20,6 +20,7 @@ */ #include "config.h" +#include "config_components.h" #include "voc.h" #include "internal.h" diff --git a/libavformat/voc_packet.c b/libavformat/voc_packet.c index e5ae0be1d..32f8b29aa 100644 --- a/libavformat/voc_packet.c +++ b/libavformat/voc_packet.c @@ -72,7 +72,7 @@ ff_voc_get_packet(AVFormatContext *s, AVPacket *pkt, AVStream *st, int max_size) if (sample_rate) par->sample_rate = sample_rate; avpriv_set_pts_info(st, 64, 1, par->sample_rate); - par->channels = channels; + par->ch_layout.nb_channels = channels; par->bits_per_coded_sample = av_get_bits_per_sample(par->codec_id); } else avio_skip(pb, 1); @@ -103,7 +103,8 @@ ff_voc_get_packet(AVFormatContext *s, AVPacket *pkt, AVStream *st, int max_size) par->sample_rate = avio_rl32(pb); avpriv_set_pts_info(st, 64, 1, par->sample_rate); par->bits_per_coded_sample = avio_r8(pb); - par->channels = avio_r8(pb); + channels = avio_r8(pb); + par->ch_layout.nb_channels = channels; } else avio_skip(pb, 6); tmp_codec = avio_rl16(pb); @@ -140,7 +141,7 @@ ff_voc_get_packet(AVFormatContext *s, AVPacket *pkt, AVStream *st, int max_size) } } - par->bit_rate = (int64_t)par->sample_rate * par->channels * par->bits_per_coded_sample; + par->bit_rate = (int64_t)par->sample_rate * par->ch_layout.nb_channels * par->bits_per_coded_sample; if (max_size <= 0) max_size = 2048; diff --git a/libavformat/vocenc.c b/libavformat/vocenc.c index 798b463a8..59c2bbba7 100644 --- a/libavformat/vocenc.c +++ b/libavformat/vocenc.c @@ -63,16 +63,17 @@ static int voc_write_packet(AVFormatContext *s, AVPacket *pkt) avio_wl24(pb, pkt->size + 12); avio_wl32(pb, par->sample_rate); avio_w8(pb, par->bits_per_coded_sample); - avio_w8(pb, par->channels); + avio_w8(pb, par->ch_layout.nb_channels); avio_wl16(pb, par->codec_tag); avio_wl32(pb, 0); } else { - if (s->streams[0]->codecpar->channels > 1) { + if (s->streams[0]->codecpar->ch_layout.nb_channels > 1) { avio_w8(pb, VOC_TYPE_EXTENDED); avio_wl24(pb, 4); - avio_wl16(pb, 65536-(256000000 + par->sample_rate*par->channels/2)/(par->sample_rate*par->channels)); + avio_wl16(pb, 65536 - (256000000 + par->sample_rate * par->ch_layout.nb_channels / 2) / + (par->sample_rate * par->ch_layout.nb_channels)); avio_w8(pb, par->codec_tag); - avio_w8(pb, par->channels - 1); + avio_w8(pb, par->ch_layout.nb_channels - 1); } avio_w8(pb, VOC_TYPE_VOICE_DATA); avio_wl24(pb, pkt->size + 2); diff --git a/libavformat/vpk.c b/libavformat/vpk.c index d542a0806..bfd49c630 100644 --- a/libavformat/vpk.c +++ b/libavformat/vpk.c @@ -21,6 +21,7 @@ #include "libavutil/intreadwrite.h" #include "avformat.h" +#include "demux.h" #include "internal.h" typedef struct VPKDemuxContext { @@ -59,14 +60,14 @@ static int vpk_read_header(AVFormatContext *s) st->codecpar->sample_rate = avio_rl32(s->pb); if (st->codecpar->sample_rate <= 0 || st->codecpar->block_align <= 0) return AVERROR_INVALIDDATA; - st->codecpar->channels = avio_rl32(s->pb); - if (st->codecpar->channels <= 0) + st->codecpar->ch_layout.nb_channels = avio_rl32(s->pb); + if (st->codecpar->ch_layout.nb_channels <= 0) return AVERROR_INVALIDDATA; - samples_per_block = ((st->codecpar->block_align / st->codecpar->channels) * 28LL) / 16; + samples_per_block = ((st->codecpar->block_align / st->codecpar->ch_layout.nb_channels) * 28LL) / 16; if (samples_per_block <= 0) return AVERROR_INVALIDDATA; vpk->block_count = (st->duration + (samples_per_block - 1)) / samples_per_block; - vpk->last_block_size = (st->duration % samples_per_block) * 16 * st->codecpar->channels / 28; + vpk->last_block_size = (st->duration % samples_per_block) * 16 * st->codecpar->ch_layout.nb_channels / 28; if (offset < avio_tell(s->pb)) return AVERROR_INVALIDDATA; @@ -85,14 +86,14 @@ static int vpk_read_packet(AVFormatContext *s, AVPacket *pkt) vpk->current_block++; if (vpk->current_block == vpk->block_count) { - unsigned size = vpk->last_block_size / par->channels; - unsigned skip = (par->block_align - vpk->last_block_size) / par->channels; + unsigned size = vpk->last_block_size / par->ch_layout.nb_channels; + unsigned skip = (par->block_align - vpk->last_block_size) / par->ch_layout.nb_channels; uint64_t pos = avio_tell(s->pb); ret = av_new_packet(pkt, vpk->last_block_size); if (ret < 0) return ret; - for (i = 0; i < par->channels; i++) { + for (i = 0; i < par->ch_layout.nb_channels; i++) { ret = avio_read(s->pb, pkt->data + i * size, size); avio_skip(s->pb, skip); if (ret != size) { diff --git a/libavformat/vqf.c b/libavformat/vqf.c index 76131cdc5..1671d03b2 100644 --- a/libavformat/vqf.c +++ b/libavformat/vqf.c @@ -136,12 +136,12 @@ static int vqf_read_header(AVFormatContext *s) return AVERROR_INVALIDDATA; avio_read(s->pb, comm_chunk, 12); - st->codecpar->channels = AV_RB32(comm_chunk ) + 1; + st->codecpar->ch_layout.nb_channels = AV_RB32(comm_chunk) + 1; read_bitrate = AV_RB32(comm_chunk + 4); rate_flag = AV_RB32(comm_chunk + 8); avio_skip(s->pb, len-12); - if (st->codecpar->channels <= 0) { + if (st->codecpar->ch_layout.nb_channels <= 0) { av_log(s, AV_LOG_ERROR, "Invalid number of channels\n"); return AVERROR_INVALIDDATA; } @@ -192,15 +192,15 @@ static int vqf_read_header(AVFormatContext *s) break; } - if (read_bitrate / st->codecpar->channels < 8 || - read_bitrate / st->codecpar->channels > 48) { + if (read_bitrate / st->codecpar->ch_layout.nb_channels < 8 || + read_bitrate / st->codecpar->ch_layout.nb_channels > 48) { av_log(s, AV_LOG_ERROR, "Invalid bitrate per channel %d\n", - read_bitrate / st->codecpar->channels); + read_bitrate / st->codecpar->ch_layout.nb_channels); return AVERROR_INVALIDDATA; } switch (((st->codecpar->sample_rate/1000) << 8) + - read_bitrate/st->codecpar->channels) { + read_bitrate/st->codecpar->ch_layout.nb_channels) { case (11<<8) + 8 : case (8 <<8) + 8 : case (11<<8) + 10: diff --git a/libavformat/wavdec.c b/libavformat/wavdec.c index 01090b694..ca61b844b 100644 --- a/libavformat/wavdec.c +++ b/libavformat/wavdec.c @@ -27,7 +27,7 @@ #include -#include "config.h" +#include "config_components.h" #include "libavutil/avassert.h" #include "libavutil/dict.h" #include "libavutil/intreadwrite.h" @@ -37,6 +37,7 @@ #include "avformat.h" #include "avio.h" #include "avio_internal.h" +#include "demux.h" #include "id3v2.h" #include "internal.h" #include "metadata.h" @@ -221,9 +222,11 @@ static int wav_parse_xma2_tag(AVFormatContext *s, int64_t size, AVStream *st) channels += avio_r8(pb); avio_skip(pb, 3); } - st->codecpar->channels = channels; + av_channel_layout_uninit(&st->codecpar->ch_layout); + st->codecpar->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + st->codecpar->ch_layout.nb_channels = channels; - if (st->codecpar->channels <= 0 || st->codecpar->sample_rate <= 0) + if (st->codecpar->ch_layout.nb_channels <= 0 || st->codecpar->sample_rate <= 0) return AVERROR_INVALIDDATA; avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); @@ -611,15 +614,15 @@ break_loop: if ( st->codecpar->bit_rate > 0 && data_size > 0 && st->codecpar->sample_rate > 0 - && sample_count > 0 && st->codecpar->channels > 1 - && sample_count % st->codecpar->channels == 0) { - if (fabs(8.0 * data_size * st->codecpar->channels * st->codecpar->sample_rate / + && sample_count > 0 && st->codecpar->ch_layout.nb_channels > 1 + && sample_count % st->codecpar->ch_layout.nb_channels == 0) { + if (fabs(8.0 * data_size * st->codecpar->ch_layout.nb_channels * st->codecpar->sample_rate / sample_count /st->codecpar->bit_rate - 1.0) < 0.3) - sample_count /= st->codecpar->channels; + sample_count /= st->codecpar->ch_layout.nb_channels; } - if ( data_size > 0 && sample_count && st->codecpar->channels - && (data_size << 3) / sample_count / st->codecpar->channels > st->codecpar->bits_per_coded_sample + 1) { + if (data_size > 0 && sample_count && st->codecpar->ch_layout.nb_channels && + (data_size << 3) / sample_count / st->codecpar->ch_layout.nb_channels > st->codecpar->bits_per_coded_sample + 1) { av_log(s, AV_LOG_WARNING, "ignoring wrong sample_count %"PRId64"\n", sample_count); sample_count = 0; } @@ -632,34 +635,34 @@ break_loop: } if (!sample_count || av_get_exact_bits_per_sample(st->codecpar->codec_id) > 0) - if ( st->codecpar->channels + if ( st->codecpar->ch_layout.nb_channels && data_size && av_get_bits_per_sample(st->codecpar->codec_id) && wav->data_end <= avio_size(pb)) sample_count = (data_size << 3) / - (st->codecpar->channels * (uint64_t)av_get_bits_per_sample(st->codecpar->codec_id)); + (st->codecpar->ch_layout.nb_channels * (uint64_t)av_get_bits_per_sample(st->codecpar->codec_id)); if (sample_count) st->duration = sample_count; if (st->codecpar->codec_id == AV_CODEC_ID_PCM_S32LE && - st->codecpar->block_align == st->codecpar->channels * 4 && + st->codecpar->block_align == st->codecpar->ch_layout.nb_channels * 4 && st->codecpar->bits_per_coded_sample == 32 && st->codecpar->extradata_size == 2 && AV_RL16(st->codecpar->extradata) == 1) { st->codecpar->codec_id = AV_CODEC_ID_PCM_F16LE; st->codecpar->bits_per_coded_sample = 16; } else if (st->codecpar->codec_id == AV_CODEC_ID_PCM_S24LE && - st->codecpar->block_align == st->codecpar->channels * 4 && + st->codecpar->block_align == st->codecpar->ch_layout.nb_channels * 4 && st->codecpar->bits_per_coded_sample == 24) { st->codecpar->codec_id = AV_CODEC_ID_PCM_F24LE; } else if (st->codecpar->codec_id == AV_CODEC_ID_XMA1 || st->codecpar->codec_id == AV_CODEC_ID_XMA2) { st->codecpar->block_align = 2048; - } else if (st->codecpar->codec_id == AV_CODEC_ID_ADPCM_MS && st->codecpar->channels > 2 && - st->codecpar->block_align < INT_MAX / st->codecpar->channels) { - st->codecpar->block_align *= st->codecpar->channels; + } else if (st->codecpar->codec_id == AV_CODEC_ID_ADPCM_MS && st->codecpar->ch_layout.nb_channels > 2 && + st->codecpar->block_align < INT_MAX / st->codecpar->ch_layout.nb_channels) { + st->codecpar->block_align *= st->codecpar->ch_layout.nb_channels; } ff_metadata_conv_ctx(s, NULL, wav_metadata_conv); diff --git a/libavformat/wavenc.c b/libavformat/wavenc.c index 2317700be..b08f862cf 100644 --- a/libavformat/wavenc.c +++ b/libavformat/wavenc.c @@ -28,6 +28,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config_components.h" + #include #include @@ -170,12 +172,12 @@ static av_cold int peak_init_writer(AVFormatContext *s) "Writing 16 bit peak for 8 bit audio does not make sense\n"); return AVERROR(EINVAL); } - if (par->channels > INT_MAX / (wav->peak_bps * wav->peak_ppv)) + if (par->ch_layout.nb_channels > INT_MAX / (wav->peak_bps * wav->peak_ppv)) return AVERROR(ERANGE); - wav->size_increment = par->channels * wav->peak_bps * wav->peak_ppv; + wav->size_increment = par->ch_layout.nb_channels * wav->peak_bps * wav->peak_ppv; - wav->peak_maxpos = av_calloc(par->channels, sizeof(*wav->peak_maxpos)); - wav->peak_maxneg = av_calloc(par->channels, sizeof(*wav->peak_maxneg)); + wav->peak_maxpos = av_calloc(par->ch_layout.nb_channels, sizeof(*wav->peak_maxpos)); + wav->peak_maxneg = av_calloc(par->ch_layout.nb_channels, sizeof(*wav->peak_maxneg)); if (!wav->peak_maxpos || !wav->peak_maxneg) goto nomem; @@ -205,7 +207,7 @@ static int peak_write_frame(AVFormatContext *s) } wav->peak_output = tmp; - for (c = 0; c < par->channels; c++) { + for (c = 0; c < par->ch_layout.nb_channels; c++) { wav->peak_maxneg[c] = -wav->peak_maxneg[c]; if (wav->peak_bps == 2 && wav->peak_format == PEAK_FORMAT_UINT8) { @@ -277,7 +279,7 @@ static int peak_write_chunk(AVFormatContext *s) avio_wl32(pb, wav->peak_format); /* 8 or 16 bit */ avio_wl32(pb, wav->peak_ppv); /* positive and negative */ avio_wl32(pb, wav->peak_block_size); /* frames per value */ - avio_wl32(pb, par->channels); /* number of channels */ + avio_wl32(pb, par->ch_layout.nb_channels); /* number of channels */ avio_wl32(pb, wav->peak_num_frames); /* number of peak frames */ avio_wl32(pb, -1); /* audio sample frame position (not implemented) */ avio_wl32(pb, 128); /* equal to size of header */ @@ -384,7 +386,7 @@ static int wav_write_packet(AVFormatContext *s, AVPacket *pkt) wav->peak_maxpos[c] = FFMAX(wav->peak_maxpos[c], (int16_t)AV_RL16(pkt->data + i)); wav->peak_maxneg[c] = FFMIN(wav->peak_maxneg[c], (int16_t)AV_RL16(pkt->data + i)); } - if (++c == s->streams[0]->codecpar->channels) { + if (++c == s->streams[0]->codecpar->ch_layout.nb_channels) { c = 0; if (++wav->peak_block_pos == wav->peak_block_size) { int ret = peak_write_frame(s); diff --git a/libavformat/wc3movie.c b/libavformat/wc3movie.c index fe2d0d424..8f5c2f18c 100644 --- a/libavformat/wc3movie.c +++ b/libavformat/wc3movie.c @@ -54,7 +54,6 @@ /* always use the same PCM audio parameters */ #define WC3_SAMPLE_RATE 22050 -#define WC3_AUDIO_CHANNELS 1 #define WC3_AUDIO_BITS 16 /* nice, constant framerate */ @@ -195,13 +194,12 @@ static int wc3_read_header(AVFormatContext *s) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE; st->codecpar->codec_tag = 1; - st->codecpar->channels = WC3_AUDIO_CHANNELS; - st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; st->codecpar->bits_per_coded_sample = WC3_AUDIO_BITS; st->codecpar->sample_rate = WC3_SAMPLE_RATE; - st->codecpar->bit_rate = st->codecpar->channels * st->codecpar->sample_rate * + st->codecpar->bit_rate = st->codecpar->ch_layout.nb_channels * st->codecpar->sample_rate * st->codecpar->bits_per_coded_sample; - st->codecpar->block_align = WC3_AUDIO_BITS * WC3_AUDIO_CHANNELS; + st->codecpar->block_align = WC3_AUDIO_BITS * st->codecpar->ch_layout.nb_channels; return 0; } diff --git a/libavformat/webm_chunk.c b/libavformat/webm_chunk.c index 24390e8e7..d69db3a00 100644 --- a/libavformat/webm_chunk.c +++ b/libavformat/webm_chunk.c @@ -28,6 +28,7 @@ #include "avio.h" #include "avio_internal.h" #include "internal.h" +#include "mux.h" #include "libavutil/log.h" #include "libavutil/opt.h" @@ -127,7 +128,7 @@ fail: s->avoid_negative_ts = oc->avoid_negative_ts; ffformatcontext(s)->avoid_negative_ts_use_pts = ffformatcontext(oc)->avoid_negative_ts_use_pts; - oc->avoid_negative_ts = 0; + oc->avoid_negative_ts = AVFMT_AVOID_NEG_TS_DISABLED; return 0; } diff --git a/libavformat/webmdashenc.c b/libavformat/webmdashenc.c index cf69bd35b..f8f227455 100644 --- a/libavformat/webmdashenc.c +++ b/libavformat/webmdashenc.c @@ -38,6 +38,8 @@ #include "libavutil/opt.h" #include "libavutil/time_internal.h" +#include "libavcodec/codec_desc.h" + typedef struct AdaptationSet { char id[10]; int *streams; @@ -93,7 +95,7 @@ static int write_header(AVFormatContext *s) } avio_printf(pb, " minBufferTime=\"PT%gS\"\n", min_buffer_time); avio_printf(pb, " profiles=\"%s\"%s", - w->is_live ? "urn:mpeg:dash:profile:isoff-live:2011" : "urn:webm:dash:profile:webm-on-demand:2012", + w->is_live ? "urn:mpeg:dash:profile:isoff-live:2011" : "urn:mpeg:dash:profile:webm-on-demand:2012", w->is_live ? "\n" : ">\n"); if (w->is_live) { time_t local_time = time(NULL); diff --git a/libavformat/westwood_aud.c b/libavformat/westwood_aud.c index ff51e8bd3..9896bd46d 100644 --- a/libavformat/westwood_aud.c +++ b/libavformat/westwood_aud.c @@ -118,9 +118,7 @@ static int wsaud_read_header(AVFormatContext *s) } avpriv_set_pts_info(st, 64, 1, sample_rate); st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; - st->codecpar->channels = channels; - st->codecpar->channel_layout = channels == 1 ? AV_CH_LAYOUT_MONO : - AV_CH_LAYOUT_STEREO; + av_channel_layout_default(&st->codecpar->ch_layout, channels); st->codecpar->sample_rate = sample_rate; return 0; @@ -164,14 +162,14 @@ static int wsaud_read_packet(AVFormatContext *s, if (ret != chunk_size) return AVERROR(EIO); - if (st->codecpar->channels <= 0) { + if (st->codecpar->ch_layout.nb_channels <= 0) { av_log(s, AV_LOG_ERROR, "invalid number of channels %d\n", - st->codecpar->channels); + st->codecpar->ch_layout.nb_channels); return AVERROR_INVALIDDATA; } /* 2 samples/byte, 1 or 2 samples per frame depending on stereo */ - pkt->duration = (chunk_size * 2) / st->codecpar->channels; + pkt->duration = (chunk_size * 2) / st->codecpar->ch_layout.nb_channels; } pkt->stream_index = st->index; diff --git a/libavformat/westwood_audenc.c b/libavformat/westwood_audenc.c index 597d68350..a2401eff5 100644 --- a/libavformat/westwood_audenc.c +++ b/libavformat/westwood_audenc.c @@ -77,7 +77,7 @@ static int wsaud_write_header(AVFormatContext *ctx) a->size = 0; /* Flag if we have stereo data. */ - if (st->codecpar->channels == 2) + if (st->codecpar->ch_layout.nb_channels == 2) flags |= 1; /* This flags that the file contains 16 bit samples rather than 8 bit diff --git a/libavformat/westwood_vqa.c b/libavformat/westwood_vqa.c index 9d116060a..e3d2e2668 100644 --- a/libavformat/westwood_vqa.c +++ b/libavformat/westwood_vqa.c @@ -32,6 +32,7 @@ #include "libavutil/intreadwrite.h" #include "avformat.h" #include "avio_internal.h" +#include "demux.h" #include "internal.h" #define FORM_TAG MKBETAG('F', 'O', 'R', 'M') @@ -226,7 +227,7 @@ static int wsvqa_read_packet(AVFormatContext *s, wsvqa->bps = 8; st->codecpar->sample_rate = wsvqa->sample_rate; st->codecpar->bits_per_coded_sample = wsvqa->bps; - st->codecpar->channels = wsvqa->channels; + av_channel_layout_default(&st->codecpar->ch_layout, wsvqa->channels); st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); diff --git a/libavformat/wsddec.c b/libavformat/wsddec.c index 1f90f5b46..9bee4d51b 100644 --- a/libavformat/wsddec.c +++ b/libavformat/wsddec.c @@ -128,18 +128,21 @@ static int wsd_read_header(AVFormatContext *s) st->codecpar->codec_id = s->iformat->raw_codec_id; st->codecpar->sample_rate = avio_rb32(pb) / 8; avio_skip(pb, 4); - st->codecpar->channels = avio_r8(pb) & 0xF; - st->codecpar->bit_rate = (int64_t)st->codecpar->channels * st->codecpar->sample_rate * 8LL; - if (!st->codecpar->channels) + st->codecpar->ch_layout.nb_channels = avio_r8(pb) & 0xF; + st->codecpar->bit_rate = (int64_t)st->codecpar->ch_layout.nb_channels * + st->codecpar->sample_rate * 8LL; + if (!st->codecpar->ch_layout.nb_channels) return AVERROR_INVALIDDATA; avio_skip(pb, 3); channel_assign = avio_rb32(pb); if (!(channel_assign & 1)) { + uint64_t ch_mask = 0; int i; for (i = 1; i < 32; i++) if ((channel_assign >> i) & 1) - st->codecpar->channel_layout |= wsd_to_av_channel_layoyt(s, i); + ch_mask |= wsd_to_av_channel_layoyt(s, i); + av_channel_layout_from_mask(&st->codecpar->ch_layout, ch_mask); } avio_skip(pb, 16); diff --git a/libavformat/wtvdec.c b/libavformat/wtvdec.c index 22e4c9256..98128b720 100644 --- a/libavformat/wtvdec.c +++ b/libavformat/wtvdec.c @@ -32,6 +32,7 @@ #include "libavutil/intfloat.h" #include "libavutil/time_internal.h" #include "avformat.h" +#include "demux.h" #include "internal.h" #include "wtv.h" #include "mpegts.h" @@ -584,11 +585,9 @@ static void parse_mpeg1waveformatex(AVStream *st) switch (AV_RL16(st->codecpar->extradata + 6)) { case 1 : case 2 : - case 4 : st->codecpar->channels = 2; - st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; + case 4 : st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; break; - case 8 : st->codecpar->channels = 1; - st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; + case 8 : st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; break; } } diff --git a/libavformat/wtvenc.c b/libavformat/wtvenc.c index 9c67a6d3e..7e28b2082 100644 --- a/libavformat/wtvenc.c +++ b/libavformat/wtvenc.c @@ -25,12 +25,12 @@ * @author Zhentan Feng */ -#include "libavutil/intreadwrite.h" #include "libavutil/avassert.h" #include "avformat.h" #include "avio_internal.h" #include "internal.h" #include "mpegts.h" +#include "mux.h" #include "wtv.h" #define WTV_BIGSECTOR_SIZE (1 << WTV_BIGSECTOR_BITS) diff --git a/libavformat/wv.c b/libavformat/wv.c index 0f4f80761..b260bb9fc 100644 --- a/libavformat/wv.c +++ b/libavformat/wv.c @@ -21,8 +21,9 @@ #include #include -#include "libavutil/common.h" +#include "libavutil/error.h" #include "libavutil/intreadwrite.h" +#include "libavutil/macros.h" #include "wv.h" diff --git a/libavformat/wvdec.c b/libavformat/wvdec.c index 0d5a86953..61a683a85 100644 --- a/libavformat/wvdec.c +++ b/libavformat/wvdec.c @@ -256,8 +256,7 @@ static int wv_read_header(AVFormatContext *s) AV_WL16(st->codecpar->extradata, wc->header.version); st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_WAVPACK; - st->codecpar->channels = wc->chan; - st->codecpar->channel_layout = wc->chmask; + av_channel_layout_from_mask(&st->codecpar->ch_layout, wc->chmask); st->codecpar->sample_rate = wc->rate; st->codecpar->bits_per_coded_sample = wc->bpp; avpriv_set_pts_info(st, 64, 1, wc->rate); diff --git a/libavformat/wvedec.c b/libavformat/wvedec.c index f133da3c8..52b3099f7 100644 --- a/libavformat/wvedec.c +++ b/libavformat/wvedec.c @@ -43,9 +43,10 @@ static int wve_read_header(AVFormatContext *s) st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; st->codecpar->codec_id = AV_CODEC_ID_PCM_ALAW; st->codecpar->sample_rate = 8000; - st->codecpar->channels = 1; + st->codecpar->ch_layout.nb_channels = 1; st->codecpar->bits_per_coded_sample = av_get_bits_per_sample(st->codecpar->codec_id); - st->codecpar->block_align = st->codecpar->bits_per_coded_sample * st->codecpar->channels / 8; + st->codecpar->block_align = st->codecpar->bits_per_coded_sample * + st->codecpar->ch_layout.nb_channels / 8; avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); avio_skip(s->pb, 10); diff --git a/libavformat/xa.c b/libavformat/xa.c index 762e90246..ec9fcbc94 100644 --- a/libavformat/xa.c +++ b/libavformat/xa.c @@ -78,16 +78,16 @@ static int xa_read_header(AVFormatContext *s) avio_skip(pb, 4); /* Skip the XA ID */ xa->out_size = avio_rl32(pb); avio_skip(pb, 2); /* Skip the tag */ - st->codecpar->channels = avio_rl16(pb); + st->codecpar->ch_layout.nb_channels = avio_rl16(pb); st->codecpar->sample_rate = avio_rl32(pb); avio_skip(pb, 4); /* Skip average byte rate */ avio_skip(pb, 2); /* Skip block align */ avio_skip(pb, 2); /* Skip bits-per-sample */ - if (!st->codecpar->channels || !st->codecpar->sample_rate) + if (!st->codecpar->ch_layout.nb_channels || !st->codecpar->sample_rate) return AVERROR_INVALIDDATA; - st->codecpar->bit_rate = av_clip(15LL * st->codecpar->channels * 8 * + st->codecpar->bit_rate = av_clip(15LL * st->codecpar->ch_layout.nb_channels * 8 * st->codecpar->sample_rate / 28, 0, INT_MAX); avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate); @@ -108,7 +108,7 @@ static int xa_read_packet(AVFormatContext *s, if (xa->sent_bytes >= xa->out_size) return AVERROR_EOF; /* 1 byte header and 14 bytes worth of samples * number channels per block */ - packet_size = 15*st->codecpar->channels; + packet_size = 15*st->codecpar->ch_layout.nb_channels; ret = av_get_packet(pb, pkt, packet_size); if(ret < 0) diff --git a/libavformat/xmv.c b/libavformat/xmv.c index ec21a4f85..4bff63297 100644 --- a/libavformat/xmv.c +++ b/libavformat/xmv.c @@ -332,7 +332,7 @@ static int xmv_process_packet_header(AVFormatContext *s) ast->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; ast->codecpar->codec_id = packet->codec_id; ast->codecpar->codec_tag = packet->compression; - ast->codecpar->channels = packet->channels; + ast->codecpar->ch_layout.nb_channels = packet->channels; ast->codecpar->sample_rate = packet->sample_rate; ast->codecpar->bits_per_coded_sample = packet->bits_per_sample; ast->codecpar->bit_rate = packet->bit_rate; diff --git a/libavformat/xvag.c b/libavformat/xvag.c index 994b710f8..f8a83f258 100644 --- a/libavformat/xvag.c +++ b/libavformat/xvag.c @@ -52,7 +52,7 @@ static int xvag_read_header(AVFormatContext *s) offset = av_bswap32(offset); avio_skip(s->pb, 28); codec = avio_rb32(s->pb); - st->codecpar->channels = avio_rb32(s->pb); + st->codecpar->ch_layout.nb_channels = avio_rb32(s->pb); avio_skip(s->pb, 4); st->duration = avio_rb32(s->pb); avio_skip(s->pb, 8); @@ -60,7 +60,7 @@ static int xvag_read_header(AVFormatContext *s) } else { avio_skip(s->pb, 28); codec = avio_rl32(s->pb); - st->codecpar->channels = avio_rl32(s->pb); + st->codecpar->ch_layout.nb_channels = avio_rl32(s->pb); avio_skip(s->pb, 4); st->duration = avio_rl32(s->pb); avio_skip(s->pb, 8); @@ -69,13 +69,14 @@ static int xvag_read_header(AVFormatContext *s) if (st->codecpar->sample_rate <= 0) return AVERROR_INVALIDDATA; - if (st->codecpar->channels <= 0 || st->codecpar->channels > FF_SANE_NB_CHANNELS) + if (st->codecpar->ch_layout.nb_channels <= 0 || + st->codecpar->ch_layout.nb_channels > FF_SANE_NB_CHANNELS) return AVERROR_INVALIDDATA; switch (codec) { case 0x1c: st->codecpar->codec_id = AV_CODEC_ID_ADPCM_PSX; - st->codecpar->block_align = 16 * st->codecpar->channels; + st->codecpar->block_align = 16 * st->codecpar->ch_layout.nb_channels; break; default: avpriv_request_sample(s, "codec %X", codec); diff --git a/libavformat/xwma.c b/libavformat/xwma.c index 37ab3a1ec..c16ff1be6 100644 --- a/libavformat/xwma.c +++ b/libavformat/xwma.c @@ -85,7 +85,7 @@ static int xwma_read_header(AVFormatContext *s) * 20/48/192kbps are all 20kbps, with the exact same codec data). * Decoder needs correct bitrate to work, so it's normalized here. */ if (st->codecpar->codec_id == AV_CODEC_ID_WMAV2) { - int ch = st->codecpar->channels; + int ch = st->codecpar->ch_layout.nb_channels; int sr = st->codecpar->sample_rate; int br = st->codecpar->bit_rate; @@ -146,9 +146,9 @@ static int xwma_read_header(AVFormatContext *s) } } - if (!st->codecpar->channels) { + if (!av_channel_layout_check(&st->codecpar->ch_layout)) { av_log(s, AV_LOG_WARNING, "Invalid channel count: %d\n", - st->codecpar->channels); + st->codecpar->ch_layout.nb_channels); return AVERROR_INVALIDDATA; } if (!st->codecpar->bits_per_coded_sample) { @@ -236,7 +236,7 @@ static int xwma_read_header(AVFormatContext *s) if (dpds_table && dpds_table_size) { int64_t cur_pos; const uint32_t bytes_per_sample - = (st->codecpar->channels * st->codecpar->bits_per_coded_sample) >> 3; + = (st->codecpar->ch_layout.nb_channels * st->codecpar->bits_per_coded_sample) >> 3; /* Estimate the duration from the total number of output bytes. */ const uint64_t total_decoded_bytes = dpds_table[dpds_table_size - 1]; @@ -244,7 +244,7 @@ static int xwma_read_header(AVFormatContext *s) if (!bytes_per_sample) { av_log(s, AV_LOG_ERROR, "Invalid bits_per_coded_sample %d for %d channels\n", - st->codecpar->bits_per_coded_sample, st->codecpar->channels); + st->codecpar->bits_per_coded_sample, st->codecpar->ch_layout.nb_channels); ret = AVERROR_INVALIDDATA; goto fail; } diff --git a/libavformat/yop.c b/libavformat/yop.c index f65e4f8b1..8fdad6899 100644 --- a/libavformat/yop.c +++ b/libavformat/yop.c @@ -25,6 +25,7 @@ #include "libavutil/channel_layout.h" #include "libavutil/intreadwrite.h" #include "avformat.h" +#include "demux.h" #include "internal.h" typedef struct yop_dec_context { @@ -72,8 +73,7 @@ static int yop_read_header(AVFormatContext *s) audio_par = audio_stream->codecpar; audio_par->codec_type = AVMEDIA_TYPE_AUDIO; audio_par->codec_id = AV_CODEC_ID_ADPCM_IMA_APC; - audio_par->channels = 1; - audio_par->channel_layout = AV_CH_LAYOUT_MONO; + audio_par->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; audio_par->sample_rate = 22050; // Video diff --git a/libavutil/Makefile b/libavutil/Makefile index d17876df1..9435a0bfb 100644 --- a/libavutil/Makefile +++ b/libavutil/Makefile @@ -20,6 +20,7 @@ HEADERS = adler32.h \ common.h \ cpu.h \ crc.h \ + csp.h \ des.h \ detection_bbox.h \ dict.h \ @@ -34,6 +35,7 @@ HEADERS = adler32.h \ frame.h \ hash.h \ hdr_dynamic_metadata.h \ + hdr_dynamic_vivid_metadata.h \ hmac.h \ hwcontext.h \ hwcontext_cuda.h \ @@ -52,6 +54,7 @@ HEADERS = adler32.h \ intreadwrite.h \ lfg.h \ log.h \ + lzo.h \ macros.h \ mathematics.h \ mastering_display_metadata.h \ @@ -80,6 +83,7 @@ HEADERS = adler32.h \ timestamp.h \ tree.h \ twofish.h \ + uuid.h \ version.h \ video_enc_params.h \ xtea.h \ @@ -87,8 +91,6 @@ HEADERS = adler32.h \ tx.h \ film_grain_params.h \ -HEADERS-$(CONFIG_LZO) += lzo.h - ARCH_HEADERS = bswap.h \ intmath.h \ intreadwrite.h \ @@ -113,6 +115,7 @@ OBJS = adler32.o \ color_utils.o \ cpu.o \ crc.o \ + csp.o \ des.o \ detection_bbox.o \ dict.o \ @@ -130,6 +133,7 @@ OBJS = adler32.o \ frame.o \ hash.o \ hdr_dynamic_metadata.o \ + hdr_dynamic_vivid_metadata.o \ hmac.o \ hwcontext.o \ imgutils.o \ @@ -139,6 +143,7 @@ OBJS = adler32.o \ lls.o \ log.o \ log2_tab.o \ + lzo.o \ mathematics.o \ mastering_display_metadata.o \ md5.o \ @@ -172,6 +177,8 @@ OBJS = adler32.o \ tx_float.o \ tx_double.o \ tx_int32.o \ + uuid.o \ + version.o \ video_enc_params.o \ film_grain_params.o \ @@ -180,7 +187,6 @@ OBJS-$(CONFIG_CUDA) += hwcontext_cuda.o OBJS-$(CONFIG_D3D11VA) += hwcontext_d3d11va.o OBJS-$(CONFIG_DXVA2) += hwcontext_dxva2.o OBJS-$(CONFIG_LIBDRM) += hwcontext_drm.o -OBJS-$(CONFIG_LZO) += lzo.o OBJS-$(CONFIG_MACOS_KPERF) += macos_kperf.o OBJS-$(CONFIG_MEDIACODEC) += hwcontext_mediacodec.o OBJS-$(CONFIG_OPENCL) += hwcontext_opencl.o @@ -190,6 +196,8 @@ OBJS-$(CONFIG_VIDEOTOOLBOX) += hwcontext_videotoolbox.o OBJS-$(CONFIG_VDPAU) += hwcontext_vdpau.o OBJS-$(CONFIG_VULKAN) += hwcontext_vulkan.o +OBJS-$(!CONFIG_VULKAN) += hwcontext_stub.o + OBJS += $(COMPAT_OBJS:%=../compat/%) # Windows resource file @@ -220,6 +228,7 @@ TESTPROGS = adler32 \ bprint \ cast5 \ camellia \ + channel_layout \ color_utils \ cpu \ crc \ @@ -256,6 +265,7 @@ TESTPROGS = adler32 \ tree \ twofish \ utf8 \ + uuid \ xtea \ tea \ diff --git a/libavutil/aarch64/asm.S b/libavutil/aarch64/asm.S index bee91d59c..a7782415d 100644 --- a/libavutil/aarch64/asm.S +++ b/libavutil/aarch64/asm.S @@ -36,10 +36,79 @@ # define __has_feature(x) 0 #endif -/* Support macros for the Armv8.5-A Branch Target Identification feature which - * requires emitting a .note.gnu.property section with the appropriate - * architecture-dependent feature bits set. - * Read more: "ELF for the Arm® 64-bit Architecture" + +/* Support macros for + * - Armv8.3-A Pointer Authentication and + * - Armv8.5-A Branch Target Identification + * features which require emitting a .note.gnu.property section with the + * appropriate architecture-dependent feature bits set. + * + * |AARCH64_SIGN_LINK_REGISTER| and |AARCH64_VALIDATE_LINK_REGISTER| expand to + * PACIxSP and AUTIxSP, respectively. |AARCH64_SIGN_LINK_REGISTER| should be + * used immediately before saving the LR register (x30) to the stack. + * |AARCH64_VALIDATE_LINK_REGISTER| should be used immediately after restoring + * it. Note |AARCH64_SIGN_LINK_REGISTER|'s modifications to LR must be undone + * with |AARCH64_VALIDATE_LINK_REGISTER| before RET. The SP register must also + * have the same value at the two points. For example: + * + * .global f + * f: + * AARCH64_SIGN_LINK_REGISTER + * stp x29, x30, [sp, #-96]! + * mov x29, sp + * ... + * ldp x29, x30, [sp], #96 + * AARCH64_VALIDATE_LINK_REGISTER + * ret + * + * |AARCH64_VALID_CALL_TARGET| expands to BTI 'c'. Either it, or + * |AARCH64_SIGN_LINK_REGISTER|, must be used at every point that may be an + * indirect call target. In particular, all symbols exported from a file must + * begin with one of these macros. For example, a leaf function that does not + * save LR can instead use |AARCH64_VALID_CALL_TARGET|: + * + * .globl return_zero + * return_zero: + * AARCH64_VALID_CALL_TARGET + * mov x0, #0 + * ret + * + * A non-leaf function which does not immediately save LR may need both macros + * because |AARCH64_SIGN_LINK_REGISTER| appears late. For example, the function + * may jump to an alternate implementation before setting up the stack: + * + * .globl with_early_jump + * with_early_jump: + * AARCH64_VALID_CALL_TARGET + * cmp x0, #128 + * b.lt .Lwith_early_jump_128 + * AARCH64_SIGN_LINK_REGISTER + * stp x29, x30, [sp, #-96]! + * mov x29, sp + * ... + * ldp x29, x30, [sp], #96 + * AARCH64_VALIDATE_LINK_REGISTER + * ret + * + * .Lwith_early_jump_128: + * ... + * ret + * + * These annotations are only required with indirect calls. Private symbols that + * are only the target of direct calls do not require annotations. Also note + * that |AARCH64_VALID_CALL_TARGET| is only valid for indirect calls (BLR), not + * indirect jumps (BR). Indirect jumps in assembly are supported through + * |AARCH64_VALID_JUMP_TARGET|. Landing Pads which shall serve for jumps and + * calls can be created using |AARCH64_VALID_JUMP_CALL_TARGET|. + * + * Although not necessary, it is safe to use these macros in 32-bit ARM + * assembly. This may be used to simplify dual 32-bit and 64-bit files. + * + * References: + * - "ELF for the Arm® 64-bit Architecture" + * https: *github.com/ARM-software/abi-aa/blob/master/aaelf64/aaelf64.rst + * - "Providing protection for complex software" + * https://developer.arm.com/architectures/learn-the-architecture/providing-protection-for-complex-software */ #if defined(__ARM_FEATURE_BTI_DEFAULT) && (__ARM_FEATURE_BTI_DEFAULT == 1) # define GNU_PROPERTY_AARCH64_BTI (1 << 0) // Has BTI @@ -51,7 +120,28 @@ # define AARCH64_VALID_JUMP_TARGET #endif -#if (GNU_PROPERTY_AARCH64_BTI != 0) +#if defined(__ARM_FEATURE_PAC_DEFAULT) +# if ((__ARM_FEATURE_PAC_DEFAULT & (1 << 0)) != 0) // authentication using key A +# define AARCH64_SIGN_LINK_REGISTER paciasp +# define AARCH64_VALIDATE_LINK_REGISTER autiasp +# elif ((__ARM_FEATURE_PAC_DEFAULT & (1 << 1)) != 0) // authentication using key B +# define AARCH64_SIGN_LINK_REGISTER pacibsp +# define AARCH64_VALIDATE_LINK_REGISTER autibsp +# else +# error Pointer authentication defines no valid key! +# endif +# if ((__ARM_FEATURE_PAC_DEFAULT & (1 << 2)) != 0) +# error Authentication of leaf functions is enabled but not supported in FFmpeg! +# endif +# define GNU_PROPERTY_AARCH64_PAC (1 << 1) +#else +# define GNU_PROPERTY_AARCH64_PAC 0 +# define AARCH64_SIGN_LINK_REGISTER +# define AARCH64_VALIDATE_LINK_REGISTER +#endif + + +#if (GNU_PROPERTY_AARCH64_BTI != 0 || GNU_PROPERTY_AARCH64_PAC != 0) && defined(__ELF__) .pushsection .note.gnu.property, "a" .balign 8 .long 4 @@ -60,7 +150,7 @@ .asciz "GNU" .long 0xc0000000 /* GNU_PROPERTY_AARCH64_FEATURE_1_AND */ .long 4 - .long GNU_PROPERTY_AARCH64_BTI + .long (GNU_PROPERTY_AARCH64_BTI | GNU_PROPERTY_AARCH64_PAC) .long 0 .popsection #endif diff --git a/libavutil/adler32.c b/libavutil/adler32.c index f7d306226..7124f1880 100644 --- a/libavutil/adler32.c +++ b/libavutil/adler32.c @@ -32,8 +32,8 @@ #include "config.h" #include "adler32.h" -#include "common.h" #include "intreadwrite.h" +#include "macros.h" #define BASE 65521L /* largest prime smaller than 65536 */ diff --git a/libavutil/aes.c b/libavutil/aes.c index 397ea7738..029d738f8 100644 --- a/libavutil/aes.c +++ b/libavutil/aes.c @@ -20,11 +20,15 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "common.h" +#include + +#include "config.h" #include "aes.h" #include "aes_internal.h" +#include "error.h" #include "intreadwrite.h" -#include "timer.h" +#include "macros.h" +#include "mem.h" const int av_aes_size= sizeof(AVAES); diff --git a/libavutil/aes_ctr.c b/libavutil/aes_ctr.c index 517d09cf9..c2d6d570e 100644 --- a/libavutil/aes_ctr.c +++ b/libavutil/aes_ctr.c @@ -19,10 +19,13 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "common.h" +#include + #include "aes_ctr.h" #include "aes.h" #include "aes_internal.h" +#include "macros.h" +#include "mem.h" #include "random_seed.h" #define AES_BLOCK_SIZE (16) diff --git a/libavutil/arm/cpu.c b/libavutil/arm/cpu.c index 81e85e252..c84a655c3 100644 --- a/libavutil/arm/cpu.c +++ b/libavutil/arm/cpu.c @@ -38,6 +38,10 @@ #include #include "libavutil/avstring.h" +#if HAVE_GETAUXVAL +#include +#endif + #define AT_HWCAP 16 /* Relevant HWCAP values from kernel headers */ @@ -48,6 +52,19 @@ #define HWCAP_VFPv3 (1 << 13) #define HWCAP_TLS (1 << 15) +static int get_auxval(uint32_t *hwcap) +{ +#if HAVE_GETAUXVAL + unsigned long ret = getauxval(AT_HWCAP); + if (ret == 0) + return -1; + *hwcap = ret; + return 0; +#else + return -1; +#endif +} + static int get_hwcap(uint32_t *hwcap) { struct { uint32_t a_type; uint32_t a_val; } auxv; @@ -106,9 +123,10 @@ int ff_get_cpu_flags_arm(void) int flags = CORE_CPU_FLAGS; uint32_t hwcap; - if (get_hwcap(&hwcap) < 0) - if (get_cpuinfo(&hwcap) < 0) - return flags; + if (get_auxval(&hwcap) < 0) + if (get_hwcap(&hwcap) < 0) + if (get_cpuinfo(&hwcap) < 0) + return flags; #define check_cap(cap, flag) do { \ if (hwcap & HWCAP_ ## cap) \ diff --git a/libavutil/attributes.h b/libavutil/attributes.h index 5cb9fe345..04c615c95 100644 --- a/libavutil/attributes.h +++ b/libavutil/attributes.h @@ -110,7 +110,7 @@ * scheduled for removal. */ #ifndef AV_NOWARN_DEPRECATED -#if AV_GCC_VERSION_AT_LEAST(4,6) +#if AV_GCC_VERSION_AT_LEAST(4,6) || defined(__clang__) # define AV_NOWARN_DEPRECATED(code) \ _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") \ diff --git a/libavutil/audio_fifo.c b/libavutil/audio_fifo.c index 243efc39e..f4103178b 100644 --- a/libavutil/audio_fifo.c +++ b/libavutil/audio_fifo.c @@ -24,15 +24,18 @@ * Audio FIFO */ -#include "avutil.h" +#include +#include + #include "audio_fifo.h" -#include "common.h" +#include "error.h" #include "fifo.h" +#include "macros.h" #include "mem.h" #include "samplefmt.h" struct AVAudioFifo { - AVFifoBuffer **buf; /**< single buffer for interleaved, per-channel buffers for planar */ + AVFifo **buf; /**< single buffer for interleaved, per-channel buffers for planar */ int nb_buffers; /**< number of buffers */ int nb_samples; /**< number of samples currently in the FIFO */ int allocated_samples; /**< current allocated size, in samples */ @@ -48,7 +51,7 @@ void av_audio_fifo_free(AVAudioFifo *af) if (af->buf) { int i; for (i = 0; i < af->nb_buffers; i++) { - av_fifo_freep(&af->buf[i]); + av_fifo_freep2(&af->buf[i]); } av_freep(&af->buf); } @@ -80,7 +83,7 @@ AVAudioFifo *av_audio_fifo_alloc(enum AVSampleFormat sample_fmt, int channels, goto error; for (i = 0; i < af->nb_buffers; i++) { - af->buf[i] = av_fifo_alloc(buf_size); + af->buf[i] = av_fifo_alloc2(buf_size, 1, 0); if (!af->buf[i]) goto error; } @@ -95,15 +98,19 @@ error: int av_audio_fifo_realloc(AVAudioFifo *af, int nb_samples) { + const size_t cur_size = av_fifo_can_read (af->buf[0]) + + av_fifo_can_write(af->buf[0]); int i, ret, buf_size; if ((ret = av_samples_get_buffer_size(&buf_size, af->channels, nb_samples, af->sample_fmt, 1)) < 0) return ret; - for (i = 0; i < af->nb_buffers; i++) { - if ((ret = av_fifo_realloc2(af->buf[i], buf_size)) < 0) - return ret; + if (buf_size > cur_size) { + for (i = 0; i < af->nb_buffers; i++) { + if ((ret = av_fifo_grow2(af->buf[i], buf_size - cur_size)) < 0) + return ret; + } } af->allocated_samples = nb_samples; return 0; @@ -126,8 +133,8 @@ int av_audio_fifo_write(AVAudioFifo *af, void **data, int nb_samples) size = nb_samples * af->sample_size; for (i = 0; i < af->nb_buffers; i++) { - ret = av_fifo_generic_write(af->buf[i], data[i], size, NULL); - if (ret != size) + ret = av_fifo_write(af->buf[i], data[i], size); + if (ret < 0) return AVERROR_BUG; } af->nb_samples += nb_samples; @@ -137,21 +144,7 @@ int av_audio_fifo_write(AVAudioFifo *af, void **data, int nb_samples) int av_audio_fifo_peek(AVAudioFifo *af, void **data, int nb_samples) { - int i, ret, size; - - if (nb_samples < 0) - return AVERROR(EINVAL); - nb_samples = FFMIN(nb_samples, af->nb_samples); - if (!nb_samples) - return 0; - - size = nb_samples * af->sample_size; - for (i = 0; i < af->nb_buffers; i++) { - if ((ret = av_fifo_generic_peek(af->buf[i], data[i], size, NULL)) < 0) - return AVERROR_BUG; - } - - return nb_samples; + return av_audio_fifo_peek_at(af, data, nb_samples, 0); } int av_audio_fifo_peek_at(AVAudioFifo *af, void **data, int nb_samples, int offset) @@ -171,7 +164,7 @@ int av_audio_fifo_peek_at(AVAudioFifo *af, void **data, int nb_samples, int offs offset *= af->sample_size; size = nb_samples * af->sample_size; for (i = 0; i < af->nb_buffers; i++) { - if ((ret = av_fifo_generic_peek_at(af->buf[i], data[i], offset, size, NULL)) < 0) + if ((ret = av_fifo_peek(af->buf[i], data[i], size, offset)) < 0) return AVERROR_BUG; } @@ -190,7 +183,7 @@ int av_audio_fifo_read(AVAudioFifo *af, void **data, int nb_samples) size = nb_samples * af->sample_size; for (i = 0; i < af->nb_buffers; i++) { - if (av_fifo_generic_read(af->buf[i], data[i], size, NULL) < 0) + if (av_fifo_read(af->buf[i], data[i], size) < 0) return AVERROR_BUG; } af->nb_samples -= nb_samples; @@ -209,7 +202,7 @@ int av_audio_fifo_drain(AVAudioFifo *af, int nb_samples) if (nb_samples) { size = nb_samples * af->sample_size; for (i = 0; i < af->nb_buffers; i++) - av_fifo_drain(af->buf[i], size); + av_fifo_drain2(af->buf[i], size); af->nb_samples -= nb_samples; } return 0; @@ -220,7 +213,7 @@ void av_audio_fifo_reset(AVAudioFifo *af) int i; for (i = 0; i < af->nb_buffers; i++) - av_fifo_reset(af->buf[i]); + av_fifo_reset2(af->buf[i]); af->nb_samples = 0; } diff --git a/libavutil/audio_fifo.h b/libavutil/audio_fifo.h index d8a9194a8..d1e4c856d 100644 --- a/libavutil/audio_fifo.h +++ b/libavutil/audio_fifo.h @@ -27,8 +27,7 @@ #ifndef AVUTIL_AUDIO_FIFO_H #define AVUTIL_AUDIO_FIFO_H -#include "avutil.h" -#include "fifo.h" +#include "attributes.h" #include "samplefmt.h" /** diff --git a/libavutil/avassert.h b/libavutil/avassert.h index 9abeadea4..51e462bba 100644 --- a/libavutil/avassert.h +++ b/libavutil/avassert.h @@ -28,8 +28,8 @@ #define AVUTIL_AVASSERT_H #include -#include "avutil.h" #include "log.h" +#include "macros.h" /** * assert() equivalent, that is always enabled. diff --git a/libavutil/avsscanf.c b/libavutil/avsscanf.c index a034407d1..7061e6d96 100644 --- a/libavutil/avsscanf.c +++ b/libavutil/avsscanf.c @@ -21,16 +21,18 @@ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include +#include +#include #include +#include #include #include #include #include -#include "config.h" -#include "common.h" #include "avstring.h" -#include "bprint.h" +#include "libm.h" typedef struct FFFILE { size_t buf_size; diff --git a/libavutil/avstring.c b/libavutil/avstring.c index 49e8df55a..5ddbe9219 100644 --- a/libavutil/avstring.c +++ b/libavutil/avstring.c @@ -19,17 +19,20 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include #include #include #include #include "config.h" -#include "common.h" #include "mem.h" #include "avassert.h" #include "avstring.h" #include "bprint.h" +#include "error.h" +#include "macros.h" +#include "version.h" int av_strstart(const char *str, const char *pfx, const char **ptr) { diff --git a/libavutil/avutil.h b/libavutil/avutil.h index 4d633156d..64b68bdbd 100644 --- a/libavutil/avutil.h +++ b/libavutil/avutil.h @@ -331,12 +331,18 @@ unsigned av_int_list_length_for_size(unsigned elsize, #define av_int_list_length(list, term) \ av_int_list_length_for_size(sizeof(*(list)), list, term) +#if FF_API_AV_FOPEN_UTF8 /** * Open a file using a UTF-8 filename. * The API of this function matches POSIX fopen(), errors are returned through * errno. + * @deprecated Avoid using it, as on Windows, the FILE* allocated by this + * function may be allocated with a different CRT than the caller + * who uses the FILE*. No replacement provided in public API. */ +attribute_deprecated FILE *av_fopen_utf8(const char *path, const char *mode); +#endif /** * Return the fractional representation of the internal time base. diff --git a/libavutil/base64.c b/libavutil/base64.c index a1316b943..3e66f4fcb 100644 --- a/libavutil/base64.c +++ b/libavutil/base64.c @@ -24,10 +24,12 @@ * @author Ryan Martell (with lots of Michael) */ -#include "common.h" +#include +#include + #include "base64.h" +#include "error.h" #include "intreadwrite.h" -#include "timer.h" /* ---------------- private code */ static const uint8_t map2[256] = diff --git a/libavutil/blowfish.c b/libavutil/blowfish.c index abc0e03d4..6df60150e 100644 --- a/libavutil/blowfish.c +++ b/libavutil/blowfish.c @@ -21,8 +21,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "avutil.h" -#include "common.h" +#include + +#include "attributes.h" #include "intreadwrite.h" #include "mem.h" #include "blowfish.h" diff --git a/libavutil/bprint.c b/libavutil/bprint.c index ea51d9b09..5b540ebc9 100644 --- a/libavutil/bprint.c +++ b/libavutil/bprint.c @@ -18,15 +18,16 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include #include #include #include #include "avstring.h" #include "bprint.h" -#include "common.h" #include "compat/va_copy.h" #include "error.h" +#include "macros.h" #include "mem.h" #define av_bprint_room(buf) ((buf)->size - FFMIN((buf)->len, (buf)->size)) diff --git a/libavutil/buffer_internal.h b/libavutil/buffer_internal.h index bdff1b5b3..adb916aaa 100644 --- a/libavutil/buffer_internal.h +++ b/libavutil/buffer_internal.h @@ -22,7 +22,6 @@ #include #include -#include "internal.h" #include "buffer.h" #include "thread.h" diff --git a/libavutil/camellia.c b/libavutil/camellia.c index f33ee9bab..3fc3b0829 100644 --- a/libavutil/camellia.c +++ b/libavutil/camellia.c @@ -18,9 +18,13 @@ * 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 "camellia.h" -#include "common.h" +#include "error.h" #include "intreadwrite.h" +#include "mem.h" #include "attributes.h" #define LR32(x,c) ((x) << (c) | (x) >> (32 - (c))) diff --git a/libavutil/cast5.c b/libavutil/cast5.c index 445eb55c1..0bf8ae992 100644 --- a/libavutil/cast5.c +++ b/libavutil/cast5.c @@ -18,9 +18,13 @@ * 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 "cast5.h" -#include "common.h" +#include "error.h" #include "intreadwrite.h" +#include "mem.h" #include "attributes.h" #define IA(x) ((x) >> 24) diff --git a/libavutil/channel_layout.c b/libavutil/channel_layout.c index ac773a9e6..21b70173b 100644 --- a/libavutil/channel_layout.c +++ b/libavutil/channel_layout.c @@ -24,12 +24,19 @@ */ #include +#include +#include -#include "avstring.h" -#include "avutil.h" +#include "avassert.h" #include "channel_layout.h" #include "bprint.h" #include "common.h" +#include "error.h" +#include "macros.h" +#include "opt.h" + +#define CHAN_IS_AMBI(x) ((x) >= AV_CHAN_AMBISONIC_BASE &&\ + (x) <= AV_CHAN_AMBISONIC_END) struct channel_name { const char *name; @@ -37,81 +44,166 @@ struct channel_name { }; static const struct channel_name channel_names[] = { - [0] = { "FL", "front left" }, - [1] = { "FR", "front right" }, - [2] = { "FC", "front center" }, - [3] = { "LFE", "low frequency" }, - [4] = { "BL", "back left" }, - [5] = { "BR", "back right" }, - [6] = { "FLC", "front left-of-center" }, - [7] = { "FRC", "front right-of-center" }, - [8] = { "BC", "back center" }, - [9] = { "SL", "side left" }, - [10] = { "SR", "side right" }, - [11] = { "TC", "top center" }, - [12] = { "TFL", "top front left" }, - [13] = { "TFC", "top front center" }, - [14] = { "TFR", "top front right" }, - [15] = { "TBL", "top back left" }, - [16] = { "TBC", "top back center" }, - [17] = { "TBR", "top back right" }, - [29] = { "DL", "downmix left" }, - [30] = { "DR", "downmix right" }, - [31] = { "WL", "wide left" }, - [32] = { "WR", "wide right" }, - [33] = { "SDL", "surround direct left" }, - [34] = { "SDR", "surround direct right" }, - [35] = { "LFE2", "low frequency 2" }, - [36] = { "TSL", "top side left" }, - [37] = { "TSR", "top side right" }, - [38] = { "BFC", "bottom front center" }, - [39] = { "BFL", "bottom front left" }, - [40] = { "BFR", "bottom front right" }, + [AV_CHAN_FRONT_LEFT ] = { "FL", "front left" }, + [AV_CHAN_FRONT_RIGHT ] = { "FR", "front right" }, + [AV_CHAN_FRONT_CENTER ] = { "FC", "front center" }, + [AV_CHAN_LOW_FREQUENCY ] = { "LFE", "low frequency" }, + [AV_CHAN_BACK_LEFT ] = { "BL", "back left" }, + [AV_CHAN_BACK_RIGHT ] = { "BR", "back right" }, + [AV_CHAN_FRONT_LEFT_OF_CENTER ] = { "FLC", "front left-of-center" }, + [AV_CHAN_FRONT_RIGHT_OF_CENTER] = { "FRC", "front right-of-center" }, + [AV_CHAN_BACK_CENTER ] = { "BC", "back center" }, + [AV_CHAN_SIDE_LEFT ] = { "SL", "side left" }, + [AV_CHAN_SIDE_RIGHT ] = { "SR", "side right" }, + [AV_CHAN_TOP_CENTER ] = { "TC", "top center" }, + [AV_CHAN_TOP_FRONT_LEFT ] = { "TFL", "top front left" }, + [AV_CHAN_TOP_FRONT_CENTER ] = { "TFC", "top front center" }, + [AV_CHAN_TOP_FRONT_RIGHT ] = { "TFR", "top front right" }, + [AV_CHAN_TOP_BACK_LEFT ] = { "TBL", "top back left" }, + [AV_CHAN_TOP_BACK_CENTER ] = { "TBC", "top back center" }, + [AV_CHAN_TOP_BACK_RIGHT ] = { "TBR", "top back right" }, + [AV_CHAN_STEREO_LEFT ] = { "DL", "downmix left" }, + [AV_CHAN_STEREO_RIGHT ] = { "DR", "downmix right" }, + [AV_CHAN_WIDE_LEFT ] = { "WL", "wide left" }, + [AV_CHAN_WIDE_RIGHT ] = { "WR", "wide right" }, + [AV_CHAN_SURROUND_DIRECT_LEFT ] = { "SDL", "surround direct left" }, + [AV_CHAN_SURROUND_DIRECT_RIGHT] = { "SDR", "surround direct right" }, + [AV_CHAN_LOW_FREQUENCY_2 ] = { "LFE2", "low frequency 2" }, + [AV_CHAN_TOP_SIDE_LEFT ] = { "TSL", "top side left" }, + [AV_CHAN_TOP_SIDE_RIGHT ] = { "TSR", "top side right" }, + [AV_CHAN_BOTTOM_FRONT_CENTER ] = { "BFC", "bottom front center" }, + [AV_CHAN_BOTTOM_FRONT_LEFT ] = { "BFL", "bottom front left" }, + [AV_CHAN_BOTTOM_FRONT_RIGHT ] = { "BFR", "bottom front right" }, }; -static const char *get_channel_name(int channel_id) +static const char *get_channel_name(enum AVChannel channel_id) { - if (channel_id < 0 || channel_id >= FF_ARRAY_ELEMS(channel_names)) + if ((unsigned) channel_id >= FF_ARRAY_ELEMS(channel_names) || + !channel_names[channel_id].name) return NULL; return channel_names[channel_id].name; } -static const struct { +void av_channel_name_bprint(AVBPrint *bp, enum AVChannel channel_id) +{ + if (channel_id >= AV_CHAN_AMBISONIC_BASE && + channel_id <= AV_CHAN_AMBISONIC_END) + av_bprintf(bp, "AMBI%d", channel_id - AV_CHAN_AMBISONIC_BASE); + else if ((unsigned)channel_id < FF_ARRAY_ELEMS(channel_names) && + channel_names[channel_id].name) + av_bprintf(bp, "%s", channel_names[channel_id].name); + else if (channel_id == AV_CHAN_NONE) + av_bprintf(bp, "NONE"); + else + av_bprintf(bp, "USR%d", channel_id); +} + +int av_channel_name(char *buf, size_t buf_size, enum AVChannel channel_id) +{ + AVBPrint bp; + + if (!buf && buf_size) + return AVERROR(EINVAL); + + av_bprint_init_for_buffer(&bp, buf, buf_size); + av_channel_name_bprint(&bp, channel_id); + + return bp.len; +} + +void av_channel_description_bprint(AVBPrint *bp, enum AVChannel channel_id) +{ + if (channel_id >= AV_CHAN_AMBISONIC_BASE && + channel_id <= AV_CHAN_AMBISONIC_END) + av_bprintf(bp, "ambisonic ACN %d", channel_id - AV_CHAN_AMBISONIC_BASE); + else if ((unsigned)channel_id < FF_ARRAY_ELEMS(channel_names) && + channel_names[channel_id].description) + av_bprintf(bp, "%s", channel_names[channel_id].description); + else if (channel_id == AV_CHAN_NONE) + av_bprintf(bp, "none"); + else + av_bprintf(bp, "user %d", channel_id); +} + +int av_channel_description(char *buf, size_t buf_size, enum AVChannel channel_id) +{ + AVBPrint bp; + + if (!buf && buf_size) + return AVERROR(EINVAL); + + av_bprint_init_for_buffer(&bp, buf, buf_size); + av_channel_description_bprint(&bp, channel_id); + + return bp.len; +} + +enum AVChannel av_channel_from_string(const char *str) +{ + int i; + char *endptr = (char *)str; + enum AVChannel id = AV_CHAN_NONE; + + if (!strncmp(str, "AMBI", 4)) { + i = strtol(str + 4, NULL, 0); + if (i < 0 || i > AV_CHAN_AMBISONIC_END - AV_CHAN_AMBISONIC_BASE) + return AV_CHAN_NONE; + return AV_CHAN_AMBISONIC_BASE + i; + } + + for (i = 0; i < FF_ARRAY_ELEMS(channel_names); i++) { + if (channel_names[i].name && !strcmp(str, channel_names[i].name)) + return i; + } + if (!strncmp(str, "USR", 3)) { + const char *p = str + 3; + id = strtol(p, &endptr, 0); + } + if (id >= 0 && !*endptr) + return id; + + return AV_CHAN_NONE; +} + +struct channel_layout_name { const char *name; - int nb_channels; - uint64_t layout; -} channel_layout_map[] = { - { "mono", 1, AV_CH_LAYOUT_MONO }, - { "stereo", 2, AV_CH_LAYOUT_STEREO }, - { "2.1", 3, AV_CH_LAYOUT_2POINT1 }, - { "3.0", 3, AV_CH_LAYOUT_SURROUND }, - { "3.0(back)", 3, AV_CH_LAYOUT_2_1 }, - { "4.0", 4, AV_CH_LAYOUT_4POINT0 }, - { "quad", 4, AV_CH_LAYOUT_QUAD }, - { "quad(side)", 4, AV_CH_LAYOUT_2_2 }, - { "3.1", 4, AV_CH_LAYOUT_3POINT1 }, - { "5.0", 5, AV_CH_LAYOUT_5POINT0_BACK }, - { "5.0(side)", 5, AV_CH_LAYOUT_5POINT0 }, - { "4.1", 5, AV_CH_LAYOUT_4POINT1 }, - { "5.1", 6, AV_CH_LAYOUT_5POINT1_BACK }, - { "5.1(side)", 6, AV_CH_LAYOUT_5POINT1 }, - { "6.0", 6, AV_CH_LAYOUT_6POINT0 }, - { "6.0(front)", 6, AV_CH_LAYOUT_6POINT0_FRONT }, - { "hexagonal", 6, AV_CH_LAYOUT_HEXAGONAL }, - { "6.1", 7, AV_CH_LAYOUT_6POINT1 }, - { "6.1(back)", 7, AV_CH_LAYOUT_6POINT1_BACK }, - { "6.1(front)", 7, AV_CH_LAYOUT_6POINT1_FRONT }, - { "7.0", 7, AV_CH_LAYOUT_7POINT0 }, - { "7.0(front)", 7, AV_CH_LAYOUT_7POINT0_FRONT }, - { "7.1", 8, AV_CH_LAYOUT_7POINT1 }, - { "7.1(wide)", 8, AV_CH_LAYOUT_7POINT1_WIDE_BACK }, - { "7.1(wide-side)", 8, AV_CH_LAYOUT_7POINT1_WIDE }, - { "octagonal", 8, AV_CH_LAYOUT_OCTAGONAL }, - { "hexadecagonal", 16, AV_CH_LAYOUT_HEXADECAGONAL }, - { "downmix", 2, AV_CH_LAYOUT_STEREO_DOWNMIX, }, - { "22.2", 24, AV_CH_LAYOUT_22POINT2, }, + AVChannelLayout layout; }; +static const struct channel_layout_name channel_layout_map[] = { + { "mono", AV_CHANNEL_LAYOUT_MONO }, + { "stereo", AV_CHANNEL_LAYOUT_STEREO }, + { "2.1", AV_CHANNEL_LAYOUT_2POINT1 }, + { "3.0", AV_CHANNEL_LAYOUT_SURROUND }, + { "3.0(back)", AV_CHANNEL_LAYOUT_2_1 }, + { "4.0", AV_CHANNEL_LAYOUT_4POINT0 }, + { "quad", AV_CHANNEL_LAYOUT_QUAD }, + { "quad(side)", AV_CHANNEL_LAYOUT_2_2 }, + { "3.1", AV_CHANNEL_LAYOUT_3POINT1 }, + { "5.0", AV_CHANNEL_LAYOUT_5POINT0_BACK }, + { "5.0(side)", AV_CHANNEL_LAYOUT_5POINT0 }, + { "4.1", AV_CHANNEL_LAYOUT_4POINT1 }, + { "5.1", AV_CHANNEL_LAYOUT_5POINT1_BACK }, + { "5.1(side)", AV_CHANNEL_LAYOUT_5POINT1 }, + { "6.0", AV_CHANNEL_LAYOUT_6POINT0 }, + { "6.0(front)", AV_CHANNEL_LAYOUT_6POINT0_FRONT }, + { "hexagonal", AV_CHANNEL_LAYOUT_HEXAGONAL }, + { "6.1", AV_CHANNEL_LAYOUT_6POINT1 }, + { "6.1(back)", AV_CHANNEL_LAYOUT_6POINT1_BACK }, + { "6.1(front)", AV_CHANNEL_LAYOUT_6POINT1_FRONT }, + { "7.0", AV_CHANNEL_LAYOUT_7POINT0 }, + { "7.0(front)", AV_CHANNEL_LAYOUT_7POINT0_FRONT }, + { "7.1", AV_CHANNEL_LAYOUT_7POINT1 }, + { "7.1(wide)", AV_CHANNEL_LAYOUT_7POINT1_WIDE_BACK }, + { "7.1(wide-side)", AV_CHANNEL_LAYOUT_7POINT1_WIDE }, + { "octagonal", AV_CHANNEL_LAYOUT_OCTAGONAL }, + { "hexadecagonal", AV_CHANNEL_LAYOUT_HEXADECAGONAL }, + { "downmix", AV_CHANNEL_LAYOUT_STEREO_DOWNMIX, }, + { "22.2", AV_CHANNEL_LAYOUT_22POINT2, }, +}; + +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS static uint64_t get_channel_layout_single(const char *name, int name_len) { int i; @@ -121,7 +213,7 @@ static uint64_t get_channel_layout_single(const char *name, int name_len) for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++) { if (strlen(channel_layout_map[i].name) == name_len && !memcmp(channel_layout_map[i].name, name, name_len)) - return channel_layout_map[i].layout; + return channel_layout_map[i].layout.u.mask; } for (i = 0; i < FF_ARRAY_ELEMS(channel_names); i++) if (channel_names[i].name && @@ -189,8 +281,8 @@ void av_bprint_channel_layout(struct AVBPrint *bp, nb_channels = av_get_channel_layout_nb_channels(channel_layout); for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++) - if (nb_channels == channel_layout_map[i].nb_channels && - channel_layout == channel_layout_map[i].layout) { + if (nb_channels == channel_layout_map[i].layout.nb_channels && + channel_layout == channel_layout_map[i].layout.u.mask) { av_bprintf(bp, "%s", channel_layout_map[i].name); return; } @@ -231,8 +323,8 @@ int av_get_channel_layout_nb_channels(uint64_t channel_layout) int64_t av_get_default_channel_layout(int nb_channels) { int i; for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++) - if (nb_channels == channel_layout_map[i].nb_channels) - return channel_layout_map[i].layout; + if (nb_channels == channel_layout_map[i].layout.nb_channels) + return channel_layout_map[i].layout.u.mask; return 0; } @@ -287,7 +379,626 @@ int av_get_standard_channel_layout(unsigned index, uint64_t *layout, { if (index >= FF_ARRAY_ELEMS(channel_layout_map)) return AVERROR_EOF; - if (layout) *layout = channel_layout_map[index].layout; + if (layout) *layout = channel_layout_map[index].layout.u.mask; if (name) *name = channel_layout_map[index].name; return 0; } +FF_ENABLE_DEPRECATION_WARNINGS +#endif + +int av_channel_layout_from_mask(AVChannelLayout *channel_layout, + uint64_t mask) +{ + if (!mask) + return AVERROR(EINVAL); + + channel_layout->order = AV_CHANNEL_ORDER_NATIVE; + channel_layout->nb_channels = av_popcount64(mask); + channel_layout->u.mask = mask; + + return 0; +} + +int av_channel_layout_from_string(AVChannelLayout *channel_layout, + const char *str) +{ + int i; + int channels = 0, nb_channels = 0, native = 1; + enum AVChannel highest_channel = AV_CHAN_NONE; + const char *dup; + char *chlist, *end; + uint64_t mask = 0; + + /* channel layout names */ + for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++) { + if (channel_layout_map[i].name && !strcmp(str, channel_layout_map[i].name)) { + *channel_layout = channel_layout_map[i].layout; + return 0; + } + } + + /* ambisonic */ + if (!strncmp(str, "ambisonic ", 10)) { + const char *p = str + 10; + char *endptr; + AVChannelLayout extra = {0}; + int order; + + order = strtol(p, &endptr, 0); + if (order < 0 || order + 1 > INT_MAX / (order + 1) || + (*endptr && *endptr != '+')) + return AVERROR(EINVAL); + + channel_layout->order = AV_CHANNEL_ORDER_AMBISONIC; + channel_layout->nb_channels = (order + 1) * (order + 1); + + if (*endptr) { + int ret = av_channel_layout_from_string(&extra, endptr + 1); + if (ret < 0) + return ret; + if (extra.nb_channels >= INT_MAX - channel_layout->nb_channels) { + av_channel_layout_uninit(&extra); + return AVERROR(EINVAL); + } + + if (extra.order == AV_CHANNEL_ORDER_NATIVE) { + channel_layout->u.mask = extra.u.mask; + } else { + channel_layout->order = AV_CHANNEL_ORDER_CUSTOM; + channel_layout->u.map = + av_calloc(channel_layout->nb_channels + extra.nb_channels, + sizeof(*channel_layout->u.map)); + if (!channel_layout->u.map) { + av_channel_layout_uninit(&extra); + return AVERROR(ENOMEM); + } + + for (i = 0; i < channel_layout->nb_channels; i++) + channel_layout->u.map[i].id = AV_CHAN_AMBISONIC_BASE + i; + for (i = 0; i < extra.nb_channels; i++) { + enum AVChannel ch = av_channel_layout_channel_from_index(&extra, i); + if (CHAN_IS_AMBI(ch)) { + av_channel_layout_uninit(&extra); + return AVERROR(EINVAL); + } + channel_layout->u.map[channel_layout->nb_channels + i].id = ch; + if (extra.order == AV_CHANNEL_ORDER_CUSTOM && + extra.u.map[i].name[0]) + av_strlcpy(channel_layout->u.map[channel_layout->nb_channels + i].name, + extra.u.map[i].name, + sizeof(channel_layout->u.map[channel_layout->nb_channels + i].name)); + } + } + channel_layout->nb_channels += extra.nb_channels; + av_channel_layout_uninit(&extra); + } + + return 0; + } + + chlist = av_strdup(str); + if (!chlist) + return AVERROR(ENOMEM); + + /* channel names */ + av_sscanf(str, "%d channels (%[^)]", &nb_channels, chlist); + end = strchr(str, ')'); + + dup = chlist; + while (*dup) { + char *channel, *chname; + int ret = av_opt_get_key_value(&dup, "@", "+", AV_OPT_FLAG_IMPLICIT_KEY, &channel, &chname); + if (ret < 0) { + av_free(chlist); + return ret; + } + if (*dup) + dup++; // skip separator + if (channel && !*channel) + av_freep(&channel); + for (i = 0; i < FF_ARRAY_ELEMS(channel_names); i++) { + if (channel_names[i].name && !strcmp(channel ? channel : chname, channel_names[i].name)) { + if (channel || i < highest_channel || mask & (1ULL << i)) + native = 0; // Not a native layout, use a custom one + highest_channel = i; + mask |= 1ULL << i; + break; + } + } + + if (!channel && i >= FF_ARRAY_ELEMS(channel_names)) { + char *endptr = chname; + enum AVChannel id = AV_CHAN_NONE; + + if (!strncmp(chname, "USR", 3)) { + const char *p = chname + 3; + id = strtol(p, &endptr, 0); + } + if (id < 0 || *endptr) { + native = 0; // Unknown channel name + channels = 0; + mask = 0; + av_free(chname); + break; + } + if (id > 63) + native = 0; // Not a native layout, use a custom one + else { + if (id < highest_channel || mask & (1ULL << id)) + native = 0; // Not a native layout, use a custom one + highest_channel = id; + mask |= 1ULL << id; + } + } + channels++; + av_free(channel); + av_free(chname); + } + + if (mask && native) { + av_free(chlist); + if (nb_channels && ((nb_channels != channels) || (!end || *++end))) + return AVERROR(EINVAL); + av_channel_layout_from_mask(channel_layout, mask); + return 0; + } + + /* custom layout of channel names */ + if (channels && !native) { + int idx = 0; + + if (nb_channels && ((nb_channels != channels) || (!end || *++end))) { + av_free(chlist); + return AVERROR(EINVAL); + } + + channel_layout->u.map = av_calloc(channels, sizeof(*channel_layout->u.map)); + if (!channel_layout->u.map) { + av_free(chlist); + return AVERROR(ENOMEM); + } + + channel_layout->order = AV_CHANNEL_ORDER_CUSTOM; + channel_layout->nb_channels = channels; + + dup = chlist; + while (*dup) { + char *channel, *chname; + int ret = av_opt_get_key_value(&dup, "@", "+", AV_OPT_FLAG_IMPLICIT_KEY, &channel, &chname); + if (ret < 0) { + av_freep(&channel_layout->u.map); + av_free(chlist); + return ret; + } + if (*dup) + dup++; // skip separator + for (i = 0; i < FF_ARRAY_ELEMS(channel_names); i++) { + if (channel_names[i].name && !strcmp(channel ? channel : chname, channel_names[i].name)) { + channel_layout->u.map[idx].id = i; + if (channel) + av_strlcpy(channel_layout->u.map[idx].name, chname, sizeof(channel_layout->u.map[idx].name)); + idx++; + break; + } + } + if (i >= FF_ARRAY_ELEMS(channel_names)) { + const char *p = (channel ? channel : chname) + 3; + channel_layout->u.map[idx].id = strtol(p, NULL, 0); + if (channel) + av_strlcpy(channel_layout->u.map[idx].name, chname, sizeof(channel_layout->u.map[idx].name)); + idx++; + } + av_free(channel); + av_free(chname); + } + av_free(chlist); + + return 0; + } + av_freep(&chlist); + + errno = 0; + mask = strtoull(str, &end, 0); + + /* channel layout mask */ + if (!errno && !*end && !strchr(str, '-') && mask) { + av_channel_layout_from_mask(channel_layout, mask); + return 0; + } + + errno = 0; + channels = strtol(str, &end, 10); + + /* number of channels */ + if (!errno && !strcmp(end, "c") && channels > 0) { + av_channel_layout_default(channel_layout, channels); + if (channel_layout->order == AV_CHANNEL_ORDER_NATIVE) + return 0; + } + + /* number of unordered channels */ + if (!errno && (!strcmp(end, "C") || !strcmp(end, " channels")) + && channels > 0) { + channel_layout->order = AV_CHANNEL_ORDER_UNSPEC; + channel_layout->nb_channels = channels; + return 0; + } + + return AVERROR(EINVAL); +} + +void av_channel_layout_uninit(AVChannelLayout *channel_layout) +{ + if (channel_layout->order == AV_CHANNEL_ORDER_CUSTOM) + av_freep(&channel_layout->u.map); + memset(channel_layout, 0, sizeof(*channel_layout)); +} + +int av_channel_layout_copy(AVChannelLayout *dst, const AVChannelLayout *src) +{ + av_channel_layout_uninit(dst); + *dst = *src; + if (src->order == AV_CHANNEL_ORDER_CUSTOM) { + dst->u.map = av_malloc_array(src->nb_channels, sizeof(*dst->u.map)); + if (!dst->u.map) + return AVERROR(ENOMEM); + memcpy(dst->u.map, src->u.map, src->nb_channels * sizeof(*src->u.map)); + } + return 0; +} + +/** + * If the layout is n-th order standard-order ambisonic, with optional + * extra non-diegetic channels at the end, return the order. + * Return a negative error code otherwise. + */ +static int ambisonic_order(const AVChannelLayout *channel_layout) +{ + int i, highest_ambi, order; + + highest_ambi = -1; + if (channel_layout->order == AV_CHANNEL_ORDER_AMBISONIC) + highest_ambi = channel_layout->nb_channels - av_popcount64(channel_layout->u.mask) - 1; + else { + const AVChannelCustom *map = channel_layout->u.map; + av_assert0(channel_layout->order == AV_CHANNEL_ORDER_CUSTOM); + + for (i = 0; i < channel_layout->nb_channels; i++) { + int is_ambi = CHAN_IS_AMBI(map[i].id); + + /* ambisonic following non-ambisonic */ + if (i > 0 && is_ambi && !CHAN_IS_AMBI(map[i - 1].id)) + return AVERROR(EINVAL); + + /* non-default ordering */ + if (is_ambi && map[i].id - AV_CHAN_AMBISONIC_BASE != i) + return AVERROR(EINVAL); + + if (CHAN_IS_AMBI(map[i].id)) + highest_ambi = i; + } + } + /* no ambisonic channels*/ + if (highest_ambi < 0) + return AVERROR(EINVAL); + + order = floor(sqrt(highest_ambi)); + /* incomplete order - some harmonics are missing */ + if ((order + 1) * (order + 1) != highest_ambi + 1) + return AVERROR(EINVAL); + + return order; +} + +/** + * If the custom layout is n-th order standard-order ambisonic, with optional + * extra non-diegetic channels at the end, write its string description in bp. + * Return a negative error code otherwise. + */ +static int try_describe_ambisonic(AVBPrint *bp, const AVChannelLayout *channel_layout) +{ + int nb_ambi_channels; + int order = ambisonic_order(channel_layout); + if (order < 0) + return order; + + av_bprintf(bp, "ambisonic %d", order); + + /* extra channels present */ + nb_ambi_channels = (order + 1) * (order + 1); + if (nb_ambi_channels < channel_layout->nb_channels) { + AVChannelLayout extra = { 0 }; + + if (channel_layout->order == AV_CHANNEL_ORDER_AMBISONIC) { + extra.order = AV_CHANNEL_ORDER_NATIVE; + extra.nb_channels = av_popcount64(channel_layout->u.mask); + extra.u.mask = channel_layout->u.mask; + } else { + extra.order = AV_CHANNEL_ORDER_CUSTOM; + extra.nb_channels = channel_layout->nb_channels - nb_ambi_channels; + extra.u.map = channel_layout->u.map + nb_ambi_channels; + } + + av_bprint_chars(bp, '+', 1); + av_channel_layout_describe_bprint(&extra, bp); + /* Not calling uninit here on extra because we don't own the u.map pointer */ + } + + return 0; +} + +int av_channel_layout_describe_bprint(const AVChannelLayout *channel_layout, + AVBPrint *bp) +{ + int i; + + switch (channel_layout->order) { + case AV_CHANNEL_ORDER_NATIVE: + for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++) + if (channel_layout->u.mask == channel_layout_map[i].layout.u.mask) { + av_bprintf(bp, "%s", channel_layout_map[i].name); + return 0; + } + // fall-through + case AV_CHANNEL_ORDER_CUSTOM: + if (channel_layout->order == AV_CHANNEL_ORDER_CUSTOM) { + int res = try_describe_ambisonic(bp, channel_layout); + if (res >= 0) + return 0; + } + if (channel_layout->nb_channels) + av_bprintf(bp, "%d channels (", channel_layout->nb_channels); + for (i = 0; i < channel_layout->nb_channels; i++) { + enum AVChannel ch = av_channel_layout_channel_from_index(channel_layout, i); + + if (i) + av_bprintf(bp, "+"); + av_channel_name_bprint(bp, ch); + if (channel_layout->order == AV_CHANNEL_ORDER_CUSTOM && + channel_layout->u.map[i].name[0]) + av_bprintf(bp, "@%s", channel_layout->u.map[i].name); + } + if (channel_layout->nb_channels) { + av_bprintf(bp, ")"); + return 0; + } + // fall-through + case AV_CHANNEL_ORDER_UNSPEC: + av_bprintf(bp, "%d channels", channel_layout->nb_channels); + return 0; + case AV_CHANNEL_ORDER_AMBISONIC: + return try_describe_ambisonic(bp, channel_layout); + default: + return AVERROR(EINVAL); + } +} + +int av_channel_layout_describe(const AVChannelLayout *channel_layout, + char *buf, size_t buf_size) +{ + AVBPrint bp; + int ret; + + if (!buf && buf_size) + return AVERROR(EINVAL); + + av_bprint_init_for_buffer(&bp, buf, buf_size); + ret = av_channel_layout_describe_bprint(channel_layout, &bp); + if (ret < 0) + return ret; + + return bp.len; +} + +enum AVChannel +av_channel_layout_channel_from_index(const AVChannelLayout *channel_layout, + unsigned int idx) +{ + int i; + + if (idx >= channel_layout->nb_channels) + return AV_CHAN_NONE; + + switch (channel_layout->order) { + case AV_CHANNEL_ORDER_CUSTOM: + return channel_layout->u.map[idx].id; + case AV_CHANNEL_ORDER_AMBISONIC: { + int ambi_channels = channel_layout->nb_channels - av_popcount64(channel_layout->u.mask); + if (idx < ambi_channels) + return AV_CHAN_AMBISONIC_BASE + idx; + idx -= ambi_channels; + } + // fall-through + case AV_CHANNEL_ORDER_NATIVE: + for (i = 0; i < 64; i++) { + if ((1ULL << i) & channel_layout->u.mask && !idx--) + return i; + } + default: + return AV_CHAN_NONE; + } +} + +enum AVChannel +av_channel_layout_channel_from_string(const AVChannelLayout *channel_layout, + const char *str) +{ + int index = av_channel_layout_index_from_string(channel_layout, str); + + if (index < 0) + return AV_CHAN_NONE; + + return av_channel_layout_channel_from_index(channel_layout, index); +} + +int av_channel_layout_index_from_channel(const AVChannelLayout *channel_layout, + enum AVChannel channel) +{ + int i; + + if (channel == AV_CHAN_NONE) + return AVERROR(EINVAL); + + switch (channel_layout->order) { + case AV_CHANNEL_ORDER_CUSTOM: + for (i = 0; i < channel_layout->nb_channels; i++) + if (channel_layout->u.map[i].id == channel) + return i; + return AVERROR(EINVAL); + case AV_CHANNEL_ORDER_AMBISONIC: + case AV_CHANNEL_ORDER_NATIVE: { + uint64_t mask = channel_layout->u.mask; + int ambi_channels = channel_layout->nb_channels - av_popcount64(mask); + if (channel_layout->order == AV_CHANNEL_ORDER_AMBISONIC && + channel >= AV_CHAN_AMBISONIC_BASE) { + if (channel - AV_CHAN_AMBISONIC_BASE >= ambi_channels) + return AVERROR(EINVAL); + return channel - AV_CHAN_AMBISONIC_BASE; + } + if ((unsigned)channel > 63 || !(mask & (1ULL << channel))) + return AVERROR(EINVAL); + mask &= (1ULL << channel) - 1; + return av_popcount64(mask) + ambi_channels; + } + default: + return AVERROR(EINVAL); + } +} + +int av_channel_layout_index_from_string(const AVChannelLayout *channel_layout, + const char *str) +{ + char *chname; + enum AVChannel ch = AV_CHAN_NONE; + + switch (channel_layout->order) { + case AV_CHANNEL_ORDER_CUSTOM: + chname = strstr(str, "@"); + if (chname) { + char buf[16]; + chname++; + av_strlcpy(buf, str, FFMIN(sizeof(buf), chname - str)); + if (!*chname) + chname = NULL; + ch = av_channel_from_string(buf); + if (ch == AV_CHAN_NONE && *buf) + return AVERROR(EINVAL); + } + for (int i = 0; chname && i < channel_layout->nb_channels; i++) { + if (!strcmp(chname, channel_layout->u.map[i].name) && + (ch == AV_CHAN_NONE || ch == channel_layout->u.map[i].id)) + return i; + } + // fall-through + case AV_CHANNEL_ORDER_AMBISONIC: + case AV_CHANNEL_ORDER_NATIVE: + ch = av_channel_from_string(str); + if (ch == AV_CHAN_NONE) + return AVERROR(EINVAL); + return av_channel_layout_index_from_channel(channel_layout, ch); + } + + return AVERROR(EINVAL); +} + +int av_channel_layout_check(const AVChannelLayout *channel_layout) +{ + if (channel_layout->nb_channels <= 0) + return 0; + + switch (channel_layout->order) { + case AV_CHANNEL_ORDER_NATIVE: + return av_popcount64(channel_layout->u.mask) == channel_layout->nb_channels; + case AV_CHANNEL_ORDER_CUSTOM: + if (!channel_layout->u.map) + return 0; + for (int i = 0; i < channel_layout->nb_channels; i++) { + if (channel_layout->u.map[i].id == AV_CHAN_NONE) + return 0; + } + return 1; + case AV_CHANNEL_ORDER_AMBISONIC: + /* If non-diegetic channels are present, ensure they are taken into account */ + return av_popcount64(channel_layout->u.mask) < channel_layout->nb_channels; + case AV_CHANNEL_ORDER_UNSPEC: + return 1; + default: + return 0; + } +} + +int av_channel_layout_compare(const AVChannelLayout *chl, const AVChannelLayout *chl1) +{ + int i; + + /* different channel counts -> not equal */ + if (chl->nb_channels != chl1->nb_channels) + return 1; + + /* if only one is unspecified -> not equal */ + if ((chl->order == AV_CHANNEL_ORDER_UNSPEC) != + (chl1->order == AV_CHANNEL_ORDER_UNSPEC)) + return 1; + /* both are unspecified -> equal */ + else if (chl->order == AV_CHANNEL_ORDER_UNSPEC) + return 0; + + /* can compare masks directly */ + if ((chl->order == AV_CHANNEL_ORDER_NATIVE || + chl->order == AV_CHANNEL_ORDER_AMBISONIC) && + chl->order == chl1->order) + return chl->u.mask != chl1->u.mask; + + /* compare channel by channel */ + for (i = 0; i < chl->nb_channels; i++) + if (av_channel_layout_channel_from_index(chl, i) != + av_channel_layout_channel_from_index(chl1, i)) + return 1; + return 0; +} + +void av_channel_layout_default(AVChannelLayout *ch_layout, int nb_channels) +{ + int i; + for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++) + if (nb_channels == channel_layout_map[i].layout.nb_channels) { + *ch_layout = channel_layout_map[i].layout; + return; + } + + ch_layout->order = AV_CHANNEL_ORDER_UNSPEC; + ch_layout->nb_channels = nb_channels; +} + +const AVChannelLayout *av_channel_layout_standard(void **opaque) +{ + uintptr_t i = (uintptr_t)*opaque; + const AVChannelLayout *ch_layout = NULL; + + if (i < FF_ARRAY_ELEMS(channel_layout_map)) { + ch_layout = &channel_layout_map[i].layout; + *opaque = (void*)(i + 1); + } + + return ch_layout; +} + +uint64_t av_channel_layout_subset(const AVChannelLayout *channel_layout, + uint64_t mask) +{ + uint64_t ret = 0; + int i; + + switch (channel_layout->order) { + case AV_CHANNEL_ORDER_NATIVE: + case AV_CHANNEL_ORDER_AMBISONIC: + return channel_layout->u.mask & mask; + case AV_CHANNEL_ORDER_CUSTOM: + for (i = 0; i < 64; i++) + if (mask & (1ULL << i) && av_channel_layout_index_from_channel(channel_layout, i) >= 0) + ret |= (1ULL << i); + break; + } + + return ret; +} diff --git a/libavutil/channel_layout.h b/libavutil/channel_layout.h index d39ae1177..4dd6614de 100644 --- a/libavutil/channel_layout.h +++ b/libavutil/channel_layout.h @@ -23,6 +23,10 @@ #define AVUTIL_CHANNEL_LAYOUT_H #include +#include + +#include "version.h" +#include "attributes.h" /** * @file @@ -34,6 +38,111 @@ * @{ */ +enum AVChannel { + ///< Invalid channel index + AV_CHAN_NONE = -1, + AV_CHAN_FRONT_LEFT, + AV_CHAN_FRONT_RIGHT, + AV_CHAN_FRONT_CENTER, + AV_CHAN_LOW_FREQUENCY, + AV_CHAN_BACK_LEFT, + AV_CHAN_BACK_RIGHT, + AV_CHAN_FRONT_LEFT_OF_CENTER, + AV_CHAN_FRONT_RIGHT_OF_CENTER, + AV_CHAN_BACK_CENTER, + AV_CHAN_SIDE_LEFT, + AV_CHAN_SIDE_RIGHT, + AV_CHAN_TOP_CENTER, + AV_CHAN_TOP_FRONT_LEFT, + AV_CHAN_TOP_FRONT_CENTER, + AV_CHAN_TOP_FRONT_RIGHT, + AV_CHAN_TOP_BACK_LEFT, + AV_CHAN_TOP_BACK_CENTER, + AV_CHAN_TOP_BACK_RIGHT, + /** Stereo downmix. */ + AV_CHAN_STEREO_LEFT = 29, + /** See above. */ + AV_CHAN_STEREO_RIGHT, + AV_CHAN_WIDE_LEFT, + AV_CHAN_WIDE_RIGHT, + AV_CHAN_SURROUND_DIRECT_LEFT, + AV_CHAN_SURROUND_DIRECT_RIGHT, + AV_CHAN_LOW_FREQUENCY_2, + AV_CHAN_TOP_SIDE_LEFT, + AV_CHAN_TOP_SIDE_RIGHT, + AV_CHAN_BOTTOM_FRONT_CENTER, + AV_CHAN_BOTTOM_FRONT_LEFT, + AV_CHAN_BOTTOM_FRONT_RIGHT, + + /** Channel is empty can be safely skipped. */ + AV_CHAN_UNUSED = 0x200, + + /** Channel contains data, but its position is unknown. */ + AV_CHAN_UNKNOWN = 0x300, + + /** + * Range of channels between AV_CHAN_AMBISONIC_BASE and + * AV_CHAN_AMBISONIC_END represent Ambisonic components using the ACN system. + * + * Given a channel id between AV_CHAN_AMBISONIC_BASE and + * AV_CHAN_AMBISONIC_END (inclusive), the ACN index of the channel is + * = - AV_CHAN_AMBISONIC_BASE. + * + * @note these values are only used for AV_CHANNEL_ORDER_CUSTOM channel + * orderings, the AV_CHANNEL_ORDER_AMBISONIC ordering orders the channels + * implicitly by their position in the stream. + */ + AV_CHAN_AMBISONIC_BASE = 0x400, + // leave space for 1024 ids, which correspond to maximum order-32 harmonics, + // which should be enough for the foreseeable use cases + AV_CHAN_AMBISONIC_END = 0x7ff, +}; + +enum AVChannelOrder { + /** + * Only the channel count is specified, without any further information + * about the channel order. + */ + AV_CHANNEL_ORDER_UNSPEC, + /** + * The native channel order, i.e. the channels are in the same order in + * which they are defined in the AVChannel enum. This supports up to 63 + * different channels. + */ + AV_CHANNEL_ORDER_NATIVE, + /** + * The channel order does not correspond to any other predefined order and + * is stored as an explicit map. For example, this could be used to support + * layouts with 64 or more channels, or with empty/skipped (AV_CHAN_SILENCE) + * channels at arbitrary positions. + */ + AV_CHANNEL_ORDER_CUSTOM, + /** + * The audio is represented as the decomposition of the sound field into + * spherical harmonics. Each channel corresponds to a single expansion + * component. Channels are ordered according to ACN (Ambisonic Channel + * Number). + * + * The channel with the index n in the stream contains the spherical + * harmonic of degree l and order m given by + * @code{.unparsed} + * l = floor(sqrt(n)), + * m = n - l * (l + 1). + * @endcode + * + * Conversely given a spherical harmonic of degree l and order m, the + * corresponding channel index n is given by + * @code{.unparsed} + * n = l * (l + 1) + m. + * @endcode + * + * Normalization is assumed to be SN3D (Schmidt Semi-Normalization) + * as defined in AmbiX format $ 2.1. + */ + AV_CHANNEL_ORDER_AMBISONIC, +}; + + /** * @defgroup channel_masks Audio channel masks * @@ -46,41 +155,46 @@ * * @{ */ -#define AV_CH_FRONT_LEFT 0x00000001 -#define AV_CH_FRONT_RIGHT 0x00000002 -#define AV_CH_FRONT_CENTER 0x00000004 -#define AV_CH_LOW_FREQUENCY 0x00000008 -#define AV_CH_BACK_LEFT 0x00000010 -#define AV_CH_BACK_RIGHT 0x00000020 -#define AV_CH_FRONT_LEFT_OF_CENTER 0x00000040 -#define AV_CH_FRONT_RIGHT_OF_CENTER 0x00000080 -#define AV_CH_BACK_CENTER 0x00000100 -#define AV_CH_SIDE_LEFT 0x00000200 -#define AV_CH_SIDE_RIGHT 0x00000400 -#define AV_CH_TOP_CENTER 0x00000800 -#define AV_CH_TOP_FRONT_LEFT 0x00001000 -#define AV_CH_TOP_FRONT_CENTER 0x00002000 -#define AV_CH_TOP_FRONT_RIGHT 0x00004000 -#define AV_CH_TOP_BACK_LEFT 0x00008000 -#define AV_CH_TOP_BACK_CENTER 0x00010000 -#define AV_CH_TOP_BACK_RIGHT 0x00020000 -#define AV_CH_STEREO_LEFT 0x20000000 ///< Stereo downmix. -#define AV_CH_STEREO_RIGHT 0x40000000 ///< See AV_CH_STEREO_LEFT. -#define AV_CH_WIDE_LEFT 0x0000000080000000ULL -#define AV_CH_WIDE_RIGHT 0x0000000100000000ULL -#define AV_CH_SURROUND_DIRECT_LEFT 0x0000000200000000ULL -#define AV_CH_SURROUND_DIRECT_RIGHT 0x0000000400000000ULL -#define AV_CH_LOW_FREQUENCY_2 0x0000000800000000ULL -#define AV_CH_TOP_SIDE_LEFT 0x0000001000000000ULL -#define AV_CH_TOP_SIDE_RIGHT 0x0000002000000000ULL -#define AV_CH_BOTTOM_FRONT_CENTER 0x0000004000000000ULL -#define AV_CH_BOTTOM_FRONT_LEFT 0x0000008000000000ULL -#define AV_CH_BOTTOM_FRONT_RIGHT 0x0000010000000000ULL +#define AV_CH_FRONT_LEFT (1ULL << AV_CHAN_FRONT_LEFT ) +#define AV_CH_FRONT_RIGHT (1ULL << AV_CHAN_FRONT_RIGHT ) +#define AV_CH_FRONT_CENTER (1ULL << AV_CHAN_FRONT_CENTER ) +#define AV_CH_LOW_FREQUENCY (1ULL << AV_CHAN_LOW_FREQUENCY ) +#define AV_CH_BACK_LEFT (1ULL << AV_CHAN_BACK_LEFT ) +#define AV_CH_BACK_RIGHT (1ULL << AV_CHAN_BACK_RIGHT ) +#define AV_CH_FRONT_LEFT_OF_CENTER (1ULL << AV_CHAN_FRONT_LEFT_OF_CENTER ) +#define AV_CH_FRONT_RIGHT_OF_CENTER (1ULL << AV_CHAN_FRONT_RIGHT_OF_CENTER) +#define AV_CH_BACK_CENTER (1ULL << AV_CHAN_BACK_CENTER ) +#define AV_CH_SIDE_LEFT (1ULL << AV_CHAN_SIDE_LEFT ) +#define AV_CH_SIDE_RIGHT (1ULL << AV_CHAN_SIDE_RIGHT ) +#define AV_CH_TOP_CENTER (1ULL << AV_CHAN_TOP_CENTER ) +#define AV_CH_TOP_FRONT_LEFT (1ULL << AV_CHAN_TOP_FRONT_LEFT ) +#define AV_CH_TOP_FRONT_CENTER (1ULL << AV_CHAN_TOP_FRONT_CENTER ) +#define AV_CH_TOP_FRONT_RIGHT (1ULL << AV_CHAN_TOP_FRONT_RIGHT ) +#define AV_CH_TOP_BACK_LEFT (1ULL << AV_CHAN_TOP_BACK_LEFT ) +#define AV_CH_TOP_BACK_CENTER (1ULL << AV_CHAN_TOP_BACK_CENTER ) +#define AV_CH_TOP_BACK_RIGHT (1ULL << AV_CHAN_TOP_BACK_RIGHT ) +#define AV_CH_STEREO_LEFT (1ULL << AV_CHAN_STEREO_LEFT ) +#define AV_CH_STEREO_RIGHT (1ULL << AV_CHAN_STEREO_RIGHT ) +#define AV_CH_WIDE_LEFT (1ULL << AV_CHAN_WIDE_LEFT ) +#define AV_CH_WIDE_RIGHT (1ULL << AV_CHAN_WIDE_RIGHT ) +#define AV_CH_SURROUND_DIRECT_LEFT (1ULL << AV_CHAN_SURROUND_DIRECT_LEFT ) +#define AV_CH_SURROUND_DIRECT_RIGHT (1ULL << AV_CHAN_SURROUND_DIRECT_RIGHT) +#define AV_CH_LOW_FREQUENCY_2 (1ULL << AV_CHAN_LOW_FREQUENCY_2 ) +#define AV_CH_TOP_SIDE_LEFT (1ULL << AV_CHAN_TOP_SIDE_LEFT ) +#define AV_CH_TOP_SIDE_RIGHT (1ULL << AV_CHAN_TOP_SIDE_RIGHT ) +#define AV_CH_BOTTOM_FRONT_CENTER (1ULL << AV_CHAN_BOTTOM_FRONT_CENTER ) +#define AV_CH_BOTTOM_FRONT_LEFT (1ULL << AV_CHAN_BOTTOM_FRONT_LEFT ) +#define AV_CH_BOTTOM_FRONT_RIGHT (1ULL << AV_CHAN_BOTTOM_FRONT_RIGHT ) +#if FF_API_OLD_CHANNEL_LAYOUT /** Channel mask value used for AVCodecContext.request_channel_layout to indicate that the user requests the channel order of the decoder output - to be the native codec channel order. */ + to be the native codec channel order. + @deprecated channel order is now indicated in a special field in + AVChannelLayout + */ #define AV_CH_LAYOUT_NATIVE 0x8000000000000000ULL +#endif /** * @} @@ -128,6 +242,149 @@ enum AVMatrixEncoding { AV_MATRIX_ENCODING_NB }; +/** + * @} + */ + +/** + * An AVChannelCustom defines a single channel within a custom order layout + * + * Unlike most structures in FFmpeg, sizeof(AVChannelCustom) is a part of the + * public ABI. + * + * No new fields may be added to it without a major version bump. + */ +typedef struct AVChannelCustom { + enum AVChannel id; + char name[16]; + void *opaque; +} AVChannelCustom; + +/** + * An AVChannelLayout holds information about the channel layout of audio data. + * + * A channel layout here is defined as a set of channels ordered in a specific + * way (unless the channel order is AV_CHANNEL_ORDER_UNSPEC, in which case an + * AVChannelLayout carries only the channel count). + * + * Unlike most structures in Libav, sizeof(AVChannelLayout) is a part of the + * public ABI and may be used by the caller. E.g. it may be allocated on stack + * or embedded in caller-defined structs. + * + * AVChannelLayout can be initialized as follows: + * - default initialization with {0}, followed by setting all used fields + * correctly; + * - by assigning one of the predefined AV_CHANNEL_LAYOUT_* initializers; + * - with a constructor function, such as av_channel_layout_default(), + * av_channel_layout_from_mask() or av_channel_layout_from_string(). + * + * The channel layout must be unitialized with av_channel_layout_uninit() + * + * Copying an AVChannelLayout via assigning is forbidden, + * av_channel_layout_copy() must be used instead (and its return value should + * be checked) + * + * No new fields may be added to it without a major version bump, except for + * new elements of the union fitting in sizeof(uint64_t). + */ +typedef struct AVChannelLayout { + /** + * Channel order used in this layout. + * This is a mandatory field. + */ + enum AVChannelOrder order; + + /** + * Number of channels in this layout. Mandatory field. + */ + int nb_channels; + + /** + * Details about which channels are present in this layout. + * For AV_CHANNEL_ORDER_UNSPEC, this field is undefined and must not be + * used. + */ + union { + /** + * This member must be used for AV_CHANNEL_ORDER_NATIVE, and may be used + * for AV_CHANNEL_ORDER_AMBISONIC to signal non-diegetic channels. + * It is a bitmask, where the position of each set bit means that the + * AVChannel with the corresponding value is present. + * + * I.e. when (mask & (1 << AV_CHAN_FOO)) is non-zero, then AV_CHAN_FOO + * is present in the layout. Otherwise it is not present. + * + * @note when a channel layout using a bitmask is constructed or + * modified manually (i.e. not using any of the av_channel_layout_* + * functions), the code doing it must ensure that the number of set bits + * is equal to nb_channels. + */ + uint64_t mask; + /** + * This member must be used when the channel order is + * AV_CHANNEL_ORDER_CUSTOM. It is a nb_channels-sized array, with each + * element signalling the presence of the AVChannel with the + * corresponding value in map[i].id. + * + * I.e. when map[i].id is equal to AV_CHAN_FOO, then AV_CH_FOO is the + * i-th channel in the audio data. + * + * When map[i].id is in the range between AV_CHAN_AMBISONIC_BASE and + * AV_CHAN_AMBISONIC_END (inclusive), the channel contains an ambisonic + * component with ACN index (as defined above) + * n = map[i].id - AV_CHAN_AMBISONIC_BASE. + * + * map[i].name may be filled with a 0-terminated string, in which case + * it will be used for the purpose of identifying the channel with the + * convenience functions below. Otherise it must be zeroed. + */ + AVChannelCustom *map; + } u; + + /** + * For some private data of the user. + */ + void *opaque; +} AVChannelLayout; + +#define AV_CHANNEL_LAYOUT_MASK(nb, m) \ + { .order = AV_CHANNEL_ORDER_NATIVE, .nb_channels = (nb), .u = { .mask = (m) }} + +#define AV_CHANNEL_LAYOUT_MONO AV_CHANNEL_LAYOUT_MASK(1, AV_CH_LAYOUT_MONO) +#define AV_CHANNEL_LAYOUT_STEREO AV_CHANNEL_LAYOUT_MASK(2, AV_CH_LAYOUT_STEREO) +#define AV_CHANNEL_LAYOUT_2POINT1 AV_CHANNEL_LAYOUT_MASK(3, AV_CH_LAYOUT_2POINT1) +#define AV_CHANNEL_LAYOUT_2_1 AV_CHANNEL_LAYOUT_MASK(3, AV_CH_LAYOUT_2_1) +#define AV_CHANNEL_LAYOUT_SURROUND AV_CHANNEL_LAYOUT_MASK(3, AV_CH_LAYOUT_SURROUND) +#define AV_CHANNEL_LAYOUT_3POINT1 AV_CHANNEL_LAYOUT_MASK(4, AV_CH_LAYOUT_3POINT1) +#define AV_CHANNEL_LAYOUT_4POINT0 AV_CHANNEL_LAYOUT_MASK(4, AV_CH_LAYOUT_4POINT0) +#define AV_CHANNEL_LAYOUT_4POINT1 AV_CHANNEL_LAYOUT_MASK(5, AV_CH_LAYOUT_4POINT1) +#define AV_CHANNEL_LAYOUT_2_2 AV_CHANNEL_LAYOUT_MASK(4, AV_CH_LAYOUT_2_2) +#define AV_CHANNEL_LAYOUT_QUAD AV_CHANNEL_LAYOUT_MASK(4, AV_CH_LAYOUT_QUAD) +#define AV_CHANNEL_LAYOUT_5POINT0 AV_CHANNEL_LAYOUT_MASK(5, AV_CH_LAYOUT_5POINT0) +#define AV_CHANNEL_LAYOUT_5POINT1 AV_CHANNEL_LAYOUT_MASK(6, AV_CH_LAYOUT_5POINT1) +#define AV_CHANNEL_LAYOUT_5POINT0_BACK AV_CHANNEL_LAYOUT_MASK(5, AV_CH_LAYOUT_5POINT0_BACK) +#define AV_CHANNEL_LAYOUT_5POINT1_BACK AV_CHANNEL_LAYOUT_MASK(6, AV_CH_LAYOUT_5POINT1_BACK) +#define AV_CHANNEL_LAYOUT_6POINT0 AV_CHANNEL_LAYOUT_MASK(6, AV_CH_LAYOUT_6POINT0) +#define AV_CHANNEL_LAYOUT_6POINT0_FRONT AV_CHANNEL_LAYOUT_MASK(6, AV_CH_LAYOUT_6POINT0_FRONT) +#define AV_CHANNEL_LAYOUT_HEXAGONAL AV_CHANNEL_LAYOUT_MASK(6, AV_CH_LAYOUT_HEXAGONAL) +#define AV_CHANNEL_LAYOUT_6POINT1 AV_CHANNEL_LAYOUT_MASK(7, AV_CH_LAYOUT_6POINT1) +#define AV_CHANNEL_LAYOUT_6POINT1_BACK AV_CHANNEL_LAYOUT_MASK(7, AV_CH_LAYOUT_6POINT1_BACK) +#define AV_CHANNEL_LAYOUT_6POINT1_FRONT AV_CHANNEL_LAYOUT_MASK(7, AV_CH_LAYOUT_6POINT1_FRONT) +#define AV_CHANNEL_LAYOUT_7POINT0 AV_CHANNEL_LAYOUT_MASK(7, AV_CH_LAYOUT_7POINT0) +#define AV_CHANNEL_LAYOUT_7POINT0_FRONT AV_CHANNEL_LAYOUT_MASK(7, AV_CH_LAYOUT_7POINT0_FRONT) +#define AV_CHANNEL_LAYOUT_7POINT1 AV_CHANNEL_LAYOUT_MASK(8, AV_CH_LAYOUT_7POINT1) +#define AV_CHANNEL_LAYOUT_7POINT1_WIDE AV_CHANNEL_LAYOUT_MASK(8, AV_CH_LAYOUT_7POINT1_WIDE) +#define AV_CHANNEL_LAYOUT_7POINT1_WIDE_BACK AV_CHANNEL_LAYOUT_MASK(8, AV_CH_LAYOUT_7POINT1_WIDE_BACK) +#define AV_CHANNEL_LAYOUT_OCTAGONAL AV_CHANNEL_LAYOUT_MASK(8, AV_CH_LAYOUT_OCTAGONAL) +#define AV_CHANNEL_LAYOUT_HEXADECAGONAL AV_CHANNEL_LAYOUT_MASK(16, AV_CH_LAYOUT_HEXADECAGONAL) +#define AV_CHANNEL_LAYOUT_STEREO_DOWNMIX AV_CHANNEL_LAYOUT_MASK(2, AV_CH_LAYOUT_STEREO_DOWNMIX) +#define AV_CHANNEL_LAYOUT_22POINT2 AV_CHANNEL_LAYOUT_MASK(24, AV_CH_LAYOUT_22POINT2) +#define AV_CHANNEL_LAYOUT_AMBISONIC_FIRST_ORDER \ + { .order = AV_CHANNEL_ORDER_AMBISONIC, .nb_channels = 4, .u = { .mask = 0 }} + +struct AVBPrint; + +#if FF_API_OLD_CHANNEL_LAYOUT /** * Return a channel layout id that matches name, or 0 if no match is found. * @@ -144,7 +401,10 @@ enum AVMatrixEncoding { * AV_CH_* macros). * * Example: "stereo+FC" = "2c+FC" = "2c+1c" = "0x7" + * + * @deprecated use av_channel_layout_from_string() */ +attribute_deprecated uint64_t av_get_channel_layout(const char *name); /** @@ -158,7 +418,9 @@ uint64_t av_get_channel_layout(const char *name); * @param[out] nb_channels number of channels * * @return 0 on success, AVERROR(EINVAL) if the parsing fails. + * @deprecated use av_channel_layout_from_string() */ +attribute_deprecated int av_get_extended_channel_layout(const char *name, uint64_t* channel_layout, int* nb_channels); /** @@ -167,23 +429,31 @@ int av_get_extended_channel_layout(const char *name, uint64_t* channel_layout, i * * @param buf put here the string containing the channel layout * @param buf_size size in bytes of the buffer + * @deprecated use av_channel_layout_describe() */ +attribute_deprecated void av_get_channel_layout_string(char *buf, int buf_size, int nb_channels, uint64_t channel_layout); -struct AVBPrint; /** * Append a description of a channel layout to a bprint buffer. + * @deprecated use av_channel_layout_describe() */ +attribute_deprecated void av_bprint_channel_layout(struct AVBPrint *bp, int nb_channels, uint64_t channel_layout); /** * Return the number of channels in the channel layout. + * @deprecated use AVChannelLayout.nb_channels */ +attribute_deprecated int av_get_channel_layout_nb_channels(uint64_t channel_layout); /** * Return default channel layout for a given number of channels. + * + * @deprecated use av_channel_layout_default() */ +attribute_deprecated int64_t av_get_default_channel_layout(int nb_channels); /** @@ -194,20 +464,28 @@ int64_t av_get_default_channel_layout(int nb_channels); * * @return index of channel in channel_layout on success, a negative AVERROR * on error. + * + * @deprecated use av_channel_layout_index_from_channel() */ +attribute_deprecated int av_get_channel_layout_channel_index(uint64_t channel_layout, uint64_t channel); /** * Get the channel with the given index in channel_layout. + * @deprecated use av_channel_layout_channel_from_index() */ +attribute_deprecated uint64_t av_channel_layout_extract_channel(uint64_t channel_layout, int index); /** * Get the name of a given channel. * * @return channel name on success, NULL on error. + * + * @deprecated use av_channel_name() */ +attribute_deprecated const char *av_get_channel_name(uint64_t channel); /** @@ -215,7 +493,9 @@ const char *av_get_channel_name(uint64_t channel); * * @param channel a channel layout with a single channel * @return channel description on success, NULL on error + * @deprecated use av_channel_description() */ +attribute_deprecated const char *av_get_channel_description(uint64_t channel); /** @@ -226,9 +506,240 @@ const char *av_get_channel_description(uint64_t channel); * @param[out] name name of the layout * @return 0 if the layout exists, * <0 if index is beyond the limits + * @deprecated use av_channel_layout_standard() */ +attribute_deprecated int av_get_standard_channel_layout(unsigned index, uint64_t *layout, const char **name); +#endif + +/** + * Get a human readable string in an abbreviated form describing a given channel. + * This is the inverse function of @ref av_channel_from_string(). + * + * @param buf pre-allocated buffer where to put the generated string + * @param buf_size size in bytes of the buffer. + * @return amount of bytes needed to hold the output string, or a negative AVERROR + * on failure. If the returned value is bigger than buf_size, then the + * string was truncated. + */ +int av_channel_name(char *buf, size_t buf_size, enum AVChannel channel); + +/** + * bprint variant of av_channel_name(). + * + * @note the string will be appended to the bprint buffer. + */ +void av_channel_name_bprint(struct AVBPrint *bp, enum AVChannel channel_id); + +/** + * Get a human readable string describing a given channel. + * + * @param buf pre-allocated buffer where to put the generated string + * @param buf_size size in bytes of the buffer. + * @return amount of bytes needed to hold the output string, or a negative AVERROR + * on failure. If the returned value is bigger than buf_size, then the + * string was truncated. + */ +int av_channel_description(char *buf, size_t buf_size, enum AVChannel channel); + +/** + * bprint variant of av_channel_description(). + * + * @note the string will be appended to the bprint buffer. + */ +void av_channel_description_bprint(struct AVBPrint *bp, enum AVChannel channel_id); + +/** + * This is the inverse function of @ref av_channel_name(). + * + * @return the channel with the given name + * AV_CHAN_NONE when name does not identify a known channel + */ +enum AVChannel av_channel_from_string(const char *name); + +/** + * Initialize a native channel layout from a bitmask indicating which channels + * are present. + * + * @param channel_layout the layout structure to be initialized + * @param mask bitmask describing the channel layout + * + * @return 0 on success + * AVERROR(EINVAL) for invalid mask values + */ +int av_channel_layout_from_mask(AVChannelLayout *channel_layout, uint64_t mask); + +/** + * Initialize a channel layout from a given string description. + * The input string can be represented by: + * - the formal channel layout name (returned by av_channel_layout_describe()) + * - single or multiple channel names (returned by av_channel_name(), eg. "FL", + * or concatenated with "+", each optionally containing a custom name after + * a "@", eg. "FL@Left+FR@Right+LFE") + * - a decimal or hexadecimal value of a native channel layout (eg. "4" or "0x4") + * - the number of channels with default layout (eg. "4c") + * - the number of unordered channels (eg. "4C" or "4 channels") + * - the ambisonic order followed by optional non-diegetic channels (eg. + * "ambisonic 2+stereo") + * + * @param channel_layout input channel layout + * @param str string describing the channel layout + * @return 0 channel layout was detected, AVERROR_INVALIDATATA otherwise + */ +int av_channel_layout_from_string(AVChannelLayout *channel_layout, + const char *str); + +/** + * Get the default channel layout for a given number of channels. + * + * @param channel_layout the layout structure to be initialized + * @param nb_channels number of channels + */ +void av_channel_layout_default(AVChannelLayout *ch_layout, int nb_channels); + +/** + * Iterate over all standard channel layouts. + * + * @param opaque a pointer where libavutil will store the iteration state. Must + * point to NULL to start the iteration. + * + * @return the standard channel layout or NULL when the iteration is + * finished + */ +const AVChannelLayout *av_channel_layout_standard(void **opaque); + +/** + * Free any allocated data in the channel layout and reset the channel + * count to 0. + * + * @param channel_layout the layout structure to be uninitialized + */ +void av_channel_layout_uninit(AVChannelLayout *channel_layout); + +/** + * Make a copy of a channel layout. This differs from just assigning src to dst + * in that it allocates and copies the map for AV_CHANNEL_ORDER_CUSTOM. + * + * @note the destination channel_layout will be always uninitialized before copy. + * + * @param dst destination channel layout + * @param src source channel layout + * @return 0 on success, a negative AVERROR on error. + */ +int av_channel_layout_copy(AVChannelLayout *dst, const AVChannelLayout *src); + +/** + * Get a human-readable string describing the channel layout properties. + * The string will be in the same format that is accepted by + * @ref av_channel_layout_from_string(), allowing to rebuild the same + * channel layout, except for opaque pointers. + * + * @param channel_layout channel layout to be described + * @param buf pre-allocated buffer where to put the generated string + * @param buf_size size in bytes of the buffer. + * @return amount of bytes needed to hold the output string, or a negative AVERROR + * on failure. If the returned value is bigger than buf_size, then the + * string was truncated. + */ +int av_channel_layout_describe(const AVChannelLayout *channel_layout, + char *buf, size_t buf_size); + +/** + * bprint variant of av_channel_layout_describe(). + * + * @note the string will be appended to the bprint buffer. + * @return 0 on success, or a negative AVERROR value on failure. + */ +int av_channel_layout_describe_bprint(const AVChannelLayout *channel_layout, + struct AVBPrint *bp); + +/** + * Get the channel with the given index in a channel layout. + * + * @param channel_layout input channel layout + * @return channel with the index idx in channel_layout on success or + * AV_CHAN_NONE on failure (if idx is not valid or the channel order is + * unspecified) + */ +enum AVChannel +av_channel_layout_channel_from_index(const AVChannelLayout *channel_layout, unsigned int idx); + +/** + * Get the index of a given channel in a channel layout. In case multiple + * channels are found, only the first match will be returned. + * + * @param channel_layout input channel layout + * @return index of channel in channel_layout on success or a negative number if + * channel is not present in channel_layout. + */ +int av_channel_layout_index_from_channel(const AVChannelLayout *channel_layout, + enum AVChannel channel); + +/** + * Get the index in a channel layout of a channel described by the given string. + * In case multiple channels are found, only the first match will be returned. + * + * This function accepts channel names in the same format as + * @ref av_channel_from_string(). + * + * @param channel_layout input channel layout + * @return a channel index described by the given string, or a negative AVERROR + * value. + */ +int av_channel_layout_index_from_string(const AVChannelLayout *channel_layout, + const char *name); + +/** + * Get a channel described by the given string. + * + * This function accepts channel names in the same format as + * @ref av_channel_from_string(). + * + * @param channel_layout input channel layout + * @return a channel described by the given string in channel_layout on success + * or AV_CHAN_NONE on failure (if the string is not valid or the channel + * order is unspecified) + */ +enum AVChannel +av_channel_layout_channel_from_string(const AVChannelLayout *channel_layout, + const char *name); + +/** + * Find out what channels from a given set are present in a channel layout, + * without regard for their positions. + * + * @param channel_layout input channel layout + * @param mask a combination of AV_CH_* representing a set of channels + * @return a bitfield representing all the channels from mask that are present + * in channel_layout + */ +uint64_t av_channel_layout_subset(const AVChannelLayout *channel_layout, + uint64_t mask); + +/** + * Check whether a channel layout is valid, i.e. can possibly describe audio + * data. + * + * @param channel_layout input channel layout + * @return 1 if channel_layout is valid, 0 otherwise. + */ +int av_channel_layout_check(const AVChannelLayout *channel_layout); + +/** + * Check whether two channel layouts are semantically the same, i.e. the same + * channels are present on the same positions in both. + * + * If one of the channel layouts is AV_CHANNEL_ORDER_UNSPEC, while the other is + * not, they are considered to be unequal. If both are AV_CHANNEL_ORDER_UNSPEC, + * they are considered equal iff the channel counts are the same in both. + * + * @param chl input channel layout + * @param chl1 input channel layout + * @return 0 if chl and chl1 are equal, 1 if they are not equal. A negative + * AVERROR code if one or both are invalid. + */ +int av_channel_layout_compare(const AVChannelLayout *chl, const AVChannelLayout *chl1); /** * @} diff --git a/libavutil/color_utils.c b/libavutil/color_utils.c index eb8bc7b5f..5e221fb79 100644 --- a/libavutil/color_utils.c +++ b/libavutil/color_utils.c @@ -21,7 +21,6 @@ #include #include -#include "common.h" #include "libavutil/color_utils.h" #include "libavutil/pixfmt.h" diff --git a/libavutil/common.h b/libavutil/common.h index 3eb9bc5f7..fd1404be6 100644 --- a/libavutil/common.h +++ b/libavutil/common.h @@ -41,7 +41,6 @@ #include "attributes.h" #include "macros.h" -#include "version.h" //rounded division & shift #define RSHIFT(a,b) ((a) > 0 ? ((a) + ((1<<(b))>>1))>>(b) : ((a) + ((1<<(b))>>1)-1)>>(b)) diff --git a/libavutil/cpu.c b/libavutil/cpu.c index 136850224..0035e927a 100644 --- a/libavutil/cpu.c +++ b/libavutil/cpu.c @@ -16,16 +16,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include -#include -#include - -#include "attributes.h" -#include "cpu.h" -#include "cpu_internal.h" #include "config.h" -#include "opt.h" -#include "common.h" #if HAVE_SCHED_GETAFFINITY #ifndef _GNU_SOURCE @@ -33,6 +24,17 @@ #endif #include #endif + +#include +#include +#include + +#include "attributes.h" +#include "cpu.h" +#include "cpu_internal.h" +#include "opt.h" +#include "common.h" + #if HAVE_GETPROCESSAFFINITYMASK || HAVE_WINRT #include #endif @@ -52,18 +54,19 @@ static atomic_int cpu_count = ATOMIC_VAR_INIT(-1); static int get_cpu_flags(void) { - if (ARCH_MIPS) - return ff_get_cpu_flags_mips(); - if (ARCH_AARCH64) - return ff_get_cpu_flags_aarch64(); - if (ARCH_ARM) - return ff_get_cpu_flags_arm(); - if (ARCH_PPC) - return ff_get_cpu_flags_ppc(); - if (ARCH_X86) - return ff_get_cpu_flags_x86(); - if (ARCH_LOONGARCH) - return ff_get_cpu_flags_loongarch(); +#if ARCH_MIPS + return ff_get_cpu_flags_mips(); +#elif ARCH_AARCH64 + return ff_get_cpu_flags_aarch64(); +#elif ARCH_ARM + return ff_get_cpu_flags_arm(); +#elif ARCH_PPC + return ff_get_cpu_flags_ppc(); +#elif ARCH_X86 + return ff_get_cpu_flags_x86(); +#elif ARCH_LOONGARCH + return ff_get_cpu_flags_loongarch(); +#endif return 0; } @@ -137,6 +140,7 @@ int av_parse_cpu_caps(unsigned *flags, const char *s) { "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" }, + { "avx512icl", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_AVX512ICL }, .unit = "flags" }, { "slowgather", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_SLOW_GATHER }, .unit = "flags" }, #define CPU_FLAG_P2 AV_CPU_FLAG_CMOV | AV_CPU_FLAG_MMX @@ -249,18 +253,19 @@ void av_cpu_force_count(int count) size_t av_cpu_max_align(void) { - if (ARCH_MIPS) - return ff_get_cpu_max_align_mips(); - 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(); - if (ARCH_LOONGARCH) - return ff_get_cpu_max_align_loongarch(); +#if ARCH_MIPS + return ff_get_cpu_max_align_mips(); +#elif ARCH_AARCH64 + return ff_get_cpu_max_align_aarch64(); +#elif ARCH_ARM + return ff_get_cpu_max_align_arm(); +#elif ARCH_PPC + return ff_get_cpu_max_align_ppc(); +#elif ARCH_X86 + return ff_get_cpu_max_align_x86(); +#elif ARCH_LOONGARCH + return ff_get_cpu_max_align_loongarch(); +#endif return 8; } diff --git a/libavutil/cpu.h b/libavutil/cpu.h index ce9bf14bf..9711e574c 100644 --- a/libavutil/cpu.h +++ b/libavutil/cpu.h @@ -54,6 +54,7 @@ #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_AVX512ICL 0x200000 ///< F/CD/BW/DQ/VL/VNNI/IFMA/VBMI/VBMI2/VPOPCNTDQ/BITALG/GFNI/VAES/VPCLMULQDQ #define AV_CPU_FLAG_SLOW_GATHER 0x2000000 ///< CPU has slow gathers. #define AV_CPU_FLAG_ALTIVEC 0x0001 ///< standard diff --git a/libavutil/cpu_internal.h b/libavutil/cpu_internal.h index e207b2d48..650d47fc9 100644 --- a/libavutil/cpu_internal.h +++ b/libavutil/cpu_internal.h @@ -30,12 +30,15 @@ (HAVE_ ## cpuext ## suffix && ((flags) & AV_CPU_FLAG_ ## cpuext) && \ !((flags) & AV_CPU_FLAG_ ## slow_cpuext ## SLOW)) +#define CPUEXT_SUFFIX_SLOW(flags, suffix, cpuext) \ + (HAVE_ ## cpuext ## suffix && \ + ((flags) & (AV_CPU_FLAG_ ## cpuext | AV_CPU_FLAG_ ## cpuext ## SLOW))) + #define CPUEXT_SUFFIX_SLOW2(flags, suffix, cpuext, slow_cpuext) \ (HAVE_ ## cpuext ## suffix && ((flags) & AV_CPU_FLAG_ ## cpuext) && \ - ((flags) & AV_CPU_FLAG_ ## slow_cpuext ## SLOW)) + ((flags) & (AV_CPU_FLAG_ ## slow_cpuext | AV_CPU_FLAG_ ## slow_cpuext ## SLOW))) #define CPUEXT_SUFFIX_FAST(flags, suffix, cpuext) CPUEXT_SUFFIX_FAST2(flags, suffix, cpuext, cpuext) -#define CPUEXT_SUFFIX_SLOW(flags, suffix, cpuext) CPUEXT_SUFFIX_SLOW2(flags, suffix, cpuext, cpuext) #define CPUEXT(flags, cpuext) CPUEXT_SUFFIX(flags, , cpuext) #define CPUEXT_FAST(flags, cpuext) CPUEXT_SUFFIX_FAST(flags, , cpuext) diff --git a/libavutil/crc.c b/libavutil/crc.c index c45ea63a6..703b56f4e 100644 --- a/libavutil/crc.c +++ b/libavutil/crc.c @@ -23,8 +23,8 @@ #include "thread.h" #include "avassert.h" #include "bswap.h" -#include "common.h" #include "crc.h" +#include "error.h" #if CONFIG_HARDCODED_TABLES static const AVCRC av_crc_table[AV_CRC_MAX][257] = { diff --git a/libavutil/csp.c b/libavutil/csp.c new file mode 100644 index 000000000..98fc83c1d --- /dev/null +++ b/libavutil/csp.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2016 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 + */ + +/** + * @file Colorspace functions for libavutil + * @author Ronald S. Bultje + * @author Leo Izen + */ + +#include + +#include "attributes.h" +#include "csp.h" +#include "pixfmt.h" +#include "rational.h" + +#define AVR(d) { (int)(d * 100000 + 0.5), 100000 } + +/* + * All constants explained in e.g. https://linuxtv.org/downloads/v4l-dvb-apis/ch02s06.html + * The older ones (bt470bg/m) are also explained in their respective ITU docs + * (e.g. https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.470-5-199802-S!!PDF-E.pdf) + * whereas the newer ones can typically be copied directly from wikipedia :) + */ +static const struct AVLumaCoefficients luma_coefficients[AVCOL_SPC_NB] = { + [AVCOL_SPC_FCC] = { AVR(0.30), AVR(0.59), AVR(0.11) }, + [AVCOL_SPC_BT470BG] = { AVR(0.299), AVR(0.587), AVR(0.114) }, + [AVCOL_SPC_SMPTE170M] = { AVR(0.299), AVR(0.587), AVR(0.114) }, + [AVCOL_SPC_BT709] = { AVR(0.2126), AVR(0.7152), AVR(0.0722) }, + [AVCOL_SPC_SMPTE240M] = { AVR(0.212), AVR(0.701), AVR(0.087) }, + [AVCOL_SPC_YCOCG] = { AVR(0.25), AVR(0.5), AVR(0.25) }, + [AVCOL_SPC_RGB] = { AVR(1), AVR(1), AVR(1) }, + [AVCOL_SPC_BT2020_NCL] = { AVR(0.2627), AVR(0.6780), AVR(0.0593) }, + [AVCOL_SPC_BT2020_CL] = { AVR(0.2627), AVR(0.6780), AVR(0.0593) }, +}; + +const struct AVLumaCoefficients *av_csp_luma_coeffs_from_avcsp(enum AVColorSpace csp) +{ + const AVLumaCoefficients *coeffs; + + if (csp >= AVCOL_SPC_NB) + return NULL; + coeffs = &luma_coefficients[csp]; + if (!coeffs->cr.num) + return NULL; + + return coeffs; +} + +#define WP_D65 { AVR(0.3127), AVR(0.3290) } +#define WP_C { AVR(0.3100), AVR(0.3160) } +#define WP_DCI { AVR(0.3140), AVR(0.3510) } +#define WP_E { {1, 3}, {1, 3} } + +static const AVColorPrimariesDesc color_primaries[AVCOL_PRI_NB] = { + [AVCOL_PRI_BT709] = { WP_D65, { { AVR(0.640), AVR(0.330) }, { AVR(0.300), AVR(0.600) }, { AVR(0.150), AVR(0.060) } } }, + [AVCOL_PRI_BT470M] = { WP_C, { { AVR(0.670), AVR(0.330) }, { AVR(0.210), AVR(0.710) }, { AVR(0.140), AVR(0.080) } } }, + [AVCOL_PRI_BT470BG] = { WP_D65, { { AVR(0.640), AVR(0.330) }, { AVR(0.290), AVR(0.600) }, { AVR(0.150), AVR(0.060) } } }, + [AVCOL_PRI_SMPTE170M] = { WP_D65, { { AVR(0.630), AVR(0.340) }, { AVR(0.310), AVR(0.595) }, { AVR(0.155), AVR(0.070) } } }, + [AVCOL_PRI_SMPTE240M] = { WP_D65, { { AVR(0.630), AVR(0.340) }, { AVR(0.310), AVR(0.595) }, { AVR(0.155), AVR(0.070) } } }, + [AVCOL_PRI_SMPTE428] = { WP_E, { { AVR(0.735), AVR(0.265) }, { AVR(0.274), AVR(0.718) }, { AVR(0.167), AVR(0.009) } } }, + [AVCOL_PRI_SMPTE431] = { WP_DCI, { { AVR(0.680), AVR(0.320) }, { AVR(0.265), AVR(0.690) }, { AVR(0.150), AVR(0.060) } } }, + [AVCOL_PRI_SMPTE432] = { WP_D65, { { AVR(0.680), AVR(0.320) }, { AVR(0.265), AVR(0.690) }, { AVR(0.150), AVR(0.060) } } }, + [AVCOL_PRI_FILM] = { WP_C, { { AVR(0.681), AVR(0.319) }, { AVR(0.243), AVR(0.692) }, { AVR(0.145), AVR(0.049) } } }, + [AVCOL_PRI_BT2020] = { WP_D65, { { AVR(0.708), AVR(0.292) }, { AVR(0.170), AVR(0.797) }, { AVR(0.131), AVR(0.046) } } }, + [AVCOL_PRI_JEDEC_P22] = { WP_D65, { { AVR(0.630), AVR(0.340) }, { AVR(0.295), AVR(0.605) }, { AVR(0.155), AVR(0.077) } } }, +}; + +const AVColorPrimariesDesc *av_csp_primaries_desc_from_id(enum AVColorPrimaries prm) +{ + const AVColorPrimariesDesc *p; + + if (prm >= AVCOL_PRI_NB) + return NULL; + p = &color_primaries[prm]; + if (!p->prim.r.x.num) + return NULL; + + return p; +} + +static av_always_inline AVRational abs_sub_q(AVRational r1, AVRational r2) +{ + AVRational diff = av_sub_q(r1, r2); + /* denominator assumed to be positive */ + return av_make_q(abs(diff.num), diff.den); +} + +enum AVColorPrimaries av_csp_primaries_id_from_desc(const AVColorPrimariesDesc *prm) +{ + AVRational delta; + + for (enum AVColorPrimaries p = 0; p < AVCOL_PRI_NB; p++) { + const AVColorPrimariesDesc *ref = &color_primaries[p]; + if (!ref->prim.r.x.num) + continue; + + delta = abs_sub_q(prm->prim.r.x, ref->prim.r.x); + delta = av_add_q(delta, abs_sub_q(prm->prim.r.y, ref->prim.r.y)); + delta = av_add_q(delta, abs_sub_q(prm->prim.g.x, ref->prim.g.x)); + delta = av_add_q(delta, abs_sub_q(prm->prim.g.y, ref->prim.g.y)); + delta = av_add_q(delta, abs_sub_q(prm->prim.b.x, ref->prim.b.x)); + delta = av_add_q(delta, abs_sub_q(prm->prim.b.y, ref->prim.b.y)); + delta = av_add_q(delta, abs_sub_q(prm->wp.x, ref->wp.x)); + delta = av_add_q(delta, abs_sub_q(prm->wp.y, ref->wp.y)); + + if (av_cmp_q(delta, av_make_q(1, 1000)) < 0) + return p; + } + + return AVCOL_PRI_UNSPECIFIED; +} diff --git a/libavutil/csp.h b/libavutil/csp.h new file mode 100644 index 000000000..37544449c --- /dev/null +++ b/libavutil/csp.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2016 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_CSP_H +#define AVUTIL_CSP_H + +#include "pixfmt.h" +#include "rational.h" + +/** + * @file Colorspace value utility functions for libavutil. + * @author Ronald S. Bultje + * @author Leo Izen + * @defgroup lavu_math_csp Colorspace Utility + * @ingroup lavu_math + * @{ + */ + +/** + * Struct containing luma coefficients to be used for RGB to YUV/YCoCg, or similar + * calculations. + */ +typedef struct AVLumaCoefficients { + AVRational cr, cg, cb; +} AVLumaCoefficients; + +/** + * Struct containing chromaticity x and y values for the standard CIE 1931 + * chromaticity definition. + */ +typedef struct AVCIExy { + AVRational x, y; +} AVCIExy; + +/** + * Struct defining the red, green, and blue primary locations in terms of CIE + * 1931 chromaticity x and y. + */ +typedef struct AVPrimaryCoefficients { + AVCIExy r, g, b; +} AVPrimaryCoefficients; + +/** + * Struct defining white point location in terms of CIE 1931 chromaticity x + * and y. + */ +typedef AVCIExy AVWhitepointCoefficients; + +/** + * Struct that contains both white point location and primaries location, providing + * the complete description of a color gamut. + */ +typedef struct AVColorPrimariesDesc { + AVWhitepointCoefficients wp; + AVPrimaryCoefficients prim; +} AVColorPrimariesDesc; + +/** + * Retrieves the Luma coefficients necessary to construct a conversion matrix + * from an enum constant describing the colorspace. + * @param csp An enum constant indicating YUV or similar colorspace. + * @return The Luma coefficients associated with that colorspace, or NULL + * if the constant is unknown to libavutil. + */ +const AVLumaCoefficients *av_csp_luma_coeffs_from_avcsp(enum AVColorSpace csp); + +/** + * Retrieves a complete gamut description from an enum constant describing the + * color primaries. + * @param prm An enum constant indicating primaries + * @return A description of the colorspace gamut associated with that enum + * constant, or NULL if the constant is unknown to libavutil. + */ +const AVColorPrimariesDesc *av_csp_primaries_desc_from_id(enum AVColorPrimaries prm); + +/** + * Detects which enum AVColorPrimaries constant corresponds to the given complete + * gamut description. + * @see enum AVColorPrimaries + * @param prm A description of the colorspace gamut + * @return The enum constant associated with this gamut, or + * AVCOL_PRI_UNSPECIFIED if no clear match can be idenitified. + */ +enum AVColorPrimaries av_csp_primaries_id_from_desc(const AVColorPrimariesDesc *prm); + +/** + * @} + */ + +#endif /* AVUTIL_CSP_H */ diff --git a/libavutil/cuda_check.h b/libavutil/cuda_check.h index 3aea085c0..f5a9234ea 100644 --- a/libavutil/cuda_check.h +++ b/libavutil/cuda_check.h @@ -21,6 +21,7 @@ #define AVUTIL_CUDA_CHECK_H #include "compat/cuda/dynlink_loader.h" +#include "error.h" typedef CUresult CUDAAPI cuda_check_GetErrorName(CUresult error, const char** pstr); typedef CUresult CUDAAPI cuda_check_GetErrorString(CUresult error, const char** pstr); diff --git a/libavutil/des.c b/libavutil/des.c index 695766618..e0e9a8666 100644 --- a/libavutil/des.c +++ b/libavutil/des.c @@ -19,10 +19,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config.h" + #include -#include "avutil.h" -#include "common.h" +#include "attributes.h" +#include "error.h" #include "intreadwrite.h" #include "mem.h" #include "des.h" diff --git a/libavutil/display.c b/libavutil/display.c index a0076e067..d31061283 100644 --- a/libavutil/display.c +++ b/libavutil/display.c @@ -23,6 +23,7 @@ #include #include "display.h" +#include "libm.h" #include "mathematics.h" // fixed point to double diff --git a/libavutil/display.h b/libavutil/display.h index d87bf6842..31d8bef36 100644 --- a/libavutil/display.h +++ b/libavutil/display.h @@ -27,7 +27,6 @@ #define AVUTIL_DISPLAY_H #include -#include "common.h" /** * @addtogroup lavu_video diff --git a/libavutil/error.c b/libavutil/error.c index b96304837..938a8bc00 100644 --- a/libavutil/error.c +++ b/libavutil/error.c @@ -18,9 +18,12 @@ #undef _GNU_SOURCE #define _XOPEN_SOURCE 600 /* XSI-compliant version of strerror_r */ -#include "avutil.h" +#include +#include +#include "config.h" #include "avstring.h" -#include "common.h" +#include "error.h" +#include "macros.h" struct error_entry { int num; diff --git a/libavutil/eval.h b/libavutil/eval.h index 068c62cda..57afc2d56 100644 --- a/libavutil/eval.h +++ b/libavutil/eval.h @@ -26,8 +26,6 @@ #ifndef AVUTIL_EVAL_H #define AVUTIL_EVAL_H -#include "avutil.h" - typedef struct AVExpr AVExpr; /** diff --git a/libavutil/fifo.c b/libavutil/fifo.c index 1060aedf1..51a5af6f3 100644 --- a/libavutil/fifo.c +++ b/libavutil/fifo.c @@ -20,13 +20,291 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "avassert.h" -#include "common.h" -#include "fifo.h" +#include +#include -static AVFifoBuffer *fifo_alloc_common(void *buffer, size_t size) +#include "avassert.h" +#include "error.h" +#include "fifo.h" +#include "macros.h" +#include "mem.h" + +// by default the FIFO can be auto-grown to 1MB +#define AUTO_GROW_DEFAULT_BYTES (1024 * 1024) + +struct AVFifo { + uint8_t *buffer; + + size_t elem_size, nb_elems; + size_t offset_r, offset_w; + // distinguishes the ambiguous situation offset_r == offset_w + int is_empty; + + unsigned int flags; + size_t auto_grow_limit; +}; + +AVFifo *av_fifo_alloc2(size_t nb_elems, size_t elem_size, + unsigned int flags) +{ + AVFifo *f; + void *buffer = NULL; + + if (!elem_size) + return NULL; + + if (nb_elems) { + buffer = av_realloc_array(NULL, nb_elems, elem_size); + if (!buffer) + return NULL; + } + f = av_mallocz(sizeof(*f)); + if (!f) { + av_free(buffer); + return NULL; + } + f->buffer = buffer; + f->nb_elems = nb_elems; + f->elem_size = elem_size; + f->is_empty = 1; + + f->flags = flags; + f->auto_grow_limit = FFMAX(AUTO_GROW_DEFAULT_BYTES / elem_size, 1); + + return f; +} + +void av_fifo_auto_grow_limit(AVFifo *f, size_t max_elems) +{ + f->auto_grow_limit = max_elems; +} + +size_t av_fifo_elem_size(const AVFifo *f) +{ + return f->elem_size; +} + +size_t av_fifo_can_read(const AVFifo *f) +{ + if (f->offset_w <= f->offset_r && !f->is_empty) + return f->nb_elems - f->offset_r + f->offset_w; + return f->offset_w - f->offset_r; +} + +size_t av_fifo_can_write(const AVFifo *f) +{ + return f->nb_elems - av_fifo_can_read(f); +} + +int av_fifo_grow2(AVFifo *f, size_t inc) +{ + uint8_t *tmp; + + if (inc > SIZE_MAX - f->nb_elems) + return AVERROR(EINVAL); + + tmp = av_realloc_array(f->buffer, f->nb_elems + inc, f->elem_size); + if (!tmp) + return AVERROR(ENOMEM); + f->buffer = tmp; + + // move the data from the beginning of the ring buffer + // to the newly allocated space + if (f->offset_w <= f->offset_r && !f->is_empty) { + const size_t copy = FFMIN(inc, f->offset_w); + memcpy(tmp + f->nb_elems * f->elem_size, tmp, copy * f->elem_size); + if (copy < f->offset_w) { + memmove(tmp, tmp + copy * f->elem_size, + (f->offset_w - copy) * f->elem_size); + f->offset_w -= copy; + } else + f->offset_w = copy == inc ? 0 : f->nb_elems + copy; + } + + f->nb_elems += inc; + + return 0; +} + +static int fifo_check_space(AVFifo *f, size_t to_write) +{ + const size_t can_write = av_fifo_can_write(f); + const size_t need_grow = to_write > can_write ? to_write - can_write : 0; + size_t can_grow; + + if (!need_grow) + return 0; + + can_grow = f->auto_grow_limit > f->nb_elems ? + f->auto_grow_limit - f->nb_elems : 0; + if ((f->flags & AV_FIFO_FLAG_AUTO_GROW) && need_grow <= can_grow) { + // allocate a bit more than necessary, if we can + const size_t inc = (need_grow < can_grow / 2 ) ? need_grow * 2 : can_grow; + return av_fifo_grow2(f, inc); + } + + return AVERROR(ENOSPC); +} + +static int fifo_write_common(AVFifo *f, const uint8_t *buf, size_t *nb_elems, + AVFifoCB read_cb, void *opaque) +{ + size_t to_write = *nb_elems; + size_t offset_w; + int ret = 0; + + ret = fifo_check_space(f, to_write); + if (ret < 0) + return ret; + + offset_w = f->offset_w; + + while (to_write > 0) { + size_t len = FFMIN(f->nb_elems - offset_w, to_write); + uint8_t *wptr = f->buffer + offset_w * f->elem_size; + + if (read_cb) { + ret = read_cb(opaque, wptr, &len); + if (ret < 0 || len == 0) + break; + } else { + memcpy(wptr, buf, len * f->elem_size); + buf += len * f->elem_size; + } + offset_w += len; + if (offset_w >= f->nb_elems) + offset_w = 0; + to_write -= len; + } + f->offset_w = offset_w; + + if (*nb_elems != to_write) + f->is_empty = 0; + *nb_elems -= to_write; + + return ret; +} + +int av_fifo_write(AVFifo *f, const void *buf, size_t nb_elems) +{ + return fifo_write_common(f, buf, &nb_elems, NULL, NULL); +} + +int av_fifo_write_from_cb(AVFifo *f, AVFifoCB read_cb, + void *opaque, size_t *nb_elems) +{ + return fifo_write_common(f, NULL, nb_elems, read_cb, opaque); +} + +static int fifo_peek_common(const AVFifo *f, uint8_t *buf, size_t *nb_elems, + size_t offset, AVFifoCB write_cb, void *opaque) +{ + size_t to_read = *nb_elems; + size_t offset_r = f->offset_r; + size_t can_read = av_fifo_can_read(f); + int ret = 0; + + if (offset > can_read || to_read > can_read - offset) { + *nb_elems = 0; + return AVERROR(EINVAL); + } + + if (offset_r >= f->nb_elems - offset) + offset_r -= f->nb_elems - offset; + else + offset_r += offset; + + while (to_read > 0) { + size_t len = FFMIN(f->nb_elems - offset_r, to_read); + uint8_t *rptr = f->buffer + offset_r * f->elem_size; + + if (write_cb) { + ret = write_cb(opaque, rptr, &len); + if (ret < 0 || len == 0) + break; + } else { + memcpy(buf, rptr, len * f->elem_size); + buf += len * f->elem_size; + } + offset_r += len; + if (offset_r >= f->nb_elems) + offset_r = 0; + to_read -= len; + } + + *nb_elems -= to_read; + + return ret; +} + +int av_fifo_read(AVFifo *f, void *buf, size_t nb_elems) +{ + int ret = fifo_peek_common(f, buf, &nb_elems, 0, NULL, NULL); + av_fifo_drain2(f, nb_elems); + return ret; +} + +int av_fifo_read_to_cb(AVFifo *f, AVFifoCB write_cb, + void *opaque, size_t *nb_elems) +{ + int ret = fifo_peek_common(f, NULL, nb_elems, 0, write_cb, opaque); + av_fifo_drain2(f, *nb_elems); + return ret; +} + +int av_fifo_peek(AVFifo *f, void *buf, size_t nb_elems, size_t offset) +{ + return fifo_peek_common(f, buf, &nb_elems, offset, NULL, NULL); +} + +int av_fifo_peek_to_cb(AVFifo *f, AVFifoCB write_cb, void *opaque, + size_t *nb_elems, size_t offset) +{ + return fifo_peek_common(f, NULL, nb_elems, offset, write_cb, opaque); +} + +void av_fifo_drain2(AVFifo *f, size_t size) +{ + const size_t cur_size = av_fifo_can_read(f); + + av_assert0(cur_size >= size); + if (cur_size == size) + f->is_empty = 1; + + if (f->offset_r >= f->nb_elems - size) + f->offset_r -= f->nb_elems - size; + else + f->offset_r += size; +} + +void av_fifo_reset2(AVFifo *f) +{ + f->offset_r = f->offset_w = 0; + f->is_empty = 1; +} + +void av_fifo_freep2(AVFifo **f) +{ + if (*f) { + av_freep(&(*f)->buffer); + av_freep(f); + } +} + + +#if FF_API_FIFO_OLD_API +FF_DISABLE_DEPRECATION_WARNINGS +#define OLD_FIFO_SIZE_MAX (size_t)FFMIN3(INT_MAX, UINT32_MAX, SIZE_MAX) + +AVFifoBuffer *av_fifo_alloc_array(size_t nmemb, size_t size) { AVFifoBuffer *f; + void *buffer; + + if (nmemb > OLD_FIFO_SIZE_MAX / size) + return NULL; + + buffer = av_realloc_array(NULL, nmemb, size); if (!buffer) return NULL; f = av_mallocz(sizeof(AVFifoBuffer)); @@ -35,21 +313,14 @@ static AVFifoBuffer *fifo_alloc_common(void *buffer, size_t size) return NULL; } f->buffer = buffer; - f->end = f->buffer + size; + f->end = f->buffer + nmemb * size; av_fifo_reset(f); return f; } AVFifoBuffer *av_fifo_alloc(unsigned int size) { - void *buffer = av_malloc(size); - return fifo_alloc_common(buffer, size); -} - -AVFifoBuffer *av_fifo_alloc_array(size_t nmemb, size_t size) -{ - void *buffer = av_malloc_array(nmemb, size); - return fifo_alloc_common(buffer, nmemb * size); + return av_fifo_alloc_array(size, 1); } void av_fifo_free(AVFifoBuffer *f) @@ -88,18 +359,35 @@ int av_fifo_realloc2(AVFifoBuffer *f, unsigned int new_size) { unsigned int old_size = f->end - f->buffer; - if (old_size < new_size) { - int len = av_fifo_size(f); - AVFifoBuffer *f2 = av_fifo_alloc(new_size); + if (new_size > OLD_FIFO_SIZE_MAX) + return AVERROR(EINVAL); - if (!f2) + if (old_size < new_size) { + size_t offset_r = f->rptr - f->buffer; + size_t offset_w = f->wptr - f->buffer; + uint8_t *tmp; + + tmp = av_realloc(f->buffer, new_size); + if (!tmp) return AVERROR(ENOMEM); - av_fifo_generic_read(f, f2->buffer, len, NULL); - f2->wptr += len; - f2->wndx += len; - av_free(f->buffer); - *f = *f2; - av_free(f2); + + // move the data from the beginning of the ring buffer + // to the newly allocated space + // the second condition distinguishes full vs empty fifo + if (offset_w <= offset_r && av_fifo_size(f)) { + const size_t copy = FFMIN(new_size - old_size, offset_w); + memcpy(tmp + old_size, tmp, copy); + if (copy < offset_w) { + memmove(tmp, tmp + copy , offset_w - copy); + offset_w -= copy; + } else + offset_w = old_size + copy; + } + + f->buffer = tmp; + f->end = f->buffer + new_size; + f->rptr = f->buffer + offset_r; + f->wptr = f->buffer + offset_w; } return 0; } @@ -126,6 +414,9 @@ int av_fifo_generic_write(AVFifoBuffer *f, void *src, int size, uint32_t wndx= f->wndx; uint8_t *wptr= f->wptr; + if (size > av_fifo_space(f)) + return AVERROR(ENOSPC); + do { int len = FFMIN(f->end - wptr, size); if (func) { @@ -136,7 +427,6 @@ int av_fifo_generic_write(AVFifoBuffer *f, void *src, int size, memcpy(wptr, src, len); src = (uint8_t *)src + len; } -// Write memory barrier needed for SMP here in theory wptr += len; if (wptr >= f->end) wptr = f->buffer; @@ -152,13 +442,8 @@ int av_fifo_generic_peek_at(AVFifoBuffer *f, void *dest, int offset, int buf_siz { uint8_t *rptr = f->rptr; - av_assert2(offset >= 0); - - /* - * *ndx are indexes modulo 2^32, they are intended to overflow, - * to handle *ndx greater than 4gb. - */ - av_assert2(buf_size + (unsigned)offset <= f->wndx - f->rndx); + if (offset < 0 || buf_size > av_fifo_size(f) - offset) + return AVERROR(EINVAL); if (offset >= f->end - rptr) rptr += offset - (f->end - f->buffer); @@ -189,31 +474,15 @@ int av_fifo_generic_peek_at(AVFifoBuffer *f, void *dest, int offset, int buf_siz int av_fifo_generic_peek(AVFifoBuffer *f, void *dest, int buf_size, void (*func)(void *, void *, int)) { -// Read memory barrier needed for SMP here in theory - uint8_t *rptr = f->rptr; - - do { - int len = FFMIN(f->end - rptr, buf_size); - if (func) - func(dest, rptr, len); - else { - memcpy(dest, rptr, len); - dest = (uint8_t *)dest + len; - } -// memory barrier needed for SMP here in theory - rptr += len; - if (rptr >= f->end) - rptr -= f->end - f->buffer; - buf_size -= len; - } while (buf_size > 0); - - return 0; + return av_fifo_generic_peek_at(f, dest, 0, buf_size, func); } int av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size, void (*func)(void *, void *, int)) { -// Read memory barrier needed for SMP here in theory + if (buf_size > av_fifo_size(f)) + return AVERROR(EINVAL); + do { int len = FFMIN(f->end - f->rptr, buf_size); if (func) @@ -222,7 +491,6 @@ int av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size, memcpy(dest, f->rptr, len); dest = (uint8_t *)dest + len; } -// memory barrier needed for SMP here in theory av_fifo_drain(f, len); buf_size -= len; } while (buf_size > 0); @@ -238,3 +506,5 @@ void av_fifo_drain(AVFifoBuffer *f, int size) f->rptr -= f->end - f->buffer; f->rndx += size; } +FF_ENABLE_DEPRECATION_WARNINGS +#endif diff --git a/libavutil/fifo.h b/libavutil/fifo.h index dc7bc6f0d..4eed364af 100644 --- a/libavutil/fifo.h +++ b/libavutil/fifo.h @@ -24,10 +24,205 @@ #ifndef AVUTIL_FIFO_H #define AVUTIL_FIFO_H +#include #include -#include "avutil.h" -#include "attributes.h" +#include "attributes.h" +#include "version.h" + +typedef struct AVFifo AVFifo; + +/** + * Callback for writing or reading from a FIFO, passed to (and invoked from) the + * av_fifo_*_cb() functions. It may be invoked multiple times from a single + * av_fifo_*_cb() call and may process less data than the maximum size indicated + * by nb_elems. + * + * @param opaque the opaque pointer provided to the av_fifo_*_cb() function + * @param buf the buffer for reading or writing the data, depending on which + * av_fifo_*_cb function is called + * @param nb_elems On entry contains the maximum number of elements that can be + * read from / written into buf. On success, the callback should + * update it to contain the number of elements actually written. + * + * @return 0 on success, a negative error code on failure (will be returned from + * the invoking av_fifo_*_cb() function) + */ +typedef int AVFifoCB(void *opaque, void *buf, size_t *nb_elems); + +/** + * Automatically resize the FIFO on writes, so that the data fits. This + * automatic resizing happens up to a limit that can be modified with + * av_fifo_auto_grow_limit(). + */ +#define AV_FIFO_FLAG_AUTO_GROW (1 << 0) + +/** + * Allocate and initialize an AVFifo with a given element size. + * + * @param elems initial number of elements that can be stored in the FIFO + * @param elem_size Size in bytes of a single element. Further operations on + * the returned FIFO will implicitly use this element size. + * @param flags a combination of AV_FIFO_FLAG_* + * + * @return newly-allocated AVFifo on success, a negative error code on failure + */ +AVFifo *av_fifo_alloc2(size_t elems, size_t elem_size, + unsigned int flags); + +/** + * @return Element size for FIFO operations. This element size is set at + * FIFO allocation and remains constant during its lifetime + */ +size_t av_fifo_elem_size(const AVFifo *f); + +/** + * Set the maximum size (in elements) to which the FIFO can be resized + * automatically. Has no effect unless AV_FIFO_FLAG_AUTO_GROW is used. + */ +void av_fifo_auto_grow_limit(AVFifo *f, size_t max_elems); + +/** + * @return number of elements available for reading from the given FIFO. + */ +size_t av_fifo_can_read(const AVFifo *f); + +/** + * @return number of elements that can be written into the given FIFO. + */ +size_t av_fifo_can_write(const AVFifo *f); + +/** + * Enlarge an AVFifo. + * + * On success, the FIFO will be large enough to hold exactly + * inc + av_fifo_can_read() + av_fifo_can_write() + * elements. In case of failure, the old FIFO is kept unchanged. + * + * @param f AVFifo to resize + * @param inc number of elements to allocate for, in addition to the current + * allocated size + * @return a non-negative number on success, a negative error code on failure + */ +int av_fifo_grow2(AVFifo *f, size_t inc); + +/** + * Write data into a FIFO. + * + * In case nb_elems > av_fifo_can_write(f), nothing is written and an error + * is returned. + * + * @param f the FIFO buffer + * @param buf Data to be written. nb_elems * av_fifo_elem_size(f) bytes will be + * read from buf on success. + * @param nb_elems number of elements to write into FIFO + * + * @return a non-negative number on success, a negative error code on failure + */ +int av_fifo_write(AVFifo *f, const void *buf, size_t nb_elems); + +/** + * Write data from a user-provided callback into a FIFO. + * + * @param f the FIFO buffer + * @param read_cb Callback supplying the data to the FIFO. May be called + * multiple times. + * @param opaque opaque user data to be provided to read_cb + * @param nb_elems Should point to the maximum number of elements that can be + * written. Will be updated to contain the number of elements + * actually written. + * + * @return non-negative number on success, a negative error code on failure + */ +int av_fifo_write_from_cb(AVFifo *f, AVFifoCB read_cb, + void *opaque, size_t *nb_elems); + +/** + * Read data from a FIFO. + * + * In case nb_elems > av_fifo_can_read(f), nothing is read and an error + * is returned. + * + * @param f the FIFO buffer + * @param buf Buffer to store the data. nb_elems * av_fifo_elem_size(f) bytes + * will be written into buf on success. + * @param nb_elems number of elements to read from FIFO + * + * @return a non-negative number on success, a negative error code on failure + */ +int av_fifo_read(AVFifo *f, void *buf, size_t nb_elems); + +/** + * Feed data from a FIFO into a user-provided callback. + * + * @param f the FIFO buffer + * @param write_cb Callback the data will be supplied to. May be called + * multiple times. + * @param opaque opaque user data to be provided to write_cb + * @param nb_elems Should point to the maximum number of elements that can be + * read. Will be updated to contain the total number of elements + * actually sent to the callback. + * + * @return non-negative number on success, a negative error code on failure + */ +int av_fifo_read_to_cb(AVFifo *f, AVFifoCB write_cb, + void *opaque, size_t *nb_elems); + +/** + * Read data from a FIFO without modifying FIFO state. + * + * Returns an error if an attempt is made to peek to nonexistent elements + * (i.e. if offset + nb_elems is larger than av_fifo_can_read(f)). + * + * @param f the FIFO buffer + * @param buf Buffer to store the data. nb_elems * av_fifo_elem_size(f) bytes + * will be written into buf. + * @param nb_elems number of elements to read from FIFO + * @param offset number of initial elements to skip. + * + * @return a non-negative number on success, a negative error code on failure + */ +int av_fifo_peek(AVFifo *f, void *buf, size_t nb_elems, size_t offset); + +/** + * Feed data from a FIFO into a user-provided callback. + * + * @param f the FIFO buffer + * @param write_cb Callback the data will be supplied to. May be called + * multiple times. + * @param opaque opaque user data to be provided to write_cb + * @param nb_elems Should point to the maximum number of elements that can be + * read. Will be updated to contain the total number of elements + * actually sent to the callback. + * @param offset number of initial elements to skip; offset + *nb_elems must not + * be larger than av_fifo_can_read(f). + * + * @return a non-negative number on success, a negative error code on failure + */ +int av_fifo_peek_to_cb(AVFifo *f, AVFifoCB write_cb, void *opaque, + size_t *nb_elems, size_t offset); + +/** + * Discard the specified amount of data from an AVFifo. + * @param size number of elements to discard, MUST NOT be larger than + * av_fifo_can_read(f) + */ +void av_fifo_drain2(AVFifo *f, size_t size); + +/* + * Empty the AVFifo. + * @param f AVFifo to reset + */ +void av_fifo_reset2(AVFifo *f); + +/** + * Free an AVFifo and reset pointer to NULL. + * @param f Pointer to an AVFifo to free. *f == NULL is allowed. + */ +void av_fifo_freep2(AVFifo **f); + + +#if FF_API_FIFO_OLD_API typedef struct AVFifoBuffer { uint8_t *buffer; uint8_t *rptr, *wptr, *end; @@ -38,7 +233,9 @@ typedef struct AVFifoBuffer { * Initialize an AVFifoBuffer. * @param size of FIFO * @return AVFifoBuffer or NULL in case of memory allocation failure + * @deprecated use av_fifo_alloc2() */ +attribute_deprecated AVFifoBuffer *av_fifo_alloc(unsigned int size); /** @@ -46,25 +243,33 @@ AVFifoBuffer *av_fifo_alloc(unsigned int size); * @param nmemb number of elements * @param size size of the single element * @return AVFifoBuffer or NULL in case of memory allocation failure + * @deprecated use av_fifo_alloc2() */ +attribute_deprecated AVFifoBuffer *av_fifo_alloc_array(size_t nmemb, size_t size); /** * Free an AVFifoBuffer. * @param f AVFifoBuffer to free + * @deprecated use the AVFifo API with av_fifo_freep2() */ +attribute_deprecated void av_fifo_free(AVFifoBuffer *f); /** * Free an AVFifoBuffer and reset pointer to NULL. * @param f AVFifoBuffer to free + * @deprecated use the AVFifo API with av_fifo_freep2() */ +attribute_deprecated void av_fifo_freep(AVFifoBuffer **f); /** * Reset the AVFifoBuffer to the state right after av_fifo_alloc, in particular it is emptied. * @param f AVFifoBuffer to reset + * @deprecated use av_fifo_reset2() with the new AVFifo-API */ +attribute_deprecated void av_fifo_reset(AVFifoBuffer *f); /** @@ -72,7 +277,9 @@ void av_fifo_reset(AVFifoBuffer *f); * amount of data you can read from it. * @param f AVFifoBuffer to read from * @return size + * @deprecated use av_fifo_can_read() with the new AVFifo-API */ +attribute_deprecated int av_fifo_size(const AVFifoBuffer *f); /** @@ -80,7 +287,9 @@ int av_fifo_size(const AVFifoBuffer *f); * amount of data you can write into it. * @param f AVFifoBuffer to write into * @return size + * @deprecated use av_fifo_can_write() with the new AVFifo-API */ +attribute_deprecated int av_fifo_space(const AVFifoBuffer *f); /** @@ -91,7 +300,13 @@ int av_fifo_space(const AVFifoBuffer *f); * @param buf_size number of bytes to read * @param func generic read function * @param dest data destination + * + * @return a non-negative number on success, a negative error code on failure + * + * @deprecated use the new AVFifo-API with av_fifo_peek() when func == NULL, + * av_fifo_peek_to_cb() otherwise */ +attribute_deprecated int av_fifo_generic_peek_at(AVFifoBuffer *f, void *dest, int offset, int buf_size, void (*func)(void*, void*, int)); /** @@ -101,7 +316,13 @@ int av_fifo_generic_peek_at(AVFifoBuffer *f, void *dest, int offset, int buf_siz * @param buf_size number of bytes to read * @param func generic read function * @param dest data destination + * + * @return a non-negative number on success, a negative error code on failure + * + * @deprecated use the new AVFifo-API with av_fifo_peek() when func == NULL, + * av_fifo_peek_to_cb() otherwise */ +attribute_deprecated int av_fifo_generic_peek(AVFifoBuffer *f, void *dest, int buf_size, void (*func)(void*, void*, int)); /** @@ -110,7 +331,13 @@ int av_fifo_generic_peek(AVFifoBuffer *f, void *dest, int buf_size, void (*func) * @param buf_size number of bytes to read * @param func generic read function * @param dest data destination + * + * @return a non-negative number on success, a negative error code on failure + * + * @deprecated use the new AVFifo-API with av_fifo_read() when func == NULL, + * av_fifo_read_to_cb() otherwise */ +attribute_deprecated int av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size, void (*func)(void*, void*, int)); /** @@ -124,8 +351,12 @@ int av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size, void (*func) * func must return the number of bytes written to dest_buf, or <= 0 to * indicate no more data available to write. * If func is NULL, src is interpreted as a simple byte array for source data. - * @return the number of bytes written to the FIFO + * @return the number of bytes written to the FIFO or a negative error code on failure + * + * @deprecated use the new AVFifo-API with av_fifo_write() when func == NULL, + * av_fifo_write_from_cb() otherwise */ +attribute_deprecated int av_fifo_generic_write(AVFifoBuffer *f, void *src, int size, int (*func)(void*, void*, int)); /** @@ -135,7 +366,11 @@ int av_fifo_generic_write(AVFifoBuffer *f, void *src, int size, int (*func)(void * @param f AVFifoBuffer to resize * @param size new AVFifoBuffer size in bytes * @return <0 for failure, >=0 otherwise + * + * @deprecated use the new AVFifo-API with av_fifo_grow2() to increase FIFO size, + * decreasing FIFO size is not supported */ +attribute_deprecated int av_fifo_realloc2(AVFifoBuffer *f, unsigned int size); /** @@ -146,16 +381,24 @@ int av_fifo_realloc2(AVFifoBuffer *f, unsigned int size); * @param f AVFifoBuffer to resize * @param additional_space the amount of space in bytes to allocate in addition to av_fifo_size() * @return <0 for failure, >=0 otherwise + * + * @deprecated use the new AVFifo-API with av_fifo_grow2(); note that unlike + * this function it adds to the allocated size, rather than to the used size */ +attribute_deprecated int av_fifo_grow(AVFifoBuffer *f, unsigned int additional_space); /** * Read and discard the specified amount of data from an AVFifoBuffer. * @param f AVFifoBuffer to read from * @param size amount of data to read in bytes + * + * @deprecated use the new AVFifo-API with av_fifo_drain2() */ +attribute_deprecated void av_fifo_drain(AVFifoBuffer *f, int size); +#if FF_API_FIFO_PEEK2 /** * Return a pointer to the data stored in a FIFO buffer at a certain offset. * The FIFO buffer is not modified. @@ -165,7 +408,9 @@ void av_fifo_drain(AVFifoBuffer *f, int size); * than the used buffer size or the returned pointer will * point outside to the buffer data. * The used buffer size can be checked with av_fifo_size(). + * @deprecated use the new AVFifo-API with av_fifo_peek() or av_fifo_peek_to_cb() */ +attribute_deprecated static inline uint8_t *av_fifo_peek2(const AVFifoBuffer *f, int offs) { uint8_t *ptr = f->rptr + offs; @@ -175,5 +420,7 @@ static inline uint8_t *av_fifo_peek2(const AVFifoBuffer *f, int offs) ptr = f->end - (f->buffer - ptr); return ptr; } +#endif +#endif #endif /* AVUTIL_FIFO_H */ diff --git a/libavutil/file.h b/libavutil/file.h index 3ef4a6022..8ec210e78 100644 --- a/libavutil/file.h +++ b/libavutil/file.h @@ -19,9 +19,10 @@ #ifndef AVUTIL_FILE_H #define AVUTIL_FILE_H +#include #include -#include "avutil.h" +#include "attributes.h" /** * @file diff --git a/libavutil/file_open.c b/libavutil/file_open.c index cc302f2f7..58a607335 100644 --- a/libavutil/file_open.c +++ b/libavutil/file_open.c @@ -45,7 +45,7 @@ static int win32_open(const char *filename_utf8, int oflag, int pmode) wchar_t *filename_w; /* convert UTF-8 to wide chars */ - if (utf8towchar(filename_utf8, &filename_w)) + if (get_extended_win32_path(filename_utf8, &filename_w)) return -1; if (!filename_w) goto fallback; @@ -155,7 +155,7 @@ int avpriv_tempfile(const char *prefix, char **filename, int log_offset, void *l return fd; /* success */ } -FILE *av_fopen_utf8(const char *path, const char *mode) +FILE *avpriv_fopen_utf8(const char *path, const char *mode) { int fd; int access; @@ -188,3 +188,10 @@ FILE *av_fopen_utf8(const char *path, const char *mode) return NULL; return fdopen(fd, mode); } + +#if FF_API_AV_FOPEN_UTF8 +FILE *av_fopen_utf8(const char *path, const char *mode) +{ + return avpriv_fopen_utf8(path, mode); +} +#endif diff --git a/libavutil/fixed_dsp.c b/libavutil/fixed_dsp.c index f1b195f18..154f3bc2d 100644 --- a/libavutil/fixed_dsp.c +++ b/libavutil/fixed_dsp.c @@ -45,6 +45,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "common.h" #include "fixed_dsp.h" static void vector_fmul_add_c(int *dst, const int *src0, const int *src1, const int *src2, int len){ @@ -161,8 +162,9 @@ AVFixedDSPContext * avpriv_alloc_fixed_dsp(int bit_exact) fdsp->butterflies_fixed = butterflies_fixed_c; fdsp->scalarproduct_fixed = scalarproduct_fixed_c; - if (ARCH_X86) - ff_fixed_dsp_init_x86(fdsp); +#if ARCH_X86 + ff_fixed_dsp_init_x86(fdsp); +#endif return fdsp; } diff --git a/libavutil/fixed_dsp.h b/libavutil/fixed_dsp.h index f554cb503..fec806ff2 100644 --- a/libavutil/fixed_dsp.h +++ b/libavutil/fixed_dsp.h @@ -49,8 +49,8 @@ #define AVUTIL_FIXED_DSP_H #include +#include "config.h" #include "attributes.h" -#include "common.h" #include "libavcodec/mathops.h" typedef struct AVFixedDSPContext { diff --git a/libavutil/float_dsp.c b/libavutil/float_dsp.c index 6e28d71b5..8676c8b0f 100644 --- a/libavutil/float_dsp.c +++ b/libavutil/float_dsp.c @@ -150,15 +150,16 @@ av_cold AVFloatDSPContext *avpriv_float_dsp_alloc(int bit_exact) fdsp->butterflies_float = butterflies_float_c; fdsp->scalarproduct_float = avpriv_scalarproduct_float_c; - if (ARCH_AARCH64) - ff_float_dsp_init_aarch64(fdsp); - if (ARCH_ARM) - ff_float_dsp_init_arm(fdsp); - if (ARCH_PPC) - ff_float_dsp_init_ppc(fdsp, bit_exact); - if (ARCH_X86) - ff_float_dsp_init_x86(fdsp); - if (ARCH_MIPS) - ff_float_dsp_init_mips(fdsp); +#if ARCH_AARCH64 + ff_float_dsp_init_aarch64(fdsp); +#elif ARCH_ARM + ff_float_dsp_init_arm(fdsp); +#elif ARCH_PPC + ff_float_dsp_init_ppc(fdsp, bit_exact); +#elif ARCH_X86 + ff_float_dsp_init_x86(fdsp); +#elif ARCH_MIPS + ff_float_dsp_init_mips(fdsp); +#endif return fdsp; } diff --git a/libavutil/frame.c b/libavutil/frame.c index 8997c85e3..4c16488c6 100644 --- a/libavutil/frame.c +++ b/libavutil/frame.c @@ -28,10 +28,12 @@ #include "samplefmt.h" #include "hwcontext.h" +#if FF_API_OLD_CHANNEL_LAYOUT #define CHECK_CHANNELS_CONSISTENCY(frame) \ av_assert2(!(frame)->channel_layout || \ (frame)->channels == \ av_get_channel_layout_nb_channels((frame)->channel_layout)) +#endif #if FF_API_COLORSPACE_NAME const char *av_get_colorspace_name(enum AVColorSpace val) @@ -186,18 +188,27 @@ fail: static int get_audio_buffer(AVFrame *frame, int align) { - int channels; int planar = av_sample_fmt_is_planar(frame->format); - int planes; + int channels, planes; int ret, i; - if (!frame->channels) - frame->channels = av_get_channel_layout_nb_channels(frame->channel_layout); - - channels = frame->channels; - planes = planar ? channels : 1; - - CHECK_CHANNELS_CONSISTENCY(frame); +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + if (!frame->ch_layout.nb_channels) { + if (frame->channel_layout) { + av_channel_layout_from_mask(&frame->ch_layout, frame->channel_layout); + } else { + frame->ch_layout.nb_channels = frame->channels; + frame->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + } + } + frame->channels = frame->ch_layout.nb_channels; + frame->channel_layout = frame->ch_layout.order == AV_CHANNEL_ORDER_NATIVE ? + frame->ch_layout.u.mask : 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + channels = frame->ch_layout.nb_channels; + planes = planar ? channels : 1; if (!frame->linesize[0]) { ret = av_samples_get_buffer_size(&frame->linesize[0], channels, frame->nb_samples, frame->format, @@ -245,10 +256,17 @@ int av_frame_get_buffer(AVFrame *frame, int align) if (frame->format < 0) return AVERROR(EINVAL); +FF_DISABLE_DEPRECATION_WARNINGS if (frame->width > 0 && frame->height > 0) return get_video_buffer(frame, align); - else if (frame->nb_samples > 0 && (frame->channel_layout || frame->channels > 0)) + else if (frame->nb_samples > 0 && + (av_channel_layout_check(&frame->ch_layout) +#if FF_API_OLD_CHANNEL_LAYOUT + || frame->channel_layout || frame->channels > 0 +#endif + )) return get_audio_buffer(frame, align); +FF_ENABLE_DEPRECATION_WARNINGS return AVERROR(EINVAL); } @@ -327,19 +345,44 @@ int av_frame_ref(AVFrame *dst, const AVFrame *src) int i, ret = 0; av_assert1(dst->width == 0 && dst->height == 0); +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS av_assert1(dst->channels == 0); +FF_ENABLE_DEPRECATION_WARNINGS +#endif + av_assert1(dst->ch_layout.nb_channels == 0 && + dst->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC); dst->format = src->format; dst->width = src->width; dst->height = src->height; + dst->nb_samples = src->nb_samples; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS dst->channels = src->channels; dst->channel_layout = src->channel_layout; - dst->nb_samples = src->nb_samples; + if (!av_channel_layout_check(&src->ch_layout)) { + if (src->channel_layout) + av_channel_layout_from_mask(&dst->ch_layout, src->channel_layout); + else { + dst->ch_layout.nb_channels = src->channels; + dst->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + } + } +FF_ENABLE_DEPRECATION_WARNINGS +#endif ret = frame_copy_props(dst, src, 0); if (ret < 0) goto fail; + // this check is needed only until FF_API_OLD_CHANNEL_LAYOUT is out + if (av_channel_layout_check(&src->ch_layout)) { + ret = av_channel_layout_copy(&dst->ch_layout, &src->ch_layout); + if (ret < 0) + goto fail; + } + /* duplicate the frame data if it's not refcounted */ if (!src->buf[0]) { ret = av_frame_get_buffer(dst, 0); @@ -392,13 +435,12 @@ int av_frame_ref(AVFrame *dst, const AVFrame *src) /* duplicate extended data */ if (src->extended_data != src->data) { - int ch = src->channels; + int ch = dst->ch_layout.nb_channels; if (!ch) { ret = AVERROR(EINVAL); goto fail; } - CHECK_CHANNELS_CONSISTENCY(src); dst->extended_data = av_malloc_array(sizeof(*dst->extended_data), ch); if (!dst->extended_data) { @@ -456,13 +498,21 @@ void av_frame_unref(AVFrame *frame) if (frame->extended_data != frame->data) av_freep(&frame->extended_data); + av_channel_layout_uninit(&frame->ch_layout); + get_frame_defaults(frame); } void av_frame_move_ref(AVFrame *dst, AVFrame *src) { av_assert1(dst->width == 0 && dst->height == 0); +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS av_assert1(dst->channels == 0); +FF_ENABLE_DEPRECATION_WARNINGS +#endif + av_assert1(dst->ch_layout.nb_channels == 0 && + dst->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC); *dst = *src; if (src->extended_data == src->data) @@ -502,9 +552,18 @@ int av_frame_make_writable(AVFrame *frame) tmp.format = frame->format; tmp.width = frame->width; tmp.height = frame->height; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS tmp.channels = frame->channels; tmp.channel_layout = frame->channel_layout; +FF_ENABLE_DEPRECATION_WARNINGS +#endif tmp.nb_samples = frame->nb_samples; + ret = av_channel_layout_copy(&tmp.ch_layout, &frame->ch_layout); + if (ret < 0) { + av_frame_unref(&tmp); + return ret; + } if (frame->hw_frames_ctx) ret = av_hwframe_get_buffer(frame->hw_frames_ctx, &tmp, 0); @@ -545,10 +604,18 @@ AVBufferRef *av_frame_get_plane_buffer(AVFrame *frame, int plane) int planes, i; if (frame->nb_samples) { - int channels = frame->channels; + int channels = frame->ch_layout.nb_channels; + +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + if (!channels) { + channels = frame->channels; + CHECK_CHANNELS_CONSISTENCY(frame); + } +FF_ENABLE_DEPRECATION_WARNINGS +#endif if (!channels) return NULL; - CHECK_CHANNELS_CONSISTENCY(frame); planes = av_sample_fmt_is_planar(frame->format) ? channels : 1; } else planes = 4; @@ -654,16 +721,35 @@ static int frame_copy_video(AVFrame *dst, const AVFrame *src) static int frame_copy_audio(AVFrame *dst, const AVFrame *src) { int planar = av_sample_fmt_is_planar(dst->format); - int channels = dst->channels; + int channels = dst->ch_layout.nb_channels; int planes = planar ? channels : 1; int i; - if (dst->nb_samples != src->nb_samples || - dst->channels != src->channels || - dst->channel_layout != src->channel_layout) - return AVERROR(EINVAL); +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + if (!channels || !src->ch_layout.nb_channels) { + if (dst->channels != src->channels || + dst->channel_layout != src->channel_layout) + return AVERROR(EINVAL); + CHECK_CHANNELS_CONSISTENCY(src); + } + if (!channels) { + channels = dst->channels; + planes = planar ? channels : 1; + } +FF_ENABLE_DEPRECATION_WARNINGS +#endif - CHECK_CHANNELS_CONSISTENCY(src); + if (dst->nb_samples != src->nb_samples || +#if FF_API_OLD_CHANNEL_LAYOUT + (av_channel_layout_check(&dst->ch_layout) && + av_channel_layout_check(&src->ch_layout) && +#endif + av_channel_layout_compare(&dst->ch_layout, &src->ch_layout)) +#if FF_API_OLD_CHANNEL_LAYOUT + ) +#endif + return AVERROR(EINVAL); for (i = 0; i < planes; i++) if (!dst->extended_data[i] || !src->extended_data[i]) @@ -680,10 +766,17 @@ int av_frame_copy(AVFrame *dst, const AVFrame *src) if (dst->format != src->format || dst->format < 0) return AVERROR(EINVAL); +FF_DISABLE_DEPRECATION_WARNINGS if (dst->width > 0 && dst->height > 0) return frame_copy_video(dst, src); - else if (dst->nb_samples > 0 && dst->channels > 0) + else if (dst->nb_samples > 0 && + (av_channel_layout_check(&dst->ch_layout) +#if FF_API_OLD_CHANNEL_LAYOUT + || dst->channels > 0 +#endif + )) return frame_copy_audio(dst, src); +FF_ENABLE_DEPRECATION_WARNINGS return AVERROR(EINVAL); } @@ -723,6 +816,7 @@ const char *av_frame_side_data_name(enum AVFrameSideDataType type) case AV_FRAME_DATA_SPHERICAL: return "Spherical Mapping"; case AV_FRAME_DATA_ICC_PROFILE: return "ICC profile"; case AV_FRAME_DATA_DYNAMIC_HDR_PLUS: return "HDR Dynamic Metadata SMPTE2094-40 (HDR10+)"; + case AV_FRAME_DATA_DYNAMIC_HDR_VIVID: return "HDR Dynamic Metadata CUVA 005.1 2021 (Vivid)"; case AV_FRAME_DATA_REGIONS_OF_INTEREST: return "Regions Of Interest"; case AV_FRAME_DATA_VIDEO_ENC_PARAMS: return "Video encoding parameters"; case AV_FRAME_DATA_SEI_UNREGISTERED: return "H.26[45] User Data Unregistered SEI message"; diff --git a/libavutil/frame.h b/libavutil/frame.h index 18e239f87..33fac2054 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -30,6 +30,7 @@ #include "avutil.h" #include "buffer.h" +#include "channel_layout.h" #include "dict.h" #include "rational.h" #include "samplefmt.h" @@ -201,6 +202,13 @@ enum AVFrameSideDataType { * libavutil/dovi_meta.h. */ AV_FRAME_DATA_DOVI_METADATA, + + /** + * HDR Vivid dynamic metadata associated with a video frame. The payload is + * an AVDynamicHDRVivid type and contains information for color + * volume transform - CUVA 005.1-2021. + */ + AV_FRAME_DATA_DYNAMIC_HDR_VIVID, }; enum AVActiveFormatDescription { @@ -493,10 +501,14 @@ typedef struct AVFrame { */ int sample_rate; +#if FF_API_OLD_CHANNEL_LAYOUT /** * Channel layout of the audio data. + * @deprecated use ch_layout instead */ + attribute_deprecated uint64_t channel_layout; +#endif /** * AVBuffer references backing the data for this frame. All the pointers in @@ -620,12 +632,16 @@ typedef struct AVFrame { #define FF_DECODE_ERROR_CONCEALMENT_ACTIVE 4 #define FF_DECODE_ERROR_DECODE_SLICES 8 +#if FF_API_OLD_CHANNEL_LAYOUT /** * number of audio channels, only used for audio. * - encoding: unused * - decoding: Read by user. + * @deprecated use ch_layout instead */ + attribute_deprecated int channels; +#endif /** * size of the corresponding packet containing the compressed @@ -681,6 +697,11 @@ typedef struct AVFrame { * for the target frame's private_ref field. */ AVBufferRef *private_ref; + + /** + * Channel layout of the audio data. + */ + AVChannelLayout ch_layout; } AVFrame; @@ -760,7 +781,7 @@ void av_frame_move_ref(AVFrame *dst, AVFrame *src); * The following fields must be set on frame before calling this function: * - format (pixel format for video, sample format for audio) * - width and height for video - * - nb_samples and channel_layout for audio + * - nb_samples and ch_layout for audio * * This function will fill AVFrame.data and AVFrame.buf arrays and, if * necessary, allocate and fill AVFrame.extended_data and AVFrame.extended_buf. diff --git a/libavutil/getenv_utf8.h b/libavutil/getenv_utf8.h new file mode 100644 index 000000000..c10291adf --- /dev/null +++ b/libavutil/getenv_utf8.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 AVUTIL_GETENV_UTF8_H +#define AVUTIL_GETENV_UTF8_H + +#include + +#include "config.h" +#include "mem.h" + +#if HAVE_GETENV && defined(_WIN32) + +#include "libavutil/wchar_filename.h" + +static inline char *getenv_utf8(const char *varname) +{ + wchar_t *varname_w, *var_w; + char *var; + + if (utf8towchar(varname, &varname_w)) + return NULL; + if (!varname_w) + return NULL; + + var_w = _wgetenv(varname_w); + av_free(varname_w); + + if (!var_w) + return NULL; + if (wchartoutf8(var_w, &var)) + return NULL; + + return var; + + // No CP_ACP fallback compared to other *_utf8() functions: + // non UTF-8 strings must not be returned. +} + +static inline void freeenv_utf8(char *var) +{ + av_free(var); +} + +static inline char *getenv_dup(const char *varname) +{ + return getenv_utf8(varname); +} + +#else + +static inline char *getenv_utf8(const char *varname) +{ + return getenv(varname); +} + +static inline void freeenv_utf8(char *var) +{ +} + +static inline char *getenv_dup(const char *varname) +{ + char *var = getenv(varname); + if (!var) + return NULL; + return av_strdup(var); +} + +#endif // HAVE_GETENV && defined(_WIN32) + +#endif // AVUTIL_GETENV_UTF8_H diff --git a/libavutil/hdr_dynamic_vivid_metadata.c b/libavutil/hdr_dynamic_vivid_metadata.c new file mode 100644 index 000000000..32da01f58 --- /dev/null +++ b/libavutil/hdr_dynamic_vivid_metadata.c @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2021 Limin 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 "hdr_dynamic_vivid_metadata.h" +#include "mem.h" + +AVDynamicHDRVivid *av_dynamic_hdr_vivid_alloc(size_t *size) +{ + AVDynamicHDRVivid *hdr_vivid = av_mallocz(sizeof(AVDynamicHDRVivid)); + if (!hdr_vivid) + return NULL; + + if (size) + *size = sizeof(*hdr_vivid); + + return hdr_vivid; +} + +AVDynamicHDRVivid *av_dynamic_hdr_vivid_create_side_data(AVFrame *frame) +{ + AVFrameSideData *side_data = av_frame_new_side_data(frame, + AV_FRAME_DATA_DYNAMIC_HDR_VIVID, + sizeof(AVDynamicHDRVivid)); + if (!side_data) + return NULL; + + memset(side_data->data, 0, sizeof(AVDynamicHDRVivid)); + + return (AVDynamicHDRVivid *)side_data->data; +} diff --git a/libavutil/hdr_dynamic_vivid_metadata.h b/libavutil/hdr_dynamic_vivid_metadata.h new file mode 100644 index 000000000..a34f83072 --- /dev/null +++ b/libavutil/hdr_dynamic_vivid_metadata.h @@ -0,0 +1,285 @@ +/* + * Copyright (c) 2021 Limin 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 AVUTIL_HDR_DYNAMIC_VIVID_METADATA_H +#define AVUTIL_HDR_DYNAMIC_VIVID_METADATA_H + +#include "frame.h" +#include "rational.h" + +/** + * Color tone mapping parameters at a processing window in a dynamic metadata for + * CUVA 005.1:2021. + */ +typedef struct AVHDRVividColorToneMappingParams { + /** + * The nominal maximum display luminance of the targeted system display, + * in multiples of 1.0/4095 candelas per square metre. The value shall be in + * the range of 0.0 to 1.0, inclusive. + */ + AVRational targeted_system_display_maximum_luminance; + + /** + * This flag indicates that transfer the base paramter(for value of 1) + */ + int base_enable_flag; + + /** + * base_param_m_p in the base parameter, + * in multiples of 1.0/16383. The value shall be in + * the range of 0.0 to 1.0, inclusive. + */ + AVRational base_param_m_p; + + /** + * base_param_m_m in the base parameter, + * in multiples of 1.0/10. The value shall be in + * the range of 0.0 to 6.3, inclusive. + */ + AVRational base_param_m_m; + + /** + * base_param_m_a in the base parameter, + * in multiples of 1.0/1023. The value shall be in + * the range of 0.0 to 1.0 inclusive. + */ + AVRational base_param_m_a; + + /** + * base_param_m_b in the base parameter, + * in multiples of 1/1023. The value shall be in + * the range of 0.0 to 1.0, inclusive. + */ + AVRational base_param_m_b; + + /** + * base_param_m_n in the base parameter, + * in multiples of 1.0/10. The value shall be in + * the range of 0.0 to 6.3, inclusive. + */ + AVRational base_param_m_n; + + /** + * indicates k1_0 in the base parameter, + * base_param_k1 <= 1: k1_0 = base_param_k1 + * base_param_k1 > 1: reserved + */ + int base_param_k1; + + /** + * indicates k2_0 in the base parameter, + * base_param_k2 <= 1: k2_0 = base_param_k2 + * base_param_k2 > 1: reserved + */ + int base_param_k2; + + /** + * indicates k3_0 in the base parameter, + * base_param_k3 == 1: k3_0 = base_param_k3 + * base_param_k3 == 2: k3_0 = maximum_maxrgb + * base_param_k3 > 2: reserved + */ + int base_param_k3; + + /** + * This flag indicates that delta mode of base paramter(for value of 1) + */ + int base_param_Delta_enable_mode; + + /** + * base_param_Delta in the base parameter, + * in multiples of 1.0/127. The value shall be in + * the range of 0.0 to 1.0, inclusive. + */ + AVRational base_param_Delta; + + /** + * indicates 3Spline_enable_flag in the base parameter, + * This flag indicates that transfer three Spline of base paramter(for value of 1) + */ + int three_Spline_enable_flag; + + /** + * The number of three Spline. The value shall be in the range + * of 1 to 2, inclusive. + */ + int three_Spline_num; + + /** + * The mode of three Spline. the value shall be in the range + * of 0 to 3, inclusive. + */ + int three_Spline_TH_mode; + + /** + * three_Spline_TH_enable_MB is in the range of 0.0 to 1.0, inclusive + * and in multiples of 1.0/255. + * + */ + AVRational three_Spline_TH_enable_MB; + + /** + * 3Spline_TH_enable of three Spline. + * The value shall be in the range of 0.0 to 1.0, inclusive. + * and in multiples of 1.0/4095. + */ + AVRational three_Spline_TH_enable; + + /** + * 3Spline_TH_Delta1 of three Spline. + * The value shall be in the range of 0.0 to 0.25, inclusive, + * and in multiples of 0.25/1023. + */ + AVRational three_Spline_TH_Delta1; + + /** + * 3Spline_TH_Delta2 of three Spline. + * The value shall be in the range of 0.0 to 0.25, inclusive, + * and in multiples of 0.25/1023. + */ + AVRational three_Spline_TH_Delta2; + + /** + * 3Spline_enable_Strength of three Spline. + * The value shall be in the range of 0.0 to 1.0, inclusive, + * and in multiples of 1.0/255. + */ + AVRational three_Spline_enable_Strength; +} AVHDRVividColorToneMappingParams; + + +/** + * Color transform parameters at a processing window in a dynamic metadata for + * CUVA 005.1:2021. + */ +typedef struct AVHDRVividColorTransformParams { + /** + * Indicates the minimum brightness of the displayed content. + * The values should be in the range of 0.0 to 1.0, + * inclusive and in multiples of 1/4095. + */ + AVRational minimum_maxrgb; + + /** + * Indicates the average brightness of the displayed content. + * The values should be in the range of 0.0 to 1.0, + * inclusive and in multiples of 1/4095. + */ + AVRational average_maxrgb; + + /** + * Indicates the variance brightness of the displayed content. + * The values should be in the range of 0.0 to 1.0, + * inclusive and in multiples of 1/4095. + */ + AVRational variance_maxrgb; + + /** + * Indicates the maximum brightness of the displayed content. + * The values should be in the range of 0.0 to 1.0, inclusive + * and in multiples of 1/4095. + */ + AVRational maximum_maxrgb; + + /** + * This flag indicates that the metadata for the tone mapping function in + * the processing window is present (for value of 1). + */ + int tone_mapping_mode_flag; + + /** + * The number of tone mapping param. The value shall be in the range + * of 1 to 2, inclusive. + */ + int tone_mapping_param_num; + + /** + * The color tone mapping parameters. + */ + AVHDRVividColorToneMappingParams tm_params[2]; + + /** + * This flag indicates that the metadata for the color saturation mapping in + * the processing window is present (for value of 1). + */ + int color_saturation_mapping_flag; + + /** + * The number of color saturation param. The value shall be in the range + * of 0 to 7, inclusive. + */ + int color_saturation_num; + + /** + * Indicates the color correction strength parameter. + * The values should be in the range of 0.0 to 2.0, inclusive + * and in multiples of 1/128. + */ + AVRational color_saturation_gain[8]; +} AVHDRVividColorTransformParams; + +/** + * This struct represents dynamic metadata for color volume transform - + * CUVA 005.1:2021 standard + * + * To be used as payload of a AVFrameSideData or AVPacketSideData with the + * appropriate type. + * + * @note The struct should be allocated with + * av_dynamic_hdr_vivid_alloc() and its size is not a part of + * the public ABI. + */ +typedef struct AVDynamicHDRVivid { + /** + * The system start code. The value shall be set to 0x01. + */ + uint8_t system_start_code; + + /** + * The number of processing windows. The value shall be set to 0x01 + * if the system_start_code is 0x01. + */ + uint8_t num_windows; + + /** + * The color transform parameters for every processing window. + */ + AVHDRVividColorTransformParams params[3]; +} AVDynamicHDRVivid; + +/** + * Allocate an AVDynamicHDRVivid structure and set its fields to + * default values. The resulting struct can be freed using av_freep(). + * + * @return An AVDynamicHDRVivid filled with default values or NULL + * on failure. + */ +AVDynamicHDRVivid *av_dynamic_hdr_vivid_alloc(size_t *size); + +/** + * Allocate a complete AVDynamicHDRVivid and add it to the frame. + * @param frame The frame which side data is added to. + * + * @return The AVDynamicHDRVivid structure to be filled by caller or NULL + * on failure. + */ +AVDynamicHDRVivid *av_dynamic_hdr_vivid_create_side_data(AVFrame *frame); + +#endif /* AVUTIL_HDR_DYNAMIC_VIVID_METADATA_H */ diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c index 31c7840db..ab9ad3703 100644 --- a/libavutil/hwcontext.c +++ b/libavutil/hwcontext.c @@ -18,6 +18,7 @@ #include "config.h" +#include "avassert.h" #include "buffer.h" #include "common.h" #include "hwcontext.h" @@ -788,6 +789,8 @@ fail: int av_hwframe_map(AVFrame *dst, const AVFrame *src, int flags) { + AVBufferRef *orig_dst_frames = dst->hw_frames_ctx; + enum AVPixelFormat orig_dst_fmt = dst->format; AVHWFramesContext *src_frames, *dst_frames; HWMapDescriptor *hwmap; int ret; @@ -824,8 +827,10 @@ int av_hwframe_map(AVFrame *dst, const AVFrame *src, int flags) src_frames->internal->hw_type->map_from) { ret = src_frames->internal->hw_type->map_from(src_frames, dst, src, flags); - if (ret != AVERROR(ENOSYS)) + if (ret >= 0) return ret; + else if (ret != AVERROR(ENOSYS)) + goto fail; } } @@ -836,12 +841,30 @@ int av_hwframe_map(AVFrame *dst, const AVFrame *src, int flags) dst_frames->internal->hw_type->map_to) { ret = dst_frames->internal->hw_type->map_to(dst_frames, dst, src, flags); - if (ret != AVERROR(ENOSYS)) + if (ret >= 0) return ret; + else if (ret != AVERROR(ENOSYS)) + goto fail; } } return AVERROR(ENOSYS); + +fail: + // if the caller provided dst frames context, it should be preserved + // by this function + av_assert0(orig_dst_frames == NULL || + orig_dst_frames == dst->hw_frames_ctx); + + // preserve user-provided dst frame fields, but clean + // anything we might have set + dst->hw_frames_ctx = NULL; + av_frame_unref(dst); + + dst->hw_frames_ctx = orig_dst_frames; + dst->format = orig_dst_fmt; + + return ret; } int av_hwframe_ctx_create_derived(AVBufferRef **derived_frame_ctx, diff --git a/libavutil/hwcontext.h b/libavutil/hwcontext.h index 04d19d89c..c18b7e1e8 100644 --- a/libavutil/hwcontext.h +++ b/libavutil/hwcontext.h @@ -571,6 +571,10 @@ enum { * possible with the given arguments and hwframe setup, while other return * values indicate that it failed somehow. * + * On failure, the destination frame will be left blank, except for the + * hw_frames_ctx/format fields thay may have been set by the caller - those will + * be preserved as they were. + * * @param dst Destination frame, to contain the mapping. * @param src Source frame, to be mapped. * @param flags Some combination of AV_HWFRAME_MAP_* flags. diff --git a/libavutil/hwcontext_d3d11va.c b/libavutil/hwcontext_d3d11va.c index 8ab96bad2..1bc8b6c82 100644 --- a/libavutil/hwcontext_d3d11va.c +++ b/libavutil/hwcontext_d3d11va.c @@ -166,6 +166,17 @@ static AVBufferRef *wrap_texture_buf(AVHWFramesContext *ctx, ID3D11Texture2D *te return NULL; } + if (s->nb_surfaces <= s->nb_surfaces_used) { + frames_hwctx->texture_infos = av_realloc_f(frames_hwctx->texture_infos, + s->nb_surfaces_used + 1, + sizeof(*frames_hwctx->texture_infos)); + if (!frames_hwctx->texture_infos) { + ID3D11Texture2D_Release(tex); + return NULL; + } + s->nb_surfaces = s->nb_surfaces_used + 1; + } + frames_hwctx->texture_infos[s->nb_surfaces_used].texture = tex; frames_hwctx->texture_infos[s->nb_surfaces_used].index = index; s->nb_surfaces_used++; @@ -284,7 +295,7 @@ static int d3d11va_frames_init(AVHWFramesContext *ctx) } } - hwctx->texture_infos = av_calloc(ctx->initial_pool_size, sizeof(*hwctx->texture_infos)); + hwctx->texture_infos = av_realloc_f(NULL, ctx->initial_pool_size, sizeof(*hwctx->texture_infos)); if (!hwctx->texture_infos) return AVERROR(ENOMEM); s->nb_surfaces = ctx->initial_pool_size; @@ -339,7 +350,7 @@ static int d3d11va_transfer_get_formats(AVHWFramesContext *ctx, return 0; } -static int d3d11va_create_staging_texture(AVHWFramesContext *ctx) +static int d3d11va_create_staging_texture(AVHWFramesContext *ctx, DXGI_FORMAT format) { AVD3D11VADeviceContext *device_hwctx = ctx->device_ctx->hwctx; D3D11VAFramesContext *s = ctx->internal->priv; @@ -348,7 +359,7 @@ static int d3d11va_create_staging_texture(AVHWFramesContext *ctx) .Width = ctx->width, .Height = ctx->height, .MipLevels = 1, - .Format = s->format, + .Format = format, .SampleDesc = { .Count = 1 }, .ArraySize = 1, .Usage = D3D11_USAGE_STAGING, @@ -404,7 +415,8 @@ 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); + ID3D11Texture2D_GetDesc((ID3D11Texture2D *)texture, &desc); + int res = d3d11va_create_staging_texture(ctx, desc.Format); if (res < 0) return res; } diff --git a/libavutil/hwcontext_opencl.c b/libavutil/hwcontext_opencl.c index 26a3a2459..32aec7d22 100644 --- a/libavutil/hwcontext_opencl.c +++ b/libavutil/hwcontext_opencl.c @@ -72,6 +72,12 @@ #include "hwcontext_drm.h" #endif +#if HAVE_OPENCL_VAAPI_INTEL_MEDIA && CONFIG_LIBMFX +extern int ff_qsv_get_surface_base_handle(mfxFrameSurface1 *surf, + enum AVHWDeviceType base_dev_typ, + void **base_handle); +#endif + typedef struct OpenCLDeviceContext { // Default command queue to use for transfer/mapping operations on @@ -1405,7 +1411,8 @@ static int opencl_get_plane_format(enum AVPixelFormat pixfmt, // 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) + comp->shift + comp->depth != 16 && + comp->shift + comp->depth != 32) return AVERROR(EINVAL); // The depth must not vary between components. if (depth && comp->depth != depth) @@ -1449,6 +1456,8 @@ static int opencl_get_plane_format(enum AVPixelFormat pixfmt, } else { if (depth <= 16) image_format->image_channel_data_type = CL_UNORM_INT16; + else if (depth == 32) + image_format->image_channel_data_type = CL_FLOAT; else return AVERROR(EINVAL); } @@ -2146,6 +2155,7 @@ fail: clReleaseMemObject(mapping->frame.planes[p]); } av_free(mapping); + memset(dst->data, 0, sizeof(dst->data)); return err; } @@ -2248,8 +2258,14 @@ static int opencl_map_from_qsv(AVHWFramesContext *dst_fc, AVFrame *dst, #if CONFIG_LIBMFX if (src->format == AV_PIX_FMT_QSV) { + void *base_handle; mfxFrameSurface1 *mfx_surface = (mfxFrameSurface1*)src->data[3]; - va_surface = *(VASurfaceID*)mfx_surface->Data.MemId; + err = ff_qsv_get_surface_base_handle(mfx_surface, + AV_HWDEVICE_TYPE_VAAPI, + &base_handle); + if (err < 0) + return err; + va_surface = *(VASurfaceID *)base_handle; } else #endif if (src->format == AV_PIX_FMT_VAAPI) { @@ -2317,6 +2333,7 @@ fail: if (desc->planes[p]) clReleaseMemObject(desc->planes[p]); av_freep(&desc); + memset(dst->data, 0, sizeof(dst->data)); return err; } @@ -2407,6 +2424,7 @@ fail: 0, NULL, &event); if (cle == CL_SUCCESS) opencl_wait_events(dst_fc, &event, 1); + memset(dst->data, 0, sizeof(dst->data)); return err; } @@ -2562,6 +2580,7 @@ fail: 0, NULL, &event); if (cle == CL_SUCCESS) opencl_wait_events(dst_fc, &event, 1); + memset(dst->data, 0, sizeof(dst->data)); return err; } @@ -2793,6 +2812,7 @@ fail: clReleaseMemObject(mapping->object_buffers[i]); } av_free(mapping); + memset(dst->data, 0, sizeof(dst->data)); return err; } diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c index 853fb7f60..56dffa1f2 100644 --- a/libavutil/hwcontext_qsv.c +++ b/libavutil/hwcontext_qsv.c @@ -16,6 +16,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include #include @@ -71,12 +72,11 @@ typedef struct QSVDeviceContext { typedef struct QSVFramesContext { mfxSession session_download; - int session_download_init; + atomic_int session_download_init; mfxSession session_upload; - int session_upload_init; + atomic_int session_upload_init; #if HAVE_PTHREADS pthread_mutex_t session_lock; - pthread_cond_t session_cond; #endif AVBufferRef *child_frames_ref; @@ -91,7 +91,8 @@ typedef struct QSVFramesContext { mfxExtOpaqueSurfaceAlloc opaque_alloc; mfxExtBuffer *ext_buffers[1]; - AVFrame realigned_tmp_frame; + AVFrame realigned_upload_frame; + AVFrame realigned_download_frame; } QSVFramesContext; static const struct { @@ -105,13 +106,45 @@ static const struct { #if CONFIG_VAAPI { AV_PIX_FMT_YUYV422, MFX_FOURCC_YUY2 }, -#if QSV_VERSION_ATLEAST(1, 27) { AV_PIX_FMT_Y210, MFX_FOURCC_Y210 }, #endif -#endif }; +extern int ff_qsv_get_surface_base_handle(mfxFrameSurface1 *surf, + enum AVHWDeviceType base_dev_type, + void **base_handle); + +/** + * Caller needs to allocate enough space for base_handle pointer. + **/ +int ff_qsv_get_surface_base_handle(mfxFrameSurface1 *surf, + enum AVHWDeviceType base_dev_type, + void **base_handle) +{ + mfxHDLPair *handle_pair; + handle_pair = surf->Data.MemId; + switch (base_dev_type) { +#if CONFIG_VAAPI + case AV_HWDEVICE_TYPE_VAAPI: + base_handle[0] = handle_pair->first; + return 0; +#endif +#if CONFIG_D3D11VA + case AV_HWDEVICE_TYPE_D3D11VA: + base_handle[0] = handle_pair->first; + base_handle[1] = handle_pair->second; + return 0; +#endif +#if CONFIG_DXVA2 + case AV_HWDEVICE_TYPE_DXVA2: + base_handle[0] = handle_pair->first; + return 0; +#endif + } + return AVERROR(EINVAL); +} + static uint32_t qsv_fourcc_from_pix_fmt(enum AVPixelFormat pix_fmt) { int i; @@ -263,14 +296,14 @@ static void qsv_frames_uninit(AVHWFramesContext *ctx) #if HAVE_PTHREADS pthread_mutex_destroy(&s->session_lock); - pthread_cond_destroy(&s->session_cond); #endif av_freep(&s->mem_ids); av_freep(&s->surface_ptrs); av_freep(&s->surfaces_internal); av_freep(&s->handle_pairs_internal); - av_frame_unref(&s->realigned_tmp_frame); + av_frame_unref(&s->realigned_upload_frame); + av_frame_unref(&s->realigned_download_frame); av_buffer_unref(&s->child_frames_ref); } @@ -710,7 +743,6 @@ static int qsv_frames_init(AVHWFramesContext *ctx) #if HAVE_PTHREADS pthread_mutex_init(&s->session_lock, NULL); - pthread_cond_init(&s->session_cond, NULL); #endif return 0; @@ -774,12 +806,22 @@ static int qsv_frames_derive_from(AVHWFramesContext *dst_ctx, #if CONFIG_D3D11VA case AV_HWDEVICE_TYPE_D3D11VA: { + D3D11_TEXTURE2D_DESC texDesc; + dst_ctx->initial_pool_size = src_ctx->initial_pool_size; AVD3D11VAFramesContext *dst_hwctx = dst_ctx->hwctx; - mfxHDLPair *pair = (mfxHDLPair*)src_hwctx->surfaces[i].Data.MemId; - dst_hwctx->texture = (ID3D11Texture2D*)pair->first; + dst_hwctx->texture_infos = av_calloc(src_hwctx->nb_surfaces, + sizeof(*dst_hwctx->texture_infos)); + if (!dst_hwctx->texture_infos) + return AVERROR(ENOMEM); if (src_hwctx->frame_type & MFX_MEMTYPE_SHARED_RESOURCE) dst_hwctx->MiscFlags = D3D11_RESOURCE_MISC_SHARED; - dst_hwctx->BindFlags = qsv_get_d3d11va_bind_flags(src_hwctx->frame_type); + for (i = 0; i < src_hwctx->nb_surfaces; i++) { + mfxHDLPair *pair = (mfxHDLPair*)src_hwctx->surfaces[i].Data.MemId; + dst_hwctx->texture_infos[i].texture = (ID3D11Texture2D*)pair->first; + dst_hwctx->texture_infos[i].index = pair->second == (mfxMemId)MFX_INFINITE ? (intptr_t)0 : (intptr_t)pair->second; + } + ID3D11Texture2D_GetDesc(dst_hwctx->texture_infos[0].texture, &texDesc); + dst_hwctx->BindFlags = texDesc.BindFlags; } break; #endif @@ -870,7 +912,7 @@ static int qsv_map_from(AVHWFramesContext *ctx, if (child_frames_ctx->device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) { mfxHDLPair *pair = (mfxHDLPair*)surf->Data.MemId; dst->data[0] = pair->first; - dst->data[1] = pair->second; + dst->data[1] = pair->second == (mfxMemId)MFX_INFINITE ? (uint8_t *)0 : pair->second; } else { dst->data[3] = child_data; } @@ -900,7 +942,7 @@ static int qsv_map_from(AVHWFramesContext *ctx, if (child_frames_ctx->device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) { mfxHDLPair *pair = (mfxHDLPair*)surf->Data.MemId; dummy->data[0] = pair->first; - dummy->data[1] = pair->second; + dummy->data[1] = pair->second == (mfxMemId)MFX_INFINITE ? (uint8_t *)0 : pair->second; } else { dummy->data[3] = child_data; } @@ -990,6 +1032,32 @@ static int map_frame_to_surface(const AVFrame *frame, mfxFrameSurface1 *surface) return 0; } +static int qsv_internal_session_check_init(AVHWFramesContext *ctx, int upload) +{ + QSVFramesContext *s = ctx->internal->priv; + atomic_int *inited = upload ? &s->session_upload_init : &s->session_download_init; + mfxSession *session = upload ? &s->session_upload : &s->session_download; + int ret = 0; + + if (atomic_load(inited)) + return 0; + +#if HAVE_PTHREADS + pthread_mutex_lock(&s->session_lock); +#endif + + if (!atomic_load(inited)) { + ret = qsv_init_internal_session(ctx, session, upload); + atomic_store(inited, 1); + } + +#if HAVE_PTHREADS + pthread_mutex_unlock(&s->session_lock); +#endif + + return ret; +} + static int qsv_transfer_data_from(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src) { @@ -1000,42 +1068,46 @@ static int qsv_transfer_data_from(AVHWFramesContext *ctx, AVFrame *dst, mfxSyncPoint sync = NULL; mfxStatus err; int ret = 0; + /* download to temp frame if the output is not padded as libmfx requires */ + AVFrame *tmp_frame = &s->realigned_download_frame; + AVFrame *dst_frame; + int realigned = 0; - while (!s->session_download_init && !s->session_download && !ret) { -#if HAVE_PTHREADS - if (pthread_mutex_trylock(&s->session_lock) == 0) { -#endif - if (!s->session_download_init) { - ret = qsv_init_internal_session(ctx, &s->session_download, 0); - if (s->session_download) - s->session_download_init = 1; - } -#if HAVE_PTHREADS - pthread_mutex_unlock(&s->session_lock); - pthread_cond_signal(&s->session_cond); - } else { - pthread_mutex_lock(&s->session_lock); - while (!s->session_download_init && !s->session_download) { - pthread_cond_wait(&s->session_cond, &s->session_lock); - } - pthread_mutex_unlock(&s->session_lock); - } -#endif - } - + ret = qsv_internal_session_check_init(ctx, 0); if (ret < 0) return ret; + /* According to MSDK spec for mfxframeinfo, "Width must be a multiple of 16. + * Height must be a multiple of 16 for progressive frame sequence and a + * multiple of 32 otherwise.", so allign all frames to 16 before downloading. */ + if (dst->height & 15 || dst->linesize[0] & 15) { + realigned = 1; + if (tmp_frame->format != dst->format || + tmp_frame->width != FFALIGN(dst->linesize[0], 16) || + tmp_frame->height != FFALIGN(dst->height, 16)) { + av_frame_unref(tmp_frame); + + tmp_frame->format = dst->format; + tmp_frame->width = FFALIGN(dst->linesize[0], 16); + tmp_frame->height = FFALIGN(dst->height, 16); + ret = av_frame_get_buffer(tmp_frame, 0); + if (ret < 0) + return ret; + } + } + + dst_frame = realigned ? tmp_frame : dst; + if (!s->session_download) { if (s->child_frames_ref) - return qsv_transfer_data_child(ctx, dst, src); + return qsv_transfer_data_child(ctx, dst_frame, src); av_log(ctx, AV_LOG_ERROR, "Surface download not possible\n"); return AVERROR(ENOSYS); } out.Info = in->Info; - map_frame_to_surface(dst, &out); + map_frame_to_surface(dst_frame, &out); do { err = MFXVideoVPP_RunFrameVPPAsync(s->session_download, in, &out, NULL, &sync); @@ -1056,6 +1128,16 @@ static int qsv_transfer_data_from(AVHWFramesContext *ctx, AVFrame *dst, return AVERROR_UNKNOWN; } + if (realigned) { + tmp_frame->width = dst->width; + tmp_frame->height = dst->height; + ret = av_frame_copy(dst, tmp_frame); + tmp_frame->width = FFALIGN(dst->linesize[0], 16); + tmp_frame->height = FFALIGN(dst->height, 16); + if (ret < 0) + return ret; + } + return 0; } @@ -1071,32 +1153,11 @@ static int qsv_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst, mfxStatus err; int ret = 0; /* make a copy if the input is not padded as libmfx requires */ - AVFrame *tmp_frame = &s->realigned_tmp_frame; + AVFrame *tmp_frame = &s->realigned_upload_frame; const AVFrame *src_frame; int realigned = 0; - - while (!s->session_upload_init && !s->session_upload && !ret) { -#if HAVE_PTHREADS - if (pthread_mutex_trylock(&s->session_lock) == 0) { -#endif - if (!s->session_upload_init) { - ret = qsv_init_internal_session(ctx, &s->session_upload, 1); - if (s->session_upload) - s->session_upload_init = 1; - } -#if HAVE_PTHREADS - pthread_mutex_unlock(&s->session_lock); - pthread_cond_signal(&s->session_cond); - } else { - pthread_mutex_lock(&s->session_lock); - while (!s->session_upload_init && !s->session_upload) { - pthread_cond_wait(&s->session_cond, &s->session_lock); - } - pthread_mutex_unlock(&s->session_lock); - } -#endif - } + ret = qsv_internal_session_check_init(ctx, 1); if (ret < 0) return ret; @@ -1299,7 +1360,8 @@ static int qsv_map_to(AVHWFramesContext *dst_ctx, { mfxHDLPair *pair = (mfxHDLPair*)hwctx->surfaces[i].Data.MemId; if (pair->first == src->data[0] - && pair->second == src->data[1]) { + && (pair->second == src->data[1] + || (pair->second == (mfxMemId)MFX_INFINITE && src->data[1] == (uint8_t *)0))) { index = i; break; } diff --git a/libavutil/hwcontext_stub.c b/libavutil/hwcontext_stub.c new file mode 100644 index 000000000..8683f07fc --- /dev/null +++ b/libavutil/hwcontext_stub.c @@ -0,0 +1,39 @@ +/* + * 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" + +#if !CONFIG_VULKAN +#include +#include "pixfmt.h" + +typedef enum VkFormat VkFormat; +typedef struct AVVkFrame AVVkFrame; +const VkFormat *av_vkfmt_from_pixfmt(enum AVPixelFormat p); +AVVkFrame *av_vk_frame_alloc(void); + +const VkFormat *av_vkfmt_from_pixfmt(enum AVPixelFormat p) +{ + return NULL; +} + +AVVkFrame *av_vk_frame_alloc(void) +{ + return NULL; +} +#endif /* CONFIG_VULKAN */ diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c index 994b744e4..c3a98bc4b 100644 --- a/libavutil/hwcontext_vaapi.c +++ b/libavutil/hwcontext_vaapi.c @@ -1026,7 +1026,12 @@ static void vaapi_unmap_from_drm(AVHWFramesContext *dst_fc, static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst, const AVFrame *src, int flags) { +#if VA_CHECK_VERSION(1, 1, 0) VAAPIFramesContext *src_vafc = src_fc->internal->priv; + int use_prime2; +#else + int k; +#endif AVHWFramesContext *dst_fc = (AVHWFramesContext*)dst->hw_frames_ctx->data; AVVAAPIDeviceContext *dst_dev = dst_fc->device_ctx->hwctx; @@ -1034,10 +1039,28 @@ static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst, const VAAPIFormatDescriptor *format_desc; VASurfaceID surface_id; VAStatus vas = VA_STATUS_SUCCESS; - int use_prime2; uint32_t va_fourcc; int err, i, j; +#if !VA_CHECK_VERSION(1, 1, 0) + unsigned long buffer_handle; + VASurfaceAttribExternalBuffers buffer_desc; + VASurfaceAttrib attrs[2] = { + { + .type = VASurfaceAttribMemoryType, + .flags = VA_SURFACE_ATTRIB_SETTABLE, + .value.type = VAGenericValueTypeInteger, + .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME, + }, + { + .type = VASurfaceAttribExternalBufferDescriptor, + .flags = VA_SURFACE_ATTRIB_SETTABLE, + .value.type = VAGenericValueTypePointer, + .value.value.p = &buffer_desc, + } + }; +#endif + desc = (AVDRMFrameDescriptor*)src->data[0]; if (desc->nb_objects != 1) { @@ -1072,6 +1095,7 @@ static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst, format_desc = vaapi_format_from_fourcc(va_fourcc); av_assert0(format_desc); +#if VA_CHECK_VERSION(1, 1, 0) use_prime2 = !src_vafc->prime_2_import_unsupported && desc->objects[0].format_modifier != DRM_FORMAT_MOD_INVALID; if (use_prime2) { @@ -1183,6 +1207,37 @@ static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst, &surface_id, 1, buffer_attrs, FF_ARRAY_ELEMS(buffer_attrs)); } +#else + buffer_handle = desc->objects[0].fd; + buffer_desc.pixel_format = va_fourcc; + buffer_desc.width = src_fc->width; + buffer_desc.height = src_fc->height; + buffer_desc.data_size = desc->objects[0].size; + buffer_desc.buffers = &buffer_handle; + buffer_desc.num_buffers = 1; + buffer_desc.flags = 0; + + k = 0; + for (i = 0; i < desc->nb_layers; i++) { + for (j = 0; j < desc->layers[i].nb_planes; j++) { + buffer_desc.pitches[k] = desc->layers[i].planes[j].pitch; + buffer_desc.offsets[k] = desc->layers[i].planes[j].offset; + ++k; + } + } + buffer_desc.num_planes = k; + + if (format_desc->chroma_planes_swapped && + buffer_desc.num_planes == 3) { + FFSWAP(uint32_t, buffer_desc.pitches[1], buffer_desc.pitches[2]); + FFSWAP(uint32_t, buffer_desc.offsets[1], buffer_desc.offsets[2]); + } + + vas = vaCreateSurfaces(dst_dev->display, format_desc->rt_format, + src->width, src->height, + &surface_id, 1, + attrs, FF_ARRAY_ELEMS(attrs)); +#endif if (vas != VA_STATUS_SUCCESS) { av_log(dst_fc, AV_LOG_ERROR, "Failed to create surface from DRM " "object: %d (%s).\n", vas, vaErrorStr(vas)); diff --git a/libavutil/hwcontext_videotoolbox.c b/libavutil/hwcontext_videotoolbox.c index 0a8dbe9f3..e442a9500 100644 --- a/libavutil/hwcontext_videotoolbox.c +++ b/libavutil/hwcontext_videotoolbox.c @@ -210,9 +210,36 @@ static int vt_pool_alloc(AVHWFramesContext *ctx) return AVERROR_EXTERNAL; } -static AVBufferRef *vt_dummy_pool_alloc(void *opaque, size_t size) +static void videotoolbox_buffer_release(void *opaque, uint8_t *data) { - return NULL; + CVPixelBufferRelease((CVPixelBufferRef)data); +} + +static AVBufferRef *vt_pool_alloc_buffer(void *opaque, size_t size) +{ + CVPixelBufferRef pixbuf; + AVBufferRef *buf; + CVReturn err; + AVHWFramesContext *ctx = opaque; + VTFramesContext *fctx = ctx->internal->priv; + + err = CVPixelBufferPoolCreatePixelBuffer( + NULL, + fctx->pool, + &pixbuf + ); + if (err != kCVReturnSuccess) { + av_log(ctx, AV_LOG_ERROR, "Failed to create pixel buffer from pool: %d\n", err); + return NULL; + } + + buf = av_buffer_create((uint8_t *)pixbuf, size, + videotoolbox_buffer_release, NULL, 0); + if (!buf) { + CVPixelBufferRelease(pixbuf); + return NULL; + } + return buf; } static void vt_frames_uninit(AVHWFramesContext *ctx) @@ -238,9 +265,9 @@ static int vt_frames_init(AVHWFramesContext *ctx) return AVERROR(ENOSYS); } - // create a dummy pool so av_hwframe_get_buffer doesn't EINVAL if (!ctx->pool) { - ctx->internal->pool_internal = av_buffer_pool_init2(0, ctx, vt_dummy_pool_alloc, NULL); + ctx->internal->pool_internal = av_buffer_pool_init2( + sizeof(CVPixelBufferRef), ctx, vt_pool_alloc_buffer, NULL); if (!ctx->internal->pool_internal) return AVERROR(ENOMEM); } @@ -252,41 +279,11 @@ static int vt_frames_init(AVHWFramesContext *ctx) return 0; } -static void videotoolbox_buffer_release(void *opaque, uint8_t *data) -{ - CVPixelBufferRelease((CVPixelBufferRef)data); -} - static int vt_get_buffer(AVHWFramesContext *ctx, AVFrame *frame) { - VTFramesContext *fctx = ctx->internal->priv; - - if (ctx->pool && ctx->pool->size != 0) { - frame->buf[0] = av_buffer_pool_get(ctx->pool); - if (!frame->buf[0]) - return AVERROR(ENOMEM); - } else { - CVPixelBufferRef pixbuf; - AVBufferRef *buf = NULL; - CVReturn err; - - err = CVPixelBufferPoolCreatePixelBuffer( - NULL, - fctx->pool, - &pixbuf - ); - if (err != kCVReturnSuccess) { - av_log(ctx, AV_LOG_ERROR, "Failed to create pixel buffer from pool: %d\n", err); - return AVERROR_EXTERNAL; - } - - buf = av_buffer_create((uint8_t *)pixbuf, 1, videotoolbox_buffer_release, NULL, 0); - if (!buf) { - CVPixelBufferRelease(pixbuf); - return AVERROR(ENOMEM); - } - frame->buf[0] = buf; - } + frame->buf[0] = av_buffer_pool_get(ctx->pool); + if (!frame->buf[0]) + return AVERROR(ENOMEM); frame->data[3] = frame->buf[0]->data; frame->format = AV_PIX_FMT_VIDEOTOOLBOX; @@ -711,6 +708,30 @@ fail: return err; } +static int vt_map_from(AVHWFramesContext *hwfc, AVFrame *dst, + const AVFrame *src, int flags) +{ + int err; + + if (dst->format == AV_PIX_FMT_NONE) + dst->format = hwfc->sw_format; + else if (dst->format != hwfc->sw_format) + return AVERROR(ENOSYS); + + err = vt_map_frame(hwfc, dst, src, flags); + if (err) + return err; + + dst->width = src->width; + dst->height = src->height; + + err = av_frame_copy_props(dst, src); + if (err) + return err; + + return 0; +} + static int vt_device_create(AVHWDeviceContext *ctx, const char *device, AVDictionary *opts, int flags) { @@ -736,6 +757,7 @@ const HWContextType ff_hwcontext_type_videotoolbox = { .transfer_get_formats = vt_transfer_get_formats, .transfer_data_to = vt_transfer_data_to, .transfer_data_from = vt_transfer_data_from, + .map_from = vt_map_from, .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_VIDEOTOOLBOX, AV_PIX_FMT_NONE }, }; diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 60a6cf6a9..237caa4bc 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -1054,7 +1054,7 @@ static int setup_queue_families(AVHWDeviceContext *ctx, VkDeviceCreateInfo *cd) SETUP_QUEUE(enc_index) SETUP_QUEUE(dec_index) -#undef ADD_QUEUE +#undef SETUP_QUEUE av_free(qf); @@ -1321,8 +1321,18 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, VulkanDevicePriv *p = ctx->internal->priv; FFVulkanFunctions *vk = &p->vkfn; AVVulkanDeviceContext *hwctx = ctx->hwctx; + + /* + * VkPhysicalDeviceVulkan12Features has a timelineSemaphore field, but + * MoltenVK doesn't implement VkPhysicalDeviceVulkan12Features yet, so we + * use VkPhysicalDeviceTimelineSemaphoreFeatures directly. + */ + VkPhysicalDeviceTimelineSemaphoreFeatures timeline_features = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES, + }; VkPhysicalDeviceVulkan12Features dev_features_1_2 = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES, + .pNext = &timeline_features, }; VkPhysicalDeviceVulkan11Features dev_features_1_1 = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES, @@ -1366,7 +1376,7 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, #undef COPY_FEATURE /* We require timeline semaphores */ - if (!dev_features_1_2.timelineSemaphore) { + if (!timeline_features.timelineSemaphore) { av_log(ctx, AV_LOG_ERROR, "Device does not support timeline semaphores!\n"); err = AVERROR(ENOSYS); goto end; @@ -2927,6 +2937,7 @@ static int vulkan_map_from_drm(AVHWFramesContext *hwfc, AVFrame *dst, fail: vulkan_frame_free(hwfc->device_ctx->hwctx, (uint8_t *)f); + dst->data[0] = NULL; return err; } diff --git a/libavutil/imgutils.h b/libavutil/imgutils.h index cb2d74728..be5333556 100644 --- a/libavutil/imgutils.h +++ b/libavutil/imgutils.h @@ -27,8 +27,10 @@ * @{ */ -#include "avutil.h" +#include +#include #include "pixdesc.h" +#include "pixfmt.h" #include "rational.h" /** diff --git a/libavutil/integer.c b/libavutil/integer.c index 78e252fbd..b709c6d48 100644 --- a/libavutil/integer.c +++ b/libavutil/integer.c @@ -25,9 +25,11 @@ * @author Michael Niedermayer */ -#include "common.h" +#include + #include "integer.h" #include "avassert.h" +#include "intmath.h" static const AVInteger zero_i; diff --git a/libavutil/integer.h b/libavutil/integer.h index 45f733c04..2d9b5bb10 100644 --- a/libavutil/integer.h +++ b/libavutil/integer.h @@ -29,7 +29,7 @@ #define AVUTIL_INTEGER_H #include -#include "common.h" +#include "attributes.h" #define AV_INTEGER_SIZE 8 diff --git a/libavutil/internal.h b/libavutil/internal.h index 0a7f1c625..b44cbaaa7 100644 --- a/libavutil/internal.h +++ b/libavutil/internal.h @@ -37,13 +37,13 @@ #include #include #include +#include #include "config.h" #include "attributes.h" #include "timer.h" #include "dict.h" #include "macros.h" #include "pixfmt.h" -#include "version.h" #if ARCH_X86 # include "x86/emms.h" @@ -184,8 +184,10 @@ void avpriv_request_sample(void *avc, #pragma comment(linker, "/include:" EXTERN_PREFIX "avpriv_snprintf") #endif +#define avpriv_fopen_utf8 ff_fopen_utf8 #define avpriv_open ff_open #define avpriv_tempfile ff_tempfile + #define PTRDIFF_SPECIFIER "Id" #define SIZE_SPECIFIER "Iu" #else @@ -257,6 +259,11 @@ static av_always_inline av_const int64_t ff_rint64_clip(double a, int64_t amin, av_warn_unused_result int avpriv_open(const char *filename, int flags, ...); +/** + * Open a file using a UTF-8 filename. + */ +FILE *avpriv_fopen_utf8(const char *path, const char *mode); + /** * Wrapper to work around the lack of mkstemp() on mingw. * Also, tries to create file in /tmp first, if possible. diff --git a/libavutil/lls.c b/libavutil/lls.c index 3a136baa2..c1e038daf 100644 --- a/libavutil/lls.c +++ b/libavutil/lls.c @@ -28,8 +28,8 @@ #include #include +#include "config.h" #include "attributes.h" -#include "internal.h" #include "lls.h" static void update_lls(LLSModel *m, const double *var) @@ -117,6 +117,7 @@ av_cold void avpriv_init_lls(LLSModel *m, int indep_count) m->indep_count = indep_count; m->update_lls = update_lls; m->evaluate_lls = evaluate_lls; - if (ARCH_X86) - ff_init_lls_x86(m); +#if ARCH_X86 + ff_init_lls_x86(m); +#endif } diff --git a/libavutil/log.c b/libavutil/log.c index 66defa9c4..5948e5046 100644 --- a/libavutil/log.c +++ b/libavutil/log.c @@ -32,9 +32,11 @@ #if HAVE_IO_H #include #endif +#include #include +#include #include -#include "avutil.h" +#include #include "bprint.h" #include "common.h" #include "internal.h" diff --git a/libavutil/log.h b/libavutil/log.h index 99625af53..ab7ceabe2 100644 --- a/libavutil/log.h +++ b/libavutil/log.h @@ -22,8 +22,8 @@ #define AVUTIL_LOG_H #include -#include "avutil.h" #include "attributes.h" +#include "version.h" typedef enum { AV_CLASS_CATEGORY_NA = 0, diff --git a/libavutil/loongarch/loongson_intrinsics.h b/libavutil/loongarch/loongson_intrinsics.h index 6e0439f82..eb256863c 100644 --- a/libavutil/loongarch/loongson_intrinsics.h +++ b/libavutil/loongarch/loongson_intrinsics.h @@ -33,7 +33,7 @@ * Xiwei Gu * Lu Wang * - * This file is a header file for loongarch builtin extention. + * This file is a header file for loongarch builtin extension. * */ @@ -42,50 +42,50 @@ /** * MAJOR version: Macro usage changes. - * MINOR version: Add new functions, or bug fix. + * MINOR version: Add new functions, or bug fixes. * MICRO version: Comment changes or implementation changes. */ #define LSOM_VERSION_MAJOR 1 -#define LSOM_VERSION_MINOR 0 -#define LSOM_VERSION_MICRO 3 +#define LSOM_VERSION_MINOR 1 +#define LSOM_VERSION_MICRO 0 #define DUP2_ARG1(_INS, _IN0, _IN1, _OUT0, _OUT1) \ -{ \ - _OUT0 = _INS(_IN0); \ - _OUT1 = _INS(_IN1); \ -} + { \ + _OUT0 = _INS(_IN0); \ + _OUT1 = _INS(_IN1); \ + } #define DUP2_ARG2(_INS, _IN0, _IN1, _IN2, _IN3, _OUT0, _OUT1) \ -{ \ - _OUT0 = _INS(_IN0, _IN1); \ - _OUT1 = _INS(_IN2, _IN3); \ -} + { \ + _OUT0 = _INS(_IN0, _IN1); \ + _OUT1 = _INS(_IN2, _IN3); \ + } #define DUP2_ARG3(_INS, _IN0, _IN1, _IN2, _IN3, _IN4, _IN5, _OUT0, _OUT1) \ -{ \ - _OUT0 = _INS(_IN0, _IN1, _IN2); \ - _OUT1 = _INS(_IN3, _IN4, _IN5); \ -} + { \ + _OUT0 = _INS(_IN0, _IN1, _IN2); \ + _OUT1 = _INS(_IN3, _IN4, _IN5); \ + } #define DUP4_ARG1(_INS, _IN0, _IN1, _IN2, _IN3, _OUT0, _OUT1, _OUT2, _OUT3) \ -{ \ - DUP2_ARG1(_INS, _IN0, _IN1, _OUT0, _OUT1); \ - DUP2_ARG1(_INS, _IN2, _IN3, _OUT2, _OUT3); \ -} + { \ + DUP2_ARG1(_INS, _IN0, _IN1, _OUT0, _OUT1); \ + DUP2_ARG1(_INS, _IN2, _IN3, _OUT2, _OUT3); \ + } -#define DUP4_ARG2(_INS, _IN0, _IN1, _IN2, _IN3, _IN4, _IN5, _IN6, _IN7, \ - _OUT0, _OUT1, _OUT2, _OUT3) \ -{ \ - DUP2_ARG2(_INS, _IN0, _IN1, _IN2, _IN3, _OUT0, _OUT1); \ - DUP2_ARG2(_INS, _IN4, _IN5, _IN6, _IN7, _OUT2, _OUT3); \ -} +#define DUP4_ARG2(_INS, _IN0, _IN1, _IN2, _IN3, _IN4, _IN5, _IN6, _IN7, _OUT0, \ + _OUT1, _OUT2, _OUT3) \ + { \ + DUP2_ARG2(_INS, _IN0, _IN1, _IN2, _IN3, _OUT0, _OUT1); \ + DUP2_ARG2(_INS, _IN4, _IN5, _IN6, _IN7, _OUT2, _OUT3); \ + } -#define DUP4_ARG3(_INS, _IN0, _IN1, _IN2, _IN3, _IN4, _IN5, _IN6, _IN7, \ - _IN8, _IN9, _IN10, _IN11, _OUT0, _OUT1, _OUT2, _OUT3) \ -{ \ - DUP2_ARG3(_INS, _IN0, _IN1, _IN2, _IN3, _IN4, _IN5, _OUT0, _OUT1); \ - DUP2_ARG3(_INS, _IN6, _IN7, _IN8, _IN9, _IN10, _IN11, _OUT2, _OUT3); \ -} +#define DUP4_ARG3(_INS, _IN0, _IN1, _IN2, _IN3, _IN4, _IN5, _IN6, _IN7, _IN8, \ + _IN9, _IN10, _IN11, _OUT0, _OUT1, _OUT2, _OUT3) \ + { \ + DUP2_ARG3(_INS, _IN0, _IN1, _IN2, _IN3, _IN4, _IN5, _OUT0, _OUT1); \ + DUP2_ARG3(_INS, _IN6, _IN7, _IN8, _IN9, _IN10, _IN11, _OUT2, _OUT3); \ + } #ifdef __loongarch_sx #include @@ -94,11 +94,11 @@ * Description : Dot product & addition of byte vector elements * Arguments : Inputs - in_c, in_h, in_l * Outputs - out - * Retrun Type - halfword + * Return Type - halfword * Details : Signed byte elements from in_h are multiplied by * signed byte elements from in_l, and then added adjacent to * each other to get results with the twice size of input. - * Then the results plus to signed half word elements from in_c. + * Then the results plus to signed half-word elements from in_c. * Example : out = __lsx_vdp2add_h_b(in_c, in_h, in_l) * in_c : 1,2,3,4, 1,2,3,4 * in_h : 1,2,3,4, 5,6,7,8, 1,2,3,4, 5,6,7,8 @@ -106,13 +106,13 @@ * out : 23,40,41,26, 23,40,41,26 * ============================================================================= */ -static inline __m128i __lsx_vdp2add_h_b(__m128i in_c, __m128i in_h, __m128i in_l) -{ - __m128i out; +static inline __m128i __lsx_vdp2add_h_b(__m128i in_c, __m128i in_h, + __m128i in_l) { + __m128i out; - out = __lsx_vmaddwev_h_b(in_c, in_h, in_l); - out = __lsx_vmaddwod_h_b(out, in_h, in_l); - return out; + out = __lsx_vmaddwev_h_b(in_c, in_h, in_l); + out = __lsx_vmaddwod_h_b(out, in_h, in_l); + return out; } /* @@ -120,35 +120,61 @@ static inline __m128i __lsx_vdp2add_h_b(__m128i in_c, __m128i in_h, __m128i in_l * Description : Dot product & addition of byte vector elements * Arguments : Inputs - in_c, in_h, in_l * Outputs - out - * Retrun Type - halfword + * Return Type - halfword * Details : Unsigned byte elements from in_h are multiplied by * unsigned byte elements from in_l, and then added adjacent to * each other to get results with the twice size of input. - * The results plus to signed half word elements from in_c. - * Example : out = __lsx_vdp2add_h_b(in_c, in_h, in_l) + * The results plus to signed half-word elements from in_c. + * Example : out = __lsx_vdp2add_h_bu(in_c, in_h, in_l) * in_c : 1,2,3,4, 1,2,3,4 * in_h : 1,2,3,4, 5,6,7,8, 1,2,3,4, 5,6,7,8 * in_l : 8,7,6,5, 4,3,2,1, 8,7,6,5, 4,3,2,1 * out : 23,40,41,26, 23,40,41,26 * ============================================================================= */ -static inline __m128i __lsx_vdp2add_h_bu(__m128i in_c, __m128i in_h, __m128i in_l) -{ - __m128i out; +static inline __m128i __lsx_vdp2add_h_bu(__m128i in_c, __m128i in_h, + __m128i in_l) { + __m128i out; - out = __lsx_vmaddwev_h_bu(in_c, in_h, in_l); - out = __lsx_vmaddwod_h_bu(out, in_h, in_l); - return out; + out = __lsx_vmaddwev_h_bu(in_c, in_h, in_l); + out = __lsx_vmaddwod_h_bu(out, in_h, in_l); + return out; } /* * ============================================================================= - * Description : Dot product & addition of half word vector elements + * Description : Dot product & addition of byte vector elements * Arguments : Inputs - in_c, in_h, in_l * Outputs - out - * Retrun Type - __m128i - * Details : Signed half word elements from in_h are multiplied by - * signed half word elements from in_l, and then added adjacent to + * Return Type - halfword + * Details : Unsigned byte elements from in_h are multiplied by + * signed byte elements from in_l, and then added adjacent to + * each other to get results with the twice size of input. + * The results plus to signed half-word elements from in_c. + * Example : out = __lsx_vdp2add_h_bu_b(in_c, in_h, in_l) + * in_c : 1,1,1,1, 1,1,1,1 + * in_h : 1,2,3,4, 5,6,7,8, 1,2,3,4, 5,6,7,8 + * in_l : -1,-2,-3,-4, -5,-6,-7,-8, 1,2,3,4, 5,6,7,8 + * out : -4,-24,-60,-112, 6,26,62,114 + * ============================================================================= + */ +static inline __m128i __lsx_vdp2add_h_bu_b(__m128i in_c, __m128i in_h, + __m128i in_l) { + __m128i out; + + out = __lsx_vmaddwev_h_bu_b(in_c, in_h, in_l); + out = __lsx_vmaddwod_h_bu_b(out, in_h, in_l); + return out; +} + +/* + * ============================================================================= + * Description : Dot product & addition of half-word vector elements + * Arguments : Inputs - in_c, in_h, in_l + * Outputs - out + * Return Type - __m128i + * Details : Signed half-word elements from in_h are multiplied by + * signed half-word elements from in_l, and then added adjacent to * each other to get results with the twice size of input. * Then the results plus to signed word elements from in_c. * Example : out = __lsx_vdp2add_h_b(in_c, in_h, in_l) @@ -158,13 +184,13 @@ static inline __m128i __lsx_vdp2add_h_bu(__m128i in_c, __m128i in_h, __m128i in_ * out : 23,40,41,26 * ============================================================================= */ -static inline __m128i __lsx_vdp2add_w_h(__m128i in_c, __m128i in_h, __m128i in_l) -{ - __m128i out; +static inline __m128i __lsx_vdp2add_w_h(__m128i in_c, __m128i in_h, + __m128i in_l) { + __m128i out; - out = __lsx_vmaddwev_w_h(in_c, in_h, in_l); - out = __lsx_vmaddwod_w_h(out, in_h, in_l); - return out; + out = __lsx_vmaddwev_w_h(in_c, in_h, in_l); + out = __lsx_vmaddwod_w_h(out, in_h, in_l); + return out; } /* @@ -172,7 +198,7 @@ static inline __m128i __lsx_vdp2add_w_h(__m128i in_c, __m128i in_h, __m128i in_l * Description : Dot product of byte vector elements * Arguments : Inputs - in_h, in_l * Outputs - out - * Retrun Type - halfword + * Return Type - halfword * Details : Signed byte elements from in_h are multiplied by * signed byte elements from in_l, and then added adjacent to * each other to get results with the twice size of input. @@ -182,13 +208,12 @@ static inline __m128i __lsx_vdp2add_w_h(__m128i in_c, __m128i in_h, __m128i in_l * out : 22,38,38,22, 22,38,38,22 * ============================================================================= */ -static inline __m128i __lsx_vdp2_h_b(__m128i in_h, __m128i in_l) -{ - __m128i out; +static inline __m128i __lsx_vdp2_h_b(__m128i in_h, __m128i in_l) { + __m128i out; - out = __lsx_vmulwev_h_b(in_h, in_l); - out = __lsx_vmaddwod_h_b(out, in_h, in_l); - return out; + out = __lsx_vmulwev_h_b(in_h, in_l); + out = __lsx_vmaddwod_h_b(out, in_h, in_l); + return out; } /* @@ -196,7 +221,7 @@ static inline __m128i __lsx_vdp2_h_b(__m128i in_h, __m128i in_l) * Description : Dot product of byte vector elements * Arguments : Inputs - in_h, in_l * Outputs - out - * Retrun Type - halfword + * Return Type - halfword * Details : Unsigned byte elements from in_h are multiplied by * unsigned byte elements from in_l, and then added adjacent to * each other to get results with the twice size of input. @@ -206,13 +231,12 @@ static inline __m128i __lsx_vdp2_h_b(__m128i in_h, __m128i in_l) * out : 22,38,38,22, 22,38,38,22 * ============================================================================= */ -static inline __m128i __lsx_vdp2_h_bu(__m128i in_h, __m128i in_l) -{ - __m128i out; +static inline __m128i __lsx_vdp2_h_bu(__m128i in_h, __m128i in_l) { + __m128i out; - out = __lsx_vmulwev_h_bu(in_h, in_l); - out = __lsx_vmaddwod_h_bu(out, in_h, in_l); - return out; + out = __lsx_vmulwev_h_bu(in_h, in_l); + out = __lsx_vmaddwod_h_bu(out, in_h, in_l); + return out; } /* @@ -220,7 +244,7 @@ static inline __m128i __lsx_vdp2_h_bu(__m128i in_h, __m128i in_l) * Description : Dot product of byte vector elements * Arguments : Inputs - in_h, in_l * Outputs - out - * Retrun Type - halfword + * Return Type - halfword * Details : Unsigned byte elements from in_h are multiplied by * signed byte elements from in_l, and then added adjacent to * each other to get results with the twice size of input. @@ -230,13 +254,12 @@ static inline __m128i __lsx_vdp2_h_bu(__m128i in_h, __m128i in_l) * out : 22,38,38,22, 22,38,38,6 * ============================================================================= */ -static inline __m128i __lsx_vdp2_h_bu_b(__m128i in_h, __m128i in_l) -{ - __m128i out; +static inline __m128i __lsx_vdp2_h_bu_b(__m128i in_h, __m128i in_l) { + __m128i out; - out = __lsx_vmulwev_h_bu_b(in_h, in_l); - out = __lsx_vmaddwod_h_bu_b(out, in_h, in_l); - return out; + out = __lsx_vmulwev_h_bu_b(in_h, in_l); + out = __lsx_vmaddwod_h_bu_b(out, in_h, in_l); + return out; } /* @@ -244,7 +267,7 @@ static inline __m128i __lsx_vdp2_h_bu_b(__m128i in_h, __m128i in_l) * Description : Dot product of byte vector elements * Arguments : Inputs - in_h, in_l * Outputs - out - * Retrun Type - halfword + * Return Type - halfword * Details : Signed byte elements from in_h are multiplied by * signed byte elements from in_l, and then added adjacent to * each other to get results with the twice size of input. @@ -254,19 +277,19 @@ static inline __m128i __lsx_vdp2_h_bu_b(__m128i in_h, __m128i in_l) * out : 22,38,38,22 * ============================================================================= */ -static inline __m128i __lsx_vdp2_w_h(__m128i in_h, __m128i in_l) -{ - __m128i out; +static inline __m128i __lsx_vdp2_w_h(__m128i in_h, __m128i in_l) { + __m128i out; - out = __lsx_vmulwev_w_h(in_h, in_l); - out = __lsx_vmaddwod_w_h(out, in_h, in_l); - return out; + out = __lsx_vmulwev_w_h(in_h, in_l); + out = __lsx_vmaddwod_w_h(out, in_h, in_l); + return out; } /* * ============================================================================= * Description : Clip all halfword elements of input vector between min & max - * out = ((_in) < (min)) ? (min) : (((_in) > (max)) ? (max) : (_in)) + * out = ((_in) < (min)) ? (min) : (((_in) > (max)) ? (max) : + * (_in)) * Arguments : Inputs - _in (input vector) * - min (min threshold) * - max (max threshold) @@ -279,13 +302,12 @@ static inline __m128i __lsx_vdp2_w_h(__m128i in_h, __m128i in_l) * out : 1,2,9,9, 1,9,9,9 * ============================================================================= */ -static inline __m128i __lsx_vclip_h(__m128i _in, __m128i min, __m128i max) -{ - __m128i out; +static inline __m128i __lsx_vclip_h(__m128i _in, __m128i min, __m128i max) { + __m128i out; - out = __lsx_vmax_h(min, _in); - out = __lsx_vmin_h(max, out); - return out; + out = __lsx_vmax_h(min, _in); + out = __lsx_vmin_h(max, out); + return out; } /* @@ -293,20 +315,19 @@ static inline __m128i __lsx_vclip_h(__m128i _in, __m128i min, __m128i max) * Description : Set each element of vector between 0 and 255 * Arguments : Inputs - _in * Outputs - out - * Retrun Type - halfword + * Return Type - halfword * Details : Signed byte elements from _in are clamped between 0 and 255. * Example : out = __lsx_vclip255_h(_in) * _in : -8,255,280,249, -8,255,280,249 * out : 0,255,255,249, 0,255,255,249 * ============================================================================= */ -static inline __m128i __lsx_vclip255_h(__m128i _in) -{ - __m128i out; +static inline __m128i __lsx_vclip255_h(__m128i _in) { + __m128i out; - out = __lsx_vmaxi_h(_in, 0); - out = __lsx_vsat_hu(out, 7); - return out; + out = __lsx_vmaxi_h(_in, 0); + out = __lsx_vsat_hu(out, 7); + return out; } /* @@ -314,20 +335,19 @@ static inline __m128i __lsx_vclip255_h(__m128i _in) * Description : Set each element of vector between 0 and 255 * Arguments : Inputs - _in * Outputs - out - * Retrun Type - word + * Return Type - word * Details : Signed byte elements from _in are clamped between 0 and 255. * Example : out = __lsx_vclip255_w(_in) * _in : -8,255,280,249 * out : 0,255,255,249 * ============================================================================= */ -static inline __m128i __lsx_vclip255_w(__m128i _in) -{ - __m128i out; +static inline __m128i __lsx_vclip255_w(__m128i _in) { + __m128i out; - out = __lsx_vmaxi_w(_in, 0); - out = __lsx_vsat_wu(out, 7); - return out; + out = __lsx_vmaxi_w(_in, 0); + out = __lsx_vsat_wu(out, 7); + return out; } /* @@ -343,12 +363,12 @@ static inline __m128i __lsx_vclip255_w(__m128i _in) * _in1(out) : 1,2,3,4 * ============================================================================= */ -#define LSX_SWAP(_in0, _in1) \ -{ \ - _in0 = __lsx_vxor_v(_in0, _in1); \ - _in1 = __lsx_vxor_v(_in0, _in1); \ - _in0 = __lsx_vxor_v(_in0, _in1); \ -} \ +#define LSX_SWAP(_in0, _in1) \ + { \ + _in0 = __lsx_vxor_v(_in0, _in1); \ + _in1 = __lsx_vxor_v(_in0, _in1); \ + _in0 = __lsx_vxor_v(_in0, _in1); \ + } /* * ============================================================================= @@ -364,25 +384,27 @@ static inline __m128i __lsx_vclip255_w(__m128i _in) * ============================================================================= */ #define LSX_TRANSPOSE4x4_W(_in0, _in1, _in2, _in3, _out0, _out1, _out2, _out3) \ -{ \ + { \ __m128i _t0, _t1, _t2, _t3; \ \ - _t0 = __lsx_vilvl_w(_in1, _in0); \ - _t1 = __lsx_vilvh_w(_in1, _in0); \ - _t2 = __lsx_vilvl_w(_in3, _in2); \ - _t3 = __lsx_vilvh_w(_in3, _in2); \ + _t0 = __lsx_vilvl_w(_in1, _in0); \ + _t1 = __lsx_vilvh_w(_in1, _in0); \ + _t2 = __lsx_vilvl_w(_in3, _in2); \ + _t3 = __lsx_vilvh_w(_in3, _in2); \ _out0 = __lsx_vilvl_d(_t2, _t0); \ _out1 = __lsx_vilvh_d(_t2, _t0); \ _out2 = __lsx_vilvl_d(_t3, _t1); \ _out3 = __lsx_vilvh_d(_t3, _t1); \ -} + } /* * ============================================================================= * Description : Transpose 8x8 block with byte elements in vectors * Arguments : Inputs - _in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7 - * Outputs - _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7 - * Details : The rows of the matrix become columns, and the columns become rows. + * Outputs - _out0, _out1, _out2, _out3, _out4, _out5, _out6, + * _out7 + * Details : The rows of the matrix become columns, and the columns + * become rows. * Example : LSX_TRANSPOSE8x8_B * _in0 : 00,01,02,03,04,05,06,07, 00,00,00,00,00,00,00,00 * _in1 : 10,11,12,13,14,15,16,17, 00,00,00,00,00,00,00,00 @@ -403,34 +425,35 @@ static inline __m128i __lsx_vclip255_w(__m128i _in) * _ out7 : 07,17,27,37,47,57,67,77, 00,00,00,00,00,00,00,00 * ============================================================================= */ -#define LSX_TRANSPOSE8x8_B(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ - _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7)\ -{ \ - __m128i zero = {0}; \ - __m128i shuf8 = {0x0F0E0D0C0B0A0908, 0x1716151413121110}; \ - __m128i _t0, _t1, _t2, _t3, _t4, _t5, _t6, _t7; \ - \ - _t0 = __lsx_vilvl_b(_in2, _in0); \ - _t1 = __lsx_vilvl_b(_in3, _in1); \ - _t2 = __lsx_vilvl_b(_in6, _in4); \ - _t3 = __lsx_vilvl_b(_in7, _in5); \ - _t4 = __lsx_vilvl_b(_t1, _t0); \ - _t5 = __lsx_vilvh_b(_t1, _t0); \ - _t6 = __lsx_vilvl_b(_t3, _t2); \ - _t7 = __lsx_vilvh_b(_t3, _t2); \ - _out0 = __lsx_vilvl_w(_t6, _t4); \ - _out2 = __lsx_vilvh_w(_t6, _t4); \ - _out4 = __lsx_vilvl_w(_t7, _t5); \ - _out6 = __lsx_vilvh_w(_t7, _t5); \ - _out1 = __lsx_vshuf_b(zero, _out0, shuf8); \ - _out3 = __lsx_vshuf_b(zero, _out2, shuf8); \ - _out5 = __lsx_vshuf_b(zero, _out4, shuf8); \ - _out7 = __lsx_vshuf_b(zero, _out6, shuf8); \ -} +#define LSX_TRANSPOSE8x8_B(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _out0, _out1, _out2, _out3, _out4, _out5, _out6, \ + _out7) \ + { \ + __m128i zero = { 0 }; \ + __m128i shuf8 = { 0x0F0E0D0C0B0A0908, 0x1716151413121110 }; \ + __m128i _t0, _t1, _t2, _t3, _t4, _t5, _t6, _t7; \ + \ + _t0 = __lsx_vilvl_b(_in2, _in0); \ + _t1 = __lsx_vilvl_b(_in3, _in1); \ + _t2 = __lsx_vilvl_b(_in6, _in4); \ + _t3 = __lsx_vilvl_b(_in7, _in5); \ + _t4 = __lsx_vilvl_b(_t1, _t0); \ + _t5 = __lsx_vilvh_b(_t1, _t0); \ + _t6 = __lsx_vilvl_b(_t3, _t2); \ + _t7 = __lsx_vilvh_b(_t3, _t2); \ + _out0 = __lsx_vilvl_w(_t6, _t4); \ + _out2 = __lsx_vilvh_w(_t6, _t4); \ + _out4 = __lsx_vilvl_w(_t7, _t5); \ + _out6 = __lsx_vilvh_w(_t7, _t5); \ + _out1 = __lsx_vshuf_b(zero, _out0, shuf8); \ + _out3 = __lsx_vshuf_b(zero, _out2, shuf8); \ + _out5 = __lsx_vshuf_b(zero, _out4, shuf8); \ + _out7 = __lsx_vshuf_b(zero, _out6, shuf8); \ + } /* * ============================================================================= - * Description : Transpose 8x8 block with half word elements in vectors + * Description : Transpose 8x8 block with half-word elements in vectors * Arguments : Inputs - in0, in1, in2, in3, in4, in5, in6, in7 * Outputs - out0, out1, out2, out3, out4, out5, out6, out7 * Details : @@ -445,37 +468,38 @@ static inline __m128i __lsx_vclip255_w(__m128i _in) * 70,71,72,73,74,75,76,77 07,17,27,37,47,57,67,77 * ============================================================================= */ -#define LSX_TRANSPOSE8x8_H(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ - _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7)\ -{ \ - __m128i _s0, _s1, _t0, _t1, _t2, _t3, _t4, _t5, _t6, _t7; \ - \ - _s0 = __lsx_vilvl_h(_in6, _in4); \ - _s1 = __lsx_vilvl_h(_in7, _in5); \ - _t0 = __lsx_vilvl_h(_s1, _s0); \ - _t1 = __lsx_vilvh_h(_s1, _s0); \ - _s0 = __lsx_vilvh_h(_in6, _in4); \ - _s1 = __lsx_vilvh_h(_in7, _in5); \ - _t2 = __lsx_vilvl_h(_s1, _s0); \ - _t3 = __lsx_vilvh_h(_s1, _s0); \ - _s0 = __lsx_vilvl_h(_in2, _in0); \ - _s1 = __lsx_vilvl_h(_in3, _in1); \ - _t4 = __lsx_vilvl_h(_s1, _s0); \ - _t5 = __lsx_vilvh_h(_s1, _s0); \ - _s0 = __lsx_vilvh_h(_in2, _in0); \ - _s1 = __lsx_vilvh_h(_in3, _in1); \ - _t6 = __lsx_vilvl_h(_s1, _s0); \ - _t7 = __lsx_vilvh_h(_s1, _s0); \ - \ - _out0 = __lsx_vpickev_d(_t0, _t4); \ - _out2 = __lsx_vpickev_d(_t1, _t5); \ - _out4 = __lsx_vpickev_d(_t2, _t6); \ - _out6 = __lsx_vpickev_d(_t3, _t7); \ - _out1 = __lsx_vpickod_d(_t0, _t4); \ - _out3 = __lsx_vpickod_d(_t1, _t5); \ - _out5 = __lsx_vpickod_d(_t2, _t6); \ - _out7 = __lsx_vpickod_d(_t3, _t7); \ -} +#define LSX_TRANSPOSE8x8_H(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _out0, _out1, _out2, _out3, _out4, _out5, _out6, \ + _out7) \ + { \ + __m128i _s0, _s1, _t0, _t1, _t2, _t3, _t4, _t5, _t6, _t7; \ + \ + _s0 = __lsx_vilvl_h(_in6, _in4); \ + _s1 = __lsx_vilvl_h(_in7, _in5); \ + _t0 = __lsx_vilvl_h(_s1, _s0); \ + _t1 = __lsx_vilvh_h(_s1, _s0); \ + _s0 = __lsx_vilvh_h(_in6, _in4); \ + _s1 = __lsx_vilvh_h(_in7, _in5); \ + _t2 = __lsx_vilvl_h(_s1, _s0); \ + _t3 = __lsx_vilvh_h(_s1, _s0); \ + _s0 = __lsx_vilvl_h(_in2, _in0); \ + _s1 = __lsx_vilvl_h(_in3, _in1); \ + _t4 = __lsx_vilvl_h(_s1, _s0); \ + _t5 = __lsx_vilvh_h(_s1, _s0); \ + _s0 = __lsx_vilvh_h(_in2, _in0); \ + _s1 = __lsx_vilvh_h(_in3, _in1); \ + _t6 = __lsx_vilvl_h(_s1, _s0); \ + _t7 = __lsx_vilvh_h(_s1, _s0); \ + \ + _out0 = __lsx_vpickev_d(_t0, _t4); \ + _out2 = __lsx_vpickev_d(_t1, _t5); \ + _out4 = __lsx_vpickev_d(_t2, _t6); \ + _out6 = __lsx_vpickev_d(_t3, _t7); \ + _out1 = __lsx_vpickod_d(_t0, _t4); \ + _out3 = __lsx_vpickod_d(_t1, _t5); \ + _out5 = __lsx_vpickod_d(_t2, _t6); \ + _out7 = __lsx_vpickod_d(_t3, _t7); \ + } /* * ============================================================================= @@ -483,7 +507,8 @@ static inline __m128i __lsx_vclip255_w(__m128i _in) * Arguments : Inputs - _in0, _in1, _in2, _in3 (input 8x4 byte block) * Outputs - _out0, _out1, _out2, _out3 (output 4x8 byte block) * Return Type - as per RTYPE - * Details : The rows of the matrix become columns, and the columns become rows. + * Details : The rows of the matrix become columns, and the columns become + * rows. * Example : LSX_TRANSPOSE8x4_B * _in0 : 00,01,02,03,00,00,00,00, 00,00,00,00,00,00,00,00 * _in1 : 10,11,12,13,00,00,00,00, 00,00,00,00,00,00,00,00 @@ -500,26 +525,26 @@ static inline __m128i __lsx_vclip255_w(__m128i _in) * _out3 : 03,13,23,33,43,53,63,73, 00,00,00,00,00,00,00,00 * ============================================================================= */ -#define LSX_TRANSPOSE8x4_B(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ - _out0, _out1, _out2, _out3) \ -{ \ - __m128i _tmp0_m, _tmp1_m, _tmp2_m, _tmp3_m; \ - \ - _tmp0_m = __lsx_vpackev_w(_in4, _in0); \ - _tmp1_m = __lsx_vpackev_w(_in5, _in1); \ - _tmp2_m = __lsx_vilvl_b(_tmp1_m, _tmp0_m); \ - _tmp0_m = __lsx_vpackev_w(_in6, _in2); \ - _tmp1_m = __lsx_vpackev_w(_in7, _in3); \ - \ - _tmp3_m = __lsx_vilvl_b(_tmp1_m, _tmp0_m); \ - _tmp0_m = __lsx_vilvl_h(_tmp3_m, _tmp2_m); \ - _tmp1_m = __lsx_vilvh_h(_tmp3_m, _tmp2_m); \ - \ - _out0 = __lsx_vilvl_w(_tmp1_m, _tmp0_m); \ - _out2 = __lsx_vilvh_w(_tmp1_m, _tmp0_m); \ - _out1 = __lsx_vilvh_d(_out2, _out0); \ - _out3 = __lsx_vilvh_d(_out0, _out2); \ -} +#define LSX_TRANSPOSE8x4_B(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _out0, _out1, _out2, _out3) \ + { \ + __m128i _tmp0_m, _tmp1_m, _tmp2_m, _tmp3_m; \ + \ + _tmp0_m = __lsx_vpackev_w(_in4, _in0); \ + _tmp1_m = __lsx_vpackev_w(_in5, _in1); \ + _tmp2_m = __lsx_vilvl_b(_tmp1_m, _tmp0_m); \ + _tmp0_m = __lsx_vpackev_w(_in6, _in2); \ + _tmp1_m = __lsx_vpackev_w(_in7, _in3); \ + \ + _tmp3_m = __lsx_vilvl_b(_tmp1_m, _tmp0_m); \ + _tmp0_m = __lsx_vilvl_h(_tmp3_m, _tmp2_m); \ + _tmp1_m = __lsx_vilvh_h(_tmp3_m, _tmp2_m); \ + \ + _out0 = __lsx_vilvl_w(_tmp1_m, _tmp0_m); \ + _out2 = __lsx_vilvh_w(_tmp1_m, _tmp0_m); \ + _out1 = __lsx_vilvh_d(_out2, _out0); \ + _out3 = __lsx_vilvh_d(_out0, _out2); \ + } /* * ============================================================================= @@ -547,29 +572,30 @@ static inline __m128i __lsx_vclip255_w(__m128i _in) * 120,121,122,123,124,125,126,127 * ============================================================================= */ -#define LSX_TRANSPOSE16x8_B(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, _in8, \ - _in9, _in10, _in11, _in12, _in13, _in14, _in15, _out0, \ - _out1, _out2, _out3, _out4, _out5, _out6, _out7) \ -{ \ - __m128i _tmp0, _tmp1, _tmp2, _tmp3, _tmp4, _tmp5, _tmp6, _tmp7; \ - __m128i _t0, _t1, _t2, _t3, _t4, _t5, _t6, _t7; \ - DUP4_ARG2(__lsx_vilvl_b, _in2, _in0, _in3, _in1, _in6, _in4, _in7, _in5, \ - _tmp0, _tmp1, _tmp2, _tmp3); \ - DUP4_ARG2(__lsx_vilvl_b, _in10, _in8, _in11, _in9, _in14, _in12, _in15, \ - _in13, _tmp4, _tmp5, _tmp6, _tmp7); \ - DUP2_ARG2(__lsx_vilvl_b, _tmp1, _tmp0, _tmp3, _tmp2, _t0, _t2); \ - DUP2_ARG2(__lsx_vilvh_b, _tmp1, _tmp0, _tmp3, _tmp2, _t1, _t3); \ - DUP2_ARG2(__lsx_vilvl_b, _tmp5, _tmp4, _tmp7, _tmp6, _t4, _t6); \ - DUP2_ARG2(__lsx_vilvh_b, _tmp5, _tmp4, _tmp7, _tmp6, _t5, _t7); \ - DUP2_ARG2(__lsx_vilvl_w, _t2, _t0, _t3, _t1, _tmp0, _tmp4); \ - DUP2_ARG2(__lsx_vilvh_w, _t2, _t0, _t3, _t1, _tmp2, _tmp6); \ - DUP2_ARG2(__lsx_vilvl_w, _t6, _t4, _t7, _t5, _tmp1, _tmp5); \ - DUP2_ARG2(__lsx_vilvh_w, _t6, _t4, _t7, _t5, _tmp3, _tmp7); \ - DUP2_ARG2(__lsx_vilvl_d, _tmp1, _tmp0, _tmp3, _tmp2, _out0, _out2); \ - DUP2_ARG2(__lsx_vilvh_d, _tmp1, _tmp0, _tmp3, _tmp2, _out1, _out3); \ - DUP2_ARG2(__lsx_vilvl_d, _tmp5, _tmp4, _tmp7, _tmp6, _out4, _out6); \ - DUP2_ARG2(__lsx_vilvh_d, _tmp5, _tmp4, _tmp7, _tmp6, _out5, _out7); \ -} +#define LSX_TRANSPOSE16x8_B(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _in8, _in9, _in10, _in11, _in12, _in13, _in14, \ + _in15, _out0, _out1, _out2, _out3, _out4, _out5, \ + _out6, _out7) \ + { \ + __m128i _tmp0, _tmp1, _tmp2, _tmp3, _tmp4, _tmp5, _tmp6, _tmp7; \ + __m128i _t0, _t1, _t2, _t3, _t4, _t5, _t6, _t7; \ + DUP4_ARG2(__lsx_vilvl_b, _in2, _in0, _in3, _in1, _in6, _in4, _in7, _in5, \ + _tmp0, _tmp1, _tmp2, _tmp3); \ + DUP4_ARG2(__lsx_vilvl_b, _in10, _in8, _in11, _in9, _in14, _in12, _in15, \ + _in13, _tmp4, _tmp5, _tmp6, _tmp7); \ + DUP2_ARG2(__lsx_vilvl_b, _tmp1, _tmp0, _tmp3, _tmp2, _t0, _t2); \ + DUP2_ARG2(__lsx_vilvh_b, _tmp1, _tmp0, _tmp3, _tmp2, _t1, _t3); \ + DUP2_ARG2(__lsx_vilvl_b, _tmp5, _tmp4, _tmp7, _tmp6, _t4, _t6); \ + DUP2_ARG2(__lsx_vilvh_b, _tmp5, _tmp4, _tmp7, _tmp6, _t5, _t7); \ + DUP2_ARG2(__lsx_vilvl_w, _t2, _t0, _t3, _t1, _tmp0, _tmp4); \ + DUP2_ARG2(__lsx_vilvh_w, _t2, _t0, _t3, _t1, _tmp2, _tmp6); \ + DUP2_ARG2(__lsx_vilvl_w, _t6, _t4, _t7, _t5, _tmp1, _tmp5); \ + DUP2_ARG2(__lsx_vilvh_w, _t6, _t4, _t7, _t5, _tmp3, _tmp7); \ + DUP2_ARG2(__lsx_vilvl_d, _tmp1, _tmp0, _tmp3, _tmp2, _out0, _out2); \ + DUP2_ARG2(__lsx_vilvh_d, _tmp1, _tmp0, _tmp3, _tmp2, _out1, _out3); \ + DUP2_ARG2(__lsx_vilvl_d, _tmp5, _tmp4, _tmp7, _tmp6, _out4, _out6); \ + DUP2_ARG2(__lsx_vilvh_d, _tmp5, _tmp4, _tmp7, _tmp6, _out5, _out7); \ + } /* * ============================================================================= @@ -585,33 +611,33 @@ static inline __m128i __lsx_vclip255_w(__m128i _in) * ============================================================================= */ #define LSX_BUTTERFLY_4_B(_in0, _in1, _in2, _in3, _out0, _out1, _out2, _out3) \ -{ \ + { \ _out0 = __lsx_vadd_b(_in0, _in3); \ _out1 = __lsx_vadd_b(_in1, _in2); \ _out2 = __lsx_vsub_b(_in1, _in2); \ _out3 = __lsx_vsub_b(_in0, _in3); \ -} + } #define LSX_BUTTERFLY_4_H(_in0, _in1, _in2, _in3, _out0, _out1, _out2, _out3) \ -{ \ + { \ _out0 = __lsx_vadd_h(_in0, _in3); \ _out1 = __lsx_vadd_h(_in1, _in2); \ _out2 = __lsx_vsub_h(_in1, _in2); \ _out3 = __lsx_vsub_h(_in0, _in3); \ -} + } #define LSX_BUTTERFLY_4_W(_in0, _in1, _in2, _in3, _out0, _out1, _out2, _out3) \ -{ \ + { \ _out0 = __lsx_vadd_w(_in0, _in3); \ _out1 = __lsx_vadd_w(_in1, _in2); \ _out2 = __lsx_vsub_w(_in1, _in2); \ _out3 = __lsx_vsub_w(_in0, _in3); \ -} + } #define LSX_BUTTERFLY_4_D(_in0, _in1, _in2, _in3, _out0, _out1, _out2, _out3) \ -{ \ + { \ _out0 = __lsx_vadd_d(_in0, _in3); \ _out1 = __lsx_vadd_d(_in1, _in2); \ _out2 = __lsx_vsub_d(_in1, _in2); \ _out3 = __lsx_vsub_d(_in0, _in3); \ -} + } /* * ============================================================================= @@ -630,59 +656,63 @@ static inline __m128i __lsx_vclip255_w(__m128i _in) * _out7 = _in0 - _in7; * ============================================================================= */ -#define LSX_BUTTERFLY_8_B(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ - _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7)\ -{ \ - _out0 = __lsx_vadd_b(_in0, _in7); \ - _out1 = __lsx_vadd_b(_in1, _in6); \ - _out2 = __lsx_vadd_b(_in2, _in5); \ - _out3 = __lsx_vadd_b(_in3, _in4); \ - _out4 = __lsx_vsub_b(_in3, _in4); \ - _out5 = __lsx_vsub_b(_in2, _in5); \ - _out6 = __lsx_vsub_b(_in1, _in6); \ - _out7 = __lsx_vsub_b(_in0, _in7); \ -} +#define LSX_BUTTERFLY_8_B(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _out0, _out1, _out2, _out3, _out4, _out5, _out6, \ + _out7) \ + { \ + _out0 = __lsx_vadd_b(_in0, _in7); \ + _out1 = __lsx_vadd_b(_in1, _in6); \ + _out2 = __lsx_vadd_b(_in2, _in5); \ + _out3 = __lsx_vadd_b(_in3, _in4); \ + _out4 = __lsx_vsub_b(_in3, _in4); \ + _out5 = __lsx_vsub_b(_in2, _in5); \ + _out6 = __lsx_vsub_b(_in1, _in6); \ + _out7 = __lsx_vsub_b(_in0, _in7); \ + } -#define LSX_BUTTERFLY_8_H(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ - _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7)\ -{ \ - _out0 = __lsx_vadd_h(_in0, _in7); \ - _out1 = __lsx_vadd_h(_in1, _in6); \ - _out2 = __lsx_vadd_h(_in2, _in5); \ - _out3 = __lsx_vadd_h(_in3, _in4); \ - _out4 = __lsx_vsub_h(_in3, _in4); \ - _out5 = __lsx_vsub_h(_in2, _in5); \ - _out6 = __lsx_vsub_h(_in1, _in6); \ - _out7 = __lsx_vsub_h(_in0, _in7); \ -} +#define LSX_BUTTERFLY_8_H(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _out0, _out1, _out2, _out3, _out4, _out5, _out6, \ + _out7) \ + { \ + _out0 = __lsx_vadd_h(_in0, _in7); \ + _out1 = __lsx_vadd_h(_in1, _in6); \ + _out2 = __lsx_vadd_h(_in2, _in5); \ + _out3 = __lsx_vadd_h(_in3, _in4); \ + _out4 = __lsx_vsub_h(_in3, _in4); \ + _out5 = __lsx_vsub_h(_in2, _in5); \ + _out6 = __lsx_vsub_h(_in1, _in6); \ + _out7 = __lsx_vsub_h(_in0, _in7); \ + } -#define LSX_BUTTERFLY_8_W(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ - _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7)\ -{ \ - _out0 = __lsx_vadd_w(_in0, _in7); \ - _out1 = __lsx_vadd_w(_in1, _in6); \ - _out2 = __lsx_vadd_w(_in2, _in5); \ - _out3 = __lsx_vadd_w(_in3, _in4); \ - _out4 = __lsx_vsub_w(_in3, _in4); \ - _out5 = __lsx_vsub_w(_in2, _in5); \ - _out6 = __lsx_vsub_w(_in1, _in6); \ - _out7 = __lsx_vsub_w(_in0, _in7); \ -} +#define LSX_BUTTERFLY_8_W(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _out0, _out1, _out2, _out3, _out4, _out5, _out6, \ + _out7) \ + { \ + _out0 = __lsx_vadd_w(_in0, _in7); \ + _out1 = __lsx_vadd_w(_in1, _in6); \ + _out2 = __lsx_vadd_w(_in2, _in5); \ + _out3 = __lsx_vadd_w(_in3, _in4); \ + _out4 = __lsx_vsub_w(_in3, _in4); \ + _out5 = __lsx_vsub_w(_in2, _in5); \ + _out6 = __lsx_vsub_w(_in1, _in6); \ + _out7 = __lsx_vsub_w(_in0, _in7); \ + } -#define LSX_BUTTERFLY_8_D(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ - _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7)\ -{ \ - _out0 = __lsx_vadd_d(_in0, _in7); \ - _out1 = __lsx_vadd_d(_in1, _in6); \ - _out2 = __lsx_vadd_d(_in2, _in5); \ - _out3 = __lsx_vadd_d(_in3, _in4); \ - _out4 = __lsx_vsub_d(_in3, _in4); \ - _out5 = __lsx_vsub_d(_in2, _in5); \ - _out6 = __lsx_vsub_d(_in1, _in6); \ - _out7 = __lsx_vsub_d(_in0, _in7); \ -} +#define LSX_BUTTERFLY_8_D(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _out0, _out1, _out2, _out3, _out4, _out5, _out6, \ + _out7) \ + { \ + _out0 = __lsx_vadd_d(_in0, _in7); \ + _out1 = __lsx_vadd_d(_in1, _in6); \ + _out2 = __lsx_vadd_d(_in2, _in5); \ + _out3 = __lsx_vadd_d(_in3, _in4); \ + _out4 = __lsx_vsub_d(_in3, _in4); \ + _out5 = __lsx_vsub_d(_in2, _in5); \ + _out6 = __lsx_vsub_d(_in1, _in6); \ + _out7 = __lsx_vsub_d(_in0, _in7); \ + } -#endif //LSX +#endif // LSX #ifdef __loongarch_asx #include @@ -700,13 +730,12 @@ static inline __m128i __lsx_vclip255_w(__m128i _in) * Example : See out = __lasx_xvdp2_w_h(in_h, in_l) * ============================================================================= */ -static inline __m256i __lasx_xvdp2_h_bu(__m256i in_h, __m256i in_l) -{ - __m256i out; +static inline __m256i __lasx_xvdp2_h_bu(__m256i in_h, __m256i in_l) { + __m256i out; - out = __lasx_xvmulwev_h_bu(in_h, in_l); - out = __lasx_xvmaddwod_h_bu(out, in_h, in_l); - return out; + out = __lasx_xvmulwev_h_bu(in_h, in_l); + out = __lasx_xvmaddwod_h_bu(out, in_h, in_l); + return out; } /* @@ -718,18 +747,17 @@ static inline __m256i __lasx_xvdp2_h_bu(__m256i in_h, __m256i in_l) * Details : Signed byte elements from in_h are multiplied with * signed byte elements from in_l producing a result * twice the size of input i.e. signed halfword. - * Then this iniplication results of adjacent odd-even elements + * Then this multiplication results of adjacent odd-even elements * are added to the out vector * Example : See out = __lasx_xvdp2_w_h(in_h, in_l) * ============================================================================= */ -static inline __m256i __lasx_xvdp2_h_b(__m256i in_h, __m256i in_l) -{ - __m256i out; +static inline __m256i __lasx_xvdp2_h_b(__m256i in_h, __m256i in_l) { + __m256i out; - out = __lasx_xvmulwev_h_b(in_h, in_l); - out = __lasx_xvmaddwod_h_b(out, in_h, in_l); - return out; + out = __lasx_xvmulwev_h_b(in_h, in_l); + out = __lasx_xvmaddwod_h_b(out, in_h, in_l); + return out; } /* @@ -749,13 +777,12 @@ static inline __m256i __lasx_xvdp2_h_b(__m256i in_h, __m256i in_l) * out : 22,38,38,22, 22,38,38,22 * ============================================================================= */ -static inline __m256i __lasx_xvdp2_w_h(__m256i in_h, __m256i in_l) -{ - __m256i out; +static inline __m256i __lasx_xvdp2_w_h(__m256i in_h, __m256i in_l) { + __m256i out; - out = __lasx_xvmulwev_w_h(in_h, in_l); - out = __lasx_xvmaddwod_w_h(out, in_h, in_l); - return out; + out = __lasx_xvmulwev_w_h(in_h, in_l); + out = __lasx_xvmaddwod_w_h(out, in_h, in_l); + return out; } /* @@ -763,22 +790,21 @@ static inline __m256i __lasx_xvdp2_w_h(__m256i in_h, __m256i in_l) * Description : Dot product of word vector elements * Arguments : Inputs - in_h, in_l * Output - out - * Retrun Type - signed double + * Return Type - signed double * Details : Signed word elements from in_h are multiplied with * signed word elements from in_l producing a result - * twice the size of input i.e. signed double word. + * twice the size of input i.e. signed double-word. * Then this multiplied results of adjacent odd-even elements * are added to the out vector. * Example : See out = __lasx_xvdp2_w_h(in_h, in_l) * ============================================================================= */ -static inline __m256i __lasx_xvdp2_d_w(__m256i in_h, __m256i in_l) -{ - __m256i out; +static inline __m256i __lasx_xvdp2_d_w(__m256i in_h, __m256i in_l) { + __m256i out; - out = __lasx_xvmulwev_d_w(in_h, in_l); - out = __lasx_xvmaddwod_d_w(out, in_h, in_l); - return out; + out = __lasx_xvmulwev_d_w(in_h, in_l); + out = __lasx_xvmaddwod_d_w(out, in_h, in_l); + return out; } /* @@ -795,13 +821,12 @@ static inline __m256i __lasx_xvdp2_d_w(__m256i in_h, __m256i in_l) * Example : See out = __lasx_xvdp2_w_h(in_h, in_l) * ============================================================================= */ -static inline __m256i __lasx_xvdp2_w_hu_h(__m256i in_h, __m256i in_l) -{ - __m256i out; +static inline __m256i __lasx_xvdp2_w_hu_h(__m256i in_h, __m256i in_l) { + __m256i out; - out = __lasx_xvmulwev_w_hu_h(in_h, in_l); - out = __lasx_xvmaddwod_w_hu_h(out, in_h, in_l); - return out; + out = __lasx_xvmulwev_w_hu_h(in_h, in_l); + out = __lasx_xvmaddwod_w_hu_h(out, in_h, in_l); + return out; } /* @@ -809,7 +834,7 @@ static inline __m256i __lasx_xvdp2_w_hu_h(__m256i in_h, __m256i in_l) * Description : Dot product & addition of byte vector elements * Arguments : Inputs - in_h, in_l * Output - out - * Retrun Type - halfword + * Return Type - halfword * Details : Signed byte elements from in_h are multiplied with * signed byte elements from in_l producing a result * twice the size of input i.e. signed halfword. @@ -818,13 +843,59 @@ static inline __m256i __lasx_xvdp2_w_hu_h(__m256i in_h, __m256i in_l) * Example : See out = __lasx_xvdp2add_w_h(in_c, in_h, in_l) * ============================================================================= */ -static inline __m256i __lasx_xvdp2add_h_b(__m256i in_c,__m256i in_h, __m256i in_l) -{ - __m256i out; +static inline __m256i __lasx_xvdp2add_h_b(__m256i in_c, __m256i in_h, + __m256i in_l) { + __m256i out; - out = __lasx_xvmaddwev_h_b(in_c, in_h, in_l); - out = __lasx_xvmaddwod_h_b(out, in_h, in_l); - return out; + out = __lasx_xvmaddwev_h_b(in_c, in_h, in_l); + out = __lasx_xvmaddwod_h_b(out, in_h, in_l); + return out; +} + +/* + * ============================================================================= + * Description : Dot product & addition of byte vector elements + * Arguments : Inputs - in_h, in_l + * Output - out + * Return Type - halfword + * Details : Unsigned byte elements from in_h are multiplied with + * unsigned byte elements from in_l producing a result + * twice the size of input i.e. signed halfword. + * Then this multiplied results of adjacent odd-even elements + * are added to the in_c vector. + * Example : See out = __lasx_xvdp2add_w_h(in_c, in_h, in_l) + * ============================================================================= + */ +static inline __m256i __lasx_xvdp2add_h_bu(__m256i in_c, __m256i in_h, + __m256i in_l) { + __m256i out; + + out = __lasx_xvmaddwev_h_bu(in_c, in_h, in_l); + out = __lasx_xvmaddwod_h_bu(out, in_h, in_l); + return out; +} + +/* + * ============================================================================= + * Description : Dot product & addition of byte vector elements + * Arguments : Inputs - in_h, in_l + * Output - out + * Return Type - halfword + * Details : Unsigned byte elements from in_h are multiplied with + * signed byte elements from in_l producing a result + * twice the size of input i.e. signed halfword. + * Then this multiplied results of adjacent odd-even elements + * are added to the in_c vector. + * Example : See out = __lasx_xvdp2add_w_h(in_c, in_h, in_l) + * ============================================================================= + */ +static inline __m256i __lasx_xvdp2add_h_bu_b(__m256i in_c, __m256i in_h, + __m256i in_l) { + __m256i out; + + out = __lasx_xvmaddwev_h_bu_b(in_c, in_h, in_l); + out = __lasx_xvmaddwod_h_bu_b(out, in_h, in_l); + return out; } /* @@ -845,13 +916,13 @@ static inline __m256i __lasx_xvdp2add_h_b(__m256i in_c,__m256i in_h, __m256i in_ * out : 23,40,41,26, 23,40,41,26 * ============================================================================= */ -static inline __m256i __lasx_xvdp2add_w_h(__m256i in_c, __m256i in_h, __m256i in_l) -{ - __m256i out; +static inline __m256i __lasx_xvdp2add_w_h(__m256i in_c, __m256i in_h, + __m256i in_l) { + __m256i out; - out = __lasx_xvmaddwev_w_h(in_c, in_h, in_l); - out = __lasx_xvmaddwod_w_h(out, in_h, in_l); - return out; + out = __lasx_xvmaddwev_w_h(in_c, in_h, in_l); + out = __lasx_xvmaddwod_w_h(out, in_h, in_l); + return out; } /* @@ -868,13 +939,13 @@ static inline __m256i __lasx_xvdp2add_w_h(__m256i in_c, __m256i in_h, __m256i in * Example : See out = __lasx_xvdp2add_w_h(in_c, in_h, in_l) * ============================================================================= */ -static inline __m256i __lasx_xvdp2add_w_hu(__m256i in_c, __m256i in_h, __m256i in_l) -{ - __m256i out; +static inline __m256i __lasx_xvdp2add_w_hu(__m256i in_c, __m256i in_h, + __m256i in_l) { + __m256i out; - out = __lasx_xvmaddwev_w_hu(in_c, in_h, in_l); - out = __lasx_xvmaddwod_w_hu(out, in_h, in_l); - return out; + out = __lasx_xvmaddwev_w_hu(in_c, in_h, in_l); + out = __lasx_xvmaddwod_w_hu(out, in_h, in_l); + return out; } /* @@ -891,13 +962,13 @@ static inline __m256i __lasx_xvdp2add_w_hu(__m256i in_c, __m256i in_h, __m256i i * Example : See out = __lasx_xvdp2add_w_h(in_c, in_h, in_l) * ============================================================================= */ -static inline __m256i __lasx_xvdp2add_w_hu_h(__m256i in_c, __m256i in_h, __m256i in_l) -{ - __m256i out; +static inline __m256i __lasx_xvdp2add_w_hu_h(__m256i in_c, __m256i in_h, + __m256i in_l) { + __m256i out; - out = __lasx_xvmaddwev_w_hu_h(in_c, in_h, in_l); - out = __lasx_xvmaddwod_w_hu_h(out, in_h, in_l); - return out; + out = __lasx_xvmaddwev_w_hu_h(in_c, in_h, in_l); + out = __lasx_xvmaddwod_w_hu_h(out, in_h, in_l); + return out; } /* @@ -915,14 +986,14 @@ static inline __m256i __lasx_xvdp2add_w_hu_h(__m256i in_c, __m256i in_h, __m256i * Example : See out = __lasx_xvdp2sub_w_h(in_c, in_h, in_l) * ============================================================================= */ -static inline __m256i __lasx_xvdp2sub_h_bu(__m256i in_c, __m256i in_h, __m256i in_l) -{ - __m256i out; +static inline __m256i __lasx_xvdp2sub_h_bu(__m256i in_c, __m256i in_h, + __m256i in_l) { + __m256i out; - out = __lasx_xvmulwev_h_bu(in_h, in_l); - out = __lasx_xvmaddwod_h_bu(out, in_h, in_l); - out = __lasx_xvsub_h(in_c, out); - return out; + out = __lasx_xvmulwev_h_bu(in_h, in_l); + out = __lasx_xvmaddwod_h_bu(out, in_h, in_l); + out = __lasx_xvsub_h(in_c, out); + return out; } /* @@ -944,14 +1015,14 @@ static inline __m256i __lasx_xvdp2sub_h_bu(__m256i in_c, __m256i in_h, __m256i i * out : -7,-3,0,0, 0,-1,0,-1 * ============================================================================= */ -static inline __m256i __lasx_xvdp2sub_w_h(__m256i in_c, __m256i in_h, __m256i in_l) -{ - __m256i out; +static inline __m256i __lasx_xvdp2sub_w_h(__m256i in_c, __m256i in_h, + __m256i in_l) { + __m256i out; - out = __lasx_xvmulwev_w_h(in_h, in_l); - out = __lasx_xvmaddwod_w_h(out, in_h, in_l); - out = __lasx_xvsub_w(in_c, out); - return out; + out = __lasx_xvmulwev_w_h(in_h, in_l); + out = __lasx_xvmaddwod_w_h(out, in_h, in_l); + out = __lasx_xvsub_w(in_c, out); + return out; } /* @@ -960,10 +1031,10 @@ static inline __m256i __lasx_xvdp2sub_w_h(__m256i in_c, __m256i in_h, __m256i in * Arguments : Inputs - in_h, in_l * Output - out * Return Type - signed word - * Details : Signed halfword elements from in_h are iniplied with + * Details : Signed halfword elements from in_h are multiplied with * signed halfword elements from in_l producing a result * four times the size of input i.e. signed doubleword. - * Then this iniplication results of four adjacent elements + * Then this multiplication results of four adjacent elements * are added together and stored to the out vector. * Example : out = __lasx_xvdp4_d_h(in_h, in_l) * in_h : 3,1,3,0, 0,0,0,1, 0,0,1,-1, 0,0,0,1 @@ -971,14 +1042,13 @@ static inline __m256i __lasx_xvdp2sub_w_h(__m256i in_c, __m256i in_h, __m256i in * out : -2,0,1,1 * ============================================================================= */ -static inline __m256i __lasx_xvdp4_d_h(__m256i in_h, __m256i in_l) -{ - __m256i out; +static inline __m256i __lasx_xvdp4_d_h(__m256i in_h, __m256i in_l) { + __m256i out; - out = __lasx_xvmulwev_w_h(in_h, in_l); - out = __lasx_xvmaddwod_w_h(out, in_h, in_l); - out = __lasx_xvhaddw_d_w(out, out); - return out; + out = __lasx_xvmulwev_w_h(in_h, in_l); + out = __lasx_xvmaddwod_w_h(out, in_h, in_l); + out = __lasx_xvhaddw_d_w(out, out); + return out; } /* @@ -993,13 +1063,12 @@ static inline __m256i __lasx_xvdp4_d_h(__m256i in_h, __m256i in_l) * Example : See out = __lasx_xvaddwh_w_h(in_h, in_l) * ============================================================================= */ -static inline __m256i __lasx_xvaddwh_h_b(__m256i in_h, __m256i in_l) -{ - __m256i out; +static inline __m256i __lasx_xvaddwh_h_b(__m256i in_h, __m256i in_l) { + __m256i out; - out = __lasx_xvilvh_b(in_h, in_l); - out = __lasx_xvhaddw_h_b(out, out); - return out; + out = __lasx_xvilvh_b(in_h, in_l); + out = __lasx_xvhaddw_h_b(out, out); + return out; } /* @@ -1017,13 +1086,12 @@ static inline __m256i __lasx_xvaddwh_h_b(__m256i in_h, __m256i in_l) * out : 1,0,0,-1, 1,0,0, 2 * ============================================================================= */ - static inline __m256i __lasx_xvaddwh_w_h(__m256i in_h, __m256i in_l) -{ - __m256i out; +static inline __m256i __lasx_xvaddwh_w_h(__m256i in_h, __m256i in_l) { + __m256i out; - out = __lasx_xvilvh_h(in_h, in_l); - out = __lasx_xvhaddw_w_h(out, out); - return out; + out = __lasx_xvilvh_h(in_h, in_l); + out = __lasx_xvhaddw_w_h(out, out); + return out; } /* @@ -1038,13 +1106,12 @@ static inline __m256i __lasx_xvaddwh_h_b(__m256i in_h, __m256i in_l) * Example : See out = __lasx_xvaddwl_w_h(in_h, in_l) * ============================================================================= */ -static inline __m256i __lasx_xvaddwl_h_b(__m256i in_h, __m256i in_l) -{ - __m256i out; +static inline __m256i __lasx_xvaddwl_h_b(__m256i in_h, __m256i in_l) { + __m256i out; - out = __lasx_xvilvl_b(in_h, in_l); - out = __lasx_xvhaddw_h_b(out, out); - return out; + out = __lasx_xvilvl_b(in_h, in_l); + out = __lasx_xvhaddw_h_b(out, out); + return out; } /* @@ -1062,13 +1129,12 @@ static inline __m256i __lasx_xvaddwl_h_b(__m256i in_h, __m256i in_l) * out : 5,-1,4,2, 1,0,2,-1 * ============================================================================= */ -static inline __m256i __lasx_xvaddwl_w_h(__m256i in_h, __m256i in_l) -{ - __m256i out; +static inline __m256i __lasx_xvaddwl_w_h(__m256i in_h, __m256i in_l) { + __m256i out; - out = __lasx_xvilvl_h(in_h, in_l); - out = __lasx_xvhaddw_w_h(out, out); - return out; + out = __lasx_xvilvl_h(in_h, in_l); + out = __lasx_xvhaddw_w_h(out, out); + return out; } /* @@ -1083,13 +1149,12 @@ static inline __m256i __lasx_xvaddwl_w_h(__m256i in_h, __m256i in_l) * Example : See out = __lasx_xvaddwl_w_h(in_h, in_l) * ============================================================================= */ -static inline __m256i __lasx_xvaddwl_h_bu(__m256i in_h, __m256i in_l) -{ - __m256i out; +static inline __m256i __lasx_xvaddwl_h_bu(__m256i in_h, __m256i in_l) { + __m256i out; - out = __lasx_xvilvl_b(in_h, in_l); - out = __lasx_xvhaddw_hu_bu(out, out); - return out; + out = __lasx_xvilvl_b(in_h, in_l); + out = __lasx_xvhaddw_hu_bu(out, out); + return out; } /* @@ -1103,13 +1168,12 @@ static inline __m256i __lasx_xvaddwl_h_bu(__m256i in_h, __m256i in_l) * Example : See out = __lasx_xvaddw_w_w_h(in_h, in_l) * ============================================================================= */ -static inline __m256i __lasx_xvaddw_h_h_bu(__m256i in_h, __m256i in_l) -{ - __m256i out; +static inline __m256i __lasx_xvaddw_h_h_bu(__m256i in_h, __m256i in_l) { + __m256i out; - out = __lasx_xvsllwil_hu_bu(in_l, 0); - out = __lasx_xvadd_h(in_h, out); - return out; + out = __lasx_xvsllwil_hu_bu(in_l, 0); + out = __lasx_xvadd_h(in_h, out); + return out; } /* @@ -1126,13 +1190,12 @@ static inline __m256i __lasx_xvaddw_h_h_bu(__m256i in_h, __m256i in_l) * out : 2, 0,1,2, -1,0,1,1, * ============================================================================= */ -static inline __m256i __lasx_xvaddw_w_w_h(__m256i in_h, __m256i in_l) -{ - __m256i out; +static inline __m256i __lasx_xvaddw_w_w_h(__m256i in_h, __m256i in_l) { + __m256i out; - out = __lasx_xvsllwil_w_h(in_l, 0); - out = __lasx_xvadd_w(in_h, out); - return out; + out = __lasx_xvsllwil_w_h(in_l, 0); + out = __lasx_xvadd_w(in_h, out); + return out; } /* @@ -1153,15 +1216,15 @@ static inline __m256i __lasx_xvaddw_w_w_h(__m256i in_h, __m256i in_l) * out : 201, 602,1203,2004, -995, -1794,-2793,-3992 * ============================================================================= */ -static inline __m256i __lasx_xvmaddwl_w_h(__m256i in_c, __m256i in_h, __m256i in_l) -{ - __m256i tmp0, tmp1, out; +static inline __m256i __lasx_xvmaddwl_w_h(__m256i in_c, __m256i in_h, + __m256i in_l) { + __m256i tmp0, tmp1, out; - tmp0 = __lasx_xvsllwil_w_h(in_h, 0); - tmp1 = __lasx_xvsllwil_w_h(in_l, 0); - tmp0 = __lasx_xvmul_w(tmp0, tmp1); - out = __lasx_xvadd_w(tmp0, in_c); - return out; + tmp0 = __lasx_xvsllwil_w_h(in_h, 0); + tmp1 = __lasx_xvsllwil_w_h(in_l, 0); + tmp0 = __lasx_xvmul_w(tmp0, tmp1); + out = __lasx_xvadd_w(tmp0, in_c); + return out; } /* @@ -1177,15 +1240,15 @@ static inline __m256i __lasx_xvmaddwl_w_h(__m256i in_c, __m256i in_h, __m256i in * Example : See out = __lasx_xvmaddwl_w_h(in_c, in_h, in_l) * ============================================================================= */ -static inline __m256i __lasx_xvmaddwh_w_h(__m256i in_c, __m256i in_h, __m256i in_l) -{ - __m256i tmp0, tmp1, out; +static inline __m256i __lasx_xvmaddwh_w_h(__m256i in_c, __m256i in_h, + __m256i in_l) { + __m256i tmp0, tmp1, out; - tmp0 = __lasx_xvilvh_h(in_h, in_h); - tmp1 = __lasx_xvilvh_h(in_l, in_l); - tmp0 = __lasx_xvmulwev_w_h(tmp0, tmp1); - out = __lasx_xvadd_w(tmp0, in_c); - return out; + tmp0 = __lasx_xvilvh_h(in_h, in_h); + tmp1 = __lasx_xvilvh_h(in_l, in_l); + tmp0 = __lasx_xvmulwev_w_h(tmp0, tmp1); + out = __lasx_xvadd_w(tmp0, in_c); + return out; } /* @@ -1203,14 +1266,13 @@ static inline __m256i __lasx_xvmaddwh_w_h(__m256i in_c, __m256i in_h, __m256i in * out : 6,1,3,0, 0,0,1,0 * ============================================================================= */ -static inline __m256i __lasx_xvmulwl_w_h(__m256i in_h, __m256i in_l) -{ - __m256i tmp0, tmp1, out; +static inline __m256i __lasx_xvmulwl_w_h(__m256i in_h, __m256i in_l) { + __m256i tmp0, tmp1, out; - tmp0 = __lasx_xvsllwil_w_h(in_h, 0); - tmp1 = __lasx_xvsllwil_w_h(in_l, 0); - out = __lasx_xvmul_w(tmp0, tmp1); - return out; + tmp0 = __lasx_xvsllwil_w_h(in_h, 0); + tmp1 = __lasx_xvsllwil_w_h(in_l, 0); + out = __lasx_xvmul_w(tmp0, tmp1); + return out; } /* @@ -1228,39 +1290,39 @@ static inline __m256i __lasx_xvmulwl_w_h(__m256i in_h, __m256i in_l) * out : 0,0,0,0, 0,0,0,1 * ============================================================================= */ -static inline __m256i __lasx_xvmulwh_w_h(__m256i in_h, __m256i in_l) -{ - __m256i tmp0, tmp1, out; +static inline __m256i __lasx_xvmulwh_w_h(__m256i in_h, __m256i in_l) { + __m256i tmp0, tmp1, out; - tmp0 = __lasx_xvilvh_h(in_h, in_h); - tmp1 = __lasx_xvilvh_h(in_l, in_l); - out = __lasx_xvmulwev_w_h(tmp0, tmp1); - return out; + tmp0 = __lasx_xvilvh_h(in_h, in_h); + tmp1 = __lasx_xvilvh_h(in_l, in_l); + out = __lasx_xvmulwev_w_h(tmp0, tmp1); + return out; } /* * ============================================================================= - * Description : The low half of the vector elements are expanded and - * added saturately after being doubled. + * Description : The low half of the vector elements are added to the high half + * after being doubled, then saturated. * Arguments : Inputs - in_h, in_l * Output - out - * Details : The in_h vector adds the in_l vector saturately after the lower - * half of the two-fold zero extension (unsigned byte to unsigned - * halfword) and the results are stored to the out vector. + * Details : The in_h vector adds the in_l vector after the lower half of + * the two-fold zero extension (unsigned byte to unsigned + * halfword) and then saturated. The results are stored to the out + * vector. * Example : out = __lasx_xvsaddw_hu_hu_bu(in_h, in_l) * in_h : 2,65532,1,2, 1,0,0,0, 0,0,1,0, 1,0,0,1 - * in_l : 3,6,3,0, 0,0,0,1, 0,0,1,1, 0,0,0,1, 3,18,3,0, 0,0,0,1, 0,0,1,1, 0,0,0,1 - * out : 5,65535,4,2, 1,0,0,1, 3,18,4,0, 1,0,0,2, + * in_l : 3,6,3,0, 0,0,0,1, 0,0,1,1, 0,0,0,1, 3,18,3,0, 0,0,0,1, 0,0,1,1, + * 0,0,0,1 + * out : 5,65535,4,2, 1,0,0,1, 3,18,4,0, 1,0,0,2, * ============================================================================= */ -static inline __m256i __lasx_xvsaddw_hu_hu_bu(__m256i in_h, __m256i in_l) -{ - __m256i tmp1, out; - __m256i zero = {0}; +static inline __m256i __lasx_xvsaddw_hu_hu_bu(__m256i in_h, __m256i in_l) { + __m256i tmp1, out; + __m256i zero = { 0 }; - tmp1 = __lasx_xvilvl_b(zero, in_l); - out = __lasx_xvsadd_hu(in_h, tmp1); - return out; + tmp1 = __lasx_xvilvl_b(zero, in_l); + out = __lasx_xvsadd_hu(in_h, tmp1); + return out; } /* @@ -1279,13 +1341,12 @@ static inline __m256i __lasx_xvsaddw_hu_hu_bu(__m256i in_h, __m256i in_l) * out : 1,2,9,9, 1,9,9,9, 4,4,4,4, 5,5,5,5 * ============================================================================= */ -static inline __m256i __lasx_xvclip_h(__m256i in, __m256i min, __m256i max) -{ - __m256i out; +static inline __m256i __lasx_xvclip_h(__m256i in, __m256i min, __m256i max) { + __m256i out; - out = __lasx_xvmax_h(min, in); - out = __lasx_xvmin_h(max, out); - return out; + out = __lasx_xvmax_h(min, in); + out = __lasx_xvmin_h(max, out); + return out; } /* @@ -1298,13 +1359,12 @@ static inline __m256i __lasx_xvclip_h(__m256i in, __m256i min, __m256i max) * Example : See out = __lasx_xvclip255_w(in) * ============================================================================= */ -static inline __m256i __lasx_xvclip255_h(__m256i in) -{ - __m256i out; +static inline __m256i __lasx_xvclip255_h(__m256i in) { + __m256i out; - out = __lasx_xvmaxi_h(in, 0); - out = __lasx_xvsat_hu(out, 7); - return out; + out = __lasx_xvmaxi_h(in, 0); + out = __lasx_xvsat_hu(out, 7); + return out; } /* @@ -1319,20 +1379,19 @@ static inline __m256i __lasx_xvclip255_h(__m256i in) * out : 0,255,255,249, 0,255,255,249 * ============================================================================= */ -static inline __m256i __lasx_xvclip255_w(__m256i in) -{ - __m256i out; +static inline __m256i __lasx_xvclip255_w(__m256i in) { + __m256i out; - out = __lasx_xvmaxi_w(in, 0); - out = __lasx_xvsat_wu(out, 7); - return out; + out = __lasx_xvmaxi_w(in, 0); + out = __lasx_xvsat_wu(out, 7); + return out; } /* * ============================================================================= * Description : Indexed halfword element values are replicated to all - * elements in output vector. If 'indx < 8' use xvsplati_l_*, - * if 'indx >= 8' use xvsplati_h_*. + * elements in output vector. If 'idx < 8' use xvsplati_l_*, + * if 'idx >= 8' use xvsplati_h_*. * Arguments : Inputs - in, idx * Output - out * Details : Idx element value from in vector is replicated to all @@ -1344,20 +1403,19 @@ static inline __m256i __lasx_xvclip255_w(__m256i in) * out : 11,11,11,11, 11,11,11,11, 11,11,11,11, 11,11,11,11 * ============================================================================= */ -static inline __m256i __lasx_xvsplati_l_h(__m256i in, int idx) -{ - __m256i out; +static inline __m256i __lasx_xvsplati_l_h(__m256i in, int idx) { + __m256i out; - out = __lasx_xvpermi_q(in, in, 0x02); - out = __lasx_xvreplve_h(out, idx); - return out; + out = __lasx_xvpermi_q(in, in, 0x02); + out = __lasx_xvreplve_h(out, idx); + return out; } /* * ============================================================================= * Description : Indexed halfword element values are replicated to all - * elements in output vector. If 'indx < 8' use xvsplati_l_*, - * if 'indx >= 8' use xvsplati_h_*. + * elements in output vector. If 'idx < 8' use xvsplati_l_*, + * if 'idx >= 8' use xvsplati_h_*. * Arguments : Inputs - in, idx * Output - out * Details : Idx element value from in vector is replicated to all @@ -1369,18 +1427,17 @@ static inline __m256i __lasx_xvsplati_l_h(__m256i in, int idx) * out : 2,2,2,2, 2,2,2,2, 2,2,2,2, 2,2,2,2 * ============================================================================= */ -static inline __m256i __lasx_xvsplati_h_h(__m256i in, int idx) -{ - __m256i out; +static inline __m256i __lasx_xvsplati_h_h(__m256i in, int idx) { + __m256i out; - out = __lasx_xvpermi_q(in, in, 0x13); - out = __lasx_xvreplve_h(out, idx); - return out; + out = __lasx_xvpermi_q(in, in, 0x13); + out = __lasx_xvreplve_h(out, idx); + return out; } /* * ============================================================================= - * Description : Transpose 4x4 block with double word elements in vectors + * Description : Transpose 4x4 block with double-word elements in vectors * Arguments : Inputs - _in0, _in1, _in2, _in3 * Outputs - _out0, _out1, _out2, _out3 * Example : LASX_TRANSPOSE4x4_D @@ -1395,24 +1452,26 @@ static inline __m256i __lasx_xvsplati_h_h(__m256i in, int idx) * _out3 : 4,4,4,4 * ============================================================================= */ -#define LASX_TRANSPOSE4x4_D(_in0, _in1, _in2, _in3, _out0, _out1, _out2, _out3) \ -{ \ - __m256i _tmp0, _tmp1, _tmp2, _tmp3; \ - _tmp0 = __lasx_xvilvl_d(_in1, _in0); \ - _tmp1 = __lasx_xvilvh_d(_in1, _in0); \ - _tmp2 = __lasx_xvilvl_d(_in3, _in2); \ - _tmp3 = __lasx_xvilvh_d(_in3, _in2); \ - _out0 = __lasx_xvpermi_q(_tmp2, _tmp0, 0x20); \ - _out2 = __lasx_xvpermi_q(_tmp2, _tmp0, 0x31); \ - _out1 = __lasx_xvpermi_q(_tmp3, _tmp1, 0x20); \ - _out3 = __lasx_xvpermi_q(_tmp3, _tmp1, 0x31); \ -} +#define LASX_TRANSPOSE4x4_D(_in0, _in1, _in2, _in3, _out0, _out1, _out2, \ + _out3) \ + { \ + __m256i _tmp0, _tmp1, _tmp2, _tmp3; \ + _tmp0 = __lasx_xvilvl_d(_in1, _in0); \ + _tmp1 = __lasx_xvilvh_d(_in1, _in0); \ + _tmp2 = __lasx_xvilvl_d(_in3, _in2); \ + _tmp3 = __lasx_xvilvh_d(_in3, _in2); \ + _out0 = __lasx_xvpermi_q(_tmp2, _tmp0, 0x20); \ + _out2 = __lasx_xvpermi_q(_tmp2, _tmp0, 0x31); \ + _out1 = __lasx_xvpermi_q(_tmp3, _tmp1, 0x20); \ + _out3 = __lasx_xvpermi_q(_tmp3, _tmp1, 0x31); \ + } /* * ============================================================================= * Description : Transpose 8x8 block with word elements in vectors * Arguments : Inputs - _in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7 - * Outputs - _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7 + * Outputs - _out0, _out1, _out2, _out3, _out4, _out5, _out6, + * _out7 * Example : LASX_TRANSPOSE8x8_W * _in0 : 1,2,3,4,5,6,7,8 * _in1 : 2,2,3,4,5,6,7,8 @@ -1433,38 +1492,39 @@ static inline __m256i __lasx_xvsplati_h_h(__m256i in, int idx) * _out7 : 8,8,8,8,8,8,8,8 * ============================================================================= */ -#define LASX_TRANSPOSE8x8_W(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ - _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7) \ -{ \ - __m256i _s0_m, _s1_m; \ - __m256i _tmp0_m, _tmp1_m, _tmp2_m, _tmp3_m; \ - __m256i _tmp4_m, _tmp5_m, _tmp6_m, _tmp7_m; \ - \ - _s0_m = __lasx_xvilvl_w(_in2, _in0); \ - _s1_m = __lasx_xvilvl_w(_in3, _in1); \ - _tmp0_m = __lasx_xvilvl_w(_s1_m, _s0_m); \ - _tmp1_m = __lasx_xvilvh_w(_s1_m, _s0_m); \ - _s0_m = __lasx_xvilvh_w(_in2, _in0); \ - _s1_m = __lasx_xvilvh_w(_in3, _in1); \ - _tmp2_m = __lasx_xvilvl_w(_s1_m, _s0_m); \ - _tmp3_m = __lasx_xvilvh_w(_s1_m, _s0_m); \ - _s0_m = __lasx_xvilvl_w(_in6, _in4); \ - _s1_m = __lasx_xvilvl_w(_in7, _in5); \ - _tmp4_m = __lasx_xvilvl_w(_s1_m, _s0_m); \ - _tmp5_m = __lasx_xvilvh_w(_s1_m, _s0_m); \ - _s0_m = __lasx_xvilvh_w(_in6, _in4); \ - _s1_m = __lasx_xvilvh_w(_in7, _in5); \ - _tmp6_m = __lasx_xvilvl_w(_s1_m, _s0_m); \ - _tmp7_m = __lasx_xvilvh_w(_s1_m, _s0_m); \ - _out0 = __lasx_xvpermi_q(_tmp4_m, _tmp0_m, 0x20); \ - _out1 = __lasx_xvpermi_q(_tmp5_m, _tmp1_m, 0x20); \ - _out2 = __lasx_xvpermi_q(_tmp6_m, _tmp2_m, 0x20); \ - _out3 = __lasx_xvpermi_q(_tmp7_m, _tmp3_m, 0x20); \ - _out4 = __lasx_xvpermi_q(_tmp4_m, _tmp0_m, 0x31); \ - _out5 = __lasx_xvpermi_q(_tmp5_m, _tmp1_m, 0x31); \ - _out6 = __lasx_xvpermi_q(_tmp6_m, _tmp2_m, 0x31); \ - _out7 = __lasx_xvpermi_q(_tmp7_m, _tmp3_m, 0x31); \ -} +#define LASX_TRANSPOSE8x8_W(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _out0, _out1, _out2, _out3, _out4, _out5, _out6, \ + _out7) \ + { \ + __m256i _s0_m, _s1_m; \ + __m256i _tmp0_m, _tmp1_m, _tmp2_m, _tmp3_m; \ + __m256i _tmp4_m, _tmp5_m, _tmp6_m, _tmp7_m; \ + \ + _s0_m = __lasx_xvilvl_w(_in2, _in0); \ + _s1_m = __lasx_xvilvl_w(_in3, _in1); \ + _tmp0_m = __lasx_xvilvl_w(_s1_m, _s0_m); \ + _tmp1_m = __lasx_xvilvh_w(_s1_m, _s0_m); \ + _s0_m = __lasx_xvilvh_w(_in2, _in0); \ + _s1_m = __lasx_xvilvh_w(_in3, _in1); \ + _tmp2_m = __lasx_xvilvl_w(_s1_m, _s0_m); \ + _tmp3_m = __lasx_xvilvh_w(_s1_m, _s0_m); \ + _s0_m = __lasx_xvilvl_w(_in6, _in4); \ + _s1_m = __lasx_xvilvl_w(_in7, _in5); \ + _tmp4_m = __lasx_xvilvl_w(_s1_m, _s0_m); \ + _tmp5_m = __lasx_xvilvh_w(_s1_m, _s0_m); \ + _s0_m = __lasx_xvilvh_w(_in6, _in4); \ + _s1_m = __lasx_xvilvh_w(_in7, _in5); \ + _tmp6_m = __lasx_xvilvl_w(_s1_m, _s0_m); \ + _tmp7_m = __lasx_xvilvh_w(_s1_m, _s0_m); \ + _out0 = __lasx_xvpermi_q(_tmp4_m, _tmp0_m, 0x20); \ + _out1 = __lasx_xvpermi_q(_tmp5_m, _tmp1_m, 0x20); \ + _out2 = __lasx_xvpermi_q(_tmp6_m, _tmp2_m, 0x20); \ + _out3 = __lasx_xvpermi_q(_tmp7_m, _tmp3_m, 0x20); \ + _out4 = __lasx_xvpermi_q(_tmp4_m, _tmp0_m, 0x31); \ + _out5 = __lasx_xvpermi_q(_tmp5_m, _tmp1_m, 0x31); \ + _out6 = __lasx_xvpermi_q(_tmp6_m, _tmp2_m, 0x31); \ + _out7 = __lasx_xvpermi_q(_tmp7_m, _tmp3_m, 0x31); \ + } /* * ============================================================================= @@ -1472,52 +1532,54 @@ static inline __m256i __lasx_xvsplati_h_h(__m256i in, int idx) * Arguments : Inputs - _in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, * _in8, _in9, _in10, _in11, _in12, _in13, _in14, _in15 * (input 16x8 byte block) - * Outputs - _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7 - * (output 8x16 byte block) - * Details : The rows of the matrix become columns, and the columns become rows. + * Outputs - _out0, _out1, _out2, _out3, _out4, _out5, _out6, + * _out7 (output 8x16 byte block) + * Details : The rows of the matrix become columns, and the columns become + * rows. * Example : See LASX_TRANSPOSE16x8_H * ============================================================================= */ -#define LASX_TRANSPOSE16x8_B(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ - _in8, _in9, _in10, _in11, _in12, _in13, _in14, _in15, \ - _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7) \ -{ \ - __m256i _tmp0_m, _tmp1_m, _tmp2_m, _tmp3_m; \ - __m256i _tmp4_m, _tmp5_m, _tmp6_m, _tmp7_m; \ - \ - _tmp0_m = __lasx_xvilvl_b(_in2, _in0); \ - _tmp1_m = __lasx_xvilvl_b(_in3, _in1); \ - _tmp2_m = __lasx_xvilvl_b(_in6, _in4); \ - _tmp3_m = __lasx_xvilvl_b(_in7, _in5); \ - _tmp4_m = __lasx_xvilvl_b(_in10, _in8); \ - _tmp5_m = __lasx_xvilvl_b(_in11, _in9); \ - _tmp6_m = __lasx_xvilvl_b(_in14, _in12); \ - _tmp7_m = __lasx_xvilvl_b(_in15, _in13); \ - _out0 = __lasx_xvilvl_b(_tmp1_m, _tmp0_m); \ - _out1 = __lasx_xvilvh_b(_tmp1_m, _tmp0_m); \ - _out2 = __lasx_xvilvl_b(_tmp3_m, _tmp2_m); \ - _out3 = __lasx_xvilvh_b(_tmp3_m, _tmp2_m); \ - _out4 = __lasx_xvilvl_b(_tmp5_m, _tmp4_m); \ - _out5 = __lasx_xvilvh_b(_tmp5_m, _tmp4_m); \ - _out6 = __lasx_xvilvl_b(_tmp7_m, _tmp6_m); \ - _out7 = __lasx_xvilvh_b(_tmp7_m, _tmp6_m); \ - _tmp0_m = __lasx_xvilvl_w(_out2, _out0); \ - _tmp2_m = __lasx_xvilvh_w(_out2, _out0); \ - _tmp4_m = __lasx_xvilvl_w(_out3, _out1); \ - _tmp6_m = __lasx_xvilvh_w(_out3, _out1); \ - _tmp1_m = __lasx_xvilvl_w(_out6, _out4); \ - _tmp3_m = __lasx_xvilvh_w(_out6, _out4); \ - _tmp5_m = __lasx_xvilvl_w(_out7, _out5); \ - _tmp7_m = __lasx_xvilvh_w(_out7, _out5); \ - _out0 = __lasx_xvilvl_d(_tmp1_m, _tmp0_m); \ - _out1 = __lasx_xvilvh_d(_tmp1_m, _tmp0_m); \ - _out2 = __lasx_xvilvl_d(_tmp3_m, _tmp2_m); \ - _out3 = __lasx_xvilvh_d(_tmp3_m, _tmp2_m); \ - _out4 = __lasx_xvilvl_d(_tmp5_m, _tmp4_m); \ - _out5 = __lasx_xvilvh_d(_tmp5_m, _tmp4_m); \ - _out6 = __lasx_xvilvl_d(_tmp7_m, _tmp6_m); \ - _out7 = __lasx_xvilvh_d(_tmp7_m, _tmp6_m); \ -} +#define LASX_TRANSPOSE16x8_B(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _in8, _in9, _in10, _in11, _in12, _in13, _in14, \ + _in15, _out0, _out1, _out2, _out3, _out4, _out5, \ + _out6, _out7) \ + { \ + __m256i _tmp0_m, _tmp1_m, _tmp2_m, _tmp3_m; \ + __m256i _tmp4_m, _tmp5_m, _tmp6_m, _tmp7_m; \ + \ + _tmp0_m = __lasx_xvilvl_b(_in2, _in0); \ + _tmp1_m = __lasx_xvilvl_b(_in3, _in1); \ + _tmp2_m = __lasx_xvilvl_b(_in6, _in4); \ + _tmp3_m = __lasx_xvilvl_b(_in7, _in5); \ + _tmp4_m = __lasx_xvilvl_b(_in10, _in8); \ + _tmp5_m = __lasx_xvilvl_b(_in11, _in9); \ + _tmp6_m = __lasx_xvilvl_b(_in14, _in12); \ + _tmp7_m = __lasx_xvilvl_b(_in15, _in13); \ + _out0 = __lasx_xvilvl_b(_tmp1_m, _tmp0_m); \ + _out1 = __lasx_xvilvh_b(_tmp1_m, _tmp0_m); \ + _out2 = __lasx_xvilvl_b(_tmp3_m, _tmp2_m); \ + _out3 = __lasx_xvilvh_b(_tmp3_m, _tmp2_m); \ + _out4 = __lasx_xvilvl_b(_tmp5_m, _tmp4_m); \ + _out5 = __lasx_xvilvh_b(_tmp5_m, _tmp4_m); \ + _out6 = __lasx_xvilvl_b(_tmp7_m, _tmp6_m); \ + _out7 = __lasx_xvilvh_b(_tmp7_m, _tmp6_m); \ + _tmp0_m = __lasx_xvilvl_w(_out2, _out0); \ + _tmp2_m = __lasx_xvilvh_w(_out2, _out0); \ + _tmp4_m = __lasx_xvilvl_w(_out3, _out1); \ + _tmp6_m = __lasx_xvilvh_w(_out3, _out1); \ + _tmp1_m = __lasx_xvilvl_w(_out6, _out4); \ + _tmp3_m = __lasx_xvilvh_w(_out6, _out4); \ + _tmp5_m = __lasx_xvilvl_w(_out7, _out5); \ + _tmp7_m = __lasx_xvilvh_w(_out7, _out5); \ + _out0 = __lasx_xvilvl_d(_tmp1_m, _tmp0_m); \ + _out1 = __lasx_xvilvh_d(_tmp1_m, _tmp0_m); \ + _out2 = __lasx_xvilvl_d(_tmp3_m, _tmp2_m); \ + _out3 = __lasx_xvilvh_d(_tmp3_m, _tmp2_m); \ + _out4 = __lasx_xvilvl_d(_tmp5_m, _tmp4_m); \ + _out5 = __lasx_xvilvh_d(_tmp5_m, _tmp4_m); \ + _out6 = __lasx_xvilvl_d(_tmp7_m, _tmp6_m); \ + _out7 = __lasx_xvilvh_d(_tmp7_m, _tmp6_m); \ + } /* * ============================================================================= @@ -1525,9 +1587,10 @@ static inline __m256i __lasx_xvsplati_h_h(__m256i in, int idx) * Arguments : Inputs - _in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, * _in8, _in9, _in10, _in11, _in12, _in13, _in14, _in15 * (input 16x8 byte block) - * Outputs - _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7 - * (output 8x16 byte block) - * Details : The rows of the matrix become columns, and the columns become rows. + * Outputs - _out0, _out1, _out2, _out3, _out4, _out5, _out6, + * _out7 (output 8x16 byte block) + * Details : The rows of the matrix become columns, and the columns become + * rows. * Example : LASX_TRANSPOSE16x8_H * _in0 : 1,2,3,4,5,6,7,8,0,0,0,0,0,0,0,0 * _in1 : 2,2,3,4,5,6,7,8,0,0,0,0,0,0,0,0 @@ -1556,72 +1619,73 @@ static inline __m256i __lasx_xvsplati_h_h(__m256i in, int idx) * _out7 : 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 * ============================================================================= */ -#define LASX_TRANSPOSE16x8_H(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ - _in8, _in9, _in10, _in11, _in12, _in13, _in14, _in15, \ - _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7) \ - { \ - __m256i _tmp0_m, _tmp1_m, _tmp2_m, _tmp3_m; \ - __m256i _tmp4_m, _tmp5_m, _tmp6_m, _tmp7_m; \ - __m256i _t0, _t1, _t2, _t3, _t4, _t5, _t6, _t7; \ - \ - _tmp0_m = __lasx_xvilvl_h(_in2, _in0); \ - _tmp1_m = __lasx_xvilvl_h(_in3, _in1); \ - _tmp2_m = __lasx_xvilvl_h(_in6, _in4); \ - _tmp3_m = __lasx_xvilvl_h(_in7, _in5); \ - _tmp4_m = __lasx_xvilvl_h(_in10, _in8); \ - _tmp5_m = __lasx_xvilvl_h(_in11, _in9); \ - _tmp6_m = __lasx_xvilvl_h(_in14, _in12); \ - _tmp7_m = __lasx_xvilvl_h(_in15, _in13); \ - _t0 = __lasx_xvilvl_h(_tmp1_m, _tmp0_m); \ - _t1 = __lasx_xvilvh_h(_tmp1_m, _tmp0_m); \ - _t2 = __lasx_xvilvl_h(_tmp3_m, _tmp2_m); \ - _t3 = __lasx_xvilvh_h(_tmp3_m, _tmp2_m); \ - _t4 = __lasx_xvilvl_h(_tmp5_m, _tmp4_m); \ - _t5 = __lasx_xvilvh_h(_tmp5_m, _tmp4_m); \ - _t6 = __lasx_xvilvl_h(_tmp7_m, _tmp6_m); \ - _t7 = __lasx_xvilvh_h(_tmp7_m, _tmp6_m); \ - _tmp0_m = __lasx_xvilvl_d(_t2, _t0); \ - _tmp2_m = __lasx_xvilvh_d(_t2, _t0); \ - _tmp4_m = __lasx_xvilvl_d(_t3, _t1); \ - _tmp6_m = __lasx_xvilvh_d(_t3, _t1); \ - _tmp1_m = __lasx_xvilvl_d(_t6, _t4); \ - _tmp3_m = __lasx_xvilvh_d(_t6, _t4); \ - _tmp5_m = __lasx_xvilvl_d(_t7, _t5); \ - _tmp7_m = __lasx_xvilvh_d(_t7, _t5); \ - _out0 = __lasx_xvpermi_q(_tmp1_m, _tmp0_m, 0x20); \ - _out1 = __lasx_xvpermi_q(_tmp3_m, _tmp2_m, 0x20); \ - _out2 = __lasx_xvpermi_q(_tmp5_m, _tmp4_m, 0x20); \ - _out3 = __lasx_xvpermi_q(_tmp7_m, _tmp6_m, 0x20); \ - \ - _tmp0_m = __lasx_xvilvh_h(_in2, _in0); \ - _tmp1_m = __lasx_xvilvh_h(_in3, _in1); \ - _tmp2_m = __lasx_xvilvh_h(_in6, _in4); \ - _tmp3_m = __lasx_xvilvh_h(_in7, _in5); \ - _tmp4_m = __lasx_xvilvh_h(_in10, _in8); \ - _tmp5_m = __lasx_xvilvh_h(_in11, _in9); \ - _tmp6_m = __lasx_xvilvh_h(_in14, _in12); \ - _tmp7_m = __lasx_xvilvh_h(_in15, _in13); \ - _t0 = __lasx_xvilvl_h(_tmp1_m, _tmp0_m); \ - _t1 = __lasx_xvilvh_h(_tmp1_m, _tmp0_m); \ - _t2 = __lasx_xvilvl_h(_tmp3_m, _tmp2_m); \ - _t3 = __lasx_xvilvh_h(_tmp3_m, _tmp2_m); \ - _t4 = __lasx_xvilvl_h(_tmp5_m, _tmp4_m); \ - _t5 = __lasx_xvilvh_h(_tmp5_m, _tmp4_m); \ - _t6 = __lasx_xvilvl_h(_tmp7_m, _tmp6_m); \ - _t7 = __lasx_xvilvh_h(_tmp7_m, _tmp6_m); \ - _tmp0_m = __lasx_xvilvl_d(_t2, _t0); \ - _tmp2_m = __lasx_xvilvh_d(_t2, _t0); \ - _tmp4_m = __lasx_xvilvl_d(_t3, _t1); \ - _tmp6_m = __lasx_xvilvh_d(_t3, _t1); \ - _tmp1_m = __lasx_xvilvl_d(_t6, _t4); \ - _tmp3_m = __lasx_xvilvh_d(_t6, _t4); \ - _tmp5_m = __lasx_xvilvl_d(_t7, _t5); \ - _tmp7_m = __lasx_xvilvh_d(_t7, _t5); \ - _out4 = __lasx_xvpermi_q(_tmp1_m, _tmp0_m, 0x20); \ - _out5 = __lasx_xvpermi_q(_tmp3_m, _tmp2_m, 0x20); \ - _out6 = __lasx_xvpermi_q(_tmp5_m, _tmp4_m, 0x20); \ - _out7 = __lasx_xvpermi_q(_tmp7_m, _tmp6_m, 0x20); \ -} +#define LASX_TRANSPOSE16x8_H(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _in8, _in9, _in10, _in11, _in12, _in13, _in14, \ + _in15, _out0, _out1, _out2, _out3, _out4, _out5, \ + _out6, _out7) \ + { \ + __m256i _tmp0_m, _tmp1_m, _tmp2_m, _tmp3_m; \ + __m256i _tmp4_m, _tmp5_m, _tmp6_m, _tmp7_m; \ + __m256i _t0, _t1, _t2, _t3, _t4, _t5, _t6, _t7; \ + \ + _tmp0_m = __lasx_xvilvl_h(_in2, _in0); \ + _tmp1_m = __lasx_xvilvl_h(_in3, _in1); \ + _tmp2_m = __lasx_xvilvl_h(_in6, _in4); \ + _tmp3_m = __lasx_xvilvl_h(_in7, _in5); \ + _tmp4_m = __lasx_xvilvl_h(_in10, _in8); \ + _tmp5_m = __lasx_xvilvl_h(_in11, _in9); \ + _tmp6_m = __lasx_xvilvl_h(_in14, _in12); \ + _tmp7_m = __lasx_xvilvl_h(_in15, _in13); \ + _t0 = __lasx_xvilvl_h(_tmp1_m, _tmp0_m); \ + _t1 = __lasx_xvilvh_h(_tmp1_m, _tmp0_m); \ + _t2 = __lasx_xvilvl_h(_tmp3_m, _tmp2_m); \ + _t3 = __lasx_xvilvh_h(_tmp3_m, _tmp2_m); \ + _t4 = __lasx_xvilvl_h(_tmp5_m, _tmp4_m); \ + _t5 = __lasx_xvilvh_h(_tmp5_m, _tmp4_m); \ + _t6 = __lasx_xvilvl_h(_tmp7_m, _tmp6_m); \ + _t7 = __lasx_xvilvh_h(_tmp7_m, _tmp6_m); \ + _tmp0_m = __lasx_xvilvl_d(_t2, _t0); \ + _tmp2_m = __lasx_xvilvh_d(_t2, _t0); \ + _tmp4_m = __lasx_xvilvl_d(_t3, _t1); \ + _tmp6_m = __lasx_xvilvh_d(_t3, _t1); \ + _tmp1_m = __lasx_xvilvl_d(_t6, _t4); \ + _tmp3_m = __lasx_xvilvh_d(_t6, _t4); \ + _tmp5_m = __lasx_xvilvl_d(_t7, _t5); \ + _tmp7_m = __lasx_xvilvh_d(_t7, _t5); \ + _out0 = __lasx_xvpermi_q(_tmp1_m, _tmp0_m, 0x20); \ + _out1 = __lasx_xvpermi_q(_tmp3_m, _tmp2_m, 0x20); \ + _out2 = __lasx_xvpermi_q(_tmp5_m, _tmp4_m, 0x20); \ + _out3 = __lasx_xvpermi_q(_tmp7_m, _tmp6_m, 0x20); \ + \ + _tmp0_m = __lasx_xvilvh_h(_in2, _in0); \ + _tmp1_m = __lasx_xvilvh_h(_in3, _in1); \ + _tmp2_m = __lasx_xvilvh_h(_in6, _in4); \ + _tmp3_m = __lasx_xvilvh_h(_in7, _in5); \ + _tmp4_m = __lasx_xvilvh_h(_in10, _in8); \ + _tmp5_m = __lasx_xvilvh_h(_in11, _in9); \ + _tmp6_m = __lasx_xvilvh_h(_in14, _in12); \ + _tmp7_m = __lasx_xvilvh_h(_in15, _in13); \ + _t0 = __lasx_xvilvl_h(_tmp1_m, _tmp0_m); \ + _t1 = __lasx_xvilvh_h(_tmp1_m, _tmp0_m); \ + _t2 = __lasx_xvilvl_h(_tmp3_m, _tmp2_m); \ + _t3 = __lasx_xvilvh_h(_tmp3_m, _tmp2_m); \ + _t4 = __lasx_xvilvl_h(_tmp5_m, _tmp4_m); \ + _t5 = __lasx_xvilvh_h(_tmp5_m, _tmp4_m); \ + _t6 = __lasx_xvilvl_h(_tmp7_m, _tmp6_m); \ + _t7 = __lasx_xvilvh_h(_tmp7_m, _tmp6_m); \ + _tmp0_m = __lasx_xvilvl_d(_t2, _t0); \ + _tmp2_m = __lasx_xvilvh_d(_t2, _t0); \ + _tmp4_m = __lasx_xvilvl_d(_t3, _t1); \ + _tmp6_m = __lasx_xvilvh_d(_t3, _t1); \ + _tmp1_m = __lasx_xvilvl_d(_t6, _t4); \ + _tmp3_m = __lasx_xvilvh_d(_t6, _t4); \ + _tmp5_m = __lasx_xvilvl_d(_t7, _t5); \ + _tmp7_m = __lasx_xvilvh_d(_t7, _t5); \ + _out4 = __lasx_xvpermi_q(_tmp1_m, _tmp0_m, 0x20); \ + _out5 = __lasx_xvpermi_q(_tmp3_m, _tmp2_m, 0x20); \ + _out6 = __lasx_xvpermi_q(_tmp5_m, _tmp4_m, 0x20); \ + _out7 = __lasx_xvpermi_q(_tmp7_m, _tmp6_m, 0x20); \ + } /* * ============================================================================= @@ -1629,61 +1693,65 @@ static inline __m256i __lasx_xvsplati_h_h(__m256i in, int idx) * Arguments : Inputs - _in0, _in1, _in2, _in3 * Outputs - _out0, _out1, _out2, _out3 * Return Type - signed halfword - * Details : The rows of the matrix become columns, and the columns become rows. + * Details : The rows of the matrix become columns, and the columns become + * rows. * Example : See LASX_TRANSPOSE8x8_H * ============================================================================= */ -#define LASX_TRANSPOSE4x4_H(_in0, _in1, _in2, _in3, _out0, _out1, _out2, _out3) \ -{ \ - __m256i _s0_m, _s1_m; \ - \ - _s0_m = __lasx_xvilvl_h(_in1, _in0); \ - _s1_m = __lasx_xvilvl_h(_in3, _in2); \ - _out0 = __lasx_xvilvl_w(_s1_m, _s0_m); \ - _out2 = __lasx_xvilvh_w(_s1_m, _s0_m); \ - _out1 = __lasx_xvilvh_d(_out0, _out0); \ - _out3 = __lasx_xvilvh_d(_out2, _out2); \ -} +#define LASX_TRANSPOSE4x4_H(_in0, _in1, _in2, _in3, _out0, _out1, _out2, \ + _out3) \ + { \ + __m256i _s0_m, _s1_m; \ + \ + _s0_m = __lasx_xvilvl_h(_in1, _in0); \ + _s1_m = __lasx_xvilvl_h(_in3, _in2); \ + _out0 = __lasx_xvilvl_w(_s1_m, _s0_m); \ + _out2 = __lasx_xvilvh_w(_s1_m, _s0_m); \ + _out1 = __lasx_xvilvh_d(_out0, _out0); \ + _out3 = __lasx_xvilvh_d(_out2, _out2); \ + } /* * ============================================================================= * Description : Transpose input 8x8 byte block * Arguments : Inputs - _in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7 * (input 8x8 byte block) - * Outputs - _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7 - * (output 8x8 byte block) + * Outputs - _out0, _out1, _out2, _out3, _out4, _out5, _out6, + * _out7 (output 8x8 byte block) * Example : See LASX_TRANSPOSE8x8_H * ============================================================================= */ -#define LASX_TRANSPOSE8x8_B(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, _out0, \ - _out1, _out2, _out3, _out4, _out5, _out6, _out7) \ -{ \ - __m256i _tmp0_m, _tmp1_m, _tmp2_m, _tmp3_m; \ - __m256i _tmp4_m, _tmp5_m, _tmp6_m, _tmp7_m; \ - _tmp0_m = __lasx_xvilvl_b(_in2, _in0); \ - _tmp1_m = __lasx_xvilvl_b(_in3, _in1); \ - _tmp2_m = __lasx_xvilvl_b(_in6, _in4); \ - _tmp3_m = __lasx_xvilvl_b(_in7, _in5); \ - _tmp4_m = __lasx_xvilvl_b(_tmp1_m, _tmp0_m); \ - _tmp5_m = __lasx_xvilvh_b(_tmp1_m, _tmp0_m); \ - _tmp6_m = __lasx_xvilvl_b(_tmp3_m, _tmp2_m); \ - _tmp7_m = __lasx_xvilvh_b(_tmp3_m, _tmp2_m); \ - _out0 = __lasx_xvilvl_w(_tmp6_m, _tmp4_m); \ - _out2 = __lasx_xvilvh_w(_tmp6_m, _tmp4_m); \ - _out4 = __lasx_xvilvl_w(_tmp7_m, _tmp5_m); \ - _out6 = __lasx_xvilvh_w(_tmp7_m, _tmp5_m); \ - _out1 = __lasx_xvbsrl_v(_out0, 8); \ - _out3 = __lasx_xvbsrl_v(_out2, 8); \ - _out5 = __lasx_xvbsrl_v(_out4, 8); \ - _out7 = __lasx_xvbsrl_v(_out6, 8); \ -} +#define LASX_TRANSPOSE8x8_B(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _out0, _out1, _out2, _out3, _out4, _out5, _out6, \ + _out7) \ + { \ + __m256i _tmp0_m, _tmp1_m, _tmp2_m, _tmp3_m; \ + __m256i _tmp4_m, _tmp5_m, _tmp6_m, _tmp7_m; \ + _tmp0_m = __lasx_xvilvl_b(_in2, _in0); \ + _tmp1_m = __lasx_xvilvl_b(_in3, _in1); \ + _tmp2_m = __lasx_xvilvl_b(_in6, _in4); \ + _tmp3_m = __lasx_xvilvl_b(_in7, _in5); \ + _tmp4_m = __lasx_xvilvl_b(_tmp1_m, _tmp0_m); \ + _tmp5_m = __lasx_xvilvh_b(_tmp1_m, _tmp0_m); \ + _tmp6_m = __lasx_xvilvl_b(_tmp3_m, _tmp2_m); \ + _tmp7_m = __lasx_xvilvh_b(_tmp3_m, _tmp2_m); \ + _out0 = __lasx_xvilvl_w(_tmp6_m, _tmp4_m); \ + _out2 = __lasx_xvilvh_w(_tmp6_m, _tmp4_m); \ + _out4 = __lasx_xvilvl_w(_tmp7_m, _tmp5_m); \ + _out6 = __lasx_xvilvh_w(_tmp7_m, _tmp5_m); \ + _out1 = __lasx_xvbsrl_v(_out0, 8); \ + _out3 = __lasx_xvbsrl_v(_out2, 8); \ + _out5 = __lasx_xvbsrl_v(_out4, 8); \ + _out7 = __lasx_xvbsrl_v(_out6, 8); \ + } /* * ============================================================================= * Description : Transpose 8x8 block with halfword elements in vectors. * Arguments : Inputs - _in0, _in1, ~ * Outputs - _out0, _out1, ~ - * Details : The rows of the matrix become columns, and the columns become rows. + * Details : The rows of the matrix become columns, and the columns become + * rows. * Example : LASX_TRANSPOSE8x8_H * _in0 : 1,2,3,4, 5,6,7,8, 1,2,3,4, 5,6,7,8 * _in1 : 8,2,3,4, 5,6,7,8, 8,2,3,4, 5,6,7,8 @@ -1704,40 +1772,41 @@ static inline __m256i __lasx_xvsplati_h_h(__m256i in, int idx) * _out7 : 8,8,8,8, 8,8,8,8, 8,8,8,8, 8,8,8,8 * ============================================================================= */ -#define LASX_TRANSPOSE8x8_H(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, _out0, \ - _out1, _out2, _out3, _out4, _out5, _out6, _out7) \ -{ \ - __m256i _s0_m, _s1_m; \ - __m256i _tmp0_m, _tmp1_m, _tmp2_m, _tmp3_m; \ - __m256i _tmp4_m, _tmp5_m, _tmp6_m, _tmp7_m; \ - \ - _s0_m = __lasx_xvilvl_h(_in6, _in4); \ - _s1_m = __lasx_xvilvl_h(_in7, _in5); \ - _tmp0_m = __lasx_xvilvl_h(_s1_m, _s0_m); \ - _tmp1_m = __lasx_xvilvh_h(_s1_m, _s0_m); \ - _s0_m = __lasx_xvilvh_h(_in6, _in4); \ - _s1_m = __lasx_xvilvh_h(_in7, _in5); \ - _tmp2_m = __lasx_xvilvl_h(_s1_m, _s0_m); \ - _tmp3_m = __lasx_xvilvh_h(_s1_m, _s0_m); \ - \ - _s0_m = __lasx_xvilvl_h(_in2, _in0); \ - _s1_m = __lasx_xvilvl_h(_in3, _in1); \ - _tmp4_m = __lasx_xvilvl_h(_s1_m, _s0_m); \ - _tmp5_m = __lasx_xvilvh_h(_s1_m, _s0_m); \ - _s0_m = __lasx_xvilvh_h(_in2, _in0); \ - _s1_m = __lasx_xvilvh_h(_in3, _in1); \ - _tmp6_m = __lasx_xvilvl_h(_s1_m, _s0_m); \ - _tmp7_m = __lasx_xvilvh_h(_s1_m, _s0_m); \ - \ - _out0 = __lasx_xvpickev_d(_tmp0_m, _tmp4_m); \ - _out2 = __lasx_xvpickev_d(_tmp1_m, _tmp5_m); \ - _out4 = __lasx_xvpickev_d(_tmp2_m, _tmp6_m); \ - _out6 = __lasx_xvpickev_d(_tmp3_m, _tmp7_m); \ - _out1 = __lasx_xvpickod_d(_tmp0_m, _tmp4_m); \ - _out3 = __lasx_xvpickod_d(_tmp1_m, _tmp5_m); \ - _out5 = __lasx_xvpickod_d(_tmp2_m, _tmp6_m); \ - _out7 = __lasx_xvpickod_d(_tmp3_m, _tmp7_m); \ -} +#define LASX_TRANSPOSE8x8_H(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _out0, _out1, _out2, _out3, _out4, _out5, _out6, \ + _out7) \ + { \ + __m256i _s0_m, _s1_m; \ + __m256i _tmp0_m, _tmp1_m, _tmp2_m, _tmp3_m; \ + __m256i _tmp4_m, _tmp5_m, _tmp6_m, _tmp7_m; \ + \ + _s0_m = __lasx_xvilvl_h(_in6, _in4); \ + _s1_m = __lasx_xvilvl_h(_in7, _in5); \ + _tmp0_m = __lasx_xvilvl_h(_s1_m, _s0_m); \ + _tmp1_m = __lasx_xvilvh_h(_s1_m, _s0_m); \ + _s0_m = __lasx_xvilvh_h(_in6, _in4); \ + _s1_m = __lasx_xvilvh_h(_in7, _in5); \ + _tmp2_m = __lasx_xvilvl_h(_s1_m, _s0_m); \ + _tmp3_m = __lasx_xvilvh_h(_s1_m, _s0_m); \ + \ + _s0_m = __lasx_xvilvl_h(_in2, _in0); \ + _s1_m = __lasx_xvilvl_h(_in3, _in1); \ + _tmp4_m = __lasx_xvilvl_h(_s1_m, _s0_m); \ + _tmp5_m = __lasx_xvilvh_h(_s1_m, _s0_m); \ + _s0_m = __lasx_xvilvh_h(_in2, _in0); \ + _s1_m = __lasx_xvilvh_h(_in3, _in1); \ + _tmp6_m = __lasx_xvilvl_h(_s1_m, _s0_m); \ + _tmp7_m = __lasx_xvilvh_h(_s1_m, _s0_m); \ + \ + _out0 = __lasx_xvpickev_d(_tmp0_m, _tmp4_m); \ + _out2 = __lasx_xvpickev_d(_tmp1_m, _tmp5_m); \ + _out4 = __lasx_xvpickev_d(_tmp2_m, _tmp6_m); \ + _out6 = __lasx_xvpickev_d(_tmp3_m, _tmp7_m); \ + _out1 = __lasx_xvpickod_d(_tmp0_m, _tmp4_m); \ + _out3 = __lasx_xvpickod_d(_tmp1_m, _tmp5_m); \ + _out5 = __lasx_xvpickod_d(_tmp2_m, _tmp6_m); \ + _out7 = __lasx_xvpickod_d(_tmp3_m, _tmp7_m); \ + } /* * ============================================================================= @@ -1752,34 +1821,34 @@ static inline __m256i __lasx_xvsplati_h_h(__m256i in, int idx) * _out3 = _in0 - _in3; * ============================================================================= */ -#define LASX_BUTTERFLY_4_B(_in0, _in1, _in2, _in3, _out0, _out1, _out2, _out3) \ -{ \ - _out0 = __lasx_xvadd_b(_in0, _in3); \ - _out1 = __lasx_xvadd_b(_in1, _in2); \ - _out2 = __lasx_xvsub_b(_in1, _in2); \ - _out3 = __lasx_xvsub_b(_in0, _in3); \ -} -#define LASX_BUTTERFLY_4_H(_in0, _in1, _in2, _in3, _out0, _out1, _out2, _out3) \ -{ \ - _out0 = __lasx_xvadd_h(_in0, _in3); \ - _out1 = __lasx_xvadd_h(_in1, _in2); \ - _out2 = __lasx_xvsub_h(_in1, _in2); \ - _out3 = __lasx_xvsub_h(_in0, _in3); \ -} -#define LASX_BUTTERFLY_4_W(_in0, _in1, _in2, _in3, _out0, _out1, _out2, _out3) \ -{ \ - _out0 = __lasx_xvadd_w(_in0, _in3); \ - _out1 = __lasx_xvadd_w(_in1, _in2); \ - _out2 = __lasx_xvsub_w(_in1, _in2); \ - _out3 = __lasx_xvsub_w(_in0, _in3); \ -} -#define LASX_BUTTERFLY_4_D(_in0, _in1, _in2, _in3, _out0, _out1, _out2, _out3) \ -{ \ - _out0 = __lasx_xvadd_d(_in0, _in3); \ - _out1 = __lasx_xvadd_d(_in1, _in2); \ - _out2 = __lasx_xvsub_d(_in1, _in2); \ - _out3 = __lasx_xvsub_d(_in0, _in3); \ -} +#define LASX_BUTTERFLY_4_B(_in0, _in1, _in2, _in3, _out0, _out1, _out2, _out3) \ + { \ + _out0 = __lasx_xvadd_b(_in0, _in3); \ + _out1 = __lasx_xvadd_b(_in1, _in2); \ + _out2 = __lasx_xvsub_b(_in1, _in2); \ + _out3 = __lasx_xvsub_b(_in0, _in3); \ + } +#define LASX_BUTTERFLY_4_H(_in0, _in1, _in2, _in3, _out0, _out1, _out2, _out3) \ + { \ + _out0 = __lasx_xvadd_h(_in0, _in3); \ + _out1 = __lasx_xvadd_h(_in1, _in2); \ + _out2 = __lasx_xvsub_h(_in1, _in2); \ + _out3 = __lasx_xvsub_h(_in0, _in3); \ + } +#define LASX_BUTTERFLY_4_W(_in0, _in1, _in2, _in3, _out0, _out1, _out2, _out3) \ + { \ + _out0 = __lasx_xvadd_w(_in0, _in3); \ + _out1 = __lasx_xvadd_w(_in1, _in2); \ + _out2 = __lasx_xvsub_w(_in1, _in2); \ + _out3 = __lasx_xvsub_w(_in0, _in3); \ + } +#define LASX_BUTTERFLY_4_D(_in0, _in1, _in2, _in3, _out0, _out1, _out2, _out3) \ + { \ + _out0 = __lasx_xvadd_d(_in0, _in3); \ + _out1 = __lasx_xvadd_d(_in1, _in2); \ + _out2 = __lasx_xvsub_d(_in1, _in2); \ + _out3 = __lasx_xvsub_d(_in0, _in3); \ + } /* * ============================================================================= @@ -1798,59 +1867,63 @@ static inline __m256i __lasx_xvsplati_h_h(__m256i in, int idx) * _out7 = _in0 - _in7; * ============================================================================= */ -#define LASX_BUTTERFLY_8_B(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ - _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7)\ -{ \ - _out0 = __lasx_xvadd_b(_in0, _in7); \ - _out1 = __lasx_xvadd_b(_in1, _in6); \ - _out2 = __lasx_xvadd_b(_in2, _in5); \ - _out3 = __lasx_xvadd_b(_in3, _in4); \ - _out4 = __lasx_xvsub_b(_in3, _in4); \ - _out5 = __lasx_xvsub_b(_in2, _in5); \ - _out6 = __lasx_xvsub_b(_in1, _in6); \ - _out7 = __lasx_xvsub_b(_in0, _in7); \ -} +#define LASX_BUTTERFLY_8_B(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _out0, _out1, _out2, _out3, _out4, _out5, _out6, \ + _out7) \ + { \ + _out0 = __lasx_xvadd_b(_in0, _in7); \ + _out1 = __lasx_xvadd_b(_in1, _in6); \ + _out2 = __lasx_xvadd_b(_in2, _in5); \ + _out3 = __lasx_xvadd_b(_in3, _in4); \ + _out4 = __lasx_xvsub_b(_in3, _in4); \ + _out5 = __lasx_xvsub_b(_in2, _in5); \ + _out6 = __lasx_xvsub_b(_in1, _in6); \ + _out7 = __lasx_xvsub_b(_in0, _in7); \ + } -#define LASX_BUTTERFLY_8_H(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ - _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7)\ -{ \ - _out0 = __lasx_xvadd_h(_in0, _in7); \ - _out1 = __lasx_xvadd_h(_in1, _in6); \ - _out2 = __lasx_xvadd_h(_in2, _in5); \ - _out3 = __lasx_xvadd_h(_in3, _in4); \ - _out4 = __lasx_xvsub_h(_in3, _in4); \ - _out5 = __lasx_xvsub_h(_in2, _in5); \ - _out6 = __lasx_xvsub_h(_in1, _in6); \ - _out7 = __lasx_xvsub_h(_in0, _in7); \ -} +#define LASX_BUTTERFLY_8_H(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _out0, _out1, _out2, _out3, _out4, _out5, _out6, \ + _out7) \ + { \ + _out0 = __lasx_xvadd_h(_in0, _in7); \ + _out1 = __lasx_xvadd_h(_in1, _in6); \ + _out2 = __lasx_xvadd_h(_in2, _in5); \ + _out3 = __lasx_xvadd_h(_in3, _in4); \ + _out4 = __lasx_xvsub_h(_in3, _in4); \ + _out5 = __lasx_xvsub_h(_in2, _in5); \ + _out6 = __lasx_xvsub_h(_in1, _in6); \ + _out7 = __lasx_xvsub_h(_in0, _in7); \ + } -#define LASX_BUTTERFLY_8_W(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ - _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7)\ -{ \ - _out0 = __lasx_xvadd_w(_in0, _in7); \ - _out1 = __lasx_xvadd_w(_in1, _in6); \ - _out2 = __lasx_xvadd_w(_in2, _in5); \ - _out3 = __lasx_xvadd_w(_in3, _in4); \ - _out4 = __lasx_xvsub_w(_in3, _in4); \ - _out5 = __lasx_xvsub_w(_in2, _in5); \ - _out6 = __lasx_xvsub_w(_in1, _in6); \ - _out7 = __lasx_xvsub_w(_in0, _in7); \ -} +#define LASX_BUTTERFLY_8_W(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _out0, _out1, _out2, _out3, _out4, _out5, _out6, \ + _out7) \ + { \ + _out0 = __lasx_xvadd_w(_in0, _in7); \ + _out1 = __lasx_xvadd_w(_in1, _in6); \ + _out2 = __lasx_xvadd_w(_in2, _in5); \ + _out3 = __lasx_xvadd_w(_in3, _in4); \ + _out4 = __lasx_xvsub_w(_in3, _in4); \ + _out5 = __lasx_xvsub_w(_in2, _in5); \ + _out6 = __lasx_xvsub_w(_in1, _in6); \ + _out7 = __lasx_xvsub_w(_in0, _in7); \ + } -#define LASX_BUTTERFLY_8_D(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ - _out0, _out1, _out2, _out3, _out4, _out5, _out6, _out7)\ -{ \ - _out0 = __lasx_xvadd_d(_in0, _in7); \ - _out1 = __lasx_xvadd_d(_in1, _in6); \ - _out2 = __lasx_xvadd_d(_in2, _in5); \ - _out3 = __lasx_xvadd_d(_in3, _in4); \ - _out4 = __lasx_xvsub_d(_in3, _in4); \ - _out5 = __lasx_xvsub_d(_in2, _in5); \ - _out6 = __lasx_xvsub_d(_in1, _in6); \ - _out7 = __lasx_xvsub_d(_in0, _in7); \ -} +#define LASX_BUTTERFLY_8_D(_in0, _in1, _in2, _in3, _in4, _in5, _in6, _in7, \ + _out0, _out1, _out2, _out3, _out4, _out5, _out6, \ + _out7) \ + { \ + _out0 = __lasx_xvadd_d(_in0, _in7); \ + _out1 = __lasx_xvadd_d(_in1, _in6); \ + _out2 = __lasx_xvadd_d(_in2, _in5); \ + _out3 = __lasx_xvadd_d(_in3, _in4); \ + _out4 = __lasx_xvsub_d(_in3, _in4); \ + _out5 = __lasx_xvsub_d(_in2, _in5); \ + _out6 = __lasx_xvsub_d(_in1, _in6); \ + _out7 = __lasx_xvsub_d(_in0, _in7); \ + } -#endif //LASX +#endif // LASX /* * ============================================================================= @@ -1863,15 +1936,13 @@ static inline __m256i __lasx_xvsplati_h_h(__m256i in, int idx) * VP:1,2,3,4, * ============================================================================= */ -#define VECT_PRINT(RTYPE, element_num, in0, enter) \ -{ \ - RTYPE _tmp0 = (RTYPE)in0; \ - int _i = 0; \ - if (enter) \ - printf("\nVP:"); \ - for(_i = 0; _i < element_num; _i++) \ - printf("%d,",_tmp0[_i]); \ -} +#define VECT_PRINT(RTYPE, element_num, in0, enter) \ + { \ + RTYPE _tmp0 = (RTYPE)in0; \ + int _i = 0; \ + if (enter) printf("\nVP:"); \ + for (_i = 0; _i < element_num; _i++) printf("%d,", _tmp0[_i]); \ + } #endif /* LOONGSON_INTRINSICS_H */ #endif /* AVUTIL_LOONGARCH_LOONGSON_INTRINSICS_H */ diff --git a/libavutil/lzo.c b/libavutil/lzo.c index 1ae076e33..bcbe2c861 100644 --- a/libavutil/lzo.c +++ b/libavutil/lzo.c @@ -19,13 +19,15 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include +#include #include -#include "avutil.h" #include "avassert.h" -#include "common.h" #include "intreadwrite.h" #include "lzo.h" +#include "macros.h" +#include "mem.h" /// Define if we may write up to 12 bytes beyond the output buffer. #define OUTBUF_PADDED 1 diff --git a/libavutil/mathematics.c b/libavutil/mathematics.c index f4e541fa2..b878317d6 100644 --- a/libavutil/mathematics.c +++ b/libavutil/mathematics.c @@ -26,6 +26,7 @@ #include #include +#include "avutil.h" #include "mathematics.h" #include "libavutil/intmath.h" #include "libavutil/common.h" diff --git a/libavutil/mem.c b/libavutil/mem.c index 194d88058..18aff5291 100644 --- a/libavutil/mem.c +++ b/libavutil/mem.c @@ -37,10 +37,13 @@ #include #endif -#include "avutil.h" -#include "common.h" +#include "attributes.h" +#include "avassert.h" #include "dynarray.h" +#include "error.h" +#include "internal.h" #include "intreadwrite.h" +#include "macros.h" #include "mem.h" #ifdef MALLOC_PREFIX @@ -59,8 +62,6 @@ void free(void *ptr); #endif /* MALLOC_PREFIX */ -#include "mem_internal.h" - #define ALIGN (HAVE_AVX512 ? 64 : (HAVE_AVX ? 32 : 16)) /* NOTE: if you want to override these functions with your own @@ -509,6 +510,8 @@ void *av_fast_realloc(void *ptr, unsigned int *size, size_t min_size) return ptr; max_size = atomic_load_explicit(&max_alloc_size, memory_order_relaxed); + /* *size is an unsigned, so the real maximum is <= UINT_MAX. */ + max_size = FFMIN(max_size, UINT_MAX); if (min_size > max_size) { *size = 0; @@ -541,6 +544,8 @@ static inline void fast_malloc(void *ptr, unsigned int *size, size_t min_size, i } max_size = atomic_load_explicit(&max_alloc_size, memory_order_relaxed); + /* *size is an unsigned, so the real maximum is <= UINT_MAX. */ + max_size = FFMIN(max_size, UINT_MAX); if (min_size > max_size) { av_freep(ptr); diff --git a/libavutil/mem.h b/libavutil/mem.h index b9fe80738..d91174196 100644 --- a/libavutil/mem.h +++ b/libavutil/mem.h @@ -250,8 +250,7 @@ void *av_mallocz_array(size_t nmemb, size_t size) av_malloc_attrib av_alloc_size /** * Allocate, reallocate, or free a block of memory. * - * If `ptr` is `NULL` and `size` > 0, allocate a new block. If `size` is - * zero, free the memory block pointed to by `ptr`. Otherwise, expand or + * If `ptr` is `NULL` and `size` > 0, allocate a new block. Otherwise, expand or * shrink that block of memory according to `size`. * * @param ptr Pointer to a memory block already allocated with @@ -260,10 +259,11 @@ void *av_mallocz_array(size_t nmemb, size_t size) av_malloc_attrib av_alloc_size * reallocated * * @return Pointer to a newly-reallocated block or `NULL` if the block - * cannot be reallocated or the function is used to free the memory block + * cannot be reallocated * * @warning Unlike av_malloc(), the returned pointer is not guaranteed to be - * correctly aligned. + * correctly aligned. The returned pointer must be freed after even + * if size is zero. * @see av_fast_realloc() * @see av_reallocp() */ @@ -311,8 +311,7 @@ void *av_realloc_f(void *ptr, size_t nelem, size_t elsize); /** * Allocate, reallocate, or free an array. * - * If `ptr` is `NULL` and `nmemb` > 0, allocate a new block. If - * `nmemb` is zero, free the memory block pointed to by `ptr`. + * If `ptr` is `NULL` and `nmemb` > 0, allocate a new block. * * @param ptr Pointer to a memory block already allocated with * av_realloc() or `NULL` @@ -320,19 +319,19 @@ void *av_realloc_f(void *ptr, size_t nelem, size_t elsize); * @param size Size of the single element of the array * * @return Pointer to a newly-reallocated block or NULL if the block - * cannot be reallocated or the function is used to free the memory block + * cannot be reallocated * * @warning Unlike av_malloc(), the allocated memory is not guaranteed to be - * correctly aligned. + * correctly aligned. The returned pointer must be freed after even if + * nmemb is zero. * @see av_reallocp_array() */ av_alloc_size(2, 3) void *av_realloc_array(void *ptr, size_t nmemb, size_t size); /** - * Allocate, reallocate, or free an array through a pointer to a pointer. + * Allocate, reallocate an array through a pointer to a pointer. * - * If `*ptr` is `NULL` and `nmemb` > 0, allocate a new block. If `nmemb` is - * zero, free the memory block pointed to by `*ptr`. + * If `*ptr` is `NULL` and `nmemb` > 0, allocate a new block. * * @param[in,out] ptr Pointer to a pointer to a memory block already * allocated with av_realloc(), or a pointer to `NULL`. @@ -343,7 +342,7 @@ av_alloc_size(2, 3) void *av_realloc_array(void *ptr, size_t nmemb, size_t size) * @return Zero on success, an AVERROR error code on failure * * @warning Unlike av_malloc(), the allocated memory is not guaranteed to be - * correctly aligned. + * correctly aligned. *ptr must be freed after even if nmemb is zero. */ int av_reallocp_array(void *ptr, size_t nmemb, size_t size); diff --git a/libavutil/opt.c b/libavutil/opt.c index d951edca9..8ffb10449 100644 --- a/libavutil/opt.c +++ b/libavutil/opt.c @@ -39,6 +39,7 @@ #include "opt.h" #include "samplefmt.h" #include "bprint.h" +#include "version.h" #include @@ -71,7 +72,11 @@ static int read_number(const AVOption *o, const void *dst, double *num, int *den case AV_OPT_TYPE_INT: *intnum = *(int *)dst; return 0; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS case AV_OPT_TYPE_CHANNEL_LAYOUT: +FF_ENABLE_DEPRECATION_WARNINGS +#endif case AV_OPT_TYPE_DURATION: case AV_OPT_TYPE_INT64: case AV_OPT_TYPE_UINT64: @@ -126,7 +131,11 @@ static int write_number(void *obj, const AVOption *o, void *dst, double num, int *(int *)dst = llrint(num / den) * intnum; break; case AV_OPT_TYPE_DURATION: +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS case AV_OPT_TYPE_CHANNEL_LAYOUT: +FF_ENABLE_DEPRECATION_WARNINGS +#endif case AV_OPT_TYPE_INT64:{ double d = num / den; if (intnum == 1 && d == (double)INT64_MAX) { @@ -465,6 +474,16 @@ static int set_string_dict(void *obj, const AVOption *o, const char *val, uint8_ return 0; } +static int set_string_channel_layout(void *obj, const AVOption *o, + const char *val, void *dst) +{ + AVChannelLayout *channel_layout = dst; + av_channel_layout_uninit(channel_layout); + if (!val) + return 0; + return av_channel_layout_from_string(channel_layout, val); +} + int av_opt_set(void *obj, const char *name, const char *val, int search_flags) { int ret = 0; @@ -472,12 +491,17 @@ int av_opt_set(void *obj, const char *name, const char *val, int search_flags) const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); if (!o || !target_obj) return AVERROR_OPTION_NOT_FOUND; +FF_DISABLE_DEPRECATION_WARNINGS if (!val && (o->type != AV_OPT_TYPE_STRING && o->type != AV_OPT_TYPE_PIXEL_FMT && o->type != AV_OPT_TYPE_SAMPLE_FMT && o->type != AV_OPT_TYPE_IMAGE_SIZE && o->type != AV_OPT_TYPE_DURATION && o->type != AV_OPT_TYPE_COLOR && - o->type != AV_OPT_TYPE_CHANNEL_LAYOUT && o->type != AV_OPT_TYPE_BOOL)) +#if FF_API_OLD_CHANNEL_LAYOUT + o->type != AV_OPT_TYPE_CHANNEL_LAYOUT && +#endif + o->type != AV_OPT_TYPE_BOOL)) return AVERROR(EINVAL); +FF_ENABLE_DEPRECATION_WARNINGS if (o->flags & AV_OPT_FLAG_READONLY) return AVERROR(EINVAL); @@ -533,6 +557,8 @@ int av_opt_set(void *obj, const char *name, const char *val, int search_flags) } case AV_OPT_TYPE_COLOR: return set_string_color(obj, o, val, dst); +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS case AV_OPT_TYPE_CHANNEL_LAYOUT: if (!val || !strcmp(val, "none")) { *(int64_t *)dst = 0; @@ -546,6 +572,15 @@ int av_opt_set(void *obj, const char *name, const char *val, int search_flags) return ret; } break; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + case AV_OPT_TYPE_CHLAYOUT: + ret = set_string_channel_layout(obj, o, val, dst); + if (ret < 0) { + av_log(obj, AV_LOG_ERROR, "Unable to parse option value \"%s\" as channel layout\n", val); + ret = AVERROR(EINVAL); + } + return ret; case AV_OPT_TYPE_DICT: return set_string_dict(obj, o, val, dst); } @@ -709,6 +744,8 @@ int av_opt_set_sample_fmt(void *obj, const char *name, enum AVSampleFormat fmt, return set_format(obj, name, fmt, search_flags, AV_OPT_TYPE_SAMPLE_FMT, "sample", AV_SAMPLE_FMT_NB); } +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS int av_opt_set_channel_layout(void *obj, const char *name, int64_t cl, int search_flags) { void *target_obj; @@ -724,6 +761,8 @@ int av_opt_set_channel_layout(void *obj, const char *name, int64_t cl, int searc *(int64_t *)(((uint8_t *)target_obj) + o->offset) = cl; return 0; } +FF_ENABLE_DEPRECATION_WARNINGS +#endif int av_opt_set_dict_val(void *obj, const char *name, const AVDictionary *val, int search_flags) @@ -744,6 +783,22 @@ int av_opt_set_dict_val(void *obj, const char *name, const AVDictionary *val, return 0; } +int av_opt_set_chlayout(void *obj, const char *name, + const AVChannelLayout *channel_layout, + int search_flags) +{ + void *target_obj; + const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); + AVChannelLayout *dst; + + if (!o || !target_obj) + return AVERROR_OPTION_NOT_FOUND; + + dst = (AVChannelLayout*)((uint8_t*)target_obj + o->offset); + + return av_channel_layout_copy(dst, channel_layout); +} + static void format_duration(char *buf, size_t size, int64_t d) { char *e; @@ -872,10 +927,18 @@ int av_opt_get(void *obj, const char *name, int search_flags, uint8_t **out_val) (int)((uint8_t *)dst)[0], (int)((uint8_t *)dst)[1], (int)((uint8_t *)dst)[2], (int)((uint8_t *)dst)[3]); break; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS case AV_OPT_TYPE_CHANNEL_LAYOUT: + i64 = *(int64_t *)dst; ret = snprintf(buf, sizeof(buf), "0x%"PRIx64, i64); break; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + case AV_OPT_TYPE_CHLAYOUT: + ret = av_channel_layout_describe(dst, buf, sizeof(buf)); + break; case AV_OPT_TYPE_DICT: if (!*(AVDictionary **)dst && (search_flags & AV_OPT_ALLOW_NULL)) { *out_val = NULL; @@ -1017,6 +1080,8 @@ int av_opt_get_sample_fmt(void *obj, const char *name, int search_flags, enum AV return get_format(obj, name, search_flags, out_fmt, AV_OPT_TYPE_SAMPLE_FMT, "sample"); } +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS int av_opt_get_channel_layout(void *obj, const char *name, int search_flags, int64_t *cl) { void *dst, *target_obj; @@ -1033,6 +1098,24 @@ int av_opt_get_channel_layout(void *obj, const char *name, int search_flags, int *cl = *(int64_t *)dst; return 0; } +FF_ENABLE_DEPRECATION_WARNINGS +#endif + +int av_opt_get_chlayout(void *obj, const char *name, int search_flags, AVChannelLayout *cl) +{ + void *dst, *target_obj; + const AVOption *o = av_opt_find2(obj, name, NULL, 0, search_flags, &target_obj); + if (!o || !target_obj) + return AVERROR_OPTION_NOT_FOUND; + if (o->type != AV_OPT_TYPE_CHLAYOUT) { + av_log(obj, AV_LOG_ERROR, + "The value for option '%s' is not a channel layout.\n", name); + return AVERROR(EINVAL); + } + + dst = ((uint8_t*)target_obj) + o->offset; + return av_channel_layout_copy(cl, dst); +} int av_opt_get_dict_val(void *obj, const char *name, int search_flags, AVDictionary **out_val) { @@ -1225,7 +1308,12 @@ static void opt_list(void *obj, void *av_log_obj, const char *unit, case AV_OPT_TYPE_COLOR: av_log(av_log_obj, AV_LOG_INFO, "%-12s ", ""); break; + case AV_OPT_TYPE_CHLAYOUT: +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS case AV_OPT_TYPE_CHANNEL_LAYOUT: +FF_ENABLE_DEPRECATION_WARNINGS +#endif av_log(av_log_obj, AV_LOG_INFO, "%-12s ", ""); break; case AV_OPT_TYPE_BOOL: @@ -1282,6 +1370,7 @@ static void opt_list(void *obj, void *av_log_obj, const char *unit, opt->type == AV_OPT_TYPE_IMAGE_SIZE || opt->type == AV_OPT_TYPE_STRING || opt->type == AV_OPT_TYPE_DICT || + opt->type == AV_OPT_TYPE_CHLAYOUT || opt->type == AV_OPT_TYPE_VIDEO_RATE) && !opt->default_val.str)) { av_log(av_log_obj, AV_LOG_INFO, " (default "); @@ -1334,11 +1423,16 @@ static void opt_list(void *obj, void *av_log_obj, const char *unit, case AV_OPT_TYPE_STRING: case AV_OPT_TYPE_DICT: case AV_OPT_TYPE_VIDEO_RATE: + case AV_OPT_TYPE_CHLAYOUT: av_log(av_log_obj, AV_LOG_INFO, "\"%s\"", opt->default_val.str); break; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS case AV_OPT_TYPE_CHANNEL_LAYOUT: av_log(av_log_obj, AV_LOG_INFO, "0x%"PRIx64, opt->default_val.i64); break; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } av_log(av_log_obj, AV_LOG_INFO, ")"); } @@ -1388,7 +1482,11 @@ void av_opt_set_defaults2(void *s, int mask, int flags) case AV_OPT_TYPE_INT64: case AV_OPT_TYPE_UINT64: case AV_OPT_TYPE_DURATION: +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS case AV_OPT_TYPE_CHANNEL_LAYOUT: +FF_ENABLE_DEPRECATION_WARNINGS +#endif case AV_OPT_TYPE_PIXEL_FMT: case AV_OPT_TYPE_SAMPLE_FMT: write_number(s, opt, dst, 1, 1, opt->default_val.i64); @@ -1421,6 +1519,9 @@ void av_opt_set_defaults2(void *s, int mask, int flags) case AV_OPT_TYPE_BINARY: set_string_binary(s, opt, opt->default_val.str, dst); break; + case AV_OPT_TYPE_CHLAYOUT: + set_string_channel_layout(s, opt, opt->default_val.str, dst); + break; case AV_OPT_TYPE_DICT: set_string_dict(s, opt, opt->default_val.str, dst); break; @@ -1628,6 +1729,10 @@ void av_opt_free(void *obj) av_dict_free((AVDictionary **)(((uint8_t *)obj) + o->offset)); break; + case AV_OPT_TYPE_CHLAYOUT: + av_channel_layout_uninit((AVChannelLayout *)(((uint8_t *)obj) + o->offset)); + break; + default: break; } @@ -1745,7 +1850,11 @@ static int opt_size(enum AVOptionType type) case AV_OPT_TYPE_FLAGS: return sizeof(int); case AV_OPT_TYPE_DURATION: +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS case AV_OPT_TYPE_CHANNEL_LAYOUT: +FF_ENABLE_DEPRECATION_WARNINGS +#endif case AV_OPT_TYPE_INT64: case AV_OPT_TYPE_UINT64: return sizeof(int64_t); @@ -1819,6 +1928,9 @@ int av_opt_copy(void *dst, const void *src) ret2 = av_dict_copy(ddict, *sdict, 0); if (ret2 < 0) ret = ret2; + } else if (o->type == AV_OPT_TYPE_CHLAYOUT) { + if (field_dst != field_src) + ret = av_channel_layout_copy(field_dst, field_src); } else { int size = opt_size(o->type); if (size < 0) @@ -1882,7 +1994,11 @@ int av_opt_query_ranges_default(AVOptionRanges **ranges_arg, void *obj, const ch case AV_OPT_TYPE_DOUBLE: case AV_OPT_TYPE_DURATION: case AV_OPT_TYPE_COLOR: +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS case AV_OPT_TYPE_CHANNEL_LAYOUT: +FF_ENABLE_DEPRECATION_WARNINGS +#endif break; case AV_OPT_TYPE_STRING: range->component_min = 0; @@ -1962,12 +2078,24 @@ int av_opt_is_set_to_default(void *obj, const AVOption *o) case AV_OPT_TYPE_PIXEL_FMT: case AV_OPT_TYPE_SAMPLE_FMT: case AV_OPT_TYPE_INT: +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS case AV_OPT_TYPE_CHANNEL_LAYOUT: +FF_ENABLE_DEPRECATION_WARNINGS +#endif case AV_OPT_TYPE_DURATION: case AV_OPT_TYPE_INT64: case AV_OPT_TYPE_UINT64: read_number(o, dst, NULL, NULL, &i64); return o->default_val.i64 == i64; + case AV_OPT_TYPE_CHLAYOUT: { + AVChannelLayout ch_layout = { 0 }; + if (o->default_val.str) { + if ((ret = av_channel_layout_from_string(&ch_layout, o->default_val.str)) < 0) + return ret; + } + return !av_channel_layout_compare((AVChannelLayout *)dst, &ch_layout); + } case AV_OPT_TYPE_STRING: str = *(char **)dst; if (str == o->default_val.str) //2 NULLs diff --git a/libavutil/opt.h b/libavutil/opt.h index 2820435ee..461b5d3b6 100644 --- a/libavutil/opt.h +++ b/libavutil/opt.h @@ -29,6 +29,7 @@ #include "rational.h" #include "avutil.h" +#include "channel_layout.h" #include "dict.h" #include "log.h" #include "pixfmt.h" @@ -237,8 +238,11 @@ enum AVOptionType{ AV_OPT_TYPE_VIDEO_RATE, ///< offset must point to AVRational AV_OPT_TYPE_DURATION, AV_OPT_TYPE_COLOR, +#if FF_API_OLD_CHANNEL_LAYOUT AV_OPT_TYPE_CHANNEL_LAYOUT, +#endif AV_OPT_TYPE_BOOL, + AV_OPT_TYPE_CHLAYOUT, }; /** @@ -693,7 +697,11 @@ int av_opt_set_image_size(void *obj, const char *name, int w, int h, int search_ int av_opt_set_pixel_fmt (void *obj, const char *name, enum AVPixelFormat fmt, int search_flags); int av_opt_set_sample_fmt(void *obj, const char *name, enum AVSampleFormat fmt, int search_flags); int av_opt_set_video_rate(void *obj, const char *name, AVRational val, int search_flags); +#if FF_API_OLD_CHANNEL_LAYOUT +attribute_deprecated int av_opt_set_channel_layout(void *obj, const char *name, int64_t ch_layout, int search_flags); +#endif +int av_opt_set_chlayout(void *obj, const char *name, const AVChannelLayout *layout, int search_flags); /** * @note Any old dictionary present is discarded and replaced with a copy of the new one. The * caller still owns val is and responsible for freeing it. @@ -748,7 +756,11 @@ int av_opt_get_image_size(void *obj, const char *name, int search_flags, int *w_ int av_opt_get_pixel_fmt (void *obj, const char *name, int search_flags, enum AVPixelFormat *out_fmt); int av_opt_get_sample_fmt(void *obj, const char *name, int search_flags, enum AVSampleFormat *out_fmt); int av_opt_get_video_rate(void *obj, const char *name, int search_flags, AVRational *out_val); +#if FF_API_OLD_CHANNEL_LAYOUT +attribute_deprecated int av_opt_get_channel_layout(void *obj, const char *name, int search_flags, int64_t *ch_layout); +#endif +int av_opt_get_chlayout(void *obj, const char *name, int search_flags, AVChannelLayout *layout); /** * @param[out] out_val The returned dictionary is a copy of the actual value and must * be freed with av_dict_free() by the caller diff --git a/libavutil/pixdesc.c b/libavutil/pixdesc.c index 727d7540b..6e57a82cb 100644 --- a/libavutil/pixdesc.c +++ b/libavutil/pixdesc.c @@ -432,10 +432,12 @@ 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] = { .name = "xvmc", .flags = AV_PIX_FMT_FLAG_HWACCEL, }, +#endif [AV_PIX_FMT_UYVY422] = { .name = "uyvy422", .nb_components = 3, diff --git a/libavutil/pixelutils.c b/libavutil/pixelutils.c index ebee3d6f9..820889a14 100644 --- a/libavutil/pixelutils.c +++ b/libavutil/pixelutils.c @@ -16,12 +16,17 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + #include "config.h" -#include "common.h" #include "pixelutils.h" -#include "internal.h" #if CONFIG_PIXELUTILS +#include +#include + +#include "attributes.h" +#include "macros.h" #include "x86/pixelutils.h" @@ -60,7 +65,8 @@ static const av_pixelutils_sad_fn sad_c[] = { block_sad_16x16_c, block_sad_32x32_c, }; - +#else +#include "log.h" #endif /* CONFIG_PIXELUTILS */ av_pixelutils_sad_fn av_pixelutils_get_sad_fn(int w_bits, int h_bits, int aligned, void *log_ctx) diff --git a/libavutil/pixelutils.h b/libavutil/pixelutils.h index a8dbc157e..7a997cde1 100644 --- a/libavutil/pixelutils.h +++ b/libavutil/pixelutils.h @@ -21,7 +21,6 @@ #include #include -#include "common.h" /** * Sum of abs(src1[x] - src2[x]) diff --git a/libavutil/pixfmt.h b/libavutil/pixfmt.h index 02e355eb4..2d3927cc3 100644 --- a/libavutil/pixfmt.h +++ b/libavutil/pixfmt.h @@ -260,7 +260,9 @@ enum AVPixelFormat { AV_PIX_FMT_BAYER_GRBG16LE, ///< bayer, GRGR..(odd line), BGBG..(even line), 16-bit samples, little-endian AV_PIX_FMT_BAYER_GRBG16BE, ///< bayer, GRGR..(odd line), BGBG..(even line), 16-bit samples, big-endian +#if FF_API_XVMC AV_PIX_FMT_XVMC,///< XVideo Motion Acceleration via common packet passing +#endif AV_PIX_FMT_YUV440P10LE, ///< planar YUV 4:4:0,20bpp, (1 Cr & Cb sample per 1x2 Y samples), little-endian AV_PIX_FMT_YUV440P10BE, ///< planar YUV 4:4:0,20bpp, (1 Cr & Cb sample per 1x2 Y samples), big-endian @@ -360,7 +362,7 @@ enum AVPixelFormat { AV_PIX_FMT_P410LE, ///< interleaved chroma YUV 4:4:4, 30bpp, data in the high bits, little-endian AV_PIX_FMT_P216BE, ///< interleaved chroma YUV 4:2:2, 32bpp, big-endian - AV_PIX_FMT_P216LE, ///< interleaved chroma YUV 4:2:2, 32bpp, liddle-endian + AV_PIX_FMT_P216LE, ///< interleaved chroma YUV 4:2:2, 32bpp, little-endian AV_PIX_FMT_P416BE, ///< interleaved chroma YUV 4:4:4, 48bpp, big-endian AV_PIX_FMT_P416LE, ///< interleaved chroma YUV 4:4:4, 48bpp, little-endian diff --git a/libavutil/ppc/cpu.c b/libavutil/ppc/cpu.c index b022149fa..96b491c71 100644 --- a/libavutil/ppc/cpu.c +++ b/libavutil/ppc/cpu.c @@ -28,7 +28,7 @@ #include #endif #elif defined(__OpenBSD__) -#include +#include #include #include #elif defined(__AMIGAOS4__) diff --git a/libavutil/qsort.h b/libavutil/qsort.h index 39b7a0885..6014f88be 100644 --- a/libavutil/qsort.h +++ b/libavutil/qsort.h @@ -21,7 +21,7 @@ #ifndef AVUTIL_QSORT_H #define AVUTIL_QSORT_H -#include "common.h" +#include "macros.h" /** diff --git a/libavutil/rc4.c b/libavutil/rc4.c index ffcb11214..74c1f4892 100644 --- a/libavutil/rc4.c +++ b/libavutil/rc4.c @@ -20,8 +20,9 @@ * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "avutil.h" -#include "common.h" + +#include "error.h" +#include "macros.h" #include "mem.h" #include "rc4.h" diff --git a/libavutil/ripemd.c b/libavutil/ripemd.c index b8e9761a2..e170c69f4 100644 --- a/libavutil/ripemd.c +++ b/libavutil/ripemd.c @@ -22,10 +22,12 @@ #include #include +#include "config.h" #include "attributes.h" -#include "avutil.h" #include "bswap.h" +#include "error.h" #include "intreadwrite.h" +#include "macros.h" #include "ripemd.h" #include "mem.h" diff --git a/libavutil/samplefmt.c b/libavutil/samplefmt.c index c7428940e..6d3ec34da 100644 --- a/libavutil/samplefmt.c +++ b/libavutil/samplefmt.c @@ -16,11 +16,13 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "common.h" +#include "error.h" +#include "macros.h" +#include "mem.h" #include "samplefmt.h" +#include #include -#include #include typedef struct SampleFmtInfo { diff --git a/libavutil/samplefmt.h b/libavutil/samplefmt.h index f27019919..1999c9bca 100644 --- a/libavutil/samplefmt.h +++ b/libavutil/samplefmt.h @@ -21,9 +21,6 @@ #include -#include "avutil.h" -#include "attributes.h" - /** * @addtogroup lavu_audio * @{ diff --git a/libavutil/sha.c b/libavutil/sha.c index ab42869c7..0df044032 100644 --- a/libavutil/sha.c +++ b/libavutil/sha.c @@ -23,9 +23,10 @@ #include +#include "config.h" #include "attributes.h" -#include "avutil.h" #include "bswap.h" +#include "error.h" #include "sha.h" #include "intreadwrite.h" #include "mem.h" diff --git a/libavutil/sha512.c b/libavutil/sha512.c index 97aaaa865..0574a46f9 100644 --- a/libavutil/sha512.c +++ b/libavutil/sha512.c @@ -23,9 +23,10 @@ #include +#include "config.h" #include "attributes.h" -#include "avutil.h" #include "bswap.h" +#include "error.h" #include "sha512.h" #include "intreadwrite.h" #include "mem.h" diff --git a/libavutil/slicethread.c b/libavutil/slicethread.c index 867ce3223..ea1c9c831 100644 --- a/libavutil/slicethread.c +++ b/libavutil/slicethread.c @@ -18,6 +18,7 @@ #include #include "cpu.h" +#include "internal.h" #include "slicethread.h" #include "mem.h" #include "thread.h" diff --git a/libavutil/stereo3d.c b/libavutil/stereo3d.c index 279fcc1ff..9c29ab01b 100644 --- a/libavutil/stereo3d.c +++ b/libavutil/stereo3d.c @@ -21,7 +21,8 @@ #include #include "avstring.h" -#include "common.h" +#include "frame.h" +#include "macros.h" #include "mem.h" #include "stereo3d.h" diff --git a/libavutil/tea.c b/libavutil/tea.c index b138f8bea..93a379536 100644 --- a/libavutil/tea.c +++ b/libavutil/tea.c @@ -22,9 +22,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "avutil.h" -#include "common.h" +#include #include "intreadwrite.h" +#include "mem.h" #include "tea.h" typedef struct AVTEA { diff --git a/libavutil/tests/adler32.c b/libavutil/tests/adler32.c index 13f760b47..356e1a97e 100644 --- a/libavutil/tests/adler32.c +++ b/libavutil/tests/adler32.c @@ -27,12 +27,11 @@ #define LEN 7001 -static volatile int checksum; - int main(int argc, char **argv) { int i; uint8_t data[LEN]; + AVAdler checksum; av_log_set_level(AV_LOG_DEBUG); diff --git a/libavutil/tests/aes_ctr.c b/libavutil/tests/aes_ctr.c index 9dbf0af8a..486dae334 100644 --- a/libavutil/tests/aes_ctr.c +++ b/libavutil/tests/aes_ctr.c @@ -16,6 +16,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + #include "libavutil/log.h" #include "libavutil/mem_internal.h" #include "libavutil/aes_ctr.h" diff --git a/libavutil/tests/camellia.c b/libavutil/tests/camellia.c index 1716b59a3..9fdd6cd7e 100644 --- a/libavutil/tests/camellia.c +++ b/libavutil/tests/camellia.c @@ -19,8 +19,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include +#include + #include "libavutil/camellia.h" #include "libavutil/log.h" +#include "libavutil/mem.h" int main(int argc, char *argv[]) { diff --git a/libavutil/tests/cast5.c b/libavutil/tests/cast5.c index ce3aa80b5..1ba3075e7 100644 --- a/libavutil/tests/cast5.c +++ b/libavutil/tests/cast5.c @@ -19,8 +19,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include +#include + #include "libavutil/cast5.h" #include "libavutil/log.h" +#include "libavutil/mem.h" int main(int argc, char** argv) { diff --git a/libavutil/tests/channel_layout.c b/libavutil/tests/channel_layout.c new file mode 100644 index 000000000..5516db090 --- /dev/null +++ b/libavutil/tests/channel_layout.c @@ -0,0 +1,353 @@ +/* + * Copyright (c) 2021 James Almer + * + * 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.c" + +#define CHANNEL_NAME(x) \ + av_bprint_clear(&bp); \ + av_channel_name_bprint(&bp, x); + +#define CHANNEL_DESCRIPTION(x) \ + av_bprint_clear(&bp); \ + av_channel_description_bprint(&bp, x); + +#define CHANNEL_LAYOUT_FROM_MASK(x) \ + av_channel_layout_uninit(&layout); \ + av_bprint_clear(&bp); \ + if (!av_channel_layout_from_mask(&layout, x) && \ + av_channel_layout_check(&layout)) \ + av_channel_layout_describe_bprint(&layout, &bp); \ + else \ + av_bprintf(&bp, "fail"); + +#define CHANNEL_LAYOUT_FROM_STRING(x) \ + av_channel_layout_uninit(&layout); \ + av_bprint_clear(&bp); \ + if (!av_channel_layout_from_string(&layout, x) && \ + av_channel_layout_check(&layout)) \ + av_channel_layout_describe_bprint(&layout, &bp); \ + else \ + av_bprintf(&bp, "fail"); + +#define CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(x) \ + ret = av_channel_layout_channel_from_index(&layout, x); \ + if (ret < 0) \ + ret = -1 + +#define CHANNEL_LAYOUT_SUBSET(x) \ + mask = av_channel_layout_subset(&layout, x) + +#define CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(x) \ + ret = av_channel_layout_index_from_channel(&layout, x); \ + if (ret < 0) \ + ret = -1 + +#define CHANNEL_LAYOUT_CHANNEL_FROM_STRING(x) \ + ret = av_channel_layout_channel_from_string(&layout, x); \ + if (ret < 0) \ + ret = -1 + +#define CHANNEL_LAYOUT_INDEX_FROM_STRING(x) \ + ret = av_channel_layout_index_from_string(&layout, x); \ + if (ret < 0) \ + ret = -1 + +int main(void) +{ + const AVChannelLayout *playout; + AVChannelLayout layout = { 0 }; + AVBPrint bp; + void *iter = NULL; + uint64_t mask; + int ret; + + av_bprint_init(&bp, 64, AV_BPRINT_SIZE_AUTOMATIC); + + printf("Testing av_channel_layout_standard\n"); + while (playout = av_channel_layout_standard(&iter)) { + av_channel_layout_describe_bprint(playout, &bp); + printf("%-14s ", bp.str); + av_bprint_clear(&bp); + for (int i = 0; i < 63; i++) { + int idx = av_channel_layout_index_from_channel(playout, i); + if (idx >= 0) { + if (idx) + av_bprintf(&bp, "+"); + av_channel_name_bprint(&bp, i); + } + } + printf("%s\n", bp.str); + av_bprint_clear(&bp); + } + + printf("\nTesting av_channel_name\n"); + CHANNEL_NAME(AV_CHAN_FRONT_LEFT); + printf("With AV_CHAN_FRONT_LEFT: %27s\n", bp.str); + CHANNEL_NAME(AV_CHAN_FRONT_RIGHT); + printf("With AV_CHAN_FRONT_RIGHT: %26s\n", bp.str); + CHANNEL_NAME(63); + printf("With 63: %43s\n", bp.str); + CHANNEL_NAME(AV_CHAN_AMBISONIC_BASE); + printf("With AV_CHAN_AMBISONIC_BASE: %23s\n", bp.str); + CHANNEL_NAME(AV_CHAN_AMBISONIC_END); + printf("With AV_CHAN_AMBISONIC_END: %24s\n", bp.str); + + printf("Testing av_channel_description\n"); + CHANNEL_DESCRIPTION(AV_CHAN_FRONT_LEFT); + printf("With AV_CHAN_FRONT_LEFT: %27s\n", bp.str); + CHANNEL_DESCRIPTION(AV_CHAN_FRONT_RIGHT); + printf("With AV_CHAN_FRONT_RIGHT: %26s\n", bp.str); + CHANNEL_DESCRIPTION(63); + printf("With 63: %43s\n", bp.str); + CHANNEL_DESCRIPTION(AV_CHAN_AMBISONIC_BASE); + printf("With AV_CHAN_AMBISONIC_BASE: %23s\n", bp.str); + CHANNEL_DESCRIPTION(AV_CHAN_AMBISONIC_END); + printf("With AV_CHAN_AMBISONIC_END: %24s\n", bp.str); + + printf("\nTesting av_channel_from_string\n"); + printf("With \"FL\": %41d\n", av_channel_from_string("FL")); + printf("With \"FR\": %41d\n", av_channel_from_string("FR")); + printf("With \"USR63\": %38d\n", av_channel_from_string("USR63")); + printf("With \"AMBI0\": %38d\n", av_channel_from_string("AMBI0")); + printf("With \"AMBI1023\": %35d\n", av_channel_from_string("AMBI1023")); + + printf("\n==Native layouts==\n"); + + printf("\nTesting av_channel_layout_from_string\n"); + CHANNEL_LAYOUT_FROM_STRING("0x3f"); + printf("With \"0x3f\": %39s\n", bp.str); + CHANNEL_LAYOUT_FROM_STRING("63"); + printf("With \"63\": %41s\n", bp.str); + CHANNEL_LAYOUT_FROM_STRING("6c"); + printf("With \"6c\": %41s\n", bp.str); + CHANNEL_LAYOUT_FROM_STRING("6C"); + printf("With \"6C\": %41s\n", bp.str); + CHANNEL_LAYOUT_FROM_STRING("6 channels"); + printf("With \"6 channels\": %33s\n", bp.str); + CHANNEL_LAYOUT_FROM_STRING("6 channels (FL+FR+FC+LFE+BL+BR)"); + printf("With \"6 channels (FL+FR+FC+LFE+BL+BR)\": %12s\n", bp.str); + CHANNEL_LAYOUT_FROM_STRING("FL+FR+FC+LFE+BL+BR"); + printf("With \"FL+FR+FC+LFE+BL+BR\": %25s\n", bp.str); + CHANNEL_LAYOUT_FROM_STRING("5.1"); + printf("With \"5.1\": %40s\n", bp.str); + CHANNEL_LAYOUT_FROM_STRING("FL+FR+USR63"); + printf("With \"FL+FR+USR63\": %32s\n", bp.str); + CHANNEL_LAYOUT_FROM_STRING("FL+FR+FC+LFE+SL+SR"); + printf("With \"FL+FR+FC+LFE+SL+SR\": %25s\n", bp.str); + CHANNEL_LAYOUT_FROM_STRING("5.1(side)"); + printf("With \"5.1(side)\": %34s\n", bp.str); + + printf("\nTesting av_channel_layout_from_mask\n"); + CHANNEL_LAYOUT_FROM_MASK(AV_CH_LAYOUT_5POINT1); + printf("With AV_CH_LAYOUT_5POINT1: %25s\n", bp.str); + + printf("\nTesting av_channel_layout_channel_from_index\n"); + CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(0); + printf("On 5.1(side) layout with 0: %24d\n", ret); + CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(1); + printf("On 5.1(side) layout with 1: %24d\n", ret); + CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(2); + printf("On 5.1(side) layout with 2: %24d\n", ret); + CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(3); + printf("On 5.1(side) layout with 3: %24d\n", ret); + CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(4); + printf("On 5.1(side) layout with 4: %24d\n", ret); + CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(5); + printf("On 5.1(side) layout with 5: %24d\n", ret); + CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(6); + printf("On 5.1(side) layout with 6: %24d\n", ret); + + printf("\nTesting av_channel_layout_index_from_channel\n"); + CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(AV_CHAN_FRONT_LEFT); + printf("On 5.1(side) layout with AV_CHAN_FRONT_LEFT: %7d\n", ret); + CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(AV_CHAN_FRONT_RIGHT); + printf("On 5.1(side) layout with AV_CHAN_FRONT_RIGHT: %6d\n", ret); + CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(AV_CHAN_FRONT_CENTER); + printf("On 5.1(side) layout with AV_CHAN_FRONT_CENTER: %5d\n", ret); + CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(AV_CHAN_LOW_FREQUENCY); + printf("On 5.1(side) layout with AV_CHAN_LOW_FREQUENCY: %4d\n", ret); + CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(AV_CHAN_SIDE_LEFT); + printf("On 5.1(side) layout with AV_CHAN_SIDE_LEFT: %8d\n", ret); + CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(AV_CHAN_SIDE_RIGHT); + printf("On 5.1(side) layout with AV_CHAN_SIDE_RIGHT: %7d\n", ret); + CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(AV_CHAN_BACK_CENTER); + printf("On 5.1(side) layout with AV_CHAN_BACK_CENTER: %6d\n", ret); + + printf("\nTesting av_channel_layout_channel_from_string\n"); + CHANNEL_LAYOUT_CHANNEL_FROM_STRING("FL"); + printf("On 5.1(side) layout with \"FL\": %21d\n", ret); + CHANNEL_LAYOUT_CHANNEL_FROM_STRING("FR"); + printf("On 5.1(side) layout with \"FR\": %21d\n", ret); + CHANNEL_LAYOUT_CHANNEL_FROM_STRING("FC"); + printf("On 5.1(side) layout with \"FC\": %21d\n", ret); + CHANNEL_LAYOUT_CHANNEL_FROM_STRING("LFE"); + printf("On 5.1(side) layout with \"LFE\": %20d\n", ret); + CHANNEL_LAYOUT_CHANNEL_FROM_STRING("SL"); + printf("On 5.1(side) layout with \"SL\": %21d\n", ret); + CHANNEL_LAYOUT_CHANNEL_FROM_STRING("SR"); + printf("On 5.1(side) layout with \"SR\": %21d\n", ret); + CHANNEL_LAYOUT_CHANNEL_FROM_STRING("BC"); + printf("On 5.1(side) layout with \"BC\": %21d\n", ret); + + printf("\nTesting av_channel_layout_index_from_string\n"); + CHANNEL_LAYOUT_INDEX_FROM_STRING("FL"); + printf("On 5.1(side) layout with \"FL\": %21d\n", ret); + CHANNEL_LAYOUT_INDEX_FROM_STRING("FR"); + printf("On 5.1(side) layout with \"FR\": %21d\n", ret); + CHANNEL_LAYOUT_INDEX_FROM_STRING("FC"); + printf("On 5.1(side) layout with \"FC\": %21d\n", ret); + CHANNEL_LAYOUT_INDEX_FROM_STRING("LFE"); + printf("On 5.1(side) layout with \"LFE\": %20d\n", ret); + CHANNEL_LAYOUT_INDEX_FROM_STRING("SL"); + printf("On 5.1(side) layout with \"SL\": %21d\n", ret); + CHANNEL_LAYOUT_INDEX_FROM_STRING("SR"); + printf("On 5.1(side) layout with \"SR\": %21d\n", ret); + CHANNEL_LAYOUT_INDEX_FROM_STRING("BC"); + printf("On 5.1(side) layout with \"BC\": %21d\n", ret); + + printf("\nTesting av_channel_layout_subset\n"); + CHANNEL_LAYOUT_SUBSET(AV_CH_LAYOUT_STEREO); + printf("On 5.1(side) layout with AV_CH_LAYOUT_STEREO: 0x%"PRIx64"\n", mask); + CHANNEL_LAYOUT_SUBSET(AV_CH_LAYOUT_2POINT1); + printf("On 5.1(side) layout with AV_CH_LAYOUT_2POINT1: 0x%"PRIx64"\n", mask); + CHANNEL_LAYOUT_SUBSET(AV_CH_LAYOUT_4POINT1); + printf("On 5.1(side) layout with AV_CH_LAYOUT_4POINT1: 0x%"PRIx64"\n", mask); + + printf("\n==Custom layouts==\n"); + + printf("\nTesting av_channel_layout_from_string\n"); + CHANNEL_LAYOUT_FROM_STRING("FL+FR+FC+BL+BR+LFE"); + printf("With \"FL+FR+FC+BL+BR+LFE\": %34s\n", bp.str); + CHANNEL_LAYOUT_FROM_STRING("2 channels (FR+FL)"); + printf("With \"2 channels (FR+FL)\": %34s\n", bp.str); + CHANNEL_LAYOUT_FROM_STRING("ambisonic 1+FR+FL"); + printf("With \"ambisonic 1+FR+FL\": %35s\n", bp.str); + CHANNEL_LAYOUT_FROM_STRING("ambisonic 2+FC@Foo"); + printf("With \"ambisonic 2+FC@Foo\": %34s\n", bp.str); + CHANNEL_LAYOUT_FROM_STRING("FL@Foo+FR@Bar"); + printf("With \"FL@Foo+FR@Bar\": %39s\n", bp.str); + CHANNEL_LAYOUT_FROM_STRING("FR+FL@Foo+USR63@Foo"); + printf("With \"FR+FL@Foo+USR63@Foo\": %33s\n", bp.str); + + printf("\nTesting av_channel_layout_index_from_string\n"); + CHANNEL_LAYOUT_INDEX_FROM_STRING("FR"); + printf("On \"FR+FL@Foo+USR63@Foo\" layout with \"FR\": %18d\n", ret); + CHANNEL_LAYOUT_INDEX_FROM_STRING("FL"); + printf("On \"FR+FL@Foo+USR63@Foo\" layout with \"FL\": %18d\n", ret); + CHANNEL_LAYOUT_INDEX_FROM_STRING("USR63"); + printf("On \"FR+FL@Foo+USR63@Foo\" layout with \"USR63\": %15d\n", ret); + CHANNEL_LAYOUT_INDEX_FROM_STRING("Foo"); + printf("On \"FR+FL@Foo+USR63@Foo\" layout with \"Foo\": %17d\n", ret); + CHANNEL_LAYOUT_INDEX_FROM_STRING("@Foo"); + printf("On \"FR+FL@Foo+USR63@Foo\" layout with \"@Foo\": %16d\n", ret); + CHANNEL_LAYOUT_INDEX_FROM_STRING("FR@Foo"); + printf("On \"FR+FL@Foo+USR63@Foo\" layout with \"FR@Foo\": %14d\n", ret); + CHANNEL_LAYOUT_INDEX_FROM_STRING("FL@Foo"); + printf("On \"FR+FL@Foo+USR63@Foo\" layout with \"FL@Foo\": %14d\n", ret); + CHANNEL_LAYOUT_INDEX_FROM_STRING("USR63@Foo"); + printf("On \"FR+FL@Foo+USR63@Foo\" layout with \"USR63@Foo\": %11d\n", ret); + CHANNEL_LAYOUT_INDEX_FROM_STRING("BC"); + printf("On \"FR+FL@Foo+USR63@Foo\" layout with \"BC\": %18d\n", ret); + + printf("\nTesting av_channel_layout_channel_from_string\n"); + CHANNEL_LAYOUT_CHANNEL_FROM_STRING("FR"); + printf("On \"FR+FL@Foo+USR63@Foo\" layout with \"FR\": %18d\n", ret); + CHANNEL_LAYOUT_CHANNEL_FROM_STRING("FL"); + printf("On \"FR+FL@Foo+USR63@Foo\" layout with \"FL\": %18d\n", ret); + CHANNEL_LAYOUT_CHANNEL_FROM_STRING("USR63"); + printf("On \"FR+FL@Foo+USR63@Foo\" layout with \"USR63\": %15d\n", ret); + CHANNEL_LAYOUT_CHANNEL_FROM_STRING("Foo"); + printf("On \"FR+FL@Foo+USR63@Foo\" layout with \"Foo\": %17d\n", ret); + CHANNEL_LAYOUT_CHANNEL_FROM_STRING("@Foo"); + printf("On \"FR+FL@Foo+USR63@Foo\" layout with \"@Foo\": %16d\n", ret); + CHANNEL_LAYOUT_CHANNEL_FROM_STRING("FR@Foo"); + printf("On \"FR+FL@Foo+USR63@Foo\" layout with \"FR@Foo\": %14d\n", ret); + CHANNEL_LAYOUT_CHANNEL_FROM_STRING("FL@Foo"); + printf("On \"FR+FL@Foo+USR63@Foo\" layout with \"FL@Foo\": %14d\n", ret); + CHANNEL_LAYOUT_CHANNEL_FROM_STRING("USR63@Foo"); + printf("On \"FR+FL@Foo+USR63@Foo\" layout with \"USR63@Foo\": %11d\n", ret); + CHANNEL_LAYOUT_CHANNEL_FROM_STRING("BC"); + printf("On \"FR+FL@Foo+USR63@Foo\" layout with \"BC\": %18d\n", ret); + + printf("\nTesting av_channel_layout_index_from_channel\n"); + CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(AV_CHAN_FRONT_RIGHT); + printf("On \"FR+FL@Foo+USR63@Foo\" layout with AV_CHAN_FRONT_RIGHT: %3d\n", ret); + CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(AV_CHAN_FRONT_LEFT); + printf("On \"FR+FL@Foo+USR63@Foo\" layout with AV_CHAN_FRONT_LEFT: %4d\n", ret); + CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(63); + printf("On \"FR+FL@Foo+USR63@Foo\" layout with 63: %20d\n", ret); + CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(AV_CHAN_BACK_CENTER); + printf("On \"FR+FL@Foo+USR63@Foo\" layout with AV_CHAN_BACK_CENTER: %3d\n", ret); + + printf("\nTesting av_channel_layout_channel_from_index\n"); + CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(0); + printf("On \"FR+FL@Foo+USR63@Foo\" layout with 0: %21d\n", ret); + CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(1); + printf("On \"FR+FL@Foo+USR63@Foo\" layout with 1: %21d\n", ret); + CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(2); + printf("On \"FR+FL@Foo+USR63@Foo\" layout with 2: %21d\n", ret); + CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(3); + printf("On \"FR+FL@Foo+USR63@Foo\" layout with 3: %21d\n", ret); + + printf("\nTesting av_channel_layout_subset\n"); + CHANNEL_LAYOUT_SUBSET(AV_CH_LAYOUT_STEREO); + printf("On \"FR+FL@Foo+USR63@Foo\" layout with AV_CH_LAYOUT_STEREO: 0x%"PRIx64"\n", mask); + CHANNEL_LAYOUT_SUBSET(AV_CH_LAYOUT_QUAD); + printf("On \"FR+FL@Foo+USR63@Foo\" layout with AV_CH_LAYOUT_QUAD: 0x%"PRIx64"\n", mask); + + printf("\n==Ambisonic layouts==\n"); + + printf("\nTesting av_channel_layout_from_string\n"); + CHANNEL_LAYOUT_FROM_STRING("ambisonic 1"); + printf("With \"ambisonic 1\": %41s\n", bp.str); + CHANNEL_LAYOUT_FROM_STRING("ambisonic 2+stereo"); + printf("With \"ambisonic 2+stereo\": %34s\n", bp.str); + + printf("\nTesting av_channel_layout_index_from_channel\n"); + CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(AV_CHAN_AMBISONIC_BASE); + printf("On \"ambisonic 2+stereo\" layout with AV_CHAN_AMBISONIC_BASE: %d\n", ret); + CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(AV_CHAN_FRONT_LEFT); + printf("On \"ambisonic 2+stereo\" layout with AV_CHAN_FRONT_LEFT: %5d\n", ret); + CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(AV_CHAN_FRONT_RIGHT); + printf("On \"ambisonic 2+stereo\" layout with AV_CHAN_FRONT_RIGHT: %4d\n", ret); + CHANNEL_LAYOUT_INDEX_FROM_CHANNEL(AV_CHAN_BACK_CENTER); + printf("On \"ambisonic 2+stereo\" layout with AV_CHAN_BACK_CENTER: %4d\n", ret); + + printf("\nTesting av_channel_layout_channel_from_index\n"); + CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(0); + printf("On \"ambisonic 2+stereo\" layout with 0: %22d\n", ret); + CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(9); + printf("On \"ambisonic 2+stereo\" layout with 9: %22d\n", ret); + CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(10); + printf("On \"ambisonic 2+stereo\" layout with 10: %21d\n", ret); + CHANNEL_LAYOUT_CHANNEL_FROM_INDEX(11); + printf("On \"ambisonic 2+stereo\" layout with 11: %21d\n", ret); + + printf("\nTesting av_channel_layout_subset\n"); + CHANNEL_LAYOUT_SUBSET(AV_CH_LAYOUT_STEREO); + printf("On \"ambisonic 2+stereo\" layout with AV_CH_LAYOUT_STEREO: 0x%"PRIx64"\n", mask); + CHANNEL_LAYOUT_SUBSET(AV_CH_LAYOUT_QUAD); + printf("On \"ambisonic 2+stereo\" layout with AV_CH_LAYOUT_QUAD: 0x%"PRIx64"\n", mask); + + av_channel_layout_uninit(&layout); + av_bprint_finalize(&bp, NULL); + + return 0; +} diff --git a/libavutil/tests/color_utils.c b/libavutil/tests/color_utils.c index ea0127158..4bdc55033 100644 --- a/libavutil/tests/color_utils.c +++ b/libavutil/tests/color_utils.c @@ -18,7 +18,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include "libavutil/color_utils.c" +#include "libavutil/macros.h" int main(int argc, char *argv[]) { diff --git a/libavutil/tests/display.c b/libavutil/tests/display.c index 893ebb554..19b07fc15 100644 --- a/libavutil/tests/display.c +++ b/libavutil/tests/display.c @@ -18,6 +18,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include "libavutil/display.c" static void print_matrix(int32_t matrix[9]) diff --git a/libavutil/tests/encryption_info.c b/libavutil/tests/encryption_info.c index d489612b7..55c668c6d 100644 --- a/libavutil/tests/encryption_info.c +++ b/libavutil/tests/encryption_info.c @@ -22,6 +22,7 @@ #include #include "libavutil/avassert.h" +#include "libavutil/mem.h" static const AVSubsampleEncryptionInfo test_subsamples[] = {{1, 2}, {3, 4}, {5, 6}, {7, 8}}; static const size_t test_subsample_count = sizeof(test_subsamples) / sizeof(test_subsamples[0]); diff --git a/libavutil/tests/fifo.c b/libavutil/tests/fifo.c index 8a550e088..8cbc44c43 100644 --- a/libavutil/tests/fifo.c +++ b/libavutil/tests/fifo.c @@ -18,91 +18,179 @@ #include #include +#include "libavutil/common.h" #include "libavutil/fifo.h" +#include "libavutil/lfg.h" +#include "libavutil/random_seed.h" + +typedef struct CBState { + unsigned int read_idx; + unsigned int write_idx; + unsigned int to_process; + unsigned int offset; +} CBState; + +static int read_cb(void *opaque, void *buf, size_t *nb_elems) +{ + CBState *s = opaque; + unsigned *b = buf; + + *nb_elems = FFMIN(*nb_elems, s->to_process); + + for (unsigned i = 0; i < *nb_elems; i++) + if (b[i] != s->read_idx + s->offset + i) { + printf("Mismatch at idx %u offset %u i %u\n", + s->read_idx, s->offset, i); + return AVERROR_BUG; + } + + s->offset += *nb_elems; + s->to_process -= *nb_elems; + + return 0; +} + +static int write_cb(void *opaque, void *buf, size_t *nb_elems) +{ + CBState *s = opaque; + unsigned *b = buf; + + *nb_elems = FFMIN(*nb_elems, s->to_process); + + for (unsigned i = 0; i < *nb_elems; i++) + b[i] = s->write_idx + i; + + s->write_idx += *nb_elems; + s->to_process -= *nb_elems; + + return 0; +} int main(void) { /* create a FIFO buffer */ - AVFifoBuffer *fifo = av_fifo_alloc(13 * sizeof(int)); + AVFifo *fifo = av_fifo_alloc2(13, sizeof(int), 0); int i, j, n, *p; /* fill data */ - for (i = 0; av_fifo_space(fifo) >= sizeof(int); i++) - av_fifo_generic_write(fifo, &i, sizeof(int), NULL); - - /* peek at FIFO */ - n = av_fifo_size(fifo) / sizeof(int); - for (i = -n + 1; i < n; i++) { - int *v = (int *)av_fifo_peek2(fifo, i * sizeof(int)); - printf("%d: %d\n", i, *v); - } - printf("\n"); + for (i = 0; av_fifo_can_write(fifo); i++) + av_fifo_write(fifo, &i, 1); /* peek_at at FIFO */ - n = av_fifo_size(fifo) / sizeof(int); + n = av_fifo_can_read(fifo); for (i = 0; i < n; i++) { - av_fifo_generic_peek_at(fifo, &j, i * sizeof(int), sizeof(j), NULL); + av_fifo_peek(fifo, &j, 1, i); printf("%d: %d\n", i, j); } printf("\n"); /* generic peek at FIFO */ - n = av_fifo_size(fifo); - p = malloc(n); + n = av_fifo_can_read(fifo); + p = malloc(n * av_fifo_elem_size(fifo)); if (p == NULL) { fprintf(stderr, "failed to allocate memory.\n"); exit(1); } - (void) av_fifo_generic_peek(fifo, p, n, NULL); + (void) av_fifo_peek(fifo, p, n, 0); /* read data at p */ - n /= sizeof(int); for(i = 0; i < n; ++i) printf("%d: %d\n", i, p[i]); putchar('\n'); /* read data */ - for (i = 0; av_fifo_size(fifo) >= sizeof(int); i++) { - av_fifo_generic_read(fifo, &j, sizeof(int), NULL); + for (i = 0; av_fifo_can_read(fifo); i++) { + av_fifo_read(fifo, &j, 1); printf("%d ", j); } printf("\n"); - /* test *ndx overflow */ - av_fifo_reset(fifo); - fifo->rndx = fifo->wndx = ~(uint32_t)0 - 5; - /* fill data */ - for (i = 0; av_fifo_space(fifo) >= sizeof(int); i++) - av_fifo_generic_write(fifo, &i, sizeof(int), NULL); + for (i = 0; av_fifo_can_write(fifo); i++) + av_fifo_write(fifo, &i, 1); /* peek_at at FIFO */ - n = av_fifo_size(fifo) / sizeof(int); + n = av_fifo_can_read(fifo); for (i = 0; i < n; i++) { - av_fifo_generic_peek_at(fifo, &j, i * sizeof(int), sizeof(j), NULL); + av_fifo_peek(fifo, &j, 1, i); printf("%d: %d\n", i, j); } putchar('\n'); /* test fifo_grow */ - (void) av_fifo_grow(fifo, 15 * sizeof(int)); + (void) av_fifo_grow2(fifo, 15); /* fill data */ - n = av_fifo_size(fifo) / sizeof(int); - for (i = n; av_fifo_space(fifo) >= sizeof(int); ++i) - av_fifo_generic_write(fifo, &i, sizeof(int), NULL); + n = av_fifo_can_read(fifo); + for (i = n; av_fifo_can_write(fifo); ++i) + av_fifo_write(fifo, &i, 1); /* peek_at at FIFO */ - n = av_fifo_size(fifo) / sizeof(int); + n = av_fifo_can_read(fifo); for (i = 0; i < n; i++) { - av_fifo_generic_peek_at(fifo, &j, i * sizeof(int), sizeof(j), NULL); + av_fifo_peek(fifo, &j, 1, i); printf("%d: %d\n", i, j); } - av_fifo_free(fifo); + av_fifo_freep2(&fifo); + + /* test randomly-sized write/read/peek with a callback */ + { + CBState s = { 0 }; + uint32_t seed = av_get_random_seed(); + + AVLFG lfg; + int ret; + + av_lfg_init(&lfg, seed); + + fifo = av_fifo_alloc2(1, sizeof(unsigned), AV_FIFO_FLAG_AUTO_GROW); + + for (i = 0; i < 32; i++) { + size_t nb_elems = 16; + unsigned to_process = av_lfg_get(&lfg) % nb_elems; + + s.to_process = to_process; + + ret = av_fifo_write_from_cb(fifo, write_cb, &s, &nb_elems); + if (ret < 0 || s.to_process || nb_elems != to_process) { + printf("FIFO write fail; seed %"PRIu32"\n", seed); + return 1; + } + + nb_elems = av_fifo_can_read(fifo); + if (nb_elems > 1) { + s.offset = av_lfg_get(&lfg) % (nb_elems - 1); + nb_elems -= s.offset; + + s.to_process = av_lfg_get(&lfg) % nb_elems; + to_process = s.to_process; + + ret = av_fifo_peek_to_cb(fifo, read_cb, &s, &nb_elems, s.offset); + if (ret < 0 || s.to_process || nb_elems != to_process) { + printf("FIFO peek fail; seed %"PRIu32"\n", seed); + return 1; + } + } + + nb_elems = av_fifo_can_read(fifo); + to_process = nb_elems ? av_lfg_get(&lfg) % nb_elems : 0; + s.to_process = to_process; + s.offset = 0; + + ret = av_fifo_read_to_cb(fifo, read_cb, &s, &nb_elems); + if (ret < 0 || s.to_process || to_process != nb_elems) { + printf("FIFO read fail; seed %"PRIu32"\n", seed); + return 1; + } + s.read_idx += s.offset; + } + } + + av_fifo_freep2(&fifo); free(p); return 0; diff --git a/libavutil/tests/md5.c b/libavutil/tests/md5.c index 42e4538e0..0ac8f2834 100644 --- a/libavutil/tests/md5.c +++ b/libavutil/tests/md5.c @@ -33,8 +33,8 @@ int main(void) { uint8_t md5val[16]; int i; - volatile uint8_t in[1000]; // volatile to workaround http://llvm.org/bugs/show_bug.cgi?id=20849 - // FIXME remove volatile once it has been fixed and all fate clients are updated + + uint8_t in[1000]; for (i = 0; i < 1000; i++) in[i] = i * i; diff --git a/libavutil/tests/opt.c b/libavutil/tests/opt.c index e6ea89237..5799e45c6 100644 --- a/libavutil/tests/opt.c +++ b/libavutil/tests/opt.c @@ -41,7 +41,7 @@ typedef struct TestContext { enum AVSampleFormat sample_fmt; int64_t duration; uint8_t color[4]; - int64_t channel_layout; + AVChannelLayout channel_layout; void *binary; int binary_size; void *binary1; @@ -81,7 +81,7 @@ static const AVOption test_options[]= { {"video_rate", "set videorate", OFFSET(video_rate), AV_OPT_TYPE_VIDEO_RATE, { .str = "25" }, 0, INT_MAX, 1 }, {"duration", "set duration", OFFSET(duration), AV_OPT_TYPE_DURATION, { .i64 = 1000 }, 0, INT64_MAX, 1 }, {"color", "set color", OFFSET(color), AV_OPT_TYPE_COLOR, { .str = "pink" }, 0, 0, 1 }, - {"cl", "set channel layout", OFFSET(channel_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, { .i64 = AV_CH_LAYOUT_HEXAGONAL }, 0, INT64_MAX, 1 }, + {"cl", "set channel layout", OFFSET(channel_layout), AV_OPT_TYPE_CHLAYOUT, { .str = "hexagonal" }, 0, 0, 1 }, {"bin", "set binary value", OFFSET(binary), AV_OPT_TYPE_BINARY, { .str="62696e00" }, 0, 0, 1 }, {"bin1", "set binary value", OFFSET(binary1), AV_OPT_TYPE_BINARY, { .str=NULL }, 0, 0, 1 }, {"bin2", "set binary value", OFFSET(binary2), AV_OPT_TYPE_BINARY, { .str="" }, 0, 0, 1 }, @@ -138,7 +138,7 @@ int main(void) printf("sample_fmt=%s\n", av_get_sample_fmt_name(test_ctx.sample_fmt)); printf("duration=%"PRId64"\n", test_ctx.duration); printf("color=%d %d %d %d\n", test_ctx.color[0], test_ctx.color[1], test_ctx.color[2], test_ctx.color[3]); - printf("channel_layout=%"PRId64"=%"PRId64"\n", test_ctx.channel_layout, (int64_t)AV_CH_LAYOUT_HEXAGONAL); + printf("channel_layout=%"PRId64"=%"PRId64"\n", test_ctx.channel_layout.u.mask, (int64_t)AV_CH_LAYOUT_HEXAGONAL); if (test_ctx.binary) printf("binary=%x %x %x %x\n", ((uint8_t*)test_ctx.binary)[0], ((uint8_t*)test_ctx.binary)[1], ((uint8_t*)test_ctx.binary)[2], ((uint8_t*)test_ctx.binary)[3]); printf("binary_size=%d\n", test_ctx.binary_size); @@ -280,7 +280,7 @@ int main(void) "color=blue", "color=0x223300", "color=0x42FF07AA", - "cl=stereo+downmix", + "cl=FL+FR", "cl=foo", "bin=boguss", "bin=111", diff --git a/libavutil/tests/pixelutils.c b/libavutil/tests/pixelutils.c index 2f807584b..927c8d921 100644 --- a/libavutil/tests/pixelutils.c +++ b/libavutil/tests/pixelutils.c @@ -16,6 +16,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + +#include "libavutil/internal.h" +#include "libavutil/mem.h" #include "libavutil/pixelutils.c" #define W1 320 diff --git a/libavutil/tests/twofish.c b/libavutil/tests/twofish.c index 7e8b12923..a4ccbfd37 100644 --- a/libavutil/tests/twofish.c +++ b/libavutil/tests/twofish.c @@ -20,10 +20,12 @@ */ #include "libavutil/log.h" +#include "libavutil/mem.h" #include "libavutil/twofish.h" #include #include +#include int main(int argc, char *argv[]) { diff --git a/libavutil/tests/uuid.c b/libavutil/tests/uuid.c new file mode 100644 index 000000000..ff688be03 --- /dev/null +++ b/libavutil/tests/uuid.c @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2022 Pierre-Anthony Lemieux + * Zane van Iperen + * + * 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/uuid.h" +#include "libavutil/log.h" + +static const char *UUID_1 = "6021b21e-894e-43ff-8317-1ca891c1c49b"; +static const char *UUID_1_UC = "6021B21E-894E-43FF-8317-1CA891C1C49B"; +static const char *UUID_1_MIXED = "6021b21e-894E-43fF-8317-1CA891C1c49b"; +static const char *UUID_1_URN = "urn:uuid:6021b21e-894e-43ff-8317-1ca891c1c49b"; +static const AVUUID UUID_1_BYTES = {0x60, 0x21, 0xb2, 0x1e, 0x89, 0x4e, 0x43, 0xff, + 0x83, 0x17, 0x1c, 0xa8, 0x91, 0xc1, 0xc4, 0x9b}; + +static const AVUUID UUID_NIL = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +static const char *UUID_BAD_1 = "16a2c9f8-afbc-4767-8621-8cb2b27599"; +static const char *UUID_BAD_2 = "75df62c2999b4bd38c9d8058fcde9123"; +static const char *UUID_BAD_3 = "a1b9a05e-f1d1-464g-a951-1ba0a374f02"; +static const char *UUID_BAD_4 = "279c66d432-7b39-41d5-966f-5e8138265c20"; + +int main(int argc, char **argv) +{ + AVUUID uuid; + AVUUID uuid2 = {0x32, 0xc7, 0x00, 0xc4, 0xd5, 0xd7, 0x42, 0x0, + 0x93, 0xc0, 0x3b, 0x6d, 0xea, 0x1b, 0x20, 0x5b}; + + /* test parsing */ + + if (av_uuid_parse(UUID_1, uuid)) + return 1; + + if (!av_uuid_equal(uuid, UUID_1_BYTES)) + return 1; + + /* test nil */ + + av_uuid_nil(uuid); + + if (!av_uuid_equal(uuid, UUID_NIL)) + return 1; + + /* test equality */ + + if (av_uuid_equal(UUID_1_BYTES, uuid2)) + return 1; + + /* test copy */ + + av_uuid_copy(uuid2, UUID_1_BYTES); + + if (!av_uuid_equal(uuid2, UUID_1_BYTES)) + return 1; + + /* test uppercase parsing */ + + if (av_uuid_parse(UUID_1_UC, uuid)) + return 1; + + if (!av_uuid_equal(uuid, UUID_1_BYTES)) + return 1; + + /* test mixed-case parsing */ + + if (av_uuid_parse(UUID_1_MIXED, uuid)) + return 1; + + if (!av_uuid_equal(uuid, UUID_1_BYTES)) + return 1; + + /* test URN uuid parse */ + + if (av_uuid_urn_parse(UUID_1_URN, uuid)) + return 1; + + if (!av_uuid_equal(uuid, UUID_1_BYTES)) + return 1; + + /* test parse range */ + + if (av_uuid_parse_range(UUID_1_URN + 9, UUID_1_URN + 45, uuid)) + return 1; + + if (!av_uuid_equal(uuid, UUID_1_BYTES)) + return 1; + + /* test bad parse range */ + + if (!av_uuid_parse_range(UUID_1_URN + 9, UUID_1_URN + 44, uuid)) + return 1; + + /* test bad parse range 2 */ + + if (!av_uuid_parse_range(UUID_1_URN + 8, UUID_1_URN + 44, uuid)) + return 1; + + /* test bad parse range 2 */ + + if (!av_uuid_parse_range(UUID_1_URN + 8, UUID_1_URN + 45, uuid)) + return 1; + + /* test bad uuid 1 */ + + if (!av_uuid_parse(UUID_BAD_1, uuid)) + return 1; + + /* test bad uuid 2 */ + + if (!av_uuid_parse(UUID_BAD_2, uuid)) + return 1; + + /* test bad uuid 3 */ + + if (!av_uuid_parse(UUID_BAD_3, uuid)) + return 1; + + /* test bad uuid 4 */ + + if (!av_uuid_parse(UUID_BAD_4, uuid)) + return 1; + + return 0; +} diff --git a/libavutil/thread.h b/libavutil/thread.h index be5c4b134..7106fd0d4 100644 --- a/libavutil/thread.h +++ b/libavutil/thread.h @@ -31,7 +31,11 @@ #if defined(ASSERT_LEVEL) && ASSERT_LEVEL > 1 +#include + +#include "error.h" #include "log.h" +#include "macros.h" #define ASSERT_PTHREAD_ABORT(func, ret) do { \ char errbuf[AV_ERROR_MAX_STRING_SIZE] = ""; \ diff --git a/libavutil/threadmessage.c b/libavutil/threadmessage.c index 764b7fb81..f0e23f28f 100644 --- a/libavutil/threadmessage.c +++ b/libavutil/threadmessage.c @@ -18,13 +18,15 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include "fifo.h" +#include "mem.h" #include "threadmessage.h" #include "thread.h" struct AVThreadMessageQueue { #if HAVE_THREADS - AVFifoBuffer *fifo; + AVFifo *fifo; pthread_mutex_t lock; pthread_cond_t cond_recv; pthread_cond_t cond_send; @@ -64,7 +66,7 @@ int av_thread_message_queue_alloc(AVThreadMessageQueue **mq, av_free(rmq); return AVERROR(ret); } - if (!(rmq->fifo = av_fifo_alloc(elsize * nelem))) { + if (!(rmq->fifo = av_fifo_alloc2(nelem, elsize, 0))) { pthread_cond_destroy(&rmq->cond_send); pthread_cond_destroy(&rmq->cond_recv); pthread_mutex_destroy(&rmq->lock); @@ -93,7 +95,7 @@ void av_thread_message_queue_free(AVThreadMessageQueue **mq) #if HAVE_THREADS if (*mq) { av_thread_message_flush(*mq); - av_fifo_freep(&(*mq)->fifo); + av_fifo_freep2(&(*mq)->fifo); pthread_cond_destroy(&(*mq)->cond_send); pthread_cond_destroy(&(*mq)->cond_recv); pthread_mutex_destroy(&(*mq)->lock); @@ -107,9 +109,9 @@ int av_thread_message_queue_nb_elems(AVThreadMessageQueue *mq) #if HAVE_THREADS int ret; pthread_mutex_lock(&mq->lock); - ret = av_fifo_size(mq->fifo); + ret = av_fifo_can_read(mq->fifo); pthread_mutex_unlock(&mq->lock); - return ret / mq->elsize; + return ret; #else return AVERROR(ENOSYS); #endif @@ -121,14 +123,14 @@ static int av_thread_message_queue_send_locked(AVThreadMessageQueue *mq, void *msg, unsigned flags) { - while (!mq->err_send && av_fifo_space(mq->fifo) < mq->elsize) { + while (!mq->err_send && !av_fifo_can_write(mq->fifo)) { if ((flags & AV_THREAD_MESSAGE_NONBLOCK)) return AVERROR(EAGAIN); pthread_cond_wait(&mq->cond_send, &mq->lock); } if (mq->err_send) return mq->err_send; - av_fifo_generic_write(mq->fifo, msg, mq->elsize, NULL); + av_fifo_write(mq->fifo, msg, 1); /* one message is sent, signal one receiver */ pthread_cond_signal(&mq->cond_recv); return 0; @@ -138,14 +140,14 @@ static int av_thread_message_queue_recv_locked(AVThreadMessageQueue *mq, void *msg, unsigned flags) { - while (!mq->err_recv && av_fifo_size(mq->fifo) < mq->elsize) { + while (!mq->err_recv && !av_fifo_can_read(mq->fifo)) { if ((flags & AV_THREAD_MESSAGE_NONBLOCK)) return AVERROR(EAGAIN); pthread_cond_wait(&mq->cond_recv, &mq->lock); } - if (av_fifo_size(mq->fifo) < mq->elsize) + if (!av_fifo_can_read(mq->fifo)) return mq->err_recv; - av_fifo_generic_read(mq->fifo, msg, mq->elsize, NULL); + av_fifo_read(mq->fifo, msg, 1); /* one message space appeared, signal one sender */ pthread_cond_signal(&mq->cond_send); return 0; @@ -208,25 +210,25 @@ void av_thread_message_queue_set_err_recv(AVThreadMessageQueue *mq, } #if HAVE_THREADS -static void free_func_wrap(void *arg, void *msg, int size) +static int free_func_wrap(void *arg, void *buf, size_t *nb_elems) { AVThreadMessageQueue *mq = arg; - mq->free_func(msg); + uint8_t *msg = buf; + for (size_t i = 0; i < *nb_elems; i++) + mq->free_func(msg + i * mq->elsize); + return 0; } #endif void av_thread_message_flush(AVThreadMessageQueue *mq) { #if HAVE_THREADS - int used, off; - void *free_func = mq->free_func; + size_t used; pthread_mutex_lock(&mq->lock); - used = av_fifo_size(mq->fifo); - if (free_func) - for (off = 0; off < used; off += mq->elsize) - av_fifo_generic_peek_at(mq->fifo, mq, off, mq->elsize, free_func_wrap); - av_fifo_drain(mq->fifo, used); + used = av_fifo_can_read(mq->fifo); + if (mq->free_func) + av_fifo_read_to_cb(mq->fifo, free_func_wrap, mq, &used); /* only the senders need to be notified since the queue is empty and there * is nothing to read */ pthread_cond_broadcast(&mq->cond_send); diff --git a/libavutil/timecode.c b/libavutil/timecode.c index 2fc3295e2..b93f05b4b 100644 --- a/libavutil/timecode.c +++ b/libavutil/timecode.c @@ -27,6 +27,7 @@ */ #include +#include "common.h" #include "timecode.h" #include "log.h" #include "error.h" @@ -103,7 +104,7 @@ char *av_timecode_make_string(const AVTimecode *tc, char *buf, int framenum) { int fps = tc->fps; int drop = tc->flags & AV_TIMECODE_FLAG_DROPFRAME; - int hh, mm, ss, ff, neg = 0; + int hh, mm, ss, ff, ff_len, neg = 0; framenum += tc->start; if (drop) @@ -118,9 +119,10 @@ char *av_timecode_make_string(const AVTimecode *tc, char *buf, int framenum) hh = framenum / (fps*3600LL); if (tc->flags & AV_TIMECODE_FLAG_24HOURSMAX) hh = hh % 24; - snprintf(buf, AV_TIMECODE_STR_SIZE, "%s%02d:%02d:%02d%c%02d", + ff_len = fps > 10000 ? 5 : fps > 1000 ? 4 : fps > 100 ? 3 : fps > 10 ? 2 : 1; + snprintf(buf, AV_TIMECODE_STR_SIZE, "%s%02d:%02d:%02d%c%0*d", neg ? "-" : "", - hh, mm, ss, drop ? ';' : ':', ff); + hh, mm, ss, drop ? ';' : ':', ff_len, ff); return buf; } diff --git a/libavutil/timer.h b/libavutil/timer.h index 71ea2f912..48e576739 100644 --- a/libavutil/timer.h +++ b/libavutil/timer.h @@ -48,6 +48,7 @@ #include #endif +#include "common.h" #include "log.h" #if ARCH_AARCH64 diff --git a/libavutil/twofish.c b/libavutil/twofish.c index 649b4bc41..9f9687ecc 100644 --- a/libavutil/twofish.c +++ b/libavutil/twofish.c @@ -18,9 +18,13 @@ * 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 "twofish.h" -#include "common.h" +#include "error.h" #include "intreadwrite.h" +#include "mem.h" #include "attributes.h" #define LR(x, n) ((x) << (n) | (x) >> (32 - (n))) diff --git a/libavutil/tx.c b/libavutil/tx.c index fa81ada2f..4cc3a9875 100644 --- a/libavutil/tx.c +++ b/libavutil/tx.c @@ -16,19 +16,16 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "cpu.h" +#include "qsort.h" +#include "bprint.h" + #include "tx_priv.h" -int ff_tx_type_is_mdct(enum AVTXType type) -{ - switch (type) { - case AV_TX_FLOAT_MDCT: - case AV_TX_DOUBLE_MDCT: - case AV_TX_INT32_MDCT: - return 1; - default: - return 0; - } -} +#define TYPE_IS(type, x) \ + (((x) == AV_TX_FLOAT_ ## type) || \ + ((x) == AV_TX_DOUBLE_ ## type) || \ + ((x) == AV_TX_INT32_ ## type)) /* Calculates the modular multiplicative inverse */ static av_always_inline int mulinv(int n, int m) @@ -42,22 +39,26 @@ static av_always_inline int mulinv(int n, int m) } /* Guaranteed to work for any n, m where gcd(n, m) == 1 */ -int ff_tx_gen_compound_mapping(AVTXContext *s) +int ff_tx_gen_compound_mapping(AVTXContext *s, int n, int m) { int *in_map, *out_map; - const int n = s->n; - const int m = s->m; - const int inv = s->inv; - const int len = n*m; - const int m_inv = mulinv(m, n); - const int n_inv = mulinv(n, m); - const int mdct = ff_tx_type_is_mdct(s->type); + const int inv = s->inv; + const int len = n*m; /* Will not be equal to s->len for MDCTs */ + const int mdct = TYPE_IS(MDCT, s->type); + int m_inv, n_inv; - if (!(s->pfatab = av_malloc(2*len*sizeof(*s->pfatab)))) + /* Make sure the numbers are coprime */ + if (av_gcd(n, m) != 1) + return AVERROR(EINVAL); + + m_inv = mulinv(m, n); + n_inv = mulinv(n, m); + + if (!(s->map = av_malloc(2*len*sizeof(*s->map)))) return AVERROR(ENOMEM); - in_map = s->pfatab; - out_map = s->pfatab + n*m; + in_map = s->map; + out_map = s->map + len; /* Ruritanian map for input, CRT map for output, can be swapped */ for (int j = 0; j < m; j++) { @@ -92,48 +93,50 @@ int ff_tx_gen_compound_mapping(AVTXContext *s) return 0; } -static inline int split_radix_permutation(int i, int m, int inverse) +static inline int split_radix_permutation(int i, int len, int inv) { - m >>= 1; - if (m <= 1) + len >>= 1; + if (len <= 1) return i & 1; - if (!(i & m)) - return split_radix_permutation(i, m, inverse) * 2; - m >>= 1; - return split_radix_permutation(i, m, inverse) * 4 + 1 - 2*(!(i & m) ^ inverse); + if (!(i & len)) + return split_radix_permutation(i, len, inv) * 2; + len >>= 1; + return split_radix_permutation(i, len, inv) * 4 + 1 - 2*(!(i & len) ^ inv); } int ff_tx_gen_ptwo_revtab(AVTXContext *s, int invert_lookup) { - const int m = s->m, inv = s->inv; + int len = s->len; - if (!(s->revtab = av_malloc(s->m*sizeof(*s->revtab)))) - return AVERROR(ENOMEM); - if (!(s->revtab_c = av_malloc(m*sizeof(*s->revtab_c)))) + if (!(s->map = av_malloc(len*sizeof(*s->map)))) return AVERROR(ENOMEM); - /* Default */ - for (int i = 0; i < m; i++) { - int k = -split_radix_permutation(i, m, inv) & (m - 1); - if (invert_lookup) - s->revtab[i] = s->revtab_c[i] = k; - else - s->revtab[i] = s->revtab_c[k] = i; + if (invert_lookup) { + for (int i = 0; i < s->len; i++) + s->map[i] = -split_radix_permutation(i, len, s->inv) & (len - 1); + } else { + for (int i = 0; i < s->len; i++) + s->map[-split_radix_permutation(i, len, s->inv) & (len - 1)] = i; } return 0; } -int ff_tx_gen_ptwo_inplace_revtab_idx(AVTXContext *s, int *revtab) +int ff_tx_gen_ptwo_inplace_revtab_idx(AVTXContext *s) { - int nb_inplace_idx = 0; + int *src_map, out_map_idx = 0, len = s->len; - if (!(s->inplace_idx = av_malloc(s->m*sizeof(*s->inplace_idx)))) + if (!s->sub || !s->sub->map) + return AVERROR(EINVAL); + + if (!(s->map = av_mallocz(len*sizeof(*s->map)))) return AVERROR(ENOMEM); + src_map = s->sub->map; + /* The first coefficient is always already in-place */ - for (int src = 1; src < s->m; src++) { - int dst = revtab[src]; + for (int src = 1; src < s->len; src++) { + int dst = src_map[src]; int found = 0; if (dst <= src) @@ -143,48 +146,53 @@ int ff_tx_gen_ptwo_inplace_revtab_idx(AVTXContext *s, int *revtab) * and if so, skips it, since to fully permute a loop we must only * enter it once. */ do { - for (int j = 0; j < nb_inplace_idx; j++) { - if (dst == s->inplace_idx[j]) { + for (int j = 0; j < out_map_idx; j++) { + if (dst == s->map[j]) { found = 1; break; } } - dst = revtab[dst]; + dst = src_map[dst]; } while (dst != src && !found); if (!found) - s->inplace_idx[nb_inplace_idx++] = src; + s->map[out_map_idx++] = src; } - s->inplace_idx[nb_inplace_idx++] = 0; + s->map[out_map_idx++] = 0; return 0; } static void parity_revtab_generator(int *revtab, int n, int inv, int offset, int is_dual, int dual_high, int len, - int basis, int dual_stride) + int basis, int dual_stride, int inv_lookup) { len >>= 1; if (len <= basis) { - int k1, k2, *even, *odd, stride; + int k1, k2, stride, even_idx, odd_idx; is_dual = is_dual && dual_stride; dual_high = is_dual & dual_high; stride = is_dual ? FFMIN(dual_stride, len) : 0; - even = &revtab[offset + dual_high*(stride - 2*len)]; - odd = &even[len + (is_dual && !dual_high)*len + dual_high*len]; + even_idx = offset + dual_high*(stride - 2*len); + odd_idx = even_idx + len + (is_dual && !dual_high)*len + dual_high*len; for (int i = 0; i < len; i++) { k1 = -split_radix_permutation(offset + i*2 + 0, n, inv) & (n - 1); k2 = -split_radix_permutation(offset + i*2 + 1, n, inv) & (n - 1); - *even++ = k1; - *odd++ = k2; + if (inv_lookup) { + revtab[even_idx++] = k1; + revtab[odd_idx++] = k2; + } else { + revtab[k1] = even_idx++; + revtab[k2] = odd_idx++; + } if (stride && !((i + 1) % stride)) { - even += stride; - odd += stride; + even_idx += stride; + odd_idx += stride; } } @@ -192,22 +200,52 @@ static void parity_revtab_generator(int *revtab, int n, int inv, int offset, } parity_revtab_generator(revtab, n, inv, offset, - 0, 0, len >> 0, basis, dual_stride); + 0, 0, len >> 0, basis, dual_stride, inv_lookup); parity_revtab_generator(revtab, n, inv, offset + (len >> 0), - 1, 0, len >> 1, basis, dual_stride); + 1, 0, len >> 1, basis, dual_stride, inv_lookup); parity_revtab_generator(revtab, n, inv, offset + (len >> 0) + (len >> 1), - 1, 1, len >> 1, basis, dual_stride); + 1, 1, len >> 1, basis, dual_stride, inv_lookup); } -void ff_tx_gen_split_radix_parity_revtab(int *revtab, int len, int inv, - int basis, int dual_stride) +int ff_tx_gen_split_radix_parity_revtab(AVTXContext *s, int invert_lookup, + int basis, int dual_stride) { + int len = s->len; + int inv = s->inv; + + if (!(s->map = av_mallocz(len*sizeof(*s->map)))) + return AVERROR(ENOMEM); + basis >>= 1; if (len < basis) - return; + return AVERROR(EINVAL); + av_assert0(!dual_stride || !(dual_stride & (dual_stride - 1))); av_assert0(dual_stride <= basis); - parity_revtab_generator(revtab, len, inv, 0, 0, 0, len, basis, dual_stride); + parity_revtab_generator(s->map, len, inv, 0, 0, 0, len, + basis, dual_stride, invert_lookup); + + return 0; +} + +static void reset_ctx(AVTXContext *s) +{ + if (!s) + return; + + if (s->sub) + for (int i = 0; i < s->nb_sub; i++) + reset_ctx(&s->sub[i]); + + if (s->cd_self->uninit) + s->cd_self->uninit(s); + + av_freep(&s->sub); + av_freep(&s->map); + av_freep(&s->exp); + av_freep(&s->tmp); + + memset(s, 0, sizeof(*s)); } av_cold void av_tx_uninit(AVTXContext **ctx) @@ -215,53 +253,431 @@ av_cold void av_tx_uninit(AVTXContext **ctx) if (!(*ctx)) return; - av_free((*ctx)->pfatab); - av_free((*ctx)->exptab); - av_free((*ctx)->revtab); - av_free((*ctx)->revtab_c); - av_free((*ctx)->inplace_idx); - av_free((*ctx)->tmp); - + reset_ctx(*ctx); av_freep(ctx); } +static av_cold int ff_tx_null_init(AVTXContext *s, const FFTXCodelet *cd, + uint64_t flags, FFTXCodeletOptions *opts, + int len, int inv, const void *scale) +{ + /* Can only handle one sample+type to one sample+type transforms */ + if (TYPE_IS(MDCT, s->type) || TYPE_IS(RDFT, s->type)) + return AVERROR(EINVAL); + return 0; +} + +/* Null transform when the length is 1 */ +static void ff_tx_null(AVTXContext *s, void *_out, void *_in, ptrdiff_t stride) +{ + memcpy(_out, _in, stride); +} + +static const FFTXCodelet ff_tx_null_def = { + .name = NULL_IF_CONFIG_SMALL("null"), + .function = ff_tx_null, + .type = TX_TYPE_ANY, + .flags = AV_TX_UNALIGNED | FF_TX_ALIGNED | + FF_TX_OUT_OF_PLACE | AV_TX_INPLACE, + .factors[0] = TX_FACTOR_ANY, + .min_len = 1, + .max_len = 1, + .init = ff_tx_null_init, + .cpu_flags = FF_TX_CPU_FLAGS_ALL, + .prio = FF_TX_PRIO_MAX, +}; + +static const FFTXCodelet * const ff_tx_null_list[] = { + &ff_tx_null_def, + NULL, +}; + +#if !CONFIG_SMALL +static void print_flags(AVBPrint *bp, uint64_t f) +{ + int prev = 0; + const char *sep = ", "; + av_bprintf(bp, "flags: ["); + if ((f & FF_TX_ALIGNED) && ++prev) + av_bprintf(bp, "aligned"); + if ((f & AV_TX_UNALIGNED) && ++prev) + av_bprintf(bp, "%sunaligned", prev > 1 ? sep : ""); + if ((f & AV_TX_INPLACE) && ++prev) + av_bprintf(bp, "%sinplace", prev > 1 ? sep : ""); + if ((f & FF_TX_OUT_OF_PLACE) && ++prev) + av_bprintf(bp, "%sout_of_place", prev > 1 ? sep : ""); + if ((f & FF_TX_FORWARD_ONLY) && ++prev) + av_bprintf(bp, "%sfwd_only", prev > 1 ? sep : ""); + if ((f & FF_TX_INVERSE_ONLY) && ++prev) + av_bprintf(bp, "%sinv_only", prev > 1 ? sep : ""); + if ((f & FF_TX_PRESHUFFLE) && ++prev) + av_bprintf(bp, "%spreshuf", prev > 1 ? sep : ""); + if ((f & AV_TX_FULL_IMDCT) && ++prev) + av_bprintf(bp, "%simdct_full", prev > 1 ? sep : ""); + av_bprintf(bp, "]"); +} + +static void print_type(AVBPrint *bp, enum AVTXType type) +{ + av_bprintf(bp, "%s", + type == TX_TYPE_ANY ? "any" : + type == AV_TX_FLOAT_FFT ? "fft_float" : + type == AV_TX_FLOAT_MDCT ? "mdct_float" : + type == AV_TX_FLOAT_RDFT ? "rdft_float" : + type == AV_TX_DOUBLE_FFT ? "fft_double" : + type == AV_TX_DOUBLE_MDCT ? "mdct_double" : + type == AV_TX_DOUBLE_RDFT ? "rdft_double" : + type == AV_TX_INT32_FFT ? "fft_int32" : + type == AV_TX_INT32_MDCT ? "mdct_int32" : + type == AV_TX_INT32_RDFT ? "rdft_int32" : + "unknown"); +} + +static void print_cd_info(const FFTXCodelet *cd, int prio, int print_prio) +{ + AVBPrint bp = { 0 }; + av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC); + + av_bprintf(&bp, "%s - type: ", cd->name); + + print_type(&bp, cd->type); + + av_bprintf(&bp, ", len: "); + if (cd->min_len != cd->max_len) + av_bprintf(&bp, "[%i, ", cd->min_len); + + if (cd->max_len == TX_LEN_UNLIMITED) + av_bprintf(&bp, "∞"); + else + av_bprintf(&bp, "%i", cd->max_len); + + av_bprintf(&bp, "%s, factors: [", cd->min_len != cd->max_len ? "]" : ""); + for (int i = 0; i < TX_MAX_SUB; i++) { + if (i && cd->factors[i]) + av_bprintf(&bp, ", "); + if (cd->factors[i] == TX_FACTOR_ANY) + av_bprintf(&bp, "any"); + else if (cd->factors[i]) + av_bprintf(&bp, "%i", cd->factors[i]); + else + break; + } + + av_bprintf(&bp, "], "); + print_flags(&bp, cd->flags); + + if (print_prio) + av_bprintf(&bp, ", prio: %i", prio); + + av_log(NULL, AV_LOG_VERBOSE, "%s\n", bp.str); +} + +static void print_tx_structure(AVTXContext *s, int depth) +{ + const FFTXCodelet *cd = s->cd_self; + + for (int i = 0; i <= depth; i++) + av_log(NULL, AV_LOG_VERBOSE, " "); + + print_cd_info(cd, cd->prio, 0); + + for (int i = 0; i < s->nb_sub; i++) + print_tx_structure(&s->sub[i], depth + 1); +} +#endif /* CONFIG_SMALL */ + +typedef struct TXCodeletMatch { + const FFTXCodelet *cd; + int prio; +} TXCodeletMatch; + +static int cmp_matches(TXCodeletMatch *a, TXCodeletMatch *b) +{ + return FFDIFFSIGN(b->prio, a->prio); +} + +/* We want all factors to completely cover the length */ +static inline int check_cd_factors(const FFTXCodelet *cd, int len) +{ + int all_flag = 0; + + for (int i = 0; i < TX_MAX_SUB; i++) { + int factor = cd->factors[i]; + + /* Conditions satisfied */ + if (len == 1) + return 1; + + /* No more factors */ + if (!factor) { + break; + } else if (factor == TX_FACTOR_ANY) { + all_flag = 1; + continue; + } + + if (factor == 2) { /* Fast path */ + int bits_2 = ff_ctz(len); + if (!bits_2) + return 0; /* Factor not supported */ + + len >>= bits_2; + } else { + int res = len % factor; + if (res) + return 0; /* Factor not supported */ + + while (!res) { + len /= factor; + res = len % factor; + } + } + } + + return all_flag || (len == 1); +} + +av_cold int ff_tx_init_subtx(AVTXContext *s, enum AVTXType type, + uint64_t flags, FFTXCodeletOptions *opts, + int len, int inv, const void *scale) +{ + int ret = 0; + AVTXContext *sub = NULL; + TXCodeletMatch *cd_tmp, *cd_matches = NULL; + unsigned int cd_matches_size = 0; + int nb_cd_matches = 0; +#if !CONFIG_SMALL + AVBPrint bp = { 0 }; +#endif + + /* Array of all compiled codelet lists. Order is irrelevant. */ + const FFTXCodelet * const * const codelet_list[] = { + ff_tx_codelet_list_float_c, + ff_tx_codelet_list_double_c, + ff_tx_codelet_list_int32_c, + ff_tx_null_list, +#if HAVE_X86ASM + ff_tx_codelet_list_float_x86, +#endif + }; + int codelet_list_num = FF_ARRAY_ELEMS(codelet_list); + + /* We still accept functions marked with SLOW, even if the CPU is + * marked with the same flag, but we give them lower priority. */ + const int cpu_flags = av_get_cpu_flags(); + const int slow_mask = AV_CPU_FLAG_SSE2SLOW | AV_CPU_FLAG_SSE3SLOW | + AV_CPU_FLAG_ATOM | AV_CPU_FLAG_SSSE3SLOW | + AV_CPU_FLAG_AVXSLOW | AV_CPU_FLAG_SLOW_GATHER; + + static const int slow_penalties[][2] = { + { AV_CPU_FLAG_SSE2SLOW, 1 + 64 }, + { AV_CPU_FLAG_SSE3SLOW, 1 + 64 }, + { AV_CPU_FLAG_SSSE3SLOW, 1 + 64 }, + { AV_CPU_FLAG_ATOM, 1 + 128 }, + { AV_CPU_FLAG_AVXSLOW, 1 + 128 }, + { AV_CPU_FLAG_SLOW_GATHER, 1 + 32 }, + }; + + /* Flags the transform wants */ + uint64_t req_flags = flags; + + /* Flags the codelet may require to be present */ + uint64_t inv_req_mask = AV_TX_FULL_IMDCT | FF_TX_PRESHUFFLE; + + /* Unaligned codelets are compatible with the aligned flag */ + if (req_flags & FF_TX_ALIGNED) + req_flags |= AV_TX_UNALIGNED; + + /* If either flag is set, both are okay, so don't check for an exact match */ + if ((req_flags & AV_TX_INPLACE) && (req_flags & FF_TX_OUT_OF_PLACE)) + req_flags &= ~(AV_TX_INPLACE | FF_TX_OUT_OF_PLACE); + if ((req_flags & FF_TX_ALIGNED) && (req_flags & AV_TX_UNALIGNED)) + req_flags &= ~(FF_TX_ALIGNED | AV_TX_UNALIGNED); + + /* Loop through all codelets in all codelet lists to find matches + * to the requirements */ + while (codelet_list_num--) { + const FFTXCodelet * const * list = codelet_list[codelet_list_num]; + const FFTXCodelet *cd = NULL; + + while ((cd = *list++)) { + int max_factor = 0; + + /* Check if the type matches */ + if (cd->type != TX_TYPE_ANY && type != cd->type) + continue; + + /* Check direction for non-orthogonal codelets */ + if (((cd->flags & FF_TX_FORWARD_ONLY) && inv) || + ((cd->flags & (FF_TX_INVERSE_ONLY | AV_TX_FULL_IMDCT)) && !inv)) + continue; + + /* Check if the requested flags match from both sides */ + if (((req_flags & cd->flags) != (req_flags)) || + ((inv_req_mask & cd->flags) != (req_flags & inv_req_mask))) + continue; + + /* Check if length is supported */ + if ((len < cd->min_len) || (cd->max_len != -1 && (len > cd->max_len))) + continue; + + /* Check if the CPU supports the required ISA */ + if (cd->cpu_flags != FF_TX_CPU_FLAGS_ALL && + !(cpu_flags & (cd->cpu_flags & ~slow_mask))) + continue; + + /* Check for factors */ + if (!check_cd_factors(cd, len)) + continue; + + /* Realloc array and append */ + cd_tmp = av_fast_realloc(cd_matches, &cd_matches_size, + sizeof(*cd_tmp) * (nb_cd_matches + 1)); + if (!cd_tmp) { + av_free(cd_matches); + return AVERROR(ENOMEM); + } + + cd_matches = cd_tmp; + cd_matches[nb_cd_matches].cd = cd; + cd_matches[nb_cd_matches].prio = cd->prio; + + /* If the CPU has a SLOW flag, and the instruction is also flagged + * as being slow for such, reduce its priority */ + for (int i = 0; i < FF_ARRAY_ELEMS(slow_penalties); i++) { + if ((cpu_flags & cd->cpu_flags) & slow_penalties[i][0]) + cd_matches[nb_cd_matches].prio -= slow_penalties[i][1]; + } + + /* Prioritize aligned-only codelets */ + if ((cd->flags & FF_TX_ALIGNED) && !(cd->flags & AV_TX_UNALIGNED)) + cd_matches[nb_cd_matches].prio += 64; + + /* Codelets for specific lengths are generally faster */ + if ((len == cd->min_len) && (len == cd->max_len)) + cd_matches[nb_cd_matches].prio += 64; + + /* Forward-only or inverse-only transforms are generally better */ + if ((cd->flags & (FF_TX_FORWARD_ONLY | FF_TX_INVERSE_ONLY))) + cd_matches[nb_cd_matches].prio += 64; + + /* Larger factors are generally better */ + for (int i = 0; i < TX_MAX_SUB; i++) + max_factor = FFMAX(cd->factors[i], max_factor); + if (max_factor) + cd_matches[nb_cd_matches].prio += 16*max_factor; + + nb_cd_matches++; + } + } + +#if !CONFIG_SMALL + /* Print debugging info */ + av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC); + av_bprintf(&bp, "For transform of length %i, %s, ", len, + inv ? "inverse" : "forward"); + print_type(&bp, type); + av_bprintf(&bp, ", "); + print_flags(&bp, flags); + av_bprintf(&bp, ", found %i matches%s", nb_cd_matches, + nb_cd_matches ? ":" : "."); +#endif + + /* No matches found */ + if (!nb_cd_matches) + return AVERROR(ENOSYS); + + /* Sort the list */ + AV_QSORT(cd_matches, nb_cd_matches, TXCodeletMatch, cmp_matches); + +#if !CONFIG_SMALL + av_log(NULL, AV_LOG_VERBOSE, "%s\n", bp.str); + + for (int i = 0; i < nb_cd_matches; i++) { + av_log(NULL, AV_LOG_VERBOSE, " %i: ", i + 1); + print_cd_info(cd_matches[i].cd, cd_matches[i].prio, 1); + } +#endif + + if (!s->sub) { + s->sub = sub = av_mallocz(TX_MAX_SUB*sizeof(*sub)); + if (!sub) { + ret = AVERROR(ENOMEM); + goto end; + } + } + + /* Attempt to initialize each */ + for (int i = 0; i < nb_cd_matches; i++) { + const FFTXCodelet *cd = cd_matches[i].cd; + AVTXContext *sctx = &s->sub[s->nb_sub]; + + sctx->len = len; + sctx->inv = inv; + sctx->type = type; + sctx->flags = flags; + sctx->cd_self = cd; + + s->fn[s->nb_sub] = cd->function; + s->cd[s->nb_sub] = cd; + + ret = 0; + if (cd->init) + ret = cd->init(sctx, cd, flags, opts, len, inv, scale); + + if (ret >= 0) { + s->nb_sub++; + goto end; + } + + s->fn[s->nb_sub] = NULL; + s->cd[s->nb_sub] = NULL; + + reset_ctx(sctx); + if (ret == AVERROR(ENOMEM)) + break; + } + + if (!s->nb_sub) + av_freep(&s->sub); + +end: + av_free(cd_matches); + return ret; +} + av_cold int av_tx_init(AVTXContext **ctx, av_tx_fn *tx, enum AVTXType type, int inv, int len, const void *scale, uint64_t flags) { - int err; - AVTXContext *s = av_mallocz(sizeof(*s)); - if (!s) - return AVERROR(ENOMEM); + int ret; + AVTXContext tmp = { 0 }; + const double default_scale_d = 1.0; + const float default_scale_f = 1.0f; - switch (type) { - case AV_TX_FLOAT_FFT: - case AV_TX_FLOAT_MDCT: - if ((err = ff_tx_init_mdct_fft_float(s, tx, type, inv, len, scale, flags))) - goto fail; - if (ARCH_X86) - ff_tx_init_float_x86(s, tx); - break; - case AV_TX_DOUBLE_FFT: - case AV_TX_DOUBLE_MDCT: - if ((err = ff_tx_init_mdct_fft_double(s, tx, type, inv, len, scale, flags))) - goto fail; - break; - case AV_TX_INT32_FFT: - case AV_TX_INT32_MDCT: - if ((err = ff_tx_init_mdct_fft_int32(s, tx, type, inv, len, scale, flags))) - goto fail; - break; - default: - err = AVERROR(EINVAL); - goto fail; - } + if (!len || type >= AV_TX_NB || !ctx || !tx) + return AVERROR(EINVAL); - *ctx = s; + if (!(flags & AV_TX_UNALIGNED)) + flags |= FF_TX_ALIGNED; + if (!(flags & AV_TX_INPLACE)) + flags |= FF_TX_OUT_OF_PLACE; - return 0; + if (!scale && ((type == AV_TX_FLOAT_MDCT) || (type == AV_TX_INT32_MDCT))) + scale = &default_scale_f; + else if (!scale && (type == AV_TX_DOUBLE_MDCT)) + scale = &default_scale_d; -fail: - av_tx_uninit(&s); - *tx = NULL; - return err; + ret = ff_tx_init_subtx(&tmp, type, flags, NULL, len, inv, scale); + if (ret < 0) + return ret; + + *ctx = &tmp.sub[0]; + *tx = tmp.fn[0]; + +#if !CONFIG_SMALL + av_log(NULL, AV_LOG_VERBOSE, "Transform tree:\n"); + print_tx_structure(*ctx, 0); +#endif + + return ret; } diff --git a/libavutil/tx.h b/libavutil/tx.h index 55173810e..3de2f7231 100644 --- a/libavutil/tx.h +++ b/libavutil/tx.h @@ -38,50 +38,59 @@ typedef struct AVComplexInt32 { enum AVTXType { /** - * Standard complex to complex FFT with sample data type AVComplexFloat. + * Standard complex to complex FFT with sample data type of AVComplexFloat, + * AVComplexDouble or AVComplexInt32, for each respective variant. + * * Output is not 1/len normalized. Scaling currently unsupported. - * The stride parameter is ignored. + * The stride parameter must be set to the size of a single sample in bytes. */ - AV_TX_FLOAT_FFT = 0, + AV_TX_FLOAT_FFT = 0, + AV_TX_DOUBLE_FFT = 2, + AV_TX_INT32_FFT = 4, /** - * Standard MDCT with sample data type of float and a scale type of - * float. Length is the frame size, not the window size (which is 2x frame) + * Standard MDCT with a sample data type of float, double or int32_t, + * respecively. For the float and int32 variants, the scale type is + * 'float', while for the double variant, it's 'double'. + * If scale is NULL, 1.0 will be used as a default. + * + * Length is the frame size, not the window size (which is 2x frame). * For forward transforms, the stride specifies the spacing between each * sample in the output array in bytes. The input must be a flat array. * * For inverse transforms, the stride specifies the spacing between each - * sample in the input array in bytes. The output will be a flat array. - * Stride must be a non-zero multiple of sizeof(float). + * sample in the input array in bytes. The output must be a flat array. * * NOTE: the inverse transform is half-length, meaning the output will not * contain redundant data. This is what most codecs work with. To do a full * inverse transform, set the AV_TX_FULL_IMDCT flag on init. */ - AV_TX_FLOAT_MDCT = 1, - - /** - * Same as AV_TX_FLOAT_FFT with a data type of AVComplexDouble. - */ - AV_TX_DOUBLE_FFT = 2, - - /** - * Same as AV_TX_FLOAT_MDCT with data and scale type of double. - * Stride must be a non-zero multiple of sizeof(double). - */ + AV_TX_FLOAT_MDCT = 1, AV_TX_DOUBLE_MDCT = 3, + AV_TX_INT32_MDCT = 5, /** - * Same as AV_TX_FLOAT_FFT with a data type of AVComplexInt32. + * Real to complex and complex to real DFTs. + * For the float and int32 variants, the scale type is 'float', while for + * the double variant, it's a 'double'. If scale is NULL, 1.0 will be used + * as a default. + * + * The stride parameter must be set to the size of a single sample in bytes. + * + * The forward transform performs a real-to-complex DFT of N samples to + * N/2+1 complex values. + * + * The inverse transform performs a complex-to-real DFT of N/2+1 complex + * values to N real samples. The output is not normalized, but can be + * made so by setting the scale value to 1.0/len. + * NOTE: the inverse transform always overwrites the input. */ - AV_TX_INT32_FFT = 4, + AV_TX_FLOAT_RDFT = 6, + AV_TX_DOUBLE_RDFT = 7, + AV_TX_INT32_RDFT = 8, - /** - * Same as AV_TX_FLOAT_MDCT with data type of int32_t and scale type of float. - * Only scale values less than or equal to 1.0 are supported. - * Stride must be a non-zero multiple of sizeof(int32_t). - */ - AV_TX_INT32_MDCT = 5, + /* Not part of the API, do not use */ + AV_TX_NB, }; /** @@ -145,7 +154,7 @@ int av_tx_init(AVTXContext **ctx, av_tx_fn *tx, enum AVTXType type, int inv, int len, const void *scale, uint64_t flags); /** - * Frees a context and sets ctx to NULL, does nothing when ctx == NULL + * Frees a context and sets *ctx to NULL, does nothing when *ctx == NULL. */ void av_tx_uninit(AVTXContext **ctx); diff --git a/libavutil/tx_priv.h b/libavutil/tx_priv.h index 63dc6bbe6..c9eda44e6 100644 --- a/libavutil/tx_priv.h +++ b/libavutil/tx_priv.h @@ -25,36 +25,72 @@ #include "attributes.h" #ifdef TX_FLOAT -#define TX_NAME(x) x ## _float +#define TX_TAB(x) x ## _float +#define TX_NAME(x) x ## _float_c +#define TX_NAME_STR(x) NULL_IF_CONFIG_SMALL(x "_float_c") +#define TX_TYPE(x) AV_TX_FLOAT_ ## x +#define TX_FN_NAME(fn, suffix) ff_tx_ ## fn ## _float_ ## suffix +#define TX_FN_NAME_STR(fn, suffix) NULL_IF_CONFIG_SMALL(#fn "_float_" #suffix) +#define MULT(x, m) ((x) * (m)) #define SCALE_TYPE float -typedef float FFTSample; -typedef AVComplexFloat FFTComplex; +typedef float TXSample; +typedef AVComplexFloat TXComplex; #elif defined(TX_DOUBLE) -#define TX_NAME(x) x ## _double +#define TX_TAB(x) x ## _double +#define TX_NAME(x) x ## _double_c +#define TX_NAME_STR(x) NULL_IF_CONFIG_SMALL(x "_double_c") +#define TX_TYPE(x) AV_TX_DOUBLE_ ## x +#define TX_FN_NAME(fn, suffix) ff_tx_ ## fn ## _double_ ## suffix +#define TX_FN_NAME_STR(fn, suffix) NULL_IF_CONFIG_SMALL(#fn "_double_" #suffix) +#define MULT(x, m) ((x) * (m)) #define SCALE_TYPE double -typedef double FFTSample; -typedef AVComplexDouble FFTComplex; +typedef double TXSample; +typedef AVComplexDouble TXComplex; #elif defined(TX_INT32) -#define TX_NAME(x) x ## _int32 +#define TX_TAB(x) x ## _int32 +#define TX_NAME(x) x ## _int32_c +#define TX_NAME_STR(x) NULL_IF_CONFIG_SMALL(x "_int32_c") +#define TX_TYPE(x) AV_TX_INT32_ ## x +#define TX_FN_NAME(fn, suffix) ff_tx_ ## fn ## _int32_ ## suffix +#define TX_FN_NAME_STR(fn, suffix) NULL_IF_CONFIG_SMALL(#fn "_int32_" #suffix) +#define MULT(x, m) (((((int64_t)(x)) * (int64_t)(m)) + 0x40000000) >> 31) #define SCALE_TYPE float -typedef int32_t FFTSample; -typedef AVComplexInt32 FFTComplex; +typedef int32_t TXSample; +typedef AVComplexInt32 TXComplex; #else -typedef void FFTComplex; +typedef void TXComplex; #endif +#define TX_DECL_FN(fn, suffix) \ + void TX_FN_NAME(fn, suffix)(AVTXContext *s, void *o, void *i, ptrdiff_t st); + +#define TX_DEF(fn, tx_type, len_min, len_max, f1, f2, \ + p, init_fn, suffix, cf, cd_flags, cf2) \ + &(const FFTXCodelet){ \ + .name = TX_FN_NAME_STR(fn, suffix), \ + .function = TX_FN_NAME(fn, suffix), \ + .type = TX_TYPE(tx_type), \ + .flags = FF_TX_ALIGNED | FF_TX_OUT_OF_PLACE | cd_flags, \ + .factors = { f1, f2 }, \ + .min_len = len_min, \ + .max_len = len_max, \ + .init = init_fn, \ + .cpu_flags = cf2 | AV_CPU_FLAG_ ## cf, \ + .prio = p, \ + } + #if defined(TX_FLOAT) || defined(TX_DOUBLE) -#define CMUL(dre, dim, are, aim, bre, bim) \ - do { \ - (dre) = (are) * (bre) - (aim) * (bim); \ - (dim) = (are) * (bim) + (aim) * (bre); \ +#define CMUL(dre, dim, are, aim, bre, bim) \ + do { \ + (dre) = (are) * (bre) - (aim) * (bim); \ + (dim) = (are) * (bim) + (aim) * (bre); \ } while (0) -#define SMUL(dre, dim, are, aim, bre, bim) \ - do { \ - (dre) = (are) * (bre) - (aim) * (bim); \ - (dim) = (are) * (bim) - (aim) * (bre); \ +#define SMUL(dre, dim, are, aim, bre, bim) \ + do { \ + (dre) = (are) * (bre) - (aim) * (bim); \ + (dim) = (are) * (bim) - (aim) * (bre); \ } while (0) #define UNSCALE(x) (x) @@ -65,91 +101,164 @@ typedef void FFTComplex; #elif defined(TX_INT32) /* Properly rounds the result */ -#define CMUL(dre, dim, are, aim, bre, bim) \ - do { \ - int64_t accu; \ - (accu) = (int64_t)(bre) * (are); \ - (accu) -= (int64_t)(bim) * (aim); \ - (dre) = (int)(((accu) + 0x40000000) >> 31); \ - (accu) = (int64_t)(bim) * (are); \ - (accu) += (int64_t)(bre) * (aim); \ - (dim) = (int)(((accu) + 0x40000000) >> 31); \ +#define CMUL(dre, dim, are, aim, bre, bim) \ + do { \ + int64_t accu; \ + (accu) = (int64_t)(bre) * (are); \ + (accu) -= (int64_t)(bim) * (aim); \ + (dre) = (int)(((accu) + 0x40000000) >> 31); \ + (accu) = (int64_t)(bim) * (are); \ + (accu) += (int64_t)(bre) * (aim); \ + (dim) = (int)(((accu) + 0x40000000) >> 31); \ } while (0) -#define SMUL(dre, dim, are, aim, bre, bim) \ - do { \ - int64_t accu; \ - (accu) = (int64_t)(bre) * (are); \ - (accu) -= (int64_t)(bim) * (aim); \ - (dre) = (int)(((accu) + 0x40000000) >> 31); \ - (accu) = (int64_t)(bim) * (are); \ - (accu) -= (int64_t)(bre) * (aim); \ - (dim) = (int)(((accu) + 0x40000000) >> 31); \ +#define SMUL(dre, dim, are, aim, bre, bim) \ + do { \ + int64_t accu; \ + (accu) = (int64_t)(bre) * (are); \ + (accu) -= (int64_t)(bim) * (aim); \ + (dre) = (int)(((accu) + 0x40000000) >> 31); \ + (accu) = (int64_t)(bim) * (are); \ + (accu) -= (int64_t)(bre) * (aim); \ + (dim) = (int)(((accu) + 0x40000000) >> 31); \ } while (0) -#define UNSCALE(x) ((double)x/2147483648.0) +#define UNSCALE(x) ((double)(x)/2147483648.0) #define RESCALE(x) (av_clip64(lrintf((x) * 2147483648.0), INT32_MIN, INT32_MAX)) -#define FOLD(x, y) ((int)((x) + (unsigned)(y) + 32) >> 6) +#define FOLD(x, y) ((int32_t)((x) + (unsigned)(y) + 32) >> 6) -#endif +#endif /* TX_INT32 */ -#define BF(x, y, a, b) \ - do { \ - x = (a) - (b); \ - y = (a) + (b); \ +#define BF(x, y, a, b) \ + do { \ + x = (a) - (b); \ + y = (a) + (b); \ } while (0) -#define CMUL3(c, a, b) \ - CMUL((c).re, (c).im, (a).re, (a).im, (b).re, (b).im) +#define CMUL3(c, a, b) CMUL((c).re, (c).im, (a).re, (a).im, (b).re, (b).im) -#define COSTABLE(size) \ - DECLARE_ALIGNED(32, FFTSample, TX_NAME(ff_cos_##size))[size/4 + 1] +/* Codelet flags, used to pick codelets. Must be a superset of enum AVTXFlags, + * but if it runs out of bits, it can be made separate. */ +#define FF_TX_OUT_OF_PLACE (1ULL << 63) /* Can be OR'd with AV_TX_INPLACE */ +#define FF_TX_ALIGNED (1ULL << 62) /* Cannot be OR'd with AV_TX_UNALIGNED */ +#define FF_TX_PRESHUFFLE (1ULL << 61) /* Codelet expects permuted coeffs */ +#define FF_TX_INVERSE_ONLY (1ULL << 60) /* For non-orthogonal inverse-only transforms */ +#define FF_TX_FORWARD_ONLY (1ULL << 59) /* For non-orthogonal forward-only transforms */ + +typedef enum FFTXCodeletPriority { + FF_TX_PRIO_BASE = 0, /* Baseline priority */ + + /* For SIMD, set base prio to the register size in bits and increment in + * steps of 64 depending on faster/slower features, like FMA. */ + + FF_TX_PRIO_MIN = -131072, /* For naive implementations */ + FF_TX_PRIO_MAX = 32768, /* For custom implementations/ASICs */ +} FFTXCodeletPriority; + +/* Codelet options */ +typedef struct FFTXCodeletOptions { + int invert_lookup; /* If codelet is flagged as FF_TX_CODELET_PRESHUFFLE, + invert the lookup direction for the map generated */ +} FFTXCodeletOptions; + +/* Maximum amount of subtransform functions, subtransforms and factors. Arbitrary. */ +#define TX_MAX_SUB 4 + +typedef struct FFTXCodelet { + const char *name; /* Codelet name, for debugging */ + av_tx_fn function; /* Codelet function, != NULL */ + enum AVTXType type; /* Type of codelet transform */ +#define TX_TYPE_ANY INT32_MAX /* Special type to allow all types */ + + uint64_t flags; /* A combination of AVTXFlags and codelet + * flags that describe its properties. */ + + int factors[TX_MAX_SUB]; /* Length factors */ +#define TX_FACTOR_ANY -1 /* When used alone, signals that the codelet + * supports all factors. Otherwise, if other + * factors are present, it signals that whatever + * remains will be supported, as long as the + * other factors are a component of the length */ + + int min_len; /* Minimum length of transform, must be >= 1 */ + int max_len; /* Maximum length of transform */ +#define TX_LEN_UNLIMITED -1 /* Special length value to permit all lengths */ + + int (*init)(AVTXContext *s, /* Optional callback for current context initialization. */ + const struct FFTXCodelet *cd, + uint64_t flags, + FFTXCodeletOptions *opts, + int len, int inv, + const void *scale); + + int (*uninit)(AVTXContext *s); /* Optional callback for uninitialization. */ + + int cpu_flags; /* CPU flags. If any negative flags like + * SLOW are present, will avoid picking. + * 0x0 to signal it's a C codelet */ +#define FF_TX_CPU_FLAGS_ALL 0x0 /* Special CPU flag for C */ + + int prio; /* < 0 = least, 0 = no pref, > 0 = prefer */ +} FFTXCodelet; -/* Used by asm, reorder with care */ struct AVTXContext { - int n; /* Non-power-of-two part */ - int m; /* Power-of-two part */ - int inv; /* Is inverse */ - int type; /* Type */ - uint64_t flags; /* Flags */ - double scale; /* Scale */ + /* Fields the root transform and subtransforms use or may use. + * NOTE: This section is used by assembly, do not reorder or change */ + int len; /* Length of the transform */ + int inv; /* If transform is inverse */ + int *map; /* Lookup table(s) */ + TXComplex *exp; /* Any non-pre-baked multiplication factors needed */ + TXComplex *tmp; /* Temporary buffer, if needed */ - FFTComplex *exptab; /* MDCT exptab */ - FFTComplex *tmp; /* Temporary buffer needed for all compound transforms */ - int *pfatab; /* Input/Output mapping for compound transforms */ - int *revtab; /* Input mapping for power of two transforms */ - int *inplace_idx; /* Required indices to revtab for in-place transforms */ + AVTXContext *sub; /* Subtransform context(s), if needed */ + av_tx_fn fn[TX_MAX_SUB]; /* Function(s) for the subtransforms */ + int nb_sub; /* Number of subtransforms. + * The reason all of these are set here + * rather than in each separate context + * is to eliminate extra pointer + * dereferences. */ - int *revtab_c; /* Revtab for only the C transforms, needed because - * checkasm makes us reuse the same context. */ - - av_tx_fn top_tx; /* Used for computing transforms derived from other - * transforms, like full-length iMDCTs and RDFTs. - * NOTE: Do NOT use this to mix assembly with C code. */ + /* Fields mainly useul/applicable for the root transform or initialization. + * Fields below are not used by assembly code. */ + const FFTXCodelet *cd[TX_MAX_SUB]; /* Subtransform codelets */ + const FFTXCodelet *cd_self; /* Codelet for the current context */ + enum AVTXType type; /* Type of transform */ + uint64_t flags; /* A combination of AVTXFlags and + * codelet flags used when creating */ + float scale_f; + double scale_d; + void *opaque; /* Free to use by implementations */ }; -/* Checks if type is an MDCT */ -int ff_tx_type_is_mdct(enum AVTXType type); +/* Create a subtransform in the current context with the given parameters. + * The flags parameter from FFTXCodelet.init() should be preserved as much + * as that's possible. + * MUST be called during the sub() callback of each codelet. */ +int ff_tx_init_subtx(AVTXContext *s, enum AVTXType type, + uint64_t flags, FFTXCodeletOptions *opts, + int len, int inv, const void *scale); /* * Generates the PFA permutation table into AVTXContext->pfatab. The end table * is appended to the start table. */ -int ff_tx_gen_compound_mapping(AVTXContext *s); +int ff_tx_gen_compound_mapping(AVTXContext *s, int n, int m); /* * Generates a standard-ish (slightly modified) Split-Radix revtab into - * AVTXContext->revtab + * AVTXContext->map. Invert lookup changes how the mapping needs to be applied. + * If it's set to 0, it has to be applied like out[map[i]] = in[i], otherwise + * if it's set to 1, has to be applied as out[i] = in[map[i]] */ int ff_tx_gen_ptwo_revtab(AVTXContext *s, int invert_lookup); /* * Generates an index into AVTXContext->inplace_idx that if followed in the - * specific order, allows the revtab to be done in-place. AVTXContext->revtab - * must already exist. + * specific order, allows the revtab to be done in-place. The sub-transform + * and its map should already be initialized. */ -int ff_tx_gen_ptwo_inplace_revtab_idx(AVTXContext *s, int *revtab); +int ff_tx_gen_ptwo_inplace_revtab_idx(AVTXContext *s); /* * This generates a parity-based revtab of length len and direction inv. @@ -179,25 +288,26 @@ int ff_tx_gen_ptwo_inplace_revtab_idx(AVTXContext *s, int *revtab); * * If length is smaller than basis/2 this function will not do anything. */ -void ff_tx_gen_split_radix_parity_revtab(int *revtab, int len, int inv, - int basis, int dual_stride); +int ff_tx_gen_split_radix_parity_revtab(AVTXContext *s, int invert_lookup, + int basis, int dual_stride); -/* Templated init functions */ -int ff_tx_init_mdct_fft_float(AVTXContext *s, av_tx_fn *tx, - enum AVTXType type, int inv, int len, - const void *scale, uint64_t flags); -int ff_tx_init_mdct_fft_double(AVTXContext *s, av_tx_fn *tx, - enum AVTXType type, int inv, int len, - const void *scale, uint64_t flags); -int ff_tx_init_mdct_fft_int32(AVTXContext *s, av_tx_fn *tx, - enum AVTXType type, int inv, int len, - const void *scale, uint64_t flags); +/* Typed init function to initialize shared tables. Will initialize all tables + * for all factors of a length. */ +void ff_tx_init_tabs_float (int len); +void ff_tx_init_tabs_double(int len); +void ff_tx_init_tabs_int32 (int len); -typedef struct CosTabsInitOnce { - void (*func)(void); - AVOnce control; -} CosTabsInitOnce; +/* Typed init function to initialize an MDCT exptab in a context. */ +int ff_tx_mdct_gen_exp_float (AVTXContext *s); +int ff_tx_mdct_gen_exp_double(AVTXContext *s); +int ff_tx_mdct_gen_exp_int32 (AVTXContext *s); -void ff_tx_init_float_x86(AVTXContext *s, av_tx_fn *tx); +/* Lists of codelets */ +extern const FFTXCodelet * const ff_tx_codelet_list_float_c []; +extern const FFTXCodelet * const ff_tx_codelet_list_float_x86 []; + +extern const FFTXCodelet * const ff_tx_codelet_list_double_c []; + +extern const FFTXCodelet * const ff_tx_codelet_list_int32_c []; #endif /* AVUTIL_TX_PRIV_H */ diff --git a/libavutil/tx_template.c b/libavutil/tx_template.c index cad66a8bc..1e4354580 100644 --- a/libavutil/tx_template.c +++ b/libavutil/tx_template.c @@ -24,134 +24,160 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -/* All costabs for a type are defined here */ -COSTABLE(16); -COSTABLE(32); -COSTABLE(64); -COSTABLE(128); -COSTABLE(256); -COSTABLE(512); -COSTABLE(1024); -COSTABLE(2048); -COSTABLE(4096); -COSTABLE(8192); -COSTABLE(16384); -COSTABLE(32768); -COSTABLE(65536); -COSTABLE(131072); -DECLARE_ALIGNED(32, FFTComplex, TX_NAME(ff_cos_53))[4]; -DECLARE_ALIGNED(32, FFTComplex, TX_NAME(ff_cos_7))[3]; -DECLARE_ALIGNED(32, FFTComplex, TX_NAME(ff_cos_9))[4]; +#define TABLE_DEF(name, size) \ + DECLARE_ALIGNED(32, TXSample, TX_TAB(ff_tx_tab_ ##name))[size] -static FFTSample * const cos_tabs[18] = { - NULL, - NULL, - NULL, - NULL, - TX_NAME(ff_cos_16), - TX_NAME(ff_cos_32), - TX_NAME(ff_cos_64), - TX_NAME(ff_cos_128), - TX_NAME(ff_cos_256), - TX_NAME(ff_cos_512), - TX_NAME(ff_cos_1024), - TX_NAME(ff_cos_2048), - TX_NAME(ff_cos_4096), - TX_NAME(ff_cos_8192), - TX_NAME(ff_cos_16384), - TX_NAME(ff_cos_32768), - TX_NAME(ff_cos_65536), - TX_NAME(ff_cos_131072), +#define SR_TABLE(len) \ + TABLE_DEF(len, len/4 + 1) + +/* Power of two tables */ +SR_TABLE(8); +SR_TABLE(16); +SR_TABLE(32); +SR_TABLE(64); +SR_TABLE(128); +SR_TABLE(256); +SR_TABLE(512); +SR_TABLE(1024); +SR_TABLE(2048); +SR_TABLE(4096); +SR_TABLE(8192); +SR_TABLE(16384); +SR_TABLE(32768); +SR_TABLE(65536); +SR_TABLE(131072); + +/* Other factors' tables */ +TABLE_DEF(53, 8); +TABLE_DEF( 7, 6); +TABLE_DEF( 9, 8); + +typedef struct FFSRTabsInitOnce { + void (*func)(void); + AVOnce control; + int factors[TX_MAX_SUB]; /* Must be sorted high -> low */ +} FFSRTabsInitOnce; + +#define INIT_FF_SR_TAB(len) \ +static av_cold void TX_TAB(ff_tx_init_tab_ ##len)(void) \ +{ \ + double freq = 2*M_PI/len; \ + TXSample *tab = TX_TAB(ff_tx_tab_ ##len); \ + \ + for (int i = 0; i < len/4; i++) \ + *tab++ = RESCALE(cos(i*freq)); \ + \ + *tab = 0; \ +} + +INIT_FF_SR_TAB(8) +INIT_FF_SR_TAB(16) +INIT_FF_SR_TAB(32) +INIT_FF_SR_TAB(64) +INIT_FF_SR_TAB(128) +INIT_FF_SR_TAB(256) +INIT_FF_SR_TAB(512) +INIT_FF_SR_TAB(1024) +INIT_FF_SR_TAB(2048) +INIT_FF_SR_TAB(4096) +INIT_FF_SR_TAB(8192) +INIT_FF_SR_TAB(16384) +INIT_FF_SR_TAB(32768) +INIT_FF_SR_TAB(65536) +INIT_FF_SR_TAB(131072) + +static FFSRTabsInitOnce sr_tabs_init_once[] = { + { TX_TAB(ff_tx_init_tab_8), AV_ONCE_INIT }, + { TX_TAB(ff_tx_init_tab_16), AV_ONCE_INIT }, + { TX_TAB(ff_tx_init_tab_32), AV_ONCE_INIT }, + { TX_TAB(ff_tx_init_tab_64), AV_ONCE_INIT }, + { TX_TAB(ff_tx_init_tab_128), AV_ONCE_INIT }, + { TX_TAB(ff_tx_init_tab_256), AV_ONCE_INIT }, + { TX_TAB(ff_tx_init_tab_512), AV_ONCE_INIT }, + { TX_TAB(ff_tx_init_tab_1024), AV_ONCE_INIT }, + { TX_TAB(ff_tx_init_tab_2048), AV_ONCE_INIT }, + { TX_TAB(ff_tx_init_tab_4096), AV_ONCE_INIT }, + { TX_TAB(ff_tx_init_tab_8192), AV_ONCE_INIT }, + { TX_TAB(ff_tx_init_tab_16384), AV_ONCE_INIT }, + { TX_TAB(ff_tx_init_tab_32768), AV_ONCE_INIT }, + { TX_TAB(ff_tx_init_tab_65536), AV_ONCE_INIT }, + { TX_TAB(ff_tx_init_tab_131072), AV_ONCE_INIT }, }; -static av_always_inline void init_cos_tabs_idx(int index) +static av_cold void TX_TAB(ff_tx_init_tab_53)(void) { - int m = 1 << index; - double freq = 2*M_PI/m; - FFTSample *tab = cos_tabs[index]; - - for (int i = 0; i < m/4; i++) - *tab++ = RESCALE(cos(i*freq)); - - *tab = 0; + TX_TAB(ff_tx_tab_53)[0] = RESCALE(cos(2 * M_PI / 12)); + TX_TAB(ff_tx_tab_53)[1] = RESCALE(cos(2 * M_PI / 12)); + TX_TAB(ff_tx_tab_53)[2] = RESCALE(cos(2 * M_PI / 6)); + TX_TAB(ff_tx_tab_53)[3] = RESCALE(cos(2 * M_PI / 6)); + TX_TAB(ff_tx_tab_53)[4] = RESCALE(cos(2 * M_PI / 5)); + TX_TAB(ff_tx_tab_53)[5] = RESCALE(sin(2 * M_PI / 5)); + TX_TAB(ff_tx_tab_53)[6] = RESCALE(cos(2 * M_PI / 10)); + TX_TAB(ff_tx_tab_53)[7] = RESCALE(sin(2 * M_PI / 10)); } -#define INIT_FF_COS_TABS_FUNC(index, size) \ -static av_cold void init_cos_tabs_ ## size (void) \ -{ \ - init_cos_tabs_idx(index); \ -} - -INIT_FF_COS_TABS_FUNC(4, 16) -INIT_FF_COS_TABS_FUNC(5, 32) -INIT_FF_COS_TABS_FUNC(6, 64) -INIT_FF_COS_TABS_FUNC(7, 128) -INIT_FF_COS_TABS_FUNC(8, 256) -INIT_FF_COS_TABS_FUNC(9, 512) -INIT_FF_COS_TABS_FUNC(10, 1024) -INIT_FF_COS_TABS_FUNC(11, 2048) -INIT_FF_COS_TABS_FUNC(12, 4096) -INIT_FF_COS_TABS_FUNC(13, 8192) -INIT_FF_COS_TABS_FUNC(14, 16384) -INIT_FF_COS_TABS_FUNC(15, 32768) -INIT_FF_COS_TABS_FUNC(16, 65536) -INIT_FF_COS_TABS_FUNC(17, 131072) - -static av_cold void ff_init_53_tabs(void) +static av_cold void TX_TAB(ff_tx_init_tab_7)(void) { - TX_NAME(ff_cos_53)[0] = (FFTComplex){ RESCALE(cos(2 * M_PI / 12)), RESCALE(cos(2 * M_PI / 12)) }; - TX_NAME(ff_cos_53)[1] = (FFTComplex){ RESCALE(cos(2 * M_PI / 6)), RESCALE(cos(2 * M_PI / 6)) }; - TX_NAME(ff_cos_53)[2] = (FFTComplex){ RESCALE(cos(2 * M_PI / 5)), RESCALE(sin(2 * M_PI / 5)) }; - TX_NAME(ff_cos_53)[3] = (FFTComplex){ RESCALE(cos(2 * M_PI / 10)), RESCALE(sin(2 * M_PI / 10)) }; + TX_TAB(ff_tx_tab_7)[0] = RESCALE(cos(2 * M_PI / 7)); + TX_TAB(ff_tx_tab_7)[1] = RESCALE(sin(2 * M_PI / 7)); + TX_TAB(ff_tx_tab_7)[2] = RESCALE(sin(2 * M_PI / 28)); + TX_TAB(ff_tx_tab_7)[3] = RESCALE(cos(2 * M_PI / 28)); + TX_TAB(ff_tx_tab_7)[4] = RESCALE(cos(2 * M_PI / 14)); + TX_TAB(ff_tx_tab_7)[5] = RESCALE(sin(2 * M_PI / 14)); } -static av_cold void ff_init_7_tabs(void) +static av_cold void TX_TAB(ff_tx_init_tab_9)(void) { - TX_NAME(ff_cos_7)[0] = (FFTComplex){ RESCALE(cos(2 * M_PI / 7)), RESCALE(sin(2 * M_PI / 7)) }; - TX_NAME(ff_cos_7)[1] = (FFTComplex){ RESCALE(sin(2 * M_PI / 28)), RESCALE(cos(2 * M_PI / 28)) }; - TX_NAME(ff_cos_7)[2] = (FFTComplex){ RESCALE(cos(2 * M_PI / 14)), RESCALE(sin(2 * M_PI / 14)) }; + TX_TAB(ff_tx_tab_9)[0] = RESCALE(cos(2 * M_PI / 3)); + TX_TAB(ff_tx_tab_9)[1] = RESCALE(sin(2 * M_PI / 3)); + TX_TAB(ff_tx_tab_9)[2] = RESCALE(cos(2 * M_PI / 9)); + TX_TAB(ff_tx_tab_9)[3] = RESCALE(sin(2 * M_PI / 9)); + TX_TAB(ff_tx_tab_9)[4] = RESCALE(cos(2 * M_PI / 36)); + TX_TAB(ff_tx_tab_9)[5] = RESCALE(sin(2 * M_PI / 36)); + TX_TAB(ff_tx_tab_9)[6] = TX_TAB(ff_tx_tab_9)[2] + TX_TAB(ff_tx_tab_9)[5]; + TX_TAB(ff_tx_tab_9)[7] = TX_TAB(ff_tx_tab_9)[3] - TX_TAB(ff_tx_tab_9)[4]; } -static av_cold void ff_init_9_tabs(void) -{ - TX_NAME(ff_cos_9)[0] = (FFTComplex){ RESCALE(cos(2 * M_PI / 3)), RESCALE( sin(2 * M_PI / 3)) }; - TX_NAME(ff_cos_9)[1] = (FFTComplex){ RESCALE(cos(2 * M_PI / 9)), RESCALE( sin(2 * M_PI / 9)) }; - TX_NAME(ff_cos_9)[2] = (FFTComplex){ RESCALE(cos(2 * M_PI / 36)), RESCALE( sin(2 * M_PI / 36)) }; - TX_NAME(ff_cos_9)[3] = (FFTComplex){ TX_NAME(ff_cos_9)[1].re + TX_NAME(ff_cos_9)[2].im, - TX_NAME(ff_cos_9)[1].im - TX_NAME(ff_cos_9)[2].re }; -} - -static CosTabsInitOnce cos_tabs_init_once[] = { - { ff_init_53_tabs, AV_ONCE_INIT }, - { ff_init_7_tabs, AV_ONCE_INIT }, - { ff_init_9_tabs, AV_ONCE_INIT }, - { NULL }, - { init_cos_tabs_16, AV_ONCE_INIT }, - { init_cos_tabs_32, AV_ONCE_INIT }, - { init_cos_tabs_64, AV_ONCE_INIT }, - { init_cos_tabs_128, AV_ONCE_INIT }, - { init_cos_tabs_256, AV_ONCE_INIT }, - { init_cos_tabs_512, AV_ONCE_INIT }, - { init_cos_tabs_1024, AV_ONCE_INIT }, - { init_cos_tabs_2048, AV_ONCE_INIT }, - { init_cos_tabs_4096, AV_ONCE_INIT }, - { init_cos_tabs_8192, AV_ONCE_INIT }, - { init_cos_tabs_16384, AV_ONCE_INIT }, - { init_cos_tabs_32768, AV_ONCE_INIT }, - { init_cos_tabs_65536, AV_ONCE_INIT }, - { init_cos_tabs_131072, AV_ONCE_INIT }, +static FFSRTabsInitOnce nptwo_tabs_init_once[] = { + { TX_TAB(ff_tx_init_tab_53), AV_ONCE_INIT, { 15, 5, 3 } }, + { TX_TAB(ff_tx_init_tab_9), AV_ONCE_INIT, { 9 } }, + { TX_TAB(ff_tx_init_tab_7), AV_ONCE_INIT, { 7 } }, }; -static av_cold void init_cos_tabs(int index) +av_cold void TX_TAB(ff_tx_init_tabs)(int len) { - ff_thread_once(&cos_tabs_init_once[index].control, - cos_tabs_init_once[index].func); + int factor_2 = ff_ctz(len); + if (factor_2) { + int idx = factor_2 - 3; + for (int i = 0; i <= idx; i++) + ff_thread_once(&sr_tabs_init_once[i].control, + sr_tabs_init_once[i].func); + len >>= factor_2; + } + + for (int i = 0; i < FF_ARRAY_ELEMS(nptwo_tabs_init_once); i++) { + int f, f_idx = 0; + + if (len <= 1) + return; + + while ((f = nptwo_tabs_init_once[i].factors[f_idx++])) { + if (f % len) + continue; + + ff_thread_once(&nptwo_tabs_init_once[i].control, + nptwo_tabs_init_once[i].func); + len /= f; + break; + } + } } -static av_always_inline void fft3(FFTComplex *out, FFTComplex *in, +static av_always_inline void fft3(TXComplex *out, TXComplex *in, ptrdiff_t stride) { - FFTComplex tmp[2]; + TXComplex tmp[2]; + const TXSample *tab = TX_TAB(ff_tx_tab_53); #ifdef TX_INT32 int64_t mtmp[4]; #endif @@ -163,19 +189,19 @@ static av_always_inline void fft3(FFTComplex *out, FFTComplex *in, out[0*stride].im = in[0].im + tmp[1].im; #ifdef TX_INT32 - mtmp[0] = (int64_t)TX_NAME(ff_cos_53)[0].re * tmp[0].re; - mtmp[1] = (int64_t)TX_NAME(ff_cos_53)[0].im * tmp[0].im; - mtmp[2] = (int64_t)TX_NAME(ff_cos_53)[1].re * tmp[1].re; - mtmp[3] = (int64_t)TX_NAME(ff_cos_53)[1].re * tmp[1].im; + mtmp[0] = (int64_t)tab[0] * tmp[0].re; + mtmp[1] = (int64_t)tab[1] * tmp[0].im; + mtmp[2] = (int64_t)tab[2] * tmp[1].re; + mtmp[3] = (int64_t)tab[2] * tmp[1].im; out[1*stride].re = in[0].re - (mtmp[2] + mtmp[0] + 0x40000000 >> 31); out[1*stride].im = in[0].im - (mtmp[3] - mtmp[1] + 0x40000000 >> 31); out[2*stride].re = in[0].re - (mtmp[2] - mtmp[0] + 0x40000000 >> 31); out[2*stride].im = in[0].im - (mtmp[3] + mtmp[1] + 0x40000000 >> 31); #else - tmp[0].re = TX_NAME(ff_cos_53)[0].re * tmp[0].re; - tmp[0].im = TX_NAME(ff_cos_53)[0].im * tmp[0].im; - tmp[1].re = TX_NAME(ff_cos_53)[1].re * tmp[1].re; - tmp[1].im = TX_NAME(ff_cos_53)[1].re * tmp[1].im; + tmp[0].re = tab[0] * tmp[0].re; + tmp[0].im = tab[1] * tmp[0].im; + tmp[1].re = tab[2] * tmp[1].re; + tmp[1].im = tab[2] * tmp[1].im; out[1*stride].re = in[0].re - tmp[1].re + tmp[0].re; out[1*stride].im = in[0].im - tmp[1].im - tmp[0].im; out[2*stride].re = in[0].re - tmp[1].re - tmp[0].re; @@ -183,38 +209,39 @@ static av_always_inline void fft3(FFTComplex *out, FFTComplex *in, #endif } -#define DECL_FFT5(NAME, D0, D1, D2, D3, D4) \ -static av_always_inline void NAME(FFTComplex *out, FFTComplex *in, \ - ptrdiff_t stride) \ -{ \ - FFTComplex z0[4], t[6]; \ - \ - BF(t[1].im, t[0].re, in[1].re, in[4].re); \ - BF(t[1].re, t[0].im, in[1].im, in[4].im); \ - BF(t[3].im, t[2].re, in[2].re, in[3].re); \ - BF(t[3].re, t[2].im, in[2].im, in[3].im); \ - \ - out[D0*stride].re = in[0].re + t[0].re + t[2].re; \ - out[D0*stride].im = in[0].im + t[0].im + t[2].im; \ - \ - SMUL(t[4].re, t[0].re, TX_NAME(ff_cos_53)[2].re, TX_NAME(ff_cos_53)[3].re, t[2].re, t[0].re); \ - SMUL(t[4].im, t[0].im, TX_NAME(ff_cos_53)[2].re, TX_NAME(ff_cos_53)[3].re, t[2].im, t[0].im); \ - CMUL(t[5].re, t[1].re, TX_NAME(ff_cos_53)[2].im, TX_NAME(ff_cos_53)[3].im, t[3].re, t[1].re); \ - CMUL(t[5].im, t[1].im, TX_NAME(ff_cos_53)[2].im, TX_NAME(ff_cos_53)[3].im, t[3].im, t[1].im); \ - \ - BF(z0[0].re, z0[3].re, t[0].re, t[1].re); \ - BF(z0[0].im, z0[3].im, t[0].im, t[1].im); \ - BF(z0[2].re, z0[1].re, t[4].re, t[5].re); \ - BF(z0[2].im, z0[1].im, t[4].im, t[5].im); \ - \ - out[D1*stride].re = in[0].re + z0[3].re; \ - out[D1*stride].im = in[0].im + z0[0].im; \ - out[D2*stride].re = in[0].re + z0[2].re; \ - out[D2*stride].im = in[0].im + z0[1].im; \ - out[D3*stride].re = in[0].re + z0[1].re; \ - out[D3*stride].im = in[0].im + z0[2].im; \ - out[D4*stride].re = in[0].re + z0[0].re; \ - out[D4*stride].im = in[0].im + z0[3].im; \ +#define DECL_FFT5(NAME, D0, D1, D2, D3, D4) \ +static av_always_inline void NAME(TXComplex *out, TXComplex *in, \ + ptrdiff_t stride) \ +{ \ + TXComplex z0[4], t[6]; \ + const TXSample *tab = TX_TAB(ff_tx_tab_53); \ + \ + BF(t[1].im, t[0].re, in[1].re, in[4].re); \ + BF(t[1].re, t[0].im, in[1].im, in[4].im); \ + BF(t[3].im, t[2].re, in[2].re, in[3].re); \ + BF(t[3].re, t[2].im, in[2].im, in[3].im); \ + \ + out[D0*stride].re = in[0].re + t[0].re + t[2].re; \ + out[D0*stride].im = in[0].im + t[0].im + t[2].im; \ + \ + SMUL(t[4].re, t[0].re, tab[4], tab[6], t[2].re, t[0].re); \ + SMUL(t[4].im, t[0].im, tab[4], tab[6], t[2].im, t[0].im); \ + CMUL(t[5].re, t[1].re, tab[5], tab[7], t[3].re, t[1].re); \ + CMUL(t[5].im, t[1].im, tab[5], tab[7], t[3].im, t[1].im); \ + \ + BF(z0[0].re, z0[3].re, t[0].re, t[1].re); \ + BF(z0[0].im, z0[3].im, t[0].im, t[1].im); \ + BF(z0[2].re, z0[1].re, t[4].re, t[5].re); \ + BF(z0[2].im, z0[1].im, t[4].im, t[5].im); \ + \ + out[D1*stride].re = in[0].re + z0[3].re; \ + out[D1*stride].im = in[0].im + z0[0].im; \ + out[D2*stride].re = in[0].re + z0[2].re; \ + out[D2*stride].im = in[0].im + z0[1].im; \ + out[D3*stride].re = in[0].re + z0[1].re; \ + out[D3*stride].im = in[0].im + z0[2].im; \ + out[D4*stride].re = in[0].re + z0[0].re; \ + out[D4*stride].im = in[0].im + z0[3].im; \ } DECL_FFT5(fft5, 0, 1, 2, 3, 4) @@ -222,11 +249,11 @@ DECL_FFT5(fft5_m1, 0, 6, 12, 3, 9) DECL_FFT5(fft5_m2, 10, 1, 7, 13, 4) DECL_FFT5(fft5_m3, 5, 11, 2, 8, 14) -static av_always_inline void fft7(FFTComplex *out, FFTComplex *in, +static av_always_inline void fft7(TXComplex *out, TXComplex *in, ptrdiff_t stride) { - FFTComplex t[6], z[3]; - const FFTComplex *tab = TX_NAME(ff_cos_7); + TXComplex t[6], z[3]; + const TXComplex *tab = (const TXComplex *)TX_TAB(ff_tx_tab_7); #ifdef TX_INT32 int64_t mtmp[12]; #endif @@ -309,11 +336,11 @@ static av_always_inline void fft7(FFTComplex *out, FFTComplex *in, out[6*stride].im = in[0].im + z[0].im; } -static av_always_inline void fft9(FFTComplex *out, FFTComplex *in, +static av_always_inline void fft9(TXComplex *out, TXComplex *in, ptrdiff_t stride) { - const FFTComplex *tab = TX_NAME(ff_cos_9); - FFTComplex t[16], w[4], x[5], y[5], z[2]; + const TXComplex *tab = (const TXComplex *)TX_TAB(ff_tx_tab_9); + TXComplex t[16], w[4], x[5], y[5], z[2]; #ifdef TX_INT32 int64_t mtmp[12]; #endif @@ -423,20 +450,20 @@ static av_always_inline void fft9(FFTComplex *out, FFTComplex *in, y[4].re = y[0].re - y[4].re; y[4].im = y[0].im - y[4].im; - out[1*stride] = (FFTComplex){ x[1].re + y[1].im, x[1].im - y[1].re }; - out[2*stride] = (FFTComplex){ x[2].re + y[2].im, x[2].im - y[2].re }; - out[3*stride] = (FFTComplex){ x[3].re + y[3].im, x[3].im - y[3].re }; - out[4*stride] = (FFTComplex){ x[4].re + y[4].im, x[4].im - y[4].re }; - out[5*stride] = (FFTComplex){ x[4].re - y[4].im, x[4].im + y[4].re }; - out[6*stride] = (FFTComplex){ x[3].re - y[3].im, x[3].im + y[3].re }; - out[7*stride] = (FFTComplex){ x[2].re - y[2].im, x[2].im + y[2].re }; - out[8*stride] = (FFTComplex){ x[1].re - y[1].im, x[1].im + y[1].re }; + out[1*stride] = (TXComplex){ x[1].re + y[1].im, x[1].im - y[1].re }; + out[2*stride] = (TXComplex){ x[2].re + y[2].im, x[2].im - y[2].re }; + out[3*stride] = (TXComplex){ x[3].re + y[3].im, x[3].im - y[3].re }; + out[4*stride] = (TXComplex){ x[4].re + y[4].im, x[4].im - y[4].re }; + out[5*stride] = (TXComplex){ x[4].re - y[4].im, x[4].im + y[4].re }; + out[6*stride] = (TXComplex){ x[3].re - y[3].im, x[3].im + y[3].re }; + out[7*stride] = (TXComplex){ x[2].re - y[2].im, x[2].im + y[2].re }; + out[8*stride] = (TXComplex){ x[1].re - y[1].im, x[1].im + y[1].re }; } -static av_always_inline void fft15(FFTComplex *out, FFTComplex *in, +static av_always_inline void fft15(TXComplex *out, TXComplex *in, ptrdiff_t stride) { - FFTComplex tmp[15]; + TXComplex tmp[15]; for (int i = 0; i < 5; i++) fft3(tmp + i, in + i*3, 5); @@ -446,7 +473,7 @@ static av_always_inline void fft15(FFTComplex *out, FFTComplex *in, fft5_m3(out, tmp + 10, stride); } -#define BUTTERFLIES(a0,a1,a2,a3) \ +#define BUTTERFLIES(a0, a1, a2, a3) \ do { \ r0=a0.re; \ i0=a0.im; \ @@ -460,7 +487,7 @@ static av_always_inline void fft15(FFTComplex *out, FFTComplex *in, BF(a2.im, a0.im, i0, t6); \ } while (0) -#define TRANSFORM(a0,a1,a2,a3,wre,wim) \ +#define TRANSFORM(a0, a1, a2, a3, wre, wim) \ do { \ CMUL(t1, t2, a2.re, a2.im, wre, -wim); \ CMUL(t5, t6, a3.re, a3.im, wre, wim); \ @@ -468,15 +495,16 @@ static av_always_inline void fft15(FFTComplex *out, FFTComplex *in, } while (0) /* z[0...8n-1], w[1...2n-1] */ -static void split_radix_combine(FFTComplex *z, const FFTSample *cos, int n) +static inline void TX_NAME(ff_tx_fft_sr_combine)(TXComplex *z, + const TXSample *cos, int len) { - int o1 = 2*n; - int o2 = 4*n; - int o3 = 6*n; - const FFTSample *wim = cos + o1 - 7; - FFTSample t1, t2, t3, t4, t5, t6, r0, i0, r1, i1; + int o1 = 2*len; + int o2 = 4*len; + int o3 = 6*len; + const TXSample *wim = cos + o1 - 7; + TXSample t1, t2, t3, t4, t5, t6, r0, i0, r1, i1; - for (int i = 0; i < n; i += 4) { + for (int i = 0; i < len; i += 4) { TRANSFORM(z[0], z[o1 + 0], z[o2 + 0], z[o3 + 0], cos[0], wim[7]); TRANSFORM(z[2], z[o1 + 2], z[o2 + 2], z[o3 + 2], cos[2], wim[5]); TRANSFORM(z[4], z[o1 + 4], z[o2 + 4], z[o3 + 4], cos[4], wim[3]); @@ -493,26 +521,63 @@ static void split_radix_combine(FFTComplex *z, const FFTSample *cos, int n) } } -#define DECL_FFT(n, n2, n4) \ -static void fft##n(FFTComplex *z) \ -{ \ - fft##n2(z); \ - fft##n4(z + n4*2); \ - fft##n4(z + n4*3); \ - split_radix_combine(z, TX_NAME(ff_cos_##n), n4/2); \ +static av_cold int TX_NAME(ff_tx_fft_sr_codelet_init)(AVTXContext *s, + const FFTXCodelet *cd, + uint64_t flags, + FFTXCodeletOptions *opts, + int len, int inv, + const void *scale) +{ + TX_TAB(ff_tx_init_tabs)(len); + return ff_tx_gen_ptwo_revtab(s, opts ? opts->invert_lookup : 1); } -static void fft2(FFTComplex *z) +#define DECL_SR_CODELET_DEF(n) \ +static const FFTXCodelet TX_NAME(ff_tx_fft##n##_ns_def) = { \ + .name = TX_NAME_STR("fft" #n "_ns"), \ + .function = TX_NAME(ff_tx_fft##n##_ns), \ + .type = TX_TYPE(FFT), \ + .flags = AV_TX_INPLACE | AV_TX_UNALIGNED | \ + FF_TX_PRESHUFFLE, \ + .factors[0] = 2, \ + .min_len = n, \ + .max_len = n, \ + .init = TX_NAME(ff_tx_fft_sr_codelet_init), \ + .cpu_flags = FF_TX_CPU_FLAGS_ALL, \ + .prio = FF_TX_PRIO_BASE, \ +}; + +#define DECL_SR_CODELET(n, n2, n4) \ +static void TX_NAME(ff_tx_fft##n##_ns)(AVTXContext *s, void *dst, \ + void *src, ptrdiff_t stride) \ +{ \ + TXComplex *z = dst; \ + const TXSample *cos = TX_TAB(ff_tx_tab_##n); \ + \ + TX_NAME(ff_tx_fft##n2##_ns)(s, z, z, stride); \ + TX_NAME(ff_tx_fft##n4##_ns)(s, z + n4*2, z + n4*2, stride); \ + TX_NAME(ff_tx_fft##n4##_ns)(s, z + n4*3, z + n4*3, stride); \ + TX_NAME(ff_tx_fft_sr_combine)(z, cos, n4 >> 1); \ +} \ + \ +DECL_SR_CODELET_DEF(n) + +static void TX_NAME(ff_tx_fft2_ns)(AVTXContext *s, void *dst, + void *src, ptrdiff_t stride) { - FFTComplex tmp; + TXComplex *z = dst; + TXComplex tmp; + BF(tmp.re, z[0].re, z[0].re, z[1].re); BF(tmp.im, z[0].im, z[0].im, z[1].im); z[1] = tmp; } -static void fft4(FFTComplex *z) +static void TX_NAME(ff_tx_fft4_ns)(AVTXContext *s, void *dst, + void *src, ptrdiff_t stride) { - FFTSample t1, t2, t3, t4, t5, t6, t7, t8; + TXComplex *z = dst; + TXSample t1, t2, t3, t4, t5, t6, t7, t8; BF(t3, t1, z[0].re, z[1].re); BF(t8, t6, z[3].re, z[2].re); @@ -524,11 +589,14 @@ static void fft4(FFTComplex *z) BF(z[2].im, z[0].im, t2, t5); } -static void fft8(FFTComplex *z) +static void TX_NAME(ff_tx_fft8_ns)(AVTXContext *s, void *dst, + void *src, ptrdiff_t stride) { - FFTSample t1, t2, t3, t4, t5, t6, r0, i0, r1, i1; + TXComplex *z = dst; + TXSample t1, t2, t3, t4, t5, t6, r0, i0, r1, i1; + const TXSample cos = TX_TAB(ff_tx_tab_8)[1]; - fft4(z); + TX_NAME(ff_tx_fft4_ns)(s, z, z, stride); BF(t1, z[5].re, z[4].re, -z[5].re); BF(t2, z[5].im, z[4].im, -z[5].im); @@ -536,19 +604,23 @@ static void fft8(FFTComplex *z) BF(t6, z[7].im, z[6].im, -z[7].im); BUTTERFLIES(z[0], z[2], z[4], z[6]); - TRANSFORM(z[1], z[3], z[5], z[7], RESCALE(M_SQRT1_2), RESCALE(M_SQRT1_2)); + TRANSFORM(z[1], z[3], z[5], z[7], cos, cos); } -static void fft16(FFTComplex *z) +static void TX_NAME(ff_tx_fft16_ns)(AVTXContext *s, void *dst, + void *src, ptrdiff_t stride) { - FFTSample t1, t2, t3, t4, t5, t6, r0, i0, r1, i1; - FFTSample cos_16_1 = TX_NAME(ff_cos_16)[1]; - FFTSample cos_16_2 = TX_NAME(ff_cos_16)[2]; - FFTSample cos_16_3 = TX_NAME(ff_cos_16)[3]; + TXComplex *z = dst; + const TXSample *cos = TX_TAB(ff_tx_tab_16); - fft8(z + 0); - fft4(z + 8); - fft4(z + 12); + TXSample t1, t2, t3, t4, t5, t6, r0, i0, r1, i1; + TXSample cos_16_1 = cos[1]; + TXSample cos_16_2 = cos[2]; + TXSample cos_16_3 = cos[3]; + + TX_NAME(ff_tx_fft8_ns)(s, z + 0, z + 0, stride); + TX_NAME(ff_tx_fft4_ns)(s, z + 8, z + 8, stride); + TX_NAME(ff_tx_fft4_ns)(s, z + 12, z + 12, stride); t1 = z[ 8].re; t2 = z[ 8].im; @@ -561,47 +633,217 @@ static void fft16(FFTComplex *z) TRANSFORM(z[ 3], z[ 7], z[11], z[15], cos_16_3, cos_16_1); } -DECL_FFT(32,16,8) -DECL_FFT(64,32,16) -DECL_FFT(128,64,32) -DECL_FFT(256,128,64) -DECL_FFT(512,256,128) -DECL_FFT(1024,512,256) -DECL_FFT(2048,1024,512) -DECL_FFT(4096,2048,1024) -DECL_FFT(8192,4096,2048) -DECL_FFT(16384,8192,4096) -DECL_FFT(32768,16384,8192) -DECL_FFT(65536,32768,16384) -DECL_FFT(131072,65536,32768) +DECL_SR_CODELET_DEF(2) +DECL_SR_CODELET_DEF(4) +DECL_SR_CODELET_DEF(8) +DECL_SR_CODELET_DEF(16) +DECL_SR_CODELET(32,16,8) +DECL_SR_CODELET(64,32,16) +DECL_SR_CODELET(128,64,32) +DECL_SR_CODELET(256,128,64) +DECL_SR_CODELET(512,256,128) +DECL_SR_CODELET(1024,512,256) +DECL_SR_CODELET(2048,1024,512) +DECL_SR_CODELET(4096,2048,1024) +DECL_SR_CODELET(8192,4096,2048) +DECL_SR_CODELET(16384,8192,4096) +DECL_SR_CODELET(32768,16384,8192) +DECL_SR_CODELET(65536,32768,16384) +DECL_SR_CODELET(131072,65536,32768) -static void (* const fft_dispatch[])(FFTComplex*) = { - NULL, fft2, fft4, fft8, fft16, fft32, fft64, fft128, fft256, fft512, - fft1024, fft2048, fft4096, fft8192, fft16384, fft32768, fft65536, fft131072 +static av_cold int TX_NAME(ff_tx_fft_sr_init)(AVTXContext *s, + const FFTXCodelet *cd, + uint64_t flags, + FFTXCodeletOptions *opts, + int len, int inv, + const void *scale) +{ + int ret; + int is_inplace = !!(flags & AV_TX_INPLACE); + FFTXCodeletOptions sub_opts = { .invert_lookup = !is_inplace }; + + flags &= ~FF_TX_OUT_OF_PLACE; /* We want the subtransform to be */ + flags |= AV_TX_INPLACE; /* in-place */ + flags |= FF_TX_PRESHUFFLE; /* This function handles the permute step */ + + if ((ret = ff_tx_init_subtx(s, TX_TYPE(FFT), flags, &sub_opts, len, inv, scale))) + return ret; + + if (is_inplace && (ret = ff_tx_gen_ptwo_inplace_revtab_idx(s))) + return ret; + + return 0; +} + +static void TX_NAME(ff_tx_fft_sr)(AVTXContext *s, void *_dst, + void *_src, ptrdiff_t stride) +{ + TXComplex *src = _src; + TXComplex *dst = _dst; + int *map = s->sub[0].map; + int len = s->len; + + /* Compilers can't vectorize this anyway without assuming AVX2, which they + * generally don't, at least without -march=native -mtune=native */ + for (int i = 0; i < len; i++) + dst[i] = src[map[i]]; + + s->fn[0](&s->sub[0], dst, dst, stride); +} + +static void TX_NAME(ff_tx_fft_sr_inplace)(AVTXContext *s, void *_dst, + void *_src, ptrdiff_t stride) +{ + TXComplex *dst = _dst; + TXComplex tmp; + const int *map = s->sub->map; + const int *inplace_idx = s->map; + int src_idx, dst_idx; + + src_idx = *inplace_idx++; + do { + tmp = dst[src_idx]; + dst_idx = map[src_idx]; + do { + FFSWAP(TXComplex, tmp, dst[dst_idx]); + dst_idx = map[dst_idx]; + } while (dst_idx != src_idx); /* Can be > as well, but was less predictable */ + dst[dst_idx] = tmp; + } while ((src_idx = *inplace_idx++)); + + s->fn[0](&s->sub[0], dst, dst, stride); +} + +static const FFTXCodelet TX_NAME(ff_tx_fft_sr_def) = { + .name = TX_NAME_STR("fft_sr"), + .function = TX_NAME(ff_tx_fft_sr), + .type = TX_TYPE(FFT), + .flags = AV_TX_UNALIGNED | FF_TX_OUT_OF_PLACE, + .factors[0] = 2, + .min_len = 2, + .max_len = TX_LEN_UNLIMITED, + .init = TX_NAME(ff_tx_fft_sr_init), + .cpu_flags = FF_TX_CPU_FLAGS_ALL, + .prio = FF_TX_PRIO_BASE, }; +static const FFTXCodelet TX_NAME(ff_tx_fft_sr_inplace_def) = { + .name = TX_NAME_STR("fft_sr_inplace"), + .function = TX_NAME(ff_tx_fft_sr_inplace), + .type = TX_TYPE(FFT), + .flags = AV_TX_UNALIGNED | AV_TX_INPLACE, + .factors[0] = 2, + .min_len = 2, + .max_len = TX_LEN_UNLIMITED, + .init = TX_NAME(ff_tx_fft_sr_init), + .cpu_flags = FF_TX_CPU_FLAGS_ALL, + .prio = FF_TX_PRIO_BASE, +}; + +static void TX_NAME(ff_tx_fft_naive)(AVTXContext *s, void *_dst, void *_src, + ptrdiff_t stride) +{ + TXComplex *src = _src; + TXComplex *dst = _dst; + const int n = s->len; + double phase = s->inv ? 2.0*M_PI/n : -2.0*M_PI/n; + + for(int i = 0; i < n; i++) { + TXComplex tmp = { 0 }; + for(int j = 0; j < n; j++) { + const double factor = phase*i*j; + const TXComplex mult = { + RESCALE(cos(factor)), + RESCALE(sin(factor)), + }; + TXComplex res; + CMUL3(res, src[j], mult); + tmp.re += res.re; + tmp.im += res.im; + } + dst[i] = tmp; + } +} + +static const FFTXCodelet TX_NAME(ff_tx_fft_naive_def) = { + .name = TX_NAME_STR("fft_naive"), + .function = TX_NAME(ff_tx_fft_naive), + .type = TX_TYPE(FFT), + .flags = AV_TX_UNALIGNED | FF_TX_OUT_OF_PLACE, + .factors[0] = TX_FACTOR_ANY, + .min_len = 2, + .max_len = TX_LEN_UNLIMITED, + .init = NULL, + .cpu_flags = FF_TX_CPU_FLAGS_ALL, + .prio = FF_TX_PRIO_MIN, +}; + +static av_cold int TX_NAME(ff_tx_fft_pfa_init)(AVTXContext *s, + const FFTXCodelet *cd, + uint64_t flags, + FFTXCodeletOptions *opts, + int len, int inv, + const void *scale) +{ + int ret; + int sub_len = len / cd->factors[0]; + FFTXCodeletOptions sub_opts = { .invert_lookup = 0 }; + + flags &= ~FF_TX_OUT_OF_PLACE; /* We want the subtransform to be */ + flags |= AV_TX_INPLACE; /* in-place */ + flags |= FF_TX_PRESHUFFLE; /* This function handles the permute step */ + + if ((ret = ff_tx_init_subtx(s, TX_TYPE(FFT), flags, &sub_opts, + sub_len, inv, scale))) + return ret; + + if ((ret = ff_tx_gen_compound_mapping(s, cd->factors[0], sub_len))) + return ret; + + if (!(s->tmp = av_malloc(len*sizeof(*s->tmp)))) + return AVERROR(ENOMEM); + + TX_TAB(ff_tx_init_tabs)(len / sub_len); + + return 0; +} + #define DECL_COMP_FFT(N) \ -static void compound_fft_##N##xM(AVTXContext *s, void *_out, \ - void *_in, ptrdiff_t stride) \ +static void TX_NAME(ff_tx_fft_pfa_##N##xM)(AVTXContext *s, void *_out, \ + void *_in, ptrdiff_t stride) \ { \ - const int m = s->m, *in_map = s->pfatab, *out_map = in_map + N*m; \ - FFTComplex *in = _in; \ - FFTComplex *out = _out; \ - FFTComplex fft##N##in[N]; \ - void (*fftp)(FFTComplex *z) = fft_dispatch[av_log2(m)]; \ + const int m = s->sub->len; \ + const int *in_map = s->map, *out_map = in_map + s->len; \ + const int *sub_map = s->sub->map; \ + TXComplex *in = _in; \ + TXComplex *out = _out; \ + TXComplex fft##N##in[N]; \ \ for (int i = 0; i < m; i++) { \ for (int j = 0; j < N; j++) \ fft##N##in[j] = in[in_map[i*N + j]]; \ - fft##N(s->tmp + s->revtab_c[i], fft##N##in, m); \ + fft##N(s->tmp + sub_map[i], fft##N##in, m); \ } \ \ for (int i = 0; i < N; i++) \ - fftp(s->tmp + m*i); \ + s->fn[0](&s->sub[0], s->tmp + m*i, s->tmp + m*i, sizeof(TXComplex)); \ \ for (int i = 0; i < N*m; i++) \ out[i] = s->tmp[out_map[i]]; \ -} +} \ + \ +static const FFTXCodelet TX_NAME(ff_tx_fft_pfa_##N##xM_def) = { \ + .name = TX_NAME_STR("fft_pfa_" #N "xM"), \ + .function = TX_NAME(ff_tx_fft_pfa_##N##xM), \ + .type = TX_TYPE(FFT), \ + .flags = AV_TX_UNALIGNED | FF_TX_OUT_OF_PLACE, \ + .factors = { N, TX_FACTOR_ANY }, \ + .min_len = N*2, \ + .max_len = TX_LEN_UNLIMITED, \ + .init = TX_NAME(ff_tx_fft_pfa_init), \ + .cpu_flags = FF_TX_CPU_FLAGS_ALL, \ + .prio = FF_TX_PRIO_BASE, \ +}; DECL_COMP_FFT(3) DECL_COMP_FFT(5) @@ -609,229 +851,47 @@ DECL_COMP_FFT(7) DECL_COMP_FFT(9) DECL_COMP_FFT(15) -static void split_radix_fft(AVTXContext *s, void *_out, void *_in, - ptrdiff_t stride) +static av_cold int TX_NAME(ff_tx_mdct_naive_init)(AVTXContext *s, + const FFTXCodelet *cd, + uint64_t flags, + FFTXCodeletOptions *opts, + int len, int inv, + const void *scale) { - FFTComplex *in = _in; - FFTComplex *out = _out; - int m = s->m, mb = av_log2(m); - - if (s->flags & AV_TX_INPLACE) { - FFTComplex tmp; - int src, dst, *inplace_idx = s->inplace_idx; - - src = *inplace_idx++; - - do { - tmp = out[src]; - dst = s->revtab_c[src]; - do { - FFSWAP(FFTComplex, tmp, out[dst]); - dst = s->revtab_c[dst]; - } while (dst != src); /* Can be > as well, but is less predictable */ - out[dst] = tmp; - } while ((src = *inplace_idx++)); - } else { - for (int i = 0; i < m; i++) - out[i] = in[s->revtab_c[i]]; - } - - fft_dispatch[mb](out); + s->scale_d = *((SCALE_TYPE *)scale); + s->scale_f = s->scale_d; + return 0; } -static void naive_fft(AVTXContext *s, void *_out, void *_in, - ptrdiff_t stride) +static void TX_NAME(ff_tx_mdct_naive_fwd)(AVTXContext *s, void *_dst, + void *_src, ptrdiff_t stride) { - FFTComplex *in = _in; - FFTComplex *out = _out; - const int n = s->n; - double phase = s->inv ? 2.0*M_PI/n : -2.0*M_PI/n; - - for(int i = 0; i < n; i++) { - FFTComplex tmp = { 0 }; - for(int j = 0; j < n; j++) { - const double factor = phase*i*j; - const FFTComplex mult = { - RESCALE(cos(factor)), - RESCALE(sin(factor)), - }; - FFTComplex res; - CMUL3(res, in[j], mult); - tmp.re += res.re; - tmp.im += res.im; - } - out[i] = tmp; - } -} - -#define DECL_COMP_IMDCT(N) \ -static void compound_imdct_##N##xM(AVTXContext *s, void *_dst, void *_src, \ - ptrdiff_t stride) \ -{ \ - FFTComplex fft##N##in[N]; \ - FFTComplex *z = _dst, *exp = s->exptab; \ - const int m = s->m, len8 = N*m >> 1; \ - const int *in_map = s->pfatab, *out_map = in_map + N*m; \ - const FFTSample *src = _src, *in1, *in2; \ - void (*fftp)(FFTComplex *) = fft_dispatch[av_log2(m)]; \ - \ - stride /= sizeof(*src); /* To convert it from bytes */ \ - in1 = src; \ - in2 = src + ((N*m*2) - 1) * stride; \ - \ - for (int i = 0; i < m; i++) { \ - for (int j = 0; j < N; j++) { \ - const int k = in_map[i*N + j]; \ - FFTComplex tmp = { in2[-k*stride], in1[k*stride] }; \ - CMUL3(fft##N##in[j], tmp, exp[k >> 1]); \ - } \ - fft##N(s->tmp + s->revtab_c[i], fft##N##in, m); \ - } \ - \ - for (int i = 0; i < N; i++) \ - fftp(s->tmp + m*i); \ - \ - for (int i = 0; i < len8; i++) { \ - const int i0 = len8 + i, i1 = len8 - i - 1; \ - const int s0 = out_map[i0], s1 = out_map[i1]; \ - FFTComplex src1 = { s->tmp[s1].im, s->tmp[s1].re }; \ - FFTComplex src0 = { s->tmp[s0].im, s->tmp[s0].re }; \ - \ - CMUL(z[i1].re, z[i0].im, src1.re, src1.im, exp[i1].im, exp[i1].re); \ - CMUL(z[i0].re, z[i1].im, src0.re, src0.im, exp[i0].im, exp[i0].re); \ - } \ -} - -DECL_COMP_IMDCT(3) -DECL_COMP_IMDCT(5) -DECL_COMP_IMDCT(7) -DECL_COMP_IMDCT(9) -DECL_COMP_IMDCT(15) - -#define DECL_COMP_MDCT(N) \ -static void compound_mdct_##N##xM(AVTXContext *s, void *_dst, void *_src, \ - ptrdiff_t stride) \ -{ \ - FFTSample *src = _src, *dst = _dst; \ - FFTComplex *exp = s->exptab, tmp, fft##N##in[N]; \ - const int m = s->m, len4 = N*m, len3 = len4 * 3, len8 = len4 >> 1; \ - const int *in_map = s->pfatab, *out_map = in_map + N*m; \ - void (*fftp)(FFTComplex *) = fft_dispatch[av_log2(m)]; \ - \ - stride /= sizeof(*dst); \ - \ - for (int i = 0; i < m; i++) { /* Folding and pre-reindexing */ \ - for (int j = 0; j < N; j++) { \ - const int k = in_map[i*N + j]; \ - if (k < len4) { \ - tmp.re = FOLD(-src[ len4 + k], src[1*len4 - 1 - k]); \ - tmp.im = FOLD(-src[ len3 + k], -src[1*len3 - 1 - k]); \ - } else { \ - tmp.re = FOLD(-src[ len4 + k], -src[5*len4 - 1 - k]); \ - tmp.im = FOLD( src[-len4 + k], -src[1*len3 - 1 - k]); \ - } \ - CMUL(fft##N##in[j].im, fft##N##in[j].re, tmp.re, tmp.im, \ - exp[k >> 1].re, exp[k >> 1].im); \ - } \ - fft##N(s->tmp + s->revtab_c[i], fft##N##in, m); \ - } \ - \ - for (int i = 0; i < N; i++) \ - fftp(s->tmp + m*i); \ - \ - for (int i = 0; i < len8; i++) { \ - const int i0 = len8 + i, i1 = len8 - i - 1; \ - const int s0 = out_map[i0], s1 = out_map[i1]; \ - FFTComplex src1 = { s->tmp[s1].re, s->tmp[s1].im }; \ - FFTComplex src0 = { s->tmp[s0].re, s->tmp[s0].im }; \ - \ - CMUL(dst[2*i1*stride + stride], dst[2*i0*stride], src0.re, src0.im, \ - exp[i0].im, exp[i0].re); \ - CMUL(dst[2*i0*stride + stride], dst[2*i1*stride], src1.re, src1.im, \ - exp[i1].im, exp[i1].re); \ - } \ -} - -DECL_COMP_MDCT(3) -DECL_COMP_MDCT(5) -DECL_COMP_MDCT(7) -DECL_COMP_MDCT(9) -DECL_COMP_MDCT(15) - -static void monolithic_imdct(AVTXContext *s, void *_dst, void *_src, - ptrdiff_t stride) -{ - FFTComplex *z = _dst, *exp = s->exptab; - const int m = s->m, len8 = m >> 1; - const FFTSample *src = _src, *in1, *in2; - void (*fftp)(FFTComplex *) = fft_dispatch[av_log2(m)]; - - stride /= sizeof(*src); - in1 = src; - in2 = src + ((m*2) - 1) * stride; - - for (int i = 0; i < m; i++) { - FFTComplex tmp = { in2[-2*i*stride], in1[2*i*stride] }; - CMUL3(z[s->revtab_c[i]], tmp, exp[i]); - } - - fftp(z); - - for (int i = 0; i < len8; i++) { - const int i0 = len8 + i, i1 = len8 - i - 1; - FFTComplex src1 = { z[i1].im, z[i1].re }; - FFTComplex src0 = { z[i0].im, z[i0].re }; - - CMUL(z[i1].re, z[i0].im, src1.re, src1.im, exp[i1].im, exp[i1].re); - CMUL(z[i0].re, z[i1].im, src0.re, src0.im, exp[i0].im, exp[i0].re); - } -} - -static void monolithic_mdct(AVTXContext *s, void *_dst, void *_src, - ptrdiff_t stride) -{ - FFTSample *src = _src, *dst = _dst; - FFTComplex *exp = s->exptab, tmp, *z = _dst; - const int m = s->m, len4 = m, len3 = len4 * 3, len8 = len4 >> 1; - void (*fftp)(FFTComplex *) = fft_dispatch[av_log2(m)]; + TXSample *src = _src; + TXSample *dst = _dst; + double scale = s->scale_d; + int len = s->len; + const double phase = M_PI/(4.0*len); stride /= sizeof(*dst); - for (int i = 0; i < m; i++) { /* Folding and pre-reindexing */ - const int k = 2*i; - if (k < len4) { - tmp.re = FOLD(-src[ len4 + k], src[1*len4 - 1 - k]); - tmp.im = FOLD(-src[ len3 + k], -src[1*len3 - 1 - k]); - } else { - tmp.re = FOLD(-src[ len4 + k], -src[5*len4 - 1 - k]); - tmp.im = FOLD( src[-len4 + k], -src[1*len3 - 1 - k]); + for (int i = 0; i < len; i++) { + double sum = 0.0; + for (int j = 0; j < len*2; j++) { + int a = (2*j + 1 + len) * (2*i + 1); + sum += UNSCALE(src[j]) * cos(a * phase); } - CMUL(z[s->revtab_c[i]].im, z[s->revtab_c[i]].re, tmp.re, tmp.im, - exp[i].re, exp[i].im); - } - - fftp(z); - - for (int i = 0; i < len8; i++) { - const int i0 = len8 + i, i1 = len8 - i - 1; - FFTComplex src1 = { z[i1].re, z[i1].im }; - FFTComplex src0 = { z[i0].re, z[i0].im }; - - CMUL(dst[2*i1*stride + stride], dst[2*i0*stride], src0.re, src0.im, - exp[i0].im, exp[i0].re); - CMUL(dst[2*i0*stride + stride], dst[2*i1*stride], src1.re, src1.im, - exp[i1].im, exp[i1].re); + dst[i*stride] = RESCALE(sum*scale); } } -static void naive_imdct(AVTXContext *s, void *_dst, void *_src, - ptrdiff_t stride) +static void TX_NAME(ff_tx_mdct_naive_inv)(AVTXContext *s, void *_dst, + void *_src, ptrdiff_t stride) { - int len = s->n; + TXSample *src = _src; + TXSample *dst = _dst; + double scale = s->scale_d; + int len = s->len >> 1; int len2 = len*2; - FFTSample *src = _src; - FFTSample *dst = _dst; - double scale = s->scale; const double phase = M_PI/(4.0*len2); stride /= sizeof(*src); @@ -854,36 +914,183 @@ static void naive_imdct(AVTXContext *s, void *_dst, void *_src, } } -static void naive_mdct(AVTXContext *s, void *_dst, void *_src, - ptrdiff_t stride) +static const FFTXCodelet TX_NAME(ff_tx_mdct_naive_fwd_def) = { + .name = TX_NAME_STR("mdct_naive_fwd"), + .function = TX_NAME(ff_tx_mdct_naive_fwd), + .type = TX_TYPE(MDCT), + .flags = AV_TX_UNALIGNED | FF_TX_OUT_OF_PLACE | FF_TX_FORWARD_ONLY, + .factors = { 2, TX_FACTOR_ANY }, /* MDCTs need an even length */ + .min_len = 2, + .max_len = TX_LEN_UNLIMITED, + .init = TX_NAME(ff_tx_mdct_naive_init), + .cpu_flags = FF_TX_CPU_FLAGS_ALL, + .prio = FF_TX_PRIO_MIN, +}; + +static const FFTXCodelet TX_NAME(ff_tx_mdct_naive_inv_def) = { + .name = TX_NAME_STR("mdct_naive_inv"), + .function = TX_NAME(ff_tx_mdct_naive_inv), + .type = TX_TYPE(MDCT), + .flags = AV_TX_UNALIGNED | FF_TX_OUT_OF_PLACE | FF_TX_INVERSE_ONLY, + .factors = { 2, TX_FACTOR_ANY }, + .min_len = 2, + .max_len = TX_LEN_UNLIMITED, + .init = TX_NAME(ff_tx_mdct_naive_init), + .cpu_flags = FF_TX_CPU_FLAGS_ALL, + .prio = FF_TX_PRIO_MIN, +}; + +static av_cold int TX_NAME(ff_tx_mdct_sr_init)(AVTXContext *s, + const FFTXCodelet *cd, + uint64_t flags, + FFTXCodeletOptions *opts, + int len, int inv, + const void *scale) { - int len = s->n*2; - FFTSample *src = _src; - FFTSample *dst = _dst; - double scale = s->scale; - const double phase = M_PI/(4.0*len); + int ret; + FFTXCodeletOptions sub_opts = { .invert_lookup = 0 }; + + s->scale_d = *((SCALE_TYPE *)scale); + s->scale_f = s->scale_d; + + flags &= ~FF_TX_OUT_OF_PLACE; /* We want the subtransform to be */ + flags |= AV_TX_INPLACE; /* in-place */ + flags |= FF_TX_PRESHUFFLE; /* This function handles the permute step */ + + if ((ret = ff_tx_init_subtx(s, TX_TYPE(FFT), flags, &sub_opts, len >> 1, + inv, scale))) + return ret; + + if ((ret = TX_TAB(ff_tx_mdct_gen_exp)(s))) + return ret; + + return 0; +} + +static void TX_NAME(ff_tx_mdct_sr_fwd)(AVTXContext *s, void *_dst, void *_src, + ptrdiff_t stride) +{ + TXSample *src = _src, *dst = _dst; + TXComplex *exp = s->exp, tmp, *z = _dst; + const int len2 = s->len >> 1; + const int len4 = s->len >> 2; + const int len3 = len2 * 3; + const int *sub_map = s->sub->map; stride /= sizeof(*dst); - for (int i = 0; i < len; i++) { - double sum = 0.0; - for (int j = 0; j < len*2; j++) { - int a = (2*j + 1 + len) * (2*i + 1); - sum += UNSCALE(src[j]) * cos(a * phase); + for (int i = 0; i < len2; i++) { /* Folding and pre-reindexing */ + const int k = 2*i; + const int idx = sub_map[i]; + if (k < len2) { + tmp.re = FOLD(-src[ len2 + k], src[1*len2 - 1 - k]); + tmp.im = FOLD(-src[ len3 + k], -src[1*len3 - 1 - k]); + } else { + tmp.re = FOLD(-src[ len2 + k], -src[5*len2 - 1 - k]); + tmp.im = FOLD( src[-len2 + k], -src[1*len3 - 1 - k]); } - dst[i*stride] = RESCALE(sum*scale); + CMUL(z[idx].im, z[idx].re, tmp.re, tmp.im, exp[i].re, exp[i].im); + } + + s->fn[0](&s->sub[0], z, z, sizeof(TXComplex)); + + for (int i = 0; i < len4; i++) { + const int i0 = len4 + i, i1 = len4 - i - 1; + TXComplex src1 = { z[i1].re, z[i1].im }; + TXComplex src0 = { z[i0].re, z[i0].im }; + + CMUL(dst[2*i1*stride + stride], dst[2*i0*stride], src0.re, src0.im, + exp[i0].im, exp[i0].re); + CMUL(dst[2*i0*stride + stride], dst[2*i1*stride], src1.re, src1.im, + exp[i1].im, exp[i1].re); } } -static void full_imdct_wrapper_fn(AVTXContext *s, void *_dst, void *_src, - ptrdiff_t stride) +static void TX_NAME(ff_tx_mdct_sr_inv)(AVTXContext *s, void *_dst, void *_src, + ptrdiff_t stride) { - int len = s->m*s->n*4; + TXComplex *z = _dst, *exp = s->exp; + const TXSample *src = _src, *in1, *in2; + const int len2 = s->len >> 1; + const int len4 = s->len >> 2; + const int *sub_map = s->sub->map; + + stride /= sizeof(*src); + in1 = src; + in2 = src + ((len2*2) - 1) * stride; + + for (int i = 0; i < len2; i++) { + TXComplex tmp = { in2[-2*i*stride], in1[2*i*stride] }; + CMUL3(z[sub_map[i]], tmp, exp[i]); + } + + s->fn[0](&s->sub[0], z, z, sizeof(TXComplex)); + + for (int i = 0; i < len4; i++) { + const int i0 = len4 + i, i1 = len4 - i - 1; + TXComplex src1 = { z[i1].im, z[i1].re }; + TXComplex src0 = { z[i0].im, z[i0].re }; + + CMUL(z[i1].re, z[i0].im, src1.re, src1.im, exp[i1].im, exp[i1].re); + CMUL(z[i0].re, z[i1].im, src0.re, src0.im, exp[i0].im, exp[i0].re); + } +} + +static const FFTXCodelet TX_NAME(ff_tx_mdct_sr_fwd_def) = { + .name = TX_NAME_STR("mdct_sr_fwd"), + .function = TX_NAME(ff_tx_mdct_sr_fwd), + .type = TX_TYPE(MDCT), + .flags = AV_TX_UNALIGNED | FF_TX_OUT_OF_PLACE | FF_TX_FORWARD_ONLY, + .factors[0] = 2, + .min_len = 2, + .max_len = TX_LEN_UNLIMITED, + .init = TX_NAME(ff_tx_mdct_sr_init), + .cpu_flags = FF_TX_CPU_FLAGS_ALL, + .prio = FF_TX_PRIO_BASE, +}; + +static const FFTXCodelet TX_NAME(ff_tx_mdct_sr_inv_def) = { + .name = TX_NAME_STR("mdct_sr_inv"), + .function = TX_NAME(ff_tx_mdct_sr_inv), + .type = TX_TYPE(MDCT), + .flags = AV_TX_UNALIGNED | FF_TX_OUT_OF_PLACE | FF_TX_INVERSE_ONLY, + .factors[0] = 2, + .min_len = 2, + .max_len = TX_LEN_UNLIMITED, + .init = TX_NAME(ff_tx_mdct_sr_init), + .cpu_flags = FF_TX_CPU_FLAGS_ALL, + .prio = FF_TX_PRIO_BASE, +}; + +static av_cold int TX_NAME(ff_tx_mdct_inv_full_init)(AVTXContext *s, + const FFTXCodelet *cd, + uint64_t flags, + FFTXCodeletOptions *opts, + int len, int inv, + const void *scale) +{ + int ret; + + s->scale_d = *((SCALE_TYPE *)scale); + s->scale_f = s->scale_d; + + flags &= ~AV_TX_FULL_IMDCT; + + if ((ret = ff_tx_init_subtx(s, TX_TYPE(MDCT), flags, NULL, len, 1, scale))) + return ret; + + return 0; +} + +static void TX_NAME(ff_tx_mdct_inv_full)(AVTXContext *s, void *_dst, + void *_src, ptrdiff_t stride) +{ + int len = s->len << 1; int len2 = len >> 1; int len4 = len >> 2; - FFTSample *dst = _dst; + TXSample *dst = _dst; - s->top_tx(s, dst + len4, _src, stride); + s->fn[0](&s->sub[0], dst + len4, _src, stride); stride /= sizeof(*dst); @@ -893,132 +1100,376 @@ static void full_imdct_wrapper_fn(AVTXContext *s, void *_dst, void *_src, } } -static int gen_mdct_exptab(AVTXContext *s, int len4, double scale) +static const FFTXCodelet TX_NAME(ff_tx_mdct_inv_full_def) = { + .name = TX_NAME_STR("mdct_inv_full"), + .function = TX_NAME(ff_tx_mdct_inv_full), + .type = TX_TYPE(MDCT), + .flags = AV_TX_UNALIGNED | AV_TX_INPLACE | + FF_TX_OUT_OF_PLACE | AV_TX_FULL_IMDCT, + .factors = { 2, TX_FACTOR_ANY }, + .min_len = 2, + .max_len = TX_LEN_UNLIMITED, + .init = TX_NAME(ff_tx_mdct_inv_full_init), + .cpu_flags = FF_TX_CPU_FLAGS_ALL, + .prio = FF_TX_PRIO_BASE, +}; + +static av_cold int TX_NAME(ff_tx_mdct_pfa_init)(AVTXContext *s, + const FFTXCodelet *cd, + uint64_t flags, + FFTXCodeletOptions *opts, + int len, int inv, + const void *scale) { + int ret, sub_len; + FFTXCodeletOptions sub_opts = { .invert_lookup = 0 }; + + len >>= 1; + sub_len = len / cd->factors[0]; + + s->scale_d = *((SCALE_TYPE *)scale); + s->scale_f = s->scale_d; + + flags &= ~FF_TX_OUT_OF_PLACE; /* We want the subtransform to be */ + flags |= AV_TX_INPLACE; /* in-place */ + flags |= FF_TX_PRESHUFFLE; /* This function handles the permute step */ + + if ((ret = ff_tx_init_subtx(s, TX_TYPE(FFT), flags, &sub_opts, + sub_len, inv, scale))) + return ret; + + if ((ret = ff_tx_gen_compound_mapping(s, cd->factors[0], sub_len))) + return ret; + + if ((ret = TX_TAB(ff_tx_mdct_gen_exp)(s))) + return ret; + + if (!(s->tmp = av_malloc(len*sizeof(*s->tmp)))) + return AVERROR(ENOMEM); + + TX_TAB(ff_tx_init_tabs)(len / sub_len); + + return 0; +} + +#define DECL_COMP_IMDCT(N) \ +static void TX_NAME(ff_tx_mdct_pfa_##N##xM_inv)(AVTXContext *s, void *_dst, \ + void *_src, ptrdiff_t stride) \ +{ \ + TXComplex fft##N##in[N]; \ + TXComplex *z = _dst, *exp = s->exp; \ + const TXSample *src = _src, *in1, *in2; \ + const int len4 = s->len >> 2; \ + const int m = s->sub->len; \ + const int *in_map = s->map, *out_map = in_map + N*m; \ + const int *sub_map = s->sub->map; \ + \ + stride /= sizeof(*src); /* To convert it from bytes */ \ + in1 = src; \ + in2 = src + ((N*m*2) - 1) * stride; \ + \ + for (int i = 0; i < m; i++) { \ + for (int j = 0; j < N; j++) { \ + const int k = in_map[i*N + j]; \ + TXComplex tmp = { in2[-k*stride], in1[k*stride] }; \ + CMUL3(fft##N##in[j], tmp, exp[k >> 1]); \ + } \ + fft##N(s->tmp + sub_map[i], fft##N##in, m); \ + } \ + \ + for (int i = 0; i < N; i++) \ + s->fn[0](&s->sub[0], s->tmp + m*i, s->tmp + m*i, sizeof(TXComplex)); \ + \ + for (int i = 0; i < len4; i++) { \ + const int i0 = len4 + i, i1 = len4 - i - 1; \ + const int s0 = out_map[i0], s1 = out_map[i1]; \ + TXComplex src1 = { s->tmp[s1].im, s->tmp[s1].re }; \ + TXComplex src0 = { s->tmp[s0].im, s->tmp[s0].re }; \ + \ + CMUL(z[i1].re, z[i0].im, src1.re, src1.im, exp[i1].im, exp[i1].re); \ + CMUL(z[i0].re, z[i1].im, src0.re, src0.im, exp[i0].im, exp[i0].re); \ + } \ +} \ + \ +static const FFTXCodelet TX_NAME(ff_tx_mdct_pfa_##N##xM_inv_def) = { \ + .name = TX_NAME_STR("mdct_pfa_" #N "xM_inv"), \ + .function = TX_NAME(ff_tx_mdct_pfa_##N##xM_inv), \ + .type = TX_TYPE(MDCT), \ + .flags = AV_TX_UNALIGNED | FF_TX_OUT_OF_PLACE | FF_TX_INVERSE_ONLY, \ + .factors = { N, TX_FACTOR_ANY }, \ + .min_len = N*2, \ + .max_len = TX_LEN_UNLIMITED, \ + .init = TX_NAME(ff_tx_mdct_pfa_init), \ + .cpu_flags = FF_TX_CPU_FLAGS_ALL, \ + .prio = FF_TX_PRIO_BASE, \ +}; + +DECL_COMP_IMDCT(3) +DECL_COMP_IMDCT(5) +DECL_COMP_IMDCT(7) +DECL_COMP_IMDCT(9) +DECL_COMP_IMDCT(15) + +#define DECL_COMP_MDCT(N) \ +static void TX_NAME(ff_tx_mdct_pfa_##N##xM_fwd)(AVTXContext *s, void *_dst, \ + void *_src, ptrdiff_t stride) \ +{ \ + TXComplex fft##N##in[N]; \ + TXSample *src = _src, *dst = _dst; \ + TXComplex *exp = s->exp, tmp; \ + const int m = s->sub->len; \ + const int len4 = N*m; \ + const int len3 = len4 * 3; \ + const int len8 = s->len >> 2; \ + const int *in_map = s->map, *out_map = in_map + N*m; \ + const int *sub_map = s->sub->map; \ + \ + stride /= sizeof(*dst); \ + \ + for (int i = 0; i < m; i++) { /* Folding and pre-reindexing */ \ + for (int j = 0; j < N; j++) { \ + const int k = in_map[i*N + j]; \ + if (k < len4) { \ + tmp.re = FOLD(-src[ len4 + k], src[1*len4 - 1 - k]); \ + tmp.im = FOLD(-src[ len3 + k], -src[1*len3 - 1 - k]); \ + } else { \ + tmp.re = FOLD(-src[ len4 + k], -src[5*len4 - 1 - k]); \ + tmp.im = FOLD( src[-len4 + k], -src[1*len3 - 1 - k]); \ + } \ + CMUL(fft##N##in[j].im, fft##N##in[j].re, tmp.re, tmp.im, \ + exp[k >> 1].re, exp[k >> 1].im); \ + } \ + fft##N(s->tmp + sub_map[i], fft##N##in, m); \ + } \ + \ + for (int i = 0; i < N; i++) \ + s->fn[0](&s->sub[0], s->tmp + m*i, s->tmp + m*i, sizeof(TXComplex)); \ + \ + for (int i = 0; i < len8; i++) { \ + const int i0 = len8 + i, i1 = len8 - i - 1; \ + const int s0 = out_map[i0], s1 = out_map[i1]; \ + TXComplex src1 = { s->tmp[s1].re, s->tmp[s1].im }; \ + TXComplex src0 = { s->tmp[s0].re, s->tmp[s0].im }; \ + \ + CMUL(dst[2*i1*stride + stride], dst[2*i0*stride], src0.re, src0.im, \ + exp[i0].im, exp[i0].re); \ + CMUL(dst[2*i0*stride + stride], dst[2*i1*stride], src1.re, src1.im, \ + exp[i1].im, exp[i1].re); \ + } \ +} \ + \ +static const FFTXCodelet TX_NAME(ff_tx_mdct_pfa_##N##xM_fwd_def) = { \ + .name = TX_NAME_STR("mdct_pfa_" #N "xM_fwd"), \ + .function = TX_NAME(ff_tx_mdct_pfa_##N##xM_fwd), \ + .type = TX_TYPE(MDCT), \ + .flags = AV_TX_UNALIGNED | FF_TX_OUT_OF_PLACE | FF_TX_FORWARD_ONLY, \ + .factors = { N, TX_FACTOR_ANY }, \ + .min_len = N*2, \ + .max_len = TX_LEN_UNLIMITED, \ + .init = TX_NAME(ff_tx_mdct_pfa_init), \ + .cpu_flags = FF_TX_CPU_FLAGS_ALL, \ + .prio = FF_TX_PRIO_BASE, \ +}; + +DECL_COMP_MDCT(3) +DECL_COMP_MDCT(5) +DECL_COMP_MDCT(7) +DECL_COMP_MDCT(9) +DECL_COMP_MDCT(15) + +static av_cold int TX_NAME(ff_tx_rdft_init)(AVTXContext *s, + const FFTXCodelet *cd, + uint64_t flags, + FFTXCodeletOptions *opts, + int len, int inv, + const void *scale) +{ + int ret; + double f, m; + TXSample *tab; + + s->scale_d = *((SCALE_TYPE *)scale); + s->scale_f = s->scale_d; + + if ((ret = ff_tx_init_subtx(s, TX_TYPE(FFT), flags, NULL, len >> 1, inv, scale))) + return ret; + + if (!(s->exp = av_mallocz((8 + (len >> 2) - 1)*sizeof(*s->exp)))) + return AVERROR(ENOMEM); + + tab = (TXSample *)s->exp; + + f = 2*M_PI/len; + + m = (inv ? 2*s->scale_d : s->scale_d); + + *tab++ = RESCALE((inv ? 0.5 : 1.0) * m); + *tab++ = RESCALE(inv ? 0.5*m : 1.0); + *tab++ = RESCALE( m); + *tab++ = RESCALE(-m); + + *tab++ = RESCALE( (0.5 - 0.0) * m); + *tab++ = RESCALE( (0.0 - 0.5) * m); + *tab++ = RESCALE( (0.5 - inv) * m); + *tab++ = RESCALE(-(0.5 - inv) * m); + + for (int i = 0; i < len >> 2; i++) + *tab++ = RESCALE(cos(i*f)); + for (int i = len >> 2; i >= 0; i--) + *tab++ = RESCALE(cos(i*f) * (inv ? +1.0 : -1.0)); + + return 0; +} + +#define DECL_RDFT(name, inv) \ +static void TX_NAME(ff_tx_rdft_ ##name)(AVTXContext *s, void *_dst, \ + void *_src, ptrdiff_t stride) \ +{ \ + const int len2 = s->len >> 1; \ + const int len4 = s->len >> 2; \ + const TXSample *fact = (void *)s->exp; \ + const TXSample *tcos = fact + 8; \ + const TXSample *tsin = tcos + len4; \ + TXComplex *data = inv ? _src : _dst; \ + TXComplex t[3]; \ + \ + if (!inv) \ + s->fn[0](&s->sub[0], data, _src, sizeof(TXComplex)); \ + else \ + data[0].im = data[len2].re; \ + \ + /* The DC value's both components are real, but we need to change them \ + * into complex values. Also, the middle of the array is special-cased. \ + * These operations can be done before or after the loop. */ \ + t[0].re = data[0].re; \ + data[0].re = t[0].re + data[0].im; \ + data[0].im = t[0].re - data[0].im; \ + data[ 0].re = MULT(fact[0], data[ 0].re); \ + data[ 0].im = MULT(fact[1], data[ 0].im); \ + data[len4].re = MULT(fact[2], data[len4].re); \ + data[len4].im = MULT(fact[3], data[len4].im); \ + \ + for (int i = 1; i < len4; i++) { \ + /* Separate even and odd FFTs */ \ + t[0].re = MULT(fact[4], (data[i].re + data[len2 - i].re)); \ + t[0].im = MULT(fact[5], (data[i].im - data[len2 - i].im)); \ + t[1].re = MULT(fact[6], (data[i].im + data[len2 - i].im)); \ + t[1].im = MULT(fact[7], (data[i].re - data[len2 - i].re)); \ + \ + /* Apply twiddle factors to the odd FFT and add to the even FFT */ \ + CMUL(t[2].re, t[2].im, t[1].re, t[1].im, tcos[i], tsin[i]); \ + \ + data[ i].re = t[0].re + t[2].re; \ + data[ i].im = t[2].im - t[0].im; \ + data[len2 - i].re = t[0].re - t[2].re; \ + data[len2 - i].im = t[2].im + t[0].im; \ + } \ + \ + if (inv) { \ + s->fn[0](&s->sub[0], _dst, data, sizeof(TXComplex)); \ + } else { \ + /* Move [0].im to the last position, as convention requires */ \ + data[len2].re = data[0].im; \ + data[ 0].im = 0; \ + } \ +} + +DECL_RDFT(r2c, 0) +DECL_RDFT(c2r, 1) + +static const FFTXCodelet TX_NAME(ff_tx_rdft_r2c_def) = { + .name = TX_NAME_STR("rdft_r2c"), + .function = TX_NAME(ff_tx_rdft_r2c), + .type = TX_TYPE(RDFT), + .flags = AV_TX_UNALIGNED | AV_TX_INPLACE | + FF_TX_OUT_OF_PLACE | FF_TX_FORWARD_ONLY, + .factors = { 2, TX_FACTOR_ANY }, + .min_len = 2, + .max_len = TX_LEN_UNLIMITED, + .init = TX_NAME(ff_tx_rdft_init), + .cpu_flags = FF_TX_CPU_FLAGS_ALL, + .prio = FF_TX_PRIO_BASE, +}; + +static const FFTXCodelet TX_NAME(ff_tx_rdft_c2r_def) = { + .name = TX_NAME_STR("rdft_c2r"), + .function = TX_NAME(ff_tx_rdft_c2r), + .type = TX_TYPE(RDFT), + .flags = AV_TX_UNALIGNED | AV_TX_INPLACE | + FF_TX_OUT_OF_PLACE | FF_TX_INVERSE_ONLY, + .factors = { 2, TX_FACTOR_ANY }, + .min_len = 2, + .max_len = TX_LEN_UNLIMITED, + .init = TX_NAME(ff_tx_rdft_init), + .cpu_flags = FF_TX_CPU_FLAGS_ALL, + .prio = FF_TX_PRIO_BASE, +}; + +int TX_TAB(ff_tx_mdct_gen_exp)(AVTXContext *s) +{ + int len4 = s->len >> 1; + double scale = s->scale_d; const double theta = (scale < 0 ? len4 : 0) + 1.0/8.0; - if (!(s->exptab = av_malloc_array(len4, sizeof(*s->exptab)))) + if (!(s->exp = av_malloc_array(len4, sizeof(*s->exp)))) return AVERROR(ENOMEM); scale = sqrt(fabs(scale)); for (int i = 0; i < len4; i++) { const double alpha = M_PI_2 * (i + theta) / len4; - s->exptab[i].re = RESCALE(cos(alpha) * scale); - s->exptab[i].im = RESCALE(sin(alpha) * scale); + s->exp[i].re = RESCALE(cos(alpha) * scale); + s->exp[i].im = RESCALE(sin(alpha) * scale); } return 0; } -int TX_NAME(ff_tx_init_mdct_fft)(AVTXContext *s, av_tx_fn *tx, - enum AVTXType type, int inv, int len, - const void *scale, uint64_t flags) -{ - const int is_mdct = ff_tx_type_is_mdct(type); - int err, l, n = 1, m = 1, max_ptwo = 1 << (FF_ARRAY_ELEMS(fft_dispatch) - 1); +const FFTXCodelet * const TX_NAME(ff_tx_codelet_list)[] = { + /* Split-Radix codelets */ + &TX_NAME(ff_tx_fft2_ns_def), + &TX_NAME(ff_tx_fft4_ns_def), + &TX_NAME(ff_tx_fft8_ns_def), + &TX_NAME(ff_tx_fft16_ns_def), + &TX_NAME(ff_tx_fft32_ns_def), + &TX_NAME(ff_tx_fft64_ns_def), + &TX_NAME(ff_tx_fft128_ns_def), + &TX_NAME(ff_tx_fft256_ns_def), + &TX_NAME(ff_tx_fft512_ns_def), + &TX_NAME(ff_tx_fft1024_ns_def), + &TX_NAME(ff_tx_fft2048_ns_def), + &TX_NAME(ff_tx_fft4096_ns_def), + &TX_NAME(ff_tx_fft8192_ns_def), + &TX_NAME(ff_tx_fft16384_ns_def), + &TX_NAME(ff_tx_fft32768_ns_def), + &TX_NAME(ff_tx_fft65536_ns_def), + &TX_NAME(ff_tx_fft131072_ns_def), - if (is_mdct) - len >>= 1; + /* Standalone transforms */ + &TX_NAME(ff_tx_fft_sr_def), + &TX_NAME(ff_tx_fft_sr_inplace_def), + &TX_NAME(ff_tx_fft_pfa_3xM_def), + &TX_NAME(ff_tx_fft_pfa_5xM_def), + &TX_NAME(ff_tx_fft_pfa_7xM_def), + &TX_NAME(ff_tx_fft_pfa_9xM_def), + &TX_NAME(ff_tx_fft_pfa_15xM_def), + &TX_NAME(ff_tx_fft_naive_def), + &TX_NAME(ff_tx_mdct_sr_fwd_def), + &TX_NAME(ff_tx_mdct_sr_inv_def), + &TX_NAME(ff_tx_mdct_pfa_3xM_fwd_def), + &TX_NAME(ff_tx_mdct_pfa_5xM_fwd_def), + &TX_NAME(ff_tx_mdct_pfa_7xM_fwd_def), + &TX_NAME(ff_tx_mdct_pfa_9xM_fwd_def), + &TX_NAME(ff_tx_mdct_pfa_15xM_fwd_def), + &TX_NAME(ff_tx_mdct_pfa_3xM_inv_def), + &TX_NAME(ff_tx_mdct_pfa_5xM_inv_def), + &TX_NAME(ff_tx_mdct_pfa_7xM_inv_def), + &TX_NAME(ff_tx_mdct_pfa_9xM_inv_def), + &TX_NAME(ff_tx_mdct_pfa_15xM_inv_def), + &TX_NAME(ff_tx_mdct_naive_fwd_def), + &TX_NAME(ff_tx_mdct_naive_inv_def), + &TX_NAME(ff_tx_mdct_inv_full_def), + &TX_NAME(ff_tx_rdft_r2c_def), + &TX_NAME(ff_tx_rdft_c2r_def), - l = len; - -#define CHECK_FACTOR(DST, FACTOR, SRC) \ - if (DST == 1 && !(SRC % FACTOR)) { \ - DST = FACTOR; \ - SRC /= FACTOR; \ - } - CHECK_FACTOR(n, 15, len) - CHECK_FACTOR(n, 9, len) - CHECK_FACTOR(n, 7, len) - CHECK_FACTOR(n, 5, len) - CHECK_FACTOR(n, 3, len) -#undef CHECK_FACTOR - - /* len must be a power of two now */ - if (!(len & (len - 1)) && len >= 2 && len <= max_ptwo) { - m = len; - len = 1; - } - - s->n = n; - s->m = m; - s->inv = inv; - s->type = type; - s->flags = flags; - - /* If we weren't able to split the length into factors we can handle, - * resort to using the naive and slow FT. This also filters out - * direct 3, 5 and 15 transforms as they're too niche. */ - if (len > 1 || m == 1) { - if (is_mdct && (l & 1)) /* Odd (i)MDCTs are not supported yet */ - return AVERROR(ENOSYS); - if (flags & AV_TX_INPLACE) /* Neither are in-place naive transforms */ - return AVERROR(ENOSYS); - s->n = l; - s->m = 1; - *tx = naive_fft; - if (is_mdct) { - s->scale = *((SCALE_TYPE *)scale); - *tx = inv ? naive_imdct : naive_mdct; - if (inv && (flags & AV_TX_FULL_IMDCT)) { - s->top_tx = *tx; - *tx = full_imdct_wrapper_fn; - } - } - return 0; - } - - if (n > 1 && m > 1) { /* 2D transform case */ - if ((err = ff_tx_gen_compound_mapping(s))) - return err; - if (!(s->tmp = av_malloc(n*m*sizeof(*s->tmp)))) - return AVERROR(ENOMEM); - if (!(m & (m - 1))) { - *tx = n == 3 ? compound_fft_3xM : - n == 5 ? compound_fft_5xM : - n == 7 ? compound_fft_7xM : - n == 9 ? compound_fft_9xM : - compound_fft_15xM; - if (is_mdct) - *tx = n == 3 ? inv ? compound_imdct_3xM : compound_mdct_3xM : - n == 5 ? inv ? compound_imdct_5xM : compound_mdct_5xM : - n == 7 ? inv ? compound_imdct_7xM : compound_mdct_7xM : - n == 9 ? inv ? compound_imdct_9xM : compound_mdct_9xM : - inv ? compound_imdct_15xM : compound_mdct_15xM; - } - } else { /* Direct transform case */ - *tx = split_radix_fft; - if (is_mdct) - *tx = inv ? monolithic_imdct : monolithic_mdct; - } - - if (n == 3 || n == 5 || n == 15) - init_cos_tabs(0); - else if (n == 7) - init_cos_tabs(1); - else if (n == 9) - init_cos_tabs(2); - - if (m != 1 && !(m & (m - 1))) { - if ((err = ff_tx_gen_ptwo_revtab(s, n == 1 && !is_mdct && !(flags & AV_TX_INPLACE)))) - return err; - if (flags & AV_TX_INPLACE) { - if (is_mdct) /* In-place MDCTs are not supported yet */ - return AVERROR(ENOSYS); - if ((err = ff_tx_gen_ptwo_inplace_revtab_idx(s, s->revtab_c))) - return err; - } - for (int i = 4; i <= av_log2(m); i++) - init_cos_tabs(i); - } - - if (is_mdct) { - if (inv && (flags & AV_TX_FULL_IMDCT)) { - s->top_tx = *tx; - *tx = full_imdct_wrapper_fn; - } - return gen_mdct_exptab(s, n*m, *((SCALE_TYPE *)scale)); - } - - return 0; -} + NULL, +}; diff --git a/libavutil/utils.c b/libavutil/utils.c index ea9b5097b..94d247bbe 100644 --- a/libavutil/utils.c +++ b/libavutil/utils.c @@ -19,55 +19,12 @@ #include "config.h" #include "avutil.h" #include "avassert.h" -#include "samplefmt.h" -#include "internal.h" /** * @file * various utility functions */ -#include "libavutil/ffversion.h" -const char av_util_ffversion[] = "FFmpeg version " FFMPEG_VERSION; - -const char *av_version_info(void) -{ - return FFMPEG_VERSION; -} - -unsigned avutil_version(void) -{ - av_assert0(AV_SAMPLE_FMT_DBLP == 9); - av_assert0(AVMEDIA_TYPE_ATTACHMENT == 4); - av_assert0(AV_PICTURE_TYPE_BI == 7); - av_assert0(LIBAVUTIL_VERSION_MICRO >= 100); - av_assert0(HAVE_MMX2 == HAVE_MMXEXT); - - av_assert0(((size_t)-1) > 0); // C guarantees this but if false on a platform we care about revert at least b284e1ffe343d6697fb950d1ee517bafda8a9844 - - if (av_sat_dadd32(1, 2) != 5) { - av_log(NULL, AV_LOG_FATAL, "Libavutil has been built with a broken binutils, please upgrade binutils and rebuild\n"); - abort(); - } - - if (llrint(1LL<<60) != 1LL<<60) { - av_log(NULL, AV_LOG_ERROR, "Libavutil has been linked to a broken llrint()\n"); - } - - return LIBAVUTIL_VERSION_INT; -} - -const char *avutil_configuration(void) -{ - return FFMPEG_CONFIGURATION; -} - -const char *avutil_license(void) -{ -#define LICENSE_PREFIX "libavutil license: " - return &LICENSE_PREFIX FFMPEG_LICENSE[sizeof(LICENSE_PREFIX) - 1]; -} - const char *av_get_media_type_string(enum AVMediaType media_type) { switch (media_type) { diff --git a/libavutil/uuid.c b/libavutil/uuid.c new file mode 100644 index 000000000..062e28736 --- /dev/null +++ b/libavutil/uuid.c @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2022 Pierre-Anthony Lemieux + * Zane van Iperen + * + * 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 + */ + +/* + * Copyright (C) 1996, 1997 Theodore Ts'o. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + */ + +/** + * @file + * UUID parsing and serialization utilities. + * The library treat the UUID as an opaque sequence of 16 unsigned bytes, + * i.e. ignoring the internal layout of the UUID, which depends on the type + * of the UUID. + * + * @author Pierre-Anthony Lemieux + * @author Zane van Iperen + */ + +#include "uuid.h" +#include "error.h" +#include "avstring.h" + +int av_uuid_parse(const char *in, AVUUID uu) +{ + if (strlen(in) != 36) + return AVERROR(EINVAL); + + return av_uuid_parse_range(in, in + 36, uu); +} + +static int xdigit_to_int(char c) +{ + c = av_tolower(c); + + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + + if (c >= '0' && c <= '9') + return c - '0'; + + return -1; +} + +int av_uuid_parse_range(const char *in_start, const char *in_end, AVUUID uu) +{ + int i; + const char *cp; + + if ((in_end - in_start) != 36) + return AVERROR(EINVAL); + + for (i = 0, cp = in_start; i < 16; i++) { + int hi; + int lo; + + if (i == 4 || i == 6 || i == 8 || i == 10) + cp++; + + hi = xdigit_to_int(*cp++); + lo = xdigit_to_int(*cp++); + + if (hi == -1 || lo == -1) + return AVERROR(EINVAL); + + uu[i] = (hi << 4) + lo; + } + + return 0; +} + +static const char hexdigits_lower[16] = "0123456789abcdef"; + +void av_uuid_unparse(const AVUUID uuid, char *out) +{ + char *p = out; + + for (int i = 0; i < 16; i++) { + uint8_t tmp; + + if (i == 4 || i == 6 || i == 8 || i == 10) + *p++ = '-'; + + tmp = uuid[i]; + *p++ = hexdigits_lower[tmp >> 4]; + *p++ = hexdigits_lower[tmp & 15]; + } + + *p = '\0'; +} + +int av_uuid_urn_parse(const char *in, AVUUID uu) +{ + if (av_stristr(in, "urn:uuid:") != in) + return AVERROR(EINVAL); + + return av_uuid_parse(in + 9, uu); +} diff --git a/libavutil/uuid.h b/libavutil/uuid.h new file mode 100644 index 000000000..4b5088911 --- /dev/null +++ b/libavutil/uuid.h @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2022 Pierre-Anthony Lemieux + * Zane van Iperen + * + * 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 + * UUID parsing and serialization utilities. + * The library treats the UUID as an opaque sequence of 16 unsigned bytes, + * i.e. ignoring the internal layout of the UUID, which depends on the type + * of the UUID. + * + * @author Pierre-Anthony Lemieux + * @author Zane van Iperen + */ + +#ifndef AVUTIL_UUID_H +#define AVUTIL_UUID_H + +#include +#include + +#define AV_PRI_UUID \ + "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-" \ + "%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx" + +#define AV_PRI_URN_UUID \ + "urn:uuid:%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-" \ + "%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx" + +/* AV_UUID_ARG() is used together with AV_PRI_UUID() or AV_PRI_URN_UUID + * to print UUIDs, e.g. + * av_log(NULL, AV_LOG_DEBUG, "UUID: " AV_PRI_UUID, AV_UUID_ARG(uuid)); + */ +#define AV_UUID_ARG(x) \ + (x)[ 0], (x)[ 1], (x)[ 2], (x)[ 3], \ + (x)[ 4], (x)[ 5], (x)[ 6], (x)[ 7], \ + (x)[ 8], (x)[ 9], (x)[10], (x)[11], \ + (x)[12], (x)[13], (x)[14], (x)[15] + +#define AV_UUID_LEN 16 + +/* Binary representation of a UUID */ +typedef uint8_t AVUUID[AV_UUID_LEN]; + +/** + * Parses a string representation of a UUID formatted according to IETF RFC 4122 + * into an AVUUID. The parsing is case-insensitive. The string must be 37 + * characters long, including the terminating NUL character. + * + * Example string representation: "2fceebd0-7017-433d-bafb-d073a7116696" + * + * @param[in] in String representation of a UUID, + * e.g. 2fceebd0-7017-433d-bafb-d073a7116696 + * @param[out] uu AVUUID + * @return A non-zero value in case of an error. + */ +int av_uuid_parse(const char *in, AVUUID uu); + +/** + * Parses a URN representation of a UUID, as specified at IETF RFC 4122, + * into an AVUUID. The parsing is case-insensitive. The string must be 46 + * characters long, including the terminating NUL character. + * + * Example string representation: "urn:uuid:2fceebd0-7017-433d-bafb-d073a7116696" + * + * @param[in] in URN UUID + * @param[out] uu AVUUID + * @return A non-zero value in case of an error. + */ +int av_uuid_urn_parse(const char *in, AVUUID uu); + +/** + * Parses a string representation of a UUID formatted according to IETF RFC 4122 + * into an AVUUID. The parsing is case-insensitive. + * + * @param[in] in_start Pointer to the first character of the string representation + * @param[in] in_end Pointer to the character after the last character of the + * string representation. That memory location is never + * accessed. It is an error if `in_end - in_start != 36`. + * @param[out] uu AVUUID + * @return A non-zero value in case of an error. + */ +int av_uuid_parse_range(const char *in_start, const char *in_end, AVUUID uu); + +/** + * Serializes a AVUUID into a string representation according to IETF RFC 4122. + * The string is lowercase and always 37 characters long, including the + * terminating NUL character. + * + * @param[in] uu AVUUID + * @param[out] out Pointer to an array of no less than 37 characters. + * @return A non-zero value in case of an error. + */ +void av_uuid_unparse(const AVUUID uu, char *out); + +/** + * Compares two UUIDs for equality. + * + * @param[in] uu1 AVUUID + * @param[in] uu2 AVUUID + * @return Nonzero if uu1 and uu2 are identical, 0 otherwise + */ +static inline int av_uuid_equal(const AVUUID uu1, const AVUUID uu2) +{ + return memcmp(uu1, uu2, AV_UUID_LEN) == 0; +} + +/** + * Copies the bytes of src into dest. + * + * @param[out] dest AVUUID + * @param[in] src AVUUID + */ +static inline void av_uuid_copy(AVUUID dest, const AVUUID src) +{ + memcpy(dest, src, AV_UUID_LEN); +} + +/** + * Sets a UUID to the nil UUID, i.e. a UUID with have all + * its 128 bits set to zero. + * + * @param[in,out] uu UUID to be set to the nil UUID + */ +static inline void av_uuid_nil(AVUUID uu) +{ + memset(uu, 0, AV_UUID_LEN); +} + +#endif /* AVUTIL_UUID_H */ diff --git a/libavutil/version.c b/libavutil/version.c new file mode 100644 index 000000000..b0f4f94a7 --- /dev/null +++ b/libavutil/version.c @@ -0,0 +1,71 @@ +/* + * Version functions. + * + * 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 "avutil.h" +#include "common.h" +#include "libm.h" +#include "log.h" +#include "samplefmt.h" +#include "version.h" + +#include "libavutil/ffversion.h" +const char av_util_ffversion[] = "FFmpeg version " FFMPEG_VERSION; + +const char *av_version_info(void) +{ + return FFMPEG_VERSION; +} + +unsigned avutil_version(void) +{ + av_assert0(AV_SAMPLE_FMT_DBLP == 9); + av_assert0(AVMEDIA_TYPE_ATTACHMENT == 4); + av_assert0(AV_PICTURE_TYPE_BI == 7); + av_assert0(LIBAVUTIL_VERSION_MICRO >= 100); + av_assert0(HAVE_MMX2 == HAVE_MMXEXT); + + av_assert0(((size_t)-1) > 0); // C guarantees this but if false on a platform we care about revert at least b284e1ffe343d6697fb950d1ee517bafda8a9844 + + if (av_sat_dadd32(1, 2) != 5) { + av_log(NULL, AV_LOG_FATAL, "Libavutil has been built with a broken binutils, please upgrade binutils and rebuild\n"); + abort(); + } + + if (llrint(1LL<<60) != 1LL<<60) { + av_log(NULL, AV_LOG_ERROR, "Libavutil has been linked to a broken llrint()\n"); + } + + return LIBAVUTIL_VERSION_INT; +} + +const char *avutil_configuration(void) +{ + return FFMPEG_CONFIGURATION; +} + +const char *avutil_license(void) +{ +#define LICENSE_PREFIX "libavutil license: " + return &LICENSE_PREFIX FFMPEG_LICENSE[sizeof(LICENSE_PREFIX) - 1]; +} diff --git a/libavutil/version.h b/libavutil/version.h index 58c617975..87178e9e9 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 57 -#define LIBAVUTIL_VERSION_MINOR 17 +#define LIBAVUTIL_VERSION_MINOR 28 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ @@ -109,6 +109,11 @@ #define FF_API_DECLARE_ALIGNED (LIBAVUTIL_VERSION_MAJOR < 58) #define FF_API_COLORSPACE_NAME (LIBAVUTIL_VERSION_MAJOR < 58) #define FF_API_AV_MALLOCZ_ARRAY (LIBAVUTIL_VERSION_MAJOR < 58) +#define FF_API_FIFO_PEEK2 (LIBAVUTIL_VERSION_MAJOR < 58) +#define FF_API_FIFO_OLD_API (LIBAVUTIL_VERSION_MAJOR < 58) +#define FF_API_XVMC (LIBAVUTIL_VERSION_MAJOR < 58) +#define FF_API_OLD_CHANNEL_LAYOUT (LIBAVUTIL_VERSION_MAJOR < 58) +#define FF_API_AV_FOPEN_UTF8 (LIBAVUTIL_VERSION_MAJOR < 58) /** * @} diff --git a/libavutil/version_major.h b/libavutil/version_major.h new file mode 100644 index 000000000..e4db2e34d --- /dev/null +++ b/libavutil/version_major.h @@ -0,0 +1,25 @@ +/* + * 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_VERSION_MAJOR_H +#define AVUTIL_VERSION_MAJOR_H + +/* This file is intentionally empty; it's only kept to fulfill make + * dependencies for ffbuild/libversion.sh. It is not installed. */ + +#endif /* AVUTIL_VERSION_MAJOR_H */ diff --git a/libavutil/video_enc_params.c b/libavutil/video_enc_params.c index 7d903af38..54bfed0ed 100644 --- a/libavutil/video_enc_params.c +++ b/libavutil/video_enc_params.c @@ -16,12 +16,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include #include #include #include "buffer.h" -#include "common.h" #include "frame.h" #include "mem.h" #include "video_enc_params.h" diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c index 00df08b55..403f0b1f2 100644 --- a/libavutil/vulkan.c +++ b/libavutil/vulkan.c @@ -829,11 +829,12 @@ void ff_vk_print_shader(void *ctx, FFVkSPIRVShader *shd, int prio) int line = 0; const char *p = shd->src.str; const char *start = p; + const size_t len = strlen(p); AVBPrint buf; av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); - for (int i = 0; i < strlen(p); i++) { + for (int i = 0; i < len; i++) { if (p[i] == '\n') { av_bprintf(&buf, "%i\t", ++line); av_bprint_append_data(&buf, start, &p[i] - start + 1); diff --git a/libavutil/vulkan_functions.h b/libavutil/vulkan_functions.h index 96922d728..d15a5d9a4 100644 --- a/libavutil/vulkan_functions.h +++ b/libavutil/vulkan_functions.h @@ -38,7 +38,7 @@ typedef enum FFVulkanExtensions { FF_VK_EXT_EXTERNAL_WIN32_SEM = 1ULL << 7, /* VK_KHR_external_semaphore_win32 */ #endif - FF_VK_EXT_NO_FLAG = 1ULL << 63, + FF_VK_EXT_NO_FLAG = 1ULL << 31, } FFVulkanExtensions; /* Macro containing every function that we utilize in our codebase */ diff --git a/libavutil/wchar_filename.h b/libavutil/wchar_filename.h index 90f082452..9a04a069f 100644 --- a/libavutil/wchar_filename.h +++ b/libavutil/wchar_filename.h @@ -20,6 +20,8 @@ #define AVUTIL_WCHAR_FILENAME_H #ifdef _WIN32 + +#define WIN32_LEAN_AND_MEAN #include #include "mem.h" @@ -40,6 +42,237 @@ static inline int utf8towchar(const char *filename_utf8, wchar_t **filename_w) MultiByteToWideChar(CP_UTF8, 0, filename_utf8, -1, *filename_w, num_chars); return 0; } + +av_warn_unused_result +static inline int wchartocp(unsigned int code_page, const wchar_t *filename_w, + char **filename) +{ + DWORD flags = code_page == CP_UTF8 ? WC_ERR_INVALID_CHARS : 0; + int num_chars = WideCharToMultiByte(code_page, flags, filename_w, -1, + NULL, 0, NULL, NULL); + if (num_chars <= 0) { + *filename = NULL; + return 0; + } + *filename = (char*)av_malloc_array(num_chars, sizeof *filename); + if (!*filename) { + errno = ENOMEM; + return -1; + } + WideCharToMultiByte(code_page, flags, filename_w, -1, + *filename, num_chars, NULL, NULL); + return 0; +} + +av_warn_unused_result +static inline int wchartoutf8(const wchar_t *filename_w, char **filename) +{ + return wchartocp(CP_UTF8, filename_w, filename); +} + +av_warn_unused_result +static inline int wchartoansi(const wchar_t *filename_w, char **filename) +{ + return wchartocp(CP_ACP, filename_w, filename); +} + +av_warn_unused_result +static inline int utf8toansi(const char *filename_utf8, char **filename) +{ + wchar_t *filename_w = NULL; + int ret = -1; + if (utf8towchar(filename_utf8, &filename_w)) + return -1; + + if (!filename_w) { + *filename = NULL; + return 0; + } + + ret = wchartoansi(filename_w, filename); + av_free(filename_w); + return ret; +} + +/** + * Checks for extended path prefixes for which normalization needs to be skipped. + * see .NET6: PathInternal.IsExtended() + * https://github.com/dotnet/runtime/blob/9260c249140ef90b4299d0fe1aa3037e25228518/src/libraries/Common/src/System/IO/PathInternal.Windows.cs#L165 + */ +static inline int path_is_extended(const wchar_t *path) +{ + if (path[0] == L'\\' && (path[1] == L'\\' || path[1] == L'?') && path[2] == L'?' && path[3] == L'\\') + return 1; + + return 0; +} + +/** + * Checks for a device path prefix. + * see .NET6: PathInternal.IsDevice() + * we don't check forward slashes and extended paths (as already done) + * https://github.com/dotnet/runtime/blob/9260c249140ef90b4299d0fe1aa3037e25228518/src/libraries/Common/src/System/IO/PathInternal.Windows.cs#L132 + */ +static inline int path_is_device_path(const wchar_t *path) +{ + if (path[0] == L'\\' && path[1] == L'\\' && path[2] == L'.' && path[3] == L'\\') + return 1; + + return 0; +} + +/** + * Performs path normalization by calling GetFullPathNameW(). + * see .NET6: PathHelper.GetFullPathName() + * https://github.com/dotnet/runtime/blob/2a99e18eedabcf1add064c099da59d9301ce45e0/src/libraries/System.Private.CoreLib/src/System/IO/PathHelper.Windows.cs#L70 + */ +static inline int get_full_path_name(wchar_t **ppath_w) +{ + int num_chars; + wchar_t *temp_w; + + num_chars = GetFullPathNameW(*ppath_w, 0, NULL, NULL); + if (num_chars <= 0) { + errno = EINVAL; + return -1; + } + + temp_w = (wchar_t *)av_calloc(num_chars, sizeof(wchar_t)); + if (!temp_w) { + errno = ENOMEM; + return -1; + } + + num_chars = GetFullPathNameW(*ppath_w, num_chars, temp_w, NULL); + if (num_chars <= 0) { + av_free(temp_w); + errno = EINVAL; + return -1; + } + + av_freep(ppath_w); + *ppath_w = temp_w; + + return 0; +} + +/** + * Normalizes a Windows file or folder path. + * Expansion of short paths (with 8.3 path components) is currently omitted + * as it is not required for accessing long paths. + * see .NET6: PathHelper.Normalize() + * https://github.com/dotnet/runtime/blob/2a99e18eedabcf1add064c099da59d9301ce45e0/src/libraries/System.Private.CoreLib/src/System/IO/PathHelper.Windows.cs#L25 + */ +static inline int path_normalize(wchar_t **ppath_w) +{ + int ret; + + if ((ret = get_full_path_name(ppath_w)) < 0) + return ret; + + /* What .NET does at this point is to call PathHelper.TryExpandShortFileName() + * in case the path contains a '~' character. + * We don't need to do this as we don't need to normalize the file name + * for presentation, and the extended path prefix works with 8.3 path + * components as well + */ + return 0; +} + +/** + * Adds an extended path or UNC prefix to longs paths or paths ending + * with a space or a dot. (' ' or '.'). + * This function expects that the path has been normalized before by + * calling path_normalize() and it doesn't check whether the path is + * actually long (> MAX_PATH). + * see .NET6: PathInternal.EnsureExtendedPrefix() + * https://github.com/dotnet/runtime/blob/9260c249140ef90b4299d0fe1aa3037e25228518/src/libraries/Common/src/System/IO/PathInternal.Windows.cs#L107 + */ +static inline int add_extended_prefix(wchar_t **ppath_w) +{ + const wchar_t *unc_prefix = L"\\\\?\\UNC\\"; + const wchar_t *extended_path_prefix = L"\\\\?\\"; + const wchar_t *path_w = *ppath_w; + const size_t len = wcslen(path_w); + wchar_t *temp_w; + + /* We're skipping the check IsPartiallyQualified() because + * we expect to have called GetFullPathNameW() already. */ + if (len < 2 || path_is_extended(*ppath_w) || path_is_device_path(*ppath_w)) { + return 0; + } + + if (path_w[0] == L'\\' && path_w[1] == L'\\') { + /* unc_prefix length is 8 plus 1 for terminating zeros, + * we subtract 2 for the leading '\\' of the original path */ + temp_w = (wchar_t *)av_calloc(len - 2 + 8 + 1, sizeof(wchar_t)); + if (!temp_w) { + errno = ENOMEM; + return -1; + } + wcscpy(temp_w, unc_prefix); + wcscat(temp_w, path_w + 2); + } else { + // The length of extended_path_prefix is 4 plus 1 for terminating zeros + temp_w = (wchar_t *)av_calloc(len + 4 + 1, sizeof(wchar_t)); + if (!temp_w) { + errno = ENOMEM; + return -1; + } + wcscpy(temp_w, extended_path_prefix); + wcscat(temp_w, path_w); + } + + av_freep(ppath_w); + *ppath_w = temp_w; + + return 0; +} + +/** + * Converts a file or folder path to wchar_t for use with Windows file + * APIs. Paths with extended path prefix (either '\\?\' or \??\') are + * left unchanged. + * All other paths are normalized and converted to absolute paths. + * Longs paths (>= MAX_PATH) are prefixed with the extended path or extended + * UNC path prefix. + * see .NET6: Path.GetFullPath() and Path.GetFullPathInternal() + * https://github.com/dotnet/runtime/blob/2a99e18eedabcf1add064c099da59d9301ce45e0/src/libraries/System.Private.CoreLib/src/System/IO/Path.Windows.cs#L126 + */ +static inline int get_extended_win32_path(const char *path, wchar_t **ppath_w) +{ + int ret; + size_t len; + + if ((ret = utf8towchar(path, ppath_w)) < 0) + return ret; + + if (path_is_extended(*ppath_w)) { + /* Paths prefixed with '\\?\' or \??\' are considered normalized by definition. + * Windows doesn't normalize those paths and neither should we. + */ + return 0; + } + + if ((ret = path_normalize(ppath_w)) < 0) { + av_freep(ppath_w); + return ret; + } + + /* see .NET6: PathInternal.EnsureExtendedPrefixIfNeeded() + * https://github.com/dotnet/runtime/blob/9260c249140ef90b4299d0fe1aa3037e25228518/src/libraries/Common/src/System/IO/PathInternal.Windows.cs#L92 + */ + len = wcslen(*ppath_w); + if (len >= MAX_PATH) { + if ((ret = add_extended_prefix(ppath_w)) < 0) { + av_freep(ppath_w); + return ret; + } + } + + return 0; +} + #endif #endif /* AVUTIL_WCHAR_FILENAME_H */ diff --git a/libavutil/x86/Makefile b/libavutil/x86/Makefile index d747c3704..d66839e35 100644 --- a/libavutil/x86/Makefile +++ b/libavutil/x86/Makefile @@ -3,7 +3,8 @@ OBJS += x86/cpu.o \ x86/float_dsp_init.o \ x86/imgutils_init.o \ x86/lls_init.o \ - x86/tx_float_init.o \ + +OBJS-$(HAVE_X86ASM) += x86/tx_float_init.o \ OBJS-$(CONFIG_PIXELUTILS) += x86/pixelutils_init.o \ diff --git a/libavutil/x86/cpu.c b/libavutil/x86/cpu.c index 7b13fcae9..d6cd4fab9 100644 --- a/libavutil/x86/cpu.c +++ b/libavutil/x86/cpu.c @@ -150,9 +150,13 @@ int ff_get_cpu_flags_x86(void) 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) + if ((rval & AV_CPU_FLAG_AVX2) && (ebx & 0xd0030000) == 0xd0030000) { rval |= AV_CPU_FLAG_AVX512; - +#if HAVE_AVX512ICL + if ((ebx & 0xd0200000) == 0xd0200000 && (ecx & 0x5f42) == 0x5f42) + rval |= AV_CPU_FLAG_AVX512ICL; +#endif /* HAVE_AVX512ICL */ + } } #endif /* HAVE_AVX512 */ #endif /* HAVE_AVX2 */ diff --git a/libavutil/x86/cpu.h b/libavutil/x86/cpu.h index 937c697fa..40a1eef0a 100644 --- a/libavutil/x86/cpu.h +++ b/libavutil/x86/cpu.h @@ -80,6 +80,7 @@ #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 EXTERNAL_AVX512ICL(flags) CPUEXT_SUFFIX(flags, _EXTERNAL, AVX512ICL) #define INLINE_AMD3DNOW(flags) CPUEXT_SUFFIX(flags, _INLINE, AMD3DNOW) #define INLINE_AMD3DNOWEXT(flags) CPUEXT_SUFFIX(flags, _INLINE, AMD3DNOWEXT) diff --git a/libavutil/x86/cpuid.asm b/libavutil/x86/cpuid.asm index c3f7866ec..766f77fcd 100644 --- a/libavutil/x86/cpuid.asm +++ b/libavutil/x86/cpuid.asm @@ -21,7 +21,7 @@ ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ;****************************************************************************** -%include "x86util.asm" +%include "libavutil/x86/x86util.asm" SECTION .text diff --git a/libavutil/x86/emms.asm b/libavutil/x86/emms.asm index 8611762d7..df84f2221 100644 --- a/libavutil/x86/emms.asm +++ b/libavutil/x86/emms.asm @@ -18,7 +18,7 @@ ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ;****************************************************************************** -%include "x86util.asm" +%include "libavutil/x86/x86util.asm" SECTION .text diff --git a/libavutil/x86/emms.h b/libavutil/x86/emms.h index c21e34b45..8ceec110c 100644 --- a/libavutil/x86/emms.h +++ b/libavutil/x86/emms.h @@ -21,11 +21,14 @@ #include "config.h" #include "libavutil/attributes.h" -#include "libavutil/cpu.h" void avpriv_emms_asm(void); #if HAVE_MMX_INLINE +#ifndef __MMX__ +#include "libavutil/cpu.h" +#endif + # define emms_c emms_c /** * Empty mmx state. diff --git a/libavutil/x86/fixed_dsp.asm b/libavutil/x86/fixed_dsp.asm index 979dd5c33..2f411850f 100644 --- a/libavutil/x86/fixed_dsp.asm +++ b/libavutil/x86/fixed_dsp.asm @@ -20,7 +20,7 @@ ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ;****************************************************************************** -%include "x86util.asm" +%include "libavutil/x86/x86util.asm" SECTION .text diff --git a/libavutil/x86/float_dsp.asm b/libavutil/x86/float_dsp.asm index 517fd6363..cca4d019c 100644 --- a/libavutil/x86/float_dsp.asm +++ b/libavutil/x86/float_dsp.asm @@ -20,7 +20,7 @@ ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ;****************************************************************************** -%include "x86util.asm" +%include "libavutil/x86/x86util.asm" SECTION_RODATA 32 pd_reverse: dd 7, 6, 5, 4, 3, 2, 1, 0 @@ -294,7 +294,7 @@ VECTOR_DMUL_SCALAR ; vector_fmul_window(float *dst, const float *src0, ; const float *src1, const float *win, int len); ;----------------------------------------------------------------------------- -%macro VECTOR_FMUL_WINDOW 0 +INIT_XMM sse cglobal vector_fmul_window, 5, 6, 6, dst, src0, src1, win, len, len1 shl lend, 2 lea len1q, [lenq - mmsize] @@ -305,7 +305,6 @@ cglobal vector_fmul_window, 5, 6, 6, dst, src0, src1, win, len, len1 .loop: mova m0, [winq + lenq] mova m4, [src0q + lenq] -%if cpuflag(sse) mova m1, [winq + len1q] mova m5, [src1q + len1q] shufps m1, m1, 0x1b @@ -319,34 +318,12 @@ cglobal vector_fmul_window, 5, 6, 6, dst, src0, src1, win, len, len1 addps m2, m3 subps m1, m0 shufps m2, m2, 0x1b -%else - pswapd m1, [winq + len1q] - pswapd m5, [src1q + len1q] - mova m2, m0 - mova m3, m1 - pfmul m2, m4 - pfmul m3, m5 - pfmul m1, m4 - pfmul m0, m5 - pfadd m2, m3 - pfsub m1, m0 - pswapd m2, m2 -%endif mova [dstq + lenq], m1 mova [dstq + len1q], m2 sub len1q, mmsize add lenq, mmsize jl .loop -%if mmsize == 8 - femms -%endif REP_RET -%endmacro - -INIT_MMX 3dnowext -VECTOR_FMUL_WINDOW -INIT_XMM sse -VECTOR_FMUL_WINDOW ;----------------------------------------------------------------------------- ; vector_fmul_add(float *dst, const float *src0, const float *src1, diff --git a/libavutil/x86/float_dsp_init.c b/libavutil/x86/float_dsp_init.c index 8826e4e2c..ad17bc204 100644 --- a/libavutil/x86/float_dsp_init.c +++ b/libavutil/x86/float_dsp_init.c @@ -56,8 +56,6 @@ void ff_vector_dmul_scalar_sse2(double *dst, const double *src, void ff_vector_dmul_scalar_avx(double *dst, const double *src, double mul, int len); -void ff_vector_fmul_window_3dnowext(float *dst, const float *src0, - const float *src1, const float *win, int len); void ff_vector_fmul_window_sse(float *dst, const float *src0, const float *src1, const float *win, int len); @@ -83,9 +81,6 @@ av_cold void ff_float_dsp_init_x86(AVFloatDSPContext *fdsp) { int cpu_flags = av_get_cpu_flags(); - if (EXTERNAL_AMD3DNOWEXT(cpu_flags)) { - fdsp->vector_fmul_window = ff_vector_fmul_window_3dnowext; - } if (EXTERNAL_SSE(cpu_flags)) { fdsp->vector_fmul = ff_vector_fmul_sse; fdsp->vector_fmac_scalar = ff_vector_fmac_scalar_sse; diff --git a/libavutil/x86/imgutils_init.c b/libavutil/x86/imgutils_init.c index 4ea398205..91a16cf59 100644 --- a/libavutil/x86/imgutils_init.c +++ b/libavutil/x86/imgutils_init.c @@ -21,9 +21,8 @@ #include "libavutil/cpu.h" #include "libavutil/error.h" -#include "libavutil/imgutils.h" #include "libavutil/imgutils_internal.h" -#include "libavutil/internal.h" +#include "libavutil/macros.h" #include "cpu.h" diff --git a/libavutil/x86/lls.asm b/libavutil/x86/lls.asm index 317fba6fc..d2526d1ff 100644 --- a/libavutil/x86/lls.asm +++ b/libavutil/x86/lls.asm @@ -20,7 +20,7 @@ ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ;****************************************************************************** -%include "x86util.asm" +%include "libavutil/x86/x86util.asm" SECTION .text diff --git a/libavutil/x86/pixelutils.asm b/libavutil/x86/pixelutils.asm index 36c57c5f7..fbe9b4597 100644 --- a/libavutil/x86/pixelutils.asm +++ b/libavutil/x86/pixelutils.asm @@ -21,48 +21,10 @@ ;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ;****************************************************************************** -%include "x86util.asm" +%include "libavutil/x86/x86util.asm" SECTION .text -;------------------------------------------------------------------------------- -; int ff_pixelutils_sad_8x8_mmx(const uint8_t *src1, ptrdiff_t stride1, -; const uint8_t *src2, ptrdiff_t stride2); -;------------------------------------------------------------------------------- -INIT_MMX mmx -cglobal pixelutils_sad_8x8, 4,4,0, src1, stride1, src2, stride2 - pxor m7, m7 - pxor m6, m6 -%rep 4 - mova m0, [src1q] - mova m2, [src1q + stride1q] - mova m1, [src2q] - mova m3, [src2q + stride2q] - psubusb m4, m0, m1 - psubusb m5, m2, m3 - psubusb m1, m0 - psubusb m3, m2 - por m1, m4 - por m3, m5 - punpcklbw m0, m1, m7 - punpcklbw m2, m3, m7 - punpckhbw m1, m7 - punpckhbw m3, m7 - paddw m0, m1 - paddw m2, m3 - paddw m0, m2 - paddw m6, m0 - lea src1q, [src1q + 2*stride1q] - lea src2q, [src2q + 2*stride2q] -%endrep - psrlq m0, m6, 32 - paddw m6, m0 - psrlq m0, m6, 16 - paddw m6, m0 - movd eax, m6 - movzx eax, ax - RET - ;------------------------------------------------------------------------------- ; int ff_pixelutils_sad_8x8_mmxext(const uint8_t *src1, ptrdiff_t stride1, ; const uint8_t *src2, ptrdiff_t stride2); @@ -83,26 +45,6 @@ cglobal pixelutils_sad_8x8, 4,4,0, src1, stride1, src2, stride2 movd eax, m2 RET -;------------------------------------------------------------------------------- -; int ff_pixelutils_sad_16x16_mmxext(const uint8_t *src1, ptrdiff_t stride1, -; const uint8_t *src2, ptrdiff_t stride2); -;------------------------------------------------------------------------------- -INIT_MMX mmxext -cglobal pixelutils_sad_16x16, 4,4,0, src1, stride1, src2, stride2 - pxor m2, m2 -%rep 16 - mova m0, [src1q] - mova m1, [src1q + 8] - psadbw m0, [src2q] - psadbw m1, [src2q + 8] - paddw m2, m0 - paddw m2, m1 - add src1q, stride1q - add src2q, stride2q -%endrep - movd eax, m2 - RET - ;------------------------------------------------------------------------------- ; int ff_pixelutils_sad_16x16_sse2(const uint8_t *src1, ptrdiff_t stride1, ; const uint8_t *src2, ptrdiff_t stride2); diff --git a/libavutil/x86/pixelutils_init.c b/libavutil/x86/pixelutils_init.c index 184a3a4a9..c3c066241 100644 --- a/libavutil/x86/pixelutils_init.c +++ b/libavutil/x86/pixelutils_init.c @@ -21,13 +21,9 @@ #include "pixelutils.h" #include "cpu.h" -int ff_pixelutils_sad_8x8_mmx(const uint8_t *src1, ptrdiff_t stride1, - const uint8_t *src2, ptrdiff_t stride2); int ff_pixelutils_sad_8x8_mmxext(const uint8_t *src1, ptrdiff_t stride1, const uint8_t *src2, ptrdiff_t stride2); -int ff_pixelutils_sad_16x16_mmxext(const uint8_t *src1, ptrdiff_t stride1, - const uint8_t *src2, ptrdiff_t stride2); int ff_pixelutils_sad_16x16_sse2(const uint8_t *src1, ptrdiff_t stride1, const uint8_t *src2, ptrdiff_t stride2); int ff_pixelutils_sad_a_16x16_sse2(const uint8_t *src1, ptrdiff_t stride1, @@ -53,10 +49,6 @@ void ff_pixelutils_sad_init_x86(av_pixelutils_sad_fn *sad, int aligned) { int cpu_flags = av_get_cpu_flags(); - if (EXTERNAL_MMX(cpu_flags)) { - sad[2] = ff_pixelutils_sad_8x8_mmx; - } - // The best way to use SSE2 would be to do 2 SADs in parallel, // but we'd have to modify the pixelutils API to return SIMD functions. @@ -65,7 +57,6 @@ void ff_pixelutils_sad_init_x86(av_pixelutils_sad_fn *sad, int aligned) // so just use the MMX 8x8 version even when SSE2 is available. if (EXTERNAL_MMXEXT(cpu_flags)) { sad[2] = ff_pixelutils_sad_8x8_mmxext; - sad[3] = ff_pixelutils_sad_16x16_mmxext; } if (EXTERNAL_SSE2(cpu_flags)) { diff --git a/libavutil/x86/tx_float.asm b/libavutil/x86/tx_float.asm index 4d2283fae..21f99d394 100644 --- a/libavutil/x86/tx_float.asm +++ b/libavutil/x86/tx_float.asm @@ -29,7 +29,9 @@ ; replace some shuffles with vblends? ; avx512 split-radix -%include "x86util.asm" +%include "libavutil/x86/x86util.asm" + +%define private_prefix ff_tx %if ARCH_X86_64 %define ptr resq @@ -39,25 +41,22 @@ %assign i 16 %rep 14 -cextern cos_ %+ i %+ _float ; ff_cos_i_float... +cextern tab_ %+ i %+ _float ; ff_tab_i_float... %assign i (i << 1) %endrep struc AVTXContext - .n: resd 1 ; Non-power-of-two part - .m: resd 1 ; Power-of-two part - .inv: resd 1 ; Is inverse - .type: resd 1 ; Type - .flags: resq 1 ; Flags - .scale: resq 1 ; Scale + .len: resd 1 ; Length + .inv resd 1 ; Inverse flag + .map: ptr 1 ; Lookup table(s) + .exp: ptr 1 ; Exponentiation factors + .tmp: ptr 1 ; Temporary data - .exptab: ptr 1 ; MDCT exptab - .tmp: ptr 1 ; Temporary buffer needed for all compound transforms - .pfatab: ptr 1 ; Input/Output mapping for compound transforms - .revtab: ptr 1 ; Input mapping for power of two transforms - .inplace_idx: ptr 1 ; Required indices to revtab for in-place transforms + .sub: ptr 1 ; Subcontexts + .fn: ptr 4 ; Subcontext functions + .nb_sub: resd 1 ; Subcontext count - .top_tx ptr 1 ; Used for transforms derived from other transforms + ; Everything else is inaccessible endstruc SECTION_RODATA 32 @@ -485,8 +484,8 @@ SECTION .text movaps [outq + 10*mmsize], tx1_o0 movaps [outq + 14*mmsize], tx2_o0 - movaps tw_e, [cos_64_float + mmsize] - vperm2f128 tw_o, tw_o, [cos_64_float + 64 - 4*7 - mmsize], 0x23 + movaps tw_e, [tab_64_float + mmsize] + vperm2f128 tw_o, tw_o, [tab_64_float + 64 - 4*7 - mmsize], 0x23 movaps m0, [outq + 1*mmsize] movaps m1, [outq + 3*mmsize] @@ -708,14 +707,21 @@ cglobal fft4_ %+ %1 %+ _float, 4, 4, 3, ctx, out, in, stride FFT4 fwd, 0 FFT4 inv, 1 +%macro FFT8_SSE_FN 2 INIT_XMM sse3 -cglobal fft8_float, 4, 4, 6, ctx, out, in, tmp - mov ctxq, [ctxq + AVTXContext.revtab] - +cglobal fft8_ %+ %1, 4, 4, 6, ctx, out, in, tmp +%if %2 + mov ctxq, [ctxq + AVTXContext.map] LOAD64_LUT m0, inq, ctxq, (mmsize/2)*0, tmpq LOAD64_LUT m1, inq, ctxq, (mmsize/2)*1, tmpq LOAD64_LUT m2, inq, ctxq, (mmsize/2)*2, tmpq LOAD64_LUT m3, inq, ctxq, (mmsize/2)*3, tmpq +%else + movaps m0, [inq + 0*mmsize] + movaps m1, [inq + 1*mmsize] + movaps m2, [inq + 2*mmsize] + movaps m3, [inq + 3*mmsize] +%endif FFT8 m0, m1, m2, m3, m4, m5 @@ -730,13 +736,22 @@ cglobal fft8_float, 4, 4, 6, ctx, out, in, tmp movups [outq + 3*mmsize], m1 RET +%endmacro +FFT8_SSE_FN float, 1 +FFT8_SSE_FN ns_float, 0 + +%macro FFT8_AVX_FN 2 INIT_YMM avx -cglobal fft8_float, 4, 4, 4, ctx, out, in, tmp - mov ctxq, [ctxq + AVTXContext.revtab] - +cglobal fft8_ %+ %1, 4, 4, 4, ctx, out, in, tmp +%if %2 + mov ctxq, [ctxq + AVTXContext.map] LOAD64_LUT m0, inq, ctxq, (mmsize/2)*0, tmpq, m2 LOAD64_LUT m1, inq, ctxq, (mmsize/2)*1, tmpq, m3 +%else + movaps m0, [inq + 0*mmsize] + movaps m1, [inq + 1*mmsize] +%endif FFT8_AVX m0, m1, m2, m3 @@ -750,16 +765,26 @@ cglobal fft8_float, 4, 4, 4, ctx, out, in, tmp vextractf128 [outq + 16*3], m0, 1 RET +%endmacro -%macro FFT16_FN 1 +FFT8_AVX_FN float, 1 +FFT8_AVX_FN ns_float, 0 + +%macro FFT16_FN 3 INIT_YMM %1 -cglobal fft16_float, 4, 4, 8, ctx, out, in, tmp - mov ctxq, [ctxq + AVTXContext.revtab] - +cglobal fft16_ %+ %2, 4, 4, 8, ctx, out, in, tmp +%if %3 + movaps m0, [inq + 0*mmsize] + movaps m1, [inq + 1*mmsize] + movaps m2, [inq + 2*mmsize] + movaps m3, [inq + 3*mmsize] +%else + mov ctxq, [ctxq + AVTXContext.map] LOAD64_LUT m0, inq, ctxq, (mmsize/2)*0, tmpq, m4 LOAD64_LUT m1, inq, ctxq, (mmsize/2)*1, tmpq, m5 LOAD64_LUT m2, inq, ctxq, (mmsize/2)*2, tmpq, m6 LOAD64_LUT m3, inq, ctxq, (mmsize/2)*3, tmpq, m7 +%endif FFT16 m0, m1, m2, m3, m4, m5, m6, m7 @@ -780,28 +805,43 @@ cglobal fft16_float, 4, 4, 8, ctx, out, in, tmp RET %endmacro -FFT16_FN avx -FFT16_FN fma3 +FFT16_FN avx, float, 0 +FFT16_FN avx, ns_float, 1 +FFT16_FN fma3, float, 0 +FFT16_FN fma3, ns_float, 1 -%macro FFT32_FN 1 +%macro FFT32_FN 3 INIT_YMM %1 -cglobal fft32_float, 4, 4, 16, ctx, out, in, tmp - mov ctxq, [ctxq + AVTXContext.revtab] - - LOAD64_LUT m4, inq, ctxq, (mmsize/2)*4, tmpq, m8, m9 - LOAD64_LUT m5, inq, ctxq, (mmsize/2)*5, tmpq, m10, m11 - LOAD64_LUT m6, inq, ctxq, (mmsize/2)*6, tmpq, m12, m13 - LOAD64_LUT m7, inq, ctxq, (mmsize/2)*7, tmpq, m14, m15 +cglobal fft32_ %+ %2, 4, 4, 16, ctx, out, in, tmp +%if %3 + movaps m4, [inq + 4*mmsize] + movaps m5, [inq + 5*mmsize] + movaps m6, [inq + 6*mmsize] + movaps m7, [inq + 7*mmsize] +%else + mov ctxq, [ctxq + AVTXContext.map] + LOAD64_LUT m4, inq, ctxq, (mmsize/2)*4, tmpq, m8, m12 + LOAD64_LUT m5, inq, ctxq, (mmsize/2)*5, tmpq, m9, m13 + LOAD64_LUT m6, inq, ctxq, (mmsize/2)*6, tmpq, m10, m14 + LOAD64_LUT m7, inq, ctxq, (mmsize/2)*7, tmpq, m11, m15 +%endif FFT8 m4, m5, m6, m7, m8, m9 - LOAD64_LUT m0, inq, ctxq, (mmsize/2)*0, tmpq, m8, m9 - LOAD64_LUT m1, inq, ctxq, (mmsize/2)*1, tmpq, m10, m11 - LOAD64_LUT m2, inq, ctxq, (mmsize/2)*2, tmpq, m12, m13 - LOAD64_LUT m3, inq, ctxq, (mmsize/2)*3, tmpq, m14, m15 +%if %3 + movaps m0, [inq + 0*mmsize] + movaps m1, [inq + 1*mmsize] + movaps m2, [inq + 2*mmsize] + movaps m3, [inq + 3*mmsize] +%else + LOAD64_LUT m0, inq, ctxq, (mmsize/2)*0, tmpq, m8, m12 + LOAD64_LUT m1, inq, ctxq, (mmsize/2)*1, tmpq, m9, m13 + LOAD64_LUT m2, inq, ctxq, (mmsize/2)*2, tmpq, m10, m14 + LOAD64_LUT m3, inq, ctxq, (mmsize/2)*3, tmpq, m11, m15 +%endif - movaps m8, [cos_32_float] - vperm2f128 m9, m9, [cos_32_float + 4*8 - 4*7], 0x23 + movaps m8, [tab_32_float] + vperm2f128 m9, m9, [tab_32_float + 4*8 - 4*7], 0x23 FFT16 m0, m1, m2, m3, m10, m11, m12, m13 @@ -839,8 +879,10 @@ cglobal fft32_float, 4, 4, 16, ctx, out, in, tmp %endmacro %if ARCH_X86_64 -FFT32_FN avx -FFT32_FN fma3 +FFT32_FN avx, float, 0 +FFT32_FN avx, ns_float, 1 +FFT32_FN fma3, float, 0 +FFT32_FN fma3, ns_float, 1 %endif %macro FFT_SPLIT_RADIX_DEF 1-2 @@ -858,8 +900,8 @@ ALIGN 16 POP lenq sub outq, (%1*4) + (%1*2) + (%1/2) - lea rtabq, [cos_ %+ %1 %+ _float] - lea itabq, [cos_ %+ %1 %+ _float + %1 - 4*7] + lea rtabq, [tab_ %+ %1 %+ _float] + lea itabq, [tab_ %+ %1 %+ _float + %1 - 4*7] %if %0 > 1 cmp tgtq, %1 @@ -881,30 +923,44 @@ ALIGN 16 %endif %endmacro -%macro FFT_SPLIT_RADIX_FN 1 +%macro FFT_SPLIT_RADIX_FN 3 INIT_YMM %1 -cglobal split_radix_fft_float, 4, 8, 16, 272, lut, out, in, len, tmp, itab, rtab, tgt - movsxd lenq, dword [lutq + AVTXContext.m] - mov lutq, [lutq + AVTXContext.revtab] +cglobal fft_sr_ %+ %2, 4, 8, 16, 272, lut, out, in, len, tmp, itab, rtab, tgt + movsxd lenq, dword [lutq + AVTXContext.len] + mov lutq, [lutq + AVTXContext.map] mov tgtq, lenq ; Bottom-most/32-point transform =============================================== ALIGN 16 .32pt: - LOAD64_LUT m4, inq, lutq, (mmsize/2)*4, tmpq, m8, m9 - LOAD64_LUT m5, inq, lutq, (mmsize/2)*5, tmpq, m10, m11 - LOAD64_LUT m6, inq, lutq, (mmsize/2)*6, tmpq, m12, m13 - LOAD64_LUT m7, inq, lutq, (mmsize/2)*7, tmpq, m14, m15 +%if %3 + movaps m4, [inq + 4*mmsize] + movaps m5, [inq + 5*mmsize] + movaps m6, [inq + 6*mmsize] + movaps m7, [inq + 7*mmsize] +%else + LOAD64_LUT m4, inq, lutq, (mmsize/2)*4, tmpq, m8, m12 + LOAD64_LUT m5, inq, lutq, (mmsize/2)*5, tmpq, m9, m13 + LOAD64_LUT m6, inq, lutq, (mmsize/2)*6, tmpq, m10, m14 + LOAD64_LUT m7, inq, lutq, (mmsize/2)*7, tmpq, m11, m15 +%endif FFT8 m4, m5, m6, m7, m8, m9 - LOAD64_LUT m0, inq, lutq, (mmsize/2)*0, tmpq, m8, m9 - LOAD64_LUT m1, inq, lutq, (mmsize/2)*1, tmpq, m10, m11 - LOAD64_LUT m2, inq, lutq, (mmsize/2)*2, tmpq, m12, m13 - LOAD64_LUT m3, inq, lutq, (mmsize/2)*3, tmpq, m14, m15 +%if %3 + movaps m0, [inq + 0*mmsize] + movaps m1, [inq + 1*mmsize] + movaps m2, [inq + 2*mmsize] + movaps m3, [inq + 3*mmsize] +%else + LOAD64_LUT m0, inq, lutq, (mmsize/2)*0, tmpq, m8, m12 + LOAD64_LUT m1, inq, lutq, (mmsize/2)*1, tmpq, m9, m13 + LOAD64_LUT m2, inq, lutq, (mmsize/2)*2, tmpq, m10, m14 + LOAD64_LUT m3, inq, lutq, (mmsize/2)*3, tmpq, m11, m15 +%endif - movaps m8, [cos_32_float] - vperm2f128 m9, m9, [cos_32_float + 32 - 4*7], 0x23 + movaps m8, [tab_32_float] + vperm2f128 m9, m9, [tab_32_float + 32 - 4*7], 0x23 FFT16 m0, m1, m2, m3, m10, m11, m12, m13 @@ -916,7 +972,11 @@ ALIGN 16 movaps [outq + 5*mmsize], m5 movaps [outq + 7*mmsize], m7 +%if %3 + add inq, 8*mmsize +%else add lutq, (mmsize/2)*8 +%endif cmp lenq, 32 jg .64pt @@ -947,24 +1007,42 @@ ALIGN 16 SWAP m4, m1 SWAP m6, m3 - LOAD64_LUT tx1_e0, inq, lutq, (mmsize/2)*0, tmpq, tw_e, tw_o - LOAD64_LUT tx1_e1, inq, lutq, (mmsize/2)*1, tmpq, tmp1, tmp2 - LOAD64_LUT tx1_o0, inq, lutq, (mmsize/2)*2, tmpq, tw_e, tw_o - LOAD64_LUT tx1_o1, inq, lutq, (mmsize/2)*3, tmpq, tmp1, tmp2 +%if %3 + movaps tx1_e0, [inq + 0*mmsize] + movaps tx1_e1, [inq + 1*mmsize] + movaps tx1_o0, [inq + 2*mmsize] + movaps tx1_o1, [inq + 3*mmsize] +%else + LOAD64_LUT tx1_e0, inq, lutq, (mmsize/2)*0, tmpq, tw_e, tmp1 + LOAD64_LUT tx1_e1, inq, lutq, (mmsize/2)*1, tmpq, tw_o, tmp2 + LOAD64_LUT tx1_o0, inq, lutq, (mmsize/2)*2, tmpq, tw_e, tmp1 + LOAD64_LUT tx1_o1, inq, lutq, (mmsize/2)*3, tmpq, tw_o, tmp2 +%endif FFT16 tx1_e0, tx1_e1, tx1_o0, tx1_o1, tw_e, tw_o, tx2_o0, tx2_o1 - LOAD64_LUT tx2_e0, inq, lutq, (mmsize/2)*4, tmpq, tmp1, tmp2 - LOAD64_LUT tx2_e1, inq, lutq, (mmsize/2)*5, tmpq, tw_e, tw_o - LOAD64_LUT tx2_o0, inq, lutq, (mmsize/2)*6, tmpq, tmp1, tmp2 - LOAD64_LUT tx2_o1, inq, lutq, (mmsize/2)*7, tmpq, tw_e, tw_o +%if %3 + movaps tx2_e0, [inq + 4*mmsize] + movaps tx2_e1, [inq + 5*mmsize] + movaps tx2_o0, [inq + 6*mmsize] + movaps tx2_o1, [inq + 7*mmsize] +%else + LOAD64_LUT tx2_e0, inq, lutq, (mmsize/2)*4, tmpq, tw_e, tmp1 + LOAD64_LUT tx2_e1, inq, lutq, (mmsize/2)*5, tmpq, tw_o, tmp2 + LOAD64_LUT tx2_o0, inq, lutq, (mmsize/2)*6, tmpq, tw_e, tmp1 + LOAD64_LUT tx2_o1, inq, lutq, (mmsize/2)*7, tmpq, tw_o, tmp2 +%endif FFT16 tx2_e0, tx2_e1, tx2_o0, tx2_o1, tmp1, tmp2, tw_e, tw_o - movaps tw_e, [cos_64_float] - vperm2f128 tw_o, tw_o, [cos_64_float + 64 - 4*7], 0x23 + movaps tw_e, [tab_64_float] + vperm2f128 tw_o, tw_o, [tab_64_float + 64 - 4*7], 0x23 +%if %3 + add inq, 8*mmsize +%else add lutq, (mmsize/2)*8 +%endif cmp tgtq, 64 je .deinterleave @@ -989,8 +1067,8 @@ ALIGN 16 POP lenq sub outq, 24*mmsize - lea rtabq, [cos_128_float] - lea itabq, [cos_128_float + 128 - 4*7] + lea rtabq, [tab_128_float] + lea itabq, [tab_128_float + 128 - 4*7] cmp tgtq, 128 je .deinterleave @@ -1016,8 +1094,8 @@ ALIGN 16 POP lenq sub outq, 48*mmsize - lea rtabq, [cos_256_float] - lea itabq, [cos_256_float + 256 - 4*7] + lea rtabq, [tab_256_float] + lea itabq, [tab_256_float + 256 - 4*7] cmp tgtq, 256 je .deinterleave @@ -1044,8 +1122,8 @@ ALIGN 16 POP lenq sub outq, 96*mmsize - lea rtabq, [cos_512_float] - lea itabq, [cos_512_float + 512 - 4*7] + lea rtabq, [tab_512_float] + lea itabq, [tab_512_float + 512 - 4*7] cmp tgtq, 512 je .deinterleave @@ -1079,8 +1157,8 @@ ALIGN 16 POP lenq sub outq, 192*mmsize - lea rtabq, [cos_1024_float] - lea itabq, [cos_1024_float + 1024 - 4*7] + lea rtabq, [tab_1024_float] + lea itabq, [tab_1024_float + 1024 - 4*7] cmp tgtq, 1024 je .deinterleave @@ -1160,8 +1238,8 @@ FFT_SPLIT_RADIX_DEF 131072 vextractf128 [outq + 13*mmsize + 0], tw_e, 1 vextractf128 [outq + 13*mmsize + 16], tx2_e0, 1 - movaps tw_e, [cos_64_float + mmsize] - vperm2f128 tw_o, tw_o, [cos_64_float + 64 - 4*7 - mmsize], 0x23 + movaps tw_e, [tab_64_float + mmsize] + vperm2f128 tw_o, tw_o, [tab_64_float + 64 - 4*7 - mmsize], 0x23 movaps m0, [outq + 1*mmsize] movaps m1, [outq + 3*mmsize] @@ -1207,8 +1285,10 @@ FFT_SPLIT_RADIX_DEF 131072 %endmacro %if ARCH_X86_64 -FFT_SPLIT_RADIX_FN avx +FFT_SPLIT_RADIX_FN fma3, float, 0 +FFT_SPLIT_RADIX_FN fma3, ns_float, 1 %if HAVE_AVX2_EXTERNAL -FFT_SPLIT_RADIX_FN avx2 +FFT_SPLIT_RADIX_FN avx2, float, 0 +FFT_SPLIT_RADIX_FN avx2, ns_float, 1 %endif %endif diff --git a/libavutil/x86/tx_float_init.c b/libavutil/x86/tx_float_init.c index 8b77a5f29..5db0b57d1 100644 --- a/libavutil/x86/tx_float_init.c +++ b/libavutil/x86/tx_float_init.c @@ -21,86 +21,83 @@ #include "libavutil/attributes.h" #include "libavutil/x86/cpu.h" -void ff_fft2_float_sse3 (AVTXContext *s, void *out, void *in, ptrdiff_t stride); -void ff_fft4_inv_float_sse2 (AVTXContext *s, void *out, void *in, ptrdiff_t stride); -void ff_fft4_fwd_float_sse2 (AVTXContext *s, void *out, void *in, ptrdiff_t stride); -void ff_fft8_float_sse3 (AVTXContext *s, void *out, void *in, ptrdiff_t stride); -void ff_fft8_float_avx (AVTXContext *s, void *out, void *in, ptrdiff_t stride); -void ff_fft16_float_avx (AVTXContext *s, void *out, void *in, ptrdiff_t stride); -void ff_fft16_float_fma3 (AVTXContext *s, void *out, void *in, ptrdiff_t stride); -void ff_fft32_float_avx (AVTXContext *s, void *out, void *in, ptrdiff_t stride); -void ff_fft32_float_fma3 (AVTXContext *s, void *out, void *in, ptrdiff_t stride); +#include "config.h" -void ff_split_radix_fft_float_avx (AVTXContext *s, void *out, void *in, ptrdiff_t stride); -void ff_split_radix_fft_float_avx2(AVTXContext *s, void *out, void *in, ptrdiff_t stride); +TX_DECL_FN(fft2, sse3) +TX_DECL_FN(fft4_fwd, sse2) +TX_DECL_FN(fft4_inv, sse2) +TX_DECL_FN(fft8, sse3) +TX_DECL_FN(fft8_ns, sse3) +TX_DECL_FN(fft8, avx) +TX_DECL_FN(fft8_ns, avx) +TX_DECL_FN(fft16, avx) +TX_DECL_FN(fft16_ns, avx) +TX_DECL_FN(fft16, fma3) +TX_DECL_FN(fft16_ns, fma3) +TX_DECL_FN(fft32, avx) +TX_DECL_FN(fft32_ns, avx) +TX_DECL_FN(fft32, fma3) +TX_DECL_FN(fft32_ns, fma3) +TX_DECL_FN(fft_sr, fma3) +TX_DECL_FN(fft_sr_ns, fma3) +TX_DECL_FN(fft_sr, avx2) +TX_DECL_FN(fft_sr_ns, avx2) -av_cold void ff_tx_init_float_x86(AVTXContext *s, av_tx_fn *tx) -{ - int cpu_flags = av_get_cpu_flags(); - int gen_revtab = 0, basis, revtab_interleave; - - if (s->flags & AV_TX_UNALIGNED) - return; - - if (ff_tx_type_is_mdct(s->type)) - return; - -#define TXFN(fn, gentab, sr_basis, interleave) \ - do { \ - *tx = fn; \ - gen_revtab = gentab; \ - basis = sr_basis; \ - revtab_interleave = interleave; \ - } while (0) - - if (s->n == 1) { - if (EXTERNAL_SSE2(cpu_flags)) { - if (s->m == 4 && s->inv) - TXFN(ff_fft4_inv_float_sse2, 0, 0, 0); - else if (s->m == 4) - TXFN(ff_fft4_fwd_float_sse2, 0, 0, 0); - } - - if (EXTERNAL_SSE3(cpu_flags)) { - if (s->m == 2) - TXFN(ff_fft2_float_sse3, 0, 0, 0); - else if (s->m == 8) - TXFN(ff_fft8_float_sse3, 1, 8, 0); - } - - if (EXTERNAL_AVX_FAST(cpu_flags)) { - if (s->m == 8) - TXFN(ff_fft8_float_avx, 1, 8, 0); - else if (s->m == 16) - TXFN(ff_fft16_float_avx, 1, 8, 2); -#if ARCH_X86_64 - else if (s->m == 32) - TXFN(ff_fft32_float_avx, 1, 8, 2); - else if (s->m >= 64 && s->m <= 131072 && !(s->flags & AV_TX_INPLACE)) - TXFN(ff_split_radix_fft_float_avx, 1, 8, 2); -#endif - } - - if (EXTERNAL_FMA3_FAST(cpu_flags)) { - if (s->m == 16) - TXFN(ff_fft16_float_fma3, 1, 8, 2); -#if ARCH_X86_64 - else if (s->m == 32) - TXFN(ff_fft32_float_fma3, 1, 8, 2); -#endif - } - -#if ARCH_X86_64 - if (EXTERNAL_AVX2_FAST(cpu_flags)) { - if (s->m >= 64 && s->m <= 131072 && !(s->flags & AV_TX_INPLACE)) - TXFN(ff_split_radix_fft_float_avx2, 1, 8, 2); - } -#endif - } - - if (gen_revtab) - ff_tx_gen_split_radix_parity_revtab(s->revtab, s->m, s->inv, basis, - revtab_interleave); - -#undef TXFN +#define DECL_INIT_FN(basis, interleave) \ +static av_cold int b ##basis## _i ##interleave(AVTXContext *s, \ + const FFTXCodelet *cd, \ + uint64_t flags, \ + FFTXCodeletOptions *opts, \ + int len, int inv, \ + const void *scale) \ +{ \ + const int inv_lookup = opts ? opts->invert_lookup : 1; \ + ff_tx_init_tabs_float(len); \ + if (cd->max_len == 2) \ + return ff_tx_gen_ptwo_revtab(s, inv_lookup); \ + else \ + return ff_tx_gen_split_radix_parity_revtab(s, inv_lookup, \ + basis, interleave); \ } + +DECL_INIT_FN(8, 0) +DECL_INIT_FN(8, 2) + +const FFTXCodelet * const ff_tx_codelet_list_float_x86[] = { + TX_DEF(fft2, FFT, 2, 2, 2, 0, 128, NULL, sse3, SSE3, AV_TX_INPLACE, 0), + TX_DEF(fft2, FFT, 2, 2, 2, 0, 192, b8_i0, sse3, SSE3, AV_TX_INPLACE | FF_TX_PRESHUFFLE, 0), + TX_DEF(fft4_fwd, FFT, 4, 4, 2, 0, 128, NULL, sse2, SSE2, AV_TX_INPLACE | FF_TX_FORWARD_ONLY, 0), + TX_DEF(fft4_fwd, FFT, 4, 4, 2, 0, 192, b8_i0, sse2, SSE2, AV_TX_INPLACE | FF_TX_PRESHUFFLE, 0), + TX_DEF(fft4_inv, FFT, 4, 4, 2, 0, 128, NULL, sse2, SSE2, AV_TX_INPLACE | FF_TX_INVERSE_ONLY, 0), + TX_DEF(fft8, FFT, 8, 8, 2, 0, 128, b8_i0, sse3, SSE3, AV_TX_INPLACE, 0), + TX_DEF(fft8_ns, FFT, 8, 8, 2, 0, 192, b8_i0, sse3, SSE3, AV_TX_INPLACE | FF_TX_PRESHUFFLE, 0), + TX_DEF(fft8, FFT, 8, 8, 2, 0, 256, b8_i0, avx, AVX, AV_TX_INPLACE, AV_CPU_FLAG_AVXSLOW), + TX_DEF(fft8_ns, FFT, 8, 8, 2, 0, 320, b8_i0, avx, AVX, AV_TX_INPLACE | FF_TX_PRESHUFFLE, + AV_CPU_FLAG_AVXSLOW), + TX_DEF(fft16, FFT, 16, 16, 2, 0, 256, b8_i2, avx, AVX, AV_TX_INPLACE, AV_CPU_FLAG_AVXSLOW), + TX_DEF(fft16_ns, FFT, 16, 16, 2, 0, 320, b8_i2, avx, AVX, AV_TX_INPLACE | FF_TX_PRESHUFFLE, + AV_CPU_FLAG_AVXSLOW), + TX_DEF(fft16, FFT, 16, 16, 2, 0, 288, b8_i2, fma3, FMA3, AV_TX_INPLACE, AV_CPU_FLAG_AVXSLOW), + TX_DEF(fft16_ns, FFT, 16, 16, 2, 0, 352, b8_i2, fma3, FMA3, AV_TX_INPLACE | FF_TX_PRESHUFFLE, + AV_CPU_FLAG_AVXSLOW), + +#if ARCH_X86_64 + TX_DEF(fft32, FFT, 32, 32, 2, 0, 256, b8_i2, avx, AVX, AV_TX_INPLACE, AV_CPU_FLAG_AVXSLOW), + TX_DEF(fft32_ns, FFT, 32, 32, 2, 0, 320, b8_i2, avx, AVX, AV_TX_INPLACE | FF_TX_PRESHUFFLE, + AV_CPU_FLAG_AVXSLOW), + TX_DEF(fft32, FFT, 32, 32, 2, 0, 288, b8_i2, fma3, FMA3, AV_TX_INPLACE, AV_CPU_FLAG_AVXSLOW), + TX_DEF(fft32_ns, FFT, 32, 32, 2, 0, 352, b8_i2, fma3, FMA3, AV_TX_INPLACE | FF_TX_PRESHUFFLE, + AV_CPU_FLAG_AVXSLOW), + TX_DEF(fft_sr, FFT, 64, 131072, 2, 0, 288, b8_i2, fma3, FMA3, 0, AV_CPU_FLAG_AVXSLOW), + TX_DEF(fft_sr_ns, FFT, 64, 131072, 2, 0, 352, b8_i2, fma3, FMA3, AV_TX_INPLACE | FF_TX_PRESHUFFLE, + AV_CPU_FLAG_AVXSLOW), +#if HAVE_AVX2_EXTERNAL + TX_DEF(fft_sr, FFT, 64, 131072, 2, 0, 320, b8_i2, avx2, AVX2, 0, + AV_CPU_FLAG_AVXSLOW | AV_CPU_FLAG_SLOW_GATHER), + TX_DEF(fft_sr_ns, FFT, 64, 131072, 2, 0, 384, b8_i2, avx2, AVX2, AV_TX_INPLACE | FF_TX_PRESHUFFLE, + AV_CPU_FLAG_AVXSLOW | AV_CPU_FLAG_SLOW_GATHER), +#endif +#endif + + NULL, +}; diff --git a/libavutil/x86/x86inc.asm b/libavutil/x86/x86inc.asm index 01c35e3a4..251ee797d 100644 --- a/libavutil/x86/x86inc.asm +++ b/libavutil/x86/x86inc.asm @@ -817,32 +817,33 @@ BRANCH_INSTR jz, je, jnz, jne, jl, jle, jnl, jnle, jg, jge, jng, jnge, ja, jae, ; cpuflags -%assign cpuflags_mmx (1<<0) -%assign cpuflags_mmx2 (1<<1) | cpuflags_mmx -%assign cpuflags_3dnow (1<<2) | cpuflags_mmx -%assign cpuflags_3dnowext (1<<3) | cpuflags_3dnow -%assign cpuflags_sse (1<<4) | cpuflags_mmx2 -%assign cpuflags_sse2 (1<<5) | cpuflags_sse -%assign cpuflags_sse2slow (1<<6) | cpuflags_sse2 -%assign cpuflags_lzcnt (1<<7) | cpuflags_sse2 -%assign cpuflags_sse3 (1<<8) | cpuflags_sse2 -%assign cpuflags_ssse3 (1<<9) | cpuflags_sse3 -%assign cpuflags_sse4 (1<<10)| cpuflags_ssse3 -%assign cpuflags_sse42 (1<<11)| cpuflags_sse4 -%assign cpuflags_aesni (1<<12)| cpuflags_sse42 -%assign cpuflags_avx (1<<13)| cpuflags_sse42 -%assign cpuflags_xop (1<<14)| cpuflags_avx -%assign cpuflags_fma4 (1<<15)| cpuflags_avx -%assign cpuflags_fma3 (1<<16)| cpuflags_avx -%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_mmx (1<<0) +%assign cpuflags_mmx2 (1<<1) | cpuflags_mmx +%assign cpuflags_3dnow (1<<2) | cpuflags_mmx +%assign cpuflags_3dnowext (1<<3) | cpuflags_3dnow +%assign cpuflags_sse (1<<4) | cpuflags_mmx2 +%assign cpuflags_sse2 (1<<5) | cpuflags_sse +%assign cpuflags_sse2slow (1<<6) | cpuflags_sse2 +%assign cpuflags_lzcnt (1<<7) | cpuflags_sse2 +%assign cpuflags_sse3 (1<<8) | cpuflags_sse2 +%assign cpuflags_ssse3 (1<<9) | cpuflags_sse3 +%assign cpuflags_sse4 (1<<10)| cpuflags_ssse3 +%assign cpuflags_sse42 (1<<11)| cpuflags_sse4 +%assign cpuflags_aesni (1<<12)| cpuflags_sse42 +%assign cpuflags_avx (1<<13)| cpuflags_sse42 +%assign cpuflags_xop (1<<14)| cpuflags_avx +%assign cpuflags_fma4 (1<<15)| cpuflags_avx +%assign cpuflags_fma3 (1<<16)| cpuflags_avx +%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_avx512icl (1<<25)| cpuflags_avx512 -%assign cpuflags_cache32 (1<<21) -%assign cpuflags_cache64 (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_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) diff --git a/libavutil/xtea.c b/libavutil/xtea.c index f7892af9f..6f376c365 100644 --- a/libavutil/xtea.c +++ b/libavutil/xtea.c @@ -28,8 +28,8 @@ * @ingroup lavu_xtea */ -#include "avutil.h" -#include "common.h" +#include +#include "config.h" #include "intreadwrite.h" #include "mem.h" #include "xtea.h" diff --git a/libpostproc/Makefile b/libpostproc/Makefile index 34317193a..d3f3b27f3 100644 --- a/libpostproc/Makefile +++ b/libpostproc/Makefile @@ -4,8 +4,10 @@ FFLIBS = avutil HEADERS = postprocess.h \ version.h \ + version_major.h \ -OBJS = postprocess.o +OBJS = postprocess.o \ + version.o \ # Windows resource file SLIBOBJS-$(HAVE_GNU_WINDRES) += postprocres.o diff --git a/libpostproc/postprocess.c b/libpostproc/postprocess.c index 2ca7a3779..383c691cb 100644 --- a/libpostproc/postprocess.c +++ b/libpostproc/postprocess.c @@ -92,26 +92,6 @@ try to unroll inner for(x=0 ... loop to avoid these damn if(x ... checks #include "libavutil/avstring.h" #include "libavutil/ppc/util_altivec.h" -#include "libavutil/ffversion.h" -const char postproc_ffversion[] = "FFmpeg version " FFMPEG_VERSION; - -unsigned postproc_version(void) -{ - av_assert0(LIBPOSTPROC_VERSION_MICRO >= 100); - return LIBPOSTPROC_VERSION_INT; -} - -const char *postproc_configuration(void) -{ - return FFMPEG_CONFIGURATION; -} - -const char *postproc_license(void) -{ -#define LICENSE_PREFIX "libpostproc license: " - return &LICENSE_PREFIX FFMPEG_LICENSE[sizeof(LICENSE_PREFIX) - 1]; -} - #define GET_MODE_BUFFER_SIZE 500 #define OPTIONS_ARRAY_SIZE 10 #define BLOCK_SIZE 8 diff --git a/libpostproc/postprocess.h b/libpostproc/postprocess.h index ba456cf3e..5decb7e8a 100644 --- a/libpostproc/postprocess.h +++ b/libpostproc/postprocess.h @@ -34,7 +34,13 @@ * @{ */ +#include "libpostproc/version_major.h" +#ifndef HAVE_AV_CONFIG_H +/* When included as part of the ffmpeg build, only include the major version + * to avoid unnecessary rebuilds. When included externally, keep including + * the full version information. */ #include "libpostproc/version.h" +#endif /** * Return the LIBPOSTPROC_VERSION_INT constant. diff --git a/libpostproc/version.c b/libpostproc/version.c new file mode 100644 index 000000000..494575ae6 --- /dev/null +++ b/libpostproc/version.c @@ -0,0 +1,44 @@ +/* + * Version functions. + * + * 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/avassert.h" +#include "postprocess.h" +#include "version.h" + +#include "libavutil/ffversion.h" +const char postproc_ffversion[] = "FFmpeg version " FFMPEG_VERSION; + +unsigned postproc_version(void) +{ + av_assert0(LIBPOSTPROC_VERSION_MICRO >= 100); + return LIBPOSTPROC_VERSION_INT; +} + +const char *postproc_configuration(void) +{ + return FFMPEG_CONFIGURATION; +} + +const char *postproc_license(void) +{ +#define LICENSE_PREFIX "libpostproc license: " + return &LICENSE_PREFIX FFMPEG_LICENSE[sizeof(LICENSE_PREFIX) - 1]; +} diff --git a/libpostproc/version.h b/libpostproc/version.h index 0c8db478d..397f3f74a 100644 --- a/libpostproc/version.h +++ b/libpostproc/version.h @@ -28,8 +28,9 @@ #include "libavutil/version.h" -#define LIBPOSTPROC_VERSION_MAJOR 56 -#define LIBPOSTPROC_VERSION_MINOR 3 +#include "version_major.h" + +#define LIBPOSTPROC_VERSION_MINOR 6 #define LIBPOSTPROC_VERSION_MICRO 100 #define LIBPOSTPROC_VERSION_INT AV_VERSION_INT(LIBPOSTPROC_VERSION_MAJOR, \ diff --git a/libpostproc/version_major.h b/libpostproc/version_major.h new file mode 100644 index 000000000..7afc4dbb7 --- /dev/null +++ b/libpostproc/version_major.h @@ -0,0 +1,31 @@ +/* + * Version macros. + * + * 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 POSTPROC_VERSION_MAJOR_H +#define POSTPROC_VERSION_MAJOR_H + +/** + * @file + * Libpostproc version macros + */ + +#define LIBPOSTPROC_VERSION_MAJOR 56 + +#endif /* POSTPROC_VERSION_MAJOR_H */ diff --git a/libswresample/Makefile b/libswresample/Makefile index f528427f5..dc80027c3 100644 --- a/libswresample/Makefile +++ b/libswresample/Makefile @@ -4,6 +4,7 @@ FFLIBS = avutil HEADERS = swresample.h \ version.h \ + version_major.h \ OBJS = audioconvert.o \ dither.o \ @@ -13,6 +14,7 @@ OBJS = audioconvert.o \ resample_dsp.o \ swresample.o \ swresample_frame.o \ + version.o \ OBJS-$(CONFIG_LIBSOXR) += soxr_resample.o diff --git a/libswresample/audioconvert.c b/libswresample/audioconvert.c index 500aa0e5c..1d75ba149 100644 --- a/libswresample/audioconvert.c +++ b/libswresample/audioconvert.c @@ -176,9 +176,13 @@ AudioConvert *swri_audio_convert_alloc(enum AVSampleFormat out_fmt, } } - if(HAVE_X86ASM && HAVE_MMX) swri_audio_convert_init_x86(ctx, out_fmt, in_fmt, channels); - if(ARCH_ARM) swri_audio_convert_init_arm(ctx, out_fmt, in_fmt, channels); - if(ARCH_AARCH64) swri_audio_convert_init_aarch64(ctx, out_fmt, in_fmt, channels); +#if ARCH_X86 && HAVE_X86ASM && HAVE_MMX + swri_audio_convert_init_x86(ctx, out_fmt, in_fmt, channels); +#elif ARCH_ARM + swri_audio_convert_init_arm(ctx, out_fmt, in_fmt, channels); +#elif ARCH_AARCH64 + swri_audio_convert_init_aarch64(ctx, out_fmt, in_fmt, channels); +#endif return ctx; } diff --git a/libswresample/noise_shaping_data.c b/libswresample/noise_shaping_data.c index 77e0f2eaf..5fd213698 100644 --- a/libswresample/noise_shaping_data.c +++ b/libswresample/noise_shaping_data.c @@ -31,10 +31,6 @@ static double const mew44[] = { 1.662, -1.263, .4827, -.2913, .1268, -.1124, .03252, -.01265, -.03524}; static double const iew44[] = { 2.847, -4.685, 6.214, -7.184, 6.639, -5.032, 3.263, -1.632, .4191}; -static double const ges44[] = { - 2.2061, -.4706, -.2534, -.6214, 1.0587, .0676, -.6054, -.2738}; -static double const ges48[] = { - 2.2374, -.7339, -.1251, -.6033, .903, .0116, -.5853, -.2571}; static double const shi48[] = { 2.8720729351043701172, -5.0413231849670410156, 6.2442994117736816406, diff --git a/libswresample/options.c b/libswresample/options.c index 691170915..ffa27c590 100644 --- a/libswresample/options.c +++ b/libswresample/options.c @@ -34,12 +34,19 @@ #define OFFSET(x) offsetof(SwrContext,x) #define PARAM AV_OPT_FLAG_AUDIO_PARAM +#define DEPREC AV_OPT_FLAG_DEPRECATED static const AVOption options[]={ -{"ich" , "set input channel count" , OFFSET(user_in_ch_count ), AV_OPT_TYPE_INT, {.i64=0 }, 0 , SWR_CH_MAX, PARAM}, -{"in_channel_count" , "set input channel count" , OFFSET(user_in_ch_count ), AV_OPT_TYPE_INT, {.i64=0 }, 0 , SWR_CH_MAX, PARAM}, -{"och" , "set output channel count" , OFFSET(user_out_ch_count ), AV_OPT_TYPE_INT, {.i64=0 }, 0 , SWR_CH_MAX, PARAM}, -{"out_channel_count" , "set output channel count" , OFFSET(user_out_ch_count ), AV_OPT_TYPE_INT, {.i64=0 }, 0 , SWR_CH_MAX, PARAM}, +#if FF_API_OLD_CHANNEL_LAYOUT +{"ich" , "set input channel count (Deprecated, use ichl)", + OFFSET(user_in_ch_count ), AV_OPT_TYPE_INT, {.i64=0 }, 0 , SWR_CH_MAX, PARAM|DEPREC}, +{"in_channel_count" , "set input channel count (Deprecated, use in_chlayout)", + OFFSET(user_in_ch_count ), AV_OPT_TYPE_INT, {.i64=0 }, 0 , SWR_CH_MAX, PARAM|DEPREC}, +{"och" , "set output channel count (Deprecated, use ochl)", + OFFSET(user_out_ch_count ), AV_OPT_TYPE_INT, {.i64=0 }, 0 , SWR_CH_MAX, PARAM|DEPREC}, +{"out_channel_count" , "set output channel count (Deprecated, use out_chlayout)", + OFFSET(user_out_ch_count ), AV_OPT_TYPE_INT, {.i64=0 }, 0 , SWR_CH_MAX, PARAM|DEPREC}, +#endif {"uch" , "set used channel count" , OFFSET(user_used_ch_count), AV_OPT_TYPE_INT, {.i64=0 }, 0 , SWR_CH_MAX, PARAM}, {"used_channel_count" , "set used channel count" , OFFSET(user_used_ch_count), AV_OPT_TYPE_INT, {.i64=0 }, 0 , SWR_CH_MAX, PARAM}, {"isr" , "set input sample rate" , OFFSET( in_sample_rate), AV_OPT_TYPE_INT , {.i64=0 }, 0 , INT_MAX , PARAM}, @@ -52,10 +59,20 @@ static const AVOption options[]={ {"out_sample_fmt" , "set output sample format" , OFFSET(out_sample_fmt ), AV_OPT_TYPE_SAMPLE_FMT , {.i64=AV_SAMPLE_FMT_NONE}, -1 , INT_MAX, PARAM}, {"tsf" , "set internal sample format" , OFFSET(user_int_sample_fmt), AV_OPT_TYPE_SAMPLE_FMT , {.i64=AV_SAMPLE_FMT_NONE}, -1 , INT_MAX, PARAM}, {"internal_sample_fmt" , "set internal sample format" , OFFSET(user_int_sample_fmt), AV_OPT_TYPE_SAMPLE_FMT , {.i64=AV_SAMPLE_FMT_NONE}, -1 , INT_MAX, PARAM}, -{"icl" , "set input channel layout" , OFFSET(user_in_ch_layout ), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0 }, INT64_MIN, INT64_MAX , PARAM, "channel_layout"}, -{"in_channel_layout" , "set input channel layout" , OFFSET(user_in_ch_layout ), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0 }, INT64_MIN, INT64_MAX , PARAM, "channel_layout"}, -{"ocl" , "set output channel layout" , OFFSET(user_out_ch_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0 }, INT64_MIN, INT64_MAX , PARAM, "channel_layout"}, -{"out_channel_layout" , "set output channel layout" , OFFSET(user_out_ch_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0 }, INT64_MIN, INT64_MAX , PARAM, "channel_layout"}, +#if FF_API_OLD_CHANNEL_LAYOUT +{"icl" , "set input channel layout (Deprecated, use ichl)", + OFFSET(user_in_ch_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0 }, INT64_MIN, INT64_MAX, PARAM|DEPREC, "channel_layout"}, +{"in_channel_layout" , "set input channel layout (Deprecated, use in_chlayout)", + OFFSET(user_in_ch_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0 }, INT64_MIN, INT64_MAX, PARAM|DEPREC, "channel_layout"}, +{"ocl" , "set output channel layout (Deprecated, use ochl)", + OFFSET(user_out_ch_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0 }, INT64_MIN, INT64_MAX, PARAM|DEPREC, "channel_layout"}, +{"out_channel_layout" , "set output channel layout (Deprecated, use out_chlayout)", + OFFSET(user_out_ch_layout), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=0 }, INT64_MIN, INT64_MAX, PARAM|DEPREC, "channel_layout"}, +#endif +{"ichl" , "set input channel layout" , OFFSET(user_in_chlayout ), AV_OPT_TYPE_CHLAYOUT, {.str=NULL }, 0, 0 , PARAM, "chlayout"}, +{"in_chlayout" , "set input channel layout" , OFFSET(user_in_chlayout ), AV_OPT_TYPE_CHLAYOUT, {.str=NULL }, 0, 0 , PARAM, "chlayout"}, +{"ochl" , "set output channel layout" , OFFSET(user_out_chlayout), AV_OPT_TYPE_CHLAYOUT, {.str=NULL }, 0, 0 , PARAM, "chlayout"}, +{"out_chlayout" , "set output channel layout" , OFFSET(user_out_chlayout), AV_OPT_TYPE_CHLAYOUT, {.str=NULL }, 0, 0 , PARAM, "chlayout"}, {"clev" , "set center mix level" , OFFSET(clev ), AV_OPT_TYPE_FLOAT, {.dbl=C_30DB }, -32 , 32 , PARAM}, {"center_mix_level" , "set center mix level" , OFFSET(clev ), AV_OPT_TYPE_FLOAT, {.dbl=C_30DB }, -32 , 32 , PARAM}, {"slev" , "set surround mix level" , OFFSET(slev ), AV_OPT_TYPE_FLOAT, {.dbl=C_30DB }, -32 , 32 , PARAM}, diff --git a/libswresample/rematrix.c b/libswresample/rematrix.c index 94b3de88f..fe823dc57 100644 --- a/libswresample/rematrix.c +++ b/libswresample/rematrix.c @@ -64,15 +64,37 @@ int swr_set_matrix(struct SwrContext *s, const double *matrix, int stride) { int nb_in, nb_out, in, out; + int user_in_chlayout_nb_channels, user_out_chlayout_nb_channels; if (!s || s->in_convert) // s needs to be allocated but not initialized return AVERROR(EINVAL); memset(s->matrix, 0, sizeof(s->matrix)); memset(s->matrix_flt, 0, sizeof(s->matrix_flt)); - 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); + +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + user_in_chlayout_nb_channels = av_get_channel_layout_nb_channels(s->user_in_ch_layout); +FF_ENABLE_DEPRECATION_WARNINGS + if (!user_in_chlayout_nb_channels) +#endif + user_in_chlayout_nb_channels = s->user_in_chlayout.nb_channels; + nb_in = +#if FF_API_OLD_CHANNEL_LAYOUT + (s->user_in_ch_count > 0) ? s->user_in_ch_count : +#endif + user_in_chlayout_nb_channels; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + user_out_chlayout_nb_channels = av_get_channel_layout_nb_channels(s->user_out_ch_layout); +FF_ENABLE_DEPRECATION_WARNINGS + if (!user_out_chlayout_nb_channels) +#endif + user_out_chlayout_nb_channels = s->user_out_chlayout.nb_channels; + nb_out = +#if FF_API_OLD_CHANNEL_LAYOUT + (s->user_out_ch_count > 0) ? s->user_out_ch_count : +#endif + user_out_chlayout_nb_channels; 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]; @@ -88,95 +110,140 @@ static int even(int64_t layout){ return 0; } -static int64_t clean_layout(void *s, int64_t layout){ - if(layout && layout != AV_CH_FRONT_CENTER && !(layout&(layout-1))) { - char buf[128]; - av_get_channel_layout_string(buf, sizeof(buf), -1, layout); - av_log(s, AV_LOG_VERBOSE, "Treating %s as mono\n", buf); - return AV_CH_FRONT_CENTER; - } +static int clean_layout(AVChannelLayout *out, const AVChannelLayout *in, void *s) +{ + int ret = 0; - return layout; + if (av_channel_layout_index_from_channel(in, AV_CHAN_FRONT_CENTER) < 0 && in->nb_channels == 1) { + char buf[128]; + av_channel_layout_describe(in, buf, sizeof(buf)); + av_log(s, AV_LOG_VERBOSE, "Treating %s as mono\n", buf); + *out = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; + } else + ret = av_channel_layout_copy(out, in); + + return ret; } -static int sane_layout(int64_t layout){ - if(!(layout & AV_CH_LAYOUT_SURROUND)) // at least 1 front speaker +static int sane_layout(AVChannelLayout *ch_layout) { + if (ch_layout->order != AV_CHANNEL_ORDER_NATIVE) return 0; - if(!even(layout & (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT))) // no asymetric front + if(!av_channel_layout_subset(ch_layout, AV_CH_LAYOUT_SURROUND)) // at least 1 front speaker return 0; - if(!even(layout & (AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT))) // no asymetric side + if(!even(av_channel_layout_subset(ch_layout, (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT)))) // no asymetric front return 0; - if(!even(layout & (AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT))) + if(!even(av_channel_layout_subset(ch_layout, (AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT)))) // no asymetric side return 0; - if(!even(layout & (AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER))) + if(!even(av_channel_layout_subset(ch_layout, (AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT)))) return 0; - if(av_get_channel_layout_nb_channels(layout) >= SWR_CH_MAX) + if(!even(av_channel_layout_subset(ch_layout, (AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER)))) + return 0; + if(ch_layout->nb_channels >= SWR_CH_MAX) return 0; return 1; } +#if FF_API_OLD_CHANNEL_LAYOUT av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout_param, double center_mix_level, double surround_mix_level, double lfe_mix_level, double maxval, double rematrix_volume, double *matrix_param, int stride, enum AVMatrixEncoding matrix_encoding, void *log_context) { - int i, j, out_i; + AVChannelLayout in_ch_layout = { 0 }, out_ch_layout = { 0 }; + int ret; + + ret = av_channel_layout_from_mask(&in_ch_layout, in_ch_layout_param); + ret |= av_channel_layout_from_mask(&out_ch_layout, out_ch_layout_param); + if (ret < 0) + return ret; + + return swr_build_matrix2(&in_ch_layout, &out_ch_layout, center_mix_level, surround_mix_level, + lfe_mix_level, maxval, rematrix_volume, matrix_param, + stride, matrix_encoding, log_context); +} +#endif + +av_cold int swr_build_matrix2(const AVChannelLayout *in_layout, const AVChannelLayout *out_layout, + double center_mix_level, double surround_mix_level, + double lfe_mix_level, double maxval, + double rematrix_volume, double *matrix_param, + ptrdiff_t stride, enum AVMatrixEncoding matrix_encoding, void *log_context) +{ + int i, j, out_i, ret; + AVChannelLayout in_ch_layout = { 0 }, out_ch_layout = { 0 }; double matrix[NUM_NAMED_CHANNELS][NUM_NAMED_CHANNELS]={{0}}; - int64_t unaccounted, in_ch_layout, out_ch_layout; + int64_t unaccounted; double maxcoef=0; char buf[128]; - in_ch_layout = clean_layout(log_context, in_ch_layout_param); - out_ch_layout = clean_layout(log_context, out_ch_layout_param); + ret = clean_layout(&in_ch_layout, in_layout, log_context); + ret |= clean_layout(&out_ch_layout, out_layout, log_context); + if (ret < 0) + goto fail; - if( out_ch_layout == AV_CH_LAYOUT_STEREO_DOWNMIX - && (in_ch_layout & AV_CH_LAYOUT_STEREO_DOWNMIX) == 0 - ) - out_ch_layout = AV_CH_LAYOUT_STEREO; - - if( in_ch_layout == AV_CH_LAYOUT_STEREO_DOWNMIX - && (out_ch_layout & AV_CH_LAYOUT_STEREO_DOWNMIX) == 0 - ) - in_ch_layout = AV_CH_LAYOUT_STEREO; - - if (in_ch_layout == AV_CH_LAYOUT_22POINT2 && - out_ch_layout != AV_CH_LAYOUT_22POINT2) { - in_ch_layout = (AV_CH_LAYOUT_7POINT1_WIDE_BACK|AV_CH_BACK_CENTER); - av_get_channel_layout_string(buf, sizeof(buf), -1, in_ch_layout); + if( !av_channel_layout_compare(&out_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO_DOWNMIX) + && !av_channel_layout_subset(&in_ch_layout, AV_CH_LAYOUT_STEREO_DOWNMIX) + ) { + av_channel_layout_uninit(&out_ch_layout); + out_ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; + } + if( !av_channel_layout_compare(&in_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO_DOWNMIX) + && !av_channel_layout_subset(&out_ch_layout, AV_CH_LAYOUT_STEREO_DOWNMIX) + ) { + av_channel_layout_uninit(&in_ch_layout); + in_ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO; + } + if (!av_channel_layout_compare(&in_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_22POINT2) && + av_channel_layout_compare(&out_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_22POINT2)) { + av_channel_layout_from_mask(&in_ch_layout, (AV_CH_LAYOUT_7POINT1_WIDE_BACK|AV_CH_BACK_CENTER)); + av_channel_layout_describe(&in_ch_layout, buf, sizeof(buf)); av_log(log_context, AV_LOG_WARNING, "Full-on remixing from 22.2 has not yet been implemented! " "Processing the input as '%s'\n", buf); } - if(!sane_layout(in_ch_layout)){ - av_get_channel_layout_string(buf, sizeof(buf), -1, in_ch_layout_param); + if(!av_channel_layout_check(&in_ch_layout)) { + av_log(log_context, AV_LOG_ERROR, "Input channel layout is invalid\n"); + ret = AVERROR(EINVAL); + goto fail; + } + if(!sane_layout(&in_ch_layout)) { + av_channel_layout_describe(&in_ch_layout, buf, sizeof(buf)); av_log(log_context, AV_LOG_ERROR, "Input channel layout '%s' is not supported\n", buf); - return AVERROR(EINVAL); + ret = AVERROR(EINVAL); + goto fail; } - if(!sane_layout(out_ch_layout)){ - av_get_channel_layout_string(buf, sizeof(buf), -1, out_ch_layout_param); + if(!av_channel_layout_check(&out_ch_layout)) { + av_log(log_context, AV_LOG_ERROR, "Output channel layout is invalid\n"); + ret = AVERROR(EINVAL); + goto fail; + } + if(!sane_layout(&out_ch_layout)) { + av_channel_layout_describe(&out_ch_layout, buf, sizeof(buf)); av_log(log_context, AV_LOG_ERROR, "Output channel layout '%s' is not supported\n", buf); - return AVERROR(EINVAL); + ret = AVERROR(EINVAL); + goto fail; } for(i=0; i= 0 + && av_channel_layout_index_from_channel(&out_ch_layout, i) >= 0) matrix[i][i]= 1.0; } - unaccounted= in_ch_layout & ~out_ch_layout; + unaccounted = in_ch_layout.u.mask & ~out_ch_layout.u.mask; //FIXME implement dolby surround //FIXME implement full ac3 if(unaccounted & AV_CH_FRONT_CENTER){ - if((out_ch_layout & AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO){ - if(in_ch_layout & AV_CH_LAYOUT_STEREO) { + if (av_channel_layout_subset(&out_ch_layout, AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO) { + if (av_channel_layout_subset(&in_ch_layout, AV_CH_LAYOUT_STEREO)) { matrix[ FRONT_LEFT][FRONT_CENTER]+= center_mix_level; matrix[FRONT_RIGHT][FRONT_CENTER]+= center_mix_level; } else { @@ -187,23 +254,23 @@ av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout av_assert0(0); } if(unaccounted & AV_CH_LAYOUT_STEREO){ - if(out_ch_layout & AV_CH_FRONT_CENTER){ + if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0) { matrix[FRONT_CENTER][ FRONT_LEFT]+= M_SQRT1_2; matrix[FRONT_CENTER][FRONT_RIGHT]+= M_SQRT1_2; - if(in_ch_layout & AV_CH_FRONT_CENTER) + if (av_channel_layout_index_from_channel(&in_ch_layout, AV_CHAN_FRONT_CENTER) >= 0) matrix[FRONT_CENTER][ FRONT_CENTER] = center_mix_level*sqrt(2); }else av_assert0(0); } if(unaccounted & AV_CH_BACK_CENTER){ - if(out_ch_layout & AV_CH_BACK_LEFT){ + if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_BACK_LEFT) >= 0) { matrix[ BACK_LEFT][BACK_CENTER]+= M_SQRT1_2; matrix[BACK_RIGHT][BACK_CENTER]+= M_SQRT1_2; - }else if(out_ch_layout & AV_CH_SIDE_LEFT){ + } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_SIDE_LEFT) >= 0) { matrix[ SIDE_LEFT][BACK_CENTER]+= M_SQRT1_2; matrix[SIDE_RIGHT][BACK_CENTER]+= M_SQRT1_2; - }else if(out_ch_layout & AV_CH_FRONT_LEFT){ + } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_LEFT) >= 0) { if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY || matrix_encoding == AV_MATRIX_ENCODING_DPLII) { if (unaccounted & (AV_CH_BACK_LEFT | AV_CH_SIDE_LEFT)) { @@ -217,24 +284,24 @@ av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout matrix[ FRONT_LEFT][BACK_CENTER]+= surround_mix_level * M_SQRT1_2; matrix[FRONT_RIGHT][BACK_CENTER]+= surround_mix_level * M_SQRT1_2; } - }else if(out_ch_layout & AV_CH_FRONT_CENTER){ + } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0) { matrix[ FRONT_CENTER][BACK_CENTER]+= surround_mix_level * M_SQRT1_2; }else av_assert0(0); } if(unaccounted & AV_CH_BACK_LEFT){ - if(out_ch_layout & AV_CH_BACK_CENTER){ + if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_BACK_CENTER) >= 0) { matrix[BACK_CENTER][ BACK_LEFT]+= M_SQRT1_2; matrix[BACK_CENTER][BACK_RIGHT]+= M_SQRT1_2; - }else if(out_ch_layout & AV_CH_SIDE_LEFT){ - if(in_ch_layout & AV_CH_SIDE_LEFT){ + } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_SIDE_LEFT) >= 0) { + if (av_channel_layout_index_from_channel(&in_ch_layout, AV_CHAN_SIDE_LEFT) >= 0) { matrix[ SIDE_LEFT][ BACK_LEFT]+= M_SQRT1_2; matrix[SIDE_RIGHT][BACK_RIGHT]+= M_SQRT1_2; }else{ matrix[ SIDE_LEFT][ BACK_LEFT]+= 1.0; matrix[SIDE_RIGHT][BACK_RIGHT]+= 1.0; } - }else if(out_ch_layout & AV_CH_FRONT_LEFT){ + } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_LEFT) >= 0) { if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) { matrix[FRONT_LEFT ][BACK_LEFT ] -= surround_mix_level * M_SQRT1_2; matrix[FRONT_LEFT ][BACK_RIGHT] -= surround_mix_level * M_SQRT1_2; @@ -249,7 +316,7 @@ av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout matrix[ FRONT_LEFT][ BACK_LEFT] += surround_mix_level; matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level; } - }else if(out_ch_layout & AV_CH_FRONT_CENTER){ + } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0) { matrix[ FRONT_CENTER][BACK_LEFT ]+= surround_mix_level*M_SQRT1_2; matrix[ FRONT_CENTER][BACK_RIGHT]+= surround_mix_level*M_SQRT1_2; }else @@ -257,20 +324,20 @@ av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout } if(unaccounted & AV_CH_SIDE_LEFT){ - if(out_ch_layout & AV_CH_BACK_LEFT){ + if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_BACK_LEFT) >= 0) { /* if back channels do not exist in the input, just copy side channels to back channels, otherwise mix side into back */ - if (in_ch_layout & AV_CH_BACK_LEFT) { + if (av_channel_layout_index_from_channel(&in_ch_layout, AV_CHAN_BACK_LEFT) >= 0) { matrix[BACK_LEFT ][SIDE_LEFT ] += M_SQRT1_2; matrix[BACK_RIGHT][SIDE_RIGHT] += M_SQRT1_2; } else { matrix[BACK_LEFT ][SIDE_LEFT ] += 1.0; matrix[BACK_RIGHT][SIDE_RIGHT] += 1.0; } - }else if(out_ch_layout & AV_CH_BACK_CENTER){ + } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_BACK_CENTER) >= 0) { matrix[BACK_CENTER][ SIDE_LEFT]+= M_SQRT1_2; matrix[BACK_CENTER][SIDE_RIGHT]+= M_SQRT1_2; - }else if(out_ch_layout & AV_CH_FRONT_LEFT){ + } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_LEFT) >= 0) { if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) { matrix[FRONT_LEFT ][SIDE_LEFT ] -= surround_mix_level * M_SQRT1_2; matrix[FRONT_LEFT ][SIDE_RIGHT] -= surround_mix_level * M_SQRT1_2; @@ -285,7 +352,7 @@ av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout matrix[ FRONT_LEFT][ SIDE_LEFT] += surround_mix_level; matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level; } - }else if(out_ch_layout & AV_CH_FRONT_CENTER){ + } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0) { matrix[ FRONT_CENTER][SIDE_LEFT ]+= surround_mix_level * M_SQRT1_2; matrix[ FRONT_CENTER][SIDE_RIGHT]+= surround_mix_level * M_SQRT1_2; }else @@ -293,10 +360,10 @@ av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout } if(unaccounted & AV_CH_FRONT_LEFT_OF_CENTER){ - if(out_ch_layout & AV_CH_FRONT_LEFT){ + if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_LEFT) >= 0) { matrix[ FRONT_LEFT][ FRONT_LEFT_OF_CENTER]+= 1.0; matrix[FRONT_RIGHT][FRONT_RIGHT_OF_CENTER]+= 1.0; - }else if(out_ch_layout & AV_CH_FRONT_CENTER){ + } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0) { matrix[ FRONT_CENTER][ FRONT_LEFT_OF_CENTER]+= M_SQRT1_2; matrix[ FRONT_CENTER][FRONT_RIGHT_OF_CENTER]+= M_SQRT1_2; }else @@ -304,9 +371,9 @@ av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout } /* mix LFE into front left/right or center */ if (unaccounted & AV_CH_LOW_FREQUENCY) { - if (out_ch_layout & AV_CH_FRONT_CENTER) { + if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_CENTER) >= 0) { matrix[FRONT_CENTER][LOW_FREQUENCY] += lfe_mix_level; - } else if (out_ch_layout & AV_CH_FRONT_LEFT) { + } else if (av_channel_layout_index_from_channel(&out_ch_layout, AV_CHAN_FRONT_LEFT) >= 0) { matrix[FRONT_LEFT ][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2; matrix[FRONT_RIGHT][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2; } else @@ -316,15 +383,17 @@ av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout for(out_i=i=0; i<64; i++){ double sum=0; int in_i=0; - if((out_ch_layout & (1ULL<= 0 + && av_channel_layout_index_from_channel(&out_ch_layout, i) >= 0); sum += fabs(matrix_param[stride*out_i + in_i]); in_i++; } @@ -350,17 +419,22 @@ av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout } av_log(log_context, AV_LOG_DEBUG, "Matrix coefficients:\n"); - for(i=0; imatrix, 0, sizeof(s->matrix)); - ret = swr_build_matrix(s->in_ch_layout, s->out_ch_layout, + ret = swr_build_matrix2(&s->in_ch_layout, &s->out_ch_layout, s->clev, s->slev, s->lfe_mix_level, maxval, s->rematrix_volume, (double*)s->matrix, s->matrix[1] - s->matrix[0], s->matrix_encoding, s); @@ -491,8 +565,9 @@ av_cold int swri_rematrix_init(SwrContext *s){ s->matrix_ch[i][0]= ch_in; } - if(HAVE_X86ASM && HAVE_MMX) - return swri_rematrix_init_x86(s); +#if ARCH_X86 && HAVE_X86ASM && HAVE_MMX + return swri_rematrix_init_x86(s); +#endif return 0; } @@ -519,8 +594,8 @@ int swri_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mus off = len1 * out->bps; } - av_assert0(!s->out_ch_layout || out->ch_count == av_get_channel_layout_nb_channels(s->out_ch_layout)); - av_assert0(!s-> in_ch_layout || in ->ch_count == av_get_channel_layout_nb_channels(s-> in_ch_layout)); + av_assert0(s->out_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC || out->ch_count == s->out_ch_layout.nb_channels); + av_assert0(s-> in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC || in ->ch_count == s->in_ch_layout.nb_channels); for(out_i=0; out_ich_count; out_i++){ switch(s->matrix_ch[out_i][0]){ diff --git a/libswresample/rematrix_template.c b/libswresample/rematrix_template.c index add65e315..d4726c4db 100644 --- a/libswresample/rematrix_template.c +++ b/libswresample/rematrix_template.c @@ -88,13 +88,16 @@ static void RENAME(mix8to2)(SAMPLE **out, const SAMPLE **in, COEFF *coeffp, inte } static RENAME(mix_any_func_type) *RENAME(get_mix_any_func)(SwrContext *s){ - if( s->out_ch_layout == AV_CH_LAYOUT_STEREO && (s->in_ch_layout == AV_CH_LAYOUT_5POINT1 || s->in_ch_layout == AV_CH_LAYOUT_5POINT1_BACK) + if ( !av_channel_layout_compare(&s->out_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO) + && ( !av_channel_layout_compare(&s->in_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1) + || !av_channel_layout_compare(&s->in_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1_BACK)) && s->matrix[0][2] == s->matrix[1][2] && s->matrix[0][3] == s->matrix[1][3] && !s->matrix[0][1] && !s->matrix[0][5] && !s->matrix[1][0] && !s->matrix[1][4] ) return RENAME(mix6to2); - if( s->out_ch_layout == AV_CH_LAYOUT_STEREO && s->in_ch_layout == AV_CH_LAYOUT_7POINT1 + if ( !av_channel_layout_compare(&s->out_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO) + && !av_channel_layout_compare(&s->in_ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_7POINT1) && s->matrix[0][2] == s->matrix[1][2] && s->matrix[0][3] == s->matrix[1][3] && !s->matrix[0][1] && !s->matrix[0][5] && !s->matrix[1][0] && !s->matrix[1][4] && !s->matrix[0][7] && !s->matrix[1][6] diff --git a/libswresample/resample.c b/libswresample/resample.c index f1ec77f54..8f9efc3f2 100644 --- a/libswresample/resample.c +++ b/libswresample/resample.c @@ -452,9 +452,6 @@ static int set_compensation(ResampleContext *c, int sample_delta, int compensati static int multiple_resample(ResampleContext *c, AudioData *dst, int dst_size, AudioData *src, int src_size, int *consumed){ int i; - int av_unused mm_flags = av_get_cpu_flags(); - int need_emms = c->format == AV_SAMPLE_FMT_S16P && ARCH_X86_32 && - (mm_flags & (AV_CPU_FLAG_MMX2 | AV_CPU_FLAG_SSE2)) == AV_CPU_FLAG_MMX2; int64_t max_src_size = (INT64_MAX/2 / c->phase_count) / c->src_incr; if (c->compensation_distance) @@ -500,9 +497,6 @@ static int multiple_resample(ResampleContext *c, AudioData *dst, int dst_size, A } } - if(need_emms) - emms_c(); - if (c->compensation_distance) { c->compensation_distance -= dst_size; if (!c->compensation_distance) { diff --git a/libswresample/resample_dsp.c b/libswresample/resample_dsp.c index b2424eb6f..611f44373 100644 --- a/libswresample/resample_dsp.c +++ b/libswresample/resample_dsp.c @@ -68,7 +68,11 @@ void swri_resample_dsp_init(ResampleContext *c) break; } - if (ARCH_X86) swri_resample_dsp_x86_init(c); - else if (ARCH_ARM) swri_resample_dsp_arm_init(c); - else if (ARCH_AARCH64) swri_resample_dsp_aarch64_init(c); +#if ARCH_X86 + swri_resample_dsp_x86_init(c); +#elif ARCH_ARM + swri_resample_dsp_arm_init(c); +#elif ARCH_AARCH64 + swri_resample_dsp_aarch64_init(c); +#endif } diff --git a/libswresample/swresample.c b/libswresample/swresample.c index 16734c9df..9b77ef65b 100644 --- a/libswresample/swresample.c +++ b/libswresample/swresample.c @@ -29,26 +29,6 @@ #define ALIGN 32 -#include "libavutil/ffversion.h" -const char swr_ffversion[] = "FFmpeg version " FFMPEG_VERSION; - -unsigned swresample_version(void) -{ - av_assert0(LIBSWRESAMPLE_VERSION_MICRO >= 100); - return LIBSWRESAMPLE_VERSION_INT; -} - -const char *swresample_configuration(void) -{ - return FFMPEG_CONFIGURATION; -} - -const char *swresample_license(void) -{ -#define LICENSE_PREFIX "libswresample license: " - return &LICENSE_PREFIX FFMPEG_LICENSE[sizeof(LICENSE_PREFIX) - 1]; -} - int swr_set_channel_mapping(struct SwrContext *s, const int *channel_map){ if(!s || s->in_convert) // s needs to be allocated but not initialized return AVERROR(EINVAL); @@ -56,6 +36,8 @@ int swr_set_channel_mapping(struct SwrContext *s, const int *channel_map){ return 0; } +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS struct SwrContext *swr_alloc_set_opts(struct SwrContext *s, int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate, int64_t in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate, @@ -97,6 +79,58 @@ fail: swr_free(&s); return NULL; } +FF_ENABLE_DEPRECATION_WARNINGS +#endif + +int swr_alloc_set_opts2(struct SwrContext **ps, + AVChannelLayout *out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate, + AVChannelLayout *in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate, + int log_offset, void *log_ctx) { + struct SwrContext *s = *ps; + int ret; + + if (!s) s = swr_alloc(); + if (!s) return AVERROR(ENOMEM); + + *ps = s; + + s->log_level_offset = log_offset; + s->log_ctx = log_ctx; + + if ((ret = av_opt_set_chlayout(s, "ochl", out_ch_layout, 0)) < 0) + goto fail; + + if ((ret = av_opt_set_int(s, "osf", out_sample_fmt, 0)) < 0) + goto fail; + + if ((ret = av_opt_set_int(s, "osr", out_sample_rate, 0)) < 0) + goto fail; + + if ((ret = av_opt_set_chlayout(s, "ichl", in_ch_layout, 0)) < 0) + goto fail; + + if ((ret = av_opt_set_int(s, "isf", in_sample_fmt, 0)) < 0) + goto fail; + + if ((ret = av_opt_set_int(s, "isr", in_sample_rate, 0)) < 0) + goto fail; + + av_opt_set_int(s, "uch", 0, 0); + +#if FF_API_OLD_CHANNEL_LAYOUT + // Clear old API values so they don't take precedence in swr_init() + av_opt_set_int(s, "icl", 0, 0); + av_opt_set_int(s, "ocl", 0, 0); + av_opt_set_int(s, "ich", 0, 0); + av_opt_set_int(s, "och", 0, 0); +#endif + + return 0; +fail: + av_log(s, AV_LOG_ERROR, "Failed to set option\n"); + swr_free(ps); + return ret; +} static void set_audiodata_fmt(AudioData *a, enum AVSampleFormat fmt){ a->fmt = fmt; @@ -125,6 +159,8 @@ static void clear_context(SwrContext *s){ free_temp(&s->drop_temp); free_temp(&s->dither.noise); free_temp(&s->dither.temp); + av_channel_layout_uninit(&s->in_ch_layout); + av_channel_layout_uninit(&s->out_ch_layout); swri_audio_convert_free(&s-> in_convert); swri_audio_convert_free(&s->out_convert); swri_audio_convert_free(&s->full_convert); @@ -138,6 +174,9 @@ av_cold void swr_free(SwrContext **ss){ SwrContext *s= *ss; if(s){ clear_context(s); + av_channel_layout_uninit(&s->user_in_chlayout); + av_channel_layout_uninit(&s->user_out_chlayout); + if (s->resampler) s->resampler->free(&s->resample); } @@ -172,25 +211,66 @@ av_cold int swr_init(struct SwrContext *s){ av_log(s, AV_LOG_ERROR, "Requested output sample rate %d is invalid\n", s->out_sample_rate); return AVERROR(EINVAL); } + s->used_ch_count = s->user_used_ch_count; +#if FF_API_OLD_CHANNEL_LAYOUT s->out.ch_count = s-> user_out_ch_count; s-> in.ch_count = s-> user_in_ch_count; - s->used_ch_count = s->user_used_ch_count; - s-> in_ch_layout = s-> user_in_ch_layout; - s->out_ch_layout = s->user_out_ch_layout; + // if the old/new fields are set inconsistently, prefer the old ones + if ((s->user_in_ch_count && s->user_in_ch_count != s->user_in_chlayout.nb_channels) || + (s->user_in_ch_layout && (s->user_in_chlayout.order != AV_CHANNEL_ORDER_NATIVE || + s->user_in_chlayout.u.mask != s->user_in_ch_layout))) { + av_channel_layout_uninit(&s->in_ch_layout); + if (s->user_in_ch_layout) + av_channel_layout_from_mask(&s->in_ch_layout, s->user_in_ch_layout); + else { + s->in_ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + s->in_ch_layout.nb_channels = s->user_in_ch_count; + } + } else + av_channel_layout_copy(&s->in_ch_layout, &s->user_in_chlayout); + + if ((s->user_out_ch_count && s->user_out_ch_count != s->user_out_chlayout.nb_channels) || + (s->user_out_ch_layout && (s->user_out_chlayout.order != AV_CHANNEL_ORDER_NATIVE || + s->user_out_chlayout.u.mask != s->user_out_ch_layout))) { + av_channel_layout_uninit(&s->out_ch_layout); + if (s->user_out_ch_layout) + av_channel_layout_from_mask(&s->out_ch_layout, s->user_out_ch_layout); + else { + s->out_ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + s->out_ch_layout.nb_channels = s->user_out_ch_count; + } + } else + av_channel_layout_copy(&s->out_ch_layout, &s->user_out_chlayout); + + if (!s->out.ch_count && !s->user_out_ch_layout) + s->out.ch_count = s->out_ch_layout.nb_channels; + if (!s-> in.ch_count && !s-> user_in_ch_layout) + s-> in.ch_count = s->in_ch_layout.nb_channels; +#else + s->out.ch_count = s-> user_out_chlayout.nb_channels; + s-> in.ch_count = s-> user_in_chlayout.nb_channels; + + ret = av_channel_layout_copy(&s->in_ch_layout, &s->user_in_chlayout); + ret |= av_channel_layout_copy(&s->out_ch_layout, &s->user_out_chlayout); + if (ret < 0) + return ret; +#endif s->int_sample_fmt= s->user_int_sample_fmt; s->dither.method = s->user_dither_method; - if(av_get_channel_layout_nb_channels(s-> in_ch_layout) > SWR_CH_MAX) { - av_log(s, AV_LOG_WARNING, "Input channel layout 0x%"PRIx64" is invalid or unsupported.\n", s-> in_ch_layout); - s->in_ch_layout = 0; + if (!av_channel_layout_check(&s->in_ch_layout) || s->in_ch_layout.nb_channels > SWR_CH_MAX) { + av_channel_layout_describe(&s->in_ch_layout, l1, sizeof(l1)); + av_log(s, AV_LOG_WARNING, "Input channel layout \"%s\" is invalid or unsupported.\n", l1); + av_channel_layout_uninit(&s->in_ch_layout); } - if(av_get_channel_layout_nb_channels(s->out_ch_layout) > SWR_CH_MAX) { - av_log(s, AV_LOG_WARNING, "Output channel layout 0x%"PRIx64" is invalid or unsupported.\n", s->out_ch_layout); - s->out_ch_layout = 0; + if (!av_channel_layout_check(&s->out_ch_layout) || s->out_ch_layout.nb_channels > SWR_CH_MAX) { + av_channel_layout_describe(&s->out_ch_layout, l2, sizeof(l2)); + av_log(s, AV_LOG_WARNING, "Output channel layout \"%s\" is invalid or unsupported.\n", l2); + av_channel_layout_uninit(&s->out_ch_layout); } switch(s->engine){ @@ -206,17 +286,18 @@ av_cold int swr_init(struct SwrContext *s){ if(!s->used_ch_count) s->used_ch_count= s->in.ch_count; - if(s->used_ch_count && s-> in_ch_layout && s->used_ch_count != av_get_channel_layout_nb_channels(s-> in_ch_layout)){ + if (s->used_ch_count && s->in_ch_layout.order != AV_CHANNEL_ORDER_UNSPEC && s->used_ch_count != s->in_ch_layout.nb_channels) { av_log(s, AV_LOG_WARNING, "Input channel layout has a different number of channels than the number of used channels, ignoring layout\n"); - s-> in_ch_layout= 0; + av_channel_layout_uninit(&s->in_ch_layout); } - if(!s-> in_ch_layout) - s-> in_ch_layout= av_get_default_channel_layout(s->used_ch_count); - if(!s->out_ch_layout) - s->out_ch_layout= av_get_default_channel_layout(s->out.ch_count); + if (!s->in_ch_layout.nb_channels || s->in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) + av_channel_layout_default(&s->in_ch_layout, s->used_ch_count); + if (!s->out_ch_layout.nb_channels || s->out_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) + av_channel_layout_default(&s->out_ch_layout, s->out.ch_count); - s->rematrix= s->out_ch_layout !=s->in_ch_layout || s->rematrix_volume!=1.0 || + s->rematrix = av_channel_layout_compare(&s->out_ch_layout, &s->in_ch_layout) || + s->rematrix_volume!=1.0 || s->rematrix_custom; if(s->int_sample_fmt == AV_SAMPLE_FMT_NONE){ @@ -291,33 +372,36 @@ av_cold int swr_init(struct SwrContext *s){ #define RSC 1 //FIXME finetune if(!s-> in.ch_count) - s-> in.ch_count= av_get_channel_layout_nb_channels(s-> in_ch_layout); + s-> in.ch_count = s->in_ch_layout.nb_channels; if(!s->used_ch_count) s->used_ch_count= s->in.ch_count; if(!s->out.ch_count) - s->out.ch_count= av_get_channel_layout_nb_channels(s->out_ch_layout); + s->out.ch_count = s->out_ch_layout.nb_channels; if(!s-> in.ch_count){ - av_assert0(!s->in_ch_layout); + av_assert0(s->in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC); av_log(s, AV_LOG_ERROR, "Input channel count and layout are unset\n"); ret = AVERROR(EINVAL); goto fail; } - av_get_channel_layout_string(l1, sizeof(l1), s-> in.ch_count, s-> in_ch_layout); - av_get_channel_layout_string(l2, sizeof(l2), s->out.ch_count, s->out_ch_layout); - if (s->out_ch_layout && s->out.ch_count != av_get_channel_layout_nb_channels(s->out_ch_layout)) { +#if FF_API_OLD_CHANNEL_LAYOUT + av_channel_layout_describe(&s->out_ch_layout, l1, sizeof(l1)); + if (s->out_ch_layout.order != AV_CHANNEL_ORDER_UNSPEC && s->out.ch_count != s->out_ch_layout.nb_channels) { av_log(s, AV_LOG_ERROR, "Output channel layout %s mismatches specified channel count %d\n", l2, s->out.ch_count); ret = AVERROR(EINVAL); goto fail; } - if (s->in_ch_layout && s->used_ch_count != av_get_channel_layout_nb_channels(s->in_ch_layout)) { +#endif + av_channel_layout_describe(&s->in_ch_layout, l1, sizeof(l1)); + if (s->in_ch_layout.order != AV_CHANNEL_ORDER_UNSPEC && s->used_ch_count != s->in_ch_layout.nb_channels) { av_log(s, AV_LOG_ERROR, "Input channel layout %s mismatches specified channel count %d\n", l1, s->used_ch_count); ret = AVERROR(EINVAL); goto fail; } - if ((!s->out_ch_layout || !s->in_ch_layout) && s->used_ch_count != s->out.ch_count && !s->rematrix_custom) { + if (( s->out_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC + || s-> in_ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) && s->used_ch_count != s->out.ch_count && !s->rematrix_custom) { av_log(s, AV_LOG_ERROR, "Rematrix is needed between %s and %s " "but there is not enough information to do it\n", l1, l2); ret = AVERROR(EINVAL); diff --git a/libswresample/swresample.h b/libswresample/swresample.h index c7b84fbca..26d42fab8 100644 --- a/libswresample/swresample.h +++ b/libswresample/swresample.h @@ -34,11 +34,11 @@ * Audio resampling, sample format conversion and mixing library. * * Interaction with lswr is done through SwrContext, which is - * allocated with swr_alloc() or swr_alloc_set_opts(). It is opaque, so all parameters + * allocated with swr_alloc() or swr_alloc_set_opts2(). It is opaque, so all parameters * must be set with the @ref avoptions API. * * The first thing you will need to do in order to use lswr is to allocate - * SwrContext. This can be done with swr_alloc() or swr_alloc_set_opts(). If you + * SwrContext. This can be done with swr_alloc() or swr_alloc_set_opts2(). If you * are using the former, you must set options through the @ref avoptions API. * The latter function provides the same feature, but it allows you to set some * common options in the same statement. @@ -57,13 +57,14 @@ * av_opt_set_sample_fmt(swr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0); * @endcode * - * The same job can be done using swr_alloc_set_opts() as well: + * The same job can be done using swr_alloc_set_opts2() as well: * @code - * SwrContext *swr = swr_alloc_set_opts(NULL, // we're allocating a new context - * AV_CH_LAYOUT_STEREO, // out_ch_layout + * SwrContext *swr = NULL; + * int ret = swr_alloc_set_opts2(&swr, // we're allocating a new context + * &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO, // out_ch_layout * AV_SAMPLE_FMT_S16, // out_sample_fmt * 44100, // out_sample_rate - * AV_CH_LAYOUT_5POINT1, // in_ch_layout + * &(AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT1, // in_ch_layout * AV_SAMPLE_FMT_FLTP, // in_sample_fmt * 48000, // in_sample_rate * 0, // log_offset @@ -73,7 +74,7 @@ * Once all values have been set, it must be initialized with swr_init(). If * you need to change the conversion parameters, you can change the parameters * using @ref AVOptions, as described above in the first example; or by using - * swr_alloc_set_opts(), but with the first argument the allocated context. + * swr_alloc_set_opts2(), but with the first argument the allocated context. * You must then call swr_init() again. * * The conversion itself is done by repeatedly calling swr_convert(). @@ -124,7 +125,13 @@ #include "libavutil/frame.h" #include "libavutil/samplefmt.h" +#include "libswresample/version_major.h" +#ifndef HAVE_AV_CONFIG_H +/* When included as part of the ffmpeg build, only include the major version + * to avoid unnecessary rebuilds. When included externally, keep including + * the full version information. */ #include "libswresample/version.h" +#endif /** * @name Option constants @@ -199,9 +206,9 @@ const AVClass *swr_get_class(void); * Allocate SwrContext. * * If you use this function you will need to set the parameters (manually or - * with swr_alloc_set_opts()) before calling swr_init(). + * with swr_alloc_set_opts2()) before calling swr_init(). * - * @see swr_alloc_set_opts(), swr_init(), swr_free() + * @see swr_alloc_set_opts2(), swr_init(), swr_free() * @return NULL on error, allocated context otherwise */ struct SwrContext *swr_alloc(void); @@ -227,6 +234,7 @@ int swr_init(struct SwrContext *s); */ int swr_is_initialized(struct SwrContext *s); +#if FF_API_OLD_CHANNEL_LAYOUT /** * Allocate SwrContext if needed and set/reset common parameters. * @@ -246,12 +254,41 @@ int swr_is_initialized(struct SwrContext *s); * * @see swr_init(), swr_free() * @return NULL on error, allocated context otherwise + * @deprecated use @ref swr_alloc_set_opts2() */ +attribute_deprecated struct SwrContext *swr_alloc_set_opts(struct SwrContext *s, int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate, int64_t in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate, int log_offset, void *log_ctx); +#endif +/** + * Allocate SwrContext if needed and set/reset common parameters. + * + * This function does not require *ps to be allocated with swr_alloc(). On the + * other hand, swr_alloc() can use swr_alloc_set_opts2() to set the parameters + * on the allocated context. + * + * @param ps Pointer to an existing Swr context if available, or to NULL if not. + * On success, *ps will be set to the allocated context. + * @param out_ch_layout output channel layout (e.g. AV_CHANNEL_LAYOUT_*) + * @param out_sample_fmt output sample format (AV_SAMPLE_FMT_*). + * @param out_sample_rate output sample rate (frequency in Hz) + * @param in_ch_layout input channel layout (e.g. AV_CHANNEL_LAYOUT_*) + * @param in_sample_fmt input sample format (AV_SAMPLE_FMT_*). + * @param in_sample_rate input sample rate (frequency in Hz) + * @param log_offset logging level offset + * @param log_ctx parent logging context, can be NULL + * + * @see swr_init(), swr_free() + * @return 0 on success, a negative AVERROR code on error. + * On error, the Swr context is freed and *ps set to NULL. + */ +int swr_alloc_set_opts2(struct SwrContext **ps, + AVChannelLayout *out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate, + AVChannelLayout *in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate, + int log_offset, void *log_ctx); /** * @} * @@ -362,6 +399,40 @@ int swr_set_compensation(struct SwrContext *s, int sample_delta, int compensatio */ int swr_set_channel_mapping(struct SwrContext *s, const int *channel_map); +#if FF_API_OLD_CHANNEL_LAYOUT +/** + * Generate a channel mixing matrix. + * + * This function is the one used internally by libswresample for building the + * default mixing matrix. It is made public just as a utility function for + * building custom matrices. + * + * @param in_layout input channel layout + * @param out_layout output channel layout + * @param center_mix_level mix level for the center channel + * @param surround_mix_level mix level for the surround channel(s) + * @param lfe_mix_level mix level for the low-frequency effects channel + * @param rematrix_maxval if 1.0, coefficients will be normalized to prevent + * overflow. if INT_MAX, coefficients will not be + * normalized. + * @param[out] matrix mixing coefficients; matrix[i + stride * o] is + * the weight of input channel i in output channel o. + * @param stride distance between adjacent input channels in the + * matrix array + * @param matrix_encoding matrixed stereo downmix mode (e.g. dplii) + * @param log_ctx parent logging context, can be NULL + * @return 0 on success, negative AVERROR code on failure + * @deprecated use @ref swr_build_matrix2() + */ +attribute_deprecated +int swr_build_matrix(uint64_t in_layout, uint64_t out_layout, + double center_mix_level, double surround_mix_level, + double lfe_mix_level, double rematrix_maxval, + double rematrix_volume, double *matrix, + int stride, enum AVMatrixEncoding matrix_encoding, + void *log_ctx); +#endif + /** * Generate a channel mixing matrix. * @@ -385,12 +456,12 @@ int swr_set_channel_mapping(struct SwrContext *s, const int *channel_map); * @param log_ctx parent logging context, can be NULL * @return 0 on success, negative AVERROR code on failure */ -int swr_build_matrix(uint64_t in_layout, uint64_t out_layout, - double center_mix_level, double surround_mix_level, - double lfe_mix_level, double rematrix_maxval, - double rematrix_volume, double *matrix, - int stride, enum AVMatrixEncoding matrix_encoding, - void *log_ctx); +int swr_build_matrix2(const AVChannelLayout *in_layout, const AVChannelLayout *out_layout, + double center_mix_level, double surround_mix_level, + double lfe_mix_level, double maxval, + double rematrix_volume, double *matrix, + ptrdiff_t stride, enum AVMatrixEncoding matrix_encoding, + void *log_context); /** * Set a customized remix matrix. diff --git a/libswresample/swresample_frame.c b/libswresample/swresample_frame.c index d95c1cc53..53ac48713 100644 --- a/libswresample/swresample_frame.c +++ b/libswresample/swresample_frame.c @@ -26,39 +26,79 @@ int swr_config_frame(SwrContext *s, const AVFrame *out, const AVFrame *in) { + AVChannelLayout ch_layout = { 0 }; + int ret; + swr_close(s); if (in) { - if (av_opt_set_int(s, "icl", in->channel_layout, 0) < 0) +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + // if the old/new fields are set inconsistently, prefer the old ones + if ((in->channel_layout && (in->ch_layout.order != AV_CHANNEL_ORDER_NATIVE || + in->ch_layout.u.mask != in->channel_layout))) { + av_channel_layout_from_mask(&ch_layout, in->channel_layout); +FF_ENABLE_DEPRECATION_WARNINGS + } else +#endif + if ((ret = av_channel_layout_copy(&ch_layout, &in->ch_layout)) < 0) goto fail; - if (av_opt_set_int(s, "isf", in->format, 0) < 0) + if ((ret = av_opt_set_chlayout(s, "ichl", &ch_layout, 0)) < 0) goto fail; - if (av_opt_set_int(s, "isr", in->sample_rate, 0) < 0) + if ((ret = av_opt_set_int(s, "isf", in->format, 0)) < 0) + goto fail; + if ((ret = av_opt_set_int(s, "isr", in->sample_rate, 0)) < 0) goto fail; } if (out) { - if (av_opt_set_int(s, "ocl", out->channel_layout, 0) < 0) +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + // if the old/new fields are set inconsistently, prefer the old ones + if ((out->channel_layout && (out->ch_layout.order != AV_CHANNEL_ORDER_NATIVE || + out->ch_layout.u.mask != out->channel_layout))) { + av_channel_layout_uninit(&ch_layout); + av_channel_layout_from_mask(&ch_layout, out->channel_layout); +FF_ENABLE_DEPRECATION_WARNINGS + } else +#endif + if ((ret = av_channel_layout_copy(&ch_layout, &out->ch_layout)) < 0) goto fail; - if (av_opt_set_int(s, "osf", out->format, 0) < 0) + if ((ret = av_opt_set_chlayout(s, "ochl", &ch_layout, 0)) < 0) goto fail; - if (av_opt_set_int(s, "osr", out->sample_rate, 0) < 0) + if ((ret = av_opt_set_int(s, "osf", out->format, 0)) < 0) + goto fail; + if ((ret = av_opt_set_int(s, "osr", out->sample_rate, 0)) < 0) goto fail; } - return 0; + ret = 0; fail: - av_log(s, AV_LOG_ERROR, "Failed to set option\n"); - return AVERROR(EINVAL); + if (ret < 0) + av_log(s, AV_LOG_ERROR, "Failed to set option\n"); + av_channel_layout_uninit(&ch_layout); + return ret; } static int config_changed(SwrContext *s, const AVFrame *out, const AVFrame *in) { + AVChannelLayout ch_layout = { 0 }; int ret = 0; if (in) { - if (s->in_ch_layout != in->channel_layout || +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + // if the old/new fields are set inconsistently, prefer the old ones + if ((in->channel_layout && (in->ch_layout.order != AV_CHANNEL_ORDER_NATIVE || + in->ch_layout.u.mask != in->channel_layout))) { + av_channel_layout_from_mask(&ch_layout, in->channel_layout); +FF_ENABLE_DEPRECATION_WARNINGS + } else +#endif + if ((ret = av_channel_layout_copy(&ch_layout, &in->ch_layout)) < 0) + return ret; + if (av_channel_layout_compare(&s->in_ch_layout, &ch_layout) || s->in_sample_rate != in->sample_rate || s->in_sample_fmt != in->format) { ret |= AVERROR_INPUT_CHANGED; @@ -66,12 +106,25 @@ static int config_changed(SwrContext *s, } if (out) { - if (s->out_ch_layout != out->channel_layout || +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + // if the old/new fields are set inconsistently, prefer the old ones + if ((out->channel_layout && (out->ch_layout.order != AV_CHANNEL_ORDER_NATIVE || + out->ch_layout.u.mask != out->channel_layout))) { + av_channel_layout_uninit(&ch_layout); + av_channel_layout_from_mask(&ch_layout, out->channel_layout); +FF_ENABLE_DEPRECATION_WARNINGS + } else +#endif + if ((ret = av_channel_layout_copy(&ch_layout, &out->ch_layout)) < 0) + return ret; + if (av_channel_layout_compare(&s->out_ch_layout, &ch_layout) || s->out_sample_rate != out->sample_rate || s->out_sample_fmt != out->format) { ret |= AVERROR_OUTPUT_CHANGED; } } + av_channel_layout_uninit(&ch_layout); return ret; } @@ -116,7 +169,14 @@ static inline int available_samples(AVFrame *out) if (av_sample_fmt_is_planar(out->format)) { return samples; } else { - int channels = av_get_channel_layout_nb_channels(out->channel_layout); + int channels; +#if FF_API_OLD_CHANNEL_LAYOUT +FF_DISABLE_DEPRECATION_WARNINGS + channels = av_get_channel_layout_nb_channels(out->channel_layout); +FF_ENABLE_DEPRECATION_WARNINGS + if (!channels) +#endif + channels = out->ch_layout.nb_channels; return samples / channels; } } diff --git a/libswresample/swresample_internal.h b/libswresample/swresample_internal.h index f2ea5a226..262a0e2b8 100644 --- a/libswresample/swresample_internal.h +++ b/libswresample/swresample_internal.h @@ -99,8 +99,8 @@ struct SwrContext { enum AVSampleFormat in_sample_fmt; ///< input sample format enum AVSampleFormat int_sample_fmt; ///< internal sample format (AV_SAMPLE_FMT_FLTP or AV_SAMPLE_FMT_S16P) enum AVSampleFormat out_sample_fmt; ///< output sample format - int64_t in_ch_layout; ///< input channel layout - int64_t out_ch_layout; ///< output channel layout + AVChannelLayout in_ch_layout; ///< input channel layout + AVChannelLayout out_ch_layout; ///< output channel layout int in_sample_rate; ///< input sample rate int out_sample_rate; ///< output sample rate int flags; ///< miscellaneous flags such as SWR_FLAG_RESAMPLE @@ -114,11 +114,15 @@ struct SwrContext { int used_ch_count; ///< number of used input channels (mapped channel count if channel_map, otherwise in.ch_count) int engine; + int user_used_ch_count; ///< User set used channel count +#if FF_API_OLD_CHANNEL_LAYOUT int user_in_ch_count; ///< User set input channel count int user_out_ch_count; ///< User set output channel count - int user_used_ch_count; ///< User set used channel count int64_t user_in_ch_layout; ///< User set input channel layout int64_t user_out_ch_layout; ///< User set output channel layout +#endif + AVChannelLayout user_in_chlayout; ///< User set input channel layout + AVChannelLayout user_out_chlayout; ///< User set output channel layout enum AVSampleFormat user_int_sample_fmt; ///< User set internal sample format int user_dither_method; ///< User set dither method diff --git a/libswresample/tests/swresample.c b/libswresample/tests/swresample.c index 14a8f14f3..b627aa4ad 100644 --- a/libswresample/tests/swresample.c +++ b/libswresample/tests/swresample.c @@ -109,21 +109,21 @@ static const int rates[] = { 48000, }; -static const uint64_t layouts[]={ - AV_CH_LAYOUT_MONO , - AV_CH_LAYOUT_STEREO , - AV_CH_LAYOUT_2_1 , - AV_CH_LAYOUT_SURROUND , - AV_CH_LAYOUT_4POINT0 , - AV_CH_LAYOUT_2_2 , - AV_CH_LAYOUT_QUAD , - AV_CH_LAYOUT_5POINT0 , - AV_CH_LAYOUT_5POINT1 , - AV_CH_LAYOUT_5POINT0_BACK , - AV_CH_LAYOUT_5POINT1_BACK , - AV_CH_LAYOUT_7POINT0 , - AV_CH_LAYOUT_7POINT1 , - AV_CH_LAYOUT_7POINT1_WIDE , +static const AVChannelLayout layouts[]={ + AV_CHANNEL_LAYOUT_MONO , + AV_CHANNEL_LAYOUT_STEREO , + AV_CHANNEL_LAYOUT_2_1 , + AV_CHANNEL_LAYOUT_SURROUND , + AV_CHANNEL_LAYOUT_4POINT0 , + AV_CHANNEL_LAYOUT_2_2 , + AV_CHANNEL_LAYOUT_QUAD , + AV_CHANNEL_LAYOUT_5POINT0 , + AV_CHANNEL_LAYOUT_5POINT1 , + AV_CHANNEL_LAYOUT_5POINT0_BACK , + AV_CHANNEL_LAYOUT_5POINT1_BACK , + AV_CHANNEL_LAYOUT_7POINT0 , + AV_CHANNEL_LAYOUT_7POINT1 , + AV_CHANNEL_LAYOUT_7POINT1_WIDE , }; static void setup_array(uint8_t *out[SWR_CH_MAX], uint8_t *in, enum AVSampleFormat format, int samples){ @@ -224,7 +224,7 @@ static void audiogen(void *data, enum AVSampleFormat sample_fmt, int main(int argc, char **argv){ int in_sample_rate, out_sample_rate, ch ,i, flush_count; - uint64_t in_ch_layout, out_ch_layout; + AVChannelLayout in_ch_layout = { 0 }, out_ch_layout = { 0 }; enum AVSampleFormat in_sample_fmt, out_sample_fmt; uint8_t array_in[SAMPLES*8*8]; uint8_t array_mid[SAMPLES*8*8*3]; @@ -281,44 +281,38 @@ int main(int argc, char **argv){ int in_ch_count; int out_count, mid_count, out_ch_count; - in_ch_layout = layouts[vector % FF_ARRAY_ELEMS(layouts)]; vector /= FF_ARRAY_ELEMS(layouts); - out_ch_layout = layouts[vector % FF_ARRAY_ELEMS(layouts)]; vector /= FF_ARRAY_ELEMS(layouts); + av_channel_layout_copy(&in_ch_layout, &layouts[vector % FF_ARRAY_ELEMS(layouts)]); vector /= FF_ARRAY_ELEMS(layouts); + av_channel_layout_copy(&out_ch_layout, &layouts[vector % FF_ARRAY_ELEMS(layouts)]); vector /= FF_ARRAY_ELEMS(layouts); in_sample_fmt = formats[vector % FF_ARRAY_ELEMS(formats)]; vector /= FF_ARRAY_ELEMS(formats); out_sample_fmt = formats[vector % FF_ARRAY_ELEMS(formats)]; vector /= FF_ARRAY_ELEMS(formats); out_sample_rate = rates [vector % FF_ARRAY_ELEMS(rates )]; vector /= FF_ARRAY_ELEMS(rates); av_assert0(!vector); if(specific_test == 0){ - if(out_sample_rate != in_sample_rate || in_ch_layout != out_ch_layout) + if(out_sample_rate != in_sample_rate || av_channel_layout_compare(&in_ch_layout, &out_ch_layout)) continue; } - in_ch_count= av_get_channel_layout_nb_channels(in_ch_layout); - out_ch_count= av_get_channel_layout_nb_channels(out_ch_layout); - av_get_channel_layout_string( in_layout_string, sizeof( in_layout_string), in_ch_count, in_ch_layout); - av_get_channel_layout_string(out_layout_string, sizeof(out_layout_string), out_ch_count, out_ch_layout); + in_ch_count= in_ch_layout.nb_channels; + out_ch_count= out_ch_layout.nb_channels; + av_channel_layout_describe(&in_ch_layout, in_layout_string, sizeof( in_layout_string)); + av_channel_layout_describe(&out_ch_layout, out_layout_string, sizeof(out_layout_string)); fprintf(stderr, "TEST: %s->%s, rate:%5d->%5d, fmt:%s->%s\n", in_layout_string, out_layout_string, in_sample_rate, out_sample_rate, av_get_sample_fmt_name(in_sample_fmt), av_get_sample_fmt_name(out_sample_fmt)); - forw_ctx = swr_alloc_set_opts(forw_ctx, out_ch_layout, out_sample_fmt, out_sample_rate, - in_ch_layout, in_sample_fmt, in_sample_rate, - 0, 0); - backw_ctx = swr_alloc_set_opts(backw_ctx, in_ch_layout, in_sample_fmt, in_sample_rate, - out_ch_layout, out_sample_fmt, out_sample_rate, - 0, 0); - if(!forw_ctx) { + if (swr_alloc_set_opts2(&forw_ctx, &out_ch_layout, out_sample_fmt, out_sample_rate, + &in_ch_layout, in_sample_fmt, in_sample_rate, + 0, 0) < 0) { fprintf(stderr, "Failed to init forw_cts\n"); return 1; } - if(!backw_ctx) { + if (swr_alloc_set_opts2(&backw_ctx, &in_ch_layout, in_sample_fmt, in_sample_rate, + &out_ch_layout, out_sample_fmt, out_sample_rate, + 0, 0) < 0) { fprintf(stderr, "Failed to init backw_ctx\n"); return 1; } - if (uint_rand(rand_seed) % 3 == 0) - av_opt_set_int(forw_ctx, "ich", 0, 0); - if (uint_rand(rand_seed) % 3 == 0) - av_opt_set_int(forw_ctx, "och", 0, 0); if(swr_init( forw_ctx) < 0) fprintf(stderr, "swr_init(->) failed\n"); diff --git a/libswresample/version.c b/libswresample/version.c new file mode 100644 index 000000000..00f71e339 --- /dev/null +++ b/libswresample/version.c @@ -0,0 +1,45 @@ +/* + * Version functions. + * + * 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/avassert.h" +#include "swresample.h" +#include "version.h" + +#include "libavutil/ffversion.h" +const char swr_ffversion[] = "FFmpeg version " FFMPEG_VERSION; + +unsigned swresample_version(void) +{ + av_assert0(LIBSWRESAMPLE_VERSION_MICRO >= 100); + return LIBSWRESAMPLE_VERSION_INT; +} + +const char *swresample_configuration(void) +{ + return FFMPEG_CONFIGURATION; +} + +const char *swresample_license(void) +{ +#define LICENSE_PREFIX "libswresample license: " + return &LICENSE_PREFIX FFMPEG_LICENSE[sizeof(LICENSE_PREFIX) - 1]; +} + diff --git a/libswresample/version.h b/libswresample/version.h index d6fb8c3e2..7e5c58ec8 100644 --- a/libswresample/version.h +++ b/libswresample/version.h @@ -28,8 +28,9 @@ #include "libavutil/version.h" -#define LIBSWRESAMPLE_VERSION_MAJOR 4 -#define LIBSWRESAMPLE_VERSION_MINOR 3 +#include "version_major.h" + +#define LIBSWRESAMPLE_VERSION_MINOR 7 #define LIBSWRESAMPLE_VERSION_MICRO 100 #define LIBSWRESAMPLE_VERSION_INT AV_VERSION_INT(LIBSWRESAMPLE_VERSION_MAJOR, \ diff --git a/libswresample/version_major.h b/libswresample/version_major.h new file mode 100644 index 000000000..7f265c207 --- /dev/null +++ b/libswresample/version_major.h @@ -0,0 +1,31 @@ +/* + * Version macros. + * + * This file is part of libswresample + * + * libswresample 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. + * + * libswresample is distributed in the hope that 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 libswresample; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SWRESAMPLE_VERSION_MAJOR_H +#define SWRESAMPLE_VERSION_MAJOR_H + +/** + * @file + * Libswresample version macros + */ + +#define LIBSWRESAMPLE_VERSION_MAJOR 4 + +#endif /* SWRESAMPLE_VERSION_MAJOR_H */ diff --git a/libswresample/x86/audio_convert.asm b/libswresample/x86/audio_convert.asm index d441636d3..d6d6a8149 100644 --- a/libswresample/x86/audio_convert.asm +++ b/libswresample/x86/audio_convert.asm @@ -608,15 +608,6 @@ pack_8ch_%2_to_%1_u_int %+ SUFFIX: %macro NOP_N 0-6 %endmacro -INIT_MMX mmx -CONV int32, int16, u, 2, 1, INT16_TO_INT32_N, NOP_N -CONV int32, int16, a, 2, 1, INT16_TO_INT32_N, NOP_N -CONV int16, int32, u, 1, 2, INT32_TO_INT16_N, NOP_N -CONV int16, int32, a, 1, 2, INT32_TO_INT16_N, NOP_N - -PACK_6CH float, float, u, 2, 2, 0, NOP_N, NOP_N -PACK_6CH float, float, a, 2, 2, 0, NOP_N, NOP_N - INIT_XMM sse PACK_6CH float, float, u, 2, 2, 7, NOP_N, NOP_N PACK_6CH float, float, a, 2, 2, 7, NOP_N, NOP_N diff --git a/libswresample/x86/audio_convert_init.c b/libswresample/x86/audio_convert_init.c index a7d5ab89f..f6d36f9ca 100644 --- a/libswresample/x86/audio_convert_init.c +++ b/libswresample/x86/audio_convert_init.c @@ -26,7 +26,7 @@ #define PROTO(pre, in, out, cap) void ff ## pre ## in## _to_ ##out## _a_ ##cap(uint8_t **dst, const uint8_t **src, int len); #define PROTO2(pre, out, cap) PROTO(pre, int16, out, cap) PROTO(pre, int32, out, cap) PROTO(pre, float, out, cap) #define PROTO3(pre, cap) PROTO2(pre, int16, cap) PROTO2(pre, int32, cap) PROTO2(pre, float, cap) -#define PROTO4(pre) PROTO3(pre, mmx) PROTO3(pre, sse) PROTO3(pre, sse2) PROTO3(pre, ssse3) PROTO3(pre, sse4) PROTO3(pre, avx) PROTO3(pre, avx2) +#define PROTO4(pre) PROTO3(pre, sse) PROTO3(pre, sse2) PROTO3(pre, ssse3) PROTO3(pre, sse4) PROTO3(pre, avx) PROTO3(pre, avx2) PROTO4(_) PROTO4(_pack_2ch_) PROTO4(_pack_6ch_) @@ -52,15 +52,8 @@ av_cold void swri_audio_convert_init_x86(struct AudioConvert *ac, ac->simd_f = ff_int32_to_int16_a_ ## cap;\ } -MULTI_CAPS_FUNC(MMX, mmx) MULTI_CAPS_FUNC(SSE2, sse2) - if(EXTERNAL_MMX(mm_flags)) { - if(channels == 6) { - if( out_fmt == AV_SAMPLE_FMT_FLT && in_fmt == AV_SAMPLE_FMT_FLTP || out_fmt == AV_SAMPLE_FMT_S32 && in_fmt == AV_SAMPLE_FMT_S32P) - ac->simd_f = ff_pack_6ch_float_to_float_a_mmx; - } - } if(EXTERNAL_SSE(mm_flags)) { if(channels == 6) { if( out_fmt == AV_SAMPLE_FMT_FLT && in_fmt == AV_SAMPLE_FMT_FLTP || out_fmt == AV_SAMPLE_FMT_S32 && in_fmt == AV_SAMPLE_FMT_S32P) diff --git a/libswresample/x86/rematrix.asm b/libswresample/x86/rematrix.asm index 7984b9a72..968010701 100644 --- a/libswresample/x86/rematrix.asm +++ b/libswresample/x86/rematrix.asm @@ -223,12 +223,6 @@ mix_2_1_int16_u_int %+ SUFFIX: %endmacro -INIT_MMX mmx -MIX1_INT16 u -MIX1_INT16 a -MIX2_INT16 u -MIX2_INT16 a - INIT_XMM sse MIX2_FLT u MIX2_FLT a diff --git a/libswresample/x86/rematrix_init.c b/libswresample/x86/rematrix_init.c index 0608c74e7..b6ed38bf6 100644 --- a/libswresample/x86/rematrix_init.c +++ b/libswresample/x86/rematrix_init.c @@ -28,7 +28,6 @@ mix_2_1_func_type ff_mix_2_1_a_## type ## _ ## simd; D(float, sse) D(float, avx) -D(int16, mmx) D(int16, sse2) av_cold int swri_rematrix_init_x86(struct SwrContext *s){ @@ -43,10 +42,6 @@ av_cold int swri_rematrix_init_x86(struct SwrContext *s){ s->mix_2_1_simd = NULL; if (s->midbuf.fmt == AV_SAMPLE_FMT_S16P){ - if(EXTERNAL_MMX(mm_flags)) { - s->mix_1_1_simd = ff_mix_1_1_a_int16_mmx; - s->mix_2_1_simd = ff_mix_2_1_a_int16_mmx; - } if(EXTERNAL_SSE2(mm_flags)) { s->mix_1_1_simd = ff_mix_1_1_a_int16_sse2; s->mix_2_1_simd = ff_mix_2_1_a_int16_sse2; diff --git a/libswresample/x86/resample.asm b/libswresample/x86/resample.asm index 7107cf9d4..6c3dc2870 100644 --- a/libswresample/x86/resample.asm +++ b/libswresample/x86/resample.asm @@ -594,11 +594,6 @@ INIT_XMM fma4 RESAMPLE_FNS float, 4, 2, s, pf_1 %endif -%if ARCH_X86_32 -INIT_MMX mmxext -RESAMPLE_FNS int16, 2, 1 -%endif - INIT_XMM sse2 RESAMPLE_FNS int16, 2, 1 %if HAVE_XOP_EXTERNAL diff --git a/libswresample/x86/resample_init.c b/libswresample/x86/resample_init.c index 32c080ea4..d13ccd483 100644 --- a/libswresample/x86/resample_init.c +++ b/libswresample/x86/resample_init.c @@ -35,7 +35,6 @@ int ff_resample_common_##type##_##opt(ResampleContext *c, void *dst, \ int ff_resample_linear_##type##_##opt(ResampleContext *c, void *dst, \ const void *src, int sz, int upd) -RESAMPLE_FUNCS(int16, mmxext); RESAMPLE_FUNCS(int16, sse2); RESAMPLE_FUNCS(int16, xop); RESAMPLE_FUNCS(float, sse); @@ -52,10 +51,6 @@ av_cold void swri_resample_dsp_x86_init(ResampleContext *c) switch(c->format){ case AV_SAMPLE_FMT_S16P: - if (ARCH_X86_32 && EXTERNAL_MMXEXT(mm_flags)) { - c->dsp.resample_linear = ff_resample_linear_int16_mmxext; - c->dsp.resample_common = ff_resample_common_int16_mmxext; - } if (EXTERNAL_SSE2(mm_flags)) { c->dsp.resample_linear = ff_resample_linear_int16_sse2; c->dsp.resample_common = ff_resample_common_int16_sse2; diff --git a/libswscale/Makefile b/libswscale/Makefile index a0ec71e06..8e95f74c6 100644 --- a/libswscale/Makefile +++ b/libswscale/Makefile @@ -3,6 +3,7 @@ DESC = FFmpeg image rescaling library HEADERS = swscale.h \ version.h \ + version_major.h \ OBJS = alphablend.o \ hscale.o \ @@ -16,6 +17,7 @@ OBJS = alphablend.o \ swscale.o \ swscale_unscaled.o \ utils.o \ + version.o \ yuv2rgb.o \ vscale.o \ diff --git a/libswscale/aarch64/hscale.S b/libswscale/aarch64/hscale.S index af55ffe2b..b7b21b7a0 100644 --- a/libswscale/aarch64/hscale.S +++ b/libswscale/aarch64/hscale.S @@ -1,5 +1,7 @@ /* * Copyright (c) 2016 Clément Bœsch + * Copyright (c) 2019-2021 Sebastian Pop + * Copyright (c) 2022 Jonathan Swinney * * This file is part of FFmpeg. * @@ -20,7 +22,25 @@ #include "libavutil/aarch64/asm.S" -function ff_hscale_8_to_15_neon, export=1 +/* +;----------------------------------------------------------------------------- +; horizontal line scaling +; +; void hscaleto__ +; (SwsContext *c, int{16,32}_t *dst, +; int dstW, const uint{8,16}_t *src, +; const int16_t *filter, +; const int32_t *filterPos, int filterSize); +; +; Scale one horizontal line. Input is either 8-bit width or 16-bit width +; ($source_width can be either 8, 9, 10 or 16, difference is whether we have to +; downscale before multiplying). Filter is 14 bits. Output is either 15 bits +; (in int16_t) or 19 bits (in int32_t), as given in $intermediate_nbits. Each +; output pixel is generated from $filterSize input pixels, the position of +; the first pixel is given in filterPos[nOutputPixel]. +;----------------------------------------------------------------------------- */ + +function ff_hscale8to15_X8_neon, export=1 sbfiz x7, x6, #1, #32 // filterSize*2 (*2 because int16) 1: ldr w8, [x5], #4 // filterPos[idx] ldr w0, [x5], #4 // filterPos[idx + 1] @@ -61,20 +81,162 @@ function ff_hscale_8_to_15_neon, export=1 smlal v3.4S, v18.4H, v19.4H // v3 accumulates srcp[filterPos[3] + {0..3}] * filter[{0..3}] smlal2 v3.4S, v18.8H, v19.8H // v3 accumulates srcp[filterPos[3] + {4..7}] * filter[{4..7}] b.gt 2b // inner loop if filterSize not consumed completely - addp v0.4S, v0.4S, v0.4S // part0 horizontal pair adding - addp v1.4S, v1.4S, v1.4S // part1 horizontal pair adding - addp v2.4S, v2.4S, v2.4S // part2 horizontal pair adding - addp v3.4S, v3.4S, v3.4S // part3 horizontal pair adding - addp v0.4S, v0.4S, v0.4S // part0 horizontal pair adding - addp v1.4S, v1.4S, v1.4S // part1 horizontal pair adding - addp v2.4S, v2.4S, v2.4S // part2 horizontal pair adding - addp v3.4S, v3.4S, v3.4S // part3 horizontal pair adding - zip1 v0.4S, v0.4S, v1.4S // part01 = zip values from part0 and part1 - zip1 v2.4S, v2.4S, v3.4S // part23 = zip values from part2 and part3 - mov v0.d[1], v2.d[0] // part0123 = zip values from part01 and part23 + addp v0.4S, v0.4S, v1.4S // part01 horizontal pair adding + addp v2.4S, v2.4S, v3.4S // part23 horizontal pair adding + addp v0.4S, v0.4S, v2.4S // part0123 horizontal pair adding subs w2, w2, #4 // dstW -= 4 sqshrn v0.4H, v0.4S, #7 // shift and clip the 2x16-bit final values st1 {v0.4H}, [x1], #8 // write to destination part0123 b.gt 1b // loop until end of line ret endfunc + +function ff_hscale8to15_4_neon, export=1 +// x0 SwsContext *c (not used) +// x1 int16_t *dst +// x2 int dstW +// x3 const uint8_t *src +// x4 const int16_t *filter +// x5 const int32_t *filterPos +// x6 int filterSize +// x8-x15 registers for gathering src data + +// v0 madd accumulator 4S +// v1-v4 filter values (16 bit) 8H +// v5 madd accumulator 4S +// v16-v19 src values (8 bit) 8B + +// This implementation has 4 sections: +// 1. Prefetch src data +// 2. Interleaved prefetching src data and madd +// 3. Complete madd +// 4. Complete remaining iterations when dstW % 8 != 0 + + sub sp, sp, #32 // allocate 32 bytes on the stack + cmp w2, #16 // if dstW <16, skip to the last block used for wrapping up + b.lt 2f + + // load 8 values from filterPos to be used as offsets into src + ldp w8, w9, [x5] // filterPos[idx + 0], [idx + 1] + ldp w10, w11, [x5, #8] // filterPos[idx + 2], [idx + 3] + ldp w12, w13, [x5, #16] // filterPos[idx + 4], [idx + 5] + ldp w14, w15, [x5, #24] // filterPos[idx + 6], [idx + 7] + add x5, x5, #32 // advance filterPos + + // gather random access data from src into contiguous memory + ldr w8, [x3, w8, UXTW] // src[filterPos[idx + 0]][0..3] + ldr w9, [x3, w9, UXTW] // src[filterPos[idx + 1]][0..3] + ldr w10, [x3, w10, UXTW] // src[filterPos[idx + 2]][0..3] + ldr w11, [x3, w11, UXTW] // src[filterPos[idx + 3]][0..3] + ldr w12, [x3, w12, UXTW] // src[filterPos[idx + 4]][0..3] + ldr w13, [x3, w13, UXTW] // src[filterPos[idx + 5]][0..3] + ldr w14, [x3, w14, UXTW] // src[filterPos[idx + 6]][0..3] + ldr w15, [x3, w15, UXTW] // src[filterPos[idx + 7]][0..3] + stp w8, w9, [sp] // *scratch_mem = { src[filterPos[idx + 0]][0..3], src[filterPos[idx + 1]][0..3] } + stp w10, w11, [sp, #8] // *scratch_mem = { src[filterPos[idx + 2]][0..3], src[filterPos[idx + 3]][0..3] } + stp w12, w13, [sp, #16] // *scratch_mem = { src[filterPos[idx + 4]][0..3], src[filterPos[idx + 5]][0..3] } + stp w14, w15, [sp, #24] // *scratch_mem = { src[filterPos[idx + 6]][0..3], src[filterPos[idx + 7]][0..3] } + +1: + ld4 {v16.8B, v17.8B, v18.8B, v19.8B}, [sp] // transpose 8 bytes each from src into 4 registers + + // load 8 values from filterPos to be used as offsets into src + ldp w8, w9, [x5] // filterPos[idx + 0][0..3], [idx + 1][0..3], next iteration + ldp w10, w11, [x5, #8] // filterPos[idx + 2][0..3], [idx + 3][0..3], next iteration + ldp w12, w13, [x5, #16] // filterPos[idx + 4][0..3], [idx + 5][0..3], next iteration + ldp w14, w15, [x5, #24] // filterPos[idx + 6][0..3], [idx + 7][0..3], next iteration + + movi v0.2D, #0 // Clear madd accumulator for idx 0..3 + movi v5.2D, #0 // Clear madd accumulator for idx 4..7 + + ld4 {v1.8H, v2.8H, v3.8H, v4.8H}, [x4], #64 // load filter idx + 0..7 + + add x5, x5, #32 // advance filterPos + + // interleaved SIMD and prefetching intended to keep ld/st and vector pipelines busy + uxtl v16.8H, v16.8B // unsigned extend long, covert src data to 16-bit + uxtl v17.8H, v17.8B // unsigned extend long, covert src data to 16-bit + ldr w8, [x3, w8, UXTW] // src[filterPos[idx + 0]], next iteration + ldr w9, [x3, w9, UXTW] // src[filterPos[idx + 1]], next iteration + uxtl v18.8H, v18.8B // unsigned extend long, covert src data to 16-bit + uxtl v19.8H, v19.8B // unsigned extend long, covert src data to 16-bit + ldr w10, [x3, w10, UXTW] // src[filterPos[idx + 2]], next iteration + ldr w11, [x3, w11, UXTW] // src[filterPos[idx + 3]], next iteration + + smlal v0.4S, v1.4H, v16.4H // multiply accumulate inner loop j = 0, idx = 0..3 + smlal v0.4S, v2.4H, v17.4H // multiply accumulate inner loop j = 1, idx = 0..3 + ldr w12, [x3, w12, UXTW] // src[filterPos[idx + 4]], next iteration + ldr w13, [x3, w13, UXTW] // src[filterPos[idx + 5]], next iteration + smlal v0.4S, v3.4H, v18.4H // multiply accumulate inner loop j = 2, idx = 0..3 + smlal v0.4S, v4.4H, v19.4H // multiply accumulate inner loop j = 3, idx = 0..3 + ldr w14, [x3, w14, UXTW] // src[filterPos[idx + 6]], next iteration + ldr w15, [x3, w15, UXTW] // src[filterPos[idx + 7]], next iteration + + smlal2 v5.4S, v1.8H, v16.8H // multiply accumulate inner loop j = 0, idx = 4..7 + smlal2 v5.4S, v2.8H, v17.8H // multiply accumulate inner loop j = 1, idx = 4..7 + stp w8, w9, [sp] // *scratch_mem = { src[filterPos[idx + 0]][0..3], src[filterPos[idx + 1]][0..3] } + stp w10, w11, [sp, #8] // *scratch_mem = { src[filterPos[idx + 2]][0..3], src[filterPos[idx + 3]][0..3] } + smlal2 v5.4S, v3.8H, v18.8H // multiply accumulate inner loop j = 2, idx = 4..7 + smlal2 v5.4S, v4.8H, v19.8H // multiply accumulate inner loop j = 3, idx = 4..7 + stp w12, w13, [sp, #16] // *scratch_mem = { src[filterPos[idx + 4]][0..3], src[filterPos[idx + 5]][0..3] } + stp w14, w15, [sp, #24] // *scratch_mem = { src[filterPos[idx + 6]][0..3], src[filterPos[idx + 7]][0..3] } + + sub w2, w2, #8 // dstW -= 8 + sqshrn v0.4H, v0.4S, #7 // shift and clip the 2x16-bit final values + sqshrn v1.4H, v5.4S, #7 // shift and clip the 2x16-bit final values + st1 {v0.4H, v1.4H}, [x1], #16 // write to dst[idx + 0..7] + cmp w2, #16 // continue on main loop if there are at least 16 iterations left + b.ge 1b + + // last full iteration + ld4 {v16.8B, v17.8B, v18.8B, v19.8B}, [sp] + ld4 {v1.8H, v2.8H, v3.8H, v4.8H}, [x4], #64 // load filter idx + 0..7 + + movi v0.2D, #0 // Clear madd accumulator for idx 0..3 + movi v5.2D, #0 // Clear madd accumulator for idx 4..7 + + uxtl v16.8H, v16.8B // unsigned extend long, covert src data to 16-bit + uxtl v17.8H, v17.8B // unsigned extend long, covert src data to 16-bit + uxtl v18.8H, v18.8B // unsigned extend long, covert src data to 16-bit + uxtl v19.8H, v19.8B // unsigned extend long, covert src data to 16-bit + + smlal v0.4S, v1.4H, v16.4H // multiply accumulate inner loop j = 0, idx = 0..3 + smlal v0.4S, v2.4H, v17.4H // multiply accumulate inner loop j = 1, idx = 0..3 + smlal v0.4S, v3.4H, v18.4H // multiply accumulate inner loop j = 2, idx = 0..3 + smlal v0.4S, v4.4H, v19.4H // multiply accumulate inner loop j = 3, idx = 0..3 + + smlal2 v5.4S, v1.8H, v16.8H // multiply accumulate inner loop j = 0, idx = 4..7 + smlal2 v5.4S, v2.8H, v17.8H // multiply accumulate inner loop j = 1, idx = 4..7 + smlal2 v5.4S, v3.8H, v18.8H // multiply accumulate inner loop j = 2, idx = 4..7 + smlal2 v5.4S, v4.8H, v19.8H // multiply accumulate inner loop j = 3, idx = 4..7 + + subs w2, w2, #8 // dstW -= 8 + sqshrn v0.4H, v0.4S, #7 // shift and clip the 2x16-bit final values + sqshrn v1.4H, v5.4S, #7 // shift and clip the 2x16-bit final values + st1 {v0.4H, v1.4H}, [x1], #16 // write to dst[idx + 0..7] + + cbnz w2, 2f // if >0 iterations remain, jump to the wrap up section + + add sp, sp, #32 // clean up stack + ret + + // finish up when dstW % 8 != 0 or dstW < 16 +2: + // load src + ldr w8, [x5], #4 // filterPos[i] + add x9, x3, w8, UXTW // calculate the address for src load + ld1 {v5.S}[0], [x9] // src[filterPos[i] + 0..3] + // load filter + ld1 {v6.4H}, [x4], #8 // filter[filterSize * i + 0..3] + + uxtl v5.8H, v5.8B // unsigned exten long, convert src data to 16-bit + smull v0.4S, v5.4H, v6.4H // 4 iterations of src[...] * filter[...] + addv s0, v0.4S // add up products of src and filter values + sqshrn h0, s0, #7 // shift and clip the 2x16-bit final value + st1 {v0.H}[0], [x1], #2 // dst[i] = ... + sub w2, w2, #1 // dstW-- + cbnz w2, 2b + + add sp, sp, #32 // clean up stack + ret +endfunc diff --git a/libswscale/aarch64/swscale.c b/libswscale/aarch64/swscale.c index 09d0a7130..ab28be4da 100644 --- a/libswscale/aarch64/swscale.c +++ b/libswscale/aarch64/swscale.c @@ -22,25 +22,46 @@ #include "libswscale/swscale_internal.h" #include "libavutil/aarch64/cpu.h" -void ff_hscale_8_to_15_neon(SwsContext *c, int16_t *dst, int dstW, - const uint8_t *src, const int16_t *filter, - const int32_t *filterPos, int filterSize); +#define SCALE_FUNC(filter_n, from_bpc, to_bpc, opt) \ +void ff_hscale ## from_bpc ## to ## to_bpc ## _ ## filter_n ## _ ## opt( \ + SwsContext *c, int16_t *data, \ + int dstW, const uint8_t *src, \ + const int16_t *filter, \ + const int32_t *filterPos, int filterSize) +#define SCALE_FUNCS(filter_n, opt) \ + SCALE_FUNC(filter_n, 8, 15, opt); +#define ALL_SCALE_FUNCS(opt) \ + SCALE_FUNCS(4, opt); \ + SCALE_FUNCS(X8, opt) + +ALL_SCALE_FUNCS(neon); void ff_yuv2planeX_8_neon(const int16_t *filter, int filterSize, const int16_t **src, uint8_t *dest, int dstW, const uint8_t *dither, int offset); +#define ASSIGN_SCALE_FUNC2(hscalefn, filtersize, opt) do { \ + if (c->srcBpc == 8 && c->dstBpc <= 14) { \ + hscalefn = \ + ff_hscale8to15_ ## filtersize ## _ ## opt; \ + } \ +} while (0) + +#define ASSIGN_SCALE_FUNC(hscalefn, filtersize, opt) \ + switch (filtersize) { \ + case 4: ASSIGN_SCALE_FUNC2(hscalefn, 4, opt); break; \ + default: if (filtersize % 8 == 0) \ + ASSIGN_SCALE_FUNC2(hscalefn, X8, opt); \ + break; \ + } + av_cold void ff_sws_init_swscale_aarch64(SwsContext *c) { int cpu_flags = av_get_cpu_flags(); if (have_neon(cpu_flags)) { - if (c->srcBpc == 8 && c->dstBpc <= 14 && - (c->hLumFilterSize % 8) == 0 && - (c->hChrFilterSize % 8) == 0) - { - c->hyScale = c->hcScale = ff_hscale_8_to_15_neon; - } + ASSIGN_SCALE_FUNC(c->hyScale, c->hLumFilterSize, neon); + ASSIGN_SCALE_FUNC(c->hcScale, c->hChrFilterSize, neon); if (c->dstBpc == 8) { c->yuv2planeX = ff_yuv2planeX_8_neon; } diff --git a/libswscale/input.c b/libswscale/input.c index 6acc39f89..fe0c27d74 100644 --- a/libswscale/input.c +++ b/libswscale/input.c @@ -21,17 +21,11 @@ #include #include #include -#include -#include "libavutil/avutil.h" #include "libavutil/bswap.h" #include "libavutil/intreadwrite.h" -#include "libavutil/mathematics.h" -#include "libavutil/pixdesc.h" #include "libavutil/avassert.h" #include "config.h" -#include "rgb2rgb.h" -#include "swscale.h" #include "swscale_internal.h" #define input_pixel(pos) (isBE(origin) ? AV_RB16(pos) : AV_RL16(pos)) diff --git a/libswscale/options.c b/libswscale/options.c index f6ea9e1f9..4d41b835b 100644 --- a/libswscale/options.c +++ b/libswscale/options.c @@ -18,9 +18,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/avutil.h" #include "libavutil/opt.h" -#include "libavutil/pixfmt.h" #include "swscale.h" #include "swscale_internal.h" diff --git a/libswscale/rgb2rgb.c b/libswscale/rgb2rgb.c index a7300f3ba..b8be76913 100644 --- a/libswscale/rgb2rgb.c +++ b/libswscale/rgb2rgb.c @@ -137,10 +137,11 @@ void (*yuyvtoyuv422)(uint8_t *ydst, uint8_t *udst, uint8_t *vdst, av_cold void ff_sws_rgb2rgb_init(void) { rgb2rgb_init_c(); - if (ARCH_AARCH64) - rgb2rgb_init_aarch64(); - if (ARCH_X86) - rgb2rgb_init_x86(); +#if ARCH_AARCH64 + rgb2rgb_init_aarch64(); +#elif ARCH_X86 + rgb2rgb_init_x86(); +#endif } void rgb32to24(const uint8_t *src, uint8_t *dst, int src_size) diff --git a/libswscale/rgb2rgb.h b/libswscale/rgb2rgb.h index 48bba1586..7272e98c5 100644 --- a/libswscale/rgb2rgb.h +++ b/libswscale/rgb2rgb.h @@ -26,10 +26,7 @@ #ifndef SWSCALE_RGB2RGB_H #define SWSCALE_RGB2RGB_H -#include - -#include "libavutil/avutil.h" -#include "swscale.h" +#include /* A full collection of RGB to RGB(BGR) converters */ extern void (*rgb24tobgr32)(const uint8_t *src, uint8_t *dst, int src_size); diff --git a/libswscale/swscale.c b/libswscale/swscale.c index feef3482d..7b40f49da 100644 --- a/libswscale/swscale.c +++ b/libswscale/swscale.c @@ -18,22 +18,18 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include -#include +#include #include #include #include "libavutil/avassert.h" -#include "libavutil/avutil.h" #include "libavutil/bswap.h" +#include "libavutil/common.h" #include "libavutil/cpu.h" -#include "libavutil/imgutils.h" #include "libavutil/intreadwrite.h" -#include "libavutil/mathematics.h" #include "libavutil/mem_internal.h" #include "libavutil/pixdesc.h" #include "config.h" -#include "rgb2rgb.h" #include "swscale_internal.h" #include "swscale.h" @@ -594,14 +590,15 @@ void ff_sws_init_scale(SwsContext *c) { sws_init_swscale(c); - if (ARCH_PPC) - ff_sws_init_swscale_ppc(c); - if (ARCH_X86) - ff_sws_init_swscale_x86(c); - if (ARCH_AARCH64) - ff_sws_init_swscale_aarch64(c); - if (ARCH_ARM) - ff_sws_init_swscale_arm(c); +#if ARCH_PPC + ff_sws_init_swscale_ppc(c); +#elif ARCH_X86 + ff_sws_init_swscale_x86(c); +#elif ARCH_AARCH64 + ff_sws_init_swscale_aarch64(c); +#elif ARCH_ARM + ff_sws_init_swscale_arm(c); +#endif } static void reset_ptr(const uint8_t *src[], enum AVPixelFormat format) diff --git a/libswscale/swscale.h b/libswscale/swscale.h index daa53dc01..3ebf7c698 100644 --- a/libswscale/swscale.h +++ b/libswscale/swscale.h @@ -33,7 +33,13 @@ #include "libavutil/frame.h" #include "libavutil/log.h" #include "libavutil/pixfmt.h" +#include "version_major.h" +#ifndef HAVE_AV_CONFIG_H +/* When included as part of the ffmpeg build, only include the major version + * to avoid unnecessary rebuilds. When included externally, keep including + * the full version information. */ #include "version.h" +#endif /** * @defgroup libsws libswscale diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h index 3a78d95ba..e118b5445 100644 --- a/libswscale/swscale_internal.h +++ b/libswscale/swscale_internal.h @@ -24,10 +24,8 @@ #include #include "config.h" -#include "version.h" #include "libavutil/avassert.h" -#include "libavutil/avutil.h" #include "libavutil/common.h" #include "libavutil/frame.h" #include "libavutil/intreadwrite.h" @@ -1144,5 +1142,5 @@ void ff_sws_slice_worker(void *priv, int jobnr, int threadnr, #define MAX_LINES_AHEAD 4 //shuffle filter and filterPos for hyScale and hcScale filters in avx2 -void ff_shuffle_filter_coefficients(SwsContext *c, int* filterPos, int filterSize, int16_t *filter, int dstW); +int ff_shuffle_filter_coefficients(SwsContext *c, int* filterPos, int filterSize, int16_t *filter, int dstW); #endif /* SWSCALE_SWSCALE_INTERNAL_H */ diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c index 7cb2a62f0..8838cc8b5 100644 --- a/libswscale/swscale_unscaled.c +++ b/libswscale/swscale_unscaled.c @@ -2222,12 +2222,13 @@ void ff_get_unscaled_swscale(SwsContext *c) c->convert_unscaled = planarCopyWrapper; } - if (ARCH_PPC) - ff_get_unscaled_swscale_ppc(c); - if (ARCH_ARM) - ff_get_unscaled_swscale_arm(c); - if (ARCH_AARCH64) - ff_get_unscaled_swscale_aarch64(c); +#if ARCH_PPC + ff_get_unscaled_swscale_ppc(c); +#elif ARCH_ARM + ff_get_unscaled_swscale_arm(c); +#elif ARCH_AARCH64 + ff_get_unscaled_swscale_aarch64(c); +#endif } /* Convert the palette to the same packed 32-bit format as the palette */ diff --git a/libswscale/utils.c b/libswscale/utils.c index c5ea8853d..cb4f5b521 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -40,8 +40,6 @@ #include "libavutil/attributes.h" #include "libavutil/avassert.h" -#include "libavutil/avutil.h" -#include "libavutil/bswap.h" #include "libavutil/cpu.h" #include "libavutil/imgutils.h" #include "libavutil/intreadwrite.h" @@ -67,23 +65,6 @@ static void sws_printVec2(SwsVector *a, AVClass *log_ctx, int log_level); static void handle_formats(SwsContext *c); -unsigned swscale_version(void) -{ - av_assert0(LIBSWSCALE_VERSION_MICRO >= 100); - return LIBSWSCALE_VERSION_INT; -} - -const char *swscale_configuration(void) -{ - return FFMPEG_CONFIGURATION; -} - -const char *swscale_license(void) -{ -#define LICENSE_PREFIX "libswscale license: " - return &LICENSE_PREFIX FFMPEG_LICENSE[sizeof(LICENSE_PREFIX) - 1]; -} - typedef struct FormatEntry { uint8_t is_supported_in :1; uint8_t is_supported_out :1; @@ -278,39 +259,48 @@ static const FormatEntry format_entries[] = { [AV_PIX_FMT_P416LE] = { 1, 1 }, }; -void ff_shuffle_filter_coefficients(SwsContext *c, int *filterPos, int filterSize, int16_t *filter, int dstW){ +int ff_shuffle_filter_coefficients(SwsContext *c, int *filterPos, + int filterSize, int16_t *filter, + int dstW) +{ #if ARCH_X86_64 - int i, j, k, l; + int i, j, k; int cpu_flags = av_get_cpu_flags(); + // avx2 hscale filter processes 16 pixel blocks. + if (!filter || dstW % 16 != 0) + return 0; if (EXTERNAL_AVX2_FAST(cpu_flags) && !(cpu_flags & AV_CPU_FLAG_SLOW_GATHER)) { - if ((c->srcBpc == 8) && (c->dstBpc <= 14)){ - if (dstW % 16 == 0){ - if (filter != NULL){ - for (i = 0; i < dstW; i += 8){ - FFSWAP(int, filterPos[i + 2], filterPos[i+4]); - FFSWAP(int, filterPos[i + 3], filterPos[i+5]); - } - if (filterSize > 4){ - int16_t *tmp2 = av_malloc(dstW * filterSize * 2); - memcpy(tmp2, filter, dstW * filterSize * 2); - for (i = 0; i < dstW; i += 16){//pixel - for (k = 0; k < filterSize / 4; ++k){//fcoeff - for (j = 0; j < 16; ++j){//inner pixel - for (l = 0; l < 4; ++l){//coeff - int from = i * filterSize + j * filterSize + k * 4 + l; - int to = (i) * filterSize + j * 4 + l + k * 64; - filter[to] = tmp2[from]; - } - } - } - } - av_free(tmp2); - } - } - } + if ((c->srcBpc == 8) && (c->dstBpc <= 14)) { + int16_t *filterCopy = NULL; + if (filterSize > 4) { + if (!FF_ALLOC_TYPED_ARRAY(filterCopy, dstW * filterSize)) + return AVERROR(ENOMEM); + memcpy(filterCopy, filter, dstW * filterSize * sizeof(int16_t)); + } + // Do not swap filterPos for pixels which won't be processed by + // the main loop. + for (i = 0; i + 8 <= dstW; i += 8) { + FFSWAP(int, filterPos[i + 2], filterPos[i + 4]); + FFSWAP(int, filterPos[i + 3], filterPos[i + 5]); + } + if (filterSize > 4) { + // 16 pixels are processed at a time. + for (i = 0; i + 16 <= dstW; i += 16) { + // 4 filter coeffs are processed at a time. + for (k = 0; k + 4 <= filterSize; k += 4) { + for (j = 0; j < 16; ++j) { + int from = (i + j) * filterSize + k; + int to = i * filterSize + j * 4 + k * 16; + memcpy(&filter[to], &filterCopy[from], 4 * sizeof(int16_t)); + } + } + } + } + av_free(filterCopy); } } #endif + return 0; } int sws_isSupportedInput(enum AVPixelFormat pix_fmt) @@ -1028,11 +1018,16 @@ int sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4], srcRange, table, dstRange, brightness, contrast, saturation); - c->cascaded_context[1] = sws_getContext(tmp_width, tmp_height, tmp_format, - dstW, dstH, c->dstFormat, - c->flags, NULL, NULL, c->param); + c->cascaded_context[1] = sws_alloc_set_opts(tmp_width, tmp_height, tmp_format, + dstW, dstH, c->dstFormat, + c->flags, c->param); if (!c->cascaded_context[1]) return -1; + c->cascaded_context[1]->srcRange = srcRange; + c->cascaded_context[1]->dstRange = dstRange; + ret = sws_init_context(c->cascaded_context[1], NULL , NULL); + if (ret < 0) + return ret; sws_setColorspaceDetails(c->cascaded_context[1], inv_table, srcRange, table, dstRange, 0, 1 << 16, 1 << 16); @@ -1049,9 +1044,10 @@ int sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4], contrast, saturation); // FIXME factorize - if (ARCH_PPC) - ff_yuv2rgb_init_tables_ppc(c, inv_table, brightness, - contrast, saturation); +#if ARCH_PPC + ff_yuv2rgb_init_tables_ppc(c, inv_table, brightness, + contrast, saturation); +#endif } fill_rgb2yuv_table(c, table, dstRange); @@ -1825,7 +1821,7 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter, { const int filterAlign = X86_MMX(cpu_flags) ? 4 : PPC_ALTIVEC(cpu_flags) ? 8 : - have_neon(cpu_flags) ? 8 : 1; + have_neon(cpu_flags) ? 4 : 1; if ((ret = initFilter(&c->hLumFilter, &c->hLumFilterPos, &c->hLumFilterSize, c->lumXInc, @@ -1836,7 +1832,8 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter, get_local_pos(c, 0, 0, 0), get_local_pos(c, 0, 0, 0))) < 0) goto fail; - ff_shuffle_filter_coefficients(c, c->hLumFilterPos, c->hLumFilterSize, c->hLumFilter, dstW); + if (ff_shuffle_filter_coefficients(c, c->hLumFilterPos, c->hLumFilterSize, c->hLumFilter, dstW) < 0) + goto nomem; if ((ret = initFilter(&c->hChrFilter, &c->hChrFilterPos, &c->hChrFilterSize, c->chrXInc, c->chrSrcW, c->chrDstW, filterAlign, 1 << 14, @@ -1846,7 +1843,8 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter, get_local_pos(c, c->chrSrcHSubSample, c->src_h_chr_pos, 0), get_local_pos(c, c->chrDstHSubSample, c->dst_h_chr_pos, 0))) < 0) goto fail; - ff_shuffle_filter_coefficients(c, c->hChrFilterPos, c->hChrFilterSize, c->hChrFilter, c->chrDstW); + if (ff_shuffle_filter_coefficients(c, c->hChrFilterPos, c->hChrFilterSize, c->hChrFilter, c->chrDstW) < 0) + goto nomem; } } // initialize horizontal stuff diff --git a/libswscale/version.c b/libswscale/version.c new file mode 100644 index 000000000..b165e2563 --- /dev/null +++ b/libswscale/version.c @@ -0,0 +1,41 @@ +/* + * Version functions. + * + * 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/avassert.h" +#include "swscale.h" +#include "version.h" + +unsigned swscale_version(void) +{ + av_assert0(LIBSWSCALE_VERSION_MICRO >= 100); + return LIBSWSCALE_VERSION_INT; +} + +const char *swscale_configuration(void) +{ + return FFMPEG_CONFIGURATION; +} + +const char *swscale_license(void) +{ +#define LICENSE_PREFIX "libswscale license: " + return &LICENSE_PREFIX FFMPEG_LICENSE[sizeof(LICENSE_PREFIX) - 1]; +} diff --git a/libswscale/version.h b/libswscale/version.h index 24448248e..4c6af261e 100644 --- a/libswscale/version.h +++ b/libswscale/version.h @@ -26,8 +26,9 @@ #include "libavutil/version.h" -#define LIBSWSCALE_VERSION_MAJOR 6 -#define LIBSWSCALE_VERSION_MINOR 4 +#include "version_major.h" + +#define LIBSWSCALE_VERSION_MINOR 7 #define LIBSWSCALE_VERSION_MICRO 100 #define LIBSWSCALE_VERSION_INT AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \ @@ -40,10 +41,4 @@ #define LIBSWSCALE_IDENT "SwS" AV_STRINGIFY(LIBSWSCALE_VERSION) -/** - * FF_API_* defines may be placed below to indicate public API that will be - * 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. - */ - #endif /* SWSCALE_VERSION_H */ diff --git a/libswscale/version_major.h b/libswscale/version_major.h new file mode 100644 index 000000000..2f8418780 --- /dev/null +++ b/libswscale/version_major.h @@ -0,0 +1,35 @@ +/* + * 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 SWSCALE_VERSION_MAJOR_H +#define SWSCALE_VERSION_MAJOR_H + +/** + * @file + * swscale version macros + */ + +#define LIBSWSCALE_VERSION_MAJOR 6 + +/** + * FF_API_* defines may be placed below to indicate public API that will be + * 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. + */ + +#endif /* SWSCALE_VERSION_MAJOR_H */ diff --git a/libswscale/x86/input.asm b/libswscale/x86/input.asm index af9afcaa5..6de6733fa 100644 --- a/libswscale/x86/input.asm +++ b/libswscale/x86/input.asm @@ -93,7 +93,31 @@ shuf_rgb_12x4: db 0, 0x80, 1, 0x80, 2, 0x80, 3, 0x80, \ 6, 0x80, 7, 0x80, 8, 0x80, 9, 0x80 shuf_rgb_3x56: db 2, 0x80, 3, 0x80, 4, 0x80, 5, 0x80, \ 8, 0x80, 9, 0x80, 10, 0x80, 11, 0x80 - +pd_65535f: times 8 dd 65535.0 +pb_pack_shuffle16le: db 0, 1, 4, 5, \ + 8, 9, 12, 13, \ + -1, -1, -1, -1, \ + -1, -1, -1, -1, \ + -1, -1, -1, -1, \ + -1, -1, -1, -1, \ + 0, 1, 4, 5, \ + 8, 9, 12, 13 +pb_shuffle32be: db 3, 2, 1, 0, \ + 7, 6, 5, 4, \ + 11, 10, 9, 8, \ + 15, 14, 13, 12, \ + 3, 2, 1, 0, \ + 7, 6, 5, 4, \ + 11, 10, 9, 8, \ + 15, 14, 13, 12 +pb_shuffle16be: db 1, 0, 3, 2, \ + 5, 4, 7, 6, \ + 9, 8, 11, 10, \ + 13, 12, 15, 14, \ + 1, 0, 3, 2, \ + 5, 4, 7, 6, \ + 9, 8, 11, 10, \ + 13, 12, 15, 14 SECTION .text ;----------------------------------------------------------------------------- @@ -109,23 +133,18 @@ SECTION .text ; %2 = rgb or bgr %macro RGB24_TO_Y_FN 2-3 cglobal %2 %+ 24ToY, 6, 6, %1, dst, src, u1, u2, w, table -%if mmsize == 8 - mova m5, [%2_Ycoeff_12x4] - mova m6, [%2_Ycoeff_3x56] -%define coeff1 m5 -%define coeff2 m6 -%elif ARCH_X86_64 +%if ARCH_X86_64 mova m8, [%2_Ycoeff_12x4] mova m9, [%2_Ycoeff_3x56] %define coeff1 m8 %define coeff2 m9 -%else ; x86-32 && mmsize == 16 +%else ; x86-32 %define coeff1 [%2_Ycoeff_12x4] %define coeff2 [%2_Ycoeff_3x56] -%endif ; x86-32/64 && mmsize == 8/16 -%if (ARCH_X86_64 || mmsize == 8) && %0 == 3 +%endif ; x86-32/64 +%if ARCH_X86_64 && %0 == 3 jmp mangle(private_prefix %+ _ %+ %3 %+ 24ToY %+ SUFFIX).body -%else ; (ARCH_X86_64 && %0 == 3) || mmsize == 8 +%else ; ARCH_X86_64 && %0 == 3 .body: %if cpuflag(ssse3) mova m7, [shuf_rgb_12x4] @@ -160,7 +179,6 @@ cglobal %2 %+ 24ToY, 6, 6, %1, dst, src, u1, u2, w, table movd m1, [srcq+2] ; (byte) { R0, B1, G1, R1 } movd m2, [srcq+6] ; (byte) { B2, G2, R2, B3 } movd m3, [srcq+8] ; (byte) { R2, B3, G3, R3 } -%if mmsize == 16 ; i.e. sse2 punpckldq m0, m2 ; (byte) { B0, G0, R0, B1, B2, G2, R2, B3 } punpckldq m1, m3 ; (byte) { R0, B1, G1, R1, R2, B3, G3, R3 } movd m2, [srcq+12] ; (byte) { B4, G4, R4, B5 } @@ -169,7 +187,6 @@ cglobal %2 %+ 24ToY, 6, 6, %1, dst, src, u1, u2, w, table movd m6, [srcq+20] ; (byte) { R6, B7, G7, R7 } punpckldq m2, m5 ; (byte) { B4, G4, R4, B5, B6, G6, R6, B7 } punpckldq m3, m6 ; (byte) { R4, B5, G5, R5, R6, B7, G7, R7 } -%endif ; mmsize == 16 punpcklbw m0, m7 ; (word) { B0, G0, R0, B1, B2, G2, R2, B3 } punpcklbw m1, m7 ; (word) { R0, B1, G1, R1, R2, B3, G3, R3 } punpcklbw m2, m7 ; (word) { B4, G4, R4, B5, B6, G6, R6, B7 } @@ -191,7 +208,7 @@ cglobal %2 %+ 24ToY, 6, 6, %1, dst, src, u1, u2, w, table add wq, mmsize jl .loop REP_RET -%endif ; (ARCH_X86_64 && %0 == 3) || mmsize == 8 +%endif ; ARCH_X86_64 && %0 == 3 %endmacro ; %1 = nr. of XMM registers @@ -251,12 +268,10 @@ cglobal %2 %+ 24ToUV, 7, 7, %1, dstU, dstV, u1, src, u2, w, table movd m1, [srcq+2] ; (byte) { R0, B1, G1, R1 } movd m4, [srcq+6] ; (byte) { B2, G2, R2, B3 } movd m5, [srcq+8] ; (byte) { R2, B3, G3, R3 } -%if mmsize == 16 punpckldq m0, m4 ; (byte) { B0, G0, R0, B1, B2, G2, R2, B3 } punpckldq m1, m5 ; (byte) { R0, B1, G1, R1, R2, B3, G3, R3 } movd m4, [srcq+12] ; (byte) { B4, G4, R4, B5 } movd m5, [srcq+14] ; (byte) { R4, B5, G5, R5 } -%endif ; mmsize == 16 punpcklbw m0, m7 ; (word) { B0, G0, R0, B1, B2, G2, R2, B3 } punpcklbw m1, m7 ; (word) { R0, B1, G1, R1, R2, B3, G3, R3 } %endif ; cpuflag(ssse3) @@ -270,12 +285,10 @@ cglobal %2 %+ 24ToUV, 7, 7, %1, dstU, dstV, u1, src, u2, w, table pshufb m5, m4, shuf_rgb2 ; (word) { R4, B5, G5, R5, R6, B7, G7, R7 } pshufb m4, shuf_rgb1 ; (word) { B4, G4, R4, B5, B6, G6, R6, B7 } %else ; !cpuflag(ssse3) -%if mmsize == 16 movd m1, [srcq+18] ; (byte) { B6, G6, R6, B7 } movd m3, [srcq+20] ; (byte) { R6, B7, G7, R7 } punpckldq m4, m1 ; (byte) { B4, G4, R4, B5, B6, G6, R6, B7 } punpckldq m5, m3 ; (byte) { R4, B5, G5, R5, R6, B7, G7, R7 } -%endif ; mmsize == 16 && !cpuflag(ssse3) punpcklbw m4, m7 ; (word) { B4, G4, R4, B5, B6, G6, R6, B7 } punpcklbw m5, m7 ; (word) { R4, B5, G5, R5, R6, B7, G7, R7 } %endif ; cpuflag(ssse3) @@ -296,13 +309,8 @@ cglobal %2 %+ 24ToUV, 7, 7, %1, dstU, dstV, u1, src, u2, w, table psrad m4, 9 packssdw m0, m1 ; (word) { U[0-7] } packssdw m2, m4 ; (word) { V[0-7] } -%if mmsize == 8 mova [dstUq+wq], m0 mova [dstVq+wq], m2 -%else ; mmsize == 16 - mova [dstUq+wq], m0 - mova [dstVq+wq], m2 -%endif ; mmsize == 8/16 add wq, mmsize jl .loop REP_RET @@ -318,11 +326,6 @@ RGB24_TO_UV_FN %2, rgb RGB24_TO_UV_FN %2, bgr, rgb %endmacro -%if ARCH_X86_32 -INIT_MMX mmx -RGB24_FUNCS 0, 0 -%endif - INIT_XMM sse2 RGB24_FUNCS 10, 12 @@ -459,13 +462,8 @@ cglobal %2%3%4%5 %+ ToUV, 7, 7, %1, dstU, dstV, u1, src, u2, w, table psrad m1, 9 packssdw m0, m4 ; (word) { U[0-7] } packssdw m2, m1 ; (word) { V[0-7] } -%if mmsize == 8 mova [dstUq+wq], m0 mova [dstVq+wq], m2 -%else ; mmsize == 16 - mova [dstUq+wq], m0 - mova [dstVq+wq], m2 -%endif ; mmsize == 8/16 add wq, mmsize jl .loop sub wq, mmsize - 1 @@ -511,11 +509,6 @@ RGB32_TO_UV_FN %2, a, r, g, b, rgba RGB32_TO_UV_FN %2, a, b, g, r, rgba %endmacro -%if ARCH_X86_32 -INIT_MMX mmx -RGB32_FUNCS 0, 0 -%endif - INIT_XMM sse2 RGB32_FUNCS 8, 12 @@ -564,25 +557,18 @@ cglobal %2ToY, 5, 5, %1, dst, unused0, unused1, src, w movsxd wq, wd %endif add dstq, wq -%if mmsize == 16 test srcq, 15 -%endif lea srcq, [srcq+wq*2] %ifidn %2, yuyv pcmpeqb m2, m2 ; (byte) { 0xff } x 16 psrlw m2, 8 ; (word) { 0x00ff } x 8 %endif ; yuyv -%if mmsize == 16 jnz .loop_u_start neg wq LOOP_YUYV_TO_Y a, %2 .loop_u_start: neg wq LOOP_YUYV_TO_Y u, %2 -%else ; mmsize == 8 - neg wq - LOOP_YUYV_TO_Y a, %2 -%endif ; mmsize == 8/16 %endmacro ; %1 = a (aligned) or u (unaligned) @@ -608,16 +594,9 @@ cglobal %2ToY, 5, 5, %1, dst, unused0, unused1, src, w packuswb m0, m1 ; (byte) { U0, V0, ..., U7, V7 } pand m1, m0, m2 ; (word) { U0, U1, ..., U7 } psrlw m0, 8 ; (word) { V0, V1, ..., V7 } -%if mmsize == 16 packuswb m1, m0 ; (byte) { U0, ... U7, V1, ... V7 } movh [dstUq+wq], m1 movhps [dstVq+wq], m1 -%else ; mmsize == 8 - packuswb m1, m1 ; (byte) { U0, ... U3 } - packuswb m0, m0 ; (byte) { V0, ... V3 } - movh [dstUq+wq], m1 - movh [dstVq+wq], m0 -%endif ; mmsize == 8/16 add wq, mmsize / 2 jl .loop_%1 REP_RET @@ -637,24 +616,24 @@ cglobal %2ToUV, 4, 5, %1, dstU, dstV, unused, src, w %endif add dstUq, wq add dstVq, wq -%if mmsize == 16 && %0 == 2 +%if %0 == 2 test srcq, 15 %endif lea srcq, [srcq+wq*4] pcmpeqb m2, m2 ; (byte) { 0xff } x 16 psrlw m2, 8 ; (word) { 0x00ff } x 8 ; NOTE: if uyvy+avx, u/a are identical -%if mmsize == 16 && %0 == 2 +%if %0 == 2 jnz .loop_u_start neg wq LOOP_YUYV_TO_UV a, %2 .loop_u_start: neg wq LOOP_YUYV_TO_UV u, %2 -%else ; mmsize == 8 +%else neg wq LOOP_YUYV_TO_UV a, %2 -%endif ; mmsize == 8/16 +%endif %endmacro ; %1 = a (aligned) or u (unaligned) @@ -692,35 +671,18 @@ cglobal %2ToUV, 4, 5, %1, dstU, dstV, unused, src, w %endif add dstUq, wq add dstVq, wq -%if mmsize == 16 test srcq, 15 -%endif lea srcq, [srcq+wq*2] pcmpeqb m5, m5 ; (byte) { 0xff } x 16 psrlw m5, 8 ; (word) { 0x00ff } x 8 -%if mmsize == 16 jnz .loop_u_start neg wq LOOP_NVXX_TO_UV a, %2 .loop_u_start: neg wq LOOP_NVXX_TO_UV u, %2 -%else ; mmsize == 8 - neg wq - LOOP_NVXX_TO_UV a, %2 -%endif ; mmsize == 8/16 %endmacro -%if ARCH_X86_32 -INIT_MMX mmx -YUYV_TO_Y_FN 0, yuyv -YUYV_TO_Y_FN 0, uyvy -YUYV_TO_UV_FN 0, yuyv -YUYV_TO_UV_FN 0, uyvy -NVXX_TO_UV_FN 0, nv12 -NVXX_TO_UV_FN 0, nv21 -%endif - INIT_XMM sse2 YUYV_TO_Y_FN 3, yuyv YUYV_TO_Y_FN 2, uyvy @@ -738,3 +700,461 @@ YUYV_TO_UV_FN 3, uyvy, 1 NVXX_TO_UV_FN 5, nv12 NVXX_TO_UV_FN 5, nv21 %endif + +%if ARCH_X86_64 +%define RY_IDX 0 +%define GY_IDX 1 +%define BY_IDX 2 +%define RU_IDX 3 +%define GU_IDX 4 +%define BU_IDX 5 +%define RV_IDX 6 +%define GV_IDX 7 +%define BV_IDX 8 +%define RGB2YUV_SHIFT 15 + +%define R m0 +%define G m1 +%define B m2 + +%macro SWAP32 1 +%if mmsize > 16 || cpuflag(sse4) + pshufb m%1, [pb_shuffle32be] +%else + psrlw xm7, xm%1, 8 + psllw xm%1, 8 + por xm%1, xm7 + pshuflw xm%1, xm%1, (2 << 6 | 3 << 4 | 0 << 2 | 1 << 0) + pshufhw xm%1, xm%1, (2 << 6 | 3 << 4 | 0 << 2 | 1 << 0) +%endif +%endmacro + +; 1 - dest +; 2 - source +; 3 - is big endian +; 4 - load only 2 values on sse2 +%macro LOADF32 4 + %if notcpuflag(sse4) && %4 + %if %3 ; big endian + mov tmp1q, %2 + bswap tmp1q + movq xm%1, tmp1q + %else + movq m%1, %2 + %endif + %else + movu m%1, %2 + %if %3 + SWAP32 %1 + %endif + %endif + maxps m%1, m9 ; 0.0 (nan, -inf) -> 0.0 + mulps m%1, m8 ; [pd_65535f] + minps m%1, m8 ; +inf -> 65535 + ; cvtps2dq rounds to nearest int + ; assuming mxcsr register is default rounding + ; 0.40 -> 0.0, 0.50 -> 0.0, 0.51 -> 1.0 + cvtps2dq m%1, m%1 + + %if notcpuflag(sse4) && %4 + ; line up the 2 values in lanes 0,2 + %if %3 ; big endian + pshufd m%1, m%1, (3 << 6 | 0 << 4 | 2 << 2 | 1 << 0) + %else + pshufd m%1, m%1, (3 << 6 | 1 << 4 | 2 << 2 | 0 << 0) + %endif + %endif +%endmacro + +; 1 - dest +; 2 - source +; 3 - is big endian +%macro LOAD16 3 + %if cpuflag(sse4) || mmsize > 16 + pmovzxwd m%1, %2 + %if %3 ; bigendian + pshufb m%1, m8 ; [pb_shuffle16be] + %endif + %else + %if %3 ; bigendian + mov tmp1d, dword %2 + bswap tmp1d + movd xm%1, tmp1d + pshuflw m%1, m%1, (3 << 6 | 0 << 4 | 3 << 2 | 1 << 0) + pshufd m%1, m%1, (3 << 6 | 1 << 4 | 2 << 2 | 0 << 0) + %else + movd xm%1, %2 + punpcklwd m%1, m9 ; interleave words with zero + pshufd m%1, m%1, (3 << 6 | 1 << 4 | 2 << 2 | 0 << 0) + %endif + %endif +%endmacro + +%macro LOAD8_RGB 0 + %if cpuflag(sse4) || mmsize > 16 + pmovzxbd R, [srcRq + xq] + pmovzxbd G, [srcGq + xq] + pmovzxbd B, [srcBq + xq] + %else + ; thought this would be faster but from my measurments its not + ; movd m0, [srcRq + xq + 0]; overeads by 2 bytes + ; punpcklbw m0, m9 ; interleave bytes with zero + ; punpcklwd m0, m9 ; interleave words with zero + ; pshufd m0, m0, (3 << 6 | 1 << 4 | 2 << 2 | 0 << 0) + + movzx tmp2q, byte [srcRq + xq + 1] + movzx tmp1q, byte [srcRq + xq + 0] + shl tmp2q, 32 + or tmp1q, tmp2q + movq xm0, tmp1q + + movzx tmp2q, byte [srcGq + xq + 1] + movzx tmp3q, byte [srcGq + xq + 0] + shl tmp2q, 32 + or tmp3q, tmp2q + movq xm1, tmp3q + + movzx tmp2q, byte [srcBq + xq + 1] + movzx tmp1q, byte [srcBq + xq + 0] + shl tmp2q, 32 + or tmp1q, tmp2q + movq xm2, tmp1q + + pshufd m0, m0, (3 << 6 | 1 << 4 | 2 << 2 | 0 << 0) + pshufd m1, m1, (3 << 6 | 1 << 4 | 2 << 2 | 0 << 0) + pshufd m2, m2, (3 << 6 | 1 << 4 | 2 << 2 | 0 << 0) + %endif +%endmacro + +; 1 - dest +; 2 - source +; 3 - store only 2 values on sse2 +%macro STORE16 3 + %if %3 && notcpuflag(sse4) + pshufd m%2, m%2, (3 << 6 | 1 << 4 | 2 << 2 | 0 << 0) + pshuflw m%2, m%2, (3 << 6 | 1 << 4 | 2 << 2 | 0 << 0) + movd %1, m%2 + %elif mmsize > 16 + pshufb m%2, m7 ; [pb_pack_shuffle16le] + vpermq m%2, m%2, (3 << 6 | 0 << 4 | 3 << 2 | 0 << 0) + movu %1, xm%2 + %else + %if cpuflag(sse4) + pshufb m%2, m7 ; [pb_pack_shuffle16le] + %else + pshuflw m%2, m%2, (1 << 6 | 1 << 4 | 2 << 2 | 0 << 0) + pshufhw m%2, m%2, (1 << 6 | 1 << 4 | 2 << 2 | 0 << 0) + pshufd m%2, m%2, (3 << 6 | 3 << 4 | 2 << 2 | 0 << 0) + %endif + movq %1, m%2 + %endif +%endmacro + +%macro PMUL 3 +%if cpuflag(sse4) || mmsize > 16 + pmulld %1, %2, %3 +%else + pmuludq %1, %2, %3 +%endif +%endmacro + +; 1 - name +; 2 - depth +; 3 - is big endian +; 4 - is float +; in sse2 mode only 2 values are done per loop, due to lack of pmulld instruction +%macro planar_rgb_to_y_fn 4 +%if %2 == 8 + %define OFFSET (0x801<<(RGB2YUV_SHIFT-7)) + %define RSHIFT (RGB2YUV_SHIFT-6) +%else + %if %2 < 16 + %define SHIFT %2 + %define BPC %2 + %else + %define SHIFT 14 + %define BPC 16 + %endif + %define OFFSET ((16 << (RGB2YUV_SHIFT + BPC - 8)) + (1 << (RGB2YUV_SHIFT + SHIFT - 15))) + %define RSHIFT (RGB2YUV_SHIFT + SHIFT - 14) +%endif +cglobal planar_%1_to_y, 4, 12, 13, dst, src, w, rgb2yuv, srcR, srcG, srcB, x, tmp1, tmp2, tmp3, tmp4 + VBROADCASTSS m10, dword [rgb2yuvq + RY_IDX*4] ; ry + VBROADCASTSS m11, dword [rgb2yuvq + GY_IDX*4] ; gy + VBROADCASTSS m12, dword [rgb2yuvq + BY_IDX*4] ; by + pxor m9, m9 + + %if %4 + movu m8, [pd_65535f] + %endif + + %if cpuflag(sse4) || mmsize > 16 + movu m7, [pb_pack_shuffle16le] + %if %3 && %2 > 8 && %2 <= 16 + movu m8, [pb_shuffle16be] + %endif + %endif + + mov xq, OFFSET + movq xm6, xq + VBROADCASTSS m6, xm6 + + mov srcGq, [srcq + 0] + mov srcBq, [srcq + 8] + mov srcRq, [srcq + 16] + + xor xq, xq + %%loop_x: + %if %4 + LOADF32 0, [srcRq + xq*4], %3, 1 + LOADF32 1, [srcGq + xq*4], %3, 1 + LOADF32 2, [srcBq + xq*4], %3, 1 + %elif %2 == 8 + LOAD8_RGB + %else + LOAD16 0, [srcRq + xq*2], %3 + LOAD16 1, [srcGq + xq*2], %3 + LOAD16 2, [srcBq + xq*2], %3 + %endif + + PMUL R, R, m10 ; r*ry + PMUL G, G, m11 ; g*gy + PMUL B, B, m12 ; b*by + paddd m0, m6 ; + OFFSET + paddd B, G + paddd m0, B + psrad m0, RSHIFT + STORE16 [dstq + 2*xq], 0, 1 + + %if cpuflag(avx2) || cpuflag(sse4) + add xq, mmsize/4 + %else + add xd, 2 + %endif + cmp xd, wd + jl %%loop_x +RET +%endmacro + +; 1 - name +; 2 - depth +; 3 - is big endian +; 4 - is float +; in sse2 mode only 2 values are done per loop, due to lack of pmulld instruction +%macro planar_rgb_to_uv_fn 4 +%if %2 == 8 + %define OFFSET (0x4001<<(RGB2YUV_SHIFT-7)) + %define RSHIFT (RGB2YUV_SHIFT-6) +%else + %if %2 < 16 + %define SHIFT %2 + %define BPC %2 + %else + %define SHIFT 14 + %define BPC 16 + %endif + %define OFFSET ((128 << (RGB2YUV_SHIFT + BPC - 8)) + (1 << (RGB2YUV_SHIFT + SHIFT - 15))) + %define RSHIFT (RGB2YUV_SHIFT + SHIFT - 14) +%endif +cglobal planar_%1_to_uv, 5, 12, 16, dstU, dstV, src, w, rgb2yuv, srcR, srcG, srcB, x, tmp1, tmp2, tmp3 + VBROADCASTSS m10, dword [rgb2yuvq + RU_IDX*4] ; ru + VBROADCASTSS m11, dword [rgb2yuvq + GU_IDX*4] ; gu + VBROADCASTSS m12, dword [rgb2yuvq + BU_IDX*4] ; bu + VBROADCASTSS m13, dword [rgb2yuvq + RV_IDX*4] ; rv + VBROADCASTSS m14, dword [rgb2yuvq + GV_IDX*4] ; gv + VBROADCASTSS m15, dword [rgb2yuvq + BV_IDX*4] ; bv + pxor m9, m9 + + %if %4 + movu m8, [pd_65535f] + %endif + + %if cpuflag(sse4) || mmsize > 16 + movu m7, [pb_pack_shuffle16le] + %if %3 && %2 > 8 && %2 <= 16 + movu m8, [pb_shuffle16be] + %endif + %endif + + mov xq, OFFSET + movq xm6, xq + VBROADCASTSS m6, xm6 + + mov srcGq, [srcq + 0] + mov srcBq, [srcq + 8] + mov srcRq, [srcq + 16] + + xor xq, xq + %%loop_x: + %if %4 + LOADF32 0, [srcRq + xq*4], %3, 1 + LOADF32 1, [srcGq + xq*4], %3, 1 + LOADF32 2, [srcBq + xq*4], %3, 1 + %elif %2 == 8 + LOAD8_RGB + %else + LOAD16 0, [srcRq + xq*2], %3 + LOAD16 1, [srcGq + xq*2], %3 + LOAD16 2, [srcBq + xq*2], %3 + %endif + + PMUL m5, R, m10 ; r*ru + PMUL m4, G, m11 ; b*gu + paddd m4, m5 + PMUL m5, B, m12 ; b*bu + paddd m4, m6 ; + OFFSET + paddd m4, m5 + psrad m4, RSHIFT + STORE16 [dstUq + 2*xq], 4, 1 + + PMUL R, R, m13 ; r*rv + PMUL G, G, m14 ; g*gv*g + PMUL B, B, m15 ; b*bv + paddd m0, m6 ; + OFFSET + paddd B, G + paddd m0, B + psrad m0, RSHIFT + STORE16 [dstVq + 2*xq], 0, 1 + + %if cpuflag(avx2) || cpuflag(sse4) + add xd, mmsize/4 + %else + add xd, 2 + %endif + cmp xd, wd + jl %%loop_x +RET +%endmacro + +; 1 - name +; 2 - depth +; 3 - is big endian +; 4 - is float +%macro planar_rgb_to_a_fn 4 +cglobal planar_%1_to_a, 4, 6, 10, dst, src, w, rgb2yuv, srcA, x + %if %4 && (cpuflag(sse4) || mmsize > 16) + movu m7, [pb_pack_shuffle16le] + %elif %3 && (cpuflag(sse4) || mmsize > 16) + movu m7, [pb_shuffle16be] + %endif + + %if %4 + movu m8, [pd_65535f] + %endif + + pxor m9, m9 + mov srcAq, [srcq + 24] + xor xq, xq + %%loop_x: + %if %4 ; float + LOADF32 0, [srcAq + xq*4], %3, 0 + STORE16 [dstq + xq*2], 0, 0 + add xq, mmsize/4 + %elif %2 == 8 + ; only need to convert 8bit value to 16bit + %if cpuflag(sse4) || mmsize > 16 + pmovzxbw m0, [srcAq + xq] + %else + movsd m0, [srcAq + xq] + punpcklbw m0, m9 ; interleave bytes with zero + %endif + psllw m0, 6 + movu [dstq + xq*2], m0 + add xq, mmsize/2 + %else + ; only need to convert 16bit format to 16le + movu m0, [srcAq + xq*2] + %if %3 ; bigendian + %if cpuflag(sse4) || mmsize > 16 + pshufb m0, m7 ; [pb_shuffle16be] + %else + psrlw m7, m0, 8 + psllw m0, 8 + por m0, m7 + %endif + %endif + %if %2 < 16 + psllw m0, (14 - %2) + %endif + movu [dstq + xq*2], m0 + add xq, mmsize/2 + %endif + cmp xd, wd + jl %%loop_x +RET +%endmacro + +; 1 - name +; 2 - depth +; 3 - is float +%macro planer_rgbxx_y_fn_decl 3 +planar_rgb_to_y_fn %1le, %2, 0, %3 +planar_rgb_to_y_fn %1be, %2, 1, %3 +%endmacro + +; 1 - name +; 2 - depth +; 3 - is float +%macro planer_rgbxx_uv_fn_decl 3 +planar_rgb_to_uv_fn %1le, %2, 0, %3 +planar_rgb_to_uv_fn %1be, %2, 1, %3 +%endmacro + +; 1 - name +; 2 - depth +; 3 - is float +%macro planer_rgbxx_a_fn_decl 3 +planar_rgb_to_a_fn %1le, %2, 0, %3 +planar_rgb_to_a_fn %1be, %2, 1, %3 +%endmacro + +%macro planar_rgb_y_all_fn_decl 0 +planar_rgb_to_y_fn rgb, 8, 0, 0 +planer_rgbxx_y_fn_decl rgb9, 9, 0 +planer_rgbxx_y_fn_decl rgb10, 10, 0 +planer_rgbxx_y_fn_decl rgb12, 12, 0 +planer_rgbxx_y_fn_decl rgb14, 14, 0 +planer_rgbxx_y_fn_decl rgb16, 16, 0 +planer_rgbxx_y_fn_decl rgbf32, 32, 1 +%endmacro + +%macro planar_rgb_uv_all_fn_decl 0 +planar_rgb_to_uv_fn rgb, 8, 0, 0 +planer_rgbxx_uv_fn_decl rgb9, 9, 0 +planer_rgbxx_uv_fn_decl rgb10, 10, 0 +planer_rgbxx_uv_fn_decl rgb12, 12, 0 +planer_rgbxx_uv_fn_decl rgb14, 14, 0 +planer_rgbxx_uv_fn_decl rgb16, 16, 0 +planer_rgbxx_uv_fn_decl rgbf32, 32, 1 +%endmacro + +%macro planar_rgb_a_all_fn_decl 0 +planar_rgb_to_a_fn rgb, 8, 0, 0 +planer_rgbxx_a_fn_decl rgb10, 10, 0 +planer_rgbxx_a_fn_decl rgb12, 12, 0 +planer_rgbxx_a_fn_decl rgb16, 16, 0 +planer_rgbxx_a_fn_decl rgbf32, 32, 1 +%endmacro + +; sse2 to_y only matches c speed with current implementation +; except on floating point formats +INIT_XMM sse2 +planer_rgbxx_y_fn_decl rgbf32, 32, 1 +planar_rgb_uv_all_fn_decl +planar_rgb_a_all_fn_decl + +; sse4 to_a conversions are just the sse2 ones +; except on floating point formats +INIT_XMM sse4 +planar_rgb_y_all_fn_decl +planar_rgb_uv_all_fn_decl +planer_rgbxx_a_fn_decl rgbf32, 32, 1 + +%if HAVE_AVX2_EXTERNAL +INIT_YMM avx2 +planar_rgb_y_all_fn_decl +planar_rgb_uv_all_fn_decl +planar_rgb_a_all_fn_decl +%endif + +%endif ; ARCH_X86_64 diff --git a/libswscale/x86/output.asm b/libswscale/x86/output.asm index 52cf9f2c2..84e94baaf 100644 --- a/libswscale/x86/output.asm +++ b/libswscale/x86/output.asm @@ -38,7 +38,49 @@ pw_32: times 8 dw 32 pd_255: times 8 dd 255 pw_512: times 8 dw 512 pw_1024: times 8 dw 1024 - +pd_65535_invf: times 8 dd 0x37800080 ;1.0/65535.0 +pd_yuv2gbrp16_start: times 8 dd -0x40000000 +pd_yuv2gbrp_y_start: times 8 dd (1 << 9) +pd_yuv2gbrp_uv_start: times 8 dd ((1 << 9) - (128 << 19)) +pd_yuv2gbrp_a_start: times 8 dd (1 << 18) +pd_yuv2gbrp16_offset: times 8 dd 0x10000 ;(1 << 16) +pd_yuv2gbrp16_round13: times 8 dd 0x02000 ;(1 << 13) +pd_yuv2gbrp16_a_offset: times 8 dd 0x20002000 +pd_yuv2gbrp16_upper30: times 8 dd 0x3FFFFFFF ;(1<<30) - 1 +pd_yuv2gbrp16_upper27: times 8 dd 0x07FFFFFF ;(1<<27) - 1 +pd_yuv2gbrp16_upperC: times 8 dd 0xC0000000 +pb_pack_shuffle8: db 0, 4, 8, 12, \ + -1, -1, -1, -1, \ + -1, -1, -1, -1, \ + -1, -1, -1, -1, \ + -1, -1, -1, -1, \ + 0, 4, 8, 12, \ + -1, -1, -1, -1, \ + -1, -1, -1, -1 +pb_pack_shuffle16le: db 0, 1, 4, 5, \ + 8, 9, 12, 13, \ + -1, -1, -1, -1, \ + -1, -1, -1, -1, \ + -1, -1, -1, -1, \ + -1, -1, -1, -1, \ + 0, 1, 4, 5, \ + 8, 9, 12, 13 +pb_pack_shuffle16be: db 1, 0, 5, 4, \ + 9, 8, 13, 12, \ + -1, -1, -1, -1, \ + -1, -1, -1, -1, \ + -1, -1, -1, -1, \ + -1, -1, -1, -1, \ + 1, 0, 5, 4, \ + 9, 8, 13, 12 +pb_shuffle32be: db 3, 2, 1, 0, \ + 7, 6, 5, 4, \ + 11, 10, 9, 8, \ + 15, 14, 13, 12, \ + 3, 2, 1, 0, \ + 7, 6, 5, 4, \ + 11, 10, 9, 8, \ + 15, 14, 13, 12 yuv2nv12_shuffle_mask: times 2 db 0, 4, 8, 12, \ -1, -1, -1, -1, \ -1, -1, -1, -1, \ @@ -270,11 +312,9 @@ cglobal yuv2planeX_%1, %3, 8, %2, filter, fltsize, src, dst, w, dither, offset %endif ; %1 == 8/9/10/16 %endmacro -%if ARCH_X86_32 +%if ARCH_X86_32 && HAVE_ALIGNED_STACK == 0 INIT_MMX mmxext yuv2planeX_fn 8, 0, 7 -yuv2planeX_fn 9, 0, 5 -yuv2planeX_fn 10, 0, 5 %endif INIT_XMM sse2 @@ -365,19 +405,11 @@ cglobal yuv2plane1_%1, %3, %3, %2, src, dst, w, dither, offset movq m3, [ditherq] ; dither test offsetd, offsetd jz .no_rot -%if mmsize == 16 punpcklqdq m3, m3 -%endif ; mmsize == 16 PALIGNR m3, m3, 3, m2 .no_rot: -%if mmsize == 8 - mova m2, m3 - punpckhbw m3, m4 ; byte->word - punpcklbw m2, m4 ; byte->word -%else punpcklbw m3, m4 mova m2, m3 -%endif %elif %1 == 9 pxor m4, m4 mova m3, [pw_512] @@ -389,36 +421,22 @@ cglobal yuv2plane1_%1, %3, %3, %2, src, dst, w, dither, offset %else ; %1 == 16 %if cpuflag(sse4) ; sse4/avx mova m4, [pd_4] -%else ; mmx/sse2 +%else ; sse2 mova m4, [pd_4min0x40000] mova m5, [minshort] -%endif ; mmx/sse2/sse4/avx +%endif ; sse2/sse4/avx %endif ; %1 == .. ; actual pixel scaling -%if mmsize == 8 - yuv2plane1_mainloop %1, a -%else ; mmsize == 16 test dstq, 15 jnz .unaligned yuv2plane1_mainloop %1, a REP_RET .unaligned: yuv2plane1_mainloop %1, u -%endif ; mmsize == 8/16 REP_RET %endmacro -%if ARCH_X86_32 -INIT_MMX mmx -yuv2plane1_fn 8, 0, 5 -yuv2plane1_fn 16, 0, 3 - -INIT_MMX mmxext -yuv2plane1_fn 9, 0, 3 -yuv2plane1_fn 10, 0, 3 -%endif - INIT_XMM sse2 yuv2plane1_fn 8, 5, 5 yuv2plane1_fn 9, 5, 3 @@ -549,3 +567,393 @@ yuv2nv12cX_fn yuv2nv12 yuv2nv12cX_fn yuv2nv21 %endif %endif ; ARCH_X86_64 + +;----------------------------------------------------------------------------- +; planar grb yuv2anyX functions +; void ff_yuv2_full_X_(SwsContext *c, const int16_t *lumFilter, +; const int16_t **lumSrcx, int lumFilterSize, +; const int16_t *chrFilter, const int16_t **chrUSrcx, +; const int16_t **chrVSrcx, int chrFilterSize, +; const int16_t **alpSrcx, uint8_t **dest, +; int dstW, int y) +;----------------------------------------------------------------------------- + +%if ARCH_X86_64 +struc SwsContext + .padding: resb 40292 ; offsetof(SwsContext, yuv2rgb_y_offset) + .yuv2rgb_y_offset: resd 1 + .yuv2rgb_y_coeff: resd 1 + .yuv2rgb_v2r_coeff: resd 1 + .yuv2rgb_v2g_coeff: resd 1 + .yuv2rgb_u2g_coeff: resd 1 + .yuv2rgb_u2b_coeff: resd 1 +endstruc + +%define R m0 +%define G m1 +%define B m2 +%define A m3 + +%define Y m4 +%define U m5 +%define V m6 + +; Clip a signed integer to an unsigned power of two range. +; av_clip_uintp2 +; 1 - dest +; 2 - bit position to clip at +%macro CLIPP2 2 + ; (~a) >> 31 & ((1<= 16 + movu m%1, [ptrq + xq*4] +%else + LOAD16 %1, [ptrq + xq*2] +%endif +%endmacro + +; 1 - dest +; 2 - source +%macro STORE8 2 + mov ptrq, %1 + %if mmsize > 16 + pshufb m%2, [pb_pack_shuffle8] + vextractf128 xm4, m%2, 1 + por xm%2, xm4 + movq [ptrq + xq], xm%2 + %else + %if cpuflag(sse4) + pshufb m%2, [pb_pack_shuffle8] + %else + psrldq m4, m%2, 3 + por m%2, m4 + psrldq m4, m%2, 6 + por m%2, m4 + %endif + movd [ptrq + xq], m%2 + %endif +%endmacro + +; 1 - dest +; 2 - source +; 3 - is big endian +%macro STORE16 3 + mov ptrq, %1 + %if mmsize > 16 + %if %3 ; bigendian + pshufb m%2, [pb_pack_shuffle16be] + %else + pshufb m%2, [pb_pack_shuffle16le] + %endif + vpermq m%2, m%2, (3 << 6 | 0 << 4 | 3 << 2 | 0 << 0) + movu [ptrq + xq*2], xm%2 + %else + %if cpuflag(sse4) && %3 ; bigendian + pshufb m%2, [pb_pack_shuffle16be] + %elif cpuflag(sse4) + pshufb m%2, [pb_pack_shuffle16le] + %else + pshuflw m%2, m%2, (1 << 6 | 1 << 4 | 2 << 2 | 0 << 0) + pshufhw m%2, m%2, (1 << 6 | 1 << 4 | 2 << 2 | 0 << 0) + pshufd m%2, m%2, (3 << 6 | 3 << 4 | 2 << 2 | 0 << 0) + %if %3 ; bigendian + psrlw m4, m%2, 8 + psllw m%2, 8 + por m%2, m4 + %endif + %endif + movq [ptrq + xq*2], m%2 + %endif +%endmacro + +%macro SWAP32 1 +%if mmsize > 16 || cpuflag(sse4) + pshufb m%1, [pb_shuffle32be] +%else + psrlw m4, m%1, 8 + psllw m%1, 8 + por m%1, m4 + pshuflw m%1, m%1, (2 << 6 | 3 << 4 | 0 << 2 | 1 << 0) + pshufhw m%1, m%1, (2 << 6 | 3 << 4 | 0 << 2 | 1 << 0) +%endif +%endmacro + +; 1 - dest +; 2 - source +; 3 - depth +; 4 - is big endian +%macro STORE_PIXELS 4 +%if %3 > 16 + %if %4 + SWAP32 %2 + %endif + mov ptrq, %1 + movu [ptrq + xq*4], m%2 +%elif %3 > 8 + STORE16 %1, %2, %4 +%else + STORE8 %1, %2 +%endif +%endmacro + +%macro PMULLO 3 +%if cpuflag(sse4) || mmsize > 16 + pmulld %1, %2, %3 +%else + %ifidni %1, %2 + %else + mova %1, %2 + %endif + pshufd m7, %1, (2 << 6 | 3 << 4 | 0 << 2 | 1 << 0) ; 0xb1 + pshufd m8, %3, (2 << 6 | 3 << 4 | 0 << 2 | 1 << 0) ; 0xb1 + pmuludq m7, m8 + pshufd m7, m7, (3 << 6 | 1 << 4 | 2 << 2 | 0 << 0) ; 0xd8 + pmuludq %1, %3 + pshufd %1, %1, (3 << 6 | 1 << 4 | 2 << 2 | 0 << 0) ; 0xd8 + punpckldq %1, m7 +%endif +%endmacro + +; 1 - name +; 2 - depth +; 3 - has alpha +; 3 - is big endian +; 5 - is float +%macro yuv2gbrp_fn 5 +%define DEPTH %2 +%define HAS_ALPHA %3 +%define IS_BE %4 +%define FLOAT %5 +%define SH (22 + 8 - DEPTH) + +%if DEPTH >= 16 + %define RGB_SHIFT 14 + %define A_SHIFT 14 +%elif 22 != SH + %define RGB_SHIFT SH + %define A_SHIFT (SH-3) +%else + %define RGB_SHIFT 22 + %define A_SHIFT 19 +%endif + +%if DEPTH >= 16 + %define YUV_SHIFT 14 + %define Y_START m9 + %define Y_ROUND [pd_yuv2gbrp16_round13] + %define UV_START m9 + %define A_START m9 + %define A_CLIP2P 30 +%else + %define YUV_SHIFT 10 + %define Y_START [pd_yuv2gbrp_y_start] + %define Y_ROUND m9 + %define UV_START [pd_yuv2gbrp_uv_start] + %define A_START [pd_yuv2gbrp_a_start] + %define A_CLIP2P 27 +%endif + +cglobal yuv2%1_full_X, 12, 14, 16, ptr, lumFilter, lumSrcx, lumFilterSize, chrFilter, chrUSrcx, chrVSrcx, chrFilterSize, alpSrcx, dest, dstW, y, x, j + VBROADCASTSS m10, dword [ptrq + SwsContext.yuv2rgb_y_offset] + VBROADCASTSS m11, dword [ptrq + SwsContext.yuv2rgb_y_coeff] + VBROADCASTSS m12, dword [ptrq + SwsContext.yuv2rgb_v2r_coeff] + VBROADCASTSS m13, dword [ptrq + SwsContext.yuv2rgb_v2g_coeff] + VBROADCASTSS m14, dword [ptrq + SwsContext.yuv2rgb_u2g_coeff] + VBROADCASTSS m15, dword [ptrq + SwsContext.yuv2rgb_u2b_coeff] + +%if DEPTH >= 16 + movu m9, [pd_yuv2gbrp16_start] +%else + mov xq, (1 << (SH-1)) + movq xm9, xq + VBROADCASTSS m9, xm9 +%endif + xor xq, xq + + %%loop_x: + movu Y, Y_START + movu U, UV_START + movu V, UV_START + + xor jq, jq + %%loop_luma: + movsx ptrd, word [lumFilterq + jq*2] + movd xm0, ptrd + VBROADCASTSS m0, xm0 + LOAD_PIXELS 1, lumSrcxq, DEPTH + PMULLO m1, m1, m0 + paddd Y, m1 + inc jd + cmp jd, lumFilterSized + jl %%loop_luma + +%if HAS_ALPHA + cmp alpSrcxq, 0 + je %%skip_alpha_load + xor jq, jq + movu A, A_START + %%loop_alpha: + movsx ptrd, word [lumFilterq + jq*2] + movd xm0, ptrd + VBROADCASTSS m0, xm0 + LOAD_PIXELS 1, alpSrcxq, DEPTH + PMULLO m1, m1, m0 + paddd A, m1 + inc jd + cmp jd, lumFilterSized + jl %%loop_alpha +%if DEPTH >= 16 + psrad A, 1 + paddd A, [pd_yuv2gbrp16_a_offset] +%endif + %%skip_alpha_load: +%endif + xor jq, jq + %%loop_chr: + movsx ptrd, word [chrFilterq + jq*2] + movd xm0, ptrd + VBROADCASTSS m0, xm0 + LOAD_PIXELS 1, chrUSrcxq, DEPTH + LOAD_PIXELS 2, chrVSrcxq, DEPTH + PMULLO m1, m1, m0 + PMULLO m2, m2, m0 + paddd U, m1 + paddd V, m2 + inc jd + cmp jd, chrFilterSized + jl %%loop_chr + + psrad Y, YUV_SHIFT +%if DEPTH >= 16 + paddd Y, [pd_yuv2gbrp16_offset] +%endif + psrad U, YUV_SHIFT + psrad V, YUV_SHIFT + + psubd Y, m10 ; yuv2rgb_y_offset + PMULLO Y, Y, m11 ; yuv2rgb_y_coeff + paddd Y, Y_ROUND + + PMULLO R, V, m12 ; yuv2rgb_v2r_coeff + PMULLO B, U, m15 ; yuv2rgb_u2b_coeff + + PMULLO U, U, m14 ; yuv2rgb_u2g_coeff + PMULLO V, V, m13 ; yuv2rgb_v2g_coeff + paddd G, U, V + paddd R, Y + paddd G, Y + paddd B, Y + + CLIPP2 R, 30 + CLIPP2 G, 30 + CLIPP2 B, 30 + + psrad R, RGB_SHIFT + psrad G, RGB_SHIFT + psrad B, RGB_SHIFT + +%if FLOAT + cvtdq2ps R, R + cvtdq2ps G, G + cvtdq2ps B, B + mulps R, [pd_65535_invf] + mulps G, [pd_65535_invf] + mulps B, [pd_65535_invf] +%endif + STORE_PIXELS [destq + 0], 1, DEPTH, IS_BE ; G + STORE_PIXELS [destq + 8], 2, DEPTH, IS_BE ; B + STORE_PIXELS [destq + 16], 0, DEPTH, IS_BE ; R + +%if HAS_ALPHA + cmp alpSrcxq, 0 + je %%skip_alpha_store + CLIPP2 A, A_CLIP2P + psrad A, A_SHIFT +%if FLOAT + cvtdq2ps A, A + mulps A, [pd_65535_invf] +%endif + STORE_PIXELS [destq + 24], 3, DEPTH, IS_BE + %%skip_alpha_store: +%endif + add xq, mmsize/4 + cmp xd, dstWd + jl %%loop_x + + RET +%endmacro + +%macro yuv2gbrp_fn_decl 2 +INIT_%1 %2 +yuv2gbrp_fn gbrp, 8, 0, 0, 0 +yuv2gbrp_fn gbrap, 8, 1, 0, 0 +yuv2gbrp_fn gbrp9le, 9, 0, 0, 0 +yuv2gbrp_fn gbrp10le, 10, 0, 0, 0 +yuv2gbrp_fn gbrap10le, 10, 1, 0, 0 +yuv2gbrp_fn gbrp12le, 12, 0, 0, 0 +yuv2gbrp_fn gbrap12le, 12, 1, 0, 0 +yuv2gbrp_fn gbrp14le, 14, 0, 0, 0 +yuv2gbrp_fn gbrp16le, 16, 0, 0, 0 +yuv2gbrp_fn gbrap16le, 16, 1, 0, 0 +yuv2gbrp_fn gbrpf32le, 32, 0, 0, 1 +yuv2gbrp_fn gbrapf32le, 32, 1, 0, 1 + +yuv2gbrp_fn gbrp9be, 9, 0, 1, 0 +yuv2gbrp_fn gbrp10be, 10, 0, 1, 0 +yuv2gbrp_fn gbrap10be, 10, 1, 1, 0 +yuv2gbrp_fn gbrp12be, 12, 0, 1, 0 +yuv2gbrp_fn gbrap12be, 12, 1, 1, 0 +yuv2gbrp_fn gbrp14be, 14, 0, 1, 0 +yuv2gbrp_fn gbrp16be, 16, 0, 1, 0 +yuv2gbrp_fn gbrap16be, 16, 1, 1, 0 +yuv2gbrp_fn gbrpf32be, 32, 0, 1, 1 +yuv2gbrp_fn gbrapf32be, 32, 1, 1, 1 +%endmacro + +yuv2gbrp_fn_decl XMM, sse2 +yuv2gbrp_fn_decl XMM, sse4 + +%if HAVE_AVX2_EXTERNAL +yuv2gbrp_fn_decl YMM, avx2 +%endif + +%endif ; ARCH_X86_64 diff --git a/libswscale/x86/rgb2rgb.c b/libswscale/x86/rgb2rgb.c index 0ab139aca..b325e5dbd 100644 --- a/libswscale/x86/rgb2rgb.c +++ b/libswscale/x86/rgb2rgb.c @@ -85,20 +85,11 @@ DECLARE_ALIGNED(8, extern const uint64_t, ff_bgr2UVOffset); // Note: We have C, MMX, MMXEXT, 3DNOW versions, there is no 3DNOW + MMXEXT one. -#define COMPILE_TEMPLATE_MMXEXT 0 -#define COMPILE_TEMPLATE_AMD3DNOW 0 #define COMPILE_TEMPLATE_SSE2 0 #define COMPILE_TEMPLATE_AVX 0 -//MMX versions -#undef RENAME -#define RENAME(a) a ## _mmx -#include "rgb2rgb_template.c" - // MMXEXT versions #undef RENAME -#undef COMPILE_TEMPLATE_MMXEXT -#define COMPILE_TEMPLATE_MMXEXT 1 #define RENAME(a) a ## _mmxext #include "rgb2rgb_template.c" @@ -116,19 +107,6 @@ DECLARE_ALIGNED(8, extern const uint64_t, ff_bgr2UVOffset); #define RENAME(a) a ## _avx #include "rgb2rgb_template.c" -//3DNOW versions -#undef RENAME -#undef COMPILE_TEMPLATE_MMXEXT -#undef COMPILE_TEMPLATE_SSE2 -#undef COMPILE_TEMPLATE_AVX -#undef COMPILE_TEMPLATE_AMD3DNOW -#define COMPILE_TEMPLATE_MMXEXT 0 -#define COMPILE_TEMPLATE_SSE2 0 -#define COMPILE_TEMPLATE_AVX 0 -#define COMPILE_TEMPLATE_AMD3DNOW 1 -#define RENAME(a) a ## _3dnow -#include "rgb2rgb_template.c" - /* RGB15->RGB16 original by Strepto/Astral ported to gcc & bugfixed : A'rpi @@ -165,10 +143,6 @@ av_cold void rgb2rgb_init_x86(void) int cpu_flags = av_get_cpu_flags(); #if HAVE_INLINE_ASM - if (INLINE_MMX(cpu_flags)) - rgb2rgb_init_mmx(); - if (INLINE_AMD3DNOW(cpu_flags)) - rgb2rgb_init_3dnow(); if (INLINE_MMXEXT(cpu_flags)) rgb2rgb_init_mmxext(); if (INLINE_SSE2(cpu_flags)) diff --git a/libswscale/x86/rgb2rgb_template.c b/libswscale/x86/rgb2rgb_template.c index ae2469e66..4aba25dd5 100644 --- a/libswscale/x86/rgb2rgb_template.c +++ b/libswscale/x86/rgb2rgb_template.c @@ -36,35 +36,15 @@ #undef SFENCE #undef PAVGB -#if COMPILE_TEMPLATE_AMD3DNOW -#define PREFETCH "prefetch" -#define PAVGB "pavgusb" -#elif COMPILE_TEMPLATE_MMXEXT #define PREFETCH "prefetchnta" #define PAVGB "pavgb" -#else -#define PREFETCH " # nop" -#endif - -#if COMPILE_TEMPLATE_AMD3DNOW -/* On K6 femms is faster than emms. On K7 femms is directly mapped to emms. */ -#define EMMS "femms" -#else -#define EMMS "emms" -#endif - -#if COMPILE_TEMPLATE_MMXEXT #define MOVNTQ "movntq" #define SFENCE "sfence" -#else -#define MOVNTQ "movq" -#define SFENCE " # nop" -#endif + +#define EMMS "emms" #if !COMPILE_TEMPLATE_SSE2 -#if !COMPILE_TEMPLATE_AMD3DNOW - static inline void RENAME(rgb24tobgr32)(const uint8_t *src, uint8_t *dst, int src_size) { uint8_t *dest = dst; @@ -1353,9 +1333,7 @@ static inline void RENAME(yuy2toyv12)(const uint8_t *src, uint8_t *ydst, uint8_t SFENCE" \n\t" :::"memory"); } -#endif /* !COMPILE_TEMPLATE_AMD3DNOW */ -#if COMPILE_TEMPLATE_MMXEXT || COMPILE_TEMPLATE_AMD3DNOW static inline void RENAME(planar2x)(const uint8_t *src, uint8_t *dst, int srcWidth, int srcHeight, int srcStride, int dstStride) { int x,y; @@ -1453,9 +1431,7 @@ static inline void RENAME(planar2x)(const uint8_t *src, uint8_t *dst, int srcWid SFENCE" \n\t" :::"memory"); } -#endif /* COMPILE_TEMPLATE_MMXEXT || COMPILE_TEMPLATE_AMD3DNOW */ -#if !COMPILE_TEMPLATE_AMD3DNOW /** * Height should be a multiple of 2 and width should be a multiple of 16. * (If this is a problem for anyone then tell me, and I will fix it.) @@ -1559,7 +1535,6 @@ static inline void RENAME(uyvytoyv12)(const uint8_t *src, uint8_t *ydst, uint8_t SFENCE" \n\t" :::"memory"); } -#endif /* !COMPILE_TEMPLATE_AMD3DNOW */ /** * Height should be a multiple of 2 and width should be a multiple of 2. @@ -1673,7 +1648,6 @@ static inline void RENAME(rgb24toyv12)(const uint8_t *src, uint8_t *ydst, uint8_ "1: \n\t" PREFETCH" 64(%0, %%"FF_REG_d") \n\t" PREFETCH" 64(%1, %%"FF_REG_d") \n\t" -#if COMPILE_TEMPLATE_MMXEXT || COMPILE_TEMPLATE_AMD3DNOW "movq (%0, %%"FF_REG_d"), %%mm0 \n\t" "movq (%1, %%"FF_REG_d"), %%mm1 \n\t" "movq 6(%0, %%"FF_REG_d"), %%mm2 \n\t" @@ -1688,32 +1662,6 @@ static inline void RENAME(rgb24toyv12)(const uint8_t *src, uint8_t *ydst, uint8_ PAVGB" %%mm3, %%mm2 \n\t" "punpcklbw %%mm7, %%mm0 \n\t" "punpcklbw %%mm7, %%mm2 \n\t" -#else - "movd (%0, %%"FF_REG_d"), %%mm0 \n\t" - "movd (%1, %%"FF_REG_d"), %%mm1 \n\t" - "movd 3(%0, %%"FF_REG_d"), %%mm2 \n\t" - "movd 3(%1, %%"FF_REG_d"), %%mm3 \n\t" - "punpcklbw %%mm7, %%mm0 \n\t" - "punpcklbw %%mm7, %%mm1 \n\t" - "punpcklbw %%mm7, %%mm2 \n\t" - "punpcklbw %%mm7, %%mm3 \n\t" - "paddw %%mm1, %%mm0 \n\t" - "paddw %%mm3, %%mm2 \n\t" - "paddw %%mm2, %%mm0 \n\t" - "movd 6(%0, %%"FF_REG_d"), %%mm4 \n\t" - "movd 6(%1, %%"FF_REG_d"), %%mm1 \n\t" - "movd 9(%0, %%"FF_REG_d"), %%mm2 \n\t" - "movd 9(%1, %%"FF_REG_d"), %%mm3 \n\t" - "punpcklbw %%mm7, %%mm4 \n\t" - "punpcklbw %%mm7, %%mm1 \n\t" - "punpcklbw %%mm7, %%mm2 \n\t" - "punpcklbw %%mm7, %%mm3 \n\t" - "paddw %%mm1, %%mm4 \n\t" - "paddw %%mm3, %%mm2 \n\t" - "paddw %%mm4, %%mm2 \n\t" - "psrlw $2, %%mm0 \n\t" - "psrlw $2, %%mm2 \n\t" -#endif "movq "BGR2V_IDX"(%5), %%mm1 \n\t" "movq "BGR2V_IDX"(%5), %%mm3 \n\t" @@ -1732,7 +1680,6 @@ static inline void RENAME(rgb24toyv12)(const uint8_t *src, uint8_t *ydst, uint8_ "packssdw %%mm1, %%mm0 \n\t" // V1 V0 U1 U0 "psraw $7, %%mm0 \n\t" -#if COMPILE_TEMPLATE_MMXEXT || COMPILE_TEMPLATE_AMD3DNOW "movq 12(%0, %%"FF_REG_d"), %%mm4 \n\t" "movq 12(%1, %%"FF_REG_d"), %%mm1 \n\t" "movq 18(%0, %%"FF_REG_d"), %%mm2 \n\t" @@ -1747,33 +1694,6 @@ static inline void RENAME(rgb24toyv12)(const uint8_t *src, uint8_t *ydst, uint8_ PAVGB" %%mm3, %%mm2 \n\t" "punpcklbw %%mm7, %%mm4 \n\t" "punpcklbw %%mm7, %%mm2 \n\t" -#else - "movd 12(%0, %%"FF_REG_d"), %%mm4 \n\t" - "movd 12(%1, %%"FF_REG_d"), %%mm1 \n\t" - "movd 15(%0, %%"FF_REG_d"), %%mm2 \n\t" - "movd 15(%1, %%"FF_REG_d"), %%mm3 \n\t" - "punpcklbw %%mm7, %%mm4 \n\t" - "punpcklbw %%mm7, %%mm1 \n\t" - "punpcklbw %%mm7, %%mm2 \n\t" - "punpcklbw %%mm7, %%mm3 \n\t" - "paddw %%mm1, %%mm4 \n\t" - "paddw %%mm3, %%mm2 \n\t" - "paddw %%mm2, %%mm4 \n\t" - "movd 18(%0, %%"FF_REG_d"), %%mm5 \n\t" - "movd 18(%1, %%"FF_REG_d"), %%mm1 \n\t" - "movd 21(%0, %%"FF_REG_d"), %%mm2 \n\t" - "movd 21(%1, %%"FF_REG_d"), %%mm3 \n\t" - "punpcklbw %%mm7, %%mm5 \n\t" - "punpcklbw %%mm7, %%mm1 \n\t" - "punpcklbw %%mm7, %%mm2 \n\t" - "punpcklbw %%mm7, %%mm3 \n\t" - "paddw %%mm1, %%mm5 \n\t" - "paddw %%mm3, %%mm2 \n\t" - "paddw %%mm5, %%mm2 \n\t" - "movq "MANGLE(ff_w1111)", %%mm5 \n\t" - "psrlw $2, %%mm4 \n\t" - "psrlw $2, %%mm2 \n\t" -#endif "movq "BGR2V_IDX"(%5), %%mm1 \n\t" "movq "BGR2V_IDX"(%5), %%mm3 \n\t" @@ -1822,7 +1742,7 @@ static inline void RENAME(rgb24toyv12)(const uint8_t *src, uint8_t *ydst, uint8_ #endif /* HAVE_7REGS */ #endif /* !COMPILE_TEMPLATE_SSE2 */ -#if !COMPILE_TEMPLATE_AMD3DNOW && !COMPILE_TEMPLATE_AVX +#if !COMPILE_TEMPLATE_AVX && COMPILE_TEMPLATE_SSE2 static void RENAME(interleaveBytes)(const uint8_t *src1, const uint8_t *src2, uint8_t *dest, int width, int height, int src1Stride, int src2Stride, int dstStride) @@ -1833,7 +1753,6 @@ static void RENAME(interleaveBytes)(const uint8_t *src1, const uint8_t *src2, ui int w; if (width >= 16) { -#if COMPILE_TEMPLATE_SSE2 if (!((((intptr_t)src1) | ((intptr_t)src2) | ((intptr_t)dest))&15)) { __asm__( "xor %%"FF_REG_a", %%"FF_REG_a" \n\t" @@ -1854,7 +1773,6 @@ static void RENAME(interleaveBytes)(const uint8_t *src1, const uint8_t *src2, ui : "memory", XMM_CLOBBERS("xmm0", "xmm1", "xmm2",) "%"FF_REG_a ); } else -#endif __asm__( "xor %%"FF_REG_a", %%"FF_REG_a" \n\t" "1: \n\t" @@ -1896,10 +1814,10 @@ static void RENAME(interleaveBytes)(const uint8_t *src1, const uint8_t *src2, ui ::: "memory" ); } -#endif /* !COMPILE_TEMPLATE_AMD3DNOW && !COMPILE_TEMPLATE_AVX */ +#endif /* !COMPILE_TEMPLATE_AVX && COMPILE_TEMPLATE_SSE2 */ #if !COMPILE_TEMPLATE_AVX || HAVE_AVX_EXTERNAL -#if !COMPILE_TEMPLATE_AMD3DNOW && (ARCH_X86_32 || COMPILE_TEMPLATE_SSE2) && COMPILE_TEMPLATE_MMXEXT == COMPILE_TEMPLATE_SSE2 && HAVE_X86ASM +#if COMPILE_TEMPLATE_SSE2 && HAVE_X86ASM void RENAME(ff_nv12ToUV)(uint8_t *dstU, uint8_t *dstV, const uint8_t *unused, const uint8_t *src1, @@ -1919,18 +1837,14 @@ static void RENAME(deinterleaveBytes)(const uint8_t *src, uint8_t *dst1, uint8_t dst2 += dst2Stride; } __asm__( -#if !COMPILE_TEMPLATE_SSE2 - EMMS" \n\t" -#endif SFENCE" \n\t" ::: "memory" ); } -#endif /* !COMPILE_TEMPLATE_AMD3DNOW */ +#endif /* COMPILE_TEMPLATE_SSE2 && HAVE_X86ASM */ #endif /* !COMPILE_TEMPLATE_AVX || HAVE_AVX_EXTERNAL */ #if !COMPILE_TEMPLATE_SSE2 -#if !COMPILE_TEMPLATE_AMD3DNOW static inline void RENAME(vu9_to_vu12)(const uint8_t *src1, const uint8_t *src2, uint8_t *dst1, uint8_t *dst2, int width, int height, @@ -2108,7 +2022,6 @@ static inline void RENAME(yvu9_to_yuy2)(const uint8_t *src1, const uint8_t *src2 ::: "memory" ); } -#endif /* !COMPILE_TEMPLATE_AMD3DNOW */ static void RENAME(extract_even)(const uint8_t *src, uint8_t *dst, x86_reg count) { @@ -2185,7 +2098,7 @@ static void RENAME(extract_odd)(const uint8_t *src, uint8_t *dst, x86_reg count) } } -#if !COMPILE_TEMPLATE_AMD3DNOW +#if ARCH_X86_32 static void RENAME(extract_even2)(const uint8_t *src, uint8_t *dst0, uint8_t *dst1, x86_reg count) { dst0+= count; @@ -2231,7 +2144,7 @@ static void RENAME(extract_even2)(const uint8_t *src, uint8_t *dst0, uint8_t *ds count++; } } -#endif /* !COMPILE_TEMPLATE_AMD3DNOW */ +#endif /* ARCH_X86_32 */ static void RENAME(extract_even2avg)(const uint8_t *src0, const uint8_t *src1, uint8_t *dst0, uint8_t *dst1, x86_reg count) { @@ -2286,7 +2199,6 @@ static void RENAME(extract_even2avg)(const uint8_t *src0, const uint8_t *src1, u } } -#if !COMPILE_TEMPLATE_AMD3DNOW static void RENAME(extract_odd2)(const uint8_t *src, uint8_t *dst0, uint8_t *dst1, x86_reg count) { dst0+= count; @@ -2333,7 +2245,6 @@ static void RENAME(extract_odd2)(const uint8_t *src, uint8_t *dst0, uint8_t *dst count++; } } -#endif /* !COMPILE_TEMPLATE_AMD3DNOW */ static void RENAME(extract_odd2avg)(const uint8_t *src0, const uint8_t *src1, uint8_t *dst0, uint8_t *dst1, x86_reg count) { @@ -2415,7 +2326,6 @@ static void RENAME(yuyvtoyuv420)(uint8_t *ydst, uint8_t *udst, uint8_t *vdst, co ); } -#if !COMPILE_TEMPLATE_AMD3DNOW static void RENAME(yuyvtoyuv422)(uint8_t *ydst, uint8_t *udst, uint8_t *vdst, const uint8_t *src, int width, int height, int lumStride, int chromStride, int srcStride) @@ -2438,7 +2348,6 @@ static void RENAME(yuyvtoyuv422)(uint8_t *ydst, uint8_t *udst, uint8_t *vdst, co ::: "memory" ); } -#endif /* !COMPILE_TEMPLATE_AMD3DNOW */ static void RENAME(uyvytoyuv420)(uint8_t *ydst, uint8_t *udst, uint8_t *vdst, const uint8_t *src, int width, int height, @@ -2465,7 +2374,7 @@ static void RENAME(uyvytoyuv420)(uint8_t *ydst, uint8_t *udst, uint8_t *vdst, co ); } -#if !COMPILE_TEMPLATE_AMD3DNOW +#if ARCH_X86_32 static void RENAME(uyvytoyuv422)(uint8_t *ydst, uint8_t *udst, uint8_t *vdst, const uint8_t *src, int width, int height, int lumStride, int chromStride, int srcStride) @@ -2488,13 +2397,12 @@ static void RENAME(uyvytoyuv422)(uint8_t *ydst, uint8_t *udst, uint8_t *vdst, co ::: "memory" ); } -#endif /* !COMPILE_TEMPLATE_AMD3DNOW */ +#endif /* ARCH_X86_32 */ #endif /* !COMPILE_TEMPLATE_SSE2 */ static av_cold void RENAME(rgb2rgb_init)(void) { #if !COMPILE_TEMPLATE_SSE2 -#if !COMPILE_TEMPLATE_AMD3DNOW rgb15to16 = RENAME(rgb15to16); rgb15tobgr24 = RENAME(rgb15tobgr24); rgb15to32 = RENAME(rgb15to32); @@ -2519,13 +2427,12 @@ static av_cold void RENAME(rgb2rgb_init)(void) yuy2toyv12 = RENAME(yuy2toyv12); vu9_to_vu12 = RENAME(vu9_to_vu12); yvu9_to_yuy2 = RENAME(yvu9_to_yuy2); +#if ARCH_X86_32 uyvytoyuv422 = RENAME(uyvytoyuv422); +#endif yuyvtoyuv422 = RENAME(yuyvtoyuv422); -#endif /* !COMPILE_TEMPLATE_AMD3DNOW */ -#if COMPILE_TEMPLATE_MMXEXT || COMPILE_TEMPLATE_AMD3DNOW planar2x = RENAME(planar2x); -#endif /* COMPILE_TEMPLATE_MMXEXT || COMPILE_TEMPLATE_AMD3DNOW */ #if HAVE_7REGS ff_rgb24toyv12 = RENAME(rgb24toyv12); #endif /* HAVE_7REGS */ @@ -2534,11 +2441,11 @@ static av_cold void RENAME(rgb2rgb_init)(void) uyvytoyuv420 = RENAME(uyvytoyuv420); #endif /* !COMPILE_TEMPLATE_SSE2 */ -#if !COMPILE_TEMPLATE_AMD3DNOW && !COMPILE_TEMPLATE_AVX +#if !COMPILE_TEMPLATE_AVX && COMPILE_TEMPLATE_SSE2 interleaveBytes = RENAME(interleaveBytes); -#endif /* !COMPILE_TEMPLATE_AMD3DNOW && !COMPILE_TEMPLATE_AVX */ +#endif /* !COMPILE_TEMPLATE_AVX && COMPILE_TEMPLATE_SSE2 */ #if !COMPILE_TEMPLATE_AVX || HAVE_AVX_EXTERNAL -#if !COMPILE_TEMPLATE_AMD3DNOW && (ARCH_X86_32 || COMPILE_TEMPLATE_SSE2) && COMPILE_TEMPLATE_MMXEXT == COMPILE_TEMPLATE_SSE2 && HAVE_X86ASM +#if COMPILE_TEMPLATE_SSE2 && HAVE_X86ASM deinterleaveBytes = RENAME(deinterleaveBytes); #endif #endif diff --git a/libswscale/x86/scale.asm b/libswscale/x86/scale.asm index 83cabff72..c62ae3dcc 100644 --- a/libswscale/x86/scale.asm +++ b/libswscale/x86/scale.asm @@ -61,13 +61,11 @@ cglobal hscale%1to%2_%4, %5, 10, %6, pos0, dst, w, srcmem, filter, fltpos, fltsi %define mov32 mov %endif ; x86-64 %if %2 == 19 -%if mmsize == 8 ; mmx - mova m2, [max_19bit_int] -%elif cpuflag(sse4) +%if cpuflag(sse4) mova m2, [max_19bit_int] %else ; ssse3/sse2 mova m2, [max_19bit_flt] -%endif ; mmx/sse2/ssse3/sse4 +%endif ; sse2/ssse3/sse4 %endif ; %2 == 19 %if %1 == 16 mova m6, [minshort] @@ -144,12 +142,7 @@ cglobal hscale%1to%2_%4, %5, 10, %6, pos0, dst, w, srcmem, filter, fltpos, fltsi pmaddwd m1, [filterq+wq*8+mmsize*1] ; *= filter[{8,9,..,14,15}] ; add up horizontally (4 srcpix * 4 coefficients -> 1 dstpix) -%if mmsize == 8 ; mmx - movq m4, m0 - punpckldq m0, m1 - punpckhdq m4, m1 - paddd m0, m4 -%elif notcpuflag(ssse3) ; sse2 +%if notcpuflag(ssse3) ; sse2 mova m4, m0 shufps m0, m1, 10001000b shufps m4, m1, 11011101b @@ -159,7 +152,7 @@ cglobal hscale%1to%2_%4, %5, 10, %6, pos0, dst, w, srcmem, filter, fltpos, fltsi ; filter[{ 4, 5, 6, 7}]*src[filterPos[1]+{0,1,2,3}], ; filter[{ 8, 9,10,11}]*src[filterPos[2]+{0,1,2,3}], ; filter[{12,13,14,15}]*src[filterPos[3]+{0,1,2,3}] -%endif ; mmx/sse2/ssse3/sse4 +%endif ; sse2/ssse3/sse4 %else ; %3 == 8, i.e. filterSize == 8 scaling ; load 2x8 or 4x8 source pixels into m0, m1, m4 and m5 mov32 pos0q, dword [fltposq+wq*2+0] ; filterPos[0] @@ -197,14 +190,7 @@ cglobal hscale%1to%2_%4, %5, 10, %6, pos0, dst, w, srcmem, filter, fltpos, fltsi pmaddwd m5, [filterq+wq*8+mmsize*3] ; *= filter[{24,25,..,30,31}] ; add up horizontally (8 srcpix * 8 coefficients -> 1 dstpix) -%if mmsize == 8 - paddd m0, m1 - paddd m4, m5 - movq m1, m0 - punpckldq m0, m4 - punpckhdq m1, m4 - paddd m0, m1 -%elif notcpuflag(ssse3) ; sse2 +%if notcpuflag(ssse3) ; sse2 %if %1 == 8 %define mex m6 %else @@ -233,7 +219,7 @@ cglobal hscale%1to%2_%4, %5, 10, %6, pos0, dst, w, srcmem, filter, fltpos, fltsi ; filter[{ 8, 9,...,14,15}]*src[filterPos[1]+{0,1,...,6,7}], ; filter[{16,17,...,22,23}]*src[filterPos[2]+{0,1,...,6,7}], ; filter[{24,25,...,30,31}]*src[filterPos[3]+{0,1,...,6,7}] -%endif ; mmx/sse2/ssse3/sse4 +%endif ; sse2/ssse3/sse4 %endif ; %3 == 4/8 %else ; %3 == X, i.e. any filterSize scaling @@ -274,7 +260,7 @@ cglobal hscale%1to%2_%4, %5, 10, %6, pos0, dst, w, srcmem, filter, fltpos, fltsi mov srcq, srcmemmp .innerloop: - ; load 2x4 (mmx) or 2x8 (sse) source pixels into m0/m1 -> m4/m5 + ; load 2x8 (sse) source pixels into m0/m1 -> m4/m5 movbh m0, [srcq+ pos0q *srcmul] ; src[filterPos[0] + {0,1,2,3(,4,5,6,7)}] movbh m1, [srcq+(pos1q+dlt)*srcmul] ; src[filterPos[1] + {0,1,2,3(,4,5,6,7)}] %if %1 == 8 @@ -319,12 +305,6 @@ cglobal hscale%1to%2_%4, %5, 10, %6, pos0, dst, w, srcmem, filter, fltpos, fltsi lea filterq, [filterq+(fltsizeq+dlt)*2] -%if mmsize == 8 ; mmx - movq m0, m4 - punpckldq m4, m5 - punpckhdq m0, m5 - paddd m0, m4 -%else ; mmsize == 16 %if notcpuflag(ssse3) ; sse2 mova m1, m4 punpcklqdq m4, m5 @@ -344,7 +324,6 @@ cglobal hscale%1to%2_%4, %5, 10, %6, pos0, dst, w, srcmem, filter, fltpos, fltsi phaddd m4, m4 SWAP 0, 4 %endif ; sse2/ssse3/sse4 -%endif ; mmsize == 8/16 %endif ; %3 ==/!= X %if %1 == 16 ; add 0x8000 * sum(coeffs), i.e. back from signed -> unsigned @@ -372,7 +351,7 @@ cglobal hscale%1to%2_%4, %5, 10, %6, pos0, dst, w, srcmem, filter, fltpos, fltsi %endif ; %3 ==/!= X %endif ; %2 == 15/19 %ifnidn %3, X - add wq, (mmsize<use_mmx_vfilter && !(c->flags & SWS_ACCURATE_RND)) { -#if HAVE_MMX_EXTERNAL - if (EXTERNAL_MMX(cpu_flags)) - c->yuv2planeX = yuv2yuvX_mmx; -#endif #if HAVE_MMXEXT_EXTERNAL if (EXTERNAL_MMXEXT(cpu_flags)) c->yuv2planeX = yuv2yuvX_mmxext; @@ -385,6 +469,14 @@ av_cold void ff_sws_init_swscale_x86(SwsContext *c) c->yuv2planeX = yuv2yuvX_avx2; #endif } +#if ARCH_X86_32 && !HAVE_ALIGNED_STACK + // The better yuv2planeX_8 functions need aligned stack on x86-32, + // so we use MMXEXT in this case if they are not available. + if (EXTERNAL_MMXEXT(cpu_flags)) { + if (c->dstBpc == 8 && !c->use_mmx_vfilter) + c->yuv2planeX = ff_yuv2planeX_8_mmxext; + } +#endif /* ARCH_X86_32 && !HAVE_ALIGNED_STACK */ #define ASSIGN_SCALE_FUNC2(hscalefn, filtersize, opt1, opt2) do { \ if (c->srcBpc == 8) { \ @@ -408,12 +500,6 @@ av_cold void ff_sws_init_swscale_x86(SwsContext *c) ff_hscale16to19_ ## filtersize ## _ ## opt1; \ } \ } while (0) -#define ASSIGN_MMX_SCALE_FUNC(hscalefn, filtersize, opt1, opt2) \ - switch (filtersize) { \ - case 4: ASSIGN_SCALE_FUNC2(hscalefn, 4, opt1, opt2); break; \ - case 8: ASSIGN_SCALE_FUNC2(hscalefn, 8, opt1, opt2); break; \ - default: ASSIGN_SCALE_FUNC2(hscalefn, X, opt1, opt2); break; \ - } #define ASSIGN_VSCALEX_FUNC(vscalefn, opt, do_16_case, condition_8bit) \ switch(c->dstBpc){ \ case 16: do_16_case; break; \ @@ -421,12 +507,12 @@ switch(c->dstBpc){ \ case 9: if (!isBE(c->dstFormat)) vscalefn = ff_yuv2planeX_9_ ## opt; break; \ case 8: if ((condition_8bit) && !c->use_mmx_vfilter) vscalefn = ff_yuv2planeX_8_ ## opt; break; \ } -#define ASSIGN_VSCALE_FUNC(vscalefn, opt1, opt2, opt2chk) \ +#define ASSIGN_VSCALE_FUNC(vscalefn, opt) \ switch(c->dstBpc){ \ - case 16: if (!isBE(c->dstFormat)) vscalefn = ff_yuv2plane1_16_ ## opt1; break; \ - case 10: if (!isBE(c->dstFormat) && !isSemiPlanarYUV(c->dstFormat) && opt2chk) vscalefn = ff_yuv2plane1_10_ ## opt2; break; \ - case 9: if (!isBE(c->dstFormat) && opt2chk) vscalefn = ff_yuv2plane1_9_ ## opt2; break; \ - case 8: vscalefn = ff_yuv2plane1_8_ ## opt1; break; \ + case 16: if (!isBE(c->dstFormat)) vscalefn = ff_yuv2plane1_16_ ## opt; break; \ + case 10: if (!isBE(c->dstFormat) && !isSemiPlanarYUV(c->dstFormat)) vscalefn = ff_yuv2plane1_10_ ## opt; break; \ + case 9: if (!isBE(c->dstFormat)) vscalefn = ff_yuv2plane1_9_ ## opt; break; \ + case 8: vscalefn = ff_yuv2plane1_8_ ## opt; break; \ default: av_assert0(c->dstBpc>8); \ } #define case_rgb(x, X, opt) \ @@ -435,46 +521,6 @@ switch(c->dstBpc){ \ if (!c->chrSrcHSubSample) \ c->chrToYV12 = ff_ ## x ## ToUV_ ## opt; \ break -#if ARCH_X86_32 - if (EXTERNAL_MMX(cpu_flags)) { - ASSIGN_MMX_SCALE_FUNC(c->hyScale, c->hLumFilterSize, mmx, mmx); - ASSIGN_MMX_SCALE_FUNC(c->hcScale, c->hChrFilterSize, mmx, mmx); - ASSIGN_VSCALE_FUNC(c->yuv2plane1, mmx, mmxext, cpu_flags & AV_CPU_FLAG_MMXEXT); - - switch (c->srcFormat) { - case AV_PIX_FMT_YA8: - c->lumToYV12 = ff_yuyvToY_mmx; - if (c->needAlpha) - c->alpToYV12 = ff_uyvyToY_mmx; - break; - case AV_PIX_FMT_YUYV422: - c->lumToYV12 = ff_yuyvToY_mmx; - c->chrToYV12 = ff_yuyvToUV_mmx; - break; - case AV_PIX_FMT_UYVY422: - c->lumToYV12 = ff_uyvyToY_mmx; - c->chrToYV12 = ff_uyvyToUV_mmx; - break; - case AV_PIX_FMT_NV12: - c->chrToYV12 = ff_nv12ToUV_mmx; - break; - case AV_PIX_FMT_NV21: - c->chrToYV12 = ff_nv21ToUV_mmx; - break; - case_rgb(rgb24, RGB24, mmx); - case_rgb(bgr24, BGR24, mmx); - case_rgb(bgra, BGRA, mmx); - case_rgb(rgba, RGBA, mmx); - case_rgb(abgr, ABGR, mmx); - case_rgb(argb, ARGB, mmx); - default: - break; - } - } - if (EXTERNAL_MMXEXT(cpu_flags)) { - ASSIGN_VSCALEX_FUNC(c->yuv2planeX, mmxext, , 1); - } -#endif /* ARCH_X86_32 */ #define ASSIGN_SSE_SCALE_FUNC(hscalefn, filtersize, opt1, opt2) \ switch (filtersize) { \ case 4: ASSIGN_SCALE_FUNC2(hscalefn, 4, opt1, opt2); break; \ @@ -488,7 +534,7 @@ switch(c->dstBpc){ \ ASSIGN_SSE_SCALE_FUNC(c->hcScale, c->hChrFilterSize, sse2, sse2); ASSIGN_VSCALEX_FUNC(c->yuv2planeX, sse2, , HAVE_ALIGNED_STACK || ARCH_X86_64); - ASSIGN_VSCALE_FUNC(c->yuv2plane1, sse2, sse2, 1); + ASSIGN_VSCALE_FUNC(c->yuv2plane1, sse2); switch (c->srcFormat) { case AV_PIX_FMT_YA8: @@ -544,7 +590,7 @@ switch(c->dstBpc){ \ if (EXTERNAL_AVX(cpu_flags)) { ASSIGN_VSCALEX_FUNC(c->yuv2planeX, avx, , HAVE_ALIGNED_STACK || ARCH_X86_64); - ASSIGN_VSCALE_FUNC(c->yuv2plane1, avx, avx, 1); + ASSIGN_VSCALE_FUNC(c->yuv2plane1, avx); switch (c->srcFormat) { case AV_PIX_FMT_YUYV422: @@ -601,5 +647,162 @@ switch(c->dstBpc){ \ break; } } + + +#define INPUT_PLANER_RGB_A_FUNC_CASE(fmt, name, opt) \ + case fmt: \ + c->readAlpPlanar = ff_planar_##name##_to_a_##opt; + +#define INPUT_PLANER_RGBA_YUV_FUNC_CASE(rgb_fmt, rgba_fmt, name, opt) \ + case rgba_fmt: \ + case rgb_fmt: \ + c->readLumPlanar = ff_planar_##name##_to_y_##opt; \ + c->readChrPlanar = ff_planar_##name##_to_uv_##opt; \ + break; + +#define INPUT_PLANER_RGB_YUV_FUNC_CASE(fmt, name, opt) \ + case fmt: \ + c->readLumPlanar = ff_planar_##name##_to_y_##opt; \ + c->readChrPlanar = ff_planar_##name##_to_uv_##opt; \ + break; + +#define INPUT_PLANER_RGB_UV_FUNC_CASE(fmt, name, opt) \ + case fmt: \ + c->readChrPlanar = ff_planar_##name##_to_uv_##opt; \ + break; + +#define INPUT_PLANER_RGBAXX_YUVA_FUNC_CASE(rgb_fmt, rgba_fmt, name, opt) \ + INPUT_PLANER_RGB_A_FUNC_CASE(rgba_fmt##LE, name##le, opt) \ + INPUT_PLANER_RGB_YUV_FUNC_CASE(rgb_fmt##LE, name##le, opt) \ + INPUT_PLANER_RGB_A_FUNC_CASE(rgba_fmt##BE, name##be, opt) \ + INPUT_PLANER_RGB_YUV_FUNC_CASE(rgb_fmt##BE, name##be, opt) + +#define INPUT_PLANER_RGBAXX_UVA_FUNC_CASE(rgb_fmt, rgba_fmt, name, opt) \ + INPUT_PLANER_RGB_A_FUNC_CASE(rgba_fmt##LE, name##le, opt) \ + INPUT_PLANER_RGB_UV_FUNC_CASE(rgb_fmt##LE, name##le, opt) \ + INPUT_PLANER_RGB_A_FUNC_CASE(rgba_fmt##BE, name##be, opt) \ + INPUT_PLANER_RGB_UV_FUNC_CASE(rgb_fmt##BE, name##be, opt) + +#define INPUT_PLANER_RGBAXX_YUV_FUNC_CASE(rgb_fmt, rgba_fmt, name, opt) \ + INPUT_PLANER_RGBA_YUV_FUNC_CASE(rgb_fmt##LE, rgba_fmt##LE, name##le, opt) \ + INPUT_PLANER_RGBA_YUV_FUNC_CASE(rgb_fmt##BE, rgba_fmt##BE, name##be, opt) + +#define INPUT_PLANER_RGBXX_YUV_FUNC_CASE(rgb_fmt, name, opt) \ + INPUT_PLANER_RGB_YUV_FUNC_CASE(rgb_fmt##LE, name##le, opt) \ + INPUT_PLANER_RGB_YUV_FUNC_CASE(rgb_fmt##BE, name##be, opt) + +#define INPUT_PLANER_RGBXX_UV_FUNC_CASE(rgb_fmt, name, opt) \ + INPUT_PLANER_RGB_UV_FUNC_CASE(rgb_fmt##LE, name##le, opt) \ + INPUT_PLANER_RGB_UV_FUNC_CASE(rgb_fmt##BE, name##be, opt) + +#define INPUT_PLANER_RGB_YUVA_ALL_CASES(opt) \ + INPUT_PLANER_RGB_A_FUNC_CASE( AV_PIX_FMT_GBRAP, rgb, opt) \ + INPUT_PLANER_RGB_YUV_FUNC_CASE( AV_PIX_FMT_GBRP, rgb, opt) \ + INPUT_PLANER_RGBXX_YUV_FUNC_CASE( AV_PIX_FMT_GBRP9, rgb9, opt) \ + INPUT_PLANER_RGBAXX_YUVA_FUNC_CASE(AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRAP10, rgb10, opt) \ + INPUT_PLANER_RGBAXX_YUVA_FUNC_CASE(AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRAP12, rgb12, opt) \ + INPUT_PLANER_RGBXX_YUV_FUNC_CASE( AV_PIX_FMT_GBRP14, rgb14, opt) \ + INPUT_PLANER_RGBAXX_YUVA_FUNC_CASE(AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP16, rgb16, opt) \ + INPUT_PLANER_RGBAXX_YUVA_FUNC_CASE(AV_PIX_FMT_GBRPF32, AV_PIX_FMT_GBRAPF32, rgbf32, opt) + + + if (EXTERNAL_SSE2(cpu_flags)) { + switch (c->srcFormat) { + INPUT_PLANER_RGB_A_FUNC_CASE( AV_PIX_FMT_GBRAP, rgb, sse2); + INPUT_PLANER_RGB_UV_FUNC_CASE( AV_PIX_FMT_GBRP, rgb, sse2); + INPUT_PLANER_RGBXX_UV_FUNC_CASE( AV_PIX_FMT_GBRP9, rgb9, sse2); + INPUT_PLANER_RGBAXX_UVA_FUNC_CASE( AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRAP10, rgb10, sse2); + INPUT_PLANER_RGBAXX_UVA_FUNC_CASE( AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRAP12, rgb12, sse2); + INPUT_PLANER_RGBXX_UV_FUNC_CASE( AV_PIX_FMT_GBRP14, rgb14, sse2); + INPUT_PLANER_RGBAXX_UVA_FUNC_CASE( AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP16, rgb16, sse2); + INPUT_PLANER_RGBAXX_YUVA_FUNC_CASE(AV_PIX_FMT_GBRPF32, AV_PIX_FMT_GBRAPF32, rgbf32, sse2); + default: + break; + } + } + + if (EXTERNAL_SSE4(cpu_flags)) { + switch (c->srcFormat) { + case AV_PIX_FMT_GBRAP: + INPUT_PLANER_RGB_YUV_FUNC_CASE( AV_PIX_FMT_GBRP, rgb, sse4); + INPUT_PLANER_RGBXX_YUV_FUNC_CASE( AV_PIX_FMT_GBRP9, rgb9, sse4); + INPUT_PLANER_RGBAXX_YUV_FUNC_CASE( AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRAP10, rgb10, sse4); + INPUT_PLANER_RGBAXX_YUV_FUNC_CASE( AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRAP12, rgb12, sse4); + INPUT_PLANER_RGBXX_YUV_FUNC_CASE( AV_PIX_FMT_GBRP14, rgb14, sse4); + INPUT_PLANER_RGBAXX_YUV_FUNC_CASE( AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP16, rgb16, sse4); + INPUT_PLANER_RGBAXX_YUVA_FUNC_CASE(AV_PIX_FMT_GBRPF32, AV_PIX_FMT_GBRAPF32, rgbf32, sse4); + default: + break; + } + } + + if (EXTERNAL_AVX2_FAST(cpu_flags)) { + switch (c->srcFormat) { + INPUT_PLANER_RGB_YUVA_ALL_CASES(avx2) + default: + break; + } + } + + if(c->flags & SWS_FULL_CHR_H_INT) { + + /* yuv2gbrp uses the SwsContext for yuv coefficients + if struct offsets change the asm needs to be updated too */ + av_assert0(offsetof(SwsContext, yuv2rgb_y_offset) == 40292); + +#define YUV2ANYX_FUNC_CASE(fmt, name, opt) \ + case fmt: \ + c->yuv2anyX = ff_yuv2##name##_full_X_##opt; \ + break; + +#define YUV2ANYX_GBRAP_CASES(opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRP, gbrp, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRAP, gbrap, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRP9LE, gbrp9le, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRP10LE, gbrp10le, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRAP10LE, gbrap10le, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRP12LE, gbrp12le, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRAP12LE, gbrap12le, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRP14LE, gbrp14le, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRP16LE, gbrp16le, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRAP16LE, gbrap16le, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRPF32LE, gbrpf32le, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRAPF32LE, gbrapf32le, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRP9BE, gbrp9be, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRP10BE, gbrp10be, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRAP10BE, gbrap10be, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRP12BE, gbrp12be, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRAP12BE, gbrap12be, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRP14BE, gbrp14be, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRP16BE, gbrp16be, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRAP16BE, gbrap16be, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRPF32BE, gbrpf32be, opt) \ + YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRAPF32BE, gbrapf32be, opt) + + if (EXTERNAL_SSE2(cpu_flags)) { + switch (c->dstFormat) { + YUV2ANYX_GBRAP_CASES(sse2) + default: + break; + } + } + + if (EXTERNAL_SSE4(cpu_flags)) { + switch (c->dstFormat) { + YUV2ANYX_GBRAP_CASES(sse4) + default: + break; + } + } + + if (EXTERNAL_AVX2_FAST(cpu_flags)) { + switch (c->dstFormat) { + YUV2ANYX_GBRAP_CASES(avx2) + default: + break; + } + } + } + #endif } diff --git a/libswscale/x86/swscale_template.c b/libswscale/x86/swscale_template.c index 97d8cae61..6190fcb4f 100644 --- a/libswscale/x86/swscale_template.c +++ b/libswscale/x86/swscale_template.c @@ -29,13 +29,8 @@ #undef PREFETCH -#if COMPILE_TEMPLATE_MMXEXT #define REAL_MOVNTQ(a,b) "movntq " #a ", " #b " \n\t" #define MOVNTQ2 "movntq " -#else -#define REAL_MOVNTQ(a,b) "movq " #a ", " #b " \n\t" -#define MOVNTQ2 "movq " -#endif #define MOVNTQ(a,b) REAL_MOVNTQ(a,b) #define YSCALEYUV2PACKEDX_UV \ @@ -600,13 +595,8 @@ static void RENAME(yuv2rgb555_X)(SwsContext *c, const int16_t *lumFilter, "cmp "dstw", "#index" \n\t"\ " jb 1b \n\t" -#if COMPILE_TEMPLATE_MMXEXT #undef WRITEBGR24 #define WRITEBGR24(dst, dstw, index) WRITEBGR24MMXEXT(dst, dstw, index) -#else -#undef WRITEBGR24 -#define WRITEBGR24(dst, dstw, index) WRITEBGR24MMX(dst, dstw, index) -#endif #if HAVE_6REGS static void RENAME(yuv2bgr24_X_ar)(SwsContext *c, const int16_t *lumFilter, @@ -1478,17 +1468,13 @@ static av_cold void RENAME(sws_init_swscale)(SwsContext *c) } if (c->srcBpc == 8 && c->dstBpc <= 14) { - // Use the new MMX scaler if the MMXEXT one can't be used (it is faster than the x86 ASM one). -#if COMPILE_TEMPLATE_MMXEXT - if (c->flags & SWS_FAST_BILINEAR && c->canMMXEXTBeUsed) { - c->hyscale_fast = ff_hyscale_fast_mmxext; - c->hcscale_fast = ff_hcscale_fast_mmxext; - } else { -#endif /* COMPILE_TEMPLATE_MMXEXT */ - c->hyscale_fast = NULL; - c->hcscale_fast = NULL; -#if COMPILE_TEMPLATE_MMXEXT - } -#endif /* COMPILE_TEMPLATE_MMXEXT */ + // Use the new MMX scaler if the MMXEXT one can't be used (it is faster than the x86 ASM one). + if (c->flags & SWS_FAST_BILINEAR && c->canMMXEXTBeUsed) { + c->hyscale_fast = ff_hyscale_fast_mmxext; + c->hcscale_fast = ff_hcscale_fast_mmxext; + } else { + c->hyscale_fast = NULL; + c->hcscale_fast = NULL; + } } } diff --git a/libswscale/x86/yuv2rgb.c b/libswscale/x86/yuv2rgb.c index 47f45bd7c..675406224 100644 --- a/libswscale/x86/yuv2rgb.c +++ b/libswscale/x86/yuv2rgb.c @@ -44,23 +44,22 @@ //MMX versions #if HAVE_MMX #undef RENAME -#undef COMPILE_TEMPLATE_MMXEXT -#define COMPILE_TEMPLATE_MMXEXT 0 +#define COMPILE_TEMPLATE_MMX #define RENAME(a) a ## _mmx #include "yuv2rgb_template.c" +#undef COMPILE_TEMPLATE_MMX #endif /* HAVE_MMX */ // MMXEXT versions #undef RENAME -#undef COMPILE_TEMPLATE_MMXEXT -#define COMPILE_TEMPLATE_MMXEXT 1 +#define COMPILE_TEMPLATE_MMXEXT #define RENAME(a) a ## _mmxext #include "yuv2rgb_template.c" +#undef COMPILE_TEMPLATE_MMXEXT //SSSE3 versions #undef RENAME -#undef COMPILE_TEMPLATE_MMXEXT -#define COMPILE_TEMPLATE_MMXEXT 0 +#define COMPILE_TEMPLATE_SSSE3 #define RENAME(a) a ## _ssse3 #include "yuv2rgb_template.c" @@ -127,10 +126,6 @@ av_cold SwsFunc ff_yuv2rgb_init_x86(SwsContext *c) break; } else return yuv420_bgr32_mmx; - case AV_PIX_FMT_RGB24: - return yuv420_rgb24_mmx; - case AV_PIX_FMT_BGR24: - return yuv420_bgr24_mmx; case AV_PIX_FMT_RGB565: return yuv420_rgb16_mmx; case AV_PIX_FMT_RGB555: diff --git a/libswscale/x86/yuv2rgb_template.c b/libswscale/x86/yuv2rgb_template.c index d506f75e1..596943bb7 100644 --- a/libswscale/x86/yuv2rgb_template.c +++ b/libswscale/x86/yuv2rgb_template.c @@ -47,7 +47,7 @@ extern void RENAME(ff_yuv_420_bgr24)(x86_reg index, uint8_t *image, const uint8_ const uint8_t *pv_index, const uint64_t *pointer_c_dither, const uint8_t *py_2index); -#if !COMPILE_TEMPLATE_MMXEXT +#ifndef COMPILE_TEMPLATE_MMXEXT extern void RENAME(ff_yuv_420_rgb15)(x86_reg index, uint8_t *image, const uint8_t *pu_index, const uint8_t *pv_index, const uint64_t *pointer_c_dither, const uint8_t *py_2index); @@ -165,6 +165,7 @@ static inline int RENAME(yuva420_bgr32)(SwsContext *c, const uint8_t *src[], } #endif +#if !defined(COMPILE_TEMPLATE_MMX) static inline int RENAME(yuv420_rgb24)(SwsContext *c, const uint8_t *src[], int srcStride[], int srcSliceY, int srcSliceH, @@ -192,4 +193,4 @@ static inline int RENAME(yuv420_bgr24)(SwsContext *c, const uint8_t *src[], } return srcSliceH; } - +#endif diff --git a/libswscale/x86/yuv_2_rgb.asm b/libswscale/x86/yuv_2_rgb.asm index 2f0b4130d..c5fa3ee69 100644 --- a/libswscale/x86/yuv_2_rgb.asm +++ b/libswscale/x86/yuv_2_rgb.asm @@ -69,6 +69,9 @@ SECTION .text %ifidn %1, yuva %define parameters index, image, pu_index, pv_index, pointer_c_dither, py_2index, pa_2index %define GPR_num 7 + %else + %define parameters index, image, pu_index, pv_index, pointer_c_dither, py_2index + %define GPR_num 6 %endif %else %define parameters index, image, pu_index, pv_index, pointer_c_dither, py_2index @@ -139,10 +142,10 @@ cglobal %1_420_%2%3, GPR_num, GPR_num, reg_num, parameters VBROADCASTSD vr_coff, [pointer_c_ditherq + 4 * 8] %endif %endif +.loop0: movu m_y, [py_2indexq + 2 * indexq] movh m_u, [pu_indexq + indexq] movh m_v, [pv_indexq + indexq] -.loop0: pxor m4, m4 mova m7, m6 punpcklbw m0, m4 @@ -347,9 +350,6 @@ cglobal %1_420_%2%3, GPR_num, GPR_num, reg_num, parameters %endif ; PACK RGB15/16 %endif ; PACK RGB15/16/32 -movu m_y, [py_2indexq + 2 * indexq + 8 * time_num] -movh m_v, [pv_indexq + indexq + 4 * time_num] -movh m_u, [pu_indexq + indexq + 4 * time_num] add imageq, 8 * depth * time_num add indexq, 4 * time_num js .loop0 @@ -359,8 +359,6 @@ REP_RET %endmacro INIT_MMX mmx -yuv2rgb_fn yuv, rgb, 24 -yuv2rgb_fn yuv, bgr, 24 yuv2rgb_fn yuv, rgb, 32 yuv2rgb_fn yuv, bgr, 32 yuv2rgb_fn yuva, rgb, 32 diff --git a/libswscale/yuv2rgb.c b/libswscale/yuv2rgb.c index 76232cb36..6ee483d12 100644 --- a/libswscale/yuv2rgb.c +++ b/libswscale/yuv2rgb.c @@ -679,10 +679,11 @@ SwsFunc ff_yuv2rgb_get_func_ptr(SwsContext *c) { SwsFunc t = NULL; - if (ARCH_PPC) - t = ff_yuv2rgb_init_ppc(c); - if (ARCH_X86) - t = ff_yuv2rgb_init_x86(c); +#if ARCH_PPC + t = ff_yuv2rgb_init_ppc(c); +#elif ARCH_X86 + t = ff_yuv2rgb_init_x86(c); +#endif if (t) return t; diff --git a/tests/Makefile b/tests/Makefile index 87807ed31..d9c509a41 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,4 +1,16 @@ +ifneq ($(strip $(KEEP)),) +ifneq ($(strip $(KEEP)),0) +# KEEP_FILES is normally undefined; it is set to 2 # if the user requested +# to keep all intermediate FATE-files by setting KEEP. +# For some tests it is also set to 1 if it is unset; this indicates +# that only some intermediate files (namely only non-raw files) +# are to be kept. This allows reusing these intermediate files as input +# files for other tests (mostly the seek-tests). +KEEP_FILES = 2 +endif +endif + THREADS = 1 VREF = tests/vsynth1/00.pgm AREF = tests/data/asynth1.sw @@ -68,22 +80,50 @@ XYES = $(if $(strip $(1)), \ yes) ENCDEC = $(call ALLYES, $(firstword $(1))_ENCODER $(lastword $(1))_DECODER \ - $(firstword $(2))_MUXER $(lastword $(2))_DEMUXER) + $(firstword $(2))_MUXER $(lastword $(2))_DEMUXER \ + $(3) FILE_PROTOCOL) ENCDEC2 = $(call ALLYES, $(firstword $(1))_ENCODER $(lastword $(1))_DECODER \ $(firstword $(2))_ENCODER $(lastword $(2))_DECODER \ - $(firstword $(3))_MUXER $(lastword $(3))_DEMUXER) + $(firstword $(3))_MUXER $(lastword $(3))_DEMUXER \ + $(4) FILE_PROTOCOL) -DEMDEC = $(call ALLYES, $(1)_DEMUXER $(2:%=%_DECODER)) -ENCMUX = $(call ALLYES, $(1:%=%_ENCODER) $(2)_MUXER) +# RAWVIDEO_ENCODER and PCM_S16LE_ENCODER corresponds to the default codecs +# for framecrc. These requirements are not always necessary. +TRANSCODE = $(call ALLYES, $(firstword $(1))_ENCODER $(lastword $(1))_DECODER \ + $(firstword $(2))_MUXER $(lastword $(2))_DEMUXER \ + $(3) FILE_PROTOCOL PIPE_PROTOCOL RAWVIDEO_ENCODER \ + PCM_S16LE_ENCODER FRAMECRC_MUXER) -DEMMUX = $(call ALLYES, $(1)_DEMUXER $(2)_MUXER) +REMUX = $(call ALLYES, $(firstword $(1))_MUXER $(lastword $(1))_DEMUXER \ + $(2) FILE_PROTOCOL PIPE_PROTOCOL FRAMECRC_MUXER) -FILTERDEMDEC = $(call ALLYES, $(1:%=%_FILTER) $(2)_DEMUXER $(3)_DECODER) -FILTERDEMDECMUX = $(call ALLYES, $(1:%=%_FILTER) $(2)_DEMUXER $(3)_DECODER $(4)_MUXER) -FILTERDEMDECENCMUX = $(call ALLYES, $(1:%=%_FILTER) $(2)_DEMUXER $(3)_DECODER $(4)_ENCODER $(5)_MUXER) +DEMDEC = $(call ALLYES, $(1)_DEMUXER $(2:%=%_DECODER) $(3) FILE_PROTOCOL) +ENCMUX = $(call ALLYES, $(1:%=%_ENCODER) $(2)_MUXER $(3)) -PARSERDEMDEC = $(call ALLYES, $(1)_PARSER $(2)_DEMUXER $(3)_DECODER) +FRAMEMD5 = $(call ALLYES, $(1)_DEMUXER $(2:%=%_DECODER) $(3) \ + PCM_S16LE_ENCODER RAWVIDEO_ENCODER FRAMEMD5_MUXER \ + PIPE_PROTOCOL FILE_PROTOCOL) +FRAMECRC = $(call ALLYES, $(1)_DEMUXER $(2:%=%_DECODER) $(3) \ + PCM_S16LE_ENCODER RAWVIDEO_ENCODER FRAMECRC_MUXER \ + PIPE_PROTOCOL FILE_PROTOCOL) + +# Variant of DEMDEC for use with the "pcm" command. +PCM = $(call ALLYES, $(1)_DEMUXER $(2)_DECODER $(3) FILE_PROTOCOL \ + PCM_S16LE_ENCODER PCM_S16LE_MUXER PIPE_PROTOCOL) + +DEMMUX = $(call ALLYES, $(1)_DEMUXER $(2)_MUXER $(3) FILE_PROTOCOL) + +# Variant of FRAMECRC for the cases with -lavfi where no demuxer is involved. +FILTERFRAMECRC = $(call ALLYES, $(1:%=%_FILTER) $(2) PCM_S16LE_ENCODER \ + RAWVIDEO_ENCODER FRAMECRC_MUXER PIPE_PROTOCOL) +# Specialization of FRAMECRC to be used when filtering is involved. +FILTERDEMDEC = $(call ALLYES, $(1:%=%_FILTER) $(2:%=%_DEMUXER) $(3:%=%_DECODER) \ + $(4) PCM_S16LE_ENCODER RAWVIDEO_ENCODER \ + FRAMECRC_MUXER FILE_PROTOCOL PIPE_PROTOCOL) +FILTERDEMDECENCMUX = $(call ALLYES, $(1:%=%_FILTER) $(2)_DEMUXER $(3)_DECODER $(4)_ENCODER $(5)_MUXER $(6) FILE_PROTOCOL) + +PARSERDEMDEC = $(call ALLYES, $(1)_PARSER $(2)_DEMUXER $(3)_DECODER $(4) FILE_PROTOCOL) # Allow overriding CONFIG_LARGE_TESTS via LARGE_TESTS, if set on the # make command line. @@ -105,6 +145,7 @@ include $(SRC_PATH)/tests/fate/lavf-container.mak include $(SRC_PATH)/tests/fate/lavf-image.mak include $(SRC_PATH)/tests/fate/lavf-image2pipe.mak include $(SRC_PATH)/tests/fate/lavf-video.mak +# Must be included after acodec.mak, vcodec.mak and lavf-*.mak include $(SRC_PATH)/tests/fate/seek.mak include $(SRC_PATH)/tests/fate/aac.mak @@ -125,6 +166,7 @@ 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 +# Must be included after lavf-container.mak include $(SRC_PATH)/tests/fate/concatdec.mak include $(SRC_PATH)/tests/fate/cover-art.mak include $(SRC_PATH)/tests/fate/dca.mak @@ -133,13 +175,16 @@ include $(SRC_PATH)/tests/fate/dfa.mak include $(SRC_PATH)/tests/fate/dnn.mak include $(SRC_PATH)/tests/fate/dnxhd.mak include $(SRC_PATH)/tests/fate/dpcm.mak +include $(SRC_PATH)/tests/fate/dvvideo.mak include $(SRC_PATH)/tests/fate/ea.mak include $(SRC_PATH)/tests/fate/exif.mak +# Must be included after lavf-video.mak include $(SRC_PATH)/tests/fate/ffmpeg.mak include $(SRC_PATH)/tests/fate/ffprobe.mak include $(SRC_PATH)/tests/fate/fft.mak include $(SRC_PATH)/tests/fate/fifo-muxer.mak include $(SRC_PATH)/tests/fate/filter-audio.mak +# Must be included after vcodec.mak include $(SRC_PATH)/tests/fate/filter-video.mak include $(SRC_PATH)/tests/fate/fits.mak include $(SRC_PATH)/tests/fate/flac.mak @@ -153,6 +198,7 @@ include $(SRC_PATH)/tests/fate/hlsenc.mak include $(SRC_PATH)/tests/fate/hw.mak include $(SRC_PATH)/tests/fate/id3v2.mak include $(SRC_PATH)/tests/fate/image.mak +include $(SRC_PATH)/tests/fate/imf.mak include $(SRC_PATH)/tests/fate/indeo.mak include $(SRC_PATH)/tests/fate/libavcodec.mak include $(SRC_PATH)/tests/fate/libavdevice.mak @@ -189,12 +235,14 @@ include $(SRC_PATH)/tests/fate/speedhq.mak include $(SRC_PATH)/tests/fate/subtitles.mak include $(SRC_PATH)/tests/fate/truehd.mak include $(SRC_PATH)/tests/fate/utvideo.mak +include $(SRC_PATH)/tests/fate/vbn.mak include $(SRC_PATH)/tests/fate/video.mak include $(SRC_PATH)/tests/fate/voice.mak include $(SRC_PATH)/tests/fate/vorbis.mak include $(SRC_PATH)/tests/fate/vpx.mak include $(SRC_PATH)/tests/fate/vqf.mak include $(SRC_PATH)/tests/fate/wavpack.mak +include $(SRC_PATH)/tests/fate/webm-dash-manifest.mak include $(SRC_PATH)/tests/fate/wma.mak include $(SRC_PATH)/tests/fate/xvid.mak @@ -221,7 +269,7 @@ $(FATE_FFMPEG) $(FATE_FFMPEG_FFPROBE) $(FATE_SAMPLES_AVCONV) $(FATE_SAMPLES_FFMP $(FATE_FFPROBE) $(FATE_FFMPEG_FFPROBE) $(FATE_SAMPLES_FFPROBE) $(FATE_SAMPLES_FFMPEG_FFPROBE): ffprobe$(PROGSSUF)$(EXESUF) $(FATE_SAMPLES_FASTSTART): tools/qt-faststart$(EXESUF) -$(FATE_SAMPLES_DUMP_DATA): tools/venc_data_dump$(EXESUF) +$(FATE_SAMPLES_DUMP_DATA) $(FATE_SAMPLES_DUMP_DATA-yes): tools/venc_data_dump$(EXESUF) $(FATE_SAMPLES_SCALE_SLICE): tools/scale_slice_test$(EXESUF) ifdef SAMPLES @@ -249,12 +297,12 @@ fate:: $(FATE) fate-hw: $(FATE_HW-yes) FATE += $(FATE_HW-yes) -$(FATE) $(FATE_TESTS-no): export PROGSUF = $(PROGSSUF) -$(FATE) $(FATE_TESTS-no): export EXECSUF = $(EXESUF) -$(FATE) $(FATE_TESTS-no): export HOSTEXECSUF = $(HOSTEXESUF) -$(FATE) $(FATE_TESTS-no): $(FATE_UTILS:%=tests/%$(HOSTEXESUF)) | $(FATE_OUTDIRS) +$(FATE): export PROGSUF = $(PROGSSUF) +$(FATE): export EXECSUF = $(EXESUF) +$(FATE): export HOSTEXECSUF = $(HOSTEXESUF) +$(FATE): $(FATE_UTILS:%=tests/%$(HOSTEXESUF)) | $(FATE_OUTDIRS) @echo "TEST $(@:fate-%=%)" - $(Q)$(SRC_PATH)/tests/fate-run.sh $@ "$(TARGET_SAMPLES)" "$(TARGET_EXEC)" "$(TARGET_PATH)" '$(CMD)' '$(CMP)' '$(REF)' '$(FUZZ)' '$(THREADS)' '$(THREAD_TYPE)' '$(CPUFLAGS)' '$(CMP_SHIFT)' '$(CMP_TARGET)' '$(SIZE_TOLERANCE)' '$(CMP_UNIT)' '$(GEN)' '$(HWACCEL)' '$(REPORT)' '$(KEEP)' + $(Q)$(SRC_PATH)/tests/fate-run.sh $@ "$(TARGET_SAMPLES)" "$(TARGET_EXEC)" "$(TARGET_PATH)" '$(CMD)' '$(CMP)' '$(REF)' '$(FUZZ)' '$(THREADS)' '$(THREAD_TYPE)' '$(CPUFLAGS)' '$(CMP_SHIFT)' '$(CMP_TARGET)' '$(SIZE_TOLERANCE)' '$(CMP_UNIT)' '$(GEN)' '$(HWACCEL)' '$(REPORT)' '$(KEEP_FILES)' fate-list: @printf '%s\n' $(sort $(FATE)) diff --git a/tests/api/api-flac-test.c b/tests/api/api-flac-test.c index b4f52b191..d1e45acda 100644 --- a/tests/api/api-flac-test.c +++ b/tests/api/api-flac-test.c @@ -50,13 +50,13 @@ static int generate_raw_frame(uint16_t *frame_data, int i, int sample_rate, } static int init_encoder(const AVCodec *enc, AVCodecContext **enc_ctx, - int64_t ch_layout, int sample_rate) + const AVChannelLayout *ch_layout, int sample_rate) { AVCodecContext *ctx; int result; char name_buff[NAME_BUFF_SIZE]; - av_get_channel_layout_string(name_buff, NAME_BUFF_SIZE, 0, ch_layout); + av_channel_layout_describe(ch_layout, name_buff, NAME_BUFF_SIZE); av_log(NULL, AV_LOG_INFO, "channel layout: %s, sample rate: %i\n", name_buff, sample_rate); ctx = avcodec_alloc_context3(enc); @@ -67,7 +67,7 @@ static int init_encoder(const AVCodec *enc, AVCodecContext **enc_ctx, ctx->sample_fmt = AV_SAMPLE_FMT_S16; ctx->sample_rate = sample_rate; - ctx->channel_layout = ch_layout; + av_channel_layout_copy(&ctx->ch_layout, ch_layout); result = avcodec_open2(ctx, enc, NULL); if (result < 0) { @@ -80,7 +80,7 @@ static int init_encoder(const AVCodec *enc, AVCodecContext **enc_ctx, } static int init_decoder(const AVCodec *dec, AVCodecContext **dec_ctx, - int64_t ch_layout) + const AVChannelLayout *ch_layout) { AVCodecContext *ctx; int result; @@ -92,9 +92,7 @@ static int init_decoder(const AVCodec *dec, AVCodecContext **dec_ctx, } ctx->request_sample_fmt = AV_SAMPLE_FMT_S16; - /* XXX: FLAC ignores it for some reason */ - ctx->request_channel_layout = ch_layout; - ctx->channel_layout = ch_layout; + av_channel_layout_copy(&ctx->ch_layout, ch_layout); result = avcodec_open2(ctx, dec, NULL); if (result < 0) { @@ -131,7 +129,9 @@ static int run_test(const AVCodec *enc, const AVCodec *dec, in_frame->nb_samples = enc_ctx->frame_size; in_frame->format = enc_ctx->sample_fmt; - in_frame->channel_layout = enc_ctx->channel_layout; + result = av_channel_layout_copy(&in_frame->ch_layout, &enc_ctx->ch_layout); + if (result < 0) + return result; if (av_frame_get_buffer(in_frame, 0) != 0) { av_log(NULL, AV_LOG_ERROR, "Can't allocate a buffer for input frame\n"); return AVERROR(ENOMEM); @@ -161,8 +161,8 @@ static int run_test(const AVCodec *enc, const AVCodec *dec, return result; generate_raw_frame((uint16_t*)(in_frame->data[0]), i, enc_ctx->sample_rate, - enc_ctx->channels, enc_ctx->frame_size); - in_frame_bytes = in_frame->nb_samples * in_frame->channels * sizeof(uint16_t); + enc_ctx->ch_layout.nb_channels, enc_ctx->frame_size); + in_frame_bytes = in_frame->nb_samples * in_frame->ch_layout.nb_channels * sizeof(uint16_t); if (in_frame_bytes > in_frame->linesize[0]) { av_log(NULL, AV_LOG_ERROR, "Incorrect value of input frame linesize\n"); return 1; @@ -209,7 +209,7 @@ static int run_test(const AVCodec *enc, const AVCodec *dec, return AVERROR_UNKNOWN; } - if (in_frame->channel_layout != out_frame->channel_layout) { + if (av_channel_layout_compare(&in_frame->ch_layout, &out_frame->ch_layout)) { av_log(NULL, AV_LOG_ERROR, "Error frames before and after decoding has different channel layout\n"); return AVERROR_UNKNOWN; } @@ -218,7 +218,7 @@ static int run_test(const AVCodec *enc, const AVCodec *dec, av_log(NULL, AV_LOG_ERROR, "Error frames before and after decoding has different sample format\n"); return AVERROR_UNKNOWN; } - out_frame_bytes = out_frame->nb_samples * out_frame->channels * sizeof(uint16_t); + out_frame_bytes = out_frame->nb_samples * out_frame->ch_layout.nb_channels * sizeof(uint16_t); if (out_frame_bytes > out_frame->linesize[0]) { av_log(NULL, AV_LOG_ERROR, "Incorrect value of output frame linesize\n"); return 1; @@ -247,7 +247,10 @@ int main(void) { const AVCodec *enc = NULL, *dec = NULL; AVCodecContext *enc_ctx = NULL, *dec_ctx = NULL; - uint64_t channel_layouts[] = {AV_CH_LAYOUT_STEREO, AV_CH_LAYOUT_5POINT1_BACK, AV_CH_LAYOUT_SURROUND, AV_CH_LAYOUT_STEREO_DOWNMIX}; + const AVChannelLayout channel_layouts[] = { AV_CHANNEL_LAYOUT_STEREO, + AV_CHANNEL_LAYOUT_5POINT1_BACK, + AV_CHANNEL_LAYOUT_SURROUND, + AV_CHANNEL_LAYOUT_STEREO_DOWNMIX }; int sample_rates[] = {8000, 44100, 48000, 192000}; int cl, sr; @@ -265,9 +268,9 @@ int main(void) for (cl = 0; cl < FF_ARRAY_ELEMS(channel_layouts); cl++) { for (sr = 0; sr < FF_ARRAY_ELEMS(sample_rates); sr++) { - if (init_encoder(enc, &enc_ctx, channel_layouts[cl], sample_rates[sr]) != 0) + if (init_encoder(enc, &enc_ctx, &channel_layouts[cl], sample_rates[sr]) != 0) return 1; - if (init_decoder(dec, &dec_ctx, channel_layouts[cl]) != 0) + if (init_decoder(dec, &dec_ctx, &channel_layouts[cl]) != 0) return 1; if (run_test(enc, dec, enc_ctx, dec_ctx) != 0) return 1; diff --git a/tests/checkasm/Makefile b/tests/checkasm/Makefile index 4ef5fa87d..e869c70b5 100644 --- a/tests/checkasm/Makefile +++ b/tests/checkasm/Makefile @@ -9,8 +9,11 @@ AVCODECOBJS-$(CONFIG_G722DSP) += g722dsp.o AVCODECOBJS-$(CONFIG_H264DSP) += h264dsp.o AVCODECOBJS-$(CONFIG_H264PRED) += h264pred.o AVCODECOBJS-$(CONFIG_H264QPEL) += h264qpel.o +AVCODECOBJS-$(CONFIG_IDCTDSP) += idctdsp.o AVCODECOBJS-$(CONFIG_LLVIDDSP) += llviddsp.o AVCODECOBJS-$(CONFIG_LLVIDENCDSP) += llviddspenc.o +AVCODECOBJS-$(CONFIG_ME_CMP) += motion.o +AVCODECOBJS-$(CONFIG_VC1DSP) += vc1dsp.o AVCODECOBJS-$(CONFIG_VP8DSP) += vp8dsp.o AVCODECOBJS-$(CONFIG_VIDEODSP) += videodsp.o @@ -45,7 +48,7 @@ AVFILTEROBJS-$(CONFIG_NLMEANS_FILTER) += vf_nlmeans.o CHECKASMOBJS-$(CONFIG_AVFILTER) += $(AVFILTEROBJS-yes) # swscale tests -SWSCALEOBJS += sw_rgb.o sw_scale.o +SWSCALEOBJS += sw_gbrp.o sw_rgb.o sw_scale.o CHECKASMOBJS-$(CONFIG_SWSCALE) += $(SWSCALEOBJS) diff --git a/tests/checkasm/af_afir.c b/tests/checkasm/af_afir.c index b8a845db8..08c55dacf 100644 --- a/tests/checkasm/af_afir.c +++ b/tests/checkasm/af_afir.c @@ -21,7 +21,7 @@ #include #include -#include "libavfilter/af_afir.h" +#include "libavfilter/af_afirdsp.h" #include "libavutil/internal.h" #include "libavutil/mem_internal.h" #include "checkasm.h" diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c index 90d080de0..5ffcafbda 100644 --- a/tests/checkasm/checkasm.c +++ b/tests/checkasm/checkasm.c @@ -21,6 +21,7 @@ */ #include "config.h" +#include "config_components.h" #if CONFIG_LINUX_PERF # ifndef _GNU_SOURCE @@ -122,6 +123,9 @@ static const struct { #if CONFIG_HUFFYUV_DECODER { "huffyuvdsp", checkasm_check_huffyuvdsp }, #endif + #if CONFIG_IDCTDSP + { "idctdsp", checkasm_check_idctdsp }, + #endif #if CONFIG_JPEG2000_DECODER { "jpeg2000dsp", checkasm_check_jpeg2000dsp }, #endif @@ -131,6 +135,9 @@ static const struct { #if CONFIG_LLVIDENCDSP { "llviddspenc", checkasm_check_llviddspenc }, #endif + #if CONFIG_ME_CMP + { "motion", checkasm_check_motion }, + #endif #if CONFIG_OPUS_DECODER { "opusdsp", checkasm_check_opusdsp }, #endif @@ -146,6 +153,9 @@ static const struct { #if CONFIG_V210_ENCODER { "v210enc", checkasm_check_v210enc }, #endif + #if CONFIG_VC1DSP + { "vc1dsp", checkasm_check_vc1dsp }, + #endif #if CONFIG_VP8DSP { "vp8dsp", checkasm_check_vp8dsp }, #endif @@ -183,6 +193,7 @@ static const struct { #endif #endif #if CONFIG_SWSCALE + { "sw_gbrp", checkasm_check_sw_gbrp }, { "sw_rgb", checkasm_check_sw_rgb }, { "sw_scale", checkasm_check_sw_scale }, #endif @@ -219,23 +230,24 @@ static const struct { { "MMI", "mmi", AV_CPU_FLAG_MMI }, { "MSA", "msa", AV_CPU_FLAG_MSA }, #elif ARCH_X86 - { "MMX", "mmx", AV_CPU_FLAG_MMX|AV_CPU_FLAG_CMOV }, - { "MMXEXT", "mmxext", AV_CPU_FLAG_MMXEXT }, - { "3DNOW", "3dnow", AV_CPU_FLAG_3DNOW }, - { "3DNOWEXT", "3dnowext", AV_CPU_FLAG_3DNOWEXT }, - { "SSE", "sse", AV_CPU_FLAG_SSE }, - { "SSE2", "sse2", AV_CPU_FLAG_SSE2|AV_CPU_FLAG_SSE2SLOW }, - { "SSE3", "sse3", AV_CPU_FLAG_SSE3|AV_CPU_FLAG_SSE3SLOW }, - { "SSSE3", "ssse3", AV_CPU_FLAG_SSSE3|AV_CPU_FLAG_ATOM }, - { "SSE4.1", "sse4", AV_CPU_FLAG_SSE4 }, - { "SSE4.2", "sse42", AV_CPU_FLAG_SSE42 }, - { "AES-NI", "aesni", AV_CPU_FLAG_AESNI }, - { "AVX", "avx", AV_CPU_FLAG_AVX }, - { "XOP", "xop", AV_CPU_FLAG_XOP }, - { "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 }, + { "MMX", "mmx", AV_CPU_FLAG_MMX|AV_CPU_FLAG_CMOV }, + { "MMXEXT", "mmxext", AV_CPU_FLAG_MMXEXT }, + { "3DNOW", "3dnow", AV_CPU_FLAG_3DNOW }, + { "3DNOWEXT", "3dnowext", AV_CPU_FLAG_3DNOWEXT }, + { "SSE", "sse", AV_CPU_FLAG_SSE }, + { "SSE2", "sse2", AV_CPU_FLAG_SSE2|AV_CPU_FLAG_SSE2SLOW }, + { "SSE3", "sse3", AV_CPU_FLAG_SSE3|AV_CPU_FLAG_SSE3SLOW }, + { "SSSE3", "ssse3", AV_CPU_FLAG_SSSE3|AV_CPU_FLAG_ATOM }, + { "SSE4.1", "sse4", AV_CPU_FLAG_SSE4 }, + { "SSE4.2", "sse42", AV_CPU_FLAG_SSE42 }, + { "AES-NI", "aesni", AV_CPU_FLAG_AESNI }, + { "AVX", "avx", AV_CPU_FLAG_AVX }, + { "XOP", "xop", AV_CPU_FLAG_XOP }, + { "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 }, + { "AVX-512ICL", "avx512icl", AV_CPU_FLAG_AVX512ICL }, #elif ARCH_LOONGARCH { "LSX", "lsx", AV_CPU_FLAG_LSX }, { "LASX", "lasx", AV_CPU_FLAG_LASX }, diff --git a/tests/checkasm/checkasm.h b/tests/checkasm/checkasm.h index 68b0697d3..b601a9875 100644 --- a/tests/checkasm/checkasm.h +++ b/tests/checkasm/checkasm.h @@ -64,19 +64,23 @@ void checkasm_check_hevc_idct(void); void checkasm_check_hevc_pel(void); void checkasm_check_hevc_sao(void); void checkasm_check_huffyuvdsp(void); +void checkasm_check_idctdsp(void); void checkasm_check_jpeg2000dsp(void); void checkasm_check_llviddsp(void); void checkasm_check_llviddspenc(void); +void checkasm_check_motion(void); void checkasm_check_nlmeans(void); void checkasm_check_opusdsp(void); void checkasm_check_pixblockdsp(void); void checkasm_check_sbrdsp(void); void checkasm_check_synth_filter(void); +void checkasm_check_sw_gbrp(void); void checkasm_check_sw_rgb(void); void checkasm_check_sw_scale(void); void checkasm_check_utvideodsp(void); void checkasm_check_v210dec(void); void checkasm_check_v210enc(void); +void checkasm_check_vc1dsp(void); void checkasm_check_vf_eq(void); void checkasm_check_vf_gblur(void); void checkasm_check_vf_hflip(void); diff --git a/tests/checkasm/h264dsp.c b/tests/checkasm/h264dsp.c index 739245295..3c95f9d74 100644 --- a/tests/checkasm/h264dsp.c +++ b/tests/checkasm/h264dsp.c @@ -23,6 +23,7 @@ #include "libavcodec/avcodec.h" #include "libavcodec/h264dsp.h" #include "libavcodec/h264data.h" +#include "libavcodec/h264_parse.h" #include "libavutil/common.h" #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" diff --git a/tests/checkasm/hevc_sao.c b/tests/checkasm/hevc_sao.c index 6b750758e..4a2301024 100644 --- a/tests/checkasm/hevc_sao.c +++ b/tests/checkasm/hevc_sao.c @@ -78,20 +78,26 @@ static void check_sao_band(HEVCDSPContext h, int bit_depth) for (i = 0; i <= 4; i++) { int block_size = sao_size[i]; + int prev_size = i > 0 ? sao_size[i - 1] : 0; 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_%d_%d", block_size, bit_depth)) { - 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(); + for (int w = prev_size + 4; w <= block_size; w += 4) { + randomize_buffers(src0, src1, BUF_SIZE); + randomize_buffers2(offset_val, OFFSET_LENGTH); + memset(dst0, 0, BUF_SIZE); + memset(dst1, 0, BUF_SIZE); + + call_ref(dst0, src0, stride, stride, offset_val, left_class, w, block_size); + call_new(dst1, src1, stride, stride, offset_val, left_class, w, block_size); + for (int j = 0; j < block_size; j++) { + if (memcmp(dst0 + j*stride, dst1 + j*stride, w*SIZEOF_PIXEL)) + fail(); + } + } bench_new(dst1, src1, stride, stride, offset_val, left_class, block_size, block_size); } } @@ -109,21 +115,26 @@ static void check_sao_edge(HEVCDSPContext h, int bit_depth) for (i = 0; i <= 4; i++) { int block_size = sao_size[i]; + int prev_size = i > 0 ? sao_size[i - 1] : 0; 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); + for (int w = prev_size + 4; w <= block_size; w += 4) { + 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(); + if (check_func(h.sao_edge_filter[i], "hevc_sao_edge_%d_%d", block_size, bit_depth)) { + call_ref(dst0, src0 + offset, stride, offset_val, eo, w, block_size); + call_new(dst1, src1 + offset, stride, offset_val, eo, w, block_size); + for (int j = 0; j < block_size; j++) { + if (memcmp(dst0 + j*stride, dst1 + j*stride, w*SIZEOF_PIXEL)) + fail(); + } + } bench_new(dst1, src1 + offset, stride, offset_val, eo, block_size, block_size); } } diff --git a/tests/checkasm/idctdsp.c b/tests/checkasm/idctdsp.c new file mode 100644 index 000000000..02724536a --- /dev/null +++ b/tests/checkasm/idctdsp.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2022 Ben Avison + * + * 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/idctdsp.h" + +#include "libavutil/common.h" +#include "libavutil/internal.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" + +#define IDCTDSP_TEST(func) { #func, offsetof(IDCTDSPContext, func) }, + +typedef struct { + const char *name; + size_t offset; +} test; + +#define RANDOMIZE_BUFFER16(name, size) \ + do { \ + int i; \ + for (i = 0; i < size; ++i) { \ + uint16_t r = rnd() % 0x201 - 0x100; \ + AV_WN16A(name##0 + i, r); \ + AV_WN16A(name##1 + i, r); \ + } \ + } while (0) + +#define RANDOMIZE_BUFFER8(name, size) \ + do { \ + int i; \ + for (i = 0; i < size; ++i) { \ + uint8_t r = rnd(); \ + name##0[i] = r; \ + name##1[i] = r; \ + } \ + } while (0) + +static void check_add_put_clamped(void) +{ + /* Source buffers are only as big as needed, since any over-read won't affect results */ + LOCAL_ALIGNED_16(int16_t, src0, [64]); + LOCAL_ALIGNED_16(int16_t, src1, [64]); + /* Destination buffers have borders of one row above/below and 8 columns left/right to catch overflows */ + LOCAL_ALIGNED_8(uint8_t, dst0, [10 * 24]); + LOCAL_ALIGNED_8(uint8_t, dst1, [10 * 24]); + + AVCodecContext avctx = { 0 }; + IDCTDSPContext h; + + const test tests[] = { + IDCTDSP_TEST(add_pixels_clamped) + IDCTDSP_TEST(put_pixels_clamped) + IDCTDSP_TEST(put_signed_pixels_clamped) + }; + + ff_idctdsp_init(&h, &avctx); + + for (size_t t = 0; t < FF_ARRAY_ELEMS(tests); ++t) { + void (*func)(const int16_t *, uint8_t * ptrdiff_t) = *(void **)((intptr_t) &h + tests[t].offset); + if (check_func(func, "idctdsp.%s", tests[t].name)) { + declare_func_emms(AV_CPU_FLAG_MMX, void, const int16_t *, uint8_t *, ptrdiff_t); + RANDOMIZE_BUFFER16(src, 64); + RANDOMIZE_BUFFER8(dst, 10 * 24); + call_ref(src0, dst0 + 24 + 8, 24); + call_new(src1, dst1 + 24 + 8, 24); + if (memcmp(dst0, dst1, 10 * 24)) + fail(); + bench_new(src1, dst1 + 24 + 8, 24); + } + } +} + +void checkasm_check_idctdsp(void) +{ + check_add_put_clamped(); + report("idctdsp"); +} diff --git a/tests/checkasm/motion.c b/tests/checkasm/motion.c new file mode 100644 index 000000000..011282217 --- /dev/null +++ b/tests/checkasm/motion.c @@ -0,0 +1,151 @@ +/* + * + * 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_internal.h" + +#include "libavcodec/me_cmp.h" + +#include "checkasm.h" + +static void fill_random(uint8_t *tab, int size) +{ + int i; + for (i = 0; i < size; i++) { + tab[i] = rnd() % 256; + } +} + +static void test_motion(const char *name, me_cmp_func test_func) +{ + /* test configurarion */ +#define ITERATIONS 16 +#define WIDTH 64 +#define HEIGHT 64 + + /* motion estimation can look up to 17 bytes ahead */ + static const int look_ahead = 17; + + int i, x, y, d1, d2; + uint8_t *ptr; + + LOCAL_ALIGNED_16(uint8_t, img1, [WIDTH * HEIGHT]); + LOCAL_ALIGNED_16(uint8_t, img2, [WIDTH * HEIGHT]); + + declare_func_emms(AV_CPU_FLAG_MMX, int, struct MpegEncContext *c, + uint8_t *blk1 /* align width (8 or 16) */, + uint8_t *blk2 /* align 1 */, ptrdiff_t stride, + int h); + + if (test_func == NULL) { + return; + } + + /* test correctness */ + fill_random(img1, WIDTH * HEIGHT); + fill_random(img2, WIDTH * HEIGHT); + + if (check_func(test_func, "%s", name)) { + for (i = 0; i < ITERATIONS; i++) { + x = rnd() % (WIDTH - look_ahead); + y = rnd() % (HEIGHT - look_ahead); + + ptr = img2 + y * WIDTH + x; + d2 = call_ref(NULL, img1, ptr, WIDTH, 8); + d1 = call_new(NULL, img1, ptr, WIDTH, 8); + + if (d1 != d2) { + fail(); + printf("func: %s, x=%d y=%d, error: asm=%d c=%d\n", name, x, y, d1, d2); + break; + } + } + // benchmark with the final value of ptr + bench_new(NULL, img1, ptr, WIDTH, 8); + } +} + +#define ME_CMP_1D_ARRAYS(XX) \ + XX(sad) \ + XX(sse) \ + XX(hadamard8_diff) \ + XX(vsad) \ + XX(vsse) \ + XX(nsse) \ + XX(me_pre_cmp) \ + XX(me_cmp) \ + XX(me_sub_cmp) \ + XX(mb_cmp) \ + XX(ildct_cmp) \ + XX(frame_skip_cmp) \ + XX(median_sad) + +// tests for functions not yet implemented +#if 0 + XX(dct_sad) \ + XX(quant_psnr) \ + XX(bit) \ + XX(rd) \ + XX(w53) \ + XX(w97) \ + XX(dct_max) \ + XX(dct264_sad) \ + +#endif + +static void check_motion(void) +{ + char buf[64]; + AVCodecContext *av_ctx; + MECmpContext me_ctx; + + memset(&me_ctx, 0, sizeof(me_ctx)); + + /* allocate AVCodecContext */ + av_ctx = avcodec_alloc_context3(NULL); + av_ctx->flags |= AV_CODEC_FLAG_BITEXACT; + + ff_me_cmp_init(&me_ctx, av_ctx); + + for (int i = 0; i < FF_ARRAY_ELEMS(me_ctx.pix_abs); i++) { + for (int j = 0; j < FF_ARRAY_ELEMS(me_ctx.pix_abs[0]); j++) { + snprintf(buf, sizeof(buf), "pix_abs_%d_%d", i, j); + test_motion(buf, me_ctx.pix_abs[i][j]); + } + } + +#define XX(me_cmp_array) \ + for (int i = 0; i < FF_ARRAY_ELEMS(me_ctx.me_cmp_array); i++) { \ + snprintf(buf, sizeof(buf), #me_cmp_array "_%d", i); \ + test_motion(buf, me_ctx.me_cmp_array[i]); \ + } + ME_CMP_1D_ARRAYS(XX) +#undef XX + + avcodec_free_context(&av_ctx); +} + +void checkasm_check_motion(void) +{ + check_motion(); + report("motion"); +} diff --git a/tests/checkasm/sw_gbrp.c b/tests/checkasm/sw_gbrp.c new file mode 100644 index 000000000..848e5366a --- /dev/null +++ b/tests/checkasm/sw_gbrp.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 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_internal.h" +#include "libavutil/pixdesc.h" + +#include "libswscale/swscale.h" +#include "libswscale/swscale_internal.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 int planar_fmts[] = { + AV_PIX_FMT_GBRP, + AV_PIX_FMT_GBRP9BE, + AV_PIX_FMT_GBRP9LE, + AV_PIX_FMT_GBRP10BE, + AV_PIX_FMT_GBRP10LE, + AV_PIX_FMT_GBRP12BE, + AV_PIX_FMT_GBRP12LE, + AV_PIX_FMT_GBRP14BE, + AV_PIX_FMT_GBRP14LE, + AV_PIX_FMT_GBRAP, + AV_PIX_FMT_GBRAP10BE, + AV_PIX_FMT_GBRAP10LE, + AV_PIX_FMT_GBRAP12BE, + AV_PIX_FMT_GBRAP12LE, + AV_PIX_FMT_GBRP16BE, + AV_PIX_FMT_GBRP16LE, + AV_PIX_FMT_GBRAP16BE, + AV_PIX_FMT_GBRAP16LE, + AV_PIX_FMT_GBRPF32BE, + AV_PIX_FMT_GBRPF32LE, + AV_PIX_FMT_GBRAPF32BE, + AV_PIX_FMT_GBRAPF32LE +}; + +static void check_output_yuv2gbrp(void) +{ + struct SwsContext *ctx; + const AVPixFmtDescriptor *desc; + int fmi, fsi, isi, i; + int dstW, byte_size, luma_filter_size, chr_filter_size; +#define LARGEST_FILTER 16 +#define FILTER_SIZES 4 + static const int filter_sizes[] = {1, 4, 8, 16}; +#define LARGEST_INPUT_SIZE 512 +#define INPUT_SIZES 6 + static const int input_sizes[] = {8, 24, 128, 144, 256, 512}; + uint8_t *dst0[4]; + uint8_t *dst1[4]; + + declare_func(void, void *c, const int16_t *lumFilter, + const int16_t **lumSrcx, int lumFilterSize, + const int16_t *chrFilter, const int16_t **chrUSrcx, + const int16_t **chrVSrcx, int chrFilterSize, + const int16_t **alpSrcx, uint8_t **dest, + int dstW, int y); + + const int16_t *luma[LARGEST_FILTER]; + const int16_t *chru[LARGEST_FILTER]; + const int16_t *chrv[LARGEST_FILTER]; + const int16_t *alpha[LARGEST_FILTER]; + + LOCAL_ALIGNED_8(int16_t, luma_filter, [LARGEST_FILTER]); + LOCAL_ALIGNED_8(int16_t, chr_filter, [LARGEST_FILTER]); + + LOCAL_ALIGNED_8(int32_t, src_y, [LARGEST_FILTER * LARGEST_INPUT_SIZE]); + LOCAL_ALIGNED_8(int32_t, src_u, [LARGEST_FILTER * LARGEST_INPUT_SIZE]); + LOCAL_ALIGNED_8(int32_t, src_v, [LARGEST_FILTER * LARGEST_INPUT_SIZE]); + LOCAL_ALIGNED_8(int32_t, src_a, [LARGEST_FILTER * LARGEST_INPUT_SIZE]); + + LOCAL_ALIGNED_8(uint8_t, dst0_r, [LARGEST_INPUT_SIZE * sizeof(int32_t)]); + LOCAL_ALIGNED_8(uint8_t, dst0_g, [LARGEST_INPUT_SIZE * sizeof(int32_t)]); + LOCAL_ALIGNED_8(uint8_t, dst0_b, [LARGEST_INPUT_SIZE * sizeof(int32_t)]); + LOCAL_ALIGNED_8(uint8_t, dst0_a, [LARGEST_INPUT_SIZE * sizeof(int32_t)]); + + LOCAL_ALIGNED_8(uint8_t, dst1_r, [LARGEST_INPUT_SIZE * sizeof(int32_t)]); + LOCAL_ALIGNED_8(uint8_t, dst1_g, [LARGEST_INPUT_SIZE * sizeof(int32_t)]); + LOCAL_ALIGNED_8(uint8_t, dst1_b, [LARGEST_INPUT_SIZE * sizeof(int32_t)]); + LOCAL_ALIGNED_8(uint8_t, dst1_a, [LARGEST_INPUT_SIZE * sizeof(int32_t)]); + + randomize_buffers((uint8_t*)src_y, LARGEST_FILTER * LARGEST_INPUT_SIZE * sizeof(int32_t)); + randomize_buffers((uint8_t*)src_u, LARGEST_FILTER * LARGEST_INPUT_SIZE * sizeof(int32_t)); + randomize_buffers((uint8_t*)src_v, LARGEST_FILTER * LARGEST_INPUT_SIZE * sizeof(int32_t)); + randomize_buffers((uint8_t*)src_a, LARGEST_FILTER * LARGEST_INPUT_SIZE * sizeof(int32_t)); + randomize_buffers((uint8_t*)luma_filter, LARGEST_FILTER * sizeof(int16_t)); + randomize_buffers((uint8_t*)chr_filter, LARGEST_FILTER * sizeof(int16_t)); + + dst0[0] = (uint8_t*)dst0_g; + dst0[1] = (uint8_t*)dst0_b; + dst0[2] = (uint8_t*)dst0_r; + dst0[3] = (uint8_t*)dst0_a; + + dst1[0] = (uint8_t*)dst1_g; + dst1[1] = (uint8_t*)dst1_b; + dst1[2] = (uint8_t*)dst1_r; + dst1[3] = (uint8_t*)dst1_a; + + for (i = 0; i < LARGEST_FILTER; i++) { + luma[i] = (int16_t *)(src_y + i*LARGEST_INPUT_SIZE); + chru[i] = (int16_t *)(src_u + i*LARGEST_INPUT_SIZE); + chrv[i] = (int16_t *)(src_v + i*LARGEST_INPUT_SIZE); + alpha[i] = (int16_t *)(src_a + i*LARGEST_INPUT_SIZE); + } + + ctx = sws_alloc_context(); + if (sws_init_context(ctx, NULL, NULL) < 0) + fail(); + + ctx->flags |= SWS_FULL_CHR_H_INT; + ctx->yuv2rgb_y_offset = rnd(); + ctx->yuv2rgb_y_coeff = rnd(); + ctx->yuv2rgb_v2r_coeff = rnd(); + ctx->yuv2rgb_v2g_coeff = rnd(); + ctx->yuv2rgb_u2g_coeff = rnd(); + ctx->yuv2rgb_u2b_coeff = rnd(); + + for (fmi = 0; fmi < FF_ARRAY_ELEMS(planar_fmts); fmi++) { + for (fsi = 0; fsi < FILTER_SIZES; fsi++) { + for (isi = 0; isi < INPUT_SIZES; isi++ ) { + desc = av_pix_fmt_desc_get(planar_fmts[fmi]); + ctx->dstFormat = planar_fmts[fmi]; + + dstW = input_sizes[isi]; + luma_filter_size = filter_sizes[fsi]; + chr_filter_size = filter_sizes[fsi]; + + if (desc->comp[0].depth > 16) { + byte_size = 4; + } else if (desc->comp[0].depth > 8) { + byte_size = 2; + } else { + byte_size = 1; + } + + ff_sws_init_scale(ctx); + if (check_func(ctx->yuv2anyX, "yuv2%s_full_X_%d_%d", desc->name, luma_filter_size, dstW)) { + for (i = 0; i < 4; i ++) { + memset(dst0[i], 0xFF, LARGEST_INPUT_SIZE * sizeof(int32_t)); + memset(dst1[i], 0xFF, LARGEST_INPUT_SIZE * sizeof(int32_t)); + } + + call_ref(ctx, luma_filter, luma, luma_filter_size, + chr_filter, chru, chrv, chr_filter_size, + alpha, dst0, dstW, 0); + call_new(ctx, luma_filter, luma, luma_filter_size, + chr_filter, chru, chrv, chr_filter_size, + alpha, dst1, dstW, 0); + + if (memcmp(dst0[0], dst1[0], dstW * byte_size) || + memcmp(dst0[1], dst1[1], dstW * byte_size) || + memcmp(dst0[2], dst1[2], dstW * byte_size) || + memcmp(dst0[3], dst1[3], dstW * byte_size) ) + fail(); + + bench_new(ctx, luma_filter, luma, luma_filter_size, + chr_filter, chru, chrv, chr_filter_size, + alpha, dst1, dstW, 0); + } + } + } + } + sws_freeContext(ctx); +} + +#undef LARGEST_INPUT_SIZE +#undef INPUT_SIZES + +static void check_input_planar_rgb_to_y(void) +{ + struct SwsContext *ctx; + const AVPixFmtDescriptor *desc; + int fmi, isi; + int dstW, byte_size; +#define LARGEST_INPUT_SIZE 512 +#define INPUT_SIZES 6 + static const int input_sizes[] = {8, 24, 128, 144, 256, 512}; + uint8_t *src[4]; + int32_t rgb2yuv[9] = {0}; + + declare_func(void, uint8_t *dst, uint8_t *src[4], int w, int32_t *rgb2yuv); + + LOCAL_ALIGNED_8(int32_t, src_r, [LARGEST_INPUT_SIZE]); + LOCAL_ALIGNED_8(int32_t, src_g, [LARGEST_INPUT_SIZE]); + LOCAL_ALIGNED_8(int32_t, src_b, [LARGEST_INPUT_SIZE]); + LOCAL_ALIGNED_8(int32_t, src_a, [LARGEST_INPUT_SIZE]); + + LOCAL_ALIGNED_8(uint8_t, dst0_y, [LARGEST_INPUT_SIZE * sizeof(int32_t)]); + LOCAL_ALIGNED_8(uint8_t, dst1_y, [LARGEST_INPUT_SIZE * sizeof(int32_t)]); + + randomize_buffers((uint8_t*)src_r, LARGEST_INPUT_SIZE * sizeof(int32_t)); + randomize_buffers((uint8_t*)src_g, LARGEST_INPUT_SIZE * sizeof(int32_t)); + randomize_buffers((uint8_t*)src_b, LARGEST_INPUT_SIZE * sizeof(int32_t)); + randomize_buffers((uint8_t*)src_a, LARGEST_INPUT_SIZE * sizeof(int32_t)); + randomize_buffers((uint8_t*)rgb2yuv, 9 * sizeof(int32_t)); + + src[0] = (uint8_t*)src_g; + src[1] = (uint8_t*)src_b; + src[2] = (uint8_t*)src_r; + src[3] = (uint8_t*)src_a; + + ctx = sws_alloc_context(); + if (sws_init_context(ctx, NULL, NULL) < 0) + fail(); + + for (fmi = 0; fmi < FF_ARRAY_ELEMS(planar_fmts); fmi++) { + for (isi = 0; isi < INPUT_SIZES; isi++ ) { + desc = av_pix_fmt_desc_get(planar_fmts[fmi]); + ctx->srcFormat = planar_fmts[fmi]; + ctx->dstFormat = AV_PIX_FMT_YUVA444P16; + byte_size = 2; + dstW = input_sizes[isi]; + + ff_sws_init_scale(ctx); + if(check_func(ctx->readLumPlanar, "planar_%s_to_y_%d", desc->name, dstW)) { + memset(dst0_y, 0xFF, LARGEST_INPUT_SIZE * sizeof(int32_t)); + memset(dst1_y, 0xFF, LARGEST_INPUT_SIZE * sizeof(int32_t)); + + call_ref(dst0_y, src, dstW, rgb2yuv); + call_new(dst1_y, src, dstW, rgb2yuv); + + if (memcmp(dst0_y, dst1_y, dstW * byte_size)) + fail(); + + bench_new(dst1_y, src, dstW, rgb2yuv); + + } + } + } + sws_freeContext(ctx); +} + +#undef LARGEST_INPUT_SIZE +#undef INPUT_SIZES + +static void check_input_planar_rgb_to_uv(void) +{ + struct SwsContext *ctx; + const AVPixFmtDescriptor *desc; + int fmi, isi; + int dstW, byte_size; +#define LARGEST_INPUT_SIZE 512 +#define INPUT_SIZES 6 + static const int input_sizes[] = {8, 24, 128, 144, 256, 512}; + uint8_t *src[4]; + int32_t rgb2yuv[9] = {0}; + + declare_func(void, uint8_t *dstU, uint8_t *dstV, + uint8_t *src[4], int w, int32_t *rgb2yuv); + + LOCAL_ALIGNED_8(int32_t, src_r, [LARGEST_INPUT_SIZE]); + LOCAL_ALIGNED_8(int32_t, src_g, [LARGEST_INPUT_SIZE]); + LOCAL_ALIGNED_8(int32_t, src_b, [LARGEST_INPUT_SIZE]); + LOCAL_ALIGNED_8(int32_t, src_a, [LARGEST_INPUT_SIZE]); + + LOCAL_ALIGNED_8(uint8_t, dst0_u, [LARGEST_INPUT_SIZE * sizeof(int32_t)]); + LOCAL_ALIGNED_8(uint8_t, dst0_v, [LARGEST_INPUT_SIZE * sizeof(int32_t)]); + + LOCAL_ALIGNED_8(uint8_t, dst1_u, [LARGEST_INPUT_SIZE * sizeof(int32_t)]); + LOCAL_ALIGNED_8(uint8_t, dst1_v, [LARGEST_INPUT_SIZE * sizeof(int32_t)]); + + randomize_buffers((uint8_t*)src_r, LARGEST_INPUT_SIZE * sizeof(int32_t)); + randomize_buffers((uint8_t*)src_g, LARGEST_INPUT_SIZE * sizeof(int32_t)); + randomize_buffers((uint8_t*)src_b, LARGEST_INPUT_SIZE * sizeof(int32_t)); + randomize_buffers((uint8_t*)src_a, LARGEST_INPUT_SIZE * sizeof(int32_t)); + randomize_buffers((uint8_t*)rgb2yuv, 9 * sizeof(int32_t)); + + src[0] = (uint8_t*)src_g; + src[1] = (uint8_t*)src_b; + src[2] = (uint8_t*)src_r; + src[3] = (uint8_t*)src_a; + + ctx = sws_alloc_context(); + if (sws_init_context(ctx, NULL, NULL) < 0) + fail(); + + for (fmi = 0; fmi < FF_ARRAY_ELEMS(planar_fmts); fmi++) { + for (isi = 0; isi < INPUT_SIZES; isi++ ) { + desc = av_pix_fmt_desc_get(planar_fmts[fmi]); + ctx->srcFormat = planar_fmts[fmi]; + ctx->dstFormat = AV_PIX_FMT_YUVA444P16; + byte_size = 2; + dstW = input_sizes[isi]; + + ff_sws_init_scale(ctx); + if(check_func(ctx->readChrPlanar, "planar_%s_to_uv_%d", desc->name, dstW)) { + memset(dst0_u, 0xFF, LARGEST_INPUT_SIZE * sizeof(int32_t)); + memset(dst0_v, 0xFF, LARGEST_INPUT_SIZE * sizeof(int32_t)); + memset(dst1_u, 0xFF, LARGEST_INPUT_SIZE * sizeof(int32_t)); + memset(dst1_v, 0xFF, LARGEST_INPUT_SIZE * sizeof(int32_t)); + + call_ref(dst0_u, dst0_v, src, dstW, rgb2yuv); + call_new(dst1_u, dst1_v, src, dstW, rgb2yuv); + + if (memcmp(dst0_u, dst1_u, dstW * byte_size) || + memcmp(dst0_v, dst1_v, dstW * byte_size)) + fail(); + + bench_new(dst1_u, dst1_v, src, dstW, rgb2yuv); + } + } + } + sws_freeContext(ctx); +} + +#undef LARGEST_INPUT_SIZE +#undef INPUT_SIZES + +static void check_input_planar_rgb_to_a(void) +{ + struct SwsContext *ctx; + const AVPixFmtDescriptor *desc; + int fmi, isi; + int dstW, byte_size; +#define LARGEST_INPUT_SIZE 512 +#define INPUT_SIZES 6 + static const int input_sizes[] = {8, 24, 128, 144, 256, 512}; + uint8_t *src[4]; + int32_t rgb2yuv[9] = {0}; + + declare_func(void, uint8_t *dst, uint8_t *src[4], int w, int32_t *rgb2yuv); + + LOCAL_ALIGNED_8(int32_t, src_r, [LARGEST_INPUT_SIZE]); + LOCAL_ALIGNED_8(int32_t, src_g, [LARGEST_INPUT_SIZE]); + LOCAL_ALIGNED_8(int32_t, src_b, [LARGEST_INPUT_SIZE]); + LOCAL_ALIGNED_8(int32_t, src_a, [LARGEST_INPUT_SIZE]); + + LOCAL_ALIGNED_8(uint8_t, dst0_a, [LARGEST_INPUT_SIZE * sizeof(int32_t)]); + LOCAL_ALIGNED_8(uint8_t, dst1_a, [LARGEST_INPUT_SIZE * sizeof(int32_t)]); + + randomize_buffers((uint8_t*)src_r, LARGEST_INPUT_SIZE * sizeof(int32_t)); + randomize_buffers((uint8_t*)src_g, LARGEST_INPUT_SIZE * sizeof(int32_t)); + randomize_buffers((uint8_t*)src_b, LARGEST_INPUT_SIZE * sizeof(int32_t)); + randomize_buffers((uint8_t*)src_a, LARGEST_INPUT_SIZE * sizeof(int32_t)); + randomize_buffers((uint8_t*)rgb2yuv, 9 * sizeof(int32_t)); + + src[0] = (uint8_t*)src_g; + src[1] = (uint8_t*)src_b; + src[2] = (uint8_t*)src_r; + src[3] = (uint8_t*)src_a; + + ctx = sws_alloc_context(); + if (sws_init_context(ctx, NULL, NULL) < 0) + fail(); + + for (fmi = 0; fmi < FF_ARRAY_ELEMS(planar_fmts); fmi++) { + for (isi = 0; isi < INPUT_SIZES; isi++ ) { + desc = av_pix_fmt_desc_get(planar_fmts[fmi]); + if (!(desc->flags & AV_PIX_FMT_FLAG_ALPHA)) + continue; + + ctx->srcFormat = planar_fmts[fmi]; + ctx->dstFormat = AV_PIX_FMT_YUVA444P16; + byte_size = 2; + dstW = input_sizes[isi]; + + ff_sws_init_scale(ctx); + if(check_func(ctx->readAlpPlanar, "planar_%s_to_a_%d", desc->name, dstW)) { + memset(dst0_a, 0x00, LARGEST_INPUT_SIZE * sizeof(int32_t)); + memset(dst1_a, 0x00, LARGEST_INPUT_SIZE * sizeof(int32_t)); + + call_ref(dst0_a, src, dstW, rgb2yuv); + call_new(dst1_a, src, dstW, rgb2yuv); + + if (memcmp(dst0_a, dst1_a, dstW * byte_size)) + fail(); + bench_new(dst1_a, src, dstW, rgb2yuv); + } + } + } + sws_freeContext(ctx); +} + +void checkasm_check_sw_gbrp(void) +{ + check_output_yuv2gbrp(); + report("output_yuv2gbrp"); + + check_input_planar_rgb_to_y(); + report("input_planar_rgb_y"); + + check_input_planar_rgb_to_uv(); + report("input_planar_rgb_uv"); + + check_input_planar_rgb_to_a(); + report("input_planar_rgb_a"); +} diff --git a/tests/checkasm/sw_scale.c b/tests/checkasm/sw_scale.c index 3c0a083b4..b643a47c3 100644 --- a/tests/checkasm/sw_scale.c +++ b/tests/checkasm/sw_scale.c @@ -75,11 +75,11 @@ static void check_yuv2yuvX(void) int dstW, const uint8_t *dither, int offset); const int16_t **src; - LOCAL_ALIGNED_8(int16_t, src_pixels, [LARGEST_FILTER * LARGEST_INPUT_SIZE]); - LOCAL_ALIGNED_8(int16_t, filter_coeff, [LARGEST_FILTER]); - LOCAL_ALIGNED_8(uint8_t, dst0, [LARGEST_INPUT_SIZE]); - LOCAL_ALIGNED_8(uint8_t, dst1, [LARGEST_INPUT_SIZE]); - LOCAL_ALIGNED_8(uint8_t, dither, [LARGEST_INPUT_SIZE]); + LOCAL_ALIGNED_16(int16_t, src_pixels, [LARGEST_FILTER * LARGEST_INPUT_SIZE]); + LOCAL_ALIGNED_16(int16_t, filter_coeff, [LARGEST_FILTER]); + LOCAL_ALIGNED_16(uint8_t, dst0, [LARGEST_INPUT_SIZE]); + LOCAL_ALIGNED_16(uint8_t, dst1, [LARGEST_INPUT_SIZE]); + LOCAL_ALIGNED_16(uint8_t, dither, [LARGEST_INPUT_SIZE]); union VFilterData{ const int16_t *src; uint16_t coeff[8]; @@ -148,7 +148,11 @@ static void check_hscale(void) { 8, 18 }, }; - int i, j, fsi, hpi, width; +#define LARGEST_INPUT_SIZE 512 +#define INPUT_SIZES 6 + static const int input_sizes[INPUT_SIZES] = {8, 24, 128, 144, 256, 512}; + + int i, j, fsi, hpi, width, dstWi; struct SwsContext *ctx; // padded @@ -178,57 +182,59 @@ static void check_hscale(void) for (hpi = 0; hpi < HSCALE_PAIRS; hpi++) { for (fsi = 0; fsi < FILTER_SIZES; fsi++) { - width = filter_sizes[fsi]; + for (dstWi = 0; dstWi < INPUT_SIZES; dstWi++) { + width = filter_sizes[fsi]; - ctx->srcBpc = hscale_pairs[hpi][0]; - ctx->dstBpc = hscale_pairs[hpi][1]; - ctx->hLumFilterSize = ctx->hChrFilterSize = width; - ctx->dstW = ctx->chrDstW = SRC_PIXELS; + ctx->srcBpc = hscale_pairs[hpi][0]; + ctx->dstBpc = hscale_pairs[hpi][1]; + ctx->hLumFilterSize = ctx->hChrFilterSize = width; - for (i = 0; i < SRC_PIXELS; i++) { - filterPos[i] = i; - filterPosAvx[i] = i; + for (i = 0; i < SRC_PIXELS; i++) { + filterPos[i] = i; + filterPosAvx[i] = i; - // These filter cofficients are chosen to try break two corner - // cases, namely: - // - // - Negative filter coefficients. The filters output signed - // values, and it should be possible to end up with negative - // output values. - // - // - Positive clipping. The hscale filter function has clipping - // at (1<<15) - 1 - // - // The coefficients sum to the 1.0 point for the hscale - // functions (1 << 14). + // These filter cofficients are chosen to try break two corner + // cases, namely: + // + // - Negative filter coefficients. The filters output signed + // values, and it should be possible to end up with negative + // output values. + // + // - Positive clipping. The hscale filter function has clipping + // at (1<<15) - 1 + // + // The coefficients sum to the 1.0 point for the hscale + // functions (1 << 14). - for (j = 0; j < width; j++) { - filter[i * width + j] = -((1 << 14) / (width - 1)); + for (j = 0; j < width; j++) { + filter[i * width + j] = -((1 << 14) / (width - 1)); + } + filter[i * width + (rnd() % width)] = ((1 << 15) - 1); } - filter[i * width + (rnd() % width)] = ((1 << 15) - 1); - } - for (i = 0; i < MAX_FILTER_WIDTH; i++) { - // These values should be unused in SIMD implementations but - // may still be read, random coefficients here should help show - // issues where they are used in error. + for (i = 0; i < MAX_FILTER_WIDTH; i++) { + // These values should be unused in SIMD implementations but + // may still be read, random coefficients here should help show + // issues where they are used in error. - filter[SRC_PIXELS * width + i] = rnd(); - } - ff_sws_init_scale(ctx); - memcpy(filterAvx2, filter, sizeof(uint16_t) * (SRC_PIXELS * MAX_FILTER_WIDTH + MAX_FILTER_WIDTH)); - if ((cpu_flags & AV_CPU_FLAG_AVX2) && !(cpu_flags & AV_CPU_FLAG_SLOW_GATHER)) - ff_shuffle_filter_coefficients(ctx, filterPosAvx, width, filterAvx2, SRC_PIXELS); + filter[SRC_PIXELS * width + i] = rnd(); + } + ctx->dstW = ctx->chrDstW = input_sizes[dstWi]; + ff_sws_init_scale(ctx); + memcpy(filterAvx2, filter, sizeof(uint16_t) * (SRC_PIXELS * MAX_FILTER_WIDTH + MAX_FILTER_WIDTH)); + if ((cpu_flags & AV_CPU_FLAG_AVX2) && !(cpu_flags & AV_CPU_FLAG_SLOW_GATHER)) + ff_shuffle_filter_coefficients(ctx, filterPosAvx, width, filterAvx2, SRC_PIXELS); - if (check_func(ctx->hcScale, "hscale_%d_to_%d_width%d", ctx->srcBpc, ctx->dstBpc + 1, width)) { - memset(dst0, 0, SRC_PIXELS * sizeof(dst0[0])); - memset(dst1, 0, SRC_PIXELS * sizeof(dst1[0])); + if (check_func(ctx->hcScale, "hscale_%d_to_%d__fs_%d_dstW_%d", ctx->srcBpc, ctx->dstBpc + 1, width, ctx->dstW)) { + memset(dst0, 0, SRC_PIXELS * sizeof(dst0[0])); + memset(dst1, 0, SRC_PIXELS * sizeof(dst1[0])); - call_ref(NULL, dst0, SRC_PIXELS, src, filter, filterPos, width); - call_new(NULL, dst1, SRC_PIXELS, src, filterAvx2, filterPosAvx, width); - if (memcmp(dst0, dst1, SRC_PIXELS * sizeof(dst0[0]))) - fail(); - bench_new(NULL, dst0, SRC_PIXELS, src, filter, filterPosAvx, width); + call_ref(NULL, dst0, ctx->dstW, src, filter, filterPos, width); + call_new(NULL, dst1, ctx->dstW, src, filterAvx2, filterPosAvx, width); + if (memcmp(dst0, dst1, ctx->dstW * sizeof(dst0[0]))) + fail(); + bench_new(NULL, dst0, ctx->dstW, src, filter, filterPosAvx, width); + } } } } diff --git a/tests/checkasm/v210dec.c b/tests/checkasm/v210dec.c index 7dd50a827..6aef519cc 100644 --- a/tests/checkasm/v210dec.c +++ b/tests/checkasm/v210dec.c @@ -20,7 +20,7 @@ #include #include "checkasm.h" -#include "libavcodec/v210dec.h" +#include "libavcodec/v210dec_init.h" static uint32_t get_v210(void) { diff --git a/tests/checkasm/v210enc.c b/tests/checkasm/v210enc.c index c3d5cc514..9942e0813 100644 --- a/tests/checkasm/v210enc.c +++ b/tests/checkasm/v210enc.c @@ -20,7 +20,7 @@ #include #include "checkasm.h" -#include "libavcodec/v210enc.h" +#include "libavcodec/v210enc_init.h" #include "libavutil/common.h" #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" diff --git a/tests/checkasm/vc1dsp.c b/tests/checkasm/vc1dsp.c new file mode 100644 index 000000000..52628d15e --- /dev/null +++ b/tests/checkasm/vc1dsp.c @@ -0,0 +1,452 @@ +/* + * Copyright (c) 2022 Ben Avison + * + * 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/vc1dsp.h" + +#include "libavutil/common.h" +#include "libavutil/internal.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/mem_internal.h" + +#define VC1DSP_TEST(func) { #func, offsetof(VC1DSPContext, func) }, +#define VC1DSP_SIZED_TEST(func, width, height) { #func, offsetof(VC1DSPContext, func), width, height }, + +typedef struct { + const char *name; + size_t offset; + int width; + int height; +} test; + +typedef struct matrix { + size_t width; + size_t height; + float d[]; +} matrix; + +static const matrix T8 = { 8, 8, { + 12, 12, 12, 12, 12, 12, 12, 12, + 16, 15, 9, 4, -4, -9, -15, -16, + 16, 6, -6, -16, -16, -6, 6, 16, + 15, -4, -16, -9, 9, 16, 4, -15, + 12, -12, -12, 12, 12, -12, -12, 12, + 9, -16, 4, 15, -15, -4, 16, -9, + 6, -16, 16, -6, -6, 16, -16, 6, + 4, -9, 15, -16, 16, -15, 9, -4 +} }; + +static const matrix T4 = { 4, 4, { + 17, 17, 17, 17, + 22, 10, -10, -22, + 17, -17, -17, 17, + 10, -22, 22, -10 +} }; + +static const matrix T8t = { 8, 8, { + 12, 16, 16, 15, 12, 9, 6, 4, + 12, 15, 6, -4, -12, -16, -16, -9, + 12, 9, -6, -16, -12, 4, 16, 15, + 12, 4, -16, -9, 12, 15, -6, -16, + 12, -4, -16, 9, 12, -15, -6, 16, + 12, -9, -6, 16, -12, -4, 16, -15, + 12, -15, 6, 4, -12, 16, -16, 9, + 12, -16, 16, -15, 12, -9, 6, -4 +} }; + +static const matrix T4t = { 4, 4, { + 17, 22, 17, 10, + 17, 10, -17, -22, + 17, -10, -17, 22, + 17, -22, 17, -10 +} }; + +static matrix *new_matrix(size_t width, size_t height) +{ + matrix *out = av_mallocz(sizeof (matrix) + height * width * sizeof (float)); + if (out == NULL) { + fprintf(stderr, "Memory allocation failure\n"); + exit(EXIT_FAILURE); + } + out->width = width; + out->height = height; + return out; +} + +static matrix *multiply(const matrix *a, const matrix *b) +{ + matrix *out; + if (a->width != b->height) { + fprintf(stderr, "Incompatible multiplication\n"); + exit(EXIT_FAILURE); + } + out = new_matrix(b->width, a->height); + for (int j = 0; j < out->height; ++j) + for (int i = 0; i < out->width; ++i) { + float sum = 0; + for (int k = 0; k < a->width; ++k) + sum += a->d[j * a->width + k] * b->d[k * b->width + i]; + out->d[j * out->width + i] = sum; + } + return out; +} + +static void normalise(matrix *a) +{ + for (int j = 0; j < a->height; ++j) + for (int i = 0; i < a->width; ++i) { + float *p = a->d + j * a->width + i; + *p *= 64; + if (a->height == 4) + *p /= (const unsigned[]) { 289, 292, 289, 292 } [j]; + else + *p /= (const unsigned[]) { 288, 289, 292, 289, 288, 289, 292, 289 } [j]; + if (a->width == 4) + *p /= (const unsigned[]) { 289, 292, 289, 292 } [i]; + else + *p /= (const unsigned[]) { 288, 289, 292, 289, 288, 289, 292, 289 } [i]; + } +} + +static void divide_and_round_nearest(matrix *a, float by) +{ + for (int j = 0; j < a->height; ++j) + for (int i = 0; i < a->width; ++i) { + float *p = a->d + j * a->width + i; + *p = rintf(*p / by); + } +} + +static void tweak(matrix *a) +{ + for (int j = 4; j < a->height; ++j) + for (int i = 0; i < a->width; ++i) { + float *p = a->d + j * a->width + i; + *p += 1; + } +} + +/* The VC-1 spec places restrictions on the values permitted at three + * different stages: + * - D: the input coefficients in frequency domain + * - E: the intermediate coefficients, inverse-transformed only horizontally + * - R: the fully inverse-transformed coefficients + * + * To fully cater for the ranges specified requires various intermediate + * values to be held to 17-bit precision; yet these conditions do not appear + * to be utilised in real-world streams. At least some assembly + * implementations have chosen to restrict these values to 16-bit precision, + * to accelerate the decoding of real-world streams at the cost of strict + * adherence to the spec. To avoid our test marking these as failures, + * reduce our random inputs. + */ +#define ATTENUATION 4 + +static matrix *generate_inverse_quantized_transform_coefficients(size_t width, size_t height) +{ + matrix *raw, *tmp, *D, *E, *R; + raw = new_matrix(width, height); + for (int i = 0; i < width * height; ++i) + raw->d[i] = (int) (rnd() % (1024/ATTENUATION)) - 512/ATTENUATION; + tmp = multiply(height == 8 ? &T8 : &T4, raw); + D = multiply(tmp, width == 8 ? &T8t : &T4t); + normalise(D); + divide_and_round_nearest(D, 1); + for (int i = 0; i < width * height; ++i) { + if (D->d[i] < -2048/ATTENUATION || D->d[i] > 2048/ATTENUATION-1) { + /* Rare, so simply try again */ + av_free(raw); + av_free(tmp); + av_free(D); + return generate_inverse_quantized_transform_coefficients(width, height); + } + } + E = multiply(D, width == 8 ? &T8 : &T4); + divide_and_round_nearest(E, 8); + for (int i = 0; i < width * height; ++i) + if (E->d[i] < -4096/ATTENUATION || E->d[i] > 4096/ATTENUATION-1) { + /* Rare, so simply try again */ + av_free(raw); + av_free(tmp); + av_free(D); + av_free(E); + return generate_inverse_quantized_transform_coefficients(width, height); + } + R = multiply(height == 8 ? &T8t : &T4t, E); + tweak(R); + divide_and_round_nearest(R, 128); + for (int i = 0; i < width * height; ++i) + if (R->d[i] < -512/ATTENUATION || R->d[i] > 512/ATTENUATION-1) { + /* Rare, so simply try again */ + av_free(raw); + av_free(tmp); + av_free(D); + av_free(E); + av_free(R); + return generate_inverse_quantized_transform_coefficients(width, height); + } + av_free(raw); + av_free(tmp); + av_free(E); + av_free(R); + return D; +} + +#define RANDOMIZE_BUFFER16(name, size) \ + do { \ + int i; \ + for (i = 0; i < size; ++i) { \ + uint16_t r = rnd(); \ + AV_WN16A(name##0 + i, r); \ + AV_WN16A(name##1 + i, r); \ + } \ + } while (0) + +#define RANDOMIZE_BUFFER8(name, size) \ + do { \ + int i; \ + for (i = 0; i < size; ++i) { \ + uint8_t r = rnd(); \ + name##0[i] = r; \ + name##1[i] = r; \ + } \ + } while (0) + +#define RANDOMIZE_BUFFER8_MID_WEIGHTED(name, size) \ + do { \ + uint8_t *p##0 = name##0, *p##1 = name##1; \ + int i = (size); \ + while (i-- > 0) { \ + int x = 0x80 | (rnd() & 0x7F); \ + x >>= rnd() % 9; \ + if (rnd() & 1) \ + x = -x; \ + *p##1++ = *p##0++ = 0x80 + x; \ + } \ + } while (0) + +static void check_inv_trans_inplace(void) +{ + /* Inverse transform input coefficients are stored in a 16-bit buffer + * with row stride of 8 coefficients irrespective of transform size. + * vc1_inv_trans_8x8 differs from the others in two ways: coefficients + * are stored in column-major order, and the outputs are written back + * to the input buffer, so we oversize it slightly to catch overruns. */ + LOCAL_ALIGNED_16(int16_t, inv_trans_in0, [10 * 8]); + LOCAL_ALIGNED_16(int16_t, inv_trans_in1, [10 * 8]); + + VC1DSPContext h; + + ff_vc1dsp_init(&h); + + if (check_func(h.vc1_inv_trans_8x8, "vc1dsp.vc1_inv_trans_8x8")) { + matrix *coeffs; + declare_func_emms(AV_CPU_FLAG_MMX, void, int16_t *); + RANDOMIZE_BUFFER16(inv_trans_in, 10 * 8); + coeffs = generate_inverse_quantized_transform_coefficients(8, 8); + for (int j = 0; j < 8; ++j) + for (int i = 0; i < 8; ++i) { + int idx = 8 + i * 8 + j; + inv_trans_in1[idx] = inv_trans_in0[idx] = coeffs->d[j * 8 + i]; + } + call_ref(inv_trans_in0 + 8); + call_new(inv_trans_in1 + 8); + if (memcmp(inv_trans_in0, inv_trans_in1, 10 * 8 * sizeof (int16_t))) + fail(); + bench_new(inv_trans_in1 + 8); + av_free(coeffs); + } +} + +static void check_inv_trans_adding(void) +{ + /* Inverse transform input coefficients are stored in a 16-bit buffer + * with row stride of 8 coefficients irrespective of transform size. */ + LOCAL_ALIGNED_16(int16_t, inv_trans_in0, [8 * 8]); + LOCAL_ALIGNED_16(int16_t, inv_trans_in1, [8 * 8]); + + /* For all but vc1_inv_trans_8x8, the inverse transform is narrowed and + * added with saturation to an array of unsigned 8-bit values. Oversize + * this by 8 samples left and right and one row above and below. */ + LOCAL_ALIGNED_8(uint8_t, inv_trans_out0, [10 * 24]); + LOCAL_ALIGNED_8(uint8_t, inv_trans_out1, [10 * 24]); + + VC1DSPContext h; + + const test tests[] = { + VC1DSP_SIZED_TEST(vc1_inv_trans_8x4, 8, 4) + VC1DSP_SIZED_TEST(vc1_inv_trans_4x8, 4, 8) + VC1DSP_SIZED_TEST(vc1_inv_trans_4x4, 4, 4) + VC1DSP_SIZED_TEST(vc1_inv_trans_8x8_dc, 8, 8) + VC1DSP_SIZED_TEST(vc1_inv_trans_8x4_dc, 8, 4) + VC1DSP_SIZED_TEST(vc1_inv_trans_4x8_dc, 4, 8) + VC1DSP_SIZED_TEST(vc1_inv_trans_4x4_dc, 4, 4) + }; + + ff_vc1dsp_init(&h); + + for (size_t t = 0; t < FF_ARRAY_ELEMS(tests); ++t) { + void (*func)(uint8_t *, ptrdiff_t, int16_t *) = *(void **)((intptr_t) &h + tests[t].offset); + if (check_func(func, "vc1dsp.%s", tests[t].name)) { + matrix *coeffs; + declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *, ptrdiff_t, int16_t *); + RANDOMIZE_BUFFER16(inv_trans_in, 8 * 8); + RANDOMIZE_BUFFER8(inv_trans_out, 10 * 24); + coeffs = generate_inverse_quantized_transform_coefficients(tests[t].width, tests[t].height); + for (int j = 0; j < tests[t].height; ++j) + for (int i = 0; i < tests[t].width; ++i) { + int idx = j * 8 + i; + inv_trans_in1[idx] = inv_trans_in0[idx] = coeffs->d[j * tests[t].width + i]; + } + call_ref(inv_trans_out0 + 24 + 8, 24, inv_trans_in0); + call_new(inv_trans_out1 + 24 + 8, 24, inv_trans_in1); + if (memcmp(inv_trans_out0, inv_trans_out1, 10 * 24)) + fail(); + bench_new(inv_trans_out1 + 24 + 8, 24, inv_trans_in1 + 8); + av_free(coeffs); + } + } +} + +static void check_loop_filter(void) +{ + /* Deblocking filter buffers are big enough to hold a 16x16 block, + * plus 16 columns left and 4 rows above to hold filter inputs + * (depending on whether v or h neighbouring block edge, oversized + * horizontally to maintain 16-byte alignment) plus 16 columns and + * 4 rows below to catch write overflows */ + LOCAL_ALIGNED_16(uint8_t, filter_buf0, [24 * 48]); + LOCAL_ALIGNED_16(uint8_t, filter_buf1, [24 * 48]); + + VC1DSPContext h; + + const test tests[] = { + VC1DSP_TEST(vc1_v_loop_filter4) + VC1DSP_TEST(vc1_h_loop_filter4) + VC1DSP_TEST(vc1_v_loop_filter8) + VC1DSP_TEST(vc1_h_loop_filter8) + VC1DSP_TEST(vc1_v_loop_filter16) + VC1DSP_TEST(vc1_h_loop_filter16) + }; + + ff_vc1dsp_init(&h); + + for (size_t t = 0; t < FF_ARRAY_ELEMS(tests); ++t) { + void (*func)(uint8_t *, ptrdiff_t, int) = *(void **)((intptr_t) &h + tests[t].offset); + declare_func_emms(AV_CPU_FLAG_MMX, void, uint8_t *, ptrdiff_t, int); + if (check_func(func, "vc1dsp.%s", tests[t].name)) { + for (int count = 1000; count > 0; --count) { + int pq = rnd() % 31 + 1; + RANDOMIZE_BUFFER8_MID_WEIGHTED(filter_buf, 24 * 48); + call_ref(filter_buf0 + 4 * 48 + 16, 48, pq); + call_new(filter_buf1 + 4 * 48 + 16, 48, pq); + if (memcmp(filter_buf0, filter_buf1, 24 * 48)) + fail(); + } + } + for (int j = 0; j < 24; ++j) + for (int i = 0; i < 48; ++i) + filter_buf1[j * 48 + i] = 0x60 + 0x40 * (i >= 16 && j >= 4); + if (check_func(func, "vc1dsp.%s_bestcase", tests[t].name)) + bench_new(filter_buf1 + 4 * 48 + 16, 48, 1); + if (check_func(func, "vc1dsp.%s_worstcase", tests[t].name)) + bench_new(filter_buf1 + 4 * 48 + 16, 48, 31); + } +} + +#define TEST_UNESCAPE \ + do { \ + for (int count = 100; count > 0; --count) { \ + escaped_offset = rnd() & 7; \ + unescaped_offset = rnd() & 7; \ + escaped_len = (1u << (rnd() % 8) + 3) - (rnd() & 7); \ + RANDOMIZE_BUFFER8(unescaped, UNESCAPE_BUF_SIZE); \ + len0 = call_ref(escaped0 + escaped_offset, escaped_len, unescaped0 + unescaped_offset); \ + len1 = call_new(escaped1 + escaped_offset, escaped_len, unescaped1 + unescaped_offset); \ + if (len0 != len1 || memcmp(unescaped0, unescaped1, UNESCAPE_BUF_SIZE)) \ + fail(); \ + } \ + } while (0) + +static void check_unescape(void) +{ + /* This appears to be a typical length of buffer in use */ +#define LOG2_UNESCAPE_BUF_SIZE 17 +#define UNESCAPE_BUF_SIZE (1u< #include "checkasm.h" -#include "libavfilter/blend.h" +#include "libavfilter/vf_blend_init.h" #include "libavutil/common.h" #include "libavutil/internal.h" #include "libavutil/intreadwrite.h" diff --git a/tests/checkasm/vf_gblur.c b/tests/checkasm/vf_gblur.c index a7a1c1a24..3686a6c9f 100644 --- a/tests/checkasm/vf_gblur.c +++ b/tests/checkasm/vf_gblur.c @@ -19,7 +19,7 @@ #include #include #include "checkasm.h" -#include "libavfilter/gblur.h" +#include "libavfilter/vf_gblur_init.h" #define WIDTH 256 #define HEIGHT 256 diff --git a/tests/checkasm/vf_hflip.c b/tests/checkasm/vf_hflip.c index a3b6e613d..96614d12c 100644 --- a/tests/checkasm/vf_hflip.c +++ b/tests/checkasm/vf_hflip.c @@ -19,6 +19,7 @@ #include #include "checkasm.h" #include "libavfilter/hflip.h" +#include "libavfilter/vf_hflip_init.h" #include "libavutil/intreadwrite.h" #include "libavutil/mem_internal.h" diff --git a/tests/checkasm/vf_nlmeans.c b/tests/checkasm/vf_nlmeans.c index 87474d680..0f1f9fd40 100644 --- a/tests/checkasm/vf_nlmeans.c +++ b/tests/checkasm/vf_nlmeans.c @@ -19,7 +19,7 @@ */ #include "checkasm.h" -#include "libavfilter/vf_nlmeans.h" +#include "libavfilter/vf_nlmeans_init.h" #include "libavutil/avassert.h" #define randomize_buffer(buf, size) do { \ diff --git a/tests/checkasm/vf_threshold.c b/tests/checkasm/vf_threshold.c index 2c5cc807e..e6a425edf 100644 --- a/tests/checkasm/vf_threshold.c +++ b/tests/checkasm/vf_threshold.c @@ -18,7 +18,7 @@ #include #include "checkasm.h" -#include "libavfilter/threshold.h" +#include "libavfilter/vf_threshold_init.h" #include "libavutil/intreadwrite.h" #include "libavutil/mem_internal.h" diff --git a/tests/fate-run.sh b/tests/fate-run.sh index fbfc0a925..525e8e549 100755 --- a/tests/fate-run.sh +++ b/tests/fate-run.sh @@ -86,15 +86,15 @@ runecho(){ } probefmt(){ - run ffprobe${PROGSUF}${EXECSUF} -show_entries format=format_name -print_format default=nw=1:nk=1 "$@" + run ffprobe${PROGSUF}${EXECSUF} -bitexact -show_entries format=format_name -print_format default=nw=1:nk=1 "$@" } probeaudiostream(){ - run ffprobe${PROGSUF}${EXECSUF} -show_entries stream=codec_name,codec_time_base,sample_fmt,channels,channel_layout:side_data "$@" + run ffprobe${PROGSUF}${EXECSUF} -bitexact -show_entries stream=codec_name,codec_time_base,sample_fmt,channels,channel_layout:side_data "$@" } probetags(){ - run ffprobe${PROGSUF}${EXECSUF} -show_entries format_tags "$@" + run ffprobe${PROGSUF}${EXECSUF} -bitexact -show_entries format_tags "$@" } runlocal(){ @@ -103,11 +103,11 @@ runlocal(){ } probeframes(){ - run ffprobe${PROGSUF}${EXECSUF} -show_frames "$@" + run ffprobe${PROGSUF}${EXECSUF} -bitexact -show_frames "$@" } probechapters(){ - run ffprobe${PROGSUF}${EXECSUF} -show_chapters "$@" + run ffprobe${PROGSUF}${EXECSUF} -bitexact -show_chapters "$@" } probegaplessinfo(){ @@ -195,34 +195,47 @@ enc_dec_pcm(){ } FLAGS="-flags +bitexact -sws_flags +accurate_rnd+bitexact -fflags +bitexact" -DEC_OPTS="-threads $threads -idct simple $FLAGS" +DEC_OPTS="-threads $threads -thread_type $thread_type -idct simple $FLAGS" ENC_OPTS="-threads 1 -idct simple -dct fastint" enc_dec(){ - src_fmt=$1 + enc_fmt_in=$1 srcfile=$2 - enc_fmt=$3 - enc_opt=$4 - dec_fmt=$5 - dec_opt=$6 - ffprobe_opts=$9 - encfile="${outdir}/${test}.${enc_fmt}" - decfile="${outdir}/${test}.out.${dec_fmt}" + enc_fmt_out=$3 + enc_opt_out=$4 + dec_fmt_out=$5 + dec_opt_out=$6 + dec_opt_in=$7 + ffprobe_opts=$8 + twopass=$9 + encfile="${outdir}/${test}.${enc_fmt_out}" + decfile="${outdir}/${test}.out.${dec_fmt_out}" cleanfiles="$cleanfiles $decfile" - test "$7" = -keep || cleanfiles="$cleanfiles $encfile" + test "$keep" -ge 1 || cleanfiles="$cleanfiles $encfile" tsrcfile=$(target_path $srcfile) tencfile=$(target_path $encfile) tdecfile=$(target_path $decfile) - ffmpeg -auto_conversion_filters -f $src_fmt $DEC_OPTS -i $tsrcfile $ENC_OPTS $enc_opt $FLAGS \ - -f $enc_fmt -y $tencfile || return + + if [ -n "$twopass" ]; then + logfile_prefix="${outdir}/${test}.pass1" + cleanfiles="$cleanfiles ${logfile_prefix}-0.log" + tlogfile_prefix=$(target_path $logfile_prefix) + ffmpeg -auto_conversion_filters -f $enc_fmt_in $DEC_OPTS -i $tsrcfile \ + $ENC_OPTS $enc_opt_out $FLAGS -pass 1 -passlogfile $tlogfile_prefix \ + -f $enc_fmt_out -y $tencfile || return + enc_opt_out="$enc_opt_out -pass 2 -passlogfile $tlogfile_prefix" + fi + + ffmpeg -auto_conversion_filters -f $enc_fmt_in $DEC_OPTS -i $tsrcfile $ENC_OPTS $enc_opt_out $FLAGS \ + -f $enc_fmt_out -y $tencfile || return do_md5sum $encfile echo $(wc -c $encfile) - ffmpeg -auto_conversion_filters $8 $DEC_OPTS -i $tencfile $ENC_OPTS $dec_opt $FLAGS \ - -f $dec_fmt -y $tdecfile || return + ffmpeg -auto_conversion_filters $dec_opt_in $DEC_OPTS -i $tencfile $ENC_OPTS $dec_opt_out $FLAGS \ + -f $dec_fmt_out -y $tdecfile || return do_md5sum $decfile tests/tiny_psnr${HOSTEXECSUF} $srcfile $decfile $cmp_unit $cmp_shift test -z $ffprobe_opts || \ - run ffprobe${PROGSUF}${EXECSUF} $ffprobe_opts $tencfile || return + run ffprobe${PROGSUF}${EXECSUF} -bitexact $ffprobe_opts $tencfile || return } transcode(){ @@ -230,22 +243,23 @@ transcode(){ srcfile=$2 enc_fmt=$3 enc_opt=$4 - final_decode=$5 - ffprobe_opts=$7 - additional_input=$8 + final_encode=$5 + ffprobe_opts=$6 + additional_input=$7 + final_decode=$8 test -z "$additional_input" || additional_input="$DEC_OPTS $additional_input" encfile="${outdir}/${test}.${enc_fmt}" - test "$6" = -keep || cleanfiles="$cleanfiles $encfile" + test $keep -ge 1 || cleanfiles="$cleanfiles $encfile" tsrcfile=$(target_path $srcfile) tencfile=$(target_path $encfile) ffmpeg -f $src_fmt $DEC_OPTS -i $tsrcfile $additional_input \ $ENC_OPTS $enc_opt $FLAGS -f $enc_fmt -y $tencfile || return do_md5sum $encfile echo $(wc -c $encfile) - ffmpeg $DEC_OPTS -i $tencfile $ENC_OPTS $FLAGS $final_decode \ + ffmpeg $DEC_OPTS $final_decode -i $tencfile $ENC_OPTS $FLAGS $final_encode \ -f framecrc - || return test -z $ffprobe_opts || \ - run ffprobe${PROGSUF}${EXECSUF} $ffprobe_opts $tencfile || return + run ffprobe${PROGSUF}${EXECSUF} -bitexact $ffprobe_opts $tencfile || return } stream_remux(){ @@ -254,9 +268,9 @@ stream_remux(){ enc_fmt=$3 stream_maps=$4 final_decode=$5 - ffprobe_opts=$7 + ffprobe_opts=$6 encfile="${outdir}/${test}.${enc_fmt}" - test "$6" = -keep || cleanfiles="$cleanfiles $encfile" + test $keep -ge 1 || cleanfiles="$cleanfiles $encfile" tsrcfile=$(target_path $srcfile) tencfile=$(target_path $encfile) ffmpeg -f $src_fmt -i $tsrcfile $stream_maps -codec copy $FLAGS \ @@ -264,7 +278,7 @@ stream_remux(){ ffmpeg $DEC_OPTS -i $tencfile $ENC_OPTS $FLAGS $final_decode \ -f framecrc - || return test -z $ffprobe_opts || \ - run ffprobe${PROGSUF}${EXECSUF} $ffprobe_opts $tencfile || return + run ffprobe${PROGSUF}${EXECSUF} -bitexact $ffprobe_opts $tencfile || return } # FIXME: There is a certain duplication between the avconv-related helper @@ -272,8 +286,6 @@ stream_remux(){ ffmpeg2="$target_exec ${target_path}/ffmpeg${PROGSUF}${EXECSUF}" raw_src="${target_path}/tests/vsynth1/%02d.pgm" pcm_src="${target_path}/tests/data/asynth1.sw" -crcfile="tests/data/$test.lavf.crc" -target_crcfile="${target_path}/$crcfile" [ "${V-0}" -gt 0 ] && echov=echov || echov=: @@ -303,22 +315,25 @@ do_avconv(){ do_avconv_crc(){ f="$1" shift - run_avconv $* -f crc "$target_crcfile" - echo "$f $(cat $crcfile)" + printf "%s " "$f" + run_avconv $* -f crc - } lavf_audio(){ t="${test#lavf-}" outdir="tests/data/lavf" file=${outdir}/lavf.$t + test "$keep" -ge 1 || cleanfiles="$cleanfiles $file" do_avconv $file -auto_conversion_filters $DEC_OPTS $1 -ar 44100 -f s16le -i $pcm_src "$ENC_OPTS -metadata title=lavftest" -t 1 -qscale 10 $2 - do_avconv_crc $file -auto_conversion_filters $DEC_OPTS $3 -i $target_path/$file + test "$4" = "disable_crc" || + do_avconv_crc $file -auto_conversion_filters $DEC_OPTS $3 -i $target_path/$file } lavf_container(){ t="${test#lavf-}" outdir="tests/data/lavf" file=${outdir}/lavf.$t + test "$keep" -ge 1 || cleanfiles="$cleanfiles $file" do_avconv $file -auto_conversion_filters $DEC_OPTS -f image2 -c:v pgmyuv -i $raw_src $DEC_OPTS -ar 44100 -f s16le $1 -i $pcm_src "$ENC_OPTS -metadata title=lavftest" -b:a 64k -t 1 -qscale:v 10 $2 test "$3" = "disable_crc" || do_avconv_crc $file -auto_conversion_filters $DEC_OPTS -i $target_path/$file $3 @@ -340,17 +355,25 @@ lavf_container_fate() t="${test#lavf-fate-}" outdir="tests/data/lavf-fate" file=${outdir}/lavf.$t + cleanfiles="$cleanfiles $file" input="${target_samples}/$1" do_avconv $file -auto_conversion_filters $DEC_OPTS $2 -i "$input" "$ENC_OPTS -metadata title=lavftest" -vcodec copy -acodec copy do_avconv_crc $file -auto_conversion_filters $DEC_OPTS -i $target_path/$file $3 } lavf_image(){ + nb_frames=13 t="${test#lavf-}" outdir="tests/data/images/$t" mkdir -p "$outdir" file=${outdir}/%02d.$t - run_avconv $DEC_OPTS -f image2 -c:v pgmyuv -i $raw_src $1 "$ENC_OPTS -metadata title=lavftest" -vf scale -frames 13 -y -qscale 10 $target_path/$file + if [ "$keep" -lt 1 ]; then + for i in `seq $nb_frames`; do + filename=`printf "$file" $i` + cleanfiles="$cleanfiles $filename" + done + fi + run_avconv $DEC_OPTS -f image2 -c:v pgmyuv -i $raw_src $1 "$ENC_OPTS -metadata title=lavftest" -vf scale -frames $nb_frames -y -qscale 10 $target_path/$file do_md5sum ${outdir}/02.$t do_avconv_crc $file -auto_conversion_filters $DEC_OPTS $2 -i $target_path/$file $2 echo $(wc -c ${outdir}/02.$t) @@ -369,6 +392,7 @@ lavf_video(){ t="${test#lavf-}" outdir="tests/data/lavf" file=${outdir}/lavf.$t + test "$keep" -ge 1 || cleanfiles="$cleanfiles $file" do_avconv $file -auto_conversion_filters $DEC_OPTS -f image2 -c:v pgmyuv -i $raw_src "$ENC_OPTS -metadata title=lavftest" -t 1 -qscale 10 $1 $2 do_avconv_crc $file -auto_conversion_filters $DEC_OPTS -i $target_path/$file $1 } @@ -377,16 +401,51 @@ refcmp_metadata(){ refcmp=$1 pixfmt=$2 fuzz=${3:-0.001} - ffmpeg $FLAGS $ENC_OPTS \ + ffmpeg -auto_conversion_filters $FLAGS $ENC_OPTS \ -lavfi "testsrc2=size=300x200:rate=1:duration=5,format=${pixfmt},split[ref][tmp];[tmp]avgblur=4[enc];[enc][ref]${refcmp},metadata=print:file=-" \ -f null /dev/null | awk -v ref=${ref} -v fuzz=${fuzz} -f ${base}/refcmp-metadata.awk - } +cmp_metadata(){ + refcmp=$1 + pixfmt=$2 + fuzz=${3:-0.001} + ffmpeg $FLAGS $ENC_OPTS \ + -lavfi "testsrc2=size=300x200:rate=1:duration=5,format=${pixfmt},${refcmp},metadata=print:file=-" \ + -f null /dev/null | awk -v ref=${ref} -v fuzz=${fuzz} -f ${base}/refcmp-metadata.awk - +} + +refcmp_metadata_files(){ + file1=$1 + file2=$2 + refcmp=$3 + pixfmt=$4 + fuzz=${5:-0.001} + ffmpeg -auto_conversion_filters $FLAGS -i $file1 $FLAGS -i $file2 $ENC_OPTS \ + -lavfi "[0:v]format=${pixfmt}[v0];[1:v]format=${pixfmt}[v1];[v0][v1]${refcmp},metadata=print:file=-" \ + -f null /dev/null | awk -v ref=${ref} -v fuzz=${fuzz} -f ${base}/refcmp-metadata.awk - +} + +refcmp_metadata_transcode(){ + srcfile=$1 + enc_opt=$2 + enc_fmt=$3 + enc_ext=$4 + shift 4 + encfile="${outdir}/${test}.${enc_ext}" + cleanfiles="$cleanfiles $encfile" + tsrcfile=$(target_path $srcfile) + tencfile=$(target_path $encfile) + ffmpeg $DEC_OPTS -i $tsrcfile $ENC_OPTS $enc_opt $FLAGS -y -f $enc_fmt $tencfile || return + refcmp_metadata_files $tencfile $tsrcfile "$@" +} + pixfmt_conversion(){ conversion="${test#pixfmt-}" outdir="tests/data/pixfmt" raw_dst="$outdir/$conversion.out.yuv" file=${outdir}/${conversion}.yuv + cleanfiles="$cleanfiles $raw_dst $file" run_avconv $DEC_OPTS -r 1 -f image2 -c:v pgmyuv -i $raw_src \ $ENC_OPTS -f rawvideo -t 1 -s 352x288 -pix_fmt $conversion $target_path/$raw_dst do_avconv $file $DEC_OPTS -f rawvideo -s 352x288 -pix_fmt $conversion -i $target_path/$raw_dst \ @@ -563,7 +622,7 @@ if test $err != 0 && test $gen != "no" ; then fi if test $err = 0; then - if test $keep = 0; then + if test $keep -lt 2; then rm -f $outfile $errfile $cmpfile $cleanfiles fi elif test $gen = "no"; then diff --git a/tests/fate/ac3.mak b/tests/fate/ac3.mak index 39b555161..f0c3d1804 100644 --- a/tests/fate/ac3.mak +++ b/tests/fate/ac3.mak @@ -6,13 +6,13 @@ FATE_AC3 += fate-ac3-4.0 fate-ac3-4.0: CMD = pcm -i $(TARGET_SAMPLES)/ac3/millers_crossing_4.0.ac3 fate-ac3-4.0: REF = $(SAMPLES)/ac3/millers_crossing_4.0_v2.pcm -#request_channel_layout 4 -> front channel +#downmix 4.0 -> front channel FATE_AC3 += fate-ac3-4.0-downmix-mono -fate-ac3-4.0-downmix-mono: CMD = pcm -request_channel_layout 4 -i $(TARGET_SAMPLES)/ac3/millers_crossing_4.0.ac3 +fate-ac3-4.0-downmix-mono: CMD = pcm -downmix mono -i $(TARGET_SAMPLES)/ac3/millers_crossing_4.0.ac3 fate-ac3-4.0-downmix-mono: REF = $(SAMPLES)/ac3/millers_crossing_4.0_mono_v2.pcm FATE_AC3 += fate-ac3-4.0-downmix-stereo -fate-ac3-4.0-downmix-stereo: CMD = pcm -request_channel_layout stereo -i $(TARGET_SAMPLES)/ac3/millers_crossing_4.0.ac3 +fate-ac3-4.0-downmix-stereo: CMD = pcm -downmix stereo -i $(TARGET_SAMPLES)/ac3/millers_crossing_4.0.ac3 fate-ac3-4.0-downmix-stereo: REF = $(SAMPLES)/ac3/millers_crossing_4.0_stereo_v2.pcm FATE_AC3 += fate-ac3-5.1 @@ -20,11 +20,11 @@ fate-ac3-5.1: CMD = pcm -i $(TARGET_SAMPLES)/ac3/monsters_inc_5.1_448_small.ac3 fate-ac3-5.1: REF = $(SAMPLES)/ac3/monsters_inc_5.1_448_small_v2.pcm FATE_AC3 += fate-ac3-5.1-downmix-mono -fate-ac3-5.1-downmix-mono: CMD = pcm -request_channel_layout FC -i $(TARGET_SAMPLES)/ac3/monsters_inc_5.1_448_small.ac3 +fate-ac3-5.1-downmix-mono: CMD = pcm -downmix FC -i $(TARGET_SAMPLES)/ac3/monsters_inc_5.1_448_small.ac3 fate-ac3-5.1-downmix-mono: REF = $(SAMPLES)/ac3/monsters_inc_5.1_448_small_mono_v2.pcm FATE_AC3 += fate-ac3-5.1-downmix-stereo -fate-ac3-5.1-downmix-stereo: CMD = pcm -request_channel_layout 2c -i $(TARGET_SAMPLES)/ac3/monsters_inc_5.1_448_small.ac3 +fate-ac3-5.1-downmix-stereo: CMD = pcm -downmix stereo -i $(TARGET_SAMPLES)/ac3/monsters_inc_5.1_448_small.ac3 fate-ac3-5.1-downmix-stereo: REF = $(SAMPLES)/ac3/monsters_inc_5.1_448_small_stereo_v2.pcm FATE_AC3 += fate-ac3-fixed-2.0 @@ -32,15 +32,15 @@ fate-ac3-fixed-2.0: CMD = pcm -c ac3_fixed -i $(TARGET_SAMPLES)/ac3/monsters_inc fate-ac3-fixed-2.0: REF = $(SAMPLES)/ac3/monsters_inc_2.0_192_small_v2.pcm FATE_AC3 += fate-ac3-fixed-4.0-downmix-mono -fate-ac3-fixed-4.0-downmix-mono: CMD = pcm -c ac3_fixed -request_channel_layout mono -i $(TARGET_SAMPLES)/ac3/millers_crossing_4.0.ac3 +fate-ac3-fixed-4.0-downmix-mono: CMD = pcm -c ac3_fixed -downmix mono -i $(TARGET_SAMPLES)/ac3/millers_crossing_4.0.ac3 fate-ac3-fixed-4.0-downmix-mono: REF = $(SAMPLES)/ac3/millers_crossing_4.0_mono_v2.pcm FATE_AC3 += fate-ac3-fixed-5.1-downmix-mono -fate-ac3-fixed-5.1-downmix-mono: CMD = pcm -c ac3_fixed -request_channel_layout 4 -i $(TARGET_SAMPLES)/ac3/monsters_inc_5.1_448_small.ac3 +fate-ac3-fixed-5.1-downmix-mono: CMD = pcm -c ac3_fixed -downmix mono -i $(TARGET_SAMPLES)/ac3/monsters_inc_5.1_448_small.ac3 fate-ac3-fixed-5.1-downmix-mono: REF = $(SAMPLES)/ac3/monsters_inc_5.1_448_small_mono_v2.pcm FATE_AC3 += fate-ac3-fixed-5.1-downmix-stereo -fate-ac3-fixed-5.1-downmix-stereo: CMD = pcm -c ac3_fixed -request_channel_layout 3 -i $(TARGET_SAMPLES)/ac3/monsters_inc_5.1_448_small.ac3 +fate-ac3-fixed-5.1-downmix-stereo: CMD = pcm -c ac3_fixed -downmix stereo -i $(TARGET_SAMPLES)/ac3/monsters_inc_5.1_448_small.ac3 fate-ac3-fixed-5.1-downmix-stereo: REF = $(SAMPLES)/ac3/monsters_inc_5.1_448_small_stereo_v2.pcm FATE_EAC3 += fate-eac3-1 diff --git a/tests/fate/acodec.mak b/tests/fate/acodec.mak index eda449c08..27b69ad9f 100644 --- a/tests/fate/acodec.mak +++ b/tests/fate/acodec.mak @@ -1,36 +1,38 @@ fate-acodec-%: CODEC = $(@:fate-acodec-%=%) fate-acodec-%: SRC = tests/data/asynth-44100-2.wav -fate-acodec-%: CMD = enc_dec wav $(SRC) $(FMT) "-b:a 128k -c $(CODEC) $(ENCOPTS)" wav "-c pcm_s16le $(DECOPTS)" "$(KEEP_OVERRIDE)" +fate-acodec-%: CMD = enc_dec wav $(SRC) $(FMT) "-b:a 128k -c $(CODEC) $(ENCOPTS)" wav "-c pcm_s16le $(DECOPTS)" fate-acodec-%: CMP_UNIT = 2 fate-acodec-%: REF = $(SRC_PATH)/tests/ref/acodec/$(@:fate-acodec-%=%) FATE_ACODEC_PCM-$(call ENCDEC, PCM_ALAW, WAV) += alaw FATE_ACODEC_PCM-$(call ENCDEC, PCM_MULAW, WAV) += mulaw -FATE_ACODEC_PCM-$(call ENCDEC, PCM_S8, MOV) += s8 -FATE_ACODEC_PCM-$(call ENCDEC, PCM_U8, WAV) += u8 +FATE_ACODEC_PCM_RESAMPLE-$(call ENCDEC, PCM_S8, MOV) += s8 +FATE_ACODEC_PCM_RESAMPLE-$(call ENCDEC, PCM_U8, WAV) += u8 FATE_ACODEC_PCM-$(call ENCDEC, PCM_S16BE, MOV) += s16be FATE_ACODEC_PCM-$(call ENCDEC, PCM_S16LE, WAV) += s16le FATE_ACODEC_PCM-$(call ENCDEC, PCM_U16BE, NUT) += u16be FATE_ACODEC_PCM-$(call ENCDEC, PCM_U16LE, NUT) += u16le -FATE_ACODEC_PCM-$(call ENCDEC, PCM_S24BE, MOV) += s24be -FATE_ACODEC_PCM-$(call ENCDEC, PCM_S24LE, WAV) += s24le -FATE_ACODEC_PCM-$(call ENCDEC, PCM_U24BE, NUT) += u24be -FATE_ACODEC_PCM-$(call ENCDEC, PCM_U24LE, NUT) += u24le -FATE_ACODEC_PCM-$(call ENCDEC, PCM_S32BE, MOV) += s32be -FATE_ACODEC_PCM-$(call ENCDEC, PCM_S32LE, WAV) += s32le -FATE_ACODEC_PCM-$(call ENCDEC, PCM_U32BE, NUT) += u32be -FATE_ACODEC_PCM-$(call ENCDEC, PCM_U32LE, NUT) += u32le -FATE_ACODEC_PCM-$(call ENCDEC, PCM_F32BE, AU) += f32be -FATE_ACODEC_PCM-$(call ENCDEC, PCM_F32LE, WAV) += f32le -FATE_ACODEC_PCM-$(call ENCDEC, PCM_F64BE, AU) += f64be -FATE_ACODEC_PCM-$(call ENCDEC, PCM_F64LE, WAV) += f64le -FATE_ACODEC_PCM-$(call ENCDEC, PCM_S8_PLANAR, NUT) += s8_planar -FATE_ACODEC_PCM-$(call ENCDEC, PCM_S16BE_PLANAR, NUT) += s16be_planar -FATE_ACODEC_PCM-$(call ENCDEC, PCM_S16LE_PLANAR, NUT) += s16le_planar -FATE_ACODEC_PCM-$(call ENCDEC, PCM_S24LE_PLANAR, NUT) += s24le_planar -FATE_ACODEC_PCM-$(call ENCDEC, PCM_S32LE_PLANAR, NUT) += s32le_planar +FATE_ACODEC_PCM_RESAMPLE-$(call ENCDEC, PCM_S24BE, MOV) += s24be +FATE_ACODEC_PCM_RESAMPLE-$(call ENCDEC, PCM_S24LE, WAV) += s24le +FATE_ACODEC_PCM_RESAMPLE-$(call ENCDEC, PCM_U24BE, NUT) += u24be +FATE_ACODEC_PCM_RESAMPLE-$(call ENCDEC, PCM_U24LE, NUT) += u24le +FATE_ACODEC_PCM_RESAMPLE-$(call ENCDEC, PCM_S32BE, MOV) += s32be +FATE_ACODEC_PCM_RESAMPLE-$(call ENCDEC, PCM_S32LE, WAV) += s32le +FATE_ACODEC_PCM_RESAMPLE-$(call ENCDEC, PCM_U32BE, NUT) += u32be +FATE_ACODEC_PCM_RESAMPLE-$(call ENCDEC, PCM_U32LE, NUT) += u32le +FATE_ACODEC_PCM_RESAMPLE-$(call ENCDEC, PCM_F32BE, AU) += f32be +FATE_ACODEC_PCM_RESAMPLE-$(call ENCDEC, PCM_F32LE, WAV) += f32le +FATE_ACODEC_PCM_RESAMPLE-$(call ENCDEC, PCM_F64BE, AU) += f64be +FATE_ACODEC_PCM_RESAMPLE-$(call ENCDEC, PCM_F64LE, WAV) += f64le +FATE_ACODEC_PCM_RESAMPLE-$(call ENCDEC, PCM_S8_PLANAR, NUT) += s8_planar +FATE_ACODEC_PCM_RESAMPLE-$(call ENCDEC, PCM_S16BE_PLANAR, NUT) += s16be_planar +FATE_ACODEC_PCM_RESAMPLE-$(call ENCDEC, PCM_S16LE_PLANAR, NUT) += s16le_planar +FATE_ACODEC_PCM_RESAMPLE-$(call ENCDEC, PCM_S24LE_PLANAR, NUT) += s24le_planar +FATE_ACODEC_PCM_RESAMPLE-$(call ENCDEC, PCM_S32LE_PLANAR, NUT) += s32le_planar -FATE_ACODEC_PCM := $(FATE_ACODEC_PCM-yes:%=fate-acodec-pcm-%) +FATE_ACODEC_PCM-$(CONFIG_ARESAMPLE_FILTER) += $(FATE_ACODEC_PCM_RESAMPLE-yes) +FATE_ACODEC_PCM := $(if $(call ENCDEC, PCM_S16LE, WAV), $(FATE_ACODEC_PCM-yes)) +FATE_ACODEC_PCM := $(FATE_ACODEC_PCM:%=fate-acodec-pcm-%) FATE_ACODEC += $(FATE_ACODEC_PCM) fate-acodec-pcm: $(FATE_ACODEC_PCM) @@ -44,20 +46,22 @@ fate-acodec-pcm-u%be: FMT = nut fate-acodec-pcm-u%le: FMT = nut fate-acodec-pcm-f%be: FMT = au -FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_ADX, ADX) += adx -FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_ARGO, ARGO_ASF) += argo +FATE_ACODEC_ADPCM_RESAMPLE-$(call ENCDEC, ADPCM_ADX, ADX) += adx +FATE_ACODEC_ADPCM_RESAMPLE-$(call ENCDEC, ADPCM_ARGO, ARGO_ASF) += argo FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_IMA_APM, APM) += ima_apm FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_IMA_ALP, ALP) += ima_alp -FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_IMA_QT, AIFF) += ima_qt +FATE_ACODEC_ADPCM_RESAMPLE-$(call ENCDEC, ADPCM_IMA_QT, AIFF) += ima_qt FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_IMA_SSI, KVAG) += ima_ssi -FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_IMA_WAV, WAV) += ima_wav +FATE_ACODEC_ADPCM_RESAMPLE-$(call ENCDEC, ADPCM_IMA_WAV, WAV) += ima_wav FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_IMA_WS, WSAUD) += ima_ws FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_MS, WAV) += ms FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_SWF, FLV) += swf FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_SWF, WAV) += swf-wav FATE_ACODEC_ADPCM-$(call ENCDEC, ADPCM_YAMAHA, WAV) += yamaha -FATE_ACODEC_ADPCM := $(FATE_ACODEC_ADPCM-yes:%=fate-acodec-adpcm-%) +FATE_ACODEC_ADPCM-$(CONFIG_ARESAMPLE_FILTER) += $(FATE_ACODEC_ADPCM_RESAMPLE-yes) +FATE_ACODEC_ADPCM := $(if $(call ENCDEC, PCM_S16LE, WAV), $(FATE_ACODEC_ADPCM-yes)) +FATE_ACODEC_ADPCM := $(FATE_ACODEC_ADPCM:%=fate-acodec-adpcm-%) FATE_ACODEC += $(FATE_ACODEC_ADPCM) fate-acodec-adpcm: $(FATE_ACODEC_ADPCM) @@ -80,49 +84,44 @@ fate-acodec-adpcm-swf-wav: CODEC = adpcm_swf fate-acodec-adpcm-ima_alp: FMT = alp fate-acodec-adpcm-ima_alp: ENCOPTS = -type pcm -FATE_ACODEC_ADPCM_TRELLIS-$(call ENCDEC, ADPCM_ADX, ADX) += adx -FATE_ACODEC_ADPCM_TRELLIS-$(call ENCDEC, ADPCM_IMA_QT, AIFF) += ima_qt -FATE_ACODEC_ADPCM_TRELLIS-$(call ENCDEC, ADPCM_IMA_WAV, WAV) += ima_wav -FATE_ACODEC_ADPCM_TRELLIS-$(call ENCDEC, ADPCM_MS, WAV) += ms -FATE_ACODEC_ADPCM_TRELLIS-$(call ENCDEC, ADPCM_SWF, FLV) += swf -FATE_ACODEC_ADPCM_TRELLIS-$(call ENCDEC, ADPCM_YAMAHA, WAV) += yamaha +FATE_ACODEC_ADPCM_TRELLIS := ima_qt ima_wav ms swf yamaha -FATE_ACODEC_ADPCM_TRELLIS := $(FATE_ACODEC_ADPCM_TRELLIS-yes:%=fate-acodec-adpcm-%-trellis) +FATE_ACODEC_ADPCM_TRELLIS := $(FATE_ACODEC_ADPCM_TRELLIS:%=fate-acodec-adpcm-%-trellis) +FATE_ACODEC_ADPCM_TRELLIS := $(filter $(addsuffix -trellis,$(FATE_ACODEC_ADPCM)), $(FATE_ACODEC_ADPCM_TRELLIS)) FATE_ACODEC += $(FATE_ACODEC_ADPCM_TRELLIS) fate-acodec-adpcm-trellis: $(FATE_ACODEC_ADPCM_TRELLIS) fate-acodec-adpcm-%-trellis: CODEC = adpcm_$(@:fate-acodec-adpcm-%-trellis=%) fate-acodec-adpcm-%-trellis: ENCOPTS = -trellis 5 -fate-acodec-adpcm-adx-trellis: FMT = adx fate-acodec-adpcm-ima_qt-trellis: FMT = aiff fate-acodec-adpcm-ima_wav-trellis: FMT = wav fate-acodec-adpcm-ms-trellis: FMT = wav fate-acodec-adpcm-swf-trellis: FMT = flv fate-acodec-adpcm-yamaha-trellis: FMT = wav -FATE_ACODEC-$(call ENCDEC, MP2, MP2 MP3) += fate-acodec-mp2 +FATE_ACODEC-$(call ENCDEC, MP2, MP2 MP3, ARESAMPLE_FILTER) += fate-acodec-mp2 fate-acodec-mp2: FMT = mp2 fate-acodec-mp2: CMP_SHIFT = -1924 fate-acodec-mp2: ENCOPTS = -b:a 128k -FATE_ACODEC-$(call ENCDEC, MP2FIXED MP2 , MP2 MP3) += fate-acodec-mp2fixed +FATE_ACODEC-$(call ENCDEC, MP2FIXED MP2, MP2 MP3, ARESAMPLE_FILTER) += fate-acodec-mp2fixed fate-acodec-mp2fixed: FMT = mp2 fate-acodec-mp2fixed: CMP_SHIFT = -1924 fate-acodec-mp2fixed: ENCOPTS = -b:a 384k -FATE_ACODEC-$(call ENCDEC, ALAC, MOV) += fate-acodec-alac +FATE_ACODEC-$(call ENCDEC, ALAC, MOV, ARESAMPLE_FILTER) += fate-acodec-alac fate-acodec-alac: FMT = mov fate-acodec-alac: CODEC = alac -compression_level 1 -FATE_ACODEC-$(call ENCDEC, DCA, DTS) += fate-acodec-dca +FATE_ACODEC-$(call ENCDEC, DCA, DTS, ARESAMPLE_FILTER) += fate-acodec-dca 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 -af aresample fate-acodec-dca: CMP = oneline fate-acodec-dca: REF = 2aa580ac67820fce4f581b96ebb34acc -FATE_ACODEC-$(call ENCDEC, DCA, WAV) += fate-acodec-dca2 +FATE_ACODEC-$(call ENCDEC, DCA, WAV, ARESAMPLE_FILTER) += fate-acodec-dca2 fate-acodec-dca2: CMD = enc_dec_pcm dts wav s16le $(SRC) -c:a dca -strict -2 -flags +bitexact -af aresample fate-acodec-dca2: REF = $(SRC) fate-acodec-dca2: CMP = stddev @@ -137,7 +136,7 @@ fate-acodec-flac: CODEC = flac -compression_level 2 fate-acodec-flac-exact-rice: FMT = flac fate-acodec-flac-exact-rice: CODEC = flac -compression_level 2 -exact_rice_parameters 1 -FATE_ACODEC-$(call ENCDEC, G723_1, G723_1) += fate-acodec-g723_1 +FATE_ACODEC-$(call ENCDEC, G723_1, G723_1, ARESAMPLE_FILTER) += fate-acodec-g723_1 fate-acodec-g723_1: tests/data/asynth-8000-1.wav fate-acodec-g723_1: SRC = tests/data/asynth-8000-1.wav fate-acodec-g723_1: FMT = g723_1 @@ -154,25 +153,26 @@ fate-acodec-ra144: CMP = stddev fate-acodec-ra144: CMP_TARGET = 4777 fate-acodec-ra144: CMP_SHIFT = -320 -FATE_ACODEC-$(call ENCDEC, ROQ_DPCM, ROQ) += fate-acodec-roqaudio +FATE_ACODEC-$(call ENCDEC, ROQ_DPCM, ROQ, ARESAMPLE_FILTER) += fate-acodec-roqaudio fate-acodec-roqaudio: FMT = roq fate-acodec-roqaudio: CODEC = roq_dpcm fate-acodec-roqaudio: ENCOPTS = -ar 22050 fate-acodec-roqaudio: DECOPTS = -ar 44100 -FATE_ACODEC-$(call ENCDEC, S302M, MPEGTS) += fate-acodec-s302m +FATE_ACODEC-$(call ENCDEC, S302M, MPEGTS, ARESAMPLE_FILTER) += fate-acodec-s302m fate-acodec-s302m: FMT = mpegts fate-acodec-s302m: CODEC = s302m fate-acodec-s302m: ENCOPTS = -ar 48000 -strict -2 fate-acodec-s302m: DECOPTS = -ar 44100 -FATE_ACODEC-$(call ENCDEC, WAVPACK, WV) += fate-acodec-wavpack +FATE_ACODEC-$(call ENCDEC, WAVPACK, WV, ARESAMPLE_FILTER) += fate-acodec-wavpack fate-acodec-wavpack: FMT = wv fate-acodec-wavpack: CODEC = wavpack -compression_level 1 FATE_ACODEC-$(call ENCDEC, TTA, TTA) += fate-acodec-tta fate-acodec-tta: FMT = tta +FATE_ACODEC-yes := $(if $(call ENCDEC, PCM_S16LE, WAV), $(FATE_ACODEC-yes)) FATE_ACODEC += $(FATE_ACODEC-yes) $(FATE_ACODEC): tests/data/asynth-44100-2.wav diff --git a/tests/fate/amrnb.mak b/tests/fate/amrnb.mak index c0feec25d..6f5ed413e 100644 --- a/tests/fate/amrnb.mak +++ b/tests/fate/amrnb.mak @@ -30,7 +30,11 @@ FATE_AMRNB += fate-amrnb-12k2 fate-amrnb-12k2: CMD = pcm -i $(TARGET_SAMPLES)/amrnb/12.2k.amr fate-amrnb-12k2: REF = $(SAMPLES)/amrnb/12.2k.pcm +FATE_AMRNB_REMUX-$(call REMUX, AMR, AMR_PARSER) += fate-amrnb-remux +fate-amrnb-remux: CMD = transcode amr $(TARGET_SAMPLES)/amrnb/10.2k.amr amr "-c copy" "-c copy -t 1" + $(FATE_AMRNB): CMP = stddev FATE_SAMPLES_AVCONV-$(call DEMDEC, AMR, AMRNB) += $(FATE_AMRNB) -fate-amrnb: $(FATE_AMRNB) +FATE_SAMPLES_FFMPEG += $(FATE_AMRNB_REMUX-yes) +fate-amrnb: $(FATE_AMRNB) $(FATE_AMRNB_REMUX-yes) diff --git a/tests/fate/amrwb.mak b/tests/fate/amrwb.mak index b93835d76..7cd17d266 100644 --- a/tests/fate/amrwb.mak +++ b/tests/fate/amrwb.mak @@ -41,7 +41,11 @@ FATE_AMRWB += fate-amrwb-23k85-2 fate-amrwb-23k85-2: CMD = pcm -i $(TARGET_SAMPLES)/amrwb/deus-23k85.awb fate-amrwb-23k85-2: REF = $(SAMPLES)/amrwb/deus-23k85.pcm +FATE_AMRWB_REMUX-$(call REMUX, AMR, MOV_DEMUXER AMR_PARSER) += fate-amrwb-remux +fate-amrwb-remux: CMD = transcode mov $(TARGET_SAMPLES)/amrwb/seed-23k85.awb amr "-c copy" "-c copy -t 1" + $(FATE_AMRWB): CMP = stddev -FATE_SAMPLES_AVCONV-$(call DEMDEC, AMR, AMRWB) += $(FATE_AMRWB) -fate-amrwb: $(FATE_AMRWB) +FATE_SAMPLES_FFMPEG-$(call DEMDEC, MOV, AMRWB) += $(FATE_AMRWB) +FATE_SAMPLES_FFMPEG += $(FATE_AMRWB_REMUX-yes) +fate-amrwb: $(FATE_AMRWB) $(FATE_AMRWB_REMUX-yes) diff --git a/tests/fate/api.mak b/tests/fate/api.mak index 10288f5ab..688fc0f9b 100644 --- a/tests/fate/api.mak +++ b/tests/fate/api.mak @@ -18,6 +18,7 @@ fate-api-h264-slice: CMD = run $(APITESTSDIR)/api-h264-slice-test$(EXESUF) 2 $(T FATE_API_LIBAVFORMAT-$(call DEMDEC, FLV, FLV) += fate-api-seek fate-api-seek: $(APITESTSDIR)/api-seek-test$(EXESUF) fate-lavf-flv +fate-lavf-flv: KEEP_FILES ?= 1 fate-api-seek: CMD = run $(APITESTSDIR)/api-seek-test$(EXESUF) $(TARGET_PATH)/tests/data/lavf/lavf.flv 0 720 fate-api-seek: CMP = null diff --git a/tests/fate/bmp.mak b/tests/fate/bmp.mak index de27f19b1..050d3d135 100644 --- a/tests/fate/bmp.mak +++ b/tests/fate/bmp.mak @@ -22,7 +22,7 @@ fate-bmp-15bit-mask: CMD = framecrc -i $(TARGET_SAMPLES)/bmp/test16bf555.bmp -pi FATE_BMP += fate-bmp-16bit-mask fate-bmp-16bit-mask: CMD = framecrc -i $(TARGET_SAMPLES)/bmp/test16bf565.bmp -pix_fmt rgb565le -vf scale -FATE_BMP += fate-bmp-24bit +FATE_BMP-$(call FRAMECRC, IMAGE2, BMP) += fate-bmp-24bit fate-bmp-24bit: CMD = framecrc -i $(TARGET_SAMPLES)/bmp/test24.bmp FATE_BMP += fate-bmp-32bit @@ -37,7 +37,7 @@ fate-bmp-rle4: CMD = framecrc -i $(TARGET_SAMPLES)/bmp/testcompress4.bmp -pix_fm FATE_BMP += fate-bmp-rle8 fate-bmp-rle8: CMD = framecrc -i $(TARGET_SAMPLES)/bmp/testcompress8.bmp -pix_fmt rgb24 -vf scale -FATE_BMP-$(call DEMDEC, IMAGE2, BMP) += $(FATE_BMP) +FATE_BMP-$(call FRAMECRC, IMAGE2, BMP, SCALE_FILTER) += $(FATE_BMP) FATE_SAMPLES_AVCONV += $(FATE_BMP-yes) fate-bmp: $(FATE_BMP-yes) diff --git a/tests/fate/caf.mak b/tests/fate/caf.mak index ae2c54335..a53f5fa0f 100644 --- a/tests/fate/caf.mak +++ b/tests/fate/caf.mak @@ -1,33 +1,26 @@ FATE_CAF_FFMPEG-$(call ALLYES, CAF_DEMUXER CRC_MUXER) += fate-caf-demux fate-caf-demux: CMD = crc -i $(TARGET_SAMPLES)/caf/caf-pcm16.caf -c copy -FATE_CAF_REMUX_FFPROBE-$(CONFIG_MOV_DEMUXER) += fate-caf-alac-remux -fate-caf-alac-remux: CMD = transcode m4a $(TARGET_SAMPLES)/lossless-audio/inside.m4a caf "-map 0:a -c copy -metadata major_brand= " "-c copy -t 0.2" "" "-show_entries format_tags" +FATE_CAF_FFMPEG_FFPROBE-$(call REMUX, CAF, MOV_DEMUXER) += fate-caf-alac-remux +fate-caf-alac-remux: CMD = transcode m4a $(TARGET_SAMPLES)/lossless-audio/inside.m4a caf "-map 0:a -c copy -metadata major_brand= " "-c copy -t 0.2" "-show_entries format_tags" -FATE_CAF_REMUX-$(CONFIG_AMR_DEMUXER) += fate-caf-amr_nb-remux +FATE_CAF_FFMPEG-$(call REMUX, CAF, AMR_DEMUXER) += fate-caf-amr_nb-remux fate-caf-amr_nb-remux: CMD = transcode amr $(TARGET_SAMPLES)/amrnb/4.75k.amr caf "-c copy" "-c copy -t 0.2" -FATE_CAF_REMUX-$(CONFIG_MOV_DEMUXER) += fate-caf-qdm2-remux +FATE_CAF_FFMPEG-$(call REMUX, CAF, MOV_DEMUXER) += fate-caf-qdm2-remux fate-caf-qdm2-remux: CMD = transcode mov $(TARGET_SAMPLES)/qt-surge-suite/surge-2-16-B-QDM2.mov caf "-c copy" "-c copy -t 0.2" -FATE_CAF_REMUX-$(CONFIG_WAV_DEMUXER) += fate-caf-pcm_s24le-remux +FATE_CAF_FFMPEG-$(call REMUX, CAF, WAV_DEMUXER) += fate-caf-pcm_s24le-remux fate-caf-pcm_s24le-remux: CMD = transcode wav $(TARGET_SAMPLES)/audio-reference/divertimenti_2ch_96kHz_s24.wav caf "-c copy" "-c copy -t 0.05" -FATE_CAF_REMUX-$(call ALLYES, WAV_DEMUXER PCM_S24LE_DECODER \ - PCM_S24BE_ENCODER) \ +FATE_CAF_FFMPEG-$(call REMUX, CAF, WAV_DEMUXER PCM_S24LE_DECODER \ + PCM_S24BE_ENCODER) \ += fate-caf-pcm_s24-remux fate-caf-pcm_s24-remux: CMD = transcode wav $(TARGET_SAMPLES)/audio-reference/divertimenti_2ch_96kHz_s24.wav caf "-c pcm_s24be" "-c copy -t 0.05" -FATE_CAF_REMUX-$(CONFIG_MOV_DEMUXER) += fate-caf-mace6-remux +FATE_CAF_FFMPEG-$(call REMUX, CAF, MOV_DEMUXER) += fate-caf-mace6-remux fate-caf-mace6-remux: CMD = transcode mov $(TARGET_SAMPLES)/qtrle/Animation-16Greys.mov caf "-map 0:a -c copy" "-c copy -t 0.003" -FATE_CAF_FFMPEG-$(call ALLYES, FILE_PROTOCOL CAF_MUXER CAF_DEMUXER \ - FRAMECRC_MUXER PIPE_PROTOCOL) \ - += $(FATE_CAF_REMUX-yes) -FATE_CAF_FFMPEG_FFPROBE-$(call ALLYES, FILE_PROTOCOL CAF_MUXER \ - CAF_DEMUXER FRAMECRC_MUXER \ - PIPE_PROTOCOL) \ - += $(FATE_CAF_REMUX_FFPROBE-yes) FATE_SAMPLES_FFMPEG += $(FATE_CAF_FFMPEG-yes) FATE_SAMPLES_FFMPEG_FFPROBE += $(FATE_CAF_FFMPEG_FFPROBE-yes) fate-caf: $(FATE_CAF_FFMPEG-yes) $(FATE_CAF_FFMPEG_FFPROBE-yes) diff --git a/tests/fate/canopus.mak b/tests/fate/canopus.mak index 3d664ff91..4e5071681 100644 --- a/tests/fate/canopus.mak +++ b/tests/fate/canopus.mak @@ -8,7 +8,8 @@ fate-canopus-cllc-rgb: CMD = framecrc -i $(TARGET_SAMPLES)/cllc/sample-cllc-rgb. FATE_CANOPUS_CLLC += fate-canopus-cllc-yuy2-noblock fate-canopus-cllc-yuy2-noblock: CMD = framecrc -i $(TARGET_SAMPLES)/cllc/sample-cllc-yuy2-noblock.avi -FATE_SAMPLES_FFMPEG-$(call DEMDEC, AVI, CLLC) += $(FATE_CANOPUS_CLLC) +FATE_CANOPUS_CLLC := $(if $(call FRAMECRC, AVI, CLLC), $(FATE_CANOPUS_CLLC)) +FATE_SAMPLES_FFMPEG += $(FATE_CANOPUS_CLLC) fate-canopus-cllc: $(FATE_CANOPUS_CLLC) #lossy @@ -21,7 +22,8 @@ fate-canopus-hq_hqa-hqa: CMD = framecrc -i $(TARGET_SAMPLES)/canopus/hqa.avi FATE_CANOPUS_HQ_HQA += fate-canopus-hq_hqa-inter fate-canopus-hq_hqa-inter: CMD = framecrc -i $(TARGET_SAMPLES)/canopus/hq25i.avi -FATE_SAMPLES_FFMPEG-$(call DEMDEC, AVI, HQ_HQA) += $(FATE_CANOPUS_HQ_HQA) +FATE_CANOPUS_HQ_HQA := $(if $(call FRAMECRC, AVI, HQ_HQA), $(FATE_CANOPUS_HQ_HQA)) +FATE_SAMPLES_FFMPEG += $(FATE_CANOPUS_HQ_HQA) fate-canopus-hq_hqa: $(FATE_CANOPUS_HQ_HQA) FATE_CANOPUS_HQX += fate-canopus-hqx422 @@ -30,5 +32,6 @@ fate-canopus-hqx422: CMD = framecrc -i $(TARGET_SAMPLES)/canopus/hqx422.avi -pix FATE_CANOPUS_HQX += fate-canopus-hqx422a fate-canopus-hqx422a: CMD = framecrc -i $(TARGET_SAMPLES)/canopus/hqx422a.avi -pix_fmt yuv422p16be -an -vf scale -FATE_SAMPLES_FFMPEG-$(call DEMDEC, AVI, HQX) += $(FATE_CANOPUS_HQX) +FATE_CANOPUS_HQX := $(if $(call FRAMECRC, AVI, HQX, SCALE_FILTER), $(FATE_CANOPUS_HQX)) +FATE_SAMPLES_FFMPEG += $(FATE_CANOPUS_HQX) fate-canopus-hqx: $(FATE_CANOPUS_HQX) diff --git a/tests/fate/cdxl.mak b/tests/fate/cdxl.mak index 2a4e2dd51..db3045c27 100644 --- a/tests/fate/cdxl.mak +++ b/tests/fate/cdxl.mak @@ -7,13 +7,13 @@ fate-cdxl-ham6: CMD = framecrc -i $(TARGET_SAMPLES)/cdxl/cat.cdxl -an -frames:v FATE_CDXL += fate-cdxl-ham8 fate-cdxl-ham8: CMD = framecrc -i $(TARGET_SAMPLES)/cdxl/mirage.cdxl -an -frames:v 1 -FATE_CDXL += fate-cdxl-pal8 +FATE_CDXL-$(call FRAMECRC, CDXL, CDXL, SCALE_FILTER) += fate-cdxl-pal8 fate-cdxl-pal8: CMD = framecrc -i $(TARGET_SAMPLES)/cdxl/maku.cdxl -pix_fmt rgb24 -frames:v 11 -vf scale -FATE_CDXL += fate-cdxl-pal8-small +FATE_CDXL-$(call FRAMECRC, CDXL, CDXL, SCALE_FILTER) += fate-cdxl-pal8-small fate-cdxl-pal8-small: CMD = framecrc -i $(TARGET_SAMPLES)/cdxl/fruit.cdxl -an -pix_fmt rgb24 -frames:v 46 -vf scale -FATE_CDXL-$(call DEMDEC, CDXL, CDXL) += $(FATE_CDXL) +FATE_CDXL-$(call FRAMECRC, CDXL, CDXL) += $(FATE_CDXL) FATE_SAMPLES_AVCONV += $(FATE_CDXL-yes) fate-cdxl: $(FATE_CDXL-yes) diff --git a/tests/fate/checkasm.mak b/tests/fate/checkasm.mak index 6e7edbe65..4d2f321e8 100644 --- a/tests/fate/checkasm.mak +++ b/tests/fate/checkasm.mak @@ -19,18 +19,22 @@ FATE_CHECKASM = fate-checkasm-aacpsdsp \ fate-checkasm-hevc_pel \ fate-checkasm-hevc_sao \ fate-checkasm-huffyuvdsp \ + fate-checkasm-idctdsp \ fate-checkasm-jpeg2000dsp \ fate-checkasm-llviddsp \ fate-checkasm-llviddspenc \ + fate-checkasm-motion \ fate-checkasm-opusdsp \ fate-checkasm-pixblockdsp \ fate-checkasm-sbrdsp \ fate-checkasm-synth_filter \ + fate-checkasm-sw_gbrp \ fate-checkasm-sw_rgb \ fate-checkasm-sw_scale \ fate-checkasm-utvideodsp \ fate-checkasm-v210dec \ fate-checkasm-v210enc \ + fate-checkasm-vc1dsp \ fate-checkasm-vf_blend \ fate-checkasm-vf_colorspace \ fate-checkasm-vf_eq \ diff --git a/tests/fate/concatdec.mak b/tests/fate/concatdec.mak index 988559d25..c0dc6d4c9 100644 --- a/tests/fate/concatdec.mak +++ b/tests/fate/concatdec.mak @@ -1,21 +1,27 @@ -FATE_CONCAT_DEMUXER_SIMPLE1_LAVF-$(call ENCDEC2, MPEG2VIDEO, PCM_S16LE, MXF) += mxf -FATE_CONCAT_DEMUXER_SIMPLE1_LAVF-$(call ENCDEC2, MPEG2VIDEO, PCM_S16LE, MXF) += mxf_d10 +FATE_CONCAT_DEMUXER_SIMPLE1_LAVF := mxf mxf_d10 -FATE_CONCAT_DEMUXER_SIMPLE2_LAVF-$(call ENCDEC2, MPEG2VIDEO, MP2, MPEGTS) += ts +FATE_CONCAT_DEMUXER_SIMPLE2_LAVF := ts -FATE_CONCAT_DEMUXER_EXTENDED_LAVF-$(call ENCDEC2, MPEG2VIDEO, PCM_S16LE, MXF) += mxf -FATE_CONCAT_DEMUXER_EXTENDED_LAVF-$(call ENCDEC2, MPEG2VIDEO, PCM_S16LE, MXF) += mxf_d10 +FATE_CONCAT_DEMUXER_EXTENDED_LAVF := mxf mxf_d10 -$(foreach D,$(FATE_CONCAT_DEMUXER_SIMPLE1_LAVF-yes),$(eval fate-concat-demuxer-simple1-lavf-$(D): ffprobe$(PROGSSUF)$(EXESUF) fate-lavf-$(D))) -$(foreach D,$(FATE_CONCAT_DEMUXER_SIMPLE1_LAVF-yes),$(eval fate-concat-demuxer-simple1-lavf-$(D): CMD = concat $(SRC_PATH)/tests/simple1.ffconcat ../lavf/lavf.$(D))) -FATE_CONCAT_DEMUXER-$(CONFIG_CONCAT_DEMUXER) += $(FATE_CONCAT_DEMUXER_SIMPLE1_LAVF-yes:%=fate-concat-demuxer-simple1-lavf-%) +define FATE_CONCAT_DEMUXER_SUITE +$$(addprefix fate-lavf-,$$(FATE_CONCAT_DEMUXER_$(D)_LAVF)): KEEP_FILES ?= 1 +FATE_CONCAT_DEMUXER_$(D)_LAVF := $$(filter $$(FATE_LAVF_CONTAINER:fate-lavf-%=%),$$(FATE_CONCAT_DEMUXER_$(D)_LAVF)) +endef -$(foreach D,$(FATE_CONCAT_DEMUXER_SIMPLE2_LAVF-yes),$(eval fate-concat-demuxer-simple2-lavf-$(D): ffprobe$(PROGSSUF)$(EXESUF) fate-lavf-$(D))) -$(foreach D,$(FATE_CONCAT_DEMUXER_SIMPLE2_LAVF-yes),$(eval fate-concat-demuxer-simple2-lavf-$(D): CMD = concat $(SRC_PATH)/tests/simple2.ffconcat ../lavf/lavf.$(D))) -FATE_CONCAT_DEMUXER-$(CONFIG_CONCAT_DEMUXER) += $(FATE_CONCAT_DEMUXER_SIMPLE2_LAVF-yes:%=fate-concat-demuxer-simple2-lavf-%) +$(foreach D,SIMPLE1 SIMPLE2 EXTENDED,$(eval $(FATE_CONCAT_DEMUXER_SUITE))) -$(foreach D,$(FATE_CONCAT_DEMUXER_EXTENDED_LAVF-yes),$(eval fate-concat-demuxer-extended-lavf-$(D): ffprobe$(PROGSSUF)$(EXESUF) fate-lavf-$(D))) -$(foreach D,$(FATE_CONCAT_DEMUXER_EXTENDED_LAVF-yes),$(eval fate-concat-demuxer-extended-lavf-$(D): CMD = concat $(SRC_PATH)/tests/extended.ffconcat ../lavf/lavf.$(D) md5)) -FATE_CONCAT_DEMUXER-$(CONFIG_CONCAT_DEMUXER) += $(FATE_CONCAT_DEMUXER_EXTENDED_LAVF-yes:%=fate-concat-demuxer-extended-lavf-%) +$(foreach D,$(FATE_CONCAT_DEMUXER_SIMPLE1_LAVF),$(eval fate-concat-demuxer-simple1-lavf-$(D): fate-lavf-$(D))) +$(foreach D,$(FATE_CONCAT_DEMUXER_SIMPLE1_LAVF),$(eval fate-concat-demuxer-simple1-lavf-$(D): CMD = concat $(SRC_PATH)/tests/simple1.ffconcat ../lavf/lavf.$(D))) +FATE_CONCAT_DEMUXER += $(FATE_CONCAT_DEMUXER_SIMPLE1_LAVF:%=fate-concat-demuxer-simple1-lavf-%) -FATE-$(CONFIG_FFPROBE) += $(FATE_CONCAT_DEMUXER-yes) +$(foreach D,$(FATE_CONCAT_DEMUXER_SIMPLE2_LAVF),$(eval fate-concat-demuxer-simple2-lavf-$(D): fate-lavf-$(D))) +$(foreach D,$(FATE_CONCAT_DEMUXER_SIMPLE2_LAVF),$(eval fate-concat-demuxer-simple2-lavf-$(D): CMD = concat $(SRC_PATH)/tests/simple2.ffconcat ../lavf/lavf.$(D))) +FATE_CONCAT_DEMUXER += $(FATE_CONCAT_DEMUXER_SIMPLE2_LAVF:%=fate-concat-demuxer-simple2-lavf-%) + +$(foreach D,$(FATE_CONCAT_DEMUXER_EXTENDED_LAVF),$(eval fate-concat-demuxer-extended-lavf-$(D): fate-lavf-$(D))) +$(foreach D,$(FATE_CONCAT_DEMUXER_EXTENDED_LAVF),$(eval fate-concat-demuxer-extended-lavf-$(D): CMD = concat $(SRC_PATH)/tests/extended.ffconcat ../lavf/lavf.$(D) md5)) +FATE_CONCAT_DEMUXER += $(FATE_CONCAT_DEMUXER_EXTENDED_LAVF:%=fate-concat-demuxer-extended-lavf-%) + +FATE_CONCAT_DEMUXER := $(if $(CONFIG_CONCAT_DEMUXER), $(FATE_CONCAT_DEMUXER)) +FATE_FFPROBE += $(FATE_CONCAT_DEMUXER) diff --git a/tests/fate/cover-art.mak b/tests/fate/cover-art.mak index c2e3b1e7c..faa218274 100644 --- a/tests/fate/cover-art.mak +++ b/tests/fate/cover-art.mak @@ -37,14 +37,14 @@ FATE_COVER_ART_REMUX-$(call ALLYES, FILE_PROTOCOL FLAC_DEMUXER MJPEG_DECODER \ AIFF_DEMUXER BMP_DECODER PNG_DECODER \ FRAMECRC_MUXER PIPE_PROTOCOL) \ += fate-cover-art-aiff-id3v2-remux -fate-cover-art-aiff-id3v2-remux: CMD = transcode flac $(TARGET_SAMPLES)/cover_art/cover_art.flac aiff "-map 0 -map 0:v -map 0:v -map 0:v -c:a pcm_s16be -c:v:0 copy -filter:v:1 scale -c:v:1 png -filter:v:2 scale -c:v:2 bmp -c:v:3 copy -write_id3v2 1 -metadata:g unknown_key=unknown_value -metadata compilation=foo -metadata:s:v:0 title=first -metadata:s:v:1 title=second -metadata:s:v:1 comment=Illustration -metadata:s:v:2 title=third -metadata:s:v:2 comment=Conductor -metadata:s:v:3 title=fourth -metadata:s:v:3 comment=Composer" "-map 0 -c copy -t 0.1" "" "-show_entries format_tags:stream_tags:stream_disposition=attached_pic:stream=index,codec_name" +fate-cover-art-aiff-id3v2-remux: CMD = transcode flac $(TARGET_SAMPLES)/cover_art/cover_art.flac aiff "-map 0 -map 0:v -map 0:v -map 0:v -c:a pcm_s16be -c:v:0 copy -filter:v:1 scale -c:v:1 png -filter:v:2 scale -c:v:2 bmp -c:v:3 copy -write_id3v2 1 -metadata:g unknown_key=unknown_value -metadata compilation=foo -metadata:s:v:0 title=first -metadata:s:v:1 title=second -metadata:s:v:1 comment=Illustration -metadata:s:v:2 title=third -metadata:s:v:2 comment=Conductor -metadata:s:v:3 title=fourth -metadata:s:v:3 comment=Composer" "-map 0 -c copy -t 0.1" "-show_entries format_tags:stream_tags:stream_disposition=attached_pic:stream=index,codec_name" FATE_COVER_ART_REMUX-$(call ALLYES, FILE_PROTOCOL MP3_DEMUXER MJPEG_DECODER \ SCALE_FILTER PNG_ENCODER BMP_ENCODER \ MP3_MUXER BMP_DECODER PNG_DECODER \ FRAMECRC_MUXER PIPE_PROTOCOL) \ += fate-cover-art-mp3-id3v2-remux -fate-cover-art-mp3-id3v2-remux: CMD = transcode mp3 $(TARGET_SAMPLES)/exif/embedded_small.mp3 mp3 "-map 0 -map 0:v -map 0:v -c:a copy -filter:v:0 scale -filter:v:2 scale -c:v:0 bmp -c:v:1 copy -c:v:2 png -metadata:s:v:0 comment=Band/Orchestra" "-map 0 -c copy -t 0.1" "" "-show_entries stream_tags:stream_disposition=attached_pic:stream=index,codec_name" +fate-cover-art-mp3-id3v2-remux: CMD = transcode mp3 $(TARGET_SAMPLES)/exif/embedded_small.mp3 mp3 "-map 0 -map 0:v -map 0:v -c:a copy -filter:v:0 scale -filter:v:2 scale -c:v:0 bmp -c:v:1 copy -c:v:2 png -metadata:s:v:0 comment=Band/Orchestra" "-map 0 -c copy -t 0.1" "-show_entries stream_tags:stream_disposition=attached_pic:stream=index,codec_name" # Also covers muxing and demuxing of nonstandard channel layouts into FLAC # as well as the unorthodox multi_dim_quant option of the FLAC encoder. @@ -55,7 +55,7 @@ FATE_COVER_ART_REMUX-$(call ALLYES, FILE_PROTOCOL MOV_DEMUXER OGG_DEMUXER \ FLAC_MUXER FLAC_DEMUXER FLAC_DECODER \ FRAMECRC_MUXER PIPE_PROTOCOL) \ += fate-cover-art-flac-remux -fate-cover-art-flac-remux: CMD = transcode mov $(TARGET_SAMPLES)/lossless-audio/inside.m4a flac "-map 0 -map 1:v -map 1:v -af channelmap=channel_layout=FL+FC,aresample -c:a flac -multi_dim_quant 1 -c:v:0 copy -metadata:s:v:0 comment=Illustration -metadata:s:v:0 title=OpenMusic -filter:v:1 scale -c:v:1 png -metadata:s:v:1 title=landscape -c:v:2 copy -filter:v:3 scale -metadata:s:v:2 title=portrait -c:v:3 bmp -metadata:s:v:3 comment=Conductor -c:v:4 copy -t 0.4" "-map 0 -map 0:a -c:a:0 copy -c:v copy" "" "-show_entries format_tags:stream_tags:stream_disposition=attached_pic:stream=index,codec_name" "-f ogg -i $(TARGET_SAMPLES)/cover_art/ogg_vorbiscomment_cover.opus" +fate-cover-art-flac-remux: CMD = transcode mov $(TARGET_SAMPLES)/lossless-audio/inside.m4a flac "-map 0 -map 1:v -map 1:v -af channelmap=channel_layout=FL+FC,aresample -c:a flac -multi_dim_quant 1 -c:v:0 copy -metadata:s:v:0 comment=Illustration -metadata:s:v:0 title=OpenMusic -filter:v:1 scale -c:v:1 png -metadata:s:v:1 title=landscape -c:v:2 copy -filter:v:3 scale -metadata:s:v:2 title=portrait -c:v:3 bmp -metadata:s:v:3 comment=Conductor -c:v:4 copy -t 0.4" "-map 0 -map 0:a -c:a:0 copy -c:v copy" "-show_entries format_tags:stream_tags:stream_disposition=attached_pic:stream=index,codec_name" "-f ogg -i $(TARGET_SAMPLES)/cover_art/ogg_vorbiscomment_cover.opus" FCA_TEMP-$(call ALLYES, RAWVIDEO_MUXER FILE_PROTOCOL) = $(FATE_COVER_ART-yes) FATE_COVER_ART = $(FCA_TEMP-yes) diff --git a/tests/fate/dca.mak b/tests/fate/dca.mak index 5168c1bc7..2b8f83497 100644 --- a/tests/fate/dca.mak +++ b/tests/fate/dca.mak @@ -22,7 +22,7 @@ DCADEC_SUITE_LOSSY = core_51_24_48_768_0 \ xxch_71_24_48_2046 \ define FATE_DCADEC_LOSSLESS_SUITE -FATE_DCADEC_LOSSLESS += fate-dca-$(1) fate-dca-$(1)-dmix_2 fate-dca-$(1)-dmix_6 +FATE_DCADEC_LOSSLESS_$(2) += fate-dca-$(1) fate-dca-$(1)-dmix_2 fate-dca-$(1)-dmix_6 fate-dca-$(1): CMD = framemd5 -i $(TARGET_SAMPLES)/dts/dcadec-suite/$(1).dtshd -c:a pcm_$(2) -af aresample fate-dca-$(1)-dmix_2: CMD = framemd5 -request_channel_layout 0x3 -i $(TARGET_SAMPLES)/dts/dcadec-suite/$(1).dtshd -c:a pcm_$(2) -af aresample fate-dca-$(1)-dmix_6: CMD = framemd5 -request_channel_layout 0x60f -i $(TARGET_SAMPLES)/dts/dcadec-suite/$(1).dtshd -c:a pcm_$(2) -af aresample @@ -61,22 +61,24 @@ $(FATE_DCADEC_LOSSY): CMP = oneoff $(FATE_DCADEC_LOSSY): CMP_UNIT = f32 $(FATE_DCADEC_LOSSY): FUZZ = 9 -FATE_DCA-$(call DEMDEC, DTSHD, DCA) += $(FATE_DCADEC_LOSSLESS) $(FATE_DCADEC_LOSSY) +FATE_DCA-$(call FRAMEMD5, DTSHD, DCA, ARESAMPLE_FILTER PCM_S16LE_ENCODER) += $(FATE_DCADEC_LOSSLESS_s16le) +FATE_DCA-$(call FRAMEMD5, DTSHD, DCA, ARESAMPLE_FILTER PCM_S24LE_ENCODER) += $(FATE_DCADEC_LOSSLESS_s24le) +FATE_DCA-$(call FILTERDEMDECENCMUX, ARESAMPLE, DTSHD, DCA, PCM_F32LE, PCM_F32LE, PIPE_PROTOCOL) += $(FATE_DCADEC_LOSSY) -FATE_DCA-$(call DEMDEC, MPEGTS, DCA) += fate-dca-core +FATE_DCA-$(call PCM, MPEGTS, DCA, DTS_DEMUXER ARESAMPLE_FILTER) += fate-dca-core fate-dca-core: CMD = pcm -i $(TARGET_SAMPLES)/dts/dts.ts fate-dca-core: CMP = oneoff fate-dca-core: REF = $(SAMPLES)/dts/dts.pcm -FATE_DCA-$(call DEMDEC, DTS, DCA) += fate-dca-xll +FATE_DCA-$(call DEMDEC, DTS, DCA, ARESAMPLE_FILTER PCM_S24LE_ENCODER PCM_S24LE_MUXER) += fate-dca-xll fate-dca-xll: CMD = md5 -i $(TARGET_SAMPLES)/dts/master_audio_7.1_24bit.dts -f s24le -af aresample -FATE_DCA-$(call DEMDEC, DTS, DCA) += fate-dts_es +FATE_DCA-$(call PCM, DTS, DCA, ARESAMPLE_FILTER) += fate-dts_es 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-$(call DEMMUX, DTS, DTS, DCA_CORE_BSF MD5_PROTOCOL) += 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 diff --git a/tests/fate/dfa.mak b/tests/fate/dfa.mak index 5b725e3a9..682a9d10b 100644 --- a/tests/fate/dfa.mak +++ b/tests/fate/dfa.mak @@ -31,7 +31,7 @@ fate-dfa10: CMD = framecrc -i $(TARGET_SAMPLES)/chronomaster-dfa/0009.dfa -pix_f FATE_DFA += fate-dfa11 fate-dfa11: CMD = framecrc -i $(TARGET_SAMPLES)/chronomaster-dfa/0010.dfa -pix_fmt rgb24 -vf scale -FATE_DFA-$(call DEMDEC, DFA, DFA) += $(FATE_DFA) +FATE_DFA-$(call FRAMECRC, DFA, DFA, SCALE_FILTER) += $(FATE_DFA) FATE_SAMPLES_AVCONV += $(FATE_DFA-yes) fate-dfa: $(FATE_DFA-yes) diff --git a/tests/fate/dnxhd.mak b/tests/fate/dnxhd.mak index 59f3f90e9..f261766b5 100644 --- a/tests/fate/dnxhd.mak +++ b/tests/fate/dnxhd.mak @@ -1,15 +1,18 @@ -FATE_DNXHD = fate-dnxhd-mbaff \ - fate-dnxhr-444 \ - fate-dnxhr-12bit \ - fate-dnxhr-parse \ +FATE_DNXHD = fate-dnxhr-parse \ fate-dnxhr-prefix1 \ fate-dnxhr-prefix2 \ fate-dnxhr-prefix3 \ fate-dnxhr-prefix4 \ fate-dnxhr-prefix5 -FATE_SAMPLES_AVCONV-$(call DEMDEC, MOV, DNXHD) += $(FATE_DNXHD) -fate-dnxhd: $(FATE_DNXHD) $(FATE_VCODEC_DNXHD) +FATE_DNXHD_SCALE := fate-dnxhd-mbaff \ + fate-dnxhr-444 \ + fate-dnxhr-12bit \ + +FATE_DNXHD-$(call FRAMECRC, MOV, DNXHD) += $(FATE_DNXHD) +FATE_DNXHD-$(call FRAMECRC, MOV, DNXHD, SCALE_FILTER) += $(FATE_DNXHD_SCALE) +FATE_SAMPLES_FFMPEG += $(FATE_DNXHD-yes) +fate-dnxhd: $(FATE_DNXHD-yes) $(FATE_VCODEC_DNXHD) fate-dnxhd-mbaff: CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/dnxhd/dnxhd100_cid1260.mov -pix_fmt yuv422p10le -vf scale fate-dnxhr-444: CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/dnxhd/dnxhr444_cid1270.mov -pix_fmt yuv444p10le -vf scale diff --git a/tests/fate/dvvideo.mak b/tests/fate/dvvideo.mak new file mode 100644 index 000000000..24e50ca35 --- /dev/null +++ b/tests/fate/dvvideo.mak @@ -0,0 +1,8 @@ + +fate-bsf-dv-error-marker: CMD = md5 -i $(TARGET_SAMPLES)/dv/dvcprohd_720p50.mov -flags +bitexact -fflags +bitexact -c:v copy -bsf noise=100,dv_error_marker=color=blue -f avi +fate-bsf-dv-error-marker: CMP = oneline +fate-bsf-dv-error-marker: REF = 4e884d3e8045299d0d45ec920fa58a44 +FATE_DVVIDEO-$(call ALLYES, MOV_DEMUXER DV_ERROR_MARKER_BSF NOISE_BSF AVI_MUXER) += fate-bsf-dv-error-marker + +FATE_SAMPLES_FFMPEG += $(FATE_DVVIDEO-yes) +fate-dvvideo: $(FATE_DVVIDEO-yes) diff --git a/tests/fate/ea.mak b/tests/fate/ea.mak index 7667102ce..2d1ac6e50 100644 --- a/tests/fate/ea.mak +++ b/tests/fate/ea.mak @@ -1,25 +1,23 @@ -FATE_SAMPLES_EA-$(call DEMDEC, EA_CDATA, ADPCM_EA_XAS) += fate-ea-cdata +FATE_SAMPLES_EA-$(call ENCDEC, PCM_S16LE ADPCM_EA_XAS, PCM_S16LE EA_CDATA, ARESAMPLE_FILTER) += fate-ea-cdata fate-ea-cdata: CMD = md5 -i $(TARGET_SAMPLES)/ea-cdata/166b084d.46410f77.0009b440.24be960c.cdata -f s16le -af aresample -FATE_SAMPLES_EA-$(call DEMDEC, EA, EACMV) += fate-ea-cmv +FATE_SAMPLES_EA-$(call FRAMECRC, EA, EACMV, SCALE_FILTER) += fate-ea-cmv fate-ea-cmv: CMD = framecrc -i $(TARGET_SAMPLES)/ea-cmv/TITLE.CMV -pix_fmt rgb24 -vf scale -FATE_SAMPLES_EA-$(call DEMDEC, EA, EAMAD) += fate-ea-mad +FATE_SAMPLES_EA-$(call FRAMECRC, EA, EAMAD) += fate-ea-mad fate-ea-mad: CMD = framecrc -i $(TARGET_SAMPLES)/ea-mad/NFS6LogoE.mad -an -FATE_SAMPLES_EA-$(call DEMDEC, EA, EATGQ) += fate-ea-tgq +FATE_SAMPLES_EA-$(call FRAMECRC, EA, EATGQ) += fate-ea-tgq fate-ea-tgq: CMD = framecrc -i $(TARGET_SAMPLES)/ea-tgq/v27.tgq -an -FATE_EA_TGV += fate-ea-tgv-1 +FATE_EA_TGV-$(call FRAMECRC, EA, EATGV, SCALE_FILTER) += fate-ea-tgv-1 fate-ea-tgv-2 fate-ea-tgv-1: CMD = framecrc -i $(TARGET_SAMPLES)/ea-tgv/INTRO8K-partial.TGV -pix_fmt rgb24 -an -vf scale - -FATE_EA_TGV += fate-ea-tgv-2 fate-ea-tgv-2: CMD = framecrc -i $(TARGET_SAMPLES)/ea-tgv/INTEL_S.TGV -pix_fmt rgb24 -an -vf scale -FATE_SAMPLES_EA-$(call DEMDEC, EA, EATGV) += $(FATE_EA_TGV) -fate-ea-tgv: $(FATE_EA_TGV) +FATE_SAMPLES_EA-yes += $(FATE_EA_TGV-yes) +fate-ea-tgv: $(FATE_EA_TGV-yes) -FATE_SAMPLES_EA-$(call DEMDEC, EA, EATQI) += fate-ea-tqi +FATE_SAMPLES_EA-$(call FRAMECRC, EA, EATQI) += fate-ea-tqi fate-ea-tqi: CMD = framecrc -i $(TARGET_SAMPLES)/ea-wve/networkBackbone-partial.wve -frames:v 26 -an FATE_SAMPLES_FFMPEG += $(FATE_SAMPLES_EA-yes) diff --git a/tests/fate/ffmpeg.mak b/tests/fate/ffmpeg.mak index b80467d02..94f50423b 100644 --- a/tests/fate/ffmpeg.mak +++ b/tests/fate/ffmpeg.mak @@ -1,20 +1,20 @@ -FATE_MAPCHAN-$(CONFIG_CHANNELMAP_FILTER) += fate-mapchan-6ch-extract-2 +FATE_MAPCHAN-$(call FILTERDEMDECENCMUX, PAN, WAV, PCM_S16LE, PCM_S16LE, WAV, MD5_PROTOCOL) += fate-mapchan-6ch-extract-2 fate-mapchan-6ch-extract-2: tests/data/asynth-22050-6.wav fate-mapchan-6ch-extract-2: CMD = ffmpeg -i $(TARGET_PATH)/tests/data/asynth-22050-6.wav -map_channel 0.0.0 -fflags +bitexact -f wav md5: -map_channel 0.0.1 -fflags +bitexact -f wav md5: -FATE_MAPCHAN-$(CONFIG_CHANNELMAP_FILTER) += fate-mapchan-6ch-extract-2-downmix-mono +FATE_MAPCHAN-$(call FILTERDEMDECENCMUX, PAN ARESAMPLE, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-mapchan-6ch-extract-2-downmix-mono fate-mapchan-6ch-extract-2-downmix-mono: tests/data/asynth-22050-6.wav fate-mapchan-6ch-extract-2-downmix-mono: CMD = md5 -auto_conversion_filters -i $(TARGET_PATH)/tests/data/asynth-22050-6.wav -map_channel 0.0.1 -map_channel 0.0.0 -ac 1 -fflags +bitexact -f wav -FATE_MAPCHAN-$(CONFIG_CHANNELMAP_FILTER) += fate-mapchan-silent-mono +FATE_MAPCHAN-$(call FILTERDEMDECENCMUX, PAN, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-mapchan-silent-mono fate-mapchan-silent-mono: tests/data/asynth-22050-1.wav fate-mapchan-silent-mono: CMD = md5 -i $(TARGET_PATH)/tests/data/asynth-22050-1.wav -map_channel -1 -map_channel 0.0.0 -fflags +bitexact -f wav -FATE_MAPCHAN-$(CONFIG_CHANNELMAP_FILTER) += fate-mapchan-2ch-extract-ch0-ch2-trailing +FATE_MAPCHAN-$(call FILTERDEMDECENCMUX, PAN, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-mapchan-2ch-extract-ch0-ch2-trailing fate-mapchan-2ch-extract-ch0-ch2-trailing: tests/data/asynth-44100-2.wav fate-mapchan-2ch-extract-ch0-ch2-trailing: CMD = md5 -i $(TARGET_PATH)/tests/data/asynth-44100-2.wav -map_channel 0.0.0 -map_channel 0.0.2? -fflags +bitexact -f wav -FATE_MAPCHAN-$(CONFIG_CHANNELMAP_FILTER) += fate-mapchan-3ch-extract-ch0-ch2-trailing +FATE_MAPCHAN-$(call FILTERDEMDECENCMUX, PAN, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-mapchan-3ch-extract-ch0-ch2-trailing fate-mapchan-3ch-extract-ch0-ch2-trailing: tests/data/asynth-44100-3.wav fate-mapchan-3ch-extract-ch0-ch2-trailing: CMD = md5 -i $(TARGET_PATH)/tests/data/asynth-44100-3.wav -map_channel 0.0.0 -map_channel 0.0.2? -fflags +bitexact -f wav @@ -23,32 +23,38 @@ FATE_MAPCHAN = $(FATE_MAPCHAN-yes) FATE_FFMPEG += $(FATE_MAPCHAN) fate-mapchan: $(FATE_MAPCHAN) -FATE_FFMPEG-$(CONFIG_COLOR_FILTER) += fate-ffmpeg-filter_complex +FATE_FFMPEG-$(call FILTERFRAMECRC, COLOR) += 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-$(call FILTERFRAMECRC, AEVALSRC ASETNSAMPLES ARESAMPLE, AC3_FIXED_ENCODER) += fate-ffmpeg-filter_complex_audio fate-ffmpeg-filter_complex_audio: CMD = framecrc -auto_conversion_filters -filter_complex "aevalsrc=0:d=0.1,asetnsamples=1537" -c ac3_fixed # 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 -threads 1 -max_muxing_queue_size 16 -af aresample +FATE_SAMPLES_FFMPEG-$(call FRAMECRC, MOV, PNG ALAC, ARESAMPLE_FILTER) += fate-ffmpeg-attached_pics +fate-ffmpeg-attached_pics: CMD = threads=2 framecrc -i $(TARGET_SAMPLES)/lossless-audio/inside.m4a -threads 1 -max_muxing_queue_size 16 -af aresample -FATE_SAMPLES_FFMPEG-$(CONFIG_COLORKEY_FILTER) += fate-ffmpeg-filter_colorkey +FATE_SAMPLES_FFMPEG-$(call FILTERDEMDEC, COLORKEY OVERLAY SCALE, MPEGPS IMAGE_PPM_PIPE, CAVS PPM, CAVSVIDEO_PARSER) += fate-ffmpeg-filter_colorkey fate-ffmpeg-filter_colorkey: tests/data/filtergraphs/colorkey fate-ffmpeg-filter_colorkey: CMD = framecrc -auto_conversion_filters -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 -FATE_FFMPEG-$(CONFIG_COLOR_FILTER) += fate-ffmpeg-lavfi +FATE_FFMPEG-$(call FILTERFRAMECRC, COLOR) += fate-ffmpeg-lavfi fate-ffmpeg-lavfi: CMD = framecrc -lavfi color=d=1:r=5 -fflags +bitexact -FATE_SAMPLES_FFMPEG-$(CONFIG_RAWVIDEO_DEMUXER) += fate-force_key_frames +FATE_SAMPLES_FFMPEG-$(call ENCDEC2, MPEG4, RAWVIDEO, AVI, RAWVIDEO_DEMUXER FRAMECRC_MUXER) += fate-force_key_frames fate-force_key_frames: tests/data/vsynth_lena.yuv fate-force_key_frames: CMD = enc_dec \ "rawvideo -s 352x288 -pix_fmt yuv420p" tests/data/vsynth_lena.yuv \ avi "-c mpeg4 -g 240 -qscale 10 -force_key_frames 0.5,0:00:01.5" \ - framecrc "" "" "-skip_frame nokey" + framecrc "" "-skip_frame nokey" -FATE_SAMPLES_FFMPEG-$(call ALLYES, VOBSUB_DEMUXER DVDSUB_DECODER AVFILTER OVERLAY_FILTER DVDSUB_ENCODER) += fate-sub2video +# Tests that the video is properly autorotated using the contained +# display matrix and that the generated file does not contain +# a display matrix any more. +FATE_SAMPLES_FFMPEG_FFPROBE-$(call TRANSCODE, MPEG2VIDEO, MOV, H264_DECODER AAC_FIXED_DECODER AC3_FIXED_ENCODER EXTRACT_EXTRADATA_BSF) += fate-autorotate +fate-autorotate: CMD = transcode "mov -c:a aac_fixed" $(TARGET_SAMPLES)/filter/sample-in-issue-505.mov mov "-c:v mpeg2video -c:a ac3_fixed" "-c copy -t 0.5" "-show_entries stream_side_data_list" + +FATE_SAMPLES_FFMPEG-$(call FILTERDEMDEC, OVERLAY SCALE, RAWVIDEO VOBSUB, RAWVIDEO DVDSUB, DVDSUB_ENCODER) += fate-sub2video fate-sub2video: tests/data/vsynth_lena.yuv fate-sub2video: CMD = framecrc -auto_conversion_filters \ -f rawvideo -r 5 -s 352x288 -pix_fmt yuv420p -i $(TARGET_PATH)/tests/data/vsynth_lena.yuv \ @@ -58,7 +64,7 @@ fate-sub2video: CMD = framecrc -auto_conversion_filters \ # Very basic sub2video example, decode and convert to AVFrame with sub2video. # Attempt to not touch timestamps. -FATE_SAMPLES_FFMPEG-$(call ALLYES, VOBSUB_DEMUXER DVDSUB_DECODER AVFILTER) += fate-sub2video_basic +FATE_SAMPLES_FFMPEG-$(call FRAMECRC, VOBSUB, DVDSUB, SCALE_FILTER) += fate-sub2video_basic fate-sub2video_basic: CMD = framecrc -auto_conversion_filters \ -i $(TARGET_SAMPLES)/sub/vobsub.idx \ -vsync passthrough -copyts \ @@ -67,7 +73,7 @@ fate-sub2video_basic: CMD = framecrc -auto_conversion_filters \ # Time-limited run with a sample that doesn't require seeking and # contains samples within the initial period. -FATE_SAMPLES_FFMPEG-$(call ALLYES, SUP_DEMUXER PGSSUB_DECODER AVFILTER) += fate-sub2video_time_limited +FATE_SAMPLES_FFMPEG-$(call FRAMECRC, SUP, PGSSUB, SCALE_FILTER RAWVIDEO_ENCODER) += fate-sub2video_time_limited fate-sub2video_time_limited: CMD = framecrc -auto_conversion_filters \ -i $(TARGET_SAMPLES)/sub/pgs_sub.sup \ -vsync passthrough -copyts \ @@ -75,67 +81,70 @@ fate-sub2video_time_limited: CMD = framecrc -auto_conversion_filters \ -filter_complex "sws_flags=+accurate_rnd+bitexact\;[0:s:0]scale" \ -c:v rawvideo -threads 1 -FATE_FFMPEG-$(call ALLYES, PCM_S16LE_DEMUXER PCM_S16LE_MUXER PCM_S16LE_DECODER PCM_S16LE_ENCODER) += fate-unknown_layout-pcm +FATE_FFMPEG-$(call ENCDEC, PCM_S16LE, PCM_S16LE) += fate-unknown_layout-pcm fate-unknown_layout-pcm: $(AREF) fate-unknown_layout-pcm: CMD = md5 \ -guess_layout_max 0 -f s16le -ac 1 -ar 44100 -i $(TARGET_PATH)/$(AREF) -f s16le -FATE_FFMPEG-$(call ALLYES, PCM_S16LE_DEMUXER AC3_MUXER PCM_S16LE_DECODER AC3_FIXED_ENCODER) += fate-unknown_layout-ac3 +FATE_FFMPEG-$(call FILTERDEMDECENCMUX, ARESAMPLE, PCM_S32LE, PCM_S32LE, AC3_FIXED, AC3) += fate-unknown_layout-ac3 fate-unknown_layout-ac3: $(AREF) fate-unknown_layout-ac3: CMD = md5 -auto_conversion_filters \ -guess_layout_max 0 -f s32le -ac 1 -ar 44100 -i $(TARGET_PATH)/$(AREF) \ -f ac3 -flags +bitexact -c ac3_fixed -FATE_SAMPLES_FFMPEG-$(call ALLYES, FILE_PROTOCOL LAVFI_INDEV RAWVIDEO_DEMUXER \ - SINE_FILTER PCM_S16LE_DECODER RAWVIDEO_DECODER \ - ARESAMPLE_FILTER AMIX_FILTER MPEG4_ENCODER \ - AC3_FIXED_ENCODER FRAMECRC_MUXER PIPE_PROTOCOL) \ +FATE_SAMPLES_FFMPEG-$(call FILTERDEMDEC, AMIX ARESAMPLE SINE, RAWVIDEO, \ + PCM_S16LE RAWVIDEO, LAVFI_INDEV \ + MPEG4_ENCODER AC3_FIXED_ENCODER) \ += fate-shortest fate-shortest: tests/data/vsynth_lena.yuv fate-shortest: CMD = framecrc -auto_conversion_filters -f lavfi -i "sine=3000:d=10" -f lavfi -i "sine=1000:d=1" -sws_flags +accurate_rnd+bitexact -fflags +bitexact -flags +bitexact -idct simple -f rawvideo -s 352x288 -pix_fmt yuv420p -i $(TARGET_PATH)/tests/data/vsynth_lena.yuv -filter_complex "[0:a:0][1:a:0]amix=inputs=2[audio]" -map 2:v:0 -map "[audio]" -sws_flags +accurate_rnd+bitexact -fflags +bitexact -flags +bitexact -idct simple -dct fastint -qscale 10 -threads 1 -c:v mpeg4 -c:a ac3_fixed -shortest -FATE_STREAMCOPY-$(call ALLYES, EAC3_DEMUXER MOV_MUXER) += fate-copy-trac3074 -fate-copy-trac3074: $(SAMPLES)/eac3/csi_miami_stereo_128_spx.eac3 +# Basic test for fix_sub_duration, which calculates duration based on the +# following subtitle's pts. +FATE_SAMPLES_FFMPEG-$(call FILTERDEMDECENCMUX, MOVIE, MPEGVIDEO, \ + MPEG2VIDEO, SUBRIP, SRT, LAVFI_INDEV \ + MPEGVIDEO_PARSER CCAPTION_DECODER PIPE_PROTOCOL) \ + += fate-ffmpeg-fix_sub_duration +fate-ffmpeg-fix_sub_duration: CMD = fmtstdout srt -fix_sub_duration \ + -real_time 1 -f lavfi \ + -i "movie=$(TARGET_SAMPLES)/sub/Closedcaption_rollup.m2v[out0+subcc]" + +FATE_STREAMCOPY-$(call REMUX, MP4 MOV, EAC3_DEMUXER) += fate-copy-trac3074 fate-copy-trac3074: CMD = transcode eac3 $(TARGET_SAMPLES)/eac3/csi_miami_stereo_128_spx.eac3\ mp4 "-codec copy -map 0" "-codec copy" -FATE_STREAMCOPY-$(call ALLYES, MOV_DEMUXER MOV_MUXER) += fate-copy-trac236 -fate-copy-trac236: $(SAMPLES)/mov/fcp_export8-236.mov +FATE_STREAMCOPY-$(call TRANSCODE, RAWVIDEO DVVIDEO, MOV, PCM_S16LE_DECODER) += fate-copy-trac236 fate-copy-trac236: CMD = transcode mov $(TARGET_SAMPLES)/mov/fcp_export8-236.mov\ mov "-codec copy -map 0" -FATE_STREAMCOPY-$(call ALLYES, MPEGTS_DEMUXER MXF_MUXER PCM_S16LE_ENCODER) += fate-copy-trac4914 -fate-copy-trac4914: $(SAMPLES)/mpeg2/xdcam8mp2-1s_small.ts +FATE_STREAMCOPY-$(call TRANSCODE, RAWVIDEO MPEG2VIDEO, MXF, MPEGTS_DEMUXER MPEGVIDEO_PARSER MPEGAUDIO_PARSER MP2_DECODER ARESAMPLE_FILTER PCM_S16LE_DECODER) += fate-copy-trac4914 fate-copy-trac4914: CMD = transcode mpegts $(TARGET_SAMPLES)/mpeg2/xdcam8mp2-1s_small.ts\ mxf "-c:a pcm_s16le -af aresample -c:v copy" -FATE_STREAMCOPY-$(call ALLYES, MPEGTS_DEMUXER AVI_MUXER) += fate-copy-trac4914-avi -fate-copy-trac4914-avi: $(SAMPLES)/mpeg2/xdcam8mp2-1s_small.ts +FATE_STREAMCOPY-$(call TRANSCODE, RAWVIDEO MPEG2VIDEO, AVI, MPEGTS_DEMUXER MPEGVIDEO_PARSER MPEGAUDIO_PARSER EXTRACT_EXTRADATA_BSF MP2_DECODER ARESAMPLE_FILTER) += fate-copy-trac4914-avi fate-copy-trac4914-avi: CMD = transcode mpegts $(TARGET_SAMPLES)/mpeg2/xdcam8mp2-1s_small.ts\ avi "-c:a copy -c:v copy" "-af aresample" -FATE_STREAMCOPY-$(call ALLYES, H264_DEMUXER AVI_MUXER) += fate-copy-trac2211-avi -fate-copy-trac2211-avi: $(SAMPLES)/h264/bbc2.sample.h264 +FATE_STREAMCOPY-$(call TRANSCODE, RAWVIDEO H264, AVI, H264_DEMUXER H264_PARSER EXTRACT_EXTRADATA_BSF) += fate-copy-trac2211-avi fate-copy-trac2211-avi: CMD = transcode "h264 -r 14" $(TARGET_SAMPLES)/h264/bbc2.sample.h264\ - avi "-c:a copy -c:v copy" + avi "-c:v copy" -FATE_STREAMCOPY-$(call ENCDEC, APNG, APNG) += fate-copy-apng +ifneq (,$(filter fate-lavf-apng,$(FATE_LAVF_VIDEO))) +FATE_STREAMCOPY-$(call TRANSCODE, RAWVIDEO APNG, APNG) += fate-copy-apng +endif fate-copy-apng: fate-lavf-apng +fate-lavf-apng: KEEP_FILES ?= 1 fate-copy-apng: CMD = transcode apng tests/data/lavf/lavf.apng apng "-c:v copy" FATE_STREAMCOPY-$(call DEMMUX, OGG, OGG) += fate-limited_input_seek fate-limited_input_seek-copyts -fate-limited_input_seek: $(SAMPLES)/vorbis/moog_small.ogg fate-limited_input_seek: CMD = md5 -ss 1.5 -t 1.3 -i $(TARGET_SAMPLES)/vorbis/moog_small.ogg -c:a copy -fflags +bitexact -f ogg -fate-limited_input_seek-copyts: $(SAMPLES)/vorbis/moog_small.ogg fate-limited_input_seek-copyts: CMD = md5 -ss 1.5 -t 1.3 -i $(TARGET_SAMPLES)/vorbis/moog_small.ogg -c:a copy -copyts -fflags +bitexact -f ogg -FATE_STREAMCOPY-$(call ALLYES, MOV_DEMUXER MOV_MUXER) += fate-copy-psp -fate-copy-psp: $(SAMPLES)/h264/wwwq_cut.mp4 +FATE_STREAMCOPY-$(call REMUX, PSP MOV, H264_PARSER H264_DECODER) += fate-copy-psp fate-copy-psp: CMD = transcode "mov" $(TARGET_SAMPLES)/h264/wwwq_cut.mp4\ psp "-c copy" "-codec copy" -FATE_STREAMCOPY-$(CONFIG_FLV_DEMUXER) += fate-ffmpeg-streamloop -fate-ffmpeg-streamloop: $(SAMPLES)/flv/streamloop.flv +FATE_STREAMCOPY-$(call FRAMEMD5, FLV, H264) += fate-ffmpeg-streamloop fate-ffmpeg-streamloop: CMD = framemd5 -stream_loop 2 -i $(TARGET_SAMPLES)/flv/streamloop.flv -c copy tests/data/audio_shorter_than_video.nut: TAG = GEN @@ -147,63 +156,48 @@ tests/data/audio_shorter_than_video.nut: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data -sws_flags +accurate_rnd+bitexact -fflags +bitexact -flags +bitexact -idct simple -dct fastint -qscale 10 -c:v mpeg4 -threads 1 -c:a pcm_s16le -bitexact \ -y $(TARGET_PATH)/tests/data/audio_shorter_than_video.nut 2>/dev/null -FATE_STREAMCOPY-$(call ALLYES, FILE_PROTOCOL RAWVIDEO_DEMUXER LAVFI_INDEV \ - RAWVIDEO_DECODER PCM_S16LE_DECODER MPEG4_ENCODER \ - PCM_S16LE_ENCODER SINE_FILTER NUT_DEMUXER \ - MPEG4_DECODER ARESAMPLE_FILTER AMIX_FILTER \ - NUT_MUXER AC3_FIXED_ENCODER PIPE_PROTOCOL) \ - += fate-copy-shortest1 -fate-copy-shortest1: tests/data/audio_shorter_than_video.nut +FATE_STREAMCOPY-$(call FRAMEMD5, NUT, RAWVIDEO PCM_S16LE MPEG4, \ + RAWVIDEO_DEMUXER LAVFI_INDEV \ + MPEG4_ENCODER PCM_S16LE_ENCODER \ + SINE_FILTER ARESAMPLE_FILTER AMIX_FILTER \ + NUT_MUXER AC3_FIXED_ENCODER) \ + += fate-copy-shortest1 fate-copy-shortest2 +fate-copy-shortest1 fate-copy-shortest2: tests/data/audio_shorter_than_video.nut fate-copy-shortest1: CMD = framemd5 -auto_conversion_filters -fflags +bitexact -flags +bitexact -f lavfi -i "sine=3000:d=10" -f lavfi -i "sine=1000:d=1" -i $(TARGET_PATH)/tests/data/audio_shorter_than_video.nut -filter_complex "[0:a:0][1:a:0]amix=inputs=2[audio]" -map 2:v:0 -map "[audio]" -fflags +bitexact -flags +bitexact -c:v copy -c:a ac3_fixed -shortest - -FATE_STREAMCOPY-$(call ALLYES, FILE_PROTOCOL RAWVIDEO_DEMUXER LAVFI_INDEV \ - RAWVIDEO_DECODER PCM_S16LE_DECODER MPEG4_ENCODER \ - PCM_S16LE_ENCODER SINE_FILTER NUT_DEMUXER \ - MPEG4_DECODER ARESAMPLE_FILTER AMIX_FILTER \ - NUT_MUXER AC3_FIXED_ENCODER PIPE_PROTOCOL) \ - += fate-copy-shortest2 -fate-copy-shortest2: tests/data/audio_shorter_than_video.nut fate-copy-shortest2: CMD = framemd5 -auto_conversion_filters -fflags +bitexact -flags +bitexact -f lavfi -i "sine=3000:d=10" -i $(TARGET_PATH)/tests/data/audio_shorter_than_video.nut -filter_complex "[0:a:0][1:a:0]amix=inputs=2[audio]" -map 1:v:0 -map "[audio]" -fflags +bitexact -flags +bitexact -c:v copy -c:a ac3_fixed -shortest fate-streamcopy: $(FATE_STREAMCOPY-yes) -FATE_SAMPLES_FFMPEG-$(call ALLYES, MOV_DEMUXER MATROSKA_MUXER) += fate-rgb24-mkv -fate-rgb24-mkv: $(SAMPLES)/qtrle/aletrek-rle.mov +FATE_SAMPLES_FFMPEG-$(call TRANSCODE, RAWVIDEO, MATROSKA, MOV_DEMUXER QTRLE_DECODER) += fate-rgb24-mkv fate-rgb24-mkv: CMD = transcode "mov" $(TARGET_SAMPLES)/qtrle/aletrek-rle.mov\ matroska "-c:v rawvideo -threads 1 -pix_fmt rgb24 -allow_raw_vfw 1 -frames:v 1" -FATE_SAMPLES_FFMPEG-$(call ALLYES, AAC_DEMUXER MOV_MUXER) += fate-adtstoasc_ticket3715 -fate-adtstoasc_ticket3715: $(SAMPLES)/aac/foo.aac +FATE_SAMPLES_FFMPEG-$(call REMUX, MOV, AAC_DEMUXER AAC_DECODER AAC_PARSER AAC_ADTSTOASC_BSF) += fate-adtstoasc_ticket3715 fate-adtstoasc_ticket3715: CMD = transcode "aac" $(TARGET_SAMPLES)/aac/foo.aac\ mov "-c copy -bsf:a aac_adtstoasc" "-codec copy" -FATE_SAMPLES_FFMPEG-$(call ALLYES, MOV_DEMUXER H264_MUXER H264_MP4TOANNEXB_BSF) += fate-h264_mp4toannexb_ticket2991 -fate-h264_mp4toannexb_ticket2991: $(SAMPLES)/h264/wwwq_cut.mp4 +FATE_SAMPLES_FFMPEG-$(call REMUX, H264, MOV_DEMUXER H264_MP4TOANNEXB_BSF H264_PARSER H264_DECODER EXTRACT_EXTRADATA_BSF) += fate-h264_mp4toannexb_ticket2991 fate-h264_mp4toannexb_ticket5927 fate-h264_mp4toannexb_ticket5927_2 fate-h264_mp4toannexb_ticket2991: CMD = transcode "mp4" $(TARGET_SAMPLES)/h264/wwwq_cut.mp4\ h264 "-c:v copy -bsf:v h264_mp4toannexb" "-codec copy" - -FATE_SAMPLES_FFMPEG-$(call ALLYES, MOV_DEMUXER H264_MUXER H264_MP4TOANNEXB_BSF) += fate-h264_mp4toannexb_ticket5927 fate-h264_mp4toannexb_ticket5927_2 fate-h264_mp4toannexb_ticket5927: CMD = transcode "mp4" $(TARGET_SAMPLES)/h264/thezerotheorem-cut.mp4 \ h264 "-c:v copy -bsf:v h264_mp4toannexb -an" "-c:v copy" fate-h264_mp4toannexb_ticket5927_2: CMD = transcode "mp4" $(TARGET_SAMPLES)/h264/thezerotheorem-cut.mp4 \ h264 "-c:v copy -an" "-c:v copy" -FATE_SAMPLES_FFMPEG-$(call ALLYES, MPEGPS_DEMUXER AVI_MUXER REMOVE_EXTRADATA_BSF) += fate-ffmpeg-bsf-remove-k fate-ffmpeg-bsf-remove-r fate-ffmpeg-bsf-remove-e -fate-ffmpeg-bsf-remove-k: $(SAMPLES)/mpeg2/matrixbench_mpeg2.lq1.mpg +FATE_SAMPLES_FFMPEG-$(call TRANSCODE, MPEG4 MPEG2VIDEO, AVI, MPEGPS_DEMUXER MPEGVIDEO_DEMUXER MPEGVIDEO_PARSER EXTRACT_EXTRADATA_BSF REMOVE_EXTRADATA_BSF) += fate-ffmpeg-bsf-remove-k fate-ffmpeg-bsf-remove-r fate-ffmpeg-bsf-remove-e fate-ffmpeg-bsf-remove-k: CMD = transcode "mpeg" $(TARGET_SAMPLES)/mpeg2/matrixbench_mpeg2.lq1.mpg\ avi "-vbsf remove_extra=k" "-codec copy" -fate-ffmpeg-bsf-remove-r: $(SAMPLES)/mpeg2/matrixbench_mpeg2.lq1.mpg fate-ffmpeg-bsf-remove-r: CMD = transcode "mpeg" $(TARGET_SAMPLES)/mpeg2/matrixbench_mpeg2.lq1.mpg\ avi "-vbsf remove_extra=keyframe" "-codec copy" -fate-ffmpeg-bsf-remove-e: $(SAMPLES)/mpeg2/matrixbench_mpeg2.lq1.mpg fate-ffmpeg-bsf-remove-e: CMD = transcode "mpeg" $(TARGET_SAMPLES)/mpeg2/matrixbench_mpeg2.lq1.mpg\ avi "-vbsf remove_extra=e" "-codec copy" +FATE_SAMPLES_FFMPEG-$(call DEMMUX, APNG, FRAMECRC, SETTS_BSF PIPE_PROTOCOL) += fate-ffmpeg-setts-bsf +fate-ffmpeg-setts-bsf: CMD = framecrc -i $(TARGET_SAMPLES)/apng/clock.png -c:v copy -bsf:v "setts=duration=if(eq(NEXT_PTS\,NOPTS)\,PREV_OUTDURATION\,(NEXT_PTS-PTS)/2):ts=PTS/2" -fflags +bitexact FATE_SAMPLES_FFMPEG-yes += $(FATE_STREAMCOPY-yes) -FATE_TIME_BASE-$(call ALLYES, MPEGPS_DEMUXER MXF_MUXER) += fate-time_base -fate-time_base: $(SAMPLES)/mpeg2/dvd_single_frame.vob +FATE_TIME_BASE-$(call PARSERDEMDEC, MPEGVIDEO, MPEGPS, MPEG2VIDEO, MPEGVIDEO_DEMUXER MXF_MUXER) += fate-time_base fate-time_base: CMD = md5 -i $(TARGET_SAMPLES)/mpeg2/dvd_single_frame.vob -an -sn -c:v copy -r 25 -time_base 1001:30000 -fflags +bitexact -f mxf FATE_SAMPLES_FFMPEG-yes += $(FATE_TIME_BASE-yes) diff --git a/tests/fate/filter-audio.mak b/tests/fate/filter-audio.mak index f97318476..eff32b9f8 100644 --- a/tests/fate/filter-audio.mak +++ b/tests/fate/filter-audio.mak @@ -104,6 +104,11 @@ fate-filter-chorus: tests/data/asynth-22050-1.wav fate-filter-chorus: SRC = $(TARGET_PATH)/tests/data/asynth-22050-1.wav fate-filter-chorus: CMD = framecrc -i $(SRC) -frames:a 10 -af aresample,chorus=0.050001:0.050002:64:0.050001:0.025003:2.00004,aresample +FATE_AFILTER-$(call FILTERDEMDECENCMUX, CRYSTALIZER, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-filter-crystalizer +fate-filter-crystalizer: tests/data/asynth-44100-2.wav +fate-filter-crystalizer: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav +fate-filter-crystalizer: CMD = framecrc -i $(SRC) -af aresample,crystalizer=2:0,crystalizer=-2:0,aresample + FATE_AFILTER-$(call FILTERDEMDECENCMUX, DCSHIFT, WAV, PCM_S16LE, PCM_S16LE, WAV) += fate-filter-dcshift fate-filter-dcshift: tests/data/asynth-44100-2.wav fate-filter-dcshift: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav diff --git a/tests/fate/filter-video.mak b/tests/fate/filter-video.mak index 7df79c70e..faed832cd 100644 --- a/tests/fate/filter-video.mak +++ b/tests/fate/filter-video.mak @@ -1,26 +1,25 @@ -FATE_FILTER_SAMPLES-$(call ALLYES, SMJPEG_DEMUXER MJPEG_DECODER PERMS_FILTER OWDENOISE_FILTER) += fate-filter-owdenoise-sample +# Contains the requirements added implicitly if CMD is video_filter. +VIDEO_FILTER = $(call ALLYES, $(1:%=%_FILTER) $(2) FILE_PROTOCOL IMAGE2_DEMUXER PGMYUV_DECODER RAWVIDEO_ENCODER NUT_MUXER MD5_PROTOCOL) + +FATE_FILTER_SAMPLES-$(call FILTERDEMDECENCMUX, PERMS OWDENOISE TRIM SCALE, SMJPEG, MJPEG, RAWVIDEO, RAWVIDEO, PIPE_PROTOCOL) += fate-filter-owdenoise-sample fate-filter-owdenoise-sample: CMD = ffmpeg -auto_conversion_filters -idct simple -i $(TARGET_SAMPLES)/smjpeg/scenwin.mjpg -vf "trim=duration=0.5,perms=random,owdenoise=10:20:20:enable=not(between(t\,0.2\,1.2))" -an -f rawvideo - fate-filter-owdenoise-sample: REF = $(SAMPLES)/filter-reference/owdenoise-scenwin.raw fate-filter-owdenoise-sample: CMP_TARGET = 1 fate-filter-owdenoise-sample: FUZZ = 3539 fate-filter-owdenoise-sample: CMP = oneoff -FATE_FILTER_SAMPLES-$(call ALLYES, PERMS_FILTER DELOGO_FILTER RM_DEMUXER RV30_DECODER) += fate-filter-delogo +FATE_FILTER_SAMPLES-$(call FILTERDEMDEC, PERMS DELOGO, RM, RV30) += fate-filter-delogo fate-filter-delogo: CMD = framecrc -i $(TARGET_SAMPLES)/real/rv30.rm -vf perms=random,delogo=show=0:x=290:y=25:w=26:h=16 -an -FATE_YADIF += fate-filter-yadif-mode0 +FATE_YADIF-$(call FILTERDEMDEC, YADIF, MPEGTS, MPEG2VIDEO) += fate-filter-yadif-mode0 fate-filter-yadif-mode1 fate-filter-yadif-mode0: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -frames:v 30 -vf yadif=0 - -FATE_YADIF += fate-filter-yadif-mode1 fate-filter-yadif-mode1: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -frames:v 59 -vf yadif=1 -FATE_YADIF += fate-filter-yadif10 +FATE_YADIF-$(call FILTERDEMDEC, YADIF SCALE, MPEGTS, MPEG2VIDEO) += fate-filter-yadif10 fate-filter-yadif16 fate-filter-yadif10: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -flags bitexact -pix_fmt yuv420p10le -frames:v 30 -vf yadif=0,scale - -FATE_YADIF += fate-filter-yadif16 fate-filter-yadif16: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -flags bitexact -pix_fmt yuv420p16le -frames:v 30 -vf yadif=0,scale -FATE_FILTER_SAMPLES-$(call FILTERDEMDEC, YADIF, MPEGTS, MPEG2VIDEO) += $(FATE_YADIF) +FATE_FILTER_SAMPLES-yes += $(FATE_YADIF-yes) FATE_W3FDIF += fate-filter-w3fdif-simple fate-filter-w3fdif-simple: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -frames:v 30 -vf w3fdif=0 @@ -36,22 +35,20 @@ fate-filter-mcdeint-fast: CMD = framecrc -flags bitexact -idct simple -i $(TARGE FATE_MCDEINT += fate-filter-mcdeint-medium fate-filter-mcdeint-medium: CMD = framecrc -flags bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -frames:v 30 -vf mcdeint=mode=medium -FATE_FILTER_SAMPLES-$(call ALLYES, MCDEINT_FILTER, MPEGTS_DEMUXER, MPEG2VIDEO_DECODER SNOW_ENCODER) += $(FATE_MCDEINT) +FATE_FILTER_SAMPLES-$(call FILTERDEMDEC, MCDEINT, MPEGTS, MPEG2VIDEO, SNOW_ENCODER) += $(FATE_MCDEINT) -FATE_FILTER_SAMPLES-$(call ALLYES, CODECVIEW_FILTER RM_DEMUXER RV40_DECODER) += fate-filter-codecview-mvs +FATE_FILTER_SAMPLES-$(call FILTERDEMDEC, CODECVIEW, RM, RV40) += fate-filter-codecview-mvs fate-filter-codecview-mvs: CMD = framecrc -flags2 +export_mvs -i $(TARGET_SAMPLES)/real/spygames-2MB.rmvb -vf codecview=mv=pf+bf+bb -frames:v 60 -an -FATE_FILTER_SAMPLES-$(call ALLYES, SHOWPALETTE_FILTER FLIC_DEMUXER FLIC_DECODER) += fate-filter-showpalette +FATE_FILTER_SAMPLES-$(call FILTERDEMDEC, SHOWPALETTE SCALE, FLIC, FLIC) += fate-filter-showpalette fate-filter-showpalette: CMD = framecrc -i $(TARGET_SAMPLES)/fli/fli-engines.fli -vf showpalette=3,scale -pix_fmt bgra -FATE_FILTER_PALETTEGEN += fate-filter-palettegen-1 +FATE_FILTER_PALETTEGEN-$(call FILTERDEMDEC, SCALE PALETTEGEN, MATROSKA, H264) += fate-filter-palettegen-1 fate-filter-palettegen-2 fate-filter-palettegen-1: CMD = framecrc -i $(TARGET_SAMPLES)/filter/anim.mkv -vf scale,palettegen,scale -pix_fmt bgra - -FATE_FILTER_PALETTEGEN += fate-filter-palettegen-2 fate-filter-palettegen-2: CMD = framecrc -i $(TARGET_SAMPLES)/filter/anim.mkv -vf scale,palettegen=max_colors=128:reserve_transparent=0:stats_mode=diff,scale -pix_fmt bgra -fate-filter-palettegen: $(FATE_FILTER_PALETTEGEN) -FATE_FILTER_SAMPLES-$(call ALLYES, PALETTEGEN_FILTER MATROSKA_DEMUXER H264_DECODER) += $(FATE_FILTER_PALETTEGEN) +fate-filter-palettegen: $(FATE_FILTER_PALETTEGEN-yes) +FATE_FILTER_SAMPLES-yes += $(FATE_FILTER_PALETTEGEN-yes) FATE_FILTER_PALETTEUSE += fate-filter-paletteuse-nodither fate-filter-paletteuse-nodither: CMD = framecrc -auto_conversion_filters -i $(TARGET_SAMPLES)/filter/anim.mkv -i $(TARGET_SAMPLES)/filter/anim-palette.png -lavfi paletteuse=none -pix_fmt bgra @@ -59,335 +56,245 @@ fate-filter-paletteuse-nodither: CMD = framecrc -auto_conversion_filters -i $(TA FATE_FILTER_PALETTEUSE += fate-filter-paletteuse-bayer fate-filter-paletteuse-bayer: CMD = framecrc -auto_conversion_filters -i $(TARGET_SAMPLES)/filter/anim.mkv -i $(TARGET_SAMPLES)/filter/anim-palette.png -lavfi paletteuse=bayer -pix_fmt bgra +FATE_FILTER_PALETTEUSE += fate-filter-paletteuse-bayer0 +fate-filter-paletteuse-bayer0: CMD = framecrc -auto_conversion_filters -i $(TARGET_SAMPLES)/filter/anim.mkv -i $(TARGET_SAMPLES)/filter/anim-palette.png -lavfi paletteuse=bayer:bayer_scale=0 -pix_fmt bgra + FATE_FILTER_PALETTEUSE += fate-filter-paletteuse-sierra2_4a fate-filter-paletteuse-sierra2_4a: CMD = framecrc -auto_conversion_filters -i $(TARGET_SAMPLES)/filter/anim.mkv -i $(TARGET_SAMPLES)/filter/anim-palette.png -lavfi paletteuse=sierra2_4a:diff_mode=rectangle -pix_fmt bgra -fate-filter-paletteuse: $(FATE_FILTER_PALETTEUSE) -FATE_FILTER_SAMPLES-$(call ALLYES, PALETTEUSE_FILTER MATROSKA_DEMUXER H264_DECODER IMAGE2_DEMUXER PNG_DECODER) += $(FATE_FILTER_PALETTEUSE) +FATE_FILTER_PALETTEUSE-$(call FILTERDEMDEC, PALETTEUSE SCALE, MATROSKA IMAGE2, H264 PNG) += $(FATE_FILTER_PALETTEUSE) -FATE_FILTER-$(call ALLYES, AVDEVICE LIFE_FILTER) += fate-filter-lavd-life +fate-filter-paletteuse: $(FATE_FILTER_PALETTEUSE-yes) +FATE_FILTER_SAMPLES-yes += $(FATE_FILTER_PALETTEUSE-yes) + +FATE_FILTER-$(call FILTERFRAMECRC, LIFE, LAVFI_INDEV) += fate-filter-lavd-life fate-filter-lavd-life: CMD = framecrc -f lavfi -i life=s=40x40:r=5:seed=42:mold=64:ratio=0.1:death_color=red:life_color=green -t 2 -FATE_FILTER-$(call ALLYES, AVDEVICE TESTSRC_FILTER) += fate-filter-lavd-testsrc +FATE_FILTER-$(call FILTERFRAMECRC, TESTSRC, LAVFI_INDEV) += fate-filter-lavd-testsrc fate-filter-lavd-testsrc: CMD = framecrc -f lavfi -i testsrc=r=7:n=2:d=10 -FATE_FILTER-$(call ALLYES, TESTSRC2_FILTER) += fate-filter-testsrc2-yuv420p -fate-filter-testsrc2-yuv420p: CMD = framecrc -lavfi testsrc2=r=7:d=10 -pix_fmt yuv420p +FATE_FILTER-$(call FILTERFRAMECRC, TESTSRC2) += $(addprefix fate-filter-testsrc2-, yuv420p yuv444p rgb24 rgba) +fate-filter-testsrc2-%: CMD = framecrc -lavfi testsrc2=r=7:d=10 -pix_fmt $(word 4, $(subst -, ,$(@))) -FATE_FILTER-$(call ALLYES, TESTSRC2_FILTER) += fate-filter-testsrc2-yuv444p -fate-filter-testsrc2-yuv444p: CMD = framecrc -lavfi testsrc2=r=7:d=10 -pix_fmt yuv444p - -FATE_FILTER-$(call ALLYES, TESTSRC2_FILTER) += fate-filter-testsrc2-rgb24 -fate-filter-testsrc2-rgb24: CMD = framecrc -lavfi testsrc2=r=7:d=10 -pix_fmt rgb24 - -FATE_FILTER-$(call ALLYES, LAVFI_INDEV TESTSRC2_FILTER) += fate-filter-testsrc2-rgba -fate-filter-testsrc2-rgba: CMD = framecrc -lavfi testsrc2=r=7:d=10 -pix_fmt rgba - -FATE_FILTER-$(call ALLYES, LAVFI_INDEV ALLRGB_FILTER) += fate-filter-allrgb +FATE_FILTER-$(call FILTERFRAMECRC, ALLRGB) += fate-filter-allrgb fate-filter-allrgb: CMD = framecrc -lavfi allrgb=rate=5:duration=1 -pix_fmt rgb24 -FATE_FILTER-$(call ALLYES, LAVFI_INDEV ALLYUV_FILTER) += fate-filter-allyuv +FATE_FILTER-$(call FILTERFRAMECRC, ALLYUV) += fate-filter-allyuv fate-filter-allyuv: CMD = framecrc -lavfi allyuv=rate=5:duration=1 -pix_fmt yuv444p -FATE_FILTER-$(call ALLYES, LAVFI_INDEV PAL75BARS_FILTER) += fate-filter-pal75bars +FATE_FILTER-$(call FILTERFRAMECRC, PAL75BARS) += fate-filter-pal75bars fate-filter-pal75bars: CMD = framecrc -lavfi pal75bars=rate=5:duration=1 -pix_fmt yuv420p -FATE_FILTER-$(call ALLYES, LAVFI_INDEV PAL100BARS_FILTER) += fate-filter-pal100bars +FATE_FILTER-$(call FILTERFRAMECRC, PAL100BARS) += fate-filter-pal100bars fate-filter-pal100bars: CMD = framecrc -lavfi pal100bars=rate=5:duration=1 -pix_fmt yuv420p -FATE_FILTER-$(call ALLYES, LAVFI_INDEV RGBTESTSRC_FILTER) += fate-filter-rgbtestsrc +FATE_FILTER-$(call FILTERFRAMECRC, RGBTESTSRC) += fate-filter-rgbtestsrc fate-filter-rgbtestsrc: CMD = framecrc -lavfi rgbtestsrc=rate=5:duration=1 -pix_fmt rgb24 -FATE_FILTER-$(call ALLYES, LAVFI_INDEV SMPTEBARS_FILTER) += fate-filter-smptebars +FATE_FILTER-$(call FILTERFRAMECRC, SMPTEBARS) += fate-filter-smptebars fate-filter-smptebars: CMD = framecrc -lavfi smptebars=rate=5:duration=1 -pix_fmt yuv420p -FATE_FILTER-$(call ALLYES, LAVFI_INDEV SMPTEHDBARS_FILTER) += fate-filter-smptehdbars +FATE_FILTER-$(call FILTERFRAMECRC, SMPTEHDBARS) += fate-filter-smptehdbars fate-filter-smptehdbars: CMD = framecrc -lavfi smptehdbars=rate=5:duration=1 -pix_fmt yuv444p -FATE_FILTER-$(call ALLYES, LAVFI_INDEV YUVTESTSRC_FILTER) += fate-filter-yuvtestsrc-yuv444p +FATE_FILTER-$(call FILTERFRAMECRC, YUVTESTSRC) += fate-filter-yuvtestsrc-yuv444p fate-filter-yuvtestsrc-yuv444p: CMD = framecrc -lavfi yuvtestsrc=rate=5:duration=1 -pix_fmt yuv444p -FATE_FILTER-$(call ALLYES, LAVFI_INDEV YUVTESTSRC_FILTER) += fate-filter-yuvtestsrc-yuv444p12 +FATE_FILTER-$(call FILTERFRAMECRC, YUVTESTSRC SCALE) += fate-filter-yuvtestsrc-yuv444p12 fate-filter-yuvtestsrc-yuv444p12: CMD = framecrc -lavfi yuvtestsrc=rate=5:duration=1,format=yuv444p12,scale -pix_fmt yuv444p12le -FATE_FILTER-$(call ALLYES, AVDEVICE TESTSRC_FILTER FORMAT_FILTER CONCAT_FILTER SCALE_FILTER) += fate-filter-lavd-scalenorm +FATE_FILTER-$(call FILTERFRAMECRC, TESTSRC FORMAT CONCAT SCALE, LAVFI_INDEV FILE_PROTOCOL) += fate-filter-lavd-scalenorm 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-$(call FILTERFRAMECRC, FRAMERATE TESTSRC2) += 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 -FATE_FILTER-$(call ALLYES, FRAMERATE_FILTER TESTSRC2_FILTER FORMAT_FILTER) += fate-filter-framerate-12bit-up fate-filter-framerate-12bit-down +FATE_FILTER-$(call FILTERFRAMECRC, FRAMERATE TESTSRC2 FORMAT SCALE) += 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=yuv422p12le,scale,framerate=fps=60,scale -t 1 -pix_fmt yuv422p12le fate-filter-framerate-12bit-down: CMD = framecrc -lavfi testsrc2=r=60:d=1,format=pix_fmts=yuv422p12le,scale,framerate=fps=50,scale -t 1 -pix_fmt yuv422p12le -FATE_FILTER-$(call ALLYES, MINTERPOLATE_FILTER TESTSRC2_FILTER) += fate-filter-minterpolate-up fate-filter-minterpolate-down +FATE_FILTER-$(call FILTERFRAMECRC, MINTERPOLATE TESTSRC2) += fate-filter-minterpolate-up fate-filter-minterpolate-down fate-filter-minterpolate-up: CMD = framecrc -lavfi testsrc2=r=2:d=10,minterpolate=fps=10 -t 1 fate-filter-minterpolate-down: CMD = framecrc -lavfi testsrc2=r=2:d=10,minterpolate=fps=1 -t 1 -FATE_FILTER_VSYNTH-$(CONFIG_BOXBLUR_FILTER) += fate-filter-boxblur +FATE_FILTER_VSYNTH_PGMYUV-$(CONFIG_BOXBLUR_FILTER) += fate-filter-boxblur fate-filter-boxblur: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf boxblur=2:1 -FATE_FILTER_VSYNTH-$(call ALLYES, COLORCHANNELMIXER_FILTER FORMAT_FILTER PERMS_FILTER) += fate-filter-colorchannelmixer +FATE_FILTER_VSYNTH_PGMYUV-$(call ALLYES, COLORCHANNELMIXER_FILTER SCALE_FILTER FORMAT_FILTER PERMS_FILTER) += fate-filter-colorchannelmixer fate-filter-colorchannelmixer: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf scale,format=rgb24,perms=random,colorchannelmixer=.31415927:.4:.31415927:0:.27182818:.8:.27182818:0:.2:.6:.2:0 -flags +bitexact -sws_flags +accurate_rnd+bitexact -FATE_FILTER_VSYNTH-$(CONFIG_DRAWBOX_FILTER) += fate-filter-drawbox +FATE_FILTER_VSYNTH_PGMYUV-$(CONFIG_DRAWBOX_FILTER) += fate-filter-drawbox fate-filter-drawbox: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf drawbox=224:24:88:72:red@0.5 -FATE_FILTER_VSYNTH-$(CONFIG_FADE_FILTER) += fate-filter-fade +FATE_FILTER_VSYNTH_PGMYUV-$(CONFIG_FADE_FILTER) += fate-filter-fade fate-filter-fade: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf fade=in:5:15,fade=out:30:15 -FATE_FILTER_VSYNTH-$(call ALLYES, INTERLACE_FILTER FIELDORDER_FILTER) += fate-filter-fieldorder +FATE_FILTER_VSYNTH_PGMYUV-$(call ALLYES, INTERLACE_FILTER SCALE_FILTER FIELDORDER_FILTER) += fate-filter-fieldorder fate-filter-fieldorder: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf interlace=tff,scale,fieldorder=bff -sws_flags +accurate_rnd+bitexact -define FATE_FPFILTER_SUITE -FATE_FILTER_FRAMEPACK += fate-filter-framepack-$(1) -fate-filter-framepack-$(1): CMD = framecrc -c:v pgmyuv -i $(TARGET_PATH)/tests/vsynth1/%02d.pgm -c:v pgmyuv -i $(TARGET_PATH)/tests/vsynth1/%02d.pgm -filter_complex framepack=$(1) -frames 15 -endef - FPMODES = columns frameseq lines sbs tab -$(foreach MODE,$(FPMODES),$(eval $(call FATE_FPFILTER_SUITE,$(MODE)))) -FATE_FILTER_VSYNTH-$(CONFIG_FRAMEPACK_FILTER) += $(FATE_FILTER_FRAMEPACK) +FATE_FILTER_FRAMEPACK := $(addprefix fate-filter-framepack-, $(FPMODES)) +$(FATE_FILTER_FRAMEPACK): CMD = framecrc -c:v pgmyuv -i $(TARGET_PATH)/tests/vsynth1/%02d.pgm -c:v pgmyuv -i $(TARGET_PATH)/tests/vsynth1/%02d.pgm -filter_complex framepack=$(@:fate-filter-framepack-%=%) -frames 15 + +FATE_FILTER_VSYNTH_PGMYUV-$(CONFIG_FRAMEPACK_FILTER) += $(FATE_FILTER_FRAMEPACK) fate-filter-framepack: $(FATE_FILTER_FRAMEPACK) -FATE_FILTER_VSYNTH-$(CONFIG_GRADFUN_FILTER) += fate-filter-gradfun +FATE_FILTER_VSYNTH_PGMYUV-$(CONFIG_GRADFUN_FILTER) += fate-filter-gradfun fate-filter-gradfun: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf gradfun -FATE_FILTER_VSYNTH-$(CONFIG_HQDN3D_FILTER) += fate-filter-hqdn3d +FATE_FILTER_VSYNTH_PGMYUV-$(CONFIG_HQDN3D_FILTER) += fate-filter-hqdn3d fate-filter-hqdn3d: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf hqdn3d -FATE_FILTER_VSYNTH-$(CONFIG_INTERLACE_FILTER) += fate-filter-interlace +FATE_FILTER_VSYNTH_PGMYUV-$(CONFIG_INTERLACE_FILTER) += fate-filter-interlace fate-filter-interlace: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf interlace -FATE_FILTER_VSYNTH-$(CONFIG_INTERLACE_FILTER) += fate-filter-interlace-complex +FATE_FILTER_VSYNTH_PGMYUV-$(CONFIG_INTERLACE_FILTER) += fate-filter-interlace-complex fate-filter-interlace-complex: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf interlace=lowpass=complex -FATE_FILTER_VSYNTH-$(call ALLYES, NEGATE_FILTER PERMS_FILTER) += fate-filter-negate +FATE_FILTER_VSYNTH_PGMYUV-$(call ALLYES, NEGATE_FILTER PERMS_FILTER) += fate-filter-negate fate-filter-negate: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf perms=random,negate -FATE_FILTER_VSYNTH-$(CONFIG_HISTOGRAM_FILTER) += fate-filter-histogram-levels +FATE_FILTER_VSYNTH_PGMYUV-$(CONFIG_HISTOGRAM_FILTER) += fate-filter-histogram-levels fate-filter-histogram-levels: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf histogram -flags +bitexact -sws_flags +accurate_rnd+bitexact -FATE_FILTER_VSYNTH-$(CONFIG_WAVEFORM_FILTER) += fate-filter-waveform_column +FATE_FILTER_VSYNTH_PGMYUV-$(CONFIG_WAVEFORM_FILTER) += fate-filter-waveform_column fate-filter-waveform_column: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf waveform -flags +bitexact -sws_flags +accurate_rnd+bitexact -FATE_FILTER_VSYNTH-$(CONFIG_WAVEFORM_FILTER) += fate-filter-waveform_row +FATE_FILTER_VSYNTH_PGMYUV-$(CONFIG_WAVEFORM_FILTER) += fate-filter-waveform_row fate-filter-waveform_row: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf waveform=m=row -flags +bitexact -sws_flags +accurate_rnd+bitexact -FATE_FILTER_VSYNTH-$(CONFIG_WAVEFORM_FILTER) += fate-filter-waveform_envelope +FATE_FILTER_VSYNTH_PGMYUV-$(CONFIG_WAVEFORM_FILTER) += fate-filter-waveform_envelope fate-filter-waveform_envelope: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf waveform=e=3 -flags +bitexact -sws_flags +accurate_rnd+bitexact -FATE_FILTER_VSYNTH-$(CONFIG_WAVEFORM_FILTER) += fate-filter-waveform_uv +FATE_FILTER_VSYNTH_PGMYUV-$(CONFIG_WAVEFORM_FILTER) += fate-filter-waveform_uv fate-filter-waveform_uv: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf waveform=c=6 -flags +bitexact -sws_flags +accurate_rnd+bitexact -FATE_FILTER_VSYNTH-$(CONFIG_VECTORSCOPE_FILTER) += fate-filter-vectorscope_gray +FATE_FILTER_VSYNTH_PGMYUV-$(CONFIG_VECTORSCOPE_FILTER) += fate-filter-vectorscope_gray fate-filter-vectorscope_gray: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf vectorscope=gray -sws_flags +accurate_rnd+bitexact -frames:v 3 -FATE_FILTER_VSYNTH-$(CONFIG_VECTORSCOPE_FILTER) += fate-filter-vectorscope_color +FATE_FILTER_VSYNTH_PGMYUV-$(CONFIG_VECTORSCOPE_FILTER) += fate-filter-vectorscope_color fate-filter-vectorscope_color: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf vectorscope=color -sws_flags +accurate_rnd+bitexact -frames:v 3 -FATE_FILTER_VSYNTH-$(CONFIG_VECTORSCOPE_FILTER) += fate-filter-vectorscope_color2 +FATE_FILTER_VSYNTH_PGMYUV-$(CONFIG_VECTORSCOPE_FILTER) += fate-filter-vectorscope_color2 fate-filter-vectorscope_color2: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf vectorscope=color2 -sws_flags +accurate_rnd+bitexact -frames:v 3 -FATE_FILTER_VSYNTH-$(CONFIG_VECTORSCOPE_FILTER) += fate-filter-vectorscope_color3 +FATE_FILTER_VSYNTH_PGMYUV-$(CONFIG_VECTORSCOPE_FILTER) += fate-filter-vectorscope_color3 fate-filter-vectorscope_color3: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf vectorscope=color3 -sws_flags +accurate_rnd+bitexact -frames:v 3 -FATE_FILTER_VSYNTH-$(CONFIG_VECTORSCOPE_FILTER) += fate-filter-vectorscope_color4 +FATE_FILTER_VSYNTH_PGMYUV-$(CONFIG_VECTORSCOPE_FILTER) += fate-filter-vectorscope_color4 fate-filter-vectorscope_color4: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf vectorscope=color4 -sws_flags +accurate_rnd+bitexact -frames:v 3 -FATE_FILTER_VSYNTH-$(CONFIG_VECTORSCOPE_FILTER) += fate-filter-vectorscope_xy +FATE_FILTER_VSYNTH_PGMYUV-$(call ALLYES, VECTORSCOPE_FILTER SCALE_FILTER) += fate-filter-vectorscope_xy fate-filter-vectorscope_xy: CMD = framecrc -auto_conversion_filters -c:v pgmyuv -i $(SRC) -vf vectorscope=x=0:y=1 -sws_flags +accurate_rnd+bitexact -frames:v 3 -FATE_FILTER_VSYNTH-$(CONFIG_MERGEPLANES_FILTER) += fate-filter-mergeplanes +FATE_FILTER_VSYNTH_PGMYUV-$(CONFIG_MERGEPLANES_FILTER) += fate-filter-mergeplanes fate-filter-mergeplanes: tests/data/filtergraphs/mergeplanes fate-filter-mergeplanes: CMD = framecrc -c:v pgmyuv -i $(SRC) -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/mergeplanes -FATE_FILTER_VSYNTH-$(CONFIG_HSTACK_FILTER) += fate-filter-hstack +FATE_FILTER_VSYNTH_PGMYUV-$(CONFIG_HSTACK_FILTER) += fate-filter-hstack fate-filter-hstack: tests/data/filtergraphs/hstack fate-filter-hstack: CMD = framecrc -c:v pgmyuv -i $(SRC) -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/hstack -FATE_FILTER_VSYNTH-$(CONFIG_VSTACK_FILTER) += fate-filter-vstack +FATE_FILTER_VSYNTH_PGMYUV-$(CONFIG_VSTACK_FILTER) += fate-filter-vstack fate-filter-vstack: tests/data/filtergraphs/vstack fate-filter-vstack: CMD = framecrc -c:v pgmyuv -i $(SRC) -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/vstack -FATE_FILTER_VSYNTH-$(CONFIG_OVERLAY_FILTER) += fate-filter-overlay -fate-filter-overlay: tests/data/filtergraphs/overlay -fate-filter-overlay: CMD = framecrc -c:v pgmyuv -i $(SRC) -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/overlay +FATE_FILTER_OVERLAY-$(call FILTERDEMDEC, SCALE OVERLAY, IMAGE2, PGMYUV) += fate-filter-overlay +fate-filter-overlay: CMD = framecrc -c:v pgmyuv -i $(SRC) -c:v pgmyuv -i $(SRC) -filter_complex_script $(FILTERGRAPH) -FATE_FILTER_VSYNTH-$(call ALLYES, SPLIT_FILTER SCALE_FILTER PAD_FILTER OVERLAY_FILTER) += fate-filter-overlay_rgb -fate-filter-overlay_rgb: tests/data/filtergraphs/overlay_rgb -fate-filter-overlay_rgb: CMD = framecrc -auto_conversion_filters -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/overlay_rgb +FATE_FILTER_OVERLAY-$(call FILTERDEMDEC, SPLIT SCALE PAD OVERLAY, IMAGE2, PGMYUV) += $(addprefix fate-filter-overlay_, rgb yuv420 yuv420p10 nv12 nv21 yuv422 yuv422p10 yuv444) +fate-filter-overlay_%: CMD = framecrc -auto_conversion_filters -c:v pgmyuv -i $(SRC) -filter_complex_script $(FILTERGRAPH) +fate-filter-overlay_yuv420: CMD = framecrc -c:v pgmyuv -i $(SRC) -filter_complex_script $(FILTERGRAPH) +fate-filter-overlay_%p10: CMD = framecrc -auto_conversion_filters -c:v pgmyuv -i $(SRC) -filter_complex_script $(FILTERGRAPH) -pix_fmt $(@:fate-filter-overlay_%=%)le -frames:v 3 -FATE_FILTER_VSYNTH-$(call ALLYES, SPLIT_FILTER SCALE_FILTER PAD_FILTER OVERLAY_FILTER) += fate-filter-overlay_yuv420 -fate-filter-overlay_yuv420: tests/data/filtergraphs/overlay_yuv420 -fate-filter-overlay_yuv420: CMD = framecrc -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/overlay_yuv420 +$(addprefix fate-filter-overlay_, nv12 nv21): REF = $(SRC_PATH)/tests/ref/fate/filter-overlay_yuv420 -FATE_FILTER_VSYNTH-$(call ALLYES, SPLIT_FILTER SCALE_FILTER PAD_FILTER OVERLAY_FILTER) += fate-filter-overlay_yuv420p10 -fate-filter-overlay_yuv420p10: tests/data/filtergraphs/overlay_yuv420p10 -fate-filter-overlay_yuv420p10: CMD = framecrc -auto_conversion_filters -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/overlay_yuv420p10 -pix_fmt yuv420p10le -frames:v 3 +FATE_FILTER_OVERLAY_SAMPLES-$(call FILTERDEMDEC, SCALE OVERLAY, MATROSKA, H264 DVDSUB) += fate-filter-overlay-dvdsub-2397 +fate-filter-overlay-dvdsub-2397: CMD = framecrc -auto_conversion_filters -flags bitexact -i $(TARGET_SAMPLES)/filter/242_4.mkv -filter_complex_script $(FILTERGRAPH) -c:a copy -FATE_FILTER_VSYNTH-$(call ALLYES, SPLIT_FILTER SCALE_FILTER PAD_FILTER OVERLAY_FILTER) += fate-filter-overlay_nv12 -fate-filter-overlay_nv12: tests/data/filtergraphs/overlay_nv12 -fate-filter-overlay_nv12: CMD = framecrc -auto_conversion_filters -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/overlay_nv12 -fate-filter-overlay_nv12: REF = $(SRC_PATH)/tests/ref/fate/filter-overlay_yuv420 +FATE_FILTER_OVERLAY := $(FATE_FILTER_OVERLAY-yes) $(FATE_FILTER_OVERLAY_SAMPLES-yes) +$(FATE_FILTER_OVERLAY): FILTERGRAPH = $(TARGET_PATH)/tests/data/filtergraphs/$(@:fate-filter-%=%) +$(FATE_FILTER_OVERLAY): fate-filter-%: tests/data/filtergraphs/% +FATE_FILTER_VSYNTH-yes += $(FATE_FILTER_OVERLAY-yes) -FATE_FILTER_VSYNTH-$(call ALLYES, SPLIT_FILTER SCALE_FILTER PAD_FILTER OVERLAY_FILTER) += fate-filter-overlay_nv21 -fate-filter-overlay_nv21: tests/data/filtergraphs/overlay_nv21 -fate-filter-overlay_nv21: CMD = framecrc -auto_conversion_filters -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/overlay_nv21 -fate-filter-overlay_nv21: REF = $(SRC_PATH)/tests/ref/fate/filter-overlay_yuv420 - -FATE_FILTER_VSYNTH-$(call ALLYES, SPLIT_FILTER SCALE_FILTER PAD_FILTER OVERLAY_FILTER) += fate-filter-overlay_yuv422 -fate-filter-overlay_yuv422: tests/data/filtergraphs/overlay_yuv422 -fate-filter-overlay_yuv422: CMD = framecrc -auto_conversion_filters -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/overlay_yuv422 - -FATE_FILTER_VSYNTH-$(call ALLYES, SPLIT_FILTER SCALE_FILTER PAD_FILTER OVERLAY_FILTER) += fate-filter-overlay_yuv422p10 -fate-filter-overlay_yuv422p10: tests/data/filtergraphs/overlay_yuv422p10 -fate-filter-overlay_yuv422p10: CMD = framecrc -auto_conversion_filters -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/overlay_yuv422p10 -pix_fmt yuv422p10le -frames:v 3 - -FATE_FILTER_VSYNTH-$(call ALLYES, SPLIT_FILTER SCALE_FILTER PAD_FILTER OVERLAY_FILTER) += fate-filter-overlay_yuv444 -fate-filter-overlay_yuv444: tests/data/filtergraphs/overlay_yuv444 -fate-filter-overlay_yuv444: CMD = framecrc -auto_conversion_filters -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/overlay_yuv444 - -FATE_FILTER_OVERLAY_ALPHA += fate-filter-overlay_yuv420_yuva420 fate-filter-overlay_yuv422_yuva422 fate-filter-overlay_yuv444_yuva444 fate-filter-overlay_rgb_rgba fate-filter-overlay_gbrp_gbrap -FATE_FILTER_OVERLAY_ALPHA += fate-filter-overlay_yuva420_yuva420 fate-filter-overlay_yuva422_yuva422 fate-filter-overlay_yuva444_yuva444 fate-filter-overlay_rgba_rgba fate-filter-overlay_gbrap_gbrap +FATE_FILTER_OVERLAY_ALPHA-$(call FILTERDEMDEC, COLOR FORMAT OVERLAY SCALE, IMAGE_PNG_PIPE, PNG) := yuv420_yuva420 yuv422_yuva422 yuv444_yuva444 gbrp_gbrap yuva420_yuva420 yuva422_yuva422 yuva444_yuva444 gbrap_gbrap +FATE_FILTER_OVERLAY_ALPHA-$(call FILTERDEMDEC, COLOR FORMAT OVERLAY, IMAGE_PNG_PIPE, PNG) += rgb_rgba rgba_rgba +FATE_FILTER_OVERLAY_ALPHA := $(addprefix fate-filter-overlay_, $(FATE_FILTER_OVERLAY_ALPHA-yes)) $(FATE_FILTER_OVERLAY_ALPHA): SRC = $(TARGET_SAMPLES)/png1/lena-rgba.png $(FATE_FILTER_OVERLAY_ALPHA): CMD = framecrc -i $(SRC) -sws_flags +accurate_rnd+bitexact -vf $(FILTER) -frames:v 1 fate-filter-overlay_yuv420_yuva420: FILTER = "scale,format=yuva420p[over];color=black:128x128,format=yuv420p[main];[main][over]overlay=format=yuv420" fate-filter-overlay_yuv422_yuva422: FILTER = "scale,format=yuva422p[over];color=black:128x128,format=yuv422p[main];[main][over]overlay=format=yuv422" fate-filter-overlay_yuv444_yuva444: FILTER = "scale,format=yuva444p[over];color=black:128x128,format=yuv444p[main];[main][over]overlay=format=yuv444" -fate-filter-overlay_rgb_rgba: FILTER = "scale,format=rgba[over];color=black:128x128,format=rgb24[main];[main][over]overlay=format=rgb" +fate-filter-overlay_rgb_rgba: FILTER = "format=rgba[over];color=black:128x128,format=rgb24[main];[main][over]overlay=format=rgb" fate-filter-overlay_gbrp_gbrap: FILTER = "scale,format=gbrap[over];color=black:128x128,format=gbrp[main];[main][over]overlay=format=gbrp" fate-filter-overlay_yuva420_yuva420: FILTER = "scale,format=yuva420p[over];color=black:128x128,format=yuva420p[main];[main][over]overlay=format=yuv420" fate-filter-overlay_yuva422_yuva422: FILTER = "scale,format=yuva422p[over];color=black:128x128,format=yuva422p[main];[main][over]overlay=format=yuv422" fate-filter-overlay_yuva444_yuva444: FILTER = "scale,format=yuva444p[over];color=black:128x128,format=yuva444p[main];[main][over]overlay=format=yuv444" -fate-filter-overlay_rgba_rgba: FILTER = "scale,format=rgba[over];color=black:128x128,format=rgba[main];[main][over]overlay=format=rgb" +fate-filter-overlay_rgba_rgba: FILTER = "format=rgba[over];color=black:128x128,format=rgba[main];[main][over]overlay=format=rgb" fate-filter-overlay_gbrap_gbrap: FILTER = "scale,format=gbrap[over];color=black:128x128,format=gbrap[main];[main][over]overlay=format=gbrp" -FATE_FILTER_SAMPLES-$(call ALLYES, PNG_DECODER APNG_DEMUXER FORMAT_FILTER COLOR_FILTER OVERLAY_FILTER) += $(FATE_FILTER_OVERLAY_ALPHA) +FATE_FILTER_SAMPLES-yes += $(FATE_FILTER_OVERLAY_SAMPLES-yes) $(FATE_FILTER_OVERLAY_ALPHA) +fate-filter-overlays: $(FATE_FILTER_OVERLAY) $(FATE_FILTER_OVERLAY_ALPHA) -FATE_FILTER_VSYNTH-$(CONFIG_PHASE_FILTER) += fate-filter-phase +FATE_FILTER_VSYNTH_PGMYUV-$(CONFIG_PHASE_FILTER) += fate-filter-phase fate-filter-phase: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf phase -FATE_REMOVEGRAIN += fate-filter-removegrain-mode-00 -fate-filter-removegrain-mode-00: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 1 -vf removegrain=0:0:0 +FATE_REMOVEGRAIN := 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 \ + 16 17 18 19 20 21 22 23 24 +FATE_REMOVEGRAIN := $(addprefix fate-filter-removegrain-mode-, $(FATE_REMOVEGRAIN)) +$(FATE_REMOVEGRAIN): MODE = $(word 5, $(subst -, ,$(@))) +$(FATE_REMOVEGRAIN): CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 1 -vf removegrain=$(MODE):$(MODE):$(MODE) +FATE_REMOVEGRAIN-$(call FILTERDEMDEC, REMOVEGRAIN, IMAGE2, PGMYUV) += $(FATE_REMOVEGRAIN) +fate-filter-removegrain: $(FATE_REMOVEGRAIN-yes) +FATE_FILTER_VSYNTH-yes += $(FATE_REMOVEGRAIN-yes) -FATE_REMOVEGRAIN += fate-filter-removegrain-mode-01 -fate-filter-removegrain-mode-01: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 1 -vf removegrain=1:1:1 - -FATE_REMOVEGRAIN += fate-filter-removegrain-mode-02 -fate-filter-removegrain-mode-02: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 1 -vf removegrain=2:2:2 - -FATE_REMOVEGRAIN += fate-filter-removegrain-mode-03 -fate-filter-removegrain-mode-03: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 1 -vf removegrain=3:3:3 - -FATE_REMOVEGRAIN += fate-filter-removegrain-mode-04 -fate-filter-removegrain-mode-04: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 1 -vf removegrain=4:4:4 - -FATE_REMOVEGRAIN += fate-filter-removegrain-mode-05 -fate-filter-removegrain-mode-05: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 1 -vf removegrain=5:5:5 - -FATE_REMOVEGRAIN += fate-filter-removegrain-mode-06 -fate-filter-removegrain-mode-06: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 1 -vf removegrain=6:6:6 - -FATE_REMOVEGRAIN += fate-filter-removegrain-mode-07 -fate-filter-removegrain-mode-07: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 1 -vf removegrain=7:7:7 - -FATE_REMOVEGRAIN += fate-filter-removegrain-mode-08 -fate-filter-removegrain-mode-08: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 1 -vf removegrain=8:8:8 - -FATE_REMOVEGRAIN += fate-filter-removegrain-mode-09 -fate-filter-removegrain-mode-09: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 1 -vf removegrain=9:9:9 - -FATE_REMOVEGRAIN += fate-filter-removegrain-mode-10 -fate-filter-removegrain-mode-10: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 1 -vf removegrain=10:10:10 - -FATE_REMOVEGRAIN += fate-filter-removegrain-mode-11 -fate-filter-removegrain-mode-11: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 1 -vf removegrain=11:11:11 - -FATE_REMOVEGRAIN += fate-filter-removegrain-mode-12 -fate-filter-removegrain-mode-12: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 1 -vf removegrain=12:12:12 - -FATE_REMOVEGRAIN += fate-filter-removegrain-mode-13 -fate-filter-removegrain-mode-13: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 1 -vf removegrain=13:13:13 - -FATE_REMOVEGRAIN += fate-filter-removegrain-mode-14 -fate-filter-removegrain-mode-14: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 1 -vf removegrain=14:14:14 - -FATE_REMOVEGRAIN += fate-filter-removegrain-mode-15 -fate-filter-removegrain-mode-15: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 1 -vf removegrain=15:15:15 - -FATE_REMOVEGRAIN += fate-filter-removegrain-mode-16 -fate-filter-removegrain-mode-16: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 1 -vf removegrain=16:16:16 - -FATE_REMOVEGRAIN += fate-filter-removegrain-mode-17 -fate-filter-removegrain-mode-17: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 1 -vf removegrain=17:17:17 - -FATE_REMOVEGRAIN += fate-filter-removegrain-mode-18 -fate-filter-removegrain-mode-18: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 1 -vf removegrain=18:18:18 - -FATE_REMOVEGRAIN += fate-filter-removegrain-mode-19 -fate-filter-removegrain-mode-19: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 1 -vf removegrain=19:19:19 - -FATE_REMOVEGRAIN += fate-filter-removegrain-mode-20 -fate-filter-removegrain-mode-20: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 1 -vf removegrain=20:20:20 - -FATE_REMOVEGRAIN += fate-filter-removegrain-mode-21 -fate-filter-removegrain-mode-21: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 1 -vf removegrain=21:21:21 - -FATE_REMOVEGRAIN += fate-filter-removegrain-mode-22 -fate-filter-removegrain-mode-22: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 1 -vf removegrain=22:22:22 - -FATE_REMOVEGRAIN += fate-filter-removegrain-mode-23 -fate-filter-removegrain-mode-23: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 1 -vf removegrain=23:23:23 - -FATE_REMOVEGRAIN += fate-filter-removegrain-mode-24 -fate-filter-removegrain-mode-24: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 1 -vf removegrain=24:24:24 - -fate-filter-removegrain: $(FATE_REMOVEGRAIN) -FATE_FILTER_VSYNTH-$(CONFIG_REMOVEGRAIN_FILTER) += $(FATE_REMOVEGRAIN) - -FATE_FILTER_VSYNTH-$(CONFIG_SEPARATEFIELDS_FILTER) += fate-filter-separatefields +FATE_FILTER_VSYNTH_PGMYUV-$(CONFIG_SEPARATEFIELDS_FILTER) += fate-filter-separatefields fate-filter-separatefields: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf separatefields -FATE_FILTER_VSYNTH-$(CONFIG_WEAVE_FILTER) += fate-filter-weave +FATE_FILTER_VSYNTH_PGMYUV-$(CONFIG_WEAVE_FILTER) += fate-filter-weave fate-filter-weave: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf weave=bottom -FATE_FILTER_VSYNTH-$(CONFIG_SELECT_FILTER) += fate-filter-select-alternate +FATE_FILTER_VSYNTH_PGMYUV-$(CONFIG_SELECT_FILTER) += fate-filter-select-alternate fate-filter-select-alternate: tests/data/filtergraphs/select-alternate fate-filter-select-alternate: CMD = framecrc -c:v pgmyuv -i $(SRC) -filter_script $(TARGET_PATH)/tests/data/filtergraphs/select-alternate -FATE_FILTER_VSYNTH-$(call ALLYES, SETPTS_FILTER SETTB_FILTER) += fate-filter-setpts +FATE_FILTER_VSYNTH_PGMYUV-$(call ALLYES, SETPTS_FILTER SETTB_FILTER) += fate-filter-setpts fate-filter-setpts: tests/data/filtergraphs/setpts fate-filter-setpts: CMD = framecrc -c:v pgmyuv -i $(SRC) -filter_script $(TARGET_PATH)/tests/data/filtergraphs/setpts FATE_SHUFFLEFRAMES += fate-filter-shuffleframes fate-filter-shuffleframes: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf shuffleframes="2|1|0" -FATE_FILTER_VSYNTH-$(CONFIG_SHUFFLEFRAMES_FILTER) += $(FATE_SHUFFLEFRAMES) +FATE_FILTER_VSYNTH_PGMYUV-$(CONFIG_SHUFFLEFRAMES_FILTER) += $(FATE_SHUFFLEFRAMES) -FATE_SHUFFLEPLANES += fate-filter-shuffleplanes-dup-luma +FATE_SHUFFLEPLANES-$(call ALLYES, SCALE_FILTER SHUFFLEPLANES_FILTER) += fate-filter-shuffleplanes-dup-luma fate-filter-shuffleplanes-dup-luma: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf scale,format=yuva444p,shuffleplanes=0:0:0:0 -FATE_SHUFFLEPLANES += fate-filter-shuffleplanes-swapuv +FATE_SHUFFLEPLANES-$(CONFIG_SHUFFLEPLANES_FILTER) += fate-filter-shuffleplanes-swapuv fate-filter-shuffleplanes-swapuv: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf shuffleplanes=0:2:1:0 -FATE_FILTER_VSYNTH-$(CONFIG_SHUFFLEPLANES_FILTER) += $(FATE_SHUFFLEPLANES) +FATE_FILTER_VSYNTH_PGMYUV-yes += $(FATE_SHUFFLEPLANES-yes) FATE_SWAPRECT += fate-filter-swaprect fate-filter-swaprect: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf swaprect -FATE_FILTER_VSYNTH-$(CONFIG_SWAPRECT_FILTER) += $(FATE_SWAPRECT) +FATE_FILTER_VSYNTH_PGMYUV-$(CONFIG_SWAPRECT_FILTER) += $(FATE_SWAPRECT) -FATE_FILTER_VSYNTH-$(CONFIG_TBLEND_FILTER) += fate-filter-tblend +FATE_FILTER_VSYNTH_PGMYUV-$(CONFIG_TBLEND_FILTER) += fate-filter-tblend fate-filter-tblend: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf tblend=all_mode=difference128 -FATE_FILTER_VSYNTH-$(CONFIG_TELECINE_FILTER) += fate-filter-telecine +FATE_FILTER_VSYNTH_PGMYUV-$(CONFIG_TELECINE_FILTER) += fate-filter-telecine fate-filter-telecine: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf telecine -FATE_FILTER_VSYNTH-$(CONFIG_TRANSPOSE_FILTER) += fate-filter-transpose +FATE_FILTER-$(call FILTERFRAMECRC, TESTSRC2 TPAD) += fate-filter-tpad-add fate-filter-tpad-clone +fate-filter-tpad-add: CMD = framecrc -lavfi testsrc2=d=1:r=2,tpad=start=1:stop=3:color=gray +fate-filter-tpad-clone: CMD = framecrc -lavfi testsrc2=d=1:r=2,tpad=start=1:stop=2:stop_mode=clone:color=black + +FATE_FILTER_VSYNTH_PGMYUV-$(CONFIG_TRANSPOSE_FILTER) += fate-filter-transpose fate-filter-transpose: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf transpose FATE_TRIM += fate-filter-trim-duration @@ -402,56 +309,65 @@ fate-filter-trim-mixed: CMD = framecrc -i $(SRC) -vf trim=start=0.2:end=0.4:star FATE_TRIM += fate-filter-trim-time fate-filter-trim-time: CMD = framecrc -i $(SRC) -vf trim=0:0.09 -FATE_FILTER_VSYNTH-$(CONFIG_TRIM_FILTER) += $(FATE_TRIM) +FATE_FILTER_VSYNTH-$(call FILTERDEMDEC, TRIM, IMAGE2, PGM) += $(FATE_TRIM) -FATE_FILTER-$(call ALLYES, TESTSRC2_FILTER UNTILE_FILTER) += fate-filter-untile +FATE_FILTER-$(call FILTERFRAMECRC, TESTSRC2 UNTILE) += fate-filter-untile fate-filter-untile: CMD = framecrc -lavfi testsrc2=d=1:r=2,untile=2x2 -FATE_FILTER_VSYNTH-$(CONFIG_UNSHARP_FILTER) += fate-filter-unsharp +FATE_FILTER_VSYNTH_PGMYUV-$(CONFIG_UNSHARP_FILTER) += fate-filter-unsharp fate-filter-unsharp: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf unsharp=11:11:-1.5:11:11:-1.5 -FATE_FILTER_VSYNTH-$(CONFIG_UNSHARP_FILTER) += fate-filter-unsharp-yuv420p10 +FATE_FILTER_VSYNTH-$(call FILTERFRAMECRC, TESTSRC2 SCALE UNSHARP) += fate-filter-unsharp-yuv420p10 fate-filter-unsharp-yuv420p10: CMD = framecrc -lavfi testsrc2=r=2:d=10,scale,format=yuv420p10,unsharp=11:11:-1.5:11:11:-1.5,scale -pix_fmt yuv420p10le -flags +bitexact -sws_flags +accurate_rnd+bitexact -FATE_FILTER_SAMPLES-$(call ALLYES, SMJPEG_DEMUXER MJPEG_DECODER PERMS_FILTER HQDN3D_FILTER) += fate-filter-hqdn3d-sample +FATE_FILTER_SAMPLES-$(call FILTERDEMDEC, PERMS HQDN3D, SMJPEG, MJPEG) += fate-filter-hqdn3d-sample fate-filter-hqdn3d-sample: tests/data/filtergraphs/hqdn3d fate-filter-hqdn3d-sample: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/smjpeg/scenwin.mjpg -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/hqdn3d -an -FATE_FILTER_SAMPLES-$(call ALLYES, MATROSKA_DEMUXER OVERLAY_FILTER H264_DECODER DVDSUB_DECODER) += fate-filter-overlay-dvdsub-2397 -fate-filter-overlay-dvdsub-2397: tests/data/filtergraphs/overlay-dvdsub-2397 -fate-filter-overlay-dvdsub-2397: CMD = framecrc -auto_conversion_filters -flags bitexact -i $(TARGET_SAMPLES)/filter/242_4.mkv -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/overlay-dvdsub-2397 -c:a copy +FATE_FILTER_EPX-$(call FILTERDEMDEC, SCALE EPX, IMAGE2, PNG) = fate-filter-ep2x fate-filter-ep3x +FATE_FILTER_SAMPLES-yes += $(FATE_FILTER_EPX-yes) +fate-filter-ep2x: CMD = framecrc -i $(TARGET_SAMPLES)/filter/pixelart%d.png -vf scale,format=rgb32,epx=2,scale,format=bgra +fate-filter-ep3x: CMD = framecrc -i $(TARGET_SAMPLES)/filter/pixelart%d.png -vf scale,format=rgb32,epx=3,scale,format=bgra +fate-filter-epx: $(FATE_FILTER_EPX-yes) -FATE_FILTER_HQX-$(call ALLYES, IMAGE2_DEMUXER PNG_DECODER HQX_FILTER) = fate-filter-hq2x fate-filter-hq3x fate-filter-hq4x +FATE_FILTER_HQX-$(call FILTERDEMDEC, SCALE HQX, IMAGE2, PNG) = fate-filter-hq2x fate-filter-hq3x fate-filter-hq4x FATE_FILTER_SAMPLES-yes += $(FATE_FILTER_HQX-yes) fate-filter-hq2x: CMD = framecrc -i $(TARGET_SAMPLES)/filter/pixelart%d.png -vf scale,format=rgb32,hqx=2,scale,format=bgra fate-filter-hq3x: CMD = framecrc -i $(TARGET_SAMPLES)/filter/pixelart%d.png -vf scale,format=rgb32,hqx=3,scale,format=bgra fate-filter-hq4x: CMD = framecrc -i $(TARGET_SAMPLES)/filter/pixelart%d.png -vf scale,format=rgb32,hqx=4,scale,format=bgra fate-filter-hqx: $(FATE_FILTER_HQX-yes) -FATE_FILTER_XBR-$(call ALLYES, IMAGE2_DEMUXER PNG_DECODER XBR_FILTER) = fate-filter-2xbr fate-filter-3xbr fate-filter-4xbr +FATE_FILTER_XBR-$(call FILTERDEMDEC, SCALE XBR, IMAGE2, PNG) = fate-filter-2xbr fate-filter-3xbr fate-filter-4xbr FATE_FILTER_SAMPLES-yes += $(FATE_FILTER_XBR-yes) fate-filter-2xbr: CMD = framecrc -i $(TARGET_SAMPLES)/filter/pixelart%d.png -vf scale,xbr=2,scale -pix_fmt bgra fate-filter-3xbr: CMD = framecrc -i $(TARGET_SAMPLES)/filter/pixelart%d.png -vf scale,xbr=3,scale -pix_fmt bgra fate-filter-4xbr: CMD = framecrc -i $(TARGET_SAMPLES)/filter/pixelart%d.png -vf scale,xbr=4,scale -pix_fmt bgra fate-filter-xbr: $(FATE_FILTER_XBR-yes) -FATE_FILTER_SAMPLES-$(call ALLYES, UTVIDEO_DECODER AVI_DEMUXER PERMS_FILTER CURVES_FILTER) += fate-filter-curves +FATE_FILTER_SAMPLES-$(call FILTERDEMDEC, PERMS CURVES, AVI, UTVIDEO) += fate-filter-curves fate-filter-curves: CMD = framecrc -i $(TARGET_SAMPLES)/utvideo/utvideo_rgb_median.avi -vf perms=random,curves=vintage -FATE_FILTER_SAMPLES-$(call ALLYES, VMD_DEMUXER VMDVIDEO_DECODER FORMAT_FILTER PERMS_FILTER GRADFUN_FILTER) += fate-filter-gradfun-sample +FATE_FILTER_SAMPLES-$(call FILTERDEMDEC, FORMAT PERMS GRADFUN SCALE, VMD, VMDVIDEO) += fate-filter-gradfun-sample fate-filter-gradfun-sample: tests/data/filtergraphs/gradfun fate-filter-gradfun-sample: CMD = framecrc -auto_conversion_filters -i $(TARGET_SAMPLES)/vmd/12.vmd -filter_script $(TARGET_PATH)/tests/data/filtergraphs/gradfun -an -frames:v 20 -FATE_FILTER-$(call ALLYES, TESTSRC_FILTER SINE_FILTER CONCAT_FILTER) += fate-filter-concat fate-filter-concat-vfr +FATE_FILTER-$(call FILTERFRAMECRC, TESTSRC SINE CONCAT, FILE_PROTOCOL) += fate-filter-concat fate-filter-concat-vfr fate-filter-concat: tests/data/filtergraphs/concat fate-filter-concat: CMD = framecrc -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/concat fate-filter-concat-vfr: tests/data/filtergraphs/concat-vfr fate-filter-concat-vfr: CMD = framecrc -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/concat-vfr -FATE_FILTER-$(call ALLYES, TESTSRC2_FILTER FPS_FILTER MPDECIMATE_FILTER) += fate-filter-mpdecimate +FATE_FILTER-$(call FILTERFRAMECRC, TESTSRC2 CHROMASHIFT) += fate-filter-chromashift-smear fate-filter-chromashift-wrap +fate-filter-chromashift-smear: CMD = framecrc -lavfi testsrc2=r=5:d=1,chromashift=cbh=-1:cbv=1:crh=2:crv=-2:edge=smear -pix_fmt yuv420p +fate-filter-chromashift-wrap: CMD = framecrc -lavfi testsrc2=r=5:d=1,chromashift=cbh=-1:cbv=1:crh=2:crv=-2:edge=wrap -pix_fmt yuv420p + +FATE_FILTER-$(call FILTERFRAMECRC, TESTSRC2 FPS DECIMATE) += fate-filter-decimate +fate-filter-decimate: CMD = framecrc -lavfi testsrc2=r=24:d=10,fps=60,decimate=5,decimate=4,decimate=3 -pix_fmt yuv420p + +FATE_FILTER-$(call FILTERFRAMECRC, TESTSRC2 FPS MPDECIMATE) += 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-start-drop fate-filter-fps-start-fill +FATE_FILTER-$(call FILTERFRAMECRC, FPS TESTSRC2) += $(addprefix fate-filter-fps-, up up-round-down up-round-up down down-round-down down-round-up down-eof-pass start-drop 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 @@ -462,111 +378,86 @@ fate-filter-fps-down-eof-pass: CMD = framecrc -lavfi testsrc2=r=7:d=3.5,fps=3:eo 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_SAMPLES-$(call FILTERDEMDEC, FPS SCALE, MOV, QTRLE) += fate-filter-fps-cfr fate-filter-fps fate-filter-fps-r fate-filter-fps-cfr: CMD = framecrc -auto_conversion_filters -i $(TARGET_SAMPLES)/qtrle/apple-animation-variable-fps-bug.mov -r 30 -vsync cfr -pix_fmt yuv420p fate-filter-fps-r: CMD = framecrc -auto_conversion_filters -i $(TARGET_SAMPLES)/qtrle/apple-animation-variable-fps-bug.mov -r 30 -vf fps -pix_fmt yuv420p fate-filter-fps: CMD = framecrc -auto_conversion_filters -i $(TARGET_SAMPLES)/qtrle/apple-animation-variable-fps-bug.mov -vf fps=30 -pix_fmt yuv420p -FATE_FILTER_VSYNTH-$(call ALLYES, FORMAT_FILTER SPLIT_FILTER ALPHAEXTRACT_FILTER ALPHAMERGE_FILTER) += fate-filter-alphaextract_alphamerge_rgb -fate-filter-alphaextract_alphamerge_rgb: tests/data/filtergraphs/alphamerge_alphaextract_rgb -fate-filter-alphaextract_alphamerge_rgb: CMD = framecrc -auto_conversion_filters -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/alphamerge_alphaextract_rgb +FATE_FILTER_ALPHAEXTRACT_ALPHAMERGE := $(addprefix fate-filter-alphaextract_alphamerge_, rgb yuv) +FATE_FILTER_VSYNTH_PGMYUV-$(call ALLYES, SCALE_FILTER FORMAT_FILTER SPLIT_FILTER ALPHAEXTRACT_FILTER ALPHAMERGE_FILTER) += $(FATE_FILTER_ALPHAEXTRACT_ALPHAMERGE) +$(FATE_FILTER_ALPHAEXTRACT_ALPHAMERGE): fate-filter-alphaextract_alphamerge_%: tests/data/filtergraphs/alphamerge_alphaextract_% +$(FATE_FILTER_ALPHAEXTRACT_ALPHAMERGE): CMD = framecrc -auto_conversion_filters -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/alphamerge_alphaextract$(@:fate-filter-alphaextract_alphamerge%=%) -FATE_FILTER_VSYNTH-$(call ALLYES, FORMAT_FILTER SPLIT_FILTER ALPHAEXTRACT_FILTER ALPHAMERGE_FILTER) += fate-filter-alphaextract_alphamerge_yuv -fate-filter-alphaextract_alphamerge_yuv: tests/data/filtergraphs/alphamerge_alphaextract_yuv -fate-filter-alphaextract_alphamerge_yuv: CMD = framecrc -auto_conversion_filters -c:v pgmyuv -i $(SRC) -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/alphamerge_alphaextract_yuv - -FATE_FILTER_VSYNTH-$(CONFIG_CROP_FILTER) += fate-filter-crop +FATE_FILTER_VSYNTH_VIDEO_FILTER-$(CONFIG_CROP_FILTER) += fate-filter-crop fate-filter-crop: CMD = video_filter "crop=iw-100:ih-100:100:100" -FATE_FILTER_VSYNTH-$(call ALLYES, CROP_FILTER SCALE_FILTER) += fate-filter-crop_scale +FATE_FILTER_VSYNTH_VIDEO_FILTER-$(call ALLYES, CROP_FILTER SCALE_FILTER) += fate-filter-crop_scale fate-filter-crop_scale: CMD = video_filter "crop=iw-100:ih-100:100:100,scale=w=400:h=-1" -FATE_FILTER_VSYNTH-$(call ALLYES, CROP_FILTER SCALE_FILTER VFLIP_FILTER) += fate-filter-crop_scale_vflip +FATE_FILTER_VSYNTH_VIDEO_FILTER-$(call ALLYES, CROP_FILTER SCALE_FILTER VFLIP_FILTER) += fate-filter-crop_scale_vflip fate-filter-crop_scale_vflip: CMD = video_filter "null,null,crop=iw-200:ih-200:200:200,crop=iw-20:ih-20:20:20,scale=w=200:h=200,scale=w=250:h=250,vflip,vflip,null,scale=w=200:h=200,crop=iw-100:ih-100:100:100,vflip,scale=w=200:h=200,null,vflip,crop=iw-100:ih-100:100:100,null" -FATE_FILTER_VSYNTH-$(call ALLYES, CROP_FILTER VFLIP_FILTER) += fate-filter-crop_vflip +FATE_FILTER_VSYNTH_VIDEO_FILTER-$(call ALLYES, CROP_FILTER VFLIP_FILTER) += fate-filter-crop_vflip fate-filter-crop_vflip: CMD = video_filter "crop=iw-100:ih-100:100:100,vflip" -FATE_FILTER_VSYNTH-$(CONFIG_NULL_FILTER) += fate-filter-null +FATE_FILTER_VSYNTH_VIDEO_FILTER-$(CONFIG_NULL_FILTER) += fate-filter-null fate-filter-null: CMD = video_filter "null" -FATE_FILTER_VSYNTH-$(CONFIG_SCALE_FILTER) += fate-filter-scale200 +FATE_FILTER_VSYNTH_VIDEO_FILTER-$(CONFIG_SCALE_FILTER) += fate-filter-scale200 fate-filter-scale200: CMD = video_filter "scale=w=200:h=200" -FATE_FILTER_VSYNTH-$(CONFIG_SCALE_FILTER) += fate-filter-scale500 +FATE_FILTER_VSYNTH_VIDEO_FILTER-$(CONFIG_SCALE_FILTER) += fate-filter-scale500 fate-filter-scale500: CMD = video_filter "scale=w=500:h=500" -FATE_FILTER_VSYNTH-$(CONFIG_SCALE2REF_FILTER) += fate-filter-scale2ref_keep_aspect +FATE_FILTER_VSYNTH-$(call ALLYES, TESTSRC_FILTER SCALE2REF_FILTER NULLSINK_FILTER FRAMEMD5_MUXER FILE_PROTOCOL PIPE_PROTOCOL) += fate-filter-scale2ref_keep_aspect fate-filter-scale2ref_keep_aspect: tests/data/filtergraphs/scale2ref_keep_aspect fate-filter-scale2ref_keep_aspect: CMD = framemd5 -frames:v 5 -filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/scale2ref_keep_aspect -map "[main]" -FATE_FILTER_VSYNTH-$(CONFIG_SCALE_FILTER) += fate-filter-scalechroma +FATE_FILTER_VSYNTH-$(call FILTERDEMDEC, SCALE, RAWVIDEO, RAWVIDEO) += fate-filter-scalechroma fate-filter-scalechroma: tests/data/vsynth1.yuv fate-filter-scalechroma: CMD = framecrc -flags bitexact -s 352x288 -pix_fmt yuv444p -i $(TARGET_PATH)/tests/data/vsynth1.yuv -pix_fmt yuv420p -sws_flags +bitexact -vf scale=out_v_chr_pos=33:out_h_chr_pos=151 -FATE_FILTER_VSYNTH-$(CONFIG_VFLIP_FILTER) += fate-filter-vflip +FATE_FILTER_VSYNTH_VIDEO_FILTER-$(CONFIG_VFLIP_FILTER) += fate-filter-vflip fate-filter-vflip: CMD = video_filter "vflip" -FATE_FILTER_VSYNTH-$(CONFIG_COLORLEVELS_FILTER) += fate-filter-colorlevels +FATE_FILTER_VSYNTH_PGMYUV-$(call ALLYES, SCALE_FILTER FORMAT_FILTER COLORLEVELS_FILTER) += fate-filter-colorlevels fate-filter-colorlevels-16 fate-filter-colorlevels: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf scale,format=rgb24,colorlevels -flags +bitexact -sws_flags +accurate_rnd+bitexact - -FATE_FILTER_VSYNTH-$(CONFIG_COLORLEVELS_FILTER) += fate-filter-colorlevels-16 fate-filter-colorlevels-16: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf scale,format=rgb48,colorlevels,scale -pix_fmt rgb48le -flags +bitexact -sws_flags +accurate_rnd+bitexact -FATE_FILTER_VSYNTH-$(CONFIG_COLORBALANCE_FILTER) += fate-filter-colorbalance +FATE_FILTER_VSYNTH_PGMYUV-$(call ALLYES, SCALE_FILTER FORMAT_FILTER COLORBALANCE_FILTER) += fate-filter-colorbalance fate-filter-colorbalance-gbrap fate-filter-colorbalance-rgba64 fate-filter-colorbalance-gbrap-16 fate-filter-colorbalance: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf scale,format=rgb24,colorbalance=rs=.2 -flags +bitexact -sws_flags +accurate_rnd+bitexact -frames:v 3 - -FATE_FILTER_VSYNTH-$(CONFIG_COLORBALANCE_FILTER) += fate-filter-colorbalance-gbrap fate-filter-colorbalance-gbrap: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf scale,format=gbrap,colorbalance=gh=.2 -flags +bitexact -sws_flags +accurate_rnd+bitexact -frames:v 3 - -FATE_FILTER_VSYNTH-$(CONFIG_COLORBALANCE_FILTER) += fate-filter-colorbalance-rgba64 fate-filter-colorbalance-rgba64: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf scale,format=rgba64,colorbalance=rm=.2,scale -pix_fmt rgba64le -flags +bitexact -sws_flags +accurate_rnd+bitexact -frames:v 3 - -FATE_FILTER_VSYNTH-$(CONFIG_COLORBALANCE_FILTER) += fate-filter-colorbalance-gbrap-16 fate-filter-colorbalance-gbrap-16: CMD = framecrc -c:v pgmyuv -i $(SRC) -vf scale,format=gbrap,colorbalance=bh=.2 -pix_fmt gbrap -flags +bitexact -sws_flags +accurate_rnd+bitexact -frames:v 3 -FATE_FILTER_VSYNTH-$(CONFIG_COLORMATRIX_FILTER) += fate-filter-colormatrix1 +FATE_FILTER_VSYNTH_VIDEO_FILTER-$(CONFIG_COLORMATRIX_FILTER) += fate-filter-colormatrix1 fate-filter-colormatrix2 fate-filter-colormatrix1: CMD = video_filter "colormatrix=bt601:smpte240m,colormatrix=smpte240m:fcc,colormatrix=fcc:bt601,colormatrix=bt601:fcc,colormatrix=fcc:smpte240m,colormatrix=smpte240m:bt709" - -FATE_FILTER_VSYNTH-$(CONFIG_COLORMATRIX_FILTER) += fate-filter-colormatrix2 fate-filter-colormatrix2: CMD = video_filter "colormatrix=bt709:fcc,colormatrix=fcc:bt709,colormatrix=bt709:bt601,colormatrix=bt601:bt709,colormatrix=bt709:smpte240m,colormatrix=smpte240m:bt601" -FATE_FILTER_VSYNTH-$(call ALLYES, CROP_FILTER VFLIP_FILTER) += fate-filter-vflip_crop +FATE_FILTER_VSYNTH_VIDEO_FILTER-$(call ALLYES, CROP_FILTER VFLIP_FILTER) += fate-filter-vflip_crop fate-filter-vflip_crop: CMD = video_filter "vflip,crop=iw-100:ih-100:100:100" -FATE_FILTER_VSYNTH-$(CONFIG_VFLIP_FILTER) += fate-filter-vflip_vflip +FATE_FILTER_VSYNTH_VIDEO_FILTER-$(CONFIG_VFLIP_FILTER) += fate-filter-vflip_vflip fate-filter-vflip_vflip: CMD = video_filter "vflip,vflip" -FATE_FILTER_VSYNTH-$(call ALLYES, FORMAT_FILTER PERMS_FILTER EDGEDETECT_FILTER) += fate-filter-edgedetect +FATE_FILTER_VSYNTH_VIDEO_FILTER-$(call ALLYES, SCALE_FILTER FORMAT_FILTER PERMS_FILTER EDGEDETECT_FILTER) += fate-filter-edgedetect fate-filter-edgedetect-colormix fate-filter-edgedetect: CMD = video_filter "scale,format=gray,perms=random,edgedetect" -frames:v 20 - -FATE_FILTER_VSYNTH-$(call ALLYES, FORMAT_FILTER PERMS_FILTER EDGEDETECT_FILTER) += fate-filter-edgedetect-colormix fate-filter-edgedetect-colormix: CMD = video_filter "scale,format=gbrp,perms=random,edgedetect=mode=colormix" -frames:v 20 -FATE_FILTER_VSYNTH-$(call ALLYES, PERMS_FILTER HUE_FILTER) += fate-filter-hue1 +FATE_FILTER_VSYNTH_VIDEO_FILTER-$(call ALLYES, PERMS_FILTER HUE_FILTER) += fate-filter-hue1 fate-filter-hue2 fate-filter-hue3 fate-filter-hue1: CMD = video_filter "perms=random,hue=s=sin(2*PI*t)+1" -frames:v 20 - -FATE_FILTER_VSYNTH-$(call ALLYES, PERMS_FILTER HUE_FILTER) += fate-filter-hue2 fate-filter-hue2: CMD = video_filter "perms=random,hue=h=18*n" -frames:v 20 - -FATE_FILTER_VSYNTH-$(call ALLYES, PERMS_FILTER HUE_FILTER) += fate-filter-hue3 fate-filter-hue3: CMD = video_filter "perms=random,hue=b=n-10" -frames:v 20 -FATE_FILTER_VSYNTH-$(call ALLYES, FORMAT_FILTER PERMS_FILTER HUE_FILTER) += fate-filter-hue4 +FATE_FILTER_VSYNTH_VIDEO_FILTER-$(call ALLYES, SCALE_FILTER FORMAT_FILTER PERMS_FILTER HUE_FILTER) += fate-filter-hue4 fate-filter-hue4: CMD = video_filter "scale,format=yuv422p10,perms=random,hue=h=18*n:s=n/10,scale" -frames:v 20 -pix_fmt yuv422p10le -FATE_FILTER_VSYNTH-$(CONFIG_IDET_FILTER) += fate-filter-idet +FATE_FILTER_VSYNTH-$(call FILTERDEMDEC, IDET, IMAGE2, PGM) += fate-filter-idet fate-filter-idet: CMD = framecrc -flags bitexact -idct simple -i $(SRC) -vf idet -frames:v 25 -flags +bitexact -FATE_FILTER_VSYNTH-$(CONFIG_PAD_FILTER) += fate-filter-pad +FATE_FILTER_VSYNTH_VIDEO_FILTER-$(CONFIG_PAD_FILTER) += fate-filter-pad fate-filter-pad: CMD = video_filter "pad=iw*1.5:ih*1.5:iw*0.3:ih*0.2" -FATE_FILTER_PP = fate-filter-pp fate-filter-pp1 fate-filter-pp2 fate-filter-pp3 fate-filter-pp4 fate-filter-pp5 fate-filter-pp6 -FATE_FILTER_VSYNTH-$(CONFIG_PP_FILTER) += $(FATE_FILTER_PP) -$(FATE_FILTER_PP): fate-vsynth1-mpeg4-qprd -fate-vsynth1-mpeg4-qprd: KEEP_OVERRIDE= -keep - -fate-filter-pp: CMD = framecrc -flags bitexact -export_side_data venc_params -idct simple -i $(TARGET_PATH)/tests/data/fate/vsynth1-mpeg4-qprd.avi -frames:v 5 -flags +bitexact -vf "pp=be/hb/vb/tn/l5/al" fate-filter-pp1: CMD = video_filter "pp=fq|4/be/hb/vb/tn/l5/al" fate-filter-pp2: CMD = video_filter "qp=2*(x+y),pp=be/h1/v1/lb" fate-filter-pp3: CMD = video_filter "qp=2*(x+y),pp=be/ha|128|7/va/li" @@ -574,103 +465,59 @@ fate-filter-pp4: CMD = video_filter "pp=be/ci" fate-filter-pp5: CMD = video_filter "pp=md" fate-filter-pp6: CMD = video_filter "pp=be/fd" -FATE_FILTER_VSYNTH-$(CONFIG_PP7_FILTER) += fate-filter-pp7 -fate-filter-pp7: fate-vsynth1-mpeg4-qprd +FATE_FILTER_VSYNTH_VIDEO_FILTER-$(CONFIG_PP_FILTER) += $(addprefix fate-filter-, pp1 pp4 pp5 pp6) +FATE_FILTER_VSYNTH_VIDEO_FILTER-$(call ALLYES, PP_FILTER QP_FILTER) += fate-filter-pp2 fate-filter-pp3 + +FATE_FILTER_VSYNTH1_MPEG4_QPRD-$(call FILTERDEMDEC, PP, AVI, MPEG4) += pp +fate-filter-pp: CMD = framecrc -flags bitexact -export_side_data venc_params -idct simple -i $(TARGET_PATH)/tests/data/fate/vsynth1-mpeg4-qprd.avi -frames:v 5 -flags +bitexact -vf "pp=be/hb/vb/tn/l5/al" + +FATE_FILTER_VSYNTH1_MPEG4_QPRD-$(call FILTERDEMDEC, PP7, AVI, MPEG4) += pp7 fate-filter-pp7: CMD = framecrc -flags bitexact -export_side_data venc_params -idct simple -i $(TARGET_PATH)/tests/data/fate/vsynth1-mpeg4-qprd.avi -frames:v 5 -flags +bitexact -vf "pp7" -FATE_FILTER_VSYNTH-$(CONFIG_SPP_FILTER) += fate-filter-spp -fate-filter-spp: fate-vsynth1-mpeg4-qprd +FATE_FILTER_VSYNTH1_MPEG4_QPRD-$(call FILTERDEMDEC, SPP, AVI, MPEG4) += spp fate-filter-spp: CMD = framecrc -flags bitexact -export_side_data venc_params -idct simple -i $(TARGET_PATH)/tests/data/fate/vsynth1-mpeg4-qprd.avi -frames:v 5 -flags +bitexact -vf "spp=idct=simple:dct=int" -FATE_FILTER_VSYNTH-$(CONFIG_CODECVIEW_FILTER) += fate-filter-codecview -fate-filter-codecview: fate-vsynth1-mpeg4-qprd +FATE_FILTER_VSYNTH1_MPEG4_QPRD-$(call FILTERDEMDEC, PP, AVI, MPEG4) += codecview fate-filter-codecview: CMD = framecrc -flags bitexact -idct simple -flags2 +export_mvs -i $(TARGET_PATH)/tests/data/fate/vsynth1-mpeg4-qprd.avi -frames:v 5 -flags +bitexact -vf codecview=mv=pf+bf+bb -FATE_FILTER_VSYNTH-$(call ALLYES, QP_FILTER PP_FILTER) += fate-filter-qp +# The above tests use vsynth1-mpeg4-qprd.avi created by fate-vsynth1-mpeg4-qprd +# as input. So only add them if all the requirements of fate-vsynth1-mpeg4-qprd +# are met, add a dependency to the test and ensure that the file is kept. +FATE_FILTER_VSYNTH1_MPEG4_QPRD := $(if $(filter fate-vsynth1-mpeg4-qprd, $(FATE_VSYNTH1)),$(addprefix fate-filter-, $(FATE_FILTER_VSYNTH1_MPEG4_QPRD-yes))) +FATE_FILTER_VSYNTH-yes += $(FATE_FILTER_VSYNTH1_MPEG4_QPRD) +$(FATE_FILTER_VSYNTH1_MPEG4_QPRD): fate-vsynth1-mpeg4-qprd +fate-vsynth1-mpeg4-qprd: KEEP_FILES ?= 1 + +FATE_FILTER_VSYNTH_VIDEO_FILTER-$(call ALLYES, QP_FILTER PP_FILTER) += fate-filter-qp fate-filter-qp: CMD = video_filter "qp=34,pp=be/hb/vb/tn/l5/al" -FATE_FILTER_VSYNTH-$(CONFIG_SELECT_FILTER) += fate-filter-select +FATE_FILTER_VSYNTH-$(call FILTERDEMDEC, SELECT, IMAGE2, PGM) += fate-filter-select fate-filter-select: CMD = framecrc -flags bitexact -idct simple -i $(SRC) -vf "select=not(eq(mod(n\,2)\,0)+eq(mod(n\,3)\,0))" -frames:v 25 -flags +bitexact -FATE_FILTER_VSYNTH-$(CONFIG_SETDAR_FILTER) += fate-filter-setdar +FATE_FILTER_VSYNTH_VIDEO_FILTER-$(CONFIG_SETDAR_FILTER) += fate-filter-setdar fate-filter-setdar: CMD = video_filter "setdar=dar=16/9" -FATE_FILTER_VSYNTH-$(CONFIG_SETSAR_FILTER) += fate-filter-setsar +FATE_FILTER_VSYNTH_VIDEO_FILTER-$(CONFIG_SETSAR_FILTER) += fate-filter-setsar fate-filter-setsar: CMD = video_filter "setsar=sar=16/11" -FATE_STEREO3D += fate-filter-stereo3d-al-sbsl -fate-filter-stereo3d-al-sbsl: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=al:sbsl +FATE_STEREO3D := al-sbsl ar-abl abr-mr abr-ml sbsl-abl sbsl-abr sbsl-al sbsl-sbsr +FATE_STEREO3D := $(addprefix fate-filter-stereo3d-, $(FATE_STEREO3D)) +$(FATE_STEREO3D): CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -vf stereo3d=$(word 4, $(subst -, ,$(@))):$(word 5, $(subst -, ,$(@))) +FATE_STEREO3D-$(call FILTERDEMDEC, STEREO3D, IMAGE2, PGMYUV) += $(FATE_STEREO3D) -FATE_STEREO3D += fate-filter-stereo3d-ar-abl -fate-filter-stereo3d-ar-abl: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=ar:abl +FATE_STEREO3D_ANAGLYPH := agmc agmd agmg agmh arbg arcc arcd arcg arch argg \ + aybc aybd aybg aybh +FATE_STEREO3D_ANAGLYPH := $(addprefix fate-filter-stereo3d-sbsl-, $(FATE_STEREO3D_ANAGLYPH)) +$(FATE_STEREO3D_ANAGLYPH): CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=$(word 4, $(subst -, ,$(@))):$(word 5, $(subst -, ,$(@))) +FATE_STEREO3D-$(call FILTERDEMDEC, SCALE STEREO3D, IMAGE2, PGMYUV) += $(FATE_STEREO3D_ANAGLYPH) -FATE_STEREO3D += fate-filter-stereo3d-abr-mr -fate-filter-stereo3d-abr-mr: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=abr:mr +fate-filter-stereo3d: $(FATE_STEREO3D-yes) +FATE_FILTER_VSYNTH-yes += $(FATE_STEREO3D-yes) -FATE_STEREO3D += fate-filter-stereo3d-abr-ml -fate-filter-stereo3d-abr-ml: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=abr:ml - -FATE_STEREO3D += fate-filter-stereo3d-sbsl-abl -fate-filter-stereo3d-sbsl-abl: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=sbsl:abl - -FATE_STEREO3D += fate-filter-stereo3d-sbsl-abr -fate-filter-stereo3d-sbsl-abr: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=sbsl:abr - -FATE_STEREO3D += fate-filter-stereo3d-sbsl-al -fate-filter-stereo3d-sbsl-al: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=sbsl:al - -FATE_STEREO3D += fate-filter-stereo3d-sbsl-sbsr -fate-filter-stereo3d-sbsl-sbsr: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=sbsl:sbsr - -FATE_STEREO3D += fate-filter-stereo3d-sbsl-agmc -fate-filter-stereo3d-sbsl-agmc: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=sbsl:agmc - -FATE_STEREO3D += fate-filter-stereo3d-sbsl-agmd -fate-filter-stereo3d-sbsl-agmd: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=sbsl:agmd - -FATE_STEREO3D += fate-filter-stereo3d-sbsl-agmg -fate-filter-stereo3d-sbsl-agmg: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=sbsl:agmg - -FATE_STEREO3D += fate-filter-stereo3d-sbsl-agmh -fate-filter-stereo3d-sbsl-agmh: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=sbsl:agmh - -FATE_STEREO3D += fate-filter-stereo3d-sbsl-arbg -fate-filter-stereo3d-sbsl-arbg: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=sbsl:arbg - -FATE_STEREO3D += fate-filter-stereo3d-sbsl-arcc -fate-filter-stereo3d-sbsl-arcc: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=sbsl:arcc - -FATE_STEREO3D += fate-filter-stereo3d-sbsl-arcd -fate-filter-stereo3d-sbsl-arcd: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=sbsl:arcd - -FATE_STEREO3D += fate-filter-stereo3d-sbsl-arcg -fate-filter-stereo3d-sbsl-arcg: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=sbsl:arcg - -FATE_STEREO3D += fate-filter-stereo3d-sbsl-arch -fate-filter-stereo3d-sbsl-arch: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=sbsl:arch - -FATE_STEREO3D += fate-filter-stereo3d-sbsl-argg -fate-filter-stereo3d-sbsl-argg: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=sbsl:argg - -FATE_STEREO3D += fate-filter-stereo3d-sbsl-aybc -fate-filter-stereo3d-sbsl-aybc: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=sbsl:aybc - -FATE_STEREO3D += fate-filter-stereo3d-sbsl-aybd -fate-filter-stereo3d-sbsl-aybd: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=sbsl:aybd - -FATE_STEREO3D += fate-filter-stereo3d-sbsl-aybg -fate-filter-stereo3d-sbsl-aybg: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=sbsl:aybg - -FATE_STEREO3D += fate-filter-stereo3d-sbsl-aybh -fate-filter-stereo3d-sbsl-aybh: CMD = framecrc -c:v pgmyuv -i $(SRC) -frames:v 5 -flags +bitexact -sws_flags +accurate_rnd+bitexact -vf scale,stereo3d=sbsl:aybh - -fate-filter-stereo3d: $(FATE_STEREO3D) -FATE_FILTER_VSYNTH-$(CONFIG_STEREO3D_FILTER) += $(FATE_STEREO3D) - -FATE_FILTER_VSYNTH-$(CONFIG_THUMBNAIL_FILTER) += fate-filter-thumbnail +FATE_FILTER_VSYNTH_VIDEO_FILTER-$(call ALLYES, SCALE_FILTER THUMBNAIL_FILTER) += fate-filter-thumbnail fate-filter-thumbnail: CMD = video_filter "scale,thumbnail=10" -FATE_FILTER_VSYNTH-$(CONFIG_TILE_FILTER) += fate-filter-tile +FATE_FILTER_VSYNTH_VIDEO_FILTER-$(CONFIG_TILE_FILTER) += fate-filter-tile fate-filter-tile: CMD = video_filter "tile=3x3:nb_frames=5:padding=7:margin=2" @@ -686,12 +533,8 @@ ifneq (,$(RUNNING_PIXFMTS_TESTS)) -include tests/pixfmts.mak endif -define PIXDESC_TEST -FATE_FILTER_PIXDESC-$(CONFIG_FORMAT_FILTER) += fate-filter-pixdesc-$(1) -fate-filter-pixdesc-$(1): CMD = video_filter "scale,format=$(1),pixdesctest" -pix_fmt $(1) -endef - -$(foreach fmt, $(PIXFMTS), $(eval $(call PIXDESC_TEST,$(fmt)))) +FATE_FILTER_PIXDESC-$(call VIDEO_FILTER, SCALE FORMAT PIXDESCTEST) += $(addprefix fate-filter-pixdesc-, $(PIXFMTS)) +fate-filter-pixdesc-%: CMD = video_filter "scale,format=$(@:fate-filter-pixdesc-%=%),pixdesctest" -pix_fmt $(@:fate-filter-pixdesc-%=%) fate-filter-pixdesc: $(FATE_FILTER_PIXDESC-yes) FATE_FILTER_VSYNTH-yes += $(FATE_FILTER_PIXDESC-yes) @@ -766,59 +609,64 @@ 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 -$(FATE_FILTER_PIXFMTS-yes): libavfilter/tests/filtfmts$(EXESUF) -FATE_FILTER_VSYNTH-$(CONFIG_FORMAT_FILTER) += $(FATE_FILTER_PIXFMTS-yes) +# pixfmts uses video_filter internally and also adds format and scale filters. +FATE_FILTER_PIXFMTS := $(if $(call VIDEO_FILTER, FORMAT SCALE),$(FATE_FILTER_PIXFMTS-yes)) -fate-filter-pixfmts: $(FATE_FILTER_PIXFMTS-yes) +$(FATE_FILTER_PIXFMTS): libavfilter/tests/filtfmts$(EXESUF) +FATE_FILTER_VSYNTH-yes += $(FATE_FILTER_PIXFMTS) +fate-filter-pixfmts: $(FATE_FILTER_PIXFMTS) + +FATE_FILTER_VSYNTH-$(call VIDEO_FILTER) += $(FATE_FILTER_VSYNTH_VIDEO_FILTER-yes) +FATE_FILTER_VSYNTH-$(call FRAMECRC, IMAGE2, PGMYUV) += $(FATE_FILTER_VSYNTH_PGMYUV-yes) $(FATE_FILTER_VSYNTH-yes): $(VREF) $(FATE_FILTER_VSYNTH-yes): SRC = $(TARGET_PATH)/tests/vsynth1/%02d.pgm -FATE_AVCONV-$(call DEMDEC, IMAGE2, PGMYUV) += $(FATE_FILTER_VSYNTH-yes) +FATE_FFMPEG += $(FATE_FILTER_VSYNTH-yes) # # Metadata tests # FILTER_METADATA_COMMAND = ffprobe$(PROGSSUF)$(EXESUF) -of compact=p=0 -show_entries frame=pts:frame_tags -bitexact -f lavfi -SCENEDETECT_DEPS = FFPROBE LAVFI_INDEV MOVIE_FILTER SELECT_FILTER SCALE_FILTER \ - AVCODEC AVDEVICE MOV_DEMUXER SVQ3_DECODER ZLIB +SCENEDETECT_DEPS = LAVFI_INDEV FILE_PROTOCOL MOVIE_FILTER SELECT_FILTER \ + SCALE_FILTER MOV_DEMUXER SVQ3_DECODER ZLIB FATE_METADATA_FILTER-$(call ALLYES, $(SCENEDETECT_DEPS)) += fate-filter-metadata-scenedetect fate-filter-metadata-scenedetect: SRC = $(TARGET_SAMPLES)/svq3/Vertical400kbit.sorenson3.mov fate-filter-metadata-scenedetect: CMD = run $(FILTER_METADATA_COMMAND) "sws_flags=+accurate_rnd+bitexact;movie='$(SRC)',select=gt(scene\,.25)" -SCDET_DEPS = FFPROBE LAVFI_INDEV MOVIE_FILTER SCDET_FILTER SCALE_FILTER \ - AVCODEC AVDEVICE MOV_DEMUXER SVQ3_DECODER ZLIB +SCDET_DEPS = LAVFI_INDEV FILE_PROTOCOL MOVIE_FILTER SCDET_FILTER SCALE_FILTER \ + MOV_DEMUXER SVQ3_DECODER ZLIB FATE_METADATA_FILTER-$(call ALLYES, $(SCDET_DEPS)) += fate-filter-metadata-scdet fate-filter-metadata-scdet: SRC = $(TARGET_SAMPLES)/svq3/Vertical400kbit.sorenson3.mov fate-filter-metadata-scdet: CMD = run $(FILTER_METADATA_COMMAND) "sws_flags=+accurate_rnd+bitexact;movie='$(SRC)',scdet=s=1" -CROPDETECT_DEPS = FFPROBE LAVFI_INDEV MOVIE_FILTER CROPDETECT_FILTER SCALE_FILTER \ - AVCODEC AVDEVICE MOV_DEMUXER H264_DECODER +CROPDETECT_DEPS = LAVFI_INDEV FILE_PROTOCOL MOVIE_FILTER CROPDETECT_FILTER \ + SCALE_FILTER MOV_DEMUXER H264_DECODER FATE_METADATA_FILTER-$(call ALLYES, $(CROPDETECT_DEPS)) += fate-filter-metadata-cropdetect 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" -FREEZEDETECT_DEPS = FFPROBE AVDEVICE LAVFI_INDEV MPTESTSRC_FILTER SCALE_FILTER FREEZEDETECT_FILTER +FREEZEDETECT_DEPS = LAVFI_INDEV MPTESTSRC_FILTER SCALE_FILTER FREEZEDETECT_FILTER FATE_METADATA_FILTER-$(call ALLYES, $(FREEZEDETECT_DEPS)) += fate-filter-metadata-freezedetect fate-filter-metadata-freezedetect: CMD = run $(FILTER_METADATA_COMMAND) "sws_flags=+accurate_rnd+bitexact;mptestsrc=r=25:d=10:m=51,freezedetect" -SIGNALSTATS_DEPS = FFPROBE AVDEVICE LAVFI_INDEV COLOR_FILTER SCALE_FILTER SIGNALSTATS_FILTER +SIGNALSTATS_DEPS = LAVFI_INDEV COLOR_FILTER SCALE_FILTER SIGNALSTATS_FILTER FATE_METADATA_FILTER-$(call ALLYES, $(SIGNALSTATS_DEPS)) += fate-filter-metadata-signalstats-yuv420p fate-filter-metadata-signalstats-yuv420p10 fate-filter-metadata-signalstats-yuv420p: CMD = run $(FILTER_METADATA_COMMAND) "sws_flags=+accurate_rnd+bitexact;color=white:duration=1:r=1,signalstats" fate-filter-metadata-signalstats-yuv420p10: CMD = run $(FILTER_METADATA_COMMAND) "sws_flags=+accurate_rnd+bitexact;color=white:duration=1:r=1,format=yuv420p10,signalstats" -SILENCEDETECT_DEPS = FFPROBE AVDEVICE LAVFI_INDEV AMOVIE_FILTER TTA_DEMUXER TTA_DECODER SILENCEDETECT_FILTER +SILENCEDETECT_DEPS = LAVFI_INDEV FILE_PROTOCOL 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)/lossless-audio/inside.tta fate-filter-metadata-silencedetect: CMD = run $(FILTER_METADATA_COMMAND) "amovie='$(SRC)',silencedetect=n=-33.5dB:d=0.2" -EBUR128_METADATA_DEPS = FFPROBE AVDEVICE LAVFI_INDEV AMOVIE_FILTER FLAC_DEMUXER FLAC_DECODER EBUR128_FILTER +EBUR128_METADATA_DEPS = LAVFI_INDEV FILE_PROTOCOL AMOVIE_FILTER FLAC_DEMUXER FLAC_DECODER ARESAMPLE_FILTER EBUR128_FILTER FATE_METADATA_FILTER-$(call ALLYES, $(EBUR128_METADATA_DEPS)) += fate-filter-metadata-ebur128 fate-filter-metadata-ebur128: SRC = $(TARGET_SAMPLES)/filter/seq-3341-7_seq-3342-5-24bit.flac fate-filter-metadata-ebur128: CMD = run $(FILTER_METADATA_COMMAND) "amovie='$(SRC)',ebur128=metadata=1" -READVITC_METADATA_DEPS = FFPROBE LAVFI_INDEV MOVIE_FILTER AVCODEC AVDEVICE \ +READVITC_METADATA_DEPS = FILE_PROTOCOL LAVFI_INDEV MOVIE_FILTER \ AVI_DEMUXER FFVHUFF_DECODER READVITC_FILTER FATE_METADATA_FILTER-$(call ALLYES, $(READVITC_METADATA_DEPS)) += fate-filter-metadata-readvitc-def fate-filter-metadata-readvitc-def: SRC = $(TARGET_SAMPLES)/filter/sample-vitc.avi @@ -828,37 +676,45 @@ FATE_METADATA_FILTER-$(call ALLYES, $(READVITC_METADATA_DEPS)) += fate-filter-me fate-filter-metadata-readvitc-thr: SRC = $(TARGET_SAMPLES)/filter/sample-vitc.avi fate-filter-metadata-readvitc-thr: CMD = run $(FILTER_METADATA_COMMAND) "movie='$(SRC)',readvitc=thr_b=0.3:thr_w=0.5" -AVF_PHASE_METER_DEPS = FFPROBE AVDEVICE LAVFI_INDEV AMOVIE_FILTER FLAC_DEMUXER FLAC_DECODER SINE_FILTER APHASEMETER_FILTER +AVF_PHASE_METER_DEPS = FFPROBE LAVFI_INDEV AMOVIE_FILTER FLAC_DEMUXER FLAC_DECODER SINE_FILTER APHASEMETER_FILTER ARESAMPLE_FILTER FATE_METADATA_FILTER-$(call ALLYES, $(AVF_PHASE_METER_DEPS)) += fate-filter-metadata-avf-aphase-meter-mono fate-filter-metadata-avf-aphase-meter-mono: CMD = run $(FILTER_METADATA_COMMAND) sine="frequency=1000:sample_rate=48000:duration=1,aphasemeter=video=0" -FATE_METADATA_FILTER-$(call ALLYES, $(AVF_PHASE_METER_DEPS)) += fate-filter-metadata-avf-aphase-meter-out-of-phase +FATE_METADATA_FILTER-$(call ALLYES, $(AVF_PHASE_METER_DEPS) FILE_PROTOCOL) += fate-filter-metadata-avf-aphase-meter-out-of-phase fate-filter-metadata-avf-aphase-meter-out-of-phase: SRC = $(TARGET_SAMPLES)/filter/out-of-phase-1000hz.flac fate-filter-metadata-avf-aphase-meter-out-of-phase: CMD = run $(FILTER_METADATA_COMMAND) "amovie='$(SRC)',aphasemeter=video=0" -tests/data/file4560-override2rotate0.mov: TAG = GEN -tests/data/file4560-override2rotate0.mov: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ - -i $(TARGET_SAMPLES)/filter/sample-in-issue-505.mov -c copy -flags +bitexact -metadata:s:v:0 rotate=0 $(TARGET_PATH)/$@ -y 2>/dev/null +FATE_FILTER_SAMPLES-$(call TRANSCODE, RAWVIDEO H264, MOV, ARESAMPLE_FILTER AAC_FIXED_DECODER) += fate-filter-meta-4560-rotate0 +fate-filter-meta-4560-rotate0: CMD = transcode mov $(TARGET_SAMPLES)/filter/sample-in-issue-505.mov mov "-c copy -metadata:s:v:0 rotate=0" "-af aresample" "" "" "-flags +bitexact -c:a aac_fixed" -FATE_FILTER_SAMPLES-$(call ALLYES, MOV_DEMUXER H264_DECODER AAC_FIXED_DECODER PCM_S16LE_ENCODER MOV_MUXER) += fate-filter-meta-4560-rotate0 -fate-filter-meta-4560-rotate0: tests/data/file4560-override2rotate0.mov -fate-filter-meta-4560-rotate0: CMD = framecrc -auto_conversion_filters -flags +bitexact -c:a aac_fixed -i $(TARGET_PATH)/tests/data/file4560-override2rotate0.mov +FATE_FILTER_CMP_METADATA-$(CONFIG_BLOCKDETECT_FILTER) += fate-filter-refcmp-blockdetect-yuv +fate-filter-refcmp-blockdetect-yuv: CMD = cmp_metadata blockdetect yuv420p 0.015 -REFCMP_DEPS = FFMPEG LAVFI_INDEV TESTSRC2_FILTER AVGBLUR_FILTER METADATA_FILTER +FATE_FILTER_CMP_METADATA-$(CONFIG_BLURDETECT_FILTER) += fate-filter-refcmp-blurdetect-yuv +fate-filter-refcmp-blurdetect-yuv: CMD = cmp_metadata blurdetect yuv420p 0.015 -FATE_FILTER-$(call ALLYES, $(REFCMP_DEPS) PSNR_FILTER) += fate-filter-refcmp-psnr-rgb +FATE_FILTER_CMP_METADATA-$(CONFIG_SITI_FILTER) += fate-filter-refcmp-siti-yuv +fate-filter-refcmp-siti-yuv: CMD = cmp_metadata siti yuv420p 0.015 + +FATE_FILTER-$(call ALLYES, TESTSRC2_FILTER METADATA_FILTER WRAPPED_AVFRAME_ENCODER \ + NULL_MUXER PIPE_PROTOCOL) += $(FATE_FILTER_CMP_METADATA-yes) + +FATE_FILTER_REFCMP_METADATA-$(call ALLYES, PSNR_FILTER SCALE_FILTER) += fate-filter-refcmp-psnr-rgb fate-filter-refcmp-psnr-rgb: CMD = refcmp_metadata psnr rgb24 0.002 -FATE_FILTER-$(call ALLYES, $(REFCMP_DEPS) PSNR_FILTER) += fate-filter-refcmp-psnr-yuv +FATE_FILTER_REFCMP_METADATA-$(CONFIG_PSNR_FILTER) += fate-filter-refcmp-psnr-yuv fate-filter-refcmp-psnr-yuv: CMD = refcmp_metadata psnr yuv422p 0.0015 -FATE_FILTER-$(call ALLYES, $(REFCMP_DEPS) SSIM_FILTER) += fate-filter-refcmp-ssim-rgb +FATE_FILTER_REFCMP_METADATA-$(call ALLYES, SSIM_FILTER SCALE_FILTER) += fate-filter-refcmp-ssim-rgb fate-filter-refcmp-ssim-rgb: CMD = refcmp_metadata ssim rgb24 0.015 -FATE_FILTER-$(call ALLYES, $(REFCMP_DEPS) SSIM_FILTER) += fate-filter-refcmp-ssim-yuv +FATE_FILTER_REFCMP_METADATA-$(CONFIG_SSIM_FILTER) += fate-filter-refcmp-ssim-yuv fate-filter-refcmp-ssim-yuv: CMD = refcmp_metadata ssim yuv422p 0.015 +FATE_FILTER-$(call ALLYES, TESTSRC2_FILTER SPLIT_FILTER AVGBLUR_FILTER \ + METADATA_FILTER WRAPPED_AVFRAME_ENCODER NULL_MUXER \ + PIPE_PROTOCOL) += $(FATE_FILTER_REFCMP_METADATA-yes) + FATE_SAMPLES_FFPROBE += $(FATE_METADATA_FILTER-yes) FATE_SAMPLES_FFMPEG += $(FATE_FILTER_SAMPLES-yes) FATE_FFMPEG += $(FATE_FILTER-yes) diff --git a/tests/fate/fits.mak b/tests/fate/fits.mak index f16fc8326..b9e99d97e 100644 --- a/tests/fate/fits.mak +++ b/tests/fate/fits.mak @@ -6,41 +6,32 @@ tests/data/fits-multi.fits: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data #mapping of fits file formats to png filenames # TODO: Use an actual 64bit input file and fix the gbrp16 test on big-endian -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-gbrap16le.fits := rgba64 +fits-png-map-gray := gray8 +fits-png-map-gbrp := rgb24 +fits-png-map-gbrp16 := rgb48 +fits-png-map-gbrap16le := rgba64 -tests/data/lena%.fits: TAG = GEN -tests/data/lena%.fits: NAME = $(map.$(@)) -tests/data/lena%.fits: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ - -i $(TARGET_SAMPLES)/png1/lena-$(map.$(@)).png \ - -y $(TARGET_PATH)/$(@) 2>/dev/null - -FATE_FITS_DEC-$(call DEMDEC, FITS, FITS) += fate-fitsdec-ext_data_min_max +FATE_FITS_DEC-$(call FRAMECRC, FITS, FITS, SCALE_FILTER) += fate-fitsdec-ext_data_min_max fate-fitsdec-ext_data_min_max: CMD = framecrc -i $(TARGET_SAMPLES)/fits/x0cj010ct_d0h.fit -pix_fmt gray16le -vf scale -FATE_FITS_DEC-$(call DEMDEC, FITS, FITS) += fate-fitsdec-blank_bitpix32 +FATE_FITS_DEC-$(call FRAMECRC, FITS, FITS, SCALE_FILTER) += fate-fitsdec-blank_bitpix32 fate-fitsdec-blank_bitpix32: CMD = framecrc -blank_value 65535 -i $(TARGET_SAMPLES)/fits/file008.fits -pix_fmt gray16le -vf scale -FATE_FITS_DEC-$(call DEMDEC, FITS, FITS) += fate-fitsdec-bitpix-32 +FATE_FITS_DEC-$(call FRAMECRC, FITS, FITS, SCALE_FILTER) += fate-fitsdec-bitpix-32 fate-fitsdec-bitpix-32: CMD = framecrc -i $(TARGET_SAMPLES)/fits/tst0005.fits -pix_fmt gray16le -vf scale -FATE_FITS_DEC-$(call DEMDEC, FITS, FITS) += fate-fitsdec-bitpix-64 +FATE_FITS_DEC-$(call FRAMECRC, FITS, FITS, SCALE_FILTER) += fate-fitsdec-bitpix-64 fate-fitsdec-bitpix-64: CMD = framecrc -i $(TARGET_SAMPLES)/fits/tst0006.fits -pix_fmt gray16le -vf scale -FATE_FITS_DEC-$(call ALLYES, GIF_DEMUXER FITS_DEMUXER GIF_DECODER FITS_DECODER FITS_ENCODER FITS_MUXER) += fate-fitsdec-multi +FATE_FITS_DEC-$(call TRANSCODE, FITS, FITS, GIF_DEMUXER GIF_DECODER SCALE_FILTER) += fate-fitsdec-multi fate-fitsdec-multi: tests/data/fits-multi.fits fate-fitsdec-multi: CMD = framecrc -i $(TARGET_PATH)/tests/data/fits-multi.fits -pix_fmt gbrap 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-fitsdec%: CMD = transcode image2 $(TARGET_SAMPLES)/png1/lena-$(fits-png-map-$(PIXFMT)).png fits "-vf scale -pix_fmt $(PIXFMT)" 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-%) +FATE_FITS_DEC-$(call TRANSCODE, FITS, FITS, IMAGE2_DEMUXER PNG_DECODER SCALE_FILTER) += $(FATE_FITS_DEC_PIXFMT:%=fate-fitsdec-%) FATE_FITS += $(FATE_FITS_DEC-yes) fate-fitsdec: $(FATE_FITS_DEC-yes) @@ -51,7 +42,7 @@ fate-fitsenc%: CMD = framecrc -auto_conversion_filters -i $(SRC) -c:v fits -pix_ FATE_FITS_ENC_PIXFMT = gray gray16be gbrp gbrap gbrp16be gbrap16be $(FATE_FITS_ENC_PIXFMT:%=fate-fitsenc-%): tests/data/fits-multi.fits -FATE_FITS_ENC-$(call ALLYES, GIF_DEMUXER GIF_DECODER FITS_ENCODER FITS_MUXER) += $(FATE_FITS_ENC_PIXFMT:%=fate-fitsenc-%) +FATE_FITS_ENC-$(call TRANSCODE, FITS, FITS, GIF_DEMUXER GIF_DECODER SCALE_FILTER) += $(FATE_FITS_ENC_PIXFMT:%=fate-fitsenc-%) FATE_FITS += $(FATE_FITS_ENC-yes) fate-fitsenc: $(FATE_FITS_ENC-yes) diff --git a/tests/fate/flvenc.mak b/tests/fate/flvenc.mak index 9682f4a2b..5032fface 100644 --- a/tests/fate/flvenc.mak +++ b/tests/fate/flvenc.mak @@ -1,11 +1,5 @@ -tests/data/add_keyframe_index.flv: TAG = GEN -tests/data/add_keyframe_index.flv: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ - -f lavfi -i "sws_flags=+accurate_rnd+bitexact;testsrc=r=7:n=2:d=20" -sws_flags '+accurate_rnd+bitexact' -metadata "encoder=Lavf" -pix_fmt yuv420p -c:v flv1 -g 7 -f flv -flags +bitexact -fflags +bitexact \ - -flvflags add_keyframe_index -idct simple -dct int -y $(TARGET_PATH)/tests/data/add_keyframe_index.flv 2> /dev/null; - -FATE_AFILTER-$(call ALLYES, FLV_MUXER FLV_DEMUXER AVDEVICE TESTSRC_FILTER LAVFI_INDEV FLV_ENCODER) += fate-flv-add_keyframe_index -fate-flv-add_keyframe_index: tests/data/add_keyframe_index.flv -fate-flv-add_keyframe_index: CMD = ffmetadata -flags +bitexact -i $(TARGET_PATH)/tests/data/add_keyframe_index.flv - +FATE_FLVENC_FFMPEG_FFPROBE-$(call TRANSCODE, FLV, FLV, RAWVIDEO_DECODER SCALE_FILTER TESTSRC_FILTER LAVFI_INDEV) += fate-flv-add_keyframe_index +fate-flv-add_keyframe_index: CMD = transcode "lavfi -graph testsrc=r=7:n=2:d=20" "foo" flv "-vf scale -c:v flv1 -dct int -g 7 -flvflags add_keyframe_index" "-c copy -t 0.1" "-show_entries format_tags" +FATE_FFMPEG_FFPROBE += $(FATE_FLVENC_FFMPEG_FFPROBE-yes) +fate-flvenc: $(FATE_FLVENC_FFMPEG_FFPROBE-yes) diff --git a/tests/fate/gif.mak b/tests/fate/gif.mak index a5147c0e3..1eef2a102 100644 --- a/tests/fate/gif.mak +++ b/tests/fate/gif.mak @@ -13,18 +13,16 @@ fate-gif-gray: CMD = framecrc -i $(TARGET_SAMPLES)/gif/Newtons_cradle_animation_ FATE_GIF += fate-gif-deal fate-gif-deal: CMD = framecrc -i $(TARGET_SAMPLES)/gif/deal.gif -vsync cfr -pix_fmt bgra -auto_conversion_filters -fate-gifenc%: fate-gif-color +FATE_GIF-$(call FRAMECRC, GIF, GIF, SCALE_FILTER) += $(FATE_GIF) + fate-gifenc%: PIXFMT = $(word 3, $(subst -, ,$(@))) fate-gifenc%: SRC = $(TARGET_SAMPLES)/gif/tc217.gif fate-gifenc%: CMD = framecrc -i $(SRC) -c:v gif -pix_fmt $(PIXFMT) -sws_flags +accurate_rnd+bitexact -vf scale FATE_GIF_ENC_PIXFMT = rgb8 bgr8 rgb4_byte bgr4_byte gray pal8 -FATE_GIF_ENC-$(call ENCDEC, GIF, GIF) = $(FATE_GIF_ENC_PIXFMT:%=fate-gifenc-%) +FATE_GIF_ENC-$(call ENCDEC, GIF, FRAMECRC GIF, SCALE_FILTER PIPE_PROTOCOL) = $(FATE_GIF_ENC_PIXFMT:%=fate-gifenc-%) -FATE_GIF += $(FATE_GIF_ENC-yes) fate-gifenc: $(FATE_GIF_ENC-yes) -FATE_GIF-$(call DEMDEC, GIF, GIF) += $(FATE_GIF) - -FATE_SAMPLES_AVCONV += $(FATE_GIF-yes) -fate-gif: $(FATE_GIF-yes) +FATE_SAMPLES_FFMPEG += $(FATE_GIF-yes) $(FATE_GIF_ENC-yes) +fate-gif: $(FATE_GIF-yes) $(FATE_GIF_ENC-yes) diff --git a/tests/fate/h264.mak b/tests/fate/h264.mak index e075b6f67..b883f3a3f 100644 --- a/tests/fate/h264.mak +++ b/tests/fate/h264.mak @@ -1,3 +1,21 @@ +FATE_H264_HIGH_BIT_DEPTH := \ + frext-hi422fr13_sony_b \ + frext-hi422fr6_sony_a \ + frext-pph10i1_panasonic_a \ + frext-pph10i2_panasonic_a \ + frext-pph10i3_panasonic_a \ + frext-pph10i4_panasonic_a \ + frext-pph10i5_panasonic_a \ + frext-pph10i6_panasonic_a \ + frext-pph10i7_panasonic_a \ + frext-pph422i1_panasonic_a \ + frext-pph422i2_panasonic_a \ + frext-pph422i3_panasonic_a \ + frext-pph422i4_panasonic_a \ + frext-pph422i5_panasonic_a \ + frext-pph422i6_panasonic_a \ + frext-pph422i7_panasonic_a \ + FATE_H264 = aud_mw_e \ ba1_ft_c \ ba1_sony_d \ @@ -115,9 +133,7 @@ FATE_H264 = aud_mw_e \ frext-hcafr4_hhi_a \ frext-hcamff1_hhi_b \ frext-hi422fr10_sony_b \ - frext-hi422fr13_sony_b \ frext-hi422fr1_sony_a \ - frext-hi422fr6_sony_a \ frext-hpca_brcm_c \ frext-hpcadq_brcm_b \ frext-hpcafl_bcrm_c \ @@ -132,20 +148,6 @@ FATE_H264 = aud_mw_e \ frext-hpcvflnl_bcrm_a \ frext-hpcvmolq_brcm_b \ frext-hpcvnl_brcm_a \ - frext-pph10i1_panasonic_a \ - frext-pph10i2_panasonic_a \ - frext-pph10i3_panasonic_a \ - frext-pph10i4_panasonic_a \ - frext-pph10i5_panasonic_a \ - frext-pph10i6_panasonic_a \ - frext-pph10i7_panasonic_a \ - frext-pph422i1_panasonic_a \ - frext-pph422i2_panasonic_a \ - frext-pph422i3_panasonic_a \ - frext-pph422i4_panasonic_a \ - frext-pph422i5_panasonic_a \ - frext-pph422i6_panasonic_a \ - frext-pph422i7_panasonic_a \ hcbp2_hhi_a \ hcmp1_hhi_a \ ls_sva_d \ @@ -182,6 +184,7 @@ FATE_H264 = aud_mw_e \ sva_fm1_e \ sva_nl1_b \ sva_nl2_e \ + $(if $(CONFIG_SCALE_FILTER),$(FATE_H264_HIGH_BIT_DEPTH)) FATE_H264_REINIT_TESTS := large_420_8-to-small_420_8 \ small_420_8-to-large_444_10 \ @@ -189,45 +192,46 @@ FATE_H264_REINIT_TESTS := large_420_8-to-small_420_8 \ small_422_9-to-small_420_9 \ FATE_H264 := $(FATE_H264:%=fate-h264-conformance-%) \ - $(FATE_H264_REINIT_TESTS:%=fate-h264-reinit-%) \ - fate-h264-extreme-plane-pred \ fate-h264-intra-refresh-recovery \ fate-h264-lossless \ fate-h264-3386 \ fate-h264-missing-frame \ fate-h264-ref-pic-mod-overflow \ fate-h264-timecode \ - fate-h264-encparams -FATE_H264-$(call DEMDEC, H264, H264) += $(FATE_H264) -FATE_H264-$(call DEMDEC, MOV, H264) += fate-h264-crop-to-container +FATE_H264-$(call FRAMECRC, H264, H264, H264_PARSER SCALE_FILTER) += $(FATE_H264_REINIT_TESTS:%=fate-h264-reinit-%) +FATE_H264-$(call FRAMECRC, H264, H264, H264_PARSER) += $(FATE_H264) +FATE_H264-$(call FRAMEMD5, H264, H264, H264_PARSER) += fate-h264-extreme-plane-pred +FATE_H264-$(call FRAMEMD5, MOV, H264) += fate-h264-crop-to-container +FATE_H264-$(call DEMDEC, H264, H264, H264_PARSER) += fate-h264-encparams # this sample has two stsd entries and needs to reload extradata -FATE_H264-$(call DEMDEC, MOV, H264) += fate-h264-extradata-reload +FATE_H264-$(call FRAMEMD5, MOV, H264, SCALE_FILTER) += fate-h264-extradata-reload -FATE_H264-$(call DEMDEC, MOV, H264) += fate-h264-interlace-crop +FATE_H264-$(call FRAMECRC, MOV, H264) += fate-h264-interlace-crop # this sample has invalid reference list modification, but decodes fine # by using a previous ref frame instead of a missing one -FATE_H264-$(call DEMDEC, MOV, H264) += fate-h264-invalid-ref-mod +FATE_H264-$(call FRAMECRC, MOV, H264, SCALE_FILTER) += fate-h264-invalid-ref-mod # this sample gives an explicit size for a single NAL unit, but contains # several NAL units -FATE_H264-$(call DEMDEC, MOV, H264) += fate-h264-mixed-nal-coding +FATE_H264-$(call FRAMECRC, MOV, H264) += fate-h264-mixed-nal-coding # this sample has invalid extradata that is not escaped -FATE_H264-$(call DEMDEC, MOV, H264) += fate-h264-unescaped-extradata +FATE_H264-$(call FRAMECRC, MOV, H264) += fate-h264-unescaped-extradata # this sample contains field-coded frames, with both fields in a single packet -FATE_H264-$(call DEMDEC, MOV, H264) += fate-h264-twofields-packet +FATE_H264-$(call FRAMECRC, MOV, H264) += fate-h264-twofields-packet -FATE_H264-$(call ALLYES, MOV_DEMUXER H264_MP4TOANNEXB_BSF H264_MUXER) += fate-h264-bsf-mp4toannexb -FATE_H264-$(call DEMDEC, MATROSKA, H264) += fate-h264-direct-bff -FATE_H264-$(call DEMDEC, FLV, H264) += fate-h264-brokensps-2580 -FATE_H264-$(call DEMDEC, MXF, H264) += fate-h264-xavc-4389 -FATE_H264-$(call DEMDEC, MOV, H264) += fate-h264-attachment-631 -FATE_H264-$(call DEMDEC, MPEGTS, H264) += fate-h264-skip-nokey fate-h264-skip-nointra +FATE_H264-$(call DEMMUX, MOV, H264, H264_MP4TOANNEXB_BSF) += fate-h264-bsf-mp4toannexb +FATE_H264-$(call FRAMECRC, MATROSKA, H264) += fate-h264-direct-bff +FATE_H264-$(call FRAMECRC, FLV, H264, SCALE_FILTER) += fate-h264-brokensps-2580 +FATE_H264-$(call FRAMECRC, MXF, H264, PCM_S24LE_DECODER SCALE_FILTER ARESAMPLE_FILTER) += fate-h264-xavc-4389 +FATE_H264-$(call FRAMECRC, MOV, H264) += fate-h264-attachment-631 +FATE_H264-$(call FRAMECRC, MPEGTS, H264, H264_PARSER MP3_DECODER SCALE_FILTER ARESAMPLE_FILTER) += fate-h264-skip-nokey fate-h264-skip-nointra FATE_H264_FFPROBE-$(call DEMDEC, MATROSKA, H264) += fate-h264-dts_5frames +FATE_H264_FFPROBE-$(call PARSERDEMDEC, H264, H264, H264) += fate-h264-afd FATE_SAMPLES_AVCONV += $(FATE_H264-yes) FATE_SAMPLES_FFPROBE += $(FATE_H264_FFPROBE-yes) @@ -447,6 +451,7 @@ fate-h264-timecode: CMD = framecrc -i $(TARGET_SAM fate-h264-reinit-%: CMD = framecrc -i $(TARGET_SAMPLES)/h264/$(@:fate-h264-%=%).h264 -vf scale,format=yuv444p10le,scale=w=352:h=288 fate-h264-dts_5frames: CMD = probeframes $(TARGET_SAMPLES)/h264/dts_5frames.mkv +fate-h264-afd: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -bitexact -show_entries frame_side_data_list $(TARGET_SAMPLES)/h264/bbc2.sample.h264 fate-h264-encparams: CMD = venc_data $(TARGET_SAMPLES)/h264-conformance/FRext/FRExt_MMCO4_Sony_B.264 0 1 FATE_SAMPLES_DUMP_DATA += fate-h264-encparams diff --git a/tests/fate/hap.mak b/tests/fate/hap.mak index ba921798c..8268798f4 100644 --- a/tests/fate/hap.mak +++ b/tests/fate/hap.mak @@ -25,8 +25,10 @@ fate-hap-alpha-only-nosnappy-128x72: CMD = framecrc -i $(TARGET_SAMPLES)/hap/Hap 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) +FATE_HAP-$(call FRAMECRC, MOV, HAP) += $(FATE_HAP) + +FATE_SAMPLES_FFMPEG += $(FATE_HAP-yes) +fate-hap: $(FATE_HAP-yes) #Test bsf conversion @@ -42,6 +44,7 @@ fate-hapqa-extract-snappy1-to-hapalphaonly: CMD = framecrc -i $(TARGET_SAMPLES)/ 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" +FATE_HAPQA_EXTRACT_BSF-$(call REMUX, FRAMECRC MOV, HAPQA_EXTRACT_BSF) += $(FATE_HAPQA_EXTRACT_BSF) #Test bsf conversion and mov tests/data/hapq_nosnappy.mov: TAG = GEN @@ -65,8 +68,8 @@ FATE_HAPQA_EXTRACT_BSF_FFPROBE += fate-hapqa-extract-nosnappy-to-hapalphaonly-mo 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 -bitexact -show_streams -select_streams v -v 0 $(TARGET_PATH)/tests/data/hapalphaonly_nosnappy.mov +FATE_HAPQA_EXTRACT_BSF_FFPROBE-$(call DEMMUX, MOV, MOV, HAPQA_EXTRACT_BSF HAP_DECODER) += $(FATE_HAPQA_EXTRACT_BSF_FFPROBE) -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_SAMPLES_FFMPEG += $(FATE_HAPQA_EXTRACT_BSF-yes) +FATE_SAMPLES_FFMPEG_FFPROBE += $(FATE_HAPQA_EXTRACT_BSF_FFPROBE-yes) +fate-hapqa-extract-bsf: $(FATE_HAPQA_EXTRACT_BSF-yes) $(FATE_HAPQA_EXTRACT_BSF_FFPROBE-yes) diff --git a/tests/fate/hevc.mak b/tests/fate/hevc.mak index f294cff41..2f16e3a29 100644 --- a/tests/fate/hevc.mak +++ b/tests/fate/hevc.mak @@ -1,4 +1,4 @@ -HEVC_SAMPLES = \ +HEVC_SAMPLES_8BIT = \ AMP_A_Samsung_4 \ AMP_A_Samsung_6 \ AMP_B_Samsung_4 \ @@ -158,23 +158,27 @@ HEVC_SAMPLES_422_10BIT = \ ADJUST_IPRED_ANGLE_A_RExt_Mitsubishi_1 \ IPCM_A_RExt_NEC \ -HEVC_SAMPLES_422_10BIN = \ - Main_422_10_A_RExt_Sony_1 \ - HEVC_SAMPLES_422_10BIN_LARGE = \ Main_422_10_B_RExt_Sony_1 \ +HEVC_SAMPLES_422_10BIN = \ + Main_422_10_A_RExt_Sony_1 \ + $(if $(CONFIG_LARGE_TESTS), $(HEVC_SAMPLES_422_10BIN_LARGE)) + HEVC_SAMPLES_444_8BIT = \ QMATRIX_A_RExt_Sony_1 \ +HEVC_SAMPLES_444_12BIT_LARGE = \ + SAO_A_RExt_MediaTek_1 \ + HEVC_SAMPLES_444_12BIT = \ IPCM_B_RExt_NEC \ PERSIST_RPARAM_A_RExt_Sony_1\ PERSIST_RPARAM_A_RExt_Sony_3\ + $(if $(CONFIG_LARGE_TESTS), $(HEVC_SAMPLES_444_12BIT_LARGE)) -HEVC_SAMPLES_444_12BIT_LARGE = \ - SAO_A_RExt_MediaTek_1 \ - +FATE_HEVC_VARS := 8BIT 10BIT 422_10BIT 422_10BIN 444_8BIT 444_12BIT +$(foreach VAR,$(FATE_HEVC_VARS), $(eval HEVC_TESTS_$(VAR) := $(addprefix fate-hevc-conformance-, $(HEVC_SAMPLES_$(VAR))))) # equivalent bitstreams # AMP_D_Hisilicon_3 -- AMP_D_Hisilicon @@ -190,100 +194,65 @@ HEVC_SAMPLES_444_12BIT_LARGE = \ # PERSIST_RPARAM_A_RExt_Sony_1 (rext) -define FATE_HEVC_TEST -FATE_HEVC += fate-hevc-conformance-$(1) -fate-hevc-conformance-$(1): CMD = framecrc -flags unaligned -i $(TARGET_SAMPLES)/hevc-conformance/$(1).bit -pix_fmt yuv420p -endef +$(HEVC_TESTS_8BIT): SCALE_OPTS := -pix_fmt yuv420p +$(HEVC_TESTS_444_8BIT): SCALE_OPTS := -pix_fmt yuv444p +$(HEVC_TESTS_10BIT): SCALE_OPTS := -pix_fmt yuv420p10le -vf scale +$(HEVC_TESTS_422_10BIT) $(HEVC_TESTS_422_10BIN): SCALE_OPTS := -pix_fmt yuv422p10le -vf scale +$(HEVC_TESTS_444_12BIT): SCALE_OPTS := -pix_fmt yuv444p12le -vf scale +fate-hevc-conformance-%: CMD = framecrc -flags unaligned -i $(TARGET_SAMPLES)/hevc-conformance/$(subst fate-hevc-conformance-,,$(@)).bit $(SCALE_OPTS) +$(HEVC_TESTS_422_10BIN): CMD = framecrc -flags unaligned -i $(TARGET_SAMPLES)/hevc-conformance/$(subst fate-hevc-conformance-,,$(@)).bin $(SCALE_OPTS) -define FATE_HEVC_TEST_10BIT -FATE_HEVC += fate-hevc-conformance-$(1) -fate-hevc-conformance-$(1): CMD = framecrc -flags unaligned -i $(TARGET_SAMPLES)/hevc-conformance/$(1).bit -pix_fmt yuv420p10le -vf scale -endef - -define FATE_HEVC_TEST_422_10BIT -FATE_HEVC += fate-hevc-conformance-$(1) -fate-hevc-conformance-$(1): CMD = framecrc -flags unaligned -i $(TARGET_SAMPLES)/hevc-conformance/$(1).bit -pix_fmt yuv422p10le -vf scale -endef - -define FATE_HEVC_TEST_422_10BIN -FATE_HEVC += fate-hevc-conformance-$(1) -fate-hevc-conformance-$(1): CMD = framecrc -flags unaligned -i $(TARGET_SAMPLES)/hevc-conformance/$(1).bin -pix_fmt yuv422p10le -vf scale -endef - -define FATE_HEVC_TEST_422_10BIN_LARGE -FATE_HEVC_LARGE += fate-hevc-conformance-$(1) -fate-hevc-conformance-$(1): CMD = framecrc -flags unaligned -i $(TARGET_SAMPLES)/hevc-conformance/$(1).bin -pix_fmt yuv422p10le -vf scale -endef - -define FATE_HEVC_TEST_444_8BIT -FATE_HEVC += fate-hevc-conformance-$(1) -fate-hevc-conformance-$(1): CMD = framecrc -flags unaligned -i $(TARGET_SAMPLES)/hevc-conformance/$(1).bit -pix_fmt yuv444p -endef - -define FATE_HEVC_TEST_444_12BIT -FATE_HEVC += fate-hevc-conformance-$(1) -fate-hevc-conformance-$(1): CMD = framecrc -flags unaligned -i $(TARGET_SAMPLES)/hevc-conformance/$(1).bit -pix_fmt yuv444p12le -vf scale -endef - -define FATE_HEVC_TEST_444_12BIT_LARGE -FATE_HEVC_LARGE += fate-hevc-conformance-$(1) -fate-hevc-conformance-$(1): CMD = framecrc -flags unaligned -i $(TARGET_SAMPLES)/hevc-conformance/$(1).bit -pix_fmt yuv444p12le -vf scale -endef - -$(foreach N,$(HEVC_SAMPLES),$(eval $(call FATE_HEVC_TEST,$(N)))) -$(foreach N,$(HEVC_SAMPLES_10BIT),$(eval $(call FATE_HEVC_TEST_10BIT,$(N)))) -$(foreach N,$(HEVC_SAMPLES_422_10BIT),$(eval $(call FATE_HEVC_TEST_422_10BIT,$(N)))) -$(foreach N,$(HEVC_SAMPLES_422_10BIN),$(eval $(call FATE_HEVC_TEST_422_10BIN,$(N)))) -$(foreach N,$(HEVC_SAMPLES_422_10BIN_LARGE),$(eval $(call FATE_HEVC_TEST_422_10BIN_LARGE,$(N)))) -$(foreach N,$(HEVC_SAMPLES_444_8BIT),$(eval $(call FATE_HEVC_TEST_444_8BIT,$(N)))) -$(foreach N,$(HEVC_SAMPLES_444_12BIT),$(eval $(call FATE_HEVC_TEST_444_12BIT,$(N)))) -$(foreach N,$(HEVC_SAMPLES_444_12BIT_LARGE),$(eval $(call FATE_HEVC_TEST_444_12BIT_LARGE,$(N)))) +FATE_HEVC-$(call FRAMECRC, HEVC, HEVC, HEVC_PARSER) += $(HEVC_TESTS_8BIT) $(HEVC_TESTS_444_8BIT) +FATE_HEVC-$(call FRAMECRC, HEVC, HEVC, HEVC_PARSER SCALE_FILTER) += \ + $(HEVC_TESTS_10BIT) \ + $(HEVC_TESTS_422_10BIT) \ + $(HEVC_TESTS_422_10BIN) \ + $(HEVC_TESTS_444_12BIT) \ fate-hevc-paramchange-yuv420p-yuv420p10: CMD = framecrc -vsync passthrough -i $(TARGET_SAMPLES)/hevc/paramchange_yuv420p_yuv420p10.hevc -sws_flags area+accurate_rnd+bitexact -FATE_HEVC_LARGE += fate-hevc-paramchange-yuv420p-yuv420p10 +FATE_HEVC-$(call FRAMECRC, HEVC, HEVC, HEVC_PARSER SCALE_FILTER LARGE_TESTS) += fate-hevc-paramchange-yuv420p-yuv420p10 tests/data/hevc-mp4.mov: TAG = GEN tests/data/hevc-mp4.mov: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -i $(TARGET_SAMPLES)/hevc-conformance/WPP_A_ericsson_MAIN10_2.bit -c copy -flags +bitexact $(TARGET_PATH)/$@ -y 2>/dev/null -FATE_HEVC-$(call ALLYES, HEVC_DEMUXER MOV_DEMUXER HEVC_MP4TOANNEXB_BSF MOV_MUXER HEVC_MUXER) += fate-hevc-bsf-mp4toannexb +FATE_HEVC-$(call ALLYES, HEVC_DEMUXER MOV_DEMUXER HEVC_PARSER HEVC_MP4TOANNEXB_BSF MOV_MUXER HEVC_MUXER) += fate-hevc-bsf-mp4toannexb fate-hevc-bsf-mp4toannexb: tests/data/hevc-mp4.mov fate-hevc-bsf-mp4toannexb: CMD = md5 -i $(TARGET_PATH)/tests/data/hevc-mp4.mov -c:v copy -fflags +bitexact -f hevc 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) -FATE_HEVC-$(call ALLYES, HEVC_DEMUXER HEVC_DECODER LARGE_TESTS) += $(FATE_HEVC_LARGE) +FATE_HEVC-$(call FRAMEMD5, HEVC, HEVC, HEVC_PARSER) += fate-hevc-skiploopfilter # this sample has two stsd entries and needs to reload extradata -FATE_HEVC-$(call DEMDEC, MOV, HEVC) += fate-hevc-extradata-reload - +FATE_HEVC-$(call FRAMEMD5, MOV, HEVC, SCALE_FILTER) += fate-hevc-extradata-reload fate-hevc-extradata-reload: CMD = framemd5 -i $(TARGET_SAMPLES)/hevc/extradata-reload-multi-stsd.mov -sws_flags bitexact fate-hevc-paired-fields: CMD = probeframes -show_entries frame=interlaced_frame,top_field_first $(TARGET_SAMPLES)/hevc/paired_fields.hevc FATE_HEVC_FFPROBE-$(call DEMDEC, HEVC, HEVC) += fate-hevc-paired-fields fate-hevc-monochrome-crop: CMD = probeframes -show_entries frame=width,height:stream=width,height $(TARGET_SAMPLES)/hevc/hevc-monochrome.hevc -FATE_HEVC_FFPROBE-$(call DEMDEC, HEVC, HEVC) += fate-hevc-monochrome-crop +FATE_HEVC_FFPROBE-$(call PARSERDEMDEC, HEVC, HEVC, HEVC) += fate-hevc-monochrome-crop fate-hevc-hdr10-plus-metadata: CMD = probeframes -show_entries frame=side_data_list $(TARGET_SAMPLES)/hevc/hdr10_plus_h265_sample.hevc FATE_HEVC_FFPROBE-$(call DEMDEC, HEVC, HEVC) += fate-hevc-hdr10-plus-metadata +fate-hevc-hdr-vivid-metadata: CMD = probeframes -show_entries frame=side_data_list $(TARGET_SAMPLES)/hevc/hdr_vivid_h265_sample.hevc +FATE_HEVC_FFPROBE-$(call PARSERDEMDEC, HEVC, HEVC, HEVC) += fate-hevc-hdr-vivid-metadata + fate-hevc-dv-rpu: CMD = probeframes -show_entries frame=side_data_list -select_streams 0 -read_intervals "%+\#2" $(TARGET_SAMPLES)/hevc/dv84.mov -FATE_HEVC_FFPROBE-$(call DEMDEC, HEVC, HEVC) += fate-hevc-dv-rpu +FATE_HEVC_FFPROBE-$(call DEMDEC, MOV, HEVC) += fate-hevc-dv-rpu fate-hevc-two-first-slice: CMD = threads=2 framemd5 -i $(TARGET_SAMPLES)/hevc/two_first_slice.mp4 -sws_flags bitexact -t 00:02.00 -an -FATE_HEVC-$(call DEMDEC, MOV, HEVC) += fate-hevc-two-first-slice +FATE_HEVC-$(call FRAMEMD5, MOV, HEVC) += fate-hevc-two-first-slice fate-hevc-cabac-tudepth: CMD = framecrc -flags unaligned -i $(TARGET_SAMPLES)/hevc/cbf_cr_cb_TUDepth_4_circle.h265 -pix_fmt yuv444p -FATE_HEVC-$(call DEMDEC, HEVC, HEVC) += fate-hevc-cabac-tudepth +FATE_HEVC-$(call FRAMECRC, HEVC, HEVC) += fate-hevc-cabac-tudepth fate-hevc-small422chroma: CMD = framecrc -flags unaligned -i $(TARGET_SAMPLES)/hevc/food.hevc -pix_fmt yuv422p10le -vf scale -FATE_HEVC-$(call DEMDEC, HEVC, HEVC) += fate-hevc-small422chroma +FATE_HEVC-$(call FRAMECRC, HEVC, HEVC, HEVC_PARSER SCALE_FILTER) += fate-hevc-small422chroma FATE_SAMPLES_AVCONV += $(FATE_HEVC-yes) FATE_SAMPLES_FFPROBE += $(FATE_HEVC_FFPROBE-yes) diff --git a/tests/fate/id3v2.mak b/tests/fate/id3v2.mak index fea754527..4dca681e3 100644 --- a/tests/fate/id3v2.mak +++ b/tests/fate/id3v2.mak @@ -1,15 +1,11 @@ FATE_ID3V2_FFPROBE-$(CONFIG_MP3_DEMUXER) += fate-id3v2-priv fate-id3v2-priv: CMD = probetags $(TARGET_SAMPLES)/id3v2/id3v2_priv.mp3 -FATE_ID3V2_FFMPEG_FFPROBE-$(call ALLYES, FILE_PROTOCOL MP3_DEMUXER MP3_MUXER \ - FRAMECRC_MUXER PIPE_PROTOCOL) \ - += fate-id3v2-priv-remux -fate-id3v2-priv-remux: CMD = transcode mp3 $(TARGET_SAMPLES)/id3v2/id3v2_priv.mp3 mp3 "-c copy" "-c copy -t 0.1" "" "-show_entries format_tags" +FATE_ID3V2_FFMPEG_FFPROBE-$(call REMUX, MP3) += fate-id3v2-priv-remux +fate-id3v2-priv-remux: CMD = transcode mp3 $(TARGET_SAMPLES)/id3v2/id3v2_priv.mp3 mp3 "-c copy" "-c copy -t 0.1" "-show_entries format_tags" -FATE_ID3V2_FFMPEG_FFPROBE-$(call ALLYES, FILE_PROTOCOL WAV_DEMUXER AIFF_MUXER \ - AIFF_DEMUXER FRAMECRC_MUXER PIPE_PROTOCOL) \ - += fate-id3v2-chapters -fate-id3v2-chapters: CMD = transcode wav $(TARGET_SAMPLES)/wav/200828-005.wav aiff "-c copy -metadata:c:0 description=foo -metadata:c:0 date=2021 -metadata:c copyright=none -metadata:c:1 genre=nonsense -write_id3v2 1" "-c copy -t 0.05" "" "-show_entries format_tags:chapters" +FATE_ID3V2_FFMPEG_FFPROBE-$(call REMUX, AIFF, WAV_DEMUXER) += fate-id3v2-chapters +fate-id3v2-chapters: CMD = transcode wav $(TARGET_SAMPLES)/wav/200828-005.wav aiff "-c copy -metadata:c:0 description=foo -metadata:c:0 date=2021 -metadata:c copyright=none -metadata:c:1 genre=nonsense -write_id3v2 1" "-c copy -t 0.05" "-show_entries format_tags:chapters" FATE_SAMPLES_FFPROBE += $(FATE_ID3V2_FFPROBE-yes) FATE_SAMPLES_FFMPEG_FFPROBE += $(FATE_ID3V2_FFMPEG_FFPROBE-yes) diff --git a/tests/fate/image.mak b/tests/fate/image.mak index 573d39891..fca4eaf60 100644 --- a/tests/fate/image.mak +++ b/tests/fate/image.mak @@ -1,13 +1,12 @@ +ADD_SCALE_IF = $(if $(findstring -vf scale,$(1)), SCALE_FILTER) + FATE_ALIASPIX += fate-aliaspix-bgr fate-aliaspix-bgr: CMD = transcode alias_pix $(TARGET_SAMPLES)/aliaspix/first.pix image2 "-c alias_pix" "-map 0 -map 0 -pix_fmt:0 bgr24 -c:v:1 copy" FATE_ALIASPIX += fate-aliaspix-gray fate-aliaspix-gray: CMD = transcode alias_pix $(TARGET_SAMPLES)/aliaspix/firstgray.pix image2 "-c alias_pix" "-map 0 -map 0 -pix_fmt:0 gray -c:v:1 copy" -FATE_ALIASPIX-$(call ALLYES, FILE_PROTOCOL IMAGE2_ALIAS_PIX_DEMUXER \ - ALIAS_PIX_DECODER ALIAS_PIX_ENCODER \ - IMAGE2_MUXER RAWVIDEO_ENCODER \ - FRAMECRC_MUXER PIPE_PROTOCOL) += $(FATE_ALIASPIX) +FATE_ALIASPIX-$(call TRANSCODE, ALIAS_PIX, IMAGE2 IMAGE2_ALIAS_PIX) += $(FATE_ALIASPIX) FATE_IMAGE += $(FATE_ALIASPIX-yes) fate-aliaspix: $(FATE_ALIASPIX-yes) @@ -17,29 +16,29 @@ fate-brenderpix-24: CMD = framecrc -c:v brender_pix -i $(TARGET_SAMPLES)/brender FATE_BRENDERPIX += fate-brenderpix-565 fate-brenderpix-565: CMD = framecrc -c:v brender_pix -i $(TARGET_SAMPLES)/brenderpix/maximafront.pix -FATE_BRENDERPIX += fate-brenderpix-defpal +FATE_BRENDERPIX-$(call DEMDEC, IMAGE2, BRENDER_PIX, SCALE_FILTER) += fate-brenderpix-defpal fate-brenderpix-defpal: CMD = framecrc -c:v brender_pix -i $(TARGET_SAMPLES)/brenderpix/rivrock1.pix -pix_fmt rgb24 -vf scale -FATE_BRENDERPIX += fate-brenderpix-intpal +FATE_BRENDERPIX-$(call DEMDEC, IMAGE2, BRENDER_PIX, SCALE_FILTER) += fate-brenderpix-intpal fate-brenderpix-intpal: CMD = framecrc -c:v brender_pix -i $(TARGET_SAMPLES)/brenderpix/testtex.pix -pix_fmt rgb24 -vf scale FATE_BRENDERPIX += fate-brenderpix-y400a fate-brenderpix-y400a: CMD = framecrc -c:v brender_pix -i $(TARGET_SAMPLES)/brenderpix/gears.pix FATE_BRENDERPIX-$(call DEMDEC, IMAGE2, BRENDER_PIX) += $(FATE_BRENDERPIX) -FATE_IMAGE += $(FATE_BRENDERPIX-yes) +FATE_IMAGE_FRAMECRC += $(FATE_BRENDERPIX-yes) fate-brenderpix: $(FATE_BRENDERPIX-yes) -FATE_IMAGE-$(call PARSERDEMDEC, BMP, IMAGE2PIPE, BMP) += fate-bmpparser +FATE_IMAGE_FRAMECRC-$(call PARSERDEMDEC, BMP, IMAGE2PIPE, BMP, SCALE_FILTER) += fate-bmpparser fate-bmpparser: CMD = framecrc -f image2pipe -i $(TARGET_SAMPLES)/bmp/numbers.bmp -pix_fmt rgb24 -vf scale define FATE_IMGSUITE_DDS -FATE_DDS += fate-dds-$(1) -fate-dds-$(1): CMD = framecrc -i $(TARGET_SAMPLES)/dds/fate_$(1).dds $(DDS_OPTS_$(1)) -vf scale +FATE_DDS-$(call DEMDEC, IMAGE2, DDS, $(call ADD_SCALE_IF, $(DDS_OPTS_$(1)))) += fate-dds-$(1) +fate-dds-$(1): CMD = framecrc -i $(TARGET_SAMPLES)/dds/fate_$(1).dds $(DDS_OPTS_$(1)) endef -DDS_OPTS_pal = -sws_flags +accurate_rnd+bitexact -pix_fmt rgba -DDS_OPTS_pal-ati = -sws_flags +accurate_rnd+bitexact -pix_fmt rgba +DDS_OPTS_pal := -sws_flags +accurate_rnd+bitexact -pix_fmt rgba -vf scale +DDS_OPTS_pal-ati:= -sws_flags +accurate_rnd+bitexact -pix_fmt rgba -vf scale DDS_FMT = alpha8 \ argb \ argb-aexp \ @@ -90,14 +89,15 @@ DDS_FMT = alpha8 \ yuyv $(foreach FMT,$(DDS_FMT),$(eval $(call FATE_IMGSUITE_DDS,$(FMT)))) -FATE_DDS-$(call DEMDEC, IMAGE2, DDS) += $(FATE_DDS) -FATE_IMAGE += $(FATE_DDS-yes) +FATE_IMAGE_FRAMECRC += $(FATE_DDS-yes) fate-dds: $(FATE_DDS-yes) -FATE_IMAGE-$(call DEMDEC, IMAGE2, DPX) += fate-dpx +FATE_IMAGE_FRAMECRC-$(call DEMDEC, IMAGE2, DPX) += fate-dpx fate-dpx: CMD = framecrc -i $(TARGET_SAMPLES)/dpx/lighthouse_rgb48.dpx -FATE_SAMPLES_AVCONV-$(call PARSERDEMDEC, DPX, IMAGE2PIPE, DPX) += fate-dpxparser +# The following sample has frames whose dimensions differ on a per-frame basis +# and therefore needs the scale filter. +FATE_IMAGE_FRAMECRC-$(call PARSERDEMDEC, DPX, IMAGE2PIPE, DPX, SCALE_FILTER) += fate-dpxparser fate-dpxparser: CMD = framecrc -f image2pipe -i $(TARGET_SAMPLES)/dpx/lena_4x_concat.dpx -sws_flags +accurate_rnd+bitexact FATE_IMAGE_PROBE-$(call DEMDEC, IMAGE2, DPX) += fate-dpx-probe @@ -226,7 +226,7 @@ fate-exr-rgb-scanline-pxr24-float-half-l1: CMD = framecrc -i $(TARGET_SAMPLES)/e FATE_EXR += fate-exr-rgb-scanline-pxr24-float-half-l2 fate-exr-rgb-scanline-pxr24-float-half-l2: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgb_scanline_pxr24_float_half.exr -pix_fmt gbrapf32le -FATE_EXR += fate-exr-rgb-scanline-pxr24-half-uint32-13x9 +FATE_EXR-$(call DEMDEC, IMAGE2, EXR, SCALE_FILTER) += fate-exr-rgb-scanline-pxr24-half-uint32-13x9 fate-exr-rgb-scanline-pxr24-half-uint32-13x9: CMD = framecrc -layer "VRaySamplerInfo" -i $(TARGET_SAMPLES)/exr/rgb_scanline_pxr24_half_uint32_13x9.exr -pix_fmt rgb48le -vf scale FATE_EXR += fate-exr-rgb-scanline-zip-half-float-l1 @@ -328,18 +328,22 @@ fate-exr-rgb-scanline-zip-half-0x0-0xFFFF: CMD = framecrc -i $(TARGET_SAMPLES)/e FATE_EXR-$(call DEMDEC, IMAGE2, EXR) += $(FATE_EXR) -FATE_IMAGE += $(FATE_EXR-yes) +FATE_IMAGE_FRAMECRC += $(FATE_EXR-yes) fate-exr: $(FATE_EXR-yes) -FATE_JPG += fate-jpg-12bpp +FATE_JPG-$(call DEMDEC, IMAGE2, MJPEG, SCALE_FILTER) += fate-jpg-12bpp fate-jpg-12bpp: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/jpg/12bpp.jpg -f rawvideo -pix_fmt gray16le -vf setsar=sar=sar,scale FATE_JPG += fate-jpg-jfif fate-jpg-jfif: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/jpg/20242.jpg +FATE_JPG_TRANSCODE-$(call TRANSCODE, MJPEG, MJPEG IMAGE_JPEG_PIPE, IMAGE_PNG_PIPE_DEMUXER PNG_DECODER SCALE_FILTER) += fate-jpg-icc +fate-jpg-icc: CMD = transcode png_pipe $(TARGET_SAMPLES)/png1/lena-int_rgb24.png mjpeg "-vf scale" "" "-show_frames" + FATE_JPG-$(call DEMDEC, IMAGE2, MJPEG) += $(FATE_JPG) -FATE_IMAGE += $(FATE_JPG-yes) -fate-jpg: $(FATE_JPG-yes) +FATE_IMAGE_FRAMECRC += $(FATE_JPG-yes) +FATE_IMAGE_TRANSCODE += $(FATE_JPG_TRANSCODE-yes) +fate-jpg: $(FATE_JPG-yes) $(FATE_JPG_TRANSCODE-yes) FATE_JPEGLS += fate-jpegls-2bpc fate-jpegls-2bpc: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/jpegls/4.jls @@ -354,20 +358,20 @@ FATE_JPEGLS += fate-jpegls-7bpc fate-jpegls-7bpc: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/jpegls/128.jls FATE_JPEGLS-$(call DEMDEC, IMAGE2, JPEGLS) += $(FATE_JPEGLS) -FATE_IMAGE += $(FATE_JPEGLS-yes) +FATE_IMAGE_FRAMECRC += $(FATE_JPEGLS-yes) fate-jpegls: $(FATE_JPEGLS-yes) -FATE_IMAGE-$(call DEMDEC, IMAGE2, QDRAW) += fate-pict +FATE_IMAGE_FRAMECRC-$(call DEMDEC, IMAGE2, QDRAW) += fate-pict fate-pict: CMD = framecrc -i $(TARGET_SAMPLES)/quickdraw/TRU256.PCT -pix_fmt rgb24 -FATE_IMAGE-$(call DEMDEC, IMAGE2, PICTOR) += fate-pictor +FATE_IMAGE_FRAMECRC-$(call DEMDEC, IMAGE2, PICTOR, SCALE_FILTER) += fate-pictor fate-pictor: CMD = framecrc -i $(TARGET_SAMPLES)/pictor/MFISH.PIC -pix_fmt rgb24 -vf scale -FATE_IMAGE-$(call PARSERDEMDEC, PNG, IMAGE2PIPE, PNG) += fate-pngparser +FATE_IMAGE_FRAMECRC-$(call PARSERDEMDEC, PNG, IMAGE2PIPE, PNG) += fate-pngparser fate-pngparser: CMD = framecrc -f image2pipe -i $(TARGET_SAMPLES)/png1/feed_4x_concat.png -pix_fmt rgba define FATE_IMGSUITE_PNG -FATE_PNG += fate-png-$(1) +FATE_PNG-$(call DEMDEC, IMAGE2, PNG, SCALE_FILTER) += fate-png-$(1) fate-png-$(1): CMD = framecrc -auto_conversion_filters -i $(TARGET_SAMPLES)/png1/lena-$(1).png -sws_flags +accurate_rnd+bitexact -pix_fmt rgb24 endef @@ -385,17 +389,21 @@ FATE_PNG_PROBE += fate-png-side-data fate-png-side-data: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_frames \ -i $(TARGET_SAMPLES)/png1/lena-int_rgb24.png +FATE_PNG_TRANSCODE-$(call TRANSCODE, PNG, IMAGE2 IMAGE_PNG_PIPE) += fate-png-icc +fate-png-icc: CMD = transcode png_pipe $(TARGET_SAMPLES)/png1/lena-int_rgb24.png image2 "-c png" "" "-show_frames" + FATE_PNG-$(call DEMDEC, IMAGE2, PNG) += $(FATE_PNG) FATE_PNG_PROBE-$(call DEMDEC, IMAGE2, PNG) += $(FATE_PNG_PROBE) -FATE_IMAGE += $(FATE_PNG-yes) +FATE_IMAGE_FRAMECRC += $(FATE_PNG-yes) FATE_IMAGE_PROBE += $(FATE_PNG_PROBE-yes) -fate-png: $(FATE_PNG-yes) $(FATE_PNG_PROBE-yes) +FATE_IMAGE_TRANSCODE += $(FATE_PNG_TRANSCODE-yes) +fate-png: $(FATE_PNG-yes) $(FATE_PNG_PROBE-yes) $(FATE_PNG_TRANSCODE-yes) -FATE_IMAGE-$(call DEMDEC, IMAGE2, PTX) += fate-ptx +FATE_IMAGE_FRAMECRC-$(call DEMDEC, IMAGE2, PTX, SCALE_FILTER) += fate-ptx fate-ptx: CMD = framecrc -i $(TARGET_SAMPLES)/ptx/_113kw_pic.ptx -pix_fmt rgb24 -vf scale define FATE_IMGSUITE_PSD -FATE_PSD += fate-psd-$(1) +FATE_PSD-$(call DEMDEC, IMAGE2, PSD, SCALE_FILTER) += fate-psd-$(1) fate-psd-$(1): CMD = framecrc -i $(TARGET_SAMPLES)/psd/lena-$(1).psd -sws_flags +accurate_rnd+bitexact -pix_fmt rgb24 -vf scale endef @@ -425,7 +433,7 @@ fate-psd-duo-tone-color: CMD = framecrc -i $(TARGET_SAMPLES)/psd/duotone-color.p FATE_PSD-$(call DEMDEC, IMAGE2, PSD) += $(FATE_PSD) -FATE_IMAGE += $(FATE_PSD-yes) +FATE_IMAGE_FRAMECRC += $(FATE_PSD-yes) fate-psd: $(FATE_PSD-yes) define FATE_IMGSUITE_SGI @@ -438,36 +446,31 @@ SGI_COLORSPACES = gray8 gray16 rgb24 rgb48 rgba rgba64 $(foreach CLSP,$(SGI_COLORSPACES),$(eval $(call FATE_IMGSUITE_SGI,$(CLSP)))) FATE_SGI-$(call DEMDEC, IMAGE2, SGI) += $(FATE_SGI) -FATE_IMAGE += $(FATE_SGI-yes) +FATE_IMAGE_FRAMECRC += $(FATE_SGI-yes) fate-sgi: $(FATE_SGI-yes) -FATE_SUNRASTER += fate-sunraster-1bit-raw -fate-sunraster-1bit-raw: CMD = framecrc -i $(TARGET_SAMPLES)/sunraster/lena-1bit-raw.sun - -FATE_SUNRASTER += fate-sunraster-1bit-rle -fate-sunraster-1bit-rle: CMD = framecrc -i $(TARGET_SAMPLES)/sunraster/lena-1bit-rle.sun - -FATE_SUNRASTER += fate-sunraster-8bit-raw -fate-sunraster-8bit-raw: CMD = framecrc -i $(TARGET_SAMPLES)/sunraster/lena-8bit-raw.sun -pix_fmt rgb24 -vf scale +define FATE_IMGSUITE_SUNRASTER +FATE_SUNRASTER-$(call DEMDEC, IMAGE2, SUNRAST, $(call ADD_SCALE_IF, $(SUNRASTER_OPTS_$(1)))) += fate-sunraster-$(1) +fate-sunraster-$(1): CMD = framecrc -i $(TARGET_SAMPLES)/sunraster/lena-$(1).sun $(SUNRASTER_OPTS_$(1)) +endef +SUNRASTER_OPTS_8bit-raw := -pix_fmt rgb24 -vf scale +SUNRASTER_OPTS_8bit-rle := -pix_fmt rgb24 -vf scale +SUNRASTER_TESTS := 1bit-raw 1bit-rle 8bit-raw 8bit-rle 24bit-raw 24bit-rle +$(foreach TEST,$(SUNRASTER_TESTS),$(eval $(call FATE_IMGSUITE_SUNRASTER,$(TEST)))) FATE_SUNRASTER += fate-sunraster-8bit_gray-raw fate-sunraster-8bit_gray-raw: CMD = framecrc -i $(TARGET_SAMPLES)/sunraster/gray.ras -FATE_SUNRASTER += fate-sunraster-8bit-rle -fate-sunraster-8bit-rle: CMD = framecrc -i $(TARGET_SAMPLES)/sunraster/lena-8bit-rle.sun -pix_fmt rgb24 -vf scale - -FATE_SUNRASTER += fate-sunraster-24bit-raw -fate-sunraster-24bit-raw: CMD = framecrc -i $(TARGET_SAMPLES)/sunraster/lena-24bit-raw.sun - -FATE_SUNRASTER += fate-sunraster-24bit-rle -fate-sunraster-24bit-rle: CMD = framecrc -i $(TARGET_SAMPLES)/sunraster/lena-24bit-rle.sun - FATE_SUNRASTER-$(call DEMDEC, IMAGE2, SUNRAST) += $(FATE_SUNRASTER) -FATE_IMAGE += $(FATE_SUNRASTER-yes) +FATE_IMAGE_FRAMECRC += $(FATE_SUNRASTER-yes) fate-sunraster: $(FATE_SUNRASTER-yes) -FATE_TARGA = CBW8 \ +define FATE_IMGSUITE_TARGA +FATE_TARGA-$(call DEMDEC, IMAGE2, TARGA, $(call ADD_SCALE_IF, $(TARGA_OPTS_$(1)))) += fate-targa-conformance-$(1) +fate-targa-conformance-$(1): CMD = framecrc -i $(TARGET_SAMPLES)/targa-conformance/$(1).TGA $(TARGA_OPTS_$(1)) +endef +TARGA_FMT := CBW8 \ CCM8 \ CTC16 \ CTC24 \ @@ -477,28 +480,17 @@ FATE_TARGA = CBW8 \ UTC16 \ UTC24 \ UTC32 +TARGA_OPTS_CCM8 := -pix_fmt rgba -vf scale +TARGA_OPTS_UCM8 := -pix_fmt rgba -vf scale +TARGA_OPTS_UTC16 := -pix_fmt rgb555le +$(foreach FMT,$(TARGA_FMT),$(eval $(call FATE_IMGSUITE_TARGA,$(FMT)))) -FATE_TARGA := $(FATE_TARGA:%=fate-targa-conformance-%) \ - fate-targa-top-to-bottom - -FATE_TARGA-$(call DEMDEC, IMAGE2, TARGA) += $(FATE_TARGA) - -FATE_IMAGE += $(FATE_TARGA-yes) -fate-targa: $(FATE_TARGA-yes) - -fate-targa-conformance-CBW8: CMD = framecrc -i $(TARGET_SAMPLES)/targa-conformance/CBW8.TGA -fate-targa-conformance-CCM8: CMD = framecrc -i $(TARGET_SAMPLES)/targa-conformance/CCM8.TGA -pix_fmt rgba -vf scale -fate-targa-conformance-CTC16: CMD = framecrc -i $(TARGET_SAMPLES)/targa-conformance/CTC16.TGA -pix_fmt rgb555le -fate-targa-conformance-CTC24: CMD = framecrc -i $(TARGET_SAMPLES)/targa-conformance/CTC24.TGA -fate-targa-conformance-CTC32: CMD = framecrc -i $(TARGET_SAMPLES)/targa-conformance/CTC32.TGA -pix_fmt bgra -fate-targa-conformance-UBW8: CMD = framecrc -i $(TARGET_SAMPLES)/targa-conformance/UBW8.TGA -fate-targa-conformance-UCM8: CMD = framecrc -i $(TARGET_SAMPLES)/targa-conformance/UCM8.TGA -pix_fmt rgba -vf scale -fate-targa-conformance-UTC16: CMD = framecrc -i $(TARGET_SAMPLES)/targa-conformance/UTC16.TGA -pix_fmt rgb555le -fate-targa-conformance-UTC24: CMD = framecrc -i $(TARGET_SAMPLES)/targa-conformance/UTC24.TGA -fate-targa-conformance-UTC32: CMD = framecrc -i $(TARGET_SAMPLES)/targa-conformance/UTC32.TGA -pix_fmt bgra - +FATE_TARGA-$(call DEMDEC, IMAGE2, TARGA) += fate-targa-top-to-bottom fate-targa-top-to-bottom: CMD = framecrc -i $(TARGET_SAMPLES)/targa/lena-top-to-bottom.tga +FATE_IMAGE_FRAMECRC += $(FATE_TARGA-yes) +fate-targa: $(FATE_TARGA-yes) + FATE_TIFF += fate-tiff-fax-g3 fate-tiff-fax-g3: CMD = framecrc -i $(TARGET_SAMPLES)/CCITT_fax/G31D.TIF @@ -507,7 +499,7 @@ fate-tiff-fax-g3s: CMD = framecrc -i $(TARGET_SAMPLES)/CCITT_fax/G31DS.TIF FATE_TIFF-$(call DEMDEC, IMAGE2, TIFF) += $(FATE_TIFF) -FATE_IMAGE += $(FATE_TIFF-yes) +FATE_IMAGE_FRAMECRC += $(FATE_TIFF-yes) fate-tiff: $(FATE_TIFF-yes) FATE_WEBP += fate-webp-rgb-lossless @@ -516,7 +508,7 @@ fate-webp-rgb-lossless: CMD = framecrc -i $(TARGET_SAMPLES)/webp/rgb_lossless.we FATE_WEBP += fate-webp-rgb-lena-lossless fate-webp-rgb-lena-lossless: CMD = framecrc -i $(TARGET_SAMPLES)/webp/rgb_lena_lossless.webp -FATE_WEBP += fate-webp-rgb-lena-lossless-rgb24 +FATE_WEBP-$(call DEMDEC, IMAGE2, WEBP, SCALE_FILTER) += fate-webp-rgb-lena-lossless-rgb24 fate-webp-rgb-lena-lossless-rgb24: CMD = framecrc -i $(TARGET_SAMPLES)/webp/rgb_lena_lossless.webp -pix_fmt rgb24 -vf scale FATE_WEBP += fate-webp-rgba-lossless @@ -533,10 +525,10 @@ FATE_WEBP += fate-webp-rgba-lossy-q80 fate-webp-rgba-lossy-q80: CMD = framecrc -i $(TARGET_SAMPLES)/webp/rgba_q80.webp FATE_WEBP-$(call DEMDEC, IMAGE2, WEBP) += $(FATE_WEBP) -FATE_IMAGE += $(FATE_WEBP-yes) +FATE_IMAGE_FRAMECRC += $(FATE_WEBP-yes) fate-webp: $(FATE_WEBP-yes) -FATE_IMAGE-$(call DEMDEC, IMAGE2, XFACE) += fate-xface +FATE_IMAGE_FRAMECRC-$(call DEMDEC, IMAGE2, XFACE) += fate-xface fate-xface: CMD = framecrc -i $(TARGET_SAMPLES)/xface/lena.xface FATE_XBM += fate-xbm10 @@ -546,13 +538,16 @@ FATE_XBM += fate-xbm11 fate-xbm11: CMD = framecrc -i $(TARGET_SAMPLES)/xbm/lbw.xbm FATE_XBM-$(call DEMDEC, IMAGE2, XBM) += $(FATE_XBM) -FATE_IMAGE += $(FATE_XBM-yes) +FATE_IMAGE_FRAMECRC += $(FATE_XBM-yes) fate-xbm: $(FATE_XBM-yes) +FATE_IMAGE-$(call ALLYES, FILE_PROTOCOL FRAMECRC_MUXER PIPE_PROTOCOL) += $(FATE_IMAGE_FRAMECRC) $(FATE_IMAGE_FRAMECRC-yes) FATE_IMAGE += $(FATE_IMAGE-yes) FATE_IMAGE_PROBE += $(FATE_IMAGE_PROBE-yes) +FATE_IMAGE_TRANSCODE += $(FATE_IMAGE_TRANSCODE-yes) FATE_SAMPLES_FFMPEG += $(FATE_IMAGE) FATE_SAMPLES_FFPROBE += $(FATE_IMAGE_PROBE) +FATE_SAMPLES_FFMPEG_FFPROBE += $(FATE_IMAGE_TRANSCODE) -fate-image: $(FATE_IMAGE) $(FATE_IMAGE_PROBE) +fate-image: $(FATE_IMAGE) $(FATE_IMAGE_PROBE) $(FATE_IMAGE_TRANSCODE) diff --git a/tests/fate/imf.mak b/tests/fate/imf.mak new file mode 100644 index 000000000..70a3efdfb --- /dev/null +++ b/tests/fate/imf.mak @@ -0,0 +1,6 @@ +FATE_IMF += fate-imf-cpl-with-repeat +fate-imf-cpl-with-repeat: CMD = framecrc -f imf -i $(TARGET_SAMPLES)/imf/countdown/CPL_bb2ce11c-1bb6-4781-8e69-967183d02b9b.xml -c:v copy + +FATE_SAMPLES_FFMPEG-$(CONFIG_IMF_DEMUXER) += $(FATE_IMF) + +fate-imf: $(FATE_IMF) diff --git a/tests/fate/lavf-audio.mak b/tests/fate/lavf-audio.mak index a0600491a..68fca3529 100644 --- a/tests/fate/lavf-audio.mak +++ b/tests/fate/lavf-audio.mak @@ -1,14 +1,10 @@ FATE_LAVF_AUDIO-$(call ENCDEC, PCM_S16BE, AIFF) += aiff FATE_LAVF_AUDIO-$(call ENCDEC, PCM_ALAW, PCM_ALAW) += al -FATE_LAVF_AUDIO-$(call ENCDEC, PCM_S16BE_PLANAR, AST) += ast FATE_LAVF_AUDIO-$(call ENCDEC, PCM_S16BE, AU) += au FATE_LAVF_AUDIO-$(call ENCDEC, PCM_S16BE, CAF) += caf FATE_LAVF_AUDIO-$(call ENCDEC, ADPCM_YAMAHA, MMF) += mmf FATE_LAVF_AUDIO-$(call ENCDEC, FLAC, OGG) += ogg -FATE_LAVF_AUDIO-$(call ENCDEC, PCM_U8, RSO) += rso -FATE_LAVF_AUDIO-$(call ENCDEC, PCM_S16LE, SOX) += sox FATE_LAVF_AUDIO-$(call ENCDEC, PCM_MULAW, PCM_MULAW) += ul -FATE_LAVF_AUDIO-$(call ENCDEC, PCM_U8, VOC) += voc FATE_LAVF_AUDIO-$(call ENCDEC, PCM_S16LE, IRCAM) += ircam FATE_LAVF_AUDIO-$(call ENCDEC, PCM_S16LE, VOC) += s16.voc FATE_LAVF_AUDIO-$(call ENCDEC, PCM_S16LE, WAV) += wav @@ -17,9 +13,15 @@ FATE_LAVF_AUDIO-$(call ENCDEC, PCM_S16LE, WAV) += peak_only.wav FATE_LAVF_AUDIO-$(call ENCDEC, PCM_S16LE, W64) += w64 FATE_LAVF_AUDIO-$(call ENCDEC, TTA, TTA) += tta FATE_LAVF_AUDIO-$(call ENCMUX, TTA, MATROSKA_AUDIO) += mka -FATE_LAVF_AUDIO-$(call ENCDEC, WAVPACK, WV) += wv +FATE_LAVF_AUDIO_RESAMPLE-$(call ENCDEC, PCM_S16BE_PLANAR, AST) += ast +FATE_LAVF_AUDIO_RESAMPLE-$(call ENCDEC, PCM_U8, RSO) += rso +FATE_LAVF_AUDIO_RESAMPLE-$(call ENCDEC, PCM_S16LE, SOX) += sox +FATE_LAVF_AUDIO_RESAMPLE-$(call ENCDEC, PCM_U8, VOC) += voc +FATE_LAVF_AUDIO_RESAMPLE-$(call ENCDEC, WAVPACK, WV) += wv +FATE_LAVF_AUDIO-$(CONFIG_ARESAMPLE_FILTER) += $(FATE_LAVF_AUDIO_RESAMPLE-yes) FATE_LAVF_AUDIO = $(FATE_LAVF_AUDIO-yes:%=fate-lavf-%) +FATE_LAVF_AUDIO := $(if $(call ENCDEC, PCM_S16LE, CRC PCM_S16LE), $(FATE_LAVF_AUDIO)) $(FATE_LAVF_AUDIO): CMD = lavf_audio $(FATE_LAVF_AUDIO): REF = $(SRC_PATH)/tests/ref/lavf/$(@:fate-lavf-%=%) @@ -32,7 +34,7 @@ fate-lavf-ast: CMD = lavf_audio "-ac 2" "-loopstart 1 -loopend 10" fate-lavf-mka: CMD = lavf_audio "" "-c:a tta" fate-lavf-voc: CMD = lavf_audio "" "-c:a pcm_u8" fate-lavf-peak.wav: CMD = lavf_audio "" "-write_peak on" -fate-lavf-peak_only.wav: CMD = lavf_audio "" "-write_peak only" +fate-lavf-peak_only.wav: CMD = lavf_audio "" "-write_peak only" "" disable_crc FATE_AVCONV += $(FATE_LAVF_AUDIO) fate-lavf-audio fate-lavf: $(FATE_LAVF_AUDIO) diff --git a/tests/fate/lavf-container.mak b/tests/fate/lavf-container.mak index 9e0eed485..7fb54d740 100644 --- a/tests/fate/lavf-container.mak +++ b/tests/fate/lavf-container.mak @@ -13,12 +13,22 @@ FATE_LAVF_CONTAINER-$(call ENCDEC2, MPEG2VIDEO, PCM_S16LE, MXF_D10 MXF) + FATE_LAVF_CONTAINER-$(call ENCDEC2, DNXHD, PCM_S16LE, MXF_OPATOM MXF) += mxf_opatom mxf_opatom_audio FATE_LAVF_CONTAINER-$(call ENCDEC2, MPEG4, MP2, NUT) += nut FATE_LAVF_CONTAINER-$(call ENCMUX, RV10 AC3_FIXED, RM) += rm -FATE_LAVF_CONTAINER-$(call ENCMUX, MJPEG PCM_S16LE, SMJPEG) += smjpeg +FATE_LAVF_CONTAINER-$(call ENCDEC2, MJPEG, PCM_S16LE, SMJPEG) += smjpeg FATE_LAVF_CONTAINER-$(call ENCDEC, FLV, SWF) += swf FATE_LAVF_CONTAINER-$(call ENCDEC2, MPEG2VIDEO, MP2, MPEGTS) += ts FATE_LAVF_CONTAINER-$(call ENCDEC, MP2, WTV) += wtv +FATE_LAVF_CONTAINER_RESAMPLE := asf avi dv_pal dv_ntsc gxf_pal gxf_ntsc \ + mkv mkv_attachment mpg mxf nut rm ts wtv +FATE_LAVF_CONTAINER-$(!CONFIG_ARESAMPLE_FILTER) := $(filter-out $(FATE_LAVF_CONTAINER_RESAMPLE),$(FATE_LAVF_CONTAINER-yes)) + +FATE_LAVF_CONTAINER_SCALE := dv dv_pal dv_ntsc flm gxf gxf_pal gxf_ntsc \ + mxf_dv25 mxf_dvcpro50 mxf_d10 mxf_opatom \ + smjpeg +FATE_LAVF_CONTAINER-$(!CONFIG_SCALE_FILTER) := $(filter-out $(FATE_LAVF_CONTAINER_SCALE),$(FATE_LAVF_CONTAINER-yes)) + FATE_LAVF_CONTAINER = $(FATE_LAVF_CONTAINER-yes:%=fate-lavf-%) +FATE_LAVF_CONTAINER := $(if $(call ENCDEC2, RAWVIDEO PGMYUV, PCM_S16LE, CRC IMAGE2, PCM_S16LE_DEMUXER), $(FATE_LAVF_CONTAINER)) $(FATE_LAVF_CONTAINER): CMD = lavf_container $(FATE_LAVF_CONTAINER): REF = $(SRC_PATH)/tests/ref/lavf/$(@:fate-lavf-%=%) diff --git a/tests/fate/lavf-image.mak b/tests/fate/lavf-image.mak index dbbd37430..38d3689ab 100644 --- a/tests/fate/lavf-image.mak +++ b/tests/fate/lavf-image.mak @@ -1,36 +1,57 @@ -FATE_LAVF_IMAGES-$(call ENCDEC, BMP, IMAGE2) += bmp -FATE_LAVF_IMAGES-$(call ENCDEC, DPX, IMAGE2) += dpx -FATE_LAVF_IMAGES-$(call ENCDEC, DPX, IMAGE2) += gbrp10le.dpx -FATE_LAVF_IMAGES-$(call ENCDEC, DPX, IMAGE2) += gbrp12le.dpx -FATE_LAVF_IMAGES-$(call ENCDEC, DPX, IMAGE2) += rgb48le.dpx -FATE_LAVF_IMAGES-$(call ENCDEC, DPX, IMAGE2) += rgb48le_10.dpx -FATE_LAVF_IMAGES-$(call ENCDEC, DPX, IMAGE2) += rgba64le.dpx -FATE_LAVF_IMAGES-$(call ENCDEC, MJPEG, IMAGE2) += jpg -FATE_LAVF_IMAGES-$(call ENCDEC, PAM, IMAGE2) += pam -FATE_LAVF_IMAGES-$(call ENCDEC, PAM, IMAGE2) += rgba.pam -FATE_LAVF_IMAGES-$(call ENCDEC, PAM, IMAGE2) += gray.pam -FATE_LAVF_IMAGES-$(call ENCDEC, PAM, IMAGE2) += gray16be.pam -FATE_LAVF_IMAGES-$(call ENCDEC, PAM, IMAGE2) += rgb48be.pam -FATE_LAVF_IMAGES-$(call ENCDEC, PAM, IMAGE2) += monob.pam -FATE_LAVF_IMAGES-$(call ENCDEC, PCX, IMAGE2) += pcx -FATE_LAVF_IMAGES-$(call ENCDEC, PGM, IMAGE2) += pgm -FATE_LAVF_IMAGES-$(call ENCDEC, PNG, IMAGE2) += png -FATE_LAVF_IMAGES-$(call ENCDEC, PNG, IMAGE2) += gray16be.png -FATE_LAVF_IMAGES-$(call ENCDEC, PNG, IMAGE2) += rgb48be.png -FATE_LAVF_IMAGES-$(call ENCDEC, PPM, IMAGE2) += ppm -FATE_LAVF_IMAGES-$(call ENCDEC, SGI, IMAGE2) += sgi -FATE_LAVF_IMAGES-$(call ENCDEC, SUNRAST, IMAGE2) += sun -FATE_LAVF_IMAGES-$(call ENCDEC, TARGA, IMAGE2) += tga -FATE_LAVF_IMAGES-$(call ENCDEC, TIFF, IMAGE2) += tiff -FATE_LAVF_IMAGES-$(call ENCDEC, XBM, IMAGE2) += xbm -FATE_LAVF_IMAGES-$(call ENCDEC, XWD, IMAGE2) += xwd -FATE_LAVF_IMAGES-$(call ENCDEC, XWD, IMAGE2) += rgba.xwd -FATE_LAVF_IMAGES-$(call ENCDEC, XWD, IMAGE2) += rgb565be.xwd -FATE_LAVF_IMAGES-$(call ENCDEC, XWD, IMAGE2) += rgb555be.xwd -FATE_LAVF_IMAGES-$(call ENCDEC, XWD, IMAGE2) += rgb8.xwd -FATE_LAVF_IMAGES-$(call ENCDEC, XWD, IMAGE2) += rgb4_byte.xwd -FATE_LAVF_IMAGES-$(call ENCDEC, XWD, IMAGE2) += gray.xwd -FATE_LAVF_IMAGES-$(call ENCDEC, XWD, IMAGE2) += monow.xwd +LAVF_IMAGES = $(call ALLYES, FILE_PROTOCOL IMAGE2_DEMUXER PGMYUV_DECODER \ + SCALE_FILTER $(1)_ENCODER IMAGE2_MUXER \ + $(1)_DECODER RAWVIDEO_ENCODER CRC_MUXER) + +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, BMP) += bmp +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, DPX) += dpx +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, DPX) += gbrp10le.dpx +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, DPX) += gbrp12le.dpx +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, DPX) += rgb48le.dpx +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, DPX) += rgb48le_10.dpx +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, DPX) += rgba64le.dpx +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, EXR) += none.grayf32le.exr +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, EXR) += none.gbrpf32le.exr +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, EXR) += none.gbrapf32le.exr +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, EXR) += rle.grayf32le.exr +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, EXR) += rle.gbrpf32le.exr +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, EXR) += rle.gbrapf32le.exr +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, EXR) += zip1.grayf32le.exr +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, EXR) += zip1.gbrpf32le.exr +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, EXR) += zip1.gbrapf32le.exr +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, EXR) += zip16.grayf32le.exr +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, EXR) += zip16.gbrpf32le.exr +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, EXR) += zip16.gbrapf32le.exr +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, MJPEG) += jpg +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, PAM) += pam +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, PAM) += rgba.pam +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, PAM) += gray.pam +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, PAM) += gray16be.pam +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, PAM) += rgb48be.pam +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, PAM) += monob.pam +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, PCX) += pcx +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, PFM) += grayf32le.pfm +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, PFM) += gbrpf32le.pfm +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, PFM) += grayf32be.pfm +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, PFM) += gbrpf32be.pfm +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, PGM) += pgm +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, PNG) += png +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, PNG) += gray16be.png +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, PNG) += rgb48be.png +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, PPM) += ppm +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, SGI) += sgi +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, SUNRAST) += sun +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, TARGA) += tga +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, TIFF) += tiff +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, QOI) += qoi +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, XBM) += xbm +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, XWD) += xwd +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, XWD) += rgba.xwd +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, XWD) += rgb565be.xwd +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, XWD) += rgb555be.xwd +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, XWD) += rgb8.xwd +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, XWD) += rgb4_byte.xwd +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, XWD) += gray.xwd +FATE_LAVF_IMAGES-$(call LAVF_IMAGES, XWD) += monow.xwd FATE_LAVF_IMAGES = $(FATE_LAVF_IMAGES-yes:%=fate-lavf-%) @@ -38,6 +59,18 @@ $(FATE_LAVF_IMAGES): CMD = lavf_image $(FATE_LAVF_IMAGES): REF = $(SRC_PATH)/tests/ref/lavf/$(@:fate-lavf-%=%) $(FATE_LAVF_IMAGES): $(VREF) +fate-lavf-none.grayf32le.exr: CMD = lavf_image "-compression none -pix_fmt grayf32le" +fate-lavf-rle.grayf32le.exr: CMD = lavf_image "-compression rle -pix_fmt grayf32le" +fate-lavf-zip1.grayf32le.exr: CMD = lavf_image "-compression zip1 -pix_fmt grayf32le" +fate-lavf-zip16.grayf32le.exr: CMD = lavf_image "-compression zip16 -pix_fmt grayf32le" +fate-lavf-none.gbrpf32le.exr: CMD = lavf_image "-compression none -pix_fmt gbrpf32le" +fate-lavf-rle.gbrpf32le.exr: CMD = lavf_image "-compression rle -pix_fmt gbrpf32le" +fate-lavf-zip1.gbrpf32le.exr: CMD = lavf_image "-compression zip1 -pix_fmt gbrpf32le" +fate-lavf-zip16.gbrpf32le.exr: CMD = lavf_image "-compression zip16 -pix_fmt gbrpf32le" +fate-lavf-none.gbrapf32le.exr: CMD = lavf_image "-compression none -pix_fmt gbrapf32le" +fate-lavf-rle.gbrapf32le.exr: CMD = lavf_image "-compression rle -pix_fmt gbrapf32le" +fate-lavf-zip1.gbrapf32le.exr: CMD = lavf_image "-compression zip1 -pix_fmt gbrapf32le" +fate-lavf-zip16.gbrapf32le.exr: CMD = lavf_image "-compression zip16 -pix_fmt gbrapf32le" fate-lavf-jpg: CMD = lavf_image "-pix_fmt yuvj420p" fate-lavf-tiff: CMD = lavf_image "-pix_fmt rgb24" fate-lavf-gbrp10le.dpx: CMD = lavf_image "-pix_fmt gbrp10le" "-pix_fmt gbrp10le" @@ -50,6 +83,10 @@ fate-lavf-gray.pam: CMD = lavf_image "-pix_fmt gray" fate-lavf-gray16be.pam: CMD = lavf_image "-pix_fmt gray16be" "-pix_fmt gray16be" fate-lavf-rgb48be.pam: CMD = lavf_image "-pix_fmt rgb48be" "-pix_fmt rgb48be" fate-lavf-monob.pam: CMD = lavf_image "-pix_fmt monob" +fate-lavf-grayf32le.pfm: CMD = lavf_image "-pix_fmt grayf32le" "-pix_fmt grayf32le" +fate-lavf-grayf32be.pfm: CMD = lavf_image "-pix_fmt grayf32be" "-pix_fmt grayf32be" +fate-lavf-gbrpf32le.pfm: CMD = lavf_image "-pix_fmt gbrpf32le" "-pix_fmt gbrpf32le" +fate-lavf-gbrpf32be.pfm: CMD = lavf_image "-pix_fmt gbrpf32be" "-pix_fmt gbrpf32be" fate-lavf-gray16be.png: CMD = lavf_image "-pix_fmt gray16be" fate-lavf-rgb48be.png: CMD = lavf_image "-pix_fmt rgb48be" fate-lavf-rgba.xwd: CMD = lavf_image "-pix_fmt rgba" diff --git a/tests/fate/lavf-image2pipe.mak b/tests/fate/lavf-image2pipe.mak index 297f677ad..318655140 100644 --- a/tests/fate/lavf-image2pipe.mak +++ b/tests/fate/lavf-image2pipe.mak @@ -1,6 +1,11 @@ -FATE_LAVF_IMAGE2PIPE-$(call ENCDEC, PBM, IMAGE2PIPE) += pbmpipe -FATE_LAVF_IMAGE2PIPE-$(call ENCDEC, PGM, IMAGE2PIPE) += pgmpipe -FATE_LAVF_IMAGE2PIPE-$(call ENCDEC, PPM, IMAGE2PIPE) += ppmpipe +LAVF_IMAGE2PIPE = $(call ALLYES, $(1)_DECODER $(1)_ENCODER $(2) \ + IMAGE2_DEMUXER PGMYUV_DECODER \ + IMAGE2PIPE_MUXER IMAGE2PIPE_DEMUXER \ + RAWVIDEO_ENCODER CRC_MUXER FILE_PROTOCOL) + +FATE_LAVF_IMAGE2PIPE-$(call LAVF_IMAGE2PIPE, PBM, PNM_PARSER SCALE_FILTER) += pbmpipe +FATE_LAVF_IMAGE2PIPE-$(call LAVF_IMAGE2PIPE, PGM, PNM_PARSER SCALE_FILTER) += pgmpipe +FATE_LAVF_IMAGE2PIPE-$(call LAVF_IMAGE2PIPE, PPM, PNM_PARSER SCALE_FILTER) += ppmpipe FATE_LAVF_IMAGE2PIPE = $(FATE_LAVF_IMAGE2PIPE-yes:%=fate-lavf-%) diff --git a/tests/fate/lavf-video.mak b/tests/fate/lavf-video.mak index f6e98246c..7557283dd 100644 --- a/tests/fate/lavf-video.mak +++ b/tests/fate/lavf-video.mak @@ -1,15 +1,19 @@ -FATE_LAVF_VIDEO-$(call ENCDEC, APNG, APNG) += apng -FATE_LAVF_VIDEO-$(call ENCDEC, APNG, APNG) += apng.png -FATE_LAVF_VIDEO-$(call ENCDEC, FITS, FITS) += gray.fits -FATE_LAVF_VIDEO-$(call ENCDEC, FITS, FITS) += gray16be.fits -FATE_LAVF_VIDEO-$(call ENCDEC, FITS, FITS) += gbrp.fits -FATE_LAVF_VIDEO-$(call ENCDEC, FITS, FITS) += gbrap.fits -FATE_LAVF_VIDEO-$(call ENCDEC, FITS, FITS) += gbrp16be.fits -FATE_LAVF_VIDEO-$(call ENCDEC, FITS, FITS) += gbrap16be.fits -FATE_LAVF_VIDEO-$(call ENCDEC, GIF, GIF) += gif -FATE_LAVF_VIDEO-$(CONFIG_YUV4MPEGPIPE_MUXER) += y4m +FATE_LAVF_VIDEO_SCALE-$(call ENCDEC, APNG, APNG) += apng +FATE_LAVF_VIDEO_SCALE-$(call ENCDEC, APNG PNG, APNG) += apng.png +FATE_LAVF_VIDEO_SCALE-$(call ENCDEC, FITS, FITS) += gray.fits +FATE_LAVF_VIDEO_SCALE-$(call ENCDEC, FITS, FITS) += gray16be.fits +FATE_LAVF_VIDEO_SCALE-$(call ENCDEC, FITS, FITS) += gbrp.fits +FATE_LAVF_VIDEO_SCALE-$(call ENCDEC, FITS, FITS) += gbrap.fits +FATE_LAVF_VIDEO_SCALE-$(call ENCDEC, FITS, FITS) += gbrp16be.fits +FATE_LAVF_VIDEO_SCALE-$(call ENCDEC, FITS, FITS) += gbrap16be.fits +FATE_LAVF_VIDEO_SCALE-$(call ENCDEC, GIF, GIF) += gif +FATE_LAVF_VIDEO-$(call ENCDEC, WRAPPED_AVFRAME RAWVIDEO, YUV4MPEGPIPE) += y4m +FATE_LAVF_VIDEO-$(CONFIG_SCALE_FILTER) += $(FATE_LAVF_VIDEO_SCALE-yes) FATE_LAVF_VIDEO = $(FATE_LAVF_VIDEO-yes:%=fate-lavf-%) +FATE_LAVF_VIDEO := $(if $(call ALLYES, IMAGE2_DEMUXER PGMYUV_DECODER \ + RAWVIDEO_ENCODER CRC_MUXER), \ + $(FATE_LAVF_VIDEO)) $(FATE_LAVF_VIDEO): CMD = lavf_video $(FATE_LAVF_VIDEO): REF = $(SRC_PATH)/tests/ref/lavf/$(@:fate-lavf-%=%) diff --git a/tests/fate/libavformat.mak b/tests/fate/libavformat.mak index 59ff0ebc8..d2acb4c9e 100644 --- a/tests/fate/libavformat.mak +++ b/tests/fate/libavformat.mak @@ -26,6 +26,11 @@ FATE_LIBAVFORMAT-$(CONFIG_IMF_DEMUXER) += fate-imf fate-imf: libavformat/tests/imf$(EXESUF) fate-imf: CMD = run libavformat/tests/imf$(EXESUF) +FATE_LIBAVFORMAT += fate-seek_utils +fate-seek_utils: libavformat/tests/seek_utils$(EXESUF) +fate-seek_utils: CMD = run libavformat/tests/seek_utils$(EXESUF) +fate-seek_utils: CMP = null + FATE_LIBAVFORMAT += $(FATE_LIBAVFORMAT-yes) FATE-$(CONFIG_AVFORMAT) += $(FATE_LIBAVFORMAT) fate-libavformat: $(FATE_LIBAVFORMAT) diff --git a/tests/fate/libavutil.mak b/tests/fate/libavutil.mak index 1ec9ed00a..80153f439 100644 --- a/tests/fate/libavutil.mak +++ b/tests/fate/libavutil.mak @@ -23,6 +23,10 @@ fate-cast5: libavutil/tests/cast5$(EXESUF) fate-cast5: CMD = run libavutil/tests/cast5$(EXESUF) fate-cast5: CMP = null +FATE_LIBAVUTIL += fate-channel_layout +fate-channel_layout: libavutil/tests/channel_layout$(EXESUF) +fate-channel_layout: CMD = run libavutil/tests/channel_layout$(EXESUF) + FATE_LIBAVUTIL += fate-audio_fifo fate-audio_fifo: libavutil/tests/audio_fifo$(EXESUF) fate-audio_fifo: CMD = run libavutil/tests/audio_fifo$(EXESUF) @@ -166,6 +170,11 @@ FATE_LIBAVUTIL += fate-opt fate-opt: libavutil/tests/opt$(EXESUF) fate-opt: CMD = run libavutil/tests/opt$(EXESUF) +FATE_LIBAVUTIL += fate-uuid +fate-uuid: libavutil/tests/uuid$(EXESUF) +fate-uuid: CMD = run libavutil/tests/uuid$(EXESUF) +fate-uuid: CMP = null + FATE_LIBAVUTIL += $(FATE_LIBAVUTIL-yes) FATE-$(CONFIG_AVUTIL) += $(FATE_LIBAVUTIL) fate-libavutil: $(FATE_LIBAVUTIL) diff --git a/tests/fate/libswscale.mak b/tests/fate/libswscale.mak index cf9319ec4..f8572f9c3 100644 --- a/tests/fate/libswscale.mak +++ b/tests/fate/libswscale.mak @@ -17,6 +17,22 @@ $(SWS_SLICE_TEST-yes): tools/scale_slice_test$(EXESUF) $(SWS_SLICE_TEST-yes): REF = /dev/null FATE_LIBSWSCALE_SAMPLES += $(SWS_SLICE_TEST-yes) +FATE_LIBSWSCALE-$(CONFIG_RAWVIDEO_DEMUXER) += fate-sws-yuv-colorspace +fate-sws-yuv-colorspace: tests/data/vsynth1.yuv +fate-sws-yuv-colorspace: ffmpeg$(PROGSSUF)$(EXESUF) +fate-sws-yuv-colorspace: CMD = framecrc \ + -f rawvideo -s 352x288 -pix_fmt yuv420p -i $(TARGET_PATH)/tests/data/vsynth1.yuv \ + -frames 1 \ + -vf scale=in_color_matrix=bt709:in_range=limited:out_color_matrix=bt601:out_range=full:flags=+accurate_rnd+bitexact + +FATE_LIBSWSCALE-$(CONFIG_RAWVIDEO_DEMUXER) += fate-sws-yuv-range +fate-sws-yuv-range: tests/data/vsynth1.yuv +fate-sws-yuv-range: ffmpeg$(PROGSSUF)$(EXESUF) +fate-sws-yuv-range: CMD = framecrc \ + -f rawvideo -s 352x288 -pix_fmt yuv420p -i $(TARGET_PATH)/tests/data/vsynth1.yuv \ + -frames 1 \ + -vf scale=in_color_matrix=bt601:in_range=limited:out_color_matrix=bt601:out_range=full:flags=+accurate_rnd+bitexact + FATE_LIBSWSCALE += $(FATE_LIBSWSCALE-yes) FATE_LIBSWSCALE_SAMPLES += $(FATE_LIBSWSCALE_SAMPLES-yes) FATE-$(CONFIG_SWSCALE) += $(FATE_LIBSWSCALE) diff --git a/tests/fate/lossless-video.mak b/tests/fate/lossless-video.mak index a81c6e9ab..05a8ba29e 100644 --- a/tests/fate/lossless-video.mak +++ b/tests/fate/lossless-video.mak @@ -1,7 +1,7 @@ FATE_LAGARITH += fate-lagarith-rgb24 fate-lagarith-rgb24: CMD = framecrc -i $(TARGET_SAMPLES)/lagarith/lag-rgb24.avi -FATE_LAGARITH += fate-lagarith-rgb32 +FATE_LAGARITH-$(call FRAMECRC, AVI, LAGARITH, SCALE_FILTER) += fate-lagarith-rgb32 fate-lagarith-rgb32: CMD = framecrc -i $(TARGET_SAMPLES)/lagarith/lag-rgb32.avi -pix_fmt bgra -vf scale FATE_LAGARITH += fate-lagarith-yuy2 @@ -19,31 +19,31 @@ fate-lagarith-ticket4119-cfr : CMD = framecrc -i $(TARGET_SAMPLES)/lagarith/laga fate-lagarith-ticket4119-vfr : CMD = framecrc -i $(TARGET_SAMPLES)/lagarith/lagarith-1.3.27-black-frames-and-off-by-ones.avi -vsync vfr fate-lagarith-ticket4119-pass: CMD = framecrc -i $(TARGET_SAMPLES)/lagarith/lagarith-1.3.27-black-frames-and-off-by-ones.avi -vsync passthrough -FATE_LOSSLESS_VIDEO-$(call DEMDEC, AVI, LAGARITH) += $(FATE_LAGARITH) -fate-lagarith: $(FATE_LAGARITH) +FATE_LAGARITH-$(call FRAMECRC, AVI, LAGARITH) += $(FATE_LAGARITH) -FATE_LOCO += fate-loco-rgb -fate-loco-rgb: CMD = framecrc -i $(TARGET_SAMPLES)/loco/pig-loco-rgb.avi +FATE_LOSSLESS_VIDEO += $(FATE_LAGARITH-yes) +fate-lagarith: $(FATE_LAGARITH-yes) -FATE_LOCO += fate-loco-yuy2 +FATE_LOCO-$(call FRAMECRC, AVI, LOCO) += fate-loco-rgb fate-loco-yuy2 +fate-loco-rgb: CMD = framecrc -i $(TARGET_SAMPLES)/loco/pig-loco-rgb.avi fate-loco-yuy2: CMD = framecrc -i $(TARGET_SAMPLES)/loco/pig-loco-0.avi -FATE_LOSSLESS_VIDEO-$(call DEMDEC, AVI, LOCO) += $(FATE_LOCO) -fate-loco: $(FATE_LOCO) +FATE_LOSSLESS_VIDEO += $(FATE_LOCO-yes) +fate-loco: $(FATE_LOCO-yes) -FATE_LOSSLESS_VIDEO-$(call DEMDEC, AVI, MSRLE) += fate-msrle-8bit +FATE_LOSSLESS_VIDEO-$(call FRAMECRC, AVI, MSRLE, SCALE_FILTER) += fate-msrle-8bit fate-msrle-8bit: CMD = framecrc -i $(TARGET_SAMPLES)/msrle/Search-RLE.avi -pix_fmt rgb24 -vf scale -FATE_LOSSLESS_VIDEO-$(call DEMDEC, AVI, MSZH) += fate-mszh +FATE_LOSSLESS_VIDEO-$(call FRAMECRC, AVI, MSZH) += fate-mszh fate-mszh: CMD = framecrc -i $(TARGET_SAMPLES)/lcl/mszh-1frame.avi -FATE_LOSSLESS_VIDEO-$(call DEMDEC, AVI, VBLE) += fate-vble +FATE_LOSSLESS_VIDEO-$(call FRAMECRC, AVI, VBLE) += fate-vble fate-vble: CMD = framecrc -i $(TARGET_SAMPLES)/vble/flowers-partial-2MB.avi -FATE_LOSSLESS_VIDEO-$(call DEMDEC, AVI, ZEROCODEC) += fate-zerocodec +FATE_LOSSLESS_VIDEO-$(call FRAMECRC, AVI, ZEROCODEC) += fate-zerocodec fate-zerocodec: CMD = framecrc -i $(TARGET_SAMPLES)/zerocodec/sample-zeco.avi -FATE_LOSSLESS_VIDEO-$(call DEMDEC, AVI, ZLIB) += fate-zlib +FATE_LOSSLESS_VIDEO-$(call FRAMECRC, AVI, ZLIB) += fate-zlib fate-zlib: CMD = framecrc -i $(TARGET_SAMPLES)/lcl/zlib-1frame.avi FATE_LOSSLESS_VIDEO += $(FATE_LOSSLESS_VIDEO-yes) diff --git a/tests/fate/matroska.mak b/tests/fate/matroska.mak index e117a0f6a..b49ec761c 100644 --- a/tests/fate/matroska.mak +++ b/tests/fate/matroska.mak @@ -12,7 +12,7 @@ fate-matroska-prores-header-insertion-bz2: CMD = framecrc -i $(TARGET_SAMPLES)/m FATE_MATROSKA-$(call DEMMUX, MATROSKA, MATROSKA) += fate-matroska-remux fate-matroska-remux: CMD = md5pipe -i $(TARGET_SAMPLES)/vp9-test-vectors/vp90-2-2pass-akiyo.webm -color_trc 4 -c:v copy -fflags +bitexact -strict -2 -f matroska fate-matroska-remux: CMP = oneline -fate-matroska-remux: REF = 26fabd90326e3de4bb6afe1b216ce232 +fate-matroska-remux: REF = b9c7b650349972c9dce42ab79b472917 FATE_MATROSKA-$(call ALLYES, MATROSKA_DEMUXER VORBIS_PARSER) += fate-matroska-xiph-lacing fate-matroska-xiph-lacing: CMD = framecrc -i $(TARGET_SAMPLES)/mkv/xiph_lacing.mka -c:a copy @@ -28,7 +28,7 @@ FATE_MATROSKA-$(call ALLYES, MATROSKA_DEMUXER ZLIB) += fate-matroska-zlib-decomp fate-matroska-zlib-decompression: CMD = framecrc -i $(TARGET_SAMPLES)/mkv/subtitle_zlib.mks -c:s copy # This tests that the matroska demuxer can decompress lzo compressed tracks. -FATE_MATROSKA-$(call ALLYES, MATROSKA_DEMUXER LZO) += fate-matroska-lzo-decompression +FATE_MATROSKA-$(CONFIG_MATROSKA_DEMUXER) += fate-matroska-lzo-decompression fate-matroska-lzo-decompression: CMD = framecrc -i $(TARGET_SAMPLES)/mkv/lzo.mka -c copy # This tests that the matroska demuxer correctly propagates @@ -55,7 +55,7 @@ fate-matroska-flac-extradata-update: CMD = transcode matroska $(TARGET_SAMPLES)/ FATE_MATROSKA_FFMPEG_FFPROBE-$(call ALLYES, MATROSKA_DEMUXER OGG_DEMUXER \ VORBIS_DECODER VORBIS_PARSER WEBM_MUXER) \ += fate-webm-dash-chapters -fate-webm-dash-chapters: CMD = transcode ogg $(TARGET_SAMPLES)/vorbis/vorbis_chapter_extension_demo.ogg webm "-c copy -cluster_time_limit 1500 -dash 1 -dash_track_number 124 -reserve_index_space 400" "-c copy -t 0.5" "" -show_chapters +fate-webm-dash-chapters: CMD = transcode ogg $(TARGET_SAMPLES)/vorbis/vorbis_chapter_extension_demo.ogg webm "-c copy -cluster_time_limit 1500 -dash 1 -dash_track_number 124 -reserve_index_space 400" "-c copy -t 0.5" -show_chapters # The input file has a Block whose payload has a size of zero before reversing # header removal compression; it furthermore uses chained SeekHeads and has @@ -65,15 +65,62 @@ fate-webm-dash-chapters: CMD = transcode ogg $(TARGET_SAMPLES)/vorbis/vorbis_cha # It furthermore tests correct propagation of the description tag. FATE_MATROSKA_FFMPEG_FFPROBE-$(call DEMMUX, MATROSKA, MATROSKA) \ += fate-matroska-zero-length-block -fate-matroska-zero-length-block: CMD = transcode matroska $(TARGET_SAMPLES)/mkv/zero_length_block.mks matroska "-c:s copy -dash 1 -dash_track_number 2000000000 -reserve_index_space 62 -metadata_header_padding 1 -default_mode infer_no_subs" "-c:s copy" "" "-show_entries stream_tags=description" +fate-matroska-zero-length-block: CMD = transcode matroska $(TARGET_SAMPLES)/mkv/zero_length_block.mks matroska "-c:s copy -dash 1 -dash_track_number 2000000000 -reserve_index_space 62 -metadata_header_padding 1 -default_mode infer_no_subs" "-c:s copy" "-show_entries stream_tags=description" + +# This mainly tests the Matroska muxer's ability to shift the data +# to create enough free space to write the Cues at the front. +# The metadata_header_padding has been chosen so that three attempts +# to write the Cues are necessary. +# It also tests writing PCM audio in both endiannesses and putting +# Cues with the same timestamp in the same CuePoint as well as +# omitting CRC-32 elements when writing Matroska. +FATE_MATROSKA-$(call TRANSCODE, PCM_S24BE PCM_S24LE, MATROSKA, WAV_DEMUXER) \ + += fate-matroska-move-cues-to-front +fate-matroska-move-cues-to-front: CMD = transcode wav $(TARGET_SAMPLES)/audio-reference/divertimenti_2ch_96kHz_s24.wav matroska "-map 0 -map 0 -c:a:0 pcm_s24be -c:a:1 copy -cluster_time_limit 5 -cues_to_front yes -metadata_header_padding 7840 -write_crc32 0" "-map 0 -c copy -t 0.1" + +# This tests DOVI (reading from MP4 and Matroska and writing to Matroska) +# as well as writing the Cues at the front (by shifting data) if +# the initially reserved amount of space turns out to be insufficient. +FATE_MATROSKA_FFMPEG_FFPROBE-$(call REMUX, MATROSKA, MOV_DEMUXER HEVC_DECODER) \ + += fate-matroska-dovi-write-config7 +fate-matroska-dovi-write-config7: CMD = transcode mov $(TARGET_SAMPLES)/mov/dovi-p7.mp4 matroska "-map 0 -c copy -cues_to_front yes -reserve_index_space 40 -metadata_header_padding 64339" "-map 0 -c copy" "-show_entries stream_side_data_list" + +FATE_MATROSKA_FFMPEG_FFPROBE-$(call REMUX, MATROSKA, MOV_DEMUXER \ + HEVC_DECODER AAC_DECODER) \ + += fate-matroska-dovi-write-config8 +fate-matroska-dovi-write-config8: CMD = transcode mov $(TARGET_SAMPLES)/hevc/dv84.mov matroska "-c copy" "-map 0 -c copy -t 0.4" "-show_entries stream_side_data_list -select_streams v" + +# This tests the scenario like tickets #4536, #5784 where +# the first packet (with the overall lowest dts) is a video packet, +# whereas an audio packet to be muxed later has the overall lowest pts +# which happens to be negative and therefore needs to be shifted. +# (-ss 1.09 ensures that a video frame has the lowest dts of all packets; +# yet there is an audio packet with the overall lowest pts. output_ts_offset +# makes the pts of the audio packet, but not the leading video packet negative +# so that we run into the above issue.) +FATE_MATROSKA-$(call REMUX, MATROSKA, MPEGTS_DEMUXER MPEGVIDEO_PARSER \ + MPEG2VIDEO_DECODER EXTRACT_EXTRADATA_BSF \ + MP3FLOAT_DECODER) \ + += fate-matroska-avoid-negative-ts +fate-matroska-avoid-negative-ts: CMD = transcode mpegts $(TARGET_SAMPLES)/mpeg2/t.mpg matroska "-c copy -ss 1.09 -output_ts_offset -60ms" "-c copy -t 0.4" + +# This tests writing the MS-compatibility modes V_MS/VFW/FOURCC and A_MS/ACM. +# It furthermore tests writing the Cues at the front if the cues_to_front +# option is set and more than enough space has been reserved in advance. +# (Btw: The keyframe flags of the input video stream seem wrong.) +FATE_MATROSKA-$(call REMUX, MATROSKA, AVI_DEMUXER) += fate-matroska-ms-mode +fate-matroska-ms-mode: CMD = transcode avi $(TARGET_SAMPLES)/vp5/potter512-400-partial.avi matroska "-map 0 -c copy -cues_to_front yes -reserve_index_space 5000" "-map 0 -c copy -t 1" + +# This tests Matroska's QT-compatibility mode. +FATE_MATROSKA-$(call REMUX, MATROSKA, MOV_DEMUXER) += fate-matroska-qt-mode +fate-matroska-qt-mode: CMD = transcode mov $(TARGET_SAMPLES)/svq1/marymary-shackles.mov matroska "-c copy" "-c copy -t 3" # This test the following features of the Matroska muxer: Writing projection # stream side-data; not setting any track to default if the user requested it; # and modifying and writing colorspace properties. -FATE_MATROSKA_FFMPEG_FFPROBE-$(call ALLYES, MATROSKA_DEMUXER MATROSKA_MUXER \ - H264_DECODER H264_PARSER) \ +FATE_MATROSKA_FFMPEG_FFPROBE-$(call REMUX, MATROSKA, H264_DECODER H264_PARSER) \ += fate-matroska-spherical-mono-remux -fate-matroska-spherical-mono-remux: CMD = transcode matroska $(TARGET_SAMPLES)/mkv/spherical.mkv matroska "-map 0 -map 0 -c copy -disposition:0 -default+forced -disposition:1 -default -default_mode passthrough -color_primaries:1 bt709 -color_trc:1 smpte170m -colorspace:1 bt2020c -color_range:1 pc" "-map 0 -c copy -t 0" "" "-show_entries stream_side_data_list:stream_disposition=default,forced:stream=color_range,color_space,color_primaries,color_transfer" +fate-matroska-spherical-mono-remux: CMD = transcode matroska $(TARGET_SAMPLES)/mkv/spherical.mkv matroska "-map 0 -map 0 -c copy -disposition:0 -default+forced -disposition:1 -default -default_mode passthrough -color_primaries:1 bt709 -color_trc:1 smpte170m -colorspace:1 bt2020c -color_range:1 pc" "-map 0 -c copy -t 0" "-show_entries stream_side_data_list:stream_disposition=default,forced:stream=color_range,color_space,color_primaries,color_transfer" # The input file of the following test contains Content Light Level as well as # Mastering Display Metadata and so this test tests correct muxing and demuxing @@ -81,14 +128,11 @@ fate-matroska-spherical-mono-remux: CMD = transcode matroska $(TARGET_SAMPLES)/m # when reencoding (here to ffv1). # Both input audio tracks are completely zero, so the noise bsf is used # to make this test interesting. -FATE_MATROSKA_FFMPEG_FFPROBE-$(call ALLYES, FILE_PROTOCOL MXF_DEMUXER \ - PRORES_DECODER PCM_S24LE_DECODER \ - FFV1_ENCODER ARESAMPLE_FILTER \ - PCM_S16BE_ENCODER NOISE_BSF \ - MATROSKA_MUXER MATROSKA_DEMUXER \ - FRAMECRC_MUXER PIPE_PROTOCOL) \ +FATE_MATROSKA_FFMPEG_FFPROBE-$(call TRANSCODE, FFV1 PRORES, MATROSKA, MXF_DEMUXER \ + PCM_S24LE_DECODER ARESAMPLE_FILTER \ + PCM_S16BE_ENCODER NOISE_BSF) \ += fate-matroska-mastering-display-metadata -fate-matroska-mastering-display-metadata: CMD = transcode mxf $(TARGET_SAMPLES)/mxf/Meridian-Apple_ProResProxy-HDR10.mxf matroska "-map 0 -map 0:0 -c:v:0 copy -c:v:1 ffv1 -c:a:0 copy -bsf:a:0 noise=amount=3 -filter:a:1 aresample -c:a:1 pcm_s16be -bsf:a:1 noise=amount=-1:drop=-4" "-map 0 -c copy" "" "-show_entries stream_side_data_list:stream=index,codec_name" +fate-matroska-mastering-display-metadata: CMD = transcode mxf $(TARGET_SAMPLES)/mxf/Meridian-Apple_ProResProxy-HDR10.mxf matroska "-map 0 -map 0:0 -c:v:0 copy -c:v:1 ffv1 -c:a:0 copy -bsf:a:0 noise=amount=3 -filter:a:1 aresample -c:a:1 pcm_s16be -bsf:a:1 noise=amount=-1:drop=-4" "-map 0 -c copy" "-show_entries stream_side_data_list:stream=index,codec_name" # This test tests remuxing annex B H.264 into Matroska. It also tests writing # the correct interlaced flags and overriding the sample aspect ratio, leading @@ -96,34 +140,46 @@ fate-matroska-mastering-display-metadata: CMD = transcode mxf $(TARGET_SAMPLES)/ # the h264_metadata filter is used to remove it as well as the H.264 AUD. # The video is decoded twice to show that this did not change the decoded # output. Furthermore, this also tests writing PCM with bitdepth 32. -FATE_MATROSKA_FFMPEG_FFPROBE-$(call ALLYES, FILE_PROTOCOL MPEGTS_DEMUXER \ - H264_PARSER MPEGAUDIO_PARSER \ - EXTRACT_EXTRADATA_BSF MP2_DECODER \ - H264_METADATA_BSF ARESAMPLE_FILTER \ - RAWVIDEO_ENCODER PCM_S32LE_ENCODER \ - PCM_S32BE_ENCODER MATROSKA_MUXER \ - MATROSKA_DEMUXER H264_DECODER \ - FRAMECRC_MUXER PIPE_PROTOCOL) \ +FATE_MATROSKA_FFMPEG_FFPROBE-$(call TRANSCODE, PCM_S32LE MP2, MATROSKA, \ + MPEGTS_DEMUXER H264_PARSER \ + H264_DECODER MPEGAUDIO_PARSER \ + EXTRACT_EXTRADATA_BSF \ + H264_METADATA_BSF \ + ARESAMPLE_FILTER \ + PCM_S32BE_ENCODER) \ += fate-matroska-h264-remux -fate-matroska-h264-remux: CMD = transcode mpegts $(TARGET_SAMPLES)/h264/h264_intra_first-small.ts matroska "-map 0:0 -map 0 -c:v copy -sar:0 3:4 -bsf:v:1 h264_metadata=aud=remove:delete_filler=1 -disposition:v +hearing_impaired -af aresample -c:a:0 pcm_s32le -c:a:1 pcm_s32be -disposition:a:0 original -metadata:s:a:0 title=swedish_silence -metadata:s:a:1 title=norwegian_silence -disposition:a:1 dub" "-map 0:v" "" "-show_entries stream=index,codec_name:stream_tags=title,language" +fate-matroska-h264-remux: CMD = transcode mpegts $(TARGET_SAMPLES)/h264/h264_intra_first-small.ts matroska "-map 0:0 -map 0 -c:v copy -sar:0 3:4 -bsf:v:1 h264_metadata=aud=remove:delete_filler=1 -disposition:v +hearing_impaired -af aresample -c:a:0 pcm_s32le -c:a:1 pcm_s32be -disposition:a:0 original -metadata:s:a:0 title=swedish_silence -metadata:s:a:1 title=norwegian_silence -disposition:a:1 dub" "-map 0:v" "-show_entries stream=index,codec_name:stream_tags=title,language" # Tests writing BlockAdditional and BlockGroups with ReferenceBlock elements; # it also tests setting a track as suitable for hearing impaired. # It also tests the capability of the VP8 parser to set the keyframe flag # (the input file lacks ReferenceBlock elements making everything a keyframe). -FATE_MATROSKA_FFMPEG_FFPROBE-$(call ALLYES, FILE_PROTOCOL MATROSKA_DEMUXER \ - VP8_PARSER MATROSKA_MUXER \ - FRAMECRC_MUXER PIPE_PROTOCOL) \ +FATE_MATROSKA_FFMPEG_FFPROBE-$(call REMUX, MATROSKA, VP8_PARSER) \ += fate-matroska-vp8-alpha-remux -fate-matroska-vp8-alpha-remux: CMD = transcode matroska $(TARGET_SAMPLES)/vp8_alpha/vp8_video_with_alpha.webm matroska "-c copy -disposition +hearing_impaired -cluster_size_limit 100000" "-c copy -t 0.2" "" "-show_entries stream_disposition:stream_side_data_list" +fate-matroska-vp8-alpha-remux: CMD = transcode matroska $(TARGET_SAMPLES)/vp8_alpha/vp8_video_with_alpha.webm matroska "-c copy -disposition +hearing_impaired -cluster_size_limit 100000" "-c copy -t 0.2" "-show_entries stream_disposition:stream_side_data_list" # The audio stream to be remuxed here has AV_DISPOSITION_VISUAL_IMPAIRED. -FATE_MATROSKA_FFMPEG_FFPROBE-$(call ALLYES, FILE_PROTOCOL MPEGTS_DEMUXER \ - AC3_DECODER MATROSKA_MUXER \ - MATROSKA_DEMUXER FRAMECRC_MUXER \ - PIPE_PROTOCOL) \ +FATE_MATROSKA_FFMPEG_FFPROBE-$(call REMUX, MATROSKA, MPEGTS_DEMUXER AC3_DECODER) \ += fate-matroska-mpegts-remux -fate-matroska-mpegts-remux: CMD = transcode mpegts $(TARGET_SAMPLES)/mpegts/pmtchange.ts matroska "-map 0:2 -map 0:2 -c copy -disposition:a:1 -visual_impaired+hearing_impaired -default_mode infer" "-map 0 -c copy" "" "-show_entries stream_disposition:stream=index" +fate-matroska-mpegts-remux: CMD = transcode mpegts $(TARGET_SAMPLES)/mpegts/pmtchange.ts matroska "-map 0:2 -map 0:2 -c copy -disposition:a:1 -visual_impaired+hearing_impaired -default_mode infer" "-map 0 -c copy" "-show_entries stream_disposition:stream=index" + +FATE_MATROSKA-$(call REMUX, MATROSKA, SUP_DEMUXER) += fate-matroska-pgs-remux +fate-matroska-pgs-remux: CMD = transcode sup $(TARGET_SAMPLES)/sub/pgs_sub.sup matroska "-copyts -c:s copy" "-copyts -c:s copy" + +# This test uses the setts bsf to derive the duration of every packet +# except the last from the next packet's pts. +FATE_MATROSKA-$(call REMUX, MATROSKA, SUP_DEMUXER PGS_FRAME_MERGE_BSF SETTS_BSF) += fate-matroska-pgs-remux-durations +fate-matroska-pgs-remux-durations: CMD = transcode sup $(TARGET_SAMPLES)/sub/pgs_sub.sup matroska "-copyts -c:s copy -bsf pgs_frame_merge,setts=duration=if(gt(DURATION\,0)\,DURATION\,if(eq(PTS\,NOPTS)\,0\,if(eq(NEXT_PTS\,NOPTS)\,0\,NEXT_PTS-PTS))):pts=PTS" "-copyts -c:s copy" + +# This test muxes DVB subtitles twice into Matroska: Once normally +# and once with durations derived via the setts filter. Said filter +# sets the duration for every packet except the last it receives. +# The "-t 20" also tests that the BSF is properly flushed even +# when processing ended due to something else than the input's EOF. +# Notice that the last packet of stream 0 before 20s is present, +# but has no duration (like stream 1). +FATE_MATROSKA-$(call REMUX, MATROSKA, MPEGTS_DEMUXER DVBSUB_PARSER SETTS_BSF) += fate-matroska-dvbsub-remux +fate-matroska-dvbsub-remux: CMD = transcode mpegts $(TARGET_SAMPLES)/sub/dvbsubtest_filter.ts matroska "-map 0:s -map 0:s -t 20 -c copy -bsf:0 setts=duration=if(gt(DURATION\,0)\,DURATION\,if(eq(PTS\,NOPTS)\,0\,if(eq(NEXT_PTS\,NOPTS)\,0\,NEXT_PTS-PTS))):pts=PTS" "-map 0 -c copy" FATE_MATROSKA_FFPROBE-$(call ALLYES, MATROSKA_DEMUXER) += fate-matroska-spherical-mono fate-matroska-spherical-mono: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_entries stream_side_data_list -select_streams v -v 0 $(TARGET_SAMPLES)/mkv/spherical.mkv @@ -132,11 +188,9 @@ fate-matroska-spherical-mono: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_entrie # It also tests that dispositions not supported by WebM are not written # (and therefore lost). It moreover tests that the muxer writes CuePoints # with multiple CueTrackPositions if the timestamps coincide. -FATE_MATROSKA_FFMPEG_FFPROBE-$(call ALLYES, FILE_PROTOCOL WEBVTT_DEMUXER \ - WEBM_MUXER MATROSKA_DEMUXER \ - FRAMECRC_MUXER PIPE_PROTOCOL) \ +FATE_MATROSKA_FFMPEG_FFPROBE-$(call REMUX, WEBM MATROSKA, WEBVTT_DEMUXER) \ += fate-webm-webvtt-remux -fate-webm-webvtt-remux: CMD = transcode webvtt $(TARGET_SAMPLES)/sub/WebVTT_capability_tester.vtt webm "-map 0 -map 0 -map 0 -map 0 -c:s copy -disposition:0 original+descriptions+hearing_impaired -disposition:1 lyrics+default+metadata -disposition:2 comment+forced -disposition:3 karaoke+captions+dub" "-map 0:0 -map 0:1 -c copy" "" "-show_entries stream_disposition:stream=index,codec_name:packet=stream_index,pts:packet_side_data_list -show_data_hash CRC32" +fate-webm-webvtt-remux: CMD = transcode webvtt $(TARGET_SAMPLES)/sub/WebVTT_capability_tester.vtt webm "-map 0 -map 0 -map 0 -map 0 -c:s copy -disposition:0 original+descriptions+hearing_impaired -disposition:1 lyrics+default+metadata -disposition:2 comment+forced -disposition:3 karaoke+captions+dub" "-map 0:0 -map 0:1 -c copy" "-show_entries stream_disposition:stream=index,codec_name:packet=stream_index,pts:packet_side_data_list -show_data_hash CRC32" FATE_SAMPLES_AVCONV += $(FATE_MATROSKA-yes) FATE_SAMPLES_FFPROBE += $(FATE_MATROSKA_FFPROBE-yes) diff --git a/tests/fate/microsoft.mak b/tests/fate/microsoft.mak index 639757880..ee1a06242 100644 --- a/tests/fate/microsoft.mak +++ b/tests/fate/microsoft.mak @@ -1,7 +1,7 @@ -FATE_MICROSOFT-$(call DEMDEC, AVI, MSMPEG4V1) += fate-msmpeg4v1 +FATE_MICROSOFT-$(call FRAMECRC, AVI, MSMPEG4V1) += fate-msmpeg4v1 fate-msmpeg4v1: CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/msmpeg4v1/mpg4.avi -an -FATE_SAMPLES_AVCONV-$(call DEMDEC, ASF, MSS1) += fate-mss1-pal +FATE_MICROSOFT-$(call FRAMECRC, ASF, MSS1) += fate-mss1-pal fate-mss1-pal: CMD = framecrc -i $(TARGET_SAMPLES)/mss1/screen_codec.wmv -an FATE_MSS2 += fate-mss2-pal @@ -10,80 +10,76 @@ fate-mss2-pal: CMD = framecrc -i $(TARGET_SAMPLES)/mss2/rlepal.wmv FATE_MSS2 += fate-mss2-pals fate-mss2-pals: CMD = framecrc -i $(TARGET_SAMPLES)/mss2/rlepals.wmv -FATE_MSS2 += fate-mss2-rgb555 -fate-mss2-rgb555: CMD = framecrc -i $(TARGET_SAMPLES)/mss2/rle555.wmv -pix_fmt rgb555le -vf scale - -FATE_MSS2 += fate-mss2-rgb555s +FATE_MSS2-$(call FRAMECRC, ASF, MSS2, SCALE_FILTER) += fate-mss2-rgb555 fate-mss2-rgb555s +fate-mss2-rgb555: CMD = framecrc -i $(TARGET_SAMPLES)/mss2/rle555.wmv -pix_fmt rgb555le -vf scale fate-mss2-rgb555s: CMD = framecrc -i $(TARGET_SAMPLES)/mss2/rle555s.wmv -pix_fmt rgb555le -vf scale FATE_MSS2 += fate-mss2-wmv fate-mss2-wmv: CMD = framecrc -i $(TARGET_SAMPLES)/mss2/msscreencodec.wmv -an -frames 100 -FATE_SAMPLES_AVCONV-$(call DEMDEC, ASF, MSS2) += $(FATE_MSS2) -fate-mss2: $(FATE_MSS2) +FATE_MSS2-$(call FRAMECRC, ASF, MSS2) += $(FATE_MSS2) -FATE_MTS2 += fate-mts2-xesc +FATE_MICROSOFT += $(FATE_MSS2-yes) +fate-mss2: $(FATE_MSS2-yes) + +FATE_MTS2-$(call FRAMECRC, ASF, MTS2) += fate-mts2-xesc fate-mts2-xesc: CMD = framecrc -i $(TARGET_SAMPLES)/mts2/sample.xesc -pix_fmt yuv444p -FATE_SAMPLES_AVCONV-$(call DEMDEC, ASF, MTS2) += $(FATE_MTS2) -fate-mts2: $(FATE_MTS2) +FATE_MICROSOFT += $(FATE_MTS2-yes) +fate-mts2: $(FATE_MTS2-yes) -FATE_MSVIDEO1 += fate-msvideo1-8bit -fate-msvideo1-8bit: CMD = framecrc -i $(TARGET_SAMPLES)/cram/skating.avi -t 1 -pix_fmt rgb24 -vf scale - -FATE_MSVIDEO1 += fate-msvideo1-16bit +FATE_MSVIDEO1-$(call FRAMECRC, AVI, MSVIDEO1, SCALE_FILTER) += fate-msvideo1-8bit fate-msvideo1-16bit +fate-msvideo1-8bit: CMD = framecrc -i $(TARGET_SAMPLES)/cram/skating.avi -t 1 -pix_fmt rgb24 -vf scale fate-msvideo1-16bit: CMD = framecrc -i $(TARGET_SAMPLES)/cram/clock-cram16.avi -pix_fmt rgb24 -vf scale -FATE_MICROSOFT-$(call DEMDEC, AVI, MSVIDEO1) += $(FATE_MSVIDEO1) -fate-msvideo1: $(FATE_MSVIDEO1) +FATE_MICROSOFT += $(FATE_MSVIDEO1-yes) +fate-msvideo1: $(FATE_MSVIDEO1-yes) -FATE_SAMPLES_AVCONV-$(call DEMDEC, ASF, MTS2) += fate-mts2 +FATE_MICROSOFT-$(call FRAMECRC, ASF, MTS2) += fate-mts2 fate-mts2: CMD = framecrc -i $(TARGET_SAMPLES)/mts2/ScreenCapture.xesc -FATE_WMV3_DRM += fate-wmv3-drm-dec +FATE_WMV3_DRM-$(call FRAMECRC, ASF, WMV3) += fate-wmv3-drm-dec fate-wmv3-drm-nodec # discard last packet to avoid fails due to overread of VC-1 decoder -fate-wmv3-drm-dec: CMD = framecrc -cryptokey 137381538c84c068111902a59c5cf6c340247c39 -i $(TARGET_SAMPLES)/wmv8/wmv_drm.wmv -an -frames:v 129 - -FATE_WMV3_DRM += fate-wmv3-drm-nodec +fate-wmv3-drm-dec: CMD = framecrc -cryptokey 137381538c84c068111902a59c5cf6c340247c39 -i $(TARGET_SAMPLES)/wmv8/wmv_drm.wmv -an -frames:v 129 fate-wmv3-drm-nodec: CMD = framecrc -cryptokey 137381538c84c068111902a59c5cf6c340247c39 -i $(TARGET_SAMPLES)/wmv8/wmv_drm.wmv -c:a copy -c:v copy -FATE_SAMPLES_AVCONV-$(call DEMDEC, ASF, WMV3) += $(FATE_WMV3_DRM) -fate-wmv3-drm: $(FATE_WMV3_DRM) +FATE_MICROSOFT += $(FATE_WMV3_DRM-yes) +fate-wmv3-drm: $(FATE_WMV3_DRM-yes) FATE_MICROSOFT-$(call DEMDEC, ASF, WMV2) += fate-wmv8-x8intra fate-wmv8-x8intra: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/wmv8/wmv8_x8intra.wmv -an -FATE_VC1-$(CONFIG_VC1_DEMUXER) += fate-vc1_sa00040 +FATE_VC1 += fate-vc1_sa00040 fate-vc1_sa00040: CMD = framecrc -i $(TARGET_SAMPLES)/vc1/SA00040.vc1 -FATE_VC1-$(CONFIG_VC1_DEMUXER) += fate-vc1_sa00050 +FATE_VC1 += fate-vc1_sa00050 fate-vc1_sa00050: CMD = framecrc -i $(TARGET_SAMPLES)/vc1/SA00050.vc1 -FATE_VC1-$(CONFIG_VC1_DEMUXER) += fate-vc1_sa10091 +FATE_VC1 += fate-vc1_sa10091 fate-vc1_sa10091: CMD = framecrc -i $(TARGET_SAMPLES)/vc1/SA10091.vc1 -FATE_VC1-$(CONFIG_VC1_DEMUXER) += fate-vc1_sa10143 +FATE_VC1 += fate-vc1_sa10143 fate-vc1_sa10143: CMD = framecrc -i $(TARGET_SAMPLES)/vc1/SA10143.vc1 -FATE_VC1-$(CONFIG_VC1_DEMUXER) += fate-vc1_sa20021 +FATE_VC1 += fate-vc1_sa20021 fate-vc1_sa20021: CMD = framecrc -i $(TARGET_SAMPLES)/vc1/SA20021.vc1 -FATE_VC1-$(CONFIG_VC1_DEMUXER) += fate-vc1_ilaced_twomv +FATE_VC1 += fate-vc1_ilaced_twomv fate-vc1_ilaced_twomv: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/vc1/ilaced_twomv.vc1 -FATE_VC1-$(CONFIG_VC1T_DEMUXER) += fate-vc1test_smm0005 -fate-vc1test_smm0005: CMD = framecrc -i $(TARGET_SAMPLES)/vc1/SMM0005.rcv +FATE_VC1-$(call FRAMECRC, VC1, VC1, VC1_PARSER EXTRACT_EXTRADATA_BSF) += $(FATE_VC1) -FATE_VC1-$(CONFIG_VC1T_DEMUXER) += fate-vc1test_smm0015 +FATE_VC1-$(call FRAMECRC, VC1T, WMV3) += fate-vc1test_smm0005 fate-vc1test_smm0015 +fate-vc1test_smm0005: CMD = framecrc -i $(TARGET_SAMPLES)/vc1/SMM0005.rcv fate-vc1test_smm0015: CMD = framecrc -i $(TARGET_SAMPLES)/vc1/SMM0015.rcv -FATE_VC1-$(CONFIG_MOV_DEMUXER) += fate-vc1-ism +FATE_VC1-$(call FRAMECRC, MOV, VC1) += fate-vc1-ism fate-vc1-ism: CMD = framecrc -i $(TARGET_SAMPLES)/isom/vc1-wmapro.ism -an -FATE_MICROSOFT-$(CONFIG_VC1_DECODER) += $(FATE_VC1-yes) +FATE_MICROSOFT += $(FATE_VC1-yes) fate-vc1: $(FATE_VC1-yes) -FATE_MICROSOFT-$(CONFIG_ASF_DEMUXER) += fate-asf-repldata +FATE_MICROSOFT-$(call ALLYES, FILE_PROTOCOL PIPE_PROTOCOL ASF_DEMUXER FRAMECRC_MUXER) += fate-asf-repldata fate-asf-repldata: CMD = framecrc -i $(TARGET_SAMPLES)/asf/bug821-2.asf -c copy FATE_MICROSOFT += $(FATE_MICROSOFT-yes) diff --git a/tests/fate/mov.mak b/tests/fate/mov.mak index e95638090..8a7218a21 100644 --- a/tests/fate/mov.mak +++ b/tests/fate/mov.mak @@ -17,6 +17,10 @@ FATE_MOV = fate-mov-3elist \ fate-mov-bbi-elst-starts-b \ fate-mov-neg-firstpts-discard-frames \ fate-mov-stream-shorter-than-movie \ +# FIXME: Uncomment these two lines once the test files are uploaded to the fate +# server. +# fate-mov-avif-demux-still-image-1-item \ +# fate-mov-avif-demux-still-image-multiple-items \ FATE_MOV_FFPROBE = fate-mov-neg-firstpts-discard \ fate-mov-neg-firstpts-discard-vorbis \ @@ -126,25 +130,41 @@ fate-mov-mp4-with-mov-in24-ver: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_entr fate-mov-mp4-extended-atom: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_packets -print_format compact -select_streams v $(TARGET_SAMPLES)/mov/extended_atom_size_probe -FATE_MOV_FFMPEG_FFPROBE-$(call ALLYES, FILE_PROTOCOL MOV_DEMUXER MJPEG_DECODER \ - SCALE_FILTER PNG_ENCODER PNG_DECODER \ - MP4_MUXER FRAMECRC_MUXER PIPE_PROTOCOL) \ - += fate-mov-cover-image -fate-mov-cover-image: CMD = transcode mov $(TARGET_SAMPLES)/cover_art/Owner-iTunes_9.0.3.15.m4a mp4 "-map 0 -map 0:v -c:a copy -c:v:0 copy -filter:v:1 scale -c:v:1 png" "-map 0 -t 0.1 -c copy" "" "-show_entries stream_disposition=attached_pic:stream=index,codec_name" +FATE_MOV_FFMPEG_FFPROBE-$(call REMUX, MP4 MOV, OGG_DEMUXER VORBIS_DECODER) \ + += fate-mov-mp4-chapters +fate-mov-mp4-chapters: CMD = transcode ogg $(TARGET_SAMPLES)/vorbis/vorbis_chapter_extension_demo.ogg mp4 "-c copy" "-c copy -t 0.1" "-show_chapters" -FATE_MOV_FFMPEG_FFPROBE-$(call ALLYES, FILE_PROTOCOL SRT_DEMUXER MOV_DEMUXER SUBRIP_DECODER TTML_ENCODER TTML_MUXER MOV_MUXER) += fate-mov-mp4-ttml-stpp fate-mov-mp4-ttml-dfxp -fate-mov-mp4-ttml-stpp: CMD = transcode srt $(TARGET_SAMPLES)/sub/SubRip_capability_tester.srt mp4 "-map 0:s -c:s ttml -time_base:s 1:1000" "-map 0 -c copy" "" "-of json -show_entries packet:stream=index,codec_type,codec_tag_string,codec_tag,codec_name,time_base,start_time,duration_ts,duration,nb_frames,nb_read_packets:stream_tags" -fate-mov-mp4-ttml-dfxp: CMD = transcode srt $(TARGET_SAMPLES)/sub/SubRip_capability_tester.srt mp4 "-map 0:s -c:s ttml -time_base:s 1:1000 -tag:s dfxp -strict unofficial" "-map 0 -c copy" "" "-of json -show_entries packet:stream=index,codec_type,codec_tag_string,codec_tag,codec_name,time_base,start_time,duration_ts,duration,nb_frames,nb_read_packets:stream_tags" +FATE_MOV_FFMPEG_FFPROBE-$(call TRANSCODE, PNG, MP4 MOV, MJPEG_DECODER SCALE_FILTER) \ + += fate-mov-cover-image +fate-mov-cover-image: CMD = transcode mov $(TARGET_SAMPLES)/cover_art/Owner-iTunes_9.0.3.15.m4a mp4 "-map 0 -map 0:v -c:a copy -c:v:0 copy -filter:v:1 scale -c:v:1 png" "-map 0 -t 0.1 -c copy" "-show_entries stream_disposition=attached_pic:stream=index,codec_name" + +FATE_MOV_FFMPEG_FFPROBE-$(call TRANSCODE, TTML SUBRIP, MP4 MOV, SRT_DEMUXER TTML_MUXER) += fate-mov-mp4-ttml-stpp fate-mov-mp4-ttml-dfxp +fate-mov-mp4-ttml-stpp: CMD = transcode srt $(TARGET_SAMPLES)/sub/SubRip_capability_tester.srt mp4 "-map 0:s -c:s ttml -time_base:s 1:1000" "-map 0 -c copy" "-of json -show_entries packet:stream=index,codec_type,codec_tag_string,codec_tag,codec_name,time_base,start_time,duration_ts,duration,nb_frames,nb_read_packets:stream_tags" +fate-mov-mp4-ttml-dfxp: CMD = transcode srt $(TARGET_SAMPLES)/sub/SubRip_capability_tester.srt mp4 "-map 0:s -c:s ttml -time_base:s 1:1000 -tag:s dfxp -strict unofficial" "-map 0 -c copy" "-of json -show_entries packet:stream=index,codec_type,codec_tag_string,codec_tag,codec_name,time_base,start_time,duration_ts,duration,nb_frames,nb_read_packets:stream_tags" + +# FIXME: Uncomment these two tests once the test files are uploaded to the fate +# server. +# avif demuxing - still image with 1 item. +#fate-mov-avif-demux-still-image-1-item: CMD = framemd5 -i $(TARGET_SAMPLES)/avif/still_image.avif -c:v copy + +# avif demuxing - still image with multiple items. only the primary item will be +# parsed. +#fate-mov-avif-demux-still-image-multiple-items: CMD = framemd5 -i $(TARGET_SAMPLES)/avif/still_image_exif.avif -c:v copy # Resulting remux should have: # 1. first audio stream with AV_DISPOSITION_HEARING_IMPAIRED # 2. second audio stream with AV_DISPOSITION_VISUAL_IMPAIRED | DESCRIPTIONS -FATE_MOV_FFMPEG_FFPROBE-$(call ALLYES, FILE_PROTOCOL PIPE_PROTOCOL \ - MPEGTS_DEMUXER MOV_DEMUXER AC3_DECODER \ - MP4_MUXER FRAMECRC_MUXER ) \ +FATE_MOV_FFMPEG_FFPROBE-$(call REMUX, MP4 MOV, MPEGTS_DEMUXER AC3_DECODER) \ += fate-mov-mp4-disposition-mpegts-remux -fate-mov-mp4-disposition-mpegts-remux: CMD = transcode mpegts $(TARGET_SAMPLES)/mpegts/pmtchange.ts mp4 "-map 0:1 -map 0:2 -c copy -disposition:a:0 +hearing_impaired" "-map 0 -c copy" "" "-of json -show_entries stream_disposition:stream=index" +fate-mov-mp4-disposition-mpegts-remux: CMD = transcode mpegts $(TARGET_SAMPLES)/mpegts/pmtchange.ts mp4 "-map 0:1 -map 0:2 -c copy -disposition:a:0 +hearing_impaired" "-map 0 -c copy" "-of json -show_entries stream_disposition:stream=index" FATE_SAMPLES_FFMPEG_FFPROBE += $(FATE_MOV_FFMPEG_FFPROBE-yes) -fate-mov: $(FATE_MOV) $(FATE_MOV_FFPROBE) $(FATE_MOV_FASTSTART) $(FATE_MOV_FFMPEG_FFPROBE-yes) +FATE_MOV_FFMPEG-$(call TRANSCODE, PCM_S16LE, MOV, WAV_DEMUXER PAN_FILTER) \ + += fate-mov-channel-description +fate-mov-channel-description: tests/data/asynth-44100-1.wav tests/data/filtergraphs/mov-channel-description +fate-mov-channel-description: CMD = transcode wav $(TARGET_PATH)/tests/data/asynth-44100-1.wav mov "-filter_complex_script $(TARGET_PATH)/tests/data/filtergraphs/mov-channel-description -map [outFL] -map [outFR] -map [outFC] -map [outLFE] -map [outBL] -map [outBR] -map [outDL] -map [outDR] -c:a pcm_s16le" "-map 0 -c copy -frames:a 0" + +FATE_FFMPEG += $(FATE_MOV_FFMPEG-yes) + +fate-mov: $(FATE_MOV) $(FATE_MOV_FFMPEG-yes) $(FATE_MOV_FFPROBE) $(FATE_MOV_FASTSTART) $(FATE_MOV_FFMPEG_FFPROBE-yes) diff --git a/tests/fate/mpeg4.mak b/tests/fate/mpeg4.mak index 26007f82f..4cec21c54 100644 --- a/tests/fate/mpeg4.mak +++ b/tests/fate/mpeg4.mak @@ -3,16 +3,23 @@ MPEG4_RESOLUTION_CHANGE = down-down down-up up-down up-up fate-mpeg4-resolution-change-%: CMD = framemd5 -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg4/resize_$(@:fate-mpeg4-resolution-change-%=%).h263 -sws_flags +bitexact -FATE_MPEG4-$(call DEMDEC, H263, H263) := $(addprefix fate-mpeg4-resolution-change-, $(MPEG4_RESOLUTION_CHANGE)) +FATE_MPEG4-$(call FRAMEMD5, M4V, MPEG4, SCALE_FILTER) := $(addprefix fate-mpeg4-resolution-change-, $(MPEG4_RESOLUTION_CHANGE)) fate-mpeg4-bsf-unpack-bframes: CMD = md5 -i $(TARGET_SAMPLES)/mpeg4/packed_bframes.avi -flags +bitexact -fflags +bitexact -c:v copy -bsf mpeg4_unpack_bframes -f avi -FATE_MPEG4-$(call ALLYES, AVI_DEMUXER MPEG4_UNPACK_BFRAMES_BSF AVI_MUXER) += fate-mpeg4-bsf-unpack-bframes +FATE_MPEG4-$(call DEMMUX, AVI, AVI, MPEG4_UNPACK_BFRAMES_BSF) += fate-mpeg4-bsf-unpack-bframes fate-mpeg4-packed: CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg4/packed_bframes.avi -flags +bitexact -fflags +bitexact -vsync cfr -FATE_MPEG4-$(call ALLYES, AVI_DEMUXER MPEG4_DECODER) += fate-mpeg4-packed +FATE_MPEG4-$(call FRAMECRC, AVI, MPEG4) += fate-mpeg4-packed -FATE_MPEG4-$(call DEMDEC, M4V, MPEG4) += fate-m4v fate-m4v-cfr +FATE_MPEG4-$(call ALLYES, FILE_PROTOCOL M4V_DEMUXER MPEG4_DECODER SCALE_FILTER \ + RAWVIDEO_ENCODER FRAMECRC_MUXER PIPE_PROTOCOL) \ + += fate-mpeg4-simple-studio-profile +fate-mpeg4-simple-studio-profile: CMD = framecrc -bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg4/mpeg4_sstp_dpcm.m4v -sws_flags +accurate_rnd+bitexact -pix_fmt yuv422p10le -vf scale + +FATE_MPEG4-$(call FRAMECRC, M4V, MPEG4) += fate-m4v fate-m4v: CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg4/demo.m4v + +FATE_MPEG4-$(call FRAMECRC, M4V, MPEG4, FPS_FILTER) += fate-m4v-cfr fate-m4v-cfr: CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg4/demo.m4v -vf fps=5 FATE_SAMPLES_AVCONV += $(FATE_MPEG4-yes) diff --git a/tests/fate/mpegts.mak b/tests/fate/mpegts.mak index bbcbfc47b..eaca8ec28 100644 --- a/tests/fate/mpegts.mak +++ b/tests/fate/mpegts.mak @@ -5,12 +5,12 @@ PROBE_CODEC_NAME_COMMAND = \ ffprobe$(PROGSSUF)$(EXESUF) -show_entries stream=codec_name \ -print_format default -bitexact -v 0 -FATE_MPEGTS_PROBE-$(call DEMDEC, MPEGTS, HEVC, AAC_LATM) += fate-mpegts-probe-latm +FATE_MPEGTS_PROBE-$(call DEMDEC, MPEGTS, HEVC, LOAS_DEMUXER) += fate-mpegts-probe-latm 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-$(call DEMDEC, MPEGTS, HEVC, LOAS_DEMUXER) += 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)" diff --git a/tests/fate/mxf.mak b/tests/fate/mxf.mak index 3a1096176..3ab936b5d 100644 --- a/tests/fate/mxf.mak +++ b/tests/fate/mxf.mak @@ -46,7 +46,7 @@ fate-mxf-user-comments: $(SAMPLES)/mxf/Sony-00001.mxf fate-mxf-user-comments: CMD = md5 -y -i $(TARGET_SAMPLES)/mxf/Sony-00001.mxf -c copy -metadata "comment_test=value" -fflags +bitexact -f mxf FATE_MXF_D10_USER_COMMENTS-$(call ALLYES, FILE_PROTOCOL MXF_DEMUXER DVVIDEO_DECODER SCALE_FILTER MPEG2VIDEO_ENCODER MXF_D10_MUXER EXTRACT_EXTRADATA_BSF MPEGVIDEO_PARSER PIPE_PROTOCOL FRAMECRC_MUXER) += fate-mxf-d10-user-comments -fate-mxf-d10-user-comments: CMD = transcode mxf $(TARGET_SAMPLES)/mxf/Avid-00005.mxf mxf_d10 "-c:v mpeg2video -b:v 30000k -minrate:v 30000k -maxrate:v 30000k -bufsize:v 30000k -rc_init_occupancy 30000k -vf scale=w=1280:h=720 -an -metadata comment_test=value -metadata company_name=FATE-company -metadata product_name=FATE-test -metadata product_version=3.14159 -store_user_comments 1" "-c copy -frames:v 5" "" "-show_entries format_tags" +fate-mxf-d10-user-comments: CMD = transcode mxf $(TARGET_SAMPLES)/mxf/Avid-00005.mxf mxf_d10 "-c:v mpeg2video -b:v 30000k -minrate:v 30000k -maxrate:v 30000k -bufsize:v 30000k -rc_init_occupancy 30000k -vf scale=w=1280:h=720 -an -metadata comment_test=value -metadata company_name=FATE-company -metadata product_name=FATE-test -metadata product_version=3.14159 -store_user_comments 1" "-c copy -frames:v 5" "-show_entries format_tags" FATE_MXF_OPATOM_USER_COMMENTS-$(call ENCDEC2, MPEG2VIDEO, PCM_S16LE, MXF) += fate-mxf-opatom-user-comments fate-mxf-opatom-user-comments: $(SAMPLES)/mxf/Sony-00001.mxf diff --git a/tests/fate/oma.mak b/tests/fate/oma.mak index a088feff2..8f872242f 100644 --- a/tests/fate/oma.mak +++ b/tests/fate/oma.mak @@ -3,19 +3,13 @@ fate-oma-demux: CMD = crc -i $(TARGET_SAMPLES)/oma/01-Untitled-partial.oma -c:a # Also tests splitting and joining the date into TYER and TDAT id3v2.3 tags. FATE_OMA_REMUX_FFPROBE-yes += fate-oma-atrac3p-remux -fate-oma-atrac3p-remux: CMD = transcode oma $(TARGET_SAMPLES)/atrac3p/at3p_sample1.oma oma "-c copy -metadata date=2021-09-23 -metadata time=16:00 -metadata title=noise -metadata id3v2_priv.foo=hex\xB3 -metadata_header_padding 500" "-c copy -t 0.2" "" "-show_entries format_tags" +fate-oma-atrac3p-remux: CMD = transcode oma $(TARGET_SAMPLES)/atrac3p/at3p_sample1.oma oma "-c copy -metadata date=2021-09-23 -metadata time=16:00 -metadata title=noise -metadata id3v2_priv.foo=hex\xB3 -metadata_header_padding 500" "-c copy -t 0.2" "-show_entries format_tags" FATE_OMA_REMUX-$(CONFIG_WAV_DEMUXER) += fate-oma-atrac3-remux fate-oma-atrac3-remux: CMD = transcode wav $(TARGET_SAMPLES)/atrac3/mc_sich_at3_132_small.wav oma "-c copy" "-c copy -t 0.1" -FATE_OMA_FFMPEG-$(call ALLYES, FILE_PROTOCOL OMA_MUXER \ - OMA_DEMUXER FRAMECRC_MUXER \ - PIPE_PROTOCOL) \ - += $(FATE_OMA_REMUX-yes) -FATE_OMA_FFMPEG_FFPROBE-$(call ALLYES, FILE_PROTOCOL OMA_MUXER \ - OMA_DEMUXER FRAMECRC_MUXER \ - PIPE_PROTOCOL) \ - += $(FATE_OMA_REMUX_FFPROBE-yes) +FATE_OMA_FFMPEG-$(call REMUX, OMA) += $(FATE_OMA_REMUX-yes) +FATE_OMA_FFMPEG_FFPROBE-$(call REMUX, OMA) += $(FATE_OMA_REMUX_FFPROBE-yes) FATE_SAMPLES_FFMPEG += $(FATE_OMA_FFMPEG-yes) FATE_SAMPLES_FFMPEG_FFPROBE += $(FATE_OMA_FFMPEG_FFPROBE-yes) fate-oma: $(FATE_OMA_FFMPEG-yes) $(FATE_OMA_FFMPEG_FFPROBE-yes) diff --git a/tests/fate/opus.mak b/tests/fate/opus.mak index cf8eeb555..573044ed1 100644 --- a/tests/fate/opus.mak +++ b/tests/fate/opus.mak @@ -5,21 +5,18 @@ 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, 07 08 09 10 12) +OPUS_OTHER_SAMPLES = $(addprefix testvector, 07 08 09 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 -af aresample - -fate-opus-$(1): REF = $(SAMPLES)/opus/$(1)$(2).dec +FATE_OPUS_$(1)-$(call FILTERDEMDECENCMUX, ARESAMPLE, MATROSKA, OPUS, PCM_S16LE, PCM_S16LE, PIPE_PROTOCOL) := $(addprefix fate-opus-,$(OPUS_$(1)_SAMPLES)) +FATE_OPUS += $$(FATE_OPUS_$(1)-yes) endef -$(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),))) +$(foreach N, CELT HYBRID SILK OTHER, $(eval $(call FATE_OPUS_TEST,$(N)))) -FATE_OPUS := $(sort $(FATE_OPUS)) +$(FATE_OPUS): CMD = ffmpeg -i $(TARGET_SAMPLES)/opus/$(@:fate-opus-%=%).mka -f s16le -af aresample - +$(FATE_OPUS): REF = $(SAMPLES)/opus/$(@:fate-opus-%=%).dec +$(FATE_OPUS_HYBRID-yes): REF = $(SAMPLES)/opus/$(@:fate-opus-%=%)_v2.dec $(FATE_OPUS): CMP = stddev $(FATE_OPUS): CMP_UNIT = s16 @@ -39,11 +36,8 @@ fate-opus-testvector12: CMP_TARGET = 160 fate-opus-tron.6ch.tinypkts: CMP_SHIFT = 1440 fate-opus-tron.6ch.tinypkts: CMP_TARGET = 0 -$(FATE_OPUS_CELT): CMP = oneoff -$(FATE_OPUS_CELT): FUZZ = 6 - -FATE_SAMPLES_AVCONV-$(call DEMDEC, MATROSKA, OPUS) += $(FATE_OPUS) -fate-opus-celt: $(FATE_OPUS_CELT) -fate-opus-hybrid: $(FATE_OPUS_HYBRID) -fate-opus-silk: $(FATE_OPUS_SILK) +FATE_SAMPLES_FFMPEG += $(FATE_OPUS) +fate-opus-celt: $(FATE_OPUS_CELT-yes) +fate-opus-hybrid: $(FATE_OPUS_HYBRID-yes) +fate-opus-silk: $(FATE_OPUS_SILK-yes) fate-opus: $(FATE_OPUS) diff --git a/tests/fate/pcm.mak b/tests/fate/pcm.mak index e3e267403..4e79fc7c4 100644 --- a/tests/fate/pcm.mak +++ b/tests/fate/pcm.mak @@ -27,6 +27,37 @@ fate-dcinema-encode: tests/data/asynth-96000-6.wav fate-dcinema-encode: SRC = tests/data/asynth-96000-6.wav fate-dcinema-encode: CMD = enc_dec_pcm daud framemd5 s16le $(SRC) -c:a pcm_s24daud -frames:a 20 +FATE_SAMPLES_PCM-$(call TRANSCODE, PCM_DVD, MPEG2VOB MPEGPS, TRUEHD_DEMUXER TRUEHD_DECODER PCM_S24LE_ENCODER) += fate-pcm_dvd-24-7.1-48000 +fate-pcm_dvd-24-7.1-48000: CMD = transcode truehd $(TARGET_SAMPLES)/truehd/atmos.thd vob "-c:a pcm_dvd" "-c:a pcm_s24le" + +FATE_SAMPLES_PCM-$(call TRANSCODE, PCM_DVD, MPEG2VOB MPEGPS, MXF_DEMUXER PCM_S16LE_DECODER) += fate-pcm_dvd-16-7.1-48000 +fate-pcm_dvd-16-7.1-48000: CMD = transcode mxf $(TARGET_SAMPLES)/mxf/Sony-00001.mxf vob "-map 0:a -c:a pcm_dvd" + +FATE_SAMPLES_PCM-$(call TRANSCODE, PCM_DVD, MPEG2VOB MPEGPS, DAUD_DEMUXER PCM_S24DAUD_DECODER) += fate-pcm_dvd-16-5.1-96000 +fate-pcm_dvd-16-5.1-96000: CMD = transcode daud $(TARGET_SAMPLES)/d-cinema/THX_Science_FLT_1920-partial.302 vob "-c:a pcm_dvd" + +FATE_SAMPLES_PCM-$(call TRANSCODE, PCM_DVD, MPEG2VOB MPEGPS, TRUEHD_DEMUXER TRUEHD_DECODER PCM_S24LE_ENCODER) += fate-pcm_dvd-24-5.1-48000 +fate-pcm_dvd-24-5.1-48000: CMD = transcode truehd $(TARGET_SAMPLES)/lossless-audio/truehd_5.1.raw vob "-c:a pcm_dvd" "-c:a pcm_s24le -t 0.2" + +FATE_SAMPLES_PCM-$(call TRANSCODE, PCM_DVD, MPEG2VOB MPEGPS, MATROSKA_DEMUXER FLAC_DECODER) += fate-pcm_dvd-16-5.1-48000 +fate-pcm_dvd-16-5.1-48000: CMD = transcode matroska $(TARGET_SAMPLES)/mkv/flac_channel_layouts.mka vob "-map 0:a:1 -c:a pcm_dvd" "-t 0.2" + +FATE_SAMPLES_PCM-$(call TRANSCODE, PCM_DVD, MPEG2VOB MPEGPS, FLAC_DEMUXER FLAC_PARSER FLAC_DECODER PCM_S24LE_ENCODER) += fate-pcm_dvd-24-2-48000 +fate-pcm_dvd-24-2-48000: CMD = transcode flac $(TARGET_SAMPLES)/filter/seq-3341-7_seq-3342-5-24bit.flac vob "-c:a pcm_dvd" "-c:a pcm_s24le -t 0.2" + +FATE_SAMPLES_PCM-$(call TRANSCODE, PCM_DVD, MPEG2VOB MPEGPS, WAV_DEMUXER PCM_S16LE_DECODER) += fate-pcm_dvd-16-2-48000 +fate-pcm_dvd-16-2-48000: CMD = transcode wav $(TARGET_SAMPLES)/wav/200828-005.wav vob "-c:a pcm_dvd" "-t 0.2" + +FATE_SAMPLES_PCM-$(call TRANSCODE, PCM_DVD, MPEG2VOB MPEGPS, MXF_DEMUXER PCM_S24LE_DECODER PCM_S24LE_ENCODER) += fate-pcm_dvd-24-1-48000 +fate-pcm_dvd-24-1-48000: CMD = transcode mxf $(TARGET_SAMPLES)/mxf/omneon_8.3.0.0_xdcam_startc_footer.mxf vob "-map 0:a:0 -c:a pcm_dvd" "-c:a pcm_s24le" + +FATE_SAMPLES_PCM-$(call TRANSCODE, PCM_DVD, MPEG2VOB MPEGPS, MXF_DEMUXER PCM_S16LE_DECODER) += fate-pcm_dvd-16-1-48000 +fate-pcm_dvd-16-1-48000: CMD = transcode mxf $(TARGET_SAMPLES)/mxf/opatom_missing_index.mxf vob "-c:a pcm_dvd" + +FATE_PCM-$(call TRANSCODE, PCM_DVD, MPEG2VOB MPEGPS, WAV_DEMUXER PCM_S16LE_DECODER) += fate-pcm_dvd-16-1-96000 +fate-pcm_dvd-16-1-96000: tests/data/asynth-96000-1.wav +fate-pcm_dvd-16-1-96000: CMD = transcode wav $(TARGET_PATH)/tests/data/asynth-96000-1.wav vob "-c:a pcm_dvd" "-t 0.2" + FATE_FFMPEG += $(FATE_PCM-yes) FATE_SAMPLES_AVCONV += $(FATE_SAMPLES_PCM-yes) fate-pcm: $(FATE_PCM-yes) $(FATE_SAMPLES_PCM-yes) diff --git a/tests/fate/pixlet.mak b/tests/fate/pixlet.mak index 7c4604cc0..524a8797c 100644 --- a/tests/fate/pixlet.mak +++ b/tests/fate/pixlet.mak @@ -1,5 +1,5 @@ -FATE_PIXLET += fate-pixlet-rgb +FATE_PIXLET-$(call FRAMECRC, MOV, PIXLET, SCALE_FILTER) += fate-pixlet-rgb fate-pixlet-rgb: CMD = framecrc -i $(TARGET_SAMPLES)/pixlet/pixlet_rgb.mov -an -pix_fmt yuv420p16le -vf scale -FATE_SAMPLES_AVCONV-$(call DEMDEC, MOV, PIXLET) += $(FATE_PIXLET) -fate-pixlet: $(FATE_PIXLET) +FATE_SAMPLES_FFMPEG += $(FATE_PIXLET-yes) +fate-pixlet: $(FATE_PIXLET-yes) diff --git a/tests/fate/prores.mak b/tests/fate/prores.mak index f2c11259d..9e05b33b9 100644 --- a/tests/fate/prores.mak +++ b/tests/fate/prores.mak @@ -6,9 +6,9 @@ FATE_PRORES = fate-prores-422 \ fate-prores-alpha_skip \ fate-prores-transparency \ fate-prores-transparency_skip \ - fate-prores-gray \ + $(if $(CONFIG_ARESAMPLE_FILTER),fate-prores-gray) \ -FATE_SAMPLES_AVCONV-$(call DEMDEC, MOV, PRORES) += $(FATE_PRORES) +FATE_SAMPLES_FFMPEG-$(call FRAMECRC, MOV, PRORES, SCALE_FILTER) += $(FATE_PRORES) fate-prores: $(FATE_PRORES) fate-prores-422: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/prores/Sequence_1-Apple_ProRes_422.mov -pix_fmt yuv422p10le -vf scale @@ -25,4 +25,4 @@ fate-prores-gray: CMD = framecrc -flags +bitexact -c:a aac_fixed -i $(TARGE FATE_PRORES_METADATA_BSF += fate-prores-metadata fate-prores-metadata: CMD = md5 -i $(TARGET_SAMPLES)/prores/Sequence_1-Apple_ProRes_422_Proxy.mov -c:v copy -bsf:v prores_metadata=color_primaries=bt470bg:color_trc=bt709:colorspace=smpte170m -bitexact -f mov -FATE_SAMPLES_FFMPEG-$(call ALLYES, MOV_DEMUXER PRORES_METADATA_BSF) += $(FATE_PRORES_METADATA_BSF) +FATE_SAMPLES_FFMPEG-$(call DEMMUX, MOV, MOV, PRORES_METADATA_BSF) += $(FATE_PRORES_METADATA_BSF) diff --git a/tests/fate/qt.mak b/tests/fate/qt.mak index 6e71f6e4d..42e5fd910 100644 --- a/tests/fate/qt.mak +++ b/tests/fate/qt.mak @@ -1,52 +1,52 @@ -FATE_QT-$(call DEMDEC, MOV, EIGHTBPS) += fate-8bps +FATE_QT-$(call FRAMECRC, MOV, EIGHTBPS, SCALE_FILTER ARESAMPLE_FILTER) += fate-8bps fate-8bps: CMD = framecrc -i $(TARGET_SAMPLES)/8bps/full9iron-partial.mov -pix_fmt rgb24 -vf scale -af aresample -FATE_QT-$(call DEMDEC, MOV, QDM2) += fate-qdm2 +FATE_QT-$(call ENCDEC, PCM_S16LE QDM2, PCM_S16LE MOV, PIPE_PROTOCOL) += fate-qdm2 fate-qdm2: CMD = pcm -i $(TARGET_SAMPLES)/qt-surge-suite/surge-2-16-B-QDM2.mov fate-qdm2: CMP = oneoff fate-qdm2: REF = $(SAMPLES)/qt-surge-suite/surge-2-16-B-QDM2.pcm fate-qdm2: FUZZ = 2 -FATE_QT-$(call DEMDEC, MOV, PCM_ALAW) += fate-qt-alaw-mono +FATE_QT-$(call ENCDEC, PCM_S16LE PCM_ALAW, MOV PCM_S16LE) += fate-qt-alaw-mono fate-qt-alaw-mono: CMD = md5 -i $(TARGET_SAMPLES)/qt-surge-suite/surge-1-16-B-alaw.mov -f s16le -FATE_QT-$(call DEMDEC, MOV, PCM_ALAW) += fate-qt-alaw-stereo +FATE_QT-$(call ENCDEC, PCM_S16LE PCM_ALAW, MOV PCM_S16LE) += fate-qt-alaw-stereo fate-qt-alaw-stereo: CMD = md5 -i $(TARGET_SAMPLES)/qt-surge-suite/surge-2-16-B-alaw.mov -f s16le -FATE_QT-$(call DEMDEC, MOV, ADPCM_IMA_QT) += fate-qt-ima4-mono +FATE_QT-$(call ENCDEC, PCM_S16LE ADPCM_IMA_QT, PCM_S16LE MOV, ARESAMPLE_FILTER) += fate-qt-ima4-mono fate-qt-ima4-mono: CMD = md5 -i $(TARGET_SAMPLES)/qt-surge-suite/surge-1-16-B-ima4.mov -f s16le -af aresample -FATE_QT-$(call DEMDEC, MOV, ADPCM_IMA_QT) += fate-qt-ima4-stereo +FATE_QT-$(call ENCDEC, PCM_S16LE ADPCM_IMA_QT, PCM_S16LE MOV, ARESAMPLE_FILTER) += fate-qt-ima4-stereo fate-qt-ima4-stereo: CMD = md5 -i $(TARGET_SAMPLES)/qt-surge-suite/surge-2-16-B-ima4.mov -f s16le -af aresample -FATE_QT-$(call DEMDEC, MOV, MACE3) += fate-qt-mac3-mono +FATE_QT-$(call ENCDEC, PCM_S16LE MACE3, PCM_S16LE MOV, ARESAMPLE_FILTER) += fate-qt-mac3-mono fate-qt-mac3-mono: CMD = md5 -i $(TARGET_SAMPLES)/qt-surge-suite/surge-1-8-MAC3.mov -f s16le -af aresample -FATE_QT-$(call DEMDEC, MOV, MACE3) += fate-qt-mac3-stereo +FATE_QT-$(call ENCDEC, PCM_S16LE MACE3, PCM_S16LE MOV, ARESAMPLE_FILTER) += fate-qt-mac3-stereo fate-qt-mac3-stereo: CMD = md5 -i $(TARGET_SAMPLES)/qt-surge-suite/surge-2-8-MAC3.mov -f s16le -af aresample -FATE_QT-$(call DEMDEC, MOV, MACE6) += fate-qt-mac6-mono +FATE_QT-$(call ENCDEC, PCM_S16LE MACE6, PCM_S16LE MOV, ARESAMPLE_FILTER) += fate-qt-mac6-mono fate-qt-mac6-mono: CMD = md5 -i $(TARGET_SAMPLES)/qt-surge-suite/surge-1-8-MAC6.mov -f s16le -af aresample -FATE_QT-$(call DEMDEC, MOV, MACE6) += fate-qt-mac6-stereo +FATE_QT-$(call ENCDEC, PCM_S16LE MACE6, PCM_S16LE MOV, ARESAMPLE_FILTER) += fate-qt-mac6-stereo fate-qt-mac6-stereo: CMD = md5 -i $(TARGET_SAMPLES)/qt-surge-suite/surge-2-8-MAC6.mov -f s16le -af aresample -FATE_QT-$(call DEMDEC, MOV, PCM_MULAW) += fate-qt-ulaw-mono +FATE_QT-$(call ENCDEC, PCM_S16LE PCM_MULAW, PCM_S16LE MOV) += fate-qt-ulaw-mono fate-qt-ulaw-mono: CMD = md5 -i $(TARGET_SAMPLES)/qt-surge-suite/surge-1-16-B-ulaw.mov -f s16le -FATE_QT-$(call DEMDEC, MOV, PCM_MULAW) += fate-qt-ulaw-stereo +FATE_QT-$(call ENCDEC, PCM_S16LE PCM_MULAW, PCM_S16LE MOV) += fate-qt-ulaw-stereo fate-qt-ulaw-stereo: CMD = md5 -i $(TARGET_SAMPLES)/qt-surge-suite/surge-2-16-B-ulaw.mov -f s16le -FATE_QT-$(call DEMDEC, MOV, QDRAW) += fate-quickdraw +FATE_QT-$(call FRAMECRC, MOV, QDRAW, SCALE_FILTER) += fate-quickdraw fate-quickdraw: CMD = framecrc -i $(TARGET_SAMPLES)/quickdraw/Airplane.mov -pix_fmt rgb24 -vf scale -FATE_QT-$(call DEMDEC, MOV, RPZA) += fate-rpza +FATE_QT-$(call FRAMECRC, MOV, RPZA, SCALE_FILTER) += fate-rpza fate-rpza: CMD = framecrc -i $(TARGET_SAMPLES)/rpza/rpza2.mov -t 2 -pix_fmt rgb24 -vf scale -FATE_QT-$(call DEMDEC, MOV, SVQ1) += fate-svq1 +FATE_QT-$(call FRAMECRC, MOV, SVQ1) += fate-svq1 fate-svq1: CMD = framecrc -i $(TARGET_SAMPLES)/svq1/marymary-shackles.mov -an -t 10 -FATE_QT-$(call DEMDEC, MOV, SVQ1) += fate-svq1-headerswap +FATE_QT-$(call FRAMECRC, MOV, SVQ1) += fate-svq1-headerswap fate-svq1-headerswap: CMD = framecrc -i $(TARGET_SAMPLES)/svq1/ct_ending_cut.mov -frames 4 FATE_SVQ3 += fate-svq3-1 @@ -59,7 +59,7 @@ fate-svq3-2: CMD = framecrc -flags +bitexact -ignore_editlist 1 -i $(TARGET_SAMP FATE_SVQ3 += fate-svq3-watermark fate-svq3-watermark: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/svq3/svq3_watermark.mov -FATE_QT-$(call ALLYES, MOV_DEMUXER SVQ3_DECODER ZLIB) += $(FATE_SVQ3) +FATE_QT-$(call FRAMECRC, MOV, SVQ3, ZLIB) += $(FATE_SVQ3) fate-svq3: $(FATE_SVQ3) FATE_QT += $(FATE_QT-yes) diff --git a/tests/fate/qtrle.mak b/tests/fate/qtrle.mak index 3dd0afbd3..3adefd200 100644 --- a/tests/fate/qtrle.mak +++ b/tests/fate/qtrle.mak @@ -1,23 +1,26 @@ FATE_QTRLE += fate-qtrle-1bit fate-qtrle-1bit: CMD = framecrc -i $(TARGET_SAMPLES)/qtrle/Animation-Monochrome.mov -an -FATE_QTRLE += fate-qtrle-2bit +FATE_QTRLE_SCALE += fate-qtrle-2bit fate-qtrle-2bit: CMD = framecrc -i $(TARGET_SAMPLES)/qtrle/Animation-4Greys.mov -pix_fmt rgb24 -an -vf scale -FATE_QTRLE += fate-qtrle-4bit +FATE_QTRLE_SCALE += fate-qtrle-4bit fate-qtrle-4bit: CMD = framecrc -i $(TARGET_SAMPLES)/qtrle/Animation-16Greys.mov -pix_fmt rgb24 -an -vf scale -FATE_QTRLE += fate-qtrle-8bit +FATE_QTRLE_SCALE += fate-qtrle-8bit fate-qtrle-8bit: CMD = framecrc -i $(TARGET_SAMPLES)/qtrle/criticalpath-credits.mov -pix_fmt rgb24 -an -vf scale -FATE_QTRLE += fate-qtrle-16bit +FATE_QTRLE_SCALE += fate-qtrle-16bit fate-qtrle-16bit: CMD = framecrc -i $(TARGET_SAMPLES)/qtrle/mr-cork-rle.mov -pix_fmt rgb24 -vf scale FATE_QTRLE += fate-qtrle-24bit fate-qtrle-24bit: CMD = framecrc -i $(TARGET_SAMPLES)/qtrle/aletrek-rle.mov -FATE_QTRLE += fate-qtrle-32bit +FATE_QTRLE_SCALE += fate-qtrle-32bit fate-qtrle-32bit: CMD = framecrc -i $(TARGET_SAMPLES)/qtrle/ultra_demo_720_480_32bpp_rle.mov -pix_fmt bgra -vf scale -FATE_SAMPLES_AVCONV-$(call DEMDEC, MOV, QTRLE) += $(FATE_QTRLE) -fate-qtrle: $(FATE_QTRLE) +FATE_QTRLE-$(call FRAMECRC, MOV, QTRLE) += $(FATE_QTRLE) +FATE_QTRLE-$(call FRAMECRC, MOV, QTRLE, SCALE_FILTER) += $(FATE_QTRLE_SCALE) + +FATE_SAMPLES_FFMPEG += $(FATE_QTRLE-yes) +fate-qtrle: $(FATE_QTRLE-yes) diff --git a/tests/fate/screen.mak b/tests/fate/screen.mak index aa9832688..bd6d22854 100644 --- a/tests/fate/screen.mak +++ b/tests/fate/screen.mak @@ -1,11 +1,11 @@ # FIXME dropped frames in this test because of coarse timebase -FATE_SCREEN-$(call DEMDEC, AVI, CSCD) += fate-cscd +FATE_SCREEN-$(call FRAMECRC, AVI, CSCD, SCALE_FILTER) += fate-cscd fate-cscd: CMD = framecrc -i $(TARGET_SAMPLES)/CSCD/sample_video.avi -an -pix_fmt rgb24 -vf scale -FATE_SCREEN-$(call DEMDEC, AVI, DXTORY) += fate-dxtory +FATE_SCREEN-$(call FRAMECRC, AVI, DXTORY) += fate-dxtory fate-dxtory: CMD = framecrc -i $(TARGET_SAMPLES)/dxtory/dxtory_mic.avi -an -FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, FIC) += fate-fic-avi +FATE_SCREEN-$(call FRAMECRC, AVI, FIC) += fate-fic-avi fate-fic-avi: CMD = framecrc -i $(TARGET_SAMPLES)/fic/fic-partial-2MB.avi -an FATE_FMVC += fate-fmvc-type1 @@ -14,8 +14,9 @@ fate-fmvc-type1: CMD = framecrc -i $(TARGET_SAMPLES)/fmvc/6-methyl-5-hepten-2-on 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_FMVC-$(call FRAMECRC, AVI, FMVC) += $(FATE_FMVC) +FATE_SCREEN += $(FATE_FMVC-yes) +fate-fmvc: $(FATE_FMVC-yes) FATE_FRAPS += fate-fraps-v0 fate-fraps-v0: CMD = framecrc -i $(TARGET_SAMPLES)/fraps/Griffin_Ragdoll01-partial.avi @@ -26,7 +27,7 @@ fate-fraps-v1: CMD = framecrc -i $(TARGET_SAMPLES)/fraps/sample-v1.avi -an FATE_FRAPS += fate-fraps-v2 fate-fraps-v2: CMD = framecrc -i $(TARGET_SAMPLES)/fraps/test3-nosound-partial.avi -FATE_FRAPS += fate-fraps-v3 +FATE_FRAPS-$(call FRAMECRC, AVI, FRAPS, SCALE_FILTER) += fate-fraps-v3 fate-fraps-v3: CMD = framecrc -i $(TARGET_SAMPLES)/fraps/psclient-partial.avi -pix_fmt rgb24 -vf scale FATE_FRAPS += fate-fraps-v4 @@ -35,8 +36,9 @@ fate-fraps-v4: CMD = framecrc -i $(TARGET_SAMPLES)/fraps/WoW_2006-11-03_14-58-17 FATE_FRAPS += fate-fraps-v5 fate-fraps-v5: CMD = framecrc -i $(TARGET_SAMPLES)/fraps/fraps-v5-bouncing-balls-partial.avi -FATE_SCREEN-$(call DEMDEC, AVI, FRAPS) += $(FATE_FRAPS) -fate-fraps: $(FATE_FRAPS) +FATE_FRAPS-$(call FRAMECRC, AVI, FRAPS) += $(FATE_FRAPS) +FATE_SCREEN += $(FATE_FRAPS-yes) +fate-fraps: $(FATE_FRAPS-yes) FATE_G2M += fate-g2m2 fate-g2m2: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/g2m/g2m2.asf -an @@ -47,13 +49,13 @@ fate-g2m3: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/g2m/g2m3.asf -frames FATE_G2M += fate-g2m4 fate-g2m4: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/g2m/g2m4.asf -FATE_SAMPLES_AVCONV-$(call DEMDEC, ASF, G2M) += $(FATE_G2M) +FATE_SCREEN-$(call FRAMECRC, ASF, G2M) += $(FATE_G2M) fate-g2m: $(FATE_G2M) FATE_RSCC += fate-iscc fate-iscc: CMD = framecrc -i $(TARGET_SAMPLES)/rscc/pip.avi -an -FATE_RSCC += fate-rscc-8bit +FATE_RSCC-$(call FRAMECRC, AVI, RSCC, SCALE_FILTER) += fate-rscc-8bit fate-rscc-8bit: CMD = framecrc -i $(TARGET_SAMPLES)/rscc/8bpp.avi -an -pix_fmt rgb24 -vf scale FATE_RSCC += fate-rscc-16bit @@ -65,8 +67,9 @@ fate-rscc-24bit: CMD = framecrc -i $(TARGET_SAMPLES)/rscc/24bpp.avi -an FATE_RSCC += fate-rscc-32bit fate-rscc-32bit: CMD = framecrc -i $(TARGET_SAMPLES)/rscc/32bpp.avi -an -FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, RSCC) += $(FATE_RSCC) -fate-rscc: $(FATE_RSCC) +FATE_RSCC-$(call FRAMECRC, AVI, RSCC) += $(FATE_RSCC) +FATE_SCREEN += $(FATE_RSCC-yes) +fate-rscc: $(FATE_RSCC-yes) FATE_SCREENPRESSO += fate-screenpresso-16bit fate-screenpresso-16bit: CMD = framecrc -i $(TARGET_SAMPLES)/spv1/16bpp_555.avi -an @@ -77,10 +80,11 @@ fate-screenpresso-24bit: CMD = framecrc -i $(TARGET_SAMPLES)/spv1/bunny.avi -an FATE_SCREENPRESSO += fate-screenpresso-32bit fate-screenpresso-32bit: CMD = framecrc -i $(TARGET_SAMPLES)/spv1/32bpp.avi -an -FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, SCREENPRESSO) += $(FATE_SCREENPRESSO) -fate-screenpresso: $(FATE_SCREENPRESSO) +FATE_SCREENPRESSO-$(call FRAMECRC, AVI, SCREENPRESSO) += $(FATE_SCREENPRESSO) +FATE_SCREEN += $(FATE_SCREENPRESSO-yes) +fate-screenpresso: $(FATE_SCREENPRESSO-yes) -FATE_SAMPLES_AVCONV-$(call DEMDEC, ASF, TDSC) += fate-tdsc +FATE_SCREEN-$(call FRAMECRC, ASF, TDSC) += fate-tdsc fate-tdsc: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/tdsc/tdsc.asf -an -pix_fmt bgr24 FATE_TSCC += fate-tscc-15bit @@ -89,16 +93,17 @@ fate-tscc-15bit: CMD = framecrc -i $(TARGET_SAMPLES)/tscc/oneminute.avi -t 15 -p FATE_TSCC += fate-tscc-32bit fate-tscc-32bit: CMD = framecrc -i $(TARGET_SAMPLES)/tscc/2004-12-17-uebung9-partial.avi -pix_fmt rgb24 -an -vf scale -FATE_SCREEN-$(call DEMDEC, AVI, TSCC) += $(FATE_TSCC) -fate-tscc: $(FATE_TSCC) +FATE_TSCC-$(call FRAMECRC, AVI, TSCC, SCALE_FILTER) += $(FATE_TSCC) +FATE_SCREEN += $(FATE_TSCC-yes) +fate-tscc: $(FATE_TSCC-yes) -FATE_TSCC2-$(CONFIG_AVI_DEMUXER) += fate-tscc2-avi +FATE_TSCC2-$(call FRAMECRC, AVI, TSCC2) += fate-tscc2-avi fate-tscc2-avi: CMD = framecrc -i $(TARGET_SAMPLES)/tscc/tsc2_16bpp.avi -FATE_TSCC2-$(CONFIG_MOV_DEMUXER) += fate-tscc2-mov +FATE_TSCC2-$(call FRAMECRC, MOV, TSCC2) += fate-tscc2-mov fate-tscc2-mov: CMD = framecrc -i $(TARGET_SAMPLES)/tscc/rec.trec -FATE_SAMPLES_AVCONV-$(CONFIG_TSCC2_DECODER) += $(FATE_TSCC2-yes) +FATE_SCREEN += $(FATE_TSCC2-yes) fate-tscc2: $(FATE_TSCC2-yes) FATE_VMNC += fate-vmnc-16bit @@ -107,8 +112,9 @@ fate-vmnc-16bit: CMD = framecrc -i $(TARGET_SAMPLES)/VMnc/test.avi -pix_fmt rgb2 FATE_VMNC += fate-vmnc-32bit fate-vmnc-32bit: CMD = framecrc -i $(TARGET_SAMPLES)/VMnc/VS2k5DebugDemo-01-partial.avi -pix_fmt rgb24 -vf scale -FATE_SCREEN-$(call DEMDEC, AVI, VMNC) += $(FATE_VMNC) -fate-vmnc: $(FATE_VMNC) +FATE_VMNC-$(call FRAMECRC, AVI, VMNC, SCALE_FILTER) += $(FATE_VMNC) +FATE_SCREEN += $(FATE_VMNC-yes) +fate-vmnc: $(FATE_VMNC-yes) FATE_ZMBV += fate-zmbv-8bit fate-zmbv-8bit: CMD = framecrc -i $(TARGET_SAMPLES)/zmbv/wc2_001-partial.avi -an -pix_fmt rgb24 -vf scale @@ -122,8 +128,9 @@ fate-zmbv-16bit: CMD = framecrc -i $(TARGET_SAMPLES)/zmbv/zmbv_16bit.avi -pix_fm FATE_ZMBV += fate-zmbv-32bit fate-zmbv-32bit: CMD = framecrc -i $(TARGET_SAMPLES)/zmbv/zmbv_32bit.avi -pix_fmt rgb24 -t 25 -vf scale -FATE_SCREEN-$(call DEMDEC, AVI, ZMBV) += $(FATE_ZMBV) -fate-zmbv: $(FATE_ZMBV) +FATE_ZMBV-$(call FRAMECRC, AVI, ZMBV, SCALE_FILTER) += $(FATE_ZMBV) +FATE_SCREEN += $(FATE_ZMBV-yes) +fate-zmbv: $(FATE_ZMBV-yes) FATE_SCREEN += $(FATE_SCREEN-yes) diff --git a/tests/fate/seek.mak b/tests/fate/seek.mak index 5efec3270..dfc2fa6a9 100644 --- a/tests/fate/seek.mak +++ b/tests/fate/seek.mak @@ -1,32 +1,16 @@ # files from fate-acodec -FATE_SEEK_ACODEC-$(call ENCDEC, ADPCM_IMA_QT, AIFF) += adpcm-ima_qt \ - adpcm-ima_qt-trellis -FATE_SEEK_ACODEC-$(call ENCDEC, ADPCM_IMA_WAV, WAV) += adpcm-ima_wav \ - adpcm-ima_wav-trellis -FATE_SEEK_ACODEC-$(call ENCDEC, ADPCM_MS, WAV) += adpcm-ms \ - adpcm-ms-trellis -FATE_SEEK_ACODEC-$(call ENCDEC, ADPCM_SWF, FLV) += adpcm-swf \ - adpcm-swf-trellis -FATE_SEEK_ACODEC-$(call ENCDEC, ADPCM_YAMAHA, WAV) += adpcm-yamaha \ - adpcm-yamaha-trellis -FATE_SEEK_ACODEC-$(call ENCDEC, ALAC, MOV) += alac -FATE_SEEK_ACODEC-$(call ENCDEC, FLAC, FLAC) += flac -FATE_SEEK_ACODEC-$(call ENCDEC, MP2, MP2 MP3) += mp2 -FATE_SEEK_ACODEC-$(call ENCDEC, PCM_ALAW, WAV) += pcm-alaw -FATE_SEEK_ACODEC-$(call ENCDEC, PCM_MULAW, WAV) += pcm-mulaw -FATE_SEEK_ACODEC-$(call ENCDEC, PCM_S8, MOV) += pcm-s8 -FATE_SEEK_ACODEC-$(call ENCDEC, PCM_U8, WAV) += pcm-u8 -FATE_SEEK_ACODEC-$(call ENCDEC, PCM_S16BE, MOV) += pcm-s16be -FATE_SEEK_ACODEC-$(call ENCDEC, PCM_S16LE, WAV) += pcm-s16le -FATE_SEEK_ACODEC-$(call ENCDEC, PCM_S24BE, MOV) += pcm-s24be -FATE_SEEK_ACODEC-$(call ENCDEC, PCM_S24LE, WAV) += pcm-s24le -FATE_SEEK_ACODEC-$(call ENCDEC, PCM_S32BE, MOV) += pcm-s32be -FATE_SEEK_ACODEC-$(call ENCDEC, PCM_S32LE, WAV) += pcm-s32le -FATE_SEEK_ACODEC-$(call ENCDEC, PCM_F32BE, AU) += pcm-f32be -FATE_SEEK_ACODEC-$(call ENCDEC, PCM_F32LE, WAV) += pcm-f32le -FATE_SEEK_ACODEC-$(call ENCDEC, PCM_F64BE, AU) += pcm-f64be -FATE_SEEK_ACODEC-$(call ENCDEC, PCM_F64LE, WAV) += pcm-f64le +FATE_SEEK_ACODEC += adpcm-ima_qt adpcm-ima_qt-trellis \ + adpcm-ima_wav adpcm-ima_wav-trellis \ + adpcm-ms adpcm-ms-trellis \ + adpcm-swf adpcm-swf-trellis \ + adpcm-yamaha adpcm-yamaha-trellis \ + alac flac mp2 \ + pcm-alaw pcm-mulaw pcm-s8 pcm-u8 \ + pcm-s16be pcm-s16le pcm-s24be \ + pcm-s24le pcm-s32be pcm-s32le \ + pcm-f32be pcm-f32le pcm-f64be \ + pcm-f64le \ fate-seek-acodec-adpcm-ima_qt: SRC = fate/acodec-adpcm-ima_qt.aiff fate-seek-acodec-adpcm-ima_wav: SRC = fate/acodec-adpcm-ima_wav.wav @@ -56,57 +40,37 @@ fate-seek-acodec-pcm-s32le: SRC = fate/acodec-pcm-s32le.wav fate-seek-acodec-pcm-s8: SRC = fate/acodec-pcm-s8.mov fate-seek-acodec-pcm-u8: SRC = fate/acodec-pcm-u8.wav -FATE_SEEK += $(FATE_SEEK_ACODEC-yes:%=fate-seek-acodec-%) +FATE_SEEK_ACODEC := $(FATE_SEEK_ACODEC:%=fate-seek-acodec-%) +# The following disables every fate-seek-* test whose +# corresponding fate-* test has unmet requirements (or is disabled). +FATE_SEEK_ACODEC := $(filter $(subst fate-,fate-seek-,$(FATE_ACODEC)), $(FATE_SEEK_ACODEC)) +FATE_SEEK += $(FATE_SEEK_ACODEC) # files from fate-vsynth_lena -FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, ASV1, AVI) += asv1 -FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, ASV2, AVI) += asv2 -FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, DNXHD, DNXHD) += dnxhd-720p -FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, DNXHD, DNXHD) += dnxhd-720p-rd -FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, DNXHD, MOV) += dnxhd-1080i -FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, DVVIDEO, DV) += dv -FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, DVVIDEO, DV) += dv-411 -FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, DVVIDEO, DV) += dv-50 -FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, FFV1, AVI) += ffv1 -FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, FLASHSV, FLV) += flashsv -FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, FLV, FLV) += flv -FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, H261, AVI) += h261 -FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, H263, AVI) += h263 -FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, H263, AVI) += h263p -FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, HUFFYUV, AVI) += huffyuv -FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, JPEGLS, AVI) += jpegls -FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, LJPEG MJPEG, AVI) += ljpeg -FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, MJPEG, AVI) += mjpeg - -FATE_SEEK_VSYNTH_LENA-$(call ALLYES, DNXHD_ENCODER DNXHD_DECODER LARGE_TESTS) += dnxhd-4k-hr-lb - -FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, MPEG1VIDEO, MPEG1VIDEO MPEGVIDEO) += \ - mpeg1 \ - mpeg1b - -FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, MPEG2VIDEO, MPEG2VIDEO MPEGVIDEO) += \ - mpeg2-422 \ - mpeg2-idct-int \ - mpeg2-ilace \ - mpeg2-ivlc-qprd \ - mpeg2-thread \ - mpeg2-thread-ivlc - -FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, MPEG4, MP4 MOV) += mpeg4 -FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, MPEG4, AVI) += $(FATE_MPEG4_AVI) -FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, MSMPEG4V3, AVI) += msmpeg4 -FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, MSMPEG4V2, AVI) += msmpeg4v2 -FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, RAWVIDEO, AVI) += rgb -FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, ROQ, ROQ) += roqvideo -FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, RV10, RM) += rv10 -FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, RV20, RM) += rv20 -FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, SNOW, AVI) += snow -FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, SNOW, AVI) += snow-ll -FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, SVQ1, MOV) += svq1 -FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, WMV1, AVI) += wmv1 -FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, WMV2, AVI) += wmv2 -FATE_SEEK_VSYNTH_LENA-$(call ENCDEC, RAWVIDEO, AVI) += yuv +FATE_SEEK_VSYNTH_LENA += asv1 asv2 \ + dnxhd-720p dnxhd-720p-rd \ + dnxhd-1080i dnxhd-4k-hr-lb \ + dv dv-411 dv-50 \ + ffv1 \ + flashsv \ + flv \ + h261 h263 h263p \ + huffyuv \ + jpegls ljpeg mjpeg \ + mpeg1 mpeg1b \ + mpeg2-422 mpeg2-idct-int \ + mpeg2-ilace mpeg2-ivlc-qprd \ + mpeg2-thread mpeg2-thread-ivlc \ + mpeg4 $(FATE_MPEG4_AVI) \ + msmpeg4 msmpeg4v2 \ + rgb \ + roqvideo \ + rv10 rv20 \ + snow snow-ll \ + svq1 \ + wmv1 wmv2 \ + yuv \ fate-seek-vsynth_lena-asv1: SRC = fate/vsynth_lena-asv1.avi fate-seek-vsynth_lena-asv2: SRC = fate/vsynth_lena-asv2.avi @@ -158,93 +122,61 @@ fate-seek-vsynth_lena-wmv1: SRC = fate/vsynth_lena-wmv1.avi fate-seek-vsynth_lena-wmv2: SRC = fate/vsynth_lena-wmv2.avi fate-seek-vsynth_lena-yuv: SRC = fate/vsynth_lena-yuv.avi -FATE_SAMPLES_SEEK += $(FATE_SEEK_VSYNTH_LENA-yes:%=fate-seek-vsynth_lena-%) +FATE_SEEK_VSYNTH_LENA := $(FATE_SEEK_VSYNTH_LENA:%=fate-seek-vsynth_lena-%) +FATE_SEEK_VSYNTH_LENA := $(filter $(subst fate-,fate-seek-,$(FATE_VSYNTH_LENA)), $(FATE_SEEK_VSYNTH_LENA)) +FATE_SAMPLES_SEEK += $(FATE_SEEK_VSYNTH_LENA) -# files from fate-lavf +# files from fate-lavf-audio -FATE_SEEK_LAVF-$(call ENCDEC, PCM_S16BE, AIFF) += aiff -FATE_SEEK_LAVF-$(call ENCDEC, PCM_ALAW, PCM_ALAW) += al -FATE_SEEK_LAVF-$(call ENCDEC2, MSMPEG4V3, MP2, ASF) += asf -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 -FATE_SEEK_LAVF-$(call ENCDEC, FLV, FLV) += flv -FATE_SEEK_LAVF-$(call ENCDEC, GIF, IMAGE2) += gif -FATE_SEEK_LAVF-$(call ENCDEC2, MPEG2VIDEO, PCM_S16LE, GXF) += gxf -FATE_SEEK_LAVF-$(call ENCDEC, MJPEG, IMAGE2) += jpg -FATE_SEEK_LAVF-$(call ENCDEC2, MPEG4, MP2, MATROSKA) += mkv -FATE_SEEK_LAVF-$(call ENCDEC, ADPCM_YAMAHA, MMF) += mmf -FATE_SEEK_LAVF-$(call ENCDEC2, MPEG4, PCM_ALAW, MOV) += mov -FATE_SEEK_LAVF-$(call ENCDEC2, MPEG1VIDEO, MP2, MPEG1SYSTEM MPEGPS) += mpg -FATE_SEEK_LAVF-$(call ENCDEC, PCM_MULAW, PCM_MULAW) += ul -FATE_SEEK_LAVF-$(call ENCDEC2, MPEG2VIDEO, PCM_S16LE, MXF) += mxf -FATE_SEEK_LAVF-$(call ENCDEC2, MPEG2VIDEO, PCM_S16LE, MXF_D10 MXF) += mxf_d10 -FATE_SEEK_LAVF-$(call ENCDEC2, DVVIDEO, PCM_S16LE, MXF) += mxf_dv25 -FATE_SEEK_LAVF-$(call ENCDEC2, DVVIDEO, PCM_S16LE, MXF) += mxf_dvcpro50 -FATE_SEEK_LAVF-$(call ENCDEC2, DNXHD, PCM_S16LE, MXF_OPATOM MXF) += mxf_opatom -FATE_SEEK_LAVF-$(call ENCDEC2, DNXHD, PCM_S16LE, MXF_OPATOM MXF) += mxf_opatom_audio -FATE_SEEK_LAVF-$(call ENCDEC2, MPEG4, MP2, NUT) += nut -FATE_SEEK_LAVF-$(call ENCDEC, FLAC, OGG) += ogg -FATE_SEEK_LAVF-$(call ENCDEC, PBM, IMAGE2PIPE) += pbmpipe -FATE_SEEK_LAVF-$(call ENCDEC, PCX, IMAGE2) += pcx -FATE_SEEK_LAVF-$(call ENCDEC, PGM, IMAGE2) += pgm -FATE_SEEK_LAVF-$(call ENCDEC, PGM, IMAGE2PIPE) += pgmpipe -FATE_SEEK_LAVF-$(call ENCDEC, PPM, IMAGE2) += ppm -FATE_SEEK_LAVF-$(call ENCDEC, PPM, IMAGE2PIPE) += ppmpipe -FATE_SEEK_LAVF-$(call ENCMUX, RV10 AC3_FIXED, RM) += rm -FATE_SEEK_LAVF-$(call ENCDEC, SGI, IMAGE2) += sgi -FATE_SEEK_LAVF-$(call ENCDEC, FLV, SWF) += swf -FATE_SEEK_LAVF-$(call ENCDEC, TARGA, IMAGE2) += tga -FATE_SEEK_LAVF-$(call ENCDEC, TIFF, IMAGE2) += tiff -FATE_SEEK_LAVF-$(call ENCDEC2, MPEG2VIDEO, MP2, MPEGTS) += ts -FATE_SEEK_LAVF-$(call ENCDEC, PCM_U8, VOC) += voc -FATE_SEEK_LAVF-$(call ENCDEC, PCM_S16LE, WAV) += wav -FATE_SEEK_LAVF-$(call ENCDEC, MP2, WTV) += wtv -FATE_SEEK_LAVF-$(CONFIG_YUV4MPEGPIPE_MUXER) += y4m +FATE_SEEK_LAVF_AUDIO += aiff al au mmf ogg ul voc wav -fate-seek-lavf-aiff: SRC = lavf/lavf.aiff -fate-seek-lavf-al: SRC = lavf/lavf.al -fate-seek-lavf-asf: SRC = lavf/lavf.asf -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: SRC = lavf/lavf.dv -fate-seek-lavf-flv: SRC = lavf/lavf.flv -fate-seek-lavf-gif: SRC = lavf/lavf.gif -fate-seek-lavf-gxf: SRC = lavf/lavf.gxf -fate-seek-lavf-jpg: SRC = images/jpg/%02d.jpg -fate-seek-lavf-mkv: SRC = lavf/lavf.mkv -fate-seek-lavf-mmf: SRC = lavf/lavf.mmf -fate-seek-lavf-mov: SRC = lavf/lavf.mov -fate-seek-lavf-mpg: SRC = lavf/lavf.mpg -fate-seek-lavf-ul: SRC = lavf/lavf.ul -fate-seek-lavf-mxf: SRC = lavf/lavf.mxf -fate-seek-lavf-mxf_d10: SRC = lavf/lavf.mxf_d10 -fate-seek-lavf-mxf_dv25: SRC = lavf/lavf.mxf_dv25 -fate-seek-lavf-mxf_dvcpro50: SRC = lavf/lavf.mxf_dvcpro50 -fate-seek-lavf-mxf_opatom: SRC = lavf/lavf.mxf_opatom -fate-seek-lavf-mxf_opatom_audio: SRC = lavf/lavf.mxf_opatom_audio -fate-seek-lavf-nut: SRC = lavf/lavf.nut -fate-seek-lavf-ogg: SRC = lavf/lavf.ogg -fate-seek-lavf-pbmpipe: SRC = lavf/pbmpipe.pbm -fate-seek-lavf-pcx: SRC = images/pcx/%02d.pcx -fate-seek-lavf-pgm: SRC = images/pgm/%02d.pgm -fate-seek-lavf-pgmpipe: SRC = lavf/pgmpipe.pgm -fate-seek-lavf-ppm: SRC = images/ppm/%02d.ppm -fate-seek-lavf-ppmpipe: SRC = lavf/ppmpipe.ppm -fate-seek-lavf-rm: SRC = lavf/lavf.rm -fate-seek-lavf-sgi: SRC = images/sgi/%02d.sgi -fate-seek-lavf-swf: SRC = lavf/lavf.swf -fate-seek-lavf-tga: SRC = images/tga/%02d.tga -fate-seek-lavf-tiff: SRC = images/tiff/%02d.tiff -fate-seek-lavf-ts: SRC = lavf/lavf.ts -fate-seek-lavf-voc: SRC = lavf/lavf.voc -fate-seek-lavf-wav: SRC = lavf/lavf.wav -fate-seek-lavf-wtv: SRC = lavf/lavf.wtv -fate-seek-lavf-y4m: SRC = lavf/lavf.y4m +FATE_SEEK_LAVF_AUDIO := $(FATE_SEEK_LAVF_AUDIO:%=fate-seek-lavf-%) +FATE_SEEK_LAVF_AUDIO := $(filter $(subst fate-,fate-seek-,$(FATE_LAVF_AUDIO)), $(FATE_SEEK_LAVF_AUDIO)) +FATE_SEEK += $(FATE_SEEK_LAVF_AUDIO) -FATE_SEEK += $(FATE_SEEK_LAVF-yes:%=fate-seek-lavf-%) +# files from fate-lavf-container + +FATE_SEEK_LAVF_CONTAINER += asf avi dv flv gxf mkv mov mpg \ + mxf mxf_d10 mxf_dv25 mxf_dvcpro50 \ + mxf_opatom mxf_opatom_audio \ + nut swf ts wtv +# rm is special: fate-lavf-rm does not read the created file +# and therefore does not require the corresponding demuxer +# to be present, so we have to explicitly check for this here. +FATE_SEEK_LAVF_CONTAINER-$(CONFIG_RM_DEMUXER) += rm +FATE_SEEK_LAVF_CONTAINER += $(FATE_SEEK_LAVF_CONTAINER-yes) + +FATE_SEEK_LAVF_CONTAINER := $(FATE_SEEK_LAVF_CONTAINER:%=fate-seek-lavf-%) +FATE_SEEK_LAVF_CONTAINER := $(filter $(subst fate-,fate-seek-,$(FATE_LAVF_CONTAINER)), $(FATE_SEEK_LAVF_CONTAINER)) +FATE_SEEK += $(FATE_SEEK_LAVF_CONTAINER) + +# files from fate-lavf-video + +FATE_SEEK_LAVF_VIDEO += gif y4m + +FATE_SEEK_LAVF_VIDEO := $(FATE_SEEK_LAVF_VIDEO:%=fate-seek-lavf-%) +FATE_SEEK_LAVF_VIDEO := $(filter $(subst fate-,fate-seek-,$(FATE_LAVF_VIDEO)), $(FATE_SEEK_LAVF_VIDEO)) +FATE_SEEK += $(FATE_SEEK_LAVF_VIDEO) + +$(FATE_SEEK_LAVF_AUDIO) $(FATE_SEEK_LAVF_CONTAINER) $(FATE_SEEK_LAVF_VIDEO): SRC = lavf/lavf.$(@:fate-seek-lavf-%=%) + +# files from fate-lavf-image + +FATE_SEEK_LAVF_IMAGE += bmp jpg pcx pgm ppm sgi tga tiff + +FATE_SEEK_LAVF_IMAGE := $(FATE_SEEK_LAVF_IMAGE:%=fate-seek-lavf-%) +FATE_SEEK_LAVF_IMAGE := $(filter $(subst fate-,fate-seek-,$(FATE_LAVF_IMAGES)), $(FATE_SEEK_LAVF_IMAGE)) +$(FATE_SEEK_LAVF_IMAGE): SRC = images/$(@:fate-seek-lavf-%=%)/%02d.$(@:fate-seek-lavf-%=%) +FATE_SEEK += $(FATE_SEEK_LAVF_IMAGE) + +#files from fate-lavf-image2pipe + +FATE_SEEK_LAVF_IMAGE2PIPE += pbmpipe pgmpipe ppmpipe + +FATE_SEEK_LAVF_IMAGE2PIPE := $(FATE_SEEK_LAVF_IMAGE2PIPE:%=fate-seek-lavf-%) +FATE_SEEK_LAVF_IMAGE2PIPE := $(filter $(subst fate-,fate-seek-,$(FATE_LAVF_IMAGE2PIPE)), $(FATE_SEEK_LAVF_IMAGE2PIPE)) +$(FATE_SEEK_LAVF_IMAGE2PIPE): SRC = lavf/$(@:fate-seek-lavf-%pipe=%)pipe.$(@:fate-seek-lavf-%pipe=%) +FATE_SEEK += $(FATE_SEEK_LAVF_IMAGE2PIPE) # extra files @@ -270,7 +202,7 @@ FATE_SEEK_EXTRA += $(FATE_SEEK_EXTRA-yes) $(FATE_SEEK) $(FATE_SAMPLES_SEEK) $(FATE_SEEK_EXTRA): libavformat/tests/seek$(EXESUF) $(FATE_SEEK) $(FATE_SAMPLES_SEEK): CMD = run libavformat/tests/seek$(EXESUF) $(TARGET_PATH)/tests/data/$(SRC) $(FATE_SEEK) $(FATE_SAMPLES_SEEK): fate-seek-%: fate-% -$(subst fate-seek-,fate-,$(FATE_SAMPLES_SEEK) $(FATE_SEEK)): KEEP_OVERRIDE = -keep +$(subst fate-seek-,fate-,$(FATE_SAMPLES_SEEK) $(FATE_SEEK)): KEEP_FILES ?= 1 fate-seek-%: REF = $(SRC_PATH)/tests/ref/seek/$(@:fate-seek-%=%) FATE_AVCONV += $(FATE_SEEK) diff --git a/tests/fate/speedhq.mak b/tests/fate/speedhq.mak index 32405b710..199ee160e 100644 --- a/tests/fate/speedhq.mak +++ b/tests/fate/speedhq.mak @@ -4,5 +4,5 @@ FATE_SPEEDHQ = fate-speedhq-422 \ fate-speedhq-422: CMD = framecrc -flags +bitexact -f rawvideo -c:v speedhq -tag:v SHQ2 -video_size 112x64 -i $(TARGET_SAMPLES)/speedhq/progressive.shq2 -pix_fmt yuv422p fate-speedhq-422-singlefield: CMD = framecrc -flags +bitexact -f rawvideo -c:v speedhq -tag:v SHQ2 -video_size 112x32 -i $(TARGET_SAMPLES)/speedhq/singlefield.shq2 -pix_fmt yuv422p -FATE_SAMPLES_FFMPEG-$(call DEMDEC, RAWVIDEO, SPEEDHQ) += $(FATE_SPEEDHQ) +FATE_SAMPLES_FFMPEG-$(call FRAMECRC, RAWVIDEO, SPEEDHQ) += $(FATE_SPEEDHQ) fate-speedhq: $(FATE_SPEEDHQ) diff --git a/tests/fate/subtitles.mak b/tests/fate/subtitles.mak index 8375cf289..bc464edce 100644 --- a/tests/fate/subtitles.mak +++ b/tests/fate/subtitles.mak @@ -22,7 +22,7 @@ fate-binsub-mksenc: CMD = md5pipe -i $(TARGET_SAMPLES)/sub/1ededcbd7b.ass -c cop FATE_SUBTITLES_ASS-$(call DEMDEC, JACOSUB, JACOSUB) += fate-sub-jacosub fate-sub-jacosub: CMD = fmtstdout ass -i $(TARGET_SAMPLES)/sub/JACOsub_capability_tester.jss -FATE_SUBTITLES-$(call DEMMUX, JACOSUB, JACOSUB) += fate-sub-jacosub-remux +FATE_SUBTITLES-$(call REMUX, JACOSUB) += fate-sub-jacosub-remux fate-sub-jacosub-remux: CMD = transcode jacosub $(TARGET_SAMPLES)/sub/JACOsub_capability_tester.jss jacosub "-map 0 -c copy" "-map 0 -c copy" fate-sub-jacosub-remux: CMP = diff diff --git a/tests/fate/utvideo.mak b/tests/fate/utvideo.mak index 9329df538..bf8401c37 100644 --- a/tests/fate/utvideo.mak +++ b/tests/fate/utvideo.mak @@ -64,8 +64,9 @@ fate-utvideo_yuv444_709_gradient: CMD = framecrc -i $(TARGET_SAMPLES)/utvideo/ut 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) +FATE_UTVIDEO-$(call FRAMECRC, AVI, UTVIDEO) += $(FATE_UTVIDEO) +FATE_SAMPLES_FFMPEG += $(FATE_UTVIDEO-yes) +fate-utvideo: $(FATE_UTVIDEO-yes) 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} -vf scale @@ -116,5 +117,6 @@ fate-utvideoenc_yuv444_none: OPTS = -pix_fmt yuv444p -pred none $(FATE_UTVIDEOENC): $(VREF) -FATE_AVCONV-$(call ENCMUX, UTVIDEO, AVI) += $(FATE_UTVIDEOENC) -fate-utvideoenc: $(FATE_UTVIDEOENC) +FATE_UTVIDEOENC-$(call FILTERDEMDECENCMUX, SCALE, IMAGE2, PGMYUV, UTVIDEO, FRAMEMD5, PIPE_PROTOCOL) += $(FATE_UTVIDEOENC) +FATE_FFMPEG += $(FATE_UTVIDEOENC-yes) +fate-utvideoenc: $(FATE_UTVIDEOENC-yes) diff --git a/tests/fate/vbn.mak b/tests/fate/vbn.mak new file mode 100644 index 000000000..91ce3c963 --- /dev/null +++ b/tests/fate/vbn.mak @@ -0,0 +1,18 @@ +fate-vbn-%: VBN_FILE = tests/data/$(subst fate-vbn-,,$(@)).vbn +fate-vbn-%: PIX_FMT = rgba +fate-vbn-raw-rgb24: PIX_FMT = rgb24 +fate-vbn-%: SRC = $(TARGET_SAMPLES)/png1/lena-$(PIX_FMT).png +fate-vbn-%: ENC_OPTS = -c:v vbn -format $(word 3,$(subst -, ,$(@))) +fate-vbn-%: CMD = refcmp_metadata_transcode "$(SRC)" "$(ENC_OPTS)" image2 vbn psnr $(PIX_FMT) + +FATE_VBN += fate-vbn-dxt1 +FATE_VBN += fate-vbn-dxt5 +FATE_VBN += fate-vbn-raw-rgba +FATE_VBN += fate-vbn-raw-rgb24 + +FATE_VBN-$(call ENCDEC2, VBN, WRAPPED_AVFRAME PNG, IMAGE2, \ + PSNR_FILTER METADATA_FILTER SCALE_FILTER \ + NULL_MUXER PIPE_PROTOCOL) += $(FATE_VBN) + +FATE_SAMPLES_FFMPEG += $(FATE_VBN-yes) +fate-vbn: $(FATE_VBN-yes) diff --git a/tests/fate/vcodec.mak b/tests/fate/vcodec.mak index 2e6d16f1e..8ca17950e 100644 --- a/tests/fate/vcodec.mak +++ b/tests/fate/vcodec.mak @@ -4,12 +4,13 @@ fate-vsynth_lena-%: SRC = tests/data/vsynth_lena.yuv fate-vsynth3-%: SRC = tests/data/vsynth3.yuv fate-vsynth%: CODEC = $(word 3, $(subst -, ,$(@))) fate-vsynth%: FMT = avi -fate-vsynth%: CMD = enc_dec "rawvideo -s 352x288 -pix_fmt yuv420p $(RAWDECOPTS)" $(SRC) $(FMT) "-c $(CODEC) $(ENCOPTS)" rawvideo "-s 352x288 -pix_fmt yuv420p -vsync passthrough $(DECOPTS)" "$(KEEP_OVERRIDE)" "$(DECINOPTS)" -fate-vsynth3-%: CMD = enc_dec "rawvideo -s $(FATEW)x$(FATEH) -pix_fmt yuv420p $(RAWDECOPTS)" $(SRC) $(FMT) "-c $(CODEC) $(ENCOPTS)" rawvideo "-s $(FATEW)x$(FATEH) -pix_fmt yuv420p -vsync passthrough $(DECOPTS)" "" "$(DECINOPTS)" +fate-vsynth%: DEFAULT_SIZE = -s 352x288 +fate-vsynth3-%: DEFAULT_SIZE = -s $(FATEW)x$(FATEH) +fate-vsynth%: CMD = enc_dec "rawvideo $(DEFAULT_SIZE) -pix_fmt yuv420p $(RAWDECOPTS)" $(SRC) $(FMT) "-c $(CODEC) $(ENCOPTS)" rawvideo "-pix_fmt yuv420p -vsync passthrough $(DECOPTS)" "" "" ${TWOPASS} fate-vsynth%: CMP_UNIT = 1 fate-vsynth%: REF = $(SRC_PATH)/tests/ref/vsynth/$(@:fate-%=%) -FATE_VCODEC-$(call ENCDEC, AMV, AVI) += amv +FATE_VCODEC_SCALE-$(call ENCDEC, AMV, AVI) += amv fate-vsynth%-amv: ENCOPTS = -strict -1 FATE_VCODEC-$(call ENCDEC, ASV1, AVI) += asv1 @@ -18,30 +19,17 @@ 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_VCODEC_SCALE-$(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_SCALE-$(call ENCDEC, CLJR, AVI) += cljr fate-vsynth%-cljr: ENCOPTS = -strict -1 -FATE_VCODEC-$(call ENCDEC, DNXHD, DNXHD) += dnxhd-720p \ - dnxhd-720p-rd \ - dnxhd-720p-10bit \ - dnxhd-720p-hr-lb \ - dnxhd-edge1-hr \ - dnxhd-edge2-hr \ - dnxhd-edge3-hr - -FATE_VCODEC-$(call ALLYES, DNXHD_ENCODER DNXHD_DECODER LARGE_TESTS) += dnxhd-4k-hr-lb \ - dnxhd-2k-hr-hq \ - dnxhd-uhd-hr-sq - - -FATE_VCODEC-$(call ENCDEC, VC2 DIRAC, MOV) += vc2-420p vc2-420p10 vc2-420p12 \ - vc2-422p vc2-422p10 vc2-422p12 \ - vc2-444p vc2-444p10 vc2-444p12 \ - vc2-thaar vc2-t5_3 +FATE_VCODEC-$(call ENCDEC, VC2 DIRAC, MOV) += vc2-420p +FATE_VCODEC_SCALE-$(call ENCDEC, VC2 DIRAC, MOV) += vc2-420p10 vc2-420p12 \ + vc2-422p vc2-422p10 vc2-422p12 \ + vc2-444p vc2-444p10 vc2-444p12 \ + vc2-thaar vc2-t5_3 fate-vsynth1-vc2-4%: FMT = mov fate-vsynth1-vc2-4%: ENCOPTS = -pix_fmt yuv$(@:fate-vsynth1-vc2-%=%) \ -c:v vc2 -frames 5 -strict -1 @@ -59,116 +47,118 @@ fate-vsynth2-vc2-t%: ENCOPTS = -pix_fmt yuv422p10 -c:v vc2 -frames 5 fate-vsynth_lena-vc2-t%: FMT = mov fate-vsynth_lena-vc2-t%: ENCOPTS = -pix_fmt yuv422p10 -c:v vc2 -frames 5 -strict -1 -wavelet_type $(@:fate-vsynth_lena-vc2-t%=%) +FATE_VCODEC_DNXHD_DNXHD := dnxhd-720p \ + dnxhd-720p-rd \ + dnxhd-720p-10bit \ + dnxhd-720p-hr-lb \ + dnxhd-edge1-hr \ + dnxhd-edge2-hr \ + dnxhd-edge3-hr \ + $(if $(CONFIG_LARGE_TESTS), dnxhd-4k-hr-lb \ + dnxhd-2k-hr-hq \ + dnxhd-uhd-hr-sq) \ + +FATE_VCODEC_SCALE-$(call ENCDEC, DNXHD, DNXHD) += $(FATE_VCODEC_DNXHD_DNXHD) + fate-vsynth%-dnxhd-720p: ENCOPTS = -s hd720 -b 90M \ -pix_fmt yuv422p -frames 5 -qmax 8 -fate-vsynth%-dnxhd-720p: FMT = dnxhd fate-vsynth%-dnxhd-720p-rd: ENCOPTS = -s hd720 -b 90M -threads 4 -mbd rd \ -pix_fmt yuv422p -frames 5 -qmax 8 -fate-vsynth%-dnxhd-720p-rd: FMT = dnxhd fate-vsynth%-dnxhd-720p-10bit: ENCOPTS = -s hd720 -b 90M \ -pix_fmt yuv422p10 -frames 5 -qmax 8 -fate-vsynth%-dnxhd-720p-10bit: FMT = dnxhd fate-vsynth%-dnxhd-720p-hr-lb: ENCOPTS = -s hd720 -profile:v dnxhr_lb \ -pix_fmt yuv422p -frames 5 fate-vsynth%-dnxhd-720p-hr-lb: DECOPTS = -sws_flags area+accurate_rnd+bitexact -fate-vsynth%-dnxhd-720p-hr-lb: FMT = dnxhd fate-vsynth%-dnxhd-4k-hr-lb: ENCOPTS = -s 4k -profile:v dnxhr_lb \ -pix_fmt yuv422p -frames 5 fate-vsynth%-dnxhd-4k-hr-lb: DECOPTS = -sws_flags area+accurate_rnd+bitexact -fate-vsynth%-dnxhd-4k-hr-lb: FMT = dnxhd fate-vsynth%-dnxhd-uhd-hr-sq: ENCOPTS = -s uhd2160 -profile:v dnxhr_sq \ -pix_fmt yuv422p -frames 5 fate-vsynth%-dnxhd-uhd-hr-sq: DECOPTS = -sws_flags area+accurate_rnd+bitexact -fate-vsynth%-dnxhd-uhd-hr-sq: FMT = dnxhd fate-vsynth%-dnxhd-2k-hr-hq: ENCOPTS = -s 2k -profile:v dnxhr_hq \ -pix_fmt yuv422p -frames 5 fate-vsynth%-dnxhd-2k-hr-hq: DECOPTS = -sws_flags area+accurate_rnd+bitexact -fate-vsynth%-dnxhd-2k-hr-hq: FMT = dnxhd fate-vsynth%-dnxhd-edge1-hr: ENCOPTS = -s 264x128 -profile:v dnxhr_hq \ -pix_fmt yuv422p -frames 5 fate-vsynth%-dnxhd-edge1-hr: DECOPTS = -sws_flags area+accurate_rnd+bitexact -fate-vsynth%-dnxhd-edge1-hr: FMT = dnxhd fate-vsynth%-dnxhd-edge2-hr: ENCOPTS = -s 271x135 -profile:v dnxhr_hq \ -pix_fmt yuv422p -frames 5 fate-vsynth%-dnxhd-edge2-hr: DECOPTS = -sws_flags area+accurate_rnd+bitexact -fate-vsynth%-dnxhd-edge2-hr: FMT = dnxhd fate-vsynth%-dnxhd-edge3-hr: ENCOPTS = -s 257x121 -profile:v dnxhr_hq \ -pix_fmt yuv422p -frames 5 fate-vsynth%-dnxhd-edge3-hr: DECOPTS = -sws_flags area+accurate_rnd+bitexact -fate-vsynth%-dnxhd-edge3-hr: FMT = dnxhd -FATE_VCODEC-$(call ENCDEC, DNXHD, MOV) += dnxhd-1080i dnxhd-1080i-10bit dnxhd-1080i-colr \ - dnxhd-hr-lb-mov dnxhd-hr-sq-mov dnxhd-hr-hq-mov +$(FATE_VCODEC_DNXHD_DNXHD:%=fate-vsynth\%-%): FMT = dnxhd +$(FATE_VCODEC_DNXHD_DNXHD:%=fate-vsynth\%-%): DECOPTS += $(DEFAULT_SIZE) + +FATE_VCODEC_DNXHD_MOV := dnxhd-1080i dnxhd-1080i-10bit dnxhd-1080i-colr \ + dnxhd-hr-lb-mov dnxhd-hr-sq-mov dnxhd-hr-hq-mov \ + +FATE_VCODEC_SCALE-$(call ENCDEC, DNXHD, MOV) += $(FATE_VCODEC_DNXHD_MOV) fate-vsynth%-dnxhd-1080i: ENCOPTS = -s hd1080 -b 120M -flags +ildct \ -pix_fmt yuv422p -frames 5 -qmax 8 -fate-vsynth%-dnxhd-1080i: FMT = mov fate-vsynth%-dnxhd-1080i-10bit: ENCOPTS = -s hd1080 -b 185M -flags +ildct \ -pix_fmt yuv422p10 -frames 5 -qmax 8 fate-vsynth%-dnxhd-1080i-10bit: DECOPTS = -sws_flags area+accurate_rnd+bitexact -fate-vsynth%-dnxhd-1080i-10bit: FMT = mov fate-vsynth%-dnxhd-1080i-colr: ENCOPTS = -s hd1080 -b 120M -flags +ildct -movflags write_colr \ -pix_fmt yuv422p -frames 5 -qmax 8 fate-vsynth%-dnxhd-1080i-colr: DECOPTS = -sws_flags area+accurate_rnd+bitexact -fate-vsynth%-dnxhd-1080i-colr: FMT = mov fate-vsynth%-dnxhd-hr-lb-mov: ENCOPTS = -s uhd2160 -profile:v dnxhr_lb \ -pix_fmt yuv422p -frames 5 fate-vsynth%-dnxhd-hr-lb-mov: DECOPTS = -sws_flags area+accurate_rnd+bitexact -fate-vsynth%-dnxhd-hr-lb-mov: FMT = mov fate-vsynth%-dnxhd-hr-sq-mov: ENCOPTS = -s 2kscope -profile:v dnxhr_sq \ -pix_fmt yuv422p -frames 5 fate-vsynth%-dnxhd-hr-sq-mov: DECOPTS = -sws_flags area+accurate_rnd+bitexact -fate-vsynth%-dnxhd-hr-sq-mov: FMT = mov fate-vsynth%-dnxhd-hr-hq-mov: ENCOPTS = -s 2kflat -profile:v dnxhr_hq \ -pix_fmt yuv422p -frames 5 fate-vsynth%-dnxhd-hr-hq-mov: DECOPTS = -sws_flags area+accurate_rnd+bitexact -fate-vsynth%-dnxhd-hr-hq-mov: FMT = mov -FATE_VCODEC-$(call ENCDEC, DVVIDEO, DV) += dv dv-411 dv-50 dv-hd dv-fhd -fate-vsynth%-dv: CODEC = dvvideo +$(FATE_VCODEC_DNXHD_MOV:%=fate-vsynth\%-%): FMT = mov +$(FATE_VCODEC_DNXHD_MOV:%=fate-vsynth\%-%): DECOPTS += $(DEFAULT_SIZE) + +FATE_VCODEC_DV := dv dv-411 dv-50 dv-hd dv-fhd +FATE_VCODEC_SCALE-$(call ENCDEC, DVVIDEO, DV) += $(FATE_VCODEC_DV) fate-vsynth%-dv: ENCOPTS = -dct int -s pal -fate-vsynth%-dv: FMT = dv -fate-vsynth%-dv-411: CODEC = dvvideo fate-vsynth%-dv-411: ENCOPTS = -dct int -s pal -pix_fmt yuv411p \ -sws_flags area fate-vsynth%-dv-411: DECOPTS = -sws_flags area -fate-vsynth%-dv-411: FMT = dv -fate-vsynth%-dv-50: CODEC = dvvideo fate-vsynth%-dv-50: ENCOPTS = -dct int -s pal -pix_fmt yuv422p \ -sws_flags neighbor fate-vsynth%-dv-50: DECOPTS = -sws_flags neighbor -fate-vsynth%-dv-50: FMT = dv -fate-vsynth%-dv-fhd: CODEC = dvvideo fate-vsynth%-dv-fhd: ENCOPTS = -dct int -s 1440x1080 -pix_fmt yuv422p \ -sws_flags neighbor fate-vsynth%-dv-fhd: DECOPTS = -sws_flags neighbor -fate-vsynth%-dv-fhd: FMT = dv -fate-vsynth%-dv-hd: CODEC = dvvideo fate-vsynth%-dv-hd: ENCOPTS = -dct int -s 960x720 -pix_fmt yuv422p \ -sws_flags neighbor fate-vsynth%-dv-hd: DECOPTS = -sws_flags neighbor -fate-vsynth%-dv-hd: FMT = dv + +$(FATE_VCODEC_DV:%=fate-vsynth\%-%): CODEC = dvvideo +$(FATE_VCODEC_DV:%=fate-vsynth\%-%): FMT = dv +$(FATE_VCODEC_DV:%=fate-vsynth\%-%): DECOPTS += $(DEFAULT_SIZE) FATE_VCODEC-$(call ENCDEC, FFV1, AVI) += ffv1 ffv1-v0 \ - ffv1-v3-yuv420p ffv1-v3-yuv422p10 ffv1-v3-yuv444p16 \ - ffv1-v3-bgr0 ffv1-v3-rgb48 + ffv1-v3-yuv420p \ + ffv1-2pass +FATE_VCODEC_SCALE-$(call ENCDEC, FFV1, AVI) += ffv1-v3-yuv422p10 ffv1-v3-yuv444p16 \ + ffv1-v3-bgr0 ffv1-v3-rgb48 fate-vsynth%-ffv1: ENCOPTS = -slices 4 fate-vsynth%-ffv1-v0: CODEC = ffv1 fate-vsynth%-ffv1-v3-yuv420p: ENCOPTS = -level 3 -pix_fmt yuv420p @@ -184,19 +174,22 @@ fate-vsynth%-ffv1-v3-bgr0: DECOPTS = -sws_flags neighbor+bitexact fate-vsynth%-ffv1-v3-rgb48: ENCOPTS = -level 3 -pix_fmt rgb48 -strict -2 \ -sws_flags neighbor+bitexact fate-vsynth%-ffv1-v3-rgb48: DECOPTS = -sws_flags neighbor+bitexact +fate-vsynth%-ffv1-2pass: TWOPASS = 1 +fate-vsynth%-ffv1-2pass: ENCOPTS = -coder range_tab -context 1 -FATE_VCODEC-$(call ENCDEC, FFVHUFF, AVI) += ffvhuff ffvhuff444 ffvhuff420p12 ffvhuff422p10left ffvhuff444p16 +FATE_VCODEC-$(call ENCDEC, FFVHUFF, AVI) += ffvhuff +FATE_VCODEC_SCALE-$(call ENCDEC, FFVHUFF, AVI) += ffvhuff444 ffvhuff420p12 ffvhuff422p10left ffvhuff444p16 fate-vsynth%-ffvhuff444: ENCOPTS = -c:v ffvhuff -pix_fmt yuv444p fate-vsynth%-ffvhuff420p12: ENCOPTS = -c:v ffvhuff -pix_fmt yuv420p12le fate-vsynth%-ffvhuff422p10left: ENCOPTS = -c:v ffvhuff -pix_fmt yuv422p10le -pred left fate-vsynth%-ffvhuff444p16: ENCOPTS = -c:v ffvhuff -pix_fmt yuv444p16le -pred plane -FATE_VCODEC-$(call ENCDEC, FLASHSV, FLV) += flashsv +FATE_VCODEC_SCALE-$(call ENCDEC, FLASHSV, FLV) += flashsv fate-vsynth%-flashsv: ENCOPTS = -sws_flags neighbor+full_chroma_int fate-vsynth%-flashsv: DECOPTS = -sws_flags area fate-vsynth%-flashsv: FMT = flv -FATE_VCODEC-$(call ENCDEC, FLASHSV2, FLV) += flashsv2 +FATE_VCODEC_SCALE-$(call ENCDEC, FLASHSV2, FLV) += flashsv2 fate-vsynth%-flashsv2: ENCOPTS = -sws_flags neighbor+full_chroma_int -strict experimental -compression_level 0 fate-vsynth%-flashsv2: DECOPTS = -sws_flags area fate-vsynth%-flashsv2: FMT = flv @@ -214,7 +207,7 @@ fate-vsynth%-h263: ENCOPTS = -qscale 10 fate-vsynth%-h263-obmc: ENCOPTS = -qscale 10 -obmc 1 fate-vsynth%-h263p: ENCOPTS = -qscale 2 -flags +aic -umv 1 -aiv 1 -ps 300 -FATE_VCODEC-$(call ENCDEC, HUFFYUV, AVI) += huffyuv huffyuvbgr24 huffyuvbgra +FATE_VCODEC_SCALE-$(call ENCDEC, HUFFYUV, AVI) += huffyuv huffyuvbgr24 huffyuvbgra fate-vsynth%-huffyuv: ENCOPTS = -c:v huffyuv -pix_fmt yuv422p -sws_flags neighbor fate-vsynth%-huffyuv: DECOPTS = -sws_flags neighbor fate-vsynth%-huffyuvbgr24: ENCOPTS = -c:v huffyuv -pix_fmt bgr24 -sws_flags neighbor @@ -222,20 +215,18 @@ fate-vsynth%-huffyuvbgr24: DECOPTS = -sws_flags neighbor fate-vsynth%-huffyuvbgra: ENCOPTS = -c:v huffyuv -pix_fmt bgr32 -sws_flags neighbor fate-vsynth%-huffyuvbgra: DECOPTS = -sws_flags neighbor -FATE_VCODEC-$(call ENCDEC, JPEGLS, AVI) += jpegls +FATE_VCODEC_SCALE-$(call ENCDEC, JPEGLS, AVI) += jpegls fate-vsynth%-jpegls: ENCOPTS = -sws_flags neighbor+full_chroma_int fate-vsynth%-jpegls: DECOPTS = -sws_flags area -FATE_VCODEC-$(call ENCDEC, JPEG2000, AVI) += jpeg2000 jpeg2000-97 +FATE_VCODEC_SCALE-$(call ENCDEC, JPEG2000, AVI) += jpeg2000 jpeg2000-97 fate-vsynth%-jpeg2000: ENCOPTS = -qscale 7 -strict experimental -pred 1 -pix_fmt rgb24 -fate-vsynth%-jpeg2000: DECINOPTS = -c:v jpeg2000 fate-vsynth%-jpeg2000-97: ENCOPTS = -qscale 7 -strict experimental -pix_fmt rgb24 -fate-vsynth%-jpeg2000-97: DECINOPTS = -c:v jpeg2000 FATE_VCODEC-$(call ENCDEC, LJPEG MJPEG, AVI) += ljpeg fate-vsynth%-ljpeg: ENCOPTS = -strict -1 -FATE_VCODEC-$(call ENCDEC, MJPEG, AVI) += mjpeg mjpeg-422 mjpeg-444 mjpeg-trell mjpeg-huffman mjpeg-trell-huffman +FATE_VCODEC_SCALE-$(call ENCDEC, MJPEG, AVI) += mjpeg mjpeg-422 mjpeg-444 mjpeg-trell mjpeg-huffman mjpeg-trell-huffman fate-vsynth%-mjpeg: ENCOPTS = -qscale 9 -pix_fmt yuvj420p fate-vsynth%-mjpeg-422: ENCOPTS = -qscale 9 -pix_fmt yuvj422p fate-vsynth%-mjpeg-444: ENCOPTS = -qscale 9 -pix_fmt yuvj444p @@ -252,8 +243,8 @@ fate-vsynth%-mpeg1b: CODEC = mpeg1video fate-vsynth%-mpeg1b: ENCOPTS = -qscale 8 -bf 3 -ps 200 fate-vsynth%-mpeg1b: FMT = mpeg1video -FATE_MPEG2 = mpeg2 \ - mpeg2-422 \ +FATE_MPEG2 := mpeg2 \ + $(if $(CONFIG_SCALE_FILTER), mpeg2-422) \ mpeg2-idct-int \ mpeg2-ilace \ mpeg2-ivlc-qprd \ @@ -345,12 +336,12 @@ fate-vsynth%-msmpeg4: ENCOPTS = -qscale 10 FATE_VCODEC-$(call ENCDEC, MSMPEG4V2, AVI) += msmpeg4v2 fate-vsynth%-msmpeg4v2: ENCOPTS = -qscale 10 -FATE_VCODEC-$(call ENCDEC, PNG, AVI) += mpng +FATE_VCODEC_SCALE-$(call ENCDEC, PNG, AVI) += mpng fate-vsynth%-mpng: CODEC = png -FATE_VCODEC-$(call ENCDEC, MSVIDEO1, AVI) += msvideo1 +FATE_VCODEC_SCALE-$(call ENCDEC, MSVIDEO1, AVI) += msvideo1 -FATE_VCODEC-$(call ENCDEC, PRORES, MOV) += prores prores_int prores_444 prores_444_int prores_ks +FATE_VCODEC_SCALE-$(call ENCDEC, PRORES, MOV) += prores prores_int prores_444 prores_444_int prores_ks fate-vsynth%-prores: FMT = mov fate-vsynth%-prores_int: CODEC = prores @@ -368,14 +359,14 @@ fate-vsynth%-prores_444_int: FMT = mov fate-vsynth%-prores_ks: ENCOPTS = -profile hq fate-vsynth%-prores_ks: FMT = mov -FATE_VCODEC-$(call ENCDEC, QTRLE, MOV) += qtrle qtrlegray +FATE_VCODEC_SCALE-$(call ENCDEC, QTRLE, MOV) += qtrle qtrlegray fate-vsynth%-qtrle: FMT = mov fate-vsynth%-qtrlegray: CODEC = qtrle fate-vsynth%-qtrlegray: ENCOPTS = -pix_fmt gray fate-vsynth%-qtrlegray: FMT = mov -FATE_VCODEC-$(call ENCDEC, RAWVIDEO, AVI) += rgb bpp1 bpp15 +FATE_VCODEC_SCALE-$(call ENCDEC, RAWVIDEO, AVI) += rgb bpp1 bpp15 fate-vsynth%-rgb: CODEC = rawvideo fate-vsynth%-rgb: ENCOPTS = -pix_fmt bgr24 fate-vsynth%-bpp1: CODEC = rawvideo @@ -383,7 +374,7 @@ fate-vsynth%-bpp1: ENCOPTS = -pix_fmt monow fate-vsynth%-bpp15: CODEC = rawvideo fate-vsynth%-bpp15: ENCOPTS = -pix_fmt bgr555le -FATE_VCODEC-$(call ENCDEC, RAWVIDEO, MOV) += mov-bgr24 mov-bpp15 mov-bpp16 +FATE_VCODEC_SCALE-$(call ENCDEC, RAWVIDEO, MOV) += mov-bgr24 mov-bpp15 mov-bpp16 fate-vsynth%-mov-bgr24: CODEC = rawvideo fate-vsynth%-mov-bgr24: ENCOPTS = -pix_fmt bgr24 fate-vsynth%-mov-bgr24: FMT = mov @@ -394,7 +385,7 @@ fate-vsynth%-mov-bpp16: CODEC = rawvideo fate-vsynth%-mov-bpp16: ENCOPTS = -pix_fmt rgb565le fate-vsynth%-mov-bpp16: FMT = mov -FATE_VCODEC-$(call ENCDEC, ROQ, ROQ) += roqvideo +FATE_VCODEC_SCALE-$(call ENCDEC, ROQ, ROQ) += roqvideo fate-vsynth%-roqvideo: CODEC = roqvideo fate-vsynth%-roqvideo: ENCOPTS = -frames 5 fate-vsynth%-roqvideo: RAWDECOPTS = -r 30 @@ -408,7 +399,7 @@ FATE_VCODEC-$(call ENCDEC, RV20, RM) += rv20 fate-vsynth%-rv20: ENCOPTS = -qscale 10 fate-vsynth%-rv20: FMT = rm -FATE_VCODEC-$(call ENCDEC, SNOW, AVI) += snow snow-hpel snow-ll +FATE_VCODEC_SCALE-$(call ENCDEC, SNOW, AVI) += snow snow-hpel fate-vsynth%-snow: ENCOPTS = -qscale 2 -flags +qpel \ -motion_est iter -dia_size 2 \ -cmp 12 -subcmp 12 -s 128x64 @@ -416,28 +407,30 @@ fate-vsynth%-snow: ENCOPTS = -qscale 2 -flags +qpel \ fate-vsynth%-snow-hpel: ENCOPTS = -qscale 2 \ -motion_est iter -dia_size 2 \ -cmp 12 -subcmp 12 -s 128x64 +fate-vsynth%-snow fate-vsynth%-snow-hpel: DECOPTS = $(DEFAULT_SIZE) +FATE_VCODEC-$(call ENCDEC, SNOW, AVI) += snow-ll fate-vsynth%-snow-ll: ENCOPTS = -qscale .001 -pred 1 \ -flags +mv4+qpel -FATE_VCODEC-$(call ENCDEC, SVQ1, MOV) += svq1 +FATE_VCODEC_SCALE-$(call ENCDEC, SVQ1, MOV) += svq1 fate-vsynth%-svq1: ENCOPTS = -qscale 3 -pix_fmt yuv410p fate-vsynth%-svq1: FMT = mov -FATE_VCODEC-$(call ENCDEC, R210, AVI) += r210 +FATE_VCODEC_SCALE-$(call ENCDEC, R210, AVI) += r210 -FATE_VCODEC-$(call ENCDEC, V210, AVI) += v210 v210-10 +FATE_VCODEC_SCALE-$(call ENCDEC, V210, AVI) += v210 v210-10 fate-vsynth%-v210-10: ENCOPTS = -pix_fmt yuv422p10 -FATE_VCODEC-$(call ENCDEC, V308, AVI) += v308 +FATE_VCODEC_SCALE-$(call ENCDEC, V308, AVI) += v308 -FATE_VCODEC-$(call ENCDEC, V408, AVI) += v408 +FATE_VCODEC_SCALE-$(call ENCDEC, V408, AVI) += v408 fate-vsynth%-v408: ENCOPTS = -sws_flags neighbor+bitexact fate-vsynth%-v408: DECOPTS = -sws_flags neighbor+bitexact -FATE_VCODEC-$(call ENCDEC, AVUI, MOV) += avui +FATE_VCODEC_SCALE-$(call ENCDEC, AVUI, MOV) += avui fate-vsynth%-avui: ENCOPTS = -s pal -strict experimental -sws_flags neighbor+bitexact -fate-vsynth%-avui: DECOPTS = -sws_flags neighbor+bitexact +fate-vsynth%-avui: DECOPTS = -sws_flags neighbor+bitexact $(DEFAULT_SIZE) fate-vsynth%-avui: FMT = mov FATE_VCODEC-$(call ENCDEC, WMV1, AVI) += wmv1 @@ -449,18 +442,20 @@ fate-vsynth%-wmv2: ENCOPTS = -qscale 10 FATE_VCODEC-$(call ENCDEC, RAWVIDEO, AVI) += yuv fate-vsynth%-yuv: CODEC = rawvideo -FATE_VCODEC-$(call ENCDEC, XFACE, NUT) += xface +FATE_VCODEC_SCALE-$(call ENCDEC, XFACE, NUT) += xface fate-vsynth%-xface: ENCOPTS = -s 48x48 -sws_flags neighbor+bitexact -fate-vsynth%-xface: DECOPTS = -sws_flags neighbor+bitexact +fate-vsynth%-xface: DECOPTS = -sws_flags neighbor+bitexact $(DEFAULT_SIZE) fate-vsynth%-xface: FMT = nut FATE_VCODEC-$(call ENCDEC, YUV4, AVI) += yuv4 -FATE_VCODEC-$(call ENCDEC, Y41P, AVI) += y41p +FATE_VCODEC_SCALE-$(call ENCDEC, Y41P, AVI) += y41p -FATE_VCODEC-$(call ENCDEC, ZLIB, AVI) += zlib +FATE_VCODEC_SCALE-$(call ENCDEC, ZLIB, AVI) += zlib +FATE_VCODEC-$(CONFIG_SCALE_FILTER) += $(FATE_VCODEC_SCALE-yes) FATE_VCODEC += $(FATE_VCODEC-yes) +FATE_VCODEC := $(if $(call ENCDEC, RAWVIDEO, RAWVIDEO),$(FATE_VCODEC)) FATE_VSYNTH1 = $(FATE_VCODEC:%=fate-vsynth1-%) FATE_VSYNTH2 = $(FATE_VCODEC:%=fate-vsynth2-%) FATE_VSYNTH_LENA = $(FATE_VCODEC:%=fate-vsynth_lena-%) diff --git a/tests/fate/video.mak b/tests/fate/video.mak index dff1f13e8..40cdd9e3b 100644 --- a/tests/fate/video.mak +++ b/tests/fate/video.mak @@ -4,55 +4,56 @@ fate-4xm-1: CMD = framecrc -i $(TARGET_SAMPLES)/4xm/version1.4xm -pix_fmt rgb24 FATE_4XM += fate-4xm-2 fate-4xm-2: CMD = framecrc -i $(TARGET_SAMPLES)/4xm/version2.4xm -pix_fmt rgb24 -an -vf scale -FATE_VIDEO-$(call DEMDEC, FOURXM, FOURXM) += $(FATE_4XM) -fate-4xm: $(FATE_4XM) +FATE_4XM-$(call FRAMECRC, FOURXM, FOURXM, SCALE_FILTER) += $(FATE_4XM) +FATE_VIDEO += $(FATE_4XM-yes) +fate-4xm: $(FATE_4XM-yes) -FATE_VIDEO-$(call DEMDEC, AVI, ZERO12V) += fate-012v +FATE_VIDEO-$(call FRAMECRC, AVI, ZERO12V, SCALE_FILTER) += fate-012v fate-012v: CMD = framecrc -i $(TARGET_SAMPLES)/012v/sample.avi -pix_fmt yuv422p16le -vf scale -FATE_VIDEO-$(call DEMDEC, AVI, AASC) += fate-aasc +FATE_VIDEO-$(call FRAMECRC, AVI, AASC, SCALE_FILTER) += fate-aasc fate-aasc: CMD = framecrc -i $(TARGET_SAMPLES)/aasc/AASC-1.5MB.AVI -pix_fmt rgb24 -vf scale -FATE_VIDEO-$(call DEMDEC, MOV, AIC) += fate-aic +FATE_VIDEO-$(call FRAMECRC, MOV, AIC) += fate-aic fate-aic: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/aic/small_apple_intermediate_codec.mov -an -frames:v 15 -FATE_VIDEO-$(call DEMDEC, MOV, AIC) += fate-aic-oddsize +FATE_VIDEO-$(call FRAMECRC, MOV, AIC) += fate-aic-oddsize fate-aic-oddsize: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/aic/aic_odd_dimensions.mov -FATE_VIDEO-$(call DEMDEC, MM, MMVIDEO) += fate-alg-mm +FATE_VIDEO-$(call FRAMECRC, MM, MMVIDEO, SCALE_FILTER) += fate-alg-mm fate-alg-mm: CMD = framecrc -i $(TARGET_SAMPLES)/alg-mm/ibmlogo.mm -an -pix_fmt rgb24 -vf scale -FATE_VIDEO-$(call DEMDEC, AVI, AMV) += fate-amv +FATE_VIDEO-$(call FRAMECRC, AVI, AMV) += fate-amv fate-amv: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/amv/MTV_high_res_320x240_sample_Penguin_Joke_MTV_from_WMV.amv -t 10 -an -FATE_VIDEO-$(call DEMDEC, TTY, ANSI) += fate-ansi +FATE_VIDEO-$(call FRAMECRC, TTY, ANSI, SCALE_FILTER) += fate-ansi fate-ansi: CMD = framecrc -chars_per_frame 44100 -i $(TARGET_SAMPLES)/ansi/TRE-IOM5.ANS -pix_fmt rgb24 -vf scale -FATE_VIDEO-$(call DEMDEC, TTY, ANSI) += fate-ansi256 +FATE_VIDEO-$(call FRAMECRC, TTY, ANSI, SCALE_FILTER) += fate-ansi256 fate-ansi256: CMD = framecrc -chars_per_frame 44100 -i $(TARGET_SAMPLES)/ansi/ansi256.ans -pix_fmt rgb24 -vf scale -FATE_VIDEO-$(call DEMDEC, RPL, ESCAPE124) += fate-armovie-escape124 +FATE_VIDEO-$(call FRAMECRC, RPL, ESCAPE124, ARESAMPLE_FILTER SCALE_FILTER) += fate-armovie-escape124 fate-armovie-escape124: CMD = framecrc -i $(TARGET_SAMPLES)/rpl/ESCAPE.RPL -pix_fmt rgb24 -vf scale -af aresample -FATE_VIDEO-$(call DEMDEC, RPL, ESCAPE130) += fate-armovie-escape130 +FATE_VIDEO-$(call FRAMECRC, RPL, ESCAPE130) += fate-armovie-escape130 fate-armovie-escape130: CMD = framecrc -i $(TARGET_SAMPLES)/rpl/landing.rpl -an -FATE_VIDEO-$(call DEMDEC, AVI, AURA) += fate-auravision-v1 +FATE_VIDEO-$(call FRAMECRC, AVI, AURA) += fate-auravision-v1 fate-auravision-v1: CMD = framecrc -i $(TARGET_SAMPLES)/auravision/SOUVIDEO.AVI -an -FATE_VIDEO-$(call DEMDEC, AVI, AURA2) += fate-auravision-v2 +FATE_VIDEO-$(call FRAMECRC, AVI, AURA2) += fate-auravision-v2 fate-auravision-v2: CMD = framecrc -i $(TARGET_SAMPLES)/auravision/salma-hayek-in-ugly-betty-partial-avi -an -FATE_VIDEO-$(call DEMDEC, AVI, AVRN) += fate-avid-interlaced +FATE_VIDEO-$(call FRAMECRC, AVI, AVRN) += fate-avid-interlaced fate-avid-interlaced: CMD = framecrc -i $(TARGET_SAMPLES)/avid/avid_ntsc_interlaced.avi -FATE_VIDEO-$(call DEMDEC, MOV, MJPEG) += fate-avid-meridian +FATE_VIDEO-$(call FRAMECRC, MOV, MJPEG) += fate-avid-meridian fate-avid-meridian: CMD = framecrc -i $(TARGET_SAMPLES)/avid/avidmeridianntsc.mov -FATE_VIDEO-$(call DEMDEC, BETHSOFTVID, BETHSOFTVID) += fate-bethsoft-vid +FATE_VIDEO-$(call FRAMECRC, BETHSOFTVID, BETHSOFTVID, ARESAMPLE_FILTER SCALE_FILTER) += fate-bethsoft-vid fate-bethsoft-vid: CMD = framecrc -i $(TARGET_SAMPLES)/bethsoft-vid/ANIM0001.VID -t 5 -pix_fmt rgb24 -vf scale -af aresample -FATE_VIDEO-$(call DEMDEC, BFI, BFI) += fate-bfi +FATE_VIDEO-$(call FRAMECRC, BFI, BFI, ARESAMPLE_FILTER SCALE_FILTER) += fate-bfi fate-bfi: CMD = framecrc -i $(TARGET_SAMPLES)/bfi/2287.bfi -pix_fmt rgb24 -vf scale -af aresample FATE_BINK_VIDEO += fate-bink-video-b @@ -64,69 +65,69 @@ fate-bink-video-f: CMD = framecrc -i $(TARGET_SAMPLES)/bink/hol2br.bik FATE_BINK_VIDEO += fate-bink-video-i fate-bink-video-i: CMD = framecrc -i $(TARGET_SAMPLES)/bink/RazOnBull.bik -an -FATE_VIDEO-$(call DEMDEC, BINK, BINK) += $(FATE_BINK_VIDEO) +FATE_VIDEO-$(call FRAMECRC, BINK, BINK) += $(FATE_BINK_VIDEO) -FATE_VIDEO-$(call DEMDEC, BMV, BMV_VIDEO) += fate-bmv-video -fate-bmv-video: CMD = framecrc -i $(TARGET_SAMPLES)/bmv/SURFING-partial.BMV -pix_fmt rgb24 -an -vf scale -vf scale +FATE_VIDEO-$(call FRAMECRC, BMV, BMV_VIDEO, SCALE_FILTER) += fate-bmv-video +fate-bmv-video: CMD = framecrc -i $(TARGET_SAMPLES)/bmv/SURFING-partial.BMV -pix_fmt rgb24 -an -vf scale -FATE_VIDEO-$(call DEMDEC, MPEGPS, CAVS) += fate-cavs +FATE_VIDEO-$(call FRAMECRC, MPEGPS, CAVS) += fate-cavs fate-cavs: CMD = framecrc -i $(TARGET_SAMPLES)/cavs/cavs.mpg -an -FATE_VIDEO-$(call DEMDEC, CDG, CDGRAPHICS) += fate-cdgraphics +FATE_VIDEO-$(call FRAMECRC, CDG, CDGRAPHICS, SCALE_FILTER) += fate-cdgraphics fate-cdgraphics: CMD = framecrc -i $(TARGET_SAMPLES)/cdgraphics/BrotherJohn.cdg -pix_fmt rgba -t 1 -vf scale -FATE_CFHD-$(CONFIG_AVI_DEMUXER) += fate-cfhd-1 +FATE_CFHD-$(call FRAMECRC, AVI, CFHD, SCALE_FILTER) += fate-cfhd-1 fate-cfhd-1: CMD = framecrc -i $(TARGET_SAMPLES)/cfhd/cfhd_422.avi -pix_fmt yuv422p10le -vf scale -FATE_CFHD-$(CONFIG_AVI_DEMUXER) += fate-cfhd-2 +FATE_CFHD-$(call FRAMECRC, AVI, CFHD, SCALE_FILTER) += fate-cfhd-2 fate-cfhd-2: CMD = framecrc -i $(TARGET_SAMPLES)/cfhd/cfhd_444.avi -pix_fmt gbrp12le -vf scale -FATE_CFHD-$(CONFIG_MOV_DEMUXER) += fate-cfhd-3 +FATE_CFHD-$(call FRAMECRC, MOV, CFHD, SCALE_FILTER) += fate-cfhd-3 fate-cfhd-3: CMD = framecrc -i $(TARGET_SAMPLES)/cfhd/cfhd_odd.mov -pix_fmt yuv422p10le -vf scale -FATE_VIDEO-$(CONFIG_CFHD_DECODER) += $(FATE_CFHD-yes) +FATE_VIDEO += $(FATE_CFHD-yes) fate-cfhd: $(FATE_CFHD-yes) -FATE_VIDEO-$(call DEMDEC, AVI, CLJR) += fate-cljr +FATE_VIDEO-$(call FRAMECRC, AVI, CLJR) += fate-cljr fate-cljr: CMD = framecrc -i $(TARGET_SAMPLES)/cljr/testcljr-partial.avi -FATE_VIDEO-$(call DEMDEC, AVI, PNG) += fate-corepng -fate-corepng: CMD = framecrc -i $(TARGET_SAMPLES)/png1/corepng-partial.avi -vf scale -af aresample +FATE_VIDEO-$(call FRAMECRC, AVI, PNG, ARESAMPLE_FILTER) += fate-corepng +fate-corepng: CMD = framecrc -i $(TARGET_SAMPLES)/png1/corepng-partial.avi -af aresample -FATE_VIDEO-$(call DEMDEC, AVI, PNG) += fate-rgbapng-4816 +FATE_VIDEO-$(call FRAMECRC, AVI, PNG) += fate-rgbapng-4816 fate-rgbapng-4816: CMD = framecrc -i $(TARGET_SAMPLES)/png1/55c99e750a5fd6_50314226.png -FATE_VIDEO-$(call DEMDEC, AVS, AVS) += fate-creatureshock-avs +FATE_VIDEO-$(call FRAMECRC, AVS, AVS, ARESAMPLE_FILTER SCALE_FILTER) += fate-creatureshock-avs fate-creatureshock-avs: CMD = framecrc -i $(TARGET_SAMPLES)/creatureshock-avs/OUTATIME.AVS -pix_fmt rgb24 -vf scale -af aresample -FATE_CVID-$(CONFIG_MOV_DEMUXER) += fate-cvid-palette +FATE_CVID-$(call FRAMECRC, MOV, CINEPAK, SCALE_FILTER) += fate-cvid-palette fate-cvid-palette: CMD = framecrc -i $(TARGET_SAMPLES)/cvid/catfight-cvid-pal8-partial.mov -pix_fmt rgb24 -an -vf scale -FATE_CVID-$(CONFIG_AVI_DEMUXER) += fate-cvid-partial +FATE_CVID-$(call FRAMECRC, AVI, CINEPAK) += fate-cvid-partial fate-cvid-partial: CMD = framecrc -i $(TARGET_SAMPLES)/cvid/laracroft-cinepak-partial.avi -an -FATE_CVID-$(CONFIG_AVI_DEMUXER) += fate-cvid-grayscale +FATE_CVID-$(call FRAMECRC, AVI, CINEPAK) += fate-cvid-grayscale fate-cvid-grayscale: CMD = framecrc -i $(TARGET_SAMPLES)/cvid/pcitva15.avi -an -FATE_VIDEO-$(CONFIG_CINEPAK_DECODER) += $(FATE_CVID-yes) +FATE_VIDEO += $(FATE_CVID-yes) fate-cvid: $(FATE_CVID-yes) -FATE_VIDEO-$(call DEMDEC, C93, C93) += fate-cyberia-c93 +FATE_VIDEO-$(call FRAMECRC, C93, C93, SCALE_FILTER ARESAMPLE_FILTER) += fate-cyberia-c93 fate-cyberia-c93: CMD = framecrc -i $(TARGET_SAMPLES)/cyberia-c93/intro1.c93 -t 3 -pix_fmt rgb24 -vf scale -af aresample -FATE_VIDEO-$(call DEMDEC, AVI, CYUV) += fate-cyuv +FATE_VIDEO-$(call FRAMECRC, AVI, CYUV) += fate-cyuv fate-cyuv: CMD = framecrc -i $(TARGET_SAMPLES)/cyuv/cyuv.avi -FATE_VIDEO-$(call DEMDEC, DSICIN, DSICINVIDEO) += fate-delphine-cin-video +FATE_VIDEO-$(call FRAMECRC, DSICIN, DSICINVIDEO, SCALE_FILTER) += fate-delphine-cin-video fate-delphine-cin-video: CMD = framecrc -i $(TARGET_SAMPLES)/delphine-cin/LOGO-partial.CIN -pix_fmt rgb24 -an -vf scale -FATE_VIDEO-$(call DEMDEC, ANM, ANM) += fate-deluxepaint-anm +FATE_VIDEO-$(call FRAMECRC, ANM, ANM, SCALE_FILTER) += fate-deluxepaint-anm fate-deluxepaint-anm: CMD = framecrc -i $(TARGET_SAMPLES)/deluxepaint-anm/INTRO1.ANM -pix_fmt rgb24 -vf scale -FATE_VIDEO-$(call DEMDEC, DIRAC, DIRAC) += fate-dirac +FATE_VIDEO-$(call FRAMECRC, DIRAC, DIRAC) += fate-dirac fate-dirac: CMD = framecrc -i $(TARGET_SAMPLES)/dirac/vts.profile-main.drc -FATE_VIDEO-$(call DEMDEC, DIRAC, DIRAC) += fate-dirac-low-delay +FATE_VIDEO-$(call FRAMECRC, DIRAC, DIRAC) += fate-dirac-low-delay fate-dirac-low-delay: CMD = framecrc -i $(TARGET_SAMPLES)/dirac/vts.profile-vc2-low-delay.drc FATE_DXA += fate-dxa-feeble @@ -135,8 +136,9 @@ fate-dxa-feeble: CMD = framecrc -i $(TARGET_SAMPLES)/dxa/meetsquid.dxa -t 2 -pix FATE_DXA += fate-dxa-scummvm fate-dxa-scummvm: CMD = framecrc -i $(TARGET_SAMPLES)/dxa/scummvm.dxa -pix_fmt rgb24 -vf scale -FATE_VIDEO-$(call DEMDEC, DXA, DXA) += $(FATE_DXA) -fate-dxa: $(FATE_DXA) +FATE_DXA-$(call FRAMECRC, DXA, DXA, SCALE_FILTER) += $(FATE_DXA) +FATE_VIDEO += $(FATE_DXA-yes) +fate-dxa: $(FATE_DXA-yes) FATE_DXV += fate-dxv-dxt1 fate-dxv-dxt1: CMD = framecrc -i $(TARGET_SAMPLES)/dxv/dxv-na.mov @@ -150,10 +152,10 @@ fate-dxv3-dxt1: CMD = framecrc -i $(TARGET_SAMPLES)/dxv/dxv3-nqna.mov FATE_DXV += fate-dxv3-dxt5 fate-dxv3-dxt5: CMD = framecrc -i $(TARGET_SAMPLES)/dxv/dxv3-nqwa.mov -FATE_VIDEO-$(call DEMDEC, MOV, DXV) += $(FATE_DXV) +FATE_VIDEO-$(call FRAMECRC, MOV, DXV) += $(FATE_DXV) fate-dxv: $(FATE_DXV) -FATE_VIDEO-$(call DEMDEC, SEGAFILM, CINEPAK) += fate-film-cvid +FATE_VIDEO-$(call FRAMECRC, SEGAFILM, CINEPAK) += fate-film-cvid fate-film-cvid: CMD = framecrc -i $(TARGET_SAMPLES)/film/logo-capcom.cpk -an FATE_FLIC += fate-flic-af11-palette-change @@ -165,49 +167,50 @@ fate-flic-af12: CMD = framecrc -i $(TARGET_SAMPLES)/fli/jj00c2.fli -pix_fmt rgb2 FATE_FLIC += fate-flic-magiccarpet fate-flic-magiccarpet: CMD = framecrc -i $(TARGET_SAMPLES)/fli/intel.dat -pix_fmt rgb24 -vf scale -FATE_VIDEO-$(call DEMDEC, FLIC, FLIC) += $(FATE_FLIC) -fate-flic: $(FATE_FLIC) +FATE_FLIC-$(call FRAMECRC, FLIC, FLIC, SCALE_FILTER) += $(FATE_FLIC) +FATE_VIDEO += $(FATE_FLIC-yes) +fate-flic: $(FATE_FLIC-yes) -FATE_VIDEO-$(call DEMDEC, AVI, FRWU) += fate-frwu +FATE_VIDEO-$(call FRAMECRC, AVI, FRWU) += fate-frwu fate-frwu: CMD = framecrc -i $(TARGET_SAMPLES)/frwu/frwu.avi -FATE_VIDEO-$(call DEMDEC, IDCIN, IDCIN) += fate-id-cin-video +FATE_VIDEO-$(call FRAMECRC, IDCIN, IDCIN, SCALE_FILTER) += fate-id-cin-video fate-id-cin-video: CMD = framecrc -i $(TARGET_SAMPLES)/idcin/idlog-2MB.cin -pix_fmt rgb24 -vf scale -FATE_VIDEO-$(call ENCDEC, ROQ PGMYUV, ROQ IMAGE2) += fate-idroq-video-encode +FATE_VIDEO-$(call ENCDEC, ROQ PGMYUV, ROQ IMAGE2, SCALE_FILTER) += fate-idroq-video-encode fate-idroq-video-encode: CMD = md5 -auto_conversion_filters -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_IFF-$(CONFIG_IFF_ILBM_DECODER) += fate-iff-byterun1 +FATE_IFF-$(call FRAMECRC, IFF, IFF_ILBM, SCALE_FILTER) += fate-iff-byterun1 fate-iff-byterun1: CMD = framecrc -i $(TARGET_SAMPLES)/iff/ASH.LBM -pix_fmt rgb24 -vf scale -FATE_IFF-$(CONFIG_EIGHTSVX_FIB_DECODER) += fate-iff-fibonacci -fate-iff-fibonacci: CMD = md5 -i $(TARGET_SAMPLES)/iff/dasboot-in-compressed -f s16le -vf scale -af aresample +FATE_IFF-$(call ENCDEC, PCM_S16LE EIGHTSVX_FIB, PCM_S16LE IFF, ARESAMPLE_FILTER) += fate-iff-fibonacci +fate-iff-fibonacci: CMD = md5 -i $(TARGET_SAMPLES)/iff/dasboot-in-compressed -f s16le -af aresample -FATE_IFF-$(CONFIG_IFF_ILBM_DECODER) += fate-iff-ilbm +FATE_IFF-$(call FRAMECRC, IFF, IFF_ILBM, SCALE_FILTER) += fate-iff-ilbm fate-iff-ilbm: CMD = framecrc -i $(TARGET_SAMPLES)/iff/lms-matriks.ilbm -pix_fmt rgb24 -vf scale FATE_VIDEO-$(CONFIG_IFF_DEMUXER) += $(FATE_IFF-yes) fate-iff: $(FATE_IFF-yes) -FATE_VIDEO-$(call DEMDEC, IPMOVIE, INTERPLAY_VIDEO) += fate-interplay-mve-8bit +FATE_VIDEO-$(call FRAMECRC, IPMOVIE, INTERPLAY_VIDEO, SCALE_FILTER) += fate-interplay-mve-8bit fate-interplay-mve-8bit: CMD = framecrc -i $(TARGET_SAMPLES)/interplay-mve/interplay-logo-2MB.mve -pix_fmt rgb24 -an -vf scale -FATE_VIDEO-$(call DEMDEC, IPMOVIE, INTERPLAY_VIDEO) += fate-interplay-mve-16bit +FATE_VIDEO-$(call FRAMECRC, IPMOVIE, INTERPLAY_VIDEO, SCALE_FILTER) += fate-interplay-mve-16bit fate-interplay-mve-16bit: CMD = framecrc -i $(TARGET_SAMPLES)/interplay-mve/descent3-level5-16bit-partial.mve -pix_fmt rgb24 -an -vf scale -FATE_VIDEO-$(call DEMDEC, MXF, JPEG2000) += fate-jpeg2000-dcinema +FATE_VIDEO-$(call FRAMECRC, MXF, JPEG2000, SCALE_FILTER) += fate-jpeg2000-dcinema fate-jpeg2000-dcinema: CMD = framecrc -flags +bitexact -c:v jpeg2000 -i $(TARGET_SAMPLES)/jpeg2000/chiens_dcinema2K.mxf -pix_fmt xyz12le -vf scale -FATE_VIDEO-$(call DEMDEC, JV, JV) += fate-jv +FATE_VIDEO-$(call FRAMECRC, JV, JV, SCALE_FILTER) += fate-jv fate-jv: CMD = framecrc -i $(TARGET_SAMPLES)/jv/intro.jv -an -pix_fmt rgb24 -vf scale -FATE_VIDEO-$(call DEMDEC, AVI, KGV1) += fate-kgv1 +FATE_VIDEO-$(call FRAMECRC, AVI, KGV1, SCALE_FILTER) += fate-kgv1 fate-kgv1: CMD = framecrc -i $(TARGET_SAMPLES)/kega/kgv1.avi -pix_fmt rgb555le -an -vf scale -FATE_VIDEO-$(call DEMDEC, AVI, KMVC) += fate-kmvc +FATE_VIDEO-$(call FRAMECRC, AVI, KMVC, SCALE_FILTER) += fate-kmvc fate-kmvc: CMD = framecrc -i $(TARGET_SAMPLES)/KMVC/LOGO1.AVI -an -t 3 -pix_fmt rgb24 -vf scale -FATE_VIDEO-$(call DEMDEC, AVI, LSCR) += fate-lscr +FATE_VIDEO-$(call FRAMECRC, AVI, LSCR) += fate-lscr fate-lscr: CMD = framecrc -i $(TARGET_SAMPLES)/lscr/lscr_compr9_short.avi FATE_MAGICYUV += fate-magicyuv-y4444i \ @@ -218,7 +221,7 @@ FATE_MAGICYUV += fate-magicyuv-y4444i \ fate-magicyuv-rgba \ fate-magicyuv-rgb -FATE_VIDEO-$(call DEMDEC, AVI, MAGICYUV) += $(FATE_MAGICYUV) +FATE_VIDEO-$(call FRAMECRC, AVI, MAGICYUV) += $(FATE_MAGICYUV) fate-magicyuv: $(FATE_MAGICYUV) fate-magicyuv-rgb: CMD = framecrc -i $(TARGET_SAMPLES)/magy/magy_rgb_median.avi @@ -229,41 +232,41 @@ fate-magicyuv-y422i: CMD = framecrc -i $(TARGET_SAMPLES)/magy/magy_yuv422_media fate-magicyuv-y4444i: CMD = framecrc -i $(TARGET_SAMPLES)/magy/magy_yuv4444_left_interlaced.avi fate-magicyuv-y444: CMD = framecrc -i $(TARGET_SAMPLES)/magy/magy_yuv444_left.avi -FATE_VIDEO-$(call DEMDEC, EA, MDEC) += fate-mdec +FATE_VIDEO-$(call FRAMECRC, EA, MDEC) += fate-mdec fate-mdec: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/ea-dct/NFS2Esprit-partial.dct -an -FATE_VIDEO-$(call DEMDEC, STR, MDEC) += fate-mdec-v3 +FATE_VIDEO-$(call FRAMECRC, STR, MDEC) += fate-mdec-v3 fate-mdec-v3: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/psx-str/abc000_cut.str -an -FATE_VIDEO-$(call DEMDEC, MSNWC_TCP, MIMIC) += fate-mimic +FATE_VIDEO-$(call FRAMECRC, MSNWC_TCP, MIMIC) += fate-mimic fate-mimic: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/mimic/mimic2-womanloveffmpeg.cam -FATE_VIDEO-$(call DEMDEC, MOV, MJPEGB) += fate-mjpegb +FATE_VIDEO-$(call FRAMECRC, MOV, MJPEGB) += fate-mjpegb fate-mjpegb: CMD = framecrc -idct simple -fflags +bitexact -i $(TARGET_SAMPLES)/mjpegb/mjpegb_part.mov -an -FATE_VIDEO-$(call DEMDEC, AVI, MJPEG) += fate-mjpeg-ticket3229 +FATE_VIDEO-$(call FRAMECRC, AVI, MJPEG) += fate-mjpeg-ticket3229 fate-mjpeg-ticket3229: CMD = framecrc -idct simple -fflags +bitexact -i $(TARGET_SAMPLES)/mjpeg/mjpeg_field_order.avi -an -FATE_VIDEO-$(call DEMDEC, MVI, MOTIONPIXELS) += fate-motionpixels +FATE_VIDEO-$(call FRAMECRC, MVI, MOTIONPIXELS, SCALE_FILTER) += fate-motionpixels fate-motionpixels: CMD = framecrc -i $(TARGET_SAMPLES)/motion-pixels/INTRO-partial.MVI -an -pix_fmt rgb24 -frames:v 111 -vf scale -FATE_VIDEO-$(call DEMDEC, MPEGTS, MPEG2VIDEO) += fate-mpeg2-field-enc fate-mpeg2-ticket186 +FATE_VIDEO-$(call FRAMECRC, MPEGTS, MPEG2VIDEO) += fate-mpeg2-field-enc fate-mpeg2-ticket186 fate-mpeg2-field-enc: CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/mpeg2_field_encoding.ts -an -frames:v 30 fate-mpeg2-ticket186: CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/t.mpg -an -FATE_VIDEO-$(call DEMDEC, MPEGVIDEO, MPEG2VIDEO) += fate-mpeg2-ticket6677 +FATE_VIDEO-$(call FRAMECRC, MPEGVIDEO, MPEG2VIDEO) += fate-mpeg2-ticket6677 fate-mpeg2-ticket6677: CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg2/sony-ct3.bs -FATE_VIDEO-$(call DEMDEC, MV, MVC1) += fate-mv-mvc1 +FATE_VIDEO-$(call FRAMECRC, MV, MVC1, SCALE_FILTER) += fate-mv-mvc1 fate-mv-mvc1: CMD = framecrc -i $(TARGET_SAMPLES)/mv/posture.mv -an -frames 25 -pix_fmt rgb555le -vf scale -FATE_VIDEO-$(call DEMDEC, MV, MVC2) += fate-mv-mvc2 +FATE_VIDEO-$(call FRAMECRC, MV, MVC2, SCALE_FILTER) += fate-mv-mvc2 fate-mv-mvc2: CMD = framecrc -i $(TARGET_SAMPLES)/mv/12345.mv -an -frames 30 -pix_fmt bgra -vf scale -FATE_VIDEO-$(call DEMDEC, MV, SGIRLE) += fate-mv-sgirle +FATE_VIDEO-$(call FRAMECRC, MV, SGIRLE) += fate-mv-sgirle fate-mv-sgirle: CMD = framecrc -i $(TARGET_SAMPLES)/mv/pet-rle.movie -an -FATE_VIDEO-$(call DEMDEC, MXG, MXPEG) += fate-mxpeg +FATE_VIDEO-$(call FRAMECRC, MXG, MXPEG) += fate-mxpeg fate-mxpeg: CMD = framecrc -idct simple -flags +bitexact -i $(TARGET_SAMPLES)/mxpeg/m1.mxg -an # FIXME dropped frames in this test because of coarse timebase @@ -276,43 +279,43 @@ fate-nuv-rtjpeg-fh: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/nuv/rtjpeg_ FATE_VIDEO-$(call DEMDEC, NUV, NUV) += $(FATE_NUV) fate-nuv: $(FATE_NUV) -FATE_VIDEO-$(call DEMDEC, PAF, PAF_VIDEO) += fate-paf-video +FATE_VIDEO-$(call FRAMECRC, PAF, PAF_VIDEO, SCALE_FILTER) += fate-paf-video fate-paf-video: CMD = framecrc -i $(TARGET_SAMPLES)/paf/hod1-partial.paf -pix_fmt rgb24 -an -vf scale -FATE_VIDEO-$(call DEMDEC, AVI, QPEG) += fate-qpeg +FATE_VIDEO-$(call FRAMECRC, AVI, QPEG, SCALE_FILTER) += fate-qpeg fate-qpeg: CMD = framecrc -i $(TARGET_SAMPLES)/qpeg/Clock.avi -an -pix_fmt rgb24 -vf scale -FATE_VIDEO-$(call DEMDEC, AVI, R210) += fate-r210 +FATE_VIDEO-$(call FRAMECRC, AVI, R210, SCALE_FILTER) += fate-r210 fate-r210: CMD = framecrc -i $(TARGET_SAMPLES)/r210/r210.avi -pix_fmt rgb48le -vf scale -FATE_VIDEO-$(call DEMDEC, RL2, RL2) += fate-rl2 +FATE_VIDEO-$(call FRAMECRC, RL2, RL2, SCALE_FILTER) += fate-rl2 fate-rl2: CMD = framecrc -i $(TARGET_SAMPLES)/rl2/Z4915300.RL2 -pix_fmt rgb24 -an -vf scale -FATE_VIDEO-$(call DEMDEC, ROQ, ROQ) += fate-roqvideo +FATE_VIDEO-$(call FRAMECRC, ROQ, ROQ) += fate-roqvideo fate-roqvideo: CMD = framecrc -i $(TARGET_SAMPLES)/idroq/idlogo.roq -an -FATE_VIDEO-$(call DEMDEC, SMUSH, SANM) += fate-sanm +FATE_VIDEO-$(call FRAMECRC, SMUSH, SANM, SCALE_FILTER) += fate-sanm fate-sanm: CMD = framecrc -i $(TARGET_SAMPLES)/smush/ronin_part.znm -an -pix_fmt rgb24 -vf scale -FATE_VIDEO-$(call DEMDEC, VMD, VMDVIDEO) += fate-sierra-vmd-video +FATE_VIDEO-$(call FRAMECRC, VMD, VMDVIDEO, SCALE_FILTER) += fate-sierra-vmd-video fate-sierra-vmd-video: CMD = framecrc -i $(TARGET_SAMPLES)/vmd/12.vmd -pix_fmt rgb24 -an -vf scale -FATE_VIDEO-$(call DEMDEC, SMACKER, SMACKER) += fate-smacker-video +FATE_VIDEO-$(call FRAMECRC, SMACKER, SMACKER, SCALE_FILTER) += fate-smacker-video fate-smacker-video: CMD = framecrc -i $(TARGET_SAMPLES)/smacker/wetlogo.smk -pix_fmt rgb24 -an -vf scale -FATE_VIDEO-$(call DEMDEC, MOV, SMC) += fate-smc +FATE_VIDEO-$(call FRAMECRC, MOV, SMC, SCALE_FILTER) += fate-smc fate-smc: CMD = framecrc -i $(TARGET_SAMPLES)/smc/cass_schi.qt -pix_fmt rgb24 -vf scale -FATE_VIDEO-$(call DEMDEC, AVI, SP5X) += fate-sp5x -fate-sp5x: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/sp5x/sp5x_problem.avi -vf scale -af aresample +FATE_VIDEO-$(call FRAMECRC, AVI, SP5X, ARESAMPLE_FILTER) += fate-sp5x +fate-sp5x: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/sp5x/sp5x_problem.avi -af aresample -FATE_VIDEO-$(call DEMDEC, THP, THP) += fate-thp +FATE_VIDEO-$(call FRAMECRC, THP, THP) += fate-thp fate-thp: CMD = framecrc -idct simple -i $(TARGET_SAMPLES)/thp/pikmin2-opening1-partial.thp -an -FATE_VIDEO-$(call DEMDEC, TIERTEXSEQ, TIERTEXSEQVIDEO) += fate-tiertex-seq +FATE_VIDEO-$(call FRAMECRC, TIERTEXSEQ, TIERTEXSEQVIDEO, SCALE_FILTER) += fate-tiertex-seq fate-tiertex-seq: CMD = framecrc -i $(TARGET_SAMPLES)/tiertex-seq/Gameover.seq -pix_fmt rgb24 -vf scale -FATE_VIDEO-$(call DEMDEC, TMV, TMV) += fate-tmv +FATE_VIDEO-$(call FRAMECRC, TMV, TMV, ARESAMPLE_FILTER SCALE_FILTER) += fate-tmv fate-tmv: CMD = framecrc -i $(TARGET_SAMPLES)/tmv/pop-partial.tmv -pix_fmt rgb24 -vf scale -af aresample FATE_TXD += fate-txd-16bpp @@ -321,53 +324,54 @@ fate-txd-16bpp: CMD = framecrc -i $(TARGET_SAMPLES)/txd/misc.txd -an FATE_TXD += fate-txd-odd fate-txd-odd: CMD = framecrc -i $(TARGET_SAMPLES)/txd/odd.txd -an -FATE_TXD += fate-txd-pal8 +FATE_TXD-$(call FRAMECRC, TXD, TXD, SCALE_FILTER) += fate-txd-pal8 fate-txd-pal8: CMD = framecrc -i $(TARGET_SAMPLES)/txd/outro.txd -pix_fmt rgb24 -an -vf scale -FATE_VIDEO-$(call DEMDEC, TXD, TXD) += $(FATE_TXD) -fate-txd: $(FATE_TXD) +FATE_TXD-$(call FRAMECRC, TXD, TXD) += $(FATE_TXD) +FATE_VIDEO += $(FATE_TXD-yes) +fate-txd: $(FATE_TXD-yes) -FATE_VIDEO-$(call DEMDEC, AVI, ULTI) += fate-ulti +FATE_VIDEO-$(call FRAMECRC, AVI, ULTI) += fate-ulti fate-ulti: CMD = framecrc -i $(TARGET_SAMPLES)/ulti/hit12w.avi -an -FATE_VIDEO-$(call DEMDEC, AVI, V210) += fate-v210 +FATE_VIDEO-$(call FRAMECRC, AVI, V210, SCALE_FILTER) += fate-v210 fate-v210: CMD = framecrc -i $(TARGET_SAMPLES)/v210/v210_720p-partial.avi -pix_fmt yuv422p16be -an -vf scale -FATE_VIDEO-$(call DEMDEC, MOV, V410) += fate-v410dec +FATE_VIDEO-$(call FRAMECRC, MOV, V410, SCALE_FILTER) += fate-v410dec fate-v410dec: CMD = framecrc -i $(TARGET_SAMPLES)/v410/lenav410.mov -pix_fmt yuv444p10le -vf scale -FATE_VIDEO-$(call ENCDEC, V410 PGMYUV, AVI IMAGE2) += fate-v410enc +FATE_VIDEO-$(call ENCDEC, V410 PGMYUV, AVI IMAGE2, SCALE_FILTER) += fate-v410enc fate-v410enc: $(VREF) fate-v410enc: CMD = md5 -f image2 -c:v pgmyuv -i $(TARGET_PATH)/tests/vsynth1/%02d.pgm -fflags +bitexact -c:v v410 -f avi -vf scale -FATE_VIDEO-$(call DEMDEC, SIFF, VB) += fate-vb +FATE_VIDEO-$(call FRAMECRC, SIFF, VB, SCALE_FILTER) += fate-vb fate-vb: CMD = framecrc -i $(TARGET_SAMPLES)/SIFF/INTRO_B.VB -t 3 -pix_fmt rgb24 -an -vf scale -FATE_VIDEO-$(call DEMDEC, AVI, VCR1) += fate-vcr1 +FATE_VIDEO-$(call FRAMECRC, AVI, VCR1) += fate-vcr1 fate-vcr1: CMD = framecrc -i $(TARGET_SAMPLES)/vcr1/VCR1test.avi -an -FATE_VIDEO-$(call DEMDEC, AVI, MPEG2VIDEO) += fate-vcr2 +FATE_VIDEO-$(call FRAMECRC, AVI, MPEG2VIDEO) += fate-vcr2 fate-vcr2: CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/vcr2/VCR2test.avi -an -FATE_VIDEO-$(call DEMDEC, AVI, XL) += fate-videoxl +FATE_VIDEO-$(call FRAMECRC, AVI, XL) += fate-videoxl fate-videoxl: CMD = framecrc -i $(TARGET_SAMPLES)/vixl/pig-vixl.avi -FATE_VIDEO-$(call DEMDEC, WSVQA, VQA) += fate-vqa-cc +FATE_VIDEO-$(call FRAMECRC, WSVQA, VQA, SCALE_FILTER) += fate-vqa-cc fate-vqa-cc: CMD = framecrc -i $(TARGET_SAMPLES)/vqa/cc-demo1-partial.vqa -pix_fmt rgb24 -an -vf scale -FATE_VIDEO-$(call DEMDEC, WC3, XAN_WC3) += fate-wc3movie-xan +FATE_VIDEO-$(call FRAMECRC, WC3, XAN_WC3, SCALE_FILTER) += fate-wc3movie-xan fate-wc3movie-xan: CMD = framecrc -i $(TARGET_SAMPLES)/wc3movie/SC_32-part.MVE -pix_fmt rgb24 -vf scale -FATE_VIDEO-$(call DEMDEC, AVI, WNV1) += fate-wnv1 +FATE_VIDEO-$(call FRAMECRC, AVI, WNV1) += fate-wnv1 fate-wnv1: CMD = framecrc -i $(TARGET_SAMPLES)/wnv1/wnv1-codec.avi -an -FATE_VIDEO-$(call DEMDEC, YOP, YOP) += fate-yop +FATE_VIDEO-$(call FRAMECRC, YOP, YOP, SCALE_FILTER) += fate-yop fate-yop: CMD = framecrc -i $(TARGET_SAMPLES)/yop/test1.yop -pix_fmt rgb24 -an -vf scale -FATE_VIDEO-$(call DEMDEC, AVI, XAN_WC4) += fate-xxan-wc4 +FATE_VIDEO-$(call FRAMECRC, AVI, XAN_WC4) += fate-xxan-wc4 fate-xxan-wc4: CMD = framecrc -i $(TARGET_SAMPLES)/wc4-xan/wc4trailer-partial.avi -an -FATE_VIDEO-$(call DEMDEC, WAV, SMVJPEG) += fate-smvjpeg +FATE_VIDEO-$(call FRAMECRC, WAV, SMVJPEG) += fate-smvjpeg fate-smvjpeg: CMD = framecrc -idct simple -flags +bitexact -i $(TARGET_SAMPLES)/smv/clock.smv -an FATE_VIDEO += $(FATE_VIDEO-yes) diff --git a/tests/fate/vpx.mak b/tests/fate/vpx.mak index 990d4e5ad..e18f3df38 100644 --- a/tests/fate/vpx.mak +++ b/tests/fate/vpx.mak @@ -4,10 +4,10 @@ fate-truemotion1-15: CMD = framecrc -i $(TARGET_SAMPLES)/duck/phant2-940.duk -pi FATE_TRUEMOTION1 += fate-truemotion1-24 fate-truemotion1-24: CMD = framecrc -i $(TARGET_SAMPLES)/duck/sonic3dblast_intro-partial.avi -pix_fmt rgb24 -an -vf scale -FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, TRUEMOTION1) += $(FATE_TRUEMOTION1) +FATE_SAMPLES_FFMPEG-$(call FRAMECRC, AVI, TRUEMOTION1, SCALE_FILTER) += $(FATE_TRUEMOTION1) fate-truemotion1: $(FATE_TRUEMOTION1) -FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, TRUEMOTION2) += fate-truemotion2 +FATE_SAMPLES_FFMPEG-$(call FRAMECRC, AVI, TRUEMOTION2) += fate-truemotion2 fate-truemotion2: CMD = framecrc -i $(TARGET_SAMPLES)/duck/tm20.avi FATE_TRUEMOTION2RT += fate-truemotion2rt-low @@ -19,104 +19,82 @@ fate-truemotion2rt-mid: CMD = framecrc -i $(TARGET_SAMPLES)/duck/tr20_mid.avi -a FATE_TRUEMOTION2RT += fate-truemotion2rt-high fate-truemotion2rt-high: CMD = framecrc -i $(TARGET_SAMPLES)/duck/tr20_high.avi -an -FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, TRUEMOTION2RT) += $(FATE_TRUEMOTION2RT) +FATE_SAMPLES_FFMPEG-$(call FRAMECRC, AVI, TRUEMOTION2RT) += $(FATE_TRUEMOTION2RT) fate-truemotion2rt: $(FATE_TRUEMOTION2RT) -FATE_VP3-$(call DEMDEC, MATROSKA, THEORA) += fate-theora-coeff-level64 +FATE_VP3-$(call FRAMECRC, MATROSKA, THEORA) += fate-theora-coeff-level64 fate-theora-coeff-level64: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/vp3/coeff_level64.mkv -FATE_VP3-$(call DEMDEC, OGG, THEORA) += fate-theora-offset +FATE_VP3-$(call FRAMECRC, OGG, THEORA) += fate-theora-offset fate-theora-offset: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/vp3/offset_test.ogv -FATE_VP3-$(call DEMDEC, AVI, VP3) += fate-vp31 +FATE_VP3-$(call FRAMECRC, AVI, VP3) += fate-vp31 fate-vp31: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/vp3/vp31.avi FATE_SAMPLES_AVCONV += $(FATE_VP3-yes) fate-vp3: $(FATE_VP3-yes) -FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, VP4) += fate-vp4 +FATE_SAMPLES_FFMPEG-$(call FRAMECRC, AVI, VP4) += fate-vp4 fate-vp4: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/vp4/KTkvw8dg1J8.avi -FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, VP5) += fate-vp5 +FATE_SAMPLES_FFMPEG-$(call FRAMECRC, AVI, VP5) += fate-vp5 fate-vp5: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/vp5/potter512-400-partial.avi -an -FATE_VP6-$(call DEMDEC, EA, VP6) += fate-vp60 +FATE_VP6-$(call FRAMECRC, EA, VP6) += fate-vp60 fate-vp60: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/ea-vp6/g36.vp6 -FATE_VP6-$(call DEMDEC, EA, VP6) += fate-vp61 +FATE_VP6-$(call FRAMECRC, EA, VP6) += fate-vp61 fate-vp61: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/ea-vp6/MovieSkirmishGondor.vp6 -t 4 -FATE_VP6-$(call DEMDEC, MOV, VP6A) += fate-vp6a +FATE_VP6-$(call FRAMECRC, MOV, VP6A) += fate-vp6a fate-vp6a: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/flash-vp6/300x180-Scr-f8-056alpha.mov -FATE_VP6-$(call DEMDEC, MOV, VP6A) += fate-vp6a-skip_alpha +FATE_VP6-$(call FRAMECRC, MOV, VP6A) += fate-vp6a-skip_alpha fate-vp6a-skip_alpha: CMD = framecrc -flags +bitexact -skip_alpha 1 -i $(TARGET_SAMPLES)/flash-vp6/300x180-Scr-f8-056alpha.mov -FATE_VP6-$(call DEMDEC, FLV, VP6F) += fate-vp6f +FATE_VP6-$(call FRAMECRC, FLV, VP6F) += fate-vp6f fate-vp6f: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/flash-vp6/clip1024.flv -FATE_VP8-$(CONFIG_WEBM_DASH_MANIFEST_DEMUXER) += fate-webm-dash-manifest -fate-webm-dash-manifest: CMD = run $(FFMPEG) -nostdin -f webm_dash_manifest -i $(TARGET_SAMPLES)/vp8/dash_video1.webm -f webm_dash_manifest -i $(TARGET_SAMPLES)/vp8/dash_video2.webm -f webm_dash_manifest -i $(TARGET_SAMPLES)/vp8/dash_audio1.webm -f webm_dash_manifest -i $(TARGET_SAMPLES)/vp8/dash_audio2.webm -c copy -map 0 -map 1 -map 2 -map 3 -f webm_dash_manifest -adaptation_sets "id=0,streams=0,1 id=1,streams=2,3" - - -FATE_VP8-$(CONFIG_WEBM_DASH_MANIFEST_DEMUXER) += fate-webm-dash-manifest-unaligned-video-streams -fate-webm-dash-manifest-unaligned-video-streams: CMD = run $(FFMPEG) -nostdin -f webm_dash_manifest -i $(TARGET_SAMPLES)/vp8/dash_video1.webm -f webm_dash_manifest -i $(TARGET_SAMPLES)/vp8/dash_video3.webm -c copy -map 0 -map 1 -f webm_dash_manifest -adaptation_sets "id=0,streams=0,1" - - -FATE_VP8-$(CONFIG_WEBM_DASH_MANIFEST_DEMUXER) += fate-webm-dash-manifest-unaligned-audio-streams -fate-webm-dash-manifest-unaligned-audio-streams: CMD = run $(FFMPEG) -nostdin -f webm_dash_manifest -i $(TARGET_SAMPLES)/vp8/dash_audio1.webm -f webm_dash_manifest -i $(TARGET_SAMPLES)/vp8/dash_audio3.webm -c copy -map 0 -map 1 -f webm_dash_manifest -adaptation_sets "id=0,streams=0,1" - - -FATE_VP8-$(CONFIG_WEBM_DASH_MANIFEST_DEMUXER) += fate-webm-dash-manifest-representations -fate-webm-dash-manifest-representations: CMD = run $(FFMPEG) -nostdin -f webm_dash_manifest -i $(TARGET_SAMPLES)/vp8/dash_video1.webm -f webm_dash_manifest -i $(TARGET_SAMPLES)/vp8/dash_video4.webm -c copy -map 0 -map 1 -f webm_dash_manifest -adaptation_sets "id=0,streams=0,1" - - -FATE_VP8-$(CONFIG_WEBM_DASH_MANIFEST_DEMUXER) += fate-webm-dash-manifest-live -fate-webm-dash-manifest-live: CMD = run $(FFMPEG) -nostdin -f webm_dash_manifest -live 1 -i $(TARGET_SAMPLES)/vp8/dash_live_video_360.hdr -f webm_dash_manifest -live 1 -i $(TARGET_SAMPLES)/vp8/dash_live_audio_171.hdr -c copy -map 0 -map 1 -fflags +bitexact -f webm_dash_manifest -live 1 -adaptation_sets "id=0,streams=0 id=1,streams=1" -chunk_start_index 1 -chunk_duration_ms 5000 -time_shift_buffer_depth 7200 -minimum_update_period 60 - - -FATE_VP8-$(CONFIG_WEBM_DASH_MANIFEST_DEMUXER) += fate-webm-dash-manifest-live-bandwidth -fate-webm-dash-manifest-live-bandwidth: CMD = run $(FFMPEG) -nostdin -f webm_dash_manifest -live 1 -bandwidth 100 -i $(TARGET_SAMPLES)/vp8/dash_live_video_360.hdr -f webm_dash_manifest -live 1 -bandwidth 200 -i $(TARGET_SAMPLES)/vp8/dash_live_audio_171.hdr -c copy -map 0 -map 1 -fflags +bitexact -f webm_dash_manifest -live 1 -adaptation_sets "id=0,streams=0 id=1,streams=1" -chunk_start_index 1 -chunk_duration_ms 5000 -time_shift_buffer_depth 7200 -minimum_update_period 60 - - -FATE_VP8-$(call DEMDEC, MATROSKA, VP8) += fate-vp8-2451 +FATE_VP8-$(call FRAMECRC, MATROSKA, VP8) += fate-vp8-2451 fate-vp8-2451: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/vp8/RRSF49-short.webm -vsync cfr -an FATE_SAMPLES_AVCONV += $(FATE_VP6-yes) fate-vp6: $(FATE_VP6-yes) -FATE_SAMPLES_AVCONV-$(call DEMDEC, AVI, VP7) += fate-vp7 +FATE_SAMPLES_FFMPEG-$(call FRAMECRC, AVI, VP7) += fate-vp7 fate-vp7: CMD = framecrc -flags +bitexact -i $(TARGET_SAMPLES)/vp7/potter-40.vp7 -frames 30 -an VP8_SUITE = 001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 define FATE_VP8_SUITE -FATE_VP8-$(call DEMDEC, IVF, VP8) += fate-vp8-test-vector$(2)-$(1) -fate-vp8-test-vector$(2)-$(1): CMD = framemd5 $(3) -i $(TARGET_SAMPLES)/vp8-test-vectors-r1/vp80-00-comprehensive-$(1).ivf -fate-vp8-test-vector$(2)-$(1): REF = $(SRC_PATH)/tests/ref/fate/vp8-test-vector-$(1) +FATE_VP8-$(call FRAMEMD5, IVF, VP8) += fate-vp8-test-vector-$(1) +fate-vp8-test-vector-$(1): CMD = framemd5 -i $(TARGET_SAMPLES)/vp8-test-vectors-r1/vp80-00-comprehensive-$(1).ivf +fate-vp8-test-vector-$(1): REF = $(SRC_PATH)/tests/ref/fate/vp8-test-vector-$(1) endef -define FATE_VP8_FULL -$(foreach N,$(VP8_SUITE),$(eval $(call FATE_VP8_SUITE,$(N),$(1),$(2)))) +$(foreach N,$(VP8_SUITE),$(eval $(call FATE_VP8_SUITE,$(N)))) # FIXME this file contains two frames with identical timestamps, # so ffmpeg drops one of them -FATE_VP8-$(call DEMDEC, IVF, VP8) += fate-vp8-sign-bias$(1) -fate-vp8-sign-bias$(1): CMD = framemd5 $(2) -i $(TARGET_SAMPLES)/vp8/sintel-signbias.ivf -fate-vp8-sign-bias$(1): REF = $(SRC_PATH)/tests/ref/fate/vp8-sign-bias +FATE_VP8-$(call FRAMEMD5, IVF, VP8) += fate-vp8-sign-bias +fate-vp8-sign-bias: CMD = framemd5 -i $(TARGET_SAMPLES)/vp8/sintel-signbias.ivf +fate-vp8-sign-bias: REF = $(SRC_PATH)/tests/ref/fate/vp8-sign-bias -FATE_VP8-$(call DEMDEC, MATROSKA, VP8) += fate-vp8-size-change$(1) -fate-vp8-size-change$(1): CMD = framemd5 $(2) -flags +bitexact -i $(TARGET_SAMPLES)/vp8/frame_size_change.webm -frames:v 30 -sws_flags bitexact+bilinear -fate-vp8-size-change$(1): REF = $(SRC_PATH)/tests/ref/fate/vp8-size-change -endef - -$(eval $(call FATE_VP8_FULL)) +FATE_VP8-$(call FRAMEMD5, MATROSKA, VP8, SCALE_FILTER) += fate-vp8-size-change +fate-vp8-size-change: CMD = framemd5 -flags +bitexact -i $(TARGET_SAMPLES)/vp8/frame_size_change.webm -frames:v 30 -sws_flags bitexact+bilinear +fate-vp8-size-change: REF = $(SRC_PATH)/tests/ref/fate/vp8-size-change FATE_SAMPLES_AVCONV += $(FATE_VP8-yes) fate-vp8: $(FATE_VP8-yes) define FATE_VP9_SUITE -FATE_VP9-$(CONFIG_MATROSKA_DEMUXER) += fate-vp9$(2)-$(1) -fate-vp9$(2)-$(1): CMD = framemd5 $(3) -i $(TARGET_SAMPLES)/vp9-test-vectors/vp90-2-$(1).webm -fate-vp9$(2)-$(1): REF = $(SRC_PATH)/tests/ref/fate/vp9-$(1) +FATE_VP9-$(call FRAMEMD5, MATROSKA, VP9) += fate-vp9-$(1) +fate-vp9-$(1): CMD = framemd5 -i $(TARGET_SAMPLES)/vp9-test-vectors/vp90-2-$(1).webm +fate-vp9-$(1): REF = $(SRC_PATH)/tests/ref/fate/vp9-$(1) endef define FATE_VP9_PROFILE_SUITE -FATE_VP9-$(CONFIG_MATROSKA_DEMUXER) += fate-vp9p$(2)-$(1) +FATE_VP9-$(call FRAMEMD5, MATROSKA, VP9, $(4)) += fate-vp9p$(2)-$(1) fate-vp9p$(2)-$(1): CMD = framemd5 -i $(TARGET_SAMPLES)/vp9-test-vectors/vp9$(2)-2-$(1).webm $(3) fate-vp9p$(2)-$(1): REF = $(SRC_PATH)/tests/ref/fate/vp9p$(2)-$(1) endef @@ -131,15 +109,14 @@ VP9_SIZE_B = 196 198 200 202 208 210 224 226 VP9_CHROMA_SUBSAMPLE = 422 440 444 VP9_HIGH_BITDEPTH = 10 12 -define FATE_VP9_FULL $(foreach Q,$(VP9_Q),$(eval $(call FATE_VP9_SUITE,00-quantizer-$(Q)))) $(foreach SHARP,$(VP9_SHARP),$(eval $(call FATE_VP9_SUITE,01-sharpness-$(SHARP)))) $(foreach W,$(VP9_SIZE_A),$(eval $(foreach H,$(VP9_SIZE_A),$(eval $(call FATE_VP9_SUITE,02-size-$(W)x$(H)))))) $(foreach W,$(VP9_SIZE_B),$(eval $(foreach H,$(VP9_SIZE_B),$(eval $(call FATE_VP9_SUITE,03-size-$(W)x$(H)))))) $(eval $(call FATE_VP9_SUITE,03-deltaq)) -$(foreach SS,$(VP9_CHROMA_SUBSAMPLE),$(eval $(call FATE_VP9_PROFILE_SUITE,04-yuv$(SS),1,))) -$(foreach BD,$(VP9_HIGH_BITDEPTH),$(eval $(call FATE_VP9_PROFILE_SUITE,20-$(BD)bit-yuv420,2,-pix_fmt yuv420p$(BD)le -vf scale))) -$(foreach BD,$(VP9_HIGH_BITDEPTH),$(eval $(foreach SS,$(VP9_CHROMA_SUBSAMPLE),$(eval $(call FATE_VP9_PROFILE_SUITE,20-$(BD)bit-yuv$(SS),3,-pix_fmt yuv$(SS)p$(BD)le -vf scale))))) +$(foreach SS,$(VP9_CHROMA_SUBSAMPLE),$(eval $(call FATE_VP9_PROFILE_SUITE,04-yuv$(SS),1,,))) +$(foreach BD,$(VP9_HIGH_BITDEPTH),$(eval $(call FATE_VP9_PROFILE_SUITE,20-$(BD)bit-yuv420,2,-pix_fmt yuv420p$(BD)le -vf scale, SCALE_FILTER))) +$(foreach BD,$(VP9_HIGH_BITDEPTH),$(eval $(foreach SS,$(VP9_CHROMA_SUBSAMPLE),$(eval $(call FATE_VP9_PROFILE_SUITE,20-$(BD)bit-yuv$(SS),3,-pix_fmt yuv$(SS)p$(BD)le -vf scale, SCALE_FILTER))))) $(eval $(call FATE_VP9_SUITE,06-bilinear)) $(eval $(call FATE_VP9_SUITE,09-lf_deltas)) $(eval $(call FATE_VP9_SUITE,10-show-existing-frame)) @@ -153,17 +130,15 @@ $(eval $(call FATE_VP9_SUITE,segmentation-sf-akiyo)) $(eval $(call FATE_VP9_SUITE,tiling-pedestrian)) $(eval $(call FATE_VP9_SUITE,trac3849)) $(eval $(call FATE_VP9_SUITE,trac4359)) -endef -$(eval $(call FATE_VP9_FULL)) -FATE_VP9-$(CONFIG_IVF_DEMUXER) += fate-vp9-05-resize +FATE_VP9-$(call FRAMEMD5, IVF, VP9, SCALE_FILTER) += fate-vp9-05-resize fate-vp9-05-resize: CMD = framemd5 -i $(TARGET_SAMPLES)/vp9-test-vectors/vp90-2-05-resize.ivf -s 352x288 -sws_flags bitexact+bilinear fate-vp9-05-resize: REF = $(SRC_PATH)/tests/ref/fate/vp9-05-resize fate-vp9-encparams: CMD = venc_data $(TARGET_SAMPLES)/vp9-test-vectors/vp90-2-segmentation-aq-akiyo.webm 0 5 -FATE_SAMPLES_DUMP_DATA += fate-vp9-encparams +FATE_SAMPLES_DUMP_DATA-$(call DEMDEC, MATROSKA, VP9) += fate-vp9-encparams -FATE_VP9-$(CONFIG_MATROSKA_DEMUXER) += fate-vp9-encparams +FATE_VP9-$(call DEMDEC, MATROSKA, VP9) += fate-vp9-encparams -FATE_SAMPLES_AVCONV-$(CONFIG_VP9_DECODER) += $(FATE_VP9-yes) +FATE_SAMPLES_FFMPEG += $(FATE_VP9-yes) fate-vp9: $(FATE_VP9-yes) diff --git a/tests/fate/wavpack.mak b/tests/fate/wavpack.mak index 8a15e536c..c684d93f9 100644 --- a/tests/fate/wavpack.mak +++ b/tests/fate/wavpack.mak @@ -1,102 +1,111 @@ -FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += $(FATE_WAVPACK) - # lossless -FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-lossless-8bit -fate-wavpack-lossless-8bit: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/lossless/8bit-partial.wv -f s8 -af aresample +FATE_WAVPACK_S8 += fate-wavpack-lossless-8bit +fate-wavpack-lossless-8bit: CMD = md5pipe -i $(TARGET_SAMPLES)/wavpack/lossless/8bit-partial.wv -f s8 -af aresample -FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-lossless-12bit -fate-wavpack-lossless-12bit: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/lossless/12bit-partial.wv -f s16le -af aresample +FATE_WAVPACK_S16 += fate-wavpack-lossless-12bit +fate-wavpack-lossless-12bit: CMD = md5pipe -i $(TARGET_SAMPLES)/wavpack/lossless/12bit-partial.wv -f s16le -af aresample -FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-lossless-16bit -fate-wavpack-lossless-16bit: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/lossless/16bit-partial.wv -f s16le -af aresample +FATE_WAVPACK_S16 += fate-wavpack-lossless-16bit +fate-wavpack-lossless-16bit: CMD = md5pipe -i $(TARGET_SAMPLES)/wavpack/lossless/16bit-partial.wv -f s16le -af aresample -FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-lossless-24bit -fate-wavpack-lossless-24bit: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/lossless/24bit-partial.wv -f s24le -af aresample +FATE_WAVPACK_S24 += fate-wavpack-lossless-24bit +fate-wavpack-lossless-24bit: CMD = md5pipe -i $(TARGET_SAMPLES)/wavpack/lossless/24bit-partial.wv -f s24le -af aresample -FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-lossless-32bit -fate-wavpack-lossless-32bit: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/lossless/32bit_int-partial.wv -f s32le -af aresample +FATE_WAVPACK_S32 += fate-wavpack-lossless-32bit +fate-wavpack-lossless-32bit: CMD = md5pipe -i $(TARGET_SAMPLES)/wavpack/lossless/32bit_int-partial.wv -f s32le -af aresample -FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-lossless-float -fate-wavpack-lossless-float: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/lossless/32bit_float-partial.wv -f f32le -af aresample +FATE_WAVPACK_F32 += fate-wavpack-lossless-float +fate-wavpack-lossless-float: CMD = md5pipe -i $(TARGET_SAMPLES)/wavpack/lossless/32bit_float-partial.wv -f f32le -af aresample # lossy -FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-lossy-8bit -fate-wavpack-lossy-8bit: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/lossy/4.0_8-bit.wv -f s8 -af aresample +FATE_WAVPACK_S8 += fate-wavpack-lossy-8bit +fate-wavpack-lossy-8bit: CMD = md5pipe -i $(TARGET_SAMPLES)/wavpack/lossy/4.0_8-bit.wv -f s8 -af aresample -FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-lossy-16bit -fate-wavpack-lossy-16bit: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/lossy/4.0_16-bit.wv -f s16le -af aresample +FATE_WAVPACK_S16 += fate-wavpack-lossy-16bit +fate-wavpack-lossy-16bit: CMD = md5pipe -i $(TARGET_SAMPLES)/wavpack/lossy/4.0_16-bit.wv -f s16le -af aresample -FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-lossy-24bit -fate-wavpack-lossy-24bit: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/lossy/4.0_24-bit.wv -f s24le -af aresample +FATE_WAVPACK_S24 += fate-wavpack-lossy-24bit +fate-wavpack-lossy-24bit: CMD = md5pipe -i $(TARGET_SAMPLES)/wavpack/lossy/4.0_24-bit.wv -f s24le -af aresample -FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-lossy-32bit -fate-wavpack-lossy-32bit: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/lossy/4.0_32-bit_int.wv -f s32le -af aresample +FATE_WAVPACK_S32 += fate-wavpack-lossy-32bit +fate-wavpack-lossy-32bit: CMD = md5pipe -i $(TARGET_SAMPLES)/wavpack/lossy/4.0_32-bit_int.wv -f s32le -af aresample -FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-lossy-float -fate-wavpack-lossy-float: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/lossy/2.0_32-bit_float.wv -f f32le -af aresample +FATE_WAVPACK_F32 += fate-wavpack-lossy-float +fate-wavpack-lossy-float: CMD = md5pipe -i $(TARGET_SAMPLES)/wavpack/lossy/2.0_32-bit_float.wv -f f32le -af aresample # channel configurations -FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-channels-monofloat -fate-wavpack-channels-monofloat: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/num_channels/mono_float-partial.wv -f f32le -af aresample +FATE_WAVPACK_F32 += fate-wavpack-channels-monofloat +fate-wavpack-channels-monofloat: CMD = md5pipe -i $(TARGET_SAMPLES)/wavpack/num_channels/mono_float-partial.wv -f f32le -af aresample -FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-channels-monoint -fate-wavpack-channels-monoint: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/num_channels/mono_16bit_int.wv -f s16le -af aresample +FATE_WAVPACK_S16 += fate-wavpack-channels-monoint +fate-wavpack-channels-monoint: CMD = md5pipe -i $(TARGET_SAMPLES)/wavpack/num_channels/mono_16bit_int.wv -f s16le -af aresample -FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-channels-4.0 -fate-wavpack-channels-4.0: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/num_channels/edward_4.0_16bit-partial.wv -f s16le -af aresample +FATE_WAVPACK_S16 += fate-wavpack-channels-4.0 +fate-wavpack-channels-4.0: CMD = md5pipe -i $(TARGET_SAMPLES)/wavpack/num_channels/edward_4.0_16bit-partial.wv -f s16le -af aresample -FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-channels-5.1 -fate-wavpack-channels-5.1: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/num_channels/panslab_sample_5.1_16bit-partial.wv -f s16le -af aresample +FATE_WAVPACK_S16 += fate-wavpack-channels-5.1 +fate-wavpack-channels-5.1: CMD = md5pipe -i $(TARGET_SAMPLES)/wavpack/num_channels/panslab_sample_5.1_16bit-partial.wv -f s16le -af aresample -FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-channels-6.1 -fate-wavpack-channels-6.1: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/num_channels/eva_2.22_6.1_16bit-partial.wv -f s16le -af aresample +FATE_WAVPACK_S16 += fate-wavpack-channels-6.1 +fate-wavpack-channels-6.1: CMD = md5pipe -i $(TARGET_SAMPLES)/wavpack/num_channels/eva_2.22_6.1_16bit-partial.wv -f s16le -af aresample -FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-channels-7.1 -fate-wavpack-channels-7.1: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/num_channels/panslab_sample_7.1_16bit-partial.wv -f s16le -af aresample +FATE_WAVPACK_S16 += fate-wavpack-channels-7.1 +fate-wavpack-channels-7.1: CMD = md5pipe -i $(TARGET_SAMPLES)/wavpack/num_channels/panslab_sample_7.1_16bit-partial.wv -f s16le -af aresample # speed modes -FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-speed-default -fate-wavpack-speed-default: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/speed_modes/default-partial.wv -f s16le -af aresample +FATE_WAVPACK_S16 += fate-wavpack-speed-default +fate-wavpack-speed-default: CMD = md5pipe -i $(TARGET_SAMPLES)/wavpack/speed_modes/default-partial.wv -f s16le -af aresample -FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-speed-fast -fate-wavpack-speed-fast: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/speed_modes/fast-partial.wv -f s16le -af aresample +FATE_WAVPACK_S16 += fate-wavpack-speed-fast +fate-wavpack-speed-fast: CMD = md5pipe -i $(TARGET_SAMPLES)/wavpack/speed_modes/fast-partial.wv -f s16le -af aresample -FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-speed-high -fate-wavpack-speed-high: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/speed_modes/high-partial.wv -f s16le -af aresample +FATE_WAVPACK_S16 += fate-wavpack-speed-high +fate-wavpack-speed-high: CMD = md5pipe -i $(TARGET_SAMPLES)/wavpack/speed_modes/high-partial.wv -f s16le -af aresample -FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-speed-vhigh -fate-wavpack-speed-vhigh: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/speed_modes/vhigh-partial.wv -f s16le -af aresample +FATE_WAVPACK_S16 += fate-wavpack-speed-vhigh +fate-wavpack-speed-vhigh: CMD = md5pipe -i $(TARGET_SAMPLES)/wavpack/speed_modes/vhigh-partial.wv -f s16le -af aresample # special cases -FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-clipping -fate-wavpack-clipping: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/special/clipping.wv -f s16le -af aresample +FATE_WAVPACK_S16 += fate-wavpack-clipping +fate-wavpack-clipping: CMD = md5pipe -i $(TARGET_SAMPLES)/wavpack/special/clipping.wv -f s16le -af aresample -FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-cuesheet -fate-wavpack-cuesheet: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/special/cue_sheet.wv -f s16le -af aresample +FATE_WAVPACK_S16 += fate-wavpack-cuesheet +fate-wavpack-cuesheet: CMD = md5pipe -i $(TARGET_SAMPLES)/wavpack/special/cue_sheet.wv -f s16le -af aresample -FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-falsestereo -fate-wavpack-falsestereo: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/special/false_stereo.wv -f s16le -af aresample +# The sample file has APE tags containing a cuesheet. +FATE_WAVPACK_FFPROBE-$(call ALLYES, WV_DEMUXER FILE_PROTOCOL) += fate-wavpack-cuesheet-tags +fate-wavpack-cuesheet-tags: CMD = probetags $(TARGET_SAMPLES)/wavpack/special/cue_sheet.wv -FATE_WAVPACK-$(call DEMDEC, WV, WAVPACK) += fate-wavpack-zerolsbs -fate-wavpack-zerolsbs: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/special/zero_lsbs.wv -f s16le -af aresample +FATE_WAVPACK_S16 += fate-wavpack-falsestereo +fate-wavpack-falsestereo: CMD = md5pipe -i $(TARGET_SAMPLES)/wavpack/special/false_stereo.wv -f s16le -af aresample -FATE_WAVPACK-$(call DEMDEC, MATROSKA, WAVPACK) += fate-wavpack-matroskamode -fate-wavpack-matroskamode: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/special/matroska_mode.mka -f s16le -af aresample +FATE_WAVPACK_S16 += fate-wavpack-zerolsbs +fate-wavpack-zerolsbs: CMD = md5pipe -i $(TARGET_SAMPLES)/wavpack/special/zero_lsbs.wv -f s16le -af aresample -FATE_WAVPACK-$(call DEMMUX, WV, MATROSKA) += fate-wavpack-matroska_mux-mono +FATE_WAVPACK-$(call FILTERDEMDECENCMUX, ARESAMPLE, MATROSKA, WAVPACK, PCM_S16LE, PCM_S16LE, MD5_PROTOCOL) += fate-wavpack-matroskamode +fate-wavpack-matroskamode: CMD = md5pipe -i $(TARGET_SAMPLES)/wavpack/special/matroska_mode.mka -f s16le -af aresample + +FATE_WAVPACK-$(call DEMMUX, WV, MATROSKA, MD5_PROTOCOL) += fate-wavpack-matroska_mux-mono fate-wavpack-matroska_mux-mono: CMD = md5pipe -i $(TARGET_SAMPLES)/wavpack/num_channels/mono_16bit_int.wv -c copy -fflags +bitexact -f matroska fate-wavpack-matroska_mux-mono: CMP = oneline fate-wavpack-matroska_mux-mono: REF = 5863eb94f7583aa9c5fded17474f2e7c -FATE_WAVPACK-$(call DEMMUX, WV, MATROSKA) += fate-wavpack-matroska_mux-61 +FATE_WAVPACK-$(call DEMMUX, WV, MATROSKA, MD5_PROTOCOL) += fate-wavpack-matroska_mux-61 fate-wavpack-matroska_mux-61: CMD = md5pipe -i $(TARGET_SAMPLES)/wavpack/num_channels/eva_2.22_6.1_16bit-partial.wv -c copy -fflags +bitexact -f matroska fate-wavpack-matroska_mux-61: CMP = oneline fate-wavpack-matroska_mux-61: REF = 2bbb393d060fa841f1172028f2c69b3a -FATE_SAMPLES_AVCONV += $(FATE_WAVPACK-yes) -fate-wavpack: $(FATE_WAVPACK-yes) +FATE_WAVPACK-$(call FILTERDEMDECENCMUX, ARESAMPLE, WV, WAVPACK, PCM_S8, PCM_S8, MD5_PROTOCOL) += $(FATE_WAVPACK_S8) +FATE_WAVPACK-$(call FILTERDEMDECENCMUX, ARESAMPLE, WV, WAVPACK, PCM_S16LE, PCM_S16LE, MD5_PROTOCOL) += $(FATE_WAVPACK_S16) +FATE_WAVPACK-$(call FILTERDEMDECENCMUX, ARESAMPLE, WV, WAVPACK, PCM_S24LE, PCM_S24LE, MD5_PROTOCOL) += $(FATE_WAVPACK_S24) +FATE_WAVPACK-$(call FILTERDEMDECENCMUX, ARESAMPLE, WV, WAVPACK, PCM_S32LE, PCM_S32LE, MD5_PROTOCOL) += $(FATE_WAVPACK_S32) +FATE_WAVPACK-$(call FILTERDEMDECENCMUX, ARESAMPLE, WV, WAVPACK, PCM_F32LE, PCM_F32LE, MD5_PROTOCOL) += $(FATE_WAVPACK_F32) + +FATE_SAMPLES_FFPROBE += $(FATE_WAVPACK_FFPROBE-yes) +FATE_SAMPLES_FFMPEG += $(FATE_WAVPACK-yes) +fate-wavpack: $(FATE_WAVPACK-yes) $(FATE_WAVPACK_FFPROBE-yes) diff --git a/tests/fate/webm-dash-manifest.mak b/tests/fate/webm-dash-manifest.mak new file mode 100644 index 000000000..0000664bb --- /dev/null +++ b/tests/fate/webm-dash-manifest.mak @@ -0,0 +1,21 @@ +FATE_WEBM_DASH_MANIFEST += fate-webm-dash-manifest +fate-webm-dash-manifest: CMD = run $(FFMPEG) -nostdin -f webm_dash_manifest -i $(TARGET_SAMPLES)/vp8/dash_video1.webm -f webm_dash_manifest -i $(TARGET_SAMPLES)/vp8/dash_video2.webm -f webm_dash_manifest -i $(TARGET_SAMPLES)/vp8/dash_audio1.webm -f webm_dash_manifest -i $(TARGET_SAMPLES)/vp8/dash_audio2.webm -c copy -map 0 -map 1 -map 2 -map 3 -f webm_dash_manifest -adaptation_sets "id=0,streams=0,1 id=1,streams=2,3" - + +FATE_WEBM_DASH_MANIFEST += fate-webm-dash-manifest-unaligned-video-streams +fate-webm-dash-manifest-unaligned-video-streams: CMD = run $(FFMPEG) -nostdin -f webm_dash_manifest -i $(TARGET_SAMPLES)/vp8/dash_video1.webm -f webm_dash_manifest -i $(TARGET_SAMPLES)/vp8/dash_video3.webm -c copy -map 0 -map 1 -f webm_dash_manifest -adaptation_sets "id=0,streams=0,1" - + +FATE_WEBM_DASH_MANIFEST += fate-webm-dash-manifest-unaligned-audio-streams +fate-webm-dash-manifest-unaligned-audio-streams: CMD = run $(FFMPEG) -nostdin -f webm_dash_manifest -i $(TARGET_SAMPLES)/vp8/dash_audio1.webm -f webm_dash_manifest -i $(TARGET_SAMPLES)/vp8/dash_audio3.webm -c copy -map 0 -map 1 -f webm_dash_manifest -adaptation_sets "id=0,streams=0,1" - + +FATE_WEBM_DASH_MANIFEST += fate-webm-dash-manifest-representations +fate-webm-dash-manifest-representations: CMD = run $(FFMPEG) -nostdin -f webm_dash_manifest -i $(TARGET_SAMPLES)/vp8/dash_video1.webm -f webm_dash_manifest -i $(TARGET_SAMPLES)/vp8/dash_video4.webm -c copy -map 0 -map 1 -f webm_dash_manifest -adaptation_sets "id=0,streams=0,1" - + +FATE_WEBM_DASH_MANIFEST += fate-webm-dash-manifest-live +fate-webm-dash-manifest-live: CMD = run $(FFMPEG) -nostdin -f webm_dash_manifest -live 1 -i $(TARGET_SAMPLES)/vp8/dash_live_video_360.hdr -f webm_dash_manifest -live 1 -i $(TARGET_SAMPLES)/vp8/dash_live_audio_171.hdr -c copy -map 0 -map 1 -fflags +bitexact -f webm_dash_manifest -live 1 -adaptation_sets "id=0,streams=0 id=1,streams=1" -chunk_start_index 1 -chunk_duration_ms 5000 -time_shift_buffer_depth 7200 -minimum_update_period 60 - + +FATE_WEBM_DASH_MANIFEST += fate-webm-dash-manifest-live-bandwidth +fate-webm-dash-manifest-live-bandwidth: CMD = run $(FFMPEG) -nostdin -f webm_dash_manifest -live 1 -bandwidth 100 -i $(TARGET_SAMPLES)/vp8/dash_live_video_360.hdr -f webm_dash_manifest -live 1 -bandwidth 200 -i $(TARGET_SAMPLES)/vp8/dash_live_audio_171.hdr -c copy -map 0 -map 1 -fflags +bitexact -f webm_dash_manifest -live 1 -adaptation_sets "id=0,streams=0 id=1,streams=1" -chunk_start_index 1 -chunk_duration_ms 5000 -time_shift_buffer_depth 7200 -minimum_update_period 60 - + +FATE_WEBM_DASH_MANIFEST-$(call DEMMUX, WEBM_DASH_MANIFEST, WEBM_DASH_MANIFEST, PIPE_PROTOCOL) += $(FATE_WEBM_DASH_MANIFEST) +fate-webm-dash-manifests: $(FATE_WEBM_DASH_MANIFEST-yes) +FATE_SAMPLES_FFMPEG += $(FATE_WEBM_DASH_MANIFEST-yes) diff --git a/tests/filtergraphs/mov-channel-description b/tests/filtergraphs/mov-channel-description new file mode 100644 index 000000000..df89347a5 --- /dev/null +++ b/tests/filtergraphs/mov-channel-description @@ -0,0 +1,8 @@ +[0:a:0]pan=FL|c0=c0[outFL]; +[0:a:0]pan=FR|c0=c1[outFR]; +[0:a:0]pan=FC|c0=c2[outFC]; +[0:a:0]pan=LFE|c0=c3[outLFE]; +[0:a:0]pan=BL|c0=c4[outBL]; +[0:a:0]pan=BR|c0=c5[outBR]; +[0:a:0]pan=DL|c0=c6[outDL]; +[0:a:0]pan=DR|c0=c7[outDR] diff --git a/tests/ref/fate/8bps b/tests/ref/fate/8bps index dab2b908d..f736bb0b9 100644 --- a/tests/ref/fate/8bps +++ b/tests/ref/fate/8bps @@ -7,7 +7,6 @@ #media_type 1: audio #codec_id 1: pcm_s16le #sample_rate 1: 22050 -#channel_layout 1: 4 #channel_layout_name 1: mono 0, 0, 0, 1, 259200, 0x7e91df07 1, 0, 0, 1024, 2048, 0x3d042426 diff --git a/tests/ref/fate/aa-demux b/tests/ref/fate/aa-demux index 89350b880..9534c82ee 100644 --- a/tests/ref/fate/aa-demux +++ b/tests/ref/fate/aa-demux @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: sipr #sample_rate 0: 8500 -#channel_layout 0: 4 #channel_layout_name 0: mono 0, 0, 0, 18000, 19, 0x36e10529 0, 18000, 18000, 18000, 19, 0x70810a69 diff --git a/tests/ref/fate/aac-autobsf-adtstoasc b/tests/ref/fate/aac-autobsf-adtstoasc index 2a2823ef9..57bfcae18 100644 --- a/tests/ref/fate/aac-autobsf-adtstoasc +++ b/tests/ref/fate/aac-autobsf-adtstoasc @@ -1,11 +1,10 @@ -224607440d242dad567b8ee2ed3afeac *tests/data/fate/aac-autobsf-adtstoasc.matroska -6651 tests/data/fate/aac-autobsf-adtstoasc.matroska +4342e4f3f93b16514bda511b3b7fd93a *tests/data/fate/aac-autobsf-adtstoasc.matroska +6642 tests/data/fate/aac-autobsf-adtstoasc.matroska #extradata 0: 2, 0x0030001c #tb 0: 1/1000 #media_type 0: audio #codec_id 0: aac #sample_rate 0: 16000 -#channel_layout 0: 4 #channel_layout_name 0: mono 0, 0, 0, 64, 4, 0x02f70117 0, 64, 64, 64, 163, 0xd5f85007 diff --git a/tests/ref/fate/adpcm-4xm b/tests/ref/fate/adpcm-4xm index cfde412da..6278639b2 100644 --- a/tests/ref/fate/adpcm-4xm +++ b/tests/ref/fate/adpcm-4xm @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 22050 -#channel_layout 0: 3 #channel_layout_name 0: stereo 0, 0, 0, 1472, 5888, 0x9086e310 0, 1476, 1476, 1472, 5888, 0xac8491f5 diff --git a/tests/ref/fate/adpcm-afc b/tests/ref/fate/adpcm-afc index 6d8e73245..4caf7a8f9 100644 --- a/tests/ref/fate/adpcm-afc +++ b/tests/ref/fate/adpcm-afc @@ -2,7 +2,6 @@ #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, 17920, 71680, 0x52373bc9 0, 17920, 17920, 17920, 71680, 0x1f854b27 diff --git a/tests/ref/fate/adpcm-dtk b/tests/ref/fate/adpcm-dtk index f3ade6d50..58305d6bd 100644 --- a/tests/ref/fate/adpcm-dtk +++ b/tests/ref/fate/adpcm-dtk @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 48000 -#channel_layout 0: 3 #channel_layout_name 0: stereo 0, 0, 0, 896, 3584, 0xdae789d5 0, 896, 896, 896, 3584, 0x168ed9b6 diff --git a/tests/ref/fate/adpcm-ea-1 b/tests/ref/fate/adpcm-ea-1 index 76be8e851..ea0ba2b04 100644 --- a/tests/ref/fate/adpcm-ea-1 +++ b/tests/ref/fate/adpcm-ea-1 @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 22050 -#channel_layout 0: 3 #channel_layout_name 0: stereo 0, 0, 0, 1484, 5936, 0x00000000 0, 1484, 1484, 1456, 5824, 0x00000000 diff --git a/tests/ref/fate/adpcm-ea-2 b/tests/ref/fate/adpcm-ea-2 index 91440874a..e0dc9dccf 100644 --- a/tests/ref/fate/adpcm-ea-2 +++ b/tests/ref/fate/adpcm-ea-2 @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 22050 -#channel_layout 0: 3 #channel_layout_name 0: stereo 0, 0, 0, 1484, 5936, 0xea261a29 0, 1484, 1484, 1456, 5824, 0x253df061 diff --git a/tests/ref/fate/adpcm-ea-maxis-xa b/tests/ref/fate/adpcm-ea-maxis-xa index c919a6754..be2218424 100644 --- a/tests/ref/fate/adpcm-ea-maxis-xa +++ b/tests/ref/fate/adpcm-ea-maxis-xa @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 22050 -#channel_layout 0: 3 #channel_layout_name 0: stereo 0, 0, 0, 28, 112, 0x291d1be4 0, 28, 28, 28, 112, 0xf08d33cc diff --git a/tests/ref/fate/adpcm-ea-r1 b/tests/ref/fate/adpcm-ea-r1 index 4e5fb6788..46415e72a 100644 --- a/tests/ref/fate/adpcm-ea-r1 +++ b/tests/ref/fate/adpcm-ea-r1 @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 48000 -#channel_layout 0: 3 #channel_layout_name 0: stereo 0, 0, 0, 1624, 6496, 0x00000000 0, 1624, 1624, 1596, 6384, 0x00000000 diff --git a/tests/ref/fate/adpcm-ima-amv b/tests/ref/fate/adpcm-ima-amv index 2f8c0a2cd..37583cf81 100644 --- a/tests/ref/fate/adpcm-ima-amv +++ b/tests/ref/fate/adpcm-ima-amv @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 22050 -#channel_layout 0: 4 #channel_layout_name 0: mono 0, 0, 0, 1378, 2756, 0x0af35034 0, 1378, 1378, 1378, 2756, 0x8462443f diff --git a/tests/ref/fate/adpcm-ima-ea-eacs b/tests/ref/fate/adpcm-ima-ea-eacs index fcfcbeb17..62da571d7 100644 --- a/tests/ref/fate/adpcm-ima-ea-eacs +++ b/tests/ref/fate/adpcm-ima-ea-eacs @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 22050 -#channel_layout 0: 3 #channel_layout_name 0: stereo 0, 0, 0, 1468, 5872, 0x00000000 0, 1468, 1468, 1468, 5872, 0x00000000 diff --git a/tests/ref/fate/adpcm-ima-ea-sead b/tests/ref/fate/adpcm-ima-ea-sead index 2d52efe3c..f78bbe843 100644 --- a/tests/ref/fate/adpcm-ima-ea-sead +++ b/tests/ref/fate/adpcm-ima-ea-sead @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 22050 -#channel_layout 0: 3 #channel_layout_name 0: stereo 0, 0, 0, 736, 2944, 0x00000000 0, 736, 736, 1472, 5888, 0x5ae3c2a4 diff --git a/tests/ref/fate/adpcm-ima-smjpeg b/tests/ref/fate/adpcm-ima-smjpeg index a216e3ab5..723fa2336 100644 --- a/tests/ref/fate/adpcm-ima-smjpeg +++ b/tests/ref/fate/adpcm-ima-smjpeg @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 22050 -#channel_layout 0: 4 #channel_layout_name 0: mono 0, 0, 0, 512, 1024, 0x00000000 0, 512, 512, 512, 1024, 0x00000000 diff --git a/tests/ref/fate/adpcm-ima-ws b/tests/ref/fate/adpcm-ima-ws index b382812d2..5431538bf 100644 --- a/tests/ref/fate/adpcm-ima-ws +++ b/tests/ref/fate/adpcm-ima-ws @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 22050 -#channel_layout 0: 4 #channel_layout_name 0: mono 0, 0, 0, 11024, 22048, 0x0843bbad 0, 11024, 11024, 1470, 2940, 0x16ff454e diff --git a/tests/ref/fate/adpcm-ima-ws-vqa3 b/tests/ref/fate/adpcm-ima-ws-vqa3 index c2f14cd1a..9c2c6b175 100644 --- a/tests/ref/fate/adpcm-ima-ws-vqa3 +++ b/tests/ref/fate/adpcm-ima-ws-vqa3 @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 22050 -#channel_layout 0: 4 #channel_layout_name 0: mono 0, 0, 0, 1470, 2940, 0xca80b853 0, 1470, 1470, 1470, 2940, 0x250c9f84 diff --git a/tests/ref/fate/adpcm-ms-mono b/tests/ref/fate/adpcm-ms-mono index e3f217d18..9823ba77b 100644 --- a/tests/ref/fate/adpcm-ms-mono +++ b/tests/ref/fate/adpcm-ms-mono @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 11025 -#channel_layout 0: 4 #channel_layout_name 0: mono 0, 0, 0, 500, 1000, 0x64cd9403 0, 500, 500, 500, 1000, 0xa4ef8a9d diff --git a/tests/ref/fate/adpcm-thp b/tests/ref/fate/adpcm-thp index 592c6610a..221b2b90b 100644 --- a/tests/ref/fate/adpcm-thp +++ b/tests/ref/fate/adpcm-thp @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 32000 -#channel_layout 0: 3 #channel_layout_name 0: stereo 0, 0, 0, 1078, 4312, 0x469714f6 0, 1078, 1078, 1064, 4256, 0x6ca28f25 diff --git a/tests/ref/fate/adpcm-vima b/tests/ref/fate/adpcm-vima index b22f128be..21b8cc4a5 100644 --- a/tests/ref/fate/adpcm-vima +++ b/tests/ref/fate/adpcm-vima @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 22050 -#channel_layout 0: 3 #channel_layout_name 0: stereo 0, 0, 0, 73500, 294000, 0x37d439ee 0, 73500, 73500, 1470, 5880, 0xe524b177 diff --git a/tests/ref/fate/adpcm-xa b/tests/ref/fate/adpcm-xa index 15b62ec4a..5207fe743 100644 --- a/tests/ref/fate/adpcm-xa +++ b/tests/ref/fate/adpcm-xa @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 37800 -#channel_layout 0: 3 #channel_layout_name 0: stereo 0, 0, 0, 2016, 8064, 0xa307ed8c 0, 2016, 2016, 2016, 8064, 0xd2551927 diff --git a/tests/ref/fate/adts-id3v1-demux b/tests/ref/fate/adts-id3v1-demux index 7caa5d687..bd8f5b119 100644 --- a/tests/ref/fate/adts-id3v1-demux +++ b/tests/ref/fate/adts-id3v1-demux @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: aac #sample_rate 0: 48000 -#channel_layout 0: 3 #channel_layout_name 0: stereo 0, 0, 0, 602112, 474, 0x4c90e7c4 0, 602112, 602112, 602112, 471, 0xb8b5e75d diff --git a/tests/ref/fate/adts-id3v2-demux b/tests/ref/fate/adts-id3v2-demux index db00e3b81..710350988 100644 --- a/tests/ref/fate/adts-id3v2-demux +++ b/tests/ref/fate/adts-id3v2-demux @@ -2,7 +2,6 @@ #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 diff --git a/tests/ref/fate/adts-id3v2-two-tags-demux b/tests/ref/fate/adts-id3v2-two-tags-demux index 4fffd2e76..5fd8c52f2 100644 --- a/tests/ref/fate/adts-id3v2-two-tags-demux +++ b/tests/ref/fate/adts-id3v2-two-tags-demux @@ -2,7 +2,6 @@ #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 diff --git a/tests/ref/fate/adtstoasc_ticket3715 b/tests/ref/fate/adtstoasc_ticket3715 index fbdeeb058..78d9e7197 100644 --- a/tests/ref/fate/adtstoasc_ticket3715 +++ b/tests/ref/fate/adtstoasc_ticket3715 @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: aac #sample_rate 0: 44100 -#channel_layout 0: 3 #channel_layout_name 0: stereo 0, 0, 0, 1024, 371, 0x14b11a4f 0, 1024, 1024, 1024, 402, 0x2f00c487 diff --git a/tests/ref/fate/amrnb-remux b/tests/ref/fate/amrnb-remux new file mode 100644 index 000000000..31d20981a --- /dev/null +++ b/tests/ref/fate/amrnb-remux @@ -0,0 +1,57 @@ +55311d26f9bb6faa36d99ee7cd34ee05 *tests/data/fate/amrnb-remux.amr +7674 tests/data/fate/amrnb-remux.amr +#tb 0: 1/8000 +#media_type 0: audio +#codec_id 0: amr_nb +#sample_rate 0: 8000 +#channel_layout_name 0: mono +0, 0, 0, 160, 27, 0xc9970c51 +0, 160, 160, 160, 27, 0xbaa00d05 +0, 320, 320, 160, 27, 0xa8af0d60 +0, 480, 480, 160, 27, 0xb6750d9f +0, 640, 640, 160, 27, 0xcd7d0e5f +0, 800, 800, 160, 27, 0xaf740d0f +0, 960, 960, 160, 27, 0xcb1c0f93 +0, 1120, 1120, 160, 27, 0xccfd0e02 +0, 1280, 1280, 160, 27, 0xb3e60d1e +0, 1440, 1440, 160, 27, 0xbe510d70 +0, 1600, 1600, 160, 27, 0xbeb30d65 +0, 1760, 1760, 160, 27, 0xd4730f2b +0, 1920, 1920, 160, 27, 0xa8540cd0 +0, 2080, 2080, 160, 27, 0xafdb0c14 +0, 2240, 2240, 160, 27, 0xd9930f24 +0, 2400, 2400, 160, 27, 0xbe5f0cec +0, 2560, 2560, 160, 27, 0xb44b0c6d +0, 2720, 2720, 160, 27, 0xdc160ec9 +0, 2880, 2880, 160, 27, 0xb8a20ce3 +0, 3040, 3040, 160, 27, 0xb9120c90 +0, 3200, 3200, 160, 27, 0xcdc70e7f +0, 3360, 3360, 160, 27, 0xc7c20f06 +0, 3520, 3520, 160, 27, 0xda530f0e +0, 3680, 3680, 160, 27, 0x90750abc +0, 3840, 3840, 160, 27, 0xa4840b6d +0, 4000, 4000, 160, 27, 0x96ed0ad1 +0, 4160, 4160, 160, 27, 0xb6b30c26 +0, 4320, 4320, 160, 27, 0x786909ce +0, 4480, 4480, 160, 27, 0xa4ae0c7d +0, 4640, 4640, 160, 27, 0x9ff90ba2 +0, 4800, 4800, 160, 27, 0x914c0c22 +0, 4960, 4960, 160, 27, 0xa8df0c9c +0, 5120, 5120, 160, 27, 0xb67f0d8e +0, 5280, 5280, 160, 27, 0xb6810cca +0, 5440, 5440, 160, 27, 0xa6110c80 +0, 5600, 5600, 160, 27, 0xda0f0ecf +0, 5760, 5760, 160, 27, 0xd6270e0d +0, 5920, 5920, 160, 27, 0xd2150ffc +0, 6080, 6080, 160, 27, 0xbd010da4 +0, 6240, 6240, 160, 27, 0xb9eb0e46 +0, 6400, 6400, 160, 27, 0xc8a80eb6 +0, 6560, 6560, 160, 27, 0xcc6b0cec +0, 6720, 6720, 160, 27, 0xab190db0 +0, 6880, 6880, 160, 27, 0xb3f90ca7 +0, 7040, 7040, 160, 27, 0xa84a0cc9 +0, 7200, 7200, 160, 27, 0xcdca0e8d +0, 7360, 7360, 160, 27, 0xaf8b0d1c +0, 7520, 7520, 160, 27, 0xd9980e15 +0, 7680, 7680, 160, 27, 0xcf810f8e +0, 7840, 7840, 160, 27, 0xb7810bd0 diff --git a/tests/ref/fate/amrwb-remux b/tests/ref/fate/amrwb-remux new file mode 100644 index 000000000..0fd3e457f --- /dev/null +++ b/tests/ref/fate/amrwb-remux @@ -0,0 +1,57 @@ +3634e03f106db1da796059bde3258efc *tests/data/fate/amrwb-remux.amr +31241 tests/data/fate/amrwb-remux.amr +#tb 0: 1/16000 +#media_type 0: audio +#codec_id 0: amr_wb +#sample_rate 0: 16000 +#channel_layout_name 0: mono +0, 0, 0, 320, 61, 0xc8891fe9 +0, 320, 320, 320, 61, 0xc2562027 +0, 640, 640, 320, 61, 0xe46e207f +0, 960, 960, 320, 61, 0xa27a1c46 +0, 1280, 1280, 320, 61, 0xf1d42007 +0, 1600, 1600, 320, 61, 0x50d61af4 +0, 1920, 1920, 320, 61, 0xbacf1eef +0, 2240, 2240, 320, 61, 0xbd691d7b +0, 2560, 2560, 320, 61, 0xfd1323a2 +0, 2880, 2880, 320, 61, 0x7ca01f0e +0, 3200, 3200, 320, 61, 0x2f812276 +0, 3520, 3520, 320, 61, 0xaef41ca8 +0, 3840, 3840, 320, 61, 0x2560211f +0, 4160, 4160, 320, 61, 0xd6ad1fd4 +0, 4480, 4480, 320, 61, 0x87d81d18 +0, 4800, 4800, 320, 61, 0x11531a44 +0, 5120, 5120, 320, 61, 0x83011d4f +0, 5440, 5440, 320, 61, 0xca39211f +0, 5760, 5760, 320, 61, 0xa0031e8d +0, 6080, 6080, 320, 61, 0x0b8a1980 +0, 6400, 6400, 320, 61, 0xd2931e62 +0, 6720, 6720, 320, 61, 0x0f7820fd +0, 7040, 7040, 320, 61, 0xcc8c2149 +0, 7360, 7360, 320, 61, 0x29f82236 +0, 7680, 7680, 320, 61, 0xf7a71f9c +0, 8000, 8000, 320, 61, 0xa64f1cba +0, 8320, 8320, 320, 61, 0x685321c1 +0, 8640, 8640, 320, 61, 0x48002221 +0, 8960, 8960, 320, 61, 0xef0a1f53 +0, 9280, 9280, 320, 61, 0x31e321a0 +0, 9600, 9600, 320, 61, 0xb49f1ead +0, 9920, 9920, 320, 61, 0xe5bb1f9d +0, 10240, 10240, 320, 61, 0xc5971d19 +0, 10560, 10560, 320, 61, 0x33182328 +0, 10880, 10880, 320, 61, 0xb791204e +0, 11200, 11200, 320, 61, 0x5db81bd8 +0, 11520, 11520, 320, 61, 0x9f171da7 +0, 11840, 11840, 320, 61, 0xec4a1974 +0, 12160, 12160, 320, 61, 0x980620e1 +0, 12480, 12480, 320, 61, 0x74cf1d0c +0, 12800, 12800, 320, 61, 0xea761ef7 +0, 13120, 13120, 320, 61, 0xa1da1cc7 +0, 13440, 13440, 320, 61, 0x68741b28 +0, 13760, 13760, 320, 61, 0x87991cee +0, 14080, 14080, 320, 61, 0x955f1d0f +0, 14400, 14400, 320, 61, 0x8eea1e69 +0, 14720, 14720, 320, 61, 0xadb21ede +0, 15040, 15040, 320, 61, 0xace61e29 +0, 15360, 15360, 320, 61, 0x67441c17 +0, 15680, 15680, 320, 61, 0x7f1b1e7c diff --git a/tests/ref/fate/apng-clock b/tests/ref/fate/apng-clock index c0480fd4e..26afc94c1 100644 --- a/tests/ref/fate/apng-clock +++ b/tests/ref/fate/apng-clock @@ -3,43 +3,43 @@ #codec_id 0: rawvideo #dimensions 0: 150x150 #sar 0: 0/1 -0, 0, 0, 1, 23524, 0xf09caaa1 -0, 1, 1, 1, 23524, 0x1a329f21 -0, 2, 2, 1, 23524, 0x9b0ca017 -0, 3, 3, 1, 23524, 0x73b09deb -0, 4, 4, 1, 23524, 0x23039f49 -0, 5, 5, 1, 23524, 0x58869e7b -0, 6, 6, 1, 23524, 0xc26397d2 -0, 7, 7, 1, 23524, 0xe07f7d87 -0, 8, 8, 1, 23524, 0x619a82ba -0, 9, 9, 1, 23524, 0x696c9757 -0, 10, 10, 1, 23524, 0x7303a4a6 -0, 11, 11, 1, 23524, 0x1e149aee -0, 12, 12, 1, 23524, 0x78dd97e0 -0, 13, 13, 1, 23524, 0xad8092d3 -0, 14, 14, 1, 23524, 0x27c090b4 -0, 15, 15, 1, 23524, 0x904c97be -0, 16, 16, 1, 23524, 0x54d29b9e -0, 17, 17, 1, 23524, 0x57689bfa -0, 18, 18, 1, 23524, 0x2772a00e -0, 19, 19, 1, 23524, 0x6a769ef6 -0, 20, 20, 1, 23524, 0x94d8aad5 -0, 21, 21, 1, 23524, 0x52f79ec4 -0, 22, 22, 1, 23524, 0x99ee9fbc -0, 23, 23, 1, 23524, 0xbd6a9e4d -0, 24, 24, 1, 23524, 0xaf4aa1cf -0, 25, 25, 1, 23524, 0xdb929f98 -0, 26, 26, 1, 23524, 0x9e189a6f -0, 27, 27, 1, 23524, 0x3ffb9410 -0, 28, 28, 1, 23524, 0x6fc9917d -0, 29, 29, 1, 23524, 0xe43e94ca -0, 30, 30, 1, 23524, 0x03b6a24f -0, 31, 31, 1, 23524, 0xc54f99b3 -0, 32, 32, 1, 23524, 0x4b9a9748 -0, 33, 33, 1, 23524, 0x25a19003 -0, 34, 34, 1, 23524, 0x2b9d77cc -0, 35, 35, 1, 23524, 0x4a5a9217 -0, 36, 36, 1, 23524, 0x241b9a7c -0, 37, 37, 1, 23524, 0xc9d39b38 -0, 38, 38, 1, 23524, 0xcca69f30 -0, 39, 39, 1, 23524, 0xe50f9ec9 +0, 0, 0, 1, 90000, 0x11af5588 +0, 1, 1, 1, 90000, 0x528c2eb8 +0, 2, 2, 1, 90000, 0xebae2d82 +0, 3, 3, 1, 90000, 0xf57951ef +0, 4, 4, 1, 90000, 0xc2a84734 +0, 5, 5, 1, 90000, 0x2dd74265 +0, 6, 6, 1, 90000, 0x5a6980cb +0, 7, 7, 1, 90000, 0x519373e4 +0, 8, 8, 1, 90000, 0xdca835fb +0, 9, 9, 1, 90000, 0xc8a46d5e +0, 10, 10, 1, 90000, 0xa01a72e3 +0, 11, 11, 1, 90000, 0xacd751fa +0, 12, 12, 1, 90000, 0x464b6d39 +0, 13, 13, 1, 90000, 0x56f1b22c +0, 14, 14, 1, 90000, 0x0595a6bb +0, 15, 15, 1, 90000, 0xb9418cdc +0, 16, 16, 1, 90000, 0x8b2b7bcf +0, 17, 17, 1, 90000, 0x1a026aaf +0, 18, 18, 1, 90000, 0x25443715 +0, 19, 19, 1, 90000, 0x3d9231cd +0, 20, 20, 1, 90000, 0xfef153a8 +0, 21, 21, 1, 90000, 0x6a7c2e7b +0, 22, 22, 1, 90000, 0x1fe92cda +0, 23, 23, 1, 90000, 0x30554ff8 +0, 24, 24, 1, 90000, 0x57e544d9 +0, 25, 25, 1, 90000, 0x4c2d3b69 +0, 26, 26, 1, 90000, 0x22c26e0c +0, 27, 27, 1, 90000, 0x254bb498 +0, 28, 28, 1, 90000, 0xcd02a4ac +0, 29, 29, 1, 90000, 0x54447feb +0, 30, 30, 1, 90000, 0x9dc87b6e +0, 31, 31, 1, 90000, 0xfb49553b +0, 32, 32, 1, 90000, 0x05316fbe +0, 33, 33, 1, 90000, 0xd796da15 +0, 34, 34, 1, 90000, 0x36064111 +0, 35, 35, 1, 90000, 0x470cb58e +0, 36, 36, 1, 90000, 0xf0ba8054 +0, 37, 37, 1, 90000, 0x3f496ff8 +0, 38, 38, 1, 90000, 0xe3a43cff +0, 39, 39, 1, 90000, 0xacdd36ce diff --git a/tests/ref/fate/armovie-escape124 b/tests/ref/fate/armovie-escape124 index 398ff767b..ce9944619 100644 --- a/tests/ref/fate/armovie-escape124 +++ b/tests/ref/fate/armovie-escape124 @@ -7,7 +7,6 @@ #media_type 1: audio #codec_id 1: pcm_s16le #sample_rate 1: 44100 -#channel_layout 1: 3 #channel_layout_name 1: stereo 0, 0, 0, 1, 230400, 0xd133e177 1, 0, 0, 44100, 176400, 0xdd61578c diff --git a/tests/ref/fate/autorotate b/tests/ref/fate/autorotate new file mode 100644 index 000000000..efdde261a --- /dev/null +++ b/tests/ref/fate/autorotate @@ -0,0 +1,60 @@ +eaeb2b429cadcfd3d0984e2270126564 *tests/data/fate/autorotate.mov +197358 tests/data/fate/autorotate.mov +#extradata 0: 34, 0x9d7d073f +#tb 0: 1/15360 +#media_type 0: video +#codec_id 0: mpeg2video +#dimensions 0: 272x480 +#sar 0: 1/1 +#tb 1: 1/44100 +#media_type 1: audio +#codec_id 1: ac3 +#sample_rate 1: 44100 +#channel_layout_name 1: mono +0, -512, 0, 512, 6997, 0x55c700f6, S=1, 40 +1, -256, -256, 1536, 416, 0x92ddc529, S=2, 10, 4 +0, 0, 512, 512, 4847, 0xe74f522e, F=0x0 +1, 1280, 1280, 1536, 418, 0xc96bce7b +0, 512, 1024, 512, 5281, 0xbd4a5dac, F=0x0 +1, 2816, 2816, 1536, 418, 0xaeffcf21 +0, 1024, 1536, 512, 3521, 0x0c07249d, F=0x0 +1, 4352, 4352, 1536, 418, 0xcd37cd04 +0, 1536, 2048, 512, 5128, 0xce8bfa02, F=0x0 +0, 2048, 2560, 512, 2759, 0x2369d21d, F=0x0 +1, 5888, 5888, 1536, 418, 0x2f80bc7d +0, 2560, 3072, 512, 2057, 0x5d7ea97b, F=0x0 +1, 7424, 7424, 1536, 418, 0xb290c6ea +0, 3072, 3584, 512, 2114, 0x91d1f369, F=0x0 +1, 8960, 8960, 1536, 418, 0xa862cc5b +0, 3584, 4096, 512, 1883, 0x3dd68028, F=0x0 +1, 10496, 10496, 1536, 418, 0xb148cc5e +0, 4096, 4608, 512, 2025, 0xcf3dc34f, F=0x0 +1, 12032, 12032, 1536, 418, 0xcf34cb00 +0, 4608, 5120, 512, 1586, 0x3977edf0, F=0x0 +1, 13568, 13568, 1536, 418, 0x4665c882 +0, 5120, 5632, 512, 1633, 0x64c5e315, F=0x0 +1, 15104, 15104, 1536, 418, 0x8e4fc865 +0, 5632, 6144, 512, 3894, 0x32306d8d +1, 16640, 16640, 1536, 418, 0x80bccbc8 +0, 6144, 6656, 512, 1490, 0xa541a35a, F=0x0 +1, 18176, 18176, 1536, 418, 0x84eaca12 +0, 6656, 7168, 512, 1253, 0x7e93302b, F=0x0 +1, 19712, 19712, 1536, 418, 0xc3b6cbd8 +0, 7168, 7680, 512, 1573, 0x58fcd6b2, F=0x0 +1, 21248, 21248, 1536, 418, 0xa345cb53 +[STREAM] +[SIDE_DATA] +side_data_type=CPB properties +max_bitrate=0 +min_bitrate=0 +avg_bitrate=0 +buffer_size=49152 +vbv_delay=-1 +[/SIDE_DATA] +[/STREAM] +[STREAM] +[SIDE_DATA] +side_data_type=Audio Service Type +service_type=0 +[/SIDE_DATA] +[/STREAM] diff --git a/tests/ref/fate/bethsoft-vid b/tests/ref/fate/bethsoft-vid index 25a62ae51..a6a0f41af 100644 --- a/tests/ref/fate/bethsoft-vid +++ b/tests/ref/fate/bethsoft-vid @@ -7,7 +7,6 @@ #media_type 1: audio #codec_id 1: pcm_s16le #sample_rate 1: 11111 -#channel_layout 1: 4 #channel_layout_name 1: mono 0, 0, 0, 1, 192000, 0x00000000 1, 0, 0, 740, 1480, 0x00000000 diff --git a/tests/ref/fate/bfi b/tests/ref/fate/bfi index 277c93543..e7583a7cd 100644 --- a/tests/ref/fate/bfi +++ b/tests/ref/fate/bfi @@ -7,7 +7,6 @@ #media_type 1: audio #codec_id 1: pcm_s16le #sample_rate 1: 11025 -#channel_layout 1: 4 #channel_layout_name 1: mono 0, 0, 0, 1, 134400, 0xc218b00c 1, 0, 0, 8884, 17768, 0x07df135c diff --git a/tests/ref/fate/bmv-audio b/tests/ref/fate/bmv-audio index 6e1a4c2fe..6de8b995c 100644 --- a/tests/ref/fate/bmv-audio +++ b/tests/ref/fate/bmv-audio @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 22050 -#channel_layout 0: 3 #channel_layout_name 0: stereo 0, 0, 0, 1856, 7424, 0x18540b36 0, 1856, 1856, 1824, 7296, 0x5acd2484 diff --git a/tests/ref/fate/caf-alac-remux b/tests/ref/fate/caf-alac-remux index 97275fd31..f33182b72 100644 --- a/tests/ref/fate/caf-alac-remux +++ b/tests/ref/fate/caf-alac-remux @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: alac #sample_rate 0: 44100 -#channel_layout 0: 3 #channel_layout_name 0: stereo 0, 0, 0, 0, 32, 0xa0af0dfe 0, 4096, 4096, 0, 6701, 0xa9ddc14e diff --git a/tests/ref/fate/caf-amr_nb-remux b/tests/ref/fate/caf-amr_nb-remux index 0eed36a5c..7ae3a7474 100644 --- a/tests/ref/fate/caf-amr_nb-remux +++ b/tests/ref/fate/caf-amr_nb-remux @@ -5,7 +5,6 @@ a00bd18f70b66286e67d84f0df034a48 *tests/data/fate/caf-amr_nb-remux.caf #media_type 0: audio #codec_id 0: amr_nb #sample_rate 0: 8000 -#channel_layout 0: 4 #channel_layout_name 0: mono 0, 0, 0, 160, 13, 0x2bf906f6 0, 160, 160, 160, 13, 0x28bd0756 diff --git a/tests/ref/fate/caf-mace6-remux b/tests/ref/fate/caf-mace6-remux index 3a0499d79..e674365b3 100644 --- a/tests/ref/fate/caf-mace6-remux +++ b/tests/ref/fate/caf-mace6-remux @@ -4,7 +4,6 @@ #media_type 0: audio #codec_id 0: mace6 #sample_rate 0: 22050 -#channel_layout 0: 4 #channel_layout_name 0: mono 0, 0, 0, 6, 1, 0x00900090 0, 6, 6, 6, 1, 0x00870087 diff --git a/tests/ref/fate/caf-pcm_s24-remux b/tests/ref/fate/caf-pcm_s24-remux index bb3136ef7..618f6f73e 100644 --- a/tests/ref/fate/caf-pcm_s24-remux +++ b/tests/ref/fate/caf-pcm_s24-remux @@ -4,7 +4,6 @@ d696d9dc23a82c51c4761f5792e7fa37 *tests/data/fate/caf-pcm_s24-remux.caf #media_type 0: audio #codec_id 0: pcm_s24be #sample_rate 0: 192000 -#channel_layout 0: 3 #channel_layout_name 0: stereo 0, 0, 0, 682, 4092, 0x71f10ea0 0, 682, 682, 682, 4092, 0x51852317 diff --git a/tests/ref/fate/caf-pcm_s24le-remux b/tests/ref/fate/caf-pcm_s24le-remux index 9520e423c..bab814c5e 100644 --- a/tests/ref/fate/caf-pcm_s24le-remux +++ b/tests/ref/fate/caf-pcm_s24le-remux @@ -4,7 +4,6 @@ ee0072a92044cbad68795cf93546c517 *tests/data/fate/caf-pcm_s24le-remux.caf #media_type 0: audio #codec_id 0: pcm_s24le #sample_rate 0: 192000 -#channel_layout 0: 3 #channel_layout_name 0: stereo 0, 0, 0, 682, 4092, 0xa6320ea0 0, 682, 682, 682, 4092, 0x27732317 diff --git a/tests/ref/fate/caf-qdm2-remux b/tests/ref/fate/caf-qdm2-remux index a3bde1264..d4f658c16 100644 --- a/tests/ref/fate/caf-qdm2-remux +++ b/tests/ref/fate/caf-qdm2-remux @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: qdm2 #sample_rate 0: 44100 -#channel_layout 0: 3 #channel_layout_name 0: stereo 0, 0, 0, 0, 370, 0x4d1897fc 0, 4096, 4096, 0, 370, 0xea999da0 diff --git a/tests/ref/fate/cdxl-demux b/tests/ref/fate/cdxl-demux index 324a40f2d..9b71b1891 100644 --- a/tests/ref/fate/cdxl-demux +++ b/tests/ref/fate/cdxl-demux @@ -7,7 +7,6 @@ #media_type 1: audio #codec_id 1: pcm_s8_planar #sample_rate 1: 11025 -#channel_layout 1: 4 #channel_layout_name 1: mono 0, 0, 0, 1, 22688, 0xc954a244 1, 0, 0, 1884, 1884, 0x06925e3e diff --git a/tests/ref/fate/channel_layout b/tests/ref/fate/channel_layout new file mode 100644 index 000000000..19bcbce7d --- /dev/null +++ b/tests/ref/fate/channel_layout @@ -0,0 +1,179 @@ +Testing av_channel_layout_standard +mono FC +stereo FL+FR +2.1 FL+FR+LFE +3.0 FL+FR+FC +3.0(back) FL+FR+BC +4.0 FL+FR+FC+BC +quad FL+FR+BL+BR +quad(side) FL+FR+SL+SR +3.1 FL+FR+FC+LFE +5.0 FL+FR+FC+BL+BR +5.0(side) FL+FR+FC+SL+SR +4.1 FL+FR+FC+LFE+BC +5.1 FL+FR+FC+LFE+BL+BR +5.1(side) FL+FR+FC+LFE+SL+SR +6.0 FL+FR+FC+BC+SL+SR +6.0(front) FL+FR+FLC+FRC+SL+SR +hexagonal FL+FR+FC+BL+BR+BC +6.1 FL+FR+FC+LFE+BC+SL+SR +6.1(back) FL+FR+FC+LFE+BL+BR+BC +6.1(front) FL+FR+LFE+FLC+FRC+SL+SR +7.0 FL+FR+FC+BL+BR+SL+SR +7.0(front) FL+FR+FC+FLC+FRC+SL+SR +7.1 FL+FR+FC+LFE+BL+BR+SL+SR +7.1(wide) FL+FR+FC+LFE+BL+BR+FLC+FRC +7.1(wide-side) FL+FR+FC+LFE+FLC+FRC+SL+SR +octagonal FL+FR+FC+BL+BR+BC+SL+SR +hexadecagonal FL+FR+FC+BL+BR+BC+SL+SR+TFL+TFC+TFR+TBL+TBC+TBR+WL+WR +downmix DL+DR +22.2 FL+FR+FC+LFE+BL+BR+FLC+FRC+BC+SL+SR+TC+TFL+TFC+TFR+TBL+TBC+TBR+LFE2+TSL+TSR+BFC+BFL+BFR + +Testing av_channel_name +With AV_CHAN_FRONT_LEFT: FL +With AV_CHAN_FRONT_RIGHT: FR +With 63: USR63 +With AV_CHAN_AMBISONIC_BASE: AMBI0 +With AV_CHAN_AMBISONIC_END: AMBI1023 +Testing av_channel_description +With AV_CHAN_FRONT_LEFT: front left +With AV_CHAN_FRONT_RIGHT: front right +With 63: user 63 +With AV_CHAN_AMBISONIC_BASE: ambisonic ACN 0 +With AV_CHAN_AMBISONIC_END: ambisonic ACN 1023 + +Testing av_channel_from_string +With "FL": 0 +With "FR": 1 +With "USR63": 63 +With "AMBI0": 1024 +With "AMBI1023": 2047 + +==Native layouts== + +Testing av_channel_layout_from_string +With "0x3f": 5.1 +With "63": 5.1 +With "6c": 5.1 +With "6C": 6 channels +With "6 channels": 6 channels +With "6 channels (FL+FR+FC+LFE+BL+BR)": 5.1 +With "FL+FR+FC+LFE+BL+BR": 5.1 +With "5.1": 5.1 +With "FL+FR+USR63": 3 channels (FL+FR+USR63) +With "FL+FR+FC+LFE+SL+SR": 5.1(side) +With "5.1(side)": 5.1(side) + +Testing av_channel_layout_from_mask +With AV_CH_LAYOUT_5POINT1: 5.1(side) + +Testing av_channel_layout_channel_from_index +On 5.1(side) layout with 0: 0 +On 5.1(side) layout with 1: 1 +On 5.1(side) layout with 2: 2 +On 5.1(side) layout with 3: 3 +On 5.1(side) layout with 4: 9 +On 5.1(side) layout with 5: 10 +On 5.1(side) layout with 6: -1 + +Testing av_channel_layout_index_from_channel +On 5.1(side) layout with AV_CHAN_FRONT_LEFT: 0 +On 5.1(side) layout with AV_CHAN_FRONT_RIGHT: 1 +On 5.1(side) layout with AV_CHAN_FRONT_CENTER: 2 +On 5.1(side) layout with AV_CHAN_LOW_FREQUENCY: 3 +On 5.1(side) layout with AV_CHAN_SIDE_LEFT: 4 +On 5.1(side) layout with AV_CHAN_SIDE_RIGHT: 5 +On 5.1(side) layout with AV_CHAN_BACK_CENTER: -1 + +Testing av_channel_layout_channel_from_string +On 5.1(side) layout with "FL": 0 +On 5.1(side) layout with "FR": 1 +On 5.1(side) layout with "FC": 2 +On 5.1(side) layout with "LFE": 3 +On 5.1(side) layout with "SL": 9 +On 5.1(side) layout with "SR": 10 +On 5.1(side) layout with "BC": -1 + +Testing av_channel_layout_index_from_string +On 5.1(side) layout with "FL": 0 +On 5.1(side) layout with "FR": 1 +On 5.1(side) layout with "FC": 2 +On 5.1(side) layout with "LFE": 3 +On 5.1(side) layout with "SL": 4 +On 5.1(side) layout with "SR": 5 +On 5.1(side) layout with "BC": -1 + +Testing av_channel_layout_subset +On 5.1(side) layout with AV_CH_LAYOUT_STEREO: 0x3 +On 5.1(side) layout with AV_CH_LAYOUT_2POINT1: 0xb +On 5.1(side) layout with AV_CH_LAYOUT_4POINT1: 0xf + +==Custom layouts== + +Testing av_channel_layout_from_string +With "FL+FR+FC+BL+BR+LFE": 6 channels (FL+FR+FC+BL+BR+LFE) +With "2 channels (FR+FL)": 2 channels (FR+FL) +With "ambisonic 1+FR+FL": ambisonic 1+2 channels (FR+FL) +With "ambisonic 2+FC@Foo": ambisonic 2+1 channels (FC@Foo) +With "FL@Foo+FR@Bar": 2 channels (FL@Foo+FR@Bar) +With "FR+FL@Foo+USR63@Foo": 3 channels (FR+FL@Foo+USR63@Foo) + +Testing av_channel_layout_index_from_string +On "FR+FL@Foo+USR63@Foo" layout with "FR": 0 +On "FR+FL@Foo+USR63@Foo" layout with "FL": 1 +On "FR+FL@Foo+USR63@Foo" layout with "USR63": 2 +On "FR+FL@Foo+USR63@Foo" layout with "Foo": -1 +On "FR+FL@Foo+USR63@Foo" layout with "@Foo": 1 +On "FR+FL@Foo+USR63@Foo" layout with "FR@Foo": -1 +On "FR+FL@Foo+USR63@Foo" layout with "FL@Foo": 1 +On "FR+FL@Foo+USR63@Foo" layout with "USR63@Foo": 2 +On "FR+FL@Foo+USR63@Foo" layout with "BC": -1 + +Testing av_channel_layout_channel_from_string +On "FR+FL@Foo+USR63@Foo" layout with "FR": 1 +On "FR+FL@Foo+USR63@Foo" layout with "FL": 0 +On "FR+FL@Foo+USR63@Foo" layout with "USR63": 63 +On "FR+FL@Foo+USR63@Foo" layout with "Foo": -1 +On "FR+FL@Foo+USR63@Foo" layout with "@Foo": 0 +On "FR+FL@Foo+USR63@Foo" layout with "FR@Foo": -1 +On "FR+FL@Foo+USR63@Foo" layout with "FL@Foo": 0 +On "FR+FL@Foo+USR63@Foo" layout with "USR63@Foo": 63 +On "FR+FL@Foo+USR63@Foo" layout with "BC": -1 + +Testing av_channel_layout_index_from_channel +On "FR+FL@Foo+USR63@Foo" layout with AV_CHAN_FRONT_RIGHT: 0 +On "FR+FL@Foo+USR63@Foo" layout with AV_CHAN_FRONT_LEFT: 1 +On "FR+FL@Foo+USR63@Foo" layout with 63: 2 +On "FR+FL@Foo+USR63@Foo" layout with AV_CHAN_BACK_CENTER: -1 + +Testing av_channel_layout_channel_from_index +On "FR+FL@Foo+USR63@Foo" layout with 0: 1 +On "FR+FL@Foo+USR63@Foo" layout with 1: 0 +On "FR+FL@Foo+USR63@Foo" layout with 2: 63 +On "FR+FL@Foo+USR63@Foo" layout with 3: -1 + +Testing av_channel_layout_subset +On "FR+FL@Foo+USR63@Foo" layout with AV_CH_LAYOUT_STEREO: 0x3 +On "FR+FL@Foo+USR63@Foo" layout with AV_CH_LAYOUT_QUAD: 0x3 + +==Ambisonic layouts== + +Testing av_channel_layout_from_string +With "ambisonic 1": ambisonic 1 +With "ambisonic 2+stereo": ambisonic 2+stereo + +Testing av_channel_layout_index_from_channel +On "ambisonic 2+stereo" layout with AV_CHAN_AMBISONIC_BASE: 0 +On "ambisonic 2+stereo" layout with AV_CHAN_FRONT_LEFT: 9 +On "ambisonic 2+stereo" layout with AV_CHAN_FRONT_RIGHT: 10 +On "ambisonic 2+stereo" layout with AV_CHAN_BACK_CENTER: -1 + +Testing av_channel_layout_channel_from_index +On "ambisonic 2+stereo" layout with 0: 1024 +On "ambisonic 2+stereo" layout with 9: 0 +On "ambisonic 2+stereo" layout with 10: 1 +On "ambisonic 2+stereo" layout with 11: -1 + +Testing av_channel_layout_subset +On "ambisonic 2+stereo" layout with AV_CH_LAYOUT_STEREO: 0x3 +On "ambisonic 2+stereo" layout with AV_CH_LAYOUT_QUAD: 0x3 diff --git a/tests/ref/fate/copy-psp b/tests/ref/fate/copy-psp index 8b2cef87f..977bef5c3 100644 --- a/tests/ref/fate/copy-psp +++ b/tests/ref/fate/copy-psp @@ -11,7 +11,6 @@ #media_type 1: audio #codec_id 1: aac #sample_rate 1: 48000 -#channel_layout 1: 3 #channel_layout_name 1: stereo 0, 0, 0, 3003, 37084, 0x021a0d3f 1, 0, 0, 1024, 10, 0x0e270398 diff --git a/tests/ref/fate/copy-shortest1 b/tests/ref/fate/copy-shortest1 index 69204b373..5038973e4 100644 --- a/tests/ref/fate/copy-shortest1 +++ b/tests/ref/fate/copy-shortest1 @@ -11,7 +11,6 @@ #media_type 1: audio #codec_id 1: ac3 #sample_rate 1: 44100 -#channel_layout 1: 4 #channel_layout_name 1: mono #stream#, dts, pts, duration, size, hash 1, -256, -256, 1536, 416, e3bd415f62aa927e9273151fdf21ebce diff --git a/tests/ref/fate/copy-shortest2 b/tests/ref/fate/copy-shortest2 index 69204b373..5038973e4 100644 --- a/tests/ref/fate/copy-shortest2 +++ b/tests/ref/fate/copy-shortest2 @@ -11,7 +11,6 @@ #media_type 1: audio #codec_id 1: ac3 #sample_rate 1: 44100 -#channel_layout 1: 4 #channel_layout_name 1: mono #stream#, dts, pts, duration, size, hash 1, -256, -256, 1536, 416, e3bd415f62aa927e9273151fdf21ebce diff --git a/tests/ref/fate/copy-trac236 b/tests/ref/fate/copy-trac236 index c34b309b3..5a9e08ad0 100644 --- a/tests/ref/fate/copy-trac236 +++ b/tests/ref/fate/copy-trac236 @@ -9,7 +9,6 @@ #media_type 1: audio #codec_id 1: pcm_s16le #sample_rate 1: 48000 -#channel_layout 1: 3 #channel_layout_name 1: stereo 0, 0, 0, 1, 518400, 0x81ab2140 1, 0, 0, 1024, 4096, 0x67dc99a3 diff --git a/tests/ref/fate/copy-trac3074 b/tests/ref/fate/copy-trac3074 index 2ef7e702c..b6d23f8c1 100644 --- a/tests/ref/fate/copy-trac3074 +++ b/tests/ref/fate/copy-trac3074 @@ -4,7 +4,6 @@ #media_type 0: audio #codec_id 0: eac3 #sample_rate 0: 48000 -#channel_layout 0: 3 #channel_layout_name 0: stereo 0, 0, 0, 1536, 512, 0x2beaf79f, S=1, 4 0, 1536, 1536, 1536, 512, 0x29ddf9d6 diff --git a/tests/ref/fate/copy-trac4914 b/tests/ref/fate/copy-trac4914 index 743dc8c05..1fd16e9a4 100644 --- a/tests/ref/fate/copy-trac4914 +++ b/tests/ref/fate/copy-trac4914 @@ -1,4 +1,4 @@ -f5150fb82c1bb5a90906fce93dcc3f76 *tests/data/fate/copy-trac4914.mxf +a0f68fa1d9ed5d3030d8244ea0b0299a *tests/data/fate/copy-trac4914.mxf 561721 tests/data/fate/copy-trac4914.mxf #tb 0: 1001/30000 #media_type 0: video @@ -9,7 +9,6 @@ f5150fb82c1bb5a90906fce93dcc3f76 *tests/data/fate/copy-trac4914.mxf #media_type 1: audio #codec_id 1: pcm_s16le #sample_rate 1: 48000 -#channel_layout 1: 3 #channel_layout_name 1: stereo 0, 0, 0, 1, 259200, 0xf36957da 1, 0, 0, 1602, 6408, 0x1dd7b37c diff --git a/tests/ref/fate/copy-trac4914-avi b/tests/ref/fate/copy-trac4914-avi index 0358ead6b..20006ea05 100644 --- a/tests/ref/fate/copy-trac4914-avi +++ b/tests/ref/fate/copy-trac4914-avi @@ -9,7 +9,6 @@ #media_type 1: audio #codec_id 1: pcm_s16le #sample_rate 1: 48000 -#channel_layout 1: 3 #channel_layout_name 1: stereo 1, 0, 0, 1152, 4608, 0xb24f5c9d 1, 1152, 1152, 1152, 4608, 0xe2da5c32 diff --git a/tests/ref/fate/corepng b/tests/ref/fate/corepng index 74bb92010..942ceceb9 100644 --- a/tests/ref/fate/corepng +++ b/tests/ref/fate/corepng @@ -7,7 +7,6 @@ #media_type 1: audio #codec_id 1: pcm_s16le #sample_rate 1: 11025 -#channel_layout 1: 4 #channel_layout_name 1: mono 0, 0, 0, 1, 230400, 0x03e25ead 1, 0, 0, 5513, 11026, 0x27ad637c diff --git a/tests/ref/fate/cover-art-aiff-id3v2-remux b/tests/ref/fate/cover-art-aiff-id3v2-remux index c294c5013..3ca2855eb 100644 --- a/tests/ref/fate/cover-art-aiff-id3v2-remux +++ b/tests/ref/fate/cover-art-aiff-id3v2-remux @@ -4,7 +4,6 @@ d4a9481090a8bab1a3f072a8108a1d6a *tests/data/fate/cover-art-aiff-id3v2-remux.aif #media_type 0: audio #codec_id 0: pcm_s16be #sample_rate 0: 44100 -#channel_layout 0: 3 #channel_layout_name 0: stereo #tb 1: 1/90000 #media_type 1: video diff --git a/tests/ref/fate/cover-art-flac-remux b/tests/ref/fate/cover-art-flac-remux index 3f779828a..fa9197588 100644 --- a/tests/ref/fate/cover-art-flac-remux +++ b/tests/ref/fate/cover-art-flac-remux @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: flac #sample_rate 0: 44100 -#channel_layout 0: 5 #channel_layout_name 0: 2 channels (FL+FC) #tb 1: 1/90000 #media_type 1: video @@ -36,7 +35,6 @@ #media_type 6: audio #codec_id 6: pcm_s16le #sample_rate 6: 44100 -#channel_layout 6: 5 #channel_layout_name 6: 2 channels (FL+FC) 0, 0, 0, 4608, 14, 0x242b036d 1, 0, 0, 0, 66888, 0x1fd72743 diff --git a/tests/ref/fate/cover-art-mp3-id3v2-remux b/tests/ref/fate/cover-art-mp3-id3v2-remux index 457f1d5a0..906a64679 100644 --- a/tests/ref/fate/cover-art-mp3-id3v2-remux +++ b/tests/ref/fate/cover-art-mp3-id3v2-remux @@ -4,7 +4,6 @@ c1b55a9a92226cd72d3f53ccd830d127 *tests/data/fate/cover-art-mp3-id3v2-remux.mp3 #media_type 0: audio #codec_id 0: mp3 #sample_rate 0: 44100 -#channel_layout 0: 3 #channel_layout_name 0: stereo #tb 1: 1/90000 #media_type 1: video diff --git a/tests/ref/fate/creatureshock-avs b/tests/ref/fate/creatureshock-avs index c8e08c9ff..19648202b 100644 --- a/tests/ref/fate/creatureshock-avs +++ b/tests/ref/fate/creatureshock-avs @@ -7,7 +7,6 @@ #media_type 1: audio #codec_id 1: pcm_s16le #sample_rate 1: 22222 -#channel_layout 1: 4 #channel_layout_name 1: mono 0, 0, 0, 1, 188892, 0x9f47a5ec 1, 0, 0, 8186, 16372, 0xfaaab59d diff --git a/tests/ref/fate/cyberia-c93 b/tests/ref/fate/cyberia-c93 index e7a5b5a08..813ef4682 100644 --- a/tests/ref/fate/cyberia-c93 +++ b/tests/ref/fate/cyberia-c93 @@ -7,7 +7,6 @@ #media_type 1: audio #codec_id 1: pcm_s16le #sample_rate 1: 16129 -#channel_layout 1: 4 #channel_layout_name 1: mono 0, 0, 0, 1, 184320, 0x8433f0f8 1, 0, 0, 14184, 28368, 0xaacc96a5 diff --git a/tests/ref/fate/d-cinema-demux b/tests/ref/fate/d-cinema-demux index 74d00f7bb..f1e8b5f75 100644 --- a/tests/ref/fate/d-cinema-demux +++ b/tests/ref/fate/d-cinema-demux @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s24daud #sample_rate 0: 96000 -#channel_layout 0: 60f #channel_layout_name 0: 5.1(side) 0, 0, 0, 1875, 36000, 0xd592781d 0, 1875, 1875, 1875, 36000, 0xd592781d diff --git a/tests/ref/fate/dca-xll_51_16_192_768_0 b/tests/ref/fate/dca-xll_51_16_192_768_0 index 6e62c616e..756d11d86 100644 --- a/tests/ref/fate/dca-xll_51_16_192_768_0 +++ b/tests/ref/fate/dca-xll_51_16_192_768_0 @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 192000 -#channel_layout 0: 60f #channel_layout_name 0: 5.1(side) #stream#, dts, pts, duration, size, hash 0, 0, 0, 2048, 24576, 91ff0dac5df86e798bfef5e573536b08 diff --git a/tests/ref/fate/dca-xll_51_16_192_768_0-dmix_2 b/tests/ref/fate/dca-xll_51_16_192_768_0-dmix_2 index 6e62c616e..756d11d86 100644 --- a/tests/ref/fate/dca-xll_51_16_192_768_0-dmix_2 +++ b/tests/ref/fate/dca-xll_51_16_192_768_0-dmix_2 @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 192000 -#channel_layout 0: 60f #channel_layout_name 0: 5.1(side) #stream#, dts, pts, duration, size, hash 0, 0, 0, 2048, 24576, 91ff0dac5df86e798bfef5e573536b08 diff --git a/tests/ref/fate/dca-xll_51_16_192_768_0-dmix_6 b/tests/ref/fate/dca-xll_51_16_192_768_0-dmix_6 index 6e62c616e..756d11d86 100644 --- a/tests/ref/fate/dca-xll_51_16_192_768_0-dmix_6 +++ b/tests/ref/fate/dca-xll_51_16_192_768_0-dmix_6 @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 192000 -#channel_layout 0: 60f #channel_layout_name 0: 5.1(side) #stream#, dts, pts, duration, size, hash 0, 0, 0, 2048, 24576, 91ff0dac5df86e798bfef5e573536b08 diff --git a/tests/ref/fate/dca-xll_51_16_192_768_1 b/tests/ref/fate/dca-xll_51_16_192_768_1 index 6e62c616e..756d11d86 100644 --- a/tests/ref/fate/dca-xll_51_16_192_768_1 +++ b/tests/ref/fate/dca-xll_51_16_192_768_1 @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 192000 -#channel_layout 0: 60f #channel_layout_name 0: 5.1(side) #stream#, dts, pts, duration, size, hash 0, 0, 0, 2048, 24576, 91ff0dac5df86e798bfef5e573536b08 diff --git a/tests/ref/fate/dca-xll_51_16_192_768_1-dmix_2 b/tests/ref/fate/dca-xll_51_16_192_768_1-dmix_2 index 17896a7cc..21a574fd9 100644 --- a/tests/ref/fate/dca-xll_51_16_192_768_1-dmix_2 +++ b/tests/ref/fate/dca-xll_51_16_192_768_1-dmix_2 @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 192000 -#channel_layout 0: 3 #channel_layout_name 0: stereo #stream#, dts, pts, duration, size, hash 0, 0, 0, 2048, 8192, 0829f71740aab1ab98b33eae21dee122 diff --git a/tests/ref/fate/dca-xll_51_16_192_768_1-dmix_6 b/tests/ref/fate/dca-xll_51_16_192_768_1-dmix_6 index 6e62c616e..756d11d86 100644 --- a/tests/ref/fate/dca-xll_51_16_192_768_1-dmix_6 +++ b/tests/ref/fate/dca-xll_51_16_192_768_1-dmix_6 @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 192000 -#channel_layout 0: 60f #channel_layout_name 0: 5.1(side) #stream#, dts, pts, duration, size, hash 0, 0, 0, 2048, 24576, 91ff0dac5df86e798bfef5e573536b08 diff --git a/tests/ref/fate/dca-xll_51_24_48_768 b/tests/ref/fate/dca-xll_51_24_48_768 index 2d10583b4..96c936bdc 100644 --- a/tests/ref/fate/dca-xll_51_24_48_768 +++ b/tests/ref/fate/dca-xll_51_24_48_768 @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: pcm_s24le #sample_rate 0: 48000 -#channel_layout 0: 60f #channel_layout_name 0: 5.1(side) #stream#, dts, pts, duration, size, hash 0, 0, 0, 512, 9216, 13a95890b5f0947d6f058ca9c30a3e01 diff --git a/tests/ref/fate/dca-xll_51_24_48_768-dmix_2 b/tests/ref/fate/dca-xll_51_24_48_768-dmix_2 index be22d7d98..0527069ae 100644 --- a/tests/ref/fate/dca-xll_51_24_48_768-dmix_2 +++ b/tests/ref/fate/dca-xll_51_24_48_768-dmix_2 @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: pcm_s24le #sample_rate 0: 48000 -#channel_layout 0: 3 #channel_layout_name 0: stereo #stream#, dts, pts, duration, size, hash 0, 0, 0, 512, 3072, d2a70550489de356a2cd6bfc40711204 diff --git a/tests/ref/fate/dca-xll_51_24_48_768-dmix_6 b/tests/ref/fate/dca-xll_51_24_48_768-dmix_6 index 2d10583b4..96c936bdc 100644 --- a/tests/ref/fate/dca-xll_51_24_48_768-dmix_6 +++ b/tests/ref/fate/dca-xll_51_24_48_768-dmix_6 @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: pcm_s24le #sample_rate 0: 48000 -#channel_layout 0: 60f #channel_layout_name 0: 5.1(side) #stream#, dts, pts, duration, size, hash 0, 0, 0, 512, 9216, 13a95890b5f0947d6f058ca9c30a3e01 diff --git a/tests/ref/fate/dca-xll_51_24_48_none b/tests/ref/fate/dca-xll_51_24_48_none index 17cfd0edb..6c5b48b26 100644 --- a/tests/ref/fate/dca-xll_51_24_48_none +++ b/tests/ref/fate/dca-xll_51_24_48_none @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: pcm_s24le #sample_rate 0: 48000 -#channel_layout 0: 60f #channel_layout_name 0: 5.1(side) #stream#, dts, pts, duration, size, hash 0, 0, 0, 1024, 18432, f9debe3f07be68533bf0295e3d2ba68a diff --git a/tests/ref/fate/dca-xll_51_24_48_none-dmix_2 b/tests/ref/fate/dca-xll_51_24_48_none-dmix_2 index 17cfd0edb..6c5b48b26 100644 --- a/tests/ref/fate/dca-xll_51_24_48_none-dmix_2 +++ b/tests/ref/fate/dca-xll_51_24_48_none-dmix_2 @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: pcm_s24le #sample_rate 0: 48000 -#channel_layout 0: 60f #channel_layout_name 0: 5.1(side) #stream#, dts, pts, duration, size, hash 0, 0, 0, 1024, 18432, f9debe3f07be68533bf0295e3d2ba68a diff --git a/tests/ref/fate/dca-xll_51_24_48_none-dmix_6 b/tests/ref/fate/dca-xll_51_24_48_none-dmix_6 index 17cfd0edb..6c5b48b26 100644 --- a/tests/ref/fate/dca-xll_51_24_48_none-dmix_6 +++ b/tests/ref/fate/dca-xll_51_24_48_none-dmix_6 @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: pcm_s24le #sample_rate 0: 48000 -#channel_layout 0: 60f #channel_layout_name 0: 5.1(side) #stream#, dts, pts, duration, size, hash 0, 0, 0, 1024, 18432, f9debe3f07be68533bf0295e3d2ba68a diff --git a/tests/ref/fate/dca-xll_71_24_48_768_0 b/tests/ref/fate/dca-xll_71_24_48_768_0 index a295d41a9..e74e54d44 100644 --- a/tests/ref/fate/dca-xll_71_24_48_768_0 +++ b/tests/ref/fate/dca-xll_71_24_48_768_0 @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: pcm_s24le #sample_rate 0: 48000 -#channel_layout 0: 63f #channel_layout_name 0: 7.1 #stream#, dts, pts, duration, size, hash 0, 0, 0, 512, 12288, ca9f8c8eb1b9b311cb79999fa376c7f0 diff --git a/tests/ref/fate/dca-xll_71_24_48_768_0-dmix_2 b/tests/ref/fate/dca-xll_71_24_48_768_0-dmix_2 index f9b7b655a..2787b6751 100644 --- a/tests/ref/fate/dca-xll_71_24_48_768_0-dmix_2 +++ b/tests/ref/fate/dca-xll_71_24_48_768_0-dmix_2 @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: pcm_s24le #sample_rate 0: 48000 -#channel_layout 0: 60f #channel_layout_name 0: 5.1(side) #stream#, dts, pts, duration, size, hash 0, 0, 0, 512, 9216, a2b724b146069938f0e2cb82490dea54 diff --git a/tests/ref/fate/dca-xll_71_24_48_768_0-dmix_6 b/tests/ref/fate/dca-xll_71_24_48_768_0-dmix_6 index f9b7b655a..2787b6751 100644 --- a/tests/ref/fate/dca-xll_71_24_48_768_0-dmix_6 +++ b/tests/ref/fate/dca-xll_71_24_48_768_0-dmix_6 @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: pcm_s24le #sample_rate 0: 48000 -#channel_layout 0: 60f #channel_layout_name 0: 5.1(side) #stream#, dts, pts, duration, size, hash 0, 0, 0, 512, 9216, a2b724b146069938f0e2cb82490dea54 diff --git a/tests/ref/fate/dca-xll_71_24_48_768_1 b/tests/ref/fate/dca-xll_71_24_48_768_1 index a295d41a9..e74e54d44 100644 --- a/tests/ref/fate/dca-xll_71_24_48_768_1 +++ b/tests/ref/fate/dca-xll_71_24_48_768_1 @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: pcm_s24le #sample_rate 0: 48000 -#channel_layout 0: 63f #channel_layout_name 0: 7.1 #stream#, dts, pts, duration, size, hash 0, 0, 0, 512, 12288, ca9f8c8eb1b9b311cb79999fa376c7f0 diff --git a/tests/ref/fate/dca-xll_71_24_48_768_1-dmix_2 b/tests/ref/fate/dca-xll_71_24_48_768_1-dmix_2 index 5b0174625..57f1dab0b 100644 --- a/tests/ref/fate/dca-xll_71_24_48_768_1-dmix_2 +++ b/tests/ref/fate/dca-xll_71_24_48_768_1-dmix_2 @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: pcm_s24le #sample_rate 0: 48000 -#channel_layout 0: 3 #channel_layout_name 0: stereo #stream#, dts, pts, duration, size, hash 0, 0, 0, 512, 3072, d2a70550489de356a2cd6bfc40711204 diff --git a/tests/ref/fate/dca-xll_71_24_48_768_1-dmix_6 b/tests/ref/fate/dca-xll_71_24_48_768_1-dmix_6 index 246b5e013..5f847e65c 100644 --- a/tests/ref/fate/dca-xll_71_24_48_768_1-dmix_6 +++ b/tests/ref/fate/dca-xll_71_24_48_768_1-dmix_6 @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: pcm_s24le #sample_rate 0: 48000 -#channel_layout 0: 60f #channel_layout_name 0: 5.1(side) #stream#, dts, pts, duration, size, hash 0, 0, 0, 512, 9216, a2b724b146069938f0e2cb82490dea54 diff --git a/tests/ref/fate/dca-xll_71_24_96_768 b/tests/ref/fate/dca-xll_71_24_96_768 index 418b4b136..df8ec4da7 100644 --- a/tests/ref/fate/dca-xll_71_24_96_768 +++ b/tests/ref/fate/dca-xll_71_24_96_768 @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: pcm_s24le #sample_rate 0: 96000 -#channel_layout 0: 63f #channel_layout_name 0: 7.1 #stream#, dts, pts, duration, size, hash 0, 0, 0, 1024, 24576, 0b24a527d66f2b0cab97f37e4cd79987 diff --git a/tests/ref/fate/dca-xll_71_24_96_768-dmix_2 b/tests/ref/fate/dca-xll_71_24_96_768-dmix_2 index 9bd0256c3..b57af93a1 100644 --- a/tests/ref/fate/dca-xll_71_24_96_768-dmix_2 +++ b/tests/ref/fate/dca-xll_71_24_96_768-dmix_2 @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: pcm_s24le #sample_rate 0: 96000 -#channel_layout 0: 60f #channel_layout_name 0: 5.1(side) #stream#, dts, pts, duration, size, hash 0, 0, 0, 1024, 18432, 0a675f172b0e1a171c46dfaa4f1d0f00 diff --git a/tests/ref/fate/dca-xll_71_24_96_768-dmix_6 b/tests/ref/fate/dca-xll_71_24_96_768-dmix_6 index 9bd0256c3..b57af93a1 100644 --- a/tests/ref/fate/dca-xll_71_24_96_768-dmix_6 +++ b/tests/ref/fate/dca-xll_71_24_96_768-dmix_6 @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: pcm_s24le #sample_rate 0: 96000 -#channel_layout 0: 60f #channel_layout_name 0: 5.1(side) #stream#, dts, pts, duration, size, hash 0, 0, 0, 1024, 18432, 0a675f172b0e1a171c46dfaa4f1d0f00 diff --git a/tests/ref/fate/dca-xll_x96_51_24_96_1509 b/tests/ref/fate/dca-xll_x96_51_24_96_1509 index bc83f793a..838b1dea5 100644 --- a/tests/ref/fate/dca-xll_x96_51_24_96_1509 +++ b/tests/ref/fate/dca-xll_x96_51_24_96_1509 @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: pcm_s24le #sample_rate 0: 96000 -#channel_layout 0: 60f #channel_layout_name 0: 5.1(side) #stream#, dts, pts, duration, size, hash 0, 0, 0, 1024, 18432, f9debe3f07be68533bf0295e3d2ba68a diff --git a/tests/ref/fate/dca-xll_x96_51_24_96_1509-dmix_2 b/tests/ref/fate/dca-xll_x96_51_24_96_1509-dmix_2 index bc83f793a..838b1dea5 100644 --- a/tests/ref/fate/dca-xll_x96_51_24_96_1509-dmix_2 +++ b/tests/ref/fate/dca-xll_x96_51_24_96_1509-dmix_2 @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: pcm_s24le #sample_rate 0: 96000 -#channel_layout 0: 60f #channel_layout_name 0: 5.1(side) #stream#, dts, pts, duration, size, hash 0, 0, 0, 1024, 18432, f9debe3f07be68533bf0295e3d2ba68a diff --git a/tests/ref/fate/dca-xll_x96_51_24_96_1509-dmix_6 b/tests/ref/fate/dca-xll_x96_51_24_96_1509-dmix_6 index bc83f793a..838b1dea5 100644 --- a/tests/ref/fate/dca-xll_x96_51_24_96_1509-dmix_6 +++ b/tests/ref/fate/dca-xll_x96_51_24_96_1509-dmix_6 @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: pcm_s24le #sample_rate 0: 96000 -#channel_layout 0: 60f #channel_layout_name 0: 5.1(side) #stream#, dts, pts, duration, size, hash 0, 0, 0, 1024, 18432, f9debe3f07be68533bf0295e3d2ba68a diff --git a/tests/ref/fate/dca-xll_xch_61_24_48_768 b/tests/ref/fate/dca-xll_xch_61_24_48_768 index 19816d93d..c0eb4aed5 100644 --- a/tests/ref/fate/dca-xll_xch_61_24_48_768 +++ b/tests/ref/fate/dca-xll_xch_61_24_48_768 @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: pcm_s24le #sample_rate 0: 48000 -#channel_layout 0: 70f #channel_layout_name 0: 6.1 #stream#, dts, pts, duration, size, hash 0, 0, 0, 512, 10752, c3c5b236c266a9090378def1ad497a21 diff --git a/tests/ref/fate/dca-xll_xch_61_24_48_768-dmix_2 b/tests/ref/fate/dca-xll_xch_61_24_48_768-dmix_2 index 1f6989fbe..0e69ebcf9 100644 --- a/tests/ref/fate/dca-xll_xch_61_24_48_768-dmix_2 +++ b/tests/ref/fate/dca-xll_xch_61_24_48_768-dmix_2 @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: pcm_s24le #sample_rate 0: 48000 -#channel_layout 0: 60f #channel_layout_name 0: 5.1(side) #stream#, dts, pts, duration, size, hash 0, 0, 0, 512, 9216, 652c4e61f9abe9fba9de792242e2d31d diff --git a/tests/ref/fate/dca-xll_xch_61_24_48_768-dmix_6 b/tests/ref/fate/dca-xll_xch_61_24_48_768-dmix_6 index 1f6989fbe..0e69ebcf9 100644 --- a/tests/ref/fate/dca-xll_xch_61_24_48_768-dmix_6 +++ b/tests/ref/fate/dca-xll_xch_61_24_48_768-dmix_6 @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: pcm_s24le #sample_rate 0: 48000 -#channel_layout 0: 60f #channel_layout_name 0: 5.1(side) #stream#, dts, pts, duration, size, hash 0, 0, 0, 512, 9216, 652c4e61f9abe9fba9de792242e2d31d diff --git a/tests/ref/fate/dcinema-encode b/tests/ref/fate/dcinema-encode index cc53488be..471820dbd 100644 --- a/tests/ref/fate/dcinema-encode +++ b/tests/ref/fate/dcinema-encode @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 96000 -#channel_layout 0: 60f #channel_layout_name 0: 5.1(side) #stream#, dts, pts, duration, size, hash 0, 0, 0, 341, 4092, 697cddfcd0e21f24782af0705b7048f3 diff --git a/tests/ref/fate/delphine-cin-audio b/tests/ref/fate/delphine-cin-audio index 6fdc8048e..c144dc68f 100644 --- a/tests/ref/fate/delphine-cin-audio +++ b/tests/ref/fate/delphine-cin-audio @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 22050 -#channel_layout 0: 4 #channel_layout_name 0: mono 0, 0, 0, 88224, 176448, 0x541ddc55 0, 88224, 88224, 1838, 3676, 0xaf455081 diff --git a/tests/ref/fate/dpcm-idroq b/tests/ref/fate/dpcm-idroq index fb45ace2c..98b50a1f8 100644 --- a/tests/ref/fate/dpcm-idroq +++ b/tests/ref/fate/dpcm-idroq @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 22050 -#channel_layout 0: 3 #channel_layout_name 0: stereo 0, 0, 0, 7456, 29824, 0x77e265b7 0, 7456, 7456, 736, 2944, 0x8dcdf50b diff --git a/tests/ref/fate/dpcm-interplay b/tests/ref/fate/dpcm-interplay index 720a98f38..207ef48e9 100644 --- a/tests/ref/fate/dpcm-interplay +++ b/tests/ref/fate/dpcm-interplay @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 22050 -#channel_layout 0: 3 #channel_layout_name 0: stereo 0, 0, 0, 1462, 5848, 0xea04292b 0, 1462, 1462, 1472, 5888, 0x0e59e942 diff --git a/tests/ref/fate/dss-lp b/tests/ref/fate/dss-lp index ab1d5344b..9b08345d0 100644 --- a/tests/ref/fate/dss-lp +++ b/tests/ref/fate/dss-lp @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 8000 -#channel_layout 0: 4 #channel_layout_name 0: mono 0, 0, 0, 240, 480, 0xf1107658 0, 240, 240, 240, 480, 0x50dee179 diff --git a/tests/ref/fate/dss-sp b/tests/ref/fate/dss-sp index f407ce7da..0984f11eb 100644 --- a/tests/ref/fate/dss-sp +++ b/tests/ref/fate/dss-sp @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 11025 -#channel_layout 0: 4 #channel_layout_name 0: mono 0, 0, 0, 264, 528, 0xa2579e96 0, 264, 264, 264, 528, 0xf9b23172 diff --git a/tests/ref/fate/ffmpeg-attached_pics b/tests/ref/fate/ffmpeg-attached_pics index 48c7ced36..515bef3ca 100644 --- a/tests/ref/fate/ffmpeg-attached_pics +++ b/tests/ref/fate/ffmpeg-attached_pics @@ -7,7 +7,6 @@ #media_type 1: audio #codec_id 1: pcm_s16le #sample_rate 1: 44100 -#channel_layout 1: 3 #channel_layout_name 1: stereo 0, 0, 0, 1, 120000, 0x748cc771 1, 0, 0, 4096, 16384, 0x00000000 diff --git a/tests/ref/fate/ffmpeg-filter_complex_audio b/tests/ref/fate/ffmpeg-filter_complex_audio index c42467506..0d1f65004 100644 --- a/tests/ref/fate/ffmpeg-filter_complex_audio +++ b/tests/ref/fate/ffmpeg-filter_complex_audio @@ -2,7 +2,6 @@ #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 diff --git a/tests/ref/fate/ffmpeg-fix_sub_duration b/tests/ref/fate/ffmpeg-fix_sub_duration new file mode 100644 index 000000000..9cd36d488 --- /dev/null +++ b/tests/ref/fate/ffmpeg-fix_sub_duration @@ -0,0 +1,31 @@ +1 +00:00:00,968 --> 00:00:01,168 +{\an7}( + +2 +00:00:01,168 --> 00:00:01,368 +{\an7}( inaudibl + +3 +00:00:01,368 --> 00:00:01,568 +{\an7}( inaudible radio chat + +4 +00:00:01,568 --> 00:00:03,103 +{\an7}( inaudible radio chatter ) + +5 +00:00:03,103 --> 00:00:03,303 +{\an7}( inaudible radio chatter ) +>> + +6 +00:00:03,303 --> 00:00:03,503 +{\an7}( inaudible radio chatter ) +>> Safety rema + +7 +00:00:03,504 --> 00:00:03,704 +{\an7}( inaudible radio chatter ) +>> Safety remains our numb + diff --git a/tests/ref/fate/ffmpeg-setts-bsf b/tests/ref/fate/ffmpeg-setts-bsf new file mode 100644 index 000000000..884e45d6e --- /dev/null +++ b/tests/ref/fate/ffmpeg-setts-bsf @@ -0,0 +1,46 @@ +#extradata 0: 794, 0x6c0b3aa4 +#tb 0: 1/100000 +#media_type 0: video +#codec_id 0: apng +#dimensions 0: 150x150 +#sar 0: 0/1 +0, 0, 0, 2000, 2053, 0xe7cffa8e +0, 2000, 2000, 2000, 596, 0xc9020463, F=0x0 +0, 4000, 4000, 2000, 593, 0x20de0bf4, F=0x0 +0, 6000, 6000, 2000, 590, 0x03940ac4, F=0x0 +0, 8000, 8000, 2000, 612, 0xae18161f, F=0x0 +0, 10000, 10000, 2000, 431, 0xceeac2db, F=0x0 +0, 12000, 12000, 2000, 531, 0x7ff9ebd0, F=0x0 +0, 14000, 14000, 2000, 484, 0x1e1de38a, F=0x0 +0, 16000, 16000, 2000, 476, 0x3869d31a, F=0x0 +0, 18000, 18000, 2000, 482, 0x9b5be0c9, F=0x0 +0, 20000, 20000, 2000, 448, 0x09e7c9ed, F=0x0 +0, 22000, 22000, 2000, 493, 0x1460e707, F=0x0 +0, 24000, 24000, 2000, 514, 0x3a99e6f3, F=0x0 +0, 26000, 26000, 2000, 590, 0x68751289, F=0x0 +0, 28000, 28000, 2000, 552, 0x58def4d3, F=0x0 +0, 30000, 30000, 2000, 453, 0x643cbf39, F=0x0 +0, 32000, 32000, 2000, 586, 0x5a4b0a3f, F=0x0 +0, 34000, 34000, 2000, 563, 0x5fb5fb41, F=0x0 +0, 36000, 36000, 2000, 627, 0xed7d1ff1, F=0x0 +0, 38000, 38000, 2000, 591, 0xd4012076, F=0x0 +0, 40000, 40000, 2000, 440, 0xd210b267, F=0x0 +0, 42000, 42000, 2000, 590, 0xec410e2e, F=0x0 +0, 44000, 44000, 2000, 569, 0x782d0227, F=0x0 +0, 46000, 46000, 2000, 536, 0x5305ff99, F=0x0 +0, 48000, 48000, 2000, 581, 0x2933f6c7, F=0x0 +0, 50000, 50000, 2000, 475, 0xa9a5ce1c, F=0x0 +0, 52000, 52000, 2000, 532, 0x5b9cf7bb, F=0x0 +0, 54000, 54000, 2000, 532, 0x3408e7e9, F=0x0 +0, 56000, 56000, 2000, 551, 0x1be00219, F=0x0 +0, 58000, 58000, 2000, 456, 0x55b1cc1b, F=0x0 +0, 60000, 60000, 2000, 416, 0x794abab6, F=0x0 +0, 62000, 62000, 2000, 525, 0x500eefad, F=0x0 +0, 64000, 64000, 2000, 531, 0x7273f14b, F=0x0 +0, 66000, 66000, 2000, 568, 0x4837fdc9, F=0x0 +0, 68000, 68000, 2000, 577, 0xed530268, F=0x0 +0, 70000, 70000, 2000, 518, 0xc9c1e644, F=0x0 +0, 72000, 72000, 2000, 572, 0x81840ac9, F=0x0 +0, 74000, 74000, 2000, 494, 0x678be2ae, F=0x0 +0, 76000, 76000, 2000, 560, 0x0174f8b9, F=0x0 +0, 78000, 78000, 2000, 578, 0xef800564, F=0x0 diff --git a/tests/ref/fate/fifo b/tests/ref/fate/fifo index 2b18ed5ff..1b0e00541 100644 --- a/tests/ref/fate/fifo +++ b/tests/ref/fate/fifo @@ -1,29 +1,3 @@ --12: 1 --11: 2 --10: 3 --9: 4 --8: 5 --7: 6 --6: 7 --5: 8 --4: 9 --3: 10 --2: 11 --1: 12 -0: 0 -1: 1 -2: 2 -3: 3 -4: 4 -5: 5 -6: 6 -7: 7 -8: 8 -9: 9 -10: 10 -11: 11 -12: 12 - 0: 0 1: 1 2: 2 diff --git a/tests/ref/fate/filter-acrossfade b/tests/ref/fate/filter-acrossfade index 8d524c4d2..8737d9da5 100644 --- a/tests/ref/fate/filter-acrossfade +++ b/tests/ref/fate/filter-acrossfade @@ -2,7 +2,6 @@ #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, 888, 3552, 0x592ce6cc 0, 888, 888, 1024, 4096, 0x20f6f6a9 diff --git a/tests/ref/fate/filter-adelay b/tests/ref/fate/filter-adelay index e3ff76360..6370f66f7 100644 --- a/tests/ref/fate/filter-adelay +++ b/tests/ref/fate/filter-adelay @@ -2,7 +2,6 @@ #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, 0x9d7bf760 0, 1024, 1024, 1024, 4096, 0xdf42c46b diff --git a/tests/ref/fate/filter-aecho b/tests/ref/fate/filter-aecho index 2c88c37fb..706e17e10 100644 --- a/tests/ref/fate/filter-aecho +++ b/tests/ref/fate/filter-aecho @@ -2,7 +2,6 @@ #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, 0x3019edd5 0, 1024, 1024, 1024, 4096, 0x2df2fe2f diff --git a/tests/ref/fate/filter-aemphasis-50fm b/tests/ref/fate/filter-aemphasis-50fm index 649cd449b..d28a7538b 100644 --- a/tests/ref/fate/filter-aemphasis-50fm +++ b/tests/ref/fate/filter-aemphasis-50fm @@ -2,7 +2,6 @@ #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, 0xb9c5fefd 0, 1024, 1024, 1024, 4096, 0xb2ae0a90 diff --git a/tests/ref/fate/filter-aemphasis-75kf b/tests/ref/fate/filter-aemphasis-75kf index 5705e9833..765f32ec4 100644 --- a/tests/ref/fate/filter-aemphasis-75kf +++ b/tests/ref/fate/filter-aemphasis-75kf @@ -2,7 +2,6 @@ #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, 0x7b2101ec 0, 1024, 1024, 1024, 4096, 0x5c16fc93 diff --git a/tests/ref/fate/filter-afade-esin b/tests/ref/fate/filter-afade-esin index f9b910c69..41dfaeb56 100644 --- a/tests/ref/fate/filter-afade-esin +++ b/tests/ref/fate/filter-afade-esin @@ -2,7 +2,6 @@ #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, 0x06e0d68a 0, 1024, 1024, 1024, 4096, 0xb325d915 diff --git a/tests/ref/fate/filter-afade-exp b/tests/ref/fate/filter-afade-exp index a0c519cd8..2a75db198 100644 --- a/tests/ref/fate/filter-afade-exp +++ b/tests/ref/fate/filter-afade-exp @@ -2,7 +2,6 @@ #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, 0x00000000 0, 1024, 1024, 1024, 4096, 0x00000000 diff --git a/tests/ref/fate/filter-afade-hsin b/tests/ref/fate/filter-afade-hsin index 2c6a0e3a1..b95bac047 100644 --- a/tests/ref/fate/filter-afade-hsin +++ b/tests/ref/fate/filter-afade-hsin @@ -2,7 +2,6 @@ #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, 0x2042232e 0, 1024, 1024, 1024, 4096, 0x2c073cf7 diff --git a/tests/ref/fate/filter-afade-iqsin b/tests/ref/fate/filter-afade-iqsin index fc22baf91..9caa3203a 100644 --- a/tests/ref/fate/filter-afade-iqsin +++ b/tests/ref/fate/filter-afade-iqsin @@ -2,7 +2,6 @@ #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, 0x220e908d 0, 1024, 1024, 1024, 4096, 0xdd65002e diff --git a/tests/ref/fate/filter-afade-log b/tests/ref/fate/filter-afade-log index 99ac0b36d..f3ba265a6 100644 --- a/tests/ref/fate/filter-afade-log +++ b/tests/ref/fate/filter-afade-log @@ -2,7 +2,6 @@ #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, 0xf01adbd3 0, 1024, 1024, 1024, 4096, 0xbbe10f8e diff --git a/tests/ref/fate/filter-afade-qsin b/tests/ref/fate/filter-afade-qsin index 026fbbcc4..df3005edb 100644 --- a/tests/ref/fate/filter-afade-qsin +++ b/tests/ref/fate/filter-afade-qsin @@ -2,7 +2,6 @@ #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, 0xd977ce0f 0, 1024, 1024, 1024, 4096, 0x9333f5b1 diff --git a/tests/ref/fate/filter-agate b/tests/ref/fate/filter-agate index b6e732a86..e2d9c2ac2 100644 --- a/tests/ref/fate/filter-agate +++ b/tests/ref/fate/filter-agate @@ -2,7 +2,6 @@ #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, 0x1af20090 0, 1024, 1024, 1024, 4096, 0x0b05ef2d diff --git a/tests/ref/fate/filter-alimiter b/tests/ref/fate/filter-alimiter index aef9765a8..56cfb614d 100644 --- a/tests/ref/fate/filter-alimiter +++ b/tests/ref/fate/filter-alimiter @@ -2,7 +2,6 @@ #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, 0xd4194af4 0, 1024, 1024, 1024, 4096, 0x686af4ab diff --git a/tests/ref/fate/filter-amerge b/tests/ref/fate/filter-amerge index b3e5eb50c..89c07029f 100644 --- a/tests/ref/fate/filter-amerge +++ b/tests/ref/fate/filter-amerge @@ -2,7 +2,6 @@ #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, 2048, 8192, 0x120efa65 0, 2048, 2048, 2048, 8192, 0x7b3cebf7 diff --git a/tests/ref/fate/filter-anequalizer b/tests/ref/fate/filter-anequalizer index caed836bd..250c9ede9 100644 --- a/tests/ref/fate/filter-anequalizer +++ b/tests/ref/fate/filter-anequalizer @@ -2,7 +2,6 @@ #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, 0x8e1bf8e0 0, 1024, 1024, 1024, 4096, 0xe315f564 diff --git a/tests/ref/fate/filter-apad b/tests/ref/fate/filter-apad index 9bf662d46..79ed050a4 100644 --- a/tests/ref/fate/filter-apad +++ b/tests/ref/fate/filter-apad @@ -2,7 +2,6 @@ #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, 0x29e3eecf 0, 1024, 1024, 1024, 4096, 0x18390b96 diff --git a/tests/ref/fate/filter-asetnsamples-nopad b/tests/ref/fate/filter-asetnsamples-nopad index c1cc01a71..e5306d451 100644 --- a/tests/ref/fate/filter-asetnsamples-nopad +++ b/tests/ref/fate/filter-asetnsamples-nopad @@ -2,7 +2,6 @@ #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, 512, 2048, 0xd2dbf701 0, 512, 512, 512, 2048, 0xdb22f7bf diff --git a/tests/ref/fate/filter-asetnsamples-pad b/tests/ref/fate/filter-asetnsamples-pad index 23cf11b8a..80f6e1d57 100644 --- a/tests/ref/fate/filter-asetnsamples-pad +++ b/tests/ref/fate/filter-asetnsamples-pad @@ -2,7 +2,6 @@ #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, 512, 2048, 0xd2dbf701 0, 512, 512, 512, 2048, 0xdb22f7bf diff --git a/tests/ref/fate/filter-asetrate b/tests/ref/fate/filter-asetrate index 6ffa94036..4b5e87d69 100644 --- a/tests/ref/fate/filter-asetrate +++ b/tests/ref/fate/filter-asetrate @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 20000 -#channel_layout 0: 3 #channel_layout_name 0: stereo 0, 0, 0, 1024, 4096, 0x29e3eecf 0, 1024, 1024, 1024, 4096, 0x18390b96 diff --git a/tests/ref/fate/filter-atrim-duration b/tests/ref/fate/filter-atrim-duration index fafda1717..1c4cf5712 100644 --- a/tests/ref/fate/filter-atrim-duration +++ b/tests/ref/fate/filter-atrim-duration @@ -2,6 +2,5 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 44100 -#channel_layout 0: 3 #channel_layout_name 0: stereo 0, 4410, 4410, 441, 1764, 0x61e374f7 diff --git a/tests/ref/fate/filter-atrim-mixed b/tests/ref/fate/filter-atrim-mixed index 4cd1d8004..7f1663940 100644 --- a/tests/ref/fate/filter-atrim-mixed +++ b/tests/ref/fate/filter-atrim-mixed @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 44100 -#channel_layout 0: 3 #channel_layout_name 0: stereo 0, 1025, 1025, 1023, 4092, 0x78560a4c 0, 2048, 2048, 1024, 4096, 0xc477fa99 diff --git a/tests/ref/fate/filter-atrim-samples b/tests/ref/fate/filter-atrim-samples index 2d8c9a523..74dc5d3b2 100644 --- a/tests/ref/fate/filter-atrim-samples +++ b/tests/ref/fate/filter-atrim-samples @@ -2,6 +2,5 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 44100 -#channel_layout 0: 3 #channel_layout_name 0: stereo 0, 26, 26, 54, 216, 0x6b376c6c diff --git a/tests/ref/fate/filter-atrim-time b/tests/ref/fate/filter-atrim-time index a0c626c4b..2f8d87ecb 100644 --- a/tests/ref/fate/filter-atrim-time +++ b/tests/ref/fate/filter-atrim-time @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 44100 -#channel_layout 0: 3 #channel_layout_name 0: stereo 0, 4410, 4410, 710, 2840, 0x658982a3 0, 5120, 5120, 1024, 4096, 0xfd6a0070 diff --git a/tests/ref/fate/filter-chorus b/tests/ref/fate/filter-chorus index 211e60ecb..97c791965 100644 --- a/tests/ref/fate/filter-chorus +++ b/tests/ref/fate/filter-chorus @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 22050 -#channel_layout 0: 4 #channel_layout_name 0: mono 0, 0, 0, 2048, 4096, 0x1fc6f1f1 0, 2048, 2048, 2048, 4096, 0xe5f7f442 diff --git a/tests/ref/fate/filter-chromashift-smear b/tests/ref/fate/filter-chromashift-smear new file mode 100644 index 000000000..949cc6cd0 --- /dev/null +++ b/tests/ref/fate/filter-chromashift-smear @@ -0,0 +1,10 @@ +#tb 0: 1/5 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 320x240 +#sar 0: 1/1 +0, 0, 0, 1, 115200, 0x39a9f743 +0, 1, 1, 1, 115200, 0x7749d86c +0, 2, 2, 1, 115200, 0x636dd339 +0, 3, 3, 1, 115200, 0x4c14ef30 +0, 4, 4, 1, 115200, 0x249bf65a diff --git a/tests/ref/fate/filter-chromashift-wrap b/tests/ref/fate/filter-chromashift-wrap new file mode 100644 index 000000000..383b24fc6 --- /dev/null +++ b/tests/ref/fate/filter-chromashift-wrap @@ -0,0 +1,10 @@ +#tb 0: 1/5 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 320x240 +#sar 0: 1/1 +0, 0, 0, 1, 115200, 0xd3940ff3 +0, 1, 1, 1, 115200, 0x4e4cf17d +0, 2, 2, 1, 115200, 0x2d67ec4a +0, 3, 3, 1, 115200, 0xf18d0848 +0, 4, 4, 1, 115200, 0x00ed0f82 diff --git a/tests/ref/fate/filter-compand b/tests/ref/fate/filter-compand index ac9095f4e..285416172 100644 --- a/tests/ref/fate/filter-compand +++ b/tests/ref/fate/filter-compand @@ -2,7 +2,6 @@ #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, 0xfc10e61b 0, 1024, 1024, 1024, 4096, 0x8801ef13 diff --git a/tests/ref/fate/filter-concat b/tests/ref/fate/filter-concat index 022697ec5..42879a45e 100644 --- a/tests/ref/fate/filter-concat +++ b/tests/ref/fate/filter-concat @@ -7,7 +7,6 @@ #media_type 1: audio #codec_id 1: pcm_s16le #sample_rate 1: 44100 -#channel_layout 1: 4 #channel_layout_name 1: mono 0, 0, 0, 1, 230400, 0x88c4d19a 1, 0, 0, 1024, 2048, 0xb3f10192 diff --git a/tests/ref/fate/filter-concat-vfr b/tests/ref/fate/filter-concat-vfr index 0dece67a0..7c5e12e09 100644 --- a/tests/ref/fate/filter-concat-vfr +++ b/tests/ref/fate/filter-concat-vfr @@ -7,7 +7,6 @@ #media_type 1: audio #codec_id 1: pcm_s16le #sample_rate 1: 44100 -#channel_layout 1: 4 #channel_layout_name 1: mono 0, 0, 0, 0, 230400, 0x88c4d19a 1, 0, 0, 1024, 2048, 0xb3f10192 diff --git a/tests/ref/fate/filter-crystalizer b/tests/ref/fate/filter-crystalizer new file mode 100644 index 000000000..ed50fb978 --- /dev/null +++ b/tests/ref/fate/filter-crystalizer @@ -0,0 +1,264 @@ +#tb 0: 1/44100 +#media_type 0: audio +#codec_id 0: pcm_s16le +#sample_rate 0: 44100 +#channel_layout_name 0: stereo +0, 0, 0, 1024, 4096, 0x29e3eecf +0, 1024, 1024, 1024, 4096, 0x18390b96 +0, 2048, 2048, 1024, 4096, 0xc477fa99 +0, 3072, 3072, 1024, 4096, 0x3bc0f14f +0, 4096, 4096, 1024, 4096, 0x2379ed91 +0, 5120, 5120, 1024, 4096, 0xfd6a0070 +0, 6144, 6144, 1024, 4096, 0x0b01f4cf +0, 7168, 7168, 1024, 4096, 0x6716fd93 +0, 8192, 8192, 1024, 4096, 0x1840f25b +0, 9216, 9216, 1024, 4096, 0x9c1ffaf1 +0, 10240, 10240, 1024, 4096, 0xcbedefaf +0, 11264, 11264, 1024, 4096, 0x3e050390 +0, 12288, 12288, 1024, 4096, 0xb30e0090 +0, 13312, 13312, 1024, 4096, 0x26b8f75b +0, 14336, 14336, 1024, 4096, 0xd706e311 +0, 15360, 15360, 1024, 4096, 0x0c480138 +0, 16384, 16384, 1024, 4096, 0x6c9a0216 +0, 17408, 17408, 1024, 4096, 0x7abce54f +0, 18432, 18432, 1024, 4096, 0xda45f63f +0, 19456, 19456, 1024, 4096, 0x50d5ff87 +0, 20480, 20480, 1024, 4096, 0x59be0352 +0, 21504, 21504, 1024, 4096, 0xa61af077 +0, 22528, 22528, 1024, 4096, 0x84c4fc07 +0, 23552, 23552, 1024, 4096, 0x4a35f345 +0, 24576, 24576, 1024, 4096, 0xbb65fa81 +0, 25600, 25600, 1024, 4096, 0xf6c7f5e5 +0, 26624, 26624, 1024, 4096, 0xd3270138 +0, 27648, 27648, 1024, 4096, 0x4782ed53 +0, 28672, 28672, 1024, 4096, 0xe308f055 +0, 29696, 29696, 1024, 4096, 0x7d33f97d +0, 30720, 30720, 1024, 4096, 0xb8b00dd4 +0, 31744, 31744, 1024, 4096, 0x7ff7efab +0, 32768, 32768, 1024, 4096, 0x29e3eecf +0, 33792, 33792, 1024, 4096, 0x18390b96 +0, 34816, 34816, 1024, 4096, 0xc477fa99 +0, 35840, 35840, 1024, 4096, 0x3bc0f14f +0, 36864, 36864, 1024, 4096, 0x2379ed91 +0, 37888, 37888, 1024, 4096, 0xfd6a0070 +0, 38912, 38912, 1024, 4096, 0x0b01f4cf +0, 39936, 39936, 1024, 4096, 0x6716fd93 +0, 40960, 40960, 1024, 4096, 0x1840f25b +0, 41984, 41984, 1024, 4096, 0x9c1ffaf1 +0, 43008, 43008, 1024, 4096, 0xcbedefaf +0, 44032, 44032, 1024, 4096, 0xda37d691 +0, 45056, 45056, 1024, 4096, 0x7193ecbf +0, 46080, 46080, 1024, 4096, 0x6e4a0a36 +0, 47104, 47104, 1024, 4096, 0x61cfe70d +0, 48128, 48128, 1024, 4096, 0xc19ffa15 +0, 49152, 49152, 1024, 4096, 0x7b32fb3d +0, 50176, 50176, 1024, 4096, 0xdacefd3f +0, 51200, 51200, 1024, 4096, 0x3964f64d +0, 52224, 52224, 1024, 4096, 0xdcf2edad +0, 53248, 53248, 1024, 4096, 0x1367f69b +0, 54272, 54272, 1024, 4096, 0xd4c6f7b9 +0, 55296, 55296, 1024, 4096, 0x9e041186 +0, 56320, 56320, 1024, 4096, 0xe939edd7 +0, 57344, 57344, 1024, 4096, 0xa932336a +0, 58368, 58368, 1024, 4096, 0x5f510e28 +0, 59392, 59392, 1024, 4096, 0x4b8501c8 +0, 60416, 60416, 1024, 4096, 0xfbc30250 +0, 61440, 61440, 1024, 4096, 0x5e7fd855 +0, 62464, 62464, 1024, 4096, 0x8ef1f265 +0, 63488, 63488, 1024, 4096, 0x9f7601c2 +0, 64512, 64512, 1024, 4096, 0xb400f0b7 +0, 65536, 65536, 1024, 4096, 0x4c91e10b +0, 66560, 66560, 1024, 4096, 0x3f41fe61 +0, 67584, 67584, 1024, 4096, 0x74fff9b9 +0, 68608, 68608, 1024, 4096, 0x18bbf5a5 +0, 69632, 69632, 1024, 4096, 0x51a70180 +0, 70656, 70656, 1024, 4096, 0x29f3e8c5 +0, 71680, 71680, 1024, 4096, 0x562efdb9 +0, 72704, 72704, 1024, 4096, 0xa2e006e0 +0, 73728, 73728, 1024, 4096, 0xa1bff541 +0, 74752, 74752, 1024, 4096, 0xd95b0012 +0, 75776, 75776, 1024, 4096, 0xd93e0912 +0, 76800, 76800, 1024, 4096, 0x6c2a1d88 +0, 77824, 77824, 1024, 4096, 0xb4d8fb8b +0, 78848, 78848, 1024, 4096, 0xf14b0492 +0, 79872, 79872, 1024, 4096, 0x1c7be7b7 +0, 80896, 80896, 1024, 4096, 0xc181f877 +0, 81920, 81920, 1024, 4096, 0xba132d14 +0, 82944, 82944, 1024, 4096, 0xabae2d9a +0, 83968, 83968, 1024, 4096, 0xb07fff15 +0, 84992, 84992, 1024, 4096, 0xa0c1ff2d +0, 86016, 86016, 1024, 4096, 0x19f7fd1f +0, 87040, 87040, 1024, 4096, 0xcb6d11a4 +0, 88064, 88064, 1024, 4096, 0x166ac8b7 +0, 89088, 89088, 1024, 4096, 0xe68dda8f +0, 90112, 90112, 1024, 4096, 0xe457b505 +0, 91136, 91136, 1024, 4096, 0xda25a409 +0, 92160, 92160, 1024, 4096, 0x5b5d9d3b +0, 93184, 93184, 1024, 4096, 0xa61eb13d +0, 94208, 94208, 1024, 4096, 0xac93b66f +0, 95232, 95232, 1024, 4096, 0xc7aeb33f +0, 96256, 96256, 1024, 4096, 0x52cccfb5 +0, 97280, 97280, 1024, 4096, 0x4e4cf487 +0, 98304, 98304, 1024, 4096, 0x19c07f35 +0, 99328, 99328, 1024, 4096, 0x63ecd34f +0, 100352, 100352, 1024, 4096, 0x122aec53 +0, 101376, 101376, 1024, 4096, 0x6581c0ad +0, 102400, 102400, 1024, 4096, 0x640edb15 +0, 103424, 103424, 1024, 4096, 0x5d66c66f +0, 104448, 104448, 1024, 4096, 0x069e9d35 +0, 105472, 105472, 1024, 4096, 0x5c9fd0e9 +0, 106496, 106496, 1024, 4096, 0x72468667 +0, 107520, 107520, 1024, 4096, 0x6e6dd02b +0, 108544, 108544, 1024, 4096, 0x93edce33 +0, 109568, 109568, 1024, 4096, 0xcdfbd519 +0, 110592, 110592, 1024, 4096, 0x8463f2bb +0, 111616, 111616, 1024, 4096, 0x5ca6f869 +0, 112640, 112640, 1024, 4096, 0x099a0398 +0, 113664, 113664, 1024, 4096, 0xa7fa10f0 +0, 114688, 114688, 1024, 4096, 0x28caddd3 +0, 115712, 115712, 1024, 4096, 0x4852ef8b +0, 116736, 116736, 1024, 4096, 0x0250ee7b +0, 117760, 117760, 1024, 4096, 0x9583da21 +0, 118784, 118784, 1024, 4096, 0x7365fb33 +0, 119808, 119808, 1024, 4096, 0x28c82066 +0, 120832, 120832, 1024, 4096, 0x94650be4 +0, 121856, 121856, 1024, 4096, 0xeb21f8eb +0, 122880, 122880, 1024, 4096, 0xcd88f455 +0, 123904, 123904, 1024, 4096, 0x66a9efaf +0, 124928, 124928, 1024, 4096, 0x5500c6ed +0, 125952, 125952, 1024, 4096, 0x0ee0c62d +0, 126976, 126976, 1024, 4096, 0x34d30762 +0, 128000, 128000, 1024, 4096, 0x8c0dec9f +0, 129024, 129024, 1024, 4096, 0x790011d8 +0, 130048, 130048, 1024, 4096, 0xb76a1136 +0, 131072, 131072, 1024, 4096, 0x7dddfea7 +0, 132096, 132096, 1024, 4096, 0xdfa3ed49 +0, 133120, 133120, 1024, 4096, 0xc129f54e +0, 134144, 134144, 1024, 4096, 0x9a86f077 +0, 135168, 135168, 1024, 4096, 0xc9eef209 +0, 136192, 136192, 1024, 4096, 0x72d4029b +0, 137216, 137216, 1024, 4096, 0x8ec20590 +0, 138240, 138240, 1024, 4096, 0xd48f18ed +0, 139264, 139264, 1024, 4096, 0xd807eadc +0, 140288, 140288, 1024, 4096, 0x1e2bea09 +0, 141312, 141312, 1024, 4096, 0x937af12e +0, 142336, 142336, 1024, 4096, 0xdedbf303 +0, 143360, 143360, 1024, 4096, 0xdc75df88 +0, 144384, 144384, 1024, 4096, 0x1845ffd6 +0, 145408, 145408, 1024, 4096, 0x20e8150c +0, 146432, 146432, 1024, 4096, 0x5ea7eeef +0, 147456, 147456, 1024, 4096, 0x4c7efa21 +0, 148480, 148480, 1024, 4096, 0x8b97e30e +0, 149504, 149504, 1024, 4096, 0xe5040228 +0, 150528, 150528, 1024, 4096, 0x6283f78c +0, 151552, 151552, 1024, 4096, 0xe7100140 +0, 152576, 152576, 1024, 4096, 0x9ea6f9b2 +0, 153600, 153600, 1024, 4096, 0x5f0e1563 +0, 154624, 154624, 1024, 4096, 0x510bf18e +0, 155648, 155648, 1024, 4096, 0x5f4fe425 +0, 156672, 156672, 1024, 4096, 0x507af3c0 +0, 157696, 157696, 1024, 4096, 0xbf14ddc6 +0, 158720, 158720, 1024, 4096, 0x1871ed69 +0, 159744, 159744, 1024, 4096, 0xc349ef9f +0, 160768, 160768, 1024, 4096, 0x4e2c1834 +0, 161792, 161792, 1024, 4096, 0x2383fe04 +0, 162816, 162816, 1024, 4096, 0x6626f415 +0, 163840, 163840, 1024, 4096, 0x283be379 +0, 164864, 164864, 1024, 4096, 0xc76c0ceb +0, 165888, 165888, 1024, 4096, 0xa0b8040f +0, 166912, 166912, 1024, 4096, 0x2535eb6d +0, 167936, 167936, 1024, 4096, 0xeb180bb5 +0, 168960, 168960, 1024, 4096, 0xbc5cf059 +0, 169984, 169984, 1024, 4096, 0x1862f1ac +0, 171008, 171008, 1024, 4096, 0x9cc2ea2b +0, 172032, 172032, 1024, 4096, 0xbb9ae754 +0, 173056, 173056, 1024, 4096, 0x716debb5 +0, 174080, 174080, 1024, 4096, 0xff3aff2a +0, 175104, 175104, 1024, 4096, 0x755dfa5c +0, 176128, 176128, 1024, 4096, 0x3b830605 +0, 177152, 177152, 1024, 4096, 0x0030dc9e +0, 178176, 178176, 1024, 4096, 0xb017fd54 +0, 179200, 179200, 1024, 4096, 0x5c7dfa2e +0, 180224, 180224, 1024, 4096, 0x7887e599 +0, 181248, 181248, 1024, 4096, 0xb730e72f +0, 182272, 182272, 1024, 4096, 0x6bb3fae4 +0, 183296, 183296, 1024, 4096, 0xcc08fc36 +0, 184320, 184320, 1024, 4096, 0x5afd9ec2 +0, 185344, 185344, 1024, 4096, 0xa1d3e83d +0, 186368, 186368, 1024, 4096, 0x7f96013c +0, 187392, 187392, 1024, 4096, 0x7a0afe31 +0, 188416, 188416, 1024, 4096, 0xa37d1701 +0, 189440, 189440, 1024, 4096, 0x4615ebc2 +0, 190464, 190464, 1024, 4096, 0x217005c1 +0, 191488, 191488, 1024, 4096, 0x1755f789 +0, 192512, 192512, 1024, 4096, 0x83e6db65 +0, 193536, 193536, 1024, 4096, 0x92ab1447 +0, 194560, 194560, 1024, 4096, 0xedbdf383 +0, 195584, 195584, 1024, 4096, 0x4316f6a9 +0, 196608, 196608, 1024, 4096, 0x1a6a0b4c +0, 197632, 197632, 1024, 4096, 0xdfd809b7 +0, 198656, 198656, 1024, 4096, 0x1d2cf5f1 +0, 199680, 199680, 1024, 4096, 0xd366f4a1 +0, 200704, 200704, 1024, 4096, 0x6a2f86e0 +0, 201728, 201728, 1024, 4096, 0xf51f08a9 +0, 202752, 202752, 1024, 4096, 0x05edefa8 +0, 203776, 203776, 1024, 4096, 0x255df2a6 +0, 204800, 204800, 1024, 4096, 0xe881d9e4 +0, 205824, 205824, 1024, 4096, 0x50380523 +0, 206848, 206848, 1024, 4096, 0x8b93eb26 +0, 207872, 207872, 1024, 4096, 0x759cf94c +0, 208896, 208896, 1024, 4096, 0x8474f591 +0, 209920, 209920, 1024, 4096, 0x0030dc9e +0, 210944, 210944, 1024, 4096, 0xb017fd54 +0, 211968, 211968, 1024, 4096, 0x5c7dfa2e +0, 212992, 212992, 1024, 4096, 0x7887e599 +0, 214016, 214016, 1024, 4096, 0xb730e72f +0, 215040, 215040, 1024, 4096, 0x6bb3fae4 +0, 216064, 216064, 1024, 4096, 0xcc08fc36 +0, 217088, 217088, 1024, 4096, 0x5afd9ec2 +0, 218112, 218112, 1024, 4096, 0xa1d3e83d +0, 219136, 219136, 1024, 4096, 0x7f96013c +0, 220160, 220160, 1024, 4096, 0x7a0afe31 +0, 221184, 221184, 1024, 4096, 0xa37d1701 +0, 222208, 222208, 1024, 4096, 0x4615ebc2 +0, 223232, 223232, 1024, 4096, 0x217005c1 +0, 224256, 224256, 1024, 4096, 0x1755f789 +0, 225280, 225280, 1024, 4096, 0x83e6db65 +0, 226304, 226304, 1024, 4096, 0x92ab1447 +0, 227328, 227328, 1024, 4096, 0xedbdf383 +0, 228352, 228352, 1024, 4096, 0x4316f6a9 +0, 229376, 229376, 1024, 4096, 0x1a6a0b4c +0, 230400, 230400, 1024, 4096, 0xdfd809b7 +0, 231424, 231424, 1024, 4096, 0x1d2cf5f1 +0, 232448, 232448, 1024, 4096, 0xd366f4a1 +0, 233472, 233472, 1024, 4096, 0x6a2f86e0 +0, 234496, 234496, 1024, 4096, 0xf51f08a9 +0, 235520, 235520, 1024, 4096, 0x05edefa8 +0, 236544, 236544, 1024, 4096, 0x255df2a6 +0, 237568, 237568, 1024, 4096, 0xe881d9e4 +0, 238592, 238592, 1024, 4096, 0x50380523 +0, 239616, 239616, 1024, 4096, 0x8b93eb26 +0, 240640, 240640, 1024, 4096, 0x759cf94c +0, 241664, 241664, 1024, 4096, 0x8474f591 +0, 242688, 242688, 1024, 4096, 0x0030dc9e +0, 243712, 243712, 1024, 4096, 0xb017fd54 +0, 244736, 244736, 1024, 4096, 0x5c7dfa2e +0, 245760, 245760, 1024, 4096, 0x7887e599 +0, 246784, 246784, 1024, 4096, 0xb730e72f +0, 247808, 247808, 1024, 4096, 0x6bb3fae4 +0, 248832, 248832, 1024, 4096, 0xcc08fc36 +0, 249856, 249856, 1024, 4096, 0x5afd9ec2 +0, 250880, 250880, 1024, 4096, 0xa1d3e83d +0, 251904, 251904, 1024, 4096, 0x7f96013c +0, 252928, 252928, 1024, 4096, 0x7a0afe31 +0, 253952, 253952, 1024, 4096, 0xa37d1701 +0, 254976, 254976, 1024, 4096, 0x4615ebc2 +0, 256000, 256000, 1024, 4096, 0x217005c1 +0, 257024, 257024, 1024, 4096, 0x1755f789 +0, 258048, 258048, 1024, 4096, 0x83e6db65 +0, 259072, 259072, 1024, 4096, 0x92ab1447 +0, 260096, 260096, 1024, 4096, 0xedbdf383 +0, 261120, 261120, 1024, 4096, 0x4316f6a9 +0, 262144, 262144, 1024, 4096, 0x1a6a0b4c +0, 263168, 263168, 1024, 4096, 0xdfd809b7 +0, 264192, 264192, 408, 1632, 0xf412313e diff --git a/tests/ref/fate/filter-dcshift b/tests/ref/fate/filter-dcshift index dad3df3ff..4ad1401a9 100644 --- a/tests/ref/fate/filter-dcshift +++ b/tests/ref/fate/filter-dcshift @@ -2,7 +2,6 @@ #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, 0x96868842 0, 1024, 1024, 1024, 4096, 0xeff98700 diff --git a/tests/ref/fate/filter-decimate b/tests/ref/fate/filter-decimate new file mode 100644 index 000000000..0edc0ea4e --- /dev/null +++ b/tests/ref/fate/filter-decimate @@ -0,0 +1,245 @@ +#tb 0: 1/24 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 320x240 +#sar 0: 1/1 +0, 0, 0, 1, 115200, 0xeba70ff3 +0, 1, 1, 1, 115200, 0xbf963f2c +0, 2, 2, 1, 115200, 0x822c77cd +0, 3, 3, 1, 115200, 0x62c0a4b1 +0, 4, 4, 1, 115200, 0x7a3fd919 +0, 5, 5, 1, 115200, 0x800efa06 +0, 6, 6, 1, 115200, 0x3326fbbe +0, 7, 7, 1, 115200, 0xb803f3ba +0, 8, 8, 1, 115200, 0xaf07f156 +0, 9, 9, 1, 115200, 0x57a3ebe3 +0, 10, 10, 1, 115200, 0x6c27ebb2 +0, 11, 11, 1, 115200, 0xea56ee4e +0, 12, 12, 1, 115200, 0xfc76f369 +0, 13, 13, 1, 115200, 0xf3f7f7f4 +0, 14, 14, 1, 115200, 0xa40c083b +0, 15, 15, 1, 115200, 0xb1eb1129 +0, 16, 16, 1, 115200, 0x093a0ab7 +0, 17, 17, 1, 115200, 0x8b140cad +0, 18, 18, 1, 115200, 0xa6681236 +0, 19, 19, 1, 115200, 0x1270137e +0, 20, 20, 1, 115200, 0x2f550e34 +0, 21, 21, 1, 115200, 0xd5ebf9a1 +0, 22, 22, 1, 115200, 0x35aee377 +0, 23, 23, 1, 115200, 0xff4cdc71 +0, 24, 24, 1, 115200, 0x5d70c0bc +0, 25, 25, 1, 115200, 0xb8c0caea +0, 26, 26, 1, 115200, 0x56f8da6b +0, 27, 27, 1, 115200, 0xca81d558 +0, 28, 28, 1, 115200, 0xdc89ea02 +0, 29, 29, 1, 115200, 0xcf06fc36 +0, 30, 30, 1, 115200, 0x14b905d5 +0, 31, 31, 1, 115200, 0xbed50cbf +0, 32, 32, 1, 115200, 0xa894103c +0, 33, 33, 1, 115200, 0x4b611da9 +0, 34, 34, 1, 115200, 0xedfc22e3 +0, 35, 35, 1, 115200, 0xa0b63573 +0, 36, 36, 1, 115200, 0x6f9148db +0, 37, 37, 1, 115200, 0x69e03976 +0, 38, 38, 1, 115200, 0xe9bf3865 +0, 39, 39, 1, 115200, 0xd9e9255f +0, 40, 40, 1, 115200, 0x99b91d6d +0, 41, 41, 1, 115200, 0x1f8011f4 +0, 42, 42, 1, 115200, 0x74f0f3d0 +0, 43, 43, 1, 115200, 0x1ca7d668 +0, 44, 44, 1, 115200, 0x84d2c990 +0, 45, 45, 1, 115200, 0x1fcfb766 +0, 46, 46, 1, 115200, 0x4e89ab81 +0, 47, 47, 1, 115200, 0xf6d5bfed +0, 48, 48, 1, 115200, 0x7124cb5f +0, 49, 49, 1, 115200, 0xdc2bb44c +0, 50, 50, 1, 115200, 0xd11ac3c8 +0, 51, 51, 1, 115200, 0x019ec083 +0, 52, 52, 1, 115200, 0xa935dd47 +0, 53, 53, 1, 115200, 0x8bff0250 +0, 54, 54, 1, 115200, 0xcd400ba8 +0, 55, 55, 1, 115200, 0xa6ea14c0 +0, 56, 56, 1, 115200, 0xaad01a88 +0, 57, 57, 1, 115200, 0xf7dd1c70 +0, 58, 58, 1, 115200, 0x26ae259f +0, 59, 59, 1, 115200, 0x51bb2e04 +0, 60, 60, 1, 115200, 0x15bd3f32 +0, 61, 61, 1, 115200, 0x6937269b +0, 62, 62, 1, 115200, 0x4d5729de +0, 63, 63, 1, 115200, 0x343f384b +0, 64, 64, 1, 115200, 0xe9353d2a +0, 65, 65, 1, 115200, 0x65753d3c +0, 66, 66, 1, 115200, 0xbda64078 +0, 67, 67, 1, 115200, 0x32c84b69 +0, 68, 68, 1, 115200, 0xd95f4557 +0, 69, 69, 1, 115200, 0x20a41a53 +0, 70, 70, 1, 115200, 0x7445fc11 +0, 71, 71, 1, 115200, 0x2b76e8a5 +0, 72, 72, 1, 115200, 0xc445cf15 +0, 73, 73, 1, 115200, 0x0a4fe0ab +0, 74, 74, 1, 115200, 0x85610638 +0, 75, 75, 1, 115200, 0x937a29b5 +0, 76, 76, 1, 115200, 0x3aa67daa +0, 77, 77, 1, 115200, 0x70b2cbef +0, 78, 78, 1, 115200, 0x7cb8d043 +0, 79, 79, 1, 115200, 0x529fc410 +0, 80, 80, 1, 115200, 0x3bc8c140 +0, 81, 81, 1, 115200, 0xb689a829 +0, 82, 82, 1, 115200, 0xb16276ee +0, 83, 83, 1, 115200, 0xf95c5305 +0, 84, 84, 1, 115200, 0x7a9a0f51 +0, 85, 85, 1, 115200, 0x823a280e +0, 86, 86, 1, 115200, 0x5c483fd4 +0, 87, 87, 1, 115200, 0x05cd5897 +0, 88, 88, 1, 115200, 0x7b075138 +0, 89, 89, 1, 115200, 0x7de4634b +0, 90, 90, 1, 115200, 0x5ea6699e +0, 91, 91, 1, 115200, 0xafc3542f +0, 92, 92, 1, 115200, 0x249b0f88 +0, 93, 93, 1, 115200, 0x1c4bb61b +0, 94, 94, 1, 115200, 0x4a4c7fff +0, 95, 95, 1, 115200, 0x7b3962f3 +0, 96, 96, 1, 115200, 0x304d5af6 +0, 97, 97, 1, 115200, 0x7da664c0 +0, 98, 98, 1, 115200, 0xe85b85e6 +0, 99, 99, 1, 115200, 0x8c7594d5 +0, 100, 100, 1, 115200, 0xe279bef2 +0, 101, 101, 1, 115200, 0x66f9d4be +0, 102, 102, 1, 115200, 0xa7cdc971 +0, 103, 103, 1, 115200, 0xad30baf5 +0, 104, 104, 1, 115200, 0x9244b378 +0, 105, 105, 1, 115200, 0x6485a7cc +0, 106, 106, 1, 115200, 0xf30e9291 +0, 107, 107, 1, 115200, 0x9f288e01 +0, 108, 108, 1, 115200, 0xade58fe5 +0, 109, 109, 1, 115200, 0x0c029251 +0, 110, 110, 1, 115200, 0x660b9c9f +0, 111, 111, 1, 115200, 0xa7c99ff7 +0, 112, 112, 1, 115200, 0xd63a9d6d +0, 113, 113, 1, 115200, 0x8b27a5cf +0, 114, 114, 1, 115200, 0xf97ba4a2 +0, 115, 115, 1, 115200, 0xa4b9aa9c +0, 116, 116, 1, 115200, 0xe197ad07 +0, 117, 117, 1, 115200, 0x9dd8a125 +0, 118, 118, 1, 115200, 0xccbca2f6 +0, 119, 119, 1, 115200, 0xb4daa104 +0, 120, 120, 1, 115200, 0x100c9d8a +0, 121, 121, 1, 115200, 0xcd239c90 +0, 122, 122, 1, 115200, 0xb0d1b2ab +0, 123, 123, 1, 115200, 0x04a1c66e +0, 124, 124, 1, 115200, 0x01ede1ed +0, 125, 125, 1, 115200, 0x13d5fc05 +0, 126, 126, 1, 115200, 0xf62401b2 +0, 127, 127, 1, 115200, 0x05a00e4e +0, 128, 128, 1, 115200, 0xfe802328 +0, 129, 129, 1, 115200, 0x527025b0 +0, 130, 130, 1, 115200, 0x1f6331a4 +0, 131, 131, 1, 115200, 0x77ad3986 +0, 132, 132, 1, 115200, 0xf8484f06 +0, 133, 133, 1, 115200, 0xc9ec372e +0, 134, 134, 1, 115200, 0x9ef33524 +0, 135, 135, 1, 115200, 0x58ed1f81 +0, 136, 136, 1, 115200, 0x4d140fb8 +0, 137, 137, 1, 115200, 0x0260fb37 +0, 138, 138, 1, 115200, 0xc30ddff1 +0, 139, 139, 1, 115200, 0x5fbec612 +0, 140, 140, 1, 115200, 0x1bdcb832 +0, 141, 141, 1, 115200, 0xaa23a217 +0, 142, 142, 1, 115200, 0x3d9d9d4e +0, 143, 143, 1, 115200, 0xcf7ca95f +0, 144, 144, 1, 115200, 0x29aeb511 +0, 145, 145, 1, 115200, 0xd727c28d +0, 146, 146, 1, 115200, 0xbbc0d640 +0, 147, 147, 1, 115200, 0x5254d5b9 +0, 148, 148, 1, 115200, 0x4e68f139 +0, 149, 149, 1, 115200, 0xc8221a08 +0, 150, 150, 1, 115200, 0xd0973761 +0, 151, 151, 1, 115200, 0xc0a44143 +0, 152, 152, 1, 115200, 0x4fc63fc3 +0, 153, 153, 1, 115200, 0x5def2bd6 +0, 154, 154, 1, 115200, 0x2d151cfd +0, 155, 155, 1, 115200, 0xdca12233 +0, 156, 156, 1, 115200, 0xe3f93a01 +0, 157, 157, 1, 115200, 0xeb562c80 +0, 158, 158, 1, 115200, 0x353428c0 +0, 159, 159, 1, 115200, 0xa27a1bb0 +0, 160, 160, 1, 115200, 0x00b31d64 +0, 161, 161, 1, 115200, 0xc9d41237 +0, 162, 162, 1, 115200, 0xe3ae0ea6 +0, 163, 163, 1, 115200, 0x532315f1 +0, 164, 164, 1, 115200, 0x1c060fa5 +0, 165, 165, 1, 115200, 0x82cefc68 +0, 166, 166, 1, 115200, 0xe59cdfb0 +0, 167, 167, 1, 115200, 0xc752d2fd +0, 168, 168, 1, 115200, 0x11a9c73f +0, 169, 169, 1, 115200, 0x5bfce0a0 +0, 170, 170, 1, 115200, 0xdfcd0d08 +0, 171, 171, 1, 115200, 0x72223121 +0, 172, 172, 1, 115200, 0x10f18168 +0, 173, 173, 1, 115200, 0x3246d9d1 +0, 174, 174, 1, 115200, 0x0ebce030 +0, 175, 175, 1, 115200, 0xe557d979 +0, 176, 176, 1, 115200, 0xbca5c41a +0, 177, 177, 1, 115200, 0x3770a682 +0, 178, 178, 1, 115200, 0xd6966c19 +0, 179, 179, 1, 115200, 0x01f13a7d +0, 180, 180, 1, 115200, 0x4c030202 +0, 181, 181, 1, 115200, 0x17f70f1a +0, 182, 182, 1, 115200, 0x953933a6 +0, 183, 183, 1, 115200, 0x334d5fc2 +0, 184, 184, 1, 115200, 0x91146079 +0, 185, 185, 1, 115200, 0xf2108405 +0, 186, 186, 1, 115200, 0xa7789bab +0, 187, 187, 1, 115200, 0x26559004 +0, 188, 188, 1, 115200, 0xc5144c57 +0, 189, 189, 1, 115200, 0xa743f4ab +0, 190, 190, 1, 115200, 0x42f7c523 +0, 191, 191, 1, 115200, 0xa1ada8b2 +0, 192, 192, 1, 115200, 0x6428a8b1 +0, 193, 193, 1, 115200, 0xbf72b6ef +0, 194, 194, 1, 115200, 0x0ef0ca5d +0, 195, 195, 1, 115200, 0xc7e6d823 +0, 196, 196, 1, 115200, 0x36dfe907 +0, 197, 197, 1, 115200, 0x5b15f784 +0, 198, 198, 1, 115200, 0x88bbe6be +0, 199, 199, 1, 115200, 0x99b0d1c3 +0, 200, 200, 1, 115200, 0x1da5cbca +0, 201, 201, 1, 115200, 0xe6efbaf8 +0, 202, 202, 1, 115200, 0x5a03b454 +0, 203, 203, 1, 115200, 0xf929b3ae +0, 204, 204, 1, 115200, 0xcffab7cf +0, 205, 205, 1, 115200, 0x6befc008 +0, 206, 206, 1, 115200, 0x434dcef4 +0, 207, 207, 1, 115200, 0x0cc5d530 +0, 208, 208, 1, 115200, 0x08c2d9c5 +0, 209, 209, 1, 115200, 0xf994d94a +0, 210, 210, 1, 115200, 0x1973d911 +0, 211, 211, 1, 115200, 0x540cd279 +0, 212, 212, 1, 115200, 0x842ed2d6 +0, 213, 213, 1, 115200, 0x8fa4c5bb +0, 214, 214, 1, 115200, 0x77b9b5d1 +0, 215, 215, 1, 115200, 0x8ae3b17d +0, 216, 216, 1, 115200, 0x52a4a175 +0, 217, 217, 1, 115200, 0x2f69ad02 +0, 218, 218, 1, 115200, 0xd56cc263 +0, 219, 219, 1, 115200, 0x8aa4bde3 +0, 220, 220, 1, 115200, 0x1f97d1e1 +0, 221, 221, 1, 115200, 0x24d2df00 +0, 222, 222, 1, 115200, 0x8a5feb1a +0, 223, 223, 1, 115200, 0xed8bf2a9 +0, 224, 224, 1, 115200, 0xfc91ff14 +0, 225, 225, 1, 115200, 0xf25b0408 +0, 226, 226, 1, 115200, 0xfbd719be +0, 227, 227, 1, 115200, 0x1719309c +0, 228, 228, 1, 115200, 0x0c645265 +0, 229, 229, 1, 115200, 0x52da4723 +0, 230, 230, 1, 115200, 0x61494396 +0, 231, 231, 1, 115200, 0xba312ea6 +0, 232, 232, 1, 115200, 0x65a32114 +0, 233, 233, 1, 115200, 0xd19b1e21 +0, 234, 234, 1, 115200, 0x0e80fe23 +0, 235, 235, 1, 115200, 0x5e4fe60c +0, 236, 236, 1, 115200, 0x4ca9d81b +0, 237, 237, 1, 115200, 0xc343b958 +0, 238, 238, 1, 115200, 0xb5b2a7d1 +0, 239, 239, 1, 115200, 0xe9879d29 diff --git a/tests/ref/fate/filter-earwax b/tests/ref/fate/filter-earwax index 6bfa725b6..762648289 100644 --- a/tests/ref/fate/filter-earwax +++ b/tests/ref/fate/filter-earwax @@ -2,7 +2,6 @@ #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, 0xb7e1f437 0, 1024, 1024, 1024, 4096, 0xa031042a diff --git a/tests/ref/fate/filter-ep2x b/tests/ref/fate/filter-ep2x new file mode 100644 index 000000000..d720510d9 --- /dev/null +++ b/tests/ref/fate/filter-ep2x @@ -0,0 +1,7 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 382x574 +#sar 0: 1/1 +0, 0, 0, 1, 877072, 0xfd71968d +0, 1, 1, 1, 877072, 0x231d2ba7 diff --git a/tests/ref/fate/filter-ep3x b/tests/ref/fate/filter-ep3x new file mode 100644 index 000000000..16f714ed4 --- /dev/null +++ b/tests/ref/fate/filter-ep3x @@ -0,0 +1,7 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 573x861 +#sar 0: 1/1 +0, 0, 0, 1, 1973412, 0x99d19757 +0, 1, 1, 1, 1973412, 0x8d5288f2 diff --git a/tests/ref/fate/filter-extrastereo b/tests/ref/fate/filter-extrastereo index 179c16779..a94d5f2e9 100644 --- a/tests/ref/fate/filter-extrastereo +++ b/tests/ref/fate/filter-extrastereo @@ -2,7 +2,6 @@ #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, 0x29e3eecf 0, 1024, 1024, 1024, 4096, 0x18390b96 diff --git a/tests/ref/fate/filter-formats b/tests/ref/fate/filter-formats index 17ff5b222..a4fc2f921 100644 --- a/tests/ref/fate/filter-formats +++ b/tests/ref/fate/filter-formats @@ -66,20 +66,20 @@ quad(side) 7 channels (FL+FR+BC+SL+SR+DL+DR) 8 channels (FL+FR+LFE+BC+SL+SR+DL+DR) 8 channels (FL+FR+FC+BC+SL+SR+DL+DR) --1 = ff_parse_channel_layout(FFFFFFFFFFFFFFFF, -1, blah); +-1 = ff_parse_channel_layout(0000000000000000, -1, blah); 0 = ff_parse_channel_layout(0000000000000001, 1, 1); 0 = ff_parse_channel_layout(0000000000000002, 1, 2); --1 = ff_parse_channel_layout(FFFFFFFFFFFFFFFF, -1, -1); +-1 = ff_parse_channel_layout(0000000000000000, -1, -1); 0 = ff_parse_channel_layout(000000000000003C, 4, 60); 0 = ff_parse_channel_layout(0000000000000041, 2, 65); 0 = ff_parse_channel_layout(0000000000000004, 1, 1c); 0 = ff_parse_channel_layout(0000000000000003, 2, 2c); --1 = ff_parse_channel_layout(FFFFFFFFFFFFFFFF, -1, -1c); --1 = ff_parse_channel_layout(FFFFFFFFFFFFFFFF, -1, 60c); --1 = ff_parse_channel_layout(FFFFFFFFFFFFFFFF, -1, 65c); +-1 = ff_parse_channel_layout(0000000000000000, -1, -1c); +-1 = ff_parse_channel_layout(0000000000000000, -1, 60c); +-1 = ff_parse_channel_layout(0000000000000000, -1, 65c); 0 = ff_parse_channel_layout(0000000000000000, 2, 2C); 0 = ff_parse_channel_layout(0000000000000000, 60, 60C); --1 = ff_parse_channel_layout(FFFFFFFFFFFFFFFF, -1, 65C); +0 = ff_parse_channel_layout(0000000000000000, 65, 65C); 0 = ff_parse_channel_layout(000000000000003F, 6, 5.1); 0 = ff_parse_channel_layout(0000000000000003, 2, stereo); 0 = ff_parse_channel_layout(0000000000000001, 1, 1+1+1+1); diff --git a/tests/ref/fate/filter-fps-down b/tests/ref/fate/filter-fps-down index 0b6725f03..0407a3e04 100644 --- a/tests/ref/fate/filter-fps-down +++ b/tests/ref/fate/filter-fps-down @@ -3,14 +3,14 @@ #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 +0, 0, 0, 1, 115200, 0xb986bcbd +0, 1, 1, 1, 115200, 0xed18e21f +0, 2, 2, 1, 115200, 0x6fedfa63 +0, 3, 3, 1, 115200, 0xa4e0d22b +0, 4, 4, 1, 115200, 0x32332c36 +0, 5, 5, 1, 115200, 0xa611fd70 +0, 6, 6, 1, 115200, 0x0fa5c984 +0, 7, 7, 1, 115200, 0x127c21d0 +0, 8, 8, 1, 115200, 0x4194305c +0, 9, 9, 1, 115200, 0x274845a7 +0, 10, 10, 1, 115200, 0x9aa1765a diff --git a/tests/ref/fate/filter-fps-down-eof-pass b/tests/ref/fate/filter-fps-down-eof-pass index 0b6725f03..0407a3e04 100644 --- a/tests/ref/fate/filter-fps-down-eof-pass +++ b/tests/ref/fate/filter-fps-down-eof-pass @@ -3,14 +3,14 @@ #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 +0, 0, 0, 1, 115200, 0xb986bcbd +0, 1, 1, 1, 115200, 0xed18e21f +0, 2, 2, 1, 115200, 0x6fedfa63 +0, 3, 3, 1, 115200, 0xa4e0d22b +0, 4, 4, 1, 115200, 0x32332c36 +0, 5, 5, 1, 115200, 0xa611fd70 +0, 6, 6, 1, 115200, 0x0fa5c984 +0, 7, 7, 1, 115200, 0x127c21d0 +0, 8, 8, 1, 115200, 0x4194305c +0, 9, 9, 1, 115200, 0x274845a7 +0, 10, 10, 1, 115200, 0x9aa1765a diff --git a/tests/ref/fate/filter-fps-down-round-down b/tests/ref/fate/filter-fps-down-round-down index 4440539b6..ede7e3303 100644 --- a/tests/ref/fate/filter-fps-down-round-down +++ b/tests/ref/fate/filter-fps-down-round-down @@ -3,13 +3,13 @@ #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 +0, 0, 0, 1, 115200, 0x8567f6cf +0, 1, 1, 1, 115200, 0x0054f5dd +0, 2, 2, 1, 115200, 0x3226f459 +0, 3, 3, 1, 115200, 0xc2c4037c +0, 4, 4, 1, 115200, 0x93892b01 +0, 5, 5, 1, 115200, 0xc875b905 +0, 6, 6, 1, 115200, 0x7f601649 +0, 7, 7, 1, 115200, 0x5cef2244 +0, 8, 8, 1, 115200, 0xe1342b12 +0, 9, 9, 1, 115200, 0x57d4cca0 diff --git a/tests/ref/fate/filter-fps-down-round-up b/tests/ref/fate/filter-fps-down-round-up index c3cf02fd2..415f1305a 100644 --- a/tests/ref/fate/filter-fps-down-round-up +++ b/tests/ref/fate/filter-fps-down-round-up @@ -3,14 +3,14 @@ #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 +0, 0, 0, 1, 115200, 0xeba70ff3 +0, 1, 1, 1, 115200, 0x8567f6cf +0, 2, 2, 1, 115200, 0x0054f5dd +0, 3, 3, 1, 115200, 0x04cab318 +0, 4, 4, 1, 115200, 0xc2c4037c +0, 5, 5, 1, 115200, 0x93892b01 +0, 6, 6, 1, 115200, 0xe4e2c25a +0, 7, 7, 1, 115200, 0x7f601649 +0, 8, 8, 1, 115200, 0x5cef2244 +0, 9, 9, 1, 115200, 0x7c13cdb3 +0, 10, 10, 1, 115200, 0x57d4cca0 diff --git a/tests/ref/fate/filter-fps-start-drop b/tests/ref/fate/filter-fps-start-drop index cfa1c4099..6c6c2af0f 100644 --- a/tests/ref/fate/filter-fps-start-drop +++ b/tests/ref/fate/filter-fps-start-drop @@ -3,9 +3,9 @@ #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 +0, 5, 5, 1, 115200, 0xa611fd70 +0, 6, 6, 1, 115200, 0xe4e2c25a +0, 7, 7, 1, 115200, 0x7f601649 +0, 8, 8, 1, 115200, 0x4194305c +0, 9, 9, 1, 115200, 0x7c13cdb3 +0, 10, 10, 1, 115200, 0x57d4cca0 diff --git a/tests/ref/fate/filter-fps-start-fill b/tests/ref/fate/filter-fps-start-fill index c5efb42a8..6ff981d38 100644 --- a/tests/ref/fate/filter-fps-start-fill +++ b/tests/ref/fate/filter-fps-start-fill @@ -3,9 +3,9 @@ #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 +0, 5, 5, 1, 115200, 0xeba70ff3 +0, 6, 6, 1, 115200, 0xeba70ff3 +0, 7, 7, 1, 115200, 0x8567f6cf +0, 8, 8, 1, 115200, 0x6fedfa63 +0, 9, 9, 1, 115200, 0x04cab318 +0, 10, 10, 1, 115200, 0xc2c4037c diff --git a/tests/ref/fate/filter-fps-up b/tests/ref/fate/filter-fps-up index dfb957c63..b19253806 100644 --- a/tests/ref/fate/filter-fps-up +++ b/tests/ref/fate/filter-fps-up @@ -3,17 +3,17 @@ #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 -0, 12, 12, 1, 115200, 0x53d5b181 -0, 13, 13, 1, 115200, 0x53d5b181 +0, 0, 0, 1, 115200, 0xeba70ff3 +0, 1, 1, 1, 115200, 0xeba70ff3 +0, 2, 2, 1, 115200, 0x0ebce86f +0, 3, 3, 1, 115200, 0x0ebce86f +0, 4, 4, 1, 115200, 0x0ebce86f +0, 5, 5, 1, 115200, 0xa9c0fe04 +0, 6, 6, 1, 115200, 0xa9c0fe04 +0, 7, 7, 1, 115200, 0x779eb44c +0, 8, 8, 1, 115200, 0x779eb44c +0, 9, 9, 1, 115200, 0x27a904da +0, 10, 10, 1, 115200, 0x27a904da +0, 11, 11, 1, 115200, 0x27a904da +0, 12, 12, 1, 115200, 0x328d092e +0, 13, 13, 1, 115200, 0x328d092e diff --git a/tests/ref/fate/filter-fps-up-round-down b/tests/ref/fate/filter-fps-up-round-down index b68e4fe97..33eff3e4f 100644 --- a/tests/ref/fate/filter-fps-up-round-down +++ b/tests/ref/fate/filter-fps-up-round-down @@ -3,17 +3,17 @@ #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 -0, 11, 11, 1, 115200, 0x53d5b181 -0, 12, 12, 1, 115200, 0x53d5b181 -0, 13, 13, 1, 115200, 0x53d5b181 +0, 0, 0, 1, 115200, 0xeba70ff3 +0, 1, 1, 1, 115200, 0xeba70ff3 +0, 2, 2, 1, 115200, 0x0ebce86f +0, 3, 3, 1, 115200, 0x0ebce86f +0, 4, 4, 1, 115200, 0xa9c0fe04 +0, 5, 5, 1, 115200, 0xa9c0fe04 +0, 6, 6, 1, 115200, 0xa9c0fe04 +0, 7, 7, 1, 115200, 0x779eb44c +0, 8, 8, 1, 115200, 0x779eb44c +0, 9, 9, 1, 115200, 0x27a904da +0, 10, 10, 1, 115200, 0x27a904da +0, 11, 11, 1, 115200, 0x328d092e +0, 12, 12, 1, 115200, 0x328d092e +0, 13, 13, 1, 115200, 0x328d092e diff --git a/tests/ref/fate/filter-fps-up-round-up b/tests/ref/fate/filter-fps-up-round-up index 692c1d6c6..a8877f08f 100644 --- a/tests/ref/fate/filter-fps-up-round-up +++ b/tests/ref/fate/filter-fps-up-round-up @@ -3,17 +3,17 @@ #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 -0, 12, 12, 1, 115200, 0x53d5b181 -0, 13, 13, 1, 115200, 0x53d5b181 +0, 0, 0, 1, 115200, 0xeba70ff3 +0, 1, 1, 1, 115200, 0xeba70ff3 +0, 2, 2, 1, 115200, 0xeba70ff3 +0, 3, 3, 1, 115200, 0x0ebce86f +0, 4, 4, 1, 115200, 0x0ebce86f +0, 5, 5, 1, 115200, 0xa9c0fe04 +0, 6, 6, 1, 115200, 0xa9c0fe04 +0, 7, 7, 1, 115200, 0x779eb44c +0, 8, 8, 1, 115200, 0x779eb44c +0, 9, 9, 1, 115200, 0x779eb44c +0, 10, 10, 1, 115200, 0x27a904da +0, 11, 11, 1, 115200, 0x27a904da +0, 12, 12, 1, 115200, 0x328d092e +0, 13, 13, 1, 115200, 0x328d092e diff --git a/tests/ref/fate/filter-framerate-12bit-down b/tests/ref/fate/filter-framerate-12bit-down index 25a3c0a53..705d07d9c 100644 --- a/tests/ref/fate/filter-framerate-12bit-down +++ b/tests/ref/fate/filter-framerate-12bit-down @@ -3,53 +3,53 @@ #codec_id 0: rawvideo #dimensions 0: 320x240 #sar 0: 1/1 -0, 0, 0, 1, 307200, 0xb49cf016 -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, 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, 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, 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, 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, 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, 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, 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, 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, 0x4df2d619 -0, 47, 47, 1, 307200, 0x21205aab -0, 48, 48, 1, 307200, 0xe00f48c2 -0, 49, 49, 1, 307200, 0xe3b11798 +0, 0, 0, 1, 307200, 0xf0d70414 +0, 1, 1, 1, 307200, 0x75d668e8 +0, 2, 2, 1, 307200, 0xca39d9c3 +0, 3, 3, 1, 307200, 0xfacaf28f +0, 4, 4, 1, 307200, 0x00bb97bf +0, 5, 5, 1, 307200, 0xb309f05f +0, 6, 6, 1, 307200, 0x08a78b1e +0, 7, 7, 1, 307200, 0x1ec21037 +0, 8, 8, 1, 307200, 0x45c901e4 +0, 9, 9, 1, 307200, 0x460775a7 +0, 10, 10, 1, 307200, 0x16ce3448 +0, 11, 11, 1, 307200, 0x6bc2b063 +0, 12, 12, 1, 307200, 0x4e628c33 +0, 13, 13, 1, 307200, 0xc965923a +0, 14, 14, 1, 307200, 0x54c8fe7c +0, 15, 15, 1, 307200, 0x11758b98 +0, 16, 16, 1, 307200, 0x73f988a8 +0, 17, 17, 1, 307200, 0xb47223da +0, 18, 18, 1, 307200, 0x03af8c25 +0, 19, 19, 1, 307200, 0x3871b12e +0, 20, 20, 1, 307200, 0x59447ef5 +0, 21, 21, 1, 307200, 0xfb7918bd +0, 22, 22, 1, 307200, 0xe9c623db +0, 23, 23, 1, 307200, 0x78634f23 +0, 24, 24, 1, 307200, 0x8229d18c +0, 25, 25, 1, 307200, 0xfb530895 +0, 26, 26, 1, 307200, 0x118b22a4 +0, 27, 27, 1, 307200, 0x4b39ea30 +0, 28, 28, 1, 307200, 0xe2f0c1ff +0, 29, 29, 1, 307200, 0xcbc65013 +0, 30, 30, 1, 307200, 0xf903e8d5 +0, 31, 31, 1, 307200, 0x870fa119 +0, 32, 32, 1, 307200, 0x7e5b2f5c +0, 33, 33, 1, 307200, 0x8b8a42a9 +0, 34, 34, 1, 307200, 0xa4a429bc +0, 35, 35, 1, 307200, 0xf308c14c +0, 36, 36, 1, 307200, 0xf255baeb +0, 37, 37, 1, 307200, 0x8c4d949e +0, 38, 38, 1, 307200, 0x28b57e98 +0, 39, 39, 1, 307200, 0x568cd24c +0, 40, 40, 1, 307200, 0xfc8e3884 +0, 41, 41, 1, 307200, 0xfee05e7f +0, 42, 42, 1, 307200, 0x3502c242 +0, 43, 43, 1, 307200, 0x3542901f +0, 44, 44, 1, 307200, 0x8d74850c +0, 45, 45, 1, 307200, 0x11d6693a +0, 46, 46, 1, 307200, 0x83cf7d6e +0, 47, 47, 1, 307200, 0x17ecef9a +0, 48, 48, 1, 307200, 0x37ba308f +0, 49, 49, 1, 307200, 0x7659d1ed diff --git a/tests/ref/fate/filter-framerate-12bit-up b/tests/ref/fate/filter-framerate-12bit-up index 15bf9be6f..15f05b67b 100644 --- a/tests/ref/fate/filter-framerate-12bit-up +++ b/tests/ref/fate/filter-framerate-12bit-up @@ -3,63 +3,63 @@ #codec_id 0: rawvideo #dimensions 0: 320x240 #sar 0: 1/1 -0, 0, 0, 1, 307200, 0xb49cf016 -0, 1, 1, 1, 307200, 0x95d191b2 -0, 2, 2, 1, 307200, 0x20e5173b -0, 3, 3, 1, 307200, 0x5378b13c -0, 4, 4, 1, 307200, 0x3e304543 -0, 5, 5, 1, 307200, 0x2f131cdb -0, 6, 6, 1, 307200, 0x83dbe321 -0, 7, 7, 1, 307200, 0xb81fc682 -0, 8, 8, 1, 307200, 0xb32a8644 -0, 9, 9, 1, 307200, 0xc5c8b0f8 -0, 10, 10, 1, 307200, 0x27945d0a -0, 11, 11, 1, 307200, 0x444c7640 -0, 12, 12, 1, 307200, 0xcba4c6bb -0, 13, 13, 1, 307200, 0xf923c7a3 -0, 14, 14, 1, 307200, 0x88149757 -0, 15, 15, 1, 307200, 0x4bdfd3ca -0, 16, 16, 1, 307200, 0x1c279695 -0, 17, 17, 1, 307200, 0x634cc809 -0, 18, 18, 1, 307200, 0xda8c6c41 -0, 19, 19, 1, 307200, 0x2136c986 -0, 20, 20, 1, 307200, 0x457576a8 -0, 21, 21, 1, 307200, 0xe2337c57 -0, 22, 22, 1, 307200, 0x8ed517c9 -0, 23, 23, 1, 307200, 0x4fd35f99 -0, 24, 24, 1, 307200, 0x4237e892 -0, 25, 25, 1, 307200, 0x1383a9d8 -0, 26, 26, 1, 307200, 0xc7195735 -0, 27, 27, 1, 307200, 0x0e058165 -0, 28, 28, 1, 307200, 0x0b81f345 -0, 29, 29, 1, 307200, 0x2ddf2f0a -0, 30, 30, 1, 307200, 0x0b58bcf7 -0, 31, 31, 1, 307200, 0x1b684a1d -0, 32, 32, 1, 307200, 0x1e44f1cf -0, 33, 33, 1, 307200, 0x3ed6b5d8 -0, 34, 34, 1, 307200, 0x00881a40 -0, 35, 35, 1, 307200, 0x2c3d1406 -0, 36, 36, 1, 307200, 0xbd67248a -0, 37, 37, 1, 307200, 0x46261913 -0, 38, 38, 1, 307200, 0xe5b2bbaa -0, 39, 39, 1, 307200, 0x0e4455cd -0, 40, 40, 1, 307200, 0xb4943212 -0, 41, 41, 1, 307200, 0xf96b6808 -0, 42, 42, 1, 307200, 0x58adad3f -0, 43, 43, 1, 307200, 0x978413f0 -0, 44, 44, 1, 307200, 0x0037320a -0, 45, 45, 1, 307200, 0xaac8e1ca -0, 46, 46, 1, 307200, 0xc3578407 -0, 47, 47, 1, 307200, 0xfc29c675 -0, 48, 48, 1, 307200, 0x22ed5b5a -0, 49, 49, 1, 307200, 0x6d58e21e -0, 50, 50, 1, 307200, 0xbf62b4c3 -0, 51, 51, 1, 307200, 0xbd5edb2d -0, 52, 52, 1, 307200, 0x55528432 -0, 53, 53, 1, 307200, 0xa3f1e514 -0, 54, 54, 1, 307200, 0xba073e6f -0, 55, 55, 1, 307200, 0x29b8df00 -0, 56, 56, 1, 307200, 0x1517512b -0, 57, 57, 1, 307200, 0x4e740b42 -0, 58, 58, 1, 307200, 0xbd6b7053 -0, 59, 59, 1, 307200, 0xe73f29ef +0, 0, 0, 1, 307200, 0xf0d70414 +0, 1, 1, 1, 307200, 0x6f4f534a +0, 2, 2, 1, 307200, 0x57f82b18 +0, 3, 3, 1, 307200, 0xcda8e8a1 +0, 4, 4, 1, 307200, 0xaa307009 +0, 5, 5, 1, 307200, 0x9ad7c3d3 +0, 6, 6, 1, 307200, 0x9df5f0d7 +0, 7, 7, 1, 307200, 0xfb7edf18 +0, 8, 8, 1, 307200, 0xef248b54 +0, 9, 9, 1, 307200, 0x61ad29ba +0, 10, 10, 1, 307200, 0xbbb6d277 +0, 11, 11, 1, 307200, 0xdd651a67 +0, 12, 12, 1, 307200, 0x15ba3293 +0, 13, 13, 1, 307200, 0x4c7162e4 +0, 14, 14, 1, 307200, 0xdbf4df9c +0, 15, 15, 1, 307200, 0xf41bf8b4 +0, 16, 16, 1, 307200, 0xd1ea6bda +0, 17, 17, 1, 307200, 0xbe30495d +0, 18, 18, 1, 307200, 0xce1b92fe +0, 19, 19, 1, 307200, 0xdf503102 +0, 20, 20, 1, 307200, 0xc6d8feaa +0, 21, 21, 1, 307200, 0x13451b24 +0, 22, 22, 1, 307200, 0x6ee0eab6 +0, 23, 23, 1, 307200, 0xdcf59507 +0, 24, 24, 1, 307200, 0x017539af +0, 25, 25, 1, 307200, 0x140bd179 +0, 26, 26, 1, 307200, 0xee8b6208 +0, 27, 27, 1, 307200, 0xb81c4fd4 +0, 28, 28, 1, 307200, 0x533c9287 +0, 29, 29, 1, 307200, 0x54a0e4d0 +0, 30, 30, 1, 307200, 0xdd700bcd +0, 31, 31, 1, 307200, 0xd49ee76f +0, 32, 32, 1, 307200, 0xd881bc34 +0, 33, 33, 1, 307200, 0x1422ea45 +0, 34, 34, 1, 307200, 0x31ede786 +0, 35, 35, 1, 307200, 0x29adb882 +0, 36, 36, 1, 307200, 0x62b4f994 +0, 37, 37, 1, 307200, 0x253558d8 +0, 38, 38, 1, 307200, 0xfb0eaa67 +0, 39, 39, 1, 307200, 0x331c2adf +0, 40, 40, 1, 307200, 0xf853359e +0, 41, 41, 1, 307200, 0xca73beb7 +0, 42, 42, 1, 307200, 0xd31b8d8a +0, 43, 43, 1, 307200, 0x83dcdaaf +0, 44, 44, 1, 307200, 0x1ee4383b +0, 45, 45, 1, 307200, 0x7ac11c03 +0, 46, 46, 1, 307200, 0x57bb11bd +0, 47, 47, 1, 307200, 0x9f448c18 +0, 48, 48, 1, 307200, 0x8b472bcd +0, 49, 49, 1, 307200, 0xbd32b115 +0, 50, 50, 1, 307200, 0xb4283663 +0, 51, 51, 1, 307200, 0x9fd04c1f +0, 52, 52, 1, 307200, 0x1d605e27 +0, 53, 53, 1, 307200, 0x155cac69 +0, 54, 54, 1, 307200, 0xfc3a7fc0 +0, 55, 55, 1, 307200, 0x801462a2 +0, 56, 56, 1, 307200, 0xd1db5657 +0, 57, 57, 1, 307200, 0x42cbf5b8 +0, 58, 58, 1, 307200, 0x7b239eae +0, 59, 59, 1, 307200, 0x4d6d0da4 diff --git a/tests/ref/fate/filter-framerate-down b/tests/ref/fate/filter-framerate-down index 4eab7aab8..c298de077 100644 --- a/tests/ref/fate/filter-framerate-down +++ b/tests/ref/fate/filter-framerate-down @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 320x240 #sar 0: 1/1 -0, 0, 0, 1, 115200, 0x3744b3ed +0, 0, 0, 1, 115200, 0xeba70ff3 diff --git a/tests/ref/fate/filter-framerate-up b/tests/ref/fate/filter-framerate-up index a276bf660..30d167932 100644 --- a/tests/ref/fate/filter-framerate-up +++ b/tests/ref/fate/filter-framerate-up @@ -3,13 +3,13 @@ #codec_id 0: rawvideo #dimensions 0: 320x240 #sar 0: 1/1 -0, 0, 0, 1, 115200, 0x3744b3ed -0, 1, 1, 1, 115200, 0xec1fdfa0 -0, 2, 2, 1, 115200, 0xa17f0d74 -0, 3, 3, 1, 115200, 0xd72532a9 -0, 4, 4, 1, 115200, 0x032e60f8 -0, 5, 5, 1, 115200, 0x6e318ba0 -0, 6, 6, 1, 115200, 0x76018292 -0, 7, 7, 1, 115200, 0x89e27599 -0, 8, 8, 1, 115200, 0x68536eac -0, 9, 9, 1, 115200, 0xc3ac62a8 +0, 0, 0, 1, 115200, 0xeba70ff3 +0, 1, 1, 1, 115200, 0xd7523c5f +0, 2, 2, 1, 115200, 0xd93564b0 +0, 3, 3, 1, 115200, 0xfd819089 +0, 4, 4, 1, 115200, 0x7f15b966 +0, 5, 5, 1, 115200, 0xa764e4d5 +0, 6, 6, 1, 115200, 0x8dc4da52 +0, 7, 7, 1, 115200, 0x7be2d1eb +0, 8, 8, 1, 115200, 0x8be7c6b2 +0, 9, 9, 1, 115200, 0xd560bee9 diff --git a/tests/ref/fate/filter-hls b/tests/ref/fate/filter-hls index ee3c7b2c6..ed0ecc8e7 100644 --- a/tests/ref/fate/filter-hls +++ b/tests/ref/fate/filter-hls @@ -2,7 +2,6 @@ #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, 1152, 2304, 0x907cb7fa 0, 1152, 1152, 1152, 2304, 0xb8dc7525 diff --git a/tests/ref/fate/filter-hls-append b/tests/ref/fate/filter-hls-append index 52b7dff48..902571cb5 100644 --- a/tests/ref/fate/filter-hls-append +++ b/tests/ref/fate/filter-hls-append @@ -2,7 +2,6 @@ #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, 1152, 2304, 0x907cb7fa 0, 26496, 26496, 1152, 2304, 0xb8dc7525 diff --git a/tests/ref/fate/filter-meta-4560-rotate0 b/tests/ref/fate/filter-meta-4560-rotate0 index 97552ffb9..82703e009 100644 --- a/tests/ref/fate/filter-meta-4560-rotate0 +++ b/tests/ref/fate/filter-meta-4560-rotate0 @@ -1,3 +1,5 @@ +dc213aee944a55af2f41950921fd62d7 *tests/data/fate/filter-meta-4560-rotate0.mov +347433 tests/data/fate/filter-meta-4560-rotate0.mov #tb 0: 1/30 #media_type 0: video #codec_id 0: rawvideo @@ -7,7 +9,6 @@ #media_type 1: audio #codec_id 1: pcm_s16le #sample_rate 1: 44100 -#channel_layout 1: 4 #channel_layout_name 1: mono 0, 0, 0, 1, 195840, 0x0602351d 1, 0, 0, 1024, 2048, 0x00000000 diff --git a/tests/ref/fate/filter-metadata-signalstats-yuv420p10 b/tests/ref/fate/filter-metadata-signalstats-yuv420p10 index 69693e848..93d3ca2c9 100644 --- a/tests/ref/fate/filter-metadata-signalstats-yuv420p10 +++ b/tests/ref/fate/filter-metadata-signalstats-yuv420p10 @@ -1 +1 @@ -pts=0|tag:lavfi.signalstats.YMIN=940|tag:lavfi.signalstats.YLOW=940|tag:lavfi.signalstats.YAVG=940|tag:lavfi.signalstats.YHIGH=940|tag:lavfi.signalstats.YMAX=940|tag:lavfi.signalstats.UMIN=512|tag:lavfi.signalstats.ULOW=512|tag:lavfi.signalstats.UAVG=512|tag:lavfi.signalstats.UHIGH=512|tag:lavfi.signalstats.UMAX=512|tag:lavfi.signalstats.VMIN=512|tag:lavfi.signalstats.VLOW=512|tag:lavfi.signalstats.VAVG=512|tag:lavfi.signalstats.VHIGH=512|tag:lavfi.signalstats.VMAX=512|tag:lavfi.signalstats.SATMIN=0|tag:lavfi.signalstats.SATLOW=0|tag:lavfi.signalstats.SATAVG=0|tag:lavfi.signalstats.SATHIGH=0|tag:lavfi.signalstats.SATMAX=0|tag:lavfi.signalstats.HUEMED=180|tag:lavfi.signalstats.HUEAVG=180|tag:lavfi.signalstats.YDIF=0|tag:lavfi.signalstats.UDIF=0|tag:lavfi.signalstats.VDIF=0|tag:lavfi.signalstats.YBITDEPTH=6|tag:lavfi.signalstats.UBITDEPTH=1|tag:lavfi.signalstats.VBITDEPTH=1 +pts=0|tag:lavfi.signalstats.YMIN=943|tag:lavfi.signalstats.YLOW=943|tag:lavfi.signalstats.YAVG=943|tag:lavfi.signalstats.YHIGH=943|tag:lavfi.signalstats.YMAX=943|tag:lavfi.signalstats.UMIN=514|tag:lavfi.signalstats.ULOW=514|tag:lavfi.signalstats.UAVG=514|tag:lavfi.signalstats.UHIGH=514|tag:lavfi.signalstats.UMAX=514|tag:lavfi.signalstats.VMIN=514|tag:lavfi.signalstats.VLOW=514|tag:lavfi.signalstats.VAVG=514|tag:lavfi.signalstats.VHIGH=514|tag:lavfi.signalstats.VMAX=514|tag:lavfi.signalstats.SATMIN=2|tag:lavfi.signalstats.SATLOW=2|tag:lavfi.signalstats.SATAVG=2|tag:lavfi.signalstats.SATHIGH=2|tag:lavfi.signalstats.SATMAX=2|tag:lavfi.signalstats.HUEMED=225|tag:lavfi.signalstats.HUEAVG=225|tag:lavfi.signalstats.YDIF=0|tag:lavfi.signalstats.UDIF=0|tag:lavfi.signalstats.VDIF=0|tag:lavfi.signalstats.YBITDEPTH=8|tag:lavfi.signalstats.UBITDEPTH=2|tag:lavfi.signalstats.VBITDEPTH=2 diff --git a/tests/ref/fate/filter-minterpolate-down b/tests/ref/fate/filter-minterpolate-down index 4eab7aab8..c298de077 100644 --- a/tests/ref/fate/filter-minterpolate-down +++ b/tests/ref/fate/filter-minterpolate-down @@ -3,4 +3,4 @@ #codec_id 0: rawvideo #dimensions 0: 320x240 #sar 0: 1/1 -0, 0, 0, 1, 115200, 0x3744b3ed +0, 0, 0, 1, 115200, 0xeba70ff3 diff --git a/tests/ref/fate/filter-minterpolate-up b/tests/ref/fate/filter-minterpolate-up index 186299078..11fe47e63 100644 --- a/tests/ref/fate/filter-minterpolate-up +++ b/tests/ref/fate/filter-minterpolate-up @@ -3,13 +3,13 @@ #codec_id 0: rawvideo #dimensions 0: 320x240 #sar 0: 1/1 -0, 0, 0, 1, 115200, 0x3744b3ed -0, 1, 1, 1, 115200, 0xf54dba9a -0, 2, 2, 1, 115200, 0xd0b30f49 -0, 3, 3, 1, 115200, 0x61720dac -0, 4, 4, 1, 115200, 0xb93a0baa -0, 5, 5, 1, 115200, 0x6e318ba0 -0, 6, 6, 1, 115200, 0xbce5157a -0, 7, 7, 1, 115200, 0xe16418a3 -0, 8, 8, 1, 115200, 0xdd91079c -0, 9, 9, 1, 115200, 0xdf69f73c +0, 0, 0, 1, 115200, 0xeba70ff3 +0, 1, 1, 1, 115200, 0x56a01933 +0, 2, 2, 1, 115200, 0x14836efb +0, 3, 3, 1, 115200, 0xb77c6df6 +0, 4, 4, 1, 115200, 0xa9726839 +0, 5, 5, 1, 115200, 0xa764e4d5 +0, 6, 6, 1, 115200, 0xc4b77097 +0, 7, 7, 1, 115200, 0xa371787a +0, 8, 8, 1, 115200, 0xf7676910 +0, 9, 9, 1, 115200, 0xe95f575f diff --git a/tests/ref/fate/filter-mpdecimate b/tests/ref/fate/filter-mpdecimate index d438dacc2..76359bbc7 100644 --- a/tests/ref/fate/filter-mpdecimate +++ b/tests/ref/fate/filter-mpdecimate @@ -3,23 +3,23 @@ #codec_id 0: rawvideo #dimensions 0: 320x240 #sar 0: 1/1 -0, 0, 0, 1, 115200, 0x3744b3ed -0, 2, 2, 1, 115200, 0x6e318ba0 -0, 3, 3, 1, 115200, 0x48d65876 -0, 5, 5, 1, 115200, 0x9087e4f1 -0, 6, 6, 1, 115200, 0xc58d5c94 -0, 8, 8, 1, 115200, 0x8c4ad4f4 -0, 9, 9, 1, 115200, 0xf96f6755 -0, 11, 11, 1, 115200, 0x90beb7ba -0, 12, 12, 1, 115200, 0xa8f4f31b -0, 14, 14, 1, 115200, 0x21441a03 -0, 15, 15, 1, 115200, 0x393b3494 -0, 17, 17, 1, 115200, 0xc7aeec1d -0, 18, 18, 1, 115200, 0x2bd24a0e -0, 20, 20, 1, 115200, 0xea66d804 -0, 21, 21, 1, 115200, 0x237953c3 -0, 23, 23, 1, 115200, 0xff98a9b1 -0, 24, 24, 1, 115200, 0x056d40ca -0, 26, 26, 1, 115200, 0xa4374737 -0, 27, 27, 1, 115200, 0x3eaa3ae8 -0, 29, 29, 1, 115200, 0x7551e9ee +0, 0, 0, 1, 115200, 0xeba70ff3 +0, 2, 2, 1, 115200, 0xa764e4d5 +0, 3, 3, 1, 115200, 0x1dadb3a3 +0, 5, 5, 1, 115200, 0x2edb3aa4 +0, 6, 6, 1, 115200, 0xb8cdb7ac +0, 8, 8, 1, 115200, 0x72f1289d +0, 9, 9, 1, 115200, 0xb789c3ba +0, 11, 11, 1, 115200, 0xd779fa6d +0, 12, 12, 1, 115200, 0xd1084e35 +0, 14, 14, 1, 115200, 0xbbc3728b +0, 15, 15, 1, 115200, 0x7bbb8ede +0, 17, 17, 1, 115200, 0x045740bf +0, 18, 18, 1, 115200, 0x939ba4bd +0, 20, 20, 1, 115200, 0x3f712b13 +0, 21, 21, 1, 115200, 0x64f1af30 +0, 23, 23, 1, 115200, 0xbe2fec7d +0, 24, 24, 1, 115200, 0x782e9c2b +0, 26, 26, 1, 115200, 0x48e5a005 +0, 27, 27, 1, 115200, 0xfcdc9615 +0, 29, 29, 1, 115200, 0xa4473eed diff --git a/tests/ref/fate/filter-overlay-dvdsub-2397 b/tests/ref/fate/filter-overlay-dvdsub-2397 index 483e5fa4e..7df4f5077 100644 --- a/tests/ref/fate/filter-overlay-dvdsub-2397 +++ b/tests/ref/fate/filter-overlay-dvdsub-2397 @@ -7,7 +7,6 @@ #media_type 1: audio #codec_id 1: dts #sample_rate 1: 48000 -#channel_layout 1: 60f #channel_layout_name 1: 5.1(side) 0, 0, 0, 1, 518400, 0x6b05d48a 1, 27, 27, 10, 2013, 0x68e7b03a diff --git a/tests/ref/fate/filter-overlay_yuv420p10 b/tests/ref/fate/filter-overlay_yuv420p10 index b431dc6cc..b3ebee803 100644 --- a/tests/ref/fate/filter-overlay_yuv420p10 +++ b/tests/ref/fate/filter-overlay_yuv420p10 @@ -3,6 +3,6 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 0, 0, 1, 304128, 0x29a6ca86 -0, 1, 1, 1, 304128, 0x82950e6f -0, 2, 2, 1, 304128, 0x8363d1d8 +0, 0, 0, 1, 304128, 0x524bcfc6 +0, 1, 1, 1, 304128, 0xab3a13af +0, 2, 2, 1, 304128, 0xac08d718 diff --git a/tests/ref/fate/filter-overlay_yuv422p10 b/tests/ref/fate/filter-overlay_yuv422p10 index 393c08169..68d7be2ab 100644 --- a/tests/ref/fate/filter-overlay_yuv422p10 +++ b/tests/ref/fate/filter-overlay_yuv422p10 @@ -3,6 +3,6 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 0, 0, 1, 405504, 0x11108b36 -0, 1, 1, 1, 405504, 0x9d5f7c2a -0, 2, 2, 1, 405504, 0x25373098 +0, 0, 0, 1, 405504, 0x58546ee8 +0, 1, 1, 1, 405504, 0xe9d654b7 +0, 2, 2, 1, 405504, 0x8fb60c61 diff --git a/tests/ref/fate/filter-paletteuse-bayer0 b/tests/ref/fate/filter-paletteuse-bayer0 new file mode 100644 index 000000000..85b3832f1 --- /dev/null +++ b/tests/ref/fate/filter-paletteuse-bayer0 @@ -0,0 +1,76 @@ +#tb 0: 1001/24000 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 320x180 +#sar 0: 1/1 +0, 0, 0, 1, 230400, 0xfb6042d2 +0, 1, 1, 1, 230400, 0x1c193c09 +0, 2, 2, 1, 230400, 0x183442f8 +0, 3, 3, 1, 230400, 0xa9634084 +0, 4, 4, 1, 230400, 0x90df3d2f +0, 5, 5, 1, 230400, 0x59d7389f +0, 6, 6, 1, 230400, 0xb9bd3a30 +0, 7, 7, 1, 230400, 0x9874ee38 +0, 8, 8, 1, 230400, 0xf661f01f +0, 9, 9, 1, 230400, 0xacbcedbd +0, 10, 10, 1, 230400, 0x05f02d59 +0, 11, 11, 1, 230400, 0xc54c2cc8 +0, 12, 12, 1, 230400, 0x19c92d61 +0, 13, 13, 1, 230400, 0x14902fb2 +0, 14, 14, 1, 230400, 0x99b62fb6 +0, 15, 15, 1, 230400, 0x3fc63293 +0, 16, 16, 1, 230400, 0x1eed4b38 +0, 17, 17, 1, 230400, 0xe9d747e0 +0, 18, 18, 1, 230400, 0x9825496f +0, 19, 19, 1, 230400, 0x94625411 +0, 20, 20, 1, 230400, 0xed7052a3 +0, 21, 21, 1, 230400, 0x80d552dc +0, 22, 22, 1, 230400, 0x89b360bb +0, 23, 23, 1, 230400, 0xee9a616a +0, 24, 24, 1, 230400, 0x30bb5f86 +0, 25, 25, 1, 230400, 0x5ec15eae +0, 26, 26, 1, 230400, 0x0956633e +0, 27, 27, 1, 230400, 0x72df62fa +0, 28, 28, 1, 230400, 0xbafd61d0 +0, 29, 29, 1, 230400, 0x393f81f3 +0, 30, 30, 1, 230400, 0xba6a848c +0, 31, 31, 1, 230400, 0x502ba0d9 +0, 32, 32, 1, 230400, 0xc81ba71d +0, 33, 33, 1, 230400, 0x54cdf270 +0, 34, 34, 1, 230400, 0xe951f3e2 +0, 35, 35, 1, 230400, 0xbf15baa1 +0, 36, 36, 1, 230400, 0xbf96bb12 +0, 37, 37, 1, 230400, 0xcdd5cafe +0, 38, 38, 1, 230400, 0x97b1cbb4 +0, 39, 39, 1, 230400, 0x955ae28f +0, 40, 40, 1, 230400, 0x6a8dd28f +0, 41, 41, 1, 230400, 0x8f02d268 +0, 42, 42, 1, 230400, 0x3075d269 +0, 43, 43, 1, 230400, 0x29e8b910 +0, 44, 44, 1, 230400, 0xb35ab888 +0, 45, 45, 1, 230400, 0xc3afb942 +0, 46, 46, 1, 230400, 0xeba8b860 +0, 47, 47, 1, 230400, 0x5de8b7ab +0, 48, 48, 1, 230400, 0x90233679 +0, 49, 49, 1, 230400, 0x5fbc3abb +0, 50, 50, 1, 230400, 0xeaa73b87 +0, 51, 51, 1, 230400, 0xbd0a3c4b +0, 52, 52, 1, 230400, 0xeddb39ba +0, 53, 53, 1, 230400, 0x269d4131 +0, 54, 54, 1, 230400, 0xae3e3e8c +0, 55, 55, 1, 230400, 0x65f54056 +0, 56, 56, 1, 230400, 0xf2173c5b +0, 57, 57, 1, 230400, 0xbd714477 +0, 58, 58, 1, 230400, 0xb60c42ed +0, 59, 59, 1, 230400, 0x8def43a5 +0, 60, 60, 1, 230400, 0xe6a73f05 +0, 61, 61, 1, 230400, 0xedfe4430 +0, 62, 62, 1, 230400, 0x76c5505a +0, 63, 63, 1, 230400, 0xf48d4d04 +0, 64, 64, 1, 230400, 0xa49950b5 +0, 65, 65, 1, 230400, 0xc64d51d8 +0, 66, 66, 1, 230400, 0xa08253ec +0, 67, 67, 1, 230400, 0xd6ef4609 +0, 68, 68, 1, 230400, 0x27a241e7 +0, 69, 69, 1, 230400, 0xe5f74b4a +0, 70, 70, 1, 230400, 0xb0194751 diff --git a/tests/ref/fate/filter-pan-downmix1 b/tests/ref/fate/filter-pan-downmix1 index 47d5044da..85630ab17 100644 --- a/tests/ref/fate/filter-pan-downmix1 +++ b/tests/ref/fate/filter-pan-downmix1 @@ -2,7 +2,6 @@ #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, 512, 2048, 0xccb10170 0, 512, 512, 512, 2048, 0xc51cf8e7 diff --git a/tests/ref/fate/filter-pan-downmix2 b/tests/ref/fate/filter-pan-downmix2 index 8d3ee1081..4ec18fc7d 100644 --- a/tests/ref/fate/filter-pan-downmix2 +++ b/tests/ref/fate/filter-pan-downmix2 @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 44100 -#channel_layout 0: 0 #channel_layout_name 0: 5 channels 0, 0, 0, 186, 1860, 0x2480a20e 0, 186, 186, 186, 1860, 0xde9e9c40 diff --git a/tests/ref/fate/filter-pan-mono1 b/tests/ref/fate/filter-pan-mono1 index 3bd7c25bc..80afee20a 100644 --- a/tests/ref/fate/filter-pan-mono1 +++ b/tests/ref/fate/filter-pan-mono1 @@ -2,7 +2,6 @@ #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 diff --git a/tests/ref/fate/filter-pan-mono2 b/tests/ref/fate/filter-pan-mono2 index 0867ca9a1..02046aebe 100644 --- a/tests/ref/fate/filter-pan-mono2 +++ b/tests/ref/fate/filter-pan-mono2 @@ -2,7 +2,6 @@ #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 diff --git a/tests/ref/fate/filter-pan-stereo1 b/tests/ref/fate/filter-pan-stereo1 index 3125d4e57..b4270bb11 100644 --- a/tests/ref/fate/filter-pan-stereo1 +++ b/tests/ref/fate/filter-pan-stereo1 @@ -2,7 +2,6 @@ #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 diff --git a/tests/ref/fate/filter-pan-stereo2 b/tests/ref/fate/filter-pan-stereo2 index 7f96799e2..dcd429a0c 100644 --- a/tests/ref/fate/filter-pan-stereo2 +++ b/tests/ref/fate/filter-pan-stereo2 @@ -2,7 +2,6 @@ #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 diff --git a/tests/ref/fate/filter-pan-stereo3 b/tests/ref/fate/filter-pan-stereo3 index effe11c78..726608b2b 100644 --- a/tests/ref/fate/filter-pan-stereo3 +++ b/tests/ref/fate/filter-pan-stereo3 @@ -2,7 +2,6 @@ #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 diff --git a/tests/ref/fate/filter-pan-stereo4 b/tests/ref/fate/filter-pan-stereo4 index 6d10ed62a..92ed0685f 100644 --- a/tests/ref/fate/filter-pan-stereo4 +++ b/tests/ref/fate/filter-pan-stereo4 @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 44100 -#channel_layout 0: 0 #channel_layout_name 0: 2 channels 0, 0, 0, 1024, 4096, 0x7bd6fc44 0, 1024, 1024, 1024, 4096, 0xed38ec37 diff --git a/tests/ref/fate/filter-pan-upmix1 b/tests/ref/fate/filter-pan-upmix1 index 87c70a7f1..c36192c22 100644 --- a/tests/ref/fate/filter-pan-upmix1 +++ b/tests/ref/fate/filter-pan-upmix1 @@ -2,7 +2,6 @@ #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 diff --git a/tests/ref/fate/filter-pan-upmix2 b/tests/ref/fate/filter-pan-upmix2 index 56db1c17e..1084a8f68 100644 --- a/tests/ref/fate/filter-pan-upmix2 +++ b/tests/ref/fate/filter-pan-upmix2 @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 44100 -#channel_layout 0: 0 #channel_layout_name 0: 9 channels 0, 0, 0, 512, 9216, 0xd561bb2b 0, 512, 512, 512, 9216, 0x591805f9 diff --git a/tests/ref/fate/filter-pixfmts-pad b/tests/ref/fate/filter-pixfmts-pad index 519473032..a30658bed 100644 --- a/tests/ref/fate/filter-pixfmts-pad +++ b/tests/ref/fate/filter-pixfmts-pad @@ -6,9 +6,9 @@ bgr0 025d4d5e5691801ba39bc9de70e39df0 bgr24 f8b65ad845905c7d0c93ca28dfbb826f bgra 929aac15e848038e367c250037575f9f gbrap 5f16cccab5a17cb766c882e865995167 -gbrap10le a677322100409f9b1d22136b14bfb534 -gbrap12le e0e43f838cfbe98086042ba54b5f70be -gbrap16le 0f4414db67b84a720106d7a3b2435766 +gbrap10le e63e0a1ae9afd7e6a732f18be194e761 +gbrap12le eb7a5ff44a9b5b46bb9829838224ed8e +gbrap16le d0f6fc33cb75588327aec1b5ad6ab4f0 gbrp 3c94d39256db2409015df913fd330a90 gbrp10le 5b356737cd8a396f39bbdadb7cb35e06 gbrp12le 91fdad0d1edf7bfa2805e2041e8da3cd @@ -17,63 +17,63 @@ gbrp16le a6156d1a37e05ee621b2a343fb158bd6 gbrp9le 9e827f438e081d334a6cae7e282698b0 gray ddc663a0491df3959d9c5795dceaa72e gray10le e6559c1c8c05ce89f44b465573db44e7 -gray12le 1e6c6757658c7ae8a1f830432c5b7722 -gray14le af3f2f911c71cb34a8179a3291b5c90f -gray16le 468bda6155bdc7a7a20c34d6e599fd16 +gray12le b066dd276b1698ee77d0c7eb95ff78c5 +gray14le 6d6b293b5d50944c5aa422245987c78e +gray16le 2734ce1793a2216c5be30816689cd2fe gray9le f8f3dfe31ca5fcba828285bceefdab9a nv12 381574979cb04be10c9168540310afad nv21 0fdeb2cdd56cf5a7147dc273456fa217 nv24 193b9eadcc06ad5081609f76249b3e47 nv42 1738ad3c31c6c16e17679f5b09ce4677 -p010le c57224f2dc09601c66aa3365b3cd7254 -p016le c57224f2dc09601c66aa3365b3cd7254 -p210le abc02945a9b9585f0914716e4787cefb -p216le 1b43feb94b8a030c0c699aa0deff017b -p410le 1f0294141ae1657d6c10c6a0d46a879f -p416le 320e558b7ee8d598231ae0763ecca275 +p010le fbbc23cc1d764a5e6fb71883d985f3ed +p016le fbbc23cc1d764a5e6fb71883d985f3ed +p210le 680912c059de39c3401cac856bd1b0c1 +p216le 8718662e226a4581561e7bb532af2d83 +p410le 5ca28f2bcc849987810e1f3437b12feb +p416le fa4e023d0bf4b03b0ffef3d4d35abf7e rgb0 0984eb985dabbe757ed6beb53db84eff rgb24 17f9e2e0c609009acaf2175c42d4a2a5 rgba b157c90191463d34fb3ce77b36c96386 -xyz12le 85abf80b77a9236a76ba0b00fcbdea2d -ya16le d85740ba2cac9fa9ea8aaea8a5864407 +xyz12le 23dadbbba70b2925ce75fb8ba8080ba3 +ya16le 8dbfcb586abf626da7d1aca887a581b9 ya8 495daaca2dcb4f7aeba7652768b41ced yuv410p cb871dcc1e84a7ef1d21f9237b88cf6e yuv411p aec2c1740de9a62db0d41f4dda9121b0 yuv420p 4398e408fc35436ce4b20468946f58b6 -yuv420p10le 74518a7d68457c54da3300e80c683e9c -yuv420p12le 32086c64c814315aa9253580708a192e -yuv420p14le 265e9fefb8b92f3cae678eb3cf4e00b4 -yuv420p16le 1ca89e47164d5f2481e39d4ac6eab2ed -yuv420p9le 59f0209084d1d1dd2861e058d1df63f4 +yuv420p10le a7d29bbe4e103fc0fb62b465f9540efa +yuv420p12le dafaf94e8d16cd846623dcaba0bc81b3 +yuv420p14le ec80062819bc67f8866ba5105d8378ad +yuv420p16le 83e437e3d6b7418c4163c24d41e199fa +yuv420p9le 98a3bede99321386b9abab7926a9f553 yuv422p e43d68568d9f782908ba56bf1e09d5d5 -yuv422p10le 18667cf7f87d8ffe1c4cc3db2100c559 -yuv422p12le 71e32220fa1bbdcac95fb57ba0dbd4f0 -yuv422p14le a0064be4d29079a811e5a315341da09a -yuv422p16le 836057e9999c763697c66c21869492b8 -yuv422p9le 3213bed797e7b4cefa4f174dc33bf246 +yuv422p10le e3ec30aacff6c8abf6fe035a195ccd26 +yuv422p12le 921b8d532cf5d0eca4ab0fe9c6d4fef5 +yuv422p14le dc41548f336883e9fd9664f329bd2a0c +yuv422p16le 04c87d2fd42cba290a4d4099760e3ee4 +yuv422p9le 994a41c11610075c7b0c466f738f49e7 yuv440p a7e34de74c96b0224fe1381ec1db2ba7 -yuv440p10le f91a481e27be7ea4a38a878e5e4330a3 -yuv440p12le 0e9953a09ac09fe5f1523b350cf7cb72 +yuv440p10le 55787c7260462e50e96f316856adf9dc +yuv440p12le 869d3d9e0e12df253b79949d2b2c0561 yuv444p 6bfd89286dc36f2789b77d747ed8fa22 -yuv444p10le b10afb5fda970dbce8aac5aab981a8cb -yuv444p12le 8f1b4b0f91d309fdaaec8a1ba6c7107f -yuv444p14le 2a87a84fa01237de9c08dd7e9ffbf78d -yuv444p16le 28508867fe7470c3539f8a84e8fb8271 -yuv444p9le 99d39ef897c6037d6c7aa6e7a0398f84 +yuv444p10le ac3142be3d7b0ec4c1e4450cb8c376ef +yuv444p12le 4c7f29501e46f4d041222536697941d0 +yuv444p14le 13631aa3ecc332aee3b3360db45011c9 +yuv444p16le 613ec343b593dda43af15f015c193d0a +yuv444p9le 96fa344943468b5cd36be92b1c05f17f yuva420p 842c27169ecdcf6de79f2b787367b51c -yuva420p10le 336fcb42c5b665c2028661e73325b359 -yuva420p16le ff45de790e7bdd3c25d8aad51289aba9 -yuva420p9le 8ef1f3b3e01b5ce222e4caeec3dec396 +yuva420p10le 01083d6f0f0c1fc0f76dc46da7f32e50 +yuva420p16le 53d2ea80c2f19b297e3601c06642f97f +yuva420p9le 8df807c68b0afe6d3d4753752886bb06 yuva422p 91dcecc4bfdff1f0db9ef8b9b5b9ac2a -yuva422p10le 1ba292c74c8646fd077a6116142b1bc8 -yuva422p12le 50e59879a9b64ac0fc7f76a110537baa -yuva422p16le 383226550fe9c93d6e8bf0d45d1423d1 -yuva422p9le 0fb76788c905c6d448143aa3c5eae116 +yuva422p10le 27cb87faf1e8f96a04bed8440862f4eb +yuva422p12le ec0cfda381a1044f7af25d993d4b68a0 +yuva422p16le 8b616c87ea907167d27743acfba06d71 +yuva422p9le eb8b4803e85b5a5c64003c3f713c156f yuva444p fb60941a57596b277417a3c7c00aa194 -yuva444p10le 251ea4ead8300d752eb355a08cbb0352 -yuva444p12le f38b7c5747b43bcc6d647f143cb069cf -yuva444p16le 5b65287e1862d2d9f1ad2cfdcde94661 -yuva444p9le e6946c10b94c271e7ea24b3bcff314e1 +yuva444p10le 89491ef450706faf23341e401750d907 +yuva444p12le 06c47dba21328165dbb7ebb3da0a2fde +yuva444p16le d089b119c8dc964de9af12bfb38f89a0 +yuva444p9le b824d34ac49a1dc483c772e15310afcd yuvj411p 87dbac57b211ab4823c1abbd702f1516 yuvj420p 1abef62bce65131ca4913eb2006fd860 yuvj422p 198c57b519e2be14b150889bd7f94898 diff --git a/tests/ref/fate/filter-pixfmts-tinterlace_pad b/tests/ref/fate/filter-pixfmts-tinterlace_pad index 8f6b1c42e..81a696121 100644 --- a/tests/ref/fate/filter-pixfmts-tinterlace_pad +++ b/tests/ref/fate/filter-pixfmts-tinterlace_pad @@ -2,23 +2,23 @@ gray 7ef396fecd8d1c9fe32173e4415ba671 yuv410p 35bc11d0d32efc9e9a969be7d720f4e6 yuv411p 17ef3cd22a74f7368b5e02f68779f294 yuv420p 93d5b6a4c44d67e4d4447e8dd0bf3d33 -yuv420p10le 14e754c6e9d41cb048ce3c93512d7d35 -yuv420p12le ce54a2e38d121a7575dff30542facaad +yuv420p10le 88ad182fc4e29270938512464be38260 +yuv420p12le 11fe824c29883301e54daad1d0e0dc8f yuv422p 3ee40b0b6533b9183764b85c853ec3f9 -yuv422p10le d4b61a84b93e74b07b7020ceed40e39e -yuv422p12le 8fd90be12a97307645ecfcd09d576643 +yuv422p10le 9e2cf74a9a6fe34243a4e50766d47d5e +yuv422p12le 82358ff3766b61444c69602d2a042bee yuv440p 1d3c1258a51d09e778cd8368b1a4126f -yuv440p10le 29d116cb550a05920e5619ab58284d30 -yuv440p12le d7518f941a3b2c137f944afe9da816a1 +yuv440p10le 89ece83dea4a50567109d851b100b982 +yuv440p12le 357b1f84199ef86680d8b86fc876e04b yuv444p 1093568ad8f479ec20e738d018dd3f8f -yuv444p10le c65233e1d8b01f3369c20738f7386801 -yuv444p12le 70dc51a857bfb215b3a81fceb114b74c +yuv444p10le 6a34ecd89704817849e89c388503c27e +yuv444p12le 6a311c441646a084653019d85ad7f839 yuva420p 4588aef20c0010e514550c9391219724 -yuva420p10le 3181e84fd7aaed606bb86eecd2e13f20 +yuva420p10le 380f36ae2450fbc6e20aea3ad6abb163 yuva422p 3426ed1ac9429202d8c29fa62a04d4c3 -yuva422p10le c00acd7c437d41755dff09c5ca3642cf +yuva422p10le 5c62eaf71afec3f7bc7ae5a327431434 yuva444p 1b9fc791c7d774b4ba8c9dc836f78cf5 -yuva444p10le 616b42a232c83b8f9e5c5168ec4b5da5 +yuva444p10le b6161c0f6f5548ba4346a9fda20ea8a8 yuvj420p 9a872e0c1b3c0b6fe856415696b758bd yuvj422p da3c9ef25528a2ee96746ce44e6969f3 yuvj440p a9a5495c6b0e2bf6e561998ea1c356a7 diff --git a/tests/ref/fate/filter-refcmp-blockdetect-yuv b/tests/ref/fate/filter-refcmp-blockdetect-yuv new file mode 100644 index 000000000..c3b3a3644 --- /dev/null +++ b/tests/ref/fate/filter-refcmp-blockdetect-yuv @@ -0,0 +1,10 @@ +frame:0 pts:0 pts_time:0 +lavfi.block=46.592525 +frame:1 pts:1 pts_time:1 +lavfi.block=40.478703 +frame:2 pts:2 pts_time:2 +lavfi.block=40.858681 +frame:3 pts:3 pts_time:3 +lavfi.block=39.519077 +frame:4 pts:4 pts_time:4 +lavfi.block=38.713215 diff --git a/tests/ref/fate/filter-refcmp-blurdetect-yuv b/tests/ref/fate/filter-refcmp-blurdetect-yuv new file mode 100644 index 000000000..426321db0 --- /dev/null +++ b/tests/ref/fate/filter-refcmp-blurdetect-yuv @@ -0,0 +1,10 @@ +frame:0 pts:0 pts_time:0 +lavfi.blur=4.499666 +frame:1 pts:1 pts_time:1 +lavfi.blur=4.677492 +frame:2 pts:2 pts_time:2 +lavfi.blur=4.735711 +frame:3 pts:3 pts_time:3 +lavfi.blur=4.532343 +frame:4 pts:4 pts_time:4 +lavfi.blur=4.532660 diff --git a/tests/ref/fate/filter-refcmp-psnr-rgb b/tests/ref/fate/filter-refcmp-psnr-rgb index f06db575a..20abd3dc5 100644 --- a/tests/ref/fate/filter-refcmp-psnr-rgb +++ b/tests/ref/fate/filter-refcmp-psnr-rgb @@ -1,45 +1,45 @@ frame:0 pts:0 pts_time:0 -lavfi.psnr.mse.r=1381.80 -lavfi.psnr.psnr.r=16.73 -lavfi.psnr.mse.g=896.00 -lavfi.psnr.psnr.g=18.61 -lavfi.psnr.mse.b=277.38 -lavfi.psnr.psnr.b=23.70 -lavfi.psnr.mse_avg=851.73 -lavfi.psnr.psnr_avg=18.83 +lavfi.psnr.mse.r=1367.642090 +lavfi.psnr.psnr.r=16.771078 +lavfi.psnr.mse.g=885.804382 +lavfi.psnr.psnr.g=18.657425 +lavfi.psnr.mse.b=274.825073 +lavfi.psnr.psnr.b=23.740240 +lavfi.psnr.mse_avg=842.757202 +lavfi.psnr.psnr_avg=18.873779 frame:1 pts:1 pts_time:1 -lavfi.psnr.mse.r=1380.37 -lavfi.psnr.psnr.r=16.73 -lavfi.psnr.mse.g=975.91 -lavfi.psnr.psnr.g=18.24 -lavfi.psnr.mse.b=435.72 -lavfi.psnr.psnr.b=21.74 -lavfi.psnr.mse_avg=930.67 -lavfi.psnr.psnr_avg=18.44 +lavfi.psnr.mse.r=1356.681152 +lavfi.psnr.psnr.r=16.806026 +lavfi.psnr.mse.g=958.161560 +lavfi.psnr.psnr.g=18.316416 +lavfi.psnr.mse.b=428.238312 +lavfi.psnr.psnr.b=21.813948 +lavfi.psnr.mse_avg=914.360352 +lavfi.psnr.psnr_avg=18.519630 frame:2 pts:2 pts_time:2 -lavfi.psnr.mse.r=1403.20 -lavfi.psnr.psnr.r=16.66 -lavfi.psnr.mse.g=954.05 -lavfi.psnr.psnr.g=18.34 -lavfi.psnr.mse.b=494.22 -lavfi.psnr.psnr.b=21.19 -lavfi.psnr.mse_avg=950.49 -lavfi.psnr.psnr_avg=18.35 +lavfi.psnr.mse.r=1387.254883 +lavfi.psnr.psnr.r=16.709242 +lavfi.psnr.mse.g=939.230957 +lavfi.psnr.psnr.g=18.403080 +lavfi.psnr.mse.b=493.913757 +lavfi.psnr.psnr.b=21.194292 +lavfi.psnr.mse_avg=940.133179 +lavfi.psnr.psnr_avg=18.398911 frame:3 pts:3 pts_time:3 -lavfi.psnr.mse.r=1452.80 -lavfi.psnr.psnr.r=16.51 -lavfi.psnr.mse.g=1001.02 -lavfi.psnr.psnr.g=18.13 -lavfi.psnr.mse.b=557.39 -lavfi.psnr.psnr.b=20.67 -lavfi.psnr.mse_avg=1003.74 -lavfi.psnr.psnr_avg=18.11 +lavfi.psnr.mse.r=1433.291260 +lavfi.psnr.psnr.r=16.567459 +lavfi.psnr.mse.g=990.005859 +lavfi.psnr.psnr.g=18.174425 +lavfi.psnr.mse.b=550.512329 +lavfi.psnr.psnr.b=20.723133 +lavfi.psnr.mse_avg=991.269836 +lavfi.psnr.psnr_avg=18.168884 frame:4 pts:4 pts_time:4 -lavfi.psnr.mse.r=1401.25 -lavfi.psnr.psnr.r=16.67 -lavfi.psnr.mse.g=1009.80 -lavfi.psnr.psnr.g=18.09 -lavfi.psnr.mse.b=602.42 -lavfi.psnr.psnr.b=20.33 -lavfi.psnr.mse_avg=1004.49 -lavfi.psnr.psnr_avg=18.11 +lavfi.psnr.mse.r=1385.949341 +lavfi.psnr.psnr.r=16.713329 +lavfi.psnr.mse.g=997.065796 +lavfi.psnr.psnr.g=18.143566 +lavfi.psnr.mse.b=601.962952 +lavfi.psnr.psnr.b=20.335106 +lavfi.psnr.mse_avg=994.992676 +lavfi.psnr.psnr_avg=18.152605 diff --git a/tests/ref/fate/filter-refcmp-siti-yuv b/tests/ref/fate/filter-refcmp-siti-yuv new file mode 100644 index 000000000..5d99972d9 --- /dev/null +++ b/tests/ref/fate/filter-refcmp-siti-yuv @@ -0,0 +1,15 @@ +frame:0 pts:0 pts_time:0 +lavfi.siti.si=106.72 +lavfi.siti.ti=0.00 +frame:1 pts:1 pts_time:1 +lavfi.siti.si=109.40 +lavfi.siti.ti=28.00 +frame:2 pts:2 pts_time:2 +lavfi.siti.si=109.29 +lavfi.siti.ti=28.38 +frame:3 pts:3 pts_time:3 +lavfi.siti.si=113.27 +lavfi.siti.ti=33.42 +frame:4 pts:4 pts_time:4 +lavfi.siti.si=110.87 +lavfi.siti.ti=30.53 diff --git a/tests/ref/fate/filter-silenceremove b/tests/ref/fate/filter-silenceremove index 58b5a3860..26f565167 100644 --- a/tests/ref/fate/filter-silenceremove +++ b/tests/ref/fate/filter-silenceremove @@ -2,7 +2,6 @@ #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, 8192, 16384, 0x00000000 0, 8192, 8192, 8192, 16384, 0x00000000 diff --git a/tests/ref/fate/filter-stereotools b/tests/ref/fate/filter-stereotools index 60acaf81b..60a74893b 100644 --- a/tests/ref/fate/filter-stereotools +++ b/tests/ref/fate/filter-stereotools @@ -2,7 +2,6 @@ #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, 0x48b6d241 0, 1024, 1024, 1024, 4096, 0xe0c4ca9a diff --git a/tests/ref/fate/filter-testsrc2-yuv420p b/tests/ref/fate/filter-testsrc2-yuv420p index aaf93ba02..4aab3955b 100644 --- a/tests/ref/fate/filter-testsrc2-yuv420p +++ b/tests/ref/fate/filter-testsrc2-yuv420p @@ -3,73 +3,73 @@ #codec_id 0: rawvideo #dimensions 0: 320x240 #sar 0: 1/1 -0, 0, 0, 1, 115200, 0x3744b3ed -0, 1, 1, 1, 115200, 0x0c1062d6 -0, 2, 2, 1, 115200, 0x201b9db1 -0, 3, 3, 1, 115200, 0x278d887e -0, 4, 4, 1, 115200, 0x309b9c06 -0, 5, 5, 1, 115200, 0x75e1a17b -0, 6, 6, 1, 115200, 0xa14e9aca -0, 7, 7, 1, 115200, 0xb73857e2 -0, 8, 8, 1, 115200, 0x686b77e7 -0, 9, 9, 1, 115200, 0x02b6ab21 -0, 10, 10, 1, 115200, 0x1fc2d693 -0, 11, 11, 1, 115200, 0x296dd4a5 -0, 12, 12, 1, 115200, 0x2d0ba5a4 -0, 13, 13, 1, 115200, 0x59e85f83 -0, 14, 14, 1, 115200, 0xc95a675e -0, 15, 15, 1, 115200, 0x40426f99 -0, 16, 16, 1, 115200, 0xf040bf35 -0, 17, 17, 1, 115200, 0xc705ccd9 -0, 18, 18, 1, 115200, 0xa76dcd9d -0, 19, 19, 1, 115200, 0x5635daa5 -0, 20, 20, 1, 115200, 0x3af5d306 -0, 21, 21, 1, 115200, 0x0caf7172 -0, 22, 22, 1, 115200, 0x7161ef8f -0, 23, 23, 1, 115200, 0xc8ce7fb1 -0, 24, 24, 1, 115200, 0xccf02fed -0, 25, 25, 1, 115200, 0x81cdf49f -0, 26, 26, 1, 115200, 0xb9170ee1 -0, 27, 27, 1, 115200, 0x7e7d78d0 -0, 28, 28, 1, 115200, 0xfe4c0185 -0, 29, 29, 1, 115200, 0x9dde4256 -0, 30, 30, 1, 115200, 0x1eb35d69 -0, 31, 31, 1, 115200, 0xad3d2e3f -0, 32, 32, 1, 115200, 0xf3282aa1 -0, 33, 33, 1, 115200, 0x1cef3c17 -0, 34, 34, 1, 115200, 0x688a442c -0, 35, 35, 1, 115200, 0x2cdb327a -0, 36, 36, 1, 115200, 0xe6c16f00 -0, 37, 37, 1, 115200, 0x6f8fac56 -0, 38, 38, 1, 115200, 0x54e8d2a1 -0, 39, 39, 1, 115200, 0x29afc657 -0, 40, 40, 1, 115200, 0xb3138f57 -0, 41, 41, 1, 115200, 0x169041ca -0, 42, 42, 1, 115200, 0x9e3e4e2b -0, 43, 43, 1, 115200, 0x192977ac -0, 44, 44, 1, 115200, 0x4aefe354 -0, 45, 45, 1, 115200, 0xc575c060 -0, 46, 46, 1, 115200, 0xfe3ec033 -0, 47, 47, 1, 115200, 0xab53a3e7 -0, 48, 48, 1, 115200, 0xbe229fcb -0, 49, 49, 1, 115200, 0x088e58c3 -0, 50, 50, 1, 115200, 0x79eaf2db -0, 51, 51, 1, 115200, 0xb32489ab -0, 52, 52, 1, 115200, 0x125d1db7 -0, 53, 53, 1, 115200, 0x81efd887 -0, 54, 54, 1, 115200, 0x0eb22945 -0, 55, 55, 1, 115200, 0x46cca5d0 -0, 56, 56, 1, 115200, 0x636c4203 -0, 57, 57, 1, 115200, 0x3d3074a6 -0, 58, 58, 1, 115200, 0xe92f787e -0, 59, 59, 1, 115200, 0xd0cd4ecf -0, 60, 60, 1, 115200, 0xf3ac6472 -0, 61, 61, 1, 115200, 0xac8063b4 -0, 62, 62, 1, 115200, 0x2b0c68f2 -0, 63, 63, 1, 115200, 0xc6173b40 -0, 64, 64, 1, 115200, 0x12c35e41 -0, 65, 65, 1, 115200, 0x57c48fdd -0, 66, 66, 1, 115200, 0x1079be75 -0, 67, 67, 1, 115200, 0xc8e7d33e -0, 68, 68, 1, 115200, 0x79cdac12 -0, 69, 69, 1, 115200, 0x8dbe5a5f +0, 0, 0, 1, 115200, 0xeba70ff3 +0, 1, 1, 1, 115200, 0xb986bcbd +0, 2, 2, 1, 115200, 0x8567f6cf +0, 3, 3, 1, 115200, 0xed18e21f +0, 4, 4, 1, 115200, 0x0054f5dd +0, 5, 5, 1, 115200, 0x6fedfa63 +0, 6, 6, 1, 115200, 0x3226f459 +0, 7, 7, 1, 115200, 0x04cab318 +0, 8, 8, 1, 115200, 0xa4e0d22b +0, 9, 9, 1, 115200, 0xc2c4037c +0, 10, 10, 1, 115200, 0x32332c36 +0, 11, 11, 1, 115200, 0x93892b01 +0, 12, 12, 1, 115200, 0xa611fd70 +0, 13, 13, 1, 115200, 0xc875b905 +0, 14, 14, 1, 115200, 0xe4e2c25a +0, 15, 15, 1, 115200, 0x0fa5c984 +0, 16, 16, 1, 115200, 0x7f601649 +0, 17, 17, 1, 115200, 0x127c21d0 +0, 18, 18, 1, 115200, 0x5cef2244 +0, 19, 19, 1, 115200, 0x4194305c +0, 20, 20, 1, 115200, 0xe1342b12 +0, 21, 21, 1, 115200, 0x7c13cdb3 +0, 22, 22, 1, 115200, 0x274845a7 +0, 23, 23, 1, 115200, 0x57d4cca0 +0, 24, 24, 1, 115200, 0x9aa1765a +0, 25, 25, 1, 115200, 0x939e3b09 +0, 26, 26, 1, 115200, 0xf0045ba2 +0, 27, 27, 1, 115200, 0xc74ace89 +0, 28, 28, 1, 115200, 0x19725c72 +0, 29, 29, 1, 115200, 0x21aa9b86 +0, 30, 30, 1, 115200, 0x1714b5da +0, 31, 31, 1, 115200, 0xe2fd85e2 +0, 32, 32, 1, 115200, 0x1b498308 +0, 33, 33, 1, 115200, 0xab1994a0 +0, 34, 34, 1, 115200, 0x1cf29d03 +0, 35, 35, 1, 115200, 0x7a068cd1 +0, 36, 36, 1, 115200, 0x5afac88e +0, 37, 37, 1, 115200, 0x72680431 +0, 38, 38, 1, 115200, 0xe982288c +0, 39, 39, 1, 115200, 0xcd3d1c48 +0, 40, 40, 1, 115200, 0x05a4e5f5 +0, 41, 41, 1, 115200, 0x14eb99ee +0, 42, 42, 1, 115200, 0x0fc1a8cc +0, 43, 43, 1, 115200, 0x460ed0ca +0, 44, 44, 1, 115200, 0xcaf53a3e +0, 45, 45, 1, 115200, 0x90dd14e0 +0, 46, 46, 1, 115200, 0xe9531496 +0, 47, 47, 1, 115200, 0xda57f8d6 +0, 48, 48, 1, 115200, 0xb932f7cc +0, 49, 49, 1, 115200, 0x4669b433 +0, 50, 50, 1, 115200, 0xb59e4897 +0, 51, 51, 1, 115200, 0xc51dd6a1 +0, 52, 52, 1, 115200, 0x0549630f +0, 53, 53, 1, 115200, 0xbd671e9b +0, 54, 54, 1, 115200, 0x0e2e7627 +0, 55, 55, 1, 115200, 0x6213fc0b +0, 56, 56, 1, 115200, 0x58ee9d54 +0, 57, 57, 1, 115200, 0xa5c3ce29 +0, 58, 58, 1, 115200, 0x38b7d09b +0, 59, 59, 1, 115200, 0x0539a7b6 +0, 60, 60, 1, 115200, 0x2f28bd54 +0, 61, 61, 1, 115200, 0x5a60bc58 +0, 62, 62, 1, 115200, 0x4f8fc1a3 +0, 63, 63, 1, 115200, 0x58169676 +0, 64, 64, 1, 115200, 0x9662b826 +0, 65, 65, 1, 115200, 0x2e92e7c5 +0, 66, 66, 1, 115200, 0x470214d5 +0, 67, 67, 1, 115200, 0xd20929be +0, 68, 68, 1, 115200, 0xfbb40344 +0, 69, 69, 1, 115200, 0xb55cb3a9 diff --git a/tests/ref/fate/filter-testsrc2-yuv444p b/tests/ref/fate/filter-testsrc2-yuv444p index 4b60e6afa..dea8300ee 100644 --- a/tests/ref/fate/filter-testsrc2-yuv444p +++ b/tests/ref/fate/filter-testsrc2-yuv444p @@ -3,73 +3,73 @@ #codec_id 0: rawvideo #dimensions 0: 320x240 #sar 0: 1/1 -0, 0, 0, 1, 230400, 0xbfb96366 -0, 1, 1, 1, 230400, 0xe63ca6e9 -0, 2, 2, 1, 230400, 0xc6acccc8 -0, 3, 3, 1, 230400, 0x6ea1b629 -0, 4, 4, 1, 230400, 0x508477ed -0, 5, 5, 1, 230400, 0x49d4d57c -0, 6, 6, 1, 230400, 0xd601a939 -0, 7, 7, 1, 230400, 0x0a0288f3 -0, 8, 8, 1, 230400, 0xa6da89f8 -0, 9, 9, 1, 230400, 0x0490ac8e -0, 10, 10, 1, 230400, 0x1873ccd2 -0, 11, 11, 1, 230400, 0x64ef9885 -0, 12, 12, 1, 230400, 0x6b8fa2f0 -0, 13, 13, 1, 230400, 0x8d9657a4 -0, 14, 14, 1, 230400, 0xb4af4f21 -0, 15, 15, 1, 230400, 0x64137e0e -0, 16, 16, 1, 230400, 0xb8b26ce2 -0, 17, 17, 1, 230400, 0xee1e7b00 -0, 18, 18, 1, 230400, 0x1c9b25d8 -0, 19, 19, 1, 230400, 0xe0c761ab -0, 20, 20, 1, 230400, 0xe1cf0c14 -0, 21, 21, 1, 230400, 0xea380055 -0, 22, 22, 1, 230400, 0x6537716f -0, 23, 23, 1, 230400, 0x8d9b9380 -0, 24, 24, 1, 230400, 0x9a04e333 -0, 25, 25, 1, 230400, 0x78005375 -0, 26, 26, 1, 230400, 0xc1cc9b9e -0, 27, 27, 1, 230400, 0x84fda020 -0, 28, 28, 1, 230400, 0x711ef4ab -0, 29, 29, 1, 230400, 0xccd04c02 -0, 30, 30, 1, 230400, 0xcf2a4bbd -0, 31, 31, 1, 230400, 0x6d0ef0c0 -0, 32, 32, 1, 230400, 0x46141d09 -0, 33, 33, 1, 230400, 0x3a3d3f71 -0, 34, 34, 1, 230400, 0xe9e7f98f -0, 35, 35, 1, 230400, 0x0f618ebb -0, 36, 36, 1, 230400, 0x9c7d07b2 -0, 37, 37, 1, 230400, 0x90f8e960 -0, 38, 38, 1, 230400, 0xe3a856aa -0, 39, 39, 1, 230400, 0xc66dcd53 -0, 40, 40, 1, 230400, 0xe7c1a281 -0, 41, 41, 1, 230400, 0xff484046 -0, 42, 42, 1, 230400, 0x1f56e486 -0, 43, 43, 1, 230400, 0x46bba179 -0, 44, 44, 1, 230400, 0x05a05e03 -0, 45, 45, 1, 230400, 0x552d3d32 -0, 46, 46, 1, 230400, 0x0899531d -0, 47, 47, 1, 230400, 0x6321c950 -0, 48, 48, 1, 230400, 0xed67b3cc -0, 49, 49, 1, 230400, 0x37ec807d -0, 50, 50, 1, 230400, 0xc6af1344 -0, 51, 51, 1, 230400, 0x2bc9132b -0, 52, 52, 1, 230400, 0x6024e553 -0, 53, 53, 1, 230400, 0xd7cef4f3 -0, 54, 54, 1, 230400, 0xf7f6eb0d -0, 55, 55, 1, 230400, 0x0a2ed09e -0, 56, 56, 1, 230400, 0x8c6883aa -0, 57, 57, 1, 230400, 0x8542f554 -0, 58, 58, 1, 230400, 0xbebf972f -0, 59, 59, 1, 230400, 0xf6f5f05f -0, 60, 60, 1, 230400, 0xa4047f4a -0, 61, 61, 1, 230400, 0x2b3f3d82 -0, 62, 62, 1, 230400, 0x99d9049a -0, 63, 63, 1, 230400, 0xe74e5520 -0, 64, 64, 1, 230400, 0x04e2cd3d -0, 65, 65, 1, 230400, 0x2324e05e -0, 66, 66, 1, 230400, 0x4e4e3400 -0, 67, 67, 1, 230400, 0xdd547c3e -0, 68, 68, 1, 230400, 0x1c6c13e4 -0, 69, 69, 1, 230400, 0xf7d2d98b +0, 0, 0, 1, 230400, 0x8246c007 +0, 1, 1, 1, 230400, 0xd2d501cf +0, 2, 2, 1, 230400, 0xdf1f26c3 +0, 3, 3, 1, 230400, 0x382310b6 +0, 4, 4, 1, 230400, 0x8f91d242 +0, 5, 5, 1, 230400, 0x5dbb2f6f +0, 6, 6, 1, 230400, 0x604503bb +0, 7, 7, 1, 230400, 0x6df5e4e5 +0, 8, 8, 1, 230400, 0x659de4a1 +0, 9, 9, 1, 230400, 0x987b0539 +0, 10, 10, 1, 230400, 0xaaab2384 +0, 11, 11, 1, 230400, 0x5810efe0 +0, 12, 12, 1, 230400, 0x6199fb72 +0, 13, 13, 1, 230400, 0x66d6b1d1 +0, 14, 14, 1, 230400, 0x9fc4ab0d +0, 15, 15, 1, 230400, 0x5acfd8e5 +0, 16, 16, 1, 230400, 0x7eacc4ea +0, 17, 17, 1, 230400, 0xd000d086 +0, 18, 18, 1, 230400, 0x80ec7b3c +0, 19, 19, 1, 230400, 0x9e33b7fb +0, 20, 20, 1, 230400, 0x31ad6518 +0, 21, 21, 1, 230400, 0x652a5d45 +0, 22, 22, 1, 230400, 0xce5bc872 +0, 23, 23, 1, 230400, 0xade7e144 +0, 24, 24, 1, 230400, 0x537e2a7d +0, 25, 25, 1, 230400, 0x0e759a3a +0, 26, 26, 1, 230400, 0xcd93e921 +0, 27, 27, 1, 230400, 0x2153f6a3 +0, 28, 28, 1, 230400, 0xc1bb504c +0, 29, 29, 1, 230400, 0xfb7ea59e +0, 30, 30, 1, 230400, 0x1400a4b2 +0, 31, 31, 1, 230400, 0x04494972 +0, 32, 32, 1, 230400, 0x10397662 +0, 33, 33, 1, 230400, 0x748f9891 +0, 34, 34, 1, 230400, 0xb84c52fa +0, 35, 35, 1, 230400, 0x9cebe9f2 +0, 36, 36, 1, 230400, 0x40a4620f +0, 37, 37, 1, 230400, 0x03194269 +0, 38, 38, 1, 230400, 0x9ad8ad4f +0, 39, 39, 1, 230400, 0x3b9d2447 +0, 40, 40, 1, 230400, 0x989df99d +0, 41, 41, 1, 230400, 0x83e0993e +0, 42, 42, 1, 230400, 0xf8fc3fd9 +0, 43, 43, 1, 230400, 0x4203fbc1 +0, 44, 44, 1, 230400, 0x22c3b599 +0, 45, 45, 1, 230400, 0x1be8926e +0, 46, 46, 1, 230400, 0xdc2fa7e1 +0, 47, 47, 1, 230400, 0x0dca1f48 +0, 48, 48, 1, 230400, 0x1b850c96 +0, 49, 49, 1, 230400, 0x08efdcac +0, 50, 50, 1, 230400, 0xaf3c6970 +0, 51, 51, 1, 230400, 0xe06e609b +0, 52, 52, 1, 230400, 0xb2b52bce +0, 53, 53, 1, 230400, 0xbbf53c13 +0, 54, 54, 1, 230400, 0x434d38e1 +0, 55, 55, 1, 230400, 0x64582812 +0, 56, 56, 1, 230400, 0xe40adfec +0, 57, 57, 1, 230400, 0xb3144fb2 +0, 58, 58, 1, 230400, 0x0ea4f04d +0, 59, 59, 1, 230400, 0x982249e9 +0, 60, 60, 1, 230400, 0x3c36d921 +0, 61, 61, 1, 230400, 0xe75a96ad +0, 62, 62, 1, 230400, 0xb7055e41 +0, 63, 63, 1, 230400, 0x90d0b0f3 +0, 64, 64, 1, 230400, 0xa0ae280c +0, 65, 65, 1, 230400, 0x67bf38f7 +0, 66, 66, 1, 230400, 0x211d8b11 +0, 67, 67, 1, 230400, 0x0463d344 +0, 68, 68, 1, 230400, 0xa3306bec +0, 69, 69, 1, 230400, 0x784833cc diff --git a/tests/ref/fate/filter-tpad-add b/tests/ref/fate/filter-tpad-add new file mode 100644 index 000000000..10e01655a --- /dev/null +++ b/tests/ref/fate/filter-tpad-add @@ -0,0 +1,11 @@ +#tb 0: 1/2 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 320x240 +#sar 0: 1/1 +0, 0, 0, 1, 115200, 0x2213b502 +0, 1, 1, 1, 115200, 0xeba70ff3 +0, 2, 2, 1, 115200, 0xa764e4d5 +0, 3, 3, 1, 115200, 0x2213b502 +0, 4, 4, 1, 115200, 0x2213b502 +0, 5, 5, 1, 115200, 0x2213b502 diff --git a/tests/ref/fate/filter-tpad-clone b/tests/ref/fate/filter-tpad-clone new file mode 100644 index 000000000..fceab34b7 --- /dev/null +++ b/tests/ref/fate/filter-tpad-clone @@ -0,0 +1,10 @@ +#tb 0: 1/2 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 320x240 +#sar 0: 1/1 +0, 0, 0, 1, 115200, 0x375ec573 +0, 1, 1, 1, 115200, 0xeba70ff3 +0, 2, 2, 1, 115200, 0xa764e4d5 +0, 3, 3, 1, 115200, 0xa764e4d5 +0, 4, 4, 1, 115200, 0xa764e4d5 diff --git a/tests/ref/fate/filter-unsharp-yuv420p10 b/tests/ref/fate/filter-unsharp-yuv420p10 index 513ee7894..302becaa3 100644 --- a/tests/ref/fate/filter-unsharp-yuv420p10 +++ b/tests/ref/fate/filter-unsharp-yuv420p10 @@ -3,23 +3,23 @@ #codec_id 0: rawvideo #dimensions 0: 320x240 #sar 0: 1/1 -0, 0, 0, 1, 230400, 0x091f3ed7 -0, 1, 1, 1, 230400, 0x4151292d -0, 2, 2, 1, 230400, 0xe7066e96 -0, 3, 3, 1, 230400, 0x57c20d15 -0, 4, 4, 1, 230400, 0x01269a37 -0, 5, 5, 1, 230400, 0xb2b04e5c -0, 6, 6, 1, 230400, 0x98fc479f -0, 7, 7, 1, 230400, 0x561915bb -0, 8, 8, 1, 230400, 0xd60c45f7 -0, 9, 9, 1, 230400, 0x747d8a28 -0, 10, 10, 1, 230400, 0x92505d36 -0, 11, 11, 1, 230400, 0x9476af1f -0, 12, 12, 1, 230400, 0x1382c3d0 -0, 13, 13, 1, 230400, 0x94ea40bd -0, 14, 14, 1, 230400, 0x8d46229a -0, 15, 15, 1, 230400, 0xe5736654 -0, 16, 16, 1, 230400, 0x04bd4db2 -0, 17, 17, 1, 230400, 0x4d721ad2 -0, 18, 18, 1, 230400, 0xebe151a2 -0, 19, 19, 1, 230400, 0xa1263f01 +0, 0, 0, 1, 230400, 0x5166b2b0 +0, 1, 1, 1, 230400, 0x1fcc8e0e +0, 2, 2, 1, 230400, 0xce04db47 +0, 3, 3, 1, 230400, 0xc25661af +0, 4, 4, 1, 230400, 0x727f06aa +0, 5, 5, 1, 230400, 0x2e0f9cc5 +0, 6, 6, 1, 230400, 0x407fb93b +0, 7, 7, 1, 230400, 0xc19c2087 +0, 8, 8, 1, 230400, 0xacacb223 +0, 9, 9, 1, 230400, 0x1277e355 +0, 10, 10, 1, 230400, 0xcd36c65d +0, 11, 11, 1, 230400, 0x6c530182 +0, 12, 12, 1, 230400, 0x803b2da3 +0, 13, 13, 1, 230400, 0x82638dc2 +0, 14, 14, 1, 230400, 0x2064904b +0, 15, 15, 1, 230400, 0xce3a7092 +0, 16, 16, 1, 230400, 0x374abb39 +0, 17, 17, 1, 230400, 0xf8b37d16 +0, 18, 18, 1, 230400, 0xb3d1c642 +0, 19, 19, 1, 230400, 0xc9b392d1 diff --git a/tests/ref/fate/filter-untile b/tests/ref/fate/filter-untile index 42c741acf..9180bf8ba 100644 --- a/tests/ref/fate/filter-untile +++ b/tests/ref/fate/filter-untile @@ -3,11 +3,11 @@ #codec_id 0: rawvideo #dimensions 0: 160x120 #sar 0: 1/1 -0, 0, 0, 1, 28800, 0xb3725302 -0, 1, 1, 1, 28800, 0xf9612057 -0, 2, 2, 1, 28800, 0x9b207db0 -0, 3, 3, 1, 28800, 0x1331c2d5 -0, 4, 4, 1, 28800, 0x2edf3ee4 -0, 5, 5, 1, 28800, 0x84105711 -0, 6, 6, 1, 28800, 0xa7a35f25 -0, 7, 7, 1, 28800, 0xa9c49677 +0, 0, 0, 1, 28800, 0xcb69686a +0, 1, 1, 1, 28800, 0xb9c13766 +0, 2, 2, 1, 28800, 0xeb439680 +0, 3, 3, 1, 28800, 0x16e9d985 +0, 4, 4, 1, 28800, 0x2f985496 +0, 5, 5, 1, 28800, 0xf71f6f72 +0, 6, 6, 1, 28800, 0x0d447518 +0, 7, 7, 1, 28800, 0xf990aba6 diff --git a/tests/ref/fate/fitsdec-gbrap16le b/tests/ref/fate/fitsdec-gbrap16le index 78abb5cde..53ef980b1 100644 --- a/tests/ref/fate/fitsdec-gbrap16le +++ b/tests/ref/fate/fitsdec-gbrap16le @@ -1,3 +1,5 @@ +64526d8da12d1fa07ceea5725647076f *tests/data/fate/fitsdec-gbrap16le.fits +135360 tests/data/fate/fitsdec-gbrap16le.fits #tb 0: 1/1 #media_type 0: video #codec_id 0: rawvideo diff --git a/tests/ref/fate/fitsdec-gbrp b/tests/ref/fate/fitsdec-gbrp index 8767b6715..23249f492 100644 --- a/tests/ref/fate/fitsdec-gbrp +++ b/tests/ref/fate/fitsdec-gbrp @@ -1,3 +1,5 @@ +38e232e4c1ca57b5866efa01da70359c *tests/data/fate/fitsdec-gbrp.fits +54720 tests/data/fate/fitsdec-gbrp.fits #tb 0: 1/1 #media_type 0: video #codec_id 0: rawvideo diff --git a/tests/ref/fate/fitsdec-gbrp16 b/tests/ref/fate/fitsdec-gbrp16 index f6368f2c0..9250690e9 100644 --- a/tests/ref/fate/fitsdec-gbrp16 +++ b/tests/ref/fate/fitsdec-gbrp16 @@ -1,3 +1,5 @@ +2078208c93ba417d3fe150ba42bf5a30 *tests/data/fate/fitsdec-gbrp16.fits +103680 tests/data/fate/fitsdec-gbrp16.fits #tb 0: 1/1 #media_type 0: video #codec_id 0: rawvideo diff --git a/tests/ref/fate/fitsdec-gray b/tests/ref/fate/fitsdec-gray index 488ee7102..b7992bfda 100644 --- a/tests/ref/fate/fitsdec-gray +++ b/tests/ref/fate/fitsdec-gray @@ -1,3 +1,5 @@ +c02ac3e0a9f2ceeb1e6e66c085a63671 *tests/data/fate/fitsdec-gray.fits +20160 tests/data/fate/fitsdec-gray.fits #tb 0: 1/1 #media_type 0: video #codec_id 0: rawvideo diff --git a/tests/ref/fate/flv-add_keyframe_index b/tests/ref/fate/flv-add_keyframe_index index 1c4da65d9..39c4bed85 100644 --- a/tests/ref/fate/flv-add_keyframe_index +++ b/tests/ref/fate/flv-add_keyframe_index @@ -1,12 +1,21 @@ -;FFMETADATA1 -hasVideo=true -hasKeyframes=true -hasAudio=false -hasMetadata=true -canSeekToEnd=true -datasize=629776 -videosize=629381 -audiosize=0 -lasttimestamp=20 -lastkeyframetimestamp=19 -lastkeyframelocation=597963 +5f38d76da3ed4a5be06ca604c53666f2 *tests/data/fate/flv-add_keyframe_index.flv +630192 tests/data/fate/flv-add_keyframe_index.flv +#tb 0: 1/1000 +#media_type 0: video +#codec_id 0: flv1 +#dimensions 0: 320x240 +#sar 0: 0/1 +0, 0, 0, 143, 9597, 0xd91d5859 +[FORMAT] +TAG:hasVideo=true +TAG:hasKeyframes=true +TAG:hasAudio=false +TAG:hasMetadata=true +TAG:canSeekToEnd=true +TAG:datasize=629776 +TAG:videosize=629381 +TAG:audiosize=0 +TAG:lasttimestamp=20 +TAG:lastkeyframetimestamp=19 +TAG:lastkeyframelocation=597963 +[/FORMAT] diff --git a/tests/ref/fate/g722-encode b/tests/ref/fate/g722-encode index d84d62701..f178c8ca3 100644 --- a/tests/ref/fate/g722-encode +++ b/tests/ref/fate/g722-encode @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 16000 -#channel_layout 0: 4 #channel_layout_name 0: mono #stream#, dts, pts, duration, size, hash 0, 0, 0, 8192, 16384, 1dd9c285eb608038f3257d1a8e02eb75 diff --git a/tests/ref/fate/g722dec-1 b/tests/ref/fate/g722dec-1 index a97fc81fb..9859984a5 100644 --- a/tests/ref/fate/g722dec-1 +++ b/tests/ref/fate/g722dec-1 @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 16000 -#channel_layout 0: 4 #channel_layout_name 0: mono 0, 0, 0, 2048, 4096, 0x4f9228b3 0, 2048, 2048, 2048, 4096, 0xfab58157 diff --git a/tests/ref/fate/g723_1-dec-1 b/tests/ref/fate/g723_1-dec-1 index f7daad1b4..e0adff275 100644 --- a/tests/ref/fate/g723_1-dec-1 +++ b/tests/ref/fate/g723_1-dec-1 @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 8000 -#channel_layout 0: 4 #channel_layout_name 0: mono 0, 0, 0, 240, 480, 0x7f6f3970 0, 240, 240, 240, 480, 0x1105a0d3 diff --git a/tests/ref/fate/g723_1-dec-2 b/tests/ref/fate/g723_1-dec-2 index a403e565d..04c1ca738 100644 --- a/tests/ref/fate/g723_1-dec-2 +++ b/tests/ref/fate/g723_1-dec-2 @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 8000 -#channel_layout 0: 4 #channel_layout_name 0: mono 0, 0, 0, 240, 480, 0x5d9d9091 0, 240, 240, 240, 480, 0x425095b7 diff --git a/tests/ref/fate/g723_1-dec-3 b/tests/ref/fate/g723_1-dec-3 index e3d397813..f4a95d13c 100644 --- a/tests/ref/fate/g723_1-dec-3 +++ b/tests/ref/fate/g723_1-dec-3 @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 8000 -#channel_layout 0: 4 #channel_layout_name 0: mono 0, 0, 0, 240, 480, 0xce908869 0, 240, 240, 240, 480, 0xfa63588e diff --git a/tests/ref/fate/g723_1-dec-4 b/tests/ref/fate/g723_1-dec-4 index 309b3afea..7b092dca1 100644 --- a/tests/ref/fate/g723_1-dec-4 +++ b/tests/ref/fate/g723_1-dec-4 @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 8000 -#channel_layout 0: 4 #channel_layout_name 0: mono 0, 0, 0, 240, 480, 0xa697b314 0, 240, 240, 240, 480, 0x43c5dc5a diff --git a/tests/ref/fate/g723_1-dec-5 b/tests/ref/fate/g723_1-dec-5 index 9e37c861a..9e0b6e4cd 100644 --- a/tests/ref/fate/g723_1-dec-5 +++ b/tests/ref/fate/g723_1-dec-5 @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 8000 -#channel_layout 0: 4 #channel_layout_name 0: mono 0, 0, 0, 240, 480, 0x4dce9773 0, 240, 240, 240, 480, 0xe6367ab8 diff --git a/tests/ref/fate/g723_1-dec-6 b/tests/ref/fate/g723_1-dec-6 index a51e8df9c..f0e67b14d 100644 --- a/tests/ref/fate/g723_1-dec-6 +++ b/tests/ref/fate/g723_1-dec-6 @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 8000 -#channel_layout 0: 4 #channel_layout_name 0: mono 0, 0, 0, 240, 480, 0x4fa1aed9 0, 240, 240, 240, 480, 0x6d7ef391 diff --git a/tests/ref/fate/g723_1-dec-7 b/tests/ref/fate/g723_1-dec-7 index db0ceb85e..34be011d8 100644 --- a/tests/ref/fate/g723_1-dec-7 +++ b/tests/ref/fate/g723_1-dec-7 @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 8000 -#channel_layout 0: 4 #channel_layout_name 0: mono 0, 0, 0, 240, 480, 0x35e4a1fd 0, 240, 240, 240, 480, 0x2f7bdd60 diff --git a/tests/ref/fate/g723_1-dec-8 b/tests/ref/fate/g723_1-dec-8 index 740ed2b4c..80ad39498 100644 --- a/tests/ref/fate/g723_1-dec-8 +++ b/tests/ref/fate/g723_1-dec-8 @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 8000 -#channel_layout 0: 4 #channel_layout_name 0: mono 0, 0, 0, 240, 480, 0x17930e0f 0, 240, 240, 240, 480, 0x7c7f4247 diff --git a/tests/ref/fate/g726-encode-2bit b/tests/ref/fate/g726-encode-2bit index 4a83c9576..2aafcc8bf 100644 --- a/tests/ref/fate/g726-encode-2bit +++ b/tests/ref/fate/g726-encode-2bit @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 8000 -#channel_layout 0: 4 #channel_layout_name 0: mono #stream#, dts, pts, duration, size, hash 0, 0, 0, 16384, 32768, b28b116d2315323aeba6b66b58b7f4ed diff --git a/tests/ref/fate/g726-encode-3bit b/tests/ref/fate/g726-encode-3bit index c551ae608..96c6b9447 100644 --- a/tests/ref/fate/g726-encode-3bit +++ b/tests/ref/fate/g726-encode-3bit @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 8000 -#channel_layout 0: 4 #channel_layout_name 0: mono #stream#, dts, pts, duration, size, hash 0, 0, 0, 10920, 21840, 517dd6d1ce566b998251f0d215fa69c0 diff --git a/tests/ref/fate/g726-encode-4bit b/tests/ref/fate/g726-encode-4bit index ea277e12c..28e9ee028 100644 --- a/tests/ref/fate/g726-encode-4bit +++ b/tests/ref/fate/g726-encode-4bit @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 8000 -#channel_layout 0: 4 #channel_layout_name 0: mono #stream#, dts, pts, duration, size, hash 0, 0, 0, 8192, 16384, a0cf3a0953adce1a1032a4fd2da00a52 diff --git a/tests/ref/fate/g726-encode-5bit b/tests/ref/fate/g726-encode-5bit index 30c456e86..c7cd7dd1d 100644 --- a/tests/ref/fate/g726-encode-5bit +++ b/tests/ref/fate/g726-encode-5bit @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 8000 -#channel_layout 0: 4 #channel_layout_name 0: mono #stream#, dts, pts, duration, size, hash 0, 0, 0, 6552, 13104, 6fe3f75df1262c5f956887de9c32df40 diff --git a/tests/ref/fate/gapless-mp3 b/tests/ref/fate/gapless-mp3 index 0b4937792..578db5553 100644 --- a/tests/ref/fate/gapless-mp3 +++ b/tests/ref/fate/gapless-mp3 @@ -1,5 +1,5 @@ -77ef234e382c15b8afc416ca9c80024b *tests/data/fate/gapless-mp3.out-1 +d7e884aea266b63f1547f1ad10188c08 *tests/data/fate/gapless-mp3.out-1 c96c3ae7bd3300fd2f4debac222de5b7 -c594be833fb94ae91f2734bcba56c359 *tests/data/fate/gapless-mp3.out-2 +75bc539914297a191f40af2d737d7380 *tests/data/fate/gapless-mp3.out-2 c96c3ae7bd3300fd2f4debac222de5b7 -5a285806cad6524a3d6184775e097d24 *tests/data/fate/gapless-mp3.out-3 +ab21e0bd0c2d84426153d4cde919a1e3 *tests/data/fate/gapless-mp3.out-3 diff --git a/tests/ref/fate/gsm-ms b/tests/ref/fate/gsm-ms index 0acf9f6e6..a7bebac0f 100644 --- a/tests/ref/fate/gsm-ms +++ b/tests/ref/fate/gsm-ms @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 8000 -#channel_layout 0: 4 #channel_layout_name 0: mono 0, 0, 0, 320, 640, 0xf79c59ee 0, 320, 320, 320, 640, 0x6e6248be diff --git a/tests/ref/fate/gsm-toast b/tests/ref/fate/gsm-toast index df5e82440..6b272433d 100644 --- a/tests/ref/fate/gsm-toast +++ b/tests/ref/fate/gsm-toast @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 8000 -#channel_layout 0: 4 #channel_layout_name 0: mono 0, 0, 0, 64, 128, 0x3ef33f6f 0, 64, 64, 160, 320, 0x2052a4e7 diff --git a/tests/ref/fate/h264-afd b/tests/ref/fate/h264-afd new file mode 100644 index 000000000..a45e899ee --- /dev/null +++ b/tests/ref/fate/h264-afd @@ -0,0 +1,282 @@ +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Active format description +active_format=14 +[/SIDE_DATA] +[/FRAME] diff --git a/tests/ref/fate/h264-skip-nointra b/tests/ref/fate/h264-skip-nointra index 025990292..82977ce67 100644 --- a/tests/ref/fate/h264-skip-nointra +++ b/tests/ref/fate/h264-skip-nointra @@ -7,7 +7,6 @@ #media_type 1: audio #codec_id 1: pcm_s16le #sample_rate 1: 48000 -#channel_layout 1: 3 #channel_layout_name 1: stereo 1, 0, 0, 1152, 4608, 0x00000000 1, 1152, 1152, 1152, 4608, 0x00000000 diff --git a/tests/ref/fate/h264-skip-nokey b/tests/ref/fate/h264-skip-nokey index 025990292..82977ce67 100644 --- a/tests/ref/fate/h264-skip-nokey +++ b/tests/ref/fate/h264-skip-nokey @@ -7,7 +7,6 @@ #media_type 1: audio #codec_id 1: pcm_s16le #sample_rate 1: 48000 -#channel_layout 1: 3 #channel_layout_name 1: stereo 1, 0, 0, 1152, 4608, 0x00000000 1, 1152, 1152, 1152, 4608, 0x00000000 diff --git a/tests/ref/fate/h264-xavc-4389 b/tests/ref/fate/h264-xavc-4389 index 5c76bc222..b8d957d96 100644 --- a/tests/ref/fate/h264-xavc-4389 +++ b/tests/ref/fate/h264-xavc-4389 @@ -7,7 +7,6 @@ #media_type 1: audio #codec_id 1: pcm_s16le #sample_rate 1: 48000 -#channel_layout 1: 4 #channel_layout_name 1: mono 0, 0, 0, 1, 8294400, 0x9a02ecf2 1, 0, 0, 1920, 3840, 0x38074ac8 diff --git a/tests/ref/fate/hevc-hdr-vivid-metadata b/tests/ref/fate/hevc-hdr-vivid-metadata new file mode 100644 index 000000000..5f6997309 --- /dev/null +++ b/tests/ref/fate/hevc-hdr-vivid-metadata @@ -0,0 +1,78 @@ +[FRAME] +[SIDE_DATA] +side_data_type=Mastering display metadata +red_x=34000/50000 +red_y=16000/50000 +green_x=13250/50000 +green_y=34500/50000 +blue_x=7500/50000 +blue_y=3000/50000 +white_point_x=15635/50000 +white_point_y=16450/50000 +min_luminance=50/10000 +max_luminance=40000000/10000 +[/SIDE_DATA] +[SIDE_DATA] +side_data_type=Content light level metadata +max_content=0 +max_average=0 +[/SIDE_DATA] +[SIDE_DATA] +side_data_type=H.26[45] User Data Unregistered SEI message +[/SIDE_DATA] +[SIDE_DATA] +side_data_type=HDR Dynamic Metadata CUVA 005.1 2021 (Vivid) +system_start_code=1 +num_windows=1 +minimum_maxrgb=0/4095 +average_maxrgb=3046/4095 +variance_maxrgb=1535/4095 +maximum_maxrgb=4095/4095 +tone_mapping_mode_flag=1 +tone_mapping_param_num=2 +targeted_system_display_maximum_luminance=2770/4095 +base_enable_flag=1 +base_param_m_p=5734/16383 +base_param_m_m=24/10 +base_param_m_a=563/1023 +base_param_m_b=0/1023 +base_param_m_n=10/10 +base_param_k1=1 +base_param_k2=1 +base_param_k3=1 +base_param_Delta_enable_mode=0 +base_param_Delta=0/127 +3Spline_enable_flag=1 +3Spline_num=1 +3Spline_TH_mode=0 +3Spline_TH_enable_MB=224/255 +3Spline_TH_enable=0/4095 +3Spline_TH_Delta1=511/1023 +3Spline_TH_Delta2=511/1023 +3Spline_enable_Strength=127/255 +targeted_system_display_maximum_luminance=2080/4095 +base_enable_flag=1 +base_param_m_p=5734/16383 +base_param_m_m=24/10 +base_param_m_a=563/1023 +base_param_m_b=0/1023 +base_param_m_n=10/10 +base_param_k1=1 +base_param_k2=1 +base_param_k3=1 +base_param_Delta_enable_mode=0 +base_param_Delta=0/127 +3Spline_enable_flag=1 +3Spline_num=1 +3Spline_TH_mode=0 +3Spline_TH_enable_MB=224/255 +3Spline_TH_enable=0/4095 +3Spline_TH_Delta1=511/1023 +3Spline_TH_Delta2=511/1023 +3Spline_enable_Strength=127/255 +color_saturation_mapping_flag=1 +color_saturation_num=2 +color_saturation_gain=38/128 +color_saturation_gain=25/128 +[/SIDE_DATA] +[/FRAME] diff --git a/tests/ref/fate/hls-fmp4 b/tests/ref/fate/hls-fmp4 index 98b037fc8..df11c5554 100644 --- a/tests/ref/fate/hls-fmp4 +++ b/tests/ref/fate/hls-fmp4 @@ -2,7 +2,6 @@ #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, 1152, 2304, 0x907cb7fa 0, 1152, 1152, 1152, 2304, 0xb8dc7525 diff --git a/tests/ref/fate/hls-init-time b/tests/ref/fate/hls-init-time index 5bc12272c..f1c62d551 100644 --- a/tests/ref/fate/hls-init-time +++ b/tests/ref/fate/hls-init-time @@ -2,7 +2,6 @@ #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, 1152, 2304, 0x28123557 0, 1152, 1152, 1152, 2304, 0x838c7e81 diff --git a/tests/ref/fate/hls-list-size b/tests/ref/fate/hls-list-size index cf7fb9fe3..2dd6ef842 100644 --- a/tests/ref/fate/hls-list-size +++ b/tests/ref/fate/hls-list-size @@ -2,7 +2,6 @@ #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, 1152, 2304, 0x9ce3278a 0, 1152, 1152, 1152, 2304, 0x5cd17b17 diff --git a/tests/ref/fate/hls-segment-single b/tests/ref/fate/hls-segment-single index ee3c7b2c6..ed0ecc8e7 100644 --- a/tests/ref/fate/hls-segment-single +++ b/tests/ref/fate/hls-segment-single @@ -2,7 +2,6 @@ #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, 1152, 2304, 0x907cb7fa 0, 1152, 1152, 1152, 2304, 0xb8dc7525 diff --git a/tests/ref/fate/hls-segment-size b/tests/ref/fate/hls-segment-size index ee3c7b2c6..ed0ecc8e7 100644 --- a/tests/ref/fate/hls-segment-size +++ b/tests/ref/fate/hls-segment-size @@ -2,7 +2,6 @@ #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, 1152, 2304, 0x907cb7fa 0, 1152, 1152, 1152, 2304, 0xb8dc7525 diff --git a/tests/ref/fate/id-cin-video b/tests/ref/fate/id-cin-video index 671b396a1..e3da4aa07 100644 --- a/tests/ref/fate/id-cin-video +++ b/tests/ref/fate/id-cin-video @@ -7,7 +7,6 @@ #media_type 1: audio #codec_id 1: pcm_s16le #sample_rate 1: 22050 -#channel_layout 1: 3 #channel_layout_name 1: stereo 0, 0, 0, 1, 230400, 0x00000000 1, 0, 0, 1575, 6300, 0xdd759df8 diff --git a/tests/ref/fate/id3v2-chapters b/tests/ref/fate/id3v2-chapters index 5aa8f82af..c845e8882 100644 --- a/tests/ref/fate/id3v2-chapters +++ b/tests/ref/fate/id3v2-chapters @@ -4,7 +4,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 48000 -#channel_layout 0: 3 #channel_layout_name 0: stereo 0, 0, 0, 1024, 4096, 0xc5b6547b 0, 1024, 1024, 1024, 4096, 0x0f27633e diff --git a/tests/ref/fate/id3v2-priv-remux b/tests/ref/fate/id3v2-priv-remux index a30f68a25..a0f370142 100644 --- a/tests/ref/fate/id3v2-priv-remux +++ b/tests/ref/fate/id3v2-priv-remux @@ -4,7 +4,6 @@ bb2816e3a05ce136e9ac14479c1ebe24 *tests/data/fate/id3v2-priv-remux.mp3 #media_type 0: audio #codec_id 0: mp3 #sample_rate 0: 48000 -#channel_layout 0: 4 #channel_layout_name 0: mono 0, -155528, -155528, 338688, 192, 0x3774510e, S=1, 10 0, 183160, 183160, 338688, 192, 0x856c5b02 diff --git a/tests/ref/fate/imf-cpl-with-repeat b/tests/ref/fate/imf-cpl-with-repeat new file mode 100644 index 000000000..e5b3992d0 --- /dev/null +++ b/tests/ref/fate/imf-cpl-with-repeat @@ -0,0 +1,46 @@ +#tb 0: 1/24 +#media_type 0: video +#codec_id 0: jpeg2000 +#dimensions 0: 640x360 +#sar 0: 0/1 +0, 0, 0, 1, 1698, 0xd8730ea4 +0, 1, 1, 1, 1966, 0x6562867e +0, 2, 2, 1, 2063, 0x18f4bb7d +0, 3, 3, 1, 1618, 0x0770dca6 +0, 4, 4, 1, 2100, 0xd0a1c42b +0, 5, 5, 1, 2068, 0xd411c582 +0, 6, 6, 1, 2520, 0x7b539dfc +0, 7, 7, 1, 1964, 0x106d867a +0, 8, 8, 1, 1964, 0x106d867a +0, 9, 9, 1, 1964, 0x106d867a +0, 10, 10, 1, 1964, 0x106d867a +0, 11, 11, 1, 1964, 0x106d867a +0, 12, 12, 1, 1964, 0x106d867a +0, 13, 13, 1, 1964, 0x106d867a +0, 14, 14, 1, 1964, 0x106d867a +0, 15, 15, 1, 1964, 0x106d867a +0, 16, 16, 1, 1964, 0x106d867a +0, 17, 17, 1, 1964, 0x106d867a +0, 18, 18, 1, 1964, 0x106d867a +0, 19, 19, 1, 1964, 0x106d867a +0, 20, 20, 1, 1964, 0x106d867a +0, 21, 21, 1, 1964, 0x106d867a +0, 22, 22, 1, 1964, 0x106d867a +0, 23, 23, 1, 1964, 0x106d867a +0, 24, 24, 1, 1964, 0x106d867a +0, 25, 25, 1, 1964, 0x106d867a +0, 26, 26, 1, 1964, 0x106d867a +0, 27, 27, 1, 1964, 0x106d867a +0, 28, 28, 1, 1964, 0x106d867a +0, 29, 29, 1, 1964, 0x106d867a +0, 30, 30, 1, 1964, 0x106d867a +0, 31, 31, 1, 2068, 0xd411c582 +0, 32, 32, 1, 2520, 0x7b539dfc +0, 33, 33, 1, 1846, 0x9d184658 +0, 34, 34, 1, 2475, 0x2967a123 +0, 35, 35, 1, 2540, 0xdc61ad87 +0, 36, 36, 1, 2214, 0xa7da105f +0, 37, 37, 1, 2486, 0xa68d89b4 +0, 38, 38, 1, 2615, 0xbc35d5ad +0, 39, 39, 1, 2150, 0x643aea98 +0, 40, 40, 1, 2628, 0x2880c4ad diff --git a/tests/ref/fate/jpg-icc b/tests/ref/fate/jpg-icc new file mode 100644 index 000000000..220146555 --- /dev/null +++ b/tests/ref/fate/jpg-icc @@ -0,0 +1,42 @@ +0a323df5cdfb9574e329b9831be054a6 *tests/data/fate/jpg-icc.mjpeg +11010 tests/data/fate/jpg-icc.mjpeg +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 128x128 +#sar 0: 1/1 +0, 0, 0, 1, 49152, 0xaac06b42 +[FRAME] +media_type=video +stream_index=0 +key_frame=1 +pts=0 +pts_time=0.000000 +pkt_dts=0 +pkt_dts_time=0.000000 +best_effort_timestamp=0 +best_effort_timestamp_time=0.000000 +pkt_duration=1 +pkt_duration_time=0.040000 +pkt_pos=0 +pkt_size=11010 +width=128 +height=128 +pix_fmt=yuvj444p +sample_aspect_ratio=1:1 +pict_type=I +coded_picture_number=0 +display_picture_number=0 +interlaced_frame=0 +top_field_first=0 +repeat_pict=0 +color_range=pc +color_space=bt470bg +color_primaries=unknown +color_transfer=unknown +chroma_location=center +[SIDE_DATA] +side_data_type=ICC profile +size=3144 +[/SIDE_DATA] +[/FRAME] diff --git a/tests/ref/fate/jv-demux b/tests/ref/fate/jv-demux index bf8211074..b5d3196cf 100644 --- a/tests/ref/fate/jv-demux +++ b/tests/ref/fate/jv-demux @@ -7,7 +7,6 @@ #media_type 1: audio #codec_id 1: pcm_u8 #sample_rate 1: 22050 -#channel_layout 1: 4 #channel_layout_name 1: mono 0, 0, 0, 1, 6, 0x000a0003 1, 0, 0, 131072, 131072, 0x14c664d6 diff --git a/tests/ref/fate/lmlm4-demux b/tests/ref/fate/lmlm4-demux index b0276d53e..9bddf5840 100644 --- a/tests/ref/fate/lmlm4-demux +++ b/tests/ref/fate/lmlm4-demux @@ -8,7 +8,6 @@ #media_type 1: audio #codec_id 1: mp2 #sample_rate 1: 48000 -#channel_layout 1: 3 #channel_layout_name 1: stereo 0, 0, -9223372036854775808, 1, 5951, 0xe9118e0d 1, 0, 0, 2160, 768, 0xaebcbebb diff --git a/tests/ref/fate/matroska-avoid-negative-ts b/tests/ref/fate/matroska-avoid-negative-ts new file mode 100644 index 000000000..129ea1be6 --- /dev/null +++ b/tests/ref/fate/matroska-avoid-negative-ts @@ -0,0 +1,41 @@ +fbe66be73d379073e0705891f290a6b2 *tests/data/fate/matroska-avoid-negative-ts.matroska +973055 tests/data/fate/matroska-avoid-negative-ts.matroska +#extradata 0: 22, 0x2885037c +#tb 0: 1/1000 +#media_type 0: video +#codec_id 0: mpeg2video +#dimensions 0: 352x288 +#sar 0: 12/11 +#tb 1: 1/1000 +#media_type 1: audio +#codec_id 1: mp3 +#sample_rate 1: 44100 +#channel_layout_name 1: mono +0, -37, 43, 40, 9156, 0xe5bd034a, S=1, 40 +1, 0, 0, 26, 417, 0x7198c15e +0, 3, 3, 40, 1740, 0x29ac4480, F=0x0 +1, 26, 26, 26, 417, 0x3c67c32d +0, 43, 123, 40, 3672, 0x98652013, F=0x0 +1, 52, 52, 26, 417, 0x8c24b1ca +1, 78, 78, 26, 417, 0x6ee576b7 +0, 83, 83, 40, 2532, 0xa2c42769, F=0x0 +1, 104, 104, 26, 417, 0x407603db +0, 123, 203, 40, 1728, 0xae823d3b, F=0x0 +1, 130, 130, 26, 417, 0xcf2804d2 +1, 156, 156, 26, 417, 0xcf2804d2 +0, 163, 163, 40, 1028, 0x286ac52a, F=0x0 +1, 182, 182, 26, 417, 0xcf2804d2 +0, 203, 283, 40, 1916, 0xd378899e, F=0x0 +1, 208, 208, 26, 417, 0xcf2804d2 +1, 235, 235, 26, 417, 0xcf2804d2 +0, 243, 243, 40, 1168, 0x424e12cf, F=0x0 +1, 261, 261, 26, 417, 0xcf2804d2 +0, 283, 363, 40, 1660, 0x5cec156c, F=0x0 +1, 287, 287, 26, 417, 0xcf2804d2 +1, 313, 313, 26, 417, 0xef163d04 +0, 323, 323, 40, 1004, 0xac0dce29, F=0x0 +1, 339, 339, 26, 417, 0x2a009b3a +0, 363, 443, 40, 3008, 0x0fc798bf, F=0x0 +1, 365, 365, 26, 417, 0xbedccb9d +1, 365, 365, 26, 417, 0x2214be3f +1, 391, 391, 26, 417, 0x8953b878 diff --git a/tests/ref/fate/matroska-dovi-write-config7 b/tests/ref/fate/matroska-dovi-write-config7 new file mode 100644 index 000000000..9207b14b5 --- /dev/null +++ b/tests/ref/fate/matroska-dovi-write-config7 @@ -0,0 +1,49 @@ +d23b8b0d0613a82ba36fdc27acf3ef5d *tests/data/fate/matroska-dovi-write-config7.matroska +72672 tests/data/fate/matroska-dovi-write-config7.matroska +#extradata 0: 116, 0x2b8d1669 +#extradata 1: 116, 0x2b8d1669 +#tb 0: 1/1000 +#media_type 0: video +#codec_id 0: hevc +#dimensions 0: 1920x1080 +#sar 0: 0/1 +#tb 1: 1/1000 +#media_type 1: video +#codec_id 1: hevc +#dimensions 1: 1920x1080 +#sar 1: 0/1 +0, -83, 0, 41, 699, 0x728548f1 +1, -83, 0, 41, 1085, 0xfb2dba82, S=1, 8 +0, -42, 167, 41, 95, 0xc0312044, F=0x0 +1, -42, 167, 41, 481, 0xf23f91d5, F=0x0 +0, 0, 83, 41, 99, 0x5e0a2221, F=0x0 +1, 0, 83, 41, 485, 0x5f7b93b2, F=0x0 +0, 42, 42, 41, 99, 0xe60e208b, F=0x0 +1, 42, 42, 41, 485, 0x8335921c, F=0x0 +0, 83, 125, 41, 99, 0xa1e422e1, F=0x0 +1, 83, 125, 41, 485, 0xc4e49472, F=0x0 +0, 125, 333, 41, 96, 0xdc762089, F=0x0 +1, 125, 333, 41, 482, 0x769c921a, F=0x0 +0, 167, 250, 41, 100, 0x89cd22a0, F=0x0 +1, 167, 250, 41, 486, 0x4aca9431, F=0x0 +0, 208, 208, 41, 100, 0x6d4521ff, F=0x0 +1, 208, 208, 41, 486, 0x3b719390, F=0x0 +0, 250, 292, 41, 99, 0x92ab22c0, F=0x0 +1, 250, 292, 41, 485, 0x83e99451, F=0x0 +0, 292, 292, 41, 95, 0xcd9020bd, F=0x0 +1, 292, 292, 41, 481, 0x44ec924e, F=0x0 +[STREAM] +[/STREAM] +[STREAM] +[SIDE_DATA] +side_data_type=DOVI configuration record +dv_version_major=1 +dv_version_minor=0 +dv_profile=7 +dv_level=4 +rpu_present_flag=1 +el_present_flag=1 +bl_present_flag=0 +dv_bl_signal_compatibility_id=6 +[/SIDE_DATA] +[/STREAM] diff --git a/tests/ref/fate/matroska-dovi-write-config8 b/tests/ref/fate/matroska-dovi-write-config8 new file mode 100644 index 000000000..5feb7b806 --- /dev/null +++ b/tests/ref/fate/matroska-dovi-write-config8 @@ -0,0 +1,59 @@ +0047ca43aa8ab2948752e367f184dc1f *tests/data/fate/matroska-dovi-write-config8.matroska +3600576 tests/data/fate/matroska-dovi-write-config8.matroska +#extradata 0: 551, 0xa18acf66 +#extradata 1: 2, 0x00340022 +#tb 0: 1/1000 +#media_type 0: video +#codec_id 0: hevc +#dimensions 0: 1920x1080 +#sar 0: 0/1 +#tb 1: 1/1000 +#media_type 1: audio +#codec_id 1: aac +#sample_rate 1: 44100 +#channel_layout_name 1: stereo +0, -67, 0, 33, 63375, 0xc76606ab, S=1, 8 +0, -34, 133, 33, 46706, 0x0e08a7e5, F=0x0 +0, 0, 67, 33, 29766, 0x753c031a, F=0x0 +1, 0, 0, 23, 6, 0x031e0108 +1, 23, 23, 23, 251, 0x6b4a7cbd +0, 33, 33, 33, 19409, 0x4b948b6c, F=0x0 +1, 46, 46, 23, 389, 0x6673c205 +0, 67, 100, 33, 21086, 0x1b9412ce, F=0x0 +1, 70, 70, 23, 356, 0x8c71a316 +1, 93, 93, 23, 339, 0x3018a45a +0, 100, 267, 33, 62043, 0xc2356b56, F=0x0 +1, 116, 116, 23, 405, 0xc89ebe05 +0, 133, 200, 33, 36175, 0x0a7df38c, F=0x0 +1, 139, 139, 23, 449, 0x42eadf96 +1, 163, 163, 23, 416, 0x28a7c9b9 +0, 167, 167, 33, 16028, 0xa57fcbe9, F=0x0 +1, 186, 186, 23, 426, 0x9a74d4ec +0, 200, 233, 33, 15428, 0x9a91f357, F=0x0 +1, 209, 209, 23, 419, 0xbe3dc54b +1, 232, 232, 23, 424, 0x5102d50e +0, 233, 400, 33, 66072, 0xa542b6d7, F=0x0 +1, 255, 255, 23, 402, 0xb11cc14c +0, 267, 333, 33, 34985, 0xbfd8ff45, F=0x0 +1, 279, 279, 23, 401, 0x3820b8f9 +0, 300, 300, 33, 16036, 0xfc39c6ea, F=0x0 +1, 302, 302, 23, 400, 0xe5c4c168 +1, 325, 325, 23, 435, 0x6dbecc33 +0, 333, 367, 33, 19893, 0x7e746f4e, F=0x0 +1, 348, 348, 23, 441, 0x0ad3d199 +0, 367, 533, 33, 77576, 0xeba2e5c8, F=0x0 +1, 372, 372, 23, 479, 0x44dce967 +1, 395, 395, 23, 439, 0x7d85e4c9 +[STREAM] +[SIDE_DATA] +side_data_type=DOVI configuration record +dv_version_major=1 +dv_version_minor=0 +dv_profile=8 +dv_level=4 +rpu_present_flag=1 +el_present_flag=0 +bl_present_flag=1 +dv_bl_signal_compatibility_id=4 +[/SIDE_DATA] +[/STREAM] diff --git a/tests/ref/fate/matroska-dvbsub-remux b/tests/ref/fate/matroska-dvbsub-remux new file mode 100644 index 000000000..b7346b8f5 --- /dev/null +++ b/tests/ref/fate/matroska-dvbsub-remux @@ -0,0 +1,52 @@ +77d210dc36d7a01988d159b3c902524c *tests/data/fate/matroska-dvbsub-remux.matroska +39010 tests/data/fate/matroska-dvbsub-remux.matroska +#extradata 0: 5, 0x00bb0064 +#extradata 1: 5, 0x00bb0064 +#tb 0: 1/1000 +#media_type 0: subtitle +#codec_id 0: dvb_subtitle +#tb 1: 1/1000 +#media_type 1: subtitle +#codec_id 1: dvb_subtitle +0, 0, 0, 280, 14, 0x05f400e1 +1, 0, 0, 0, 14, 0x05f400e1 +0, 280, 280, 5000, 14, 0x066400f1 +1, 280, 280, 0, 14, 0x066400f1 +0, 5280, 5280, 5020, 14, 0x06d40101 +1, 5280, 5280, 0, 14, 0x06d40101 +0, 10300, 10300, 3600, 14, 0x07440111 +1, 10300, 10300, 0, 14, 0x07440111 +0, 13900, 13900, 220, 14, 0x07b40121 +1, 13900, 13900, 0, 14, 0x07b40121 +0, 14120, 14120, 1440, 14, 0x08240131 +1, 14120, 14120, 0, 14, 0x08240131 +0, 15560, 15560, 40, 14, 0x08940141 +1, 15560, 15560, 0, 14, 0x08940141 +0, 15600, 15600, 160, 944, 0x454c0939 +1, 15600, 15600, 0, 944, 0x454c0939 +0, 15760, 15760, 240, 630, 0x49dbb35f +1, 15760, 15760, 0, 630, 0x49dbb35f +0, 16000, 16000, 340, 344, 0xb1eb63ed +1, 16000, 16000, 0, 344, 0xb1eb63ed +0, 16340, 16340, 600, 966, 0xb8a61edf +1, 16340, 16340, 0, 966, 0xb8a61edf +0, 16940, 16940, 460, 470, 0x80597fba +1, 16940, 16940, 0, 470, 0x80597fba +0, 17400, 17400, 360, 1212, 0x554768d6 +1, 17400, 17400, 0, 1212, 0x554768d6 +0, 17760, 17760, 220, 4804, 0xab67ddbe +1, 17760, 17760, 0, 4804, 0xab67ddbe +0, 17980, 17980, 960, 1016, 0x15e42d56 +1, 17980, 17980, 0, 1016, 0x15e42d56 +0, 18940, 18940, 220, 456, 0x57917e6f +1, 18940, 18940, 0, 456, 0x57917e6f +0, 19160, 19160, 260, 830, 0xcff3efde +1, 19160, 19160, 0, 830, 0xcff3efde +0, 19420, 19420, 100, 860, 0xd89903b6 +1, 19420, 19420, 0, 860, 0xd89903b6 +0, 19520, 19520, 220, 4426, 0x01eb43f1 +1, 19520, 19520, 0, 4426, 0x01eb43f1 +0, 19740, 19740, 220, 1132, 0xedda51a8 +1, 19740, 19740, 0, 1132, 0xedda51a8 +0, 19960, 19960, 0, 466, 0x9c957e09 +1, 19960, 19960, 0, 466, 0x9c957e09 diff --git a/tests/ref/fate/matroska-flac-channel-mapping b/tests/ref/fate/matroska-flac-channel-mapping index 6d901600e..25627d657 100644 --- a/tests/ref/fate/matroska-flac-channel-mapping +++ b/tests/ref/fate/matroska-flac-channel-mapping @@ -4,13 +4,11 @@ #media_type 0: audio #codec_id 0: flac #sample_rate 0: 48000 -#channel_layout 0: 3f #channel_layout_name 0: 5.1 #tb 1: 651/31250000 #media_type 1: audio #codec_id 1: flac #sample_rate 1: 48000 -#channel_layout 1: 60f #channel_layout_name 1: 5.1(side) 0, 0, 0, 4096, 26, 0x50f80431 1, 0, 0, 4096, 26, 0x50f80431 diff --git a/tests/ref/fate/matroska-flac-extradata-update b/tests/ref/fate/matroska-flac-extradata-update index 1a8add773..e8812f51b 100644 --- a/tests/ref/fate/matroska-flac-extradata-update +++ b/tests/ref/fate/matroska-flac-extradata-update @@ -1,5 +1,5 @@ -c2b76d47a9f0e9626a4999bd395cae08 *tests/data/fate/matroska-flac-extradata-update.matroska -2029 tests/data/fate/matroska-flac-extradata-update.matroska +732446e97bae29037ff0cd9963d4ac08 *tests/data/fate/matroska-flac-extradata-update.matroska +1987 tests/data/fate/matroska-flac-extradata-update.matroska #extradata 0: 34, 0x7acb09e7 #extradata 1: 34, 0x7acb09e7 #extradata 2: 34, 0x443402dd @@ -7,19 +7,16 @@ c2b76d47a9f0e9626a4999bd395cae08 *tests/data/fate/matroska-flac-extradata-update #media_type 0: audio #codec_id 0: flac #sample_rate 0: 48000 -#channel_layout 0: 3f #channel_layout_name 0: 5.1 #tb 1: 1/1000 #media_type 1: audio #codec_id 1: flac #sample_rate 1: 48000 -#channel_layout 1: 60f #channel_layout_name 1: 5.1(side) #tb 2: 1/1000 #media_type 2: audio #codec_id 2: flac #sample_rate 2: 48000 -#channel_layout 2: 3f #channel_layout_name 2: 5.1 0, 0, 0, 96, 26, 0x4e160341 1, 0, 0, 96, 26, 0x4e160341 diff --git a/tests/ref/fate/matroska-h264-remux b/tests/ref/fate/matroska-h264-remux index b5ecebaf2..6edd88fba 100644 --- a/tests/ref/fate/matroska-h264-remux +++ b/tests/ref/fate/matroska-h264-remux @@ -1,5 +1,5 @@ -36fda8942bfed91fed04c5ba63dc8b1a *tests/data/fate/matroska-h264-remux.matroska -2036089 tests/data/fate/matroska-h264-remux.matroska +3c00191234d5c4d77151d38a86403101 *tests/data/fate/matroska-h264-remux.matroska +2036033 tests/data/fate/matroska-h264-remux.matroska #tb 0: 1/25 #media_type 0: video #codec_id 0: rawvideo diff --git a/tests/ref/fate/matroska-lzo-decompression b/tests/ref/fate/matroska-lzo-decompression index 241d5adf4..568e32ecc 100644 --- a/tests/ref/fate/matroska-lzo-decompression +++ b/tests/ref/fate/matroska-lzo-decompression @@ -2,7 +2,6 @@ #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, 4096, 16384, 0x00000000 0, 4096, 4096, 4096, 16384, 0xad7eebf4 diff --git a/tests/ref/fate/matroska-mastering-display-metadata b/tests/ref/fate/matroska-mastering-display-metadata index 8f5d7b6a2..5b23e9506 100644 --- a/tests/ref/fate/matroska-mastering-display-metadata +++ b/tests/ref/fate/matroska-mastering-display-metadata @@ -1,5 +1,5 @@ -542ababe5c088ab925ee49373d8b8a85 *tests/data/fate/matroska-mastering-display-metadata.matroska -1669695 tests/data/fate/matroska-mastering-display-metadata.matroska +69a904789151abaee46033391a4fce46 *tests/data/fate/matroska-mastering-display-metadata.matroska +1669555 tests/data/fate/matroska-mastering-display-metadata.matroska #extradata 0: 4, 0x040901a3 #extradata 3: 200, 0x506463a8 #tb 0: 1/1000 @@ -11,13 +11,11 @@ #media_type 1: audio #codec_id 1: pcm_s24le #sample_rate 1: 48000 -#channel_layout 1: 4 #channel_layout_name 1: mono #tb 2: 1/1000 #media_type 2: audio #codec_id 2: pcm_s16be #sample_rate 2: 48000 -#channel_layout 2: 4 #channel_layout_name 2: mono #tb 3: 1/1000 #media_type 3: video diff --git a/tests/ref/fate/matroska-move-cues-to-front b/tests/ref/fate/matroska-move-cues-to-front new file mode 100644 index 000000000..78697b2ea --- /dev/null +++ b/tests/ref/fate/matroska-move-cues-to-front @@ -0,0 +1,70 @@ +8ebfcf15768bbe66611e349383fbf26a *tests/data/fate/matroska-move-cues-to-front.matroska +23210287 tests/data/fate/matroska-move-cues-to-front.matroska +#tb 0: 1/1000 +#media_type 0: audio +#codec_id 0: pcm_s24be +#sample_rate 0: 192000 +#channel_layout_name 0: stereo +#tb 1: 1/1000 +#media_type 1: audio +#codec_id 1: pcm_s24le +#sample_rate 1: 192000 +#channel_layout_name 1: stereo +0, 0, 0, 3, 4092, 0x71f10ea0 +1, 0, 0, 3, 4092, 0xa6320ea0 +0, 4, 4, 3, 4092, 0x51852317 +1, 4, 4, 3, 4092, 0x27732317 +0, 7, 7, 3, 4092, 0xc8e2693d +1, 7, 7, 3, 4092, 0x5899693d +0, 11, 11, 3, 4092, 0x8df13008 +1, 11, 11, 3, 4092, 0x6fa63008 +0, 14, 14, 3, 4092, 0xc56bdf7f +1, 14, 14, 3, 4092, 0x22b0df7f +0, 18, 18, 3, 4092, 0x4ac2c0f9 +1, 18, 18, 3, 4092, 0x5512c0f9 +0, 21, 21, 3, 4092, 0x11a50650 +1, 21, 21, 3, 4092, 0x11b90650 +0, 25, 25, 3, 4092, 0x0a3837f4 +1, 25, 25, 3, 4092, 0x9cb537f4 +0, 28, 28, 3, 4092, 0xff0a3ce7 +1, 28, 28, 3, 4092, 0x7d1a3ce7 +0, 32, 32, 3, 4092, 0x42d2c983 +1, 32, 32, 3, 4092, 0x0f56c983 +0, 36, 36, 3, 4092, 0x2adbf4ea +1, 36, 36, 3, 4092, 0x386bf4ea +0, 39, 39, 3, 4092, 0x86d4f0a5 +1, 39, 39, 3, 4092, 0x5924f0a5 +0, 43, 43, 3, 4092, 0x5f35d5f7 +1, 43, 43, 3, 4092, 0x565fd5f7 +0, 46, 46, 3, 4092, 0xd3f27234 +1, 46, 46, 3, 4092, 0x4d197234 +0, 50, 50, 3, 4092, 0xb3a97ff5 +1, 50, 50, 3, 4092, 0x61e67ff5 +0, 53, 53, 3, 4092, 0xce30e2ba +1, 53, 53, 3, 4092, 0xe65de2ba +0, 57, 57, 3, 4092, 0x3d482d44 +1, 57, 57, 3, 4092, 0xf85b2d44 +0, 60, 60, 3, 4092, 0x691d161c +1, 60, 60, 3, 4092, 0x3b01161c +0, 64, 64, 3, 4092, 0xe6b93525 +1, 64, 64, 3, 4092, 0xdd4e3525 +0, 67, 67, 3, 4092, 0x9ce3f785 +1, 67, 67, 3, 4092, 0x8a28f785 +0, 71, 71, 3, 4092, 0x688fc452 +1, 71, 71, 3, 4092, 0x8c5ec452 +0, 75, 75, 3, 4092, 0x400cf87e +1, 75, 75, 3, 4092, 0x1e64f87e +0, 78, 78, 3, 4092, 0x49baa923 +1, 78, 78, 3, 4092, 0x68d9a923 +0, 82, 82, 3, 4092, 0x4df27658 +1, 82, 82, 3, 4092, 0x38d77658 +0, 85, 85, 3, 4092, 0xdfebf0e7 +1, 85, 85, 3, 4092, 0xab2cf0e7 +0, 89, 89, 3, 4092, 0x69d2f76c +1, 89, 89, 3, 4092, 0x35b9f76c +0, 92, 92, 3, 4092, 0x877b89d3 +1, 92, 92, 3, 4092, 0xcc4889d3 +0, 96, 96, 3, 4092, 0x70035443 +1, 96, 96, 3, 4092, 0x04825443 +0, 99, 99, 3, 4092, 0x30135036 +1, 99, 99, 3, 4092, 0x4fba5036 diff --git a/tests/ref/fate/matroska-mpegts-remux b/tests/ref/fate/matroska-mpegts-remux index 9478294b8..2faab0892 100644 --- a/tests/ref/fate/matroska-mpegts-remux +++ b/tests/ref/fate/matroska-mpegts-remux @@ -1,16 +1,14 @@ -4e6253c1f5f96ff64ae855dea426547d *tests/data/fate/matroska-mpegts-remux.matroska -6509 tests/data/fate/matroska-mpegts-remux.matroska +acaf3ebe07afe9815e0a984921d3ab87 *tests/data/fate/matroska-mpegts-remux.matroska +6494 tests/data/fate/matroska-mpegts-remux.matroska #tb 0: 1/1000 #media_type 0: audio #codec_id 0: ac3 #sample_rate 0: 48000 -#channel_layout 0: 3 #channel_layout_name 0: stereo #tb 1: 1/1000 #media_type 1: audio #codec_id 1: ac3 #sample_rate 1: 48000 -#channel_layout 1: 3 #channel_layout_name 1: stereo 0, 0, 0, 32, 768, 0xa63778d4 1, 0, 0, 32, 768, 0xa63778d4 diff --git a/tests/ref/fate/matroska-ms-mode b/tests/ref/fate/matroska-ms-mode new file mode 100644 index 000000000..f90a7e431 --- /dev/null +++ b/tests/ref/fate/matroska-ms-mode @@ -0,0 +1,88 @@ +afb4fc9b2ca6cafc03d8029fdf4da876 *tests/data/fate/matroska-ms-mode.matroska +413086 tests/data/fate/matroska-ms-mode.matroska +#extradata 0: 40, 0x54290c93 +#extradata 1: 114, 0xb6c80771 +#tb 0: 1/1000 +#media_type 0: video +#codec_id 0: vp5 +#dimensions 0: 512x304 +#sar 0: 0/1 +#tb 1: 1/1000 +#media_type 1: audio +#codec_id 1: speex +#sample_rate 1: 32000 +#channel_layout_name 1: mono +0, 0, 0, 41, 12972, 0x6588cf8e +1, 0, 0, 0, 74, 0xd4eb274d +1, 20, 20, 0, 74, 0xef822181 +1, 40, 40, 0, 74, 0x61e3239c +0, 42, 42, 41, 478, 0xeca1eeb9 +1, 60, 60, 0, 74, 0x474623d5 +1, 80, 80, 0, 74, 0x79a21f22 +0, 83, 83, 41, 260, 0x335f8133 +1, 100, 100, 0, 74, 0xb3022058 +1, 120, 120, 0, 74, 0x57a32240 +0, 125, 125, 41, 199, 0xf6f86142 +1, 140, 140, 0, 74, 0x34892453 +1, 160, 160, 0, 74, 0x55621efb +0, 167, 167, 41, 188, 0x0eeb5f55 +1, 180, 180, 0, 74, 0xb92f206a +1, 200, 200, 0, 74, 0x1988222e +0, 209, 209, 41, 183, 0x921a5b3c +1, 220, 220, 0, 74, 0x033b20dc +1, 240, 240, 0, 74, 0xf8f41da4 +0, 250, 250, 41, 181, 0xae765703 +1, 260, 260, 0, 74, 0xfc89201f +1, 280, 280, 0, 74, 0x2b102428 +0, 292, 292, 41, 181, 0xdc975d93 +1, 300, 300, 0, 74, 0x2df42380 +1, 320, 320, 0, 74, 0xebcf20fd +0, 334, 334, 41, 181, 0x30355b73 +1, 340, 340, 0, 74, 0x3eb524f8 +1, 360, 360, 0, 74, 0x1f802308 +0, 375, 375, 41, 179, 0xef275e89 +1, 380, 380, 0, 74, 0x218d23bd +1, 400, 400, 0, 74, 0x77f82421 +0, 417, 417, 41, 181, 0xbdb35a1b +1, 420, 420, 0, 74, 0xf20023a3 +1, 440, 440, 0, 74, 0x82cc1f9a +0, 459, 459, 41, 179, 0x1b245f55 +1, 460, 460, 0, 74, 0x8d3222e4 +1, 480, 480, 0, 74, 0x939d1e4c +1, 500, 500, 0, 74, 0x55c3232c +0, 501, 501, 41, 181, 0x30355b73 +1, 520, 520, 0, 74, 0x85e02092 +1, 540, 540, 0, 74, 0xb9d02059 +0, 542, 542, 41, 179, 0xef275e89 +1, 560, 560, 0, 74, 0xbbd8211f +1, 580, 580, 0, 74, 0xe0ca20e1 +0, 584, 584, 41, 181, 0xbdb35a1b +1, 600, 600, 0, 74, 0xd4f9216b +1, 620, 620, 0, 74, 0xdea723f9 +0, 626, 626, 41, 179, 0x1b245f55 +1, 640, 640, 0, 74, 0xc2611fe9 +1, 660, 660, 0, 74, 0x9f941f2d +0, 667, 667, 41, 181, 0x30355b73 +1, 680, 680, 0, 74, 0xaf991eb9 +1, 700, 700, 0, 74, 0x7e79250e +0, 709, 709, 41, 179, 0xef275e89 +1, 720, 720, 0, 74, 0x5a421faa +1, 740, 740, 0, 74, 0x3b211ce0 +0, 751, 751, 41, 181, 0xbdb35a1b +1, 760, 760, 0, 74, 0x4a812478 +1, 780, 780, 0, 74, 0xfc1b234f +0, 792, 792, 41, 179, 0x1b245f55 +1, 800, 800, 0, 74, 0x3d561db1 +1, 820, 820, 0, 74, 0x6bbb2475 +0, 834, 834, 41, 181, 0x30355b73 +1, 840, 840, 0, 74, 0x76fe1f63 +1, 860, 860, 0, 74, 0x15861cf1 +0, 876, 876, 41, 179, 0xef275e89 +1, 880, 880, 0, 74, 0x7dca1c6a +1, 900, 900, 0, 74, 0xad8b20aa +0, 918, 918, 41, 181, 0xbdb35a1b +1, 920, 920, 0, 74, 0x6ba01e89 +1, 940, 940, 0, 74, 0x621421eb +0, 959, 959, 41, 179, 0x1b245f55 +1, 960, 960, 0, 74, 0x26672424 +1, 980, 980, 0, 74, 0xcb6120f4 diff --git a/tests/ref/fate/matroska-pgs-remux b/tests/ref/fate/matroska-pgs-remux new file mode 100644 index 000000000..ed5beb746 --- /dev/null +++ b/tests/ref/fate/matroska-pgs-remux @@ -0,0 +1,7 @@ +6703d4e9a905bc5a1fc529776e8ffb51 *tests/data/fate/matroska-pgs-remux.matroska +49744 tests/data/fate/matroska-pgs-remux.matroska +#tb 0: 1/1000 +#media_type 0: subtitle +#codec_id 0: hdmv_pgs_subtitle +0, 67, 67, 0, 26127, 0x02389441 +0, 401, 401, 0, 23155, 0x1de74712 diff --git a/tests/ref/fate/matroska-pgs-remux-durations b/tests/ref/fate/matroska-pgs-remux-durations new file mode 100644 index 000000000..a255640fa --- /dev/null +++ b/tests/ref/fate/matroska-pgs-remux-durations @@ -0,0 +1,7 @@ +a547f8b6463a60e5ef2e9a2b117c4dfa *tests/data/fate/matroska-pgs-remux-durations.matroska +49756 tests/data/fate/matroska-pgs-remux-durations.matroska +#tb 0: 1/1000 +#media_type 0: subtitle +#codec_id 0: hdmv_pgs_subtitle +0, 67, 67, 334, 26127, 0x02389441 +0, 401, 401, 0, 23155, 0x1de74712 diff --git a/tests/ref/fate/matroska-qt-mode b/tests/ref/fate/matroska-qt-mode new file mode 100644 index 000000000..17a8e6619 --- /dev/null +++ b/tests/ref/fate/matroska-qt-mode @@ -0,0 +1,124 @@ +39a3d6faff69892c8a20301560b80b14 *tests/data/fate/matroska-qt-mode.matroska +1884224 tests/data/fate/matroska-qt-mode.matroska +#extradata 0: 90, 0x817d0185 +#tb 0: 1/1000 +#media_type 0: video +#codec_id 0: svq1 +#dimensions 0: 160x120 +#sar 0: 0/1 +#tb 1: 1/1000 +#media_type 1: audio +#codec_id 1: pcm_u8 +#sample_rate 1: 22050 +#channel_layout_name 1: mono +0, 0, 0, 66, 3340, 0xcdb26464 +1, 0, 0, 46, 1024, 0x3c0f001e +1, 46, 46, 46, 1024, 0x5772fef7 +0, 67, 67, 66, 76, 0xc93b1f74, F=0x0 +1, 93, 93, 46, 1024, 0xa98efec4 +0, 133, 133, 66, 116, 0x5688353c, F=0x0 +1, 139, 139, 46, 1024, 0xba56fd5d +1, 186, 186, 46, 1024, 0x69d7063c +0, 200, 200, 66, 112, 0xbe8f3086, F=0x0 +1, 232, 232, 46, 1024, 0x2b67fc5a +0, 267, 267, 66, 132, 0xd0cd3b9c, F=0x0 +1, 279, 279, 46, 1024, 0xcdf9022d +1, 325, 325, 46, 1024, 0x91f6fd81 +0, 333, 333, 66, 200, 0x42385725, F=0x0 +1, 372, 372, 46, 1024, 0x920eff99 +0, 400, 400, 66, 164, 0x2d344be3, F=0x0 +1, 418, 418, 46, 1024, 0x09a2ff2b +1, 464, 464, 35, 785, 0x6ece8797 +0, 467, 467, 66, 176, 0xc97c53ff, F=0x0 +1, 500, 500, 46, 1024, 0x9a50fc54 +0, 533, 533, 66, 216, 0x62fe5cf9, F=0x0 +1, 546, 546, 46, 1024, 0xc5ef006e +1, 593, 593, 46, 1024, 0x53430734 +0, 600, 600, 66, 164, 0x52564b48, F=0x0 +1, 639, 639, 46, 1024, 0xaaaff2dc +0, 667, 667, 66, 244, 0x25e16dfb, F=0x0 +1, 686, 686, 46, 1024, 0xe29a01d2 +1, 732, 732, 46, 1024, 0x4deb0411 +0, 733, 733, 66, 156, 0x6abe49bf, F=0x0 +1, 779, 779, 46, 1024, 0x4f5dfd8d +0, 800, 800, 66, 152, 0x47f84373, F=0x0 +1, 825, 825, 46, 1024, 0x4dc5fdf1 +0, 867, 867, 66, 144, 0xe0c64013, F=0x0 +1, 872, 872, 46, 1024, 0x7e0dff54 +1, 918, 918, 46, 1024, 0xde9cff3e +0, 933, 933, 66, 280, 0xa3b57919, F=0x0 +1, 964, 964, 35, 785, 0xfdb78def +0, 1000, 1000, 66, 3312, 0x45ee5b17 +1, 1000, 1000, 46, 1024, 0x5224f542 +1, 1046, 1046, 46, 1024, 0x6e61f9bc +0, 1067, 1067, 66, 324, 0x07cd8cd2, F=0x0 +1, 1093, 1093, 46, 1024, 0x5727115f +0, 1133, 1133, 66, 364, 0x101d9883, F=0x0 +1, 1139, 1139, 46, 1024, 0x1b70eccb +1, 1186, 1186, 46, 1024, 0x717f0778 +0, 1200, 1200, 66, 440, 0x4628b544, F=0x0 +1, 1232, 1232, 46, 1024, 0xf1870091 +0, 1267, 1267, 66, 7020, 0x0a137edf +1, 1279, 1279, 46, 1024, 0xca1df3a7 +1, 1325, 1325, 46, 1024, 0x5a921497 +0, 1333, 1333, 66, 5768, 0xc019d7b8, F=0x0 +1, 1372, 1372, 46, 1024, 0x0655e7bf +0, 1400, 1400, 66, 4820, 0xcc946718, F=0x0 +1, 1418, 1418, 46, 1024, 0x2a8a141c +1, 1464, 1464, 35, 785, 0xbd3a81a5 +0, 1467, 1467, 66, 6112, 0xbaf23f70, F=0x0 +1, 1500, 1500, 46, 1024, 0x54b5fc77 +0, 1533, 1533, 66, 6112, 0xc79655d0, F=0x0 +1, 1546, 1546, 46, 1024, 0x8febfbc1 +1, 1593, 1593, 46, 1024, 0x8ef8f1c1 +0, 1600, 1600, 66, 5112, 0x1d8fe26b, F=0x0 +1, 1639, 1639, 46, 1024, 0x565817aa +0, 1667, 1667, 66, 5872, 0x162eed4d, F=0x0 +1, 1686, 1686, 46, 1024, 0xfdd7ef74 +1, 1732, 1732, 46, 1024, 0x69080694 +0, 1733, 1733, 66, 5092, 0x6ce7e2aa, F=0x0 +1, 1779, 1779, 46, 1024, 0xe4a105c3 +0, 1800, 1800, 66, 5648, 0xfa739b01, F=0x0 +1, 1825, 1825, 46, 1024, 0x1397f5e1 +0, 1867, 1867, 66, 5516, 0x8a778b2b, F=0x0 +1, 1872, 1872, 46, 1024, 0xb298fc7a +1, 1918, 1918, 46, 1024, 0x2869030a +0, 1933, 1933, 66, 5088, 0xdd60e51e, F=0x0 +1, 1964, 1964, 35, 785, 0xf6a49164 +0, 2000, 2000, 66, 5808, 0x14b6e8b3, F=0x0 +1, 2000, 2000, 46, 1024, 0x668ce4db +1, 2046, 2046, 46, 1024, 0x08c71cd7 +0, 2067, 2067, 66, 4512, 0x9efdf756, F=0x0 +1, 2093, 2093, 46, 1024, 0xc682e3f3 +0, 2133, 2133, 66, 5404, 0x50ce47a2, F=0x0 +1, 2139, 2139, 46, 1024, 0x98bc11c5 +1, 2186, 2186, 46, 1024, 0x4a6ef47d +0, 2200, 2200, 66, 5732, 0x7b46abbf, F=0x0 +1, 2232, 2232, 46, 1024, 0xa6660535 +0, 2267, 2267, 66, 6936, 0x325421f1 +1, 2279, 2279, 46, 1024, 0xa1d1fd9d +1, 2325, 2325, 46, 1024, 0xf012fbf3 +0, 2333, 2333, 66, 5780, 0x8eb1d896, F=0x0 +1, 2372, 2372, 46, 1024, 0xacc00616 +0, 2400, 2400, 66, 2280, 0x3a778e69 +1, 2418, 2418, 46, 1024, 0xc8660aac +1, 2464, 2464, 35, 785, 0xe9416835 +0, 2467, 2467, 66, 1220, 0x676b10f0, F=0x0 +1, 2500, 2500, 46, 1024, 0xe31622b5 +0, 2533, 2533, 66, 1584, 0x668b6e9e, F=0x0 +1, 2546, 2546, 46, 1024, 0xc53ee0b8 +1, 2593, 2593, 46, 1024, 0xf26d1102 +0, 2600, 2600, 66, 1084, 0xbdf4ca3d, F=0x0 +1, 2639, 2639, 46, 1024, 0xd2fffa3d +0, 2667, 2667, 66, 1612, 0xd9f3817a, F=0x0 +1, 2686, 2686, 46, 1024, 0x584f0189 +1, 2732, 2732, 46, 1024, 0xb765fce5 +0, 2733, 2733, 66, 1696, 0x91ceac8b, F=0x0 +1, 2779, 2779, 46, 1024, 0x570dfe8b +0, 2800, 2800, 66, 1532, 0x0b2a7bf1, F=0x0 +1, 2825, 2825, 46, 1024, 0x2aa7ff16 +0, 2867, 2867, 66, 2072, 0x3daf2859, F=0x0 +1, 2872, 2872, 46, 1024, 0x5174fe72 +1, 2918, 2918, 46, 1024, 0x21b302d0 +0, 2933, 2933, 66, 1568, 0xbd4d7e64, F=0x0 +1, 2964, 2964, 35, 785, 0x88b67dcd diff --git a/tests/ref/fate/matroska-spherical-mono-remux b/tests/ref/fate/matroska-spherical-mono-remux index 24d4413a8..6b975c158 100644 --- a/tests/ref/fate/matroska-spherical-mono-remux +++ b/tests/ref/fate/matroska-spherical-mono-remux @@ -1,5 +1,5 @@ -9176856edc1ff2b401e323f422fd8e78 *tests/data/fate/matroska-spherical-mono-remux.matroska -161583 tests/data/fate/matroska-spherical-mono-remux.matroska +31cdace875cb696973d5a493ce776eea *tests/data/fate/matroska-spherical-mono-remux.matroska +161554 tests/data/fate/matroska-spherical-mono-remux.matroska #extradata 0: 43, 0x2b0e0d7b #extradata 1: 43, 0x2b0e0d7b #tb 0: 1/1000 diff --git a/tests/ref/fate/matroska-vp8-alpha-remux b/tests/ref/fate/matroska-vp8-alpha-remux index adb771df8..17c15ec9d 100644 --- a/tests/ref/fate/matroska-vp8-alpha-remux +++ b/tests/ref/fate/matroska-vp8-alpha-remux @@ -1,5 +1,5 @@ -d06be833da8e8d9d00bf334e0dfe8a58 *tests/data/fate/matroska-vp8-alpha-remux.matroska -237192 tests/data/fate/matroska-vp8-alpha-remux.matroska +fd4f24bf776a2f84e01b0aa7fdfece38 *tests/data/fate/matroska-vp8-alpha-remux.matroska +235011 tests/data/fate/matroska-vp8-alpha-remux.matroska #tb 0: 1/1000 #media_type 0: video #codec_id 0: vp8 diff --git a/tests/ref/fate/matroska-wavpack-missing-codecprivate b/tests/ref/fate/matroska-wavpack-missing-codecprivate index 4645a86ff..2a91f1c9c 100644 --- a/tests/ref/fate/matroska-wavpack-missing-codecprivate +++ b/tests/ref/fate/matroska-wavpack-missing-codecprivate @@ -3,7 +3,6 @@ #media_type 0: audio #codec_id 0: wavpack #sample_rate 0: 44100 -#channel_layout 0: 3 #channel_layout_name 0: stereo 0, 0, 0, 22051, 14778, 0x02819286 0, 22051, 22051, 22052, 14756, 0x21976243 diff --git a/tests/ref/fate/matroska-xiph-lacing b/tests/ref/fate/matroska-xiph-lacing index c74cf9900..dd00f21e9 100644 --- a/tests/ref/fate/matroska-xiph-lacing +++ b/tests/ref/fate/matroska-xiph-lacing @@ -3,7 +3,6 @@ #media_type 0: audio #codec_id 0: vorbis #sample_rate 0: 44100 -#channel_layout 0: 3 #channel_layout_name 0: stereo 0, 0, 0, 128, 84, 0x1beb2cc9 0, 128, 128, 576, 533, 0xa5d425e9 diff --git a/tests/ref/fate/matroska-zero-length-block b/tests/ref/fate/matroska-zero-length-block index e8c5decb3..bef887d58 100644 --- a/tests/ref/fate/matroska-zero-length-block +++ b/tests/ref/fate/matroska-zero-length-block @@ -1,5 +1,5 @@ -ba78b3e846d57002711bc481fa806717 *tests/data/fate/matroska-zero-length-block.matroska -643 tests/data/fate/matroska-zero-length-block.matroska +d9c8efb9d64addce3cac97e6c417d985 *tests/data/fate/matroska-zero-length-block.matroska +630 tests/data/fate/matroska-zero-length-block.matroska #tb 0: 1/1000 #media_type 0: subtitle #codec_id 0: subrip diff --git a/tests/ref/fate/maxis-xa b/tests/ref/fate/maxis-xa index ad9d73278..120ec9e60 100644 --- a/tests/ref/fate/maxis-xa +++ b/tests/ref/fate/maxis-xa @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: adpcm_ea_maxis_xa #sample_rate 0: 22050 -#channel_layout 0: 3 #channel_layout_name 0: stereo 0, 0, 0, 28, 30, 0x51750711 0, 28, 28, 28, 30, 0x9ca20c2a diff --git a/tests/ref/fate/mkv b/tests/ref/fate/mkv index f9c3037f0..d3dfef76b 100644 --- a/tests/ref/fate/mkv +++ b/tests/ref/fate/mkv @@ -9,7 +9,6 @@ #media_type 1: audio #codec_id 1: aac #sample_rate 1: 48000 -#channel_layout 1: 3 #channel_layout_name 1: stereo 0, -42, 0, 41, 63501, 0x139d4c99 0, 0, 84, 41, 5368, 0xd964b678, F=0x0 diff --git a/tests/ref/fate/mkv-1242 b/tests/ref/fate/mkv-1242 index 34e5b4aa9..e02570109 100644 --- a/tests/ref/fate/mkv-1242 +++ b/tests/ref/fate/mkv-1242 @@ -9,7 +9,6 @@ #media_type 1: audio #codec_id 1: aac #sample_rate 1: 48000 -#channel_layout 1: 3 #channel_layout_name 1: stereo 0, -42, 0, 41, 2969, 0xa7016742 0, 0, 42, 41, 135, 0x33af1a9e, F=0x0 diff --git a/tests/ref/fate/mov-440hz-10ms b/tests/ref/fate/mov-440hz-10ms index 498879e52..77b50d262 100644 --- a/tests/ref/fate/mov-440hz-10ms +++ b/tests/ref/fate/mov-440hz-10ms @@ -5,7 +5,6 @@ #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 diff --git a/tests/ref/fate/mov-avif-demux-still-image-1-item b/tests/ref/fate/mov-avif-demux-still-image-1-item new file mode 100644 index 000000000..93773afd4 --- /dev/null +++ b/tests/ref/fate/mov-avif-demux-still-image-1-item @@ -0,0 +1,11 @@ +#format: frame checksums +#version: 2 +#hash: MD5 +#extradata 0, 13, b52ae298d37128862ef1918cf916239c +#tb 0: 1/1 +#media_type 0: video +#codec_id 0: av1 +#dimensions 0: 352x288 +#sar 0: 1/1 +#stream#, dts, pts, duration, size, hash +0, 0, 0, 1, 36265, 235b0c6e389c4084845981e08d60db04 diff --git a/tests/ref/fate/mov-avif-demux-still-image-multiple-items b/tests/ref/fate/mov-avif-demux-still-image-multiple-items new file mode 100644 index 000000000..93773afd4 --- /dev/null +++ b/tests/ref/fate/mov-avif-demux-still-image-multiple-items @@ -0,0 +1,11 @@ +#format: frame checksums +#version: 2 +#hash: MD5 +#extradata 0, 13, b52ae298d37128862ef1918cf916239c +#tb 0: 1/1 +#media_type 0: video +#codec_id 0: av1 +#dimensions 0: 352x288 +#sar 0: 1/1 +#stream#, dts, pts, duration, size, hash +0, 0, 0, 1, 36265, 235b0c6e389c4084845981e08d60db04 diff --git a/tests/ref/fate/mov-bbi-elst-starts-b b/tests/ref/fate/mov-bbi-elst-starts-b index 3ba28b5e7..f6c2c56eb 100644 --- a/tests/ref/fate/mov-bbi-elst-starts-b +++ b/tests/ref/fate/mov-bbi-elst-starts-b @@ -10,7 +10,6 @@ #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 diff --git a/tests/ref/fate/mov-channel-description b/tests/ref/fate/mov-channel-description new file mode 100644 index 000000000..21b2e1140 --- /dev/null +++ b/tests/ref/fate/mov-channel-description @@ -0,0 +1,42 @@ +497848e1bc5c9dcd416124b6f739d733 *tests/data/fate/mov-channel-description.mov +4242044 tests/data/fate/mov-channel-description.mov +#tb 0: 1/44100 +#media_type 0: audio +#codec_id 0: pcm_s16le +#sample_rate 0: 44100 +#channel_layout_name 0: 1 channels (FL) +#tb 1: 1/44100 +#media_type 1: audio +#codec_id 1: pcm_s16le +#sample_rate 1: 44100 +#channel_layout_name 1: 1 channels (FR) +#tb 2: 1/44100 +#media_type 2: audio +#codec_id 2: pcm_s16le +#sample_rate 2: 44100 +#channel_layout_name 2: mono +#tb 3: 1/44100 +#media_type 3: audio +#codec_id 3: pcm_s16le +#sample_rate 3: 44100 +#channel_layout_name 3: 1 channels (LFE) +#tb 4: 1/44100 +#media_type 4: audio +#codec_id 4: pcm_s16le +#sample_rate 4: 44100 +#channel_layout_name 4: 1 channels (BL) +#tb 5: 1/44100 +#media_type 5: audio +#codec_id 5: pcm_s16le +#sample_rate 5: 44100 +#channel_layout_name 5: 1 channels (BR) +#tb 6: 1/44100 +#media_type 6: audio +#codec_id 6: pcm_s16le +#sample_rate 6: 44100 +#channel_layout_name 6: 1 channels (DL) +#tb 7: 1/44100 +#media_type 7: audio +#codec_id 7: pcm_s16le +#sample_rate 7: 44100 +#channel_layout_name 7: 1 channels (DR) diff --git a/tests/ref/fate/mov-cover-image b/tests/ref/fate/mov-cover-image index 6141646af..5f65c630e 100644 --- a/tests/ref/fate/mov-cover-image +++ b/tests/ref/fate/mov-cover-image @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: aac #sample_rate 0: 44100 -#channel_layout 0: 3 #channel_layout_name 0: stereo #tb 1: 1/90000 #media_type 1: video diff --git a/tests/ref/fate/mov-mp3-demux b/tests/ref/fate/mov-mp3-demux index 193096064..77ec4aced 100644 --- a/tests/ref/fate/mov-mp3-demux +++ b/tests/ref/fate/mov-mp3-demux @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: mp3 #sample_rate 0: 44100 -#channel_layout 0: 3 #channel_layout_name 0: stereo 0, 0, 0, 1152, 36, 0x8e260589 0, 1152, 1152, 1152, 36, 0x8e260589 diff --git a/tests/ref/fate/mov-mp4-chapters b/tests/ref/fate/mov-mp4-chapters new file mode 100644 index 000000000..34f84de1b --- /dev/null +++ b/tests/ref/fate/mov-mp4-chapters @@ -0,0 +1,49 @@ +1fd844c2f5bf77c3344e88e30ad994e1 *tests/data/fate/mov-mp4-chapters.mp4 +111248 tests/data/fate/mov-mp4-chapters.mp4 +#extradata 0: 3469, 0xc6769ddc +#tb 0: 1/44100 +#media_type 0: audio +#codec_id 0: vorbis +#sample_rate 0: 44100 +#channel_layout_name 0: mono +0, -256, -256, 256, 28, 0xefcf103e, F=0x5 +0, 0, 0, 1152, 198, 0xfbbe5eb5 +0, 1152, 1152, 2944, 198, 0xabd95c6c +0, 4096, 4096, 256, 41, 0x954b12a5 +0, 4352, 4352, 256, 41, 0xbccd1463 +[CHAPTER] +id=0 +time_base=1/1000 +start=0 +start_time=0.000000 +end=5000 +end_time=5.000000 +TAG:title=start +[/CHAPTER] +[CHAPTER] +id=1 +time_base=1/1000 +start=5000 +start_time=5.000000 +end=10500 +end_time=10.500000 +TAG:title=Five Seconds +[/CHAPTER] +[CHAPTER] +id=2 +time_base=1/1000 +start=10500 +start_time=10.500000 +end=15000 +end_time=15.000000 +TAG:title=Ten point 5 seconds +[/CHAPTER] +[CHAPTER] +id=3 +time_base=1/1000 +start=15000 +start_time=15.000000 +end=19849 +end_time=19.849000 +TAG:title=15 sec - over soon +[/CHAPTER] diff --git a/tests/ref/fate/mov-mp4-disposition-mpegts-remux b/tests/ref/fate/mov-mp4-disposition-mpegts-remux index 184b952e0..efef04307 100644 --- a/tests/ref/fate/mov-mp4-disposition-mpegts-remux +++ b/tests/ref/fate/mov-mp4-disposition-mpegts-remux @@ -4,13 +4,11 @@ adb3b95c07a5f3e0c86641dd62f01dae *tests/data/fate/mov-mp4-disposition-mpegts-rem #media_type 0: audio #codec_id 0: ac3 #sample_rate 0: 48000 -#channel_layout 0: 3 #channel_layout_name 0: stereo #tb 1: 1/48000 #media_type 1: audio #codec_id 1: ac3 #sample_rate 1: 48000 -#channel_layout 1: 3 #channel_layout_name 1: stereo 1, 0, 0, 1536, 768, 0xa63778d4, S=1, 4 1, 1536, 1536, 1536, 768, 0x7d577f3f diff --git a/tests/ref/fate/movenc b/tests/ref/fate/movenc index 19e4e291b..968a3d27f 100644 --- a/tests/ref/fate/movenc +++ b/tests/ref/fate/movenc @@ -101,28 +101,28 @@ write_data len 1223, time nopts, type header atom ftyp 041ac8efc35a0d023c26d05eedb20403 1223 delay-moov-elst-signal-init write_data len 1004, time -33333, type sync atom sidx write_data len 996, time 966667, type sync atom sidx -5a583d89318827d2569eecbeaa18c238 996 delay-moov-elst-signal-second-frag +69c9025ffb10302c7b5c2ed9fde86c44 996 delay-moov-elst-signal-second-frag write_data len 148, time nopts, type trailer atom - write_data len 1223, time nopts, type header atom ftyp 041ac8efc35a0d023c26d05eedb20403 1223 delay-moov-elst-signal-init-discont write_data len 996, time 966667, type sync atom sidx -5a583d89318827d2569eecbeaa18c238 996 delay-moov-elst-signal-second-frag-discont +69c9025ffb10302c7b5c2ed9fde86c44 996 delay-moov-elst-signal-second-frag-discont write_data len 110, time nopts, type trailer atom - write_data len 1247, time nopts, type header atom ftyp 80511a51d1ac9cde62337eed7176ae03 1247 delay-moov-elst-signal-init-discont-largets write_data len 996, time 279621233333, type sync atom sidx -dc695d65e8a0cdafee28acd8a5ccf81a 996 delay-moov-elst-signal-second-frag-discont-largets +471fc64644a6bf4065c489fe4e04be7d 996 delay-moov-elst-signal-second-frag-discont-largets write_data len 110, time nopts, type trailer atom - write_data len 1223, time nopts, type header atom ftyp write_data len 2572, time -333333, type sync atom sidx write_data len 996, time 5166667, type sync atom sidx write_data len 148, time nopts, type trailer atom - -d37a7eda807912b9ed05ccfe003a9e4f 4939 vfr +5c873f6e37d5af09e3c6329cf94cd6ca 4939 vfr write_data len 1223, time nopts, type header atom ftyp write_data len 2572, time -333333, type sync atom sidx write_data len 996, time 5166667, type sync atom sidx write_data len 148, time nopts, type trailer atom - -d37a7eda807912b9ed05ccfe003a9e4f 4939 vfr-noduration +5c873f6e37d5af09e3c6329cf94cd6ca 4939 vfr-noduration write_data len 1231, time nopts, type header atom ftyp write_data len 1500, time -333333, type sync atom moof write_data len 1500, time nopts, type unknown atom - diff --git a/tests/ref/fate/mpeg4-simple-studio-profile b/tests/ref/fate/mpeg4-simple-studio-profile new file mode 100644 index 000000000..303265ae1 --- /dev/null +++ b/tests/ref/fate/mpeg4-simple-studio-profile @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 720x480 +#sar 0: 1/1 +0, 0, 0, 1, 1382400, 0x3d252879 diff --git a/tests/ref/fate/mpegps-remuxed-pcm-demux b/tests/ref/fate/mpegps-remuxed-pcm-demux index b5b277868..20173d3a4 100644 --- a/tests/ref/fate/mpegps-remuxed-pcm-demux +++ b/tests/ref/fate/mpegps-remuxed-pcm-demux @@ -2,7 +2,6 @@ #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 diff --git a/tests/ref/fate/mtv b/tests/ref/fate/mtv index 7b17bc1b6..a4647a39a 100644 --- a/tests/ref/fate/mtv +++ b/tests/ref/fate/mtv @@ -8,7 +8,6 @@ #media_type 1: audio #codec_id 1: mp3 #sample_rate 1: 44100 -#channel_layout 1: 3 #channel_layout_name 1: stereo 0, 0, 0, 1, 12288, 0xc2258ebc 1, 0, 0, 1152, 417, 0xae1cc66a diff --git a/tests/ref/fate/mxf-d10-user-comments b/tests/ref/fate/mxf-d10-user-comments index 64a2dec46..1b59beec7 100644 --- a/tests/ref/fate/mxf-d10-user-comments +++ b/tests/ref/fate/mxf-d10-user-comments @@ -1,4 +1,4 @@ -6dc13ae283257e898e069e5041ac8435 *tests/data/fate/mxf-d10-user-comments.mxf_d10 +8c831b8e01aa4c86e98ab87930d06f3e *tests/data/fate/mxf-d10-user-comments.mxf_d10 3782189 tests/data/fate/mxf-d10-user-comments.mxf_d10 #extradata 0: 34, 0x716b05c4 #tb 0: 1/25 @@ -13,8 +13,8 @@ 0, 3, 4, 1, 150000, 0x9bbe6feb, F=0x0 [FORMAT] TAG:operational_pattern_ul=060e2b34.04010101.0d010201.01010900 -TAG:uid=adab4424-2f25-4dc7-92ff-29bd000c0000 -TAG:generation_uid=adab4424-2f25-4dc7-92ff-29bd000c0001 +TAG:uid=adab4424-2f25-4dc7-92ff-000c00000000 +TAG:generation_uid=adab4424-2f25-4dc7-92ff-000c00000001 TAG:company_name=FATE-company TAG:product_name=FATE-test TAG:product_version_num=0.0.0.0.0 diff --git a/tests/ref/fate/mxf-demux b/tests/ref/fate/mxf-demux index 906a6d063..3010ca217 100644 --- a/tests/ref/fate/mxf-demux +++ b/tests/ref/fate/mxf-demux @@ -8,7 +8,6 @@ #media_type 1: audio #codec_id 1: pcm_alaw #sample_rate 1: 8000 -#channel_layout 1: 3 #channel_layout_name 1: stereo 0, 0, -9223372036854775808, 1, 8468, 0xc0855553 1, 0, 0, 16000, 32000, 0x479155e6 diff --git a/tests/ref/fate/mxf-opatom-user-comments b/tests/ref/fate/mxf-opatom-user-comments index ec4fdff42..14a1cee1f 100644 --- a/tests/ref/fate/mxf-opatom-user-comments +++ b/tests/ref/fate/mxf-opatom-user-comments @@ -1 +1 @@ -8475bebf3448a972ae89ba59309fd7d6 +d40b64e492133c74faa07e605eb65b2f diff --git a/tests/ref/fate/mxf-reel_name b/tests/ref/fate/mxf-reel_name index d50f0f699..f3bafcc11 100644 --- a/tests/ref/fate/mxf-reel_name +++ b/tests/ref/fate/mxf-reel_name @@ -1 +1 @@ -ce49a0361d3f79106e1952d387eace51 +75e0ac14d5632d709bd805f1cacb1fbb diff --git a/tests/ref/fate/mxf-user-comments b/tests/ref/fate/mxf-user-comments index 5fcdc5806..b4c78744b 100644 --- a/tests/ref/fate/mxf-user-comments +++ b/tests/ref/fate/mxf-user-comments @@ -1 +1 @@ -956f653cd75e1a319569caec9df81b4f +620ae205fefbb6dba74418f357a62c36 diff --git a/tests/ref/fate/nsv-demux b/tests/ref/fate/nsv-demux index bff871dab..540079ad4 100644 --- a/tests/ref/fate/nsv-demux +++ b/tests/ref/fate/nsv-demux @@ -7,7 +7,6 @@ #media_type 1: audio #codec_id 1: mp3 #sample_rate 1: 11025 -#channel_layout 1: 4 #channel_layout_name 1: mono 0, 0, 0, 1, 12, 0x1396035f 0, 1, 1, 1, 24, 0x8ab80ac7, F=0x0 diff --git a/tests/ref/fate/oma-atrac3-remux b/tests/ref/fate/oma-atrac3-remux index fb402c43c..d807c6cfb 100644 --- a/tests/ref/fate/oma-atrac3-remux +++ b/tests/ref/fate/oma-atrac3-remux @@ -5,7 +5,6 @@ #media_type 0: audio #codec_id 0: atrac3 #sample_rate 0: 44100 -#channel_layout 0: 3 #channel_layout_name 0: stereo 0, 0, 0, 1024, 384, 0xdfded1b5 0, 1024, 1024, 1024, 384, 0xd8e3badd diff --git a/tests/ref/fate/oma-atrac3p-remux b/tests/ref/fate/oma-atrac3p-remux index d909fdaee..7d1cd962e 100644 --- a/tests/ref/fate/oma-atrac3p-remux +++ b/tests/ref/fate/oma-atrac3p-remux @@ -4,7 +4,6 @@ #media_type 0: audio #codec_id 0: atrac3p #sample_rate 0: 44100 -#channel_layout 0: 3 #channel_layout_name 0: stereo 0, 0, 0, 2048, 1488, 0x69b7fad9 0, 2048, 2048, 2048, 1488, 0x3c43fdb8 diff --git a/tests/ref/fate/on2avc b/tests/ref/fate/on2avc index a9d6cbcea..2475c1498 100644 --- a/tests/ref/fate/on2avc +++ b/tests/ref/fate/on2avc @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 16000 -#channel_layout 0: 4 #channel_layout_name 0: mono 0, 0, 0, 1024, 2048, 0x00000000 0, 1024, 1024, 1024, 2048, 0x96ee1301 diff --git a/tests/ref/fate/opt b/tests/ref/fate/opt index aac3fa0e7..832f9cc8a 100644 --- a/tests/ref/fate/opt +++ b/tests/ref/fate/opt @@ -33,7 +33,7 @@ TestContext AVOptions: -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) + -cl E.......... set channel layout (default "hexagonal") -bin E.......... set binary value -bin1 E.......... set binary value -bin2 E.......... set binary value @@ -115,7 +115,7 @@ name: sample_fmt get: s16 set: OK get: s16 name: video_rate get: 25/1 set: OK get: 25/1 OK name: duration get: 0.001 set: OK get: 0.001 OK name: color get: 0xffc0cbff set: OK get: 0xffc0cbff OK -name: cl get: 0x137 set: OK get: 0x137 OK +name: cl get: hexagonal set: OK get: hexagonal OK name: bin get: 62696E00 set: OK get: 62696E00 OK name: bin1 get: set: OK get: OK name: bin2 get: set: OK get: OK @@ -129,7 +129,7 @@ name: dict1 get: set: OK get: name: dict2 get: happy=\:-) set: OK get: happy=\:-) OK Test av_opt_serialize() -num=0,toggle=1,rational=1/1,string=default,escape=\\\=\,,flags=0x00000001,size=200x300,pix_fmt=0bgr,sample_fmt=s16,video_rate=25/1,duration=0.001,color=0xffc0cbff,cl=0x137,bin=62696E00,bin1=,bin2=,num64=1,flt=0.333333,dbl=0.333333,bool1=auto,bool2=true,bool3=false,dict1=,dict2=happy\=\\:-) +num=0,toggle=1,rational=1/1,string=default,escape=\\\=\,,flags=0x00000001,size=200x300,pix_fmt=0bgr,sample_fmt=s16,video_rate=25/1,duration=0.001,color=0xffc0cbff,cl=hexagonal,bin=62696E00,bin1=,bin2=,num64=1,flt=0.333333,dbl=0.333333,bool1=auto,bool2=true,bool3=false,dict1=,dict2=happy\=\\:-) Setting entry with key 'num' to value '0' Setting entry with key 'toggle' to value '1' Setting entry with key 'rational' to value '1/1' @@ -142,7 +142,7 @@ Setting entry with key 'sample_fmt' to value 's16' Setting entry with key 'video_rate' to value '25/1' Setting entry with key 'duration' to value '0.001' Setting entry with key 'color' to value '0xffc0cbff' -Setting entry with key 'cl' to value '0x137' +Setting entry with key 'cl' to value 'hexagonal' Setting entry with key 'bin' to value '62696E00' Setting entry with key 'bin1' to value '' Setting entry with key 'bin2' to value '' @@ -154,7 +154,7 @@ Setting entry with key 'bool2' to value 'true' Setting entry with key 'bool3' to value 'false' Setting entry with key 'dict1' to value '' Setting entry with key 'dict2' to value 'happy=\:-)' -num=0,toggle=1,rational=1/1,string=default,escape=\\\=\,,flags=0x00000001,size=200x300,pix_fmt=0bgr,sample_fmt=s16,video_rate=25/1,duration=0.001,color=0xffc0cbff,cl=0x137,bin=62696E00,bin1=,bin2=,num64=1,flt=0.333333,dbl=0.333333,bool1=auto,bool2=true,bool3=false,dict1=,dict2=happy\=\\:-) +num=0,toggle=1,rational=1/1,string=default,escape=\\\=\,,flags=0x00000001,size=200x300,pix_fmt=0bgr,sample_fmt=s16,video_rate=25/1,duration=0.001,color=0xffc0cbff,cl=hexagonal,bin=62696E00,bin1=,bin2=,num64=1,flt=0.333333,dbl=0.333333,bool1=auto,bool2=true,bool3=false,dict1=,dict2=happy\=\\:-) Testing av_set_options_string() Setting options string '' @@ -296,9 +296,9 @@ OK 'color=0x223300' Setting options string 'color=0x42FF07AA' Setting entry with key 'color' to value '0x42FF07AA' OK 'color=0x42FF07AA' -Setting options string 'cl=stereo+downmix' -Setting entry with key 'cl' to value 'stereo+downmix' -OK 'cl=stereo+downmix' +Setting options string 'cl=FL+FR' +Setting entry with key 'cl' to value 'FL+FR' +OK 'cl=FL+FR' Setting options string 'cl=foo' Setting entry with key 'cl' to value 'foo' Unable to parse option value "foo" as channel layout diff --git a/tests/ref/fate/paf-audio b/tests/ref/fate/paf-audio index a9ed9e99f..b2fbc094e 100644 --- a/tests/ref/fate/paf-audio +++ b/tests/ref/fate/paf-audio @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 22050 -#channel_layout 0: 3 #channel_layout_name 0: stereo 0, 0, 0, 57330, 229320, 0x062508b4 0, 57330, 57330, 57330, 229320, 0x0a966cbf diff --git a/tests/ref/fate/paf-demux b/tests/ref/fate/paf-demux index 6a66697af..a0d1f4484 100644 --- a/tests/ref/fate/paf-demux +++ b/tests/ref/fate/paf-demux @@ -7,7 +7,6 @@ #media_type 1: audio #codec_id 1: paf_audio #sample_rate 1: 22050 -#channel_layout 1: 3 #channel_layout_name 1: stereo 0, 0, 0, 1, 262144, 0x7f9a3c6a 1, 0, 0, 57330, 131072, 0x255a6ac2 diff --git a/tests/ref/fate/pcm-planar b/tests/ref/fate/pcm-planar index 8b6c96181..b1d988bb7 100644 --- a/tests/ref/fate/pcm-planar +++ b/tests/ref/fate/pcm-planar @@ -2,7 +2,6 @@ #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, 1471, 5884, 0x00000000 0, 1471, 1471, 1471, 5884, 0x00000000 diff --git a/tests/ref/fate/pcm_dvd b/tests/ref/fate/pcm_dvd index 2a2415628..61ddcaef1 100644 --- a/tests/ref/fate/pcm_dvd +++ b/tests/ref/fate/pcm_dvd @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 48000 -#channel_layout 0: 3 #channel_layout_name 0: stereo 0, 0, 0, 334, 1336, 0x8e3c0abc 0, 400, 400, 334, 1336, 0x99c41108 diff --git a/tests/ref/fate/pcm_dvd-16-1-48000 b/tests/ref/fate/pcm_dvd-16-1-48000 new file mode 100644 index 000000000..29f4e84d5 --- /dev/null +++ b/tests/ref/fate/pcm_dvd-16-1-48000 @@ -0,0 +1,11 @@ +af7b5ae365019ec64a9397bc6b33e18c *tests/data/fate/pcm_dvd-16-1-48000.vob +8192 tests/data/fate/pcm_dvd-16-1-48000.vob +#tb 0: 1/48000 +#media_type 0: audio +#codec_id 0: pcm_s16le +#sample_rate 0: 48000 +#channel_layout_name 0: mono +0, 0, 0, 997, 1994, 0xd416def5 +0, 1004, 1004, 1006, 2012, 0xb492d66d +0, 2008, 2008, 1006, 2012, 0x52d3f72e +0, 3012, 3012, 995, 1990, 0xa23de22f diff --git a/tests/ref/fate/pcm_dvd-16-1-96000 b/tests/ref/fate/pcm_dvd-16-1-96000 new file mode 100644 index 000000000..56f3ae703 --- /dev/null +++ b/tests/ref/fate/pcm_dvd-16-1-96000 @@ -0,0 +1,26 @@ +2807776bfcb2eddd315d2b0675afc445 *tests/data/fate/pcm_dvd-16-1-96000.vob +1173504 tests/data/fate/pcm_dvd-16-1-96000.vob +#tb 0: 1/96000 +#media_type 0: audio +#codec_id 0: pcm_s16le +#sample_rate 0: 96000 +#channel_layout_name 0: mono +0, 0, 0, 997, 1994, 0xa58fdef0 +0, 1004, 1004, 1006, 2012, 0xb634eec3 +0, 2010, 2010, 1006, 2012, 0x8371e23d +0, 3012, 3012, 1006, 2012, 0x8cecf569 +0, 4017, 4017, 1006, 2012, 0xc990d62c +0, 6025, 6025, 1006, 2012, 0xf678fc74 +0, 7029, 7029, 1006, 2012, 0x78f8dde4 +0, 8033, 8033, 1006, 2012, 0x1d67ecc0 +0, 9037, 9037, 1006, 2012, 0xa520e618 +0, 10042, 10042, 1006, 2012, 0x83f2f584 +0, 11044, 11044, 1006, 2012, 0x08e6dee5 +0, 12049, 12049, 1006, 2012, 0x28d8f24f +0, 13053, 13053, 1006, 2012, 0x68b2ed35 +0, 14058, 14058, 1006, 2012, 0x3aeee8f8 +0, 15060, 15060, 1006, 2012, 0x76a2eb0a +0, 16065, 16065, 1006, 2012, 0x713eea12 +0, 17069, 17069, 1006, 2012, 0x9992ebc8 +0, 18074, 18074, 1006, 2012, 0x847fe12e +0, 19076, 19076, 124, 248, 0x2c4b88bc diff --git a/tests/ref/fate/pcm_dvd-16-2-48000 b/tests/ref/fate/pcm_dvd-16-2-48000 new file mode 100644 index 000000000..7629973ef --- /dev/null +++ b/tests/ref/fate/pcm_dvd-16-2-48000 @@ -0,0 +1,26 @@ +42ba1c4170f9fd6e98af29151f4cedb0 *tests/data/fate/pcm_dvd-16-2-48000.vob +2502656 tests/data/fate/pcm_dvd-16-2-48000.vob +#tb 0: 1/48000 +#media_type 0: audio +#codec_id 0: pcm_s16le +#sample_rate 0: 48000 +#channel_layout_name 0: stereo +0, 0, 0, 498, 1992, 0x60a8f5dd +0, 502, 502, 503, 2012, 0x685028f8 +0, 1004, 1004, 503, 2012, 0x567d0e82 +0, 1506, 1506, 503, 2012, 0x0f7240cd +0, 2008, 2008, 503, 2012, 0x61a87973 +0, 2510, 2510, 503, 2012, 0x9cdc5ce4 +0, 3514, 3514, 503, 2012, 0x6772d774 +0, 4016, 4016, 503, 2012, 0x56b0d501 +0, 4518, 4518, 503, 2012, 0xb98154d3 +0, 5020, 5020, 503, 2012, 0xc4d8035c +0, 5522, 5522, 503, 2012, 0x6af47ddd +0, 6024, 6024, 503, 2012, 0xb3dddfd4 +0, 6526, 6526, 503, 2012, 0x33354177 +0, 7028, 7028, 503, 2012, 0x6eabf85f +0, 7530, 7530, 503, 2012, 0x22e78b8d +0, 8032, 8032, 503, 2012, 0x64011afb +0, 8534, 8534, 503, 2012, 0x96e079c7 +0, 9036, 9036, 503, 2012, 0x68419738 +0, 9538, 9538, 62, 248, 0x6401374a diff --git a/tests/ref/fate/pcm_dvd-16-5.1-48000 b/tests/ref/fate/pcm_dvd-16-5.1-48000 new file mode 100644 index 000000000..47d098b48 --- /dev/null +++ b/tests/ref/fate/pcm_dvd-16-5.1-48000 @@ -0,0 +1,65 @@ +76b784964f1f13e34ff9288e327f1327 *tests/data/fate/pcm_dvd-16-5.1-48000.vob +591872 tests/data/fate/pcm_dvd-16-5.1-48000.vob +#tb 0: 1/48000 +#media_type 0: audio +#codec_id 0: pcm_s16le +#sample_rate 0: 48000 +#channel_layout_name 0: 5.1 +0, 0, 0, 166, 1992, 0x00000000 +0, 167, 167, 167, 2004, 0x00000000 +0, 334, 334, 167, 2004, 0x00000000 +0, 501, 501, 167, 2004, 0x00000000 +0, 668, 668, 167, 2004, 0x00000000 +0, 835, 835, 167, 2004, 0x00000000 +0, 1002, 1002, 167, 2004, 0x00000000 +0, 1169, 1169, 167, 2004, 0x00000000 +0, 1336, 1336, 167, 2004, 0x00000000 +0, 1503, 1503, 167, 2004, 0x00000000 +0, 1670, 1670, 167, 2004, 0x00000000 +0, 1837, 1837, 167, 2004, 0x00000000 +0, 2004, 2004, 167, 2004, 0x00000000 +0, 2171, 2171, 167, 2004, 0x00000000 +0, 2338, 2338, 167, 2004, 0x00000000 +0, 2505, 2505, 167, 2004, 0x00000000 +0, 2672, 2672, 167, 2004, 0x00000000 +0, 2839, 2839, 167, 2004, 0x00000000 +0, 3006, 3006, 167, 2004, 0x00000000 +0, 3173, 3173, 167, 2004, 0x00000000 +0, 3340, 3340, 167, 2004, 0x00000000 +0, 3507, 3507, 167, 2004, 0x00000000 +0, 3674, 3674, 167, 2004, 0x00000000 +0, 3841, 3841, 167, 2004, 0x00000000 +0, 4008, 4008, 167, 2004, 0x00000000 +0, 4175, 4175, 167, 2004, 0x00000000 +0, 4342, 4342, 167, 2004, 0x00000000 +0, 4509, 4509, 167, 2004, 0x00000000 +0, 4676, 4676, 167, 2004, 0x00000000 +0, 4843, 4843, 167, 2004, 0x00000000 +0, 5010, 5010, 167, 2004, 0x00000000 +0, 5177, 5177, 167, 2004, 0x00000000 +0, 5344, 5344, 167, 2004, 0x00000000 +0, 5511, 5511, 167, 2004, 0x00000000 +0, 5678, 5678, 167, 2004, 0x00000000 +0, 5845, 5845, 167, 2004, 0x00000000 +0, 6012, 6012, 167, 2004, 0x00000000 +0, 6179, 6179, 167, 2004, 0x00000000 +0, 6346, 6346, 167, 2004, 0x00000000 +0, 6513, 6513, 167, 2004, 0x00000000 +0, 6680, 6680, 166, 1992, 0x00000000 +0, 6847, 6847, 167, 2004, 0x00000000 +0, 7014, 7014, 167, 2004, 0x00000000 +0, 7181, 7181, 167, 2004, 0x00000000 +0, 7348, 7348, 167, 2004, 0x00000000 +0, 7515, 7515, 167, 2004, 0x00000000 +0, 7682, 7682, 167, 2004, 0x00000000 +0, 7849, 7849, 167, 2004, 0x00000000 +0, 8016, 8016, 167, 2004, 0x00000000 +0, 8183, 8183, 167, 2004, 0x00000000 +0, 8349, 8349, 167, 2004, 0x00000000 +0, 8516, 8516, 167, 2004, 0x00000000 +0, 8683, 8683, 167, 2004, 0x00000000 +0, 8850, 8850, 167, 2004, 0x00000000 +0, 9017, 9017, 167, 2004, 0x00000000 +0, 9184, 9184, 167, 2004, 0x00000000 +0, 9351, 9351, 167, 2004, 0x00000000 +0, 9518, 9518, 82, 984, 0x00000000 diff --git a/tests/ref/fate/pcm_dvd-16-5.1-96000 b/tests/ref/fate/pcm_dvd-16-5.1-96000 new file mode 100644 index 000000000..64447a9aa --- /dev/null +++ b/tests/ref/fate/pcm_dvd-16-5.1-96000 @@ -0,0 +1,51 @@ +d8e182dfa46524c28d1f78a4cc1f2719 *tests/data/fate/pcm_dvd-16-5.1-96000.vob +90112 tests/data/fate/pcm_dvd-16-5.1-96000.vob +#tb 0: 1/96000 +#media_type 0: audio +#codec_id 0: pcm_s16le +#sample_rate 0: 96000 +#channel_layout_name 0: 5.1 +0, 0, 0, 166, 1992, 0x00000000 +0, 167, 167, 167, 2004, 0x00000000 +0, 334, 334, 167, 2004, 0x00000000 +0, 501, 501, 167, 2004, 0x00000000 +0, 668, 668, 167, 2004, 0x00000000 +0, 835, 835, 167, 2004, 0x00000000 +0, 1002, 1002, 167, 2004, 0x00000000 +0, 1169, 1169, 167, 2004, 0x00000000 +0, 1337, 1337, 167, 2004, 0x00000000 +0, 1503, 1503, 167, 2004, 0x00000000 +0, 1670, 1670, 167, 2004, 0x00000000 +0, 1837, 1837, 167, 2004, 0x00000000 +0, 2004, 2004, 167, 2004, 0x00000000 +0, 2171, 2171, 167, 2004, 0x00000000 +0, 2338, 2338, 167, 2004, 0x00000000 +0, 2505, 2505, 167, 2004, 0x00000000 +0, 2672, 2672, 167, 2004, 0x00000000 +0, 2839, 2839, 167, 2004, 0x00000000 +0, 3006, 3006, 167, 2004, 0x00000000 +0, 3173, 3173, 167, 2004, 0x00000000 +0, 3340, 3340, 167, 2004, 0x00000000 +0, 3507, 3507, 167, 2004, 0x00000000 +0, 3674, 3674, 167, 2004, 0x00000000 +0, 3841, 3841, 167, 2004, 0x00000000 +0, 4009, 4009, 167, 2004, 0x00000000 +0, 4175, 4175, 167, 2004, 0x00000000 +0, 4342, 4342, 167, 2004, 0x00000000 +0, 4509, 4509, 167, 2004, 0x00000000 +0, 4676, 4676, 167, 2004, 0x00000000 +0, 4843, 4843, 167, 2004, 0x00000000 +0, 5010, 5010, 167, 2004, 0x00000000 +0, 5177, 5177, 167, 2004, 0x00000000 +0, 5344, 5344, 167, 2004, 0x00000000 +0, 5511, 5511, 167, 2004, 0x00000000 +0, 5678, 5678, 167, 2004, 0x00000000 +0, 5845, 5845, 167, 2004, 0x00000000 +0, 6012, 6012, 167, 2004, 0x00000000 +0, 6179, 6179, 167, 2004, 0x00000000 +0, 6346, 6346, 167, 2004, 0x00000000 +0, 6513, 6513, 167, 2004, 0x00000000 +0, 6681, 6681, 166, 1992, 0x00000000 +0, 6847, 6847, 167, 2004, 0x00000000 +0, 7014, 7014, 167, 2004, 0x00000000 +0, 7181, 7181, 101, 1212, 0x00000000 diff --git a/tests/ref/fate/pcm_dvd-16-7.1-48000 b/tests/ref/fate/pcm_dvd-16-7.1-48000 new file mode 100644 index 000000000..dc7ff3e6e --- /dev/null +++ b/tests/ref/fate/pcm_dvd-16-7.1-48000 @@ -0,0 +1,69 @@ +2644ceac530c074d638cc087f2045251 *tests/data/fate/pcm_dvd-16-7.1-48000.vob +126976 tests/data/fate/pcm_dvd-16-7.1-48000.vob +#tb 0: 1/48000 +#media_type 0: audio +#codec_id 0: pcm_s16le +#sample_rate 0: 48000 +#channel_layout_name 0: 7.1 +0, 0, 0, 124, 1984, 0x9d57fb8d +0, 125, 125, 125, 2000, 0x5d98ca5b +0, 250, 250, 125, 2000, 0xcf47f872 +0, 375, 375, 125, 2000, 0xd0b9c223 +0, 500, 500, 125, 2000, 0xf929e0e2 +0, 625, 625, 125, 2000, 0xc893f22c +0, 750, 750, 125, 2000, 0x8843fafa +0, 875, 875, 125, 2000, 0xb7e30a8e +0, 1000, 1000, 125, 2000, 0xe4fddc6b +0, 1125, 1125, 125, 2000, 0x5bd70b66 +0, 1250, 1250, 125, 2000, 0x9252e2e8 +0, 1375, 1375, 125, 2000, 0x1baaff6a +0, 1500, 1500, 125, 2000, 0xd363b522 +0, 1625, 1625, 125, 2000, 0xfafe00a4 +0, 1750, 1750, 125, 2000, 0x0980dc2c +0, 1875, 1875, 125, 2000, 0xb0e5128c +0, 2000, 2000, 125, 2000, 0xd8a0ddc5 +0, 2125, 2125, 125, 2000, 0xffb8e1b4 +0, 2250, 2250, 125, 2000, 0x1842ea9a +0, 2375, 2375, 125, 2000, 0x35c6e4d3 +0, 2500, 2500, 125, 2000, 0xa245009c +0, 2625, 2625, 125, 2000, 0x7daef475 +0, 2750, 2750, 125, 2000, 0x85d4fe0b +0, 2875, 2875, 125, 2000, 0x2000ec85 +0, 3000, 3000, 125, 2000, 0x56c9d7a0 +0, 3125, 3125, 125, 2000, 0x8edae018 +0, 3250, 3250, 125, 2000, 0x5345ec09 +0, 3375, 3375, 125, 2000, 0xe888ee0d +0, 3500, 3500, 125, 2000, 0xa8c10d13 +0, 3625, 3625, 125, 2000, 0x4089fd76 +0, 3750, 3750, 125, 2000, 0xf3371321 +0, 3875, 3875, 125, 2000, 0x50450212 +0, 4000, 4000, 125, 2000, 0x75eef816 +0, 4125, 4125, 125, 2000, 0xfd94ea7b +0, 4250, 4250, 125, 2000, 0xd20ec50a +0, 4375, 4375, 125, 2000, 0x4f2c0871 +0, 4500, 4500, 125, 2000, 0x441deee4 +0, 4625, 4625, 125, 2000, 0xd94d0924 +0, 4750, 4750, 125, 2000, 0xe5d0c8e6 +0, 4875, 4875, 125, 2000, 0x0166dd90 +0, 5000, 5000, 124, 1984, 0x8d0ede76 +0, 5125, 5125, 125, 2000, 0xdf0edb96 +0, 5250, 5250, 125, 2000, 0xf53bf7db +0, 5375, 5375, 125, 2000, 0x8895ee37 +0, 5500, 5500, 125, 2000, 0xaac3f939 +0, 5625, 5625, 125, 2000, 0x6ca311ed +0, 5750, 5750, 125, 2000, 0x7311d6c3 +0, 5875, 5875, 125, 2000, 0x3facdca1 +0, 6000, 6000, 125, 2000, 0xbfa9f8cb +0, 6125, 6125, 125, 2000, 0x1ef8cbd5 +0, 6250, 6250, 125, 2000, 0x835ff155 +0, 6375, 6375, 125, 2000, 0x76bd08d9 +0, 6500, 6500, 125, 2000, 0xe363d4b1 +0, 6625, 6625, 125, 2000, 0x7d22efc6 +0, 6750, 6750, 125, 2000, 0x6796cd13 +0, 6875, 6875, 125, 2000, 0x7255e228 +0, 7000, 7000, 125, 2000, 0x68fbe3f5 +0, 7125, 7125, 125, 2000, 0x901ffed7 +0, 7250, 7250, 125, 2000, 0xe9bbe07e +0, 7375, 7375, 125, 2000, 0xe4850e2b +0, 7500, 7500, 125, 2000, 0xca99f73a +0, 7625, 7625, 57, 912, 0x82c3c85e diff --git a/tests/ref/fate/pcm_dvd-24-1-48000 b/tests/ref/fate/pcm_dvd-24-1-48000 new file mode 100644 index 000000000..98f4dbcd9 --- /dev/null +++ b/tests/ref/fate/pcm_dvd-24-1-48000 @@ -0,0 +1,59 @@ +95a5e963bb6b654603089f3e17718b16 *tests/data/fate/pcm_dvd-24-1-48000.vob +106496 tests/data/fate/pcm_dvd-24-1-48000.vob +#tb 0: 1/48000 +#media_type 0: audio +#codec_id 0: pcm_s24le +#sample_rate 0: 48000 +#channel_layout_name 0: mono +0, 0, 0, 664, 1992, 0x722ccac0 +0, 672, 672, 668, 2004, 0x7a82f0db +0, 1344, 1344, 672, 2016, 0xe91cd0d1 +0, 2016, 2016, 668, 2004, 0x76fbb193 +0, 2688, 2688, 672, 2016, 0xc85bd904 +0, 3360, 3360, 668, 2004, 0x698219fa +0, 4032, 4032, 672, 2016, 0xe74cd175 +0, 4704, 4704, 668, 2004, 0x684bd409 +0, 5376, 5376, 672, 2016, 0xf497da15 +0, 6048, 6048, 668, 2004, 0x6166e1ea +0, 6720, 6720, 672, 2016, 0x3836159e +0, 7392, 7392, 668, 2004, 0x0827cfe5 +0, 8064, 8064, 672, 2016, 0x78150039 +0, 8736, 8736, 668, 2004, 0x28bcc323 +0, 9408, 9408, 672, 2016, 0x7123c17d +0, 10080, 10080, 668, 2004, 0xcbfeed6f +0, 10752, 10752, 672, 2016, 0x05d6128d +0, 11424, 11424, 668, 2004, 0xb4f1e9b9 +0, 12096, 12096, 672, 2016, 0xf83b0966 +0, 12768, 12768, 668, 2004, 0x71a9f220 +0, 13440, 13440, 672, 2016, 0x97b5fc85 +0, 14112, 14112, 668, 2004, 0xda97b165 +0, 14784, 14784, 672, 2016, 0x43c9cfcf +0, 15456, 15456, 668, 2004, 0x5d83e552 +0, 16128, 16128, 672, 2016, 0xe1bbc192 +0, 16800, 16800, 668, 2004, 0xdec9a0ba +0, 17472, 17472, 672, 2016, 0xcc01cd21 +0, 18144, 18144, 668, 2004, 0x73f99e51 +0, 18816, 18816, 672, 2016, 0x023ec896 +0, 19488, 19488, 668, 2004, 0x4d5cd720 +0, 20160, 20160, 672, 2016, 0x9af2bb31 +0, 20832, 20832, 668, 2004, 0xd2a3dac6 +0, 21504, 21504, 672, 2016, 0x02dbce4f +0, 22176, 22176, 668, 2004, 0xbba5f7e6 +0, 22848, 22848, 672, 2016, 0xfb5501c1 +0, 23520, 23520, 668, 2004, 0xe953ed65 +0, 24192, 24192, 672, 2016, 0x5c83d800 +0, 24864, 24864, 668, 2004, 0xabc0e62c +0, 25536, 25536, 672, 2016, 0xda8be7e0 +0, 26208, 26208, 668, 2004, 0x0acbc166 +0, 26880, 26880, 664, 1992, 0x46dddfa4 +0, 27552, 27552, 672, 2016, 0x9a33b4cc +0, 28224, 28224, 668, 2004, 0xda13d604 +0, 28896, 28896, 672, 2016, 0xe92dd4fb +0, 29568, 29568, 668, 2004, 0xedd2bcec +0, 30240, 30240, 672, 2016, 0x73afe253 +0, 30912, 30912, 668, 2004, 0x17eae64a +0, 31584, 31584, 672, 2016, 0x48b0f6c2 +0, 32256, 32256, 668, 2004, 0x4f72fb8d +0, 32928, 32928, 672, 2016, 0x3ad7dfdd +0, 33600, 33600, 668, 2004, 0x3e72ee51 +0, 34272, 34272, 404, 1212, 0x416c4aef diff --git a/tests/ref/fate/pcm_dvd-24-2-48000 b/tests/ref/fate/pcm_dvd-24-2-48000 new file mode 100644 index 000000000..817cd934a --- /dev/null +++ b/tests/ref/fate/pcm_dvd-24-2-48000 @@ -0,0 +1,36 @@ +6fcd235f0c165f2c5f4431f9e0d60d28 *tests/data/fate/pcm_dvd-24-2-48000.vob +8218624 tests/data/fate/pcm_dvd-24-2-48000.vob +#tb 0: 1/48000 +#media_type 0: audio +#codec_id 0: pcm_s24le +#sample_rate 0: 48000 +#channel_layout_name 0: stereo +0, 0, 0, 332, 1992, 0x13af13b9 +0, 336, 336, 334, 2004, 0x178ac9be +0, 672, 672, 336, 2016, 0xc0c9266b +0, 1008, 1008, 334, 2004, 0x0266b229 +0, 1344, 1344, 336, 2016, 0xe821e124 +0, 1680, 1680, 334, 2004, 0xd7cedefd +0, 2016, 2016, 336, 2016, 0xb817b01c +0, 2352, 2352, 334, 2004, 0xd7a8e953 +0, 2688, 2688, 336, 2016, 0xc20cf5fa +0, 3024, 3024, 334, 2004, 0xe5ee903e +0, 3360, 3360, 336, 2016, 0xbe20ec1d +0, 3696, 3696, 334, 2004, 0x9708d462 +0, 4032, 4032, 336, 2016, 0x9e82f06c +0, 4368, 4368, 334, 2004, 0x5069d037 +0, 4704, 4704, 336, 2016, 0xcfb6effe +0, 5040, 5040, 334, 2004, 0xe13c128a +0, 5376, 5376, 336, 2016, 0x8564d28e +0, 5712, 5712, 334, 2004, 0x116dc5c0 +0, 6048, 6048, 336, 2016, 0xf0ca183b +0, 6384, 6384, 334, 2004, 0x39e5d580 +0, 6720, 6720, 336, 2016, 0xaacbf84e +0, 7056, 7056, 334, 2004, 0x50b7ed68 +0, 7392, 7392, 336, 2016, 0x83451550 +0, 7728, 7728, 334, 2004, 0x4523eebf +0, 8064, 8064, 336, 2016, 0x5781de58 +0, 8400, 8400, 334, 2004, 0x66f2e12a +0, 8736, 8736, 336, 2016, 0xdaebe5e0 +0, 9072, 9072, 334, 2004, 0x9b83d9df +0, 9408, 9408, 192, 1152, 0xdaf44e66 diff --git a/tests/ref/fate/pcm_dvd-24-5.1-48000 b/tests/ref/fate/pcm_dvd-24-5.1-48000 new file mode 100644 index 000000000..361a2e5ec --- /dev/null +++ b/tests/ref/fate/pcm_dvd-24-5.1-48000 @@ -0,0 +1,94 @@ +131d92cc9349ab808cf60dd0c9ed8df6 *tests/data/fate/pcm_dvd-24-5.1-48000.vob +2519040 tests/data/fate/pcm_dvd-24-5.1-48000.vob +#tb 0: 1/48000 +#media_type 0: audio +#codec_id 0: pcm_s24le +#sample_rate 0: 48000 +#channel_layout_name 0: 5.1 +0, 0, 0, 108, 1944, 0xd474b1dc +0, 112, 112, 112, 2016, 0x7b1a40cc +0, 224, 224, 112, 2016, 0xa5be1eff +0, 336, 336, 108, 1944, 0x8e889bbf +0, 448, 448, 112, 2016, 0x64de154d +0, 560, 560, 112, 2016, 0xd0d98f35 +0, 672, 672, 112, 2016, 0xa607ff3b +0, 784, 784, 108, 1944, 0x3e32521e +0, 896, 896, 112, 2016, 0xc278e708 +0, 1008, 1008, 112, 2016, 0x6228e57a +0, 1120, 1120, 112, 2016, 0xa0fbd56d +0, 1232, 1232, 108, 1944, 0xefa5d55c +0, 1344, 1344, 112, 2016, 0x309900c8 +0, 1456, 1456, 112, 2016, 0x65d5154a +0, 1568, 1568, 112, 2016, 0x7a6777fd +0, 1680, 1680, 108, 1944, 0xeef5828c +0, 1792, 1792, 112, 2016, 0x05e2fe81 +0, 1904, 1904, 112, 2016, 0xaf4a5c67 +0, 2016, 2016, 112, 2016, 0xd881cccd +0, 2128, 2128, 108, 1944, 0xba7358a5 +0, 2240, 2240, 112, 2016, 0x0341f0d2 +0, 2352, 2352, 112, 2016, 0x0d5e2642 +0, 2464, 2464, 112, 2016, 0xc3442415 +0, 2576, 2576, 108, 1944, 0x04e23fa2 +0, 2688, 2688, 112, 2016, 0xbe5d297d +0, 2800, 2800, 112, 2016, 0x36bee2ef +0, 2912, 2912, 112, 2016, 0x5b1fa6bf +0, 2996, 2996, 108, 1944, 0x842993a2 +0, 3108, 3108, 112, 2016, 0xad60830b +0, 3220, 3220, 112, 2016, 0x59de6600 +0, 3332, 3332, 112, 2016, 0xbf6f32f0 +0, 3444, 3444, 108, 1944, 0x7a2d1b23 +0, 3556, 3556, 112, 2016, 0x05755245 +0, 3668, 3668, 112, 2016, 0x6f048e4b +0, 3780, 3780, 112, 2016, 0xbddb7141 +0, 3892, 3892, 108, 1944, 0x27f927c3 +0, 4004, 4004, 112, 2016, 0x1b72043a +0, 4116, 4116, 112, 2016, 0x8196613d +0, 4228, 4228, 112, 2016, 0x582803ae +0, 4340, 4340, 108, 1944, 0xe61b8fef +0, 4452, 4452, 112, 2016, 0xd6c793ac +0, 4564, 4564, 112, 2016, 0x9cd216a8 +0, 4676, 4676, 108, 1944, 0x0329923f +0, 4788, 4788, 112, 2016, 0x389e4741 +0, 4900, 4900, 112, 2016, 0x257b7c1c +0, 5012, 5012, 112, 2016, 0xbd6af710 +0, 5124, 5124, 108, 1944, 0x1b1a08cd +0, 5236, 5236, 112, 2016, 0x7c1c56ab +0, 5348, 5348, 112, 2016, 0x8dd343a2 +0, 5460, 5460, 112, 2016, 0xedef5b90 +0, 5572, 5572, 108, 1944, 0x1cb19fa5 +0, 5684, 5684, 112, 2016, 0x7262409f +0, 5796, 5796, 112, 2016, 0x39fb2f0c +0, 5908, 5908, 112, 2016, 0xfc2e6c94 +0, 5992, 5992, 108, 1944, 0x5ebd2dc3 +0, 6104, 6104, 112, 2016, 0x545aa3cf +0, 6216, 6216, 112, 2016, 0x2ccdb39d +0, 6328, 6328, 112, 2016, 0x1fd639a5 +0, 6440, 6440, 108, 1944, 0x0788a815 +0, 6552, 6552, 112, 2016, 0xe904c713 +0, 6664, 6664, 112, 2016, 0x2451eb77 +0, 6776, 6776, 112, 2016, 0x9cf3d1bf +0, 6888, 6888, 108, 1944, 0x25983223 +0, 7000, 7000, 112, 2016, 0x4e426817 +0, 7112, 7112, 112, 2016, 0x386fe97d +0, 7224, 7224, 112, 2016, 0x20ed0d8d +0, 7336, 7336, 108, 1944, 0xbc097653 +0, 7448, 7448, 112, 2016, 0x6211057e +0, 7560, 7560, 112, 2016, 0x0a0825f3 +0, 7672, 7672, 112, 2016, 0x377e6144 +0, 7784, 7784, 108, 1944, 0xd163ff87 +0, 7896, 7896, 112, 2016, 0xde483afa +0, 8008, 8008, 112, 2016, 0x8b80471f +0, 8120, 8120, 112, 2016, 0x35f27a6d +0, 8232, 8232, 108, 1944, 0xaa224460 +0, 8344, 8344, 112, 2016, 0xda986b7e +0, 8456, 8456, 112, 2016, 0xea5058a6 +0, 8568, 8568, 112, 2016, 0x74be6ed0 +0, 8680, 8680, 108, 1944, 0x0526c60e +0, 8792, 8792, 112, 2016, 0x953f6390 +0, 8904, 8904, 112, 2016, 0xc9cc0d3a +0, 8988, 8988, 108, 1944, 0xef0bc41e +0, 9100, 9100, 112, 2016, 0x2bcb9fff +0, 9212, 9212, 112, 2016, 0x21a51ee9 +0, 9324, 9324, 112, 2016, 0x6cd1f18b +0, 9436, 9436, 108, 1944, 0x40e849a9 +0, 9548, 9548, 52, 936, 0xd668ccc3 diff --git a/tests/ref/fate/pcm_dvd-24-7.1-48000 b/tests/ref/fate/pcm_dvd-24-7.1-48000 new file mode 100644 index 000000000..89c9b43a5 --- /dev/null +++ b/tests/ref/fate/pcm_dvd-24-7.1-48000 @@ -0,0 +1,69 @@ +f3581bf0b1cf291662fc4e087b930c84 *tests/data/fate/pcm_dvd-24-7.1-48000.vob +126976 tests/data/fate/pcm_dvd-24-7.1-48000.vob +#tb 0: 1/48000 +#media_type 0: audio +#codec_id 0: pcm_s24le +#sample_rate 0: 48000 +#channel_layout_name 0: 7.1 +0, 0, 0, 83, 1992, 0x07f25ccf +0, 83, 83, 83, 1992, 0x820309d5 +0, 166, 166, 83, 1992, 0x4f0b1c4f +0, 249, 249, 83, 1992, 0xe6791628 +0, 332, 332, 83, 1992, 0xb498e297 +0, 415, 415, 83, 1992, 0xecb54408 +0, 498, 498, 83, 1992, 0xc9715746 +0, 581, 581, 83, 1992, 0x945481b0 +0, 664, 664, 83, 1992, 0xc3c9a8aa +0, 747, 747, 83, 1992, 0xd2f47523 +0, 830, 830, 83, 1992, 0x2814f450 +0, 913, 913, 83, 1992, 0x6085a1cb +0, 996, 996, 83, 1992, 0x625b2279 +0, 1079, 1079, 83, 1992, 0xc094f133 +0, 1162, 1162, 83, 1992, 0x14a3d1ec +0, 1245, 1245, 83, 1992, 0xfe5fb1c1 +0, 1328, 1328, 83, 1992, 0x84414c88 +0, 1411, 1411, 83, 1992, 0x2e054afe +0, 1494, 1494, 83, 1992, 0xae901ffe +0, 1577, 1577, 83, 1992, 0x2657fa0a +0, 1660, 1660, 83, 1992, 0x09504b60 +0, 1743, 1743, 83, 1992, 0xbae28d8d +0, 1826, 1826, 83, 1992, 0x51a2d108 +0, 1909, 1909, 83, 1992, 0x0d715388 +0, 1992, 1992, 83, 1992, 0x15ee40e6 +0, 2075, 2075, 83, 1992, 0xf9944d76 +0, 2158, 2158, 83, 1992, 0xf018f40e +0, 2241, 2241, 83, 1992, 0xc975e78d +0, 2324, 2324, 83, 1992, 0xf86b634d +0, 2407, 2407, 83, 1992, 0xd3ace8f0 +0, 2490, 2490, 83, 1992, 0xb7b3783d +0, 2573, 2573, 83, 1992, 0x31b996ae +0, 2656, 2656, 83, 1992, 0xcaa8b1d1 +0, 2739, 2739, 83, 1992, 0x9f7d068e +0, 2822, 2822, 83, 1992, 0x3d52215a +0, 2905, 2905, 83, 1992, 0xd9445472 +0, 2988, 2988, 83, 1992, 0xe20bf044 +0, 3071, 3071, 83, 1992, 0xf6d9a9ab +0, 3154, 3154, 83, 1992, 0xe9b1ca93 +0, 3237, 3237, 83, 1992, 0xf704e3ae +0, 3320, 3320, 83, 1992, 0xc765ad45 +0, 3403, 3403, 83, 1992, 0x2408aeb8 +0, 3486, 3486, 83, 1992, 0x7f151863 +0, 3569, 3569, 83, 1992, 0xd3c51b0a +0, 3652, 3652, 83, 1992, 0x2525f59a +0, 3735, 3735, 83, 1992, 0x2e5483a0 +0, 3818, 3818, 83, 1992, 0x20fba8da +0, 3901, 3901, 83, 1992, 0xc58094a4 +0, 3984, 3984, 83, 1992, 0xfc4c12d1 +0, 4067, 4067, 83, 1992, 0x8e9f4033 +0, 4150, 4150, 83, 1992, 0xd71ae1b1 +0, 4233, 4233, 83, 1992, 0x2b2c185d +0, 4316, 4316, 83, 1992, 0x1ae9c95c +0, 4399, 4399, 83, 1992, 0x1cca11d1 +0, 4482, 4482, 83, 1992, 0x4f5a930f +0, 4565, 4565, 83, 1992, 0xb1944352 +0, 4648, 4648, 83, 1992, 0x027ff599 +0, 4731, 4731, 83, 1992, 0x024a65de +0, 4814, 4814, 83, 1992, 0x06559979 +0, 4897, 4897, 83, 1992, 0x335591ad +0, 4980, 4980, 83, 1992, 0x29e3dfd2 +0, 5063, 5063, 57, 1368, 0xd8c3d35e diff --git a/tests/ref/fate/pmp-demux b/tests/ref/fate/pmp-demux index 5c51b8b45..90475e398 100644 --- a/tests/ref/fate/pmp-demux +++ b/tests/ref/fate/pmp-demux @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: mp3 #sample_rate 0: 44100 -#channel_layout 0: 3 #channel_layout_name 0: stereo 0, 0, 0, 1152, 417, 0xcb873fba 0, 1152, 1152, 1152, 104, 0x6d521c5a diff --git a/tests/ref/fate/png-icc b/tests/ref/fate/png-icc new file mode 100644 index 000000000..542bb76f9 --- /dev/null +++ b/tests/ref/fate/png-icc @@ -0,0 +1,43 @@ +a50d37a0e72bddea2fcbba6fb773e2a0 *tests/data/fate/png-icc.image2 +49397 tests/data/fate/png-icc.image2 +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 128x128 +#sar 0: 2835/2835 +0, 0, 0, 1, 49152, 0xe0013dee +[FRAME] +media_type=video +stream_index=0 +key_frame=1 +pts=0 +pts_time=0.000000 +pkt_dts=0 +pkt_dts_time=0.000000 +best_effort_timestamp=0 +best_effort_timestamp_time=0.000000 +pkt_duration=1 +pkt_duration_time=0.040000 +pkt_pos=0 +pkt_size=49397 +width=128 +height=128 +pix_fmt=rgb24 +sample_aspect_ratio=1:1 +pict_type=I +coded_picture_number=0 +display_picture_number=0 +interlaced_frame=0 +top_field_first=0 +repeat_pict=0 +color_range=pc +color_space=unknown +color_primaries=unknown +color_transfer=unknown +chroma_location=unspecified +[SIDE_DATA] +side_data_type=ICC profile +name=Photoshop ICC profile +size=3144 +[/SIDE_DATA] +[/FRAME] diff --git a/tests/ref/fate/prores-gray b/tests/ref/fate/prores-gray index a1a63fa94..08fcf2473 100644 --- a/tests/ref/fate/prores-gray +++ b/tests/ref/fate/prores-gray @@ -7,7 +7,6 @@ #media_type 1: audio #codec_id 1: pcm_s16le #sample_rate 1: 48000 -#channel_layout 1: 3 #channel_layout_name 1: stereo 0, 0, 0, 1, 1658880, 0x43d9c9e2 1, 0, 0, 1024, 4096, 0x6c8a9a18 diff --git a/tests/ref/fate/prores-transparency b/tests/ref/fate/prores-transparency index 4e8815283..246e0b26a 100644 --- a/tests/ref/fate/prores-transparency +++ b/tests/ref/fate/prores-transparency @@ -7,7 +7,6 @@ #media_type 1: audio #codec_id 1: pcm_s16le #sample_rate 1: 48000 -#channel_layout 1: 3 #channel_layout_name 1: stereo 0, 0, 0, 1, 16588800, 0xcfb3d806 1, 0, 0, 1024, 4096, 0x00000000 diff --git a/tests/ref/fate/prores-transparency_skip b/tests/ref/fate/prores-transparency_skip index 82c180d17..3f5fa0a13 100644 --- a/tests/ref/fate/prores-transparency_skip +++ b/tests/ref/fate/prores-transparency_skip @@ -7,7 +7,6 @@ #media_type 1: audio #codec_id 1: pcm_s16le #sample_rate 1: 48000 -#channel_layout 1: 3 #channel_layout_name 1: stereo 0, 0, 0, 1, 12441600, 0x74f53304 1, 0, 0, 1024, 4096, 0x00000000 diff --git a/tests/ref/fate/psx-str-demux b/tests/ref/fate/psx-str-demux index a47c86952..18a21b0bb 100644 --- a/tests/ref/fate/psx-str-demux +++ b/tests/ref/fate/psx-str-demux @@ -7,7 +7,6 @@ #media_type 1: audio #codec_id 1: adpcm_xa #sample_rate 1: 37800 -#channel_layout 1: 3 #channel_layout_name 1: stereo 0, 0, 0, 1, 8832, 0x01ad3eeb 1, 0, 0, 1, 2304, 0xf0ad1000 diff --git a/tests/ref/fate/pva-demux b/tests/ref/fate/pva-demux index 3f1c74f36..5c0e1c1ea 100644 --- a/tests/ref/fate/pva-demux +++ b/tests/ref/fate/pva-demux @@ -7,7 +7,6 @@ #media_type 1: audio #codec_id 1: mp2 #sample_rate 1: 48000 -#channel_layout 1: 3 #channel_layout_name 1: stereo 1, 0, 0, 2160, 384, 0x071abcc8 1, 2160, 2160, 2160, 384, 0x31c9aee0 diff --git a/tests/ref/fate/ra3-144 b/tests/ref/fate/ra3-144 index 75e7bbfc7..3068227cb 100644 --- a/tests/ref/fate/ra3-144 +++ b/tests/ref/fate/ra3-144 @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 8000 -#channel_layout 0: 4 #channel_layout_name 0: mono 0, 0, 0, 160, 320, 0x00000000 0, 160, 160, 160, 320, 0x4cfd5d74 diff --git a/tests/ref/fate/redcode-demux b/tests/ref/fate/redcode-demux index 45119ec71..4815a8b8c 100644 --- a/tests/ref/fate/redcode-demux +++ b/tests/ref/fate/redcode-demux @@ -7,7 +7,6 @@ #media_type 1: audio #codec_id 1: pcm_s32be #sample_rate 1: 48000 -#channel_layout 1: 4 #channel_layout_name 1: mono 0, 0, 0, 10010, 1626280, 0x5768c7d6 1, 0, 0, 18140, 14816, 0xd185e8c7 diff --git a/tests/ref/fate/rgb24-mkv b/tests/ref/fate/rgb24-mkv index 1ef70349b..f2cff5ff9 100644 --- a/tests/ref/fate/rgb24-mkv +++ b/tests/ref/fate/rgb24-mkv @@ -1,5 +1,5 @@ -6244b8750d4155d3c9357bab26396ef9 *tests/data/fate/rgb24-mkv.matroska -58245 tests/data/fate/rgb24-mkv.matroska +a46cb669137f18ac0a42012485e5e863 *tests/data/fate/rgb24-mkv.matroska +58211 tests/data/fate/rgb24-mkv.matroska #tb 0: 1/10 #media_type 0: video #codec_id 0: rawvideo diff --git a/tests/ref/fate/s337m-demux b/tests/ref/fate/s337m-demux index 2857c65ae..42ef4df27 100644 --- a/tests/ref/fate/s337m-demux +++ b/tests/ref/fate/s337m-demux @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: dolby_e #sample_rate 0: 44800 -#channel_layout 0: 60f #channel_layout_name 0: 5.1(side) 0, 0, 0, 3600, 7664, 0x7e73f2fd 0, 3600, 3600, 3600, 7664, 0x8b980ec8 diff --git a/tests/ref/fate/segment-adts-to-mkv-header-000 b/tests/ref/fate/segment-adts-to-mkv-header-000 index 294aa2346..91729811f 100644 --- a/tests/ref/fate/segment-adts-to-mkv-header-000 +++ b/tests/ref/fate/segment-adts-to-mkv-header-000 @@ -3,7 +3,6 @@ #media_type 0: audio #codec_id 0: aac #sample_rate 0: 16000 -#channel_layout 0: 4 #channel_layout_name 0: mono 0, 0, 0, 64, 4, 0x02f70117 0, 64, 64, 64, 163, 0xd5f85007 diff --git a/tests/ref/fate/segment-adts-to-mkv-header-001 b/tests/ref/fate/segment-adts-to-mkv-header-001 index ec4669f12..e24282e3e 100644 --- a/tests/ref/fate/segment-adts-to-mkv-header-001 +++ b/tests/ref/fate/segment-adts-to-mkv-header-001 @@ -3,7 +3,6 @@ #media_type 0: audio #codec_id 0: aac #sample_rate 0: 16000 -#channel_layout 0: 4 #channel_layout_name 0: mono 0, 0, 0, 64, 153, 0xbb6e432f 0, 64, 64, 64, 185, 0xa01f4ff3 diff --git a/tests/ref/fate/segment-adts-to-mkv-header-002 b/tests/ref/fate/segment-adts-to-mkv-header-002 index 06df82456..fc42d8ad0 100644 --- a/tests/ref/fate/segment-adts-to-mkv-header-002 +++ b/tests/ref/fate/segment-adts-to-mkv-header-002 @@ -3,7 +3,6 @@ #media_type 0: audio #codec_id 0: aac #sample_rate 0: 16000 -#channel_layout 0: 4 #channel_layout_name 0: mono 0, 0, 0, 64, 156, 0x867d4f3a 0, 64, 64, 64, 201, 0x62745ff9 diff --git a/tests/ref/fate/segment-adts-to-mkv-header-all b/tests/ref/fate/segment-adts-to-mkv-header-all index 9c78d3347..dd2ec9a99 100644 --- a/tests/ref/fate/segment-adts-to-mkv-header-all +++ b/tests/ref/fate/segment-adts-to-mkv-header-all @@ -3,7 +3,6 @@ #media_type 0: audio #codec_id 0: aac #sample_rate 0: 16000 -#channel_layout 0: 4 #channel_layout_name 0: mono 0, 0, 0, 64, 4, 0x02f70117 0, 64, 64, 64, 163, 0xd5f85007 diff --git a/tests/ref/fate/shortest b/tests/ref/fate/shortest index 64b5bed31..a527bfd54 100644 --- a/tests/ref/fate/shortest +++ b/tests/ref/fate/shortest @@ -7,7 +7,6 @@ #media_type 1: audio #codec_id 1: ac3 #sample_rate 1: 44100 -#channel_layout 1: 4 #channel_layout_name 1: mono 1, -256, -256, 1536, 416, 0xef8ccbe3 0, 0, 0, 1, 8749, 0x57039d10, S=1, 8 diff --git a/tests/ref/fate/sierra-vmd-audio b/tests/ref/fate/sierra-vmd-audio index 9c0e6b2db..7bed6e64a 100644 --- a/tests/ref/fate/sierra-vmd-audio +++ b/tests/ref/fate/sierra-vmd-audio @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 22050 -#channel_layout 0: 4 #channel_layout_name 0: mono 0, 0, 0, 61740, 123480, 0x3a794c13 0, 61740, 61740, 2205, 4410, 0x109d04e0 diff --git a/tests/ref/fate/siff-demux b/tests/ref/fate/siff-demux index f8e989793..a6d47cee6 100644 --- a/tests/ref/fate/siff-demux +++ b/tests/ref/fate/siff-demux @@ -7,7 +7,6 @@ #media_type 1: audio #codec_id 1: pcm_u8 #sample_rate 1: 22050 -#channel_layout 1: 4 #channel_layout_name 1: mono 0, 0, 0, 1, 15152, 0x14fc0f1f 1, 0, 0, 22050, 22050, 0xa7d60d27 diff --git a/tests/ref/fate/smacker-audio b/tests/ref/fate/smacker-audio index 6b867874d..4703501bc 100644 --- a/tests/ref/fate/smacker-audio +++ b/tests/ref/fate/smacker-audio @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: pcm_s16le #sample_rate 0: 22050 -#channel_layout 0: 4 #channel_layout_name 0: mono 0, 0, 0, 23620, 47240, 0x9974897c 0, 23620, 23620, 1564, 3128, 0x7e4064b4 diff --git a/tests/ref/fate/smjpeg-demux b/tests/ref/fate/smjpeg-demux index cb2da6909..e394f3839 100644 --- a/tests/ref/fate/smjpeg-demux +++ b/tests/ref/fate/smjpeg-demux @@ -7,7 +7,6 @@ #media_type 1: audio #codec_id 1: adpcm_ima_smjpeg #sample_rate 1: 22050 -#channel_layout 1: 4 #channel_layout_name 1: mono 0, 0, 0, 111, 734, 0x5a042c2c 1, 0, 0, 23, 260, 0x00000000 diff --git a/tests/ref/fate/source b/tests/ref/fate/source index 69dcdc4f2..16ea7ef9c 100644 --- a/tests/ref/fate/source +++ b/tests/ref/fate/source @@ -8,6 +8,7 @@ libavcodec/reverse.c libavdevice/file_open.c libavdevice/reverse.c libavfilter/af_arnndn.c +libavfilter/file_open.c libavfilter/log2_tab.c libavformat/file_open.c libavformat/golomb_tab.c diff --git a/tests/ref/fate/sp5x b/tests/ref/fate/sp5x index 2ca79815e..6b8fbfc3d 100644 --- a/tests/ref/fate/sp5x +++ b/tests/ref/fate/sp5x @@ -7,7 +7,6 @@ #media_type 1: audio #codec_id 1: pcm_s16le #sample_rate 1: 8000 -#channel_layout 1: 4 #channel_layout_name 1: mono 0, 0, 0, 1, 115200, 0x8ebcb7f8 1, 0, 0, 1024, 2048, 0x366ee71c diff --git a/tests/ref/fate/sws-yuv-colorspace b/tests/ref/fate/sws-yuv-colorspace new file mode 100644 index 000000000..bcf3c4b89 --- /dev/null +++ b/tests/ref/fate/sws-yuv-colorspace @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 352x288 +#sar 0: 0/1 +0, 0, 0, 1, 152064, 0xcbcb97b9 diff --git a/tests/ref/fate/sws-yuv-range b/tests/ref/fate/sws-yuv-range new file mode 100644 index 000000000..5b6f93b22 --- /dev/null +++ b/tests/ref/fate/sws-yuv-range @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 352x288 +#sar 0: 0/1 +0, 0, 0, 1, 152064, 0xe75c71a9 diff --git a/tests/ref/fate/tiertex-seq b/tests/ref/fate/tiertex-seq index 1db906ad3..8bd0b5053 100644 --- a/tests/ref/fate/tiertex-seq +++ b/tests/ref/fate/tiertex-seq @@ -7,7 +7,6 @@ #media_type 1: audio #codec_id 1: pcm_s16le #sample_rate 1: 22050 -#channel_layout 1: 4 #channel_layout_name 1: mono 1, 0, 0, 882, 1764, 0x00000000 1, 882, 882, 882, 1764, 0x80a253d9 diff --git a/tests/ref/fate/time_base b/tests/ref/fate/time_base index 28815d082..fd6cac53f 100644 --- a/tests/ref/fate/time_base +++ b/tests/ref/fate/time_base @@ -1 +1 @@ -78ac0348027b75d73acb8bea14e67a59 +d408aba82d62a90ed7f46a1999b014f1 diff --git a/tests/ref/fate/tmv b/tests/ref/fate/tmv index 09198fab2..ccfaa0d98 100644 --- a/tests/ref/fate/tmv +++ b/tests/ref/fate/tmv @@ -7,7 +7,6 @@ #media_type 1: audio #codec_id 1: pcm_s16le #sample_rate 1: 22058 -#channel_layout 1: 4 #channel_layout_name 1: mono 0, 0, 0, 1, 192000, 0xc698297a 1, 0, 0, 368, 736, 0xf63db497 diff --git a/tests/ref/fate/tscc-15bit b/tests/ref/fate/tscc-15bit index ded8ad43e..be81d891e 100644 --- a/tests/ref/fate/tscc-15bit +++ b/tests/ref/fate/tscc-15bit @@ -7,7 +7,6 @@ #media_type 1: audio #codec_id 1: pcm_s16le #sample_rate 1: 11025 -#channel_layout 1: 4 #channel_layout_name 1: mono 0, 0, 0, 1, 657600, 0x50b3a0c2 1, 0, 0, 11025, 22050, 0x1740aaec diff --git a/tests/ref/fate/vbn-dxt1 b/tests/ref/fate/vbn-dxt1 new file mode 100644 index 000000000..e33d9b63e --- /dev/null +++ b/tests/ref/fate/vbn-dxt1 @@ -0,0 +1,11 @@ +frame:0 pts:0 pts_time:0 +lavfi.psnr.mse.r=36.699280 +lavfi.psnr.psnr.r=32.484230 +lavfi.psnr.mse.g=33.508362 +lavfi.psnr.psnr.g=32.879272 +lavfi.psnr.mse.b=27.947266 +lavfi.psnr.psnr.b=33.667412 +lavfi.psnr.mse.a=21186.988281 +lavfi.psnr.psnr.a=4.870111 +lavfi.psnr.mse_avg=5321.285645 +lavfi.psnr.psnr_avg=10.870638 diff --git a/tests/ref/fate/vbn-dxt5 b/tests/ref/fate/vbn-dxt5 new file mode 100644 index 000000000..ab345d60a --- /dev/null +++ b/tests/ref/fate/vbn-dxt5 @@ -0,0 +1,11 @@ +frame:0 pts:0 pts_time:0 +lavfi.psnr.mse.r=36.699280 +lavfi.psnr.psnr.r=32.484230 +lavfi.psnr.mse.g=33.508362 +lavfi.psnr.psnr.g=32.879272 +lavfi.psnr.mse.b=27.947266 +lavfi.psnr.psnr.b=33.667412 +lavfi.psnr.mse.a=0.000183 +lavfi.psnr.psnr.a=85.503792 +lavfi.psnr.mse_avg=24.538773 +lavfi.psnr.psnr_avg=34.232277 diff --git a/tests/ref/fate/vbn-raw-rgb24 b/tests/ref/fate/vbn-raw-rgb24 new file mode 100644 index 000000000..06143c27b --- /dev/null +++ b/tests/ref/fate/vbn-raw-rgb24 @@ -0,0 +1,9 @@ +frame:0 pts:0 pts_time:0 +lavfi.psnr.mse.r=0.000000 +lavfi.psnr.psnr.r=inf +lavfi.psnr.mse.g=0.000000 +lavfi.psnr.psnr.g=inf +lavfi.psnr.mse.b=0.000000 +lavfi.psnr.psnr.b=inf +lavfi.psnr.mse_avg=0.000000 +lavfi.psnr.psnr_avg=inf diff --git a/tests/ref/fate/vbn-raw-rgba b/tests/ref/fate/vbn-raw-rgba new file mode 100644 index 000000000..4614ab5c2 --- /dev/null +++ b/tests/ref/fate/vbn-raw-rgba @@ -0,0 +1,11 @@ +frame:0 pts:0 pts_time:0 +lavfi.psnr.mse.r=0.000000 +lavfi.psnr.psnr.r=inf +lavfi.psnr.mse.g=0.000000 +lavfi.psnr.psnr.g=inf +lavfi.psnr.mse.b=0.000000 +lavfi.psnr.psnr.b=inf +lavfi.psnr.mse.a=0.000000 +lavfi.psnr.psnr.a=inf +lavfi.psnr.mse_avg=0.000000 +lavfi.psnr.psnr_avg=inf diff --git a/tests/ref/fate/vqf-demux b/tests/ref/fate/vqf-demux index d768ddbb6..2669d8cc1 100644 --- a/tests/ref/fate/vqf-demux +++ b/tests/ref/fate/vqf-demux @@ -1 +1 @@ -5f4cd9a6a8bea0040db6732a7830e9d7 +e42a45601a4a7c39436907c5cdfde5ee diff --git a/tests/ref/fate/wav-ac3 b/tests/ref/fate/wav-ac3 index 039e155da..b20403e61 100644 --- a/tests/ref/fate/wav-ac3 +++ b/tests/ref/fate/wav-ac3 @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: ac3 #sample_rate 0: 44100 -#channel_layout 0: 60f #channel_layout_name 0: 5.1(side) 0, 0, 0, 1536, 2786, 0xe2fd0f40 0, 1536, 1536, 1536, 2786, 0x7a6207c2 diff --git a/tests/ref/fate/wavpack-cuesheet-tags b/tests/ref/fate/wavpack-cuesheet-tags new file mode 100644 index 000000000..be6b694ae --- /dev/null +++ b/tests/ref/fate/wavpack-cuesheet-tags @@ -0,0 +1,98 @@ +[FORMAT] +TAG:Cuesheet=REM GENRE Zydeco/Cajun +REM DATE 1997 +PERFORMER "BeauSoliel" +TITLE "L'Amour ou la Folie" +REM REPLAYGAIN_ALBUM_GAIN -6.54 dB +REM REPLAYGAIN_ALBUM_PEAK 0.972900 +FILE "CDImage.wv" WAVE + TRACK 01 AUDIO + TITLE "Newz Reel" + REM REPLAYGAIN_TRACK_GAIN -6.47 dB + REM REPLAYGAIN_TRACK_PEAK 0.972900 + INDEX 00 00:00:00 + INDEX 01 00:00:32 + TRACK 02 AUDIO + TITLE "Les Blues de Crève de Faim" + REM REPLAYGAIN_TRACK_GAIN -4.56 dB + REM REPLAYGAIN_TRACK_PEAK 0.972900 + INDEX 00 02:18:58 + INDEX 01 02:21:30 + TRACK 03 AUDIO + TITLE "L'Amour ou la Folie" + REM REPLAYGAIN_TRACK_GAIN -7.06 dB + REM REPLAYGAIN_TRACK_PEAK 0.972900 + INDEX 00 06:08:40 + INDEX 01 06:10:47 + TRACK 04 AUDIO + TITLE "It's A Sin To Tell A Lie (C'est un Péché de Dire un Menterie)" + REM REPLAYGAIN_TRACK_GAIN -5.28 dB + REM REPLAYGAIN_TRACK_PEAK 0.972900 + INDEX 00 11:29:30 + INDEX 01 11:31:40 + TRACK 05 AUDIO + TITLE "Eunice Two-Step" + REM REPLAYGAIN_TRACK_GAIN -7.72 dB + REM REPLAYGAIN_TRACK_PEAK 0.972900 + INDEX 00 16:18:13 + INDEX 01 16:21:10 + TRACK 06 AUDIO + TITLE "Charivari" + REM REPLAYGAIN_TRACK_GAIN -5.47 dB + REM REPLAYGAIN_TRACK_PEAK 0.972900 + INDEX 00 20:57:53 + INDEX 01 21:00:37 + TRACK 07 AUDIO + TITLE "Boudreaux" + REM REPLAYGAIN_TRACK_GAIN -4.71 dB + REM REPLAYGAIN_TRACK_PEAK 0.972900 + INDEX 00 26:23:25 + INDEX 01 26:25:65 + TRACK 08 AUDIO + TITLE "Valse à Pop" + REM REPLAYGAIN_TRACK_GAIN -5.20 dB + REM REPLAYGAIN_TRACK_PEAK 0.972900 + INDEX 00 29:25:33 + INDEX 01 29:27:12 + TRACK 09 AUDIO + TITLE "Can't You See (Tu Vas Voir)" + REM REPLAYGAIN_TRACK_GAIN -6.17 dB + REM REPLAYGAIN_TRACK_PEAK 0.972900 + INDEX 00 32:50:25 + INDEX 01 32:53:10 + TRACK 10 AUDIO + TITLE "Les Blues de la Prison" + REM REPLAYGAIN_TRACK_GAIN -5.44 dB + REM REPLAYGAIN_TRACK_PEAK 0.972900 + INDEX 00 35:59:05 + INDEX 01 36:01:62 + TRACK 11 AUDIO + TITLE "Danse Caribe" + REM REPLAYGAIN_TRACK_GAIN -7.46 dB + REM REPLAYGAIN_TRACK_PEAK 0.972900 + INDEX 00 39:26:73 + INDEX 01 39:29:47 + TRACK 12 AUDIO + TITLE "Valse J'Aime" + REM REPLAYGAIN_TRACK_GAIN -7.92 dB + REM REPLAYGAIN_TRACK_PEAK 0.972900 + INDEX 00 43:35:25 + INDEX 01 43:38:15 + TRACK 13 AUDIO + TITLE "Courir avec Walker" + REM REPLAYGAIN_TRACK_GAIN -5.19 dB + REM REPLAYGAIN_TRACK_PEAK 0.972900 + INDEX 00 47:30:05 + INDEX 01 47:32:70 + TRACK 14 AUDIO + TITLE "Ma Vie S'est Arrêtée" + REM REPLAYGAIN_TRACK_GAIN -5.60 dB + REM REPLAYGAIN_TRACK_PEAK 0.972900 + INDEX 00 51:31:08 + INDEX 01 51:33:72 + +TAG:Artist=BeauSoliel +TAG:Album=L'Amour ou la Folie +TAG:Year=1997 +TAG:Genre=Zydeco/Cajun +[/FORMAT] diff --git a/tests/ref/fate/wc3movie-xan b/tests/ref/fate/wc3movie-xan index 052dbbce7..4acb0a3b5 100644 --- a/tests/ref/fate/wc3movie-xan +++ b/tests/ref/fate/wc3movie-xan @@ -7,7 +7,6 @@ #media_type 1: audio #codec_id 1: pcm_s16le #sample_rate 1: 22050 -#channel_layout 1: 4 #channel_layout_name 1: mono 0, 0, 0, 1, 158400, 0x25aec781 1, 0, 0, 1470, 2940, 0x92cee2a6 diff --git a/tests/ref/fate/webm-dash-chapters b/tests/ref/fate/webm-dash-chapters index c04fc6a3e..9444824c4 100644 --- a/tests/ref/fate/webm-dash-chapters +++ b/tests/ref/fate/webm-dash-chapters @@ -1,11 +1,10 @@ -c39ad75ef516d1d2e1332d960ad1057b *tests/data/fate/webm-dash-chapters.webm -111239 tests/data/fate/webm-dash-chapters.webm +aa3ca15fae0239d6bf67fa0658a8bc3b *tests/data/fate/webm-dash-chapters.webm +111150 tests/data/fate/webm-dash-chapters.webm #extradata 0: 3469, 0xc6769ddc #tb 0: 1/1000 #media_type 0: audio #codec_id 0: vorbis #sample_rate 0: 44100 -#channel_layout 0: 4 #channel_layout_name 0: mono 0, 0, 0, 5, 28, 0xefcf103e 0, 6, 6, 26, 198, 0xfbbe5eb5 diff --git a/tests/ref/fate/webm-dash-manifest b/tests/ref/fate/webm-dash-manifest index f5fc9121d..3a557fc39 100644 --- a/tests/ref/fate/webm-dash-manifest +++ b/tests/ref/fate/webm-dash-manifest @@ -6,7 +6,7 @@ type="static" mediaPresentationDuration="PT32.501S" minBufferTime="PT1S" - profiles="urn:webm:dash:profile:webm-on-demand:2012"> + profiles="urn:mpeg:dash:profile:webm-on-demand:2012"> diff --git a/tests/ref/fate/webm-dash-manifest-representations b/tests/ref/fate/webm-dash-manifest-representations index 8556ecebe..41713bb36 100644 --- a/tests/ref/fate/webm-dash-manifest-representations +++ b/tests/ref/fate/webm-dash-manifest-representations @@ -6,7 +6,7 @@ type="static" mediaPresentationDuration="PT32.48S" minBufferTime="PT1S" - profiles="urn:webm:dash:profile:webm-on-demand:2012"> + profiles="urn:mpeg:dash:profile:webm-on-demand:2012"> diff --git a/tests/ref/fate/webm-dash-manifest-unaligned-audio-streams b/tests/ref/fate/webm-dash-manifest-unaligned-audio-streams index 6e9de211f..b1bc7ecea 100644 --- a/tests/ref/fate/webm-dash-manifest-unaligned-audio-streams +++ b/tests/ref/fate/webm-dash-manifest-unaligned-audio-streams @@ -6,7 +6,7 @@ type="static" mediaPresentationDuration="PT32.501S" minBufferTime="PT1S" - profiles="urn:webm:dash:profile:webm-on-demand:2012"> + profiles="urn:mpeg:dash:profile:webm-on-demand:2012"> diff --git a/tests/ref/fate/webm-dash-manifest-unaligned-video-streams b/tests/ref/fate/webm-dash-manifest-unaligned-video-streams index ce205638b..690c2aabe 100644 --- a/tests/ref/fate/webm-dash-manifest-unaligned-video-streams +++ b/tests/ref/fate/webm-dash-manifest-unaligned-video-streams @@ -6,7 +6,7 @@ type="static" mediaPresentationDuration="PT32.48S" minBufferTime="PT1S" - profiles="urn:webm:dash:profile:webm-on-demand:2012"> + profiles="urn:mpeg:dash:profile:webm-on-demand:2012"> diff --git a/tests/ref/fate/webm-webvtt-remux b/tests/ref/fate/webm-webvtt-remux index 15e919d74..88def03db 100644 --- a/tests/ref/fate/webm-webvtt-remux +++ b/tests/ref/fate/webm-webvtt-remux @@ -1,5 +1,5 @@ -c5625f28e6968e12d91f125edef5f16c *tests/data/fate/webm-webvtt-remux.webm -6560 tests/data/fate/webm-webvtt-remux.webm +0b43695bf27bbe48ea44e969d8908e1f *tests/data/fate/webm-webvtt-remux.webm +6528 tests/data/fate/webm-webvtt-remux.webm #tb 0: 1/1000 #media_type 0: subtitle #codec_id 0: webvtt diff --git a/tests/ref/fate/westwood-aud b/tests/ref/fate/westwood-aud index b719c50a4..cc9d1f046 100644 --- a/tests/ref/fate/westwood-aud +++ b/tests/ref/fate/westwood-aud @@ -2,7 +2,6 @@ #media_type 0: audio #codec_id 0: adpcm_ima_ws #sample_rate 0: 22050 -#channel_layout 0: 4 #channel_layout_name 0: mono 0, 0, 0, 1024, 512, 0x6694cc55 0, 1024, 1024, 1024, 512, 0xdbc5cb22 diff --git a/tests/ref/fate/wmv3-drm-nodec b/tests/ref/fate/wmv3-drm-nodec index a46c338d5..9ed8bc857 100644 --- a/tests/ref/fate/wmv3-drm-nodec +++ b/tests/ref/fate/wmv3-drm-nodec @@ -9,7 +9,6 @@ #media_type 1: audio #codec_id 1: wmavoice #sample_rate 1: 22050 -#channel_layout 1: 4 #channel_layout_name 1: mono 0, 0, 0, 0, 282, 0x000d949a 1, 0, 0, 0, 1088, 0x5cd379bb diff --git a/tests/ref/fate/wtv-demux b/tests/ref/fate/wtv-demux index abe85a4ab..5d1a02fc6 100644 --- a/tests/ref/fate/wtv-demux +++ b/tests/ref/fate/wtv-demux @@ -9,7 +9,6 @@ #media_type 1: audio #codec_id 1: mp2 #sample_rate 1: 48000 -#channel_layout 1: 3 #channel_layout_name 1: stereo 1, -2, -2, 240000, 576, 0x9b6e1638 1, 239998, 239998, 240000, 576, 0x0ca91183 diff --git a/tests/ref/fate/xmv-demux b/tests/ref/fate/xmv-demux index 6da2b1a70..9cc26e41c 100644 --- a/tests/ref/fate/xmv-demux +++ b/tests/ref/fate/xmv-demux @@ -8,7 +8,6 @@ #media_type 1: audio #codec_id 1: adpcm_ima_wav #sample_rate 1: 44100 -#channel_layout 1: 3 #channel_layout_name 1: stereo 0, 0, 0, 0, 1508, 0xefceba48 1, 0, 0, 83, 5976, 0xfa2c2db9 diff --git a/tests/ref/lavf-fate/av1.mkv b/tests/ref/lavf-fate/av1.mkv index 454aef53f..2008e1a93 100644 --- a/tests/ref/lavf-fate/av1.mkv +++ b/tests/ref/lavf-fate/av1.mkv @@ -1,3 +1,3 @@ -61e66b67c0c38532f6c6edc8c9d32e48 *tests/data/lavf-fate/lavf.av1.mkv -55656 tests/data/lavf-fate/lavf.av1.mkv +72a4713f9165c73574d40e8b81c5d70f *tests/data/lavf-fate/lavf.av1.mkv +55642 tests/data/lavf-fate/lavf.av1.mkv tests/data/lavf-fate/lavf.av1.mkv CRC=0x7c27cc15 diff --git a/tests/ref/lavf/gbrpf32be.pfm b/tests/ref/lavf/gbrpf32be.pfm new file mode 100644 index 000000000..2cd635440 --- /dev/null +++ b/tests/ref/lavf/gbrpf32be.pfm @@ -0,0 +1,3 @@ +6d470f8d6018b95b45afafc14b7d161a *tests/data/images/gbrpf32be.pfm/02.gbrpf32be.pfm +tests/data/images/gbrpf32be.pfm/%02d.gbrpf32be.pfm CRC=0x4b73053f +1216532 tests/data/images/gbrpf32be.pfm/02.gbrpf32be.pfm diff --git a/tests/ref/lavf/gbrpf32le.pfm b/tests/ref/lavf/gbrpf32le.pfm new file mode 100644 index 000000000..3ddd10044 --- /dev/null +++ b/tests/ref/lavf/gbrpf32le.pfm @@ -0,0 +1,3 @@ +892c5a05e1cbb3d2f7761d51e18b9c4c *tests/data/images/gbrpf32le.pfm/02.gbrpf32le.pfm +tests/data/images/gbrpf32le.pfm/%02d.gbrpf32le.pfm CRC=0x95e1053f +1216533 tests/data/images/gbrpf32le.pfm/02.gbrpf32le.pfm diff --git a/tests/ref/lavf/grayf32be.pfm b/tests/ref/lavf/grayf32be.pfm new file mode 100644 index 000000000..05614a0f5 --- /dev/null +++ b/tests/ref/lavf/grayf32be.pfm @@ -0,0 +1,3 @@ +0f6df0d68d7dd30e67386b1255f443c9 *tests/data/images/grayf32be.pfm/02.grayf32be.pfm +tests/data/images/grayf32be.pfm/%02d.grayf32be.pfm CRC=0xe3fda443 +405524 tests/data/images/grayf32be.pfm/02.grayf32be.pfm diff --git a/tests/ref/lavf/grayf32le.pfm b/tests/ref/lavf/grayf32le.pfm new file mode 100644 index 000000000..a419daa65 --- /dev/null +++ b/tests/ref/lavf/grayf32le.pfm @@ -0,0 +1,3 @@ +145715872a894b1fde0105d8a0106191 *tests/data/images/grayf32le.pfm/02.grayf32le.pfm +tests/data/images/grayf32le.pfm/%02d.grayf32le.pfm CRC=0x5443a443 +405525 tests/data/images/grayf32le.pfm/02.grayf32le.pfm diff --git a/tests/ref/lavf/mka b/tests/ref/lavf/mka index 9c0ec8863..7af63e077 100644 --- a/tests/ref/lavf/mka +++ b/tests/ref/lavf/mka @@ -1,3 +1,3 @@ -52d2c70afe0f9ac510819f723b5ceb3b *tests/data/lavf/lavf.mka -43583 tests/data/lavf/lavf.mka +e2d55cd3844fd7237a92181dbbcb08d9 *tests/data/lavf/lavf.mka +43569 tests/data/lavf/lavf.mka tests/data/lavf/lavf.mka CRC=0x3a1da17e diff --git a/tests/ref/lavf/mkv b/tests/ref/lavf/mkv index 6e517efed..d9497a0a6 100644 --- a/tests/ref/lavf/mkv +++ b/tests/ref/lavf/mkv @@ -1,3 +1,3 @@ -c1af29ab33c9477049672b62da221552 *tests/data/lavf/lavf.mkv -320438 tests/data/lavf/lavf.mkv +17e637fc06015fea86428840418ffea2 *tests/data/lavf/lavf.mkv +320403 tests/data/lavf/lavf.mkv tests/data/lavf/lavf.mkv CRC=0xec6c3c68 diff --git a/tests/ref/lavf/mkv_attachment b/tests/ref/lavf/mkv_attachment index 86ba4180c..a8cc075bf 100644 --- a/tests/ref/lavf/mkv_attachment +++ b/tests/ref/lavf/mkv_attachment @@ -1,3 +1,3 @@ -a669ae1a502ff0c487eee99753e7bef0 *tests/data/lavf/lavf.mkv_attachment -472593 tests/data/lavf/lavf.mkv_attachment +3855fb336711517b32b0ec41e8505b4d *tests/data/lavf/lavf.mkv_attachment +472553 tests/data/lavf/lavf.mkv_attachment tests/data/lavf/lavf.mkv_attachment CRC=0xec6c3c68 diff --git a/tests/ref/lavf/mp4 b/tests/ref/lavf/mp4 index 0becfd34f..b05fa34d0 100644 --- a/tests/ref/lavf/mp4 +++ b/tests/ref/lavf/mp4 @@ -1,9 +1,9 @@ -71c4ff2e747fe6f8169ff29244fe181d *tests/data/lavf/lavf.mp4 +a6e44724cab1c4b50c49b0fd227b87d3 *tests/data/lavf/lavf.mp4 312477 tests/data/lavf/lavf.mp4 tests/data/lavf/lavf.mp4 CRC=0x9d9a638a -3c5734ad6d05e4afc2ccefef1385e882 *tests/data/lavf/lavf.mp4 +19cbdb02f2f3e35bae779e2323be1b8e *tests/data/lavf/lavf.mp4 321363 tests/data/lavf/lavf.mp4 tests/data/lavf/lavf.mp4 CRC=0xe8130120 -07348e31d11d92396e1eedc48ea14802 *tests/data/lavf/lavf.mp4 +8ab9dd09f02b6d8146a40fc3c918d979 *tests/data/lavf/lavf.mp4 312021 tests/data/lavf/lavf.mp4 tests/data/lavf/lavf.mp4 CRC=0x9d9a638a diff --git a/tests/ref/lavf/mxf b/tests/ref/lavf/mxf index 21bf2be51..3f0c74818 100644 --- a/tests/ref/lavf/mxf +++ b/tests/ref/lavf/mxf @@ -1,9 +1,9 @@ -8938d5c4a396ff1b24d10d4f917ae1c9 *tests/data/lavf/lavf.mxf +9ec1ad83b3400de11ca2f70b3b2d4c4d *tests/data/lavf/lavf.mxf 526393 tests/data/lavf/lavf.mxf tests/data/lavf/lavf.mxf CRC=0x8dddfaab -93ea2cfdf5dda7fffdc0d2fdcfb6a9a4 *tests/data/lavf/lavf.mxf +546eb8c864c0d76c6a9d5303701e9031 *tests/data/lavf/lavf.mxf 561721 tests/data/lavf/lavf.mxf tests/data/lavf/lavf.mxf CRC=0x96ff1b48 -87bdf844ae34bcc758e44419e80177a0 *tests/data/lavf/lavf.mxf +5bd0ce691510e6fae969886c32ad7a14 *tests/data/lavf/lavf.mxf 526393 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 47ef244cb..4644c3424 100644 --- a/tests/ref/lavf/mxf_d10 +++ b/tests/ref/lavf/mxf_d10 @@ -1,3 +1,3 @@ -7f16902e28718c2a92bc082400a1c6ee *tests/data/lavf/lavf.mxf_d10 +74269c0a64b19269b127f64f3ce7fa6a *tests/data/lavf/lavf.mxf_d10 5332013 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 92509cf1f..5022f1f62 100644 --- a/tests/ref/lavf/mxf_dv25 +++ b/tests/ref/lavf/mxf_dv25 @@ -1,3 +1,3 @@ -106e33eb1634595623f0334e92204b65 *tests/data/lavf/lavf.mxf_dv25 +3339def72599c79ad5860c6860cc3123 *tests/data/lavf/lavf.mxf_dv25 3834413 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 2d569b055..5be1b6875 100644 --- a/tests/ref/lavf/mxf_dvcpro50 +++ b/tests/ref/lavf/mxf_dvcpro50 @@ -1,3 +1,3 @@ -3d5a303c22666996700f0e8f6e4cb938 *tests/data/lavf/lavf.mxf_dvcpro50 +8494122b2a8e8e5998ace60d4d508d46 *tests/data/lavf/lavf.mxf_dvcpro50 7431213 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 e34cf2559..75f85b604 100644 --- a/tests/ref/lavf/mxf_opatom +++ b/tests/ref/lavf/mxf_opatom @@ -1,3 +1,3 @@ -aab6397829bd90f0c77a3f9fde53bb9c *tests/data/lavf/lavf.mxf_opatom +215ea72602bfeb70e99fc9d79fef073c *tests/data/lavf/lavf.mxf_opatom 4717625 tests/data/lavf/lavf.mxf_opatom -tests/data/lavf/lavf.mxf_opatom CRC=0xf55aa22a +tests/data/lavf/lavf.mxf_opatom CRC=0xb13ba2f8 diff --git a/tests/ref/lavf/mxf_opatom_audio b/tests/ref/lavf/mxf_opatom_audio index 97362e7aa..0e034991c 100644 --- a/tests/ref/lavf/mxf_opatom_audio +++ b/tests/ref/lavf/mxf_opatom_audio @@ -1,3 +1,3 @@ -c356a3fdd49a1e015961678e837c12bb *tests/data/lavf/lavf.mxf_opatom_audio +633b6d373009416f214edcf456208580 *tests/data/lavf/lavf.mxf_opatom_audio 102969 tests/data/lavf/lavf.mxf_opatom_audio tests/data/lavf/lavf.mxf_opatom_audio CRC=0xd155c6ff diff --git a/tests/ref/lavf/none.gbrapf32le.exr b/tests/ref/lavf/none.gbrapf32le.exr new file mode 100644 index 000000000..3250be2cc --- /dev/null +++ b/tests/ref/lavf/none.gbrapf32le.exr @@ -0,0 +1,3 @@ +c586035e67f9ba7f2a3777933b5b22a0 *tests/data/images/none.gbrapf32le.exr/02.none.gbrapf32le.exr +tests/data/images/none.gbrapf32le.exr/%02d.none.gbrapf32le.exr CRC=0x068aca4e +1627003 tests/data/images/none.gbrapf32le.exr/02.none.gbrapf32le.exr diff --git a/tests/ref/lavf/none.gbrpf32le.exr b/tests/ref/lavf/none.gbrpf32le.exr new file mode 100644 index 000000000..41c43e372 --- /dev/null +++ b/tests/ref/lavf/none.gbrpf32le.exr @@ -0,0 +1,3 @@ +10f42423c6585fe5053c5457fba7b235 *tests/data/images/none.gbrpf32le.exr/02.none.gbrpf32le.exr +tests/data/images/none.gbrpf32le.exr/%02d.none.gbrpf32le.exr CRC=0x95e1053f +1221481 tests/data/images/none.gbrpf32le.exr/02.none.gbrpf32le.exr diff --git a/tests/ref/lavf/none.grayf32le.exr b/tests/ref/lavf/none.grayf32le.exr new file mode 100644 index 000000000..19ab9a2d2 --- /dev/null +++ b/tests/ref/lavf/none.grayf32le.exr @@ -0,0 +1,3 @@ +8aa28b10bf2591b7030b78bc29907293 *tests/data/images/none.grayf32le.exr/02.none.grayf32le.exr +tests/data/images/none.grayf32le.exr/%02d.none.grayf32le.exr CRC=0x5443a443 +410437 tests/data/images/none.grayf32le.exr/02.none.grayf32le.exr diff --git a/tests/ref/lavf/peak_only.wav b/tests/ref/lavf/peak_only.wav index c468731b0..9548e639f 100644 --- a/tests/ref/lavf/peak_only.wav +++ b/tests/ref/lavf/peak_only.wav @@ -1,3 +1,2 @@ f1a8aeeae8069f3992c4d780436c3d23 *tests/data/lavf/lavf.peak_only.wav 832 tests/data/lavf/lavf.peak_only.wav -tests/data/lavf/lavf.peak_only.wav diff --git a/tests/ref/lavf/qoi b/tests/ref/lavf/qoi new file mode 100644 index 000000000..11cd832b9 --- /dev/null +++ b/tests/ref/lavf/qoi @@ -0,0 +1,3 @@ +3887a856d13f6444e213e9e268d58d55 *tests/data/images/qoi/02.qoi +tests/data/images/qoi/%02d.qoi CRC=0x6da01946 +307658 tests/data/images/qoi/02.qoi diff --git a/tests/ref/lavf/rle.gbrapf32le.exr b/tests/ref/lavf/rle.gbrapf32le.exr new file mode 100644 index 000000000..e8093dacc --- /dev/null +++ b/tests/ref/lavf/rle.gbrapf32le.exr @@ -0,0 +1,3 @@ +94398a5ce98bb7b1b78b2b807306f6d7 *tests/data/images/rle.gbrapf32le.exr/02.rle.gbrapf32le.exr +tests/data/images/rle.gbrapf32le.exr/%02d.rle.gbrapf32le.exr CRC=0x068aca4e +1436849 tests/data/images/rle.gbrapf32le.exr/02.rle.gbrapf32le.exr diff --git a/tests/ref/lavf/rle.gbrpf32le.exr b/tests/ref/lavf/rle.gbrpf32le.exr new file mode 100644 index 000000000..beb8bf4a6 --- /dev/null +++ b/tests/ref/lavf/rle.gbrpf32le.exr @@ -0,0 +1,3 @@ +fed878e1f4391314c37088085942e572 *tests/data/images/rle.gbrpf32le.exr/02.rle.gbrpf32le.exr +tests/data/images/rle.gbrpf32le.exr/%02d.rle.gbrpf32le.exr CRC=0x95e1053f +1208298 tests/data/images/rle.gbrpf32le.exr/02.rle.gbrpf32le.exr diff --git a/tests/ref/lavf/rle.grayf32le.exr b/tests/ref/lavf/rle.grayf32le.exr new file mode 100644 index 000000000..883b1d644 --- /dev/null +++ b/tests/ref/lavf/rle.grayf32le.exr @@ -0,0 +1,3 @@ +2841f839cb5aa98bb7aded800dda7cc7 *tests/data/images/rle.grayf32le.exr/02.rle.grayf32le.exr +tests/data/images/rle.grayf32le.exr/%02d.rle.grayf32le.exr CRC=0x5443a443 +410437 tests/data/images/rle.grayf32le.exr/02.rle.grayf32le.exr diff --git a/tests/ref/lavf/zip1.gbrapf32le.exr b/tests/ref/lavf/zip1.gbrapf32le.exr new file mode 100644 index 000000000..7b2f21b89 --- /dev/null +++ b/tests/ref/lavf/zip1.gbrapf32le.exr @@ -0,0 +1,3 @@ +9fca73aac1a2e38969bed55929da48b4 *tests/data/images/zip1.gbrapf32le.exr/02.zip1.gbrapf32le.exr +tests/data/images/zip1.gbrapf32le.exr/%02d.zip1.gbrapf32le.exr CRC=0x068aca4e +902782 tests/data/images/zip1.gbrapf32le.exr/02.zip1.gbrapf32le.exr diff --git a/tests/ref/lavf/zip1.gbrpf32le.exr b/tests/ref/lavf/zip1.gbrpf32le.exr new file mode 100644 index 000000000..a98659114 --- /dev/null +++ b/tests/ref/lavf/zip1.gbrpf32le.exr @@ -0,0 +1,3 @@ +a405ee4328719c53f97d351b5910e82b *tests/data/images/zip1.gbrpf32le.exr/02.zip1.gbrpf32le.exr +tests/data/images/zip1.gbrpf32le.exr/%02d.zip1.gbrpf32le.exr CRC=0x95e1053f +897319 tests/data/images/zip1.gbrpf32le.exr/02.zip1.gbrpf32le.exr diff --git a/tests/ref/lavf/zip1.grayf32le.exr b/tests/ref/lavf/zip1.grayf32le.exr new file mode 100644 index 000000000..b89ceb22d --- /dev/null +++ b/tests/ref/lavf/zip1.grayf32le.exr @@ -0,0 +1,3 @@ +76fe15b4e0b735a6318ca273ff52fb58 *tests/data/images/zip1.grayf32le.exr/02.zip1.grayf32le.exr +tests/data/images/zip1.grayf32le.exr/%02d.zip1.grayf32le.exr CRC=0x5443a443 +91044 tests/data/images/zip1.grayf32le.exr/02.zip1.grayf32le.exr diff --git a/tests/ref/lavf/zip16.gbrapf32le.exr b/tests/ref/lavf/zip16.gbrapf32le.exr new file mode 100644 index 000000000..830ae0fe5 --- /dev/null +++ b/tests/ref/lavf/zip16.gbrapf32le.exr @@ -0,0 +1,3 @@ +8beb8db200e658e74fdd4ed4c4ca9214 *tests/data/images/zip16.gbrapf32le.exr/02.zip16.gbrapf32le.exr +tests/data/images/zip16.gbrapf32le.exr/%02d.zip16.gbrapf32le.exr CRC=0x068aca4e +807513 tests/data/images/zip16.gbrapf32le.exr/02.zip16.gbrapf32le.exr diff --git a/tests/ref/lavf/zip16.gbrpf32le.exr b/tests/ref/lavf/zip16.gbrpf32le.exr new file mode 100644 index 000000000..27fa2a7c5 --- /dev/null +++ b/tests/ref/lavf/zip16.gbrpf32le.exr @@ -0,0 +1,3 @@ +4bc7e2640ea086b7fc31cbcd4fff19f5 *tests/data/images/zip16.gbrpf32le.exr/02.zip16.gbrpf32le.exr +tests/data/images/zip16.gbrpf32le.exr/%02d.zip16.gbrpf32le.exr CRC=0x95e1053f +796693 tests/data/images/zip16.gbrpf32le.exr/02.zip16.gbrpf32le.exr diff --git a/tests/ref/lavf/zip16.grayf32le.exr b/tests/ref/lavf/zip16.grayf32le.exr new file mode 100644 index 000000000..24f82525b --- /dev/null +++ b/tests/ref/lavf/zip16.grayf32le.exr @@ -0,0 +1,3 @@ +5d5def6a4f16cef1122280d80c7c527d *tests/data/images/zip16.grayf32le.exr/02.zip16.grayf32le.exr +tests/data/images/zip16.grayf32le.exr/%02d.zip16.grayf32le.exr CRC=0x5443a443 +63997 tests/data/images/zip16.grayf32le.exr/02.zip16.grayf32le.exr diff --git a/tests/ref/seek/lavf-mkv b/tests/ref/seek/lavf-mkv index fc65b14cd..6b6436780 100644 --- a/tests/ref/seek/lavf-mkv +++ b/tests/ref/seek/lavf-mkv @@ -1,48 +1,48 @@ -ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 686 size: 208 +ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 651 size: 208 ret: 0 st:-1 flags:0 ts:-1.000000 -ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 902 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 867 size: 27837 ret: 0 st:-1 flags:1 ts: 1.894167 -ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292318 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292283 size: 27834 ret: 0 st: 0 flags:0 ts: 0.788000 -ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292318 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292283 size: 27834 ret: 0 st: 0 flags:1 ts:-0.317000 -ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 902 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 867 size: 27837 ret:-1 st: 1 flags:0 ts: 2.577000 ret: 0 st: 1 flags:1 ts: 1.471000 -ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320159 size: 209 +ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320124 size: 209 ret: 0 st:-1 flags:0 ts: 0.365002 -ret: 0 st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146870 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146835 size: 27925 ret: 0 st:-1 flags:1 ts:-0.740831 -ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 902 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 867 size: 27837 ret:-1 st: 0 flags:0 ts: 2.153000 ret: 0 st: 0 flags:1 ts: 1.048000 -ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292318 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292283 size: 27834 ret: 0 st: 1 flags:0 ts:-0.058000 -ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 686 size: 208 +ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 651 size: 208 ret: 0 st: 1 flags:1 ts: 2.836000 -ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320159 size: 209 +ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320124 size: 209 ret:-1 st:-1 flags:0 ts: 1.730004 ret: 0 st:-1 flags:1 ts: 0.624171 -ret: 0 st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146870 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146835 size: 27925 ret: 0 st: 0 flags:0 ts:-0.482000 -ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 902 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 867 size: 27837 ret: 0 st: 0 flags:1 ts: 2.413000 -ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292318 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292283 size: 27834 ret:-1 st: 1 flags:0 ts: 1.307000 ret: 0 st: 1 flags:1 ts: 0.201000 -ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 686 size: 208 +ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 651 size: 208 ret: 0 st:-1 flags:0 ts:-0.904994 -ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 902 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 867 size: 27837 ret: 0 st:-1 flags:1 ts: 1.989173 -ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292318 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292283 size: 27834 ret: 0 st: 0 flags:0 ts: 0.883000 -ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292318 size: 27834 +ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292283 size: 27834 ret: 0 st: 0 flags:1 ts:-0.222000 -ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 902 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 867 size: 27837 ret:-1 st: 1 flags:0 ts: 2.672000 ret: 0 st: 1 flags:1 ts: 1.566000 -ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320159 size: 209 +ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320124 size: 209 ret: 0 st:-1 flags:0 ts: 0.460008 -ret: 0 st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146870 size: 27925 +ret: 0 st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 146835 size: 27925 ret: 0 st:-1 flags:1 ts:-0.645825 -ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 902 size: 27837 +ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 867 size: 27837 diff --git a/tests/ref/seek/vsynth_lena-mpeg2-422 b/tests/ref/seek/vsynth_lena-mpeg2-422 index 06d8f7ac3..1fc2bf93a 100644 --- a/tests/ref/seek/vsynth_lena-mpeg2-422 +++ b/tests/ref/seek/vsynth_lena-mpeg2-422 @@ -1,46 +1,46 @@ -ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 0 size: 17497 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 0 size: 18339 ret: 0 st:-1 flags:0 ts:-1.000000 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 0 size: 17497 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 0 size: 18339 ret: 0 st:-1 flags:1 ts: 1.894167 -ret: 0 st: 0 flags:1 dts: 1.840000 pts: NOPTS pos: 325397 size: 19967 +ret: 0 st: 0 flags:1 dts: 1.840000 pts: NOPTS pos: 329242 size: 21479 ret: 0 st: 0 flags:0 ts: 0.788334 -ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 200747 size: 22575 +ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 203086 size: 24774 ret:-1 st: 0 flags:1 ts:-0.317499 ret:-1 st:-1 flags:0 ts: 2.576668 ret: 0 st:-1 flags:1 ts: 1.470835 -ret: 0 st: 0 flags:1 dts: 1.360000 pts: NOPTS pos: 265466 size: 21329 +ret: 0 st: 0 flags:1 dts: 1.360000 pts: NOPTS pos: 268154 size: 22845 ret: 0 st: 0 flags:0 ts: 0.365002 -ret: 0 st: 0 flags:1 dts: 0.400000 pts: NOPTS pos: 104454 size: 28984 +ret: 0 st: 0 flags:1 dts: 0.400000 pts: NOPTS pos: 108763 size: 32204 ret:-1 st: 0 flags:1 ts:-0.740831 ret:-1 st:-1 flags:0 ts: 2.153336 ret: 0 st:-1 flags:1 ts: 1.047503 -ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 200747 size: 22575 +ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 203086 size: 24774 ret: 0 st: 0 flags:0 ts:-0.058330 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 0 size: 17497 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 0 size: 18339 ret: 0 st: 0 flags:1 ts: 2.835837 -ret: 0 st: 0 flags:1 dts: 1.840000 pts: NOPTS pos: 325397 size: 19967 +ret: 0 st: 0 flags:1 dts: 1.840000 pts: NOPTS pos: 329242 size: 21479 ret: 0 st:-1 flags:0 ts: 1.730004 -ret: 0 st: 0 flags:1 dts: 1.840000 pts: NOPTS pos: 325397 size: 19967 +ret: 0 st: 0 flags:1 dts: 1.840000 pts: NOPTS pos: 329242 size: 21479 ret: 0 st:-1 flags:1 ts: 0.624171 -ret: 0 st: 0 flags:1 dts: 0.400000 pts: NOPTS pos: 104454 size: 28984 +ret: 0 st: 0 flags:1 dts: 0.400000 pts: NOPTS pos: 108763 size: 32204 ret: 0 st: 0 flags:0 ts:-0.481662 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 0 size: 17497 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 0 size: 18339 ret: 0 st: 0 flags:1 ts: 2.412505 -ret: 0 st: 0 flags:1 dts: 1.840000 pts: NOPTS pos: 325397 size: 19967 +ret: 0 st: 0 flags:1 dts: 1.840000 pts: NOPTS pos: 329242 size: 21479 ret: 0 st:-1 flags:0 ts: 1.306672 -ret: 0 st: 0 flags:1 dts: 1.360000 pts: NOPTS pos: 265466 size: 21329 +ret: 0 st: 0 flags:1 dts: 1.360000 pts: NOPTS pos: 268154 size: 22845 ret: 0 st:-1 flags:1 ts: 0.200839 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 0 size: 17497 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 0 size: 18339 ret: 0 st: 0 flags:0 ts:-0.904994 -ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 0 size: 17497 +ret: 0 st: 0 flags:1 dts: 0.000000 pts: NOPTS pos: 0 size: 18339 ret: 0 st: 0 flags:1 ts: 1.989173 -ret: 0 st: 0 flags:1 dts: 1.840000 pts: NOPTS pos: 325397 size: 19967 +ret: 0 st: 0 flags:1 dts: 1.840000 pts: NOPTS pos: 329242 size: 21479 ret: 0 st:-1 flags:0 ts: 0.883340 -ret: 0 st: 0 flags:1 dts: 1.360000 pts: NOPTS pos: 265466 size: 21329 +ret: 0 st: 0 flags:1 dts: 1.360000 pts: NOPTS pos: 268154 size: 22845 ret:-1 st:-1 flags:1 ts:-0.222493 ret:-1 st: 0 flags:0 ts: 2.671674 ret: 0 st: 0 flags:1 ts: 1.565841 -ret: 0 st: 0 flags:1 dts: 1.360000 pts: NOPTS pos: 265466 size: 21329 +ret: 0 st: 0 flags:1 dts: 1.360000 pts: NOPTS pos: 268154 size: 22845 ret: 0 st:-1 flags:0 ts: 0.460008 -ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 200747 size: 22575 +ret: 0 st: 0 flags:1 dts: 0.880000 pts: NOPTS pos: 203086 size: 24774 ret:-1 st:-1 flags:1 ts:-0.645825 diff --git a/tests/ref/vsynth/vsynth1-cinepak b/tests/ref/vsynth/vsynth1-cinepak index e47ae26b6..7cb33220e 100644 --- a/tests/ref/vsynth/vsynth1-cinepak +++ b/tests/ref/vsynth/vsynth1-cinepak @@ -1,4 +1,4 @@ -cd28e47a6ac396240a3fee69f15625d1 *tests/data/fate/vsynth1-cinepak.avi -408616 tests/data/fate/vsynth1-cinepak.avi -e74066a028c708f467272884ecd3f7d3 *tests/data/fate/vsynth1-cinepak.out.rawvideo -stddev: 61.38 PSNR: 12.37 MAXDIFF: 225 bytes: 7603200/ 921600 +6b9b4d2b32854fd8b0f84ee4d76b1fed *tests/data/fate/vsynth1-cinepak.avi +408910 tests/data/fate/vsynth1-cinepak.avi +4acdcc3e664d12facbcefc389079cfa6 *tests/data/fate/vsynth1-cinepak.out.rawvideo +stddev: 61.38 PSNR: 12.37 MAXDIFF: 223 bytes: 7603200/ 921600 diff --git a/tests/ref/vsynth/vsynth1-ffv1-2pass b/tests/ref/vsynth/vsynth1-ffv1-2pass new file mode 100644 index 000000000..477a1bf49 --- /dev/null +++ b/tests/ref/vsynth/vsynth1-ffv1-2pass @@ -0,0 +1,4 @@ +266ff859dade888a2c0cfddb29260186 *tests/data/fate/vsynth1-ffv1-2pass.avi +2382240 tests/data/fate/vsynth1-ffv1-2pass.avi +c5ccac874dbf808e9088bc3107860042 *tests/data/fate/vsynth1-ffv1-2pass.out.rawvideo +stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-mpeg2-422 b/tests/ref/vsynth/vsynth1-mpeg2-422 index e936ba463..a39b2b4dc 100644 --- a/tests/ref/vsynth/vsynth1-mpeg2-422 +++ b/tests/ref/vsynth/vsynth1-mpeg2-422 @@ -1,4 +1,4 @@ -6e135a1a27235a320311a932147846b4 *tests/data/fate/vsynth1-mpeg2-422.mpeg2video -730780 tests/data/fate/vsynth1-mpeg2-422.mpeg2video -0273cd8463d1fc115378748239951560 *tests/data/fate/vsynth1-mpeg2-422.out.rawvideo -stddev: 10.27 PSNR: 27.90 MAXDIFF: 162 bytes: 7603200/ 7603200 +651f054730be04257498eeae08b3bdc5 *tests/data/fate/vsynth1-mpeg2-422.mpeg2video +855859 tests/data/fate/vsynth1-mpeg2-422.mpeg2video +10fd55dbd10b08f9271eb89617766be8 *tests/data/fate/vsynth1-mpeg2-422.out.rawvideo +stddev: 9.38 PSNR: 28.68 MAXDIFF: 178 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth1-mpeg4 b/tests/ref/vsynth/vsynth1-mpeg4 index e5abc146b..0926f3323 100644 --- a/tests/ref/vsynth/vsynth1-mpeg4 +++ b/tests/ref/vsynth/vsynth1-mpeg4 @@ -1,4 +1,4 @@ -a7e57333c57e0f8a551374b063a41d9e *tests/data/fate/vsynth1-mpeg4.mp4 +7825630f9100ce18338dc598b56619ab *tests/data/fate/vsynth1-mpeg4.mp4 540105 tests/data/fate/vsynth1-mpeg4.mp4 f80ec173d37f2f91add031e95579a220 *tests/data/fate/vsynth1-mpeg4.out.rawvideo stddev: 7.97 PSNR: 30.10 MAXDIFF: 105 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-cinepak b/tests/ref/vsynth/vsynth2-cinepak index 835de78d1..72b879411 100644 --- a/tests/ref/vsynth/vsynth2-cinepak +++ b/tests/ref/vsynth/vsynth2-cinepak @@ -1,4 +1,4 @@ -663a2804f421709208c76f6e34e7bea5 *tests/data/fate/vsynth2-cinepak.avi -400402 tests/data/fate/vsynth2-cinepak.avi -2c761c3c8cda083eb8f54b2df72b257b *tests/data/fate/vsynth2-cinepak.out.rawvideo -stddev: 80.96 PSNR: 9.96 MAXDIFF: 227 bytes: 7603200/ 921600 +675d6a4370c315dc53c219a9271be4c6 *tests/data/fate/vsynth2-cinepak.avi +400720 tests/data/fate/vsynth2-cinepak.avi +cbf6900b882b484bc531f9b4799c226e *tests/data/fate/vsynth2-cinepak.out.rawvideo +stddev: 80.96 PSNR: 9.96 MAXDIFF: 229 bytes: 7603200/ 921600 diff --git a/tests/ref/vsynth/vsynth2-ffv1-2pass b/tests/ref/vsynth/vsynth2-ffv1-2pass new file mode 100644 index 000000000..e14eb1a94 --- /dev/null +++ b/tests/ref/vsynth/vsynth2-ffv1-2pass @@ -0,0 +1,4 @@ +97b5dc666896cbaf98cec3acfbe0f3fc *tests/data/fate/vsynth2-ffv1-2pass.avi +3530654 tests/data/fate/vsynth2-ffv1-2pass.avi +36d7ca943916e1743cefa609eba0205c *tests/data/fate/vsynth2-ffv1-2pass.out.rawvideo +stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-mpeg2-422 b/tests/ref/vsynth/vsynth2-mpeg2-422 index ec7244f9f..5da29b4ea 100644 --- a/tests/ref/vsynth/vsynth2-mpeg2-422 +++ b/tests/ref/vsynth/vsynth2-mpeg2-422 @@ -1,4 +1,4 @@ -b2fa9b73c3547191ecc01b8163abd4e5 *tests/data/fate/vsynth2-mpeg2-422.mpeg2video -379164 tests/data/fate/vsynth2-mpeg2-422.mpeg2video -704f6a96f93c2409219bd48b74169041 *tests/data/fate/vsynth2-mpeg2-422.out.rawvideo -stddev: 4.17 PSNR: 35.73 MAXDIFF: 70 bytes: 7603200/ 7603200 +fcaf6242ca4b706d392e40d9631e3465 *tests/data/fate/vsynth2-mpeg2-422.mpeg2video +383946 tests/data/fate/vsynth2-mpeg2-422.mpeg2video +474bb259f041bfb971691551f678fd09 *tests/data/fate/vsynth2-mpeg2-422.out.rawvideo +stddev: 3.93 PSNR: 36.23 MAXDIFF: 69 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth2-mpeg4 b/tests/ref/vsynth/vsynth2-mpeg4 index 7857d4580..47725e000 100644 --- a/tests/ref/vsynth/vsynth2-mpeg4 +++ b/tests/ref/vsynth/vsynth2-mpeg4 @@ -1,4 +1,4 @@ -b751a2d3b4e693ca39d4fafa0175fc9d *tests/data/fate/vsynth2-mpeg4.mp4 +74ab83b391f9c90f7f00fe2c3dfb6b3d *tests/data/fate/vsynth2-mpeg4.mp4 159330 tests/data/fate/vsynth2-mpeg4.mp4 2645405bc5350acc85ad72f3352f5135 *tests/data/fate/vsynth2-mpeg4.out.rawvideo stddev: 6.02 PSNR: 32.53 MAXDIFF: 89 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth3-ffv1-2pass b/tests/ref/vsynth/vsynth3-ffv1-2pass new file mode 100644 index 000000000..dd7943c9a --- /dev/null +++ b/tests/ref/vsynth/vsynth3-ffv1-2pass @@ -0,0 +1,4 @@ +96a6700731a71ee2e05c207e2334ade7 *tests/data/fate/vsynth3-ffv1-2pass.avi +53520 tests/data/fate/vsynth3-ffv1-2pass.avi +a038ad7c3c09f776304ef7accdea9c74 *tests/data/fate/vsynth3-ffv1-2pass.out.rawvideo +stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-mpeg2-422 b/tests/ref/vsynth/vsynth3-mpeg2-422 index 2247f286e..e83c23635 100644 --- a/tests/ref/vsynth/vsynth3-mpeg2-422 +++ b/tests/ref/vsynth/vsynth3-mpeg2-422 @@ -1,4 +1,4 @@ -4d108b861715f1fa010fd70baea91793 *tests/data/fate/vsynth3-mpeg2-422.mpeg2video -68612 tests/data/fate/vsynth3-mpeg2-422.mpeg2video -73b16e906d07b6bbccf4b00d4a25302c *tests/data/fate/vsynth3-mpeg2-422.out.rawvideo -stddev: 4.02 PSNR: 36.05 MAXDIFF: 46 bytes: 86700/ 86700 +96dc854fc40a6410d4edc387b63ded1a *tests/data/fate/vsynth3-mpeg2-422.mpeg2video +75445 tests/data/fate/vsynth3-mpeg2-422.mpeg2video +5337fc0bfb789919cb3325a02d48eb82 *tests/data/fate/vsynth3-mpeg2-422.out.rawvideo +stddev: 3.24 PSNR: 37.90 MAXDIFF: 27 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth3-mpeg4 b/tests/ref/vsynth/vsynth3-mpeg4 index a241e929c..e2489d050 100644 --- a/tests/ref/vsynth/vsynth3-mpeg4 +++ b/tests/ref/vsynth/vsynth3-mpeg4 @@ -1,4 +1,4 @@ -7ca3bbb8bed55d558346d258f5bea440 *tests/data/fate/vsynth3-mpeg4.mp4 +963a2970c57e1c7d46e209d5392fbeec *tests/data/fate/vsynth3-mpeg4.mp4 26037 tests/data/fate/vsynth3-mpeg4.mp4 fc0d8c1e58d254031e6207dfcae8f867 *tests/data/fate/vsynth3-mpeg4.out.rawvideo stddev: 9.66 PSNR: 28.43 MAXDIFF: 79 bytes: 86700/ 86700 diff --git a/tests/ref/vsynth/vsynth_lena-cinepak b/tests/ref/vsynth/vsynth_lena-cinepak index 6b021673a..c9cb2cfab 100644 --- a/tests/ref/vsynth/vsynth_lena-cinepak +++ b/tests/ref/vsynth/vsynth_lena-cinepak @@ -1,4 +1,4 @@ -a9ea19eb0d239a53af8630d5bc4167d0 *tests/data/fate/vsynth_lena-cinepak.avi -407574 tests/data/fate/vsynth_lena-cinepak.avi -e32d4103194665d2ea0f46d5cdd0cdf2 *tests/data/fate/vsynth_lena-cinepak.out.rawvideo +a79f907fecb95c8a5b5de670ccda215b *tests/data/fate/vsynth_lena-cinepak.avi +407952 tests/data/fate/vsynth_lena-cinepak.avi +2664cdff5f14508e891477b498cc840e *tests/data/fate/vsynth_lena-cinepak.out.rawvideo stddev: 58.10 PSNR: 12.85 MAXDIFF: 185 bytes: 7603200/ 921600 diff --git a/tests/ref/vsynth/vsynth_lena-ffv1-2pass b/tests/ref/vsynth/vsynth_lena-ffv1-2pass new file mode 100644 index 000000000..ef49a9f5a --- /dev/null +++ b/tests/ref/vsynth/vsynth_lena-ffv1-2pass @@ -0,0 +1,4 @@ +c46df7f2b5770564475710f1086cdff6 *tests/data/fate/vsynth_lena-ffv1-2pass.avi +3490446 tests/data/fate/vsynth_lena-ffv1-2pass.avi +dde5895817ad9d219f79a52d0bdfb001 *tests/data/fate/vsynth_lena-ffv1-2pass.out.rawvideo +stddev: 0.00 PSNR:999.99 MAXDIFF: 0 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth_lena-mpeg2-422 b/tests/ref/vsynth/vsynth_lena-mpeg2-422 index 5f11d4e7c..85d598782 100644 --- a/tests/ref/vsynth/vsynth_lena-mpeg2-422 +++ b/tests/ref/vsynth/vsynth_lena-mpeg2-422 @@ -1,4 +1,4 @@ -521ec92c0b8672011a43dd13db98c400 *tests/data/fate/vsynth_lena-mpeg2-422.mpeg2video -356431 tests/data/fate/vsynth_lena-mpeg2-422.mpeg2video -51ca353620f85db8b5b1c56f1a275add *tests/data/fate/vsynth_lena-mpeg2-422.out.rawvideo -stddev: 3.15 PSNR: 38.14 MAXDIFF: 49 bytes: 7603200/ 7603200 +87e5c69775b363db649c253050536045 *tests/data/fate/vsynth_lena-mpeg2-422.mpeg2video +361341 tests/data/fate/vsynth_lena-mpeg2-422.mpeg2video +93cefcf101e6d0814acfaa626a02be90 *tests/data/fate/vsynth_lena-mpeg2-422.out.rawvideo +stddev: 2.97 PSNR: 38.67 MAXDIFF: 57 bytes: 7603200/ 7603200 diff --git a/tests/ref/vsynth/vsynth_lena-mpeg4 b/tests/ref/vsynth/vsynth_lena-mpeg4 index 375c3fc65..9b7984c68 100644 --- a/tests/ref/vsynth/vsynth_lena-mpeg4 +++ b/tests/ref/vsynth/vsynth_lena-mpeg4 @@ -1,4 +1,4 @@ -a0d0edee19f6658d0e93d294e32a1a6f *tests/data/fate/vsynth_lena-mpeg4.mp4 +954162c34c24abe7a8fa6bfadcbb7dee *tests/data/fate/vsynth_lena-mpeg4.mp4 119742 tests/data/fate/vsynth_lena-mpeg4.mp4 9a1e085d9e488c5ead0c940c9612a37a *tests/data/fate/vsynth_lena-mpeg4.out.rawvideo stddev: 5.34 PSNR: 33.57 MAXDIFF: 83 bytes: 7603200/ 7603200 diff --git a/tests/refcmp-metadata.awk b/tests/refcmp-metadata.awk index fa21aad0e..850aaac5a 100644 --- a/tests/refcmp-metadata.awk +++ b/tests/refcmp-metadata.awk @@ -50,13 +50,16 @@ BEGIN { } END { + result = result && (NR == ref_nr); if (result) { for (i = 1; i <= ref_nr; i++) print ref_lines[i]; } else { for (i = 1; i <= NR; i++) print cmp_lines[i]; - if (NR != ref_nr) + if (NR == 0) + print "[refcmp] no input" > "/dev/stderr"; + else if (NR != ref_nr) print "[refcmp] lines: " NR " != " ref_nr > "/dev/stderr"; if (delta_max >= fuzz) print "[refcmp] delta_max: " delta_max " >= " fuzz > "/dev/stderr"; diff --git a/tests/tiny_ssim.c b/tests/tiny_ssim.c index 08f8e92a0..974065228 100644 --- a/tests/tiny_ssim.c +++ b/tests/tiny_ssim.c @@ -27,7 +27,6 @@ * overlapped 8x8 block sums, rather than the original gaussian weights. */ -#include "config.h" #include #include #include diff --git a/tools/ffescape.c b/tools/ffescape.c index 1ed8daa80..441e2fd01 100644 --- a/tools/ffescape.c +++ b/tools/ffescape.c @@ -19,12 +19,18 @@ */ #include "config.h" +#include +#include +#include +#include +#include #if HAVE_UNISTD_H #include /* getopt */ #endif #include "libavutil/log.h" #include "libavutil/bprint.h" +#include "libavutil/mem.h" #if !HAVE_GETOPT #include "compat/getopt.c" diff --git a/tools/graph2dot.c b/tools/graph2dot.c index fd7ea2848..d96bfd812 100644 --- a/tools/graph2dot.c +++ b/tools/graph2dot.c @@ -91,8 +91,7 @@ static void print_digraph(FILE *outfile, AVFilterGraph *graph) link->time_base.num, link->time_base.den); } else if (link->type == AVMEDIA_TYPE_AUDIO) { char buf[255]; - av_get_channel_layout_string(buf, sizeof(buf), -1, - link->channel_layout); + av_channel_layout_describe(&link->ch_layout, buf, sizeof(buf)); fprintf(outfile, "fmt:%s sr:%d cl:%s tb:%d/%d", av_get_sample_fmt_name(link->format), diff --git a/tools/ismindex.c b/tools/ismindex.c index d355cffe3..39b537819 100644 --- a/tools/ismindex.c +++ b/tools/ismindex.c @@ -574,7 +574,7 @@ static int handle_file(struct Tracks *tracks, const char *file, int split, if (tracks->audio_track < 0) tracks->audio_track = tracks->nb_tracks; tracks->nb_audio_tracks++; - track->channels = st->codecpar->channels; + track->channels = st->codecpar->ch_layout.nb_channels; track->sample_rate = st->codecpar->sample_rate; if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { track->fourcc = "AACL"; diff --git a/tools/sidxindex.c b/tools/sidxindex.c index a4f95515e..88aea6bcb 100644 --- a/tools/sidxindex.c +++ b/tools/sidxindex.c @@ -191,7 +191,7 @@ static int handle_file(struct Tracks *tracks, const char *file) track->timescale, AV_ROUND_UP)); if (track->is_audio) { - track->channels = st->codecpar->channels; + track->channels = st->codecpar->ch_layout.nb_channels; track->sample_rate = st->codecpar->sample_rate; } if (track->is_video) { diff --git a/tools/target_bsf_fuzzer.c b/tools/target_bsf_fuzzer.c index d6aaee3bd..703647b61 100644 --- a/tools/target_bsf_fuzzer.c +++ b/tools/target_bsf_fuzzer.c @@ -43,7 +43,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { const uint8_t *last = data; const uint8_t *end = data + size; AVBSFContext *bsf = NULL; - AVPacket *in, *out; + AVPacket *pkt; uint64_t keyframes = 0; uint64_t flushpattern = -1; int res; @@ -85,7 +85,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { extradata_size = bytestream2_get_le32(&gbc); bsf->par_in->sample_rate = bytestream2_get_le32(&gbc); - bsf->par_in->channels = (unsigned)bytestream2_get_le32(&gbc) % FF_SANE_NB_CHANNELS; + bsf->par_in->ch_layout.nb_channels = (unsigned)bytestream2_get_le32(&gbc) % FF_SANE_NB_CHANNELS; bsf->par_in->block_align = bytestream2_get_le32(&gbc); keyframes = bytestream2_get_le64(&gbc); flushpattern = bytestream2_get_le64(&gbc); @@ -118,9 +118,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { return 0; // Failure of av_bsf_init() does not imply that a issue was found } - in = av_packet_alloc(); - out = av_packet_alloc(); - if (!in || !out) + pkt = av_packet_alloc(); + if (!pkt) error("Failed memory allocation"); while (data < end) { @@ -133,11 +132,11 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (data + sizeof(fuzz_tag) > end) data = end; - res = av_new_packet(in, data - last); + res = av_new_packet(pkt, data - last); if (res < 0) error("Failed memory allocation"); - memcpy(in->data, last, data - last); - in->flags = (keyframes & 1) * AV_PKT_FLAG_DISCARD + (!!(keyframes & 2)) * AV_PKT_FLAG_KEY; + memcpy(pkt->data, last, data - last); + pkt->flags = (keyframes & 1) * AV_PKT_FLAG_DISCARD + (!!(keyframes & 2)) * AV_PKT_FLAG_KEY; keyframes = (keyframes >> 2) + (keyframes<<62); data += sizeof(fuzz_tag); last = data; @@ -146,28 +145,20 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { av_bsf_flush(bsf); flushpattern = (flushpattern >> 3) + (flushpattern << 61); - while (in->size) { - res = av_bsf_send_packet(bsf, in); - if (res < 0 && res != AVERROR(EAGAIN)) - break; - res = av_bsf_receive_packet(bsf, out); - if (res < 0) - break; - av_packet_unref(out); + res = av_bsf_send_packet(bsf, pkt); + if (res < 0) { + av_packet_unref(pkt); + continue; } - av_packet_unref(in); + while (av_bsf_receive_packet(bsf, pkt) >= 0) + av_packet_unref(pkt); } - res = av_bsf_send_packet(bsf, NULL); - while (!res) { - res = av_bsf_receive_packet(bsf, out); - if (res < 0) - break; - av_packet_unref(out); - } + av_bsf_send_packet(bsf, NULL); + while (av_bsf_receive_packet(bsf, pkt) >= 0) + av_packet_unref(pkt); - av_packet_free(&in); - av_packet_free(&out); + av_packet_free(&pkt); av_bsf_free(&bsf); return 0; } diff --git a/tools/target_dec_fuzzer.c b/tools/target_dec_fuzzer.c index 13766d22b..017c5cf02 100644 --- a/tools/target_dec_fuzzer.c +++ b/tools/target_dec_fuzzer.c @@ -47,12 +47,14 @@ #include "config.h" #include "libavutil/avassert.h" +#include "libavutil/avstring.h" #include "libavutil/cpu.h" #include "libavutil/imgutils.h" #include "libavutil/intreadwrite.h" #include "libavcodec/avcodec.h" #include "libavcodec/bytestream.h" +#include "libavcodec/codec_internal.h" #include "libavformat/avformat.h" //For FF_SANE_NB_CHANNELS, so we dont waste energy testing things that will get instantly rejected @@ -60,7 +62,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); -extern const AVCodec * codec_list[]; +extern const FFCodec * codec_list[]; static void error(const char *err) { @@ -68,15 +70,15 @@ static void error(const char *err) exit(1); } -static const AVCodec *c = NULL; -static const AVCodec *AVCodecInitialize(enum AVCodecID codec_id) +static const FFCodec *c = NULL; +static const FFCodec *AVCodecInitialize(enum AVCodecID codec_id) { const AVCodec *res; res = avcodec_find_decoder(codec_id); if (!res) error("Failed to find decoder"); - return res; + return ffcodec(res); } static int subtitle_handler(AVCodecContext *avctx, void *frame, @@ -102,6 +104,60 @@ const uint32_t maxiteration = 8096; static const uint64_t FUZZ_TAG = 0x4741542D5A5A5546ULL; +static int fuzz_video_get_buffer(AVCodecContext *ctx, AVFrame *frame) +{ + ptrdiff_t linesize1[4]; + size_t size[4]; + int linesize_align[AV_NUM_DATA_POINTERS]; + int i, ret, w = frame->width, h = frame->height; + + avcodec_align_dimensions2(ctx, &w, &h, linesize_align); + ret = av_image_fill_linesizes(frame->linesize, ctx->pix_fmt, w); + if (ret < 0) + return ret; + + for (i = 0; i < 4 && frame->linesize[i]; i++) + linesize1[i] = frame->linesize[i] = + FFALIGN(frame->linesize[i], linesize_align[i]); + for (; i < 4; i++) + linesize1[i] = 0; + + ret = av_image_fill_plane_sizes(size, ctx->pix_fmt, h, linesize1); + if (ret < 0) + return ret; + + frame->extended_data = frame->data; + for (i = 0; i < 4 && size[i]; i++) { + frame->buf[i] = av_buffer_alloc(size[i]); + if (!frame->buf[i]) + goto fail; + frame->data[i] = frame->buf[i]->data; + } + for (; i < AV_NUM_DATA_POINTERS; i++) { + frame->data[i] = NULL; + frame->linesize[i] = 0; + } + + return 0; +fail: + av_frame_unref(frame); + return AVERROR(ENOMEM); +} + +static int fuzz_get_buffer2(AVCodecContext *ctx, AVFrame *frame, int flags) +{ + switch (ctx->codec_type) { + case AVMEDIA_TYPE_VIDEO: + return (ctx->codec->capabilities & AV_CODEC_CAP_DR1) + ? fuzz_video_get_buffer(ctx, frame) + : avcodec_default_get_buffer2(ctx, frame, flags); + case AVMEDIA_TYPE_AUDIO: + return avcodec_default_get_buffer2(ctx, frame, flags); + default: + return AVERROR(EINVAL); + } +} + int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { uint64_t maxpixels_per_frame = 4096 * 4096; uint64_t maxpixels; @@ -126,11 +182,11 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { #ifdef FFMPEG_DECODER #define DECODER_SYMBOL0(CODEC) ff_##CODEC##_decoder #define DECODER_SYMBOL(CODEC) DECODER_SYMBOL0(CODEC) - extern AVCodec DECODER_SYMBOL(FFMPEG_DECODER); + extern FFCodec DECODER_SYMBOL(FFMPEG_DECODER); codec_list[0] = &DECODER_SYMBOL(FFMPEG_DECODER); #if FFMPEG_DECODER == tiff || FFMPEG_DECODER == tdsc - extern AVCodec DECODER_SYMBOL(mjpeg); + extern FFCodec DECODER_SYMBOL(mjpeg); codec_list[1] = &DECODER_SYMBOL(mjpeg); #endif @@ -141,29 +197,37 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { av_log_set_level(AV_LOG_PANIC); } - switch (c->type) { + switch (c->p.type) { case AVMEDIA_TYPE_AUDIO : case AVMEDIA_TYPE_VIDEO : decode_handler = audio_video_handler ; break; case AVMEDIA_TYPE_SUBTITLE: decode_handler = subtitle_handler ; break; } - switch (c->id) { + switch (c->p.id) { case AV_CODEC_ID_APE: maxsamples_per_frame /= 256; break; } maxpixels = maxpixels_per_frame * maxiteration; maxsamples = maxsamples_per_frame * maxiteration; - switch (c->id) { + switch (c->p.id) { + case AV_CODEC_ID_AASC: maxpixels /= 1024; break; case AV_CODEC_ID_AGM: maxpixels /= 1024; break; + case AV_CODEC_ID_ANM: maxpixels /= 1024; break; case AV_CODEC_ID_ARBC: maxpixels /= 1024; break; + case AV_CODEC_ID_ARGO: maxpixels /= 1024; break; case AV_CODEC_ID_BINKVIDEO: maxpixels /= 32; break; - case AV_CODEC_ID_CFHD: maxpixels /= 128; break; + case AV_CODEC_ID_CDTOONS: maxpixels /= 1024; break; + case AV_CODEC_ID_CFHD: maxpixels /= 16384; break; + case AV_CODEC_ID_CINEPAK: maxpixels /= 128; break; case AV_CODEC_ID_COOK: maxsamples /= 1<<20; break; + case AV_CODEC_ID_DFA: maxpixels /= 1024; break; case AV_CODEC_ID_DIRAC: maxpixels /= 8192; break; + case AV_CODEC_ID_DSICINVIDEO: maxpixels /= 1024; break; case AV_CODEC_ID_DST: maxsamples /= 1<<20; break; case AV_CODEC_ID_DVB_SUBTITLE: av_dict_set_int(&opts, "compute_clut", -2, 0); break; case AV_CODEC_ID_DXA: maxpixels /= 32; break; case AV_CODEC_ID_DXV: maxpixels /= 32; break; case AV_CODEC_ID_FFWAVESYNTH: maxsamples /= 16384; break; case AV_CODEC_ID_FLAC: maxsamples /= 1024; break; + case AV_CODEC_ID_FLIC: maxpixels /= 1024; break; case AV_CODEC_ID_FLV1: maxpixels /= 1024; break; case AV_CODEC_ID_G2M: maxpixels /= 1024; break; case AV_CODEC_ID_GEM: maxpixels /= 512; break; @@ -179,14 +243,17 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { case AV_CODEC_ID_INTERPLAY_ACM: maxsamples /= 16384; break; case AV_CODEC_ID_JPEG2000: maxpixels /= 16; break; case AV_CODEC_ID_LAGARITH: maxpixels /= 1024; break; + case AV_CODEC_ID_LOCO: maxpixels /= 1024; break; case AV_CODEC_ID_VORBIS: maxsamples /= 1024; break; case AV_CODEC_ID_LSCR: maxpixels /= 16; break; + case AV_CODEC_ID_MMVIDEO: maxpixels /= 256; break; case AV_CODEC_ID_MOTIONPIXELS:maxpixels /= 256; break; case AV_CODEC_ID_MP4ALS: maxsamples /= 65536; break; case AV_CODEC_ID_MSA1: maxpixels /= 16384; break; case AV_CODEC_ID_MSRLE: maxpixels /= 16; break; case AV_CODEC_ID_MSS2: maxpixels /= 16384; break; case AV_CODEC_ID_MSZH: maxpixels /= 128; break; + case AV_CODEC_ID_MVC2: maxpixels /= 128; break; case AV_CODEC_ID_MXPEG: maxpixels /= 128; break; case AV_CODEC_ID_OPUS: maxsamples /= 16384; break; case AV_CODEC_ID_PNG: maxpixels /= 128; break; @@ -198,11 +265,15 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { case AV_CODEC_ID_SANM: maxpixels /= 16; break; case AV_CODEC_ID_SCPR: maxpixels /= 32; break; case AV_CODEC_ID_SCREENPRESSO:maxpixels /= 64; break; + case AV_CODEC_ID_SIMBIOSIS_IMX:maxpixels /= 16384; break; + case AV_CODEC_ID_SMACKAUDIO: maxsamples /= 4096; break; case AV_CODEC_ID_SMACKVIDEO: maxpixels /= 64; break; case AV_CODEC_ID_SNOW: maxpixels /= 128; break; + case AV_CODEC_ID_TARGA: maxpixels /= 128; break; case AV_CODEC_ID_TAK: maxsamples /= 1024; break; case AV_CODEC_ID_TGV: maxpixels /= 32; break; case AV_CODEC_ID_THEORA: maxpixels /= 16384; break; + case AV_CODEC_ID_TQI: maxpixels /= 1024; break; case AV_CODEC_ID_TRUEMOTION2: maxpixels /= 1024; break; case AV_CODEC_ID_TSCC: maxpixels /= 1024; break; case AV_CODEC_ID_VC1: maxpixels /= 8192; break; @@ -215,18 +286,20 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { case AV_CODEC_ID_VP7: maxpixels /= 256; break; case AV_CODEC_ID_VP9: maxpixels /= 4096; break; case AV_CODEC_ID_WAVPACK: maxsamples /= 1024; break; + case AV_CODEC_ID_WCMV: maxpixels /= 1024; break; case AV_CODEC_ID_WMV3IMAGE: maxpixels /= 8192; break; case AV_CODEC_ID_WMV2: maxpixels /= 1024; break; case AV_CODEC_ID_WMV3: maxpixels /= 1024; break; case AV_CODEC_ID_WS_VQA: maxpixels /= 16384; break; case AV_CODEC_ID_WMALOSSLESS: maxsamples /= 1024; break; + case AV_CODEC_ID_YLC: maxpixels /= 1024; break; case AV_CODEC_ID_ZEROCODEC: maxpixels /= 128; break; } maxsamples_per_frame = FFMIN(maxsamples_per_frame, maxsamples); maxpixels_per_frame = FFMIN(maxpixels_per_frame , maxpixels); - AVCodecContext* ctx = avcodec_alloc_context3(c); + AVCodecContext* ctx = avcodec_alloc_context3(&c->p); AVCodecContext* parser_avctx = avcodec_alloc_context3(NULL); if (!ctx || !parser_avctx) error("Failed memory allocation"); @@ -235,11 +308,13 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { ctx->max_pixels = maxpixels_per_frame; //To reduce false positive OOM and hangs ctx->max_samples = maxsamples_per_frame; + ctx->get_buffer2 = fuzz_get_buffer2; if (size > 1024) { GetByteContext gbc; int extradata_size; int flags; + uint64_t request_channel_layout; int64_t flags64; size -= 1024; @@ -251,7 +326,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { // Try to initialize a parser for this codec, note, this may fail which just means we test without one flags = bytestream2_get_byte(&gbc); if (flags & 1) - parser = av_parser_init(c->id); + parser = av_parser_init(c->p.id); if (flags & 2) ctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; if (flags & 4) { @@ -259,7 +334,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (flags & 8) ctx->err_recognition |= AV_EF_EXPLODE; } - if ((flags & 0x10) && c->id != AV_CODEC_ID_H264) + if ((flags & 0x10) && c->p.id != AV_CODEC_ID_H264) ctx->flags2 |= AV_CODEC_FLAG2_FAST; if (flags & 0x80) ctx->flags2 |= AV_CODEC_FLAG2_EXPORT_MVS; @@ -270,7 +345,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { extradata_size = bytestream2_get_le32(&gbc); ctx->sample_rate = bytestream2_get_le32(&gbc) & 0x7FFFFFFF; - ctx->channels = (unsigned)bytestream2_get_le32(&gbc) % FF_SANE_NB_CHANNELS; + ctx->ch_layout.nb_channels = (unsigned)bytestream2_get_le32(&gbc) % FF_SANE_NB_CHANNELS; ctx->block_align = bytestream2_get_le32(&gbc) & 0x7FFFFFFF; ctx->codec_tag = bytestream2_get_le32(&gbc); if (c->codec_tags) { @@ -279,7 +354,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { ctx->codec_tag = c->codec_tags[ctx->codec_tag % n]; } keyframes = bytestream2_get_le64(&gbc); - ctx->request_channel_layout = bytestream2_get_le64(&gbc); + request_channel_layout = bytestream2_get_le64(&gbc); ctx->idct_algo = bytestream2_get_byte(&gbc) % 25; flushpattern = bytestream2_get_le64(&gbc); @@ -298,6 +373,31 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { } } + // Keep the deprecated request_channel_layout behavior to ensure old fuzzing failures + // remain reproducible. + if (request_channel_layout) { + switch (ctx->codec_id) { + case AV_CODEC_ID_AC3: + case AV_CODEC_ID_EAC3: + case AV_CODEC_ID_MLP: + case AV_CODEC_ID_TRUEHD: + case AV_CODEC_ID_DTS: + if (request_channel_layout & ~INT64_MIN) { + char *downmix_layout = av_mallocz(19); + if (!downmix_layout) + error("Failed memory allocation"); + av_strlcatf(downmix_layout, 19, "0x%"PRIx64, request_channel_layout & ~INT64_MIN); + av_dict_set(&opts, "downmix", downmix_layout, AV_DICT_DONT_STRDUP_VAL); + } + if (ctx->codec_id != AV_CODEC_ID_DTS) + break; + // fall-through + case AV_CODEC_ID_DOLBY_E: + av_dict_set_int(&opts, "channel_order", !!(request_channel_layout & INT64_MIN), 0); + break; + } + } + flags64 = bytestream2_get_le64(&gbc); if (flags64 &1) ctx->debug |= FF_DEBUG_SKIP; @@ -318,7 +418,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { ctx->width = ctx->height = 0; } - int res = avcodec_open2(ctx, c, &opts); + int res = avcodec_open2(ctx, &c->p, &opts); if (res < 0) { avcodec_free_context(&ctx); av_free(parser_avctx); diff --git a/tools/target_dem_fuzzer.c b/tools/target_dem_fuzzer.c index 3c03c8d17..32767a018 100644 --- a/tools/target_dem_fuzzer.c +++ b/tools/target_dem_fuzzer.c @@ -34,6 +34,13 @@ typedef struct IOContext { int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); +int64_t interrupt_counter; +static int interrupt_cb(void *ctx) +{ + interrupt_counter --; + return interrupt_counter < 0; +} + static void error(const char *err) { fprintf(stderr, "%s", err); @@ -160,8 +167,15 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { *strchr(extension, ',') = 0; av_strlcatf(filename, sizeof(filename), ".%s", extension); } + + interrupt_counter = bytestream2_get_le32(&gbc); + avfmt->interrupt_callback.callback = interrupt_cb; } + // HLS uses a loop with sleep, we thus must breakout or we timeout + if (fmt && !strcmp(fmt->name, "hls")) + interrupt_counter &= 31; + if (!io_buffer_size || size / io_buffer_size > maxblocks) io_buffer_size = size; diff --git a/tools/uncoded_frame.c b/tools/uncoded_frame.c index f441d3fbd..edea2367c 100644 --- a/tools/uncoded_frame.c +++ b/tools/uncoded_frame.c @@ -173,8 +173,9 @@ int main(int argc, char **argv) st->stream->codecpar->format = av_buffersink_get_format(st->sink); break; case AVMEDIA_TYPE_AUDIO: - st->stream->codecpar->channel_layout = av_buffersink_get_channel_layout(st->sink); - st->stream->codecpar->channels = av_buffersink_get_channels(st->sink); + ret = av_buffersink_get_ch_layout(st->sink, &st->stream->codecpar->ch_layout); + if (ret < 0) + goto fail; 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);